!standard 4.9 (31) 03-09-10 AI95-00311/02 !standard 4.9.1 (01) !class binding interpretation 02-09-26 !status work item 02-09-26 !status received 02-08-28 !qualifier Omission !priority Low !difficulty Easy !subject Static matching of formal scalar subtypes !summary If T1 is a generic formal scalar type, T1 does not statically match T1'Base. !question Is the following legal? generic type T1 is range <>; package Pak1 is procedure P1 (Left : T1); end Pak1; package body Pak1 is procedure P1 (Left : T1'Base) is -- Legal? (No.) begin null; end P1; end Pak1; If T1 is considered to have a null constraint, then the subtypes T1 and T1'Base statically match and the above example is legal; if T1's constraint is nonstatic, then the constraints do not statically match by 4.9.1(2), and thus the example is illegal. !recommendation (See summary.) !wording Add after 4.9(31): In any case, the constraint of a generic formal type is neither static nor null. Replace 4.9.1(1) by: A constraint *statically matches* another constraint if: o both are null constraints; or o both are static and have equal corresponding bounds or discriminant values; or o both are nonstatic and result from the same elaboration of a constraint of a subtype_indication, the same evaluation of a range of a discrete_subtype_definition, or the same declaration of a generic formal subtype. !discussion Intuitively, T1's constraint should be nonstatic by definition, since it is not known what the actual constraint will be and the actual subtype can have any legal constraint whatsoever. However, the standard does not say this. Note that the wording is intended to allow the following: generic type T1 is range <>; package Pak1 is subtype S1 is T1; procedure P1 (Left : T1); end Pak1; package body Pak1 is procedure P1 (Left : S1) is -- Legal begin null; end P1; end Pak1; That's because the constraints on S1 and T1 "result from the same declaration of a generic formal subtype". !corrigendum 4.9(31) @dinsa @xbullet of the constraint is static, and the subtype of each discriminant is static.> @dinst In any case, the constraint of a generic formal type is neither static nor null. !corrigendum 4.9.1(1) @drepl A constraint @i another constraint if both are null constraints, both are static and have equal corresponding bounds or discriminant values, or both are nonstatic and result from the same elaboration of a @fa of a @fa or the same evaluation of a @fa of a @fa. @dby A constraint @i another constraint if: @xbullet @xbullet @xbullet of a @fa, the same evaluation of a @fa of a @fa, or the same declaration of a generic formal subtype.> !ACATS test A B-Test should possibly be created to check this case. !appendix !topic Constraint of formal scalar type !reference RM95 12.5.2, 4.9(27), 4.9.1(2), 6.3(4), 6.3.1(17-18) !from Adam Beneschan 08-30-02 !discussion In this fragment: generic type T1 is range <>; package pak1 is ... What is the status of T1's constraint? Is it null, static, nonstatic, unknown, or what? The reason this matters is because I can't figure out whether this is legal: generic type T1 is range <>; package Pak1 is procedure P1 (Left : T1); end Pak1; package body Pak1 is procedure P1 (Left : T1'Base) is begin null; end P1; end Pak1; If T1 is considered to have a null constraint, then the subtypes T1 and T1'Base statically match and the above example is legal; if T1's constraint is nonstatic, then I believe the constraints to not statically match by 4.9.1(2), and thus the example is illegal. Intuitively, it seems to me that T1's constraint should be nonstatic by definition, since it is not known what the actual constraint will be and the actual subtype can have any legal constraint whatsoever. However, I can't find support in the RM for this. Perhaps something should be added to 4.9 or 4.9.1 to indicate that the constraint on a generic formal first subtype is considered to be nonstatic? **************************************************************** From: Robert A Duff Sent: Friday, September 6, 2002 4:36 PM > The reason this matters is because I can't figure out whether this is > legal: This should be illegal, IMHO, since the actual for T1 might impose a constraint, which makes the body a lie. Whether the RM says so, I don't know. Can I invoke Robert's Rule, which says that no matter what the RM says, it "really" says what we mean? ;-) **************************************************************** From: Tucker Taft Sent: Friday, September 6, 2002 9:18 PM >If T1 is considered to have a null constraint, then the subtypes T1 >and T1'Base statically match and the above example is legal; if T1's >constraint is nonstatic, then I believe the constraints to not >statically match by 4.9.1(2), and thus the example is illegal. Neither T1 nor T1'Base is static, according to 4.9(25-26). They don't match because they aren't the result of the elaboration of the same constraint or range (cf. 4.9.1(1)). >Intuitively, it seems to me that T1's constraint should be nonstatic >by definition, since it is not known what the actual constraint will >be and the actual subtype can have any legal constraint whatsoever. >However, I can't find support in the RM for this. Perhaps something >should be added to 4.9 or 4.9.1 to indicate that the constraint on a >generic formal first subtype is considered to be nonstatic? I don't see any hole here. **************************************************************** From: Adam Beneschan Sent: Monday, September 9, 2002 1:45 PM It still looks like a hole to me. The important thing here isn't whether the subtypes are static, but whether the subtypes statically match (6.3.1(17)). So 4.9(26) isn't relevant here. 4.9(25) isn't relevant either. It says "A static range is a _range_ whose bounds are static expressions ...". The definition of a _range_ in 3.5(3) is either two expressions with .. in between, or a 'Range attribute; "<>" is not a _range_, by this definition, and thus 4.9(25) doesn't apply. The key question here, I believe, is: what, exactly, *is* the constraint on T1 (particularly for the purposes of applying 4.9.1(1))? "range <>" doesn't meet the definition of a _constraint_ given in 3.2.2(5), so it doesn't appear to be technically correct to call "range <>" a constraint; but if this isn't a constraint, then the generic formal T1 has a null constraint (since I can't find anything in the RM that decrees otherwise), and thus it would seem to say that T1 and T1'Base do statically match, since their constraints are both null constraints and thus match by 4.9.1(1). **************************************************************** From: Tucker Taft Sent: Monday, September 9, 2002 3:19 PM In general, the properties of a formal (sub)type are determined by the range of potential properties of the allowed actual subtypes. Given that the actual subtype might or might not be constrained, it is not determined at compile-time whether a formal scalar type is constrained or unconstrained. I realize that is a bit of an uncomfortable position to be in, but it doesn't actually affect legality except in the case of statically matching subtypes, as you point out. The RM explicitly says the base range is non-static, and we know that T1'Base is unconstrained, but T1 itself might or might not be constrained. It would seem there are two possibilities, either we assume the "best" in the spec and then recheck upon instantiation, or we say that they clearly don't statically match, even though they might dynamically match. So I guess I agree with you now that there is a hole, and we need to specify which possibility is to be chosen. It seems clear that in the body, the two subtypes don't statically match. But in the spec, there seems some case for saying that the static matching check is deferred until instantiation time. With my implementation hat on I will have to say "yuck"... ;-) Note that a similar situation arises with formal access subtypes, where it is not known at compile time whether the actual will be constrained or unconstrained. However, since there is no 'Base attribute, this particular problem doesn't arise. However, since it is illegal to apply a constraint to an already-constrained access subtype, the legality of applying a constraint would seem to depend on an unknown-at-compile-time characteristic, bringing up the same assume-the-best vs. assume-the-worst situation. I wonder how we have handled that case? It sounds familiar... **************************************************************** From: Randy Brukardt Sent: Thursday, September 26, 2002 9:56 PM Tucker wrote: > So I guess I agree with you now that there is a hole, > and we need to specify which possibility is to be > chosen. It seems clear that in the body, the two > subtypes don't statically match. But in the spec, > there seems some case for saying that the static > matching check is deferred until instantiation time. > With my implementation hat on I will have to say "yuck"... ;-) I'm strongly in favor of this always not matching, unless someone can find an example where matching would be valuable in practice. Certainly Adam's example isn't it. :-) > Note that a similar situation arises with formal access > subtypes, where it is not known at compile time whether > the actual will be constrained or unconstrained. However, > since there is no 'Base attribute, this particular problem > doesn't arise. However, since it is illegal to apply a > constraint to an already-constrained access subtype, the > legality of applying a constraint would seem to depend on > an unknown-at-compile-time characteristic, bringing up > the same assume-the-best vs. assume-the-worst situation. > I wonder how we have handled that case? It sounds familiar... That's AI-34, which is a confirmation. (Wow!) It says that the check is not performed in the body of the generic, because legality rules don't apply there. I suppose the check is performed in the private part on instantiation, but no check is ever done in the body. Thus, its possible to doubly constrain an access subtype; supposedly the meaning is that the original constraint is dropped. There is no runtime check, either. I'm *certain* we don't want to follow this model here! **************************************************************** From: Tucker Taft Sent: Monday, October 6, 2003 12:02 PM I think we discussed this once, but it just came up in a compiler problem I was diagnosing, and I can't remember the resolution. 4.9 (static expressions, etc.) talks about "descendants of a formal scalar type" which does not include a formal derived type whose ancestor is scalar. I think that is intentional, in general, since the base subtype of a scalar formal derived type is known, and will generally be static (since all base subtypes are static, except for those of "formal scalar types"). Now the question comes up is whether the *constraint* of a scalar formal derived type is static, and just what it is. It seems that it should be considered always nonstatic, since 12.5.1 only requires that the actual be statically *compatible* with the ancestor. This implies that the actual subtype range need not be the same as that of the ancestor; it can be a narrower range. Hence, given a formal derived type: generic type T is new Positive; ... T'Base is a static unconstrained subtype T is a nonstatic constrained subtype T'Base'First is a static expression, = Positive'Base'First T'First is nonstatic, but is known to be >= Positive'First Does that sound right? **************************************************************** From: Gary Dismukes Sent: Monday, October 6, 2003 12:10 PM Yes, that looks exactly right. **************************************************************** From: Robert A. Duff Sent: Monday, October 6, 2003 1:40 PM I agree. If T'First were static, then what would its value be? Surely it can't be 1, because the Actual_Subtype'First might not be 1. And if T'First is nonstatic, then surely T is not a static subtype! **************************************************************** From: Randy Brukardt Sent: Monday, October 6, 2003 11:13 PM I believe this is AI-311, which was on the agenda (Pascal had updated it), but not discussed. Please check it to see if it handles the case you're worried about. **************************************************************** From: Tucker Taft Sent: Tuesday, October 7, 2003 5:11 AM Now here is my next question. What about static compatibility...: generic type T1 is new Positive; package Gen1 is ...; generic type T2 is new Positive; package Gen2 is package Inst1 is new Gen1(T2); -- legal? end Gen2; Is this legal? It would be nice, but the rules for static compatibility, as written, would probably say it was *not* legal, since T2 is not statically compatible with Positive, according to my reading of 4.9.1, since T2 has a non-static constraint (based on the earlier messages), and a non-static constraint can only be statically compatible if it statically matches the other constraint, and we know the constraint of T2 is not necessarily Positive'Range. On the other hand, we know that any actual type for T2 must be statically compatible with T2's ancestor, i.e. Positive, so it seems like T2 ought to be a special case. Namely, the constraint of a formal derived subtype should be considered statically compatible with its ancestor subtype (and anything that statically matches its ancestor subtype). So I think we have two holes: we need to specify that the constraint of a formal derived type is *not* static, but that it *is* statically compatible with its ancestor. Alternatively, we could express it recursively, saying that the constraint of a formal derived subtype is statically compatible if the constraint of its ancestor subtype is statically compatible (that would be more flexible). The same would *not* apply for static matching, presumably. By the way, this came up in real code written by a REAL programmer (guess who ... his initials are R.A.D. ;-). **************************************************************** From: Robert I. Eachus Sent: Tuesday, October 7, 2003 8:11 AM > Is this legal? It would be nice, but the > rules for static compatibility, as written, would > probably say it was *not* legal... I think this comes under the Robert Dewar rule that any silly ramification of the rules is wrong. Can T2 be statically compatible with Positive on line 6, and not statically compatible with Positive on line 8? That seems to stretch the definition of STATICALLY compatible completely out of shape. I'm not all that sure that I like the implementation implications of such a rule in general, but I think that this is the only special case that has to be dealt with--a legality check in the defining instance of a derived (sub)type. So subsequent checks can be made the way Tucker envisions. (A generic formal type must be statically compatible with its parent subtype, so in later uses of the type, it is okay for the formal type to be used where it needs to be statically compatible with its original parent.) **************************************************************** From: Tucker Taft Sent: Tuesday, October 7, 2003 11:06 AM Unfortunately, 311 doesn't really address the whole problem. It mostly talks about formal scalar types, rather than scalar formal derived types. It also doesn't mention static compatibility. I think the "fix" for static matching looks good for both kinds of scalar formal types, but we also need a fix to static compatibility. As mentioned in my earlier note, I suggest we fix static compatibility by saying that the constraint of a scalar formal derived type is statically compatible with anything that its parent subtype is statically compatible with. We also need to add something to make clear that the constraint of a scalar formal derived type is not static. It seems reasonable to add both of these to AI-311. **************************************************************** From: Randy Brukardt Sent: Thursday, December 4, 2003 6:54 PM I agree about the static compatibility (well, actually I don't agree it is worth changing this, but certainly the AI doesn't cover it and it is worth discussion), but I don't have a clue why you think that a scalar formal derived type could have a static constraint given the wording proposed in the AI. The AI proposes to add after 4.9(31): In any case, the constraint of a generic formal type is neither static nor null. Certainly this covers a scalar formal derived type! This covers ANY generic formal type. **************************************************************** From: Tucker Taft Sent: Thursday, December 4, 2003 10:06 PM > The AI proposes to add after 4.9(31): > > In any case, the constraint of a generic formal type is neither static nor > null. This seems to be going too far and is gratuitously upward incompatible. Why can't the constraint of a formal array type be static? For a formal derived composite type, there seems no problem inheriting the staticness from the ancestor type. It is only a formal derived scalar type that allows the constraints to differ between the ancestor and the actual, so that is the one we should be worrying about. > Certainly this covers a scalar formal derived type! This covers ANY generic > formal type. And it shouldn't. **************************************************************** From: Randy Brukardt Sent: Thursday, December 4, 2003 11:15 PM > This seems to be going too far and is gratuitously > upward incompatible. Why can't the constraint > of a formal array type be static? I could probably come up with a number of reasons if I cared to think about it, but I don't right now. > For a formal derived > composite type, there seems no problem inheriting the > staticness from the ancestor type. It is only a formal > derived scalar type that allows the constraints to differ > between the ancestor and the actual, so that is the > one we should be worrying about. Huh? The original problem of AI-311 was with a regular generic formal scalar type. Clearly this has to apply at a minimum to all generic formal types which are scalar. (That should be generally true in the RM - it's unfortunate that generic formal xxx type does not include generic derived types which are xxx, because they are implemented in exactly the same way, and have the same semantics except for additional operations. Any rule on generic formal xxx should also apply to generic formal derived xxx types, unless it has to do with primitive operations.) **************************************************************** From: Tucker Taft Sent: Friday, December 5, 2003 7:06 AM I wasn't debating that. I was debating the blanket statement that *all* formal types, including access and composite types, have non-static constraints. That seems incompatible and unnecessary. ****************************************************************