CVS difference for ai05s/ai05-0149-1.txt
--- ai05s/ai05-0149-1.txt 2009/05/19 22:46:58 1.3
+++ ai05s/ai05-0149-1.txt 2009/06/02 06:22:37 1.4
@@ -60,21 +60,21 @@
designated type is tagged, the designated type of the anonymous
access type shall be covered by the designated type of the named
access type (explicit conversion allows for more possibilities).
-
+
4) Implicit conversion is provided from a named access type with a static
accessibility level to a named, general access-to-classwide type,
provided the designated type of the target access type covers that of
the source type. The usual static accessibility level check applies.
+
-
*Incomplete access types* are created as part of a limited view of a
package. Each non-derived access type declared in the visible part of a
-package spec becomes an incomplete access type in the limited view.
+package spec becomes an incomplete access type in the limited view.
Derived access types don't become incomplete access types in the limited
view because they aren't syntactically distinguishable from any other
kind of untagged derived type.
-Incomplete named access types may *not* be used for components.
+Incomplete named access types may *not* be used for components.
Instead, anonymous access types may be used for those, and then the
anonymous access type may be implicitly converted to the named access
type in places with a full view of the named access type.
@@ -96,7 +96,7 @@
designated type is the same as that of the tested type, or if tagged,
convertible to the designated type of the tested type; otherwise},
the expected type for the simple_expression is the tested type.
-
+
Add after 4.5.2(30.2/2):
* if the tested type is a general access-to-object type, the type of the
@@ -105,7 +105,7 @@
further, if the designated type is tagged and the simple_expression is
non-null, the tag of the object designated by the value of the
simple_expression is covered by the designated type of the tested type.
-
+
!discussion
We have grouped part (1) with these other proposals as any
@@ -206,7 +206,7 @@
also end up ambiguous if the actual were of an anonymous type.
For the conversion *to* a named access-to-classwide type, this is perhaps
-more of a concern, as currently two subprograms that differ in the named
+more of a concern, as currently two subprograms that differ in the named
access type of a parameter are not ambiguous unless the actual is "null"
or an allocator. The extent of this ambiguity should be investigated
if possible in existing archives of customer code. Note that this applies
@@ -217,19 +217,19 @@
QUESTIONS:
Q: Might a special "type T is access;" syntax be worthwhile? Perhaps it could
-be a way to indicate in a limited view that a derived type
-is in fact an access type. E.g.:
+be a way to indicate in a limited view that a derived type
+is in fact an access type. E.g.:
type NT is access;
type NT is new T;
-
+
And in general it would be a way to allow the incomplete type
-to be used as a formal parameter/result type before the full type
-definition is provided.
-
+to be used as a formal parameter/result type before the full type
+definition is provided.
+
We have not proposed this syntax for now, as the need does not seem compelling.
However, it could be added to this proposal, now or at a later date.
-
+
ASIDE: Hmmm... I wonder whether we could have generic formal incomplete
types as a way to allow instantiation with a private type before
it is fully defined. This might be sufficient for a "signature"
@@ -495,8 +495,8 @@
From: Gary Dismukes
Sent: Wednesday, March 11, 2009 11:58 AM
-> What I would prefer would be to have a membership test properly report
-> whether a conversion of an anonymous access value to a named access
+> What I would prefer would be to have a membership test properly report
+> whether a conversion of an anonymous access value to a named access
> type would raise Program_Error
> *or* Constraint_Error.
@@ -508,8 +508,8 @@
From: Bob Duff
Sent: Wednesday, March 11, 2009 12:51 PM
-> What I would prefer would be to have a membership test properly report
-> whether a conversion of an anonymous access value to a named access
+> What I would prefer would be to have a membership test properly report
+> whether a conversion of an anonymous access value to a named access
> type would raise Program_Error
> *or* Constraint_Error.
@@ -520,17 +520,17 @@
From: Randy Brukardt
Sent: Wednesday, March 11, 2009 3:21 PM
-> Having an explicit level makes me nervous, especially since I presume
-> it is a static nesting level, whereas accessibility is actually
-> officially defined based on a dynamic nesting level, and in some
-> cases, there is no simple static nesting level that can be used
+> Having an explicit level makes me nervous, especially since I presume
+> it is a static nesting level, whereas accessibility is actually
+> officially defined based on a dynamic nesting level, and in some
+> cases, there is no simple static nesting level that can be used
> instead.
I pointed that out immediately after Franco posted the original message back
in November.
-
-> What I would prefer would be to have a membership test properly report
-> whether a conversion of an anonymous access value to a named access
+
+> What I would prefer would be to have a membership test properly report
+> whether a conversion of an anonymous access value to a named access
> type would raise Program_Error
> *or* Constraint_Error.
@@ -539,11 +539,11 @@
subcommittee...)
> E.g.:
->
+>
> type Acc_T is access all T;
->
+>
> X : Acc_T;
->
+>
> procedure P(A : access T) is
> begin
> if A in Acc_T then
@@ -553,13 +553,13 @@
> Put_Line("Can't convert to Acc_T");
> end if;
> end P;
->
+>
> That is, a use of "A in Acc_T" would return False iff "Acc_T(A)"
> would raise Program_Error or Constraint_Error
->
-> Right now, such a membership test is not legal, since there are no
-> implicit conversions from anonymous access types to named access
-> types, so we could add this capability without incurring any upward
+>
+> Right now, such a membership test is not legal, since there are no
+> implicit conversions from anonymous access types to named access
+> types, so we could add this capability without incurring any upward
> incompatibility.
...but thanks for working out the details. The main reason that I didn't make a
@@ -588,8 +588,8 @@
Sent: Monday, April 13, 2009 8:27 AM
> !proposal
->
-> When the tested type of a membership test is a general access type,
+>
+> When the tested type of a membership test is a general access type,
> allow the expression to be of an anonymous access type.
That's not quite right -- the new wording allows additional tests for named types
@@ -649,8 +649,8 @@
From: Randy Brukardt
Sent: Thursday, April 30, 2009 1:48 AM
-> I did realize after writing up this new version that the original
-> version allowed membership tests across distinct named access types,
+> I did realize after writing up this new version that the original
+> version allowed membership tests across distinct named access types,
> but that seemed undesirable once I realized it.
Humm, I thought it was a feature. And you described as one in your old writeup, that
@@ -659,18 +659,18 @@
As I mentioned later, it seems useful in a generic body to see if converting to a
global type or a formal access type is possible (that would depend on where you are
instantiated). Not an important need though.
-
-> I suppose another reason to disallow membership tests across distinct
-> named access types is that it introduces more incompatibility due to
+
+> I suppose another reason to disallow membership tests across distinct
+> named access types is that it introduces more incompatibility due to
> added ambiguity.
Huh? What ambiguity could occur? Is there any useful membership allowed now (I
thought all you could do is test an object against its type, getting True; I doubt
there is much of that in programs!)
-> Anyway, there are some reasons. I'm not hard over on it, and I
-> suppose membership tests between two named access-to-tagged types
-> might make some sense. Membership tests between two named
+> Anyway, there are some reasons. I'm not hard over on it, and I
+> suppose membership tests between two named access-to-tagged types
+> might make some sense. Membership tests between two named
> access-to-untagged seems pretty hard to justify.
Well, I tried above. You can take it or leave it - this isn't an important issue,
@@ -681,7 +681,7 @@
From: Steve Baird
Sent: Thursday, April 30, 2009 12:50 PM
-> I didn't see the need for membership tests between two different named
+> I didn't see the need for membership tests between two different named
> access types.
I agree with Tuck on this issue.
@@ -744,7 +744,7 @@
Looks good.
-> plus I added in Bob's proposal that we allow implicit conversions to a
+> plus I added in Bob's proposal that we allow implicit conversions to a
> named access-to-classwide type from other
> *named* access types covered by it.
@@ -756,3 +756,407 @@
;-)
****************************************************************
+
+From: Steve Baird
+Sent: Tuesday, May 19, 2009 6:42 PM
+
+> This AI makes four related proposals:
+>
+> 1) When the tested type of a membership test is a general access
+> type, allow the expression to be of an anonymous access type.
+>
+> 2) Incomplete access types, which are access types declared in a
+> limited view of a package, may be used as formal parameter and result
+> types.
+>
+> 3) Implicit conversion is provided from an anonymous access type
+> with a static accessibility level to a named, general access type,
+> provided the explicit conversion is legal (i.e. static accessibility
+> check passes; designated types match if untagged); further, if the
+> designated type is tagged, the designated type of the anonymous
+> access type shall be covered by the designated type of the named
+> access type (explicit conversion allows for more possibilities).
+>
+> 4) Implicit conversion is provided from a named access type with a static
+> accessibility level to a named, general access-to-classwide type,
+> provided the designated type of the target access type covers that of
+> the source type. The usual static accessibility level check applies.
+
+#1, #3, and #4 look good.
+
+I'm not so sure about #2.
+
+The big question is whether leaning more heavily in any way on limited views is
+a good idea.
+
+I'm inclined to say no, but I don't feel strongly about it.
+
+I'm more concerned about the details here.
+
+> An incomplete access type is OK as a parameter or result since
+> access-type parameters and results are always passed by copy, and the
+> implementation can use a default general-access-type representation
+> for them, even if the full named access type turns out to have some
+> kind of aspect clause.
+
+What makes me nervous here is presupposing the existence of a
+general-access-type representation which can always be used for parameter
+passing.
+
+Suppose an implementation chooses to support something like
+
+ type T is access Boolean;
+ pragma Bit_Address (T);
+
+or
+
+ type T is access Some_Type;
+ pragma Check_Magic_Number_Matching (T);
+ -- access values include an id which is checked
+ -- against an id value stored with the designated
+ -- object upon dereference
+
+or perhaps both.
+
+An incomplete access type *might* turn out to be subject to such a pragma, so
+this "default" representation must handle this case. So we get distributed
+overhead if, for example, this forces the use of a representation which doesn't
+fit in a register on the target machine.
+
+Now we look at two procedures, each with a single parameter of the same access
+type. For one, the access type was incomplete at the point of the subprogram
+declaration. These two subprograms have to be compatible with respect to being
+called via an access to subprogram value (similar considerations apply to
+parameters/results of dispatching operations).
+
+This means that an implementation must either use the "general" representation
+even in the case where the full view of the access type is available or the
+implementation must introduce wrappers.
+
+I'm worried that we're opening a can of worms here.
+
+****************************************************************
+
+From: Bob Duff
+Sent: Tuesday, May 19, 2009 7:08 PM
+
+> type T is access Some_Type;
+> pragma Check_Magic_Number_Matching (T);
+> -- access values include an id which is checked
+> -- against an id value stored with the designated
+> -- object upon dereference
+
+That's what some folks call a "generation count".
+
+> or perhaps both.
+>
+> An incomplete access type *might* turn out to be subject to such a
+> pragma, so this "default" representation must handle this case. So we
+> get distributed overhead if, for example, this forces the use of a
+> representation which doesn't fit in a register on the target machine.
+>
+> Now we look at two procedures, each with a single parameter of the
+> same access type. For one, the access type was incomplete at the point
+> of the subprogram declaration. These two subprograms have to be
+> compatible with respect to being called via an access to subprogram
+> value (similar considerations apply to parameters/results of
+> dispatching operations).
+>
+> This means that an implementation must either use the "general"
+> representation even in the case where the full view of the access type
+> is available or the implementation must introduce wrappers.
+
+These are implementation-defined pragmas, so they have implementation-defined
+rules. Can't the implementation just outlaw their use in the problematic cases?
+Possibly at an "unusual" time, like when the two views "come together"
+-- or even at link time?
+
+Do you believe there's a problem with GNAT's fat pointers?
+
+> I'm worried that we're opening a can of worms here.
+
+Possibly. Ichbiah always called it a "bag" of worms, by the way. ;-)
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Tuesday, May 19, 2009 9:36 PM
+
+> What makes me nervous here is presupposing the existence of a
+> general-access-type representation which can always be used for
+> parameter passing.
+
+Don't access parameters already presume that? I think there might be an issue
+with function results, but I don't understand how parameters can be a problem.
+Similarly, explicit access conversion to a general access type presumes that any
+access value can be represented as a value of a general access type with the
+same designated subtype. On the other hand, as Bob mentioned, these are
+implementation-defined pragmas, so you can create any limitation you want
+associated with them, both as far as conversion to a general access type, and
+the "hidden" conversion that might take place to an incomplete view.
+
+...
+> An incomplete access type *might* turn out to be subject to such a
+> pragma, so this "default" representation must handle this case. So we
+> get distributed overhead if, for example, this forces the use of a
+> representation which doesn't fit in a register on the target machine.
+
+How would that work
+
+> Now we look at two procedures, each with a single parameter of the
+> same access type. For one, the access type was incomplete at the point
+> of the subprogram declaration. These two subprograms have to be
+> compatible with respect to being called via an access to subprogram
+> value (similar considerations apply to parameters/results of
+> dispatching operations).
+>
+> This means that an implementation must either use the "general"
+> representation even in the case where the full view of the access type
+> is available or the implementation must introduce wrappers.
+
+I considered and then rejected making these subprograms have intrinsic calling
+convention, because generating a wrapper seems very unlikely, and the
+implementation could simply reject such uses if it so chose because these are
+implementation-defined pragmas.
+
+> I'm worried that we're opening a can of worms here.
+
+Perhaps, though I think the implementation-defined nature of these pragmas
+allows the implementator great flexibility.
+
+A bigger concern for me would be the "fat pointer" situation. However, it
+doesn't seem like such a big deal since we know that when the actual heap
+objects are created, you would have a full view of the access type, so you could
+create the appropriate kind of heap representation. Then you will know it is
+always safe to convert the presumably "general" fat pointer representation back
+to the special "thin" pointer representation, since you know the bounds were in
+fact placed contiguous with the array components. That conversion would not in
+general be safe since you wouldn't be sure where the bounds were allocated. But
+in this case, since the conversions are under control of the implementation,
+everything is copacetic.
+
+****************************************************************
+
+From: Steve Baird
+Sent: Wednesday, May 20, 2009 12:01 AM
+
+>> An incomplete access type *might* turn out to be subject to such a
+>> pragma, so this "default" representation must handle this case. So
+>> we get distributed overhead if, for example, this forces the use of
+>> a representation which doesn't fit in a register on the target
+>> machine.
+>
+> How would that work
+
+
+If, for example, a Jumbo-format pointer is passed as a pair of
+addresses, then a conservative assumption that a given incomplete
+access type *might* have a Jumbo representation would (in the absence
+of wrappers) require passing 2 addresses when a subprogram has a
+parameter of this incomplete access type.
+
+> I considered and then rejected making these subprograms have
+> intrinsic calling convention, because generating a wrapper seems very
+> unlikely, and the implementation could simply reject such uses if it
+> so chose because these are implementation-defined pragmas.
+>
+
+True, although this might involve post-compilation checks.
+
+>>
+>> I'm worried that we're opening a can of worms here.
+>
+> Perhaps, though I think the implementation-defined nature of these
+> pragmas allows the implementator great flexibility.
+>
+> A bigger concern for me would be the "fat pointer" situation.
+
+I agree that that is a concern.
+I think there are problems in this area.
+
+> However, it doesn't seem like such a big deal since we know that when
+> the actual heap objects are created, you would have a full view of
+> the access type, so you could create the appropriate kind of heap
+> representation. Then you will know it is always safe to convert the
+> presumably "general" fat pointer representation back to the special
+> "thin" pointer representation, since you know the bounds were in fact
+> placed contiguous with the array components. That conversion would
+> not in general be safe since you wouldn't be sure where the bounds
+> were allocated. But in this case, since the conversions are under
+> control of the implementation, everything is copacetic.
+
+
+There would be access-to-subprogram issues even for a pool-specific
+access type. If two subprograms have the same parameter profile but
+one expects to be passed a fat pointer and one expects a thin pointer,
+then you need wrappers, right?
+
+I think things get worse when we consider general access types because
+in that case (I think; correct me if I'm wrong) we have to deal with
+the case of a designated object which lacks a contiguous dope vector.
+
+Just in general, it seems reasonable that an implementation might have
+a strategy where the format of an access type depends on properties of
+the designated type (with some default representation used in the case
+of a Taft-amendment designated type).
+
+Any time you have an access type which gets the non-default
+representation, you're going to have problems with the incomplete view
+of that access type.
+
+As I mentioned earlier, this would require wrappers or some analogous
+implementation work for both forms of dynamic call
+(access-to-subprogram and dispatching operations).
+
+If you have two interface types that both have an abstract operation
+with the same name and profile, but one takes a parameter of an
+incomplete access type and the other takes a parameter of the complete
+access type and then you have a type which implements both of the
+interfaces, this can all be made to work but it seems like a fair
+amount of work.
+
+I think there is a fair amount of implementation effort implicit in
+this proposal.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Wednesday, May 20, 2009 9:42 AM
+
+Would problems be simplified if we disallowed a call or 'Access on such a
+subprogram at a place where there is only an incomplete view of one of the
+formal parameter access types? That would seem to eliminate the need for
+wrappers and default representations.
+
+****************************************************************
+
+From: Steve Baird
+Sent: Wednesday, May 20, 2009 9:58 AM
+
+I need to think about this.
+Currently when you declare an access-to-subprogram type, you have all the
+information you'll ever need about the conventions for calling subprograms
+designated by values of that type. You are suggesting that we abandon this rule.
+It makes me nervous, but I don't see any specific problems right off the top of
+my head.
+
+I think you would also want to disallow subprogram bodies.
+
+****************************************************************
+
+From: Steve Baird
+Sent: Wednesday, May 20, 2009 10:01 AM
+
+... and instantiations with formal access types (yes, this case is possible).
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Wednesday, May 20, 2009 11:02 AM
+
+An intriguing possibility here is to generally allow *any* incomplete type as a
+parameter or result type in a subprogram declaration, or at least any incomplete
+type that comes from the limited view of a package. If we disallow calls,
+'Access, bodies, and instantiations, but allow such subprograms to be declared,
+then "limited with" becomes significantly more useful, as it doesn't impose much
+of any restriction on the spec that has the limited with, so long as the
+corresponding body and the callers have a non-limited with.
+
+This would also eliminate the annoying distinction between derived and
+non-derived access types inherent in this proposal.
+
+The special case for incomplete tagged would simply be that you can do more with
+a subprogram whose only use of incomplete types in its profile is as parameters
+of an incomplete tagged type.
+
+Comments?
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Wednesday, May 20, 2009 11:12 AM
+
+Effectively what this would mean is that for such a subprogram, no uses that
+would "freeze" the subprogram would be permitted in a place where you only have
+an incomplete view of the result type or one of the non-tagged parameter types.
+The subprogram itself would effectively be frozen at the start of the
+compilation unit that enclosed its body.
+
+****************************************************************
+
+From: Bob Duff
+Sent: Wednesday, May 20, 2009 11:47 AM
+
+> An intriguing possibility here is to generally allow *any* incomplete
+> type as a parameter or result type in a subprogram declaration, or at
+> least any incomplete type that comes from the limited view of a
+> package. If we disallow calls, 'Access, bodies, and instantiations,
+> but allow such subprograms to be declared, then "limited with"
+> becomes significantly more useful, as it doesn't impose much of any
+> restriction on the spec that has the limited with, so long as the
+> corresponding body and the callers have a non-limited with.
+
+I like it. I'd go for "any incomplete type" -- why not?
+
+> This would also eliminate the annoying distinction between derived and
+> non-derived access types inherent in this proposal.
+
+Shrug. Derived access types are vanishingly rare.
+
+****************************************************************
+
+From: Steve Baird
+Sent: Wednesday, May 20, 2009 11:57 AM
+
+This seems like a big change, but it might work.
+
+Consider an implementation which associates implicit parameters with certain
+kinds of source-level parameters (e,g, a dope parameter for a parameter of an
+unconstrained array subtype, an Is_Constrained parameter for a non-in-mode
+parameter of a discriminated type with defaults, etc.).
+
+This means that at the point of the initial declaration of a subprogram, the set
+of implicit parameters associated with the subprogram might not be known.
+
+This is, I suppose, just one special case of not knowing the calling convention
+information for the subprogram.
+
+I believe that some (most? all?) Ada compilers currently rely on knowing this
+information at this point, but do they fundamentally need to? I'm not sure.
+
+P.S. I really like two aspects of this proposal - eliminating "the annoying
+distinction between derived and non-derived access types" and the lack of any
+requirement for extracting any more information from a limited view of a package
+than the language already requires.
+
+****************************************************************
+
+From: Steve Baird
+Sent: Wednesday, May 20, 2009 12:05 PM
+
+> Shrug. Derived access types are vanishingly rare.
+
+I agree, but it might be handy if they worked in the few cases where they come
+up.
+
+I am thinking about a situation where a user uses a derived type to get
+limited-view visibility to a type declared in an instance:
+
+ package P is
+ package I is new G;
+ type D is new I.Some_Access_Type;
+ end P;
+
+****************************************************************
+
+From: Ed Schonberg
+Sent: Wednesday, May 20, 2009 2:12 AM
+
+This is very appealing, but it will require some tweaking of freezing rules, no?
+At the end of a spec you freeze the subprograms, which freezes their formals,
+etc. Clearly nothing can be done with these incomplete types, so we need some
+paragraph in 13.14 to make this legal. Otherwise this is a very substantial
+simplification.
+
+****************************************************************
+
Questions? Ask the ACAA Technical Agent