CVS difference for ais/ai-50217.txt
--- ais/ai-50217.txt 2003/02/05 21:34:34 1.1
+++ ais/ai-50217.txt 2003/05/24 00:51:43 1.2
@@ -853,8 +853,2384 @@
**************************************************************
-[Editor's note: Mail after the above time is not posted yet. That's
-58 messages as of this writing. Sorry.]
+From: Dan Eilers
+Sent: Monday, February 3, 2003 3:04 PM
+
+I like Pascal's "weak with" proposal a lot, although I'm not yet convinced
+we need to syntactically distinguish "weak with" from normal withs.
+
+I came to this conclusion by perhaps a slightly different route:
+
+1) we have a bunch of proposed syntax extensions to solve the circular
+ types problem, any of which are believed to be feasible to implement;
+
+2) essentially none of the proposed syntax extensions have any dual-use
+ benefit towards the solution of any other problem;
+
+3) we envision a tool that can automatically translate circular specs
+ written in other languages into the proposed new syntax;
+
+4) a similar tool could also translate Ada that allowed circular with's
+ into any of the proposed syntax extensions;
+
+5) given such a tool, the users would happily write Ada with circular
+ with's, and use the tool to create their package abstracts (in
+ whatever syntax);
+
+6) this could be made automatic. When the compiler sees a "with" clause
+ for a unit that has not been compiled, instead of giving an error, it
+ can automatically invoke the translation tool to create the package
+ abstract, and then compile the abstract before continuing to compile
+ the original unit.
+
+6) this can be further optimized if desired so the translation tool is
+ integrated into the compiler, rather than needing to be a stand-alone
+ tool.
+
+
+Notes:
+
+Recursive subprogram calls don't use different syntax than non-recursive
+ones, so ideally recursive with's wouldn't either.
+
+We need to address the elaboration order concerns, but presumably that
+is more naturally done with elaboration pragmas than with different
+syntax for "with" clauses.
+
+I still think there is some possible dual-use synergy with the separate
+private issue. As Tuck corrected me, you can't just put the private
+part in a separate file. So instead of "private is separate" you would
+have to say "the remainder of this package is separate". A "with" clause
+on such a package would continue to see both the root and the subunit.
+A "with p'abstract" would see only the root. I believe such new syntax
+would at the same time solve the separate private issue and the circular
+types issue, and perhaps also the separate constants issue.
+
+**************************************************************
+
+From: Robert Dewar
+Sent: Monday, February 3, 2003 4:07 PM
+
+> 6) this could be made automatic. When the compiler sees a "with" clause
+> for a unit that has not been compiled, instead of giving an error, it
+> can automatically invoke the translation tool to create the package
+> abstract, and then compile the abstract before continuing to compile
+> the original unit.
+
+That won't do at all for a source based compilation system, there is no
+concept of "a unit that has not been compiled". One of the critical
+guarantees in GNAt is that order of compilation NEVER affects the results
+and we would strenuously object to a change in semantics which would
+destroy this guarantee. For one thing it means that the meaning of a
+program is not fully conveyed by its sources, and that is pragmatically
+and philsophically unacceptable.
+
+**************************************************************
+
+From: Robert A. Duff
+Sent: Monday, February 3, 2003 4:16 PM
+
+Yes, I agree.
+
+This makes me think that these tools that translate from other languages
+(or create bindings thereto, I guess) ought to make sure that their
+generated Ada code doesn't do anything at elab time -- at least in the
+presence of cycles. That seems achievable, and simpler than having user
+options to specify elab order.
+
+**************************************************************
+
+From: Robert Dewar
+Sent: Monday, February 3, 2003 4:25 PM
+
+Note that another objection is that this means that automated tools for
+determining the compilation order would have to do semantic analysis.
+
+**************************************************************
+
+From: Robert A. Duff
+Sent: Monday, February 3, 2003 4:12 PM
+
+Dan Eilers wrote:
+
+>...
+> 3) we envision a tool that can automatically translate circular specs
+> written in other languages into the proposed new syntax;
+
+Right, but those languages typically don't have the same
+elaboration-order issues that Ada does.
+
+> 4) a similar tool could also translate Ada that allowed circular with's
+> into any of the proposed syntax extensions;
+
+True, but...
+
+> 5) given such a tool, the users would happily write Ada with circular
+> with's, and use the tool to create their package abstracts (in
+> whatever syntax);
+
+I fear that such a tool would be inherently error prone. Suppose we
+have package specs A and B, which 'with' each other. The tool would
+have to choose which one to elaborate first, and it might guess wrong.
+I think it's better to let the user specify the order via "limited
+with".
+
+Besides, now that I think about it, how would this tool work? "Limited
+with" implies a very restricted usage of the imported package. The tool
+would have to check that such restrictions are obeyed before turning a
+"with" into a "limited with".
+
+> 6) this could be made automatic. When the compiler sees a "with" clause
+> for a unit that has not been compiled, instead of giving an error, it
+> can automatically invoke the translation tool to create the package
+> abstract, and then compile the abstract before continuing to compile
+> the original unit.
+
+Users normally don't compile. They run a build tool, which
+automatically compiles everything that needs to be compiled, in some
+order that is not easily known to the programmer. It seems error-prone
+to have the semantics depending on what happens to have already been
+compiled. That's true even if the user bypasses the build tool and
+explicitly invokes the compiler in some order.
+
+> 6) this can be further optimized if desired so the translation tool is
+> integrated into the compiler, rather than needing to be a stand-alone
+> tool.
+>
+>
+> Notes:
+>
+> Recursive subprogram calls don't use different syntax than non-recursive
+> ones, so ideally recursive with's wouldn't either.
+
+True, but this case seems different to me.
+
+If I see:
+
+ with B;
+ package A is ...
+
+I currently know for certain that the spec of B is elaborated before A.
+I don't have to go looking at B to see that that's true. I don't think
+we should break that property.
+
+> We need to address the elaboration order concerns, but presumably that
+> is more naturally done with elaboration pragmas than with different
+> syntax for "with" clauses.
+
+I don't think the existing pragmas can be used for this purpose.
+Suppose the cycle is "A with's B with's C with's A". Adding a pragma
+Elaborate in A pointing to B doesn't work, because it's not transitive
+to C. Adding Elaborate_All doesn't work, because that would require A
+to be elaborated before itself (because it's transitive).
+
+So we would have to add a new pragma to explicitly break one link in the
+cycle:
+
+ with X; pragma Don't_Elaborate(X); -- ;-)
+
+But that means precisely what "limited with X;" would mean.
+
+Elaboration pragmas were a mistake in the first place. They were added
+late in the game to Ada 83 to solve the "Brosgol anomalies". We added
+more pragmas in Ada 95, and I'm afraid we botched the job -- we *still*
+didn't solve the problems. I suggest we avoid compounding the mistake
+of using pragmas to control elaboration.
+
+Furthermore, "limited with X" implies various restrictions on the use of
+X -- you can only refer to types in X, and they are all incomplete (or
+access to incomplete). Pragmas shouldn't be in *that* business.
+
+> I still think there is some possible dual-use synergy with the separate
+> private issue. As Tuck corrected me, you can't just put the private
+> part in a separate file. So instead of "private is separate" you would
+> have to say "the remainder of this package is separate". A "with" clause
+> on such a package would continue to see both the root and the subunit.
+> A "with p'abstract" would see only the root. I believe such new syntax
+> would at the same time solve the separate private issue and the circular
+> types issue, and perhaps also the separate constants issue.
+
+Perhaps, but I skept. I'm having trouble seeing the separate-private
+issue as anything more than a simple textual translation, with no
+run-time consequences whatsoever. I haven't seen a fully worked-out
+proposal that solves both problems...
+
+P.S. This discussion makes me think of another observation. If a given
+cycle contains two or more "limited with"s, then elaboration order will
+presumably be implementation defined. I suppose that's OK -- if you
+care, you can break the cycle with just one "limited with", and use
+normal "with" for the rest.
+
+**************************************************************
+
+From: Dan Eilers
+Sent: Monday, February 3, 2003 6:23 PM
+
+Bob Duff wrote:
+
+> Perhaps, but I skept. I'm having trouble seeing the separate-private
+> issue as anything more than a simple textual translation, with no
+> run-time consequences whatsoever. I haven't seen a fully worked-out
+> proposal that solves both problems...
+
+OK, here's the canonical example worked out:
+
+-- Note: with'ing package P creates a semantic dependency on all subunits
+-- such as P.Extension declared in P, and makes all declarations in
+-- P.Extension visible as if they were declared directly in P.
+
+-- with'ing P'abstract does not create a semantic dependency on subunits
+-- such as P.Extension, and does not make p.Extension's declarations visible,
+-- and does not allow declaring objects of types from P whose full type is
+-- deferred to P.Extension.
+
+ package Employees is
+ type Employee is private; -- completed in subunit
+ type Emp_Ptr is access all Employee;
+ package Extension is separate;
+ end Employees;
+
+ package Departments is
+ type Department is private;
+ type Dept_Ptr is access all Department;
+ package Extension is separate;
+ end Departments;
+
+ with Departments'abstract;
+ separate(Employees)
+ package Extension is
+ type Emp_Ptr is access all Employee;
+ procedure Assign_Employee(E : access Employee;
+ D : access Departments.Department);
+ function Current_Department(D : access constant Employee) return
+ Departments.Dept_Ptr;
+ private
+ type Employee is record
+ dept: Departments.Dept_Ptr;
+ end record;
+ end Extension;
+
+ with Employees'abstract;
+ separate(Departments)
+ package Extension is
+ type Dept_Ptr is access all Department;
+ procedure Choose_Manager(D : access Department;
+ Manager : access Employees.Employee);
+ private
+ type Department is
+ mgr: Employees.Emp_Ptr;
+ end record;
+ end Extension;
+
+
+For the "private is separate" problem, instead of:
+
+ package p is
+ ...
+ private is separate;
+ end P;
+
+you would have:
+
+ package p is
+ ...
+ private
+ package extension is separate;
+ end;
+
+**************************************************************
+
+From: Tucker Taft
+Sent: Monday, February 3, 2003 4:27 PM
+
+Robert A Duff wrote:
+>
+> > This brings me directly to the second gotcha. I think it is clear (at
+> > least to me) that for this to be useful, the limited view of an access
+> > type has to be an access type. But there have to be limits on how this
+> > access type can be used in the limited view.
+>
+> Can't we say that it's an access type whose designated type is
+> incomplete? And then you can't do things like X.all.
+
+You are starting to give me the "willies."
+We will have to process rep-clauses if the access type
+in a limited-with-ed package is not itself considered an
+incomplete type.
+
+If we want a non-incomplete access type, then I think we need to
+declare it in a non-limited-withed place. Hence,
+this doesn't solve the problem associated with proliferation
+of access type declarations.
+
+And I do still like that "type C.T;" ;-).
+(what a pain I can be...)
+
+> >... (Translation, if you
+> > create a type with a component of (a limited view of) an access type,
+> > then it is illegal to have a non-null default value for a component of
+> > that type. Other rules are possible.)
+>
+> I think you can't have an allocator (as a default or anything else),
+> but I don't see why it couldn't be a function call that happens to
+> return the access type. Perhaps an example?
+
+Gack. You are back to requiring that the limited-with-er chooses
+a representation for a type that it isn't declaring.
+In this era where we are on the cusp of moving from 32-bit pointers
+to 64-bit pointers, I fear that rep clauses on access types may
+be more common, rather than less.
+
+
+
+By the way, I have discovered (remembered?) that we have a "loose parser"
+built into our compiler. It's job is to do lookahead where strict one-pass
+semantic analysis is difficult. For example, it scans bodies looking for
+labels, and then inserts them at the "begin." It scans generic formal
+parts looking ahead until it finds out in what parent unit the generic
+is declared, so it can interpret the names in the formal part properly.
+In any case, this is a full, but very stupid and quite "lax" parser.
+It could probably build up a tree of package and type names. It could
+certainly not make any semantic sense out of a rep clause, and since the
+rep clause could use named numbers declared in other packages
+(e.g. "for My_Acc_Type'Size use Targ_Dep.Size_Of_Access_Type;"),
+it really couldn't be made to work.
+
+So if we consider this limited-with approach, I think we want to make
+minimal assumptions about syntactic processing, and zero assumptions
+about representation processing, of the items in the limited-withed unit.
+
+I also agree with Bob that the less said about the way the magic
+happens the better. Clearly there will be some kind of compilation
+dependence on the source of the limited-withed unit, but the key point is there
+is no semantic or elaboration dependence on the unit. It seems fine if
+the source of the unit is edited "after" something that mentioned it in a limited-with
+clause is compiled, but before the unit itself is compiled. But of course,
+whenever the source is changed, everything that has a compilation-dependence
+on it will probably need to be recompiled prior to linking.
+
+The "trick" that makes it all possible is that the *fully compiled* representation of
+both units in a cyclic dependence depend on the *source text* of both units.
+The fully compiled representations don't both depend on the others fully compiled
+representation. Of course, there may be intermediate forms between source
+text and fully compiled representations, but those don't need to be mentioned.
+And the other important point is there is no transitive compilation dependence
+if the unit mentioned in a limited-with clause itself depends on other
+units, via withs or limited-withs.
+
+Presumably, mutual inlining, if supported, requires similar tricks.
+
+Other observations if we consider limited-with:
+
+I suppose to be consistent, we should interpret "limited with P.Q.R;"
+as equivalent to "limited with P, P.Q, P.Q.R;". Also it seems clear
+that limited with is ignored if there is a non-limited with for the
+same unit.
+
+Another important point is that if a unit is mentioned in a limited with
+clause, it is a *post*-compilation rule that the unit be semantically
+(or even syntactically) correct, as opposed to a legality rule. When compiling
+the unit having the limited with, the compiler may of course check some part of
+this post-compilation rule early (provided of course it doesn't create an inappropriate
+semantic dependence), but an ACATS test should not require that any particular
+errors in the unit mentioned in the limited-with be identified at this time.
+Certainly compilers will vary in how picky is the parser that they
+use to implement limited with, especially given that Ada's "syntax"
+rules slop over into semantic processing fairly frequently, due to the
+lack of direct LALR(1) parsability.
+
+The only requirement should be that *if* the unit is semantically correct,
+then you can safely mention it in a limited-with. But you cannot rely
+on the compiler detecting all (or any) errors in a unit mentioned in a limited-with,
+though it can be arbitrarily picky about it. Eventually, prior to linking,
+it will require that the unit exist and be semantically correct. This
+means that when a unit mentions a second unit in a limited-with
+clause, the second unit is "needed by" the first unit, in the
+sense of 10.2(2-6).
+
+The above is related to 10.1.4(5) which says:
+
+ When a compilation unit is compiled, all compilation units upon which
+ it depends semantically shall already exist in the environment...
+
+We could change this to "... upon which it depends semantically or
+which it mentions in a limited_with_clause shall ..." and it would still be OK.
+
+However, 10.1.4(6) which says:
+
+ The implementation may require that a compilation unit be legal before
+ inserting it into the environment.
+
+is too strict. It could be changed to:
+
+ The implementation may require that a compilation unit satisfy the Syntax
+ Rules before inserting it into the environment. The implementation may
+ require that a compilation unit be legal before allowing it to be mentioned
+ in a with_clause other than a limited_with_clause.
+
+**************************************************************
+
+From: Robert A Duff
+Sent: Monday, February 3, 2003 5:17 PM
+
+Tucker wrote:
+
+> Robert A Duff wrote:
+> > Can't we say that it's an access type whose designated type is
+> > incomplete? And then you can't do things like X.all.
+>
+> You are starting to give me the "willies."
+> [...description of willies]
+
+OK, I withdraw my suggestion.
+
+But it seems like whatever solution to the mutual recursion problem we
+choose, we really need to solve the problem of proliferation of silly
+type conversions. Otherwise, these proposals will be nearly unusable.
+
+That is, there ought to be an *implicit* conversion between access types
+in the "safe" cases. I know we discussed that before. Is it part of
+any of these proposals, or is it a separate AI? I seem to recall that
+it might be wrapped up with other access-type issues, like allowing "not
+null" constraints, and access-to-constant parameters.
+
+> And I do still like that "type C.T;" ;-).
+> (what a pain I can be...)
+
+That's a fine solution, IMHO. Your earlier e-mail about
+mutually-recursive types being part of the same abstraction
+makes me comfortable with the idea of tying the solution to
+child packages. (See, it *is* possible to convey sensible information
+about purely aesthetic concerns. ;-))
+
+But I would choose the "limited with" idea, unless it is considered too
+hard to implement.
+
+> Presumably, mutual inlining, if supported, requires similar tricks.
+
+And mutual generic instantiation?
+
+> Other observations if we consider limited-with:
+>
+> I suppose to be consistent, we should interpret "limited with P.Q.R;"
+> as equivalent to "limited with P, P.Q, P.Q.R;". Also it seems clear
+> that limited with is ignored if there is a non-limited with for the
+> same unit.
+
+Or any other "strong" dependence, such as child upon parent.
+
+I guess "strong dependence", as I've been calling it, is exactly the
+same notion as "semantic dependence".
+
+> Another important point is that if a unit is mentioned in a limited with
+> clause, it is a *post*-compilation rule that the unit be semantically
+> (or even syntactically) correct, as opposed to a legality rule. ...
+
+I don't see the need for any verbiage in the RM about this point.
+And I don't see how this differs (in theory) from normal with_clauses.
+(It might differ in practise, depending on how the compiler actually
+works.)
+
+I mean, if B says "with A;", there is currently no rule saying "A shall
+be legal." A compiler could properly say nothing more than "no errors
+found in B", even if there are errors in A. (That would be unfriendly,
+IMHO.) Of course, sometime before running the program, A must be
+compiled, and the errors detected.
+
+> ...This
+> means that when a unit mentions a second unit in a limited-with
+> clause, the second unit is "needed by" the first unit, in the
+> sense of 10.2(2-6).
+
+Yes, that's a key point. It might be that the second unit is mentioned
+*only* in limited_with_clauses, in which case there are no elaboration
+dependendences upon it, but it still needs to be included in the
+program, and elaborated at some point (possibly very late).
+
+> The above is related to 10.1.4(5) which says:
+>
+> When a compilation unit is compiled, all compilation units upon which
+> it depends semantically shall already exist in the environment...
+>
+> We could change this to "... upon which it depends semantically or
+> which it mentions in a limited_with_clause shall ..." and it would still be OK.
+
+I don't see any need to change this, given that "existing in the env" is
+such a vague concept. In GNAT, it just means the file is sitting there
+on the disk. In AdaMagic, it just means it is sitting there on the disk
+and has been "registered". Registration only does minimal syntax
+checking. In Rational's compiler, it means something more.
+
+> However, 10.1.4(6) which says:
+>
+> The implementation may require that a compilation unit be legal before
+> inserting it into the environment.
+>
+> is too strict. It could be changed to:
+
+I don't see why. The GNAT model does not take advantage of this
+permission. The permission is there for the benefit of compilers like
+Rational, where "inserting" involves running the compiler, and therefore
+checking various rules. I suppose AdaMagic takes partial advantage of
+this permission, since insertion involves some small amount of syntax
+checking.
+
+But why should we care how much checking is done on B before "limited
+with B" can be swallowed by the compiler? If B is illegal, the compiler
+can process "limited with B" if it likes, or (if it happens to notice
+the illegality), it can complain that "limited with B" is nonsense.
+It doesn't matter whether the illegality is syntactic or semantic.
+
+> The implementation may require that a compilation unit satisfy the Syntax
+> Rules before inserting it into the environment. The implementation may
+> require that a compilation unit be legal before allowing it to be mentioned
+> in a with_clause other than a limited_with_clause.
+
+I see no need for this added complexity. And it could be a burden -- if
+the compiler chooses to implement some simple Legality Rule in the
+parser, that should be allowed.
+
+**************************************************************
+
+From: Tucker Taft
+Sent: Monday, February 3, 2003 6:20 PM
+
+Robert A Duff wrote:
+> Tucker wrote:
+> ...
+
+>>The above is related to 10.1.4(5) which says:
+>>
+>> When a compilation unit is compiled, all compilation units upon which
+>> it depends semantically shall already exist in the environment...
+>>
+>>We could change this to "... upon which it depends semantically or
+>>which it mentions in a limited_with_clause shall ..." and it would still be OK.
+>
+> I don't see any need to change this, given that "existing in the env" is
+> such a vague concept. In GNAT, it just means the file is sitting there
+> on the disk. In AdaMagic, it just means it is sitting there on the disk
+> and has been "registered". Registration only does minimal syntax
+> checking. In Rational's compiler, it means something more.
+
+I think we need to say *something* about the requirements
+on a unit mentioned in a limited-with clause. Why not say
+it must exist in the environment? As you said, that is
+pretty vague. If there are no requirements on it, then
+the implementation has no place to "hang" whatever requirements
+it really does have. It can't just invent requirements that
+don't exist. But it can say, "as far as our implementation
+is concerned, that unit doesn't exist in the environment,
+so we refuse to compile the limited-with for it."
+
+>>However, 10.1.4(6) which says:
+>>
+>> The implementation may require that a compilation unit be legal before
+>> inserting it into the environment.
+>>
+>>is too strict. It could be changed to:
+>
+> I don't see why.
+
+Again, we need a place for the implementation to "hang"
+its requirements. We have given them the first handle,
+by allowing them to require existence. Now we are
+giving them the second handle, allowing them to impose
+certain other requirements on the unit. They *clearly*
+can't impose complete legality requirements, if the
+units are inserted one at a time, since there is no
+order of insertion that would allow that.
+
+> ...
+> The GNAT model does not take advantage of this
+> permission. The permission is there for the benefit of compilers like
+> Rational, where "inserting" involves running the compiler, and therefore
+> checking various rules. I suppose AdaMagic takes partial advantage of
+> this permission, since insertion involves some small amount of syntax
+> checking.
+>
+> But why should we care how much checking is done on B before "limited
+> with B" can be swallowed by the compiler? If B is illegal, the compiler
+> can process "limited with B" if it likes, or (if it happens to notice
+> the illegality), it can complain that "limited with B" is nonsense.
+> It doesn't matter whether the illegality is syntactic or semantic.
+
+You are missing the point. I am simply *allowing* compilers
+to impose requirements, but only up to a point.
+Without such verbiage, I don't believe compilers would be
+allowed to impose any requirements.
+
+I suppose you could argue all of this verbiage is unnecessary
+already, but since we felt the need to put it there in the
+first place, and we presumably aren't going to take it out,
+I believe it needs to be updated to *allow* compilers to impose
+certain requirements on limited-with'ed units. But I definitely
+don't want to force them to impose these requirements
+(and I don't think my suggested wording does that).
+
+>> The implementation may require that a compilation unit satisfy the Syntax
+>> Rules before inserting it into the environment. The implementation may
+>> require that a compilation unit be legal before allowing it to be mentioned
+>> in a with_clause other than a limited_with_clause.
+>
+> I see no need for this added complexity. And it could be a burden -- if
+> the compiler chooses to implement some simple Legality Rule in the
+> parser, that should be allowed.
+
+I'm not sure what we are discussing any more, since you
+don't seem to think that the unit even need to exist
+in the environment to be mentioned in the limited-with
+clause. I think we need to *allow* implementations
+to impose some requirements, and we might as well tie
+it to the notion of "exist" in the environment.
+*If* we tie it to that notion, we want to be sure that
+limited-with can in fact be used. That seems to mean
+that you must be able to insert units into the environment
+before they can be (fully) compiled, strictly for the purposes
+of doing a "limited with" of them.
+
+Why don't you suggest some wording so we actually
+have an alternative to consider?
+
+**************************************************************
+
+From: Robert A Duff
+Sent: Monday, February 3, 2003 6:46 PM
+
+Tucker wrote:
+
+> I think we need to say *something* about the requirements
+> on a unit mentioned in a limited-with clause. Why not say
+> it must exist in the environment? As you said, that is
+> pretty vague. If there are no requirements on it, then
+> the implementation has no place to "hang" whatever requirements
+> it really does have. It can't just invent requirements that
+> don't exist. But it can say, "as far as our implementation
+> is concerned, that unit doesn't exist in the environment,
+> so we refuse to compile the limited-with for it."
+
+OK, you have convinced me on that point. But as to 10.1.4(6):
+
+> Again, we need a place for the implementation to "hang"
+> its requirements. We have given them the first handle,
+> by allowing them to require existence. Now we are
+> giving them the second handle, allowing them to impose
+> certain other requirements on the unit.
+
+But 10.1.4(6) as is already gives sufficient permission.
+Your proposed change gives *less* permission.
+I claim there is no need to be more restrictive (on implementations),
+and that being more restrictive requires more complex RM wording.
+
+10.1.4(6) as is allows compilers to refuse to deal with "limited with X"
+on an illegal X. That is sufficient permission. If X is in the env,
+and is legal, the compiler must deal with "limited with X", because the
+only permission to refuse to admit X into the env is if it's illegal.
+
+> They *clearly*
+> can't impose complete legality requirements, if the
+> units are inserted one at a time, since there is no
+> order of insertion that would allow that.
+
+There is no requirement that units are inserted one at a time (and in
+fact they are not, in AdaMagic). Hence, it is not "*clearly*" true that
+they can't impose legality requirements.
+
+Your wording for 10.1.4(6) does not allow a compiler to impose such
+legality requirements. I think that's overspecification, and could be
+an implementation burden. For example, it is reasonable to implement
+some legality rules in the parser, and some compilers do that.
+One might wish to run the parser on X when seeing "limited with X".
+Your wording would disallow such an implementation.
+
+Imagine a front end structured as three phases:
+
+ 1. Parse and build syntax tree.
+ 2. Walk tree, build symbol table nodes for explicit declarations,
+ collect a list of all type decls, and check *some* legality
+ rules.
+ 3. Overload resolution, and check the rest of the legality rules.
+
+The "limited with" wants that list of type decls from phase 2.
+But your wording seems to forbid phase 2 from printing any error
+messages, because they're not syntax errors.
+
+> I'm not sure what we are discussing any more, since you
+> don't seem to think that the unit even need to exist
+> in the environment to be mentioned in the limited-with
+> clause.
+
+I backed off on that part.
+
+>... I think we need to *allow* implementations
+> to impose some requirements, and we might as well tie
+> it to the notion of "exist" in the environment.
+> *If* we tie it to that notion, we want to be sure that
+> limited-with can in fact be used. That seems to mean
+> that you must be able to insert units into the environment
+> before they can be (fully) compiled, strictly for the purposes
+> of doing a "limited with" of them.
+>
+> Why don't you suggest some wording so we actually
+> have an alternative to consider?
+
+OK, I propose changing 10.1.4(5) in the way you suggested, and leaving
+10.1.4(6) as is.
+
+**************************************************************
+
+From: Tucker Taft
+Sent: Monday, February 3, 2003 7:02 PM
+
+Robert A Duff wrote:
+ > ...
+> OK, I propose changing 10.1.4(5) in the way you suggested, and leaving
+> 10.1.4(6) as is.
+
+I suppose there is an unwritten rule that there
+must be some way for two packages with cylic
+dependence to be inserted into the environment.
+Clearly if the "insertion" process requires legality,
+and you can only insert one unit at a time,
+there is a problem. Either the compiler
+must allow simultaneous multiple-file insertion
+(that sounds like it might be illegal in Nebraska ;-),
+or it must allow units that are not yet demonstrably
+legal to be inserted.
+
+**************************************************************
+
+From: Robert A Duff
+Sent: Monday, February 3, 2003 7:14 PM
+
+Don't you think it's OK to leave that rule unwritten?
+I mean if that's a hole, it's already a hole.
+
+If I have some legal code, I must be able to insert it into the env
+*somehow*, since there's no permission for the implementation to refuse
+legal code. The fact that the implementation is incapable of
+determining whether it's legal seems irrelevant. *I* know it's legal.
+
+I think you're worrying overmuch about implementation issues (in
+considering RM wording). Legal code must be accepted. Therefore, code
+must be accepted if the compiler does not (yet) know whether it's legal.
+The compiler can only refuse if it can *prove* it's illegal. Make
+sense?
+
+**************************************************************
+
+From: Tucker Taft
+Sent: Monday, February 3, 2003 8:33 PM
+
+After thinking more about this, I think we need
+to make some change to the wording of 10.1.4(6). It really
+doesn't make any sense if we change 10.1.4(5) as proposed.
+We seem to agree that this sentence is primarily for
+non-source-based compilers, where the only way to insert a
+unit into the environment is by processing it in some way.
+But it is exactly those compilers that will have to change to
+support limited-with. They *cannot* require legality of all
+units inserted into the environment, if we have just
+changed 10.1.4(5) to require that the unit mentioned in
+a limited-with must already *be* in the environment.
+
+I think we should say something closer to this:
+
+ Before inserting a compilation unit into the environment,
+ the implementation may require that it obey all the Syntax
+ Rules, and any other rules that it can check given
+ what other units already exist in the environment.
+
+> ...
+> I think you're worrying overmuch about implementation issues (in
+> considering RM wording). Legal code must be accepted. Therefore, code
+> must be accepted if the compiler does not (yet) know whether it's legal.
+> The compiler can only refuse if it can *prove* it's illegal. Make
+> sense?
+
+No. ;-).
+
+I think either we should make 10.1.4(6) completely
+implementation-defined, or replace it with something
+that reflects the problem that non-source-based
+compilers will have with limited withs, since we
+know that 10.1.4(6) was crafted specifically for
+their needs.
+
+Remember, this is in the section called "implementation
+permissions" so it is specifically talking to implementors,
+not users, and it is specifically talking about implementation
+issues, not abstract semantic issues.
+
+**************************************************************
+
+From: Robert A Duff
+Sent: Monday, February 3, 2003 7:06 PM
+
+Pascal,
+
+This "weak with" ("limited with") thing is your proposal, but if you
+like, I might be willing to work out the RM wording tomorrow (Tuesday).
+This idea seems to be gaining favor, and if it's to be chosen, I don't
+really want that to take 17 more ARG meetings. Producing wording now
+might speed things up.
+
+On the other hand, if folks think it's too hard to implement, please say
+so before I waste my time.
+
+Should I do it?
+
+**************************************************************
+
+From: Pascal Leroy
+Sent: Tuesday, February 4, 2003 3:21 AM
+
+It would be very useful if you did that. You are much more competent than me at
+crafting RM wording, and furthermore I don't think I would have time to do that
+between now and the meeting.
+
+Since there seems to be some interest for the idea, it would be good to have a
+precise proposal on the table to discuss it. Experience has proven that
+discussing an AI without an initial write-up is sterile.
+
+**************************************************************
+
+From: Randy Brukardt
+Sent: Monday, February 3, 2003 8:35 PM
+
+I'm not Pascal, but I'd suggest going ahead and writing up the wording. I'm
+having a hard time getting a handle on this proposal, and I'm sure that
+would help. OTOH, since it is a complete start from scratch, it's going to
+take 17 meetings to get it right in any case. At most, you can reduce that
+number by one. :-)
+
+> On the other hand, if folks think it's too hard to implement, please say
+> so before I waste my time.
+
+At the moment, I think it's too hard to implement (given that type stubs are
+expected to take 4 hours of work; this would be more like 4 weeks). But that
+may be irrelevant. More important is that I don't see any way, within the
+current design of Janus/Ada, to implement something like this.
+
+The problem is with the obsoleteness check. Janus/Ada uses a serial number
+created from the time stamp of the symbol table file created for a library
+unit for checking. Also, the Janus/Ada compiler knows nothing about source
+files other than the one it is compiling at the moment. (Other tools are a
+bit smarter, but the compiler does not use that information itself.) It only
+knows about symbol table files.
+
+One presumes that you'd have a new kind of symbol table file that held a
+'lightly' compiled package spec for limited withs. And you'd use the time
+stamp of that file to create the serial number for obsoleteness checking.
+Clearly, when you 'really' compiled the spec, the new kind of package spec
+would have to be updated (otherwise, it wouldn't necessarily match the
+source file, because the source file could have been edited). But that would
+necessarily change the serial number, and then the links would fail. And
+there would be no way to avoid the problem.
+
+Given that there is no reliable way to determine if a file has been changed
+(file time stamps are too crude, often changing when nothing actually is
+changed, and aren't kept to enough accuracy on Windows), I don't see any way
+to implement this. The compiled=changed model works fine for Ada 95, but is
+a complete failure for limited with. Essentially, you have to adopt a
+source-based model, and that is a major change.
+
+This also has a giantic impact on build tools. They'd have to be able to
+process this new clause and come up with an appropriate order in the face of
+cycles. Of course, tools just punt if that happens now.
+
+It may be I just haven't thought about it enough. But I have a lot of things
+that I need to do before I leave for the meeting, and thinking about this
+isn't high on the list.
+
+**************************************************************
+
+From: Tucker Taft
+Sent: Monday, February 3, 2003 8:53 PM
+
+Randy's comments make me notice something
+a bit unfortunate about the limited-with
+proposal. Although we don't need a new
+kind of compilation unit, we do need a new
+way of compiling a unit in the non-source-based
+environment. (I'll call this new way of compiling
+"preregistering" the unit.) Supporting limited-with
+means that either the programmer preregisters
+all compilation units on the off chance they might
+be mentioned in a limited-with, or the compilation-order-
+determination tool gets smarter and figures out which
+units need to be "preregistered" and which don't.
+
+Having this additional step could have significant
+ripple effects into "make" scripts, regression
+testing scripts, ACATS testing scripts, compilation-order-
+determination tools, etc. It also means a new
+step to explain to programmers.
+
+None of the above is particularly rocket science, but
+it does add to the implementation and "deployment" cost
+of this proposal.
+
+In general, I think this might emerge as a very
+elegant solution, possibly as elegant as the package
+prefix/abstract approach, but significantly more
+implementation effort than either the "type C.T;"
+or the possibly modified/restricted type stub proposal.
+
+By the way, although it sounds like implementing
+"type C.T;" in Randy's compiler might be a bit
+more work than a restricted type stub, it seems like that is
+small potatoes compared to the heavy lifting involved
+in the limited-with proposal.
+
+**************************************************************
+
+From: Robert Dewar
+Sent: Monday, February 3, 2003 8:53 PM
+
+BY the way, this discussion of what is and is not required of compilers
+reminds me that I think it would be good to have an annex for the standard
+that defined a standard interchange format, right down to the bit-level
+coding and file format. That would for example, partly satisy Dan's
+concern about incomaptible source representation issues.
+
+**************************************************************
+
+From: Gary Dismukes
+Sent: Tuesday, February 4, 2003 1:28 AM
+
+> But it seems like whatever solution to the mutual recursion problem we
+> choose, we really need to solve the problem of proliferation of silly
+> type conversions. Otherwise, these proposals will be nearly unusable.
+
+I tend to agree. Certainly with the latest "limited with" proposal there
+are generally going to be multiple access types for the same designated type
+and that's true for most of the other proposals as well. It seems though
+that the models using child packages may be less prone to that since
+the child package could use an access type declared in the parent
+and reexport using a subtype if needed.
+
+> That is, there ought to be an *implicit* conversion between access types
+> in the "safe" cases. I know we discussed that before. Is it part of
+> any of these proposals, or is it a separate AI? I seem to recall that
+> it might be wrapped up with other access-type issues, like allowing "not
+> null" constraints, and access-to-constant parameters.
+
+Perhaps you're thinking of AIs 230 (generalized access types) and 231
+(access-to-constant parameters and null-excluding subtypes). AI-230
+would allow more things to be declared using anonymous general access
+types, which would increase the number of contexts where implicit
+conversions can occur, though I'm not sure how much help that will be
+for the mutual-dependence cases where there will be multiple distinct
+access types and pointers of those distinct types floating around.
+I suppose it will help to some degree. In any case, I think it's
+probably best not to wrap a requirement for easier conversions in with
+the AI-217 proposals, as I think that may tend to muddy the discussion
+(even more more than it already is;).
+
+> > And I do still like that "type C.T;" ;-).
+> > (what a pain I can be...)
+>
+> That's a fine solution, IMHO. Your earlier e-mail about
+> mutually-recursive types being part of the same abstraction
+> makes me comfortable with the idea of tying the solution to
+> child packages. (See, it *is* possible to convey sensible information
+> about purely aesthetic concerns. ;-))
+>
+> But I would choose the "limited with" idea, unless it is considered too
+> hard to implement.
+
+My feeling as well. Tucker's modified child package proposal definitely
+seems the simplest both in description and implementation effort
+(well, I guess Randy doesn't agree with that...), but like others
+I'm somewhat dissatisfied with requiring a child-based model to
+get mutual recursion. I was finding my mind being drawn back to
+wishing we could just do things as simply as other languages are
+able to, but had decided that such an approach would be tilted too
+much in favor of source-based compilers. But now that Pascal's
+bravely put forward that very suggestion, I'm happy to line up behind
+it if it stands up to scrutiny. I think the critical question is how
+much work that approach will be for non-source-based implementations.
+
+**************************************************************
+
+From: Pascal Leroy
+Sent: Tuesday, February 4, 2003 4:04 AM
+
+> Perhaps you're thinking of AIs 230 (generalized access types) and 231
+> (access-to-constant parameters and null-excluding subtypes). AI-230
+> would allow more things to be declared using anonymous general access
+> types, which would increase the number of contexts where implicit
+> conversions can occur, though I'm not sure how much help that will be
+> for the mutual-dependence cases where there will be multiple distinct
+> access types and pointers of those distinct types floating around.
+> I suppose it will help to some degree.
+
+AI 230 looked quite promising, but it has been on Tuck's action item list for
+about two years, and he didn't do his homework (but then he'll have some time on
+the plane, so you never know...)
+
+> In any case, I think it's
+> probably best not to wrap a requirement for easier conversions in with
+> the AI-217 proposals, as I think that may tend to muddy the discussion
+> (even more more than it already is;).
+
+Agreed.
+
+**************************************************************
+
+From: Robert A Duff
+Sent: Tuesday, February 4, 2003 4:11 PM
+
+I don't want to muddy the discussion *too* much. But many (if not all)
+of the cyclic-dependency solutions are going to introduce extra access
+type decls. I don't want folks to reject proposals for that reason.
+Therefore, we need to at least keep an open mind -- assume that the
+access-type-conversion annoyance can be solved.
+
+**************************************************************
+
+From: Pascal Leroy
+Sent: Tuesday, February 4, 2003 3:02 AM
+
+> In Pascal's proposal, a parent package P can weakly 'with' its children:
+> "weak with P.C;", if you want a mutually dependent pair of types,
+> one in P and one in P.C. The spec of P will be elaborated before the
+> spec of P.C, as usual.
+>
+> However, it is pointless for P.C to say "weak with P;", because the
+> child-to-parent dependency is necessarily strong (given that there's no
+> proposal to add syntax saying otherwise -- "weak children?").
+>
+> No problems here. I'm just making some observations.
+
+In my proposal it would also be possible for unit P to say "limited with P", but
+I think we would want to forbid that, as it seems methodologically dubious. (If
+you follow the model to its logical conclusions, it would for instance allow
+forward references to packages and types within the spec of P.)
+
+**************************************************************
+
+From: Pascal Leroy
+Sent: Tuesday, February 4, 2003 3:21 AM
+
+> The first is where you have a type declaration that depends on another
+> type:
+>
+> type Color is (Red, Green, Blue);
+> type Properties(C: Color) is...;
+>
+> Does the incomplete type for Properties include the discriminant?
+
+I have no doubt that the incomplete type for Properties doesn't include the
+discriminant. We discussed that issue when we did "with type" and we concluded
+that any other choice was causing endless trouble.
+
+Discriminants of incomplete types are not too useful anyway, they can only be
+used in building contrained access-to-object types. And the added complexity
+is not worth it.
+
+> I prefer the choice where only private, record and tagged
+> types are incomplete in the limited view.
+
+But then you would need to do a lot of semantic analysis, and you would have to
+define very precisely what happens during a "superficial" compilation.
+Consider for instance:
+
+ type R is record ... end record;
+ type T is new Integer range R'Alignment .. R'Size;
+
+How can T be properly defined if R is incomplete? And don't tell me that T
+would be some new kind of "incomplete integer type", because that would add so
+much complexity to the language that I'd rather forget about the entire
+proposal.
+
+As Tuck pointed out in his "willies" message, the only way that this model can
+be made to work is if the first phase can be performed by a brain-dead parser.
+
+**************************************************************
+
+From: Robert I. Eachus
+Sent: Tuesday, February 4, 2003 11:38 AM
+
+Pascal Leroy wrote:
+
+>I have no doubt that the incomplete type for Properties doesn't include the
+>discriminant. We discussed that issue when we did "with type" and we concluded
+>that any other choice was causing endless trouble.
+
+About 4 AM, I realized that what is needed is the fact that Properties
+is a type with discriminants, notthing more. But we already have that
+concept well defined, and it covers incomplete tagged types. Then I went
+back to sleep. So I propose that (incomplete) tagged types and types
+like Properties have unknown discriminants. This allows incomplete
+discrete types to be treated like other incomplete types, and incomplete
+array types to also be treated as incomplete with unknown discriminants.
+
+>But then you would need to do a lot of semantic analysis, and you would have to
+>define very precisely what happens during a "superficial" compilation. Consider
+>for instance:
+>
+> type R is record ... end record;
+> type T is new Integer range R'Alignment .. R'Size;
+>
+>How can T be properly defined if R is incomplete? And don't tell me that T
+>would be some new kind of "incomplete integer type", because that would add so
+>much complexity to the language that I'd rather forget about the entire
+>proposal.
+
+The nightmare that woke me up was not quite this case, but related.
+ (Using T'First, etc., of another discrete type.Hiding the literals is
+not enough.)
+
+As for access types, I still think we need to special case those. At
+first I was only worried about the proliferation of access types with
+the same target. But then I realized that the type matching nightmare
+gets worse in cases where some of the potential access types are hidden
+by incompleteness. The messy case is X: T := F.all. F can be an
+overloaded function, and I would hate to have the legality checked
+twice, especially if one of the checks depended on elaboration order.
+
+There is another painful case though, and I am not sure what to do about
+it...
+
+limited with B;
+package A is
+ type Foo is record...end record;
+ ...
+end A;
+
+with A;
+package B is
+ type TA is access A.Foo;
+ type Bar is record
+ TAC: TA;
+ end record;
+ ...
+end B;
+
+(You can produce variations on this theme by creating a third package in
+the cycle.) We are not talking pathological here, this is part of the
+core functionality. Now, what is the status of B.TA inside the spec of
+A? If it is incomplete we get access type proliferation. If it is an
+access type, is it an incomplete access type? Inquiring minds want to know.
+
+If you prefer, write the example as:
+
+limited with A.B;
+package A is
+ type TA is access B.T;
+ ...
+end A;
+
+package A.B is
+ type T is tagged record...end record;
+ ...
+end A.B;
+
+I can live with this version working where the first one breaks, but now
+we get back to the issue of representation of the access type. Whether
+it has to be a fat pointer or not will depend on features of T. Again,
+I can live with that, we just have to determine which features are
+visible. (Unknown discriminants for T in this case seems minimal.)
+
+**************************************************************
+
+From: Tucker Taft
+Sent: Tuesday, February 4, 2003 2:20 PM
+
+"Robert I. Eachus" wrote:
+
+> About 4 AM, I realized that what is needed is the fact that Properties
+> is a type with discriminants, notthing more.
+
+Why?
+
+>... But we already have that
+>concept well defined, and it covers incomplete tagged types. Then I went
+>back to sleep. So I propose that (incomplete) tagged types and types
+>like Properties have unknown discriminants. This allows incomplete
+>discrete types to be treated like other incomplete types, and incomplete
+>array types to also be treated as incomplete with unknown discriminants.
+
+Why can't we treat these all as plain old incomplete types?
+You haven't explained that.
+
+
+>>But then you would need to do a lot of semantic analysis, and you would have to
+>>define very precisely what happens during a "superficial" compilation. Consider
+>>for instance:
+>>
+>> type R is record ... end record;
+>> type T is new Integer range R'Alignment .. R'Size;
+>>
+>>How can T be properly defined if R is incomplete? And don't tell me that T
+>>would be some new kind of "incomplete integer type", because that would add so
+>>much complexity to the language that I'd rather forget about the entire
+>>proposal.
+>>
+>The nightmare that woke me up was not quite this case, but related.
+> (Using T'First, etc., of another discrete type.Hiding the literals is
+>not enough.)
+
+I am totally lost. These types are incomplete. You can't do anything
+with them.
+
+> As for access types, I still think we need to special case those. At
+> first I was only worried about the proliferation of access types with
+> the same target. But then I realized that the type matching nightmare
+> gets worse in cases where some of the potential access types are hidden
+> by incompleteness. The messy case is X: T := F.all. F can be an
+> overloaded function, and I would hate to have the legality checked
+> twice, especially if one of the checks depended on elaboration order.
+
+I must be missing something fundamental here. All of these types are
+just plain old incomplete types. Yes, I agree we ought to special
+case tagged and allow a bit more, but that seems irrelevant to
+what you are talking about. What is messy about the messy case?
+
+>...
+>(You can produce variations on this theme by creating a third package in
+>the cycle.) We are not talking pathological here, this is part of the
+>core functionality. Now, what is the status of B.TA inside the spec of
+>A? If it is incomplete we get access type proliferation. If it is an
+>access type, is it an incomplete access type? Inquiring minds want to know.
+
+It is incomplete and we get access type proliferation.
+
+I don't see that "limited with" can solve the access type proliferation
+problem, and trying to make it do so is doomed, in my mind.
+
+...
+>I can live with this version working where the first one breaks, but now
+>we get back to the issue of representation of the access type. Whether
+>it has to be a fat pointer or not will depend on features of T. Again,
+>I can live with that, we just have to determine which features are
+>visible. (Unknown discriminants for T in this case seems minimal.)
+
+I am presuming that all non-tagged types are incomplete, period. No new
+notion of "incomplete access types" is being added.
+
+**************************************************************
+
+From: Pascal Leroy
+Sent: Tuesday, February 4, 2003 3:00 PM
+
+> > So I propose that (incomplete) tagged types and types
+> > like Properties have unknown discriminants. This allows incomplete
+> > discrete types to be treated like other incomplete types, and incomplete
+> > array types to also be treated as incomplete with unknown discriminants.
+>
+> Why can't we treat these all as plain old incomplete types?
+> You haven't explained that.
+
+I am as puzzled as Tuck. It is my understanding that unknown discriminants
+for incomplete types are pretty much equivalent to no discriminants. So
+it's fine with me to insist that these types have unknown discriminants, but
+it doesn't make the slightest difference. (Remember, we are talking
+_incomplete_ types here, so you cannot do much with them anyway.)
+
+> I am presuming that all non-tagged types are incomplete, period. No new
+> notion of "incomplete access types" is being added.
+
+Agreed. This seems like the only way to avoid madness. Granted, this
+proposal doesn't solve the problem of proliferation of access types, but
+that problem shows up in contexts that are unrelated to circular type
+dependencies, so I think that it should be addressed by a different
+mechanism.
+
+**************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, February 4, 2003 2:53 PM
+
+Tucker said, replying to Robert Eachus:
+> > If it is incomplete we get access type proliferation. If it is an
+> > access type, is it an incomplete access type? Inquiring
+> > minds want to know.
+>
+> It is incomplete and we get access type proliferation.
+>
+> I don't see that "limited with" can solve the access type proliferation
+> problem, and trying to make it do so is doomed, in my mind.
+
+At which point, I lose interest in the proposal.
+
+All of type stubs, restricted type stubs, and Tuck's type C.T idea do solve
+the access type proliferation problem. Admittedly the structure of the
+declarations is unnatural. But the only real alternative is to adopt
+something like AI-230. That bulks up the proposal a ton.
+
+So, limited with:
+ -- Is much harder to implement in library based compilers. It's probably
+harder to implement than type stubs/type C.T in source-based compilers as
+well (certainly no easier). Affects compilation tools in all environments;
+ -- Doesn't solve the access type proliferation problem.
+
+The only advantage seems to be:
+ -- A more natural expression of package structure.
+
+But that's dubious, since you need to resort to unnatural package structures
+in order to share access types. So you're pretty much left with "much harder
+to implement".
+
+**************************************************************
+
+From: Pascal Leroy
+Sent: Tuesday, February 4, 2003 3:09 PM
+
+> > I don't see that "limited with" can solve the access type proliferation
+> > problem, and trying to make it do so is doomed, in my mind.
+>
+> At which point, I lose interest in the proposal.
+
+Access type proliferation in and of itself is not a problem. What is a
+problem is access type conversions. That problem shows up in all sorts of
+contexts, notably in OOP where you have access types (class-wide or
+specific) designating some type in a hierarchy, and all conversions must be
+explicit, even those that cannot possibly fail. That is a big pain.
+
+This has nothing to do with circular type dependences. Even if we select a
+solution to the problem of circular type dependences that doesn't cause
+proliferation of access types, the problem of access type conversions will
+remain.
+
+In C, if you have a type t you automatically get a pointer type t*. In Ada,
+I often wish we had a similar capability, where I wouldn't have to declare
+all these silly access types and convert between them explicitly.
+
+**************************************************************
+
+From: Robert I. Eachus
+Sent: Tuesday, February 4, 2003 5:20 PM
+
+Tucker Taft wrote:
+
+>It is incomplete and we get access type proliferation.
+>
+>I don't see that "limited with" can solve the access type proliferation
+>problem, and trying to make it do so is doomed, in my mind.
+
+And in my mind the proposal is doomed (or not the best one on the table)
+if it doesn't address the access type proliferation problem.
+
+>I am presuming that all non-tagged types are incomplete, period. No new
+>notion of "incomplete access types" is being added.
+
+Hmm. I must not be making myself clear. My idea is not to add
+"incomplete access types," but to try to make the limited with idea work
+with access types to these new special incomplete types. The refractory
+issue is when you have access types that carry descriptor information
+and when you don't. Where that data is stored is irrelevant. Even if
+you store the descriptor for an unconstrained array type with the data
+and pointers to both unconstrained and constrained arrays are the same
+size, some conversions and assignments are impossible or require
+recopying the data:
+
+package P is
+ type Str is new String;
+ subtype Str4 is Str(1..4);
+ type PT1 is access Str;
+ type PT2 is access Str4;
+end P;
+
+or if you prefer:
+
+limited with P;
+package Q is
+ type PT3 is access P.Str;
+ type PT4 is access P.Str4;
+end Q;
+
+Now I need to compile some code--perhaps the body of Q--that needs to do
+those damned explicit type conversions, or even just some simple
+assignments. As a programmer I have a problem, but without more
+information about the types in P than Tuck seems willing to allow, the
+compiler is SOL. It doesn't know how to create objects of type PT3
+and/or PT4, and even has trouble with legality issues:
+...
+PO3: PT3;
+PO4: PT4;
+...
+PO3.all := PO4.all; -- legal?
+
+Right now the voting seems to be that either the limited with idea is
+doomed because it is too much work, or it is doomed because it can't
+deal with the issue of access type proliferation. I'll let sleeping
+dogs lie.
+
+**************************************************************
+
+From: Tucker Taft
+Sent: Tuesday, February 4, 2003 5:58 PM
+
+"Robert I. Eachus" wrote:
+>
+> Tucker Taft wrote:
+>
+> >It is incomplete and we get access type proliferation.
+> >
+> >I don't see that "limited with" can solve the access type proliferation
+> >problem, and trying to make it do so is doomed, in my mind.
+> >
+> And in my mind the proposal is doomed (or not the best one on the table)
+> if it doesn't address the access type proliferation problem.
+
+Well, I think trying to make it address this problem very tricky,
+since it means looking at the designated subtype indication,
+and that will get you back to worrying about use visibility, etc.
+
+> >I am presuming that all non-tagged types are incomplete, period. No new
+> >notion of "incomplete access types" is being added.
+> >
+> Hmm. I must not be making myself clear. My idea is not to add
+> "incomplete access types," but to try to make the limited with idea work
+> with access types to these new special incomplete types. The refractory
+> issue is when you have access types that carry descriptor information
+> and when you don't. Where that data is stored is irrelevant. Even if
+> you store the descriptor for an unconstrained array type with the data
+> and pointers to both unconstrained and constrained arrays are the same
+> size, some conversions and assignments are impossible or require
+> recopying the data:
+
+I am getting an inkling of your concern. At least one of the
+problems you seem to be worrying about is an implementation
+issue (as opposed to a semantics issue), and is one that bedevils
+the "unrestricted" type stub proposal, and the "with type"
+proposal. Namely that when choosing a representation for access types
+to the full type, the compiler may not be aware that there are
+access types to the incomplete type. I don't think this is quite
+as serious as the problem with the "with type" proposal, since
+the compiler is doing some serious peeking at the full type
+when it creates the incomplete type, so *if* it has multiple
+access type representations, it can mark the incomplete type
+with enough extra information so that it will choose an appropriate
+representation for any access type that is declared later which
+"sees" only the incomplete type.
+
+Unfortunately, derived types create a bit of a problem, since they
+don't reveal syntactically what sort of type they are (e.g.,
+whether their first subtype is an unconstrained array subtype and
+hence pointers to it should be default be "fat" pointers).
+This would mean that the "peeker" would have to make a "guess"
+about whether the incomplete type is an unconstrained array.
+Probably it would assume all derived types are not
+unconstrained arrays. In any case, whatever guess it makes,
+it would want to record that in the limited view of the package.
+When the full view is compiled, as part of the "compatibility"
+check it would also have to check that the "guess" was correct.
+If the guess was wrong, and the type is in fact an unconstrained array,
+say, then it would have to record that fact on the incomplete
+type, and bump the timestamp (or equivalent) of the limited view
+of the package. Ultimately the units that depend on this limited
+view would get recompiled.
+
+For a source-based compiler, there isn't really any place to
+permanently record the "correct" answer, so it would probably
+end up being a link-time check, and if there were an incompatibility,
+the offending units would be recompiled with a switch directing
+them to treat the problematic incomplete type as an unconstrained array,
+even though it wasn't obvious.
+
+
+>
+> package P is
+> type Str is new String;
+> subtype Str4 is Str(1..4);
+> type PT1 is access Str;
+> type PT2 is access Str4;
+> end P;
+>
+> or if you prefer:
+>
+> limited with P;
+> package Q is
+> type PT3 is access P.Str;
+> type PT4 is access P.Str4;
+
+This wouldn't be legal, since Str4 is defined by a subtype, not
+a type declaration.
+
+> end Q;
+>
+> Now I need to compile some code--perhaps the body of Q--that needs to do
+> those damned explicit type conversions, or even just some simple
+> assignments. As a programmer I have a problem, but without more
+> information about the types in P than Tuck seems willing to allow, the
+> compiler is SOL. It doesn't know how to create objects of type PT3
+> and/or PT4, and even has trouble with legality issues:
+
+I don't see how legality issues enter into the problem of access
+type representation. You can't do much of anything with incomplete types.
+And you can't dereference access-to-incomplete, unless perhaps
+there is a complete type "nearby".
+
+> ...
+> PO3: PT3;
+> PO4: PT4;
+> ...
+> PO3.all := PO4.all; -- legal?
+>
+> Right now the voting seems to be that either the limited with idea is
+> doomed because it is too much work, or it is doomed because it can't
+> deal with the issue of access type proliferation. I'll let sleeping
+> dogs lie.
+
+I don't think it has been abandoned, so it is still important
+to try to identify (real ;-) problems associated with the
+proposal.
+
+**************************************************************
+
+From: Robert I. Eachus
+Sent: Tuesday, February 4, 2003 6:34 PM
+
+Tucker Taft wrote:
+
+>Well, I think trying to make it address this problem very tricky,
+>since it means looking at the designated subtype indication,
+>and that will get you back to worrying about use visibility, etc.
+
+Yep.
+
+...
+>For a source-based compiler, there isn't really any place to
+>permanently record the "correct" answer, so it would probably
+>end up being a link-time check, and if there were an incompatibility,
+>the offending units would be recompiled with a switch directing
+>them to treat the problematic incomplete type as an unconstrained array,
+>even though it wasn't obvious.
+
+Yep, it is a problem in any solution to the mutual dependence problem.
+ The issue here is deciding what aggrevations to add--to the user, the
+implementor, or both. We could make fairly draconian rules that stated
+that any unit that actually uses a subtype, access type to, or type
+derived from one of these magic incomplete types must depend on the
+limited withed unit, and thus see the full type. I think so far this
+has been an implicit assumption, but the devil is in the details.
+
+To take your discussion above a bit further, what happens when you
+modify the limited withed unit in a way that changes the necessary
+representation of an access type declared elsewhere? It begins to look
+like a very real dependence somehow magically wished away. You end up
+having to recompile some units due to changes in units they don't depend
+on....
+
+>I don't think it has been abandoned, so it is still important
+>to try to identify (real ;-) problems associated with the
+>proposal.
+>
+Consider the (dead) horse to have been additionally flogged.
+
+**************************************************************
+
+From: Robert A Duff
+Sent: Tuesday, February 4, 2003 7:06 PM
+
+Note that we already have a case where you can create
+access-to-incomplete without knowing what the complete type
+looks like. Namely, an incomplete type declared in a package
+spec, and completed in the body.
+
+**************************************************************
+
+From: Robert I. Eachus
+Sent: Tuesday, February 4, 2003 10:34 PM
+
+What did we used to call that? Ah, yes, I remember the Tucker Taft
+amendment. ;-) The only good thing about it was that the incomplete
+type had to be private, so it couldn't be seen outside the package.
+
+If you weren't following LMC/ARG actions then look up (Ada-83) AI-7.
+ For one meeting, John Goodenough put the AI's for consideration in two
+books--AI-2 and AI-7, plus related AI's, and everything else. (The
+final version of AI-00007/19-BI-WJ--yes that is version 19--is actually
+a consolidation of about a dozen separate AI's)
+
+As I recall, AI-7 underwent combinatorial explosion, we discovered lots
+of nits and crannies, and finally came up with a smoking gun case that
+did not require the TTA to fire off. But if you think my concern about
+access to incomplete types with discriminants is overdone, you really
+should go back and look at all those AI's. As I recall, the final
+version of AI-7 allowed the legality check on discriminant constraints
+of access to incomplete objects to be done in one of three
+places--because there were cases when each of the three wouldn't work,
+and in some cases more than one.
+
+Any "solution" to the interlocking types problem that re-opens that can
+of worms should be shot then burned and the ashes stirred and buried
+under a crossroads at midnight. I think net that AI-7 and its relatives
+took the equivalent of several three-day meetings to resolve. (This was
+"fixed" in Ada 95 by deferring all compatibility checks until object
+creation.
+
+**************************************************************
+
+From: Pascal Leroy
+Sent: Tuesday, February 4, 2003 3:55 AM
+
+> At the moment, I think it's too hard to implement (given that type stubs are
+> expected to take 4 hours of work; this would be more like 4 weeks). But that
+> may be irrelevant. More important is that I don't see any way, within the
+> current design of Janus/Ada, to implement something like this.
+
+Not sure how you came up with the 4 hours estimate, but I'm sure it would take
+me more than that to do a detailed design. At this point I'd say that the
+implementation effort for any of these proposals would be in the range 4 weeks
+.. 4 months, and I can't be more specific without doing a detailed analysis.
+But anyway, I don't think that numbers are very interesting at this point. It's
+really the essence of the implementation difficulties that need to be looked at.
+
+As far as I can tell, you and I have the same set of problems, because we are
+both library-based. I realize that the devil is in the details, and that the
+magnitude of changes can vary substantially from one implementation to another,
+but I don't buy that the "limited with" proposal would force you to go to a
+source-based model. (For Rational, going to a source-based model is a no-no;
+we'd rather get out of the Ada business; so hopefully there has to be an
+implementation technique where we stick to our current library model.)
+
+> The problem is with the obsoleteness check. Janus/Ada uses a serial number
+> created from the time stamp of the symbol table file created for a library
+> unit for checking. Also, the Janus/Ada compiler knows nothing about source
+> files other than the one it is compiling at the moment. (Other tools are a
+> bit smarter, but the compiler does not use that information itself.) It only
+> knows about symbol table files.
+
+Fine. If I substitute "Diana tree" for "symbol table", that's essentially true
+of Apex too. (Ignoring all the incremental compilation crap.)
+
+> One presumes that you'd have a new kind of symbol table file that held a
+> 'lightly' compiled package spec for limited withs. And you'd use the time
+> stamp of that file to create the serial number for obsoleteness checking.
+> Clearly, when you 'really' compiled the spec, the new kind of package spec
+> would have to be updated (otherwise, it wouldn't necessarily match the
+> source file, because the source file could have been edited).
+
+And we would indeed have the same problem. We would first created a "parsed"
+Diana tree (during "superficial" compilation) and then we would rewrite it to
+make it "analyzed" (during "full" compilation). Surely that would change the
+timestamp.
+
+> But that would
+> necessarily change the serial number, and then the links would fail. And
+> there would be no way to avoid the problem.
+>
+> Given that there is no reliable way to determine if a file has been changed
+
+The way that I plan to do this is to store in the "parsed" Diana tree (what you
+call the "light symbol table") a hash code. This hash code could be based on
+the sequence of tokens in the source, or it could be more clever and be based
+only on the names of types and packages (the information that is available after
+"superficial" compilation). Whenever clients currently use a timestamp to check
+for obsolescence, they would use the combination <timestamp, hash>. If the
+timestamps match, everything is fine. Otherwise, the Diana trees need to be
+opened, and the hashes need to be compared. I realize that this will result in
+some extra open system calls, but Ada's separate compilation already requires a
+zillion system calls, so I won't lose any sleep on that.
+
+Of course, a hash code is not exactly 100% safe, as there could be collisions.
+But if you design it well enough, you won't see a collision in your lifetime.
+(We use 96-bit hash codes all over the place for incremental compilation, and we
+have never run into a collision in all these years.)
+
+> This also has a giantic impact on build tools. They'd have to be able to
+> process this new clause and come up with an appropriate order in the face of
+> cycles. Of course, tools just punt if that happens now.
+
+But the trick is that there are no prerequisites for "superficial" compilation.
+So one approach is to blindly run "superficial" compilation over all the units,
+in any order you like (e.g. the order of i-nodes in the filesystem if you like).
+And then run "full" compilation in an order compatible with normal with clauses
+and other semantic dependencies, just like you do now (and ignoring "limited
+with" clauses). No need to process the new clause, no need to change the
+algorithm that determines the compilation order.
+
+Of course you might want to be more clever and avoid the "superficial" phase if
+it's not needed, but that's an optimization, not something you would have to do
+for correctness.
+
+**************************************************************
+
+From: Pascal Leroy
+Sent: Tuesday, February 4, 2003 4:00 AM
+
+> Supporting limited-with
+> means that either the programmer preregisters
+> all compilation units on the off chance they might
+> be mentioned in a limited-with, or the compilation-order-
+> determination tool gets smarter and figures out which
+> units need to be "preregistered" and which don't.
+
+As I mentioned in my previous response to Randy, it would be just fine if the
+compilation-order-determination tool were to systematically preregister each and
+every unit, and then run the normal ordering algorithm, ignoring "limited with"
+clauses. I would think that compiler writers would prefer to go that way,
+rather than breaking each and every compilation script in the universe. So I am
+arguing that the new step should be essentially invisible to programmers.
+
+In an implementation where the preregistration step would be costly, then yes,
+the ordering algorithm might have to be modified to avoid preregistration when
+possible.
+
+**************************************************************
+
+From: Erhard Ploedereder
+Sent: Tuesday, February 4, 2003 7:38 AM
+
+I like "limited with". It is the closest we got to what the user expects.
+I would like to see a writeup.
+
+(I have had bellyaches with Tuck's proposal of tying the cyclic dependency
+ to child packages. I waited for the aches to go away. They did not.)
+
+**************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, February 4, 2003 3:00 PM
+
+> > At the moment, I think it's too hard to implement (given that type stubs are
+> > expected to take 4 hours of work; this would be more like 4 weeks). But that
+> > may be irrelevant. More important is that I don't see any way, within the
+> > current design of Janus/Ada, to implement something like this.
+>
+> Not sure how you came up with the 4 hours estimate, but I'm sure it would take
+> me more than that to do a detailed design.
+
+I did a detailed design (in my head) when I was unable to sleep Saturday
+night.
+
+> At this point I'd say that the implementation effort for any of these proposals
+> would be in the range 4 weeks .. 4 months, and I can't be more specific without
+> doing a detailed analysis. But anyway, I don't think that numbers are very
+> interesting at this point. It's really the essence of the implementation
+> difficulties that need to be looked at.
+
+The reason I was thinking about it was that the restricted type stubs model
+pretty much matches how Janus/Ada works internally anyway. So the main cost
+is "connecting" the stub to the completion. (And many stubs works, because
+it's a one-way pointer. But I wouldn't expect that to be true on other
+implementations.) Since incomplete and private types use the same code in
+most circumstances, the visibility implications of "availability" should be
+free. (That is the biggest assumption, of course, because there are no such
+rules in Ada 95.) So all of the work is doing the connection, and a brute
+force version (walk all of the symbol table looking for stubs, then when a
+stub is found, walk the whole symbol table looking for a connection) would
+only need to be called in one place. Most of the work is figuring out where
+to call that routine. A better version would save the stubs in a list as
+they are loaded, so we wouldn't have to search for them. That version would
+have no distributed cost and not a lot of cost even when stubs are used, so
+I doubt its possible to do better.
+
+Tucker's C.T adds a lot of messing around with ghost packages, but otherwise
+is identical (we don't have to look quite so far for a completion, but the
+process is the same). Which is why I'm certain its more work.
+
+The current stub stubs requires two stubs of the same completion to match,
+even when the completion isn't available. That's more work, but I don't
+think it's a very significant amount (it's just another weird special case
+in the type matcher, just like anonymous access types and T'Class).
+
+In all of these cases, I wouldn't be surprised to find glitches, but that
+would require a pretty complete test suite. Building that would take longer
+than doing the implementation (that is often true).
+
+Limited with would require a new kind of symbol file, or something (Pascal
+suggests a hash). It also would require going in an adding a bunch of stuff
+to the make tool. No one understands how that thing really works, so that
+alone is a daunting project. And the failure to provide any sort of solution
+to the access type problem makes it feel like "with type" all over again
+(which isn't surprising, because it *IS* essentially "with type", just as
+"type C.T" is just a different syntax for type stubs).
+
+**************************************************************
+
+From: Pascal Leroy
+Sent: Tuesday, February 4, 2003 3:17 PM
+
+> Since incomplete and private types use the same code in
+> most circumstances, the visibility implications of "availability" should be
+> free.
+
+Aren't you concerned about types having three views (incomplete, partial,
+full) in the case of an incomplete type completed by a private type? That
+gives me the willies, to borrow Tuck's words, because it's currently very
+complicated in our compiler to decide what properties of a type are visible
+at a given place (because of the separation between partial and full view,
+because of characteristics that become visible "later within the immediate
+scope", etc.). Adding a third view is not going to make this easier.
+
+**************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, February 4, 2003 3:43 PM
+
+No, because we have separate type records for each view, and they have their
+own visibility. For type matching purposes, the only question is whether you
+can or cannot walk the pointer to the 'next' view, as we always match (and
+use for other purposes) the "fullest" view available. That depends on
+visibility, etc. (We have a separate set of routines that always goes to the
+completion, which the intermediate code generation uses. To heck with
+visibility at that point.) Since this stuff is recursive (well, actually it
+uses a loop), you'd first try to go from the incomplete block to the private
+block (depending on the visibility of the private), and then, once you had
+the private, you'd do the checks that we currently have. So I don't see a
+problem with three parts or ten parts for that matter.
+
+But I realize that if you somehow managed to implement types with a single
+record for both views (we tried that and concluded it was impossible. But
+perhaps we weren't clever enough. Or perhaps its impossible because of
+shared generics.), it might be much worse.
+
+But I think that any proposal has to allow stubs (or whatever) of private
+types. So you're going to have the three view issues, and if that is a
+problem, any solution to this problem will be a nightmare to implement. In
+which case you ought to stay out of the implementation difficulty debate
+altogether. :-) :-)
+
+**************************************************************
+
+From: Gary Dismukes
+Sent: Tuesday, February 4, 2003 3:20 PM
+
+Pascal wrote:
+> In my proposal it would also be possible for unit P to say "limited with P", but
+> I think we would want to forbid that, as it seems methodologically dubious. (If
+> you follow the model to its logical conclusions, it would for instance allow
+> forward references to packages and types within the spec of P.)
+
+One question is, what does it mean when you say "limited with P.C.D".
+Is it equivalent to having limited with for P, P.C, and P.C.D, in
+analogy with normal with clauses? That was my first thought, and
+it seems natural to make it behave the same, but perhaps it's more
+reasonable to say it only applies to the final named unit. That
+would avoid the issue of self-circular references when a parent
+withs its child and we would also want the rules to disallow
+a direct limited with of yourself.
+
+Another small issue is whether use clauses are allowed for packages
+named in these with clauses. I imagine that the implementation is
+effectively going to create a package entity containing an incomplete
+type representative for each type in the real package's visible part
+(along with representatives for any nested packages presumably)
+and since this will look essentially the same as other packages
+in the symbol table environment I don't see any technical problem
+with permitting a use clause for these packages. Perhaps there are
+methodological reasons for not allowing it, though I can't think
+of any. Changing a limited with to a normal with could introduce
+new illegalities due to name clashes, but that's no worse than
+adding a new with and use clause for some package.
+
+**************************************************************
+
+From: Pascal Leroy
+Sent: Tuesday, February 4, 2003 3:30 PM
+
+> One question is, what does it mean when you say "limited with P.C.D".
+> Is it equivalent to having limited with for P, P.C, and P.C.D, in
+> analogy with normal with clauses? That was my first thought, and
+> it seems natural to make it behave the same, but perhaps it's more
+> reasonable to say it only applies to the final named unit. That
+> would avoid the issue of self-circular references when a parent
+> withs its child and we would also want the rules to disallow
+> a direct limited with of yourself.
+
+From a pedagogical standpoint it would seem simpler to say that "limited
+with" works like "with", i.e. that "limited with P.C.D" is equivalent to
+"with P, P.C, P.C.D". Any other option is going to unnecessary confuse
+users.
+
+So maybe the right answer is that if a package has a "limited with" of
+itself it has no effect (but is not illegal).
+
+> Another small issue is whether use clauses are allowed for packages
+> named in these with clauses. I imagine that the implementation is
+> effectively going to create a package entity containing an incomplete
+> type representative for each type in the real package's visible part
+> (along with representatives for any nested packages presumably)
+> and since this will look essentially the same as other packages
+> in the symbol table environment I don't see any technical problem
+> with permitting a use clause for these packages.
+
+Yes, I was thinking that use clauses and package renamings would be OK in
+that context, although if they lead to problems we could disallow them. But
+I can't think of any problem at this point.
+
+**************************************************************
+
+From: Robert Dewar
+Sent: Tuesday, February 4, 2003 10:19 PM
+
+> In C, if you have a type t you automatically get a pointer type t*. In Ada,
+> I often wish we had a similar capability, where I wouldn't have to declare
+> all these silly access types and convert between them explicitly.
+
+For some reason, I never really understood it, this proposal, which I was strongly
+in favor of, never got significant support (I had suggested early on calling it
+type'access).
+
+**************************************************************
+
+From: Tucker Taft
+Sent: Tuesday, February 4, 2003 3:27 PM
+
+In discussing this further with Bob Duff, and mulling it over
+more in my mind, I see the following restrictions would probably
+be needed on the "limited with" capability. I am using the term
+"limited view" of a package to be what you get when you mention
+a package in a limited-with-clause. I am presuming that a limited
+view of a package contains only nested packages and types, and all
+the types are [tagged] incomple.
+
+A "limited with" *cannot* make the following declarations visible:
+ 1) Package instantiation
+ Because the generic being instantiated needs to be visible
+ if we are to determine what types it contains, and identifying
+ the generic may require resolving a name that is only use-visible,
+ or that is from some other compilation unit
+
+ 2) Package renaming
+ Because the package being renamed needs to be visible
+ if we are to determine what types it contains, and identifying
+ the renamed package may require resolving a name that is only use-visible,
+ or that is from some other compilation unit
+
+A "limited view" of a package *cannot* be mentioned in:
+ 3) A "use" clause
+ Because we can get a funky kind of Beaujolais effect if we have
+ a "use" clause for two different packages, and due to
+ changing a "normal" with clauses inherited from some ancestor unit
+ the meaning of an identifier switches from one thing to another; e.g.:
+
+ package A is
+ X : Integer := 7;
+ end A;
+
+ package B is
+ X : Integer := 203;
+ end B;
+
+ with A; -- change this to "with B;" and see what happens
+ package P is end;
+
+ limited with A, B;
+ use A;
+ use B; -- Probably shouldn't be allowed if only have limited view
+ package P.C is
+ Y : Integer := X; -- which X is this?
+ end P.C;
+
+ This is presuming that if we were to allow a "use" clause for a limited
+ view of a package, it would make only the types and subpackages directly visible.
+ If the "use" clause made everything in the package visible part
+ visible, but only the types were actually "usable" that could work,
+ but having visible but unusable declarations of *all* kinds,
+ rather than just types and packages, could significantly increase the effort
+ of building up a limited view.
+
+ 4) A package renaming declaration
+ This restriction is probably not as critical as the others.
+ The problem comes when someone from outside the unit containing
+ the limited with references this package renaming. What does it see?
+ If it has a "regular" with for the target of the limited-with, does
+ it see the "full" view of the package via the renaming, or only the
+ limited view of it.
+
+Possible restriction (4) brings up the issue of the opposite situation, where
+a given unit has a limited view on a package, but also has visibility
+on a renaming of a full view of the package. There seem to be various
+possibilities:
+
+ a) The renaming also provides only a limited view when referenced from the given unit.
+ b) The given unit has a full view of the package, through either the
+ renaming or the name introduced by the limited-with clause
+ c) The given unit has a limited view via the name introduced by the limited-with
+ clause, and a full view via the renaming, and they are essentially
+ completely unrelated packages.
+ d) (c), except the packages are recognized as different views of the same
+ package, and the incomplete types in the limited view are recognized
+ as being completed in the renaming, and so are treated as non-limited
+ types for all intents and purposes.
+
+(a) is probably the most consistent with the way package renamings work now,
+in that what children you see via a renaming of a library unit package is determined
+by the "with" clauses in the unit referencing the renaming, rather than by the
+with-clauses in the unit containing the renaming.
+
+(b) and (d) are both similar to the choice I suggested for "type C.T;" where
+if the completing type declaration is visible (including presumably via
+a renaming), then the incomplete type declaration is hidden from
+all visibility. In the "type C.T;" proposal, this presumably implies
+that it is as though the "type C.T;" declaration were not there at all,
+so if a renaming "package R renames C;" is visible, but "C" itself is
+not visible (because C was not directly "withed"), then you *cannot*
+refer to the type at all via "C.T." You can refer to it via "R.T"
+and then of course it is a full type.
+
+There are other possible ways of handling this for "type C.T;"
+but this approach required the smallest change to 18.3(19) and at
+least makes some kind of sense.
+
+For all proposals, the issue of visible renamings of the enclosing package
+when the package itself is not visible is thorny. A related question is when the
+completing type is *not* visible (including not via a renaming), but a declaration of a subtype
+*is* visible, or an object of the type is visible. The questions are always:
+
+ i) Is the type named via the "limited view" name complete or incomplete?
+
+ ii) If incomplete, does it nonetheless "match" the complete type in certain
+ contexts?
+
+To put it more concretely:
+
+ package P1 is
+ type A is access <incomplete view of type P2.T>;
+ -- incomplete view is visible via a limited with, type stub, type C.T, or whatever
+ Y, Z : A;
+ end;
+
+ package P2 is
+ type T is <full type definition>;
+ end P2;
+
+ with P2;
+ package P3 is
+ X : <subtype of complete view of P2.T>;
+ end P3;
+
+ with P1, P3; -- No "with" of P2, no visibility on P2.T
+ procedure P4 is begin
+ ...
+ P3.X := P1.Y.all; -- when is this legal? (*)
+ P1.Y.all := P3.X; -- same question (**)
+ if P1.Y.all = P1.Z.all then -- same question (***)
+ ...
+
+Hopefully the answers to (*) and (**) are the same, though
+the asymmetric Name Resolution wording of 5.2(4) on assignment
+statements seems like (*) and (**) might be treated differently
+unless we are careful.
+
+Note that last time we worked on the "availability" rules for type stubs,
+we required that either we be in the scope of a with clause for
+the enclosing package (or a renaming thereof, I presume), or we be in a context
+where we have the complete type "nearby" (I forget the wording at this
+point). This would say that having a visible (but not "with"ed)
+renaming of the enclosing package, or having a visible subtype,
+wouldn't help. For the above cases, this would mean that probably
+(*) and (**) would be legal, but (***) would not be legal.
+
+Have a nice day... ;-)
+
+**************************************************************
+
+From: Tucker Taft
+Sent: Tuesday, February 4, 2003 3:48 PM
+
+Pascal Leroy wrote:
+> Randy wrote:
+> > One presumes that you'd have a new kind of symbol table file that held a
+> > 'lightly' compiled package spec for limited withs. And you'd use the time
+> > stamp of that file to create the serial number for obsoleteness checking.
+> > Clearly, when you 'really' compiled the spec, the new kind of package spec
+> > would have to be updated (otherwise, it wouldn't necessarily match the
+> > source file, because the source file could have been edited).
+>
+> And we would indeed have the same problem. We would first created a "parsed"
+> Diana tree (during "superficial" compilation) and then we would rewrite it to
+> make it "analyzed" (during "full" compilation). Surely that would change the
+> timestamp...
+
+After talking with Bob Duff about this a bit, I don't think this
+really works. I think you need to keep around indefinitely both a "full view"
+of the package and a "limited view" of the package. Even after you
+do a "full" compile, some units can still do "limited with" and should only
+see the limited view. What I would recommend is you treat them as
+pretty much distinct units. When you fully compile, if there is a limited
+view already present, you could check that it is compatible with the full view
+(i.e. has the same names in the package/type tree, and the same types are
+tagged).
+
+I think if they are not compatible, then and only then does it seem worth
+obsoleting the limited view and any units compiled against it. There seems no
+point in hashing the incomplete view, since it is easy enough to check
+compatibility. Hashing would only be an optimization if this compatibility
+check turned out to be really expensive.
+
+If a unit requests a limited view, and the only non-obsolete thing you have around
+is the full view, I would at that point create the limited view from the full view.
+I would bump the time stamp on the limited view only when it is created or updated,
+and units compiled against the limited view only worry about that time stamp.
+The time stamp of the full view is irrelevant to them.
+
+**************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, February 4, 2003 4:13 PM
+
+"Easy enough to check compatibility"? You've got to be kidding. The only
+thing that we know how to do with a symbol file is load them into a symbol
+table. But you can't do that to "check compatibility", because you've got to
+load the full view into the same place (can't have two packages with the
+same library-level name).
+
+Pascal's hash idea (instead of a time stamp) makes much more sense. You'd
+create the limited symbol file for every compilation (full and limited) that
+you did, but the hash would only change if it actually is different.
+
+Keep in mind that no one actually "obsoletes" anything. How we do
+obsoleteness checking is simply to compare the time stamp serial numbers of
+every unit withed transitively for every unit withed. They better all match.
+Any mismatch is reported as an error, and the compilation aborted. And we of
+course repeat the check when linking. We use the order only to provide
+better error messages, and units are NEVER removed from the program library
+(unless the programmer does so manually).
+
+**************************************************************
+
+From: Tucker Taft
+Sent: Tuesday, February 4, 2003 5:05 PM
+
+> "Easy enough to check compatibility"? You've got to be kidding. The only
+> thing that we know how to do with a symbol file is load them into a symbol
+> table. But you can't do that to "check compatibility", because you've got to
+> load the full view into the same place (can't have two packages with the
+> same library-level name).
+
+This is my whole point. You *do* need to have both views available
+at once, since one unit might have a "limited with" of package P,
+while some unit that it depends on indirectly has a full "with" of P.
+To avoid ripple effects, we want the one with the limited-with
+to only see the limited view.
+
+You mentioned in another note that you have separate symbol table
+entries for various different forms of a type. I think you will
+need separate symbol table entries for the limited view and
+the full view. In other words, for a library package P, you really have two units,
+one whose library-level name is "P-full" and one whose name is "P-limited".
+
+> Keep in mind that no one actually "obsoletes" anything. How we do
+> obsoleteness checking is simply to compare the time stamp serial numbers of
+> every unit withed transitively for every unit withed. They better all match.
+
+Yes, I understand that approach. I probably should have simply
+talked in terms of bumping time stamps. I think the same
+point can be made in those terms. We have a similar model,
+albeit only in the program library we build up in memory.
+[Since we allow the compiler to run for a "long" time and
+to process different versions of the same file during a single
+execution, we have all the obsoleteness checking mechanism
+in there as well.]
+
+**************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, February 4, 2003 5:34 PM
+
+> This is my whole point. You *do* need to have both views available
+> at once, since one unit might have a "limited with" of package P,
+> while some unit that it depends on indirectly has a full "with" of P.
+> To avoid ripple effects, we want the one with the limited-with
+> to only see the limited view.
+
+I don't see that. Each compilation has its own symbol table, and I don't see
+any reason why the mere fact of withing something that saw a limited view of
+some package was anything to do with a package that sees the full view.
+
+> You mentioned in another note that you have separate symbol table
+> entries for various different forms of a type.
+
+No, "types" aren't in the symbol table at all. They have their own separate
+table. Type names are in the symbol table, of course, as are component
+names. But a type name has nothing to do with a type -- they're completely
+separate concepts (as they are in Ada).
+
+> I think you will
+> need separate symbol table entries for the limited view and
+> the full view. In other words, for a library package P, you really have
+> two units, one whose library-level name is "P-full" and one whose name
+> is "P-limited".
+
+If that's true, we're getting into horrific complexity territory. A
+fundamental basis of the symbol table is that most entities have only one
+name and cannot be overloaded. You're asking that all of the lookup code be
+changed to be able to handle packages with two views. Along with all of the
+declaration code (so it can write into the correct view). Moreover, that
+would be true in every compiler (source based or library based).
+
+If the proposal requires both copies in the symboltable, then I think the
+proposal should be killed as soon as possible. If not sooner.
+
+**************************************************************
+
+From: Pascal Leroy
+Sent: Wednesday, February 5, 2003 3:40 AM
+
+> I think you need to keep around indefinitely both a "full view" of
+> the package and a "limited view" of the package. Even after you
+> do a "full" compile, some units can still do "limited with" and should only
+> see the limited view. What I would recommend is you treat them as
+> pretty much distinct units.
+
+In terms of language description, you're right, a unit that does a "limited
+with" must see the limited view even for a unit that has been fully compiled.
+
+However, the implementation you suggest might make sense for your compiler, it
+doesn't make sense for ours (or for Randy's if I understand him right). We
+fundamentally depend on the invariant: 1 Ada unit = 1 Diana tree. Changing this
+is not an option. This means that if we see "limited with P" and P has been
+fully compiled, then we need to simulate/synthesize a limited view for P.
+
+For name resolution, this is simple enough. When we see the name P.T we do a
+lookup of the string "T" in the identifier table for P. The lookup has to
+succeed if and only if T is part of the limited view. We would probably do that
+by examining the Diana tree for T. Another option would be to store a bit "yes,
+I am part of the limited view" on the defining identifier for T.
+
+Once name resolution has been done, we will have access to the full tree for T.
+At this point we will need to behave as if T was incomplete. I can think of at
+least 3 ways to achieve this in our compiler, but the simplest one is probably
+to use a predicate "is this an incomplete type?" where appropriate, and have
+that predicate determine whether visibility was obtained though a "limited
+with". We already have such a predicate, but I'm pretty sure that we don't call
+it everywhere it would be needed.
+
+This certainly looks like work, but we are not talking man-years here. And
+there is certainly no need to keep two trees for each unit.
+
+**************************************************************
+
+From: Jean-Pierre Rosen
+Sent: Wednesday, February 5, 2003 3:32 AM
+
+> Add a legality rule:
+>
+> A library_item mentioned in a limited_with_clause shall be a
+> package_declaration[, not a subprogram_declaration, generic_declaration,
+> or generic_instantiation].
+
+Why not generic_instantiation?
+1) not really different from a package declaration
+2) quite useful, since instantiations are commonly used for building objects with
+ multiple facets.
+
+Later you say:
+>We do not allow a limited_with_clause to mention a generic
+>instantiation, because that would require all kinds of semantic analysis
+>stuff, such as visibility.
+Well, the instantiation has been compiled at that point, so all visibility
+should be solved.
+Maybe worth some further investigation
+
+**************************************************************
+
+From: Pascal Leroy
+Sent: Wednesday, February 5, 2003 3:59 AM
+
+The restriction is perfectly sensible. We don't want to have to do any name
+resolution to build the limited view, and in order to determine what generic we
+are talking about, we would have to do a pretty extensive name resolution (use
+clauses, parent units, renamings, etc.). Moreover, in order to build the
+instantiation, we would have to have compiled the specification of the generic
+already, but limited views cannot have compilation prerequisites (if they had,
+we could run into circularity problems).
+
+**************************************************************
+
+From: Robert A. Duff
+Sent: Wednesday, February 5, 2003 8:22 AM
+
+Tucker and I discussed this issue yesterday, and we decided that
+although it *is* troubling to make rules that cause package instances to
+be different from normal packages, it is not feasible to implement the
+proposal (in some compilers) without this restriction.
+
+If there's a cycle, then the instantiation might *not* have been
+compiled yet. How about:
+
+ limited with A;
+ package B is new Some_Generic(...);
+
+ limited with B;
+ package A is new Some_Generic(...);
+
+It cannot be the case that A and B have both been *fully* compiled
+before each other.
+
+I really think a key feature of this proposal is that when the compiler
+sees "limited with X", it can determine the list of incomplete types in
+X in a purely syntactic manner. It should not have to do any kind of
+heavy-duty semantic analysis. It should not have to look at any source
+text outside of X.
+
+It's not *so* bad, because if you wanted to do cycles like the above,
+you can always break the cycle by adding more generic formal parameters.
+
+**************************************************************
+
+From: Jean-Pierre Rosen
+Sent: Wednesday, February 5, 2003 11:28 AM
+
+Yes. I see the problem, and I have sympathy for the poor compiler writers.
+
+But with my teacher's hat on, I don't feel very easy to explain that in some
+cases, an instantiation is not equivalent to a regular package.
+
+**************************************************************
+
+From: Tucker Taft
+Sent: Wednesday, February 5, 2003 5:47 AM
+
+Pascal Leroy wrote:
+>...
+
+>
+> From a pedagogical standpoint it would seem simpler to say that "limited
+> with" works like "with", i.e. that "limited with P.C.D" is equivalent to
+> "with P, P.C, P.C.D". Any other option is going to unnecessary confuse
+> users.
+>
+> So maybe the right answer is that if a package has a "limited with" of
+> itself it has no effect (but is not illegal).
+
+Yes, that is preferable.
+
+> Yes, I was thinking that use clauses and package renamings would be OK in
+> that context, although if they lead to problems we could disallow them. But
+> I can't think of any problem at this point.
+
+I sent a note about this, titled "Restrictions on limited-with".
+Have you seen it? Any comments?
+I think "use" clauses are a bad idea.
+Renaming is tricky, and needs careful thought.
+
+**************************************************************
+
+From: Pascal Leroy
+Sent: Wednesday, February 5, 2003 6:23 AM
+
+Yes, I saw it, but after sending the above message. I agree that use clauses
+cause a Beaujolais-ish effect (maybe this should be named the Chianti effect ;-)
+and should be disallowed. I also agree that renamings should probably be
+disallowed since they cause more trouble than they are worth.
+
+**************************************************************
+
+From: Robert Dewar
+Sent: Wednesday, February 5, 2003 7:18 AM
+
+So far it seems to me that the limited-with discussion looks like it
+is very promising. I must say I was unhappy with the idea of furiously
+trying to get a resolution in Padua (and I was trying to figure out
+how to molest my schedule to attend :-) but now I am actually getting
+some confidence that
+
+a) this is going in the right direction
+b) there really is a good possibility of agreement
+
+Very encouraging :-)
+
+We will definitely try to prototype this in GNAT as soon as there is a
+reasonably well defined proposal.
**************************************************************
Questions? Ask the ACAA Technical Agent