CVS difference for ais/ai-00318.txt

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

--- ais/ai-00318.txt	2004/01/08 04:16:38	1.7
+++ ais/ai-00318.txt	2004/01/23 04:59:27	1.8
@@ -3434,3 +3434,1448 @@
 
 ****************************************************************
 
+From: Robert I. Eachus
+Sent: Tuesday, December  9, 2003,  6:10 PM
+
+ Emboldened by my success at settling the initialization issue (I
+hope!), I'll see if I can separate out another normative issue
+and resolve it.   This one may be more controversial though.  What
+should the syntax be for the new declarations?  (As far as I am
+concerned, I think this issue is distinct from Tucker's renaming
+proposal, because the renaming would normally be in the private part, or
+possibly in the body.)  I started by suggesting a change from function
+to constructor as a placeholder for the new syntax.  But from what I
+have seen, the idea of having a marker in the syntax is as popular as
+replacing the reserved word function is unpopular.
+
+I'll try to list the proposals which, to my knowledge have not yet been
+shouted down.  Of course, additional candidates are possible.  The
+current syntax rules are in 6.1 and 3.2.2 and I use terms from there in
+angle brackets:
+
+1) constructor function <defining identifier> <formal_part> return
+<subtype mark>;
+2) function <defining identifier> <formal_part> return <defining
+identifier> : <subtype indication>;
+(This is my variation of a proposal by Dan Eilers.  I put the initial
+value part below...)
+3) function <defining identifier> <formal_part> return new <subtype mark>;
+4) function <defining identifier> <formal_part> create <subtype mark>;
+
+Also there are some cases that either get permitted or ruled out by the
+syntax.  These are:
+
+A) Should it be possible for a constructor function to be a child
+program unit?
+B) Should it be possible for a constructor function to be an operator?
+(For example "+")
+C) Should it be possible for a constructor to be declared abstract?
+D) Is there a need to change the <subtype mark> to a <subtype indication>?
+This would allow constraints in constructor declarations.  They are not
+permitted as such in function declarations, because the value returned
+is not checked against some constraints. (But others are checked, see
+4.6 for details)  We may want to change this and/or these rules for
+constructors.
+E) In option 2, should an initial value be allowed after the subtype
+mark in the object declaration?  (This would probably be instead of in
+the return statement.)
+F) Again in option 2, should aliased or constant be allowed before the
+subtype delaration?
+G) Also in option 2, what about allowing <array_type_definition> instead
+of  <subtype indication>?
+
+I should give my votes, I guess.  3) is a slight leader IMHO among the
+syntax proposals, but I keep hoping for someone to come up with a better
+option. (The new implies heap use to Ada programmers.)  A. Not
+necessary,  B. Yes,  C. Yes,  D. No, E. Yes, F. No, G. Useless.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Tuesday, December  9, 2003,  8:52 PM
+
+Robert I. Eachus wrote:
+>
+> 1) constructor function <defining identifier> <formal_part> return
+> <subtype mark>;
+> 2) function <defining identifier> <formal_part> return <defining
+> identifier> : <subtype indication>;
+> (This is my variation of a proposal by Dan Eilers.  I put the initial
+> value part below...)
+> 3) function <defining identifier> <formal_part> return new <subtype mark>;
+> 4) function <defining identifier> <formal_part> create <subtype mark>;
+
+None of the above.  Functions always create new objects
+(except for the funny return-by-ref ones which might
+better be called "object selectors" or some such thing).
+The only issue is whether you have a name for the
+object being created, and whether the properties of
+that object can be inherited from the calling context.
+This can be a useful capability for any function that
+returns a composite object, limited or non-limited.
+
+As I suggested, I would argue for distinguishing the
+existing return-by-reference functions.  These are the
+ones that are going to be of limited use, and in particular,
+a call on one of these will *not* be usable at the initialization
+expression for a declared object or an aggregate component.
+
+I would suggest for the return-by-reference "functions":
+
+    limited function Ret_By_Ref(...) return Lim;
+   or
+    function Ret_By_Ref(...) return limited Lim;
+   or
+    function Ret_By_Ref(...) limited return Lim; -- probably my favorite
+   or use a non-reserved keyword:
+    function Ret_By_Ref(...) reference return Lim;
+
+or drop this capability in favor of:
+
+    function Ret_Acc(...) return access Lim;
+
+which has the very nice property of saying exactly
+what is happening, not having any funny restrictions
+on use, carrying the idea of accessibility quite naturally
+(currently the accessibility check on return by reference
+is a bit odd), etc.
+
+> Also there are some cases that either get permitted or ruled out by the
+> syntax.  These are:
+>
+> A) Should it be possible for a constructor function to be a child
+> program unit?
+> B) Should it be possible for a constructor function to be an operator?
+> (For example "+")
+> C) Should it be possible for a constructor to be declared abstract?
+> D) Is there a need to change the <subtype mark> to a <subtype indication>?
+> This would allow constraints in constructor declarations.
+
+I recommend that these look like regular functions at the
+declaration point, and in any case should
+be allowed to be abstract, operators, library level, generic, etc.
+
+> ...
+> E) In option 2, should an initial value be allowed after the subtype
+> mark in the object declaration?  (This would probably be instead of in
+> the return statement.)
+> F) Again in option 2, should aliased or constant be allowed before the
+> subtype delaration?
+> G) Also in option 2, what about allowing <array_type_definition> instead
+> of  <subtype indication>?
+
+I don't like option 2 much, and certainly not
+as the declaration.  I could see it as the body, perhaps,
+in which case it is essentially equivalent to the return ... do ...,
+where the expression, if given, is an initial value, which can
+then be modified further in the body of the function.
+
+****************************************************************
+
+From: Robert I. Eachus
+Sent: Wednesday, December 10, 2003, 12:01 PM
+
+Tucker Taft wrote:
+
+> As I suggested, I would argue for distinguishing the
+> existing return-by-reference functions.  These are the
+> ones that are going to be of limited use, and in particular,
+> a call on one of these will *not* be usable at the initialization
+> expression for a declared object or an aggregate component.
+
+
+I can't accept this.  To quote from Ada.Text_IO:
+
+   type File_Type is limited private;
+      ...
+   function Standard_Input  return File_Type;
+   function Standard_Output return File_Type;
+   function Standard_Error  return File_Type;
+
+   function Current_Input   return File_Type;
+   function Current_Output  return File_Type;
+   function Current_Error   return File_Type;
+
+Where the current return by reference functions are appropriate, they
+are currently used with no particular effort or thought by programmers.
+I find them very handy when building software where the objects have
+permanence because operations that change their value can also change
+the value in a database.
+
+The new initialization rules will make such types more useful, and more
+common than they currently are.  Right now the problem with them is that
+users must call an initialization procedure, so the designer of the ADT
+has to worry about what happens if the object is used before it is
+(non-default) initialized.  This tends to create additional run-time
+overhead.  I have several ADTs where there is an explicit initialization
+flag in the (limited) object  type.  This is the only field with a
+default initial value, and its only use is to ensure that other
+operations on the type can check the flag and raise an  exception.
+
+With the new proposal and types with unknown discriminants, that flag
+and all the associated code can go away.  A user of the ADT can't create
+an object without initializing it.  This means that there will be many
+more inquiry functions which return an existing value of the type, and
+can and should only be used as parameters in other calls.  Keeping this
+usage of the existing non-constructor limited return functions efficient
+is a necessary goal of the current effort.  As with File_Type in
+Ada.Text_IO, there will be several of these return by reference
+functions for every one of the new constructors, whatever they are called.
+
+And notice that the 'funky' return by reference functions are the
+exception to the rubric that every function returns a new object.  They
+are only useful where they do not do that, and they are useful and used
+for exactly that property.
+
+> I would suggest for the return-by-reference "functions":
+>
+>    limited function Ret_By_Ref(...) return Lim;
+>   or
+>    function Ret_By_Ref(...) return limited Lim;
+>   or
+>    function Ret_By_Ref(...) limited return Lim; -- probably my favorite
+>   or use a non-reserved keyword:
+>    function Ret_By_Ref(...) reference return Lim;
+>
+> or drop this capability in favor of:
+>
+>    function Ret_Acc(...) return access Lim;
+>
+> which has the very nice property of saying exactly
+> what is happening, not having any funny restrictions
+> on use, carrying the idea of accessibility quite naturally
+> (currently the accessibility check on return by reference
+> is a bit odd), etc.
+
+The later would work, and could be used in Ada.Text_IO.  I just don't
+like the non-upward compatible change, and the distributed cost of doing
+this.  Returning an access value is not that much less efficient than
+the current situation.  Sometimes there will be an extra level of
+indirection.  But I don't think that the methodological purity justifies
+the forced changes to existing code.  Worse, the error messages will be
+on the calls, not on the compiliation of the defining package.
+
+> I recommend that these look like regular functions at the
+> declaration point, and in any case should
+> be allowed to be abstract, operators, library level,
+> generic, etc.
+
+Noted.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Wednesday, December 10, 2003,  1:27 PM
+
+> Tucker Taft wrote:
+>
+> > As I suggested, I would argue for distinguishing the
+> > existing return-by-reference functions.  These are the
+> > ones that are going to be of limited use, and in particular,
+> > a call on one of these will *not* be usable at the initialization
+> > expression for a declared object or an aggregate component.
+>
+>
+> I can't accept this.  To quote from Ada.Text_IO:
+>
+>    type File_Type is limited private;
+>       ...
+>    function Standard_Input  return File_Type;
+>    function Standard_Output return File_Type;
+>    function Standard_Error  return File_Type;
+>
+>    function Current_Input   return File_Type;
+>    function Current_Output  return File_Type;
+>    function Current_Error   return File_Type;
+
+These are not return-by-reference in most (all?) implementations.
+The full type for File_Type is almost always an access value.
+
+Return-by-reference only happens if the full type is "very"
+limited (e.g. contains a task, a protected object, or an
+explicitly limited record).
+
+> Where the current return by reference functions are appropriate, they
+> are currently used with no particular effort or thought by programmers.
+
+I don't think they are used very much at all.  They weren't generally
+allowed in Ada 83 (returning a task outside of its scope was an error;
+protected objects and limited records didn't exist).  To use them
+now, you have to worry about the accessibility check.
+
+> I find them very handy when building software where the objects have
+> permanence because operations that change their value can also change
+> the value in a database.
+
+I don't really follow.  In any case, you would still be able
+to either use return-by-reference, or return-by-access, but
+you might have to add a reserved word to make it clear to
+the caller that they cannot call this function as an initializer
+or component of an aggregate.  Note that for limited types
+with non-limited full types, there would be no such limitation --
+functions returning such types *could* be used as initializers, etc.
+In my mind, this argues further for saying that the default
+should be that the function can be called in such contexts,
+and you should have to say more if you are creating a function
+which will *not* be usable as an initializer.
+
+> The new initialization rules will make such types more useful, and more
+> common than they currently are.  ...
+
+Are you talking about "inherently" limited types, or a type
+whose full type is non-limited, and copying is permitted inside
+the defining package?
+
+The new initialization rules will make it clearer that return-by-reference
+functions are second class citizens.
+
+> And notice that the 'funky' return by reference functions are the
+> exception to the rubric that every function returns a new object.  They
+> are only useful where they do not do that, and they are useful and used
+> for exactly that property.
+
+And it is important to highlight that property in my mind,
+since it is so weird.  Because if a type is visibly limited,
+but internally non-limited, then you can't even write
+a return-by-reference function.
+
+> > I would suggest for the return-by-reference "functions":
+> >
+> >    limited function Ret_By_Ref(...) return Lim;
+> >   or
+> >    function Ret_By_Ref(...) return limited Lim;
+> >   or
+> >    function Ret_By_Ref(...) limited return Lim; -- probably my favorite
+> >   or use a non-reserved keyword:
+> >    function Ret_By_Ref(...) reference return Lim;
+> >
+> > or drop this capability in favor of:
+> >
+> >    function Ret_Acc(...) return access Lim;
+> >
+> > which has the very nice property of saying exactly
+> > what is happening, not having any funny restrictions
+> > on use, carrying the idea of accessibility quite naturally
+> > (currently the accessibility check on return by reference
+> > is a bit odd), etc.
+>
+> The later would work, and could be used in Ada.Text_IO.
+
+As indicated above, this is probably irrelevant to Ada.Text_IO,
+since File_Type, though limited, is almost certainly *not*
+a return-by-reference type.
+
+****************************************************************
+
+From: Robert I. Eachus
+Sent: Wednesday, December 10, 2003,  2:14 PM
+
+Tucker Taft wrote:
+
+>These are not return-by-reference in most (all?) implementations.
+>The full type for File_Type is almost always an access value.
+>
+>Return-by-reference only happens if the full type is "very"
+>limited (e.g. contains a task, a protected object, or an
+>explicitly limited record).
+
+I understand what you are saying, and realized after I posted that the
+message may have seemed a bit too shrill.  My point really was that only
+the implementation can know in some cases whether a function that
+appears to be "return by reference" actuallly is, and in other cases the
+programmer may know his intent but he has to communcite it to the compiler.
+
+A better example is a tagged type (call it Foo) declared as limited
+private.  Whether or not a function that returns Foo'Class needs to be
+return by reference can depend on derived types not created yet.  So you
+must treat current primitive functions that return Foo as return by
+reference  The issue is that even though for the derived type, call it
+Foobar, the function becomes abstract, that function can be defined, and
+will be return by reference for Foobar.  Then if there is a dynamic
+dispatching case the compiler will have to be able to either select the
+function for the parent type Foo, or the fully limited child type Foobar
+at compile time.
+
+But having said that, I think that it is an unwarranted assumption that
+no current implementation of Ada.Text_IO has an inherently limited
+File_Type.
+
+>Are you talking about "inherently" limited types, or a type
+>whose full type is non-limited, and copying is permitted inside
+>the defining package?
+
+Yes, I gather that that is what you (Tucker) are just not seeing.  Once
+I have a limited type, since copying will break things, I have no reason
+not to put a protected type component in the type to insure that updates
+are sequential. (Or just make the whole thing protected.)  If the type
+was declared non-limited, I would have to resort to an access component
+and do the storage management explicitly.  However, once I make the
+visible type limited to prevent copying, why add the unnecessary code
+and overhead of an explicit indirection?
+
+>And it is important to highlight that property in my mind,
+>since it is so weird.  Because if a type is visibly limited,
+>but internally non-limited, then you can't even write
+>a return-by-reference function.
+
+But what if the programmer doesn't know whether the type is inherently
+limited?  File_Type is a perfect example.  Right now all a user needs to
+know is that he can't assign them or test for equality.  The compiler
+takes care of the rest.
+
+****************************************************************
+
+From: Jean-Pierre Rosen
+Sent: Thursday, December 11, 2003,  1:37 AM
+
+> I don't think they are used very much at all.  They weren't generally
+> allowed in Ada 83 (returning a task outside of its scope was an error;
+No. It was a pathology (Rosen's pathology :-), but not an error...
+
+****************************************************************
+
+From: Robert Dewar
+Sent: Thursday, December 11, 2003,  8:08 AM
+
+Note that the designation pathology (was it ever used for anything
+else ever?) means that implementations can ignore the situation and
+treat it as erroneous.
+
+Of course the damage to implementations had already been done by then
+and I don't think many bothered to change.
+
+****************************************************************
+
+From: Robert A. Duff
+Sent: Thursday, December 11, 2003,  1:57 PM
+
+Tuck said:
+
+> >>   13) Should allow us to still have function-like things
+> >>       that return by reference
+
+I replied:
+
+> >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.
+
+Robert Eachus replied:
+
+> 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.
+
+I don't get it.
+
+I *do* use limited tagged types.  I also use tagged types that I wish
+were limited, but I made them nonlimited so I could use aggregates and
+the like.
+
+These return-by-reference things seem pointless to me.  What they're
+"really" doing is returning a pointer to a preexisting limited object.
+If I want to do that, I tend to use an explicit access type.
+
+Can you (or somebody) show me an example where a return-by-reference
+function is better than a function returning an access value?
+
+Note that return-by-reference always returns a constant object,
+so you can't do much with it.
+
+I think I've used this feature exactly once in the last few years,
+and I can't remember why.  I do remember that I thought it necessary
+to put a comment in, explaining that this depends on the weird
+return-by-reference nature of that thing.
+
+> One last suggested inclusion:
+>
+> 19) If we adopt a partial solution, that partial solution shouldn't
+> limit a future extention to cover everything.
+
+That seems like a worthy goal.  We might say "the result type shall be
+definite".  It would be good if removing that rule didn't require any
+other language changes -- just implementation changes.
+
+Tuck said:
+
+> > > Other possible desirables:
+> > >    12) Should not require alteration in the way limited types are laid out
+
+I replied:
+
+> > I think I agree, but I'm not really sure what you're getting at.  Which
+> > proposal(s) violate this?
+
+Tuck replied:
+
+> 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 don't understand this.  I presume you are talking about
+implementations that allocate-the-max for mutable records
+(i.e., records with defaulted discrims).  Record components
+must have definite subtypes, so their size is known before the
+call -- it cannot be calculated by the constructor function.
+So the caller can always add up the component sizes and determine how
+much to allocate for the outer record.
+
+If the result subtype of the constructor is indefinite, it needs to be
+passed a thunk that takes a size, and returns an address.  Robert Eachus
+outlined this idea.  We also talked about the same idea earlier, saying
+the constructor is passed a Storage_Pool.  In the case where the
+constructor is initializing a record component, as in:
+
+    X: T := (Discrim => 123, That => Construct(456));
+
+the caller would allocate, and the thunk/pool would return the address
+of X.That.  It would raise Constraint_Error if the size is wrong.
+
+In the case of:
+
+    new T'(Construct(456))
+
+the thunk/pool actually does the allocation -- it's the storage pool
+defined by the user for the access type.
+
+I see why in the component case the size is known before the call, and
+the memory is allocated before the call.  But I don't see why that needs
+to be true in other cases, if we're willing to pass in a thunk, which
+might do some allocation, or might return the address of some
+preallocated memory.
+
+The thunk is needed whenever the result subtype is indefinite.
+Do you plan to disallow that case?
+
+If the compiler is willing to generate multiple copies of the code for
+constructor functions, it could optimize away the thunks.
+
+Likewise, if the constructor is inlined (which I suspect will be
+common), the thunk can be inlined, too.
+
+----
+
+Randy said:
+
+> Trying to lay out all possible record types contiguously is a fool's game.
+
+I believe that's a common implementation.  I think AdaMagic and GNAT
+both do that, for example.  I agree with Tuck: we don't want to change
+record layouts; the always-contiguous assumption is fundamental
+(in the compilers that use it).
+
+Tuck said:
+
+> 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.
+
+On the call side, it looks like a function call.
+It can be used anywhere a function call is allowed,
+except that in the limited case, not in an assignment_statement.
+(I think every other "assignment operation" is an initialization.)
+Or did you mean the run-time model at the call site?
+
+****************************************************************
+
+From: Dan Eilers
+Sent: Thursday, December 11, 2003,  2:24 PM
+
+I'm probably missing something obvious, but if we are going
+to provide "in-place" functions, why can't they be used in
+assignment statements?
+
+The purpose of limited types is presumably to avoid _copying_
+an object, which in-place functions seem designed to avoid,
+regardless of where they are called.
+
+****************************************************************
+
+From: Robert I. Eachus
+Sent: Friday, December 12, 2003, 12:10 AM
+
+You could allow it, but we definitely shouldn't allow it.  The effect
+would be to create a new object with the same name as the old one, and
+you can do that now, for example by having a limited object (Bar)
+declared inside a procedure (Foo).  Then which Foo.Bar you are referring
+to depends on which call of Foo is active.
+
+But now think about a limited object with a task component.  To avoid
+having ten tasks floating around with the same name, you have to
+finalize the old task before allowing the assignment.  I could go on,
+but I think you get the idea.  We could allow for example overwriting
+the value of an Ada.Text_IO.File_Type, but what happens to the file in
+the old object?   All the current Ada rules involving limited types
+depend on the object created surviving at least as long as the
+containing scope.
+
+****************************************************************
+
+From: Robert A. Duff
+Sent: Friday, December 12, 2003,  8:24 AM
+
+I think limited types need to avoid copying out of objects (the fetch,
+or Bliss dot), and also copying *into* objects (overwriting existing
+data).  Maybe you don't call the latter "copying".  But I think it's
+necessary to avoid this overwriting because otherwise, the previously
+existing value gets lost.  If it contains tasks, it raises the issue
+of when we await termination of those tasks.  If it contains finalizable
+stuff, it raises the issue of when to finalize.  I suppose you could
+finalize just before overwriting, but still, it seems like a violation
+of the identity of limited types.  Initialization seems like something
+that should only be done once.
+
+****************************************************************
+
+From: Dan Eilers
+Sent: Friday, December 12, 2003, 11:21 AM
+
+I wrote:
+> I'm probably missing something obvious, but if we are going
+> to provide "in-place" functions, why can't they be used in
+> assignment statements?
+
+Robert Eachus and Bob Duff both pointed out that the target
+of the assignment statement would need to be finalized.  But
+this is normal when assigning to objects that need finalization.
+7.6.1(12) says "The target of an assignment statement is finalized
+before copying in the new value".
+
+Maybe we would want to wordsmith this a little to avoid the term
+"copying" in the case of the proposed return-in-place functions.
+
+Bob Duff wrote:
+>                            If it contains tasks, it raises the issue
+> of when we await termination of those tasks.
+
+Is this really a serious problem?  It seems minor compared to the
+benefit of making programming with limited types as similar as possible
+to programming with non-limited types, which is important given
+that a program written using non-limited types can flip over when
+a low-level component of some record type is changed to be limited.
+
+****************************************************************
+
+From: Robert A. Duff
+Sent: Friday, December 12, 2003,  3:15 PM
+
+Dan Eilers said:
+
+> Robert Eachus and Bob Duff both pointed out that the target
+> of the assignment statement would need to be finalized.  But
+> this is normal when assigning to objects that need finalization.
+
+It's not normal when assigning to *limited* objects!  ;-)
+
+I can't get my head around the idea that an assignment_statement could
+wipe out a preexisting (already initialized) limited object.  It seems
+to defeat the purpose of limitedness.  I admit that "Bob Duff doesn't
+like it" is a fairly weak argument.  ;-)
+
+> 7.6.1(12) says "The target of an assignment statement is finalized
+> before copying in the new value".
+> Maybe we would want to wordsmith this a little to avoid the term
+> "copying" in the case of the proposed return-in-place functions.
+>
+> Bob Duff wrote:
+> >                            If it contains tasks, it raises the issue
+> > of when we await termination of those tasks.
+>
+> Is this really a serious problem?
+
+I think so.  I mean, these objects already exist, so if we're going to
+allow assignment statements, we have to say what it means.  And I can't
+think of anything good to say about that.
+
+In Ada 83, task objects contained pointers to tasks.  In Ada 95, task
+objects contain tasks; there is no longer a semantic need for the extra
+level of indirection (although some implementations choose to introduce
+the extra indirection for various reasons).  I don't know if any
+implementations actually do this, but it is certainly allowed for the
+task object to contain all the various queue links and whatnot
+-- the task object *is* the Task Control Block.
+Overwriting that data would cause chaos.
+
+(I think this change is an improvement in Ada 95, and I think avoiding
+the level of indirection is the best implementation, unless you're
+trying to interface to an existing threads package (which is common).)
+
+Another point is that a running task can refer to its own
+discriminants.
+
+The above two points seem to imply that we can't overwrite running
+tasks.  That leaves two alternatives: (1) abort the task, then overwrite
+it.  Sounds rather harsh.  Also, aborting doesn't kill the task -- it
+just gets the task *started* on the long process of going away.
+(2) Have the assignment hang, waiting until the overwritten task
+terminates.  Doesn't sound very useful.
+
+We can't allow assignment statements on limited types, but disallow them
+on types containing tasks, because generic contract problems would rear
+their ugly heads.
+
+We could raise an exception on assignment statements if the object
+contains tasks.  Yuck.
+
+I don't like any of the above possible rules, and I can't think of any
+others.
+
+>...It seems minor compared to the
+> benefit of making programming with limited types as similar as possible
+> to programming with non-limited types, which is important given
+> that a program written using non-limited types can flip over when
+> a low-level component of some record type is changed to be limited.
+
+It seems to me that allowing initialization of limited objects is
+sufficient to make the transition feasible (in cases where it makes any
+sense at all).  I'm not sure about that, though, and I'm waiting to hear
+evidence to the contrary.
+
+----
+
+I just thought of another point:
+
+For nonlimited types, giving a default for a discriminant means, oddly,
+"unconstrained objects of this type can exist".  I.e., it is possible
+to declare objects that can change size.  Some compilers choose to
+allocate the max size for these; others use a heap-based
+implementation.  (Compiler writers who choose the latter sneer at the
+former, because it means certain records will always raise
+Storage_Error.  Compiler writers who choose the former decry implicit
+heap usage.  Too bad -- it causes real portability problems.)
+
+But for *limited* types, giving a default for a discriminant means
+something totally different -- it means you want a default value
+(surprise, surprise).  And in the limited case, there is no excuse for a
+compiler to allocate the max size, because the size cannot change.
+One of the suggested implementations of Exception_Occurrence in
+AARM-11.4.1(19.a...) depends on this fact:
+
+    type Exception_Occurrence(Message_Length: Natural := 200) is
+        limited record
+            Id: Exception_Id;
+            Message: String(1..Message_Length);
+        end record;
+
+The type is private.  The client who says:
+
+    X: Exception_Occurrence;
+
+does not see the discriminant.  The implementation should allocate 200
+bytes for the characters of X.Message.  An implementation that allocates
+2**31 bytes is broken.  And there is no need for extra indirections.
+
+My point is: if we allow assignment_statements on limited types,
+the size of X could change, thus breaking various compilers.
+And if the compiler fix is to allocate the max, it would break
+various programs (and break the implementation's support for
+Exception_Occurrences).
+
+****************************************************************
+
+From: Dan Eilers
+Sent: Friday, December 12, 2003,  6:27 PM
+
+Bob Duff wrote:
+> I can't get my head around the idea that an assignment_statement could
+> wipe out a preexisting (already initialized) limited object.  It seems
+> to defeat the purpose of limitedness.  I admit that "Bob Duff doesn't
+> like it" is a fairly weak argument.  ;-)
+
+Well, I don't think the purpose of limitedness is to prevent objects
+from being "wiped out" before their scope ends.  Rather, it's to prevent
+a single object from being cloned into two objects.
+
+>...
+>The above two points seem to imply that we can't overwrite running
+>tasks.  That leaves two alternatives: (1) abort the task, then overwrite
+>it.  Sounds rather harsh.  Also, aborting doesn't kill the task -- it
+>just gets the task *started* on the long process of going away.
+>(2) Have the assignment hang, waiting until the overwritten task
+>terminates.  Doesn't sound very useful.
+
+We definitely shouldn't overwrite running tasks!
+It seems perfectly fine to me to do what happens at the end of
+a declare block that declares a task object, which I believe
+is your option (2).
+
+The usefulness doesn't so much come from the nifty new things
+you can do with tasks.  It comes from eliminating arbitrary
+restrictions on what you can do with limited objects that may or
+may not contain tasks, such as limited generic formal parameters.
+
+> My point is: if we allow assignment_statements on limited types,
+> the size of X could change, thus breaking various compilers.
+
+How about if we say that a constraint error is raised at runtime
+if assignment of limited types changes a discriminant, analogous
+to the way indefinite objects currently behave:
+
+    declare
+       x: string := "abc";
+    begin
+      x := "def";   -- wipes out previous value of x
+      x := "defg";  -- raises constraint_error at runtime
+    end;
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Tuesday, December 16, 2003,  3:25 PM
+
+Trying to define the semantics for assignment statements
+for limited types seems doomed.  Fundamentally assignments
+involve creating a copy of the right hand side, after first
+destroying the left hand side.  This really can't be done,
+since it is not possible to copy a task or a protected object,
+and for limited private types, who knows what sort of thing
+the type represents -- it might represent a physical device of
+some sort, a window on a screen, etc.
+
+Even destroying the left hand side is not easy, if there are
+tasks or protected objects.  Even unchecked deallocation
+doesn't stop a task from running, though it renders certain
+future internal references to discriminants of the task
+into exception-generating events.
+
+Other problems include dealing properly with access discriminants.
+For limited types, they are allowed to point to local objects,
+if the limited object is local.  If you were to assign the
+local limited object to a global limited object, you could
+be creating a dangling reference.
+
+The whole point of limited is to disallow copying, so it
+really makes no sense to try to then define what copying
+means.  The user can of course write an Assign procedure,
+and in some conceivable future revision we could allow you
+to call such a procedure using the ":=" syntax, but I'm
+not holding my breath.  We've been down this path, and
+the composability issues are thorny.
+
+****************************************************************
+
+From: Robert I. Eachus
+Sent: Friday, December 12, 2003,  9:48 AM
+
+Robert A Duff wrote:
+> Robert Eachus replied:
+>> 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.
+>
+> I don't get it.
+>
+> I *do* use limited tagged types.  I also use tagged types that I wish
+> were limited, but I made them nonlimited so I could use aggregates and
+> the like.
+>
+> These return-by-reference things seem pointless to me.  What they're
+> "really" doing is returning a pointer to a preexisting limited object.
+> If I want to do that, I tend to use an explicit access type.
+>
+> Can you (or somebody) show me an example where a return-by-reference
+> function is better than a function returning an access value?
+
+If you take that attitude I can't.   Seriously, the advantage is that
+there doesn't need to be a user visible access type.
+
+The area where I find them quite handy is in dealing with databases.
+You can put the database "behind" limited objects, and have lookup
+functions that are return by reference, and inquiry functions or
+procedures that take the by reference parameter and produce a report or
+whatever:  Print_Report(Lookup_Drivers(State => "MA"; Sex => Male));
+
+The advantage is that not having to have access types cuts the number of
+types floating around in half.  Yes, you know that the inquiry is
+returning an array of limited records, and there really is a pointer
+involved.  But it is not explicit, so you both don't have to worry about
+the type, and don't have to worry about about deallocation issues.
+
+> Note that return-by-reference always returns a constant object,
+> so you can't do much with it.
+>
+> I think I've used this feature exactly once in the last few years,
+> and I can't remember why.  I do remember that I thought it necessary
+> to put a comment in, explaining that this depends on the weird
+> return-by-reference nature of that thing.
+
+As I said, it is the problems with initializing limited objects that
+makes them harder to use than they need to be.  But between constructor
+functions that can be called where the object is declared, and unknown
+discriminants that insures that a constructor must be called, they
+become much more convenient.  The fact that the actual value returned is
+a constant is no problem, in fact if you are using limited types, you
+want the return values to be constants.
+
+> I see why in the component case the size is known before the call, and
+> the memory is allocated before the call.  But I don't see why that needs
+> to be true in other cases, if we're willing to pass in a thunk, which
+> might do some allocation, or might return the address of some
+> preallocated memory.
+>
+> The thunk is needed whenever the result subtype is indefinite.
+> Do you plan to disallow that case?
+>
+> If the compiler is willing to generate multiple copies of the code for
+> constructor functions, it could optimize away the thunks.
+>
+> Likewise, if the constructor is inlined (which I suspect will be
+> common), the thunk can be inlined, too.
+
+Don't declare success and go home too soon.  But I have probably been
+guilty of not trying to explain what ends up going on.  In the normal
+case, a record component can't be indefinite.  If it depends on a
+discriminant, the discriminant is part of the object as a whole.  But
+there is a special case where a component depends on a discriminant
+which is not a discriminant of the containing object.  The simple
+example is a record with a default discriminant, and a record with
+several components of this type.  To give the gory example:
+
+type Varying_String (Length: Integer := 0) is
+record
+   Contents: String(1..Length);
+end record;
+
+type Big_Object is record
+ A, B, C: Varying_String;
+end record;
+
+Some compilers support such types only by "allocating the maximum."
+These compilers generate Storage_Error if you declare an object of type
+Big_Object.  These compilers don't have to change their implementation
+for this proposal to work.  They will lay out such records as they
+currently do, and some will raise Storage_Error.  But....
+
+> Randy said:
+>
+>> Trying to lay out all possible record types contiguously is a fool's
+>> game.
+>>
+>
+> I believe that's a common implementation.  I think AdaMagic and GNAT
+> both do that, for example.  I agree with Tuck: we don't want to change
+> record layouts; the always-contiguous assumption is fundamental
+> (in the compilers that use it).
+
+Some compilers recognize such types as "special" and go the extra mile
+in laying them out non-contiguously.  If you do that, as Randy says you
+have to deal with the consequences.  So compilers that currently allow
+such types can continue to do so.  The implementation of the new
+proposal will be slightly more complex than for the "allocate the max"
+type, but only becase they have both contiguous records, and objects
+which are allocated in pieces.
+
+That's why we have been discussing those cases as well.  But unless Ada
+0Y requires compilers not to use the allocate the max strategy, nothing
+will need to change in the way compilers currently layout records.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, January 22, 2004,  7:32 PM
+
+Bob Duff said (eons ago): [Actually, December 12th]
+> Can you (or somebody) show me an example where a return-by-reference
+> function is better than a function returning an access value?
+>
+> Note that return-by-reference always returns a constant object,
+> so you can't do much with it.
+
+We had to use these guys in Claw. We needed constants of a limited
+controlled type, and the only way to do it in Ada 95 is to declare variable
+objects in the body, initialize them in the initialization part, and have
+functions return them. All we really wanted was deferred constants of a
+limited type. (The details were discussed in the appendix to AI-287.)
+
+Of course, AI-287 gives us what we really wanted in the first place, so
+there is no longer any need for the return-by-reference functions in Claw.
+
+Bob's comment makes me wonder if *all* uses of such functions are
+essentially work-arounds to get constants of limited types. In that case,
+perhaps we should be so bold is to simply drop the capability completely if
+we allow real constructor functions. After all, the solution we're currently
+discussing is incompatible with Ada 95 -- it requires the user to modify
+their source code anyway. If they simply modified it to an appropriate
+constant declaration (possibility initialized by a function, or by an
+aggregate), or to return an access to the object, they'd get what they need.
+And we wouldn't have to add a useless new feature to the language solely for
+compatibility with what looks like (in 20-20 hindsight) a useless feature.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Tuesday, December 16, 2003,  3:09 PM
+
+For those who didn't make it to the ARG meeting,
+the proposal that was finally discussed relating to returning
+limited types was as follows (a real AI will be forthcoming):
+
+  1) Get the current capability of return-by-reference "out of the way"
+     by giving it a special syntax:
+
+     function Ret_By_Ref(X : Whatever) aliased return Lim_Type;
+
+     Such an "aliased return" function can be used with any type, limited
+     or non-limited, and it means that the function is returning
+     a reference to an object whose accessibility level is no deeper
+     than that of the function itself.
+
+     An accessibility check is performed on the object associated with
+     the expression of the return statement.
+
+     A call on such a function provides a constant view of this object.
+
+  2) Allow limited types to be returned by "normal" functions so long as
+     the return expression is an aggregate, or a call on a (normal) function.
+     If the type is "deep down" limited, then such a function must build
+     the result in its final resting place.  If the underlying type is actually
+     nonlimited, the implementation could use copying as part of returning, though of course
+     minimizing copies is generally a good thing.
+
+  3) Define a new construct called an "extended" return statement which can be used
+     in "normal" functions, whether the result type is limited or non-limited.
+     This construct allows the programmer to give a name to the object being
+     returned, and includes a "do ... end" part where the object being returned
+     can be further updated prior to return.  The syntax for an extended return is:
+
+         RETURN identifier : [ALIASED] subtype_mark [:= expression] [DO
+             handled_sequence_of_statements
+         END RETURN];
+
+     As mentioned in (2) above, this construct doesn't guarantee that no
+     additional copies will be made unless the underlying result type
+     is "really" limited.  But again, extra copies would be discouraged,
+     and this construct is meant to aid in the goal of minimizing copies
+     while still providing a chance to adjust the returned value using a sequence
+     of statements.
+
+
+The implementation burden of supporting returning limited types which must
+be built "in place" was a concern.  It was concluded that imposing a restriction
+that if the full type was "really" limited, then the result subtype must be
+constrained, would help significantly.  Although this restriction is a bit
+annoying, it is something which could be lifted in a future revision, or
+a later stage of this revision process, if the benefit was felt to outweigh
+the implementation cost.  The AI will be written up in a way that will
+outline the wording both with and without this restriction, and hopefully
+vendors will do a bit more analysis on the implementation burden associated
+with build-in-place for unconstrained result subtypes, while potential
+users will assess the relative value of the full versus restricted capability.
+
+Note that the major advantage of constrained subtypes is that the caller
+can always take care of allocation, and the caller can also do task
+initialization, which includes presumably adding the task to an activation
+list.  Another advantage is that it eliminates accessibility checks associated
+with creating an object with an access discriminant, since any access discriminant
+must be constrained ahead of time.  Of course the down side is also that
+the discriminant values, if any, must be constrained ahead of time. ;-)
+
+It turns out that the proposal of allowing anonymous access result types,
+in its most general form (where the caller provides a storage pool if
+the function allocates a new object), has essentially the same problem
+as supporting unconstrained result subtypes for limited function returns,
+in that it requires the caller to provide a storage pool, activation list, etc.
+There is a subset capability for anonymous access result types as well,
+where the storage pool is not provided by the caller, but instead
+the function must qualify the return expresssion with a named access type
+if it is going to return an allocator.
+
+Probably it would make sense to support the full capability of both,
+or the subset capability of both (or no capability at all), given
+the similarity in implementation burden.  Note that it is not just
+the storage pool, but also the activation list (and perhaps master)
+for any tasks, and accessibility level checks for access discriminants,
+that come into play with the fully general capability.  The AI will
+lay out these implementation issues in so far as possible.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Tuesday, December 16, 2003,  7:09 PM
+
+Tucker Taft wrote:
+
+>For those who didn't make it to the ARG meeting,
+>the proposal that was finally discussed relating to returning
+>limited types was as follows (a real AI will be forthcoming)...
+
+Sounds like a lot of progress, and I first want to say that from a
+functionality viewpoint it seems fine.  However, I think that it is
+going to turn out to be more difficult (impossible is more difficult,
+right?) to write a legality rule that implements the decision, than to
+support all unconstrained cases.  And the discussions so far should have
+made it clear that doing that has a potential distributed overhead.
+The proposal can certainly be writen up as allowing the implementation
+to decide whether or not to allow unconstrained return values for types
+that may be "deep down" limited.
+
+The first painful case of course is a function that returns a class wide
+value of a limited tagged type.  It should be okay to allow the compiler
+to look at the specific  types that can be returned when compiling  the
+body and  reject non-conforming return statements:
+
+type Foo (<>) is tagged  limited private;
+...
+
+type My_Foo is new Foo with....
+...
+function Create(Some_Param: Integer) return Foo'Class is
+...
+   if Some_Param = 7
+   then return My_Foo(7); -- Ok.
+   elsif Some_Param = 8
+   then return Aliased_Return_Function(8); -- Oops!
+   end if;
+   ...
+
+I think I can see how to word an Implementation Permission that covers this:
+
+"An implementation may reject a function return with a limited result
+type if  the view of the result value is limited and the result subtype
+is unconstrained or if the view is limited and the return value would
+need to be copied."
+
+Argh!  Tough, but at least we can give examples.  What if there are
+several return statements in the function?  I think this takes care of
+that.  If none of the values that could be returned are "really limited"
+you are fine,  I don't see how to have some return values that are
+"really limited" and others that are not, if the return subtype is
+constrained.
+
+The problem is that this doesn't cover what I see as the most painful
+case.  If you have a component of a record which has a default
+discriminant, and the component does not depend on a discriminant of the
+record type, what then?  We are back to allocating the max before the
+call, or Alsys style mutant records.  This is okay, as long as the
+component itself is not inherently limited:
+
+task type Bar is.... end task;
+
+type Bar_Array is array(Natural range <>) of Bar;
+
+type Bar_List (D: Natural := 3) is record
+      Contents: Bar_Array(1..D);
+end Bar_List;
+
+type Problem_Record (X: Integer) is record
+   ...
+   List: Bar_List;
+   ...
+end record;
+
+Now I am not suggesting that we require any compiler to provide a useful
+implementation of this type, and I am not really worried about a
+constructor for it.  But define "subtype Bounded is Integer range
+-10..10;" and make the subtype of X,  Bounded, and we have to decide if
+we want compilers to be forced to make this work.  Personally I wouldn't
+mind outlawing this case and having the useful unconstrained
+constructors allowed.  My point is that this example doesn't seem to be
+outlawed by the current proposed rule.
+
+Let's try again:  "An implementation may reject a function return
+statement with a limited result type if  the view of the result value is
+limited and the result subtype, or the subtype of any limited
+subcomponent, is unconstrained or if the view of the return subtype is
+limited and the return value would need to be copied."
+
+Enough to chew on for now...
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Tuesday, December 16, 2003,  8:09 PM
+
+I don't think we want to make this an implementation permission.
+Either we allow unconstrained result types or we don't.
+Of course compiler implementors can experiment with extensions,
+as they have already, but users should be protected from unintentionally
+using extensions that will render their code non-portable.
+
+****************************************************************
+
+From: Robert I. Eachus
+Sent: Tuesday, December 16, 2003,  9:03 PM
+
+ My point in writing it as an implementation permission was not to make
+it possible for different compilers to support different realistic
+cases.  My point was that judging the ragged edge really has to be done
+by the compiler, not by the user, and at the point where the body of the
+function is being compiled.  The idea was that this is an
+"Implementation Permission" for compilers not to implement some
+otherwise impossible to implement bodies.  Sure, if the compilers were
+required to support these cases, they could pass extra parameters on all
+function calls "just in case."  What we want, it seems to me, is to say
+that compilers must implement the cases that can be done without
+distributed overhead, and is allowed to reject bodies because that
+overhead is missing.
+
+Incidently, I didn't mention this in my previous post, which was complex
+enough.  But if we do go with this version of the proposal we need to
+decide for all language defined limited types whether or not they are
+"really" limited.   Not doing that would result in significant
+difference between implementations.  The two most obvious cases are
+File_Type in the various IO packages and Limited_Controlled.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Tuesday, December 16, 2003, 10:31 PM
+
+If we impose the restriction, it should be based
+on properties of the type known at the end of the package
+spec where the function is declared.  (The RM-ease would be
+"somewhere within the immediate scope of the function declaration.)
+It should not depend on the properties of components or ancestors
+which are not visible at that point.  Hence, it should not be based on
+some implementation-ish thing like return-by-reference.
+We are trying to get away from that privacy-breaking rule.
+
+Note that there is no need for it to be something
+visible at the point of the *spec* of the function.
+Any error can be deferred until the full type is completely
+defined, presuming it is defined in the same package
+as the function.
+
+****************************************************************
+
+From: Robert I. Eachus
+Sent: Wednesday, December 17, 2003,  2:09 AM
+
+No.  There will be legality rules, etc. for the function specification,
+but I thought the first example I gave was sufficient to show that there
+must be a rule on limited function return VALUES.  Go back and look at
+the first example again.  If you have a 'funky' return by reference
+function that is returning an existing 'really' limited object either as
+the return value or as part of an aggregate or subcomponent of a record
+type, you are stuck.
+
+The second example is a similar case.  If you have a 'really' limited
+subcomponent, and it is part of a record that depends on a discriminant
+other than a discriminant of the return type, the object size, or even
+the number of tasks it contains, cannot be determined by the caller.
+
+What if you say, well we just won't allow any return subtype that may
+have such a subcomponent?  You end up throwing most of the potential
+useful functionality away.  In particular, you could never define a
+constructor that returned a classwide type, because some unit not
+visible from the unit where the constructor is declared could create a
+"really limited" class member, even though the constructor as written
+not only will never return a value of that non-existant type.
+
+You (Tucker) are right that there are going to be return subtypes where
+the compiler can detect  that it is not possible to have a legal return
+statement according to this rule.  Fine, the compiler can print a
+warning message.  But in 99% or more of the potentially outlawed cases,
+you will have to look at the return statements to decide whether the
+function is legal.  If you are really having trouble getting this, I can
+probably gin up another example tomorrow where a function has two return
+statements one acceptable under this rule, and one that is not.
+
+I just don't want to lose all those cases due to some misguided
+"contract model" issues.   The contract with the user of the type and
+the constructor for the usual case where the type is (limited) private
+is that the constructor will return a valid value of the return
+subtype.  Period.  There are going to be legal values of that subtype
+that cannot be returned without the infrastructure you are trying to
+avoid.  We certainly don't want to require that overhead in all cases,
+just to allow for return values that may never exist.   The contract
+that the author of the constructor has is different.  He is the one that
+has to design the type so that the constructor can return a legal (and
+meaningful) value.  If this requires user written indirection which is
+hidden from the user of the package (and the ADT) that should be fine.
+In fact, that will be nice in many cases that now look pretty ugly.
+
+Right now, the contract with the user is the result subtype.  There is
+no requirement that all possible values of the result TYPE must be legal
+in the return statement.  In fact most of  the Dynamic Semantics of 6.5
+talks about the process and the checks made at run-time to determine if
+a return value of the return type  matches the return subtype.  As  I
+see it,  the proposal is to add an additional rule or rules that belong
+in the same place, but check whether the return statement will require
+copying of a "really limited" value.  A value of a type declared as
+limited, especially in the case of limited tagged types may or may not
+be one of these "really limited" values.  I just can't imagine how you
+can do that legality check in a package spec, instead of at run-time
+when the body is executed in some cases.
+
+****************************************************************
+
+From: Robert A. Duff
+Sent: Wednesday, December 17, 2003, 10:09 AM
+
+> type My_Foo is new Foo with....
+> ...
+> function Create(Some_Param: Integer) return Foo'Class is
+
+I wasn't at the meeting, but I just talked with Tuck about it, and
+I believe the intent was to make the above function illegal (in the
+more-restricted version of the proposal).  The goal of the restriction
+is that the call site knows the discriminants/bounds, and therefore the
+size of the result object, so it can allocate the object, fill in the
+discriminants, put the tasks on their various lists, and so forth.
+
+There is no need to break privateness or look at bodies to implement the
+restriction.  And there is certainly no need for
+implementation-definedness in this area.
+
+****************************************************************
+
+From: Robert I. Eachus
+Sent: Wednesday, December 17, 2003, 11:30 AM
+
+Let me pull out an earlier example to show why I see problems with this
+restriction.  Right now this code compiles:
+
+ ---------------------------------------------------------------------------------------------------------
+
+with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
+
+package Unbounded_String_Utilities is
+
+  type String_Array(<>) is limited private;
+
+  type String_List is limited private;
+
+  function Size (Arr: String_Array) return Natural;
+
+  function Size (List: String_List) return Natural;
+
+  function To_String_Array(List: in String_List) return String_Array;
+
+private
+
+  type List_Node;
+
+  type String_List is access List_Node;
+
+  type String_Array is array(Natural range <>) of Unbounded_String;
+
+  type List_Node is record
+
+    Value: Unbounded_String;
+
+    Next: String_List;
+
+  end record;
+
+end Unbounded_String_Utilities;
+
+package body Unbounded_String_Utilities is
+
+  function Size (Arr: String_Array) return Natural is
+
+  begin return Arr'Length; end Size;
+
+  function Size (List: String_List) return Natural is
+
+    Count: Natural := 0;
+
+    Temp: String_List := List;
+
+  begin
+
+    while Temp /= null loop
+
+      Temp := Temp.Next;
+
+      Count := Count + 1;
+
+    end loop;
+
+    return Count;
+
+  end Size;
+
+  function To_String_Array(List: in String_List) return String_Array is
+
+    Result: String_Array(1..10);
+
+    Temp: String_List := List;
+
+  begin
+
+    if Temp = null then return Result(1..0); end if;
+
+    for I in 1..10 loop
+
+      Result(I) := Temp.Value;
+
+      if Temp.Next = null then return Result(1..I); end if;
+
+    end loop;
+
+    return Result & To_String_Array(Temp);
+
+  end To_String_Array;
+
+end Unbounded_String_Utilities;
+
+------------------------------------------------------------------------------------------------------------
+
+
+Of course, I can't currently call To_String_Array in a scope where the
+return type is limited.  As I understand the new proposed rule, the
+intent is that I will be able to do so.  String_Array is a type that is
+not "really" private, so the compiler can generate code for an
+initialization expression which is a call to To_String_Array outside the
+scope where String_Array is not limited.
+
+If the new restriction makes it impossible to create limited objects of
+a type with unknown discriminants, then I oppose it.  But as I
+understand what Tucker is saying, the check in this case--and similar
+cases--should be made on the function declaration.  If this currently
+legal code becomes illegal that is a significant upward
+incompatibility.  (Right now, the function is legal, but there are
+limitations on where it can be used in initialization expressions.)
+
+The case being discussed above is slightly different than this
+example--the type with unknown discriminants would be a classwide type
+instead of an array type in this example.  But the problem remains the same.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Wednesday, December 17, 2003, 11:51 AM
+
+> Let me pull out an earlier example to show why I see problems with this
+> restriction.  Right now this code compiles:
+
+And it will continue to do so.  As I indicated, the check would *not*
+be made at the point of the function declaration, but rather at the
+end of the enclosing package spec, where the full type is completely defined
+(presuming the limited type is defined in the same package).
+
+Since the full type isn't limited, there is no restriction.
+
+...
+> If the new restriction makes it impossible to create limited objects of
+> a type with unknown discriminants, then I oppose it.
+
+It doesn't, presuming the full type is not limited.
+
+> ... But as I
+> understand what Tucker is saying, the check in this case--and similar
+> cases--should be made on the function declaration.
+
+I said it would *not* be made at the function declaration, but rather
+at the end of the enclosing package spec (or to be RM-ish,
+it would be illegal if the result subtype is unconstrained and the
+type is limited throughout the immediate scope of the function, or
+something like that).
+
+****************************************************************
+

Questions? Ask the ACAA Technical Agent