!standard 7.6(00) 02-09-25 AC95-00050/01 !class amendment 02-09-30 !status received no action 02-09-30 !subject Controlled types declared in nested scopes !summary !appendix From: Steve Baird Sent: Wednesday, September 25, 2002 1:23 PM Controlled types, and their associated Initialize, Finalize, and Adjust routines, cannot be declared within subprograms, generic bodies, and other such contexts (3.9.1(3)). The following proposal is an attempt to relax this restriction in a completely compatible way. The idea is to replace the "magic" package Ada.Finalization with a "magic" generic and then have Ada.Finalization be just another instance of this generic, with no different properties than any user-defined instance would have. The generic could then be instantiated in other contexts. Tuck mentioned at the Vienna meeting that someone had suggested this approach to him. I had thought of it too; probably many people have. Does this seem like a reasonable change? -------- Replace 7.6(3-8) with Static Semantics The following language-defined library units exist: generic package Ada.Generic_Finalization is pragma Preelaborate (Generic_Finalization); pragma Remote_Types (Generic_Finalization); type Controlled is abstract tagged private; procedure Initialize (Object : in out Controlled); procedure Adjust (Object : in out Controlled); procedure Finalize (Object : in out Controlled); type Limited_Controlled is abstract tagged limited private; procedure Initialize (Object : in out Limited_Controlled); procedure Finalize (Object : in out Limited_Controlled); private ... -- not specified by the language end Ada.Generic_Finalization; with Ada.Generic_Finalization; pragma Elaborate (Ada.Generic_Finalization); package Ada.Finalization is new Ada.Generic_Finalization; pragma Preelaborate(Finalization); In 7.6(9), replace A controlled type is a descendant of Controlled or Limited_Controlled. with A controlled type is a descendant of either of the types Controlled or Limited_Controlled declared in an instance of Ada.Generic_Finalization. -------- This would allow something like generic type T is private; package G is ... end G; with Ada.Generic_Finalization; package body G is package Root is new Ada.Generic_Finalization; package Pkg is type My_Controlled is new Root.Controlled with record T_Component : T; end record; procedure Initialize (Object : in out My_Controlled); procedure Adjust (Object : in out My_Controlled); procedure Finalize (Object : in out My_Controlled); end Pkg; ... begin ... end; . Discussion Points: 1) As long as we've "got the hood up", should the 3 procedures be declared as null procedures? 2) Another name might be chosen instead of Generic_Finalization. 3) Are the pragmas right on these units? **************************************************************** From: Robert A. Duff Sent: Thursday, September 26, 2002 6:02 PM >... > The following proposal is an attempt to relax this restriction > in a completely compatible way. I think the proposal needs more explicit justification of why it's a pain-in-the-neck as is. >... > Does this seem like a reasonable change? Yes. See below for minor comments. >... > The following language-defined library units exist: > > generic > package Ada.Generic_Finalization is It would be useful to point out that the following text is exactly what previously existed in Ada.Finalization. > Discussion Points: > 1) As long as we've "got the hood up", should the 3 procedures be > declared as null procedures? Yes. (If *that* AI passes.) > 2) Another name might be chosen instead of Generic_Finalization. Seems OK to me. > 3) Are the pragmas right on these units? The latest RM (with corrigendum) has pragma Remote_Types on Ada.Finalization. Is that inherited from the generic (I don't remember the rules). I don't see why "pragma Elaborate (Ada.Generic_Finalization);" is needed on package Ada.Finalization. They're both Preelaborate anyway. (And if it does need Elaborate, why isn't it Elaborate_All?) **************************************************************** From: Randy Brukardt Sent: Thursday, September 26, 2002 8:14 PM > Is there an AI associated with this proposal? Not yet, we always wait until the discussion is complete before we decide whether a proposal is worth an AI. What I'm wondering is what is the justification for this? This doesn't seem to happen in practice. Early in the development of Claw, we tried to derive a controlled type in a library level package body, and three out of four compilers tried crashed. I suppose compilers are better now, but I'd still expect it to happen very rarely. In the example given, moving the declaration to the private part makes the generic legal, which doesn't seem to be a major difficultly. I also would be very concerned about the impact on implementations which were designed knowing that they did not have to worry about displays or static links when handling finalization. For instance, when the task supervisor in Janus/Ada does finalization, it doesn't necessarily have the display of the task available. Similarly, it is necessary in Janus's shared generic bodies to change displays when calling out. It's not clear to me whether it would be necessary to change the display back when doing finalization. We also do some finalization on-behalf-of called routines -- that would not be possible in this model. I don't have any examples of problems to show (thinking about having to change finalization in generic bodies makes my head hurt); I doubt I'd actually find the problems until I went to implement this, which of course is too late. **************************************************************** From: Randy Brukardt Sent: Friday, January 17, 2003 Private discussion on this proposal led me to write the following. I've attached it here so as to help explain why this is a very bad idea: --- > And I think that, in the interest of future generations, you should put a > detailed explanation of why this doesn't work for shared generics (it's > not obvious to me). Because the calling convention of subprograms is different in a generic body than elsewhere (there is a generic descriptor parameter). The only way to handle this is to build a thunk at instantiation time. But you can't do this without looking into the body -- and essentially you are no longer sharing if you do. The fact is that you can't create a tag in a generic body for any type that might EVER be called outside of the generic. And finalizations are generally implemented with a library subprogram, so they're outside the generic. Similarly, any object that was passed outside of the generic (such as on a access to class-wide list) could be finalized outside the generic. The current accessibility rules have this result almost by accident, but it's a critical property to any generic sharing that doesn't look into the body. (And my opinion is that sharing that does look into the body isn't generic sharing at all; it's simply an as-if optimization that could be done on any subprogram in the program. And it sure as heck doesn't need any help from the language rules.) We could diffuse this by limiting the proposal to generic specs, but I think that would be hard to explain (you can do this anywhere except in a generic body??!!), and the other issues with it still would be around. For instance, this proposal means that the task supervisor can no longer 'proxy' finalizations, because the context would now matter (you'd have to have the correct display or static links). I'd think that would make 'abort' and task termination a lot messier to implement. ****************************************************************