CVS difference for ais/ai-00344.txt

Differences between 1.3 and version 1.4
Log of other versions for file ais/ai-00344.txt

--- ais/ai-00344.txt	2004/04/06 21:51:27	1.3
+++ ais/ai-00344.txt	2004/05/29 00:38:39	1.4
@@ -1159,3 +1159,942 @@
 
 ****************************************************************
 
+From: Stephen W. Baird
+Sent: Friday, April 30, 2004  3:50 PM
+
+AI-344 requires dynamic tag allocation in some cases. This will be something
+new for some (most?) implementations. This is implementable, but this
+consequence of the AI has not been discussed by the ARG.
+
+Consider this example:
+
+  procedure Outer is
+    type Float_Vector is array (Positive range <>) of Float;
+    type Integer_Vector is array (Positive range <>) of Integer;
+    Test_Failed : exception;
+
+    type Root is tagged null record;
+    type Ref is access all Root'Class;
+    P1, P2 : Ref;
+
+    procedure Inner (N : Natural := 3) is
+	type Extension is new Root with -- legal by AI-344
+	    record
+                F1 : Integer_Vector (1 .. N) := (others => 0);
+                F2 : Float_Vector (N .. 10) := (others => 0.0);
+	    end record;
+        Local : aliased Extension;
+    begin
+        if P1 = null then
+            P1 := Local'Unchecked_Access;
+            Inner (N + 1);
+        elsif P2 = null then
+            P2 := Local'Unchecked_Access;
+            Inner (N + 1);
+        elsif P1.all = P2.all then
+            raise Test_Failed;
+        end if;
+    end Inner;
+  begin
+    Inner;
+  end Outer;
+
+It seems clear that the "P1.all = P2.all" test would be problematic if
+P1.all'Tag = P2.all'Tag. Those two objects must have distinct tags, and
+AI-344 probably should state this explicitly.
+
+This is not a problem with Unchecked_Access. It would be possible, albeit
+somewhat more complicated, to construct an instance of the problem which
+does not use Unchecked_Access (e.g. using tasks).
+
+I believe that the Ada95 designers originally intended that multiple
+elaborations of a tagged type declaration (e.g. one declared inside of a
+subprogram) might share the same statically allocated tag value, or they might
+have distinct dynamically allocated tags; either implementation should work.
+
+This is no longer true in the face of AI-344 (although it remains true for
+types whose legality does not depend on AI-344).
+
+A Tag value may outlive its corresponding tagged type. Implementations must
+be careful to avoid both dangling references and storage leaks in this case.
+Typically this means that creating a dynamically allocated Tag value cannot
+involve any kind of dynamic storage allocation. This issue already exists
+in Ada95, but only for implementations which choose to allocate Tag values
+dynamically. AI-344 forces everyone into that category, at least in some cases.
+
+****************************************************************
+
+From: Gary Dismukes
+Sent: Friday, April 30, 2004  6:53 PM
+
+Steve Baird wrote:
+> AI-344 requires dynamic tag allocation in some cases. This will be something
+> new for some (most?) implementations. This is implementable, but this
+> consequence of the AI has not been discussed by the ARG.
+
+Yuck, I think that the prospect of requiring dynamic tag allocation
+would be enough to kill this AI.
+
+> It seems clear that the "P1.all = P2.all" test would be problematic if
+> P1.all'Tag = P2.all'Tag. Those two objects must have distinct tags, and
+> AI-344 probably should state this explicitly.
+
+This seems pretty pathological.  You do have a devious mind Steve!
+I would almost rather define such usage as erroneous rather than bite
+the bullet of implementing dynamic tags just to handle such pathologies.
+
+> This is not a problem with Unchecked_Access. It would be possible, albeit
+> somewhat more complicated, to construct an instance of the problem which
+> does not use Unchecked_Access (e.g. using tasks).
+
+OK, but I can't help but wonder how much of a pathology these other
+possible cases are.  Since I'm not sure what your other examples
+are perhaps you'll have to show the details.  Somehow I suspect
+they're pretty ugly.
+
+> A Tag value may outlive its corresponding tagged type. Implementations must
+> be careful to avoid both dangling references and storage leaks in this case.
+> Typically this means that creating a dynamically allocated Tag value cannot
+> involve any kind of dynamic storage allocation. This issue already exists
+> in Ada95, but only for implementations which choose to allocate Tag values
+> dynamically. AI-344 forces everyone into that category, at least in some cases.
+
+If that's a necessary implication of the AI, then my guess is that will be
+a significant nail in its coffin.  Which side are you on anyway Steve? ;-)
+
+****************************************************************
+
+From: Robert Dewar
+Sent: Friday, April 30, 2004  7:01 PM
+
+> Yuck, I think that the prospect of requiring dynamic tag allocation
+> would be enough to kill this AI.
+
+I agree!
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Friday, April 30, 2004  10:32 PM
+
+The canonical implementation model for nested
+type extensions is that each object carries a
+static link, or a pointer to a display.  That implies
+to me that for operations with multiple controlling
+parameters, an additional check needs to be performed
+*after* the dispatch if you arrive in an operation which
+actually makes use of such a static link to make sure the static links
+or displays are the same.  If they don't agree, then an
+exception should be raised just as though there had
+been a tag mismatch.
+
+This seems like a relatively low overhead, since operations
+with multiple controlling operands are relatively rare,
+and the overhead would only be incurred when reaching
+such an operation on a nested type, meaning it is
+not a distributed overhead.
+
+Note that some implementations
+may create "wrappers" for dispatching operations of
+nested extensions to fetch the static link/display
+pointer and then call the "real" body with the static
+link/display in the "normal" register or per-task
+display used for that.  This wrapper would be the
+natural place to perform this additional check.
+
+Hence, I see no need for a "dynamic" tag, nor
+any need for distributed overhead.  It does mean,
+however, that comparing tags may not be a foolproof
+way of knowing whether the tag-check will fail
+when calling an operation with multiple controlling
+operands.  We might want to add some way of doing
+such a check, which might be by having another
+attribute which would return some kind of "'Extended_Tag"
+which would be a concatenation of the tag and
+the static link/display-ptr if present.  This would
+probably require an additional implicit dispatching
+operation, analogous to the one needed to implement
+'Size on a class-wide object.  I don't think we want
+to change 'Tag itself to have this additional overhead,
+though it probably wouldn't be that big of a deal
+either way.
+
+****************************************************************
+
+From: Stephen W. Baird
+Sent: Friday, April 30, 2004  11:28 PM
+
+dismukes@gnat.com (Gary Dismukes) wrote on 04/30/2004 04:52:33 PM:
+> Which side are you on anyway Steve?
+
+I strongly feel that it must be ok to instantiate AI-302's various
+container generics anywhere, e.g. inside of a subprogram body which is
+inside of a generic body.
+
+I also believe that the implementations of these container generics will
+need to extend Ada.Finalization.[Limited_]Controlled.
+
+As the language stands today, these requirements cannot both be satisfied.
+
+Because of this, I support AI-344 (including loosening up 3.9.1(4)).
+
+The Ada.Generic_Finalization proposal that I described a while back (after
+the Vienna meeting, I think) could also be used to solve this problem,
+although it pertains only to controlled types, not tagged types in
+general.
+
+If AI-344 is shot down, perhaps this proposal should be revisited (feel
+free to interpret this as a reason to support AI-344).
+
+P.S. Note that "dynamic tag allocation" might not be as difficult to implement
+as it sounds. Consider implementing the type Ada.Tags.Tag as a two-field record
+- a pointer to a statically allocated data structure (e.g. a dispatch table)
+and a uniquifying integer value that could be initialized by calling some name
+allocator (there are cheaper ways). Ada.Tags.External_Tag's name for a type
+might be pretty much what it is today, except with the image of this extra
+integer tacked on the end. Ada.Tags.Internal_Tag could strip an integer off the
+end of its argument to get the unique_id of its result and then use the same
+statically-initialized mapping that is used today to get the dispatch table
+address. A runtime check of the validity of this result might or might not be
+required. Some details remain (you might want to special case types whose
+legality does not depend on AI-344, setting the unique_id field to a null value
+and omitting it from the External_Tag string), but the point is that this need
+not involve anything as complicated as dynamic storage allocation.
+
+****************************************************************
+
+From: Robert Dewar
+Sent: Monday, May  3, 2004  6:07 AM
+
+This sounds like a major incompatible earthquake at the implementation
+and actual usage level. It would change the format of all tagged types
+if I understand you correctly, and I would regard that as out of the
+question. Am I missing something?
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Monday, May  3, 2004   8:19 AM
+
+> P.S. Note that "dynamic tag allocation" might not be as difficult to
+> implement as it sounds. Consider implementing
+> the type Ada.Tags.Tag as a two-field record ...
+
+This is similar to what I ws proposing.  Since the canonical
+implementation model requires that a static link/display pointer
+be added as part of extending a type in a more nested scope,
+the pair made up of the tag and the static link/display pointer
+could provide this "dynamic" tag.  As I suggested,
+the dynamic part of the tag need not be checked until
+you get to a nested overriding of a dispatching operation
+with more than one controlling operand.
+
+It is a question whether 'Tag should be changed to return
+this dynamic part, or whether a separate 'Extended_Tag
+or equivalent should be provided to get both.  In any
+case, there probably needs to be an implicit dispatching
+operation, analogous to that supporting 'Size, which
+returns the 'Extended_Tag pair [tag, static-link].
+
+This pair is similar to what some implementations use
+to represent an access-to-subprogram value when the access
+type is declared in a nested scope.
+
+I agree with Robert that we don't want a solution that
+changes the representation of existing tagged types.
+I believe the approach I suggested imposes minimal
+overhead on existing tagged types, because it only
+requires one additional implicit dispatching op which
+returns [tag, null] by default.  It could be made
+even simpler by having it be a procedure which
+updates the second half of such a two-word "extended"
+tag.  Then it could be a "null" procedure by default.
+
+****************************************************************
+
+From: Robert Dewar
+Sent: Monday, May  3, 2004  8:34 AM
+
+Sounds reasonable to me
+
+****************************************************************
+
+From: Stephen W. Baird
+Sent: Monday, May  3, 2004  12:16 PM
+
+> I agree with Robert that we don't want a solution that
+> changes the representation of existing tagged types.
+
+I agree.
+Modifying 3.9.2(16) makes a lot more sense than changing the
+implementation of Ada.Tags.Tag.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Monday, May  3, 2004  12:55 PM
+
+Hence, the wording for 3.9.2(16) should be augmented to say:
+
+   If there is more than one dynamically tagged controlling operand,
+   a check is made that they all have the same tag{, and that they
+   all are associated with the same type elaboration}.
+
+An implementation note would indicate a possible implementation
+approach for this which incurs no distributed (time) overhead.
+
+We might also add to 3.9 a declaration of an Extended_Tag type in
+Ada.Tags, and an Extended_Tag attribute of subtypes and
+class-wide objects that uniquely identifies a particular elaboration
+of a tagged type among types that exist concurrently.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Monday, May  3, 2004  12:28 PM
+
+[Editor's Note: This note seems to be about a private discussion; none of
+the previous messages are available here. The topic seems important enough to
+include here.]
+
+Stephen W Baird wrote:
+
+> You make a good point about not changing the streamed format of existing
+> types. I agree that this is important.
+>
+>>I suppose we could require types with ancestors at
+>>an outer level to add something distinguishing them, so
+>>long as all types with no such ancestors can continue
+>>to use the same streamed representation as they do today.
+>
+> I think we need something like this. Regardless of how frequently it comes
+> up, streaming rules need to be well defined.
+
+Well, we should look at AI-279 before getting too concerned
+about this case.  We say it is erroneous to use T'Class'Input
+if the tag is for a type that hasn't been frozen or doesn't
+exist.  I don't see it to be necessary to provide much stronger
+protections against the case where there are multiple types
+the tag represents.
+
+>>I just hate to devote too much implementor effort to this issue.
+>
+> I agree, although I feel that this AI (or some mechanism to allow
+> AI-302's generics to be instantiated most anywhere) is very important.
+> If we have to introduce some complexity, that does not mean we should kill
+> the AI.
+
+True, but we shouldn't introduce significant complexity just to support
+a pathological case.  I would claim it borders on pathological to
+have simultaneously instances of the "same" type from different
+dynamic scopes, and then try to stream them.
+
+One possibility would be to require that nested type extensions
+dynamically enter their tag into the tag "table" used by Internal_Tag,
+and restore any entry previously there on the way back out.  But that
+would require that each task have its own tag table.
+
+A simpler approach might be to say that T'Class'Output and T'Class'Input
+only work for extensions declared at the same level as T.  They
+would raise Constraint_Error otherwise.  That would be upward compatible
+and safe, though admittedly somewhat less flexible.  Then all we would
+need to know is the static nesting level associated with a given tag,
+which might want to be an operation in Ada.Tags defined on type Tag
+(though perhaps it should be a "private" operation).
+
+In any case, it seems this issue should be considered in the context
+of AI-279, and we shouldn't go overboard if we concluded erroneousness
+was acceptable in certain cases already.
+
+****************************************************************
+
+From: Jean-Pierre Rosen
+Sent: Tuesday, May  4, 2004  3:03 PM
+
+Not being writing a compiler, I can't comment on the dynamic tags and all that
+stuff. But I'm puzzled by the ratio complication/usefulness of the feature.
+
+After all, AFAIK, no other OO language allows defining classes nested in
+a subprogram.
+
+The only case where this would be useful seems to be to declare nested
+controlled types. If others agree on this, then let's just solve this
+problem.
+
+A possible solution would be to declare:
+   for T'Finalization use ...;
+etc.
+(of course, Ada.Finalization.Controlled would be declared this way, so
+it would be a compatible change).
+
+I remember Tuck saying that this solution was considered for Ada 95; I
+don't remember exactly why it was discarded, but I think not for reasons
+that could not be revisited.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Wednesday, May  5, 2004  2:53 AM
+
+> After all, AFAIK, no other OO language allows defining classes nested in
+> a subprogram.
+
+That's actually not true.  Java allows nested classes,
+and they can be defined essentialy anywhere, including
+inside a method (aka subprogram).  The syntax is a bit weird,
+since the class extension occurs as a side effect of writing
+a constructor followed by an open brace ("{").  It is actually
+used fairly heavily, as a way to create a short-lived call-back.
+
+I don't know about C#, but Java and C# are matching each other
+feature for feature, so I suspect if C# doesn't have it now,
+it will soon. ;-)
+
+> The only case where this would be useful seems to be to declare nested
+> controlled types. If others agree on this, then let's just solve this
+> problem.
+
+That isn't the only problem.  There are three built-in abstractions
+that use type extension -- controlled types, storage pools,
+and streams.  All of these are the kind of thing you might
+want to extend in a generic, especially one that is providing
+a "container" abstraction.  As soon as you do that, you are
+stuck with a generic that cannot be instantiated at a nested
+level.
+
+And users who have designed their own tagged types are
+essentially precluded from extending them inside generics,
+unless they want the generic to be a library-level only
+generic.
+
+>
+> A possible solution would be to declare:
+>    for T'Finalization use ...;
+> etc.
+> (of course, Ada.Finalization.Controlled would be declared this way, so
+> it would be a compatible change).
+>
+> I remember Tuck saying that this solution was considered for Ada 95; I
+> don't remember exactly why it was discarded, but I think not for reasons
+> that could not be revisited.
+
+Finalization is a massive can of worms.  I suspect most implementors
+would rather implement nested type extensions than redo finalization
+in a significantly different manner.  And my sense is that many
+of the challenges associated with nested type extension might
+come up when supporting nested finalization.  But the programmer
+wouldn't get as much benefit from the implementor's effort.
+
+****************************************************************
+
+From: Stephen W. Baird
+Sent: Friday, May  7, 2004  5:21 PM
+
+> Hence, the wording for 3.9.2(16) should be augmented to say:
+>
+>    If there is more than one dynamically tagged controlling operand,
+>    a check is made that they all have the same tag{, and that they
+>    all are associated with the same type elaboration}.
+>
+
+Are similar changes needed in order to catch bad type conversions?
+
+4.6(42) states:
+   If the operand is class-wide, a check is made that the tag of the
+operand identifies a (specific) type that is covered by or descended from
+the target type.
+
+Consider the type conversion in the example below.
+If the implementation allocates tags statically, then Param'Tag will equal
+Extension'Tag and this check will (incorrectly)  pass.
+
+I think that  5.2(10)  is ok as it stands.
+Once the conversion problem is fixed, the subtype conversion of 5.2(11)
+will perform the needed check.
+
+Membership tests may need work.
+
+4.5.2(30) states:
+   ... and, if the the type of the simple_expression is class-wide, the
+value has a tag that identifies a type covered by the tested type.
+
+Consider the membership test in the example below.
+If the implementation allocates tags statically, then Param'Tag will equal
+Extension'Tag and the membership test will (incorrectly) yield True.
+
+--------
+
+procedure Outer is
+  Test_Failed : exception;
+
+  type Root is tagged null record;
+
+  N : Natural := 0;
+
+  procedure Inner (Param : in out Root'Class) is
+    type Extension is new Root with
+      record
+        F : String (1 .. N) := (others => '?');
+      end record;
+
+    Local : Extension;
+  begin
+    if N = 0 then
+      N := 100;
+      Inner (Local);
+
+    elsif Param in Extension'Class then
+      raise Test_Failed;
+
+    else
+      begin
+        declare
+          Converted : Extension renames Extension (Param);
+        begin
+          raise Test_Failed;
+        end;
+      exception
+        when Constraint_Error =>
+          null;
+      end;
+    end if;
+  end Inner;
+
+begin
+  declare
+    Root_Var : Root;
+  begin
+    Inner (Root_Var);
+  end;
+end Outer;
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Friday, May  7, 2004  6:02 PM
+
+If we introduce the notion of an "extended tag" then we
+can probably change these all to say "an (extended) tag that
+identifies a type...", or in the case of 3.9.2(16) which
+prompted this, "... they all have the same (extended) tag."
+
+I'm not sure whether parenthesization helps or hurts...
+
+****************************************************************
+
+From: Stephen W. Baird
+Sent: Monday, May 10, 2004  1:45 PM
+
+I'd like to revisit the idea of solving the problems we've been discussing
+by changing the implementation of Ada.Tags.Tag to include a disambiguating
+component.
+
+I completely agree that we don't want to change the size or layout of
+existing tagged types.
+
+For types which are legal without  AI-344, this disambiguating component
+would always have some distinguished null value.
+
+Thus, the value would not have to be stored and the existing size/layout
+could be preserved.
+
+The statically allocated data structure that a Tag value currently
+references (typically a dispatch table and a few other odds and ends)
+could include an  "I have a shorter lifetime than my ultimate ancestor"
+flag.
+
+Pseudo-code for evaluation of R'Tag could be something like:
+     if R.Static_Tag.all.Is_An_Ai344_Type then
+        return Ada.Tags.Tag'(Static_Tag => R.Static_Tag, Disambiguator =>
+R.Disambiguator);
+    else
+        return Ada.Tags.Tag'(Static_Tag => R.Static_Tag, Disambiguator =>
+Nil_Value);
+    end if;
+
+The Disambiguator field might always reside at a fixed offset, or one of
+the "odds and ends" mentioned above might be the offset of this field.
+
+Types resulting from two elaborations of one tagged type declaration would
+be *required*  to  have distinct tags only if
+    1) The type declaration in question is a nested extension or a
+descendant thereof (i.e. it would be illegal without AI-344)
+and
+    2) The two types are descendants of the same elaboration of the
+declaration of their ultimate ancestor.
+and
+    3) The lifetimes of the two types (dynamically) overlap.
+
+If you call a procedure which declares an AI-344  type and it then calls
+itself, those two elaborations of the tagged type declaration must yield
+distinct tags.
+On the other hand, if you call the procedure, it returns, and then  you
+call it again, those two elaborations might (or might not) yield equal
+tags.
+This would allow using static links and the like as disambiguating values.
+
+The interaction between this and the last sentence of 3.9(4) would need to
+be worked out.
+
+This change would break code that makes use of Ada.Tags.Tag'Size for
+things like
+
+       type T is tagged record F1, F2 : Integer; end record;
+       pragma Assert (T'Size = 2* Integer'Size + Ada.Tags.Tag'Size);
+
+; would this be acceptable?
+
+I'm still not sure that changing Ada.Tags.Tag is a good idea, but I don't
+think it is as bad as we thought at first.
+
+If we did go with this approach, would the current wording of  4.6(42) and
+4.5.2(30) be ok? Is it already clear, for example,
+that two elaborations of one tagged type declaration do not cover each
+other and are not descendants of each other?
+The current wording of 3.9.2(16) would certainly be ok.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Monday, May 10, 2004  1:53 PM
+
+I suggested we leave Ada.Tags.Tag as is, and add a new
+type and attribute, Extended_Tag.  Can you comment on that
+alternative?  You include the mail I sent, but don't make
+any mention of it in your note.  I believe it could solve the same problem
+with less disruption.
+
+****************************************************************
+
+From: Stephen W. Baird
+Sent: Monday, May 10, 2004  3:35 PM
+
+I agree that the Extended_Tag approach would work.
+
+I think it would be better if we did not have to make the distinction
+between tags and extended tags user-visible.
+It hairs up the language specification, it introduces complexity for users
+(users now have to figure
+out which kind of tag they want in various contexts), and it just feels
+like a grafted-on solution which forces
+users to be more aware of the implementation than is necessary.
+
+Why do users want/need to be aware of this distinction?
+
+I think that if the language were being designed from scratch, it is very
+unlikely that we would end up with two kinds of tags (do you agree?).
+The language is not being designed from scratch and if compatibility
+considerations dictate a language design which looks like it was developed
+in two stages, then so be it.
+If, however, we have a more seamless alternative, then we ought to at
+least consider it.
+
+If the costs associated with changing Ada.Tags.Tag still seem too high, I
+would support Extended_Tags.
+
+****************************************************************
+
+From: Robert A. Duff
+Sent: Monday, May 10, 2004  4:52 PM
+
+I tend to agree with Steve Baird, here.  That is, make Ada.Tags.Tag work
+as if AI-344 had been there all along.  Steve outlines an implementation
+approach that would not disturb existing tagged-type layout.  One would
+have to go to some trouble to find an incompatible case -- or am I
+missing something?
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Monday, May 10, 2004  5:26 PM
+
+> I suggested we leave Ada.Tags.Tag as is, and add a new
+> type and attribute, Extended_Tag.  Can you comment on that
+> alternative?  You include the mail I sent, but don't make
+> any mention of it in your note.  I believe it could solve the same problem
+> with less disruption.
+
+I agree with Steve that adding a second kind of tag is ugly. I'm surprised
+that you'd even suggest such a thing, given the usual emphesis that you put
+on avoiding grafted-on solutions.
+
+In any case, what ever is done here should be integrated with AI-279. It
+would be silly to expend a lot of effort on these cases here, and not use
+that effort to eliminate erroneousness from AI-279. (I think that is pretty
+much required if we're going to allow nested derived tagged types. Regular
+nested tagged types are so rare and useless that we don't need to care
+whether they stream properly; but derived types are much more likely to be
+streamed. Moreover, the type is much less likely to exist if they are
+streamed, so the erroneousness is much more likely to occur.)
+
+If we required dynamic tag allocation and a dynamic, stack-based lookup
+scheme for nested tagged types, AI-279 can be defined without any
+erroneousness -- if the type doesn't "exist", Internal_Tag raises Tag_Error.
+Period. But of course this has compatibility issues -- but only with nested
+tagged types. Are these defined and streamed often enough to be worth
+worrying about?
+
+Steve's approach (of having an offset of a static link/display component in
+the tag, set to null for library level types) seems clean enough.
+
+If changing Tag'Size is not acceptable, I'd recommend defining
+Ada.Tags.Tag_Type, and putting the existing routines of Ada.Tags in the
+obsolecent features section, with the use of them erroneous for a prefix/tag
+value that does not denote a library-level tagged type.
+
+[If we're going to do that sort of major surgury, could we please figure out
+a way to make constructors a-la T'Class'Input usable by users???]
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Monday, May 10, 2004  5:30 PM
+
+> I tend to agree with Steve Baird, here.  That is, make Ada.Tags.Tag work
+> as if AI-344 had been there all along.  Steve outlines an implementation
+> approach that would not disturb existing tagged-type layout.  One would
+> have to go to some trouble to find an incompatible case -- or am I
+> missing something?
+
+Objects of nested tagged types would stream differently. (One could avoid
+that by making streaming of currently legal nested tagged types erroneous,
+but that seems silly -- and also grafted-on.)
+
+I also don't understand the model of "=" for tags here; it's not something
+that would compose properly -- so it could cost a lot of work in many
+compilers.
+
+I'm not sure whether 'Size for a tag would have to change or not. The offset
+scheme would seem to avoid that, but would put a lot of pain into "=".
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Monday, May 10, 2004  5:37 PM
+
+> I think it would be better if we did not have to make the distinction
+> between tags and extended tags user-visible.
+
+Ok.  I understand this point of view.  My problem with your earlier
+response was that I couldn't tell whether you had understood the
+extended-tag idea.  The key issue is whether there is any value
+in maintaining the notion of a "static" tag in addition to the
+more "dynamic" extended tag.  Clearly when it comes to I/O, it is
+going to be challenging to figure out how to represent the
+extended tag persistently.  Also, we have the notion of Expanded_Name,
+which based on the current wording, clearly doesn't distinguish
+particular levels.  Finally, the likelihood that there are multiple
+elaborations of the *same* tagged type declaration in existence due to
+recursion is quite small.  I hate to make all tag manipulations
+have to pay an overhead for this.
+
+I have been trying to come up with a solution that imposes no
+distributed (time) overhead on programs that make no use of
+nested extensions.  Perhaps it is not worth trying to preserve
+the space or time performance of 'Tag, given how rarely it is used.
+
+I think it would be nice at least to preserve the time performance
+of the tag check on binary dispatching operations, and hence would
+encourage implementors *not* to call an extended 'Tag attribute
+to perform the check.  Doing a check on the "static" tag part
+at the call-site, and then only comparing the "dynamic" part
+if you reach a nested extension still seems like a good idea.
+
+
+> It hairs up the language specification, it introduces complexity for users
+> (users now have to figure
+> out which kind of tag they want in various contexts), and it just feels
+> like a grafted-on solution which forces
+> users to be more aware of the implementation than is necessary.
+>
+> Why do users want/need to be aware of this distinction?
+
+Good question.  I suppose in the presence of streaming of
+class-wide types, they may need to face the issue of distinguishing
+the "static" part versus the "dynamic" part of the tag.
+
+I discussed limiting T'Class'Input and T'Class'Output to types that
+are at the same accessibility level as T.  Any comment on that?
+I think it will simplify the implementation significantly, and eliminate
+various possible erroneous situations.  And it may be related
+to this issue, one way or another ... ;-)
+
+****************************************************************
+
+From: Robert I. Eachus
+Sent: Monday, May 10, 2004  4:34 PM
+
+> If we introduce the notion of an "extended tag" then we
+> can probably change these all to say "an (extended) tag that
+> identifies a type...", or in the case of 3.9.2(16) which
+> prompted this, "... they all have the same (extended) tag."
+
+I'm not sure that I am following the whole discussion correctly.  If, as
+I understand it the problem is two dynamic instances of the same unit
+constaining a tagged type declaration are the issue, then we are trying
+to deal with a issue of broken implementations, not a language issue.
+
+My model has always been that elaboration of a tagged type declaration
+results in assignment of a _unique_ tag.  The easiest way to do this is
+to have a protected counter.  Another method is to have the tag be a
+pointer to the dispatch table for the type.  This works fine, since tag
+values can be reused after the scope containing the declaration has been
+left, at the same point as the memory would be reclaimed.  However, all
+that is implementation issues, as is how multiple tasks or partitions
+assign unique tags.  (I have always assumed that the identity of the
+partition elaborating the type declaration is part of the tag, if
+partitions don't have unique memory addresses.)
+
+If an implementation wants to use static values associated with the
+source code for most tags, that is an implementation detail--as long as
+they deal with the recursive case correctly.  The method of dealing with
+the recursive case in such a misguided implementation is not our
+responsibility.
+
+****************************************************************
+
+From: Robert Dewar
+Sent: Monday, May 10, 2004  8:19 PM
+
+> I completely agree that we don't want to change the size or layout of
+> existing tagged types.
+
+I also don't want to change the size of tags, this is just asking for
+nasty incompatibilities. I think absolute upwards compatibility for
+correct programs is essential. I don't mind exceptions being removed
+in favor of sensible behavior, or illegal code being made legal in
+some sensible way, but existing legal code that executes successfully
+should not have to be molested to be compatible with the new standard.
+No language bell/whistle is worth that.
+
+So for example, I think it is fine to remove abstract operations
+to that previously ambiguous expressions are now legal. But if a
+program that is legal and executes correctly must be modified to
+run under the new Ada even if no new feature is used, that to me
+is unacceptable (it likelyh would mean that we would be reluctant
+to implement the feature).
+
+So I think you definitely need two tag types here.
+
+****************************************************************
+
+From: Robert Dewar
+Sent: Monday, May 10, 2004  8:20 PM
+
+> I suggested we leave Ada.Tags.Tag as is, and add a new
+> type and attribute, Extended_Tag.  Can you comment on that
+> alternative?  You include the mail I sent, but don't make
+> any mention of it in your note.  I believe it could solve the same problem
+> with less disruption.
+
+Yes, I like this approach.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Friday, May 14, 2004  11:17 PM
+
+Tucker wrote on Monday:
+
+> I have been trying to come up with a solution that imposes no
+> distributed (time) overhead on programs that make no use of
+> nested extensions.  Perhaps it is not worth trying to preserve
+> the space or time performance of 'Tag, given how rarely it is used.
+>
+> I think it would be nice at least to preserve the time performance
+> of the tag check on binary dispatching operations, and hence would
+> encourage implementors *not* to call an extended 'Tag attribute
+> to perform the check.  Doing a check on the "static" tag part
+> at the call-site, and then only comparing the "dynamic" part
+> if you reach a nested extension still seems like a good idea.
+
+Re-reading this mail as I've been filing it, I realized what I was imagining
+as Steve's solution isn't quite the same. And since it meets almost all of
+the requirements that people have set out, I thought I better describe it
+more carefully.
+
+In particular, the solution I'm proposing (A) does not change the size of a
+tag; (B) allows tags to be statically allocated; (C) does not change the
+layout of library-level tagged types; and (D) has minimal overhead for
+library-level tagged types. (I refuse to consider non-derived nested tagged
+types separately. They are vanishingly rare - why complicate things? But
+they could be treated separately if you wanted to.)
+
+I'm going to describe an implementation approach; I haven't tried to figure
+out precisely what this means in RM terms (my hope is that it means
+absolutely nothing, in that no RM wording needs to change).
+
+The basic idea is that every tag includes a slot which contains the offset
+of the dynamic link/display component of a tagged object. For library-level
+types, this component offset would be zero (or some other value that cannot
+be a legal component offset - zero usually works because the tag itself
+lives there).
+
+The only thing that needs to change in that case is "=" for tag checks. It
+would be implemented like:
+
+    function Check (A, B : <any tagged object>) return Boolean is
+    begin
+        if A(Tag_Offset) /= B(Tag_Offset) then -- Compare the tag values.
+            return False;
+        elsif A(Tag_Offset)(Link_Component) = 0 then
+            return True;
+        else
+            return A(A(Tag_Offset)(Link_Component)) =
+                   B(B(Tag_Offset)(Link_Component));
+               -- Comparing the static links or display.
+        end if;
+    end Check;
+
+We'd define External_Tag would need some indication of the nesting depth
+(the number of such tags on the current call stack; this would be omitted
+for the first one, which would cover virtually all real cases); Internal_Tag
+would need to be able to look in the call stack for the correct item.
+Tucker's alternative of banning T'Class'Output for types deeper than their
+root would help, but you have the problem of recursive types for *any*
+nested tagged types.
+
+That is:
+
+    A_Stream : ....;
+
+    procedure Beauty (N : Natural := 3) is
+	  type Nested is tagged record -- Legal in Ada 95.
+                F1 : Integer_Vector (1 .. N) := (others => 0);
+                F2 : Float_Vector (N .. 10) := (others => 0.0);
+	    end record;
+        Local : Nested;
+    begin
+        if N = 1 then
+            T'Class'Output (A_Stream, Local)
+            Beauty (2);
+        elsif N = 2 then
+            Reset (A_Stream);
+            Local := T'Class'Input (A_Stream);
+               -- Ouch. Different bounds for components, same external name!
+        end if;
+    end Beauty;
+
+    Beauty (1);
+
+****************************************************************
+
+From: Robert Dewar
+Sent: Saturday, May 15, 2004  4:11 AM
+
+>I have been trying to come up with a solution that imposes no
+>distributed (time) overhead on programs that make no use of
+>nested extensions.  Perhaps it is not worth trying to preserve
+>the space or time performance of 'Tag, given how rarely it is used.
+
+I agree that 'Tag is rarely used and that a minor hit in performance
+is probably OK here.
+
+>I think it would be nice at least to preserve the time performance
+>of the tag check on binary dispatching operations
+
+This seems to me to be in price-of-admission category. If this
+cannot be achieved, the whole feature should be junked.
+
+****************************************************************
+

Questions? Ask the ACAA Technical Agent