!standard 10.1.1(19/2) 06-06-02 AC95-00132/01 !standard 12.3(11) !class confirmation 06-06-02 !status received no action 06-06-02 !status received 06-05-11 !subject Legality checking for implicitly declared generics !summary !appendix From: Stephen W. Baird Date: Thursday, Map 11, 2006 4:28 PM RM05 10.1.1(19/2) specifies the "sprouting" rules by which a child unit C of a parent generic package P causes the existence of a corresponding declaration nested immediately within each instance of P. At what point, if any, are Legality Rules enforced for these declarations? Consider the following example: generic type T is private; package Parent is end Parent; ---- generic package Parent.Child is type Tg is tagged null record; procedure Proc (X : Tg; Y : Parent.T); procedure Proc (X : Tg; Y : Integer); end Parent.Child; ---- with Parent; package Parent_Instance is new Parent (Integer); ---- with Parent_Instance; with Parent.Child; package Client_1 is -- Parent_Instance.Child is visible, but unreferenced end Client_1; ---- with Parent_Instance; with Parent.Child; package Client_2 is generic package Ren renames Parent_Instance.Child; -- Parent_Instance.Child is referenced, but not instantiated end Client_2; ---- with Parent_Instance; with Parent.Child; package Client_3 is package I is new Parent_Instance.Child; -- Parent_Instance.Child is instantiated end Client_3; Parent_Instance.Child declares a tagged type with two explicitly declared homographic primitive operations, an apparent violation of 8.3(26/2). At what point, if any, is this violation detected? RM05 12.3(11) states that "In a generic unit Legality Rules are enforced at compile time of the generic_declaration and generic body ..." . When is that ? Clearly Client_3 is rejected because Client_3.I violates the "no dispatching homographs" rule, regardless of the treatment of Parent_Instance.Child. What about Client_2 and Client_1? At one extreme, one could argue that a post-compilation check is required in order to reject any partition whose closure includes both Parent_Instance and Parent.Child, even if 10.1.1(19/2)'s conditions for visibility are never met and the offending generic is never referenced. This could only make sense if there was some burden associated with not doing this, perhaps a shared-code-generic implementation issue. At the other extreme, one could argue that it is ok to omit Legality Rule enforcement altogether in this case and accept Client_2 because Parent_Instance.Child can never be successfully instantiated. Any intermediate approach must also deal with the case where the offending generic never meets 10.1.1(19/2)'s conditions for visibility but is referenced via a sibling unit. **************************************************************** From: Edmond Schonberg Date: Thursday, May 11, 2006 5:00 PM > At what point, if any, are Legality Rules enforced for these > declarations? interesting question... My informal understanding was that sprouting only happens right before cloning, i.e. when the child unit is going to be instantiated. Otherwise this declaration has a rather ghostly existence and no checks apply to it. I don't see what would be gained by requiring legality checks on them, and in fact would find it an annoying burden on the implementation. **************************************************************** From: Tucker Taft Date: Thursday, May 11, 2006 8:20 PM Good to see you haven't lost your touch... ;-) In any case, I would say postpone any additional legality checks until an instantiation of the child takes place. Anything else seems like useless extra work. I suppose we should allow earlier detection, but I would really hate to require it. **************************************************************** From: Randy Brukardt Date: Friday, May 12, 2006 4:11 PM > RM05 10.1.1(19/2) specifies the "sprouting" rules by which a child unit C > of a parent generic package P causes the existence of a corresponding > declaration nested immediately within each instance of P. > > At what point, if any, are Legality Rules enforced for these declarations? I don't see anything in 12.3 talking about "sprouting". :-) It says that legality rules are enforced when the generic spec and body are compiled, and when the instance is compiled. It doesn't say anything about doing so at other times as might be convinient to someone somewhere. While there would be some benefit to allowing earlier detection in cases like your examples, I have to think that writing the rules for that would be very complex. (Heck, "sprouting" is very complex, and we've had to fix it several times in the past.) And examples like these are going to be rare in practice. Rare enough, I would think, that it wouldn't be worth it to require early detection. Moreover, there is some benefit to having consistent behavior (even if there are cases where that behavior might be less friendly). Because of all of that, I suggest that we leave the rules alone, and not even allow early detection. (I believe the current rules are crystal-clear about that.) ... > At one extreme, one could argue that a post-compilation check is required > in order to reject any partition whose closure includes both > Parent_Instance and Parent.Child, even if 10.1.1(19/2)'s conditions for > visibility are never met and the offending generic is never referenced. > This could only make sense if there was some burden associated with > not doing this, perhaps a shared-code-generic implementation issue. Nope. A shared generic implementation is mostly likely going to compile the (original) generic units in the normal way. Further processing would occur only when it absolutely has to (at instantiation time) -- this legality checking is pure overhead to us, and we're surely not going to do it unless required by law. As far as the implementation of the instance goes, it would be similar to an instance with a generic formal package, with the parent instance passed in in the normal way -- so "sprouting" would have no effect at all other than to define a new name that can be instantiated. Surely a renames of such a name would have the same effect. Allowing early checking would have no effect on us (surely we'd ignore it). Requiring early checking would be a royal pain (*all* instantiation-time checking is), and it would probably have to be all-new code (because the "partialness" of it). Barf. ****************************************************************