!standard 13.14 (05) 03-07-25 AI95-00369/01 !class amendment 03-07-22 !status work item 03-09-29 !status received no action 03-07-22 !status received 03-04-14 !priority Low !difficulty Medium !subject Relaxed freezing rules for generic instantiations !summary To better support generic signature packages, and mutually dependent types that involve generic instantiations, it is proposed that a generic instantiation not cause freezing immediately if any of its actual parameters are types that have not been completely defined. For such an instantiation, no special freezing happens at the point of the instantiation, other than the freezing that is due to the elaboration of the declarations within the "spec" of the instantiation. Elaboration of the body of the instantiation is deferred until a "general" freezing point occurs, which occurs at the end of the enclosing library unit or declarative part, upon encountering a "real" body, etc. NOTE: This more "relaxed" freezing and deferred body elaboration could be used for all generic instantiations, but that could create some incompatibilities, since we would be altering the point when the body of the instantiation was elaborated. This proposal is guaranteed to be upward compatible, since only instantiations that are currently illegal would be using "relaxed" freezing and deferred body elaboration. !problem Ada 95 provides formal package parameters. One way of using these parameters is to define a "signature" for a class of abstractions, such as all set abstractions, or all physical unit abstractions, and then build a new generic abstraction on top of the original class of abstractions using this signature as the template for a formal package parameter. Unfortunately, it is difficult to use signatures because of the fact that an instantiation freezes all of its actual parameters. For example: Given the signature for a set abstraction: generic type Element is private; type Set is private; with function Size(Of_Set : Set) return Natural is <>; with function Union(Left, Right : Set) return Set is <>; with function Intersection(Left, Right : Set) return Set is <>; with function Empty return Set is <>; with function Unit_Set(With_Item : Element) return Set is <>; with function Nth_Element(Of_Set : Set) return Element is <>; package Set_Signature is end; ... we could define a generic that required some set abstraction, but it didn't care which one so long as it implemented the above signature: generic with package Base_Set is new Set_Signature(<>); package Layered_Abstraction is type Cool_Type(Set : access Base_Set.Set) is limited_private; procedure Massage(CT : in out Cool_Type; New_Set : Base_Set.Set); ... end Layered_Abstraction; Now if we want to define a set type and provide the pre-instantiated signature for it, we run into trouble: generic type Elem is private; with function Hash(El : Elem) return Integer; package Hashed_Sets is type Set is private; function Union(Left, Right : Set) return Set; ... package Signature is new Set_Signature(Elem, Set); private type Set is record ... end record; end Hashed_Sets; The problem is that we can't do the instantiation of Set_Signature where we would want to do so, because the instantiation freezes the type "Set" prematurely. [For an extended example of use of signatures, see the physical units AI (AI-00324).] A similar problem occurs when a type wants to include a pointer to a container based on the type being defined. For example: package Expressions is type Expr_Ref is private; package Expr_Sequences is new Sequences(Expr_Ref); -- Freezing trouble here! type Seq_Of_Expr is access Expr_Sequences.Sequence; function Operands(Expr : Expr_Ref) return Seq_Of_Expr; ... private type Expression; -- completion deferred to body type Expr_Ref is access Expression; end Expressions; Here we have a case where we want to instantiate a generic using a private type, and use the results of the instantiation as the designated type of an access type, which is in turn used as a parameter or result type of an operation on the private type. Unfortunately, we can't instantiate the "Sequences" generic with Expr_Ref, since it is private. !proposal (See summary.) !wording (See summary.) !example (See problem.) !discussion Signature packages can be a very useful feature, but if they can't be instantiated in the generic that defines the abstraction, they become of much less use. Generics in general can be very useful, but the freezing rules mean that they are not as powerful as cut-and-paste, since they can't be applied to private types before the private type is completely defined. This proposal makes it possible for a generic instantiation to be used in more places than before, since it can be used with a private type before the type is completely defined. As things stand now, it is often necessary to completely restructure things to be able to use a generic container as part of defining a private type. --!corrigendum 13.14(05) !ACATS test An ACATS test should be created for this pragma. !summary !appendix From: Tucker Taft Sent: Wednesday, February 12, 2003 5:50 PM I talked about this AI a bit with Pascal in Padua. Here is a first cut at it. The basic idea is to relax the freezing rules associated with generic instantiations, so signatures can actually be used in a reasonable way. --- !standard 13.14 (05) 03-02-12 AI95-<>/01 !class amendment 03-02-12 !status work item 03-02-12 !status received 03-02-12 !priority Medium !difficulty Medium !subject Deferring Freezing of a Generic Instantiation !summary To better support generic signature packages, and mutually dependent types that involve generic instantiations, it is proposed that a generic instantiation not cause freezing immediately if any of its actual parameters are types that have not been completely defined. For such an instantiation, no special freezing happens at the point of the instantiation, other than the freezing that is due to the elaboration of the declarations within the "spec" of the instantiation. Elaboration of the body of the instantiation is deferred until a "general" freezing point occurs, which occurs at the end of the enclosing library unit or declarative part, upon encountering a "real" body, etc. NOTE: This more "relaxed" freezing and deferred body elaboration could be used for all generic instantiations, but that could create some incompatibilities, since we would be altering the point when the body of the instantiation was elaborated. This proposal is guaranteed to be upward compatible, since only instantiations that are currently illegal would be using "relaxed" freezing and deferred body elaboration. !problem Ada 95 provides formal package parameters. One way of using these parameters is to define a "signature" for a class of abstractions, such as all set abstractions, or all physical unit abstractions, and then build a new generic abstraction on top of the original class of abstractions using this signature as the template for a formal package parameter. Unfortunately, it is difficult to use signatures because of the fact that an instantiation freezes all of its actual parameters. For example: Given the signature for a set abstraction: generic type Element is private; type Set is private; with function Size(Of_Set : Set) return Natural is <>; with function Union(Left, Right : Set) return Set is <>; with function Intersection(Left, Right : Set) return Set is <>; with function Empty return Set is <>; with function Unit_Set(With_Item : Element) return Set is <>; with function Nth_Element(Of_Set : Set) return Element is <>; package Set_Signature is end; ... we could define a generic that required some set abstraction, but it didn't care which one so long as it implemented the above signature: generic with package Base_Set is new Set_Signature(<>); package Layered_Abstraction is type Cool_Type(Set : access Base_Set.Set) is limited_private; procedure Massage(CT : in out Cool_Type; New_Set : Base_Set.Set); ... end Layered_Abstraction; Now if we want to define a set type and provide the pre-instantiated signature for it, we run into trouble: generic type Elem is private; with function Hash(El : Elem) return Integer; package Hashed_Sets is type Set is private; function Union(Left, Right : Set) return Set; ... package Signature is new Set_Signature(Elem, Set); private type Set is record ... end record; end Hashed_Sets; The problem is that we can't do the instantiation of Set_Signature where we would want to do so, because the instantiation freezes the type "Set" prematurely. [For an extended example of use of signatures, see the physical units AI (AI-00324).] A similar problem occurs when a type wants to include a pointer to a container based on the type being defined. For example: package Expressions is type Expr_Ref is private; package Expr_Sequences is new Sequences(Expr_Ref); -- Freezing trouble here! type Seq_Of_Expr is access Expr_Sequences.Sequence; function Operands(Expr : Expr_Ref) return Seq_Of_Expr; ... private type Expression; -- completion deferred to body type Expr_Ref is access Expression; end Expressions; Here we have a case where we want to instantiate a generic using a private type, and use the results of the instantiation as the designated type of an access type, which is in turn used as a parameter or result type of an operation on the private type. Unfortunately, we can't instantiate the "Sequences" generic with Expr_Ref, since it is private. !proposal (See summary.) !wording (See summary.) !example (See problem.) !discussion Signature packages can be a very useful feature, but if they can't be instantiated in the generic that defines the abstraction, they become of much less use. Generics in general can be very useful, but the freezing rules mean that they are not as powerful as cut-and-paste, since they can't be applied to private types before the private type is completely defined. This proposal makes it possible for a generic instantiation to be used in more places than before, since it can be used with a private type before the type is completely defined. As things stand now, it is often necessary to completely restructure things to be able to use a generic container as part of defining a private type. **************************************************************** From: Robert A Duff Sent: Wednesday, February 12, 2003 7:09 PM As a user of Ada, I would find this relaxation of the freezing rules to be of *huge* benefit. ****************************************************************