Version 1.11 of ai12s/ai12-0140-1.txt

Unformatted version of ai12s/ai12-0140-1.txt version 1.11
Other versions for file ai12s/ai12-0140-1.txt

!standard 3.4(7/3)          16-08-01 AI12-0140-1/04
!standard 7.3.1(5/1)
!class binding interpretation 14-10-13
!status Amendment 1-2012 16-08-01
!status ARG Approved 9-0-2 16-06-11
!status work item 14-10-13
!status received 14-07-10
!priority Low
!difficulty Medium
!qualifier Omission
!subject Access to unconstrained partial view when full view is constrained
!summary
The view of a designated subtype is determined by where the access type is used rather than by where the access type is declared, except for access-to- incomplete-view-from-limited-view-of-package.
!question
I have the following code which is accepted by GNAT and ICCAda, but rejected by Janus/Ada:
with Ada.Unchecked_Deallocation;
package UNC is
type My_String (<>) is limited private; type My_String_Access is access My_String; private type My_String is new String; procedure Free is new Ada.Unchecked_Deallocation (My_String, My_String_Access);
end UNC; -- end of example code
Janus/Ada gives me an error: In File C:\work\undiscriminated-discriminated\unc.ads at line 10 --------------
9: procedure Free is new 10: Ada.Unchecked_Deallocation (My_String, My_String_Access);
----------------------------------------------------^ ERROR Formal and actual must both be discriminated or undiscriminated (6.4.10) [RM 12.5.4(3)]
The full view of My_String has no discriminant constraint, while My_String_Access designates the partial view of My_String, which has an unknown discriminant constraint. It's not clear that these statically match, as is required by 12.5.4(3).
The question is: Is the example code legal? (Yes.)
!recommendation
(See Summary.)
!wording
Add after 3.2(7):
AARM Ramification: "Null constraint" includes the cases of no explicit constraint, as well as unknown discriminants and unconstrained array type declarations (which are explicit ways to declare no constraint).
[Author's note: This AARM note seems somewhat useful to provide, though no longer really relates to the content of this AI.]
For context, here are 7.3.1(3/1,4/1,5/1):
For a composite type, the characteristics (see 7.3) of the type are determined in part by the characteristics of its component types. At the place where the composite type is declared, the only characteristics of component types used are those characteristics visible at that place. If later immediately within the declarative region in which the composite type is declared additional characteristics become visible for a component type, then any corresponding characteristics become visible for the composite type. Any additional predefined operators are implicitly declared at that place. If there is no such place, then additional predefined operators are not declared at all, but they still exist.
The corresponding rule applies to a type defined by a derived_type_definition, if there is a place immediately within the declarative region in which the type is declared where additional characteristics of its parent type become visible.
Redundant:[For example, an array type whose component type is limited private becomes nonlimited if the full view of the component type is nonlimited and visible at some later place immediately within the declarative region in which the array type is declared. In such a case, the predefined "=" operator is implicitly declared at that place, and assignment is allowed after that place.]
Add after 7.3.1(5/1):
The characteristics and constraints of the designated subtype of an access type follow a somewhat different rule. The view of the designated subtype of (a view of) an access type at a given place is determined by the view of the designated subtype that is visible at that place, rather than the view at the place where the access type is declared.
!discussion
The earlier version of this AI restricted itself to private types, but the more general approach suggested here seems appropriate. My belief is that most compilers (but apparently not the Janus compiler) already implement this interpretation.
Whether the view of a designated subtype is incomplete or complete at a particular place is determined by 3.10.1(2.7/3); this new rule has no effect on that at all.
Here are some examples:
package UNC2 is type My_String (<>) is limited private; -- "null constraint" type My_String_Access is access My_String; private type My_String is new String(1..10); -- "index constraint" procedure Free is new Ada.Unchecked_Deallocation (My_String, My_String_Access); end UNC2;
Above is a case where many characteristics of the designated subtype differ depending on the view. This new rule ensures that the view of the designated type to use is for the instantiation is the one visible at that place, rather than the one visible where the access type was declared. Note that every compiler that we tested this code on accepted it.
package UNC3 is type My_String (<>) is limited private; -- "null constraint" subtype My_String_P is My_String; type My_String_Access is access My_String_P; private type My_String is new String(1..10); -- "index constraint" subtype My_String_F is My_String; procedure Free is new Ada.Unchecked_Deallocation (My_String_F, My_String_Access); end UNC3;
Here again, the designated subtype's characteristics are determined by the place where the access type is used, rather than where the access type is declared.
!corrigendum 7.3.1(5/1)
Insert after the paragraph:
For example, an array type whose component type is limited private becomes nonlimited if the full view of the component type is nonlimited and visible at some later place immediately within the declarative region in which the array type is declared. In such a case, the predefined "=" operator is implicitly declared at that place, and assignment is allowed after that place.
the new paragraph:
The characteristics and constraints of the designated subtype of an access type follow a somewhat different rule. The view of the designated subtype of (a view of) an access type at a given place is determined by the view of the designated subtype that is visible at that place, rather than the view at the place where the access type is declared.
!ASIS
No ASIS effect.
!ACATS test
We probably need an ACATS C-test like the example in the question.
!appendix

!topic Access to unconstrained partial view when full view is constrained
!reference 12.5.4(3)
!from Tero Koskinen 10-07-14
!keywords unconstrained constrained partial view
!discussion

I have a following code which is accepted by GNAT and ICCAda, but
rejected by Janus/Ada:

with Ada.Unchecked_Deallocation;

package UNC is

   type My_String (<>) is limited private;
   type My_String_Access is access My_String;
private
   type My_String is new String;
   procedure Free is new
     Ada.Unchecked_Deallocation (My_String, My_String_Access);

end UNC;
-- end of example code

Janus/Ada gives me error:
In File C:\work\unconstrained-constrained\unc.ads at line 10
--------------
    9:     procedure Free is new
   10:       Ada.Unchecked_Deallocation (My_String, My_String_Access);
----------------------------------------------------^
*ERROR* Formal and actual must both be constrained or unconstrained
(6.4.10) [RM 12.5.4(3)]


Full view of My_String is constrained, while My_String_Access designates
the partial view of My_String, which is unconstrained.

The question is:
Is the example code legal or not?

PS. Originally found when compiling Adalog's debug package:
http://www.adalog.fr/compo2.htm#Debug

****************************************************************

From: Tucker Taft
Sent: Friday, July 11, 2014  9:26 AM

Your code is legal.  Janus seems to be freezing the fact that the designated
type of My_String_Access is unconstrained, rather than recomputing it based on
visibility at the point of generic instantiation.  The rule for static matching
between the designated subtype of a formal and actual has nothing to do with
where the access type is declared.

****************************************************************

From: Randy Brukardt
Sent: Monday, July 14, 2014  6:54 PM

You don't give any justification for this position. I couldn't find any in the
RM. I wouldn't expect a property of an access type to change over its life
without some explicit wording for that.

For a counter-example, access-to-incomplete types are always considered that
during their full lifetime - that does not change because of visibility. We have
special rules that say that they are treated as complete when the completion of
the incomplete type is available. (See 3.10.1(2.2/2-2.6/3)).

We've got rules defining that characteristics behave this way, but whether a
type is constrained or not does not appear to be a characteristic -- at least
its not mentioned in the list in 3.4(8/2).

So I don't see any RM reason for your interpretation. Perhaps there is a
usability one (although I think it would have to be fairly strong given the
destruction of the model that types are defined by their definition, which we
adhere to despite the often nonsense results that one gets).

****************************************************************

From: Tucker Taft
Sent: Monday, July 14, 2014  7:40 PM

>> Your code is legal.  Janus seems to be freezing the fact that the
>> designated type of My_String_Access is unconstrained, rather than
>> recomputing it based on visibility at the point of generic
>> instantiation.  The rule for static matching between the designated
>> subtype of a formal and actual has nothing to do with where the
>> access type is declared.
>
> You don't give any justification for this position. I couldn't find
> any in the RM. I wouldn't expect a property of an access type to
> change over its life without some explicit wording for that.

But this is not a property of the access type, it is a property of the
designated type. Furthermore, these are exactly the *same* type, so it is
downright weird if they don't match each other statically.  If you want other
analogies, the properties of a composite type change when more information is
learned about the component type.  See 7.3(3/3).  But my main claim is that this
is not a property of the access type at all.  It is a property of the designated
type, and you can use whatever you know about the designated type, even if it is
"more" than is known where the access type is declared.

You mention access-to-incomplete -- that seems a perfect example of this.
Anywhere you can see the completion of the incomplete type, you can use that
information, no matter where the access-to-incomplete type is declared.  Yes we
have extra wording to that effect in 3.10.1(2.4), but that wording is not saying
anything profound.  We just had to be careful because of the oddities associated
with limited with's.  There are no such subtleties for other properties relating
to designated types.

> For a counter-example, access-to-incomplete types are always
> considered that during their full lifetime - that does not change
> because of visibility. We have special rules that say that they are
> treated as complete when the completion of the incomplete type is available.
> (See 3.10.1(2.2/2-2.6/3)).
>
> We've got rules defining that characteristics behave this way, but
> whether a type is constrained or not does not appear to be a
> characteristic -- at least its not mentioned in the list in 3.4(8/2).
>
> So I don't see any RM reason for your interpretation. Perhaps there is
> a usability one (although I think it would have to be fairly strong
> given the destruction of the model that types are defined by their
> definition, which we adhere to despite the often nonsense results that one gets).

Well it sounds like an AI would be helpful to clarify this, but for me you are
inappropriately associating a property of the designated type with the access
type.  The properties of the designated type change as you learn more about the
designated type.  The particular access type involved is somewhat irrelevant, as
far as I am concerned, and especially as far as static matching is concerned.

****************************************************************

From: Randy Brukardt
Sent: Monday, July 14, 2014  8:29 PM

> But this is not a property of the access type, it is a property of the
> designated type.
> Furthermore, these are exactly the *same* type, so it is downright
> weird if they don't match each other statically.

They're the same type but different views of that type. They don't necessarily
have to match (certainly different subtypes of a type don't have to match). But
I do agree that a user would find it weird if they didn't match (this I hadn't
previously noticed).

> If you want other analogies, the properties of a composite type change
> when more information is learned about the component type.  See
> 7.3(3/3).

Um, that's the syntax for a private extension.

You probably meant 7.3.1(3/3), which is of course the "characteristics" rule
that I referred to. The problem being that whether or not a type is constrained
doesn't appear to be a "characteristic" (these are defined in 3.4(8/2). Perhaps
it should be.

> But my main claim is that
> this is not a property of the access type at all.  It is a property of
> the designated type, and you can use whatever you know about the
> designated type, even if it is "more" than is known where the access
> type is declared.

Even if it is, it doesn't appear to be a "characteristic" that appears when you
have more visibility.

> You mention access-to-incomplete -- that seems a perfect example of
> this.  Anywhere you can see the completion of the incomplete type, you
> can use that information, no matter where the access-to-incomplete
> type is declared.  Yes we have extra wording to that effect in
> 3.10.1(2.4), but that wording is not saying anything profound.  We
> just had to be careful because of the oddities associated with limited
> with's.
> There are no such subtleties for other properties relating to
> designated types.

Harmph. You seem to have conveniently forgotten about all of the problems with
"additional characteristics", especially in generics. I'd say there's a pile of
subtleties for other properties (including which properties are in fact
included). I know there's quite a pile of ACATS tests on these weird cases (and
I'd probably be strung up by implementers if I created any more :-).

...
> Well it sounds like an AI would be helpful to clarify this, but for me
> you are inappropriately associating a property of the designated type
> with the access type.  The properties of the designated type change as
> you learn more about the designated type.  The particular access type
> involved is somewhat irrelevant, as far as I am concerned, and
> especially as far as static matching is concerned.

It's pretty clear to me that we're statically matching the private view (which
is what the access type designates) to the full view (which is what the generic
has for an actual). The view designated by an access type never changes! The
question is whether the "characteristics" (the only things that rely on
visibility) include everything needed for static matching. It's certainly true
that the private view has more characteristics at the point of this instance
than it does at the point of the declaration of the access type, but does it
have enough for static matching? Static matching is quite a bit tougher than
simple type matching, after all.

We could simply say that they statically match, but that seems dangerous if
there is any way for a visibility hole to be involved (that is, a case where
both the partial and full views are visible but the relationship between them is
not visible). [I can't think of one off-hand, but there are so many ways to
create those that I can't convince myself that it is impossible.] And of course
we'd have to be careful that other subtypes don't get sucked into such a special
rule.

****************************************************************

From: Tucker Taft
Sent: Friday, June 26, 2015  5:21 PM

I believe we should add (something like) the following, somewhere or other in
the standard, to resolve AI12-0140:

The *designated subtype* of (a view of) an access type at a given point is
determined by the view of the designated subtype that is visible at that point,
except in the case where the designated subtype denoted an incomplete view at
the point of the declaration of the access type, and the incomplete view was
part of a limited view of a package. In that case, the designated subtype of
(a view of) the access type remains this incomplete view at all points that
are not within the scope of a nonlimited with clause for the package in which
the type is declared. Within the scope of such a nonlimited with clause, the
more general rule applies.

****************************************************************

From: Tucker Taft
Sent: Friday, June 26, 2015  5:27 PM

This might allow us also to remove that complex wording relating to the type of
a dereference of an access-to-incomplete type.

****************************************************************

From: Bob Duff
Sent: Friday, June 26, 2015  8:12 PM

> The *designated subtype* of (a view of) an access type at a given
> point is determined by the view of the designated subtype that is
> visible at that point, except in the case where the designated subtype
> denoted an incomplete view at the point of the declaration of the
> access type, and the incomplete view was part of a limited view of a
> package.  In that case, the designated subtype of (a view of) the
> access type remains this incomplete view at all points that are not
> within the scope of a nonlimited with clause for the package in which the
> type is declared.  Within the scope of such a nonlimited with clause, the
> more general rule applies.

"place".

****************************************************************

From: Randy Brukardt
Sent: Wednesday, July 8, 2015  7:18 PM

You mentioned this when we were discussing AI12-0003-1 (January 31, 2015);
I researched it and found that there were 20 normative references to "at
the place of" and more than 18 normative references to "at the point of" (I
stopped counting at that point, er place ;-). As such, either is fine, and
there doesn't seem to be anything to recommend one over the other.

****************************************************************

From: Bob Duff
Sent: Wednesday, July 8, 2015  9:10 PM

> > "place".
>
> You mentioned this when we were discussing AI12-0003-1 (January 31,
> 2015); I researched it and found that there were 20 normative
> references to "at the place of" and more than 18 normative references
> to "at the point of" (I stopped counting at that point, er place ;-).
> As such, either is fine, and there doesn't seem to be anything to recommend
> either.

I just looked at RM-83, chapter 8, and it has several places that use "point"
in that sense (surprisingly, to me).  So I concede: You were right, I was
wrong.  I shall attempt to remember to quit harping on this point.

****************************************************************

From: Randy Brukardt
Sent: Wednesday, July 8, 2015  7:51 PM

> The *designated subtype* of (a view of) an access type at a given
> point is determined by the view of the designated subtype that is
> visible at that point, except in the case where the designated subtype
> denoted an incomplete view at the point of the declaration of the
> access type, and the incomplete view was part of a limited view of a
> package.  In that case, the designated subtype of (a view of) the
> access type remains this incomplete view at all points that are not
> within the scope of a nonlimited with clause for the package in which
> the type is declared.  Within the scope of such a nonlimited with
> clause, the more general rule applies.

I think this would make more sense if it talked about the "view of the
designated subtype", since the designated subtype itself is surely determined
solely by the declaration (as defined in 3.10(10)). And it seems to be a
tautology that the designated subtype is determined by the view of the
designated subtype (duh!), which is what it currently says. Maybe it would be
better to start:

   The view of the designated subtype of (a view of) an access type at a given
   point is the view of the designated subtype that is visible at that point,
   except in the case ...

I think we have to be clearer than "visible at that point"; I'm not sure what
kind of visibility you're talking about here.

I'd also worry that this sort of rule would introduce a ripple effect (after
all, the reason that we have the complex incomplete rules is to avoid a ripple
effect). Since this is intended to fix issues with static matching (coming from
confusion about what view an access type uses), one could potentially get a
ripple effect anywhere that static matching is required on a designated partial
view. When we get a full proposal for this wording, I'll try to see if there is
a problem there (it could be FUD).

****************************************************************

From: Tucker Taft
Sent: Wednesday, July 8, 2015  8:09 PM

> I think this would make more sense if it talked about the "view of the
> designated subtype", since the designated subtype itself is surely
> determined solely by the declaration (as defined in 3.10(10)). And it
> seems to be a tautology that the designated subtype is determined by
> the view of the designated subtype (duh!), which is what it currently
> says. Maybe it would be better to start:
>
>     The view of the designated subtype of (a view of) an access type
>     at a given point is the view of the designated
>     subtype that is visible at that point, except in the case ...

Yes, that seems like a useful fix.

> I think we have to be clearer than "visible at that point"; I'm not
> sure what kind of visibility you're talking about here.

I don't see the ambiguity.  When you say "visible at a point" (or place)
that means exactly one thing, which is defined in in 8.3(14), saying that
"a declaration is visible everywhere within its scope, except where hidden
from *all* visibility."

> I'd also worry that this sort of rule would introduce a ripple effect
> (after all, the reason that we have the complex incomplete rules is to
> avoid a ripple effect). Since this is intended to fix issues with
> static matching (coming from confusion about what view an access type
> uses), one could potentially get a ripple effect anywhere that static
> matching is required on a designated partial view. When we get a full
> proposal for this wording, I'll try to see if there is a problem there (it could be FUD).

I don't believe this should be a concern.  It is only the
incomplete-in-limited-view types that are affected by the presence of
"with" clauses (and hence susceptible to "ripple" effects), and we make a
special exception for those.  All others require being inside the scope of the
full type to have any additional visibility.

****************************************************************

From: Randy Brukardt
Sent: Wednesday, July 8, 2015  8:52 PM

...
> > I think we have to be clearer than "visible at that point"; I'm not
> > sure what kind of visibility you're talking about here.
>
> I don't see the ambiguity.  When you say "visible at a point"
> (or place) that means exactly one thing, which is defined in
> in 8.3(14), saying that "a declaration is visible everywhere
> within its scope, except where hidden from *all* visibility."

Whenever I read "visible", I think "directly visible". And then spend some time
wondering if that was meant or something else. It's unfortunate that there's
no prefix for the 8.3(14) meaning of "visible", because it's not the intuitive
meaning of "visible". But I agree its consistent with the RM wording, so it's
probably just me that is confused (every time, even though I've been doing this
for decades and vaguely know that it doesn't mean what it seems to mean).

> > I'd also worry that this sort of rule would introduce a ripple effect
> > (after all, the reason that we have the complex incomplete rules is to
> > avoid a ripple effect). Since this is intended to fix issues with
> > static matching (coming from confusion about what view an access type
> > uses), one could potentially get a ripple effect anywhere that static
> > matching is required on a designated partial view. When we get a full
> > proposal for this wording, I'll try to see if there is a problem there (it
> > could be FUD).
>
> I don't believe this should be a concern.  It is only the
> incomplete-in-limited-view types that are affected by the
> presence of "with" clauses (and hence susceptible to "ripple"
> effects), and we make a special exception for those.  All
> others require being inside the scope of the full type to
> have any additional visibility.

You might be right. My thought was that the "scope" of something includes units
where it is "withed", so there is potential for trouble (especially if
something is exported and then imported back into the subsystem). But I'll have
to work out an example to know one way or another, and since my budget for this
FY is exhausted, I'll do that once I get a new budget. (I'm only doing critical
tasks -- mainly the meeting minutes -- now.)

****************************************************************

From: Bob Duff
Sent: Wednesday, July 8, 2015  9:15 PM

> Whenever I read "visible", I think "directly visible". ...

I have the same problem.  Ada 83 had "direct visibility" and "visibility by
selection".  Tucker renamed the latter to just plain "visibility".
I see why that makes sense, but it still trips me up from time to time.

****************************************************************

From: Tucker Taft
Sent: Saturday, June 4, 2016  7:58 PM

Here is a re-write of AI12-0140, to make a more general statement that the view
of the designated subtype of an access type is determined by the place where the
access type is *used* rather than where the access type is declared, except for
the weird rules for access-to-incomplete-view-from-limited-view-of-package.
[This is version /03 of the AI - Ed.]

****************************************************************


Questions? Ask the ACAA Technical Agent