!standard 4.3.2(8) 11-11-13 AI05-0282-1/02 !class binding interpretation 11-11-08 !status work item 11-11-08 !status received 11-09-26 !priority Low !difficulty Easy !qualifier Omission !subject Bad ancestor constraints for extension aggregates !summary ** TBD. !question 4.3.2(8) does not seem to apply if the ancestor is constrained. Consider: procedure Foo is type Root (D : natural) is tagged record F1 : String (1 .. D) := (others => 'x'); end record; subtype S1 is Root (1); subtype S2 is Root (2); type Ext is new S1 with record F2 : Integer; end record; Var : Ext := (S2 with F2 => 123); begin null; end Foo; One would hope that this would raise Constraint_Error, but nothing seems to have that effect. !recommendation ** TBD. !wording In 4.3.2(7), replace: are initialized by default as for an object of the ancestor type. with are initialized by default as for an object of the subtype denoted by the subtype_mark. and append a new paragraph: If the type of the ancestor_part has discriminants and the ancestor_part is a subtype_mark that denotes an unconstrained subtype, each discriminant of the ancestor type has the value specified for a corresponding discriminant, either in the record_component_association_list, or in the derived_type_definition or some ancestor of the type of the extension_aggregate. Replace 4.3.2(8): If the type of the ancestor_part has discriminants that are not inherited by the type of the extension_aggregate, then, unless the ancestor_part is a subtype_mark that denotes an unconstrained subtype, a check is made that each discriminant of the ancestor has the value specified for a corresponding discriminant, either in the record_component_association_list, or in the derived_type_definition for some ancestor of the type of the extension_aggregate. Constraint_Error is raised if this check fails. With: If the type of the ancestor_part has discriminants and the ancestor_part is not a subtype_mark that denotes an unconstrained subtype, then a check is made that each discriminant of the ancestor has the value specified for a corresponding discriminant, either in the record_component_association_list, or in the derived_type_definition for some ancestor of the type of the extension_aggregate. Constraint_Error is raised if this check fails. !discussion In order to help understand this wording, I think it helps to realize that if the ancestor type of an extension aggregate has discriminants, then there are 6 cases to consider: the cross-product of whether the discriminants of the ancestor type are inherited by the type of the extension aggregate (yes or no) and the three possible forms of the ancestor part: an expression a subtype mark denoting a constrained subtype a subtype mark denoting an unconstrained subtype. !ACATS Test !ASIS !appendix From: Steve Baird Sent: Monday, September 26, 2011 5:28 PM The following example obviously should raise Constraint_Error (assuming that it is not rejected at compile time - one could imagine adding some sort of "statically matching subtype" legality rule, but that seems outside the scope of this discussion): procedure Foo is type Root (D : natural) is tagged record F1 : String (1 .. D) := (others => 'x'); end record; subtype S1 is Root (1); subtype S2 is Root (2); type Ext is new S1 with record F2 : Integer; end record; Var : Ext := (S2 with F2 => 123); begin null; end Foo; It seems that the present RM wording fails to capture this intent. Note that 4.3.2(8) does not apply because it begins with "If the type of the ancestor_part has discriminants that are not inherited by the type of the extension_aggregate, ..." Perhaps this condition needs to be expanded to include the case of inherited discriminants and a constrained ancestor subtype_mark. **************************************************************** From: Steve Baird Sent: Sunday, November 13, 2011 1:02 AM Wording to discuss on Sunday. ==== In 4.3.2(7), replace: are initialized by default as for an object of the ancestor type. with are initialized by default as for an object of the subtype denoted by the subtype_mark. and append a new paragraph: If the type of the ancestor_part has discriminants and the ancestor_part is a subtype_mark that denotes an unconstrained subtype, each discriminant of the ancestor type has the value specified for a corresponding discriminant, either in the record_component_association_list, or in the derived_type_definition or some ancestor of the type of the extension_aggregate. Replace 4.3.2(8): If the type of the ancestor_part has discriminants that are not inherited by the type of the extension_aggregate, then, unless the ancestor_part is a subtype_mark that denotes an unconstrained subtype, a check is made that each discriminant of the ancestor has the value specified for a corresponding discriminant, either in the record_component_association_list, or in the derived_type_definition for some ancestor of the type of the extension_aggregate. Constraint_Error is raised if this check fails. With: If the type of the ancestor_part has discriminants and the ancestor_part is not a subtype_mark that denotes an unconstrained subtype, then a check is made that each discriminant of the ancestor has the value specified for a corresponding discriminant, either in the record_component_association_list, or in the derived_type_definition for some ancestor of the type of the extension_aggregate. Constraint_Error is raised if this check fails. ==== In order to help understand this wording, I think it helps to realize that if the ancestor type of an extension aggregate has discriminants, then there are 6 cases to consider: the cross-product of whether the discriminants of the ancestor type are inherited by the type of the extension aggregate (yes or no) and the three possible forms of the ancestor part: an expression a subtype mark denoting a constrained subtype a subtype mark denoting an unconstrained subtype. ****************************************************************