Version 1.4 of ais/ai-00384.txt
!standard 04.06 (16) 04-11-09 AI95-00384/04
!class amendment 04-11-09
!status Amendment 200Y 04-09-22
!status WG9 approved 04-11-18
!status ARG Approved 9-0-0 04-09-18
!status work item 04-09-09
!status received 04-09-09
!priority Medium
!difficulty Medium
!subject Access to discriminated type conversion rules made symmetric
!summary
The legality rule in paragraph 4.6(16) for conversion between
access-to-nontagged-discriminated types is changed to be symmetric
by permitting conversion from an access-to-unconstrained type to an
access-to-constrained type (with an appropriate run-time check on the
conversion).
!problem
The legality rule in paragraph 4.6(16) is assymmetric
between the operand type and the target type. 4.6(50) already
requires a run-time check to verify that the designated object
satisfies the constraints of the target designated subtype,
so there seems no reason to disallow at compile-time the conversion
from an access-to-unconstrained to an access-to-constrained.
Here is an example of the problem:
procedure P is
type T(B : Boolean) is record ... end record;
type Acc_T is access all T;
type Acc_T_True is access all T(True);
X : Acc_T;
Y : Acc_T_True;
Z : Acc_T := Acc_T(Y); --
W : Acc_T_True := Acc_T_True(X); --
procedure Loc(A : in Acc_T) is ...
procedure Loc_Update(B : in out Acc_T) is ...
begin
Loc(Acc_T(Y)); -- legal by 4.6(16)
Loc_Update(Acc_T(Y)); -- illegal by 4.6(16,24)
...
end P;
There seems no reason to make the conversion to Acc_T_True
illegal above, since the run-time check specified by 4.6(50)
would catch any problem.
Similarly, because access values are passed by copy,
there is already a run-time check on copy "out" for an IN OUT or
OUT parameter, so there seems no reason to disallow the
view conversion of Y to Acc_T. The combination of 4.6(24)
and 4.6(16) currently makes that illegal in Ada 95.
!proposal
The legality rule in paragraph 4.6(16) for conversion between
access-to-nontagged-discriminated types should be changed to be symmetric
by permitting conversion from an access-to-unconstrained type to an
access-to-constrained type (with an appropriate run-time check on the
conversion).
!wording
Change 4.6(16) as follows:
... and either the designated subtypes shall statically match or [the
target] {one of the} designated subtype{s} shall be discriminated and
unconstrained; ...
AI-363 has a rewrite of this paragraph. It would be changed as follows:
* If the target designated type is not tagged, then the designated
types shall be the same, and either:
- the designated subtypes shall statically match; or
- the designated type shall be discriminated in its full view and
unconstrained in any partial view, and [the target] {one of the}
designated subtype{s} shall be unconstrained.
!discussion
Most of the legality rules for conversion between two types are symmetric.
The few cases of asymmetry have to do with accessibility, or class-wide-ness.
(And the class-wide-ness asymmetry is arguably also a mistake).
This symmetry is useful because reverse conversions are implicit in conversions
used as OUT or IN OUT parameters, and it is confusing if the illegality of
the reverse conversion makes a view conversion illegal.
For some reason, 4.6(16) has an asymmetric rule for conversion between
access-to-untagged-discriminated types. The likely reason is to minimize
the number of run-time checks associated with conversions. However, unlike
the case with the class-wide conversion asymmetry, where a simple work-around
is to convert first to a class-wide type and from there to a specific
descendant, there is no way around 4.6(16). You simply can't get "there"
from "here," when "there" is an access-to-constrained and "here" is an
access-to-unconstrained.
One conceivable concern might be the impact of changing 4.6(16) on
an implementation of discriminated records where the discriminants
are stored separately from the rest of the components. We don't know of
any implementations which do this, but it has been suggested as a possible
way to efficiently support physical units associated with numeric values.
However, if you think about this implementation model, it seems more likely
that 4.6(16) as written makes it harder rather than easier. For many
current compilers, array bounds are stored separately from the array
components, except for access-to-unconstrained array types. By storing
them together in this case, the access-to-unconstrained array type can
be represented by a single pointer. With this model, it is easier to
convert from an access-to-unconstrained to an access-to-constrained.
But this is the direction that 4.6(16) disallows. This would be
true for separated discriminants as well. Converting to
access-to-constrained would be easier than converting from
access-to-constrained, since when converting from access-to-constrained to
access-to-unconstrained, you need to somehow get the separated discriminants
into the heap. This is one reason we prohibited converting an
access-to-constrained-array into an access-to-unconstrained-array type.
!example
See the example in the problem section.
!corrigendum 4.6(16)
Replace the paragraph:
- If the target designated type is not tagged, then the designated types
shall be the same, and either the designated subtypes shall statically match or
the target designated subtype shall be discriminated and unconstrained; and
by:
- If the target designated type is not tagged, then the designated types
shall be the same, and either the designated subtypes shall statically match or
one of the designated subtypes shall be discriminated and unconstrained; and
!ACATS test
Create a C-Test to insure that these conversions are legal and checked at
runtime.
!appendix
****************************************************************
Questions? Ask the ACAA Technical Agent