CVS difference for ais/ai-00359.txt

Differences between 1.2 and version 1.3
Log of other versions for file ais/ai-00359.txt

--- ais/ai-00359.txt	2003/09/30 02:01:14	1.2
+++ ais/ai-00359.txt	2003/10/29 22:54:14	1.3
@@ -556,3 +556,1319 @@
 
 ****************************************************************
 
+From: Robert Dewar
+Sent: Monday, September 29, 2003  9:00 PM
+
+> 2) The changes to the elaboration model of instantiations are substantial.
+> Ada 83 is carefully designed so that once an instantiation is elaborated, no
+> elaboration checks are needed on the use of anything in that instantiation.
+> Changing that will have gigantic effects all over compilers - most of the
+> elaboration assumptions will be invalid. (I wonder what this would do to the
+> GNAT static elaboration model?)
+
+AARGH! indeed this would be a major implementation pain, that's very
+delicate code, and I think the result would be serious upwards
+incomaptibilities with existing elaboration rules. This would need
+VERY careful looking at.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Monday, September 29, 2003  9:51 PM
+
+This seems to be exactly the kind of discussion that
+is best done in person at an ARG meeting.  I hope we
+will get some time on the agenda for this (but I
+recognize we should put a time limit on the discussion).
+
+
+Randy Brukardt wrote:
+
+> I said:
+>
+>
+>>But, merits of the problem aside, does it bother others (like it does me)
+>>that the proposed 'solution' is to change the freezing and elaboration
+>
+> rules
+>
+>>of the language in order to 'fix' what is essentially a visibility
+>
+> problem?
+
+I don't see this as a visibility problem.  It is
+exactly a freezing problem.  The freezing rules for generic
+instantiation effectively require that the actual type be
+completely defined, whereas all the other type
+composition constructs (arrays, records, access-to-T, protected, ...)
+can use private types or other not-yet-completely-defined
+types.  This is the problem, and I don't see any good
+solution other than allowing a generic to take a
+not-yet-completely-defined type as an actual.
+
+I don't see any fundamental problem with the static elaboration
+order checks, since we are only deferring the body elaboration
+to later within the same list of declarations, something
+that the static elaboration order stuff already has to deal
+with for local subprograms, local packages, etc.
+
+It might make sense so as to protect privacy and order of elaboration
+of instance bodies, to say that if one generic instance
+has its body deferred to a "general" freezing point, then
+so do all instance bodies that occur after the first
+instance and prior to the next general freezing point, with
+the original order of instances preserved when elaborating the
+deferred bodies.  This would mean that the only calls that
+reach a subprogram inside a generic instance between the
+elaboration of its instance spec and its instance body would
+be calls coming from code directly within the list of declarations
+following the instantiation, further simplifying static
+elaboration order checking.
+
+>>What Bob needs is a partial view of a generic to go along with partially
+>>viewed type.
+
+I doubt it. Bob really wants the flexibility afforded to
+private types now, namely that you can define one in terms
+of another before either is fully defined.  I don't see how
+you can do this with a "partial view."  Presumably you are
+only making incomplete types visible in this partial view.
+He typically buries the level of indirection inside the
+generic for something like an extensible sequence, so
+he wants to be able to put the sequence-of-T as a direct
+component of T.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Monday, September 29, 2003  9:51 PM
+
+P.S. This whole thing need only apply to package instances.  There seems
+to be no reason to ever defer elaboration of a subprogram
+instance body, since the elaboration doesn't do anything other
+than set an elaboration bit, and if you want to declare an operation
+on a private type and implement it using a subprogram instance, we can
+already do that using renaming-as-body, avoiding any freezing
+problems.  So this would mean that the existing situation where
+a subprogram instance doesn't need an elaboration bit would
+be preserved.  (There is no equivalent to renaming as body
+for a package, because the package spec might be defining
+types which are referenced immediately after the package spec.)
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, September 30, 2003   4:05 PM
+
+Tucker wrote:
+
+> This seems to be exactly the kind of discussion that
+> is best done in person at an ARG meeting.  I hope we
+> will get some time on the agenda for this (but I
+> recognize we should put a time limit on the discussion).
+
+Why? It's impossible in a very limited time to make technical arguments
+coherently. They make much more sense when written. The usual reason that
+face-to-face is preferred is to save time (writing responses takes a long
+time). And, of course, we get to hear from more people.
+
+But this is a black and white issue: either you believe in the corruption of
+the Ada model that is espoused here, or you don't. (Which partially depends on
+whether you believe in the program design which is suggested.)
+
+...
+> I don't see this as a visibility problem.  It is
+> exactly a freezing problem.  The freezing rules for generic
+> instantiation effectively require that the actual type be
+> completely defined, whereas all the other type
+> composition constructs (arrays, records, access-to-T, protected, ...)
+> can use private types or other not-yet-completely-defined
+> types.  This is the problem, and I don't see any good
+> solution other than allowing a generic to take a
+> not-yet-completely-defined type as an actual.
+
+OK, here's the problem. A generic is not "a type composition construct". It's a
+program unit. It needs to be used like one, not like "a type composition
+construct".
+
+> >>What Bob needs is a partial view of a generic to go along with partially
+> >>viewed type.
+>
+> I doubt it. Bob really wants the flexibility afforded to
+> private types now, namely that you can define one in terms
+> of another before either is fully defined.  I don't see how
+> you can do this with a "partial view."  Presumably you are
+> only making incomplete types visible in this partial view.
+> He typically buries the level of indirection inside the
+> generic for something like an extensible sequence, so
+> he wants to be able to put the sequence-of-T as a direct
+> component of T.
+
+The example in the AI was of a signature package. I can imagine wanting to
+include a signature in the defining package - that potentially is worth
+solving.
+
+However, declaring a visible container depending on a private type is a design
+fault (even if it was allowed). Putting a hodge-podge of abstractions, and
+especially a mixture of visibility on those abstractions, into a package spec
+is a no-no. I don't see why we should been over backwards to support bad
+designs.
+
+Note that there is no problem with the example you suggest here: just put it
+into the private part where it belongs. If the user needs access to a
+sequence-of-T, let them declare their own. (Better yet, don't use containers
+for simple tasks better programmed directly -- but that's a separate issue.)
+
+****************************************************************
+
+From: Pascal Leroy
+Sent: Tuesday, September 30, 2003   3:25 AM
+
+Tuck said:
+
+> As I said Bob Duff I believe expressed support for this
+> proposal. Is that enough, or do you want another?  If so,
+> anyone out there interested in making generics more useful by
+> relaxing these freezing rules?  Please speak up now!
+
+Bob replied:
+
+> Yes, I do support this.
+
+and Gary added:
+
+> I'll add my second.  I agree this is worth discussing.
+
+Amazing!  It's the first time we resurrect one of these AC thingies.
+Good to see that we get to exercise all the paths in the ARG procedures.
+
+****************************************************************
+
+From: Robert I. Eachus
+Sent: Tuesday, September 30, 2003  11:31 AM
+
+> Anyway, it occurs to me that the main problem could be solved with an
+> "incomplete" instantiation. To show Tucker's original example...
+
+I like it.  We could even fold it into the solution to the limited with
+proposal to the extent possible to eliminate the number of new concepts that a
+user must learn.  Hmmm.  Maybe not.  The real problem is that for "ordinary"
+generics, instantiation of the body occurs at the same place as the
+declaration.  The need is for separating the two.  So what we really want is
+something that allows the generic instantiation of the body to be deferred,
+while leaving the spec visible.
+
+Something like:
+
+package Foo will be new G(T); -- better syntax invited.
+
+The instance of course can't be called (or objects in the generic used) before
+the "full" declaration, but since that must be later in the same declarative
+part  or in the private part, it isn't a problem for users of a package.
+
+****************************************************************
+
+From: John-Pierre Rosen
+Sent: Wednesday, October  1, 2003  2:08 AM
+
+Since you ask for it (inventing syntax is such a fun):
+
+package Foo is separate new G(T);
+
+and at the place where you want the body to appear:
+
+separate package body Foo;
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, September 30, 2003  4:05 PM
+
+Tucker wrote:
+
+> This seems to be exactly the kind of discussion that
+> is best done in person at an ARG meeting.  I hope we
+> will get some time on the agenda for this (but I
+> recognize we should put a time limit on the discussion).
+
+Why? It's impossible in a very limited time to make technical arguments
+coherently. They make much more sense when written. The usual reason that
+face-to-face is preferred is to save time (writing responses takes a long
+time). And, of course, we get to hear from more people.
+
+But this is a black and white issue: either you believe in the corruption of
+the Ada model that is espoused here, or you don't. (Which partially depends
+on whether you believe in the program design which is suggested.)
+
+...
+> I don't see this as a visibility problem.  It is
+> exactly a freezing problem.  The freezing rules for generic
+> instantiation effectively require that the actual type be
+> completely defined, whereas all the other type
+> composition constructs (arrays, records, access-to-T, protected, ...)
+> can use private types or other not-yet-completely-defined
+> types.  This is the problem, and I don't see any good
+> solution other than allowing a generic to take a
+> not-yet-completely-defined type as an actual.
+
+OK, here's the problem. A generic is not "a type composition construct".
+It's a program unit. It needs to be used like one, not like "a type
+composition construct".
+
+> >>What Bob needs is a partial view of a generic to go along with partially
+> >>viewed type.
+>
+> I doubt it. Bob really wants the flexibility afforded to
+> private types now, namely that you can define one in terms
+> of another before either is fully defined.  I don't see how
+> you can do this with a "partial view."  Presumably you are
+> only making incomplete types visible in this partial view.
+> He typically buries the level of indirection inside the
+> generic for something like an extensible sequence, so
+> he wants to be able to put the sequence-of-T as a direct
+> component of T.
+
+The example in the AI was of a signature package. I can imagine wanting to
+include a signature in the defining package - that potentially is worth
+solving.
+
+However, declaring a visible container depending on a private type is a
+design fault (even if it was allowed). Putting a hodge-podge of
+abstractions, and especially a mixture of visibility on those abstractions,
+into a package spec is a no-no. I don't see why we should been over
+backwards to support bad designs.
+
+Note that there is no problem with the example you suggest here: just put it
+into the private part where it belongs. If the user needs access to a
+sequence-of-T, let them declare their own. (Better yet, don't use containers
+for simple tasks better programmed directly -- but that's a separate issue.)
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Tuesday, September 30, 2003  6:49 PM
+
+>>This seems to be exactly the kind of discussion that
+>>is best done in person at an ARG meeting.  I hope we
+>>will get some time on the agenda for this (but I
+>>recognize we should put a time limit on the discussion).
+>
+> Why? It's impossible in a very limited time to make technical arguments
+> coherently. They make much more sense when written. The usual reason that
+> face-to-face is preferred is to save time (writing responses takes a long
+> time). And, of course, we get to hear from more people.
+
+I don't have the same experience, but I realize people
+differ on these things.  I find a "white-board" discussion
+is sometimes the only way to come to a decision about
+a tough technical issue, whereas going back and forth
+with e-mail just ends up in circular arguments.  But,
+this is definitely one of those things where your mileage
+may vary.
+
+> OK, here's the problem. A generic is not "a type composition construct".
+> It's a program unit. It needs to be used like one, not like "a type
+> composition construct".
+
+I don't follow you here.  A generic is the only user-defined
+type composition construct Ada provides.  It is implemented
+as a program unit, but that doesn't make it less of a
+type composition construct.
+
+> Note that there is no problem with the example you suggest here: just put it
+> into the private part where it belongs. If the user needs access to a
+> sequence-of-T, let them declare their own. (Better yet, don't use containers
+> for simple tasks better programmed directly -- but that's a separate issue.
+
+But the problem is you can't even put it in the private
+part, because it would still need to precede the full
+definition of the private type.
+
+I really don't see what is your objection to this
+kind of use of generics.  You in particular have indicated
+a desire to minimize visible use of access types,
+so having a seq-of-T generic that has a hidden level
+of indirection seems perfectly reasonable, so they
+can be conveniently assigned and passed around.
+Once you have one of these, it seems reasonable to
+want to put one of these inside T itself (e.g.,
+T is representing an expression, and it has
+an operator and a seq-of-expressions for operands).
+
+And note that if you made the package non-generic,
+what was being done would be perfectly legal.
+That seems like the most obvious flaw.  You can
+do something useful in a sub-package, but you try
+to bundle it up into a reusable generic, and the
+freezing rules prevent you from using an instance
+of the generic in place of the original sub-package.
+Nothing else is different between the instance
+and the sub-package, only the freezing rules.  So
+to me that points the finger at the freezing rules.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, September 30, 2003  7:19 PM
+
+> I don't have the same experience, but I realize people
+> differ on these things.  I find a "white-board" discussion
+> is sometimes the only way to come to a decision about
+> a tough technical issue, whereas going back and forth
+> with e-mail just ends up in circular arguments.  But,
+> this is definitely one of those things where your mileage
+> may vary.
+
+Well, as recorder, I tend to have to spend my time writing down the
+discussion, not participating in it. Moreover, I often record points that I
+intend to make, and sometimes I never even manage to make them.
+
+...
+>> Note that there is no problem with the example you suggest here: just put it
+>> into the private part where it belongs. If the user needs access to a
+>> sequence-of-T, let them declare their own.
+>
+> But the problem is you can't even put it in the private
+> part, because it would still need to precede the full
+> definition of the private type.
+
+Right because you want indirection without indirection. You can't get there
+from here, and that is as it should be.
+
+> I really don't see what is your objection to this
+> kind of use of generics.  You in particular have indicated
+> a desire to minimize visible use of access types,
+> so having a seq-of-T generic that has a hidden level
+> of indirection seems perfectly reasonable, so they
+> can be conveniently assigned and passed around.
+> Once you have one of these, it seems reasonable to
+> want to put one of these inside T itself (e.g.,
+> T is representing an expression, and it has
+> an operator and a seq-of-expressions for operands).
+
+I'm for minimizing *visible* use of access types. It's silly to even try to
+eliminate them inside the implementation: indirection is a basic concept
+that is needed everywhere. You can't put a T inside of a T without some
+indirection, and its silly to try to hide it.
+
+This seems to be the "recursive type" discussion that's going on on
+Ada-Comment. Some people (Ed in particular) claims its impossible to do it
+without indirection, and I tend to agree. And forcing compilers off the
+market simply so you can avoid writing indirection when you clearly need it
+seems completely pointless.
+
+> And note that if you made the package non-generic,
+> what was being done would be perfectly legal.
+> That seems like the most obvious flaw.  You can
+> do something useful in a sub-package, but you try
+> to bundle it up into a reusable generic, and the
+> freezing rules prevent you from using an instance
+> of the generic in place of the original sub-package.
+> Nothing else is different between the instance
+> and the sub-package, only the freezing rules.  So
+> to me that points the finger at the freezing rules.
+
+True, but that's a bug in Ada 83. Being allowed to do that causes all of the
+bizarre "when is a operation visible" rules, which have kept the ARG busy
+for years. No one really knows what will happen when you do that; you just
+hope that your compiler accepts it. It would have been much better if such
+nested constructs were illegal. Making more of them legal is a lousy idea.
+
+****************************************************************
+
+From: Ed Schonberg
+Sent: Tuesday, September 30, 2003  7:19 PM
+
+Like other implementors, I somewhat dread touching the freezing machinery,
+because a number of invariants in the communication between front-end and
+back-end will be affected. At the programming level, this suggestion also
+seems to complicate things. Are entities within the instance usable before
+its freezing point? Types that depend on the unfrozen actuals obviously
+are not usable yet, but what about other entities? Do we need special rules
+for this, or is the instance simply not usable at all until its freezing
+point? This is not the case for nested packages, so this another epsilon
+in complication.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Tuesday, September 30, 2003  8:22 PM
+
+I'm not sure I follow you.  The normal freezing rules still apply
+to the entities inside the formal instance.  If you use them
+in certain ways, then you freeze them, and it would be an error
+if the entity was not yet completely defined.  This is exactly
+like the entities in a nested package.  In fact, the whole goal
+is that rather than freezing the actuals up front, instead, freezing
+happens just as it would for the equivalent non-generic nested
+package spec.  Remember that for a nested package, the end of
+the package is *not* a "general" freezing point.  The general
+freezing point happens at the end of the enclosing library unit
+or declarative part, or at a non-instance body.  The proposal
+is to defer the elaboration of the instance bodies to this same
+"general" freezing point, and do freezing within the instance
+spec just as it would be done for the equivalent non-generic
+package spec.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, September 30, 2003  8:58 PM
+
+> I'm not sure I follow you.  The normal freezing rules still apply
+> to the entities inside the formal instance.
+
+There is nothing 'normal' about an instance.
+
+Entities in it are already frozen (because the entities were frozen when the
+template was compiled - else code couldn't have been generated for it), and
+they're duplicated that way. Freezing of entities in a generic template can
+have no effect: they've already been frozen long before, and the representation
+cannot change.
+
+Moreover, we have to generate code for the actual parameters at the point of
+the instantiation. We could delay that until the freezing point, but then we'd
+have to delay the elaboration of the spec until that point -- it uses the same
+actual parameters, thunks, and the like. And it certainly wouldn't be practical
+to try to generate two sets of thunks and parameters, one for the spec and one
+for the body. (Besides it not being possible in general.)
+
+Beyond that, you're suggesting that everyone add a lot of code to detect
+'early' freezing of (parts of) a generic instance. In particular, you would now
+have to be able to trace freezing through generic formals -- which is clearly
+new.
+
+Moreover, a lot of the likely uses of the instantiation will raise
+Program_Error. That doesn't seem too useful. I'd rather see an explicit
+'partial' instantiation that allows signatures and incomplete types (solving
+the real problems), and doesn't add a lot of new ways to raise Program_Error.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Wednesday, October  1, 2003  1:27 AM
+
+Clearly you have special concerns due to
+your "universal" generic sharing.  However, you
+are using the term "freezing" in a way that doesn't
+really correspond to its meaning in the manual.
+It doesn't make sense to talk about freezing a type
+when the template is compiled, if the type depends
+fundamentally on properties of some actual type parameter
+(e.g., an array type whose component type is a formal
+type).  I can believe you "solidify" as much as you
+can when you compile the generic template, but that
+isn't the same as the RM meaning of "freeze."
+
+Perhaps we need a specific example.
+Here is a generic sequences package:
+
+     generic
+         type Elem is private;
+     package Seqs is
+         type Seq is private;
+         procedure Append(S : in out Seq; E : in Elem);
+         function Len(S : Seq) return Natural;
+         function Nth(S : Seq; I : Positive) return Elem;
+     private
+         type Elem_Array is array(Positive range <>) of Elem;
+         type Elem_Array_Ptr is access Elem_Array;
+
+         type Seq is record
+             Len : Natural := 0;
+             Data : Elem_Array_Ptr := null;
+         end record;
+     end Seqs;
+
+Here is an "Expression" type which consists of an operator
+and zero-or-more operands, represented as a sequence.  This
+would work fine if we hand-instantiated the Seqs package:
+
+      type Expr is private;
+      package Expr_Seqs is new Seqs(Expr); -- Freezing rule violation
+      type Expr_Seq is new Expr_Seqs.Seq;
+      function New_Expr(Op : Op_Enum; Opnds: Expr_Seq) return Expr;
+    ...
+    private
+      type Expr is record
+          Op : Op_Enum := No_Op;
+          Operands : Expr_Seq;
+      end record;
+
+The above seems perfectly reasonable, except for the
+fact that the freezing rules disallow it. I don't see
+any "Program_Error"s cropping up.  These are all just
+type declarations that build on one another.
+
+If we ignore the current freezing rules for a minute,
+can you identify the problems you would have generating
+code for the above, presuming shared generics?  That
+would be interesting to understand.
+
+Here is a possible intermediate approach:
+
+   When something declared in an instance needs to be frozen, then the
+   entire instance spec is frozen, including all the generic actuals;
+   the instance body, if any, is elaborated immediately after
+   freezing the instance spec.
+
+This means that at the point of instantiation, the spec
+is elaborated, but no further layout decisions are
+made.  At the point when any entity declared in the instance is
+frozen due to an external "freezing" reference, the
+layout decisions are made, 'Size is computed for everything,
+and the body is elaborated.  This would mean the thunks,
+etc., would be provided to the code that computes 'size, etc.
+and then elaborates the body.  The elaboration of the instance
+spec could presumably be done inline, since you have the
+template spec available at the instantiation point.  Alternatively,
+you could have a separate out-of-line procedure that
+did just the spec elaboration.
+
+If the elaboration of the instance spec itself caused
+freezing of a generic actual that was not
+completely defined, then the generic would clearly
+not allow instantiation with that actual being
+incompletely defined (just like the current rule).
+
+For the above example, the elaboration clearly doesn't
+freeze the generic actual type, so it could be instantiated
+with an incompletely defined type.  Any "freezing" reference to
+an entity exported by the instance would trigger freezing
+of the entire instance.  So for example, a call on any subprogram
+exported by the instance, or the declaration of an object
+of a type exported by the instance, would trigger freezing
+of the instance and its actuals, as well as the elaboration
+of the instance body.
+
+So if Seqs is instantiated with an incompletely defined
+type (like Expr), then the freezing of the instance spec and
+the elaboration of the instance body would be deferred until
+the type Seq, or one of the subprograms Append, Len, or Nth is frozen,
+or until a general freezing point, whichever comes first.
+
+I believe this approach would also handle the problem
+of Program_Errors due to access before elaboration,
+since any use of the instance that would check an
+elaboration bit would also cause freezing (and hence
+body elaboration).  This would also preserve the existing
+situation with respect to elaboration of generics,
+where calls from outside the instance could never result
+in the failure of an elaboration check.
+
+I think this is nearly equivalent to the "partial" instantiation
+you suggested.  Essentially the only thing that happens at
+the point of the instantiation is the elaboration of the spec.
+At a somewhat later point, freezing and body elaboration happen,
+which is really the interesting stuff as far as your shared
+generic implementation is concerned, it seems.
+
+In other words, every instantiation with an incompletely-defined
+actual type is considered a "partial" instantiation.  The
+real "action" happens later, at the freezing point for some
+entity exported by the generic.
+
+****************************************************************
+
+From: Pascal Leroy
+Sent: Wednesday, October  1, 2003  2:47 AM
+
+I have some sympathy for solving that problem, as it occurs quite often
+in practice.  However, I think that the approach of doing open-heart
+surgery on the freezing rules and the elaboration model is misguided.
+
+Couldn't we solve the problem with a categorization pragma?  Assume that
+we add a library unit pragma Well_Behaved (better name welcome) that may
+be applied to a generic and says "I promise that each and every instance
+of this generic will be preelaborable" (the actual rules may need to be
+a bit more complicated, but that's a first approximation).  This pragma
+would prevent certain constructs inside the generic spec or body, like
+declaring objects or having a statement part in the package body.
+
+A generic with pragma Well_Behaved could then be instantiated with a
+private type.  It would not cause freezing of that private type, and its
+elaboration would be effectively a no-op, so I suppose that it wouldn't
+be too hard for compilers to implement.
+
+I believe that this pragma could actually be applied to many existing
+generics without any code change (the containers being a good example).
+And evidently it could be applied to signature packages.  So at the
+expense of some generality, we would be able to solve the problem
+without major changes to the language.
+
+One advantage of this pragma is that it would document the fact that the
+generic is specifically designed to be used with private types (i.e. for
+type composition).
+
+Does that make any sense?
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Wednesday, October  1, 2003  7:50 AM
+
+> ...
+> I have some sympathy for solving that problem, as it occurs quite often
+> in practice.
+
+Given that we agree about this, it sounds like we might
+have a chance of solving this problem.
+
+> ... However, I think that the approach of doing open-heart
+> surgery on the freezing rules and the elaboration model is misguided.
+
+I prefer brain surgery ;-).
+
+Actually, I felt my "intermediate" proposal, where spec elaboration
+happens at the instantiation, and then the instance freezing
+and body elaboration happen at a later point seems fairly
+elegant and not particularly hard to implement.  It is clearly
+upward compatible, since it is only used when one of the
+actuals is not-completely-defined.  Also, it does exactly
+what is needed, namely deferring freezing, but without creating
+any "exposure" due to deferred elaboration of the body, because
+that still happens prior to any possible external call.
+
+> Couldn't we solve the problem with a categorization pragma?  Assume that
+> we add a library unit pragma Well_Behaved (better name welcome) that may
+> be applied to a generic and says "I promise that each and every instance
+> of this generic will be preelaborable" (the actual rules may need to be
+> a bit more complicated, but that's a first approximation).
+
+Note that this is pretty much what the existing paragraph 10.2.1(10) is
+all about.
+
+> ... This pragma
+> would prevent certain constructs inside the generic spec or body, like
+> declaring objects or having a statement part in the package body.
+>
+> A generic with pragma Well_Behaved could then be instantiated with a
+> private type.  It would not cause freezing of that private type, and its
+> elaboration would be effectively a no-op, so I suppose that it wouldn't
+> be too hard for compilers to implement.
+
+I wouldn't mind a pragma-based solution, but it seems
+more work to define a new pragma, and brings up the various
+nasties associated with the preelaboration pragma, in particular
+the requirement that the entire semantic closure be preelaborable.
+
+On the other hand, if we could piggy back completely on the
+existing Preelaborate pragma, and say that a generic that
+is declared within a preelaborated library unit can be instantiated
+with a not-yet-completely-defined type, that would be a fairly
+economical solution.  However, I don't see it really simplifying
+the implementation significantly, since you still have to notice
+when a type exported by an instance of such a generic is frozen,
+and at that point make sure the generic actual type is
+completely defined.  It seems more flexible to just say that
+any old generic works this way, and the freezing and body
+elaboration happen at the freezing point rather than at the
+instantiation point if there is a not-yet-completely-defined
+actual.
+
+****************************************************************
+
+From: Pascal Leroy
+Sent: Wednesday, October  1, 2003  8:04 AM
+
+> Actually, I felt my "intermediate" proposal, where spec elaboration
+> happens at the instantiation, and then the instance freezing
+> and body elaboration happen at a later point seems fairly
+> elegant and not particularly hard to implement.
+
+One thing I don't like here is the fact that the place where body
+elaboration happens is "floating": add a new object declaration, and it
+may cause instance freezing because it contains (at 17 levels deep) a
+type exported by the instance; and now body elaboration happens earlier,
+and that may change the dynamic effect of the program.  This is very
+different from the current state of affairs, where it is very clear in
+the program text where elaboration happens (and that doesn't change at
+the drop of a hat).
+
+I would be much happier if there were no need to elaborate the body at
+all.
+
+****************************************************************
+
+From: Ed Schonberg
+Sent: Wednesday, October  1, 2003  8:13 AM
+
+The simplest might be to treat instances exactly like nested packages then.
+A use of an entity exported by the instance might freeze the entity without
+freezing the instance itself, and the instance is frozen at the end of the
+current declarative part, etc. There will be some instantiation errors when
+the instance declares an object of an unfrozen type, but this will be no
+different from the current treatment.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Wednesday, October  1, 2003  7:50 AM
+
+Alternatively, we stick with a model where the freezing and
+body elaboration happen at the same time (which I think
+helps the shared generic implementation, and keeps the
+nice elab-check-minimization properties), but say the
+freezing and elab happen at the next "general" freezing
+point, and until that point, all of the entities of
+the instance are considered not-yet-completely-defined,
+making an attempt at freezing an error.
+
+In other words, if you can't freeze all the generic
+actuals at the point of instantiation, then all freezing
+and body elab is deferred until a well-defined point (the
+next general freezing point), and any need for freezing before
+that is an error.
+
+I think this would address Pascal's concern by having a stable
+well-defined point for body elab, minimize acc-before-elab problems
+by keeping freezing and body elab together, and allow generics
+to be used with not-completely-defined types.
+
+****************************************************************
+
+From: Ed Schonberg
+Sent: Wednesday, October  1, 2003  9:11 AM
+
+I don't know about the difficulties presented by shared generics, but
+if Randy allows me to ignore them for a microsecond, It seems to me
+that the simplest is to erase 13.14 (5) from the RM, and be done. An
+instance is a nested package, it may include unfrozen entities, these
+might get frozen at some subsequent point of use, the instance itself
+is frozen (together with the entities it contains) at the next general
+freezing point. The instance body is conceptually at the freeze point.
+
+Microsecond over, Randy will explain why this does not work with shared
+generics.
+
+****************************************************************
+
+From: Pascal Leroy
+Sent: Wednesday, October  1, 2003  9:12 AM
+
+> The simplest might be to treat instances exactly like nested
+> packages then.
+
+The analogy between nested packages and instances doesn't work well
+because an instance has, in addition to a specification, a body, which
+also occurs at the place of the instantiation (12.3(12)).  That's why I
+don't take at face value Tuck's argument that "it's legal if you expand
+by hand": you can only expand by hand the specification, not the body.
+
+The nasty case of course is when a construct in the instance body causes
+freezing: surely we do not want the legality of an instantiation to
+depend on the contents of the body.
+
+****************************************************************
+
+From: Robert I. Eachus
+Sent: Wednesday, October  1, 2003  2:37 PM
+
+
+I am definitely in the "don't mess with the freezing rules" camp.  But I have
+been doing some more thinking about how this problem mixes with the issues
+being addressed by "limited with."  Let me repeat Tucker's example to keep it
+handy:
+
+> Perhaps we need a specific example.
+> Here is a generic sequences package:
+>
+>      generic
+>          type Elem is private;
+>      package Seqs is
+>          type Seq is private;
+>          procedure Append(S : in out Seq; E : in Elem);
+>          function Len(S : Seq) return Natural;
+>          function Nth(S : Seq; I : Positive) return Elem;
+>      private
+>          type Elem_Array is array(Positive range <>) of Elem;
+>          type Elem_Array_Ptr is access Elem_Array;
+>
+>          type Seq is record
+>              Len : Natural := 0;
+>              Data : Elem_Array_Ptr := null;
+>          end record;
+>      end Seqs;
+>
+> Here is an "Expression" type which consists of an operator
+> and zero-or-more operands, represented as a sequence.  This
+> would work fine if we hand-instantiated the Seqs package:
+>
+>       type Expr is private;
+>       package Expr_Seqs is new Seqs(Expr); -- Freezing rule violation
+>       type Expr_Seq is new Expr_Seqs.Seq;
+>       function New_Expr(Op : Op_Enum; Opnds: Expr_Seq) return Expr;
+>     ...
+>     private
+>       type Expr is record
+>           Op : Op_Enum := No_Op;
+>           Operands : Expr_Seq;
+>       end record;
+
+And let me propose a strawman for the explicit notation camp:
+
+       type Expr is private;
+       package Expr_Seqs is limited new Seqs(Expr);
+            -- types are visible as private here.
+       subtype Expr_Seq is new Expr_Seqs.Seq;
+            -- can't derive from a private type
+       function New_Expr(Op : Op_Enum; Opnds: Expr_Seq) return Expr;
+       procedure Append(S : in out Expr_Seq; E : in Expr);
+       function Len(S : Expr_Seq) return Natural;
+       function Nth(S : Expr_Seq; I : Positive) return Expr;
+     ...
+     private
+       type Expr is record
+           Op : Op_Enum := No_Op;
+           Operands : Expr_Seq;
+       end record;
+
+       package Expr_Seqs is new Seqs(Expr)
+       -- effectively the completion of the limited new
+
+       -- use renamings to complete the declarations of Append, Len, and Nth
+
+Does it mean more work than Tucker's magic wand?  Yes.  It also means that if a
+programmer goofs, he is likely to get meaningful error messages instead of
+prematurely freezing a type, then getting a boatload of secondary messages.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Monday, October 27, 2003 11:11 PM
+
+We never really finished the discussion of this AI; the discussion stopped when
+everyone left for Canada.
+
+Let me try to show some examples of why I don't like this proposal.
+
+Let's say we have a generic array hashing package:
+
+    generic
+        type Elem is private;
+        with function Code (I : Elem) return Natural;
+        type Elem_Array is array (Positive range <>) of Elem;
+    package Array_Hashing is
+        function Hash (Arr : Elem_Array) return Natural;
+    end Array_Hashing;
+
+    package body Array_Hashing is
+        type Nat_Mod is mod Natural'Last;
+        function Hash (Arr : Elem_Array) return Natural is
+            Res : Nat_Mod := 1;
+        begin
+            for I in Arr'range loop
+               Res := Res*3 + Nat_Mod(Code(Arr(I)));
+            end loop;
+            return Natural(Res);
+        end Hash;
+    end Array_Hashing;
+
+Now, let's look at a possible use in existing code:
+
+    with Array_Hashing;
+    package User is
+        type Something is range 0 .. 200;
+        function Count (A : Something) return Natural;
+        type Array_of_Something is array (Positive range <>) of Something;
+        package My_Hash is new Array_Hashing (Something, Count, Array_of_Something);
+        NULL_HASH : constant Natural := My_Hash.Hash ((1..0 => 0));
+        ....
+    end User;
+
+This code is legal and does not raise any exceptions (yes, I tried it on both
+Janus/Ada and GNAT). Yes, I know this example is a bit contrived, but I wanted
+something simple to discuss.
+
+Now, consider that an Ada 200Y user decides to take advantage of Tucker's great
+new feature and recreate package User with Something as a private type:
+
+    package User is
+        type Something is private;
+        function Count (A : Something) return Natural;
+        type Array_of_Something is array (Positive range <>) of Something;
+        package My_Hash is new Array_Hashing (Something, Count, Array_of_Something);
+        NULL_HASH : constant Natural := My_Hash.Hash ((1..0 => 0));
+    private
+        type Something is range 0 .. 200;
+    end User;
+
+With Tucker's original proposal, this is illegal, because the call to
+My_Hash.Hash will try to freeze Something. This is ugly (because the error
+message is likely to be totally mysterious), but reasonable (the user is
+depending on a private type).
+
+OK, so the user realizes their mistake, and makes NULL_HASH a deferred
+constant. Their next program looks like:
+
+    package User is
+        type Something is private;
+        function Count (A : Something) return Natural;
+        type Array_of_Something is array (Positive range <>) of Something;
+        package My_Hash is new Array_Hashing (Something, Count, Array_of_Something);
+        NULL_HASH : constant Natural;
+    private
+        type Something is range 0 .. 200;
+        NULL_HASH : constant Natural := My_Hash.Hash ((1..0 => 0));
+    end User;
+
+This compiles fine (Something is frozen by the call, which is OK, because it is
+fully defined). But when they run it, it mysteriously raises Program_Error! The
+reason is that the instance body of My_Hash doesn't elaborate until the end of
+the package, so it isn't elaborated yet. Worse, there is absolutely nothing
+that the user can do about it - there is no way to move the body to a point
+before the deferred constant.
+
+Tucker later modified his proposal - indeed, he did it 3 or 4 times. I don't
+have a good way to refer to the different modifications, so I'm just going to
+ignore the middle ones (which weren't liked much anyway).
+
+The last modification was that the freezing and elaboration would happen at the
+next "general" freezing point. (He didn't define "general", but I presume he
+means body-or-end-of-scope.) In that modification, the program above would be
+illegal (the instantiation is not frozen when the subprogram is called). That's
+better than Program_Error, but the problem is that there isn't any way to make
+the program legal.
+
+A couple of other approaches were also tossed out. Pascal suggested a
+categorization pragma. It seems to me that this generic would be able to be
+used with such a pragma; the elaboration is trivial. However, that doesn't
+help: we still have the access-before-elaboration and/or access-before-freezing
+problem to resolve. (We can't elaborate, even logically, a body before
+everything it depends on is frozen.)
+
+Finally, there is the explicit approach that I originally proposed and later
+expanded upon by Robert Eachus. Presuming semantics similar to limited with, we
+would have:
+
+    package User is
+        type Something is private;
+        function Count (A : Something) return Natural;
+        type Array_of_Something is array (Positive range <>) of Something;
+        package My_Hash is limited new Array_Hashing (Something, Count,
+            Array_of_Something);
+        NULL_HASH : constant Natural;
+    private
+        type Something is range 0 .. 200;
+        package My_Hash is new Array_Hashing (Something, Count,
+            Array_of_Something);
+        NULL_HASH : constant Natural := My_Hash.Hash ((1..0 => 0));
+    end User;
+
+Which works fine: the user can place the elaboration/freezing of the unit
+precisely where it needs to be.
+
+The one difference that I suggested from what Robert suggested is that outside
+of the package spec, there is no problem seeing the full view of the limited
+instantiation. It only needs to be limited within the package specification
+itself. That would mean that it would be legal to use this as a formal package
+and to call routines within it from outside of the package (if you didn't want
+to do that, why would you make it visible in the first place?). So it would be
+defined as restrictions that applied only when you were in the scope of the
+limited view but not the scope of the full view.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Tuesday, October 28, 2003  7:43 AM
+
+Randy Brukardt wrote:
+...
+> Let me try to show some examples of why I don't like this proposal...
+
+In your example, you are trying to take advantage of the
+one "feature" the current model of generics gives you over
+hand instantiation, namely immediate elaboration of the body,
+whereas the purpose of this proposal is to postpone immediate
+elaboration of the body to increase the flexibility of instantiations,
+and bring them closer to the flexibility of hand-instantiation.
+
+In my own view, there is such a huge advantage of being able
+to match the flexibility of hand instantiation, that I am
+willing to forego the advantage of early body elaboration
+when the types are not completely defined at the point of
+instantiation.
+
+You have suggested we could get the best of both worlds by
+allowing the programmer to explicitly separate the instantiation
+into two pieces, using the word "limited" for the spec instantiation
+and the existing syntax for body instantiation.
+My concern is that this is adding syntax, making yet another
+overloading of limited (with rather different meaning, since
+I don't think we really have a "limited view" of the package),
+and giving instantiations yet another special property that distinguishes
+them from non-instantiations.
+
+Do you feel this is really that important?  My own view is that
+the "real" problem is that deferred constants can't be deferred
+to the body.  This would allow "normal" functions to be used
+in defining them, whereas now only instantiations can be
+used in this way.  I would rather "fix" the real problem,
+rather than going to the trouble of making instantiations different
+from non-instantiations in yet another way.
+
+One of the few times I "miss" C is when Ada forces me to
+put the initialization of large constant tables into a spec,
+or change them into variables, or use some other trick,
+whereas in C I could have easily placed the initialization
+in the equivalent of a body.
+
+-Tuck
+
+P.S. For the record, here is a copy of the suggested semantics
+given in my 10/1/03 e-mail message:
+
+> Alternatively, we stick with a model where the freezing and
+> body elaboration happen at the same time (which I think
+> helps the shared generic implementation, and keeps the
+> nice elab-check-minimization properties), but say the
+> freezing and elab happen at the next "general" freezing
+> point, and until that point, all of the entities of
+> the instance are considered not-yet-completely-defined,
+> making an attempt at freezing an error.
+>
+> In other words, if you can't freeze all the generic
+> actuals at the point of instantiation, then all freezing
+> and body elab is deferred until a well-defined point (the
+> next general freezing point), and any need for freezing before
+> that is an error.
+>
+> I think this would address Pascal's concern by having a stable
+> well-defined point for body elab, minimize acc-before-elab problems
+> by keeping freezing and body elab together, and allow generics
+> to be used with not-completely-defined types.
+
+****************************************************************
+
+From: Robert A. Duff
+Sent: Tuesday, October 28, 2003  8:01 AM
+
+What do you mean by "hand instantiation"?
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Tuesday, October 28, 2003  8:33 AM
+
+By "hand instantiation" I mean copying the generic
+unit, removing the word "generic", and editing it to
+use the actual parameters.   A goal of this AI is
+to allow a "real" generic instantiation to do the
+same kinds of things a "hand" instantiation can do,
+in particular, define some kind of set or sequence or
+other collection where the component type is a private
+type.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, October 28, 2003  3:35 PM
+
+> Do you feel this is really that important?
+
+Yes, actually. If we were defining "Bob 2005", this wouldn't be an important
+property. But we have 25 years of Ada history here. At least some users expect
+the body to elaborate at the point of the instantiation.
+
+Indeed, it is a well-known "technique" to use a generic unit to get a body to
+elaborate "early" in a spec. at a point where a body would be illegal for a
+non-generic unit. I've used that technique at least once, and I know of other
+users that have used it.
+
+If we didn't have the history and compatibility problems, we could change the
+meaning generally. But I object to the meaning changing silently in a few
+cases, with no indication in the source that something unusual is going on. Ada
+is all about readability, and we don't want minor changes far away in the
+source code to make a significant semantic difference. We call that a
+Beaujolais effect for visibility. I especially don't like the fact that such a
+change can still produce a legal program, but one that could raise
+Program_Error.
+
+And I don't like the fact that you have to look at *all* of the generic
+parameters before you can figure out anything about the instantiation -- as
+what you do is totally different in the two cases. If you have a large number
+of generic parameters, which is not uncommon, it can be hard to tell - as a
+reader and as an implementation what semantics is in effect.
+
+As far as the syntax goes, feel free to suggest something else. But it is very
+close to a "limited view", with the exception that you are allowed to use the
+full view outside of the package. Since for "limited with", you get no view
+outside the package (as there is no visible declaration), I don't think that
+this would not be a major confusion.
+
+It's a "limited view" because the types declared in the spec have to be
+incomplete. In particular, you must not be allowed to declare a component of
+them. If you could, the legality of the generic instantiation would depend on
+not only the formals and the contents of the generic spec, but also on how the
+generic and its formals are used. There a few such cases in Ada currently
+(mostly involving private types), and they are a disaster. I'm strongly opposed
+to adding more, especially for a marginal feature such as this.
+
+Instantiations *are* different. Their dynamic properties are (or at least can
+be) completely different than the equivalent hand-instantiated code. That will
+remain true unless we decide to eliminate the possibility of sharing, and until
+we change the elaboration of ALL generic bodies to happen at freezing point
+where bodies would normally be allowed. I do not expect that to happen.
+
+****************************************************************
+
+From: Robert A Duff
+Sent: Tuesday, October 28, 2003  4:23 PM
+
+A question for Randy: In your proposal, are you allowed to put the body
+of the instance in the body of the containing package (when the spec of
+the instance is in the spec of the containing package)?
+Why/why not?
+
+I kind of like Randy's idea.  Tucker says it makes instantiations
+different from non-instantiations "in yet another way".  But a normal
+package is split syntactically into two pieces, and the programmer gets
+to choose where they get elaborated (more or less).  It seems like
+Randy's idea makes instantiations *more* like regular packages, in this
+regard.
+
+Randy wrote:
+
+> Indeed, it is a well-known "technique" to use a generic unit to get a body
+                              ^^^^^^^^^
+> to elaborate "early" in a spec. at a point where a body would be illegal for
+> a non-generic unit.
+
+You misspelled "ugly hack".  ;-)
+
+> I especially don't like the fact that such
+> a change can still produce a legal program, but one that could raise
+> Program_Error.
+
+I agree, but exceptions during elaboration are *almost* as nice as
+compile-time errors, because they usually happen every time you run the
+program.  They will be noticed by any programmer who does the most
+minimal amount of testing, and fixed right away, which is cheap -- the
+same advantage as compile-time errors.  Almost.
+
+> I'm
+> strongly opposed to adding more, especially for a marginal feature such as
+> this.
+
+I don't have a strong feeling about how to fix the problem.
+But I don't consider it a marginal feature.  I find the lack of the
+ability to instantiate a generic on a private type to be huge pain.
+
+Why doesn't Ada have (say) growable arrays built in?  Well, you can
+build them yourself, using a generic.  I can say:
+
+    type T is private;
+    type T_Sequence is array(...) of T;
+
+But I cannot say:
+
+    type T is private;
+    package T_Sequences is new Growable_Array(T); -- Illegal.
+
+at least not without standing on my ear and spitting nickles.
+
+That's a nasty inconsistency.
+
+Note that in my code, quite often T contains a sequence-of-T's as a
+subcomponent.
+
+Tucker wrote:
+
+> Do you feel this is really that important?  My own view is that
+> the "real" problem is that deferred constants can't be deferred
+> to the body.
+
+Yes, we should fix that, too.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, October 28, 2003  5:05 PM
+
+Bob said:
+
+> A question for Randy: In your proposal, are you allowed to put the body
+> of the instance in the body of the containing package (when the spec of
+> the instance is in the spec of the containing package)?
+> Why/why not?
+
+I hadn't thought about that much, although I was certain someone would ask the
+question. :-)
+
+I think it would probably need the same rule as incomplete types, such that the
+completion needs to be in the spec if it is in the visible part, and could be
+in the body otherwise. For the same reasons that is true. (Is that vague
+enough.) But it would depend solely on which operations are allowed on the
+"limited view" (see below).
+
+...
+> Why doesn't Ada have (say) growable arrays built in?  Well, you can
+> build them yourself, using a generic.  I can say:
+>
+>     type T is private;
+>     type T_Sequence is array(...) of T;
+>
+> But I cannot say:
+>
+>     type T is private;
+>     package T_Sequences is new Growable_Array(T); -- Illegal.
+>
+> at least not without standing on my ear and spitting nickles.
+>
+> That's a nasty inconsistency.
+>
+> Note that in my code, quite often T contains a sequence-of-T's as a
+> subcomponent.
+
+Right, and that's the reason that the view has to be limited. Because if it is
+not, the legality of the uses of the view depends on the implementation
+(specifically the private part).
+
+For instance, if (bounded) growable array looks like:
+
+    generic
+        type T is private;
+    package Bounded_Growable_Array is
+        type Growable_Array (Limit : Natural) is private;
+    private
+        ...
+    end Bounded_Growable_Array;
+
+whether
+    type T is private;
+    package T_Sequences is limited new Bounded_Growable_Array (T);
+    ...
+    type T is record
+        Foo : T_Sequences.Growable_Array (100); -- Illegal in my proposal.
+    end record;
+is implementable depends on the contents of the private part of
+Bounded_Growable_Array.
+OTOH,
+    type T is record
+        Foo : access T_Sequences.Growable_Array :=
+		new T_Sequences.Growable_Array(100);
+    end record;
+is always OK.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, October 28, 2003  5:17 PM
+
+To expand on that a bit:
+
+This is important because the generic a separate unit, that may not even
+belong to the current programmer. That is very different than the case with
+the types declared directly at this point.
+
+If we allowed what is allowed for private types here, then changing the
+private part (implementation) of a generic could make code very far away
+from the generic illegal. Imagine an implementor changing the
+Ada.Components.Bounded_Array code from an indirect to direct
+implementation -- imagine all of the code that would suddenly break. A
+freezing-type rule here would mean that it would not be safe to change the
+implementation of a generic unit for fear that it would break existing code.
+That would be a bad policy for Ada to adopt.
+
+****************************************************************
+

Questions? Ask the ACAA Technical Agent