CVS difference for ai05s/ai05-0130-1.txt

Differences between 1.2 and version 1.3
Log of other versions for file ai05s/ai05-0130-1.txt

--- ai05s/ai05-0130-1.txt	2008/12/05 05:33:20	1.2
+++ ai05s/ai05-0130-1.txt	2009/01/17 01:58:06	1.3
@@ -1,15 +1,18 @@
-!standard 7.6(12)                                               08-12-04  AI05-0130-1/01
+!standard 7.6(12)                                               09-01-16  AI05-0130-1/02
 !standard 7.6.1(9/2)
-!class binding interpretation 08-12-04
+!class ramification 09-01-16
 !status work item 08-12-04
 !status received 08-10-17
 !priority Low
 !difficulty Medium
-!qualifier Error
+!qualifier Clarification
 !subject Order of initialization/finalization of record extension components
 
 !summary
 
+The rules about order of initialization of record components are correct. This
+can cause some extension components to be initialized before some ancestor
+components.
 
 !question
 
@@ -23,17 +26,10 @@
 composition of initialization/finalization operations impossible (the operations
 would have to be different for every extension in order to get the ordering right).
 
-Is this the intent?
+Is this the intent? (Yes.)
 
-!recommendation
+!response
 
-(See Summary.)
-
-!wording
-
-
-!discussion
-
 The question is asking about an example like:
 
    with Ada.Finalization;
@@ -99,35 +95,38 @@
   Finalize Rec1
   Finalize Rec2
 
-But the reason for this requirement is in order that the Initialize operation
+The reason for this requirement is in order that the Initialize operation
 for a component with a self-referential access discriminant can assume that other
 components of the enclosing object have already been properly initialized
-(AARM 7.6(12.b)). Such a component cannot access (or even know about) components
-of any extensions, so there does not appear to be any value to having this
-requirement apply to all of the components of a type extension (rather than
-just to the extension components alone).
-
-This requirement surely increases the burden of understanding initialization of
-a type extension, as it is not simply composing the initialization of the parent
-part with the extension components.
-
-Moreover, there is potentially an extra implementation cost here. If the implementation
-uses a subprogram to initialize components of a tagged type T, it would make
-sense to use that subprogram to initialize the parent components of an extension
-of T (and just initialize the extension components directly in T). But that
-would be complicated by this requirement, and could not be done at all in
-unusual cases.
-
-[Not sure what the right answer is here. Changing the rule could cause a subtle
-incompatibility in existing programs, and *not* changing the rule also could
-cause such an incompatibility (one presumes that this AI will spawn an appropriate
-ACATS test, whatever the decision is), by causing implementers to change their
-implementations to match the actual wording rather than their understanding.]
+(AARM 7.6(12.b)). While that can't happen in this case, it is possible to
+construct cases where an ancestor component has an Initialize operation
+that does manage to access extension components. For instance, change Rec1.D
+to a classwide type, and dispatch on it to an operation that uses the extension
+components.
+
+This requirement is counter-intuitive, as it means that an extension
+component cannot assume that all of the ancestor components are initialized
+(if there are any components constrained by access discriminants). The conceptual
+model of extension components being added to the existing components without
+any semantic changes is false in this case. That is a possible source of bugs.
+
+But, clearly, the current rule also prevents bugs (just different bugs). In
+the absence of any reason to choice one set of bugs over another, it makes
+the most sense for the language to be consistent and use the same rules for
+all types. Thus, we do not recommend a change to this rule.
+
+Note that the rules as written potentially have an extra implementation cost
+over the "composing" order. If the implementation uses a subprogram to initialize
+components of a tagged type T, it would make sense to use that subprogram to
+initialize the parent components of an extension of T (and just initialize the
+extension components directly in T). But that would be complicated by this
+requirement, and could not be done at all in unusual cases.
+
+[Data point: at least some existing implementations get this wrong. There is
+clearly an implementation burden (and possible introduction of bugs) in redoing
+the compilers to get this right. Generally, we'd want an ACATS test to check
+these examples, which would encourage implementers to change. Do we want that??]
 
-
---!corrigendum 7.6.1(9/2)
-
-
 !ACATS Test
 
 An ACATS C-test should be constructed to test a case like the example given here,
@@ -223,5 +222,134 @@
         end Finalize;
 
     end Pak1;
+
+****************************************************************
+
+From: Adam Beneschan
+Sent: Thursday, December 18, 2008  7:52 PM
+
+I wanted to point out that an important statement in the discussion of
+AI05-0130-1 is, I believe, not quite correct.
+
+The example looks essentially like:
+
+    type Rec0;
+
+    type Rec1 (D : access Rec0) is new
+       Ada.Finalization.Limited_Controlled with null record;
+
+    type Rec0 is tagged limited record
+       Comp1 : Rec1 (Rec0'access);     -- has access discriminant
+    end record;
+
+    procedure Initialize (X : in out Rec1);
+    procedure Finalize (X : in out Rec1);
+
+    type Rec4 is new Rec0 with record
+       Comp2 : Rec2;   -- a controlled type, no access discriminant
+    end record;
+
+The language rules currently require that, for an object X of type Rec4, that
+X.Comp2 be initialized before X.Comp1 and finalized after.
+
+The discussion section of the AI contains this:
+
+"But the reason for this requirement is in order that the Initialize operation for
+a component with a self-referential access discriminant can assume that other
+components of the enclosing object have already been properly initialized (AARM 7.6(12.b)).
+Such a component cannot access (or even know about) components of any extensions, so
+there does not appear to be any value to having this requirement apply to all of
+the components of a type extension (rather than just to the extension components alone)."
+     
+The last sentence is correct in the above example.  But change it to: 
+
+    type Rec0 is tagged;
+
+    type Rec1 (D : access Rec0'Class) is new  -- CHANGED!!!!!
+       Ada.Finalization.Limited_Controlled with null record;
+
+    type Rec0 is tagged limited record
+       Comp1 : Rec1 (Rec0'access);     -- has access discriminant
+    end record;
+
+    procedure Initialize (X : in out Rec1);
+    procedure Finalize (X : in out Rec1);
+
+    type Rec4 is new Rec0 with record
+       Comp2 : Rec2;   -- a controlled type, no access discriminant
+    end record;
+
+and it's no longer correct, because now when Comp1 is initialized or finalized, the
+user-defined Initialize or Finalize routine *could* access Comp2, via a dispatching call
+on D.all (or by other means).  So it would be a problem if the rules were changed to
+allow Comp2 to be initialized after Comp1, or finalized before.  E.g.:
+
+    type Rec0 is tagged;
+
+    type Rec1 (D : access Rec0'Class) is new
+       Ada.Finalization.Limited_Controlled with null record;
+
+    type Rec0 is tagged limited record
+       Comp1 : Rec1 (Rec0'access);     -- has access discriminant
+    end record;
+    function Image_Of (X : in Rec0) return String;
+
+    procedure Initialize (X : in out Rec1);
+    procedure Finalize (X : in out Rec1);
+
+    type Rec4 is new Rec0 with record
+       Comp2 : Rec2;   -- a controlled type, no access discriminant
+    end record;
+    overriding function Image_Of (X : in Rec4) return String;
+
+
+    procedure Finalize (X : in out Rec1) is
+    begin
+       Write_To_Log ("Finalizing Rec1 that refers to: " & Image_Of(X.D.all));
+       ...
+    end Finalize;
+
+Assuming that Image_Of (X : in Rec4) contains some information about X.Comp2, the above
+Finalize routine would be calling Image_Of at a point after Comp2 were finalized, if the
+language rules were changed. 
+   
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, December 18, 2008  8:07 PM
+
+Thanks, Adam, for this example, I obviously didn't think of it. Did you tell Dan?? :-)
+[This was originally his question.]
+
+Specifically, with this additional example, I no longer understand precisely what change
+he was recommending. Moreover, I can't think of a good reason for changing the rules for
+*some* extension types, but not *all* extension types. If the compiler can't use composition
+in some cases, there's little reason to go out of our way allow it in other cases -- all of
+the support code needed to handle non-composing initialization must necessarily already exist
+in the compiler. Once you've gone to all of that work, there doesn't seem to be any reason
+not to use it always. (And, of course, rules that change because of the contents of some
+construct are a maintenance hazard.)
+
+As such, I will probably rewrite it as a confirmation (the existing rules are correct),
+unless someone explains better than I can why that would be a bad idea.
+
+****************************************************************
+
+From: Dan Eilers
+Sent: Monday, January 5, 2009  8:22 PM
+
+My main concern is that the existing rules are somewhat counter-intuitive, in that they imply
+that an ancestor may not be fully initialized before its descendants.  This could conceivably
+cause problems if the initializations have side-effects, and the order of the side-effects
+matters.  Adam has a good point, that changing this can also cause problems.  So I don't feel
+strongly about how this is decided.
+
+In any case, there should be an ACATS test, especially considering that implementations currently
+differ.  There should also probably be an RM note.
+
+p.s.
+  I think access discriminants are often used as workarounds for missing language features, and
+their problems could be minimized by providing direct language support for controlled types as
+interfaces, and by-reference IN parameters with modifiable state, etc.
 
 ****************************************************************

Questions? Ask the ACAA Technical Agent