CVS difference for 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