!standard 03.02 (09) 96-11-16 AI95-00034/02 !class ramification 95-06-25 !status WG9 approved 96-12-07 !status ARG Approved (subject to editorial review) 9-0-2 96-10-07 !status work item 95-10-12 !status received 95-06-25 !priority Medium !difficulty Hard !subject Unconstrained Formal types !summary 95-06-25 A formal private subtype without discriminants is constrained. An access subtype may be doubly constrained in a generic instance; the constraint given in the subtype_indication overrides the constraint (if any) that might have come from the actual subtype. !question 95-06-25 When is a generic formal subtype unconstrained? AARM-12.3(11.c) says: 11.c A formal derived subtype is constrained if and only if the ancestor subtype is constrained. A formal array type is constrained if and only if the declarations says so. Other formal subtypes are unconstrained, even though they might be constrained in an instance. However, this does not seem to follow from the RM rules. !response 95-11-16 3.2(9) says: 9 {constrained} {unconstrained} {constrained (subtype)} {unconstrained (subtype)} A subtype is called an unconstrained subtype if its type has unknown discriminants, or if its type allows range, index, or discriminant constraints, but the subtype does not impose such a constraint; otherwise, the subtype is called a constrained subtype (since it has no unconstrained characteristics). Note the distinction between "type" and "subtype". An array type allows an index constraint, for example, whereas an array subtype may or may not impose one. Thus, 12.3(11.c) is incorrect in the case of a subtype of a formal private type with no discriminants. Such a subtype is constrained, because its type does not allow a discriminant constraint. This raises an interesting question: generic type Str_Ptr is access String; package GP is ... end GP; package body GP is subtype Str_Ptr_10 is Str_Ptr(1..10); -- Legal? (Yes.) X : Str_Ptr_10; ... end GP; Str_Ptr is unconstrained, since an access type designating String allows a constraint, and Str_Ptr does not impose one. This implies that 3.7.1(7) allows the subtype_indication "Str_Ptr(1..10)". However, the instance might try to impose a different constraint: type Str_P is access String; subtype Str_P_7 is Str_P(1..7); package P is new GP(Str_P_7); -- Legal? (Yes.) 12.3(11) says this is legal, since Legality Rules are not enforced in the body of an instance. Thus, the bounds of X are (1..10), and the constraint (1..7) is effectively ignored. Note that if the declaration of Str_Ptr_10 were in the declaration of GP instead of the body, then the instantiation P would be illegal, since Legality Rules are enforced in the instance declaration. Note that if the two constraints ever "meet", Constraint_Error will be raised, as illustrated by the following modification of the above example: generic type Str_Ptr is access String; type Obj: in out Str_Ptr; package GP is procedure Bad; end GP; package body GP is subtype Str_Ptr_10 is Str_Ptr(1..10); S: aliased String(1..10); X: Str_Ptr_10 := S'Access; procedure Bad is begin Obj := X; -- Constraint_Error is raised here. end Bad; end GP; type Str_P is access String; subtype Str_P_7 is Str_P(1..7); Actual_Obj: Str_P_7; package P is new GP(Str_P_7, Actual_Obj); ... P.Bad; -- This will propagate Constraint_Error. In the instance, Obj is constrained to (1..7), whereas X is constrained to (1..10). An attempt to assign one to the other (as in procedure Bad) will fail the constraint check. An alternative rule would be that it is illegal to give a constrained access subtype as the actual in the above case. This would be a cleaner rule, since it would avoid the anomaly of a doubly-constrained access type. However, most Ada 83 compilers probably allow the above example, and make the bounds of X be (1..10), and since constraining an access subtype is fairly uncommon, it does not seem worthwhile to use this alternative rule. Note that it is irrelevant whether a formal scalar subtype is considered constrained or unconstrained, since no compile-time rules are affected. Constrained-ness of a scalar type has an effect at run-time, but at run-time, only instances exist, not generic units. !appendix 95-10-12 !section 3.2(9) !subject Unconstrained Formal types !reference AARM-3.2(9);6.0 !from Jesper Joergensen 95-03-31 !keywords Unconstrained, Formal type !reference as: 95-5109.a Jesper Joergensen 95-3-31>> !discussion I have problems determining when a formal type is unconstrained. Paragraph 12.3(11c) says that all kinds of formal types except derived and arrays are unconstrained, but this is only a ramification so where is the proof for this? There are various definitions for "unconstrained" in chapter 3 that could be taken as covering the formal type case too, but then there is inconsistency. A private type declaration without any discriminant part, for instance, is defined by 3.2(9) to be constrained, whereas 12.3(11c) says it is unconstrained. /Jesper **************************************************************** !section 3.2(9) !subject Unconstrained Formal types !reference AARM-3.2(9);6.0 !reference 95-5109.a Jesper Joergensen 95-03-31 !keywords Unconstrained, Formal type !from Tucker Taft 95-03-31 !reference as: 95-5111.a Tucker Taft 95-3-31>> !discussion > I have problems determining when a formal type is unconstrained. Paragraph > 12.3(11c) says that all kinds of formal types except derived and arrays are > unconstrained, but this is only a ramification so where is the proof for this? > There are various definitions for "unconstrained" in chapter 3 that could be > taken as covering the formal type case too, but then there is inconsistency. > A private type declaration without any discriminant part, for instance, is > defined by 3.2(9) to be constrained, whereas 12.3(11c) says it is > unconstrained. Agreed. 12.3(11c) is in error for those types whose subtypes are always constrained per 3.2(9) because the type does not allow range, index, or discriminant constraints. A more interesting issue is formal access (sub)types whose designated subtype is unconstrained. 12.3 implies that these are unconstrained (if the type allows constraints), even if the actual subtype is constrained. For example: generic type Str_Ptr is access String; package GP is subtype Str_Ptr_5 is Str_Ptr(1..5); ... end GP; package body GP is subtype Str_Ptr_10 is Str_Ptr(1..10); X : Str_Ptr_10; ... end GP; Now suppose we instantiate GP with a constrained subtype of an access-to-string type: type Str_P is access String; subtype Str_P_7 is Str_P(1..7); package P is new GP(Str_P_7); According to 12.3, it seems pretty clear that this instantiation should fail because of the declaration of Str_Ptr_5 in the visible part of GP (access types cannot be "doubly" constrained -- see 3.6.1(5) and 3.7.1(7)). However, if the declaration of Str_Ptr_5 were removed, then this instantiation would be legal, according to 12.3(11) and 12.5.4(3-5), despite the declaration of Str_Ptr_10 in the generic body. This seems a bit surprising, to say the least. Note that this same situation exists in Ada 83, but since the Ada 83 contract model was not as strict, presumably Ada 83 compilers were supposed to complain about the declaration of Str_Ptr_10 upon instantiation. I doubt that many did, because I have never seen it on the list of Ada 83 generic contract model breakages. There seem various solutions to this problem. One is to ignore it ;-). But of course, now that it has been mentioned, we can't really do that. One "real" solution would be to require that an actual access subtype in an instantiation be unconstrained if the formal access subtype is unconstrained. A second would be to define the semantics of a "double" constraining of an access type to be equivalent to just applying the "second" constraint. I suspect that most Ada 95 compilers (and probably most Ada 83 compilers as well ;-) would currently use this latter solution (or die horribly). Since this latter solution is the most flexible, though admittedly a bit odd, we might as well leave things as they are (with perhaps a note confirming what it means). Disallowing instantiation with constrained access subtypes in such a case seems a bit like overkill, particularly since it is not upward compatible (though I'm not sure anyone would notice either way, given how rarely access subtypes are ever declared). > /Jesper -Tuck **************************************************************** !section 3.2(9) !subject Unconstrained !reference AARM-3.2(9);6.0 !reference 95-5111.a Tucker Taft 95-03-31 !from Jesper Joergensen 95-04-03 !reference as: 95-5113.a Jesper Joergensen 95-4-3>> !discussion Your example on a formal access type whose designated subtype is unconstrained is indeed very interesting, but I am still in doubt on the more simple cases: 1. 3.2(9) says that a type is unconstrained if it allows an index constraint, for example. But 3.6.1 says that such an index contstraint is allowed if the array subtype is unconstrained. Thus we have a circular definition, i.e no definition. Same problem with 3.7.1(7), or am I missing some other paragraph that is actually saving us? 2. For formal scalar types, where does the manual say that they are unconstrained? 12.5.2 says nothing about this and e.g. 3.5.4(9) only talks about the syntactic unit signed_integer_type_definition, not formal_signed_integer_type_definition. Is it implicit in the fact that nowhere it is said that a formal_signed_integer_type_definition defines a constrained first subtype? Regarding your two proposals on solution to the "access to unconstrained" problem I think that to require the actual to be unconstrained if the formal is, is a good solution that matches the array and private cases. The other solution is impossible to implement in the compiler alone (when the linker instantiates the body it must also check for this). I agree with your last remark that nonone would notice either way! /Jesper **************************************************************** !section 3.2(9) !subject Unconstrained !reference AARM-3.2(9);6.0 !reference 95-5111.a Tucker Taft 95-03-31 !reference 95-5113.a Jesper Joergensen 95-04-03 !from Tucker Taft 95-04-03 !reference as: 95-5114.a Tucker Taft 95-4-3>> !discussion > Your example on a formal access type whose designated subtype is unconstrained > is indeed very interesting, but I am still in doubt on the more simple cases: > > 1. 3.2(9) says that a type is unconstrained if it allows an index constraint, > for example. But 3.6.1 says that such an index contstraint is allowed if > the array subtype is unconstrained. Thus we have a circular definition, i.e > no definition. This is not quite circular. The distinction between *type* and *subtype* is important here. 3.2(9) says that a *subtype* is unconstrained if its *type* allows an index/discrim/range constraint, but the *subtype* does not impose one. All array types "allow" an index constraint. Only some array *subtypes* impose one. 3.6.1 says that an index constraint in a subtype_indication is only permitted if the *subtype* does not already impose an index constraint. > ... Same problem with 3.7.1(7), or am I missing some other > paragraph that is actually saving us? It is important to notice that 3.2(9) distinguishes between types and subypes. > 2. For formal scalar types, where does the manual say that they are > unconstrained? 12.5.2 says nothing about this and e.g. 3.5.4(9) only talks > about the syntactic unit signed_integer_type_definition, not > formal_signed_integer_type_definition. Is it implicit in the fact that > nowhere it is said that a formal_signed_integer_type_definition defines a > constrained first subtype? There is very little difference at compile-time between a constrained and unconstrained scalar subtype. The same attributes (e.g. 'First and 'Last) are defined for both. The primary difference between constrained and unconstrained for scalar subtypes is whether a range constraint is checked at run-time. Since run-time only applies to instances, this difference doesn't matter for formal scalar subtypes. Whether a formal scalar subtype is constrained could affect static subtype matching rules, and static compatibility in the context of a formal derived type. However, static matching is not a problem because static matching requires type matching, and because al formal scalar subtypes are never static, also requires that any constraint arise from the same subtype_indication. This can be checked without knowing whether or not the formal scalar subtype is constrained. The same logic applies to static compatibility, since if the subtypes are not static, their constraints must arise from the same subtype_indication. In any case, I would agree that the "ramification" given in 12.3(11.c) seems a bit hard to prove. > Regarding your two proposals on solution to the "access to unconstrained" > problem I think that to require the actual to be unconstrained if the formal > is, is a good solution that matches the array and private cases. The other > solution is impossible to implement in the compiler alone (when the linker > instantiates the body it must also check for this). I'm not sure I understand. I did not mean to propose that the instance would be illegal if the body included a constraint on a formal access subtype. Rather, I proposed that the language would define the constraint imposed on the formal subtype in the body to take precedence over the one coming from the actual subtype. I presume this is what most Ada 83 compilers do today (though I haven't checked). > ... I agree with your last > remark that nonone would notice either way! Except us language lawyers, of course. > /Jesper -Tuck **************************************************************** !section 03.02(09) !subject Unconstrained Formal types !reference RM95-03.02 (09) !reference AI95-00034 !from Pascal Leroy 95-10-09 !reference as: 95-5318.d Pascal Leroy 95-10-9>> !discussion This AI has an example that completely confuses me (and a number of my colleagues): generic type Str_Ptr is access String; package GP is end GP; type Str_P is access String; subtype Str_P_7 is Str_P(1..7); package P is new GP(Str_P_7); -- Legal? (Yes.) 12.5.4(3) says that "for a formal access-to-object type, the designated subtype of the formal and the actual types shall statically match." The designated subtype of the formal is clearly String. I would guess that the designated subtype of Str_P_7 is String(1..7), but I was unable to deduce that from the RM. 4.9.1(2) says that "a subtype statically matches another subtype ... if they have statically matching constraints." It's a bit unclear how this rule applies to an unconstrained subtype, but it seems safe to say that the constraint of String doesn't statically match that of String (1..7). So why is it that the instantiation above is legal? **************************************************************** !section 03.02(09) !subject Unconstrained Formal types !reference RM95-03.02 (09) !reference AI95-00034 !reference 95-5318.d Pascal Leroy 95-10-9 !from Bob Duff !reference as: 95-5324.b Robert A Duff 95-10-11>> !discussion > This AI has an example that completely confuses me (and a number of my > colleagues): > > generic > type Str_Ptr is access String; > package GP is > end GP; > > type Str_P is access String; > subtype Str_P_7 is Str_P(1..7); > package P is new GP(Str_P_7); -- Legal? (Yes.) > > 12.5.4(3) says that "for a formal access-to-object type, the designated > subtype of the formal and the actual types shall statically match." > > The designated subtype of the formal is clearly String. I would guess that > the designated subtype of Str_P_7 is String(1..7), but I was unable to deduce > that from the RM. The actual *type* is the type of Str_P, and its designated subtpe is String. This follows directly from 3.10(10). We don't talk about designated subtypes of access SUBtypes. > 4.9.1(2) says that "a subtype statically matches another subtype ... if they > have statically matching constraints." > > It's a bit unclear how this rule applies to an unconstrained subtype, but it > seems safe to say that the constraint of String doesn't statically match that > of String (1..7). > > So why is it that the instantiation above is legal? The designated subtypes are both String, and String statically matches itself. - Bob ****************************************************************