Version 1.9 of ais/ai-00423.txt

Unformatted version of ais/ai-00423.txt version 1.9
Other versions for file ais/ai-00423.txt

!standard 8.5.1(2)          05-09-29 AI95-00423/07
!standard 8.5.1(4)
!standard 8.5.4(4)
!standard 12.4(2)
!standard 12.4(5)
!standard 12.4(7)
!standard 12.4(9)
!standard 12.6(8)
!class amendment 05-03-30
!status Amendment 200Y 05-05-10
!status ARG Approved 9-0-1 05-04-18
!status work item 05-03-30
!status received 05-03-30
!priority High
!difficulty Easy
!subject Renaming, null exclusion and formal objects
!summary
(See proposal.)
!problem
At the Paris meeting, we came up with strangely inconsistent decisions regarding the interaction of "not null" with renamings:
1 - For object renamings, we said that "not null" is not permitted under any circumstances in the access_definition of the object_renaming_definition. (AI95-00409)
2 - For subprogram renamings, we said that "not null" is permitted, but is essentially ignored (like any subtype-ish property). (AI95-00404)
!proposal
It is clear that we want object renamings and subprogram renamings to be handled consistently. However, the rules outlined in the !problem section are not ideal because:
1 - Disallowing "not null" (the AI95-00409 option) has the peculiar consequence that it prevents the user from "telling the truth", something that we try to encourage. Consider:
X : not null access Integer := ...; Y : access Integer renames X;
while Y is really of a null-excluding subtype, the user cannot write an explicit null exclusion. This is unfortunate, as we would like them to be able to put the "correct subtype" here.
2 - Allowing "not null" but ignoring it (the AI95-00405 option) is the Ada 83 model, but it is generally considered undesirable. If it had not be for compatibility, modifying the rules in Ada 95 to rely on the notion of statically matching subtypes would have been best. Since null exclusion does not create any compatibility issue, it seems that we should "do the right thing".
An alternative would be to always require the null_exclusion to match exactly. We already do that for formal access types, so it would seem to be possible. But it would cause anomolies with formal private types:
generic type T is private; with procedure P (A : T); X : in out T; procedure G is ...
type A is access ...; procedure Q (P : not null A); Obj : not null A; procedure Goof is new G (T => A, P => Q, X => Obj); -- Illegal by exact rule.
This is annoying, because there is no way to change the specification of the generic to allow this to work (T is not an access type, so it doesn't allow a null exclusion).
So, the best approach seems to be to allow the user to write an explicit null_exclusion in object and subprogram renamings, but only if such a null_exclusion doesn't lie.
Similar rules should apply to generic subprograms.
In generic bodies we use an assume-the-worst rule to ensure that "not null" doesn't lie.
Finally, it is curious that anonymous access types are not permitted for generic formal objects. This is likely to make it unnecessarily hard to turn a nongeneric package into a generic package. This restriction is lifted.
!wording
Change 8.5.1(2):
object_renaming_declaration ::= defining_identifier : [null_exclusion] subtype_mark renames object_name; | defining_identifier : access_definition renames object_name;
Remove the syntax rule added by AI95-00409 after 8.5.1(2/2) (that's the one which makes a null_exclusion illegal).
Add after 8.5.1(4):
For an object_renaming_declaration with a null_exclusion or an access_definition that has a null_exclusion:
o if the object_renaming_declaration occurs within the body of a generic unit
G or within the body of a generic unit declared within the declarative region of the generic unit G, and the object_name denotes a generic formal object of G, then the declaration of that formal object shall have a null_exclusion;
o otherwise, the subtype of the object_name shall exclude null. In addition to
the places where Legality Rules normally apply (see 12.3), this rule applies also in the private part of an instance of a generic unit.
Add after 8.5.4(4):
For a parameter or result subtype of the subprogram_specification that has an explicit null_exclusion:
o if the subprogram_renaming_declaration occurs within the body of a generic
unit G or within the body of a generic unit declared within the declarative region of the generic unit G, and the callable_entity_name denotes a generic formal subprogram of G, then the corresponding parameter or result subtype of that formal subprogram shall have a null_exclusion;
o otherwise, the subtype of the corresponding parameter or result type of the
renamed callable entity shall exclude null. In addition to the places where Legality Rules normally apply (see 12.3), this rule applies also in the private part of an instance of a generic unit.
Change 12.4(2) to read:
formal_object_declaration ::= defining_identifier_list : mode [null_exclusion] subtype_mark [:= default_expression]; | defining_identifier_list : mode access_definition [:= default_expression];
Change 12.4(5) to read:
For a generic formal object of mode in out, the type of the actual shall resolve to the type determined by the subtype_mark, or for a formal_object_declaration with an access_definition, to a specific anonymous access type. If the anonymous access type is an access-to-object type, the type of the actual shall have the same designated type as that of the access_definition. If the anonymous access type is an access-to-subprogram type, the type of the actual shall have a designated profile which is type conformant with that of the access_definition.
Add after 12.4(7):
In the case where the type of the formal is defined by an access_definition, the type of the actual and the type of the formal:
o shall both be access-to-object types with statically matching designated
subtypes and with both or neither being access-to-constant types; or
o shall both be access-to-subprogram types with subtype conformant designated
profiles.
For a formal_object_declaration with a null_exclusion or an access_definition that has a null_exclusion:
o for an instantiation that occurs within the body of a generic unit G or
within the body of a generic unit declared within the declarative region of the generic unit G, and the actual denotes a generic formal object of G, then the declaration of that formal object shall have a null_exclusion;
o otherwise, the subtype of the actual shall exclude null. In addition to
the places where Legality Rules normally apply (see 12.3), this rule applies also in the private part of an instance of a generic unit.
Change 12.4(9) to read: (This includes the change from AI-255)
A formal_object_declaration declares a generic formal object. The default mode is in. For a formal object of mode in, the nominal subtype is the one denoted by the subtype_mark {or access_definition} in the declaration of the formal. For a formal object of mode in out, its type is determined by the subtype_mark {or access_definition} in the declaration; its nominal subtype is nonstatic, even if the subtype_mark denotes a static subtype; for a composite type, its nominal subtype is unconstrained if the first subtype of the type is unconstrained, even if the subtype_mark denotes a constrained subtype.
Add after 12.6(8):
For a parameter or result type of a formal_subprogram_declaration that has an explicit null_exclusion:
o for an instantiation that occurs within the body of a generic unit G or
within the body of a generic unit declared within the declarative region of the generic unit G, and the actual denotes a generic formal subprogram of G, then the corresponding parameter or result type of that formal subprogram shall have a null_exclusion;
o otherwise, the subtype of the corresponding parameter or result type of the
actual shall exclude null. In addition to the places where Legality Rules normally apply (see 12.3), this rule applies also in the private part of an instance of a generic unit.
!discussion
(See proposal.)
!example
!corrigendum 8.5.1(2)
Replace the paragraph:
object_renaming_declaration ::= defining_identifier : subtype_mark renames object_name;
by:
object_renaming_declaration ::= defining_identifier : [null_exclusion] subtype_mark renames object_name; | defining_identifier : access_definition renames object_name;
!corrigendum 8.5.1(4)
Insert after the paragraph:
The renamed entity shall be an object.
the new paragraphs:
For an object_renaming_declaration with a null_exclusion or an access_definition that has a null_exclusion:
!corrigendum 8.5.4(4)
Insert after the paragraph:
The profile of a renaming-as-declaration shall be mode-conformant with that of the renamed callable entity.
the new paragraphs:
For a parameter or result subtype of the subprogram_specification that has an explicit null_exclusion:
!corrigendum 12.4(2)
Replace the paragraph:
formal_object_declaration ::= defining_identifier_list : mode subtype_mark [:= default_expression]
by:
formal_object_declaration ::= defining_identifier_list : mode [null_exclusion] subtype_mark [:= default_expression] | defining_identifier_list : mode access_definition [:= default_expression];
!corrigendum 12.4(5)
Replace the paragraph:
For a generic formal object of mode in out, the type of the actual shall resolve to the type of the formal.
by:
For a generic formal object of mode in out, the type of the actual shall resolve to the type determined by the subtype_mark, or for a formal_object_declaration with an access_definition, to a specific anonymous access type. If the anonymous access type is an access-to-object type, the type of the actual shall have the same designated type as that of the access_definition. If the anonymous access type is an access-to-subprogram type, the type of the actual shall have a designated profile which is type conformant with that of the access_definition.
!corrigendum 12.4(7)
Insert after the paragraph:
For a generic formal object of mode in, the actual shall be an expression. For a generic formal object of mode in out, the actual shall be a name that denotes a variable for which renaming is allowed (see 8.5.1).
the new paragraphs:
In the case where the type of the formal is defined by an access_definition, the type of the actual and the type of the formal:
For a formal_object_declaration with a null_exclusion or an access_definition that has a null_exclusion:
!corrigendum 12.4(9)
Replace the paragraph:
A formal_object_declaration declares a generic formal object. The default mode is in. For a formal object of mode in, the nominal subtype is the one denoted by the subtype_mark in the declaration of the formal. For a formal object of mode in out, its type is determined by the subtype_mark in the declaration; its nominal subtype is nonstatic, even if the subtype_mark denotes a static subtype.
by:
A formal_object_declaration declares a generic formal object. The default mode is in. For a formal object of mode in, the nominal subtype is the one denoted by the subtype_mark or access_definition in the declaration of the formal. For a formal object of mode in out, its type is determined by the subtype_mark or access_definition in the declaration; its nominal subtype is nonstatic, even if the subtype_mark denotes a static subtype; for a composite type, its nominal subtype is unconstrained if the first subtype of the type is unconstrained, even if the subtype_mark denotes a constrained subtype.
!corrigendum 12.6(8)
Insert after the paragraph:
The profile of the formal and actual shall be mode-conformant.
the new paragraphs:
For a parameter or result subtype of a formal_subprogram_declaration that has an explicit null_exclusion:
!ACATS test
!appendix

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

From: Bob Duff
Sent: Saturday, June 11, 2005  9:50 PM

AARM version 1.19.

8.5.1(4.4/2):

4.3/2 {AI95-00423-01} For an object_renaming_declaration with a null_exclusion
or an access_definition that has a null_exclusion:

4.4/2 if the object_renaming_declaration occurs within the body of a generic
      unit or within the body of a generic unit declared within the
      declarative region of the generic unit, and the object_name denotes a
                            ^^^
      generic formal object of that generic unit, then the declaration of that
                               ^^^^
      formal object shall have a null_exclusion;

I find this completely mystifying.  I mean, how can you be "within the body of a
generic unit declared within the declarative region of the generic unit" without
simply being "within the body of a generic unit"?

What do "the" and "that" refer to, above?

I read the AARM example, and I am still not sure what this rule is
getting at.

Similar wording appears in 8.5.4(4.2/2):

4.2/2 if the subprogram_renaming_declaration occurs within the body of a
      generic unit or within the body of a generic unit declared within the
      declarative region of the generic unit, and the callable_entity_name
      denotes a generic formal subprogram of that generic unit, then the
      corresponding parameter or result type of that formal subprogram shall
      have a null_exclusion;

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

From: Pascal Leroy
Sent: Tuesday, June 14, 2005   1:34 AM

I agree that this sounds rather incomprehensible to me, and I believe that
it was extensively rewritten by Randy after the last meeting, so we'll
need to wait for his reply.  (Apparently he has mail problems because I
just got 6 messages from him in the last 2 minutes.)

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

From: Randy Brukardt
Sent: Tuesday, June 14, 2005   1:56 AM

Pascal writes:

> I agree that this sounds rather incomprehensible to me, and I believe that
> it was extensively rewritten by Randy after the last meeting, so we'll
> need to wait for his reply.  (Apparently he has mail problems because I
> just got 6 messages from him in the last 2 minutes.)

Naah, I'm very productive just before going home. :-)

Actually, I had a bad mail backup because of a mailing list (not one of
mine!) that started spewing messages every minute. It just got cleared out,
and all should be fine. Of course, I'm now going to bed.

One of those six messages ought to be the reply you're looking for - wrote
it 4 hours ago.

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

From: Randy Brukardt
Sent: Monday, June 13, 2005   9:36 PM

Bob is mystified:

> 8.5.1(4.4/2):
>
> 4.3/2 {AI95-00423-01} For an object_renaming_declaration with a
> null_exclusion
> or an access_definition that has a null_exclusion:
>
> 4.4/2 if the object_renaming_declaration occurs within the body
> of a generic
>       unit or within the body of a generic unit declared within the
>       declarative region of the generic unit, and the object_name
> denotes a
>                             ^^^
>       generic formal object of that generic unit, then the
> declaration of that
>                                ^^^^
>       formal object shall have a null_exclusion;
>
> I find this completely mystifying.  I mean, how can you be "within the body of a
> generic unit declared within the declarative region of the generic unit" without
> simply being "within the body of a generic unit"?

You could be in the child of a generic unit; the child can reference the
parent's formals. I even mentioned that in the AARM note:
"The rule is so complex because it has to apply to bodies of child generics
as well."

That is, if you had a generic child Inner (now you know why the parent was
called "Outer"):

generic
package Outer.Inner is
...
end Outer.Inner;

package body Outer.Inner is
  D : not null Acc_I renames Outer.B; -- Illegal.
end Outer.Inner;

> What do "the" and "that" refer to, above?

The generic unit that has the formal. The generic body may be different (if
it is a child, as above). This wording is copied from 3.10.2(32) (the
changed text), where we originally discovered this problem with
assume-the-worst rules.

> I read the AARM example, and I am still not sure what this rule is
> getting at.

The AARM example is trying to explain the need for the rule, not why it has
to be so complex.

> Similar wording appears in 8.5.4(4.2/2):
>
> 4.2/2 if the subprogram_renaming_declaration occurs within the body of a
>       generic unit or within the body of a generic unit declared within the
>       declarative region of the generic unit, and the callable_entity_name
>       denotes a generic formal subprogram of that generic unit, then the
>       corresponding parameter or result type of that formal subprogram shall
>       have a null_exclusion;

And in 3.10.2(32). There, the AARM note includes:
"Declared within the declarative region of the generic" is referring to
child and nested generic units.
Perhaps I have to add that to each rename AARM note?

If you want to try to reword this, be my guest. :-) We've tried several
times to make it better, but it seems to defy improvement. It's possible
that the adaption of the wording to renames could be improved, too. Ideas
welcome.

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

From: Randy Brukardt
Sent: Wednesday, June 15, 2005   8:39 PM

Nobody is trying to improve this wording, but no one likes it.

...

The usual way to fix such wording is to introduce a name for the unit, that
might help here because there are two different generic units involved.

4.4/2 if the object_renaming_declaration occurs within the body of a generic
       unit G or within the body of a generic unit declared within the
       declarative region of the generic unit G, and the object_name denotes a
       generic formal object of G, then the declaration of that
       formal object shall have a null_exclusion;

Does this help? (Presuming you already understand the issue with the child
units).

> > Similar wording appears in 8.5.4(4.2/2):
...

4.2/2 if the subprogram_renaming_declaration occurs within the body of a
      generic unit G or within the body of a generic unit declared within the
      declarative region of the generic unit G, and the callable_entity_name
      denotes a generic formal subprogram of G, then the
      corresponding parameter or result subtype of that formal subprogram shall
      have a null_exclusion;

Better?

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

From: Pascal Leroy
Sent: Thursday, June 16, 2005  10:25 AM

> 4.4/2 if the object_renaming_declaration occurs within the
> body of a generic
>        unit G or within the body of a generic unit declared within the
>        declarative region of the generic unit G, and the
> object_name denotes a
>        generic formal object of G, then the declaration of that
>        formal object shall have a null_exclusion;

I think it's much better.

> 4.2/2 if the subprogram_renaming_declaration occurs within
> the body of a
>       generic unit G or within the body of a generic unit
> declared within the
>       declarative region of the generic unit G, and the
> callable_entity_name
>       denotes a generic formal subprogram of G, then the
>       corresponding parameter or result subtype of that
> formal subprogram shall
>       have a null_exclusion;

Much better too.

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

Questions? Ask the ACAA Technical Agent