Version 1.29 of ais/ai-00230.txt

Unformatted version of ais/ai-00230.txt version 1.29
Other versions for file ais/ai-00230.txt

!standard 03.04.01(06)          05-11-30 AI95-00230/20
!standard 03.02.01(07)
!standard 03.02.01(08)
!standard 03.04.01(03)
!standard 03.04.01(10)
!standard 03.06(07)
!standard 03.06(22/1)
!standard 03.07(10)
!standard 03.07(27)
!standard 03.08(18/1)
!standard 03.10(12)
!standard 03.10(13)
!standard 03.10(17)
!standard 03.10.2(12)
!standard 03.10.2(34)
!standard 04.02(02)
!standard 04.02(07)
!standard 04.02(08)
!standard 04.05.02(07)
!standard 04.05.02(09)
!standard 04.06(13)
!standard 04.06(18)
!standard 04.06(49)
!standard 04.06(61)
!standard 08.05.01(02)
!standard 08.05.01(03)
!standard 08.05.01(06)
!standard 08.06(25)
!standard 13.7.2(25)
!standard 13.11(25)
!standard A.1(34)
!class amendment 00-04-13
!status Amendment 200Y 04-01-09
!status WG9 Approved 04-06-18
!status ARG Approved 8-0-4 03-12-12
!status work item 00-10-27
!status ARG Approved 10-0-0 03-10-03
!status work item 00-04-13
!status received 00-04-13
!priority Medium
!difficulty Hard
!subject Generalized use of anonymous access types
!summary
More general use of anonymous access types is proposed, to allow the flexibility of implicit conversion and run-time accessibility checking to be used in more contexts, including as components and in object renamings. A separate AI (AI-00325) investigates using anonymous access types as function result types.
NOTE: This AI is also related to AI-00231, which allows anonymous access types to be specified to be access-to-constant as opposed to access-to-variable, and to be either null-allowing or not null-allowing. Without null-allowing anonymous access types, anonymous access components are rather useless, so this proposal pretty much requires some version of AI-231 to be approved.
!problem
The goal of this proposal is to resolve a problem encountered when creating Ada packages to interface with code written in languages like Java, and in using various common object-oriented programming paradigms.
In Java and other OO languages, types that are references to a subclass are freely convertible to types that are references to a superclass. This implicit conversion, which is always safe, significantly reduces the need for explicit conversions when passing references as parameters.
With the current access type conversion rules in Ada 95, large numbers of explicit conversions are required. This obscures the explicit conversions that really do need attention, and makes the whole OO coding style seem more cumbersome in Ada than in other OO languages.
In addition to addressing the problem of minimizing unnecessary explicit-yet-safe conversions, there is the related problem of minimizing (named) "access type proliferation". This generally occurs when, for one reason or another, an access type is not defined at the point of the type declaration (e.g., with the existing "purity" rules, a pure package would never declare any access types). Ultimately, if they need an access type, users of the type end up declaring their own "personal" access type, creating yet more need for unnecessary conversions.
There are two important technical problems that need to be addressed by any solution:
Because Ada has local access types, there needs to be a way to remember the accessibility level of the object designated by a reference across certain operations, including possibly function return (see AI-00325).
Because Ada has multiple storage pools, it is important that an allocator of an anonymous access type allocates from an appropriate storage pool.
!proposal
The "access_definition" syntactic category (see 3.10(6); also see AI-00231) is permitted in more places than just as formal parameters and discriminants. In addition to the current places (parameters of mode in and discriminants of limited types) it is permitted in object renaming declarations, component definitions, and for discriminants of nonlimited types. The type associated with the type definition is an anonymous access type, which permits implicit conversions from other access types with appropriately compatible designated subtypes (as defined by 4.6(13-17)).
The accessibility level of an anonymous access type is determined at the time when the access_definition is elaborated. The general accessibility level "philosophy" is:
a) For an access object that cannot be altered during its lifetime (parameter of mode in, discriminant of a limited type), its level may be determined by the accessibility level of its initial value or enclosing object. In addition, a renaming inherits the accessibility level from the renamed/actual object.
b) For others (i.e. other kinds of components) the accessibility level must be determined by the level of its declaration. This is necessary to simplify implementation and to avoid dangling references when an access object is updated while being "viewed" at a deeper level than it truly is (which is always permitted by the current accessibility checking rules).
Applying this general philosophy to the specific cases means that for a renaming, the level is the same as the level of the type of the renamed object. For a component definition or a discriminant of a nonlimited type, the level is the same as that of the enclosing composite type. As in the current language, IN parameters take their level from the initial value, and discriminants of limited types take their level from the enclosing composite object (as opposed to enclosing type).
There is a special predefined equality (and matching inequality) operator declared in package Standard which requires at least one of the parameters to be of an anonymous access type, and the other to be convertible to that anonymous access type. This implies the addition of the type universal_access. Having added this type, it makes sense to change the literal NULL to be of this type as well, for symmetry with numeric literals, and to avoid the need for a preference rule in resolving the type of "null" when using the universal_access equality operators.
The storage pool to be used for an allocator of an anonymous access type is determined by the context in which it appears:
a) As the value for a parameter of mode in, an anonymous storage pool whose
storage is reclaimed when the subprogram returns;
b) As the initial value for a discriminant of a limited type, either:
i) the same storage pool as used for the enclosing object
if it is also created by an allocator, or
ii) an anonymous storage pool whose storage is
reclaimed when the enclosing object's scope ends.
c) As the initial value for a component other than a discriminant of
a limited type, a standard storage pool similar to that which would be used for a named access type declared at the same level as the enclosing composite type.
!wording
Delete "(including a parameter or a discriminant)" from 3.2.1(7).
Change 3.2.1(8) as follows:
A named type that is declared by a full_type_declaration, or an anonymous type that is defined by {an access_definition or} as part of declaring an object of the type, is called a full type. ...
Change 3.4.1(3) as follows:
Every type is either a specific type, a class-wide type, or a universal type. A specific type is one defined by a type_declaration, a formal_type_declaration, or a full type definition embedded in [a declaration for an object]{another construct}. Class-wide and universal types are implicitly defined, to act as representatives for an entire class of types, as follows:
Change 3.4.1(6) as follows:
Universal Types
Universal types are defined for (and belong to) the integer, real, [and] fixed point{, and access} classes, and are referred to in this standard as respectively, universal_integer, universal_real, [and] universal_fixed{, and universal_access}. These are analogous to class-wide types for these language-defined {elementary}[numeric] classes. As with class-wide types, if a formal parameter is of a universal type, then an actual parameter of any type in the corresponding class is acceptable. In addition, a value of a universal type (including an integer or real numeric_literal{, or the literal @b<null>}) is ``universal'' in that it is acceptable where some particular type in the class is expected (see 8.6).
Change 3.4.1(10) as follows:
... Similarly, the {numeric} universal types are defined to be descendants of the root types of their classes. ...
Change 3.6(7) as follows:
component_definition ::= [aliased] subtype_indication | access_definition
Change 3.6(22/1) to add "or access_definition":
... The elaboration of a component_definition in an array_type_definition consists of the elaboration of the subtype_indication {or access_definition}. ...
Eliminate paragraph 3.7(10) (which allows access discriminants only on limited types).
Change 3.7(27) as follows:
{For an access discriminant of a limited type, its} [An] access_definition is elaborated when the value of [a corresponding] {the} access discriminant is defined, either by evaluation of its default_expresssion or by elaboration of a discriminant_constraint. {For an access discriminant of a nonlimited type, its access_definition is elaborated when the full_type_declaration with the known_discriminant_part is elaborated.} The elaboration of an access_definition ...
Change paragraph 3.8(18/1) as follows:
... For the elaboration of a component_definition of a component_declaration or the discrete_subtype_definition of an entry_declaration for an entry family (see 9.5.2), {if the component subtype is defined by an access_definition or} if the constraint or range of the subtype_indication or discrete_subtype_definition is not a per-object constraint, then the {access_definition,} subtype_indication{,} or discrete_subtype_definition is elaborated. ...
Change 3.10(12) and 3.10(17) to eliminate the list of places where access_definition occurs. (In both cases, this text is not required, and listing four places (access discriminant, access parameter, component_definition, and object_renaming_declaration) is awkward. Besides, we don't use text to list where subtype_indication [for instance] is allowed.)
Modify 3.10(13) as follows:
For each [(named)] access type, {other than a specific anonymous access type,} there is [a literal null which has] a null access value designating no entity at all. The null value of [a named] {an} access type is the ... in the case of [a named] {an} access-to-object type, an allocator, which returns ...
Note: This allows allocators of anonymous access types (which was intended to be allowed in Ada 95, see 13.11(25)), and the literal null for universal_access. AI-231 expands this further.
Add the following paragraph before 3.10.2(12):
The accessibility level of the anonymous access type defined by an access_definition of an object_renaming_declaration is the same as that of the renamed view.
Change paragraph 3.10.2(12) as follows:
The accessibility level of the anonymous access type {of a component is that of the master that elaborated its access_definition. This is the same as the level of the type whose definition encloses the access_definition except in the case} of an access discriminant {specified for a limited type, in which case it} is the same as that of the containing object or associated constrained subtype.
AARM NOTE: For a type extension, for other than discriminants
of a limited type, the components inherited from the parent have the same accessibility as they did in the parent; those in the extension part have the accessibility determined by the scope where the type extension is declared. Similarly, the components of a derived untagged type other than discriminants of a limited type have the same accessibility as they did in the parent.
Change the end of the note 3.10.2(34) as follows:
... anonymous access types do not{, but they can use the predefined equality operators for universal_access} (see 4.5.2).
Delete paragraph 4.2(2).
Replace paragraph 4.2(7) by:
A literal null shall not be of a specific anonymous access type, since such types do not have a null value (see 3.10).
Note: AI-231 repeals this altogether.
Change paragraph 4.2(8) as follows:
... is of type universal_real. {The literal null is of type universal_access.}
Add the following after paragraph 4.5.2(7):
The following additional equality operators for the universal_access type are declared in package Standard for use with anonymous access types:
function "="(Left, Right : universal_access) return Boolean function "/="(Left, Right : universal_access) return Boolean
Add the following after paragraph 4.5.2(9):
Name Resolution Rules
At least one of the operands of the equality operators for universal_access shall be of a specific anonymous access type.
AARM Note: Universal access types do not count for the purposes of this rule. Otherwise, equality expressions like (X = null) would be ambiguous for normal access types.
Legality Rules
At least one of the operands of the equality operators for universal_access shall be of type universal_access, or both shall be of access-to-object types, or both shall be of access-to-subprogram types. Further: * When both are of access-to-object types, the
designated types shall be the same or one shall cover the other, and if the designated types are elementary or array types, then the designated subtypes shall statically match;
* When both are of access-to-subprogram types,
the designated profiles shall be subtype conformant.
Change paragraph 4.6(13) as follows:
{If the target type is universal_access, then the operand type shall be an access type.} If the target type is a general access{-to-object} type, then the operand type shall be {universal_access or} an access-to-object type. Further{, if the operand type is not universal_access}:
Add before 4.6(18):
If the target type is a pool-specific access-to-object type, then the operand type shall be universal_access.
Change paragraph 4.6(18) as follows:
If the target type is an access-to-subprogram type, then the operand type shall be {universal_access or} an access-to-subprogram type. Further{, if the operand type is not universal_access}:
Change paragraph 4.6(49) as follows:
* If the target type is a[n] {specific }anonymous access type, a check is made that the value of the operand is not null; if the target type is not a specific anonymous access type, then the result is null if the operand value is null.
Change paragraph 4.6(61) as follows:
22 A ramification of the overload resolution rules is that the operand of an (explicit) type_conversion cannot be [the literal null, ]an allocator, an aggregate, a string_literal, a character_literal, or an attribute_reference for an Access or Unchecked_Access attribute. Similarly, such an expression enclosed by parentheses is not allowed. A qualified_expression (see 4.7) can be used instead of such a type_conversion.
Change paragraph 8.5.1(2) as follows:
object_renaming_declaration ::= defining_identifier : subtype_mark renames object_name; | defining_identifier : access_definition renames object_name;
Change paragraph 8.5.1(3) as follows:
The type of the object_name shall resolve to the type determined by the subtype_mark{, or in the case where the type is defined by an access_definition, to a specific anonymous access type whose designated type is the same as that of the access_definition}.
NOTE: If AI-231 is adopted, then 8.5.1(4) should include a legality rule that requires the access_definition to be access-to-constant if and only if the renamed object is access-to-constant. This is type-specific information, which is included in a renaming declaration.
Change paragraph 8.5.1(6) as follows:
... any constraint implied by the subtype_mark {or access_definition} of the object_renaming_declaration is ignored.
Modify paragraph 8.6(25):
...when T is a[n] {specific} anonymous access type ...
Remove parenthetical remark from 13.7.2(5) [null has type universal_access now].
Replace paragraph 13.11(25) by:
The storage pool used for an allocator of an anonymous access type should be determined as follows:
* If the allocator is initializing an access discriminant of an object of a limited type, and the discriminant is itself a subcomponent of an object being created by an outer allocator, then the storage pool used for the outer allocator should also be used for the allocator initializing the access discriminant;
* For other access discriminants and access parameters, the storage pool should be created at the point of the allocator, and be reclaimed when the allocated object becomes inaccessible;
* Otherwise, a default storage pool should be created at the point where the anonymous access type is elaborated; such a storage pool need not support deallocation of individual objects.
AARM: Delete the first sentence of 13.11(17.c); it isn't true even in Ada 95.
Add after A.1(34):
-- The type universal_access is predefined. -- The following equality operators are predefined:
function "=" (Left, Right: universal_access) return Boolean; function "/=" (Left, Right: universal_access) return Boolean;
!example
type Obj is record M : Integer; Next : access Obj; end record;
procedure Make_Cycle(X : access Obj) is -- Create a circularly linked 2-element list Next : access Obj renames X.Next; begin Next := new Obj(M => 3, Next => X); -- X.Next.Next = X end Make_Cycle;
package P is -- illustrate various ways to use anonymous access types type T is ...
type Rec(D : access String := new String'("")) is record F : access T; -- in the absence of AI-231, will raise -- Constraint_Error if allowed to default initialize -- to null. G : access T'Class := new T; end record;
R : Rec := (D => new String'("Hello"), F => new T, G => new T);
Y : access String renames R.D;
function Fun(X : access Rec) return Integer;
end P;
package body P is function Fun(X : access Rec) return Integer Disc : access String renames X.D; begin return 123; end Fun; end P;
!discussion
In an object-oriented program, it is desirable to be able to use any descendant of a root type in a context that only depends on the properties of the root type. This principle is sometimes called "substitutability".
This is supported in Ada 95 by use of T'Class as a parameter type. However, access types are used heavily in object-oriented systems, because of the unknown size requirements when dealing with a type hierarchy. The parameter notation "access T'Class" supports access type substitutability, but only for parameters. Furthermore, it doesn't handle potentially null values. Finally, it cannot be used for record or array components (other than access discriminants). [Note that the "null value" problem is solved in AI-231. We will make no further mention of this problem; see AI-231 for more discussion of this issue.]
Explicit access type conversions can be used to provide the desired substitutability, but scattering type conversions around muddies the water, and makes it harder to find the few type conversions that are really significant.
This AI proposes the generalization of the use of anonymous access types, as declared by an access_definition. It avoids any incompatibility issues by not changing the implicit conversion rules for existing named access types.
This proposal grew out of a long discussion about the difficulties associated with a "with access type" mechanism (originally part of AI-00217). The problems encountered relate to issues such as "thin" versus "fat" access-to-array types, conventions associated with access types, access subtypes, etc. Furthermore, Erhard Ploedereder reported significant concerns among his students with the excessive numbers of explicit conversions required to use Ada 95. This happens when an actual parameter is of type access-to-T2'Class, and the formal parameter is of type access-to-T1'Class.
This problem could be solved by allowing implicit conversion only to access-to-class-wide types. However, the current access-type conversion rules are based more on the general vs. pool-specific distinction. Also, the mutually-recursive type problem need not involve tagged types at all. It would seem unnatural to require the use of tagged and class-wide types just to get the implicit conversion on named general access types that is already available for all anonymous general access types.
We propose allowing anonymous access types in object renamings, discriminants of non-limited types, and component definitions. We handle updatable components by specifying that their accessibility level is determined by the enclosing composite type. This provides the advantages of implicit conversion, without needing run-time accessibility levels for individual components.
We have split out issues relating to anonymous function result types into a separate AI-00325, so this one can be evaluated without getting bogged down in the implementation issues associated with function returns.
Similarly, issues relating to supporting access-to-constant and null-allowing anonymous access types are in AI-00231.
IMPLEMENTATION ISSUES:
Object renaming declarations with access_definitions are no harder to support than other renamings.
Component declarations with access_definitions have no special accessibility level issues, because the level is determined just like a named access type.
OTHER ALTERNATIVES CONSIDERED:
There was much discussion about something like "T'Access" being an implicitly declared access type, similar to T'Class and T'Base, associated with every type T. There was also investigation into a restricted version of that in the form of T'Class_Access, which would be an implicitly declared access-to-T'Class. The latter was rejected as being too limiting, since access type proliferation occurs with non-tagged types as well.
The more general version of T'Access was dropped because:
a) we already have anonymous access types, so it is not clear we need two different notations for them.
b) AI-00231 includes proposals to allow access-to-constant and null-allowing and non-null-allowing anonymous access types in the existing contexts (on parameters and discriminants), and crafting attribute identifiers to handle all combinations of these capabilities would seem to be unwise. The access-to-constant capability seems even more important for the wider usage we are considering in this proposal.
c) The accessibility level of T'Access was presumed to be the same as that of T. This could be limiting in various ways, and in particular you couldn't safely convert to T'Access from some potentially local access type.
d) Implementations which materialize all implicit types would have problems, as there is no limit to the types that could be constructed (T'Access'Access, T'Access'Access'Access, etc.)
We considered allowing anonymous access types in stand-alone variable declarations. However the general philosophy for accessibility levels (described above in the proposal section) would force them to have a level determined by their declaration rather than initial value. This might create confusion when copying an access parameter into a local variable and unintentionally losing the accessibility level information. By only allowing renamings, and having them preserve the accessibility level information, we avoid this possible problem. Because allowing constants but not variables introduced a non-orthogonality, we chose to allow renamings which can be used in most cases where a constant would have been useful.
As an alternative, we considered allowing variables of an anonymous access type to carry run-time accessibility levels across assignment statements with an accompanying accessibility check as well to handle up-level assignments. But this would totally change the model, since in all other cases we have fully determined the accessibility level at the point of the elaboration of the anonymous access type.
We also considered allowing generic formal objects of an anonymous access type. However, this adds significantly to the complexity of the proposal, with relatively little added benefit. Just supporting it for in mode formal objects would be feasible, as it would be nearly identical to the support required for in, but this would again not be consistent.
We have decided not to allow named subtypes of anonymous access types, because they seemed to create more problems than they solved, and are not needed if we allow anonymous access types in component declarations.
!corrigendum 3.2.1(7)
Replace the paragraph:
A type defined by a type_declaration is a named type; such a type has one or more nameable subtypes. Certain other forms of declaration also include type definitions as part of the declaration for an object (including a parameter or a discriminant). The type defined by such a declaration is anonymous — it has no nameable subtypes. For explanatory purposes, this International Standard sometimes refers to an anonymous type by a pseudo-name, written in italics, and uses such pseudo-names at places where the syntax normally requires an identifier. For a named type whose first subtype is T, this International Standard sometimes refers to the type of T as simply "the type T."
by:
A type defined by a type_declaration is a named type; such a type has one or more nameable subtypes. Certain other forms of declaration also include type definitions as part of the declaration for an object. The type defined by such a declaration is anonymous — it has no nameable subtypes. For explanatory purposes, this International Standard sometimes refers to an anonymous type by a pseudo-name, written in italics, and uses such pseudo-names at places where the syntax normally requires an identifier. For a named type whose first subtype is T, this International Standard sometimes refers to the type of T as simply "the type T".
!corrigendum 3.2.1(8)
Replace the paragraph:
A named type that is declared by a full_type_declaration, or an anonymous type that is defined as part of declaring an object of the type, is called a full type. The type_definition, task_definition, protected_definition, or access_definition that defines a full type is called a full type definition. Types declared by other forms of type_declaration are not separate types; they are partial or incomplete views of some full type.
by:
A named type that is declared by a full_type_declaration, or an anonymous type that is defined by an access_deinition or as part of declaring an object of the type, is called a full type. The type_definition, task_definition, protected_definition, or access_definition that defines a full type is called a full type definition. Types declared by other forms of type_declaration are not separate types; they are partial or incomplete views of some full type.
!corrigendum 3.4.1(3)
Replace the paragraph:
Every type is either a specific type, a class-wide type, or a universal type. A specific type is one defined by a type_declaration, a formal_type_declaration, or a full type definition embedded in a declaration for an object. Class-wide and universal types are implicitly defined, to act as representatives for an entire class of types, as follows:
by:
Every type is either a specific type, a class-wide type, or a universal type. A specific type is one defined by a type_declaration, a formal_type_declaration, or a full type definition embedded in another construct. Class-wide and universal types are implicitly defined, to act as representatives for an entire class of types, as follows:
!corrigendum 3.4.1(6)
Replace the paragraph:
Universal types
Universal types are defined for (and belong to) the integer, real, and fixed point classes, and are referred to in this standard as respectively, universal_integer, universal_real, and universal_fixed. These are analogous to class-wide types for these language-defined numeric classes. As with class-wide types, if a formal parameter is of a universal type, then an actual parameter of any type in the corresponding class is acceptable. In addition, a value of a universal type (including an integer or real numeric_literal) is "universal" in that it is acceptable where some particular type in the class is expected (see 8.6).
by:
Universal types
Universal types are defined for (and belong to) the integer, real, fixed point, and access classes, and are referred to in this standard as respectively, universal_integer, universal_real, universal_fixed, and universal_access. These are analogous to class-wide types for these language-defined elementary classes. As with class-wide types, if a formal parameter is of a universal type, then an actual parameter of any type in the corresponding class is acceptable. In addition, a value of a universal type (including an integer or real numeric_literal, or the literal null) is "universal" in that it is acceptable where some particular type in the class is expected (see 8.6).
!corrigendum 3.4.1(10)
Replace the paragraph:
A specific type T2 is defined to be a descendant of a type T1 if T2 is the same as T1, or if T2 is derived (directly or indirectly) from T1. A class-wide type T2'Class is defined to be a descendant of type T1 if T2 is a descendant of T1. Similarly, the universal types are defined to be descendants of the root types of their classes. If a type T2 is a descendant of a type T1, then T1 is called an ancestor of T2. The ultimate ancestor of a type is the ancestor of the type that is not a descendant of any other type.
by:
A specific type T2 is defined to be a descendant of a type T1 if T2 is the same as T1, or if T2 is derived (directly or indirectly) from T1. A class-wide type T2'Class is defined to be a descendant of type T1 if T2 is a descendant of T1. Similarly, the numeric universal types are defined to be descendants of the root types of their classes. If a type T2 is a descendant of a type T1, then T1 is called an ancestor of T2. The ultimate ancestor of a type is the ancestor of the type that is not a descendant of any other type.
!corrigendum 3.6(7)
Replace the paragraph:
component_definition ::= [aliased] subtype_indication
by:
component_definition ::= [aliased] subtype_indication | access_definition
!corrigendum 3.6(22/1)
Replace the paragraph:
The elaboration of a discrete_subtype_definition that does not contain any per-object expressions creates the discrete subtype, and consists of the elaboration of the subtype_indication or the evaluation of the range. The elaboration of a discrete_subtype_definition that contains one or more per-object expressions is defined in 3.8. The elaboration of a component_definition in an array_type_definition consists of the elaboration of the subtype_indication. The elaboration of any discrete_subtype_definitions and the elaboration of the component_definition are performed in an arbitrary order.
by:
The elaboration of a discrete_subtype_definition that does not contain any per-object expressions creates the discrete subtype, and consists of the elaboration of the subtype_indication or the evaluation of the range. The elaboration of a discrete_subtype_definition that contains one or more per-object expressions is defined in 3.8. The elaboration of a component_definition in an array_type_definition consists of the elaboration of the subtype_indication or access_definition. The elaboration of any discrete_subtype_definitions and the elaboration of the component_definition are performed in an arbitrary order.
!corrigendum 3.7(10)
Delete the paragraph:
A discriminant_specification for an access discriminant shall appear only in the declaration for a task or protected type, or for a type with the reserved word limited in its (full) definition or in that of one of its ancestors. 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.
!corrigendum 3.7(27)
Replace the paragraph:
An access_definition is elaborated when the value of a corresponding access discriminant is defined, either by evaluation of its default_expression or by elaboration of a discriminant_constraint. The elaboration of an access_definition creates the anonymous access type. When the expression defining the access discriminant is evaluated, it is converted to this anonymous access type (see 4.6).
by:
For an access discriminant of a limited type, its access_definition is elaborated when the value of the access discriminant is defined, either by evaluation of its default_expresssion or by elaboration of a discriminant_constraint. For an access discriminant of a nonlimited type, its access_definition is elaborated when the full_type_declaration with the known_discriminant_part is elaborated. The elaboration of an access_definition creates the anonymous access type. When the expression defining the access discriminant is evaluated, it is converted to this anonymous access type (see 4.6).
!corrigendum 3.8(18/1)
Replace the paragraph:
Within the definition of a composite type, if a component_definition or discrete_subtype_definition (see 9.5.2) includes a name that denotes a discriminant of the type, or that is an attribute_reference whose prefix denotes the current instance of the type, the expression containing the name is called a per-object expression, and the constraint or range being defined is called a per-object constraint. For the elaboration of a component_definition of a component_declaration or the discrete_subtype_definition of an entry_declaration for an entry family (see 9.5.2), if the constraint or range of the subtype_indication or discrete_subtype_definition is not a per-object constraint, then the subtype_indication or discrete_subtype_definition is elaborated. On the other hand, if the constraint or range is a per-object constraint, then the elaboration consists of the evaluation of any included expression that is not part of a per-object expression. Each such expression is evaluated once unless it is part of a named association in a discriminant constraint, in which case it is evaluated once for each associated discriminant.
by:
Within the definition of a composite type, if a component_definition or discrete_subtype_definition (see 9.5.2) includes a name that denotes a discriminant of the type, or that is an attribute_reference whose prefix denotes the current instance of the type, the expression containing the name is called a per-object expression, and the constraint or range being defined is called a per-object constraint. For the elaboration of a component_definition of a component_declaration or the discrete_subtype_definition of an entry_declaration for an entry family (see 9.5.2), if the component subtype is defined by an access_definition or if the constraint or range of the subtype_indication or discrete_subtype_definition is not a per-object constraint, then the access_definition, subtype_indication, or discrete_subtype_definition is elaborated. On the other hand, if the constraint or range is a per-object constraint, then the elaboration consists of the evaluation of any included expression that is not part of a per-object expression. Each such expression is evaluated once unless it is part of a named association in a discriminant constraint, in which case it is evaluated once for each associated discriminant.
!corrigendum 3.10(12)
Replace the paragraph:
An access_definition defines an anonymous general access-to-variable type; the subtype_mark denotes its designated subtype. An access_definition is used in the specification of an access discriminant (see 3.7) or an access parameter (see 6.1).
by:
An access_definition defines an anonymous general access-to-variable type; the subtype_mark denotes its designated subtype.
!corrigendum 3.10(13)
Replace the paragraph:
For each (named) access type, there is a literal null which has a null access value designating no entity at all. The null value of a named access type is the default initial value of the type. Other values of an access type are obtained by evaluating an attribute_reference for the Access or Unchecked_Access attribute of an aliased view of an object or non-intrinsic subprogram, or, in the case of a named access-to-object type, an allocator, which returns an access value designating a newly created object (see 3.10.2).
by:
For each access type, other than a specific anonymous access type, there is a null access value designating no entity at all. The null value of an access type is the default initial value of the type. Other values of an access type are obtained by evaluating an attribute_reference for the Access or Unchecked_Access attribute of an aliased view of an object or non-intrinsic subprogram, or, in the case of an access-to-object type, an allocator, which returns an access value designating a newly created object (see 3.10.2).
!corrigendum 3.10(17)
Replace the paragraph:
The elaboration of an access_definition creates an anonymous general access-to-variable type [(this happens as part of the initialization of an access parameter or access discriminant)].
by:
The elaboration of an access_definition creates an anonymous general access-to-variable type.
!corrigendum 3.10.2(12)
Replace the paragraph:
by:
!corrigendum 3.10.2(34)
Replace the paragraph:
82 The predefined operations of an access type also include the assignment operation, qualification, and membership tests. Explicit conversion is allowed between general access types with matching designated subtypes; explicit conversion is allowed between access-to-subprogram types with subtype conformant profiles (see 4.6). Named access types have predefined equality operators; anonymous access types do not (see 4.5.2).
by:
82 The predefined operations of an access type also include the assignment operation, qualification, and membership tests. Explicit conversion is allowed between general access types with matching designated subtypes; explicit conversion is allowed between access-to-subprogram types with subtype conformant profiles (see 4.6). Named access types have predefined equality operators; anonymous access types do not, but they can use the predefined equality operators for universal_access (see 4.5.2).
!corrigendum 4.2(2)
Delete the paragraph:
The expected type for a literal null shall be a single access type.
!corrigendum 4.2(7)
Replace the paragraph:
A literal null shall not be of an anonymous access type, since such types do not have a null value (see 3.10).
by:
A literal null shall not be of a specific anonymous access type, since such types do not have a null value (see 3.10).
!corrigendum 4.2(8)
Replace the paragraph:
An integer literal is of type universal_integer. A real literal is of type universal_real.
by:
An integer literal is of type universal_integer. A real literal is of type universal_real. The literal null is of type universal_access.
!corrigendum 4.5.2(7)
Insert after the paragraph:
function "=" (Left, Right : T) return Boolean function "/="(Left, Right : T) return Boolean
the new paragraphs:
The following additional equality operators for the universal_access type are declared in package Standard for use with anonymous access types:
function "=" (Left, Right : universal_access) return Boolean function "/="(Left, Right : universal_access) return Boolean
!corrigendum 4.5.2(9)
Insert after the paragraph:
function "<" (Left, Right : T) return Boolean function "<="(Left, Right : T) return Boolean function ">" (Left, Right : T) return Boolean function ">="(Left, Right : T) return Boolean
the new paragraphs:
Name Resolution Rules
At least one of the operands of the equality operators for universal_access shall be of a specific anonymous access type.
Legality Rules
At least one of the operands of the equality operators for universal_access shall be of type universal_access, or both shall be of access-to-object types, or both shall be of access-to-subprogram types. Further:
!corrigendum 4.6(13)
Replace the paragraph:
If the target type is a general access type, then the operand type shall be an access-to-object type. Further:
by:
If the target type is universal_access, then the operand type shall be an access type.
If the target type is a general access-to-object type, then the operand type shall be universal_access or an access-to-object type. Further, if the operand type is not universal_access:
!corrigendum 4.6(18)
Replace the paragraph:
If the target type is an access-to-subprogram type, then the operand type shall be an access-to-subprogram type. Further:
by:
!corrigendum 4.6(49)
Replace the paragraph:
by:
!corrigendum 4.6(61)
Replace the paragraph:
22 A ramification of the overload resolution rules is that the operand of an (explicit) type_conversion cannot be the literal null, an allocator, an aggregate, a string_literal, a character_literal, or an attribute_reference for an Access or Unchecked_Access attribute. Similarly, such an expression enclosed by parentheses is not allowed. A qualified_expression (see 4.7) can be used instead of such a type_conversion.
by:
22 A ramification of the overload resolution rules is that the operand of an (explicit) type_conversion cannot be an allocator, an aggregate, a string_literal, a character_literal, or an attribute_reference for an Access or Unchecked_Access attribute. Similarly, such an expression enclosed by parentheses is not allowed. A qualified_expression (see 4.7) can be used instead of such a type_conversion.
!corrigendum 8.5.1(2)
Replace the paragraph:
object_renaming_declaration ::= defining_identifier : subtype_mark renames object_name;
by:
object_renaming_declaration ::= defining_identifier : subtype_mark renames object_name; | defining_identifier : access_definition renames object_name;
!corrigendum 8.5.1(3)
Replace the paragraph:
The type of the object_name shall resolve to the type determined by the subtype_mark.
by:
The type of the object_name shall resolve to the type determined by the subtype_mark, or in the case where the type is defined by an access_definition, to a specific anonymous access type whose designated type is the same as that of the access_definition.
!corrigendum 8.5.1(6)
Replace the paragraph:
An object_renaming_declaration declares a new view of the renamed object whose properties are identical to those of the renamed view. Thus, the properties of the renamed object are not affected by the renaming_declaration. In particular, its value and whether or not it is a constant are unaffected; similarly, the constraints that apply to an object are not affected by renaming (any constraint implied by the subtype_mark of the object_renaming_declaration is ignored).
by:
An object_renaming_declaration declares a new view of the renamed object whose properties are identical to those of the renamed view. Thus, the properties of the renamed object are not affected by the renaming_declaration. In particular, its value and whether or not it is a constant are unaffected; similarly, the constraints that apply to an object are not affected by renaming (any constraint implied by the subtype_mark or access_definition of the object_renaming_declaration is ignored).
!corrigendum 8.6(25)
Replace the paragraph:
by:
!corrigendum 13.7.2(5)
Replace the paragraph:
The To_Pointer and To_Address subprograms convert back and forth between values of types Object_Pointer and Address. To_Pointer(X'Address) is equal to X'Unchecked_Access for any X that allows Unchecked_Access. To_Pointer(Null_Address) returns null. For other addresses, the behavior is unspecified. To_Address(null) returns Null_Address (for null of the appropriate type). To_Address(Y), where Y /= null, returns Y.all'Address.
by:
The To_Pointer and To_Address subprograms convert back and forth between values of types Object_Pointer and Address. To_Pointer(X'Address) is equal to X'Unchecked_Access for any X that allows Unchecked_Access. To_Pointer(Null_Address) returns null. For other addresses, the behavior is unspecified. To_Address(null) returns Null_Address. To_Address(Y), where Y /= null, returns Y.all'Address.
!corrigendum 13.11(25)
Replace the paragraph:
A storage pool for an anonymous access type should be created at the point of an allocator for the type, and be reclaimed when the designated object becomes inaccessible.
by:
The storage pool used for an allocator of an anonymous access type should be determined as follows:
!corrigendum A.1(34)
Insert after the paragraph:
function "/" (Left : universal_fixed; Right : universal_fixed;) return universal_fixed;
the new paragraphs:
-- The type universal_access is predefined. -- The following equality operators are predefined:
function "=" (Left, Right: universal_access) return Boolean; function "/=" (Left, Right: universal_access) return Boolean;
!ACATS test
Tests should be created to check on the implementation of this feature.
!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.

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

From: Tucker Taft
Sent: Monday, April 03, 2000 5:29 PM

How about if we get an e-mail discussion going, then?

The major new idea in my revision of AI-230 is the attribute
on tagged types "'Class_Access". T'Class_Access is a type
that may be used as the type of a stand-alone object, record or
array component, parameter, etc. It is "universal" in the sense
that when the expected type is T'Class_Access, any access type
whose designated type is covered by T'Class may be used.

There would need to be an accessibility check that the source type has the
same accessibility level as type T. It would have "=" and "/=" operators,
and the "null" literal. Allocators would raise Storage_Error, because
the Storage_Size for T'Class_Access is defined to be 0.

Such an access type would very closely match the reference-type implicit
conversion semantics of Java and C++, providing "substitutability"
for access-to-tagged types in much the way that T'Class supports
substitutability for tagged types.

T'Class_Access would be permitted on incomplete tagged types (a new
category of incomplete types). I suppose we would also allow
T'Class_Access on plain old incomplete types, with the same provisos
as on T'Class (e.g. only in the same library unit and the full type must
be tagged).

T'Class_Access avoids some of the difficulties associated with the
more general T'Access proposal, since it doesn't need to worry, e.g., about
thin versus fat pointers, and loosens conversion rules only in
the place where they seem most critical, namely dealing with
conversions to access-to-'class types.

The hope is that when combined with "with type T is tagged;", T'Class_Access
will make bindings to Java-like languages much more straightforward both
to create and to use.

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

From: Robert A Duff
Sent: Tuesday, April 04, 2000 10:46 AM

> How about if we get an e-mail discussion going, then?

I like the T'Class_Access idea.

But why not call it T'Access?  But keep the rule that it's only for
tagged, and the designated type is T'Class. That is, I'm just
suggesting a name change. I don't see any benefit in the extra verbiage
"Class_". Ada is already verbose enough, compared to Pascal's perfectly
readable "^T" and C's somewhat ugly "T*".

I'm not against verbosity when it imparts useful information, so let's
not have a discussion of verbodity in general!

>...Allocators would raise Storage_Error, because
> the Storage_Size for T'Class_Access is defined to be 0.

Does this mean I can use T'Class_Access in a pragma-Pure package?

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

From: Tucker Taft
Sent: Tuesday, April 04, 2000 11:44 AM

Robert A Duff wrote:

> But why not call it T'Access?  But keep the rule that it's only for
> tagged, and the designated type is T'Class. That is, I'm just
> suggesting a name change. I don't see any benefit in the extra verbiage
> "Class_".

I think there is an important benefit. At least *I* would presume
that T'Access would be an access-to-T type rather than an access-to-T'Class
type. Also, T'Class_Access is clearly only appropriate for tagged
types, whereas T'Access seems like a perfectly reasonable thing to
allow for any kind of type.

> >...Allocators would raise Storage_Error, because
> > the Storage_Size for T'Class_Access is defined to be 0.
>
> Does this mean I can use T'Class_Access in a pragma-Pure package?

That was a possibility. If we allow access types
in pure packages, we need certain restrictions.
At a minimum, access types declared in pure packages should
have Storage_Size 0. Since access parameters and discriminants
are already allowed in pure packages, it seems unnecessary
to go any further. However, we would have to amend the
rules on shared passive packages to disallow not only the declaration
of access-to-classwide types, but also the declaration of library-level
objects of a type, or access types designating a type, with any
part being of an access-to-classwide type.

Alternatively, it might be easier to disallow T'Class_Access inside
a pure library unit, if T is library-level (or a formal type),
even though you could use T'Class_Access outside a pure library
unit, despite the fact that T was declared inside a pure library unit.
That seems more prudent for now. If we decide to allow
storage-size-zero access types in pure packages in general,
then we could examine allowing T'Class_Access there as well.

Conceptually, we could think of Pure_Pkg.T'Class_Access being implicitly
declared in a (virtual) impure child of Pure_Pkg, which is only visible
to impure packages that "with" Pure_Pkg.

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

From: Robert A Duff
Sent: Tuesday, April 04, 2000 12:02 PM

> I think there is an important benefit. At least *I* would presume
> that T'Access would be an access-to-T type rather than an access-to-T'Class
> type. Also, T'Class_Access is clearly only appropriate for tagged
> types, whereas T'Access seems like a perfectly reasonable thing to
> allow for any kind of type.

But none of that is likely to cause bugs.

Another idea would be to call it T'Class'Access, presumably allowing:

    type T is tagged...;
    subtype S is T'Class;
    ... S'Access ...

I'm not particularly advocating that.

> That was a possibility. If we allow access types
> in pure packages, we need certain restrictions.
> At a minimum, access types declared in pure packages should
> have Storage_Size 0. Since access parameters and discriminants
> are already allowed in pure packages, it seems unnecessary
> to go any further. However, we would have to amend the
> rules on shared passive packages to disallow not only the declaration
> of access-to-classwide types, but also the declaration of library-level
> objects of a type, or access types designating a type, with any
> part being of an access-to-classwide type.

You realize this is a dangerous discussion. It's a side issue, but
discussing it makes the original proposal look more complicated. ;-)

> Alternatively, it might be easier to disallow T'Class_Access inside
> a pure library unit, if T is library-level (or a formal type),
> even though you could use T'Class_Access outside a pure library
> unit, despite the fact that T was declared inside a pure library unit.

I don't see the point of that. I want to declare self-referential data
structures in pure packages. Of course, the creation routines have to
be elsewhere (eg in an impure child).

> That seems more prudent for now. If we decide to allow
> storage-size-zero access types in pure packages in general,
> then we could examine allowing T'Class_Access there as well.
>
> Conceptually, we could think of Pure_Pkg.T'Class_Access being implicitly
> declared in a (virtual) impure child of Pure_Pkg, which is only visible
> to impure packages that "with" Pure_Pkg.

Sounds ugly to me. I don't like inventing all kinds of implicit junk
all over. I advocate allowing it in the pure package, unless we
actually have semantic problems with that. We already agreed that you
can't do alligators.

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

From: Tucker Taft
Sent: Tuesday, April 04, 2000 1:16 PM

Robert A Duff wrote:
>
> > I think there is an important benefit. At least *I* would presume
> > that T'Access would be an access-to-T type rather than an access-to-T'Class
> > type. Also, T'Class_Access is clearly only appropriate for tagged
> > types, whereas T'Access seems like a perfectly reasonable thing to
> > allow for any kind of type.
>
> But none of that is likely to cause bugs.

It is bound to cause confusion, in my view. Also, we might
eventually want to allow T'Access as a generall anonymous access-to-T.
If we used T'Access to mean access-to-T'Class, we would have eliminated
that possibility.

> Another idea would be to call it T'Class'Access, presumably allowing:
>
>     type T is tagged...;
>     subtype S is T'Class;
>     ... S'Access ...
>
> I'm not particularly advocating that.

That is where I started, but I rejected that because again it
implied more generality than was provided. Note that T'Class'Access
is the same number of characters as T'Class_Access ;-)

> ... I advocate allowing it in the pure package, unless we
> actually have semantic problems with that. We already agreed that you
> can't do alligators.

The semantic problems have to do with shared passive partitions, which
are allowed to depend on pure packages, but which are not allowed to
have access-to-class-wide objects, since they implicitly involve
pointers to code that is potentially not as long-lived as the
shared passive partition. I agree it is a side issue, but it is
a thorny one. Perhaps the right answer is to presume that shared
passive partitions need their own rules to prevent dangling references,
and not to try too hard to make the rules of pure library units
worry about them.

On the other hand, we do need some well defined criteria for deciding
what can go in a pure package. One goal is side-effect-freeness, but
with access parameters and access discriminants, that is pretty
much out the window. The other goal is ability to replicate freely
among different partitions, since it has no "state" of its own.
Perhaps the side-effect-freeness can be resurrected if we limit
ourselves to cases where the parameters have no access-type parts.
I suppose another way to say it is that the only side-effects are
through parameters and data accessible via access-type parts of
parameters. There is no variable "state" visible via up-level
references that could be altered. We should probably also disallow
the declaration of constants with any aliased parts, so the pure
package remains position independent, and hence freely replicable.

So I guess I am convinced -- force them to have storage size 0,
and allow them in pure packages. Similarly, we should allow
normal access-type declarations in pure packages, but with
the storage size implicitly zero, while disallowing constants
with aliased parts. Shared passive packages will
need some amended rules to deal with the allowance of
access types in pure packages.

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

From: Gary Dismukes
Sent: Tuesday, April 04, 2000 2:11 PM

> It is bound to cause confusion, in my view. Also, we might
> eventually want to allow T'Access as a generall anonymous access-to-T.
> If we used T'Access to mean access-to-T'Class, we would have eliminated
> that possibility.

Tuck, can you comment on the reason for not generalizing
the implicit conversion capability to arbitrary designated
types?  At the September meeting we were talking in terms
of an attribute T'univ_access which would allow implicit
conversions to any access-to-D where D covers T and
from any access-to-D where T covers D, but not restricted
to tagged types. It probably makes sense to restrict
the conversions so that it only goes towards one of these
special types, but what's the reason for limiting it
to class-wide types?  Is it just because the main benefit
and anticipated use is for those, or is there some fundamental
difficulty with the generalization to other types?  Or are
you just being conservative in your old age? ;-)

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

From: Tucker Taft
Sent: Tuesday, April 04, 2000 2:59 PM

> Tuck, can you comment on the reason for not generalizing
> the implicit conversion capability to arbitrary designated
> types?

There were some concerns about access-to-unconstrained-array, and
whether it is thin or fat.
I suppose there would also be a lot of anonymous access types
popping up all over, with the associated "=" and "/=", if 'univ_access
applied to all types.

The minutes indicate there were some concerns about representation,
but I don't remember the details.

> ... Is it just because the main benefit
> and anticipated use is for those, or is there some fundamental
> difficulty with the generalization to other types?  Or are
> you just being conservative in your old age? ;-)

These are all good reasons ;-)

Since this is really trying to help with Java interfacing
and "with type," the 'Class_Access seemed a smaller, more
manageable change.

I also think the proposed potentially-null anonymous access
parameter "access all T"/"access constant T" solves the
interfacing-to-C-pointer-parameter problems in a better way than
would a more general T'Univ_Access.

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

From: Robert A Duff
Sent: Tuesday, April 04, 2000 5:15 PM

> The semantic problems have to do with shared passive partitions, which
> are allowed to depend on pure packages, but which are not allowed to
> have access-to-class-wide objects, since they implicitly involve
> pointers to code that is potentially not as long-lived as the
> shared passive partition. I agree it is a side issue, but it is
> a thorny one. Perhaps the right answer is to presume that shared
> passive partitions need their own rules to prevent dangling references,
> and not to try too hard to make the rules of pure library units
> worry about them.

Yes. They can have some extra rules.

> On the other hand, we do need some well defined criteria for deciding
> what can go in a pure package. One goal is side-effect-freeness, but
> with access parameters and access discriminants, that is pretty
> much out the window.

I thought the goal was to prevent silent side effects -- ie side effects
on globals, whereas side effects on parameters (or what they point to)
are OK.

>... The other goal is ability to replicate freely
> among different partitions, since it has no "state" of its own.
> Perhaps the side-effect-freeness can be resurrected if we limit
> ourselves to cases where the parameters have no access-type parts.
> I suppose another way to say it is that the only side-effects are
> through parameters and data accessible via access-type parts of
> parameters. There is no variable "state" visible via up-level
> references that could be altered. We should probably also disallow
> the declaration of constants with any aliased parts, so the pure
> package remains position independent, and hence freely replicable.

I'm not sure I understand that. Could you give an example?

> So I guess I am convinced ...

Cool. It's not easy to convince Tucker of something. Not because he's
stubborn, but because he's usually right. ;-)

>... -- force them to have storage size 0,
> and allow them in pure packages. Similarly, we should allow
> normal access-type declarations in pure packages, but with
> the storage size implicitly zero, while disallowing constants
> with aliased parts. Shared passive packages will
> need some amended rules to deal with the allowance of
> access types in pure packages.

Sounds good to me.

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

From: Robert A Duff
Sent: Tuesday, April 04, 2000 5:24 PM

> There were some concerns about access-to-unconstrained-array, and
> whether it is thin or fat.

I think Pascal raised a concern about a 64-bit machine, where it might
make sense to have both 32-bit and 64-bit access types, where the user
chooses by writing a rep clause.
Pascal?

> Since this is really trying to help with Java interfacing
> and "with type," the 'Class_Access seemed a smaller, more
> manageable change.

I see it as a general feature. I think it's a serious flaw in Ada 95
that you have to write all kinds of type conversions that are perfectly
safe. A type conversion ought to be a red flag, saying "I'm
deliberately violating the type rules", but that doesn't work if you
have to constantly "cry wolf". You can convert implicitly from T2 to
T1'Class (where T2 is new T1) and you ought to be able to do the
analogous thing for pointer-to-T2 and pointer-to-T1'Class. The
'Class_Access idea solves that.

> I also think the proposed potentially-null anonymous access
> parameter "access all T"/"access constant T" solves the
> interfacing-to-C-pointer-parameter problems in a better way than
> would a more general T'Univ_Access.

Agreed.

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

From: Robert Dewar
Sent: Wednesday, April 05, 2000 1:09 PM

<<I think Pascal raised a concern about a 64-bit machine, where it might
make sense to have both 32-bit and 64-bit access types, where the user
chooses by writing a rep clause.>>

VMS being an obvious example, just so that this does not seem to be
only a theoretical concern.

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

From: Pascal Leroy
Sent: Thursday, April 06, 2000 4:22 AM

Yes, any proposal which assumes that "all accesses look the same" is flawed.
The 32-vs.-64-bit access types is not a theoretical issue, we do just that on
Alpha because people don't want to pay for 64-bit pointers when their data
structures are much smaller than 2Gb.

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

From: Christoph Grein
Sent: Monday, May 08, 2000 11:45 PM
Subject: [Ada-Comment] Predefined Access Types

!topic Predefined Access Types
!reference RM95-A.4.5(7,8), RM95-3.6.3, RM95-3.10
!from Christoph Grein 2000-05-09
!keywords access types, String_Access
!discussion

The type String_Access and corresponding function Free in A.4.5(7,8) seem
misplaced in this package. They are not used there at all.

In the light of the fact that when strings are handled, very often (I would even
say, virtually always) an access type is also needed even if package
Ada.Strings.Unbounded is not used, I would propose to shift these declarations
to the place where type String is defined, 3.6.3. [And correspondingly for wide
strings A.4.7.]

This removes programmers' need to declare their own access types to strings all
over the place.

In a step further, I would propose a new 'Access attribute for types:
Given any type T, T'Access would denote the following predefined general access
type

  type T'Access is access all T;

This would be implicitly defined where T is defined. Correspondingly also the
type T'Class'Access would be predefined where 'Class is defined.

[There would have to be rule to prevent recursion: Since T'Access is also a
type, T'Access'Access and so on should be ruled out as being predefined.]

If this is accepted, the type String_Access can be defined as

  subtype String_Access is String'Access;

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

From: Randy Brukardt
Sent: Tuesday, May 09, 2000 6:31 PM
To: 'Ada-Comment List'

> In the light of the fact that when strings are handled, very often (I would
> even say, virtually always) an access type is also needed even if package
> Ada.Strings.Unbounded is not used, I would propose to shift these declarations
> to the place where type String is defined, 3.6.3. [And correspondingly for
> wide strings A.4.7.]

This would be a very bad idea. Introducing names in Standard is *very*
incompatible with existing code, as the names in Standard cannot be hidden, and
would override any names currently accessible by a use clause.

For instance, if a program contained:

   package P is
	type String_Access is access all My_String;
   end P;

   procedure M is
	use P;
      V : String_Access;
      ...

Your proposal would change V's type (silently!) from P.String_Access to
Standard.String_Access. One place that would happen is for the declarations in
Ada.Strings.Unbounded that started the discussion!

Besides, your second proposal is a better way to accomplish the same thing
without polluting Standard.

> In a step further, I would propose a new 'Access attribute for types:
> Given any type T, T'Access would denote the following
> predefined general access type
>
>   type T'Access is access all T;

This proposal looks rather attractive, but would be quite expensive on compilers
hosted on memory-limited hosts. (Perhaps that doesn't matter anymore??)

In any case, this exact proposal was made by Bob Duff in response to another
proposal. I will attach your comment to that AI (AI-00230), because I don't want
to spend anyone's time on the first proposal.

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

From: Robert A Duff
Sent: Wednesday, May 10, 2000 10:14 AM

> >   type T'Access is access all T;

> This proposal looks rather attractive, but would be quite expensive on
> compilers hosted on memory-limited hosts. (Perhaps that doesn't matter
> anymore??)

I'm not sure why it is expensive. But I do think nobody should be
running compilers on anything less than a 32-bit address space.
(Target machines are often smaller, though.)

> In any case, this exact proposal was made by Bob Duff in response to another
> proposal.

Actually, I think it was Robert Dewar's idea;
I supported it.

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

From: Robert Dewar
Sent: Tuesday, May 09, 2000 7:46 PM

I strongly agree that introducing names into standard is a bad idea.

As for type'Access, let's give credit where credit is due, I pushed this
idea strongly during the design process, but it was rejected. note that
the proposal in its current form is in any case incompatible with the
current language design, which ascribes a quite different meaning top
to type'Access in certain contexts.

The objection to my proposal at the time was strong and clearly the majority
viewpoint. The basis of this objection was that providing this distinguished
anonymous type would tend to decrease type safety by encouraging the use of
this type instead of properly typed access types. I see nothing that would
change people's minds, and I think there is considerable merit in the majority
viewpoint, so I see no argument for reopening this issue.

By the way, the idea of putting this unreferenced type where it is was
precisely to provide a standard string access type, does anyone use it
this way?

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

From: Randy Brukardt
Sent: Wednesday, May 10, 2000 11:44 AM

> By the way, the idea of putting this unreferenced type where it is was
> precisely to provide a standard string access type, does anyone use it
> this way?

I didn't even realize this type was in Ada.Strings.Unbounded until this
comment, so for me at least, the answer is no.

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

From: Robert A Duff
Sent: Wednesday, May 10, 2000 3:26 PM

> I strongly agree that introducing names into standard is a bad idea.

As Tuck is fond of pointing out, it's almost the same thing as adding a
new reserved word to the language.

> As for type'Access, let's give credit where credit is due, I pushed this
> idea strongly during the design process, but it was rejected.

Right.

>... note that
> the proposal in its current form is in any case incompatible with the
> current language design, which ascribes a quite different meaning top
> to type'Access in certain contexts.

Heh?  What's type'Access?

> The objection to my proposal at the time was strong and clearly the majority
> viewpoint. The basis of this objection was that providing this distinguished
> anonymous type would tend to decrease type safety by encouraging the use of
> this type instead of properly typed access types. I see nothing that would
> change people's minds, and I think there is considerable merit in the majority
> viewpoint, so I see no argument for reopening this issue.

I see no merit whatsoever in the majority viewpoint. Most programs I've
seen (or written) declare exactly one access type per designated type,
right after the designated type is declared. So in practise, people are
*not* taking advantage of strongly typed access types. Contrast this
with (for example) integer types, where most programmers define a new
integer type for each distinct purpose in the program.

I think there *is* new information on the subject: people have realized
from experience with Ada 95 that it's a big pain to have type
conversions all over the place for perfectly safe cases (eg,
access-to-T2'Class converted to access-to-T1'Class, where T2 is derived
from T1, so conversions from T2'Class to T1'Class are of course
implicit). These bogus type conversions damage readability. And part
of the solution that has been discussed involves the T'Access idea.

> By the way, the idea of putting this unreferenced type where it is was
> precisely to provide a standard string access type, does anyone use it
> this way?

I doubt it. Lots of programs don't use unbounded strings, so it
wouldn't occur to the programmer to use this type. But it's harmless,
so no change is needed. We're certainly not going to delete the type,
and we're certainly not going to add a new type to package Standard.

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

From: Gary Dismukes [dismukes@gnat.com]
Sent: Wednesday, May 10, 2000 5:08 PM

> >... note that
> > the proposal in its current form is in any case incompatible with the
> > current language design, which ascribes a quite different meaning top
> > to type'Access in certain contexts.
>
> Heh?  What's type'Access?

I'm guessing that Robert's referring to the case where the prefix
is a current instance name (looks like a type name, though technically
it's the name of an object of course).

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

From: Robert Dewar
Sent: Wednesday, May 10, 2000 7:48 PM

Yup! That's what I was referring to, that is indeed the only context
in which type'access can appear in the current language.

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

From: Robert A Duff
Sent: Thursday, May 11, 2000 9:46 AM

> > Heh?  What's type'Access?
>
> I'm guessing that Robert's referring to the case where the prefix
> is a current instance name (looks like a type name, though technically
> it's the name of an object of course).

Isn't it *always* the name of the instance?  I mean, even if we chose to
call it T'Pointer, we would have a problem, because the attribute would
be unusable inside the type. Not a big problem, but it would be
annoying, because access types are quite often used to make
self-referential record types.

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

From: Robert Dewar [dewar@gnat.com]
Sent: Thursday, May 11, 2000 3:47 AM
To: ada-comment@ada-auth.org
Subject: Re: [Ada-Comment] Predefined Access Types

<<Where is T'Access defined? Oh - within record type definitions where it
stands for the current instance of the type.>>

Much more significantly, within tasks and protected objects to denote
the current concurrent object.

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

From: Gary Dismukes
Sent: Thursday, May 11, 2000 1:34 PM

> Isn't it *always* the name of the instance?  I mean, even if we chose to
> call it T'Pointer, we would have a problem, because the attribute would
> be unusable inside the type. Not a big problem, but it would be
> annoying, because access types are quite often used to make
> self-referential record types.

Yes, that's right, it will always denote the instance within the
type, though I suppose that if a new attribute such as 'Pointer
or whatever were used it could be defined to apply to the type
of the object in the case of an object prefix, hmm.

Anywya, as you say, the restriction within a type is annoying but
doesn't seem like a major problem. You could still use a workaround
such as applying 'Access to a subtype name.

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

From: Robert Dewar
Sent: Wednesday, May 10, 2000 7:52 PM

<<Actually, I think it was Robert Dewar's idea;
I supported it.>>

Ah Bob, if you supported it, then you can't move for a reconsideration.
To convince ourselves it is worth refighting this, we have to have at
least one person change their minds :-)

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

From: Christoph Grein
Sent: Thursday, May 11, 2000 12:00 AM

> I strongly agree that introducing names into standard is a bad idea.

OK, I see the point.

> .... note that
> the proposal in its current form is in any case incompatible with the
> current language design, which ascribes a quite different meaning top
> to type'Access in certain contexts.

RM K(2): P'Access where P denotes a subprogram
RM K(4): X'Access where X denotes an object

Where is T'Access defined? Oh - within record type definitions where it
stands for the current instance of the type.


> By the way, the idea of putting this unreferenced type where it is was
> precisely to provide a standard string access type, does anyone use it
> this way?
>

No, I dislike the idea of withing Strings.Unbounded just for this type
when I do not use any other operations of the package. So the type is
really misplaced.

The proper place in light of all the arguments presented seems to be
package Strings (RM A.4.1).

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

From: Robert A Duff
Sent: Thursday, May 11, 2000 7:28 AM

> The proper place in light of all the arguments presented seems to be
> package Strings (RM A.4.1).

Package Strings has pragma Pure, which disallows access types.

Come to think of it, Standard has pragma Pure, too, which is *another*
reason we can't put type String_Access in Standard.

By the way, I wish there were a way to declare access types without
allocators; then we could allow *those* kinds of access types in
pragma-pure packages.

I agree with you that String_Access is in a weird place.
But it's harmless. If you don't want to use it,
you can easily declare your own. Not ideal, but it works.

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

From: Michael Yoder
Sent: Thursday, May 11, 2000 10:11 AM

Christopher Grein wrote:
>
>The proper place in light of all the arguments presented seems to be
>package Strings (RM A.4.1).
>
Doing this would require (under current rules) changing package Strings
from pure to preelaborated. This potentially breaks existing code; it
seems unlikely that a user would write an existing pure package that
depends on Strings, but it's certainly imaginable (e.g., by renaming the
exceptions).

Earlier someone asked if anyone ever used the access type in
Strings.Unbounded. I have, two or three times. In each case, I knew other
parts of the program were using unbounded strings, so there was no cost to
doing so. I believe however that I would do it in any case, since IMO most
large programs use unbounded strings at least once, and a small program
won't be made a large one just by including one extra package. Even so, I
agree the type doesn't belong where it's put, and I have encountered at
least one space-constrained program for which this consideration mattered.

Perhaps a least bad solution would be to put the type in its own small
child of Strings, and make the type in Strings.Unbounded be a "renaming as
subtype" of that type. This would (I think) be entirely compatible with
the existing state of affairs.

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

From: Christoph Grein
Sent: Friday, May 12, 2000 12:01 AM

> Doing this would require (under current rules) changing package Strings
> from pure to preelaborated. ...

OK, I again see the point.

> Perhaps a least bad solution would be to put the type in its own small
> child of Strings, and make the type in Strings.Unbounded be a "renaming as
> subtype" of that type. This would (I think) be entirely compatible with
> the existing state of affairs.

Hey, I think that's a brilliant idea.

An access to String is so often needed that it should be predefined in the
language, and Michael's proposal just does this in an innocuous way.

    package Ada.Strings.Yoder is

      pragma Preelaborate(Yoder);

      type String_Access is access all String;

      procedure Free (X : in out String_Access);

    end Ada.Strings.Yoder;

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

From: Robert Dewar
Sent: Friday, May 12, 2000 12:59 AM

You can even imagine a special implementation of Ada.Strings;Yoder that
would use some special storage pool to handle string accesses
especially efficiently???

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

From: Michael Yoder
Sent: Friday, May 12, 2000 2:30 PM

This is a good idea in any case (that is, it can be done for the type in
Strings.Unbounded even if Strings.Yoder never becomes part of Ada0X :-).

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

From: Robert A Duff
Sent: Thursday, May 11, 2000 8:21 PM

> Bob, were you for or against type'Access the first time around?
> I can't remember :-)

Sometimes I can't remember what I was for or against in the past ;-),
but in this case I've been for it, or something like it, all along.

...
> Ah Bob, if you supported it, then you can't move for a reconsideration.
> To convince ourselves it is worth refighting this, we have to have at
> least one person change their minds :-)

OK.

But it *was* brought up again, independently, as part of the solution to
some other AI. I can't remember which. (*Editor's note: This one!*)

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

From: Robert Dewar
Sent: Friday, May 12, 2000 12:57 AM

Well I sure would like to see something like typ'Access come back if it
can be figured out how to do it cleanly.

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

From: Christoph Grein
Sent: Friday, May 12, 2000 12:14 AM


> <<Where is T'Access defined? Oh - within record type definitions where it
> stands for the current instance of the type.
> >>
>
> Much more significantly, within tasks and protected objects to denote
> the current concurrent object.
>

Thank you, Robert, for the details.

Wouldn't it be a good idea to include T'Access with such a hint in Annex K?
This annex is "informative", so IMO a good place for a statement like this.

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

From: Robert Dewar
Sent: Friday, May 12, 2000 1:05 AM

<<Wouldn't it be a good idea to include T'Access with such a hint in Annex K?
This annex is "informative", so IMO a good place for a statement like this.
>>

Well this already is in Annex K:

4   X'Access
                For a prefix X that denotes an aliased view of an object:

THe case of subtype_name'Access is just a special case where subtype_name
is defined to denote a specific aliased view, namely the current instance.
It would be confusing to have an entry saying

    T'Access    For a prefix that denotes a subtype T,

... since in this case T does not denote a subtype.

I suppose one could argue for a note, but my feeling is that notes belong
in text books, not in the RM. Also notes in informative annexes are a bit
odd I would think.

Although this is a summary and is informative, it is definitely written
in the style of normative text, so a note still needs to be labeled a
note I would think.

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

From: Robert A Duff
Sent: Friday, May 12, 2000 1:14 PM

> I suppose one could argue for a note, but my feeling is that notes belong
> in text books, not in the RM. Also notes in informative annexes are a bit
> odd I would think.

I guess they would be doubly informative. ;-)

> Although this is a summary and is informative, it is definitely written
> in the style of normative text, ...

In fact, this text is identical to the normative text in the body of the
RM that describes these attributes. So it's not surprising that it's in
the same style. ;-)

In the source code for the RM (in Scribe), the attributes are written as
macro calls, which generate the inline text, and also send the same text
to a separate file, which gets sorted by attribute name, and then
re-included back into Annex K.

The pragmas have a similar mechanism.

I think to build the Postscript version of the RM, you had to run Scribe
three times in a row, because the output of one run would get sucked up
into the next run as input, and it had to "settle down". Sort of like
bootstrapping a compiler.

Randy is in the process of modernizing this software. ;-)

>... so a note still needs to be labeled a
> note I would think.

I tend to think it's not the job of ARG to teach people Ada. As Robert
says, there are textbooks.

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

From: Robert A Duff
Sent: Friday, May 12, 2000 4:04 PM

Mike and Robert,

> Robert Dewar wrote:
> >You can even imagine a special implementation of Ada.Strings;Yoder that
> >would use some special storage pool to handle string accesses
> >especially efficiently???
>
> This is a good idea in any case (that is, it can be done for the type in
> Strings.Unbounded even if Strings.Yoder never becomes part of Ada0X :-).

I guess you're going to be famous, Mike. Nobody else has a predefined
Ada package named after them. Hey, maybe the ARG could make money by
letting large corporations put their names on things. Package Calendar
could be renamed package FleetBank, and so on.

Anyway, I'm not sure what you guys are getting at with efficient storage
pools. What's special about String_Access?  The fact that the
designated type is an unconstrained array?  Surely not the fact that
it's predefined. What sort of special pool are you talking about, and
whatever it is, why wouldn't it be a good idea for *any* "type Mumble is
access all Unconstrained_Array;" that appears anywhere in any program?

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

From: Robert A Duff
Sent: Friday, May 12, 2000 4:38 PM

I wrote:

> I guess you're going to be famous, Mike. Nobody else has a predefined
> Ada package named after them.

Except for Ada herself, of course!

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

From: Michael Yoder
Sent: Monday, May 15, 2000 9:25 AM

Bob Duff wrote:
>Anyway, I'm not sure what you guys are getting at with efficient storage
>pools. What's special about String_Access?  The fact that the
>designated type is an unconstrained array?  Surely not the fact that
>it's predefined. What sort of special pool are you talking about, and
>whatever it is, why wouldn't it be a good idea for *any* "type Mumble is
>access all Unconstrained_Array;" that appears anywhere in any program?

String_Access is special because you can probably improve performance by
making assumptions about the frequency of allocation of various lengths. A
simpler possibility is to choose the algorithm so as to specifically
support Strings.Unbounded : this can be done by usiing a binary-buddy
allocator when the length is a power of 2, for example. (I haven't
actually tried any such scheme, so I suppose I should qualify my enthusiasm
by saying that the idea is potentially good rather than good. But the idea
of exploring such schemes is good. :-)

If Ada had a predefined generic for vectors of variable length, it could
probably use the same allocator as that for Strings.Unbounded.

If the above is still overly concise, I'm willing to elaborate further.

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

From: Michael Yoder
Sent: Monday, May 15, 2000 11:36 AM

Robert Duff wrote:
>I guess you're going to be famous, Mike. Nobody else has a predefined
>Ada package named after them. Hey, maybe the ARG could make money by
>letting large corporations put their names on things. Package Calendar
>could be renamed package FleetBank, and so on.

I would hate to have to buy dark glasses in order to travel incognito. :-)
 So, let me propose Ada.Strings.Accesses as a name for this supposed package.

>Anyway, I'm not sure what you guys are getting at with efficient storage
>pools.

I should perhaps state that my experience makes me at least as inclined to
worry about fragmentation behavior as efficiency. In either case, there is
potential benefit in treating strings specially.

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

From: Robert Dewar
Sent: Monday, October 1, 2001 5:57 AM

I think that all AI's that propose new features should have a section
discussing the need for any work in the area. I am afraid we are going
into the mode of language experts writing up things that would be nice
to have, if we are not careful.

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

From: Tucker Taft
Sent: Monday, October 1, 2001 10:44 AM

I believe that is at least part of the intent of the "!problem"
section. Apparently the "problem" section of this AI was inadequate.
Also, in this case, we discussed the need quite a bit at the last
ARG meeting, so I was more focused on writing up the technical
aspects of the proposal, than justifying its need. I do agree with
the important of having a good justification.

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

From: Robert Dewar
Sent: Monday, October 1, 2001 11:00 AM

The important thing here is that the justification include some evidence
that this is a real world issue, i.e. a purely technical nice-to-have
justification is dubious. We need some real world examples or input.

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

From: Randy Brukardt
Sent: Monday, October 1, 2001 8:05 PM

Robert said:

> I think that all AI's that propose new features should have a section
> discussing the need for any work in the area. I am afraid we are going
> into the mode of language experts writing up things that would be nice
> to have, if we are not careful.

As Tucker responded, this is the propose of the !problem section. If the
!problem of an AI isn't convincing, then the AI has a (ahem) problem, no matter
what the merits of the proposal.

> The important thing here is that the justification include some evidence
> that this is a real world issue, i.e. a purely technical nice-to-have
> justification is dubious. We need some real world examples or input.

My own guess is that is going to be hard to come by on this one. This proposal
grew out an attempt to save "with type"; now that that has been scuttled, the
need for this one is much less compelling.

At least, this proposal gets rid of the run-time accessibility for every object
that we had discussed at the last meeting. But I'm still concerned that static
accessibility might not be enough to implement this (especially in shared
generics, where the static level /= instantiation level).

If I ever get some spare time, I'll have to think about this one some more.

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

From: Robert Dewar
Sent: Monday, October 1, 2001  8:27 PM

<<My own guess is that is going to be hard to come by on this one. This
proposal grew out an attempt to save "with type"; now that that has been
scuttled, the need for this one is much less compelling.>>

The important thing to realize about proposals for additions is that the
dynamics have in my view shifted completely. In the old days, the ARG
could via WG9 and ACATS essentially command all implementors to implement
feature X and they had to jump.

Now, at least speaking for ACT, but I suspect for other vendors too, the
issue of whether new features get implemented is far more dependent on
what real customers want. If a new feature is approved, or even "mandated"
it will not get implemented unless customers need/want it implemented and
resources are consequently available.

That's why it is so important to make sure that real demand exists before
we sit around designing neat features that would be nice to have.

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

From: Tucker Taft
Sent: Monday, October 1, 2001 11:29 PM

Randy Brukardt wrote:
> ...
> > The important thing here is that the justification include some evidence
> > that this is a real world issue, i.e. a purely technical nice-to-have
> > justification is dubious. We need some real world examples or input.
>
> My own guess is that is going to be hard to come by on this one. This
> proposal grew out an attempt to save "with type"; now that that has been
> scuttled, the need for this one is much less compelling.

I don't see that as the primary justification. The major
need relates to the large number of unnecessary explicit
conversions when using Ada 95 for "normal" OO-style
programming. The connection with "with type" was pretty
remote, in my view.

>
> At least, this proposal gets rid of the run-time accessibility for every
> object that we had discussed at the last meeting. But I'm still concerned
> that static accessibility might not be enough to implement this (especially
> in shared generics, where the static level /= instantiation level).
>
> If I ever get some spare time, I'll have to think about this one some more.

In thinking about this more, I have concluded that we should allow
access_definitions in component subtype indications, but with the
same rules as for discriminants, namely that the accessibility level
of the anon subtype is the same as the level of the enclosing composite
object. This jibes with the fact that typically a set of objects that
point at each other all have the same lifetime.

I didn't adequately deal with allocators. I think if an allocator appears
as the expression of a return statement, where the return type is specified
using an access_definition, then the storage pool to use for the allocator
is determined by the caller. This creates a very useful capability for
a function to do an allocation in a storage pool determined by context.
This is a fundamental requirement for region-based memory allocation,
which is becoming recognized as the "thinking person's alternative" to
full garbage collection. This argues for a uniform treatment of
such functions, namely that they are implicitly passed both the "caller"
accessibility level and the target storage pool for allocators.

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

From: Robert Dewar
Sent: Tuesday, October 2, 2001  5:22 AM


<<I don't see that as the primary justification. The major
need relates to the large number of unnecessary explicit
conversions when using Ada 95 for "normal" OO-style
programming. The connection with "with type" was pretty
remote, in my view.
>>

That's one level remote to me, I need a "major need" to be expressed
in terms of actual people writing actual code with actual needs and
examples.

I am afraid that the ARG is trying to take on the job of requirements
gathering for language enhancements without sufficient connection to
the outside world. We haven't even asked *vendors* what they think is
important, let alone asking actual Ada users. Language designers are
not the right people to be deciding on what is really important to
add.

For example, if you were to ask ACT what the single most important
feature needed was, I suspect it would be C++ interfacing features.
I certainly can't remember any customer asking about "large number
of unnecessary explicit conversions" :-)

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

From: Randy Brukardt
Sent: Tuesday, October 2, 2001 1:18 PM

> I am afraid that the ARG is trying to take on the job of requirements
> gathering for language enhancements without sufficient connection to
> the outside world. We haven't even asked *vendors* what they think is
> important, let alone asking actual Ada users.

Many vendors participate in this group, and have rarely been shy about
expressing their views. Certainly, ACT has been happy to provide this at every
opportunity. :-)

But I would caution against using requests to vendors as the only criteria. The
Ada community has a strong commitment to following standards, and thus I would
not expect most customers to ask their vendor to "break" the standard.
Therefore, I'd expect enhancement requests to vendors to involve areas outside
of the standard (interfacing to other languages, additional provided packages,
performance issues, etc.), and most of that isn't interesting to the ARG any.

To take a specific example. When we were building Claw, we wasted a lot of time
tracking down "bugs" caused by broken overridding (where we thought some
routine was overridding, but wasn't due to a spelling error or missing
parameter). We didn't run to a vendor (even though I probably could have
convinced one to do something :-) to fix this: we just put it down to bad
language design and lived with it. The only thing we did is mention it toward
the end of our paper on Claw. Only when I wrote up an amendment AI on the topic
(mainly to provide a fully fleshed out example AI to get comments on the format
of an amendment) did I find out that many other people shared this frustration.
I doubt anyone ran to ACT to ask for an enhancement here (although they might
now that there is a fully defined solution).

> Language designers are not the right people to be deciding on what is
> really important to add.

This is true, but I would argue that the majority of the ARG membership aren't
"language designers" per se, but vendors and/or users of Ada. Of course,
everyone is a "language designer" from time-to-time.

> I need a "major need" to be expressed
> in terms of actual people writing actual code with actual needs and
> examples.

For this particular AI, I certainly agree. So far as I remember, the problem
was driven by complaints from Erhard's students. While these are "actual
people", I have my doubts that they meet the "actual needs" qualification.
Moreover, we built Claw (certainly a large O-O system) without running into
this problem. I would much rather have "in out" parameters on functions (as
that would fix a real problem that we have had with O-O programs) than this
proposal [access parameters are not a real replacement for "in out" parameters,
as the calls are much more complex].

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

From: Robert Dewar
Sent: Tuesday, October 2, 2001  1:44 PM

<<Many vendors participate in this group, and have rarely been shy about
expressing their views. Certainly, ACT has been happy to provide this at
every opportunity. :-)>>

There is a different between having some technical person participating
in the ARG meetings, and getting formal input from vendors.

<<But I would caution against using requests to vendors as the only criteria.
The Ada community has a strong commitment to following standards, and thus I
would not expect most customers to ask their vendor to "break" the standard.
Therefore, I'd expect enhancement requests to vendors to involve areas
outside of the standard (interfacing to other languages, additional provided
packages, performance issues, etc.), and most of that isn't interesting to
the ARG any.>>

The ARG should be more interested in such issues. yes, I know it is more
fun for language designers to design neat new features -- and that's my
point.

Surely we should not use requests to vendors as the only criterion, but
it's a better sole criterion than using the input from language designers
as the only criterion.

In fact we get a wide variety of requests from customers, after all,
WITH TYPE is there because customers needed it, not because there was
some AI suggesting it, as an example.

<<Only when I wrote up an amendment AI on the topic (mainly to provide a fully
fleshed out example AI to get comments on the format of an amendment) did I
find out that many other people shared this frustration. I doubt anyone ran
to ACT to ask for an enhancement here (although they might now that there is
a fully defined solution).
>>

Remember that in our environment, customers ask us if they have any
questions or problems whatsoever in using Ada. All the time, they
are asking us "how do we do this in Ada", or "can't we find a better
way of doing things than this". So indeed we have lots of input of
this kind, but I can't find many things that would be worth new language
features.

Right now, I think there is a real danger of designing language features
that no one will implement, and thus making an updated standard irrelevant.

<<For this particular AI, I certainly agree. So far as I remember, the problem
was driven by complaints from Erhard's students. While these are "actual
people", I have my doubts that they meet the "actual needs" qualification.
Moreover, we built Claw (certainly a large O-O system) without running into
this problem. I would much rather have "in out" parameters on functions (as
that would fix a real problem that we have had with O-O programs) than
proposal [access parameters are not a real replacement for "in out"
parameters, as the calls are much more complex].
>>

The lack of in out parameters in functions, a restriction that as far as
I can tell is, like the peculiar declaration ordering rules in 83, there
only because someone thinks it is more consistent with some particular
coding philosophy (*), is indeed a significant problem.

Robert Dewar

(*) I continue to find it odd that the design principle for functions in
the Ada language is "functions can have arbitrary side effects, but no
hint of this is allowed in the function specification. If you want to
make a state change in a function, it cannot be done using IN OUT
parameters in the spec, instead it must be done covertly using global
variables" :-)

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

From: Dan Eilers
Sent: Tuesday, October 2, 2001  2:13 PM

Robert Dewar wrote:

> (*) I continue to find it odd that the design principle for functions in
> the Ada language is "functions can have arbitrary side effects, but no
> hint of this is allowed in the function specification. If you want to
> make a state change in a function, it cannot be done using IN OUT
> parameters in the spec, instead it must be done covertly using global
> variables" :-)

Well, to some extent, declaring a global variable is an overt invitation
for modification by any code within its scope. The covertness problem
with IN OUT parameters on functions is that there is no indication at
the point of the call that parameters might be modified, where such
parameters are likely to be local variables with no signal to the
reader that they are modified by the function call. I believe this
problem was pointed out in C.A.R. Hoare's famous 1973 paper "Hints
on Programming Language Design".

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

From: Randy Brukardt
Sent: Tuesday, October 2, 2001  3:08 PM

Which of course applies equally to procedure calls. And I have been
occassionally surprised by procedures modifying parameters, and it would be
nice if that was identified in the call. But it seems about 20 years too late
to complain about that...

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

From: Robert Dewar
Sent: Tuesday, October 2, 2001  10:39 PM

Fine, people who have this point of view can restrict their use of the
language. No one suggests removing USE clauses just because some
people think they are a bad idea.

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

From: Dave Emery
Sent: Tuesday, October 2, 2001  2:10 PM

At 14:44 -0400 10/2/01, dewar@GNAT.COM wrote:
>...
>The lack of in out parameters in functions, a restriction that as far as
>I can tell is, like the peculiar declaration ordering rules in 83, there
>only because someone thinks it is more consistent with some particular
>coding philosophy (*), is indeed a significant problem.

Can I vote for reconsidering/removing this (stupid) restriction?

If one argument in favor of keeping it is to allow the compiler
or some third-party verification tool to assume or to check
that the function has no side-effects, I'd rather do that
check with a pragma, and allow/trust the user to do the
right thing at the right time. Certainly this has been
a very painful restriction for interfacing with other languages
that do not accept this point of dogma :-)

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

From: Randy Brukardt
Sent: Tuesday, October 2, 2001  3:03 PM

> The ARG should be more interested in such issues. yes, I know it is more
> fun for language designers to design neat new features -- and that's my
> point.

I understand, but in practice, there haven't been much in the way of expanding
the language. When I proposed the Ada.Directories package, there was a lot of
opposition of "not important enough" (and you originally led the charge on
that). As far as C++ interfacing goes, we discussed this at the Westboro
meeting (September 1999), but no one had any proposals on what to do. The
existing work was all rather implementation-dependent. (Ed was at that meeting,
and presented various GNAT features to the group, but I don't recall if he was
there for this discussion.) And so far as I know, nothing has been proposed
since.


> Remember that in our environment, customers ask us if they have any
> questions or problems whatsoever in using Ada. All the time, they
> are asking us "how do we do this in Ada", or "can't we find a better
> way of doing things than this". So indeed we have lots of input of
> this kind, but I can't find many things that would be worth
> new language features.

I also get questions of the sort of "how do you do X?", but I'm never thinking
about new language features when I answer them. "Wait until 2006" doesn't seem
likely to satisfy many customers!

> Right now, I think there is a real danger of designing language features
> that no one will implement, and thus making an updated standard irrelevant.

Understandable, and AI-230 is certainly a possible offender in this area.

> The lack of in out parameters in functions, a restriction that as far as
> I can tell is, like the peculiar declaration ordering rules in 83, there
> only because someone thinks it is more consistent with some particular
> coding philosophy (*), is indeed a significant problem.

I've always figured that I should have the power to re-open this issue, as I
was one of the people who fought tooth-and-nail to keep it in Ada 95. The main
reason is that the Janus/Ada intermediate code does not allow copy-back for
function calls -- and changing this would be a very large change to the
optimizer and code generator. (Function calls always discard their parameters.)

My mind was changed by our work on Claw. The first problem was a query
function:

    function Is_Something (Window : in Root_Window_Type) return Boolean is
    begin
       -- Long calculation involving several system calls.
       return Answer;
    end Is_Something;

Is_Something (I forget the exact function involved) was likely to be called
frequently, so I wanted to save the result I calculated in the Window object.
So I added a component to save the value and a component to say whether the
first component was, and got a compile-time error trying to set them. Ugh.

The problem has occurred repeatedly during the development of Claw. Some
operations that we would have preferred to be functions ended up as procedures
since we needed to modify the object. On a few occasions, we used the fact that
Claw objects are assignable, and "clones" of each other to work around the
problem:

   function Is_Something (Window : in Root_Window_Type) return Boolean is
       Writable_Copy : Root_Window_Type'Class := Window;
   begin
       -- Modify components of Writable_Copy, which modifies the original object.
       return Answer;
   end Is_Something;

But that is horrible (and inefficient).

I've tried to raise the "in out" issue at the ARG meetings without success.
People are afraid that the same old bunch of opponents (minus at least one --
me!) would resurface.

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

From: Tucker Taft
Sent: Friday, February 1, 2002  11:54 AM

Here is an update to ai-00230 on anonymous access types.
I was able to resolve the problems that I had with them last time,
while eliminating the mind-bending named subtypes of anonymous access types,
but adding back components of an anonymous access type.

I think it all works safely and usefully now, especially presuming
the syntax for "access_definition" is generalized (see ai-231) to allow
control over nullness, and constantness of the designated object.

[See AI body for current proposal - Ed.]

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

Editor's notes, October 22, 2003

In creating !corrigendum sections for this AI, I noticed that several wording
changes are needed only if AI-231 is approved. I moved these wording changes
to that AI. AI-231 should be written to presume that AI-230 is approved (as it
is ahead of AI-231 in the ARG process); in particular, the needed change to
8.5.1(4) should be included in AI-231.

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

From: Javier Miranda
Sent: Tuesday, January 27, 2004  10:50 AM

Following paragraph was removed from version 1.13 to version 1.14:

-Change 3.4.1(3) as follows:
-
-   Every type is either a specific type, a class-wide type, or a universal
-   type. A specific type is one defined by a type_declaration, a
-   formal_type_declaration, an access_definition, or a full type definition
-   embedded in a declaration for an object. Class-wide and universal types are
-   implicitly defined, to act as representatives for an entire class of types,
-   as follows:

As a consequence, following paragraph (in the !discussion section)
should also be removed:

"We also fix an RM bug here; 3.4.1(3) says that all types are either specific,
 class-wide, or universal, but then fails to include access_definition (for
 anonymous access types) in any of those categories."

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

From: Bob Duff
Sent: Monday, June 6, 2005  12:38 PM

I'm using draft 11.8 of the [A]ARM.

6.1(15/2):

15/2  {AI95-00231-01} parameter_specification ::=
          defining_identifier_list : mode [null_exclusion] subtype_mark
       [:= default_expression]
        | defining_identifier_list : access_definition
       [:= default_expression]

Why do we disallow access parameters of modes 'in out' or 'out'?
We've gone to all this trouble to allow anonymous access types everywhere, but
here's a case where programmer's will have to declare a named access type.

Are there any other cases where the name of an access type is allowed, but an
access definition is not?

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

From: Tucker Taft
Sent: Monday, June 6, 2005  7:27 PM

Groan.  I think there could be some significant
implementation issues and possible dangling-reference
possibilities with writable access parameters,
since their accessibility level is dynamic.
I also find the idea of "out access constant D"
pretty painful to imagine, bordering on the
C++ "const" nightmare.  I think we would be
asking for trouble to introduce these at this
late date.

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

From: Randy Brukardt
Sent: Monday, June 6, 2005  9:59 PM

> Why do we disallow access parameters of modes 'in out' or 'out'?

I don't know, ask the Ada 9X team. :-) They were requested several times, I
believe.

> We've gone to all this trouble to allow anonymous access types everywhere, but
> here's a case where programmer's will have to declare a named access type.

As Tucker points out, they would be a real mess to allow, mainly because of
accessibility. Of course, the only reason we need these special properties
are because some people wouldn't allow "in out" parameters (at least for
tagged types) in functions. But that will never be fixed, and thus we're
stuck with this abomination.

> Are there any other cases where the name of an access type is allowed, but an
> access definition is not?

A type conversion or qualification, of course. And I can hardly imagine
trying to fix that!  Imagine:

    List := not null access constant T(Func(A, B));

John's work on the Rationale shows that you need named types in various
cases not having to do with parameter passing, in part because the implicit
conversions are only allowed when the checks cannot fail. And there are
enough cases where the checks *could* fail that I think most stuff will end
up using named types anyway.

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

From: Pascal Leroy
Sent: Tuesday, June 7, 2005  3:34 AM

> Why do we disallow access parameters of modes 'in out' or
> 'out'?

Arrrgh!  Don't even think of it at this late stage.

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

From: Gary Dismukes
Sent: Tuesday, June 7, 2005  12:37 PM

> John's work on the Rationale shows that you need named types in various
> cases not having to do with parameter passing, in part because the implicit
> conversions are only allowed when the checks cannot fail. And there are
> enough cases where the checks *could* fail that I think most stuff will end
> up using named types anyway.

This comment of Randy's caught my eye.  Specifically, I'm wondering about
the part that says "implicit conversions are only allowed when the checks
cannot fail."  What does that follow from?  In the process of considering
accessibility checks needed for the new entities that can have an anonymous
access type I was looking at cases such as the following:

   A : access Integer := ...;

   procedure Proc (X : access Integer) is
   begin
      A := X;
   end Proc;

If the above assignment is legal then it clearly requires a run-time check.
Is there a rule I'm missing that makes the assignment illegal?

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

From: Randy Brukardt
Sent: Tuesday, June 7, 2005  1:49 PM

> This comment of Randy's caught my eye.  Specifically, I'm wondering about
> the part that says "implicit conversions are only allowed when the checks
> cannot fail."  What does that follow from?

That's the basic principle of implicit conversions, as explained by Tucker.

> In the process of considering accessibility checks needed for the new
> entities that can have an anonymous access type I was looking at cases
> such as the following:
>
>    A : access Integer := ...;
>
>    procedure Proc (X : access Integer) is
>    begin
>       A := X;
>    end Proc;
>
> If the above assignment is legal then it clearly requires a run-time check.
> Is there a rule I'm missing that makes the assignment illegal?

I can't find one, which means either that the "basic principle" is garbage
(which makes me wonder why we don't allow tag checks in this case), or its
missing (which would make things less usable, of course). I don't see much
difference between tag checks and accessibility checks.

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

From: Tucker Taft
Sent: Tuesday, June 7, 2005  3:30 PM

I think I must have been dreaming.

Imnplicit conversions are a result of the overload
resolution rules.  They allow a particular "actual"
type to match a particular "expected" type.
The rules do not allow "downward" (narrowing)
implicit conversions.  They say nothing
about accessibility.

4.6(17,20) (in the Ada *95* RM) disallow conversions
(implicit or explicit) when the static accessibility check
fails, but allow anonymous-to-anonymous
"implicit" conversion when a run-time check is required.

In fact, this already happens in Ada 95 in the following:

     type T(access Integer) is limited null record;
     type Acc_T is access T;
     function New_T(X : access Integer) return Acc_T is
     begin
         return new T(X); -- accessibility check on implicit
                          -- acc type conversion
     end New_T;

So I was obviously confused.

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

From: Robert A. Duff
Sent: Friday, January 6, 2006  7:17 PM

Wording question related to user-defined "=" operators:

RM-4.5.2 says:

6     The equality operators are predefined for every specific type T that is
not limited, and not an anonymous access type, with the following
specifications:

So equality operators are predefined for composite types containing anonymous
access types:

    type T is
        record
            X: access Integer;
        end record;
    -- function "="(Left, Right: T) return Boolean is predefined.

But (for composite types):

24    Otherwise, the result is defined in terms of the primitive equals
      operator for any matching tagged components, and the predefined equals
      for any matching untagged components.

But the "predefined equals" for X above does not exist.

Furthermore, the notion of "THE primitive equals operator" is questionable
wording:

    package P is
        type T is tagged...;
        function "="(X: T; Y: Integer) return Integer;

"=" is primitive of T, and it's an "equals operator", but it's not intended to
be THE primitive equals operator of T.

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

From: Tucker Taft
Sent: Saturday, January 7, 2006  9:13 AM

> 24    Otherwise, the result is defined in terms of the primitive equals
>       operator for any matching tagged components, and the predefined equals
>       for any matching untagged components.
>
> But the "predefined equals" for X above does not exist.

I think that clearly has to refer to the predefined equals
operator in Standard applicable to all anonymous access
types.  What else could it mean?

It is interesting to me that we debated whether we should have
this predefined equality operator in Standard somewhat independently
of whether we should have anonymous access type components
and discriminants of non-limited composite types.  But as you
point out, there is a clear need for some kind of predefined
equality operator for anonymous access types as soon as we
allow them as components of non-limited types.

>
> Furthermore, the notion of "THE primitive equals operator" is questionable
> wording:
>
>     package P is
>         type T is tagged...;
>         function "="(X: T; Y: Integer) return Integer;
>
> "=" is primitive of T, and it's an "equals operator", but it's not intended to
> be THE primitive equals operator of T.

True, though this hasn't changed since Ada 95, and clearly has
been interpreted by every implementation (and hopefully every user)
to mean the primitive equals operator where both operands
are of the same type.

Neither of these seems too bad on the scale of wording clarity.
Did you encounter a problem or question that highlighted
the admitted possible ambiguity?

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

From: Randy Brukardt
Sent: Saturday, January 7, 2006  6:46 PM

...
> RM-4.5.2 says:
...
> But (for composite types):
>
> 24    Otherwise, the result is defined in terms of the primitive equals
>       operator for any matching tagged components, and the predefined equals
>       for any matching untagged components.
>
> But the "predefined equals" for X above does not exist.

It probably would be best to fix this wording to say the "predefined equals
for universal_access for any matching anonymous access components, and the
predefined equals for any other matching untagged components."

But, as Tucker points out, this seems like a fine point.

> Furthermore, the notion of "THE primitive equals operator" is questionable
> wording:
...

Sure. But this is Ada 95 wording; nothing has changed, and you probably
wrote this wording yourself :-), so I don't think it is worth changing.

And in any case, you have to suggest replacement wording, not just gripe.
:-) :-)
"the primitive equals operator with both parameters of the type and
returning Boolean" seems like too much.

Perhaps both issues should be addressed by a "To Be Honest" note???

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

From: Tucker Taft
Sent: Sunday, January 8, 2006  9:08 AM

> ...
> Perhaps both issues should be addressed by a "To Be Honest" note???

That would be my inclination, unless Bob sees a more
serious problem underlying the current words.
I don't at the moment see any possibility for actual
confusion.

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

From: Robert A. Duff
Sent: Sunday, January 8, 2006 12:07 PM

I was momentarily confused about the anon access case.
The other case is pure nitpicking.

Anyway, I agree with Randy and Tuck here -- To Be Honest is sufficient.

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

From: Robert I. Eachus
Sent: Saturday, January 7, 2006  9:44 PM

>24    Otherwise, the result is defined in terms of the primitive equals
> operator for any matching tagged components, and the predefined equals for
> any matching untagged components.

Technically I guess that removing the two 'any's would clarify this. You
could even go so far as to say "the primitive equals for pairs of
matching tagged components, and the predefined equals for pairs of
matching untagged components..."  But that seems excessive to me.

As for the issue of equality of anonymous access types, I think a note
would be appropriate.  Especially if the note made it clear what happens
if one of the access values resulted from a call to Unchecked_Access and
is no longer valid.  (Thinking about it, a note for the Unchecked_Access
case really belongs in 4.5.2.)  Or maybe it shouldn't be a note?  My
inclination is to allow code to seg fault in this case, but there is a
lot to be said for requiring that 4.5.2(33) Note 13 hold:

13 No exception is ever raised by a membership test, by a predefined
ordering operator, or by a predefined equality
operator for an elementary type, but an exception can be raised by the
evaluation of the operands. A predefined equality
operator for a composite type can only raise an exception if the type
has a tagged part whose primitive equals operator
propagates an exception.

It is tempting to leave the comparison to a no longer valid annonymous
access value  as an erroneous execution case.  However,  I suspect that
all realistic compilers would not have any work to do if this is made a
bounded error, returning True or False. (The corner case would be when
the stack grows, then shrinks, and the now unused pages for the stack
are given back to the OS.  Does anyone do that?)  This just seems like
it should be less dangerous than the case where a programmer has called
Unchecked_Deallocation on an object of a (named) access type. That does
result in a bounded error, at least for realistic cases.

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

From: Pascal Leroy
Sent: Monday, January 9, 2006  2:14 AM

> It is tempting to leave the comparison to a no longer valid
> annonymous
> access value  as an erroneous execution case.

This has been discussed many times in the past, and there doesn't seem to
be any good reason for erroneousness here.

An invalid access value is just a bit pattern.  You want to test it for
equality, fine, compare that bit pattern using one or several integer
comparison instructions.  I can't think of a machine where that would be
problematic.  Also, I can't think of a reason why you would want to
dereference the access value or otherwise check that it corresponds to a
valid address in order to implement equality.  The bottom line is, the
natural implementation is that you get either True or False, but no
erroneousness.

Of course, if you *dereference* such an access value (e.g., by using .all
in the source) then all bets are off.

None of that is specific to anonymous access types, btw.

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

From: Robert Dewar
Sent: Monday, January 9, 2006  5:38 AM

> An invalid access value is just a bit pattern. You want to test it for
>
>equality, fine, compare that bit pattern using one or several integer
>comparison instructions.  I can't think of a machine where that would be
>problematic.  Also, I can't think of a reason why you would want to
>dereference the access value or otherwise check that it corresponds to a
>valid address in order to implement equality.  The bottom line is, the
>natural implementation is that you get either True or False, but no
>erroneousness.

I agree. In fact I would generalize and say that ALL comparisons of
discrete types and access values
(not fpt), will always generate True or False under all circumstances.

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

From: Robert I. Eachus
Sent: Monday, January 9, 2006  2:49 PM

...
>None of that is specific to anonymous access types, btw.

I totally agree that there is no reason to allow an exception or worse
in this case.  I just can't find in the RM where it says that.  Or
rather,  RM 4.5.2(33), which is a note, goes out of its way to be
ambiguous in this case:  (Quoting from draft 15.)

13 No exception is ever raised by a membership test, by a predefined
ordering operator, or by a predefined equality
operator for an elementary type, but an exception can be raised by the
evaluation of the operands. A predefined equality
operator for a composite type can only raise an exception if the type
has a tagged part whose primitive equals operator
propagates an exception.

Yes, it is common sense that equality for annonymous access types does
not need to dereference the values to compare them, but we are now
navigating in murky water.  There is still hardware around where loading
an invalid bit-pattern into an address register can cause a problem.
(For example, the Motorola 68000, but not the 68020 or later, would not
allow an odd byte address in certain registers.  A more modern example
is that some 64-bit hardware requires that some of the upper bits of a
valid address be zero.)  That should not be an issue here.  We know that
at one point the address was valid, and even if the data is no longer
valid, the bit pattern should still be safe.

That is what I was referring to above.  Should be easy enough to fix.
Just add a statement to 4.5.2 saying that equality for access types does
not read the designated values of its parameters.  But that starts to
open the can of worms I suggested we leave closed.   RM 4.5.2(13) is
intended to allow access-to-subprogram values to be handles, or to in
some other way encode the context of a particular suprogram instance.
Should equality for access-to-subprogram values be allowed to
dereference the handle, but not the designated subprogram?

As I said, I think that this corner of the language is best left
undefined.  To me using the predefined testing for equality of an object
containing pointers (whatever we call them) is of dubious value anyway.
Defining what happens when one or more of those pointers is invalid is
even less likely to ever matter to anyone.  Not testing access values
for equality, but testing structures containing access values for equality.

In most such cases the programmer defining the type will probably want
to define what equality means, or even if it is valid.  Which of course
is how we got here.  The original issue under discussion was a paragraph
defining equality for containers that do, in fact, have a generic formal
equality operator for elements.  Further our goal was not to specify the
equality operation more strictly, but to rewrite the paragraph to insure
that (potentially) unnecessary calls to the generic formal "=" are
permitted but not required.

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

From: Robert Dewar
Sent: Monday, January 9, 2006  6:14 PM

> 13 No exception is ever raised by a membership test, by a predefined
> ordering operator, or by a predefined equality
> operator for an elementary type, but an exception can be raised by the
> evaluation of the operands. A predefined equality
> operator for a composite type can only raise an exception if the type
> has a tagged part whose primitive equals operator
> propagates an exception.

AArgh! aren't floating-point types elementary? It is obvious that a fpt
equality test can raise an exception if the arguments are invalid
representations and happen to be signalling NaN's

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

From: Randy Brukardt
Sent: Monday, January 9, 2006  11:40 PM

Well, this is a note, so it has no normative impact. And it dates back to
Ada 95. OTOH, there are a number of counter-examples here, and we generally
don't want notes that are wrong. I think we could make an argument for
deleting it, but I have to wonder if it is sufficiently wrong for that...

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

From: Pascal Leroy
Sent: Tuesday, January 10, 2006  3:25 AM

I would assume that an sNaN is an invalid representation, and that using
it is a bounded error that can raise C_E or P_E (see 13.9.1(9)).  So this
appears to be covered by normative wording.  The note might be slightly
misleading, but we don't normally clutter notes with junk that says
"except in the case of bounded errors, erroneous execution, plague or
pestilence".

The same applies if an implementation chooses to implement some
fixed-point types using a float representation, which is legitimate
assuming that it can provide the appropriate high-level semantics.  sNaN
is invalid and an exception is raised.

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

From: Robert Dewar
Sent: Tuesday, January 10, 2006  5:56 AM

>Well, this is a note, so it has no normative impact. And it dates back to
>Ada 95. OTOH, there are a number of counter-examples here, and we generally
>don't want notes that are wrong. I think we could make an argument for
>deleting it, but I have to wonder if it is sufficiently wrong for that...

Yes, it is sufficiently wrong, because it might induce people to think that fpt
comparisons are safe. And it might even make implementors think they have to
futz around catching NaN exceptions.

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

From: Robert Dewar
Sent: Tuesday, January 10, 2006  5:59 AM

>I would assume that an sNaN is an invalid representation, and that using
>it is a bounded error that can raise C_E or P_E (see 13.9.1(9)).  So this
>appears to be covered by normative wording.  The note might be slightly
>misleading, but we don't normally clutter notes with junk that says
>"except in the case of bounded errors, erroneous execution, plague or
>pestilence".

But this note is complete junk for the normal case, of course equality
works in these cases.

>The same applies if an implementation chooses to implement some
>fixed-point types using a float representation, which is legitimate
>assuming that it can provide the appropriate high-level semantics.  sNaN
>is invalid and an exception is raised.

So just junk the note. It is actively unhelpful

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

From: Robert Dewar
Sent: Tuesday, January 10, 2006  6:01 AM

>The same applies if an implementation chooses to implement some
>fixed-point types using a float representation, which is legitimate
>assuming that it can provide the appropriate high-level semantics.  sNaN
>is invalid and an exception is raised.

Note that in my previous message I said discrete or access types, and that's
because the above situation is perfectly reasonable and familiar. I do think
there is some advantage in stopping implementations from doing peculiar things
in the discrete/access type cases.

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

From: Robert A. Duff
Sent: Tuesday, January 10, 2006  8:29 AM

> Well, this is a note, so it has no normative impact. And it dates back to
> Ada 95. OTOH, there are a number of counter-examples here, and we generally
> don't want notes that are wrong. I think we could make an argument for
> deleting it, but I have to wonder if it is sufficiently wrong for that...

There was a similar note in Ada 83, and the above wording was an attempt to
salvage the note by making it correct.  We probably should have just deleted it
in Ada 95.  It doesn't say anything terribly interesting for Ada 83, and even
less so for Ada 95, because of the new rules about invalid values.

In "X = Y", if X is a signalling NaN, the evaluation of X is what raises the
exception.  The "=" does not raise an exception in that case, but so what?

I say, delete the note.  It's unhelpful, and if you're not a language lawyer,
it could be misleading.

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

From: Robert Dewar
Sent: Tuesday, January 10, 2006  3:59 PM

> In "X = Y", if X is a signalling NaN, the evaluation of X is what
> raises the exception.  The "=" does not raise an exception in that case,
> but so what?

Not always .. on some machines it is the equality operation which would
trap. In any case the distinction is unhelpful!

>I say, delete the note.  It's unhelpful, and if you're not a language lawyer,
>it could be misleading.

I agree.

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

From: Randy Brukardt
Sent: Tuesday, January 10, 2006  4:02 PM

> Note that in my previous message I said discrete or access types, and
> that's because the above situation is perfectly reasonable and familiar.
> I do think there is some advantage in stopping implementations from doing
> peculiar things in the discrete/access type cases.

But, normatively, the situation is the same. It would be easy to imagine an
implementation that raised Program_Error if it read an invalid holey
enumeration value, for instance. (Indeed, Janus/Ada would do just that, if the
optimizer is off; canonically, all holey enumeration values are loaded into
registers as position numbers (so as to be able to use them for indexing and
looping). The optimizer removes unneeded lookups, but if it is off, the
operation would occur and raise an exception.)

If we *really* wanted to say something about discrete and/or access type
comparisons, I think we'd need Implementation Advice. (I cannot see how we
could make this a requirement, given that it would be a "not withstanding"
rule. And there are a lot of cases identified where there might be a problem.)
Which is a lot bigger deal than removing a confusing note, and probably too
late for the Amendment.

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

From: Randy Brukardt
Sent: Tuesday, January 10, 2006  4:15 PM

I also should comment that such an IA would be rather contrary to the decision
for validity elsewhere (as discussed in AI-426). We essentially decided that an
implementation is never required to store an invalid value; it is *always*
allowed to raise an exception instead (of course, it can store invalid values
if it wants to). It would seem very odd to say something different here; this
case doesn't seem anywhere near as important as the Unchecked_Conversion one
that we were discussing in AI-426.

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


Questions? Ask the ACAA Technical Agent