!standard 03.08 (18) 00-07-13 AI95-00171/09 !standard 03.03.01 (18) !standard 03.06 (22) !standard 04.03.01 (19) !standard 04.08 (10) !standard 09.04 (14) !standard 09.05.02 (22) !class binding interpretation 98-03-19 !status Corrigendum 2000 99-08-17 !status WG9 approved 98-06-12 !status ARG Approved 11-0-1 98-04-01 !status received 96-11-16 !priority Low !difficulty Hard !qualifier Omission !subject Elaboration of subtype_indications with per-object constraints !summary The elaboration of a subtype indication with a per-object constraint occurs when an object of the enclosing type is created. This elaboration consists of the evaluation of each per-object expression of the constraint, followed by the usual actions associated with such elaboration, but using the values for any expressions that are not part of a per-object expression that were determined earlier when the type definition was elaborated. For evaluating a named association applying to multiple components in a per-object discriminant constraint, if the expression of the association is not part of a per-object expression, then it must be evaluated once for each associated component. !question When does the elaboration of a subtype indication with a per-object constraint occur? What are the actions of such an elaboration? When a component has a subtype_indication with a per-object constraint and an object of the type containing the component is declared, the subtype_indication containing the per-object constraint is apparently never elaborated. 3.8(18) explains that subtype_indications with per-object constraints are not elaborated, but that any expressions that are not part of a per-object expression are evaluated. However, what to do with the results of those evaluations never seems to be explained. 3.3.1(15-20) describes the process of elaborating an object_declaration. In step 3, per-object expressions are evaluated, but there is no mention of elaborating anything, although later paragraph 20 does seem to imply that some sort of elaborations were supposed to have taken place in step 3. The elaboration of per-object constraints is mentioned in (at least) the following other places where objects are created: 4.3.1(19) creating record aggregates 4.8(10) creating heap objects via uninitialized allocators 9.4(14) creating a protected object (This one is supposed to be redundant with 3.3.1, but in fact the two appear to be inconsistent.) According to a strict reading, elaborating the per-object constraint would appear to involve reevaluating the non-per-object expressions (since there doesn't seem to be any separate definition of what happens when a per-object constraint is elaborated), but not include any subtype compatibility checks that would normally occur as part of subtype elaboration (since elaboration of the subtype_indication containing the constraint isn't mentioned in these paragraphs). What are the intended semantics? !recommendation 98-03-19 Notwithstanding the rules given in 3.3.1(18), 4.3.1(19), and 4.8(10), the elaboration of the subtype indication of a component definition with a per-object constraint occurs when an object of the enclosing type is created. This elaboration takes place on elaboration of an object declaration, evaluation of an uninitialized allocator, and when evaluating an aggregate of the type. The elaboration consists of the evaluation of each per-object expression of the component's constraint, followed by the conversion of the value of each expression of the constraint to its appropriate expected type and the performance of the compatibility check defined for the elaboration of the subtype indication (see 3.2.2(11)). The values used for any expressions that are not part of per-object expressions of the subtype's constraint are those determined during the original elaboration of the component definition as defined in 3.8(18). Such expressions are not reevaluated during elaboration of the per-object constraint that occurs as part of object creation, despite any rules that state when a per-object constraint is elaborated (e.g., as part of evaluating an allocator or aggregate). Note further that the evaluation of expressions in a per-object constraint defined in 3.8(18) was intended to take into account the case of named associations for multiple components in a discriminant constraint. For such an association, the expression must be evaluated once for each associated component, as prescribed by 3.7.1(12). !wording Changes are required in 3.3.1(18), 4.3.1(19), 4.8(10), and 9.4(14) to state that any subtype indications for components with a per-object constraint are elaborated. The specific actions of elaborating such subtype indications and their associated constraints, as described in the recommendation, should be defined (perhaps in 3.8(18)). Also, 3.8(18) needs to account for multiple evaluations of non-per-object expressions in the case of named associations in a per-object discriminant constraint. !discussion There are two basic problems with the current wording of the standard regarding the elaboration of components with a per-object constraint. The first is that the rules don't explain what is done with the values obtained from expressions that are not part of per-object expressions (as defined in 3.8(18)) or whether such expression are reevaluated when a per-object constraint is later elaborated during object creation. The other problem is that the mention of elaboration of per-object constraints in rules such as 4.3.1(19) and 4.8(10) fails to cover the need for the subtype compatibility check that is normally performed when elaborating a subtype indication. The intent was clearly that the values of the expressions evaluated as part of elaborating a component definition with a per-object constraint (3.8(18)) should be used later when creating an object of the containing type. It would not make sense to discard the values already determined and to reevaluate the expressions (especially if they have side effects). The description in the rules for allocator and aggregate evaluation that states that a per-object constraint is elaborated should mention that only the per-object expressions are evaluated at that point and that the values for other expressions are those determined earlier when the type was elaborated. (The description of the semantics of elaborating per-object constraints should really be centralized in a single place, such as 3.8(18).) The rules for object declarations, allocator evaluation, and aggregate evaluation all fail to require the subtype compatibility check that occurs when a subtype indication is elaborated (and for object declarations even the constraint elaboration is omitted). This check is certainly needed in these cases as well. The fix for this oversight is to define each of these rules to include the elaboration of the subtype indications for components with per-object constraints (which also subsumes the elaboration of the constraint itself). One other minor gap is that the case of elaborating a named discriminant association within a per-object constraint is not covered by that rule in 3.8(18). The rule as given only describes a single evaluation for each expression of the constraint, but the intent is that for a named association the expression should be evaluated for each associated component. !corrigendum 3.03.01(18) @drepl @xhang<@xterms< 3.>The object is created, and, if there is not an initialization expression, any per-object expressions (see 3.8) are evaluated and any implicit initial values for the object or for its subcomponents are obtained as determined by the nominal subtype.> @dby @xhang<@xterms< 3.>The object is created, and, if there is not an initialization expression, any per-object constraints (see 3.8) are elaborated and any implicit initial values for the object or for its subcomponents are obtained as determined by the nominal subtype.> !corrigendum 3.06(22) @drepl The elaboration of a @fa creates the discrete subtype, and consists of the elaboration of the @fa or the evaluation of the @fa. The elaboration of a @fa in an @fa consists of the elaboration of the @fa. The elaboration of any @fas and the elaboration of the @fa are performed in an arbitrary order. @dby The elaboration of a @fa that does not contain any per-object expressions creates the discrete subtype, and consists of the elaboration of the @fa or the evaluation of the @fa. The elaboration of a @fa that contains one or more per-object expressions is defined in 3.8. The elaboration of a @fa in an @fa consists of the elaboration of the @fa. The elaboration of any @fas and the elaboration of the @fa are performed in an arbitrary order. !corrigendum 3.08(18) @drepl Within the definition of a composite type, if a @fa or @fa (see 9.5.2) includes a @fa that denotes a discriminant of the type, or that is an @fa whose @fa denotes the current instance of the type, the expression containing the @fa is called a @i, and the constraint being defined is called a @i. For the elaboration of a @fa of a @fa, if the @fa of the @fa is not a per-object constraint, then the @fa is elaborated. On the other hand, if the @fa 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. @dby Within the definition of a composite type, if a @fa or @fa (see 9.5.2) includes a @fa that denotes a discriminant of the type, or that is an @fa whose @fa denotes the current instance of the type, the expression containing the @fa is called a @i, and the @fa or @fa being defined is called a @i. For the elaboration of a @fa of a @fa or the @fa of an @fa for an entry family (see 9.5.2), if the @fa or @fa of the @fa or @fa is not a per-object constraint, then the @fa or @fa is elaborated. On the other hand, if the @fa or @fa 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. When a per-object constraint is elaborated (as part of creating an object), each per-object expression of the constraint is evaluated. For other expressions, the values determined during the elaboration of the @fa or @fa are used. Any checks associated with the enclosing @fa or @fa are performed, including the subtype compatibility check (see 3.2.2), and the associated subtype is created. !corrigendum 4.08(10) @drepl @xbullet of the @fa; any per-object constraints on subcomponents are elaborated and any implicit initial values for the subcomponents of the object are obtained as determined by the @fa and assigned to the corresponding subcomponents. A check is made that the value of the object belongs to the designated subtype. Constraint_Error is raised if this check fails. This check and the initialization of the object are performed in an arbitrary order.> @dby @xbullet of the @fa; any per-object constraints on subcomponents are elaborated (see 3.8) and any implicit initial values for the subcomponents of the object are obtained as determined by the @fa and assigned to the corresponding subcomponents. A check is made that the value of the object belongs to the designated subtype. Constraint_Error is raised if this check fails. This check and the initialization of the object are performed in an arbitrary order.> !corrigendum 9.05.02(22) @drepl For the elaboration of an @fa for an entry family, if the @fa contains no per-object expressions (see 3.8), then the @fa is elaborated. Otherwise, the elaboration of the @fa consists of the evaluation of any expression of the @fa that is not a per-object expression (or part of one). The elaboration of an @fa for a single entry has no effect. @dby The elaboration of an @fa for an entry family consists of the elaboration of the @fa, as described in 3.8. The elaboration of an @fa for a single entry has no effect. !ACATS test An extensive set of tests check cases where a constraint contains an enclosing discriminant in component_definitions (C37213x and C37215x). Test C380001 was constructed to check that the checks are made when the per-object expression contains a attribute whose prefix denotes the current instance of the type. (Test, 5-0-3, ARG Letter Ballot, February 2001). Test C380002 was constructed to check that an expression in a per-object discriminant constraint is evaluated once for each named association. (Test, 7-0-1, ARG Letter Ballot, February 2001). Tests C380003 and C380004 were constructed that these rules are enforced per-object constraints in task and protected specifications (Test, 5-1-2, ARG Letter Ballot, February 2001). !appendix !section 3.8(18) !subject Elaboration of subtype_indications with per-object constraints !reference RM95-3.8(18) !from Vince Del Vecchio 96-10-30 !reference 1996-5737.a Vince Del Vecchio 1996-10-30>> !discussion When a component has a subtype_indication with a per-object constraint and an object of the type containing the component is declared, the subtype_indication containing the per-object constraint is apparently never elaborated. 3.8(18) explains that subtype_indications with per-object constraints are not elaborated, but that any included expressions are evaluated. What to do with the results of those evaluations never seems to be explained. 3.3.1(15-20) describes the process of elaborating an object_declaration. In step 3, per-object expressions are evaluated, but there is no mention of elaborating anything, although later paragraph 20 does seem to imply that some sort of elaborations were supposed to have taken place in step 3. What should really happen is a partial elaboration of the subtype_indication should be performed, omitting pretty much any evaluation, and using instead the already evaluated results (either from 3.8(18) or from the per-object evaluations just performed). However important part of the elaboration which do need to happen include various checks (one due to a conversion in 3.7.1(12), then the compatibility check of 3.2.2(11)), and actually creating the subtype. This is described somewhat in the AARM note 3.3.1(18.a), although that is not binding. The elaboration of per-object constraints is mentioned in (at least) the following other places where objects are created: 4.3.1(19) creating record aggregates 4.8(10) creating heap objects via uninitialized allocators 9.4(14) creating a protected object (This one is supposed to be redundant with, but in fact appears to be inconsistent with 3.3.1.) Strictly read, elaborating the per-object constraint would involve reevaluating the non-per-object expressions (since there doesn't seem to be any special definition of what happens when a per-object constraint is elaborated), and not performing compatibility checks (since elaboration of the subtype_indication containing the constraint doesn't seem to be mentioned in these places). What is wanted is the same as in 3.8(18), to finish the elaboration of the subtype_indication containing the constraint. -Vince Del Vecchio vdelvecc@inmet.com **************************************************************** !from Randy Brukardt 99-08-17 Per-object constraints are mentioned in 3.8(18), 3.3.1(18), 4.3.1(19), 4.8(10), 9.1(12), 9.4(14), 9.5.2(22), 7.6(12), 7.6.1(9), and 13.14(8). 3.8(18 is the defining occurrence. The next six all deal with either the evaluation or elaboration of per-object constraints. The other three deal with other issues (Initialize calls, Finalize calls, and freezing, respectively) and do not need changes. All of 4.3.1(19), 4.8(10), 9.1(12), and 9.4(14) talk in terms of elaborating the per-object constraint. If that was properly defined, no changes are required in any of these clauses. The primary problem here is with 3.3.1(18), which does not speak in terms of elaborating the per-object constraint (meaning that needed checks aren't done). This paragraph was changed to use that terminology. The secondary problem is no definition of the elaboration of a per-object constraint. This was added to 3.8(18). It also was changed to insure that evaluation was done multiple times, if needed. As part of the repairs, I moved the discussion of per-object constraints for entries from 9.5.2(22) to 3.8(18), in order to insure that the same semantics is given to both. Since this case has to be mentioned (both when defining per-object constraint, and when defining elaboration of a per-object constraint) leaving it in 9.5.2(22) simply means the same words have to be given a second time. (Which increases the errors). I noticed another problem: a discrete_subtype_definition can be a range, which is *not* a constraint. Therefore, I added "range" to the definition of per-object constraint (or we'd just have a new hole for the next round to patch up). I think that the last phrase of 3.8(18A) ("including the subtype compabilitity check (see 3.2.2).") is redundant, but the AI recommendation seems insistent that it be included. I'd be happy to do without it. **************************************************************** !from Randy Brukardt 99-10-06 My notes from the recent ARG meeting say that the end of the first paragraph should be changed from: ... 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. to: ... then the elaboration consists of the evaluation of any included expression that is not part of a per-object expression, according to the rules given in 3.7.1. I did not make this change, because the rules in 3.7.1 are wrong for this use, unfortunately. During the meeting, I checked the behavior of existing ACATS tests [C37213B.ADA, C37213D.ADA, and others (the tests in fact are Ada 83 tests)], and they require that the values be evaluated but not be checked at this point. Given that the test suite requires this behavior, and has for many years, all compilers delay the checks, and a change would be gratuitous. However, the rules in 3.7.1 specifically say that each value is evaluated and converted when a discriminant is evaluated. So a reference to 3.7.1 would cause incorrect behavior. ****************************************************************