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

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

--- ai05s/ai05-0041-1.txt	2007/03/27 22:52:35	1.1
+++ ai05s/ai05-0041-1.txt	2007/07/26 02:58:06	1.2
@@ -1,4 +1,5 @@
-!standard 3.7.1(7/2)                                          07-03-27    AI05-0041-1/01
+!standard 3.7.1(7/2)                                          07-07-25    AI05-0041-1/02
+!standard 4.8(6/2)
 !class binding interpretation 07-03-27
 !status work item 07-03-27
 !status received 07-03-27
@@ -8,7 +9,8 @@
 !subject Can a derived type be a partial view?
 !summary
 
-** TBD.
+For the purposes of the rules for allowing allocated unconstrained objects, any
+ancestor that has a constrained partial view causes the rules to apply.
 
 !question
 
@@ -53,13 +55,49 @@
 discriminant constraints that point at unconstrained objects) would require
 the partial view rule to be enforced. What is the intent?
 
+Similar examples can be created using nested packages rather than child packages.
+
 !recommendation
 
 (See Summary.)
 
 !wording
+
+Change the new text for 3.3(23.9/3) from AI05-0008-1 as follows:
 
-** TBD.
+* it is a dereference of a pool-specific access type, and there is
+  no {ancestor of its type that has a} partial view [of its type]
+  that is constrained.
+
+Change the new text for 3.3(23.10/3) from AI05-0008-1 as follows:
+
+For the purposes of determining within a generic body whether an
+object is known to be constrained, a subtype is not considered
+indefinite {and is considered to have a partial view that is constrained}
+if it is a descendant of an untagged generic formal derived type, nor
+is an access type considered pool-specific if it is a descendant of a
+formal access type.
+
+
+Change 3.7.1(7/2) as follows:
+
+... However, in the case of an a general access subtype,
+a discriminant_constraint is illegal if the designated type has {an ancestor
+which has} a partial view that is constrained or, for a general access
+subtype, has default_expressions for its discriminants. In addition to
+the places where Legality Rules normally apply (see 12.3), these rules
+apply also in the private part of an instance of a generic unit. In a
+generic body, this rule is checked presuming all formal access types of
+the generic might be general access types, {all formal derived types have
+partial views that are constrained, }and all untagged discriminated formal
+types of the generic might have default_expressions for their discriminants.
+
+Change 4.8(6/2) as follows:
+
+... If the designated type is composite, then the subtype of the created object
+is the designated subtype when the designated subtype is constrained or there
+is {an ancestor which has} a partial view of the designated type that is
+constrained; otherwise, the created object is constrained by its initial value ...
 
 !discussion
 
@@ -69,12 +107,60 @@
 
 Defining this kind of type to be a partial view would surely work, but it would trigger a
 number of other rules (for instance, about completions, freezing, and representation clauses)
-which might be harmful. As such, doing that seems to be too dangerous to contimplate,
+which might be harmful. As such, doing that seems to be too dangerous to contemplate,
 especially for a Corrigendum level change.
 
 Changing 3.7.1(7/2) also requires changing the matching 4.8(6/2).
 
+This problem can get even more confused if there are multiple different partial views
+for a type. Consider:
 
+    package P1 is
+        type T1 (D : Integer := 10) is private;
+    private 
+        type T1 (D : Integer := 10) is ...
+    end P1;
+
+    package P1.Child is
+        type T2 is private;
+    private
+        type T2 is new T1;
+    end P1.Child;
+
+Now T2 seems to have two partial views, one constrained and one
+unconstrained. In this case, the unconstrained partial view is unimportant,
+because the child can see the full view. But that isn't always true (especially
+for nested package).
+
+The wording needs to be careful to take cases like the above and like
+
+    package P2 is
+        type T1 (D : Integer := 10) is ...
+    end P2;
+
+    package P2.Child is
+        type T2 is private;
+    private
+        type T2 is new T1;
+    end P2.Child;
+
+into account. Surely the behavior of the above and of
+
+    package P2.Child2 is
+        type T3 is private;
+    private
+        type T3 (D : Integer := 10) is ...
+    end P2.Child2;
+
+should not differ vis-a-vis the "constrained partial view" rules: an object of both T2 and T3
+ought to be unconstrained if allocated with an allocator.
+
+It also needs to be the case that generic bodies assume that every derived formal type
+has such a partial view, so that they cannot cause this problem to reemerge. Similarly,
+we need to tweak the "known to be constrained" rules so that they take into account
+these changes, so that renames of discriminant-dependent components of potentially
+unconstrained objects are illegal.
+
 --!corrigendum 10.1.2(20/2)
 
 
@@ -322,5 +408,459 @@
 
 ****************************************************************
 
+From: Stephen W. Baird [private thread]
+Date: Monday, July 16, 2007  2:36 PM
+
+Here  is an example to add to AI05-0041.
+This is an unconstrained-view-of-a-constrained-variable problem.
+Should this example compile successfully?
+If so, then what should happen when it executes?
+--------
+  procedure Derived_Ops_With_Access_Params is 
+    subtype Index is Integer range 0 .. 100; 
+    package Pkg1 is 
+        type T1 is private; 
+    private 
+        type T1 (Length : Index := 50) is 
+            record 
+                F : String (1 .. Length); 
+            end record; 
+        procedure Proc (X : access T1); 
+        package Pkg2 is 
+            type T2 is new T1; 
+        end Pkg2; 
+    end Pkg1; 
+    package body Pkg1 is 
+        procedure Proc (X : access T1) is 
+        begin 
+            X.all := (Index'Last, (others => Character'First));
+        end Proc; 
+        package body Pkg2 is 
+            type Ref is access T2; 
+            Ptr : Ref := new T2; 
+            X2  : T2 renames Ptr.all;  -- Is X2 constrained?
+        begin 
+            Proc (X2'Access); 
+        end Pkg2; 
+    end Pkg1; 
+ begin 
+    null; 
+end Derived_Ops_With_Access_Params; 
+
+****************************************************************
+
+From: Randy Brukardt
+Date: Monday, July 16, 2007  3:46 PM
+
+I'm still getting over my recent bout of pneumonia, so I might not be
+making sense, but I don't see any (new) issue here. X2 should be whatever
+a similar X1 would be (if you did the same sequence of declarations for T1).
+[Unless you are claiming that is wrong too, in which case I wouldn't confuse
+it with the derived case. But I don't *think* that is what you are saying.]
+
+So, I would like to know what this example is supposed to illustrate that
+is not covered by the AI [else I have no idea of what to add to the AI].
+Or, more generally, what's your point? (My brain is not able to guess right now.)
+
+****************************************************************
+
+From: Stephen W. Baird
+Date: Monday, July 16, 2007  6:04 PM
+
+What's new here is the interaction with parameters of anonymous access 
+types.
+
+You have an untagged unconstrained definite record type T1 which has a
+primitive operation with an "access T1" parameter. You declare a derived
+type T2, which is derived from T1. The two types disagree with respect to 
+the "has a constrained partial view" property; in particular, T1 has the 
+property and T2 does not.
+
+This is a recipe for trouble.
+
+When you call the derived subprogram, you can end up passing a reference
+to a constrained object to a subprogram which is expecting a reference to
+an unconstrained object (and which might assign a larger value to the
+designated object than it is capable of holding).
+
+Pkg1.Proc has a parameter X of type access T1.
+Since T1 has a constrained partial view, this means that
+X  designates an unconstrained object (ignoring the X=null case).
+
+So there is no need for any checks in Pkg1.Proc  when it assigns a
+big value to X.all.
+
+On the other hand, type T2 lacks a constrained partial view, so
+that allocated objects of type T2 are constrained.
+
+Thus, X2 is constrained.
+
+Note that the procedure call at the center of this whole mess,
+   Proc (X2'Access);
+is a call to the derived subprogram Pkg2.Proc, not to Pkg1.Proc.
+
+Does this clarify matters?
+
+****************************************************************
+
+From: Randy Brukardt
+Date: Monday, July 16, 2007  6:45 PM
+
+> What's new here is the interaction with parameters of anonymous access 
+> types
+> 
+> You have an untagged unconstrained definite record type T1 which has a
+> primitive operation with an "access T1" parameter. You declare a derived
+> type T2, which is derived from T1. The two types disagree with respect to the
+> "has a constrained partial view" property; in particular, T1 has the 
+> property and T2 does not.
+
+But this is the point of the AI: T1 and T2 *cannot* disagree on this property,
+or all heck breaks loose. The original example has similar problems where you
+can get nonsense results because the language isn't clear whether T2 has a
+"constrained partial view". (I *do not* agree with you that it is clear that
+it does not have this property; derived types inherit properties, and in the
+case of child units, they have to inherit partial views as well or even Ada 95
+is screwed up. This just seems to me to be a case where the wording is
+insufficiently clear...)
+
+> This is a recipe for trouble.
+
+Yes, of course, but as I said, that is the point of the original AI. There
+doesn't seem to be anything new here, other than another example of the problems
+caused if T2 does not have a "constrained partial view".
+
+> When you call the derived subprogram, you can end up passing a reference
+> to a constrained object to a subprogram which is expecting a reference to
+> an unconstrained object (and which might assign a larger value to the
+> designated object than it is capable of holding).
+> 
+> Pkg1.Proc has a parameter X of type access T1.
+> Since T1 has a constrained partial view, this means that
+> X  designates an unconstrained object (ignoring the X=null case).
+> 
+> So there is no need for any checks in Pkg1.Proc  when it assigns a
+> big value to X.all.
+> 
+> On the other hand, type T2 lacks a constrained partial view, so
+> that allocated objects of type T2 are constrained.
+
+T2 cannot "lack a constrained partial view", or there is all manner of trouble
+(see the examples in the original AI). I agree there is a bug here, but it is
+the same one we're already talking about.
+ 
+> Thus, X2 is constrained.
+> 
+> Note that the procedure call at the center of this whole mess,
+>    Proc (X2'Access);
+> is a call to the derived subprogram Pkg2.Proc, not to Pkg1.Proc.
+> 
+> Does this clarify matters?
+
+Yes, but I'm still confused as to why you think there is anything important
+different about this example from the one in the AI. The whole point of the
+AI is that types like T2 need to trigger the "constrained partial view" rules,
+or all kinds of anomolies are possible.
+
+I can believe that the AI doesn't say that very clearly, but I still don't
+know what is missing from the AI. Your original note claimed that this needed
+to be added to AI-41, and I still don't see why (other than in the !appendix
+as another curiousity). Parameter passing into derived subprograms (with any
+kind of parameter!) is why you get anomolies here. And in any case, there is
+no point of loading AIs down with dozens of examples; the only issue is to
+illustrate the problem. The original examples seem to do that just fine. What
+(if anything) am I missing??
+
+****************************************************************
+
+From: Pascal Leroy
+Date: Tuesday, July 17, 2007  2:07 AM
+
+Well, I am the one who suggested to Steve that he send this example to
+you.  It took me some time to figure out that his example was actually
+similar to the one in AI05-0041.  What I would like to see is a blurb in
+the discussion saying "while the original example involved a child unit,
+it is possible to run into the same problem with a nested package".  I
+think this is worth pointing out because, while children and nested
+packages have analogies, the differences in visibility cause derived
+subprograms to pop up at different places and they don't always have the
+same problems.
+
+If you feel strongly otherwise I am not going to fight.  Incidentally, I
+agree with you (and disagree with Steve): type T2 does have a partial view
+for the purpose of this rule.  Note that we might not want to call it a
+partial view, though, because it would cause innumerable other rules to
+kick in.
+
+****************************************************************
+
+From: Stephen W. Baird
+Date: Tuesday, July 17, 2007  3:30 PM
 
+Randy - You are right, using anonymous access parameters doesn't
+really change this into a new problem.
+
+Am I right in thinking that the presence or absence of an explicit
+partial view for a derived type should always be irrelevant for
+purposes of determining whether an allocated object is constrained?
+
+I understand that the AI hasn't been written yet; I'm asking about
+your understanding of the intent of the AI.
+
+I'm interested in the case where the parent type lacks a partial
+view and the derived type has one - the opposite of the case that
+is illustrated in the AI.
+
+****************************************************************
 
+From: Randy Brukardt
+Date: Tuesday, July 17, 2007  4:40 PM
+
+> Am I right in thinking that the presence or absence of an explicit
+> partial view for a derived type should always be irrelevant for
+> purposes of determining whether an allocated object is constrained? 
+
+I'm not sure. I'm pretty sure that that is the case when the derived type
+does not have a partial view. But...
+
+> I understand that the AI hasn't been written yet; I'm asking about
+> your understanding of the intent of the AI.
+
+I'm not sure I have one. I have an understanding of the problem, not
+so much of the solutions. I'm rather counting on Tucker to make it all
+better... ;-)
+
+> I'm interested in the case where the parent type lacks a partial
+> view and the derived type has one - the opposite of the case that
+> is illustrated in the AI.
+
+I don't think that you can ignore the partial view, if there is one, on
+the derived type. Otherwise, you can reintroduce the original problem.
+
+    package P1 is
+        type T1 (D : Integer := 10) is ...
+    end P1;
+
+    with P1;
+    package P2 is
+        type T2 is private;
+    private
+        type T2 is new T1;
+    end P2;
+
+The full view of T2 has defaulted discriminants, and one would hope that
+allocated objects of T2 would be unconstrained (else we haven't fixed
+anything with these rules). There shouldn't be a difference semantically
+between the T2 given here and "type T2 (D : Integer := 0) is ...".
+
+So I think it does matter. What's even messier is if you add a partial view
+to T1 in the above example:
+
+    package P1 is
+        type T1 (D : Integer := 10) is private;
+    private 
+        type T1 (D : Integer := 10) is ...
+    end P1;
+
+    with P1;
+    package P2 is
+        type T2 is private;
+    private
+        type T2 is new T1;
+    end P2;
+
+Now T2 seems to have two partial views, one constrained and one
+unconstrained. Yikes!
+
+Oh, what a tangled web we weave...
+
+****************************************************************
+
+From: Stephen W. Baird
+Date: Tuesday, July 17, 2007  6:12 PM
+
+This sounds desirable, but I'm worried about the reverse problem where
+thinking (statically) that allocated objects are constrained
+when (dynamically) they really aren't allows us to get in trouble.
+
+I'm thinking of something like a rename of a discriminant-dependent 
+component of an allocated object within a derivable subprogram.
+
+On the other hand, perhaps 3.7.2(4) is broad enough to cover any such 
+problems.
+
+I'll think about it.
+
+****************************************************************
+
+From: Randy Brukardt
+Date: Tuesday, July 17, 2007  6:36 PM
+
+> This sounds desirable, but I'm worried about the reverse problem where
+> thinking (statically) that allocated objects are constrained
+> when (dynamically) they really aren't allows us to get in trouble.
+
+Is that possible? It seems that if an object of a type ought to be
+allocated unconstrained because of some view, then it should be
+allocated unconstrained (and everyone else should assume that).
+
+> I'm thinking of something like a rename of a discriminant-dependent component
+> of an allocated object within a derivable subprogram.
+
+Humm.
+
+> On the other hand, perhaps 3.7.2(4) is broad enough to cover any such 
+> problems.
+
+Might be. It would seem to always apply to parameters (and when it doesn't,
+the new rule added by AI-0008 does).
+ 
+> I'll think about it.
+
+That scares me more than your original question. ;-)
+
+****************************************************************
+
+From: Pascal Leroy
+Date: Wednesday, July 18, 2007  1:50 AM
+
+> Now T2 seems to have two partial views, one constrained and 
+> one unconstrained. Yikes!
+
+From these examples, it seems to me that 3.7.1(7/2) should say something
+like:
+
+"... if the designated type has an ancestor which has a partial view that
+is constrained...".
+
+In other words, if there is a type to which you can convert that is
+private and doesn't expose defaulted discriminants, then the allocated
+objects are effectively unconstrained, and you don't want to be able to
+write an access constraint.
+
+It this fix works, it is much simpler than changing the meaning of
+"partial view".
+
+PS: I'm sure that Tuck won't like the wording above and will change it to
+something that reads better.
+
+****************************************************************
+
+From: Stephen W Baird
+Date: Wednesday, July 18, 2007  12:27 PM
+
+> From these examples, it seems to me that 3.7.1(7/2) should say something
+> like:
+> 
+> "... if the designated type has an ancestor which has a partial view that
+> is constrained...".
+
+This certainly sounds like an improvement on the current wording.
+
+As I mentioned to Randy, I am a little concerned that there may be problems
+in the opposite direction: 
+
+> ... I'm worried about the reverse problem where
+> thinking (statically) that allocated objects are constrained
+> when (dynamically) they really aren't allows us to get in trouble.
+> 
+> I'm thinking of something like a rename of a discriminant-dependent component
+> of an allocated object within a derivable subprogram.
+> 
+> On the other hand, perhaps 3.7.2(4) is broad enough to cover any 
+> such problems.
+
+I have not been able to construct any problems which 3.7.2(4) doesn't cover;
+on the other hand, relying on an erroneous execution rule isn't entirely
+satisfactory.
+
+As I mentioned to Pascal, there are also problems in this area with
+generic formal derived types (which can be solved with an assume-the-worst
+rule, or perhaps simply by invoking 3.7.2(4)):
+
+with Text_Io;
+procedure Constrained_By_Initial_Value is
+   type T1 (Is_Float : Boolean := False) is
+      record
+         case Is_Float is
+            when False =>
+               Int_Val : Integer;
+            when True =>
+               Float_Val : Float;
+         end case;
+      end record;
+
+   generic
+      type D is new T1;
+   package G is
+      type Ref is access D;
+      Ptr : Ref := new D;
+      X : D renames Ptr.all;
+
+      function Get return Integer;
+   end G;
+
+   package body G is
+      Body_Rename : Integer renames X.Int_Val;
+
+      function Get return Integer is
+      begin
+         return Body_Rename;
+      end Get;
+   end G;
+
+   package Pkg is
+      type T2 is private;
+   private
+      type T2 is new T1;
+      package I is new G (T2);
+   end Pkg;
+
+   package body Pkg is
+   begin
+      I.X := (Is_Float => True, Float_Val => 1234.5);
+      -- at this point, I.Body_Rename is a dangling rename
+      Text_Io.Put_Line (Integer'Image (I.Get));
+   end Pkg;
+
+begin
+   null;
+end Constrained_By_Initial_Value;
+
+****************************************************************
+
+From: Randy Brukardt
+Date: Wednesday, July 25, 2007  7:14 PM
+
+...
+>I have not been able to construct any problems which 3.7.2(4) doesn't cover;
+>on the other hand, relying on an erroneous execution rule isn't entirely
+>satisfactory.
+
+I agree. But we've already made massive changes to this area in AI05-0008. We
+might as well tweak those changes enough to cover this properly. I've done that
+in /02 of this AI.
+
+>As I mentioned to Pascal, there are also problems in this area with
+>generic formal derived types (which can be solved with an assume-the-worst
+>rule, or perhaps simply by invoking 3.7.2(4)):
+
+[This example came through in HTML, and that stripped all of the indentation...]
+
+...
+>generic
+>type D is new T1;
+>package G is
+>type Ref is access D;
+>Ptr : Ref := new D;
+>X : D renames Ptr.all;
+...
+>
+>package body G is
+>Body_Rename : Integer renames X.Int_Val;
+
+This is illegal with a tweaking of the existing (AI05-0008) assume-the-worst rule
+for renames ("known to be constrained"). We may need to discuss if this tweaking
+is too draconian, but I doubt it personally.
+
+****************************************************************

Questions? Ask the ACAA Technical Agent