CVS difference for ais/ai-00184.txt
--- ais/ai-00184.txt 1998/09/30 00:17:34 1.1
+++ ais/ai-00184.txt 1998/10/01 00:12:33 1.2
@@ -1,26 +1,134 @@
-!standard 04.06 (54) 97-03-19 AI95-00184/01
+!standard 04.06 (54) 97-03-29 AI95-00184/02
!class binding interpretation 97-03-19
!status work item 97-03-19
!status received 97-03-19
!priority High
!difficulty Hard
-!subject View conversion to an indefinite subtype
+!subject Definiteness and type derivation
-!summary 97-03-19
+!summary 98-03-29
+It is illegal to rename a component that depends on a discriminant of
+a variable whose nominal subtype is an indefinite generic formal type
+(or a descendant of such a type).
+
+A view conversion cannot be used to obtain a indefinite view of an
+object whose nominal subtype is definite.
+
+!question 98-03-29
+
+The definiteness of a type is not preserved by type derivation. A type with
+defaulted discriminants may be derived from a type without defaulted
+discriminants and vice-versa.
+
+This makes it possible to rename a component of a record that later
+disappears
+due to an assignment to the enclosing object, as shown in the following
+examples:
+
+1 - An example where the parent type is indefinite and the derived type is
+definite:
+
+ type T1 (D1 : Boolean) is
+ record
+ case D1 is
+ when False =>
+ C1 : Integer;
+ when True =>
+ C2 : Float;
+ end case;
+ end record;
+
+ generic
+ type F is new T1;
+ X : in out F;
+ package G is
+ C1_Ren : Integer renames X.C1;
+ end G;
+
+ type T2 (D2 : Boolean := True) is new T1 (D1 => D2);
+
+ Y : T2;
+
+ package I is new G (T2, Y);
+
+ Y := (D1 => True, C2 => 3.0); -- Oops! What happened to I.C1_Ren
+
+The declaration of C1_Ren in the generic G is legal as per RM95 8.5.1(5),
+because the formal type F is indefinite. But when G is instantiated with
+type
+T2, the actual type is definite, so now we have renamed a component that may
+disappear by assignment to the variable Y. Note that the declaration of
+C1_Ren might be in the body of G, so we cannot avoid this problem by
+rechecking RM95 8.5.1(5) on the instantiation.
-!question 97-03-19
+2 - An example where the parent type is definite and the derived type is
+indefinite:
+ type Definite_Parent (D1 : Integer := 6) is
+ record
+ F : String (1 .. D1);
+ end record;
-!recommendation 97-03-19
+ type Indefinite_Child (D2 : Integer) is new Definite_Parent (D1 =>
+D2);
+ Y : Definite_Parent;
-!wording 97-03-19
+ procedure P (X : in out Indefinite_Child) is
+ C : Character renames X.F (3);
+ begin
+ X := (0, "");
+ -- X.F (3) has disappeared!
+ end;
+ begin
+ P (Indefinite_Child (Y));
+Assume that the implementation chooses to pass X by reference. Then,
+6.4.1(10) says that there is an implicit view conversion to
+Indefinite_Child,
+and the formal parameter X then denotes the result of this view conversion.
+ The result of the explicit view conversion is unconstrained, and the result
+of the implicit view conversion is also unconstrained, hence X is
+unconstrained, which violates the language design principle of NOTE 3.7(28).
-!discussion 97-03-19
+One of the unpleasant consequences of this violation is that the assignment
+to
+X doesn't raise an exception, and after the execution of this assignment C
+denotes a non-existent component.
+
+Note that if the implementation chooses to pass by copy, then there is an
+implicit value conversion -- see 6.4.1(11-11.a). So in that case, there's
+no
+problem.
+
+!recommendation 98-03-29
+
+(See wording.)
+
+!wording 98-03-29
+
+Change RM95 8.5.1(5) to read: "The renamed entity shall not be a
+subcomponent that depends on a discriminant of a variable whose nominal
+subtype is unconstrained, unless this subtype is indefinite and not
+a descendant of a generic formal type, or the variable is aliased."
+
+Add to RM95 4.6(24): "Furthermore, the target type shall be definite if
+the operand type is."
+
+!discussion 98-03-29
+We seem to have two options to fix the above problems:
+1 - Decide that definiteness cannot be changed by type derivation.
+Obviously
+this gets rid of the problems, but it is a big change and there may be user
+code out there that depends on this capability.
+
+2 - Try to plug individual holes and hope that there aren't too many of
+them.
+That's what was done in the !wording section.
+
!appendix 97-03-19
!section 4.6(54)
@@ -73,3 +181,76 @@
****************************************************************
+
+!topic Definiteness and type derivation
+!reference RM95 3.4
+!reference AI95-00184
+!from Pascal Leroy 97-10-14
+<<reference as: 1998-15825.c Pascal Leroy 1998-3-17>>
+!discussion
+
+The definiteness of a type is not preserved by type derivation. A type with
+defaulted discriminants may be derived from a type without defaulted
+discriminants and vice-versa.
+
+This has a number of pathological consequences, as shown by the examples
+below. Note that although these examples all have generics, the problems do
+not stem from generics: AI95-00184 has an example without generics.
+
+1 - A renamed subcomponent may disappear:
+
+ type T1 (D1 : Boolean) is
+ record
+ case D1 is
+ when False =>
+ C1 : Integer;
+ when True =>
+ C2 : Float;
+ end case;
+ end record;
+
+ generic
+ type F is new T1;
+ X : in out F;
+ package G is
+ C1_Ren : Integer renames X.C1;
+ end G;
+
+ type T2 (D2 : Boolean := True) is new T1 (D1 => D2);
+
+ Y : T2;
+
+ package I is new G (T2, Y);
+
+The declaration of C1_Ren in the generic G is legal as per RM95 8.5.1(5),
+because the formal type F is indefinite. But when G is instantiated with
+type
+T2, the actual type is definite, so now we have renamed a component that may
+disappear by assignment to the variable Y. Note that the declaration of
+C1_Ren might be in the body of G, so we cannot avoid this problem by
+rechecking RM95 8.5.1(5) on the instantiation.
+
+2 - It is possible to create an unconstrained object of an indefinite
+subtype:
+
+ type T1 (D1 : Boolean := True) is ...;
+ type T2 (D2 : Boolean) is new T1 (D1 => D2);
+
+ generic
+ type F is new T1;
+ package G is
+ X : F;
+ end G;
+
+ package I is new G (T2);
+
+The declaration of X in the generic G is legal because F has defaulted
+discriminants. But when G is instantiated with T2, discriminants don't have
+defaults, so we have created an object I.X without specifying a value for
+its
+discriminants. Again, the offending construct could be in the body of the
+generic, so it cannot be detected by rechecking the instantiation.
+
+****************************************************************
+
+
Questions? Ask the ACAA Technical Agent