Version 1.10 of ais/ai-00231.txt

Unformatted version of ais/ai-00231.txt version 1.10
Other versions for file ais/ai-00231.txt

!standard 3.10 (06)          03-09-27 AI95-00231/05
!standard 3.10 (12)
!standard 4.6 (49)
!standard 8.6 (25)
!class amendment 00-04-13
!status work item 00-04-13
!status received 00-04-13
!priority Medium
!difficulty Hard
!subject Access-to-constant parameters and null-excluding access subtypes
!summary
Parameters and discriminants of an anonymous access-to-constant type are introduced. Non-controlling access parameters and access discriminants are changed to allow having a null value by default, but allow null to be excluded explicitly. Null-excluding subtypes of a named access type are introduced.
!problem
(See discussion.)
!proposal
Change non-controlling access parameters and access discriminants to allow them to have null values.
Introduce a "null exclusion," ("not null") and allow it on subtype indications, access type definitions, and access definitions. We don't call it a "constraint" because doing so creates various wording issues relating to "constrained" versus "unconstrained."
Generalize access_definition to allow specification of access-to-constant, and a null exclusion.
!wording
Replace paragraph 3.2.2(3) with:
subtype_indication ::= [null_exclusion] subtype_mark [scalar_constraint | composite_constraint]
Delete paragraph 3.2.2(5).
Modify 3.10(2) to:
access_type_definition ::= [null_exclusion] access_to_object_definition | [null_exclusion] access_to_subprogram_definition
Modify 3.10(6) to:
null_exclusion ::= not null
access_definition ::= [null_exclusion] access general_access_modifier subtype_mark
Modify 3.10(12) to:
An access_definition defines an anonymous general access type; the subtype mark denotes its @i<designated subtype>. If the word @b<constant> appears, the type is an access-to-constant type; otherwise it is an access-to-variable type. If a null_exclusion is present, or the access_definition is for a controlling access parameter (see 3.9.2), the access_definition defines an access subtype which excludes the null value; otherwise the subtype includes a null value. An access_definition is used in the specification of an access discriminant (see 3.7) or an access parameter (see 6.1). [NOTE: Drop this last sentence or make it cover all uses of access_definition if AI-230 is approved.]
Drop the parenthetical "(named)" from the first sentence of 3.10(13), since in our new model, anonymous access types have a null value, even though a subtype might exclude the null value. Drop the "named" from the last sentence of 3.10(13) as well, since anonymous access types can have allocators.
Add the following sentence to the end of 3.10(14):
The first subtype of a type defined by an access_type_definition excludes the null value if a null_exclusion is present; otherwise, the first subtype includes the null value.
Modify 3.10(15) as follows:
A composite_constraint is compatible with an unconstrained access subtype if it is compatible with the designated subtype. {A null_exclusion is compatible with an access subtype if the subtype includes a null value.} An access value satisfies a composite_constraint of an access subtype if it equals the null value of its type or if it designates an object whose value satisfies the constraint. {An access value satisifes a null_exclusion imposed on an access subtype if it does not equal the null value of its type.}
Delete paragraph 4.1.4(7) which says that anonymous access types don't have a null value.
Modify 4.6(49) to:
If the target subtype excludes the null value, then a check is made that the value of the operand is not null; if the target subtype includes null, then the result of the conversion is null if the operand value is null.
Modify 8.6(25) so that implicit conversion to any anonymous access type is permitted, with the expected rules (i.e. it is illegal to convert an access-to-constant to access-to-variable).
!example
type Non_Null_Ptr is not null access T;
procedure Show(X : Non_Null_Ptr); -- X guaranteed to not be null
procedure Pass_By_Ref(Y : not null access constant Rec); -- Pass Y by reference, but don't allow it to be updated; -- Guarantee Y is non-null.
procedure Display(W : access Window; G : access constant Graph'Class); -- Allow any pointer to a graph to be passed to the window -- display routine; allow null to be passed as well.
!discussion
It is surprising that an access-to-constant parameter/discriminant is not available. There are several circumstances where such a parameter/discriminant would be appropriate:
As a controlling parameter of an operation that doesn't modify the
designated object.
As a way to force pass-by-reference when interfacing with a foreign
language, when the external operation does not update the designated object,
As a way to provide read-only access via a discriminant.
The rule disallowing "null" for access parameters and access discriminants has turned out to be confusing, and not what is wanted in all cases when interfacing with a foreign language. Therefore, we propose to define an explicit way to exclude nulls from an access subtype, and make "access T" and "access constant T" include nulls by default when not a controlling parameter, even though this does not preserve complete upward compatibility. Note that the only incompatibility is for cases where null was passed, and these would have been rejected at compile-time or have raised Constraint_Error. It was felt it was better to have this upward incompatibility than to have the default be null-excluding for "access T" but not null-excluding for "access constant T". Note that there is no upward incompatibility for controlling access parameters; they always have null-excluding subtypes. Any worrisome loss of efficiency due to allowing null for non-controlling access parameters, or access discriminants, can be reversed by using an explicity not_null_constraint.
The general ability to specify an access subtype that excludes null for both named and anonymous access types can provide useful documentation and higher efficiency. This is especially true for parameters, by allowing the nullness check to be "pushed" to the caller, where it can be more likely removed.
What should be the default initialization of an object of a subtype that excludes null? It seems clear that the default is still null, and the initialization will raise Constraint_Error. Hence, objects of such a subtype will require explicit initialization. Perhaps a NOTE to this effect should be included in 3.10.
Note that the "all" in an access_definition is redundant, since anonymous access types are always considered "general" access types. However, it was felt more confusing to disallow use of "all" for anonymous access types, even though it has no effect.
!appendix

Randy Brukardt  00-04-13

This proposal was split out of the "with type" proposal (AI-00217) in
April 2000. Some early conversation on this feature can be found in that
AI's appendix.

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

!topic Missing change in AI95-00231
!reference AI95-00231, RM95 6.1(24)
!from Adam Beneschan 09-30-02
!discussion

Nitpick du jour:

I just noticed AI95-00231, which proposes that, among other things,
ACCESS CONSTANT be allowed as a subprogram access parameter.  It
appears that in the list of RM changes for this AI, 6.1(24) was
missed.  This paragraph includes the sentence:

   "An access parameter is of an anonymous general access-to-variable
   type (see 3.10)."

which will no longer be true since the access parameter could now be
an access-to-constant type.

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

From: Dan Eilers
Sent: Friday, January 17, 2003  2:41 PM

AI-231 proposes the syntax:

    not_null_constraint ::= NOT NULL

for null-excluding subtypes of a named access type.

I propose generalizing this to allow value-excluding subtypes
of other named types, serving the same purpose:

> The general ability to specify an access subtype that excludes null for both
> named and anonymous access types can provide useful documentation and higher
> efficiency. This is especially true for parameters, by allowing the nullness
> check to be "pushed" to the caller, where it can be more likely removed.

The same principle applies to the division-by-zero check.

   not_constraint ::= NOT NULL
   not_constraint ::= NOT 0
   not_constraint ::= NOT 0.0
   not_constraint ::= NOT Friday

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

From: Robert Dewar
Sent: Sunday, January 19, 2003  8:42 AM

While I am a little sympathetic to the non-null access type proposal, I
find Dan's proposal for extending it definitely inappropriate. It sounds
like a lot of extra work to specify and implement.

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

From: Tucker Taft
Sent: Tuesday, May 6, 2003  2:49 PM

During the AdaUK Ada 200Y workshop, Franco Gasperoni made a good
suggestion.  He felt it will be too confusing to make "access T" mean "access
all T not null" (I think others have made this point as well).

Why not just change the semantics of "access T" to allow null (though
when used as a controlling operand, there will be a run-time
check for non-null), so that "access all T" and "access T" are
synonyms.  This will be upward compatible for programs that
don't raise Constraint_Error, and the slight potential
performance degradation when the non-null aspect of access T was
important can be made up for by using "not null" explicitly.

This seems like a reasonable suggestion, and is probably one
we have debated in the past, and just were perhaps worried
about the compatibility issue.  But in fact, I suspect this
is the kind of thing that may fix more bugs that it creates.
Most uses of anon access types are for controlling operands,
and those will see no change.  The other uses often discover
a need to pass "null" eventually, and then have to switch
to a named access type, or play some other game.

Certainly when interfacing with C or Java, an "access T" that allows
null will be more useful.  And altough we could say that
"access T" is just a convenient shorthand for "access all T not null"
it does seem like a recipe for confusion when teaching Ada 200Y.

It seems like if the non-null aspect of an access parameter is
important, users will welcome the chance to say "not null" explicitly.

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

From: John Barnes
Sent: Thursday, May 8, 2003  1:28 AM

Good idea..  I always hated the potential confusion as it was.

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

From: Gary Dismukes
Sent: Tuesday, May 13, 2003  6:33 AM

I agree that this seems like a sensible change with minimal disadvantages.

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

From: Robert A Duff
Sent: Thursday, May 8, 2003  7:34 AM

Me, three.

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

From: Randy Brukardt
Sent: Saturday, September 27, 2003  6:15 PM

In the appendix of AI-231, I see a note from Adam Beneschan that 6.1(24) will
need to be changed (because it says "access-to-variable"). I think the AI needs
to include that, right?

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

From: Randy Brukardt
Sent: Saturday, September 27, 2003  6:17 PM

3.7(9) has the same wording, and will need a similar fix.

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

From: Tucker Taft
Sent: Sunday, September 28, 2003  9:09 AM

Good point.  Can you make those fixes, or do
you want another version from me?

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

From: Randy Brukardt
Sent: Monday, September 29, 2003  6:02 PM

The wording change isn't instantly obvious, so I think I'd prefer a new
version from you.

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


Questions? Ask the ACAA Technical Agent