CVS difference for ai05s/ai05-0190-1.txt

Differences between 1.8 and version 1.9
Log of other versions for file ai05s/ai05-0190-1.txt

--- ai05s/ai05-0190-1.txt	2011/01/25 08:00:08	1.8
+++ ai05s/ai05-0190-1.txt	2011/01/27 06:06:16	1.9
@@ -1354,28 +1354,6 @@
 ****************************************************************
 
 From: Randy Brukardt
-Sent: Monday, January 24, 2011  9:58 PM
-
->                           Implementation Permissions
->
-> An object created by an anonymous allocator may be allocated on the
-> stack, and automatically reclaimed, regardless of the default pool.
-
-I find this wording misleading, as it seems to imply that it is OK to allow such
-allocators even when the default pool is null. That was not the intent; there is
-some support for that in that Storage_Size is zero for such a type. But since
-you can't name the type, how can you tell?
-
-Either we should have an AARM "To Be Honest" note ("This does not apply whrn the
-default pool is null; the allocator is statically illegal and where the object
-would have been created is irrelevant.") or we should add something to the
-wording:
-
-... regardless of the default pool (other than when the default pool is null).
-
-****************************************************************
-
-From: Randy Brukardt
 Sent: Thursday, January 20, 2011  1:08 AM
 
 I'm putting the rules for AI05-0051-1 into the standard, and in writing the
@@ -1619,6 +1597,1023 @@
 > hard to word properly for some reason?
 
 This seems preferable to me.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Monday, January 24, 2011  9:58 PM
+
+>                           Implementation Permissions
+>
+> An object created by an anonymous allocator may be allocated on the
+> stack, and automatically reclaimed, regardless of the default pool.
+
+I find this wording misleading, as it seems to imply that it is OK to allow such
+allocators even when the default pool is null. That was not the intent; there is
+some support for that in that Storage_Size is zero for such a type. But since
+you can't name the type, how can you tell?
+
+Either we should have an AARM "To Be Honest" note ("This does not apply whrn the
+default pool is null; the allocator is statically illegal and where the object
+would have been created is irrelevant.") or we should add something to the
+wording:
+
+... regardless of the default pool (other than when the default pool is null).
+
+****************************************************************
+
+From: Bob Duff
+Sent: Tuesday, January 25, 2011  9:13 AM
+
+> >> The pragma applies to all nonderived access types declared in the
+> >> places defined here, including within an instance of a generic unit.
+>
+> >As written, this breaks the contract model by requiring legality
+> >checks in generic bodies at the point of an instance. We *never* do
+> >that. Either this needs to be written as a post-compilation check, or
+> >there needs to be an assume-the-worst rule, or the check needs to be
+> >done on the body when it is compiled (and not at the point of the instance).
+>
+> This problem has not been addressed in this AI. (Nor have we discussed
+> it.)
+
+Which legality check are you talking about?  Do you mean the one that says "new
+T" is illegal if (roughly speaking) Storage_Size is statically zero?  If so, it
+seems like that should be a run-time check in instances -- raise Storage_Error
+if the size is zero. We normally let the implementation round up Storage_Size
+(e.g. to a page boundary), but we should probably explicitly say that zero stays
+zero, and "new" MUST raise Storage_Error (in cases where it's not illegal).
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, January 25, 2011  1:54 PM
+
+I thought that the quoted wording was from a Legality Rule, but I see it is not
+anymore. I also thought this controlled other legality rules, but I can't find
+any. So I was mistaken. But...
+
+The original Storage_Size = 0 wording worked for generic bodies; it is simply
+not checked there. See 4.8(5.3/2). However, we *deleted* that rule in
+AI05-0157-1 since it could not possibly ever happen (see AARM 4.8(5.e/3)), and
+it eliminated checks on cases where we statically know the right answer.
+
+That happened because of issues with the Unchecked_Deallocation rule that we
+were adding. So we will have to go back and redo that AI completely. That is not
+an AI that I want to have to reopen, but it looks like we have no choice.
+
+****************************************************************
+
+From: Bob Duff
+Sent: Tuesday, January 25, 2011  3:51 PM
+
+> The original Storage_Size = 0 wording worked for generic bodies; it is
+> simply not checked there. See 4.8(5.3/2). However, we *deleted* that
+> rule in
+> AI05-0157-1 since it could not possibly ever happen (see AARM
+> 4.8(5.e/3)), and it eliminated checks on cases where we statically know the right answer.
+>
+> That happened because of issues with the Unchecked_Deallocation rule
+> that we were adding. So we will have to go back and redo that AI
+> completely. That is not an AI that I want to have to reopen, but it
+> looks like we have no choice.
+
+I don't understand the problem.  The reasoning in 4.8(5.e/3) seems still valid
+in the presence of Default_Storage_Pool.  Perhaps you can illustrate the problem
+with example code?
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, January 25, 2011  4:04 PM
+
+The problem is that now we can set the storage size of an access type declared
+in a generic package "after the fact". For instance:
+
+generic
+package Foo is
+    type Acc is access Integer;
+    procedure Something (P : out Acc);
+end Foo;
+
+package body Foo is
+    procedure Something (P : out Acc) is
+    begin
+        P := new Integer'(10);
+    end Something;
+end Foo;
+
+with Foo;
+procedure Test is
+    pragma Default_Storage_Pool (null);
+    package Bar is new Foo; -- !!
+    B : Bar.Acc;
+begin
+    Bar.Something (B);
+end Test;
+
+The wording says that the pragma applies to the instance; that means that
+Bar.Acc has a Storage_Size defined to be zero. The legality rule says that the
+allocator is illegal if Storage_Size is zero (no exceptions), so we appear to
+have a contract problem.
+
+In this case, we could depend on the notion that legality rules aren't checked
+in instance bodies, but that seems to be weird at best. (And it's inconsistent
+with the "Redundant" text in the wording.) But even if we do that, it would seem
+that we would want to recheck in the private part (why would we want it to be
+unchecked there?), so we still need rewording.
+
+****************************************************************
+
+From: Bob Duff
+Sent: Tuesday, January 25, 2011  5:16 PM
+
+>...because explicit use of pools
+> does not necessarily mean heap allocation (it is quite sensible to
+>have  pools totally allocated on the stack -- I have such pools).
+
+Yeah, me too.  I'd call that a heap within a stack.
+
+> So I tend to either suggest (1) [which is the easiest] or dropping
+> Default_Storage_Pool(null) in favor of a restriction.
+
+I can live with a restriction.  But maybe you should clarify: I think
+"Default_Storage_Pool(null)" would mean exactly the same thing as "pragma
+Restrictions(No_Standard_Storage_Pool)".  Do you see some difference?
+
+****************************************************************
+
+From: Jean-Pierre Rosen
+Sent: Wednesday, January 26, 2011  3:10 AM
+
+> (3) Default_Storage_Pool never applies to instances.
+> No way to control the pool on a per-instance basis.
+> The "new" in your example uses whatever default pool applies to the
+> generic body.
+>
+I had two contradictory reactions to this one:
+
+1) the one who writes the software component is responsible for managing its
+   memory, and the user should not interfere with (or even know) what's in the
+   body => does not apply to instances
+
+2) The user may have a special purpose (certified) pool, or wants to make sure
+   that the generic has no hidden allocator (without having to look inside the
+   body) => does apply to instances
+
+A compromise might be that the pragma does not apply to instances (i.e.
+default storage pool determined at the place of the generic), but that an
+explicit default could be an aspect of the instantiation:
+   package Inst is new Gen with Default_Storage_Pool => ...;
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Wednesday, January 26, 2011  6:42 PM
+
+I've had this concern too, although it isn't specific to generics. It seems to
+apply to any package that you might right. I have to wonder what might happen if
+some user-defined pool got used for Claw, for one example. I can easily imagine
+it causing bogus errors that would appear to be problems in Claw -- that could
+be a real pain for support reasons.
+
+Similar concerns apply to the containers. If someone applied a pool that only
+supported certain sizes, the unbounded containers probably will fail. And
+probably not in a way that has been tested. More vendor support ends up being
+needed.
+
+This concern again makes me wonder about the wisdom of even having this pragma.
+
+(And if I sound confused WRT this pragma, it is because I am. That does not seem
+to be a good sign to me.)
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Wednesday, January 26, 2011  6:25 PM
+
+> I can live with a restriction.  But maybe you should clarify:
+> I think "Default_Storage_Pool(null)" would mean exactly the same thing
+> as "pragma
+> Restrictions(No_Standard_Storage_Pool)".  Do you see some difference?
+
+Well, there are two obvious differences. The enforcement of restrictions inside
+of generics is already defined, so we don't have to do anything new there. (That
+makes it a post-compilation check, as I recall.)
+
+The other was that I was thinking of it only applying to named access types. But
+the name I suggested is wrong for that; with that name, it should apply to all
+access types. Not sure about that.
+
+****************************************************************
+==== Different thread starts here ====
+
+From: Bob Duff
+Sent: Tuesday, January 25, 2011  9:10 AM
+
+> >                           Implementation Permissions
+> >
+> > An object created by an anonymous allocator may be allocated on the
+> > stack, and automatically reclaimed, regardless of the default pool.
+>
+> I find this wording misleading, as it seems to imply that it is OK to
+> allow such allocators even when the default pool is null.
+
+I don't think it's misleading.  It does indeed "imply ... null".
+
+> ...That was not the intent;
+
+I thought it WAS the intent.  The minutes say:
+
+    Tucker explains the latest compromise. The ?however? would be
+    deleted from the null case, and an Implementation Permission would
+    be added that the stack can be used rather than the specified pool
+    for anonymous allocators.
+
+    If you say no non-specified pool, that's really what you want. OTOH,
+    forcing the use of a pool that requires a storage leak makes no
+    sense, thus we make an exception when a pool is specified. If you
+    don't want to use the stack, you can use the No_Anonymous_Allocators
+    restriction.
+
+I took this to mean that stack allocation is always OK.
+And if you don't want that, you say No_Anonymous_Allocators.
+But I can't imagine WHY you wouldn't want stack allocation
+-- it's really HEAP allocation that causes trouble in some programs.
+
+Tucker?  Others?
+
+> there is some support for that in that Storage_Size is zero for such a type.
+> But since you can't name the type, how can you tell?
+>
+> Either we should have an AARM "To Be Honest" note ("This does not
+> apply whrn the default pool is null; the allocator is statically
+> illegal and where the object would have been created is irrelevant.")
+> or we should add something to the wording:
+>
+> ... regardless of the default pool (other than when the default pool
+> is null).
+
+Yes, if I misunderstood the intent, then that last "(other than..."
+should be added.
+
+P.S. I find this sub-issue to be of the utmost unimportance, compared to the
+general usefulness of the whole storage-pool-controls feature. I don't care too
+much how it's resolved, so long as it doesn't sink the whole feature.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, January 25, 2011  2:07 PM
+
+> I took this to mean that stack allocation is always OK.
+> And if you don't want that, you say No_Anonymous_Allocators.
+> But I can't imagine WHY you wouldn't want stack allocation
+> -- it's really HEAP allocation that causes trouble in some programs.
+
+Obviously my note taking was a bit vague here. The critical sentence is "If you
+say no non-specified pool, that's really what you want." That means you don't
+want any form of "new" from any pool other than the one you specify; presumably
+you are going to convert the types to some other access type and might call
+Unchecked_Deallocation on them; having the pools be different is a significant
+problem in that case.
+
+Indeed, I still don't buy this compromise. The above argument works just as well
+when the pool is specified to a particular value. In that case, stack allocation
+will cause either runtime errors or erroneous behavior. And
+No_Anonymous_Allocators is a nasty club to fix that; it eliminates the parameter
+cases that cause trouble but it also eliminates the component and object cases
+that cannot cause any problems (presuming the pool is as specified).
+
+In my view, the entire point of the pragma is to ensure that every "new" in your
+program comes from a single pool that you define. The fact that doesn't actually
+work is a significant detriment.
+
+An alternative would be to have restrictions that are fine-grained enough to
+block the bad stuff while not disallowing stuff that isn't a problem.
+Specifically:
+
+       pragma Restrictions (No_Coextensions);
+       pragma Restrictions (No_Access_Parameter_Allocators);
+
+I've never seen any sane reason for writing a parameter allocator; an aliased
+local object works just as well and isn't misleading to the reader. (And if this
+happens a lot, the use of an access parameter instead of "in out" in the first
+place is questionable.) These are already the default in Janus/Ada [although I
+admit part of the reason is that neither work correctly anyway; it's better to
+reject a construct than to implement it wrong -- but the reason that they don't
+work is that no one other than Tucker cares about them].
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Tuesday, January 25, 2011  2:47 PM
+
+...
+> Indeed, I still don't buy this compromise. The above argument works
+> just as well when the pool is specified to a particular value. In that
+> case, stack allocation will cause either runtime errors or erroneous
+> behavior. And No_Anonymous_Allocators is a nasty club to fix that; it
+> eliminates the parameter cases that cause trouble but it also
+> eliminates the component and object cases that cannot cause any
+> problems (presuming the pool is as specified).
+
+This is questionable in my view, because even if you specify that the anonymous
+allocator use a particular storage pool, the object created will still be
+finalized when the subprogram call is completed.
+
+...
+> I've never seen any sane reason for writing a parameter allocator; an
+> aliased local object works just as well and isn't misleading to the reader.
+
+I don't see this as a valid argument.  This has been in the language for 15
+years, and some people use it as it was described and intended to be used.  It
+works like a stack-based object, and is finalized upon return.
+
+****************************************************************
+
+From: Bob Duff
+Sent: Tuesday, January 25, 2011  3:22 PM
+
+> > I took this to mean that stack allocation is always OK.
+> > And if you don't want that, you say No_Anonymous_Allocators.
+> > But I can't imagine WHY you wouldn't want stack allocation
+> > -- it's really HEAP allocation that causes trouble in some programs.
+>
+> Obviously my note taking was a bit vague here. The critical sentence
+> is "If you say no non-specified pool, that's really what you want."
+
+I thought that was somebody (probably you) expressing that opinion, and then the
+"OTOH..." was somebody else (probably Tucker) expressing the opposite opinion,
+and the "thus we..." indicates that we're going with the second opinion.
+
+>... That means you
+> don't want any form of "new" from any pool other than the one you
+>specify;  presumably you are going to convert the types to some other
+>access type and  might call Unchecked_Deallocation on them; having the
+>pools be different is  a significant problem in that case.
+>
+> Indeed, I still don't buy this compromise. The above argument works
+> just as well when the pool is specified to a particular value. In that
+> case, stack allocation will cause either runtime errors or erroneous
+> behavior. And No_Anonymous_Allocators is a nasty club to fix that; it
+> eliminates the parameter cases that cause trouble but it also
+> eliminates the component and object cases that cannot cause any
+> problems (presuming the pool is as specified).
+>
+> In my view, the entire point of the pragma is to ensure that every
+> "new" in your program comes from a single pool that you define. The
+> fact that doesn't actually work is a significant detriment.
+
+Tucker's view is almost identical.  I think it's fair to characterize his view
+as "the point of the pragma is to ensure that every heap allocation in your
+program comes from a single pool that you define."
+
+You seem to believe that coextensions and access parameter allocators are evil
+and/or useless, so shouldn't be used.  If you believe that, then it makes no
+sense to care deeply about the way pragma Default_Storage_Pool interacts with
+these features.
+
+> An alternative would be to have restrictions that are fine-grained
+> enough to block the bad stuff while not disallowing stuff that isn't a problem.
+> Specifically:
+>
+>        pragma Restrictions (No_Coextensions);
+>        pragma Restrictions (No_Access_Parameter_Allocators);
+
+If that makes you happy, it's fine with me.  I have no problem adding all manner of restrictions, and letter each project choose what restrictions to impose on itself.
+
+Anyway, we've got to choose how to deal with this controversy, and it's really
+not all that important which way we choose. And concensus doesn't require
+unanimity.  It's perfectly acceptable for you (or Tuck) to the lone "No" vote.
+You win some, you lose some.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, January 25, 2011  3:30 PM
+
+...
+> > Indeed, I still don't buy this compromise. The above argument works
+> > just as well when the pool is specified to a particular value. In
+> > that case, stack allocation will cause either runtime errors or
+> > erroneous behavior. And No_Anonymous_Allocators is a nasty club to
+> > fix that; it eliminates the parameter cases that cause trouble but
+> > it also eliminates the component and object cases that cannot cause
+> > any problems (presuming the pool is as specified).
+>
+> This is questionable in my view, because even if you specify that the
+> anonymous allocator use a particular storage pool, the object created
+> will still be finalized when the subprogram call is completed.
+
+Right, but that's the crux of the problem: "new" for access parameters simply
+does work the way most people want and need it to work. It *appears* to do the
+heap-based allocation that you need, but actually it does something completely
+different -- and something that is completely redundant with things you can do
+in other ways.
+
+But I agree that it would be dangerously inconsistent to actually fix this to do
+what it needs to do. But new pragmas cannot compound the damage.
+
+That's why I suggested another solution. The problem with requiring
+"No_Anonymous_Allocators" is that it throws out the very thing that you cannot
+do any other way: giving a storage pool to anonymous allocators. And if you want
+to give a storage pool to anonymous allocators, you want to give it to all of
+them, not just the ones that are convenient for the implementer.
+
+...
+> > An alternative would be to have restrictions that are fine-grained
+> > enough to block the bad stuff while not disallowing stuff that isn't
+> > a problem.
+> > Specifically:
+> >
+> >         pragma Restrictions (No_Coextensions);
+> >         pragma Restrictions (No_Access_Parameter_Allocators);
+> >
+> > I've never seen any sane reason for writing a parameter allocator;
+> > an aliased local object works just as well and isn't misleading to
+> > the reader.
+>
+> I don't see this as a valid argument.  This has been in the language
+> for 15 years, and some people use it as it was described and intended
+> to be used.  It works like a stack-based object, and is finalized upon
+> return.
+
+So what? It's lying to the reader: "new" means heap-based allocation. We have
+lots of other ways to get stack-based allocation, but no other way to get
+heap-based allocation. So by stealing "new" this way, Ada 95 prevented anyone
+from getting the heap-based allocation in the unlikely event that they need it.
+And it prevents us from ever giving this better semantics.
+
+I realize all that we can do these days is make the problematic cases illegal.
+Thus I've suggested additional restrictions in order to limit the size of the
+club.
+
+The original reason for proposing pragma Default_Storage_Pool was to provide a
+way to specify storage pools for anonymous access types. Any other benefits are
+a happy accident. If it does not work to specify storage pools for anonymous
+access types, then it dubious that we need it at all. Given all of the problems
+that have entailed from that primary purpose (this argument, the AI-51
+conflicts, the AI-157 conflicts), perhaps we need to abandon that primary
+purpose.
+
+That means that either this pragma should only apply to *named* access types, or
+we should dump the pragma entirely and replace it by a Restriction -
+No_Standard_Storage_Pools. (No [named?] access types can be declared without a
+storage pool clause.)
+
+In any case, I would like explore alternatives that actually meet the intent of
+enhancing anonymous access allocators (if that is possible), or that simplify
+this proposal so it doesn't promise something it can't deliver.
+
+****************************************************************
+
+From: Bob Duff
+Sent: Tuesday, January 25, 2011  3:49 PM
+
+> The original reason for proposing pragma Default_Storage_Pool was to
+> provide a way to specify storage pools for anonymous access types.
+
+That's not what I remember, but anyway, I'm certain that's not the reason I want
+this feature.  My reasons are accurately described in the !problem section of
+the AI, and they have nothing to do with anon acc types.
+
+>...Any other
+> benefits are a happy accident. If it does not work to specify storage
+>pools  for anonymous access types, then it dubious that we need it at all.
+
+I strongly disagree with that assessment.
+
+****************************************************************
+
+From: Bob Duff
+Sent: Tuesday, January 25, 2011  4:12 PM
+
+> That's not what I remember, but anyway, I'm certain that's not the
+> reason I want this feature.  My reasons are accurately described in
+> the !problem section of the AI, and they have nothing to do with anon
+> acc types.
+
+Your memory is faulty. All of the access type changes that were proposed
+originated in the bunch of "how to make anonymous access types more useful"
+discussions. One of the "requirements" that came from that was a way to specify
+storage pools for anonymous access types.
+
+I understand your position, but it seems to me that a Restriction
+No_Standard_Storage_Pool would provide the benefit you are looking for in the
+!problem statement, and without any implication that it has any effect on
+anonymous access types.
+
+I find the third paragraph somewhat bogus: if you deallocate from a type with a
+different pool, you should expect it to fail. If you need to do this, you need
+to specify a pool on each of the access types involved, and because it is so
+critical to the algorithm, it ought to be done explicitly. It makes more sense
+if you include anonymous accesses, but essentially the proposal you give is to
+ignore them for this purpose (it's still implementation-defined if the pool is
+used, and in practice it never will be used). So how does that help??
+
+****************************************************************
+
+From: Bob Duff
+Sent: Tuesday, January 25, 2011  4:27 PM
+
+> The problem is that now we can set the storage size of an access type
+> declared in a generic package "after the fact". For instance:
+
+Thanks for the example.
+
+Before I concoct wording, let's agree on what we want.
+Possibilities:
+
+(1) Your example is legal, and the "new" raises Storage_Error.
+Doesn't seem very useful.
+
+(2) "Default_Storage_Pool(My_Pool);" applies to instances, but
+"Default_Storage_Pool(null);" does not.  This seems to accomplish the goal of
+applying to instances -- you can tell Containers.Vectors which pool to use, for
+example. Telling Vectors that it can't use ANY pool doesn't seem useful; that
+would be the job of some No_Heap_Allocation restriction.
+
+(3) Default_Storage_Pool never applies to instances.
+No way to control the pool on a per-instance basis.
+The "new" in your example uses whatever default pool applies to the generic
+body.
+
+I can live with any of these.  Opinions?
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, January 25, 2011  4:46 PM
+
+> Before I concoct wording, let's agree on what we want.
+> Possibilities:
+>
+> (1) Your example is legal, and the "new" raises Storage_Error.
+> Doesn't seem very useful.
+
+I think this is actually what the current wording does. It's not useful, but it
+is at least well-defined.
+
+> (2) "Default_Storage_Pool(My_Pool);" applies to instances, but
+> "Default_Storage_Pool(null);" does not.  This seems to accomplish the
+> goal of applying to instances -- you can tell Containers.Vectors which
+> pool to use, for example.
+> Telling Vectors that it can't use ANY pool doesn't seem useful; that
+> would be the job of some No_Heap_Allocation restriction.
+
+I suppose; but then I start to wonder what the point of
+Default_Storage_Pool(null) is. You can make the same argument as above about any
+package that you didn't write (those in Claw, for example). Whether or not it is
+generic isn't that relevant. Moreover, this seems uncomfortable because we would
+have a pragma that operates differently depending on its parameters.
+
+The idea of preferring a restriction is vaguely like the
+No_Standard_Storage_Pools restriction I was suggesting elsewhere. I think that
+would be a better way to enforce that, because explicit use of pools does not
+necessarily mean heap allocation (it is quite sensible to have pools totally
+allocated on the stack -- I have such pools). And it is easy to find anything
+explicit that you don't want, it is the implicit stuff that is hard to manage.
+
+> (3) Default_Storage_Pool never applies to instances.
+> No way to control the pool on a per-instance basis.
+> The "new" in your example uses whatever default pool applies to the
+> generic body.
+
+That seems confusing to me.
+
+So I tend to either suggest (1) [which is the easiest] or dropping
+Default_Storage_Pool(null) in favor of a restriction.
+
+****************************************************************
+
+From: Bob Duff
+Sent: Tuesday, January 25, 2011  5:00 PM
+
+> > That's not what I remember, but anyway, I'm certain that's not the
+> > reason I want this feature.  My reasons are accurately described in
+> > the !problem section of the AI, and they have nothing to do with
+> > anon acc types.
+>
+> Your memory is faulty.
+
+Quite possible.  But I'm also quite certain about my current opinion.
+
+>...All of the access type changes that were proposed  originated in the
+>bunch of "how to make anonymous access types more useful"
+> discussions.
+
+I have no interest in that futile exercise.
+I can certainly believe that this AI was born from that.
+
+>...One of the "requirements" that came from that was a way to  specify
+>storage pools for anonymous access types.
+
+True.
+
+> I understand your position, but it seems to me that a Restriction
+> No_Standard_Storage_Pool would provide the benefit you are looking for
+> in the !problem statement, and without any implication that it has any
+> effect on anonymous access types.
+
+A restriction No_Standard_Storage_Pool would solve part of the problem.
+It's equivalent to the currently-proposed Default_Storage_Pool(null).
+I don't see any reason why one or the other has any particular implication about
+anon access.
+
+Default_Storage_Pool(My_Pool) is more of a convenience, avoiding writing
+"Storage_Size = 0" and "Storage_Pool = My_Pool" all over the place.
+
+> I find the third paragraph somewhat bogus: if you deallocate from a
+> type with a different pool, you should expect it to fail. If you need
+> to do this, you need to specify a pool on each of the access types
+> involved, and because it is so critical to the algorithm, it ought to
+> be done explicitly. It makes more sense if you include anonymous
+> accesses, but essentially the proposal you give is to ignore them for
+> this purpose (it's still implementation-defined if the pool is used,
+> and in practice it never will be used). So how does that help??
+
+The third paragraph is about this:
+
+    type T1 is tagged...;
+    type A1 is access all T1'Class;
+    type T2 is new T1 with...;
+    type A2 is access all T2'Class;
+
+    X : A2 := new T2...;
+    Y : A1 := A1(X);
+    Free(Y); -- Erroneous?!
+
+People do this sort of thing all the time (with the code above distributed
+across many files), and I find it appalling that it works just fine in GNAT (and
+others) but it might be erroneous, depending on the whim of the compiler writer.
+
+No user-defined pools in sight.  And no anon access in sight.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Wednesday, January 26, 2011  8:03 AM
+
+> Your memory is faulty. All of the access type changes that were
+> proposed originated in the bunch of "how to make anonymous access types more useful"
+> discussions. One of the "requirements" that came from that was a way
+> to specify storage pools for anonymous access types.
+
+I guess my memory is faulty as well, then.  I find this lumping of the "Ada 95"
+anonymous access types (access discriminants and access parameters) with the
+"Ada 2005" anonymous access types (anonymous access types for local objects,
+record components, and return values) to be a mistake.  The "Ada 95" anon access
+types have been around a long time, and the allocators for them had no inherent
+storage leak problems, as they were defined so that their storage came from
+either the stack (access parameters), or the same storage pool as that of the
+enclosing object (access discriminants).
+
+Apparently not every implementor read the Ada 95 semantics, or chose to ignore
+them for whatever reason, but the rules for finalization of such objects (which
+were reiterated in Ada 2005 and Ada 2012), and the run-time accessibility
+checking for access parameters, makes it clear that allocators for access
+discriminants (now called co-extensions) and for access parameters are very
+different from those for the "Ada 2005" anon access types, and do not need to be
+"fixed" to avoid storage leaks or to make sure that the default (heap) storage
+pool doesn't get used inadvertently.
+
+The "how to make anon access types more useful" goal was, as far as my memory
+goes, all related to the various problems that showed up with the "Ada 2005"
+anon access types.  The "Ada 95" ones worked fine, and their allocators didn't
+have any storage leaks. I don't think anyone is helped by lumping them with the
+much thornier problems associated with the Ada 2005 anon access types.
+
+I believe the global storage pool control should only affect those "Ada 2005"
+anon access type allocators that don't have a well-defined storage pool already.
+My understanding of the "compromise" was that it was always OK to use the stack
+for access-parameter allocators, or access-discriminant allocators when the base
+object was itself on the stack.  The only effect was that when the global
+storage pool was set to "null" then all allocators, including these for Ada 95
+access types, must be coming from individually user-specified storage pools,
+which being impossible for an access parameter allocator, effectively disallows
+them.  Presumably the access discriminant allocator (aka coextension) is still
+allowed so long as it is piggy-backed into an individually user-specified
+storage pool.
+
+From my perspective this is a "compromise" since I think it is dumb to ever
+disallow access parameter allocators given that they always (at least
+semantically) live on the stack. But I was willing to simply disallow them in
+these cases.
+
+I really don't believe access-parameter allocators should *ever* be allocated
+from a storage pool, as that requires a completely different run-time model for
+these beasts from what is used in all other cases, and still doesn't change when
+they need to be finalized (on subprogram return), nor does it change their
+run-time accessibility level (which corresponds to the point of call).
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Wednesday, January 26, 2011  6:22 PM
+
+> I guess my memory is faulty as well, then.
+
+Yes, it is.
+
+> I find this
+> lumping of the "Ada 95" anonymous access types (access discriminants
+> and access parameters) with the "Ada 2005"
+> anonymous access types (anonymous access types for local objects,
+> record components, and return values) to be a mistake.  The "Ada 95"
+> anon access types have been around a long time, and the allocators for
+> them had no inherent storage leak problems, as they were defined so
+> that their storage came from either the stack (access parameters), or
+> the same storage pool as that of the enclosing object (access
+> discriminants).
+
+That's absolutely a load of rubbish. The "Ada 95 anonymous access types" are the
+crux of the problem. You've apparently forgotten or have blocked out the entire
+discussion about anonymous access types.
+
+Here's a message from Franco Gasperoni expanding on his paper that originally
+started the access type discussion (this is filed in AI05-0138-1 in case you
+want to verify it):
+
+
+From: Franco Gasperoni
+Date: Friday, November 14, 2008  10:47 AM
+
+A local allocator in Ada 95 and Ada 2005 is something like
+
+    procedure P (X : access T);
+
+    procedure Q is
+    begin
+       P (new T);  --  Local anonymous allocator
+    end Q;
+
+The local anonymous allocator above is implicitly deallocated just after the
+call to P, i.e. the above is akin to something like
+
+    procedure Q is
+    begin
+       declare
+          new_T : aliased T;
+       begin
+          P (new_T'Access);
+       end;
+    end Q;
+
+This is very convenient when we want to allocate temporary data-structures and
+storage for a phase of our application.  Local allocators allow us to allocate
+storage and be assured that this storage is automatically reclaimed on our
+behalf when the phase ends.
+
+However, for some people (including me :) the fact that local anonymous
+allocators and other type of allocators behave differently can be confusing and
+error prone. Consider the following example:
+
+    package Named_Lists is
+       type Cell;
+       type Any_Cell is access all Cell'Class;
+       type Cell is tagged record
+          Next : Any_Cell;
+       end record;
+       Head : Any_Cell := new Cell;
+       procedure Insert (Head : access Cell'Class;
+                         New_Cell : access Cell'Class);
+    end Named_Lists;
+
+    package body Named_Lists is
+       procedure Insert (Head : access Cell'Class;
+                         New_Cell : access Cell'Class)
+       is
+       begin
+          New_Cell.Next := Head.Next;
+          Head.Next := Any_Cell (New_Cell);
+       end Insert;
+    end Named_Lists;
+
+If we write
+
+    with Named_Lists; use Named_Lists;
+    procedure Main is
+    begin
+       Insert (Head, new Cell);
+    end Main;
+
+then we have a Program_Error, however if we write
+
+    with Named_Lists; use named_Lists;
+    procedure Main is
+       N : Any_Cell := new Cell;
+    begin
+       Insert (Head, N);
+    end Main;
+
+or if we write
+
+    with Named_Lists; use named_Lists;
+    procedure Main is
+    begin
+       Insert (Head, Any_Cell'(new Cell));
+    end Main;
+
+we don't. This can be confusing and error prone to some users and it may be
+important at least to be able to restrict their use (with some restrictions
+pragma).
+
+Alternatively, since we can mimic the use of local anonymous allocators with a
+local aliased object we could consider giving a longer (e.g. library-level if T
+is library-level) life-time to local anonymous allocators.
+
+More generally we may want to revisit the creation and destruction of storage
+from anonymous access types (see next post on this topic).
+
+****************************************
+
+[Randy again:]
+
+The above is an explict complaint about the semantics of allocators of access
+parameters (as defined in Ada 95). I don't see anything here that suggests that
+there is no problem with Ada 95 access parameter allocators; it's exactly the
+reverse. His original paper also asked for Unchecked_Deallocation of anonymous
+access, and ability to specify storage pools, neither of which would work
+with the above example and the current semantics. Indeed, he explicitly asks
+to change the semantics of allocators of access parameters!
+
+The discussion after that considered a number of fixes, including ways to
+specify the scope of anonymous access types, before finally settling on
+No_Anonymous_Allocators as a sort of fix.
+
+My feeling with Default_Storage_Pool was that it too was intended to provide a
+part of the solution to his original concerns. If it is not, then it should do
+nothing for *any* anonymous access types. Having it do some and not all is just
+too confusing to understand. Making which ones are handled as
+*implementation-defined* is even more confusing and means that programs using
+that pragma aren't portable in some circumstances.
+
+Moreover, in the face of a pragma Default_Storage_Pool, having an allocator
+(*any* allocator) that does not respect the pragma (in the absense of a specific
+setting to the contrary) is actively harmful -- you have something that *looks*
+like a heap allocation but in fact is not.
+
+The real problem here is that anonymous access types have the wrong lifetime for
+many uses; if you want to keep the object for a long time, you really need to
+specify that when the access type is declared. Otherwise, only anonymous access
+components are likely to do the right thing (and that's only because they are
+likely to be declared at library-level). For instance, imagine the following
+code:
+
+     declare
+         A : access T := new T'(...);
+     begin
+         if <condition> then
+             P (A);
+         else
+             ...
+     end;
+
+and imagine that P is defined as:
+
+     type Acc_T is access all T;
+     Global_Chain : Acc_T;
+
+     procedure P (PM : access T) is
+     begin
+         PM.Next := Global_Chain;
+         Global_Chain := PM;
+     end P;
+
+This sort of code is quite likely when Ada 2005 limited withs appear. The
+problem of course is that the accessibility check will fail when you try to put
+the object on the global chain. (I had lots of trouble with this in Claw; it
+caused me to abandon access parameters and functions altogether. If I had been
+cleverer, I could have used .all'Unchecked_Access to strip off the dynamic
+accessibility check, but that is still barf-inducing.)
+
+Anyway, we decided not to try to fix this problem, which is fine, but the user
+hazard of getting the wrong lifetime for allocators still exists. I don't care
+so much when the user hasn't said anything about storage pools, because they are
+getting the standard allocator and that does whatever and they have no right to
+complain. But when they specify something, it seems wrong for it to be ignored.
+
+I do agree that using their specification is *also* bad for access parameters
+considering the very short lifetime of the objects (and I agree that we can't
+fix that, despite the fact that it is garbage). So I conclude that the only
+reasonable thing to do it is ban such allocators in the presense of a
+Default_Storage_Pool pragma.
+
+> Apparently not every implementor read the Ada 95 semantics, or chose
+> to ignore them for whatever reason, but the rules for finalization of
+> such objects (which were reiterated in Ada 2005 and Ada 2012), and the
+> run-time accessibility checking for access parameters, makes it clear
+> that allocators for access discriminants (now called
+> co-extensions) and for access parameters are very different from those
+> for the "Ada 2005" anon access types, and do not need to be "fixed" to
+> avoid storage leaks or to make sure that the default (heap) storage
+> pool doesn't get used inadvertently.
+
+"Robert's rule of sensibility" was applied here: the standard cannot possibly
+mean something that is clearly confusing to the reader and lacks any significant
+value.
+
+> The "how to make anon access types more useful" goal was, as far as my
+> memory goes, all related to the various problems that showed up with
+> the "Ada 2005" anon access types.  The "Ada 95" ones worked fine, and
+> their allocators didn't have any storage leaks.
+> I don't think anyone is helped by lumping them with the much thornier
+> problems associated with the Ada 2005 anon access types.
+
+From rereading part of these discussions, I see that this was always a blind
+spot of yours. The questioner gives examples of problems with anonymous access
+parameters, and you answered saying the we need to fix anonymous access objects
+(not even used in the examples). When I see "new", I see storage pool
+allocation, not stack allocation; anything else is lying to me and misleading.
+If I want a short lifetime, I'll declare an object, not use "new"! "New" only
+for global lifetimes, and I expect to have to do the cleanup myself (if they
+aren't going to live the life of the program).
+
+...
+> I really don't believe access-parameter allocators should
+> *ever* be allocated...
+
+At this point, you are absolutely right. :-)
+
+> ... from a storage pool, as that requires a completely different
+> run-time model for these beasts from what is used in all other cases,
+> and still doesn't change when they need to be finalized (on subprogram
+> return), nor does it change their run-time accessibility level (which
+> corresponds to the point of call).
+
+I reluctantly agree with this, because all of these things are wrong and do not
+do what the reader expects (and usually wants). Because it is too late to fix
+this, the only solution is to not allow them at all where they would be
+confusing. And that surely includes whenever Default_Storage_Pool is given
+(otherwise the pragma is lying, or the model is overly confusing).
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Wednesday, January 26, 2011  6:36 PM
+
+> A restriction No_Standard_Storage_Pool would solve part of the problem.
+> It's equivalent to the currently-proposed Default_Storage_Pool(null).
+> I don't see any reason why one or the other has any particular
+> implication about anon access.
+
+I really was thinking of No_Standard_Storage_Pool_for_Named_Access_Types.
+See my other message.
+
+> Default_Storage_Pool(My_Pool) is more of a convenience, avoiding
+> writing "Storage_Size = 0" and "Storage_Pool = My_Pool" all over the
+> place.
+
+Right. And it causes trouble, so one solution is to drop it. Two others are
+(1) Keep it, but eliminate all mention of anonymous access types from the pragma
+    (so it really is "Default_Storage_Pool_for_Named_Access_Types", although I
+    don't think I'd suggest this name!).
+(2) Ban anonymous allocators that don't use this pool whenever the pragma
+    applies. (They become illegal.)
+
+> > I find the third paragraph somewhat bogus: if you deallocate from a
+> > type with a different pool, you should expect it to fail. If you
+> > need to do this, you need to specify a pool on each of the access
+> > types involved, and because it is so critical to the algorithm, it
+> > ought to be done explicitly. It makes more sense if you include
+> > anonymous accesses, but essentially the proposal you give is to
+> > ignore them for this purpose (it's still implementation-defined if
+> > the pool is used, and in practice it never will be used). So how does that help??
+>
+> The third paragraph is about this:
+>
+>     type T1 is tagged...;
+>     type A1 is access all T1'Class;
+>     type T2 is new T1 with...;
+>     type A2 is access all T2'Class;
+>
+>     X : A2 := new T2...;
+>     Y : A1 := A1(X);
+>     Free(Y); -- Erroneous?!
+>
+> People do this sort of thing all the time (with the code above
+> distributed across many files), and I find it appalling that it works
+> just fine in GNAT (and others) but it might be erroneous, depending on
+> the whim of the compiler writer.
+>
+> No user-defined pools in sight.  And no anon access in sight.
+
+Right, but this example is what I consider "slightly bogus". I can't imagine why
+anyone would expect the above to work! Ada never, ever has supported this sort
+of code. If people are writing this on purpose, they get what they deserve. (I
+added code to Janus/Ada to detect this in easy cases after you showed this
+example; that at least prevents real erroneousness in such cases.)
+
+The reason I said "slightly bogus" is that I can imagine this happening by
+accident, and the fact that it is not [always] detected is annoying. But that
+almost certainly involves anonymous access types (even more likely in Ada 2012,
+as we now have more implicit conversions). No one can accidentally write named
+type conversions, and there is no reason to have multiple identical named access
+types anyway.
+
+So I don't find this example convincing. The notion of easily applying a debug
+pool to an entire program seems more compelling to me (and not that much).
 
 ****************************************************************
 

Questions? Ask the ACAA Technical Agent