CVS difference for ais/ai-00318.txt

Differences between 1.5 and version 1.6
Log of other versions for file ais/ai-00318.txt

--- ais/ai-00318.txt	2003/11/27 02:01:15	1.5
+++ ais/ai-00318.txt	2003/12/10 00:14:04	1.6
@@ -1933,3 +1933,1462 @@
 
 ****************************************************************
 
+[Editor's note: Additional discussion on this topic can be found in AI-325.]
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Monday, December  8, 2003, 10:32 AM
+
+There seem to a lot of messages flying around about how best
+to support function-like-things returning/constructing limited objects.
+
+Using the "Getting to Yes" method of trying to focus on what we agree about,
+here is a list of possibly desired features of the solution.
+I will start with those that seem to already have a consensus.
+I would most appreciate responses that indicate if I missed any "consensus"
+statements, or if there are some that are clearly *not* a consensus.
+Secondly, it would be good to have a prioritization of the nice-to-haves.
+Finally, it would be good to get some feeling about the non-consensus
+statements, and perhaps adjustments to them which might allow them to
+become consensus statements.
+
+-------------------------
+
+Consensus statements about Ada 200Y if we were to approve AI-318:
+
+   1) Should be possible to declare an object of a limited
+      type and provide an initializing expression
+   2) Should be possible to use an initialized allocator for
+      an access-to-limited type
+   3) Should be possible to provide an aggregate as the initializing expression
+      for a declaration or an initialized allocator, or for a component
+      of such an aggregate; such aggregates may use "<>" to represent default
+      initialization of a component
+   4) Should be possible to use a function call (or something that looks syntactically
+      like a function call) as the initializing expression for a declaration,
+      initialized allocator, or component of an aggregate that is of a limited type,
+      including a limited private type.
+   5) Should be possible to declare a function-like thing callable by such a function call
+      for limited types whose first subtype is a definite subtype.
+   6) Should be possible to use an aggregate or a function-call (-like-thing) as
+      an actual IN parameter of a limited type
+   7) Should *not* be possible to copy an existing limited object.  I.e.
+      Should *not* be possible to have an assignment statement for a limited
+      type, and should *not* be possible to use the name of a limited declared object
+      nor a dereference of an access-to-limited type as a component of an aggregate.
+   8) The compiler needs to know at the call-site whether function-like thing
+      is returning an existing object by reference, or returning/initializing
+      a new object
+
+Nice to have:
+   9) Ability to declare and call a function-like thing for a limited type with
+      non-defaulted discriminants
+   10) Ability to declare and call a function-like thing for a limited type with
+      unknown discriminants; such types would require an initializing expression --
+      no default initialization is defined for them.
+   11) Easy to implement
+
+Other possible desirables:
+   12) Should not require alteration in the way limited types are laid out
+   13) Should allow us to still have function-like things
+       that return by reference
+   14) Should (or should not) use the word "constructor" somewhere
+   15) Should (or should not) use the word "limited" somewhere
+   16) Should (or should not) use the word "function" somewhere
+   17) Should provide more efficient way for non-limited types to be returned/initialized
+   18) Should not "orphan" existing language features
+
+****************************************************************
+
+From: Robert A. Duff
+Sent: Monday, December  8, 2003,  2:48 PM
+
+Thanks, Tuck.  This is a very helpful summary.  I was getting lost in
+all those e-mails.
+
+> -------------------------
+>
+> Consensus statements about Ada 200Y if we were to approve AI-318:
+>
+>    1) Should be possible to declare an object of a limited
+>       type and provide an initializing expression
+>    2) Should be possible to use an initialized allocator for
+>       an access-to-limited type
+
+I would add, "even when the storage pool is user-defined".
+
+>    3) Should be possible to provide an aggregate as the initializing expression
+>       for a declaration or an initialized allocator, or for a component
+>       of such an aggregate; such aggregates may use "<>" to represent default
+>       initialization of a component
+>    4) Should be possible to use a function call (or something that looks syntactically
+>       like a function call) as the initializing expression for a declaration,
+>       initialized allocator, or component of an aggregate that is of a limited type,
+>       including a limited private type.
+>    5) Should be possible to declare a function-like thing callable by such a function call
+>       for limited types whose first subtype is a definite subtype.
+>    6) Should be possible to use an aggregate or a function-call (-like-thing) as
+>       an actual IN parameter of a limited type
+>    7) Should *not* be possible to copy an existing limited object.  I.e.
+>       Should *not* be possible to have an assignment statement for a limited
+>       type, and should *not* be possible to use the name of a limited declared object
+>       nor a dereference of an access-to-limited type as a component of an aggregate.
+>    8) The compiler needs to know at the call-site whether function-like thing
+>       is returning an existing object by reference, or returning/initializing
+>       a new object
+
+I agree with 1..8 above.
+
+Can we also get concensus on this:
+
+    Every context that allows an initialization expression for
+    nonlimited types should also allow it for limited types.
+
+?  That subsumes 1,2,part-of-3,part-of-6.  It also includes
+record-component-defaults, generic-formal-in's, and probably some
+others I've forgotten.  The relevant AI's list all the cases.
+
+> Nice to have:
+>    9) Ability to declare and call a function-like thing for a limited type with
+>       non-defaulted discriminants
+>    10) Ability to declare and call a function-like thing for a limited type with
+>       unknown discriminants; such types would require an initializing expression --
+>       no default initialization is defined for them.
+
+I think 9 and 10 are important.  I'm not quite willing to kill the whole
+idea if I can't have 9 and 10, but since these work already for the
+nonlimited case, it would seem pretty kludgy to leave them out in the
+limited case.
+
+>    11) Easy to implement
+
+Who could disaggree with that?  But I'm willing to put up with some
+implementation complexity to get 9 and 10.
+
+> Other possible desirables:
+>    12) Should not require alteration in the way limited types are laid out
+
+I think I agree, but I'm not really sure what you're getting at.  Which
+proposal(s) violate this?
+
+>    13) Should allow us to still have function-like things
+>        that return by reference
+
+I don't much care about that for my own code, but I think it would be
+irresponsible of us to be incompatible with folks have used this
+feature, even if we think perhaps it's a misguided feature.
+
+>    14) Should (or should not) use the word "constructor" somewhere
+>    15) Should (or should not) use the word "limited" somewhere
+>    16) Should (or should not) use the word "function" somewhere
+
+I have no strong opinion on the syntax, but I think these new kinds of
+constructors are conceptually "functions".  They just happen to build
+their result in the final resting place.
+
+Viewing them as "procedures" seems like a compiler-writer viewpoint; I'd
+rather take a user-oriented viewpoint.  The fact that function results
+can take their discriminants from the function parameters, but you can't
+do that for 'out' parameters, is accidental, not fundamental.
+
+Viewing them as totally new animals seems like overkill.  To me, a
+constructor is just a function that creates a new thing.  Number 8 above
+implies that we need *some* sort of new syntax.  I would prefer to keep
+it as close as possible to the existing function declaration syntax.
+But I do not feel strongly about this.
+
+>    17) Should provide more efficient way for non-limited types to be returned/initialized
+
+Seems like a nice side effect.  Not important.
+
+>    18) Should not "orphan" existing language features
+
+This seems like a possible symptom of kludgery, but not a worthy goal in
+its own right.  I mean, if I have to write "constructor" instead of
+"function" all over the place in future code, that's not a disaster.
+
+****************************************************************
+
+From: Robert I. Eachus
+Sent: Monday, December  8, 2003,  4:15 PM
+
+I had to go out after sending my previous message, so effectively Tucker
+and I crossed in the mail.  But Bob Duff did an good job of responding
+to Tucker's excellent list of points:
+
+Robert A Duff wrote:
+
+>Thanks, Tuck.  This is a very helpful summary.  I was getting lost in
+>all those e-mails.
+>
+>
+Agreed, and I was writing some of them, and referring back to others to
+keep everything straight.
+
+...
+>I agree with 1..8 above.
+>
+>Can we also get concensus on this:
+>
+>    Every context that allows an initialization expression for
+>    nonlimited types should also allow it for limited types.
+>
+>?  That subsumes 1,2,part-of-3,part-of-6.  It also includes
+>record-component-defaults, generic-formal-in's, and probably some
+>others I've forgotten.  The relevant AI's list all the cases.
+
+I like Tucker's breakdown better.  It makes it easier to say that 1,2,3,
+and 6 are must haves, and some of the other cases are nice to haves.  I
+certainly favor allowing record component defaults, and generic formal
+in parameters likewise seem safe, and in most compilers I would expect
+them to be implemented identically to required cases when the defaults
+were actually used.  But I would certainly consider any objections from
+implementors if some fringe case caused serious implementation problems.
+
+>>Nice to have:
+>>   9) Ability to declare and call a function-like thing for a limited type with
+>>      non-defaulted discriminants
+>>   10) Ability to declare and call a function-like thing for a limited type with
+>>      unknown discriminants; such types would require an initializing expression --
+>>      no default initialization is defined for them.
+>
+>I think 9 and 10 are important.  I'm not quite willing to kill the whole
+>idea if I can't have 9 and 10, but since these work already for the
+>nonlimited case, it would seem pretty kludgy to leave them out in the
+>limited case.
+
+Agree I think 10 is more important than 9, but both will be very important.
+
+>>   11) Easy to implement
+>
+>Who could disaggree with that?  But I'm willing to put up with some
+>implementation complexity to get 9 and 10.
+
+Definitely agree.
+
+>>Other possible desirables:
+>>   12) Should not require alteration in the way limited types are laid out
+>>
+>>
+>
+>I think I agree, but I'm not really sure what you're getting at.  Which
+>proposal(s) violate this?
+
+No current proposal, AFAIK.  Doesn't mean a future new variation won't.
+But there is a difference between require and permit that should be kept
+in mind.  There will be cases where compilers can generate more
+efficient layouts for types that are just not used today.  Remember that
+my example code compiles cleanly today, the only problem is that it
+exports ADTs that can't be created by users.
+
+For example, it would be an optimization for a compiler that currently
+places unbounded structures on the heap and uses 'hidden' pointers in
+the structure to manage them for the compiler to allocate one contiguous
+chunck of the heap, for all components of a record, have
+pointers/offsets in the record structure, and just one heap object to
+free when the whole record is freed.   That doesn't mean that all
+compilers have to treat records with multiple constructors that way,
+just that a compiler is allowed to do so.
+
+To be honest, I expect that the objects in point 10 above will become
+common in Ada 0Y.  The types are currently legal in Ada 95/2000, but
+they just are not used.  (And not really very usable.)  So I don't know
+if any compilers have horrible overhead if someone does  create one.  If
+so, that compiler would probably need to change its layout policy for
+limited types.
+
+>>   13) Should allow us to still have function-like things
+>>       that return by reference
+>
+>I don't much care about that for my own code, but I think it would be
+>irresponsible of us to be incompatible with folks have used this
+>feature, even if we think perhaps it's a misguided feature.
+
+Huh?  Oh.  You don't use it because you don't use limited tagged types.
+This feature will become much more useful and less 'misguided' if we can
+initialize objects of types derived from Limited_Controlled more easily.
+
+>>   14) Should (or should not) use the word "constructor" somewhere
+>>   15) Should (or should not) use the word "limited" somewhere
+>>   16) Should (or should not) use the word "function" somewhere
+>
+>I have no strong opinion on the syntax, but I think these new kinds of
+>constructors are conceptually "functions".  They just happen to build
+>their result in the final resting place.
+>
+>Viewing them as "procedures" seems like a compiler-writer viewpoint; I'd
+>rather take a user-oriented viewpoint.  The fact that function results
+>can take their discriminants from the function parameters, but you can't
+>do that for 'out' parameters, is accidental, not fundamental.
+>
+>Viewing them as totally new animals seems like overkill.  To me, a
+>constructor is just a function that creates a new thing.  Number 8 above
+>implies that we need *some* sort of new syntax.  I would prefer to keep
+>it as close as possible to the existing function declaration syntax.
+>But I do not feel strongly about this.
+>
+>
+We really need Norman Cohen to take a look at the issue.  I'm sure he
+could come up with something.  Seriously, I have no objection to
+retaining the word function.  But I do want the syntax to indicate that
+this is one of those special "constructor" things to both the user and
+the compiler.  I don't like "limited function" because that implies that
+there are also "not limited function" types. ;-)   Using "constructor
+function" seems a bit wordy but otherwise fine.  Certainly whatever the
+syntax, the RM should talk about them as constructor functions or
+constructors.  I also tried out:
+
+function Foo return new Bar;
+
+But that seems to imply that a hidden pointer must be used.
+
+function Foo return inplace Bar;
+
+Is a bit better, but even with the precedent of goto, I don't like the
+idea of reserved words that are not English words.
+
+function Foo create Bar;
+
+Might be acceptable to everyone?  I am certainly open to any good ideas.
+
+>>   17) Should provide more efficient way for non-limited types to be returned/initialized
+>>
+>Seems like a nice side effect.  Not important.
+>
+Agree.  Well maybe more than just nice if we can improve the efficiency
+of Unbounded_String in some cases.  But certainly not a requirement.
+
+>>   18) Should not "orphan" existing language features
+>
+>This seems like a possible symptom of kludgery, but not a worthy goal in
+>its own right.  I mean, if I have to write "constructor" instead of
+>"function" all over the place in future code, that's not a disaster.
+
+One last suggested inclusion:
+
+19) If we adopt a partial solution, that partial solution shouldn't
+limit a future extention to cover everything.
+
+I am certainly willing to consider scope reduction of a complete
+solution, as long as it doesn't preclude ever fixing the excluded cases.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Monday, December  8, 2003, 5:52 PM
+
+Robert A Duff wrote:
+> ...
+> Can we also get concensus on this:
+>
+>     Every context that allows an initialization expression for
+>     nonlimited types should also allow it for limited types.
+
+I agree with that.  I also believe that the reverse should be true,
+namely there should be no contexts where calling these function-like
+things are permitted, but calling good-old functions returning
+non-limited types are not permitted.
+
+So in other words, from a user point of view, these are all very
+similar.  The limited-returning ones cannot be called in certain
+contexts because those contexts would require copying the
+result.  The only context I can think of off the top of my
+head is as the right hand-side of an assignment statement,
+though there are probably others.  Whether they can be
+used as the expression of a return statement depends on the details
+of how these limited-returning things are implemented (as opposed to
+called).
+
+It is the existing limited-returning-by-ref functions that are odd, because
+they can only be called in very limited contexts.  In particular,
+a call on one of these can be used as an IN parameter, in a renaming,
+and as a prefix of a name (anyplace else?).
+
+This is not so noticeable in Ada 95, because the limitedness of the result
+and the absence of aggregates and initialization of limited types, means
+that the by-ref-ness doesn't create much additional limitation.  *But*,
+if we add aggregates and initialization of limited types, then suddenly
+these kinds of functions have some odd-ball limitations which may be
+hard to remember, especially if there are function-like things that
+don't have these limitations.
+
+Hence, I feel pretty strongly that if we are going to use syntax to make
+these two kinds of limited-returning function-like things look different,
+we should make the existing returning-by-ref functions look different
+from non-limited-returning functions, and make the new more flexible
+limited-returning functions look like good old non-limited returning functions,
+since they have so much more in common (in terms of legal calling contexts).
+
+This is why I would recommend we require something like the word "limited" on
+a function if it will be returning by-ref, and can only be called in contexts
+where by-ref makes sense.  This is of course incompatible, but it is easily
+caught at compile-time, and compilers could start allowing the word "limited"
+right away, even before they support the new capability.
+
+> > Other possible desirables:
+> >    12) Should not require alteration in the way limited types are laid out
+>
+> I think I agree, but I'm not really sure what you're getting at.  Which
+> proposal(s) violate this?
+
+There were a lot of different ideas thrown around, but at least one of
+them implied that the caller might *not* know the size of the thing
+being allocated, nor where it was being allocated.  Clearly if
+you call one of these function-like things as a component of an aggregate,
+and you lay out limited types contiguously (even if some component is
+dynamic-sized), then the caller *must* specify where the object is allocated,
+and *must* know the size before it goes out-of-line so it can add up all the sizes
+of the components and do the one overall allocation in the appropriate place
+(on the secondary stack, in some user-specified storage pool, as a component
+of a yet larger limited object, etc.).
+
+I got the sense that one solution being bandied about was that limited components
+of dynamic size would *have* to use a level of indirection, precluding a contiguous
+allocation for an enclosing limited record.  This is not the way many compilers
+do things now, and so would imply a change in the way limited types are laid out.
+I would hope (12) is a point of consensus, but I couldn't tell if that were true
+based on the flurry of messages.
+
+>
+> >    13) Should allow us to still have function-like things
+> >        that return by reference
+>
+> I don't much care about that for my own code, but I think it would be
+> irresponsible of us to be incompatible with folks have used this
+> feature, even if we think perhaps it's a misguided feature.
+
+But perhaps call these things "limited functions" because if we add
+aggregates and initialized limited objects, these guys won't be callable
+in those contexts.  Alternatively, require that they be recast as
+functions returning anonymous access types, effectively moving the ".all" from the
+return expression to the point of call (since in my experience, these
+functions almost always return a reference to a heap object, due to accessibility
+limitations).
+
+> >    14) Should (or should not) use the word "constructor" somewhere
+> >    15) Should (or should not) use the word "limited" somewhere
+> >    16) Should (or should not) use the word "function" somewhere
+>
+> I have no strong opinion on the syntax, but I think these new kinds of
+> constructors are conceptually "functions".  They just happen to build
+> their result in the final resting place.
+
+I agree (as is presumably obvious).  As indicated above, it is the return-by-ref
+guys that will begin to look like oddballs, if we add limited aggregates and
+initialization.
+
+> Viewing them as "procedures" seems like a compiler-writer viewpoint; I'd
+> rather take a user-oriented viewpoint.  The fact that function results
+> can take their discriminants from the function parameters, but you can't
+> do that for 'out' parameters, is accidental, not fundamental.
+
+I'm not sure I followed that logic, but I agree that they should be *viewed*
+as functions.  The question is how does one implement these.  I fear
+that to achieve nice-to-have's (10) and (11), allowing the first subtype
+to have non-defaulted or unknown discriminants, combined with (12), creates
+a real challenge.  Renaming a procedure call as a function nicely solved
+all the problems:
+   a) the visible declaration is a function
+   b) the renaming declaration can use the parameters to specify the
+      discriminants for the returned (i.e. OUT) object (e.g. "(Disc => 3, others => <>)")
+   c) the out of line code has a name for the pre-allocated object so
+      it can refer to the discriminants.
+
+If there is another solution that has all these capabilities that would be
+great.  I have not found one.  The hardest problem is where the discriminants
+are not explicitly determined by the caller, but are instead determined
+by some computation on the IN parameters.
+
+One suggested solution was:
+
+   function Make_Text(Len : Natural) return Lim_Text(Len);
+
+But that doesn't work if the discriminants of Lim_Text are not visible (i.e. "(<>)").
+The renaming (of a procedure call) could work because the renaming can be
+in the private part.
+
+It may be that some mild restrictions could be added to deal with this
+problem.  I would hope the restrictions can be enforced on the *declaration*
+of the function rather than at the call site.  Otherwise I fear we
+will get into the "applicable index constraint" game, which I don't
+relish.  That is, certain calls would only be permitted when there is
+an applicable discriminant constraint.
+
+
+>
+> Viewing them as totally new animals seems like overkill.  To me, a
+> constructor is just a function that creates a new thing. ...
+
+And except for the oddball return-by-ref functions, all
+functions create a new thing.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Monday, December  8, 2003, 6:53 PM
+
+Tucker said:
+
+> Hence, I feel pretty strongly that if we are going to use syntax to make
+> these two kinds of limited-returning function-like things look different,
+> we should make the existing returning-by-ref functions look different
+> from non-limited-returning functions, and make the new more flexible
+> limited-returning functions look like good old non-limited returning
+functions,
+> since they have so much more in common (in terms of legal calling
+> contexts).
+>
+> This is why I would recommend we require something like the word "limited" on
+> a function if it will be returning by-ref, and can only be called in contexts
+> where by-ref makes sense.  This is of course incompatible, but it is easily
+> caught at compile-time, and compilers could start allowing the word "limited"
+> right away, even before they support the new capability.
+
+I don't mind that in a vacuum, but I think that it means that either (1)
+non-limited constructors are actually more expensive than current functions;
+or (2) converting a limited type to non-limited requires checking all
+functions for correct behavior.
+
+The former occurs because (in one model) you get a call to Initialize that
+generally can't be optimized away on top of the Adjust and Finalize calls
+that we already have; the latter occurs (in another model) because limited
+types call Initialize and non-limited types don't.
+
+I don't much like either result.
+
+> > > Other possible desirables:
+> > >    12) Should not require alteration in the way limited types are laid out
+> >
+> > I think I agree, but I'm not really sure what you're getting at.  Which
+> > proposal(s) violate this?
+>
+> There were a lot of different ideas thrown around, but at least one of
+> them implied that the caller might *not* know the size of the thing
+> being allocated, nor where it was being allocated.  Clearly if
+> you call one of these function-like things as a component of an aggregate,
+> and you lay out limited types contiguously (even if some component is
+> dynamic-sized), then the caller *must* specify where the object is allocated,
+> and *must* know the size before it goes out-of-line so it can add up all the sizes
+> of the components and do the one overall allocation in the appropriate place
+> (on the secondary stack, in some user-specified storage pool, as a component
+> of a yet larger limited object, etc.).
+
+Trying to lay out all possible record types contiguously is a fool's game.
+Kinda like trying to implement universal generic sharing. :-) It's possible
+to get it to work, but only with lots of standing on your head. And the
+result is very use-unfriendly: objects of reasonable types like
+   type Sane_Bounded_String (D : Natural := 0) record
+        Data :  String (1 .. D);
+   end record;
+raise Storage_Error unless constrained.
+
+In any case, the vast majority of real types can be implemented
+contiguously, with any of these proposals. (Most ADTs don't have
+discriminants anyway, at least not on the top-level types.) If a few types
+have to change representation in a few compilers (and only if there are
+constructors defined) to make this work, I cannot get too excited. It can't
+be incompatible: there are no constructors now.
+
+> > Viewing them as totally new animals seems like overkill.  To me, a
+> > constructor is just a function that creates a new thing. ...
+>
+> And except for the oddball return-by-ref functions, all
+> functions create a new thing.
+
+I guess I view these as a new thing because what they do is create a
+user-defined "construction" of an object; they need to replace the
+"initialization assignment" operation of Ada as well as the "initialization"
+itself. Existing functions do not change the semantics of assignment. For
+non-controlled types, the distinction doesn't really matter, but it is a big
+deal for controlled types (of all stripes).
+
+Also, I see a new thing as necessary, because I don't believe that a useful
+constructor can be defined that won't force some representation changes in
+compilers. (That is, (12) is an impossible goal; holding to it is a disaster
+from a user perspective -- it forces unnatural separations of construction
+code into parts. And the idea of somehow specifying an aggregate as the
+argument of an In Out parameter seems goofy.) As long as the constructors
+are explicit, then there isn't a problem in that existing code would not
+have to change representation.
+
+If we don't have the will to do this right this time, I don't think there is
+any value to another partial band-aid solution. Especially if it cannot be
+extended properly in the future. Which is why Tucker's procedure renaming
+just isn't going to work.
+
+****************************************************************
+
+From: Robert I. Eachus
+Sent: Monday, December  8, 2003, 7:52 PM
+
+Tucker Taft wrote:
+
+>Hence, I feel pretty strongly that if we are going to use syntax to make
+>these two kinds of limited-returning function-like things look different,
+>we should make the existing returning-by-ref functions look different
+>from non-limited-returning functions, and make the new more flexible
+>limited-returning functions look like good old non-limited returning functions,
+>since they have so much more in common (in terms of legal calling contexts).
+>
+>This is why I would recommend we require something like the word "limited" on
+>a function if it will be returning by-ref, and can only be called in contexts
+>where by-ref makes sense.  This is of course incompatible, but it is easily
+>caught at compile-time, and compilers could start allowing the word "limited"
+>right away, even before they support the new capability.
+>
+>
+It sounds like you are proposing to make detecting whether a function is
+a constructor or a "normal" function depend on whether or not it returns
+a limited type.
+
+But that doesn't work.  The problem is that the compiler may not know
+whether or not a function can be seen in contexts where its type must be
+returned by reference.  For example,  a generic formal part may specify
+a limited type, but the actual may be non-limited.  The reverse happens
+as well.  Inside a package where a type is declared as limited private,
+the type may or may not be limited.
+
+So I have been assuming that 'flagging' constructors as such must be
+done in syntax, and constructors for non-limited types must be allowed,
+subject to the same rules and restrictions as for limited types.  The
+"normal" case will be that a constructor is actually defined in a scope
+where the return type is non-limited, at least for non-tagged types.
+
+>There were a lot of different ideas thrown around, but at least one of
+>them implied that the caller might *not* know the size of the thing
+>being allocated, nor where it was being allocated.  Clearly if
+>you call one of these function-like things as a component of an aggregate,
+>and you lay out limited types contiguously (even if some component is
+>dynamic-sized), then the caller *must* specify where the object is allocated,
+>and *must* know the size before it goes out-of-line so it can add up all the sizes
+>of the components and do the one overall allocation in the appropriate place
+>(on the secondary stack, in some user-specified storage pool, as a component
+>of a yet larger limited object, etc.).
+>
+>I got the sense that one solution being bandied about was that limited components
+>of dynamic size would *have* to use a level of indirection, precluding a contiguous
+>allocation for an enclosing limited record.  This is not the way many compilers
+>do things now, and so would imply a change in the way limited types are laid out.
+>I would hope (12) is a point of consensus, but I couldn't tell if that were true
+>based on the flurry of messages.
+>
+>
+Yes, it is not just being thrown around, it is the other proposal on the
+table.  However, there is a solution which doesn't require the caller to
+know the size of the object at the point of the call, and does not
+require a level indirection.  This requires the caller to pass a thunk
+to the constructor.  When the constructor is ready to allocate the
+actual object, it calls the thunk, giving the needed size, and the thunk
+returns an address.  The thunk can be an allocator for some heap, or can
+be code to add the size information to the size for some object on top
+of the stack.  The case of an object with many constructors as part of
+say an initial value aggregate can be accomodated by calling all the
+tasks in sequence, if the object is being created on a different stack
+than the one that contains the object being created, or in the case of a
+heap object, you can get a large chunk of heap, and eventually return
+what is not used.
+
+Like Randy, though, I consider that whether an implementation uses
+indirection for some types should be left to the implementor.  There are
+cases where it is more user friendly--and also more efficient at
+run-time--to do that.  The particular case of arrays of
+Unbounded_Strings is not an idle pasttime, it comes up fairly frequently
+so that it is worth looking at performance of various solutions in that
+case.  (Unbounded_String is a weird case in general.  If you implement
+Unbounded_Strings efficiently they are really limited objects that
+cannot be copied.  What happens on assignment is a "deep copy" that
+clones the object.)
+
+>>>   13) Should allow us to still have function-like things
+>>>       that return by reference
+>>>
+>>>
+>But perhaps call these things "limited functions" because if we add
+>aggregates and initialized limited objects, these guys won't be callable
+>in those contexts.  Alternatively, require that they be recast as
+>functions returning anonymous access types, effectively moving the ".all" from the
+>return expression to the point of call (since in my experience, these
+>functions almost always return a reference to a heap object, due to accessibility
+>limitations).
+>
+>
+I'm going to stay out of this argument, other than to say I will
+probably recast those functions that are actually return by reference
+using the new semantics.  But I don't want to have to do it at gunpoint.
+
+>I'm not sure I followed that logic, but I agree that they should be *viewed*
+>as functions.  The question is how does one implement these.  I fear
+>that to achieve nice-to-have's (10) and (11), allowing the first subtype
+>to have non-defaulted or unknown discriminants, combined with (12), creates
+>a real challenge.  Renaming a procedure call as a function nicely solved
+>all the problems:
+>   a) the visible declaration is a function
+>   b) the renaming declaration can use the parameters to specify the
+>      discriminants for the returned (i.e. OUT) object (e.g. "(Disc => 3, others => <>)")
+>   c) the out of line code has a name for the pre-allocated object so
+>      it can refer to the discriminants.
+>
+>If there is another solution that has all these capabilities that would be
+>great.  I have not found one.  The hardest problem is where the discriminants
+>are not explicitly determined by the caller, but are instead determined
+>by some computation on the IN parameters.
+>
+You have not found one, but Randy and I have.  I think it requires more
+compiler implementation work than your approach, and in some cases it
+will be less efficient (more information passed in the call).  But the
+advantage of the approach is that it does cover all cases, including
+those where neither the caller nor the constructor can know the size of
+the returned object until the point of the return statement.  Yes, if
+the compiler sees that for some types the constructors can return
+objects larger that the largest stack available, it may decide to use
+(hidden) indirection in such objects.  But I consider that to just be
+the nature of Ada.  (Has anyone really thought about what will happen
+when creating an allocate the maximum unconstrained String doesn't
+always raise Storage_Error?  In the early days, there were a few
+compilers, including the one for the DPS6, that used 16-bits for
+Integer, but a few years ago I ordered a machine with 4 Gig of memory.
+Of course the OS wouldn't allow 2Gig to be allocated for one String, but
+that day is coming.)
+
+Is it worth this potential extra overhead to make declaring private
+types with unknown discriminants work right?  I think so.  I also think
+the syntax is easier to use in the easier cases which will make the new
+constructs more popular.
+
+>It may be that some mild restrictions could be added to deal with this
+>problem.  I would hope the restrictions can be enforced on the *declaration*
+>of the function rather than at the call site.  Otherwise I fear we
+>will get into the "applicable index constraint" game, which I don't
+>relish.  That is, certain calls would only be permitted when there is
+>an applicable discriminant constraint.
+>
+>
+I very much don't relish that either.
+
+>And except for the oddball return-by-ref functions, all
+>functions create a new thing.
+>
+>
+That is a compiler implementor's view of return by value. ;-)  Users
+talk all the time about functions returning this or returning that when
+they are just returning a copy of an existing object.  From the user's
+point of view, a constructor is different even for non-limited types.
+It might be better to say that a constructor constructs a new value,
+while many functions return existing values.  Of course, arithmetic
+operations don't really fit this picture, but they are already special
+in a different way.  But especially for non-limited ADTs I see a
+semantic division between constructors, which build new records, and
+selector functions that return existing records.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Monday, December  8, 2003, 10:28 PM
+
+> Tucker said:
+>
+> > Hence, I feel pretty strongly that if we are going to use syntax to make
+> > these two kinds of limited-returning function-like things look different,
+> > we should make the existing returning-by-ref functions look different
+> > from non-limited-returning functions, and make the new more flexible
+> > limited-returning functions look like good old non-limited returning
+> functions,
+> > since they have so much more in common (in terms of legal calling
+> > contexts).
+> >
+> > This is why I would recommend we require something like the word "limited"
+> on
+> > a function if it will be returning by-ref, and can only be called in
+> contexts
+> > where by-ref makes sense.  This is of course incompatible, but it is
+> easily
+> > caught at compile-time, and compilers could start allowing the word
+> "limited"
+> > right away, even before they support the new capability.
+>
+> I don't mind that in a vacuum, but I think that it means that either (1)
+> non-limited constructors are actually more expensive than current functions;
+> or (2) converting a limited type to non-limited requires checking all
+> functions for correct behavior.
+
+Unfortunately, I have completely lost you.  I was trying to
+focus on the "call" side of things first, before plunging
+into the body/implementation side.  Once we know what we want
+from the call side, we can start to figure out what we need
+to provide on the body/implementation side.
+
+So strictly from the call side, non-limited-returning functions
+always create/initialize a new object.  Unfortunately, in Ada 95,
+the only limited-returning functions are return-by-ref of
+a preexisting object (when I say limited, I mean
+"truly" limited).
+
+Now what AI-318 is trying to provide is limited-returning
+function-like things that create/initialize a new object,
+very much like non-limited-returning functions.
+This is important because we are now proposing to allow
+limited objects to have initializing expressions, and
+we want to allow a function-call-like thing for those
+expressions.  Unfortunately, the existing limited-returning
+functions are exactly the *wrong* thing for these new
+contexts.
+
+These by-ref functions didn't seem so odd when we didn't
+allow limited initializing expressions.  There were no
+contexts where they couldn't be called due their by-ref-ness.
+The limited-ness was enough to eliminate all such contexts.
+But now we have proposed new contexts where limited types
+are allowed, but the existing kinds of functions can't
+be called in those contexts -- a definite pity.
+
+> The former occurs because (in one model) you get a call to Initialize that
+> generally can't be optimized away on top of the Adjust and Finalize calls
+> that we already have; the latter occurs (in another model) because limited
+> types call Initialize and non-limited types don't.
+
+Let's just for a moment ignore this issue of whether
+the object has to be default initialized and then re-initialized.
+Notice that I didn't mention that in any of my
+"consensus" lists, and that's not what I am focusing
+on now.  I am happy to keep searching for a solution
+that avoids the double initialization.  What I
+want first is a good specification of what the solution
+should look like on the *call* side.
+
+> I don't much like either result.
+
+I think you are talking about the implementation side,
+but let's first try to agree about the call side.
+
+> > > > Other possible desirables:
+> > > >    12) Should not require alteration in the way limited types are laid
+> out
+> ...
+> Trying to lay out all possible record types contiguously is a fool's game.
+> Kinda like trying to implement universal generic sharing. :-) It's possible
+> to get it to work, but only with lots of standing on your head. And the
+> result is very use-unfriendly: objects of reasonable types like
+>    type Sane_Bounded_String (D : Natural := 0) record
+>         Data :  String (1 .. D);
+>    end record;
+> raise Storage_Error unless constrained.
+>
+> In any case, the vast majority of real types can be implemented
+> contiguously, with any of these proposals. (Most ADTs don't have
+> discriminants anyway, at least not on the top-level types.) If a few types
+> have to change representation in a few compilers (and only if there are
+> constructors defined) to make this work, I cannot get too excited. It can't
+> be incompatible: there are no constructors now.
+
+Are you proposing that if a programmer writes a function-like
+thing for a limited type, then the layout changes?  I really think
+that is very bad news.  And despite your concern about laying out records
+contiguously, I am pretty certain that GNAT, Rational, Green
+Hills, and Aonix all lay out records contiguously (I am *very*
+certain about Green Hills and Aonix ;-).  I think that
+represents about 95% of the Ada market.
+
+> > > Viewing them as totally new animals seems like overkill.  To me, a
+> > > constructor is just a function that creates a new thing. ...
+> >
+> > And except for the oddball return-by-ref functions, all
+> > functions create a new thing.
+>
+> I guess I view these as a new thing because what they do is create a
+> user-defined "construction" of an object; they need to replace the
+> "initialization assignment" operation of Ada as well as the "initialization"
+> itself. Existing functions do not change the semantics of assignment. For
+> non-controlled types, the distinction doesn't really matter, but it is a big
+> deal for controlled types (of all stripes).
+
+From the call-side, I don't see the big difference.
+Even from the implementation side, it seems like we are
+just trying to eliminate some extra "last minute" copying
+that is currently part of non-limited-type function
+semantics.  Many functions are written with a local
+"Result" parameter, which is then built up as desired,
+and then returned.  Many other functions are little more
+than the return of an aggregate.  Both of these are
+clearly creating/initializing new objects.  All we need to
+arrange is that in both cases for a limited type,
+the object to be returned is built in its final
+resting place.  And the discriminants, if any, are known
+on the call side (at least to the generated code), before
+the out-of-line code begins.
+
+I suppose one (crazy?) possibility is that such functions must be
+inlined if the compiler run-time model needs additional
+information from the body, whereas they need not be
+inlined if the compiler run-time model uses implicit
+levels of indirection.  This would make it quite analogous
+to the case with generics, where some compilers need the
+body to be able to generate code for an instance, while
+others don't, because their run-time model supports
+sharing.
+
+> Also, I see a new thing as necessary, because I don't believe that a useful
+> constructor can be defined that won't force some representation changes in
+> compilers. (That is, (12) is an impossible goal; holding to it is a disaster
+> from a user perspective -- it forces unnatural separations of construction
+> code into parts. And the idea of somehow specifying an aggregate as the
+> argument of an In Out parameter seems goofy.) As long as the constructors
+> are explicit, then there isn't a problem in that existing code would not
+> have to change representation.
+
+I think you are again implying that by writing a constructor-ish-thing,
+the record representation would change.  This seems quite undesirable
+to me.
+
+> If we don't have the will to do this right this time, I don't think there is
+> any value to another partial band-aid solution. Especially if it cannot be
+> extended properly in the future. Which is why Tucker's procedure renaming
+> just isn't going to work.
+
+It would help if you had an example of the kind of extension you
+had in mind.    I promise I am not wedded to the procedure
+renaming approach, but I do think it satisfies the requirements,
+except perhaps from an aesthetic point of view.  I think we still
+might be able to make the "return ... do ..." approach work,
+but there would probably be more limitations.  In any case,
+I believe these things still have so much in common with
+functions that calling them anything else would hurt more than
+it would help.
+
+>          Randy.
+
+Here is a proposal that does not involve renaming:
+
+  1) Require "limited" (or some such word) if the function is going to
+     return its result by reference; all other functions must
+     return/initialize "new" objects.
+     By-ref functions can only be called in contexts that don't
+     require a new object (e.g. as an IN parameter or a renaming).
+     [Better long-term alternative: replace these oddball functions
+      with functions that have anonymous access-to-limited result types,
+      since that is what they really are.]
+
+  2) Allow "return Result : Type := <expr> do ... end return;" as a way of
+     having a name for the "new" object being returned/initialized.
+
+  3) If a limited type has "normal" functions, then its full type
+     must be definite (e.g., there must be defaults for its discriminants).
+     Note that its partial view may be indefinite (i.e. "(<>)").
+     Also note that the discriminants, though defaulted, may be given
+     new values by the initializing <expr>, if the object to be returned is
+     unconstrained (i.e. Result'Constrained is False).  This ensures
+     that the discriminants have well-defined values coming into
+     the function, though they may be changed if the new object
+     is unconstrained.
+
+  4) If the (full) result subtype is definite (and hence for
+     all limited types), then the name given in the return ... do ...
+     (e.g. "Result") can be used within the <expr> itself,
+     but only as a prefix for discriminants and the 'Constrained
+     attribute.  If 'Constrained is False, then within <expr>,
+     Result.<discrim> will necessarily be equal to its default value.
+     After <expr>, the discriminants will have the value that was
+     determined by <expr>.
+
+The above ensures that for run-time models that need it, the
+discriminants and hence the size are known prior to going to
+out-of-line code, allowing the caller to do the allocation,
+and/or to include the object contiguously in an enclosing record or array, etc.
+
+The only real restriction is that if a limited type is going
+to allow objects to have their discriminants determined by an
+initializing expression, the full type must have defaults for
+the discriminants.  And this restriction is enforced when the
+full type is declared, rather than when these functions are called.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Monday, December  8, 2003, 11:13 PM
+
+Tucker said:
+
+> Unfortunately, I have completely lost you.  I was trying to
+> focus on the "call" side of things first, before plunging
+> into the body/implementation side.  Once we know what we want
+> from the call side, we can start to figure out what we need
+> to provide on the body/implementation side.
+
+I have no idea what you mean by "call side". In any case, the only valid
+subsetting is to look at it from the user's perspective rather than the
+implementors. Other divisions just mean that you are ignoring half of the
+issues, and you're bound to get the wrong answer then.
+
+...
+> Let's just for a moment ignore this issue of whether
+> the object has to be default initialized and then re-initialized.
+> Notice that I didn't mention that in any of my
+> "consensus" lists, and that's not what I am focusing
+> on now.  I am happy to keep searching for a solution
+> that avoids the double initialization.  What I
+> want first is a good specification of what the solution
+> should look like on the *call* side.
+
+Then you're not looking at the whole issue. That's not an implementation
+detail, it's a very visible part of the user semantics.
+
+The only question is "what makes sense to the user of Ada 2005"? Once we've
+figured that out, we can look at whether some implementation restrictions
+are needed. That's the only sensible approach.
+
+...
+> > I guess I view these as a new thing because what they do is create a
+> > user-defined "construction" of an object; they need to replace the
+> > "initialization assignment" operation of Ada as well as the "initialization"
+> > itself. Existing functions do not change the semantics of assignment. For
+> > non-controlled types, the distinction doesn't really matter, but it is a big
+> > deal for controlled types (of all stripes).
+>
+> From the call-side, I don't see the big difference.
+> Even from the implementation side, it seems like we are
+> just trying to eliminate some extra "last minute" copying
+> that is currently part of non-limited-type function
+> semantics.
+
+We're also trying to eliminate unnecessary calls on Initialize, Adjust, and
+Finalize. Since those are very difficult to optimize without breaking the
+user's code, semantics which call them less often and still is safe is
+important.
+
+> > Also, I see a new thing as necessary, because I don't believe that a useful
+> > constructor can be defined that won't force some representation changes in
+> > compilers. (That is, (12) is an impossible goal; holding to it is a disaster
+> > from a user perspective -- it forces unnatural separations of construction
+> > code into parts. And the idea of somehow specifying an aggregate as the
+> > argument of an In Out parameter seems goofy.) As long as the constructors
+> > are explicit, then there isn't a problem in that existing code would not
+> > have to change representation.
+>
+> I think you are again implying that by writing a constructor-ish-thing,
+> the record representation would change.  This seems quite undesirable
+> to me.
+
+Not "would", but "could" -- in unlikely cases. If the type is definite,
+there is never a problem with any proposal.
+
+> > If we don't have the will to do this right this time, I don't think there is
+> > any value to another partial band-aid solution. Especially if it cannot be
+> > extended properly in the future. Which is why Tucker's procedure renaming
+> > just isn't going to work.
+>
+> It would help if you had an example of the kind of extension you
+> had in mind.    I promise I am not wedded to the procedure
+> renaming approach, but I do think it satisfies the requirements,
+> except perhaps from an aesthetic point of view.  I think we still
+> might be able to make the "return ... do ..." approach work,
+> but there would probably be more limitations.  In any case,
+> I believe these things still have so much in common with
+> functions that calling them anything else would hurt more than
+> it would help.
+
+Sheesh, Tuck, I wrote up a rough description of syntax and semantics
+yesterday. Do I have to do it again??
+
+> Here is a proposal that does not involve renaming:
+>
+>   1) Require "limited" (or some such word) if the function is going to
+>      return its result by reference; all other functions must
+>      return/initialize "new" objects.
+>      By-ref functions can only be called in contexts that don't
+>      require a new object (e.g. as an IN parameter or a renaming).
+>      [Better long-term alternative: replace these oddball functions
+>       with functions that have anonymous access-to-limited result types,
+>       since that is what they really are.]
+
+That's a lousy better alternative, even if it is accurate. I don't think we
+ever want to force the introduction of access type where there currently are
+none.
+
+>   2) Allow "return Result : Type := <expr> do ... end return;" as a way of
+>      having a name for the "new" object being returned/initialized.
+
+So (1) and (2) are pretty close to what I proposed Saturday night (except
+for syntax). It's not clear to me what the user-level semantics for
+non-limited types is supposed to be.
+
+>   3) If a limited type has "normal" functions, then its full type
+>      must be definite (e.g., there must be defaults for its discriminants).
+>      Note that its partial view may be indefinite (i.e. "(<>)").
+>      Also note that the discriminants, though defaulted, may be given
+>      new values by the initializing <expr>, if the object to be returned is
+>      unconstrained (i.e. Result'Constrained is False).  This ensures
+>      that the discriminants have well-defined values coming into
+>      the function, though they may be changed if the new object
+>      is unconstrained.
+
+Tagged types don't allow defaults for discriminants. So you're saying that
+useful limited types either must not be tagged or must not have
+discriminants. That seems pretty fierce.
+
+And, in any case, I don't see what this has to do with the user perspective.
+You said something about ignoring implementation details, and I can't see
+any reason for this other than an implementation detail.
+
+>   4) If the (full) result subtype is definite (and hence for
+>      all limited types), then the name given in the return ... do ...
+>      (e.g. "Result") can be used within the <expr> itself,
+>      but only as a prefix for discriminants and the 'Constrained
+>      attribute.  If 'Constrained is False, then within <expr>,
+>      Result.<discrim> will necessarily be equal to its default value.
+>      After <expr>, the discriminants will have the value that was
+>      determined by <expr>.
+
+Is this necessary? I haven't tried to work out full examples, but it adds
+complications where none seems to be needed. Anything that needs to refer to
+the name should be in the statement part, I would think. What would you need
+to do in that expression that can't be deferred to the body??
+
+> The above ensures that for run-time models that need it, the
+> discriminants and hence the size are known prior to going to
+> out-of-line code, allowing the caller to do the allocation,
+> and/or to include the object contiguously in an enclosing record
+> or array, etc.
+
+That seems like an implementation detail, again. That's fair game, of
+course, but not when you say "let's focus on the user view".
+
+> The only real restriction is that if a limited type is going
+> to allow objects to have their discriminants determined by an
+> initializing expression, the full type must have defaults for
+> the discriminants.  And this restriction is enforced when the
+> full type is declared, rather than when these functions are called.
+
+I agree that (hard) restrictions should be enforced when the constructor is
+declared (it's not really a problem with the type). There's nothing wrong
+with run-time checks if something is declared to be indefinite, but not
+otherwise. But I'd prefer to avoid restrictions if we can.
+
+I note that this proposal does seem to allow deferring or eliminating
+default initialization. But it seems to imply that non-limited types still
+require a copy (and Adjust call) afterwards. I'd much prefer to allow
+build-in-place. Perhaps the new 7.6.1 would allow that?
+
+---
+
+My quicky summary of the user view of constructors:
+
+1) These should be usable anywhere that an aggregate can be, with similar
+semantics.
+   (This implies that top-level Adjust or Initialize should not be called on
+them in general.)
+2) There should be as few as possible restrictions on the declarations and
+use of constructors.
+3) They shouldn't feel "weird".
+   (This implies retaining the function call-like syntax -- ":= Create(...);",
+   and that the declaration probably should look something like a function call.)
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, December  9, 2003, 12:07 AM
+
+Tucker said, responding to me:
+> > Is this necessary? I haven't tried to work out full examples, but it adds
+> > complications where none seems to be needed. Anything that needs to refer to
+> > the name should be in the statement part, I would think. What would you need
+> > to do in that expression that can't be deferred to the body??
+>
+> If you want to specify the initial value as an aggregate, you have
+> to specify the values for the discriminants.  If you want them
+> to match the newly created object, you need to be able to refer
+> to the discriminants of the newly created object.
+
+OK. That seems like a nice-to-have rather than a requirement. Without it,
+you still could pass the discriminants as parameters to the constructor if
+you had to. Not as pretty, but workable. A lot of the time, you'd want to do
+that anyway. I'd hate to kill the proposal with some funny visibility that
+isn't strictly necessary.
+
+> > I note that this proposal does seem to allow deferring or eliminating
+> > default initialization. But it seems to imply that non-limited types still
+> > require a copy (and Adjust call) afterwards. I'd much prefer to allow
+> > build-in-place. Perhaps the new 7.6.1 would allow that?
+>
+> I don't think I was making any such requirement.  Many compilers
+> currently preallocate space for the value returned by
+> a function having a non-limited composite result type.
+> The return ... do ... construct would allow that
+> space to be used directly.  For functions returning values
+> on the secondary stack, it would also be possible to build
+> the returned value directly on the secondary stack,
+> and avoid cutting back the secondary stack upon return
+> and just use it where it was placed.  We already do that
+> in certain circumstances.
+
+I think you're relying on 11.6 and 7.6.1 to get there. Right? That's fine as
+long as those sections have the right effect (and we all agree that is an
+appropriate effect).
+
+I don't think that the original 7.6.1 would have allowed that optimization
+(even though compilers probably do it!), but the new one ought to.
+
+> With limited types we need to create enough restrictions
+> to ensure it can be built in place.  For non-limited types,
+> the return ... do ... construct makes it more likely that
+> no extra copies are required, but we can't impose enough
+> restrictions to ensure that no copies are needed in all
+> run-time models.
+
+That's fair. It seems likely that a copy would have to be done sometime
+(certainly for elementary types, although that's no real problem).
+
+> > My quicky summary of the user view of constructors:
+> >
+> > 1) These should be usable anywhere that an aggregate can be, with similar
+> > semantics.
+> >    (This implies that top-level Adjust or Initialize should not be called on
+> > them in general.)
+> > 2) There should be as few as possible restrictions on the declarations and
+> > use of constructors.
+> > 3) They shouldn't feel "weird".
+> >    (This implies retaining the function call-like syntax -- ":= Create(...);", and that the
+> >    declaration probably should look something like a function call.)
+>
+> I agree with the above, and as indicated, I see no reason
+> not to call them functions.  The "return ... do ..." construct
+> might be called a "constructor statement" or some such thing
+> if you want to get the term "constructor" into the language ;-).
+
+It wouldn't hurt, but I'm certainly not going to be banging any shoes if it
+doesn't happen. :-)
+
+****************************************************************
+
+From: Robert I. Eachus
+Sent: Tuesday, December  9, 2003, 10:51 AM
+
+Wow!  I think we are finally converging, but four long messages, two
+each from Tucker and Randy, after I gave up for the night?  Is Tucker
+already on California time? ;-)
+
+But I would like to start pulling out one issue at a time to resolve.
+In this particular case, I am going to set ground rules for this thread,
+since it presumes that certain things will be adopted.  In this case,
+the RM requirements to be specified for initializing objects inside the
+return <object declaration> do <sequence of statements> end;
+
+My feeling is that in reality writing useful constructors for private
+types outside the body of the package that defines the type (or one of
+its children) is going to be a pretty useless capability.  Not totally
+useless, but okay to ignore for now.  This means that if there are
+discriminants, we can assume they are known and visible, and the same
+with other fields of the target type.  (But the fields of the parent
+type may not be visible in this context.)
+
+The three options that seem worth discussing are:
+
+1) Controlled types are initialized implicitly.
+2) Default initialization only occurs if there is no explicit
+initialization: (return Foo: Bar := (this, that, etc) do...)
+3) We are all big boys here.  (The constructor is normally defined by
+the same person who writes Initialize or assigns defaults.)  So there
+are no default initializations, and no run-time checks.
+4) There is a run-time check at the end of the do...end; and  an
+exception is raised if any discriminants of the object were not initialized.
+
+I think that all of these are technically viable given the way things
+seem to be headed, so this is really a normative discussion   (What do
+we want to happen?).  The one troubling case I see can occur if we
+decide that if the target is constrained its discriminants, if any get
+'copied' in from the target object.  (In practice they will be the same
+object, no copying needed.)  Then if a constructor that assumes it will
+get the constraints from the target is used to create an object that
+will get its constraints from the initial value, something should
+happen.  This leads me to tend toward 4).  If the sequence of statements
+checks 'Constrained and initializes the discriminants (or other bounds)
+if false, then the check can be optimized away.  Otherwise the
+constructor should raise Program_Error.  Compilers can provide warnings
+if code for the check is generated, or if something that reads the
+discriminants in the sequence of statements occurs where the
+discriminants may not yet be initialized.
+
+Notice though, that it might be nice if 'Constrained could be checked
+before the return statement.  I think that this is the one detail that I
+miss from my proposal in Randy's variation.  There will be cases where a
+programmer would like to write:
+
+if Foo'Constrained
+then return ...;
+else return ...;
+end if;
+
+Allowing the user to use the name of the constructor in this instance as
+a prefix for 'Constrained would allow this.  I don't see any real need
+for other attributes of the target outside the return.
+
+Which brings up an interesting point.  Will there be a restriction that
+prevents return statements inside the sequence of statements of a return
+construct?  If not, then the above will work.  But I think the principle
+of least surprise says that nested return statements should be illegal.
+
+Rule 2), it seems to me is the other contender.  If there is no explicit
+initialization in the object declaration, implicit initialization
+occurs.  This solves what to me is one troubling case with 4).  If some
+fields of a record type have defaults, those default initializations may
+not happen, and there will be no warning to the  programmer.
+
+I guess I am comfortable with either 2) or 4).  I think for most types,
+and most constructors, there will be an explicit aggregate initial
+value, with the sequence of statements if present doing any fixup
+needed.  As long as double initialization doesn't occur in that case, I
+am happy.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, December  9, 2003, 11:01 AM
+
+Robert Eachus said:
+> The three options that seem worth discussing are:
+>
+> 1) Controlled types are initialized implicitly.
+> 2) Default initialization only occurs if there is no explicit
+> initialization: (return Foo: Bar := (this, that, etc) do...)
+> 3) We are all big boys here.  (The constructor is normally defined by
+> the same person who writes Initialize or assigns defaults.)  So there
+> are no default initializations, and no run-time checks.
+> 4) There is a run-time check at the end of the do...end; and  an
+> exception is raised if any discriminants of the object were not
+> initialized.
+
+"Three options"? I see four. :-)
+
+...
+> I guess I am comfortable with either 2) or 4).  I think for most types,
+> and most constructors, there will be an explicit aggregate initial
+> value, with the sequence of statements if present doing any fixup
+> needed.  As long as double initialization doesn't occur in that case, I
+> am happy.
+
+I had proposed (2). I agree that we don't want objects floating about that
+haven't been initialized at all. And, being able to write a specific
+initialization expression allows overridding that (or pieces of it, given
+the <> notation). That seems powerful enough to me.
+
+(And nested returns aren't allowed. Once a return object is created, it has
+to be returned. Otherwise, you wouldn't be able to build the object in
+place, which is the whole point.)
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Tuesday, December  9, 2003, 11:01 AM
+
+> The three options that seem worth discussing are:
+      ^^^^^ "four" ;-)
+
+> 1) Controlled types are initialized implicitly.
+> 2) Default initialization only occurs if there is no explicit
+> initialization: (return Foo: Bar := (this, that, etc) do...)
+> 3) We are all big boys here.  (The constructor is normally defined by
+> the same person who writes Initialize or assigns defaults.)  So there
+> are no default initializations, and no run-time checks.
+> 4) There is a run-time check at the end of the do...end; and  an
+> exception is raised if any discriminants of the object were not initialized.
+
+Only (2) makes sense to me.
+
+****************************************************************
+
+From: Robert I. Eachus
+Sent: Tuesday, December  9, 2003,  4:57 PM
+
+Tucker Taft wrote:
+
+> > The three options that seem worth discussing are:
+>
+>  ^^^^^ "four" ;-)
+
+"A foolish consistancy is the hobgoblin of little minds."  -- Ralph
+Waldo Emerson.
+(Seriously, I decided to add case three, then didn't change the prefix.
+Of course, I was originally intending to leave case three out as not
+making much sense for Ada. ;-)
+
+> > 2) Default initialization only occurs if there is no explicit initialization:
+> > (return Foo: Bar := (this, that, etc) do...)
+>
+>  Only (2) makes sense to me.
+
+Since 2 is acceptable to me also, shall we consider that issue
+resolved?  Any other votes?
+
+The object in the return statement gets initialized, including a call to
+an explicit Initialize for controlled types, and and default values for
+record components, unless there is an initial value in the return statement.
+
+This implies that the syntax for these special returns should allow:
+
+return Foo: Bar := (some initial value aggregate); --without a do ... end;
+
+****************************************************************
+
+From: Robert A. Duff
+Sent: Tuesday, December  9, 2003, 5:34 PM
+
+Robert Eachus wrote:
+
+> "A foolish consistancy is the hobgoblin of little minds."  -- Ralph
+> Waldo Emerson.
+
+;-)
+
+> > > 2) Default initialization only occurs if there is no explicit initialization:
+> > > (return Foo: Bar := (this, that, etc) do...)
+> >
+> >  Only (2) makes sense to me.
+>
+> Since 2 is acceptable to me also, shall we consider that issue
+> resolved?  Any other votes?
+
+I agree with (2).
+
+****************************************************************
+
+From: Jean-Pierre Rosen
+Sent: Tuesday, December  9, 2003, 10:31 AM
+
+> Consensus statements about Ada 200Y if we were to approve AI-318:
+>
+>    1) Should be possible to declare an object of a limited
+>       type and provide an initializing expression
+>    2) Should be possible to use an initialized allocator for
+>       an access-to-limited type
+This is of course what is basically required. However, I think something
+is missing from the list:
+- the function-like thing should be able to access the characteristics
+(discriminants, bounds, etc) of the object being constructed.
+
+Seems to me that without this requirement, we could just allow
+initialization of limited types (but not assignment, of course).
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Tuesday, December  9, 2003, 12:04 PM
+
+Good point.  We clearly need to be able to query the constraints
+of the "new" object.  I said these constraints should be visible
+in the initializing expression.  They should also be visible
+in the subtype indication of:
+
+  return Result : <subtype_ind> [:= <expr>] do ...
+
+I suppose if the <subtype_ind> is unconstrained, then the
+constraints come from the calling context.
+If the <subtype_ind> is constrained, then there must be
+a check that the constraints are compatible with those coming
+from the calling context.
+
+> Seems to me that without this requirement, we could just allow
+> initialization of limited types (but not assignment, of course).
+
+I don't understand this sentence.
+
+****************************************************************
+

Questions? Ask the ACAA Technical Agent