!standard 3.4(5.1/2) 08-05-23 AI05-0096-1/01 !class binding interpretation 08-05-23 !status work item 08-05-23 !status received 06-05-21 !priority Medium !difficulty Medium !qualifier Omission !subject Deriving from formal limited types !summary An instance of a generic is illegal if a limited type extension is derived from a formal tagged limited private type and the actual type is nonlimited. !question Consider the following: generic type Lim is limited private; package Gen is ... private type New_Lim is limited new Lim; end Gen; package New_Gen is new Gen (Integer); The template is legal, but the instance seems to violate 3.4(5.1/2). However, that rule is not rechecked in the instance (it doesn't have the boilerplate wording for that), so this is legal. Is that intended? !wording Add to 3.4(5.1/2): If the parent type is a tagged formal type, in addition to the places where Legality Rules normally apply (see 12.3), this rule applies also in the private part of an instance of a generic unit. AARM Note: If the parent type is a untagged limited formal type with an actual type that is nonlimited, we allow derivation as a limited type in the private part or body as no place could have visibility on the resulting type where it was known to be nonlimited (outside of the instance). (See the previous paragraph's AARM notes for an explanation of this.) However, if the parent type is a tagged limited formal type with an actual type that is nonlimited, it would be possible to pass a value of the limited type extension to a classwide type of the parent, which would be nonlimited. That's too weird to allow (even though all of the extension components would have to be nonlimited because the rules of 3.9.1 are rechecked), so we have a special rule to prevent that in the private part (type extension from a formal type is illegal in a generic package body). !discussion As explained by AARM 3.4(5.b-f/2), 3.4(5/2) is one of the (very few) rules where we *intentionally* don't recheck the rule in the private part. Specifically, a similar example to that in the question: generic type Lim is limited private; package Gen is ... private type New_Lim is new Lim; end Gen; package New_Gen is new Gen (Some_Tagged_Type); -- OK! is allowed because nothing can have a view that "knows" that New_Lim is a tagged type. So it seems that the example in the question should also be allowed for similar reasons. However, this is not true if the parent type is known to be a tagged type, because then we could pass a value of New_Lim to the class-wide type corresponding to the parent type. If that parent type is also nonlimited, we could then assign a limited tagged type. --!corrigendum 3.4(5.1/2) !ACATS Test An appropriate example should be tested in an ACATS B-Test. !appendix From: Pascal Leroy Sent: Thursday, May 22, 2008 12:24 AM [From a private mail of an unrelated subject.] Incidentally, I am wondering how 3.4(5.1/2) interacts with generics. Shouldn't it be rechecked in the private part of an instance? Shouldn't it assume the worst in a generic body? Maybe it's a rule that ought to say "immutably limited". **************************************************************** From: Randy Brukardt Sent: Friday, May 23, 2008 9:42 PM I started to create an AI on this topic, but I've gotten less convinced that there is a problem as I've looked at it. [And then more - read the whole message.] First, let's discard the last sentence. Interfaces are never "immutably limited", and the whole point of this feature was to allow the derivation of limited interfaces to create new limited types. So if we required "immutably limited", these could never be used for their intended purpose. Second, rechecking in the private part. 3.4(5/2) does *not* require rechecking in the private part. This one of the very, very few places where that was intentional. (Indeed, it’s the only one that comes to mind!) Consider: generic type Lim is limited private; package Gen is ... private type New_Lim is new Lim; end Gen; package New_Gen is new Gen (Some_Tagged_Type); -- OK! This the only place in the language where it is legal to derive a tagged type without a record extension. And that is considered OK because there is no place where New_Lim could ever be viewed as a tagged type. (Similarly in the body of a generic.) AARM 3.4(5.b/2 - 5.f/2) explains this. 3.4(5.1/2) is a very similar rule. Consider the very similar example: generic type Lim is limited private; package Gen is ... private type New_Lim is limited new Lim; end Gen; package New_Gen is new Gen (Integer); -- OK! It seems that the same thinking should apply to this declaration: there is no location where New_Lim could ever be seen as a non-limited type. So there doesn't seem to be a problem. Similarly in the body. However, there seems to be a possible problem with tagged types. generic type Lim is tagged limited private; package Gen is ... private type New_Lim is limited new Lim with null record; end Gen; package New_Gen is new Gen (Some_Non_Limited_Tagged_Type); -- Ouch. A declaration like New_Lim is illegal in a generic body by 3.9.1(4/2). And the automatic recheck in the spec will make this illegal in the visible part. But here in the private part, we have a case where where we have a limited tagged type derived from a non-limited tagged type. Obviously, a class-wide operation of Some_Non_Limited_Tagged_Type could assign a value of New_Lim. However, even here I can't see a actual problem (although this is very weird). generic type Lim is tagged limited private; package Gen is ... private type New_Lim is limited new Lim with record Tsk : A_Task; end record; end Gen; package New_Gen is new Gen (Some_Non_Limited_Tagged_Type); -- Illegal. 3.9.1(3/2) says "if the parent type is nonlimited, then the components shall be nonlimited", and is rechecked in the private part of the instance. Since Lim is nonlimited in the instance, this declaration is illegal. So the only extension components could be nonlimited, so assignment is available for every component of New_Lim. Still, this seems too weird for words. So I suggest adding a recheck rule for tagged types only: "If the parent type is a tagged type, in addition to the places where Legality Rules normally apply (see 12.3), this rule applies also in the private part of an instance of a generic unit." AARM Note: If the parent type is a nonlimited untagged type, we allow derivation as a limited type in the private part or body as no place could have visibility on the resulting type where it was known to be nonlimited (outside of the instance). (See the previous paragraph's AARM notes for an explanation of this.) However, if the parent type is tagged, it would be possible to pass a value of the limited type extension to a classwide type of the parent, which would be nonlimited. That's too weird to allow (even though all of the extension components would have to be nonlimited because the rules of 3.9.1 are rechecked), so we have a special rule to prevent that in the private part (type extension from a formal type is illegal in a generic package body). ****************************************************************