AI22-0041-1

!standard 7.4(6/3)                                                22-06-15  AI22-0041-1/02

!standard 7.4(7/2)

!standard 7.4(7.1/2)

!class binding interpretation 22-06-14

!status work item 22-06-14

!status received 22-06-07

!priority Low

!difficulty Easy

!qualifier Omission

!subject Deferred constant subtype compatibility

!summary

A deferred constant should not be completed with an incompatible subtype.

!issue

The subtype given in the declaration of a deferred constant is part of the “contract” of the declaration. Clients should be able to assume that if the completion elaborates successfully, then the  value of the constant satisfies any checks (such as constraints, null exclusions, and enabled predicates) associated with that initial subtype. It is currently permitted to have a deferred constant whose initial subtype is subject to some (enabled) predicate which the completion’s subtype is not subject to and which will therefore not be checked when the completion is elaborated. This seems undesirable.

Should this example be legal? (No.)

package Bad_Deferred_Constant is
  pragma Assertion_Policy (Check);
  subtype S is String with Dynamic_Predicate => (S'Length >= 3);
  X : constant S;
private
  X : constant String := ""; -- legal?
end Bad_Deferred_Constant;

!recommendation

Require (at compile time) that the subtype used in the completion of a deferred constant shall be “statically compatible” with the subtype used in the initial declaration.

!wording

Delete 7.4(6/3) :

If the deferred constant declaration includes a subtype_indication S that defines a constrained subtype, then the constraint defined by the subtype_indication in the full declaration shall match the constraint defined by S statically. [Redundant: On the other hand, if the subtype of the deferred constant is unconstrained, then the full declaration is still allowed to impose a constraint. The constant itself will be constrained, like all constants;]

Add after 7.4(6/3):

If the deferred constant declaration includes a subtype_indication that defines a subtype S1, then the subtype_indication in the full declaration shall define a subtype S2 that is statically compatible with S1 (see 4.9.1). If S1 is a constrained subtype, the constraint defined by S2 shall statically match the constraint defined by S1. [Redundant: If the subtype S1 of the deferred constant is unconstrained, then the full declaration is still allowed to impose a constraint.]

Modify 7.4(7/2):

Delete 7.4(7.1/2):

!discussion

One could imagine dealing with this issue by somehow checking the value given in the completion of a deferred constant against both of the two subtypes. Adding complexity to the dynamic semantics of deferred constants does not seem like the right approach; better to deal with the issue statically.

Note that the definition of static compatibility includes a check for null exclusions (4.9.1(7/3)). Therefore, with this change, the rule 7.4(7.1/2) becomes redundant and we remove it as well. The requirement for static matching for constrained types could also have been removed, but that seemed like an unnecessary change that could increase the work for implementers with no real gain.

!example

(See issue.)

!ACATS test

A B-test similar to the given example could be written.

!appendix

From: Randy Brukardt

Sent: Wednesday, June 15, 2022  9:27 PM

The bullet 7.4(7.1/2) is now redundant, as it is covered by static compatibility - specifically, 4.9.1(7/3). The AI has been updated to reflect this.

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