CVS difference for ais/ai-00344.txt

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

--- ais/ai-00344.txt	2004/05/29 00:38:39	1.4
+++ ais/ai-00344.txt	2004/06/08 02:03:47	1.5
@@ -1,4 +1,4 @@
-!standard  3.09.01    (03)                             04-02-29  AI95-00344/01
+!standard  3.09.01    (03)                             04-06-05  AI95-00344/02
 !class amendment 03-08-07
 !status work item 04-02-29
 !status received 03-04-21
@@ -9,7 +9,7 @@
 !summary
 
 Type extensions are allowed in scopes more nested than their
-parent type. Checks are performed on function return and
+parent type. Checks are performed on function return, on streaming, and
 on allocators to ensure that objects of such a type extension
 do not "escape" to a less nested environment.
 
@@ -25,35 +25,176 @@
 !proposal
 
 Repeal the accessibility check in 3.9.1(3). Replace it by something that still
-allows generic sharing (probably prohibiting extension in generic bodies).
+allows generic sharing (by prohibiting extension in generic bodies of
+descendants of formal types).
 
-Add accessibility checks on class-wide allocators and return statements.
+Add accessibility checks on class-wide allocators, return statements, and
+T'Class'Input/Output.
 
+Require that the type "Tag" include sufficient information to distinguish
+all descendants of a given ancestor type.
+
 !wording
 
+Modify 3.9(4) as follows:
+
+    ... For a tagged type that is local to a generic package body {all of
+    whose ancestors are also local to the same generic body}, the
+    language does not specify whether repeated instantiations of the generic
+    body result in distinct tags. However, to ensure that all descendants
+    of a given type have distinct tgs, if any ancestor is declared outside the
+    generic body, the tag identifies the particular instance of the body.
+    Similarly, for a type declared at an accessibility level deeper than one
+    of its ancestor types (if any), the tag identifies the particular execution
+    of the enclosing master that elaborated the tagged type declaration.
+
+  AARM NOTE: In most cases, a tag need only identify a particular tagged
+    type declaration, and can therefore be a simple link-time-known
+    address. However, for tag checks (see 3.9.2(16)) it is essential
+    that each descendant of a given type have a unique tag. Hence, for
+    types declared in shared generic bodies where an ancestor comes from
+    outside the generic, or for types declared at a deeper level than an
+    ancestor, the tag needs to be augmented with some kind of "static
+    link," "global display," or "instance descriptor" pointer. This
+    implies that type Tag may need to be two words, the second of which
+    is normally null, but in these identified special cases needs to
+    include a static link or equivalent. Within an object of one of
+    these types with a two-word tag, the two parts of the tag would
+    typically be separated, one part as the first word of the object,
+    the second placed in the first extension part that corresponds to a
+    type declared more nested than its parent or declared in a shared
+    generic body when the parent is declared outside.
+
+Add after 3.9(7):
+
+    function Descendant_Tag(External : String; Ancestor : Tag) return Tag;
+
+    function Is_Descendant_At_Same_Level(Descendant, Ancestor : Tag) return Boolean;
+
+Modify 3.9(12):
+
+    The function Internal_Tag returns [the] {a} tag that corresponds ...
+
+Add after 3.9(12):
+
+    The function Descendant_Tag returns the (internal) tag for the type
+    that corresponds to the given external tag and is both a descendant of the
+    type identified by the Ancestor tag and has the same accessibility level as
+    the identified ancestor. Tag_Error is raised if External is not the
+    external tag for such a type.
+
+    The function Is_Descendant_At_Same_Level returns True if Descendant tag
+    identifies a type that is both a descendant of the type identified
+    by Ancestor and at the same accessibility level. If not, it returns False.
+
+  AARM NOTE: Descendant_Tag is used by T'Class'Input to identify the type
+    identified by an external tag. Because there can be multiple elaborations
+    of a given type declaration, Internal_Tag does not have enough information
+    to choose a unique such type. Descendant_Tag does not return the tag
+    for types declared at deeper accessibility levels than the ancestor
+    because again, there could be ambiguity in the presence of recursion or
+    multiple tasks. Is_Descendant_At_Same_Level is used by T'Class'Output to
+    determine whether the item being written is at the same accessibility level
+    as T. It may be used to determine prior to using T'Class'Output whether
+    Tag_Error will be raised.
+
 Delete the last two sentences of 3.9.1(3).
 
+Replace 3.9.1(4) with:
+
+    Within the body of a generic unit, or the body of any of its descendant
+    library units, a tagged type shall not be declared as a descendant
+    of a formal type of the generic unit.
+
 Add after 4.8(5):
 
-    If the designated type of the type of the allocator is tagged, the
-    accessibility level of the designated type shall not be statically deeper
-    than that of the type of the allocator.
+    If the designated type of the type of the allocator is class-wide, the
+    accessibility level of the type determined by the subtype_indication
+    or qualified_expression shall not be statically deeper than that of the type
+    of the allocator.
+
+Add at the end of 4.8(7):
+
+    ... If the designated type of the type of the allocator is class-wide, then
+    a check is made that the accessibility level of the type identified by
+    the tag of the value of the qualified_expression is not deeper than that of
+    the type of the allocator. Constraint_Error is raised if this check fails.
 
 Add after 6.5(20):
 
     If the result type is class-wide, a check is made that the accessibility
     level of the type identified by the tag of the result is not deeper than
-    that of the master that elaborated the function body.  If this check fails,
+    that of the master that elaborated the function body. If this check fails,
     Program_Error is raised.
 
+Add to end of 13.13.2(31):
+
+    ... Tag_Error is raised if the tag of Item identifies a type declared at an
+    accessibility level deeper than that of S.
+
+Modify 13.13.2(34):
+
+    First reads the external tag from Stream and determines the corresponding
+    internal tag (by calling [Tags.Internal_Tag(String'Input(Stream))]
+    {Tags.Descendant_Tag(String'Input(Stream), S'Tag) which might raise
+    Tag_Error} -- see 3.9) ...
+
 !example
 
 !discussion
 
-[Editor's note: 3.9.1(4) is retained (which prevents extension in generic
-bodies), because the contract model issues discussed in the AARM remain.
-You can get similar issues from parameters which depend on formal types.
-See the e-mail below.]
+With the proposal to add a number of generic packages to provide
+standard container abstractions, there has been growing concern about the rule
+precluding extending a type at a deeper accessibliity level. Because
+user-defined controlled types, user-defined storage pools, and
+user-defined streams are all implemented using type extension, this rule
+can interfere with natural use of generic data structures in nested
+scopes.
+
+It turns out that nested type extensions can be supported safely by
+shifting the accessibility checks to certain operations, rather than
+being enforced at the type declaration. In particular, by performing
+accessibility checks on class-wide allocators, class-wide function
+return, and class-wide stream I/O, the danger of objects outliving their
+type declaration can be eliminated.
+
+For allocators, we disallow creating an object in a collection whose
+access type outlives the type identified by the object's tag.
+Similarly, for function return, we disallow returning a classwide object
+from a function if tag identifies a type declared at a deeper level than
+the function. For similar reasons, we preclude T'Class'Input returning
+an object whose tag identifies a type that is declared at a deeper level
+than T. For symmetry, and to prevent writing something which cannot
+later be meaningfully read, we preclude T'Class'Output writing out an
+item whose tag identifies a type of a deeper level than T.
+
+To implement tag checks needed to ensure that all dynamically tagged
+controlling operands come from the same tagged type, we place additional
+requirements on the uniqueness of run-time tags. We considered defining
+a separate type called "extended tag."  However, this would add user
+complexity, and would make existing user tests for tag equality using
+the preexisting tag type no longer sufficient to ensure that the
+tag check would succeed.
+
+To implement the accessibility checks required for T'Class'Input and
+T'Class'Output, we provide two additional functions in Ada.Tags,
+Descendant_Tag and Is_Descendant_At_Same_Level. Although it is not
+strictly necessary to standardize these functions, it is useful for
+the programmer to be able to use these functions to implement their
+own checks, prior to, or as an alternative to, the predefined streaming
+attributes.
+
+We considered requiring that an external tag be sufficient to uniquely
+identify an internal tag. However, given that we only allow T'Class'Input
+and T'Class'Output for types at the same accessibility level as T, the
+only (implicit) requirement is that it be unique for descendants of
+a given type at the same accessibility level as the ancestor. Hence,
+there is no need to distinguish between different elaborations of
+a type declared in a recursive routine. However, we do (implicitly) require
+that for a type declared in a shared generic body whose parent is from
+outside the generic, the external tag should be sufficient to identify
+the particular instance, for instances at the same accessibility level
+as the parent type.
 
 IMPLEMENTATION ISSUES
 
@@ -70,9 +211,33 @@
 When defining the record layout for a nested type extension, an
 additional implicit component is allocated to contain the static link,
 or a pointer to a saved global display, or in the case of a shared
-generic, a pointer to an instantiation descriptor in which the
-static link or global display can be found.
+generic, a pointer to an instance descriptor in which the static link or
+global display can be found.
 
+The type Ada.Tags.Tag would be two words, made up of the pointer to the
+dispatch table, as now, plus a second word that would be null for
+the "normal" case, but would hold the static link, global display, or
+instance descriptor for nested type extensions.
+
+To avoid distributed overhead, we would suggest that the tag check
+required when there are multiple controlling operands only check the
+"first word" of the now two-word tag at the call site. Then an
+additional check on the second word needs to be performed *after* the
+dispatch only 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.
 
 !corrigendum 03.09.01(03)
 
@@ -2095,6 +2260,500 @@
 
 This seems to me to be in price-of-admission category. If this
 cannot be achieved, the whole feature should be junked.
+
+****************************************************************
+
+From: Stephen W. Baird
+Sent: Thursday, June 3, 2004 12:46 PM
+
+Tuck said:
+> 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 have not been able to come up with a better alternative.
+
+If we wanted to, I believe we could allow streaming of types whose
+accessibility level lies in the range between that of T and that of the call
+site. This could be done by storing an accessibility level (or something very
+much like it) in the statically allocated data structure associated with a
+tagged type declaration. The caller would then be able to produce a "full" tag.
+Having the dynamic semantics of a streaming operation depend on the location of
+the caller seems like a very bad idea. I only mention this approach in hopes
+that someone else might find a way to fix it.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, June 3, 2004  6:07 PM
+
+The trouble with this solution is that T'Class'Input is defined in terms of
+Ada.Tags.Internal_Tag. But Ada.Tags.Internal_Tag does not have any access to
+the type T, so it cannot enforce any restrictions.
+
+That means that T'Class'Input also cannot enforce any restrictions - it doesn't
+have any way to get the information it would need to do so. That seems to
+suggest that both T'Class'Input and Ada.Tags.Internal_Tag would have to be
+erroneous in this case. And that is simply not acceptable, given that the
+program does not have any real control over what it streams in. It must be
+possible to write streaming operations which detect all bad data -- without
+erroneous execution. And it is not acceptable to say that class-wide streaming
+cannot be used in such cases, as the language gives us no other "factory"
+operations that can create an object from a tag (or surregate).
+
+****************************************************************
+
+From: Steven W. Baird
+Sent: Friday, June 4, 2004  12:40 PM
+
+T'Class'Input could be defined to perform the check that you want.
+
+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 accessibility level (or something analogous - perhaps
+just a count of many AI344-ish derivations occur on the path from the root
+type to the given type).
+
+Implementing the check would then be straightforward.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Sunday, June 6, 2004  11:49 AM
+
+Here is an update to AI-344 on nested type extensions.
+It attempts to address the issues relating to T'Class'Input
+and T'Class'Output and the representation of the type Tag.
+I concluded that type Tag will probably become two words
+in most implementations (though a level of indirection
+could probably be used to keep it to one word if desired).
+
+I decided that the primary language requirement is that
+the type Tag must be sufficient to distinguish between
+all descendants of a given ancestor type.  If two types
+have no common ancestor, then they could have the
+same tag.  Hence, for existing situations where a type
+is declared in a recursive or reentrant routine, it is
+OK if all elaborations of the type declaration have
+the same tag.  However, if such a type is an extension
+of some type declared at a shallower nesting level, then
+all elaborations must be distinguished, because objects
+of two distinct elaborations might be passed to a single
+dispatching operation, and the tag check must be able
+to notice the mismatch.
+
+A related issue has to do with how unique are the external
+tags.  My conclusion is that they only need to distinguish
+between descendants that are at the same level as their
+shared ancestor, presuming we limit T'Class'Input to reading
+objects at the same level as T.  This limitation is actually
+consistent with our rule that a function may not return
+a class-wide object with a tag identifying a type from a
+deeper level than the function.  Hence, there is no need
+for an external tag to include some indication of the
+particular elaboration of a type declaration.  However,
+some kind of instance identifier may be needed in the
+presence of shared generic bodies (see the !discussion).
+
+Randy indicated a concern about different elaborations
+of a type having different component constraints.  However,
+I don't see that as any worse as different executions
+of a program having different component constraints.
+You can always get an exception if T'Class'Input is given
+bad data, whether it was produced by T'Class'Output
+or by some random bit generator.  The important thing is
+that we don't dispatch off to some out-of-scope type's
+'Read routine.
+
+Comments welcome, now or at the meeting.
+
+****************************************************************
+
+From: Robert A. Duff
+Sent: Sunday, June 6, 2004  1:53 PM
+
+> Here is an update to AI-344 on nested type extensions.
+
+I like this proposal.
+
+> Modify 3.9(4) as follows:
+>
+>     ... For a tagged type that is local to a generic package body {all of
+>     whose ancestors are also local to the same generic body}, the
+>     language does not specify whether repeated instantiations of the generic
+>     body result in distinct tags.  However, to ensure that all descendants
+>     of a given type have distinct tgs, if any ancestor is declared outside the
+
+"tgs" --> "tags"
+
+>     generic body, the tag identifies the particular instance of the body.
+>     Similarly, for a type declared at an accessibility level deeper than one
+>     of its ancestor types (if any), the tag identifies the particular execution
+>     of the enclosing master that elaborated the tagged type declaration.
+
+The above seems rather chatty, and rather implementation oriented.  Why
+not just say what you want, namely, that each type in a hierarchy rooted
+at a given ultimate ancestor has a unique tag?  The stuff about generics
+and accessibility levels can be moved into the AARM.
+
+In other words, the model implied by the first sentence of para (4) is
+(now) wrong -- we're not identifying type_decls, we're identifying types
+within a hierarchy.
+
+I think para (4.b) needs rewording as well.
+
+>   AARM NOTE: In most cases, a tag need only identify a particular tagged
+>     type declaration, and can therefore be a simple link-time-known
+>     address. However, for tag checks (see 3.9.2(16)) it is essential
+>     that each descendant of a given type have a unique tag.
+
+There!  That last sentence seems more like what the RM should say,
+rather than hiding this simple idea in the AARM.
+
+>...  Hence, for
+>     types declared in shared generic bodies where an ancestor comes from
+>     outside the generic, or for types declared at a deeper level than an
+>     ancestor, the tag needs to be augmented with some kind of "static
+>     link," "global display," or "instance descriptor" pointer. This
+>     implies that type Tag may need to be two words, the second of which
+>     is normally null, but in these identified special cases needs to
+>     include a static link or equivalent.  Within an object of one of
+>     these types with a two-word tag, the two parts of the tag would
+>     typically be separated, one part as the first word of the object,
+>     the second placed in the first extension part that corresponds to a
+>     type declared more nested than its parent or declared in a shared
+>     generic body when the parent is declared outside.
+
+>     The function Descendant_Tag returns the (internal) tag for the type
+>     that corresponds to the given external tag and is both a descendant of the
+>     type identified by the Ancestor tag and has the same accessibility level as
+>     the identified ancestor.  Tag_Error is raised if External is not the
+>     external tag for such a type.
+>
+>     The function Is_Descendant_At_Same_Level returns True if Descendant tag
+>     identifies a type that is both a descendant of the type identified
+>     by Ancestor and at the same accessibility level.  If not, it returns False.
+
+Is the above really what you mean?  Is it implementable?  It seems like
+if the two tags passed to Is_Descendant_At_Same_Level are from different
+type hierarchies (or at least, different type hierarchies in generic
+bodies and the like), then the implementation can't tell whether to
+return True or False.  The same question applies to the Tag_Error on
+Descendant_Tag.
+
+> !discussion
+>
+> With the proposal to add a number of generic packages to provide
+> standard container abstractions, there has been growing concern about the rule
+> precluding extending a type at a deeper accessibliity level.  Because
+
+"accessibliity" --> "accessibility"
+
+> user-defined controlled types, user-defined storage pools, and
+> user-defined streams are all implemented using type extension, this rule
+> can interfere with natural use of generic data structures in nested
+> scopes.
+>
+> It turns out that nested type extensions can be supported safely by
+> shifting the accessibility checks to certain operations, rather than
+> being enforced at the type declaration.  In particular, by performing
+> accessibility checks on class-wide allocators, class-wide function
+> return, and class-wide stream I/O, the danger of objects outliving their
+> type declaration can be eliminated.
+>
+> For allocators, we disallow creating an object in a collection whose
+> access type outlives the type identified by the object's tag.
+> Similarly, for function return, we disallow returning a classwide object
+> from a function if tag identifies a type declared at a deeper level than
+
+"if tag" --> "if the tag"
+
+> the function. For similar reasons, we preclude T'Class'Input returning
+> an object whose tag identifies a type that is declared at a deeper level
+> than T. For symmetry, and to prevent writing something which cannot
+
+"which" --> "that"
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Sunday, June 6, 2004  2:41 PM
+
+> I like this proposal.
+
+Glad to hear it.
+
+>>Modify 3.9(4) as follows:
+...
+> The above seems rather chatty, and rather implementation oriented.  Why
+> not just say what you want, namely, that each type in a hierarchy rooted
+> at a given ultimate ancestor has a unique tag?  The stuff about generics
+> and accessibility levels can be moved into the AARM.
+
+I agree this should be rewritten.  I tried to make incremental
+fixes to the existing wording, but I think a fresh start would
+be better.
+
+> In other words, the model implied by the first sentence of para (4) is
+> (now) wrong -- we're not identifying type_decls, we're identifying types
+> within a hierarchy.
+>
+> I think para (4.b) needs rewording as well.
+
+I wrote this without having the AARM in front of me, so
+I can easily believe you are right.
+
+>>  AARM NOTE: In most cases, a tag need only identify a particular tagged
+>>    type declaration, and can therefore be a simple link-time-known
+>>    address. However, for tag checks (see 3.9.2(16)) it is essential
+>>    that each descendant of a given type have a unique tag.
+>
+> There!  That last sentence seems more like what the RM should say,
+> rather than hiding this simple idea in the AARM.
+
+I would welcome some suggested rewording of para (4) from
+any volunteer!
+
+> ...
+>>    The function Descendant_Tag returns the (internal) tag for the type
+>>    that corresponds to the given external tag and is both a descendant of the
+>>    type identified by the Ancestor tag and has the same accessibility level as
+>>    the identified ancestor.  Tag_Error is raised if External is not the
+>>    external tag for such a type.
+>>
+>>    The function Is_Descendant_At_Same_Level returns True if Descendant tag
+>>    identifies a type that is both a descendant of the type identified
+>>    by Ancestor and at the same accessibility level.  If not, it returns False.
+>
+> Is the above really what you mean?  Is it implementable?  It seems like
+> if the two tags passed to Is_Descendant_At_Same_Level are from different
+> type hierarchies (or at least, different type hierarchies in generic
+> bodies and the like), then the implementation can't tell whether to
+> return True or False.
+
+I suppose it could be changed to require a True if the tags identify *some*
+pair of types that have the desired relationship.  It would only return
+False if the tags cannot be construed to identify such a pair.  In particular,
+if Descendant = Ancestor, then I would expect it to return True, even
+if the tag identifies a type declaration from a nested scope or a generic
+body.
+
+> ...The same question applies to the Tag_Error on Descendant_Tag.
+
+Again, it would raise Tag_Error only if there is no type with the
+given external tag and an ancestor with the given tag.
+
+I see Is_Descendant_At_Same_Level as being very easy to implement,
+presuming every tagged type descriptor has an array of ancestor tags
+(which is the canonical data structure used to implement class-wide
+membership) plus an indication of its static nesting level.
+Descendant_Tag probably implies that the tag table used to
+implement Internal_Tag needs to be updated both on elaboration and
+finalization of a tagged type.
+
+****************************************************************
+
+From: Robert A. Duff
+Sent: Sunday, June 6, 2004  8:12 PM
+
+> I would welcome some suggested rewording of para (4) from
+> any volunteer!
+
+Well, I suppose I should volunteer.  But please answer these questions
+first:
+
+The first sentence of 3.9(4) says, "The tag of a specific tagged type
+identifies the full_type_declaration of the type."  Ignoring the
+generic-related issues for the moment, it says a tag identifies a
+full_type_decl.  Not a *type*.  3.9(4.b) then says, "The language does
+not specify whether repeated elaborations of the same
+full_type_declaration correspond to distinct tags."
+
+First, I don't see how the AARM note follows from the RM text.  The RM
+seems to be saying that if a full_type_decl is elaborated twice, you get
+*one* tag.  It doesn't say you *might* get either one or two, which is
+what the AARM says.  What was the actual intent?
+
+It would seem cleaner to say a tag identifies a *type*.
+Para (4.b) goes on to explain why we didn't do that:
+for ease of (efficient) implementation, we wanted to allow
+statically-allocated type descriptors, and the tag is then naturally
+the address of that descriptor.
+
+The AI breaks that property, and explains how we need two words in some
+cases.  In particular, for nested type extensions and type extensions in
+shared generic bodies, we need to attach some extra information.
+My question is: why not attach the extra information for *all* nested
+types (even root ones), and *all* types declared in shared generics?
+If we do that, it seems like the model (and therefore the wording)
+is very simple: tags can "identify" types -- tags and types are
+one-for-one.
+
+The implementation burden seems identical to what the AI is already
+trying to propose -- namely, that in some nested cases and
+generic-sharing cases, the implementation has to conjure up an extra
+piece of info.
+
+Still no distributed overhead, in the sense that if you don't nest (and
+don't use shared generics), you don't pay anything.  The vast majority
+of tagged types are not nested.
+
+****************************************************************
+
+From: Robert I. Eachus
+Sent: Sunday, June 6, 2004  8:27 PM
+
+Robert A Duff wrote:
+
+>>  AARM NOTE: In most cases, a tag need only identify a particular tagged
+>>    type declaration, and can therefore be a simple link-time-known
+>>    address. However, for tag checks (see 3.9.2(16)) it is essential
+>>    that each descendant of a given type have a unique tag.
+>
+>There!  That last sentence seems more like what the RM should say,
+>rather than hiding this simple idea in the AARM.
+>
+Now I understand where Tucker is coming from in his vison of a proper
+implementation.  I like the fact that this version of the proposal does
+not require two part Tags, because the implementation I envision does not.
+
+I think that the only way this issue can come up is if you have two
+nested types which are derived from different instances of the same
+derived type declaration.  If in that case, which is not now legal, the
+dispatch table normally pointed to by the tag is created either on some
+heap visible at the point of the parent type declaration, or in a stack
+or stacks similarly visible, then the different instances will have
+different tags.  Yes, some tags will be in code space and others on the
+heap or stack.  As such this is not a problem.  (Even if the stack is
+marked as non-executable, it should be okay to have pointers into code
+segments stored there.)
+
+The two word vs. one word Tag is an issue, but it will occur anyway in
+64-bit environments, as a side-effect of the addressing model.  For
+example, in the AMD64 (Intel EM64T) ISA, you can have DLLs that use
+32-bit addressing which are called from a 64-bit addressing
+environment.  Obviously an Ada compiler that supports such calls must
+use a mechanism that insures that two Tags created in the 32-bit
+environment as a child of a 64-bit type are not identical, even if
+created inside two different 32-bit address maps.  The solution of
+course is to make the Tag for a 32-bit DLL 64-bits, and you can use
+Tucker's approach of a two-part Tag, or allocate the dispatch tables in
+global memory mapped into all 32-bit address spaces.  This could be, but
+need not be, a special heap visible to all threads (tasks) and
+libraries.  It could even be the case that all libraries map the
+addesses to the same 32-bit address, whether they use 32-bit or 64-bit
+addressing.  (This will work until you have a program that requires more
+than 4 Gigabytes for the globally-visible code segments and these
+dispatch tables.)
+
+Incidently, in the implementation I envision, it is possible that two
+types derived from the same parent will have the same tag values, if the
+second type is created after the scope of the first has been left.
+Absent calls to Unchecked_Conversion, this is fine.  Since the two types
+will not co-exist in time, all objects of the first type must no longer
+be live when the second type is created.  In other words, if the tags
+are the same, the types have to be non-overlapping in time, so there is
+no way to test tags of the two different derived types for equality.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Monday, June 7, 2004  11:13 AM
+
+> First, I don't see how the AARM note follows from the RM text.  The RM
+> seems to be saying that if a full_type_decl is elaborated twice, you get
+> *one* tag.  It doesn't say you *might* get either one or two, which is
+> what the AARM says.  What was the actual intent?
+
+We wanted to allow either approach, where you allocate tags statically,
+or on each elaboration.
+
+> It would seem cleaner to say a tag identifies a *type*.
+> Para (4.b) goes on to explain why we didn't do that:
+> for ease of (efficient) implementation, we wanted to allow
+> statically-allocated type descriptors, and the tag is then naturally
+> the address of that descriptor.
+>
+> The AI breaks that property, and explains how we need two words in some
+> cases.  In particular, for nested type extensions and type extensions in
+> shared generic bodies, we need to attach some extra information.
+> My question is: why not attach the extra information for *all* nested
+> types (even root ones), and *all* types declared in shared generics?
+> If we do that, it seems like the model (and therefore the wording)
+> is very simple: tags can "identify" types -- tags and types are
+> one-for-one.
+>
+> The implementation burden seems identical to what the AI is already
+> trying to propose -- namely, that in some nested cases and
+> generic-sharing cases, the implementation has to conjure up an extra
+> piece of info.
+>
+> Still no distributed overhead, in the sense that if you don't nest (and
+> don't use shared generics), you don't pay anything.  The vast majority
+> of tagged types are not nested.
+
+One goal was to require *no* change in implementation approach for
+existing tagged types, and there are certainly existing nested tagged types,
+and there are probably existing shared generic implementations that
+share tags between bodies.  I agree they are rare, so it seems quite possible
+that some implementors may decide to use the same approach for all
+non-library-level types, but I don't think we should *require* that.
+
+So I would prefer wording that continued to allow either implementation approach,
+including for nested types or types declared in generic bodies, presuming
+their ancestors obey the Ada 95 restrictions.  My suggestion would be to
+say that the tag identifies the type declaration, and is also sufficient to
+distinguish all descendants of the same ancestor that exist concurrently.
+The rule allowing sharing in generic bodies would remain, though perhaps
+it would be relegated to an implementation permission section, to get it out
+of the main part of the text.
+
+An AARM note could explain some of the implementation implications
+of these rules.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Monday, June 7, 2004  8:55 PM
+
+> > The AI breaks that property, and explains how we need two words in some
+> > cases.  In particular, for nested type extensions and type extensions in
+> > shared generic bodies, we need to attach some extra information.
+> > My question is: why not attach the extra information for *all* nested
+> > types (even root ones), and *all* types declared in shared generics?
+> > If we do that, it seems like the model (and therefore the wording)
+> > is very simple: tags can "identify" types -- tags and types are
+> > one-for-one.
+
+Tagged types derived in the spec of a shared generic are really like formal
+types of the generic (otherwise, it wouldn't be possible to implement the
+overridding rules). So attaching the extra information to all tagged types
+in shared generics is equivalent to adding it to *all* types.
+
+The important property is that the representation of existing, non-nested,
+tagged types doesn't change. (We can't break streaming of common types.) But
+nested tagged types are rare, and streaming of them should be close to
+non-existent. Similarly, our experience has been that tag checks are rare in
+real O-O code -- so I wouldn't care much if they became slightly more
+expensive.
+
+Thus, I'd probably use the two-word tags everywhere for tag operations. The
+second part would be accessed via an offset component in the static part of
+the tag itself (set to 0 for library level items). The second part would be
+allocated in tagged objects only if they are nested (or could be, for
+generic body types).
+
+Tucker said:
+
+> One goal was to require *no* change in implementation approach for
+> existing tagged types, and there are certainly existing nested tagged types,
+> and there are probably existing shared generic implementations that
+> share tags between bodies.  I agree they are rare, so it seems quite possible
+> that some implementors may decide to use the same approach for all
+> non-library-level types, but I don't think we should *require* that.
+
+That's fair, but if it requires standing on one's head, and no one is going
+to use the permission anyway (we certainly won't), why bother cluttering up
+the standard with it??
 
 ****************************************************************
 

Questions? Ask the ACAA Technical Agent