Version 1.14 of ais/ai-00108.txt
!standard 13.13.02 (09) 00-07-31 AI95-00108/08
!standard 13.13.02 (27)
!standard 13.13.02 (36)
!class binding interpretation 96-04-04
!status Corrigendum 2000 99-06-02
!status WG9 approved 96-12-07
!status ARG approved 7-0-2 96-06-17
!status work item 96-04-13
!status received 96-04-04
!priority High
!difficulty Hard
!qualifier Error
!subject Inheritance of stream attributes for type extensions
!summary
For a type extension, the predefined Read attribute is defined to call
the Read of the parent type, followed by the Read of the non-inherited
components, if any, in canonical order. The analogous rule applies to
the Write attribute.
The Input and Output attributes are not inherited by a type extension.
Default stream attributes are never inherited; rather, the default
implementation for the derived type is used.
The stream attributes must work properly for every language-defined
nonlimited type. For language-defined private types, the output
generated by the Write attribute is not specified, but it must be
readable by the Read attribute.
!question
13.1(15) says:
A derived type inherits each type-related aspect of its parent type that
was directly specified before the declaration of the derived type, or (in the
case where the parent is derived) that was inherited by the parent type from
the grandparent type. A derived subtype inherits each subtype-specific
aspect of its parent subtype that was directly specified before the
declaration of the derived type, or (in the case where the parent is derived)
that was inherited by the parent subtype from the grandparent subtype, but
only if the parent subtype statically matches the first subtype of the parent
type. An inherited aspect of representation is overridden by a subsequent
representation item that specifies the same aspect of the type or subtype.
Do these rules apply to the stream-oriented attributes Read, Write,
Input, and Output? (No.)
If an untagged derived type includes a known discriminant part, the number of
discriminants can change. If we inherit the parent's attribute definition, we
could write the wrong number of discriminants. Consider:
type Parent (D1, D2 : Integer := 1) is ...;
type Child (D : Integer := 2) is new Parent (D1 => D, D2 => D);
Clearly the default implementation of Parent'Write writes two discriminant
values. How many discriminants does Child'Write write? (One.)
Are the stream-oriented attributes intended to work properly for
language-defined types such as Unbounded_String? (Yes.)
!recommendation
(See summary.)
!wording
(See corrigendum.)
!discussion
The general rule for inheritance of type-related representation aspects
should not apply to the stream attributes of type extensions. For 'Read
and 'Write, a rule analogous to the rule for tagged equality makes the
most sense. For 'Input and 'Output, no inheritance makes sense;
instead, they should regain their predefined meaning in terms of 'Read
and 'Write.
There are several problems associated with applying the normal 13.1(15)
inheritance rules to the stream attributes of tagged types:
1) Inheriting a 'Read or 'Write of the parent type as-is for
the 'Read or 'Write of a type extension will ignore any new
components added in the extension part. A rule analogous
to the one for the equality operator makes more sense.
In particular, the default 'Read or 'Write for a type extension
should be defined to do the 'Read or 'Write of the parent type
followed by the 'Read or 'Write for each component of the
type extension, in canonical order.
2) Inheriting a 'Input or 'Output of the parent type as-is for
'Input or 'Output of a type extension makes no sense, since
the inherited 'Input is a function returning the parent type,
and the inherited 'Output puts out the discriminants of the
parent type. For these two, the only meaningful approach seems
to be for the default 'Input and 'Output for a tagged type to
always be defined in terms of the 'Read and 'Write for the
tagged type, preceded with the discriminants, if any.
For untagged derived types, there is no (new) problem for the
derived type inheriting the stream attributes. Even for tagged derived
types, if the extension part is null, the 'Read and 'Write will
effectively be inherited.
We must take care, however, that all of the components have the appropriate
attributes. For a limited type extension, the extension component could be
of a type that does not have an implementation of Write or Read. In that
case, we must take care to insure that the attribute for the new type does
handle the extension component. We do this by requiring an attribute
to be directly specified if it has a limited extension component that does
not have an implementation of Write or Read and the parent type has a
(specified) implementation of Write or Read. (An alternative would be to
inherit the original operation unmodified, but this would silently ignore
the extension components. This could cause hard-to-find bugs as the components
would probably revert to default values when they are input.) This rule is
similar to the way that functions of type extensions are inherited: they
aren't inherited, they must be overridden (except that we only invoke it
when we can't do the right thing automatically, which minimizes the places
where existing code becomes illegal).
To see how this works in practice, consider the following example:
package P is
type T is limited tagged ...;
for T'Read use ...;
type Der is new T with null record; --
--
type Der_Int is new T with --
--
--
record
Int : Integer;
end record;
protected type Protect_Type is ... --
type Der_Protect_Type is new T with --
--
--
--
record
PT : Protect_Type;
end record;
end P;
Simply making the operation uncallable doesn't work, as the operations can be
dispatched. If, in the above example, Der_Protect_Type couldn't be called,
problems would arise if T'Class'Read was called on a Der_Protect_Type object.
Clearly, the properties of the default implementation for the stream
attributes can change for derived types (as in the example given in
the question). Thus, we always want to use a "fresh" default
implementation for an attribute, rather than inheriting a default
implementation from the parent type.
For language-defined nonlimited private types, the International Standard
does not say whether the stream-oriented attributes must work properly.
It seems that they ought to. For many such types, the default version will work
properly. However, for a type like Unbounded_String, which is almost
certainly implemented as a data structure involving access values, the
default versions will not work. Therefore, for these types, the
implementer must provide an explicit version of the Read and Write
attributes.
The wording takes advantage of the newly defined "operational attributes"
(see 8652/0009 [AI-00137]) to say whether operational attributes are
inherited depends on the attribute. This simplifies the wording by
eliminating the need to describe a long list of exceptions to an inheritance
rule that we want only in some cases, and provides future flexibility.
!corrigendum 13.1(15)
Replace the paragraph:
A derived type inherits each type-related aspect of its parent type that
was directly specified before the declaration of the derived type, or (in the
case where the parent is derived) that was inherited by the parent type from
the grandparent type. A derived subtype inherits each subtype-specific
aspect of its parent subtype that was directly specified before the
declaration of the derived type, or (in the case where the parent is derived)
that was inherited by the parent subtype from the grandparent subtype, but
only if the parent subtype statically matches the first subtype of the parent
type. An inherited aspect of representation is overridden by a subsequent
representation item that specifies the same aspect of the type or subtype.
by:
A derived type inherits each type-related aspect of representation of its
parent type that was directly specified before the declaration of the derived
type, or (in the case where the parent is derived) that was inherited by the
parent type from the grandparent type. A derived subtype inherits each
subtype-specific aspect of representation of its parent subtype that was
directly specified before the declaration of the derived type, or (in the case
where the parent is derived) that was inherited by the parent subtype from the
grandparent subtype, but only if the parent subtype statically matches the
first subtype of the parent type. An inherited aspect of representation is
overridden by a subsequent representation item that specifies the same aspect
of the type or subtype.
In contrast, whether operational aspects are inherited by a derived type
depends on each specific aspect. When operational aspects are inherited by a
derived type, aspects that were directly specified before the declaration of the
derived type, or (in the case where the parent is derived) that were inherited
by the parent type from the grandparent type are inherited. An inherited
operational aspect is overridden by a subsequent operational item that specifies
the same aspect of the type.
!corrigendum 13.1(18)
Insert after the paragraph:
- If an aspect of representation of an entity is not specified, it is
chosen by default in an unspecified manner.
the new paragraph:
If an operational aspect is specified for an entity (meaning that it is
either directly specified or inherited), then that aspect of the entity is as
specified. Otherwise, the aspect of the entity has the default value for
that aspect.
!corrigendum 13.3(75)
Replace the paragraph:
- S'External_Tag
- S'External_Tag denotes an external string
representation for S'Tag; it is of the predefined type String. External_Tag may be specified
for a specific tagged type via an attribute_definition_clause; the
expression of such a clause shall be static. The default external tag
representation is implementation defined. See 3.9.2 and 13.13.2.
by:
- S'External_Tag
- S'External_Tag denotes an external string
representation for S'Tag; it is of the predefined type String. External_Tag may be specified
for a specific tagged type via an attribute_definition_clause; the
expression of such a clause shall be static. The default external tag
representation is implementation defined. See 3.9.2 and 13.13.2. The value
of External_Tag is never inherited; the default value is always used unless
a new value is directly specified for a type.
!corrigendum 13.13.02(9)
Replace the paragraph:
For elementary types, the representation in terms of stream elements is
implementation defined. For composite types, the Write or Read attribute for
each component is called in a canonical order. The canonical order of
components is last dimension varying fastest for an array, and positional
aggregate order for a record. Bounds are not included in the stream if T is
an array type. If T is a discriminated type, discriminants are included only
if they have defaults. If T is a tagged type, the tag is not included.
by:
For untagged derived types, the Write and Read attributes of the parent type
are inherited as specified in 13.1; otherwise, the default implementations of
these attributes are used.
The default implementations of Write and Read attributes execute as follows:
For elementary types, the representation in terms of stream elements is
implementation defined. For composite types, the Write or Read attribute for
each component is called in canonical order, which is
last dimension varying fastest for an array, and positional
aggregate order for a record. Bounds are not included in the stream if T is
an array type. If T is a discriminated type, discriminants are included only
if they have defaults. If T is a tagged type, the tag is not included.
For type extensions, the Write or Read attribute for the parent type
is called, followed by the Write or Read attribute of each component of the
extension part, in canonical order. For a limited type extension, if the
attribute of any ancestor type of T has been directly specified and the
attribute of any ancestor type of the type of any of the extension components
which are of a limited type has not been specified, the attribute of T
shall be directly specified.
!corrigendum 13.13.02(25)
Replace the paragraph:
Unless overridden by an attribute_definition_clause, these subprograms
execute as follows:
by:
For untagged derived types, the Output and Input attributes of the parent type
are inherited as specified in 13.1; otherwise, the default implementations of
these attributes are used. The default implementations of Output and Input
attributes execute as follows:
!corrigendum 13.13.02(36)
Replace the paragraph:
The stream-oriented attributes may be specified for any type via an
attribute_definition_clause. All nonlimited types have default
implementations for these operations. An attribute_reference for one of
these attributes is illegal if the type is limited, unless the attribute
has been specified by an attribute_definition_clause. For an
attribute_definition_clause specifying one of these attributes, the
subtype of the Item parameter shall be the base subtype if scalar, and the
first subtype otherwise. The same rule applies to the result of the Input
function.
by:
The stream-oriented attributes may be specified for any type via an
attribute_definition_clause. All nonlimited types have default
implementations for these operations. An attribute_reference for one of
these attributes is illegal if the type is limited, unless the attribute
has been specified by an attribute_definition_clause or (for a type
extension) the attribute has been specified for an ancestor type. For an
attribute_definition_clause specifying one of these attributes, the
subtype of the Item parameter shall be the base subtype if scalar, and the
first subtype otherwise. The same rule applies to the result of the Input
function.
Implementation Requirements
For every subtype S of a language-defined nonlimited specific type T, the
output generated by S'Output or S'Write shall be readable by S'Input or
S'Read, respectively. This rule applies across partitions if the implementation
conforms to the Distributed Systems Annex.
!ACATS test
A C-Test to check that the Read and Write attributes of an extension are
defined as in this issue should be created. It should also check that the
Input and Output attributes revert to the predefined versions for an extension.
Tests to check that language-defined nonlimited private types properly support
'Read and 'Write should also be created.
!appendix
!section 13.13.2(09)
!subject Missing AI: 'Input/'Output inheritance
!reference RM95-13.13.2(9,36)
!reference RM95-13.1(15)
!from Tucker Taft 95-10-30
!reference 95-5373.a Tucker Taft 95-10-30>>
!discussion
The general rule for inheritance of type-related representation aspects
should not apply to the stream attributes of type extensions.
For 'Read and 'Write, a rule analogous to the rule for tagged equality
would make the most sense. For 'Input and 'Output, no inheritance makes
sense; instead, they should regain their predefined meaning in terms
of 'Read and 'Write.
This issue was discussed at length in some Ada 95 forum or other
(perhaps the GNAT team mailing list?). There are several problems
associated with applying the normal 13.1(15) inheritance rules to
the stream attributes of tagged types:
1) Inheriting a 'Read or 'Write of the parent type as-is for
the 'Read or 'Write of a type extension will ignore any new
components added in the extension part. A rule analogous
to the one for the equality operator would make more sense.
In particular, the default 'Read or 'Write for a type extension
should be defined to do the 'Read or 'Write of the parent type
followed by the 'Read or 'Write for each component of the
type extension, in canonical order.
2) Inheriting a 'Input or 'Output of the parent type as-is for
'Input or 'Output of a type extension makes no sense, since
the inherited 'Input is a function returning the parent type,
and the inherited 'Output puts out the discriminants of the
parent type. For these two, the only meaningful approach seems
to be for the default 'Input and 'Output for a tagged type to
always be defined in terms of the 'Read and 'Write for the
tagged type, preceded with the discriminants, if any.
For untagged derived types, there is no problem for the derived
type inheriting the stream attributes. Even for tagged derived
types, if the extension part is null, the 'Read and 'Write will
effectively be inherited, given the rule suggested above.
****************************************************************
!section 13.3.2(00)
!subject stream attributes for unbounded string, bounded string etc.
!reference RM95-13.3.2(00)
!from Bob Duff
!reference 96-5480.a Robert A Duff 96-4-12>>
!discussion
Robert Dewar pointed out this issue to me.
It would seem that the stream attributes should work properly for all
the language-defined non-limited types. For example, types
Strings.Unbounded.Unbounded_String, Strings.Bounded.Bounded_String, etc.
- Bob
****************************************************************
!section 13.13.2(00)
!subject Stream-Oriented attributes for language-defined private types
!reference RM95-13.13.2
!from Laurent Guerby 96-07-15
!reference 96-5621.a Laurent Guerby 96-7-15>>
!discussion
The behaviour of the stream oriented attributes is not clearly
defined for most of private (or implementation-defined) types. This
can lead to erroneous execution (but nothing is said about it in the
RM95) if type type has a component of an access type when some object
of this type is exchanged between two partitions. An example of
interest is Unbounded_String.
--
Laurent Guerby <guerby@gnat.com>, Team Ada.
"Use the Source, Luke. The Source will be with you, always (GPL)."
****************************************************************
From Randy Brukardt 3-7-2000
Paragraph 13.1(15.1) is not normative (it follows from other rules), and
could be omitted.
****************************************************************
From: Randy Brukardt
Sent: Wednesday, April 12, 2000 9:57 PM
While doing the (almost) final check on the Corrigendum, I noticed the
following:
The new paragraph 13.13.2(27.1) says:
If T is a type extension, S'Output and S'Input are not inherited from the
parent type; they are defined in terms of S'Read and S'Write,
notwithstanding the inheritance rule stated in 13.1.
But the rewritten 13.1(15) says that operational attributes are never
inherited. It seems to me that this entire change can be deleted. (This is
AI-00108).
Additionally, the last sentence of the new 13.13.2(9) says:
For other derived types, the Write or Read attribute of the parent
type is inherited.
Again, 13.1(15) says that operation attributes are never inherited. I think
it would be better to say that the parent attribute is "called", which would
be similar to the way that the implementation for type extensions are
described.
Any comments??
****************************************************************
From: Tucker Taft
Sent: Thursday, April 13, 2000 11:09 AM
I am surprised that we say that operational attributes are never
inherited. It seems like this needs to be a per-attribute
decision. Inheriting something like external_tag does seem unwise,
but inheriting 'Read from a parent non-tagged type makes perfect
sense.
Perhaps we could say that operational attributes are
never inherited for tagged types, though their actions may be
incorporated as part of the default implementation for the
type extension. However, that doesn't work for 'Read/'Write for
limited tagged types, where they won't have any attribute
at all if it isn't inherited. The operational attribute
writeup needs some revision perhaps.
****************************************************************
From: Randy Brukardt
Sent: Thursday, April 13, 2000 7:14 PM
Tucker said:
> I am surprised that we say that operational attributes are never
> inherited. It seems like this needs to be a per-attribute
> decision. Inheriting something like external_tag does seem unwise,
> but inheriting 'Read from a parent non-tagged type makes perfect
> sense.
I looked this up to see why Pascal made it this way, and discovered that I had
talked him into this change at the last minute. Oh well, I'll have to go it
alone.
First of all, it is important to remember that operational item are a class of
attributes that certainly can be extended by both implementation-defined ones
and possibly by future amendments to the standard. Rules motivated solely by the
behavior of the current members of the class are best avoided. (That is, after
all, how we got into this mess in the first place.) So I immediately reject any
wording that handles non-tagged types differently than tagged types in the
definition of operational items (i.e. in 13.1(15)).
I'm also concerned about defining a heavy, complex inheritance mechanism, then
saying that it doesn't apply in most existing cases. I have a note saying that
the current 13.1(15.1/1) is in fact non-normative: because it says there is
nothing special happening. This certainly is the cleanest solution.
Finally, the current wording (the predefined value of each aspect is used) in
fact defers the decision as to whether or not to inherit to each attribute. That
was the intent, and is what Tucker says he wants.
> Perhaps we could say that operational attributes are
> never inherited for tagged types, though their actions may be
> incorporated as part of the default implementation for the
> type extension. However, that doesn't work for 'Read/'Write for
> limited tagged types, where they won't have any attribute
> at all if it isn't inherited. The operational attribute
> write-up needs some revision perhaps.
AI-00108 makes it pretty clear that 'Read and 'Write are *never* inherited for
tagged types, rather they are composed. If that is the case, then it is seems
very dangerous for there to be any inherited or predefined 'Read/'Write for a
limited tagged type: there may be limited components in the extension that don't
have a 'Read or 'Write to call. To say that limited tagged types are not
composed (the only alternative) would be inconsistent and confusing.
The wording for 13.13.2(9) says "For other derived types, the Write or Read
attribute of the parent type is called." (Or "inherited" instead of "called").
The intent is that here we are defining the predefined meaning for a derived
type to inherit the meaning of the parent type.
This wording seems too vague to me, since it isn't clear whether derived
elementary types are included or not. (You have to read the entire paragraph to
see the problem.) I think it ought to say something more like: "For non-tagged
derived types, the Write or Read attribute of the parent type is called, if one
exists."
After I wrote all of the above, I noticed that inheritance of limited 'Read,
etc. is moot. 13.13.2(36) says "An attribute_reference is illegal if the type is
limited, unless the attribute has been specified by an
attribute_definition_clause". Clearly, any "inherited" or even "predefined"
attribute for a derived limited has not been specified by an
attribute_definition_clause (which is a syntactic entity). Thus, while such an
attribute might exist, it is always illegal to call it. Certainly, the proposed
changes have no effect on that property.
So, my conclusion is that the Corrigendum wording is correct for 'Read and
'Write.
There does seem to be a problem for 'Input and 'Output for untagged derived
types: the current wording reverts them to their predefined implementation,
rather than inheriting them. That would be an gratuitous change, not supported
by AI-00108.
I propose to repair this problem by adding the following in front of 13.13.2(26)
(and indenting (26-27) further):
o If T is an untagged derived type, the Output or Input attribute
of the parent type is called, if one exists.
o For other types:
I believe this takes care of the open problem with inheritance.
Now, I'll don my fireproof suit. :-)
****************************************************************
From: Tucker Taft
Sent: Friday, April 14, 2000 5:56 AM
> ...
> After I wrote all of the above, I noticed that inheritance of limited 'Read,
> etc. is moot. 13.13.2(36) says "An attribute_reference is illegal if the
> type is limited, unless the attribute has been specified by an
> attribute_definition_clause". Clearly, any "inherited" or even "predefined"
> attribute for a derived limited has not been specified by an
> attribute_definition_clause (which is a syntactic entity).
Here you are wrong. "Specified" is clearly defined to include
inherited. If you want to omit inherited aspects, you need to
say "directly specified." ("Look it up," as they say ;-).
> ... Thus, while such
> an attribute might exist, it is always illegal to call it. Certainly, the
> proposed changes have no effect on that property.
This does not follow, given your misinterpretation of "specified."
> So, my conclusion is that the Corrigendum wording is correct for 'Read and
> 'Write.
I understand the need to use the notion of "calling" the parent
operation for type extensions, because that is just one of the
things being done, since the predefined 'Read include calls on
the 'Reads of the components of the extension part. Using the
"call the parent" hack for untagged types seems bogus. Here
we should say the attribute is inherited.
So I believe that operational attributes should be inherited for untagged.
For tagged, when the predefined attribute is defined component-wise,
the parent attribute is incorporated by treating the parent as a
"component" of the type extension, along with the actual components of
the extension part.
Using the "hack" of "call the parent but don't inherit" for untagged
makes no intuitive sense to me.
> There does seem to be a problem for 'Input and 'Output for untagged derived
> types: the current wording reverts them to their predefined implementation,
> rather than inheriting them. That would be an gratuitous change, not
> supported by AI-00108.
Removing inheritance from untagged operational attributes is
a gratuitous change as far as I am concerned.
Even if you wish tagged and untagged were the same, the fact
is that from the point of view of "aspects," they need to be
treated separately. (Look at the handling of "packed" as another example.)
> I propose to repair this problem by adding the following in front of
> 13.13.2(26) (and indenting (26-27) further):
>
> o If T is an untagged derived type, the Output or Input attribute
> of the parent type is called, if one exists.
Yuck. Just inherit untagged operational attributes.
> o For other types:
>
>
> I believe this takes care of the open problem with inheritance.
I don't agree.
****************************************************************
From: Pascal Leroy
Sent: Friday, April 14, 2000 6:30 AM
> Using the
> "call the parent" hack for untagged types seems bogus. Here
> we should say the attribute is inherited.
But that doesn't quite work because the (untagged) derived type may have
different discriminants than its parent.
I think that part of this discussion is covered by items 3 and 5 of AI 195,
which in fact corrects some of AI 108:
3 - For a derived type which is limited (tagged or not), the attributes Read
and Write are inherited, and the attributes Input and Output revert to their
predefined definition (i.e. they cannot be called). (This amends AI95-
00108.)
5 - For an untagged derived type with new discriminants that have defaults,
the predefined stream-oriented attributes read or write the new
discriminants, not the old ones. (This amends AI95-00108.)
****************************************************************
From: Tucker Taft
Sent: Friday, April 14, 2000 7:01 AM
> But that doesn't quite work because the (untagged) derived type may have
> different discriminants than its parent.
I think we discussed this, and concluded that a user-defined
'Read or 'Write is inherited as is, but if there is no
user-defined 'Read or 'Write, the predefined one behaves as
described below.
> I think that part of this discussion is covered by items 3 and 5 of AI 195, which in fact corrects some of AI 108:
>
> 3 - For a derived type which is limited (tagged or not), the attributes Read
> and Write are inherited, and the attributes Input and Output revert to their
> predefined definition (i.e. they cannot be called). (This amends AI95-
> 00108.)
>
> 5 - For an untagged derived type with new discriminants that have defaults,
> the predefined stream-oriented attributes read or write the new
> discriminants, not the old ones. (This amends AI95-00108.)
The above clearly indicates that saying that "operational attributes
are never inherited" is misleading at best.
****************************************************************
From: Randy Brukardt
Sent: Friday, April 14, 2000 3:54 PM
Tucker said:
> Here you are wrong. "Specified" is clearly defined to include
> inherited. If you want to omit inherited aspects, you need to
> say "directly specified." ("Look it up," as they say ;-).
I did (now). And the paragraphs in question 13.1(16-18) clearly don't apply
to operational aspects. :-)
I don't know if this was intentional on Pascal's part (I think so, but I'm
guessing, none of my mail answers that).
So that is another problem (one way or another) with this stuff.
Tucker replied to me:
> > So, my conclusion is that the Corrigendum wording is correct for 'Read and
> > 'Write.
>
> I understand the need to use the notion of "calling" the parent
> operation for type extensions, because that is just one of the
> things being done, since the predefined 'Read include calls on
> the 'Reads of the components of the extension part. Using the
> "call the parent" hack for untagged types seems bogus. Here
> we should say the attribute is inherited.
>
> ...
> Using the "hack" of "call the parent but don't inherit" for untagged
> makes no intuitive sense to me.
It's pretty hard to argue with "seems bogus". You seem to prefer a rule of
"it inherits, except when it doesn't", and I prefer to not call it
inheritance.
I guess I would like to see an actual suggestion of wording changes for
13.1(15-18) and 13.13.2(9 and 25) that meet the needs of the AI and have the
behavior that you want.
Pascal said:
>I think that part of this discussion is covered by items 3 and 5 of AI 195,
>which in fact corrects some of AI 108:
>3 - For a derived type which is limited (tagged or not), the attributes Read
>and Write are inherited, and the attributes Input and Output revert to their
>predefined definition (i.e. they cannot be called). (This amends AI95-
>00108.)
>5 - For an untagged derived type with new discriminants that have defaults,
>the predefined stream-oriented attributes read or write the new
>discriminants, not the old ones. (This amends AI95-00108.)
Keep in mind that AI-00195 never was approved or finished. So it isn't clear
just how much of it we ought to incorporate.
I now believe (having thought about this some more) that 3 is wrong for
'Read and 'Write for a type extension. That is, using the previous version
is more likely to cause bugs and confusion than it is to work properly
(because the extension components are not covered). Moreover, simply making
a type limited could silently break code. (Breaking it with a compile-time
error is at least helpful, as it points out the problem.) The situation is
similar to that for a function, which we do not allow the use of the
original.
More from Tucker:
> Even if you wish tagged and untagged were the same, the fact
> is that from the point of view of "aspects," they need to be
> treated separately. (Look at the handling of "packed" as
> another example.)
That is irrelevant to the wording of 13.1. 13.1 only has a two places where
"tagged" occurs: in 13.1(10) and 13.1(11). And it is those rules that
triggered AI-00137 in the first place! If they hadn't had special cases for
untagged types, we probably wouldn't be having this conversation (as
special-case "patches" for AI-108 probably would have made more sense).
I cannot see fixing one problem by unnecessarily introducing the *exact
same* problem in the fix. We *will* trip over any such rules again.
So I strongly believe that any rules ought to be specific to a particular
attribute or set of attributes. (Certainly the non-normative wording of
"does not inherit" in 13.1 could be dumped, but I'm not quite sure what to
replace it by.)Now I can imagine defining the entire inheritance blather at
the start of 13.13.2, but it seems awfully heavy to do so just to say what
takes two sentences to do otherwise.
Tucker replied to me:
> > I believe this takes care of the open problem with inheritance.
>
> I don't agree.
I now agree there are problems here, especially because of the cases noted
from the unfinished AI-00195.
I don't agree that we are likely to find a resolution without a meeting,
however. Tucker's argument seems to be purely based on emotion ("seems
bogus", "the hack of calling..."). Honestly, mine (while clearly superior
:-) isn't much better, as it is based on potential future uses of the
feature. To resolve this requires roundtable discussion and additional
points of view. E-Mail seems to degrade into two people dominating the
discussion, and rarely develops the consensus needed.
How to proceed from here? I think we only have one practical choice left,
but I'll let others decide that. The choices are (in no particular order):
A: Leave it as it is.
-- Too many problems have been noted, that simply isn't practical.
B: Put in half-baked changes discussed by e-mail.
-- Past experience with the corrigendum says that these get
-- heavily modified at the next meeting. Which means it is the same
-- as C.
C: Fix it at the next meeting.
-- This would be OK, but as a practical matter means that we cannot
-- meet the schedule. (Substantive changes inserted at a meeting
-- should always be reconsidered afterwards, especially in the full
-- context of the RM. The problems we're discussing came up because I
-- did that with these changes.) To at least come close to the schedule,
-- we would have to have an "extra" meeting in September/October.
D: Revert AIs 108 & 137 to the pre-operational attribute version.
-- This probably would work, but we would have to re-review the changes
-- from those versions, as I don't think that we ever did that. So,
-- more than likely, we end up with C again.
E: Vote to remove AI-108 from the corrigendum.
-- This can be supported based on the need to complete the recommendation
-- (that is, the partial reversal of AI-00108 in AI-195 implies that
-- it needs a lot more work, and not all of this work was considered in
-- the current wording). After all, there seems to be more than just a
-- disagreement in wording here, especially if AI-195 is factored in.
-- However, doing this leaves the question of dealing with AI-137 in a
-- way that doesn't interfere with the eventual solution of AI-108/195.
-- E1 would be to revert it to the original pre-operational attribute form,
-- which was quite simple, with the thought that it would be changed again
-- "next time". But that probably ends up the same as D. E2 would be to
-- "fix" it to be compatible, meaning that we still would have to come up
-- with wording for 13.1(15-18) -- which is where we started.
F: Vote to remove both AI-108 and AI-137 from the corrigendum.
-- This would be supported by the reasons given above for AI-108, and
-- an interaction argument for AI-137. This seems to be the only solution
-- that would keep us on schedule. But it is pretty severe, as we're
-- delaying answering these questions for more time.
****************************************************************
From: Randy Brukardt
Sent: Thursday, June 01, 2000 6:34 PM
Despite Tucker's violation of the our corrigendum rule (if you want a wording
change, you have to propose one), I've made an attempt to rewrite this AI to
address his concerns. I've also added points 3 and 5 from AI-195 to the
discussion of this AI, as they are addressed in the corrigendum wording.
Here is my latest cut at the wording:
Replace 13.1(15) by the following (the first paragraph is unchanged from the
previous Corrigendum):
A derived type inherits each type-related aspect of representation of its parent
type that was directly specified before the declaration of the derived type, or
(in the case where the parent is derived) that was inherited by the parent type
from the grandparent type. A derived subtype inherits each subtype-specific
aspect of representation of its parent subtype that was directly specified
before the declaration of the derived type, or (in the case where the parent is
derived) that was inherited by the parent subtype from the grandparent subtype,
but only if the parent subtype statically matches the first subtype of the
parent type. An inherited aspect of representation is overridden by a subsequent
representation item that specifies the same aspect of the type or subtype.
In contrast, whether operational aspects are inherited for a derived type
depends on the specific aspect. When operational aspects are inherited for a
derived type, aspects that were directly specified before the declaration of the
derived type, or (in the case where the parent is derived) that were inherited
by the parent type from the grandparent type are inherited. An inherited
operational aspect is overridden by a subsequent operational item that specifies
the same aspect of the type.
Add after 13.1(18):
If an operational aspect is specified for an entity (meaning that it is either
directly specified or inherited), then that aspect of the entity is as
specified. Otherwise, the aspect of the entity has the default value determined
by the specific aspect.
Replace 13.3(75) by:
S'External_Tag S'External_Tag denotes an external string representation for
S'Tag; it is of type String. External_Tag may be specified for a specific tagged
type via an attribute_definition_clause; the expression of such a clause shall
be static. The default external tag representation is implementation-defined.
See 3.9.2 and 13.13.2. The value of External_Tag is never inherited[; the
default value is always used unless it is directly specified for a type].
Replace 13.13.2(9) by:
For untagged derived types, the Write or Read attribute of the parent type is
inherited if it was directly specified for some ancestor type; otherwise, the
default implementation of the attribute is used. For other derived types, the
Write or Read attribute is not inherited; the default implementation is always
used.
The default implementation of Write and Read attributes is defined as follows:
For elementary types, the representation in terms of stream elements is
implementation defined. For composite types, the Write or Read attribute for
each component is called in a canonical order. The canonical order of components
is last dimension varying fastest for an array, and positional aggregate order
for a record. Bounds are not included in the stream if T is an array type. If T
is a discriminated type, discriminants are included only if they have defaults.
If T is a tagged type, the tag is not included. For type extensions, the Write
or Read attribute for the parent type is called, followed by the Write or Read
attribute of each non-inherited component, in canonical order.
Replace 13.13.2(25) by:
For untagged derived types, the Output or Input attribute of the parent type is
inherited if it was directly specified for some ancestor type; otherwise, the
default implementation of the attribute is used. For other derived types, the
Output or Input attribute is not inherited; the default implementation is always
used.
The default implementation of the Output and Input operations execute as
follows:
Replace 13.13.2(36) by:
The stream-oriented attributes may be specified for any type via an
attribute_definition_clause. All nonlimited types have default implementations
for these operations. An attribute_reference for one of these attributes is
illegal if the type is limited, unless the attribute has been specified by an
attribute_definition_clause or (for a type extension) all of the attributes
called by the default implementation can be referenced by this rule. For an
attribute_definition_clause specifying one of these attributes, the subtype of
the Item parameter shall be the base subtype if scalar, and the first subtype
otherwise. The same rule applies to the result of the Input function.
(The changes previously proposed for 13.13.2(26-27) are removed.)
-----
Notes:
I used square brackets above in the manner of the AARM. These don't appear in
the corrigendum.
13.1(18) is in fact wrong for 'Read/'Write/'Input/'Output as the default value
is determined by the various rules; it certainly is not "chosen in an
unspecified manner". Another reason to define operational attributes...
13.3(75) needed to be changed to say that 'External_Tag values are never
inherited.
13.13.2(9) needed to say that default definitions are never inherited, only
specified ones. (This is point 5 from the unfinished AI-195 -- the discriminants
included may be different, and we don't want to write both sets). This could be
removed (given that AI-195 wasn't finished), but doing so doesn't help the
wording much.
It also needed to name the "default implementations" (or some similar term);
otherwise, it gets very awkward.
Finally, (of course), it needed to say that untagged types inherit these
aspects, while tagged types do not. Note that all type extensions inherit their
components. See below for more on this.
13.13.2(25) needed wording similar to 13.13.2(9). Note that this wording is
repeated here in case it needs to be different from that in 13.13.2(9) [which
would be the case if I lose the argument over 195 pt. 3 for instance]; these
attributes are sufficiently different to treat them separately.
13.13.2(36) needed wording to allow calling Read and Write for limited type
extensions when all of the attributes that make up the extension exist.
This purposely is a different conclusion than the unfinished AI-195 pt. 3 comes
to. However, just inheriting existing attributes (thus silently ignoring any
extension components) seems to be more likely to cause bugs than provide
anything useful. Ada 95 goes pretty far to avoid silently dropping extension
components, yet a distributed system using these attributes could very well end
up ignoring the extensions completely. This rule (combined with the new
13.13.2(9)) allows limited extensions to work properly so long as all of the
attributes are well defined. If any of them are not defined (either because they
are limited and are not specified), then the attributes cannot be called. This
seems to provide the maximum compatibility with the old, buggy rules (we get
inheritance for null extensions, and we get inheritance with extension if all of
the components are non-limited or have specified attributes), while preventing
the bugs caused by silently ignoring components. I suspect that this change
would find/fix more bugs than breaking correct programs. And the fix is easy if
a user *really* wants inheritance without the extension components: just add an
attribute_clause for the appropriate routine (presumably inherited as well - it
has to be primitive for the parent type).
****************************************************************
From: Tucker Taft
Sent: Thursday, June 01, 2000 9:25 PM
> Despite Tucker's violation of the our corrigendum rule (if you want a
> wording change, you have to propose one), I've made an attempt to rewrite
> this AI to address his concerns. I've also added points 3 and 5 from AI-195
> to the discussion of this AI, as they are addressed in the corrigendum
> wording.
Thanks for taking the time to do this. See below for comments.
>
> Here is my latest cut at the wording:
>
> Replace 13.1(15) by the following (the first paragraph is unchanged from the
> previous Corrigendum):
>
> A derived type inherits each type-related aspect of representation of its
> parent type that was directly specified before the declaration of the
> derived type, or (in the case where the parent is derived) that was
> inherited by the parent type from the grandparent type. A derived subtype
> inherits each subtype-specific aspect of representation of its parent
> subtype that was directly specified before the declaration of the derived
> type, or (in the case where the parent is derived) that was inherited by the
> parent subtype from the grandparent subtype, but only if the parent subtype
> statically matches the first subtype of the parent type. An inherited aspect
> of representation is overridden by a subsequent representation item that
> specifies the same aspect of the type or subtype.
>
> In contrast, whether operational aspects are inherited for a derived type
> depends on the specific aspect. When operational aspects are inherited for a
> derived type, aspects that were directly specified before the declaration of
> the derived type, or (in the case where the parent is derived) that were
> inherited by the parent type from the grandparent type are inherited. An
> inherited operational aspect is overridden by a subsequent operational item
> that specifies the same aspect of the type.
Do you think it would be useful to establish a default?
E.g., unless stated otherwise in this standard, operational attributes
are (not?) inherited by derived types.
I wonder whether this whole thing could be simplified by defining something
like "an aspect supports inheritance" to mean all of the gobbledygook
about being specified before the point of derivation. Then there is
no need to repeat all that stuff everytime. Otherwise, I fear there
will be little bugs in your wording (see below for examples) when
all we are trying to say is that it supports inheritance.
> Add after 13.1(18):
>
> If an operational aspect is specified for an entity (meaning that it is
> either directly specified or inherited), then that aspect of the entity is
> as specified. Otherwise, the aspect of the entity has the default value
> determined by the specific aspect.
Is the above paragraph really necessary? This sounds like a "to be pedantic"
section to be included in the AARM only. Perhaps if it was combined
with establishing a default rule on operational attribute inheritance,
it wouldn't sound so silly.
> Replace 13.3(75) by:
>
> S'External_Tag S'External_Tag denotes an external string representation for
> S'Tag; it is of type String. External_Tag may be specified for a specific
> tagged type via an attribute_definition_clause; the expression of such a
> clause shall be static. The default external tag representation is
> implementation-defined. See 3.9.2 and 13.13.2. The value of External_Tag is
> never inherited[; the default value is always used unless
> it is directly specified for a type].
>
> Replace 13.13.2(9) by:
>
> For untagged derived types, the Write or Read attribute of the parent type
> is inherited if it was directly specified for some ancestor type; otherwise,
> the default implementation of the attribute is used. For other derived
> types, the Write or Read attribute is not inherited; the default
> implementation is always used.
Why say "For other derived types" when "For tagged derived types" is
equivalent? Another reason to switch to this wording is that the above
paragraph has "otherwise..." and then "For other ..."
That seems bound to cause confusion.
Perhaps even better than "For tagged derived types" might be
"For type extensions..."
This paragraph also seems to have one of the "little bugs" I mentioned
above because it says it is "inherited if it was directly specified
for some ancestor type" but omits the discussion about the specification
happening before the derivation. Again, I think switching to something
simple like "For untagged derived types, the Write and Read attributes
support inheritance; for tagged derived types, the attributes are
not inherited."
> The default implementation of Write and Read attributes is defined as
> follows:
> For elementary types, the representation in terms of stream elements is
> implementation defined. For composite types, the Write or Read attribute for
> each component is called in a canonical order. The canonical order of
> components is last dimension varying fastest for an array, and positional
> aggregate order for a record. Bounds are not included in the stream if T is
> an array type. If T is a discriminated type, discriminants are included only
> if they have defaults. If T is a tagged type, the tag is not included. For
> type extensions, the Write or Read attribute for the parent type is called,
> followed by the Write or Read attribute of each non-inherited
> component, in canonical order.
Remember that discriminants are also "components." For tagged types,
they never have defaults, so it is safe to say "... of each non-inherited
non-discriminant component..." (safe to say, yes; easy to say, no ;-).
Or even better: "... of each component of the extension part ..."
> Replace 13.13.2(25) by:
>
> For untagged derived types, the Output or Input attribute of the parent type
> is inherited if it was directly specified for some ancestor type; otherwise,
> the default implementation of the attribute is used. For other derived
> types, the Output or Input attribute is not inherited; the default
> implementation is always used.
Again, why not say "For tagged derived types..." (or "For type extensions...").
Also another one of the "little bugs" appears here. Again, an
alternative is "For untagged derived types, the Output and Input
attributes support inheritance; for tagged derived types, the
Output and Input attributes are not inherited."
>
> The default implementation of the Output and Input operations execute as
> follows:
>
> Replace 13.13.2(36) by:
>
> The stream-oriented attributes may be specified for any type via an
> attribute_definition_clause. All nonlimited types have default
> implementations for these operations. An attribute_reference for one of
> these attributes is illegal if the type is limited, unless the attribute has
> been specified by an attribute_definition_clause or (for a type extension)
> all of the attributes called by the default implementation can be referenced
> by this rule.
This doesn't seem quite right. Suppose the type is a limited private
extension of a type with specified stream attributes. How do you
know whether it is legal to call the attributes on the extension?
I suggest the following: If a limited tagged type specifies a Write or Read
attribute, then the corresponding attribute may be legally called
on any non-abstract descendant. However, the default implementation of the
stream attribute on such a descendant is (effectively) abstract if its
parent type or an extension component does not have a legally callable
corresponding attribute, in which case the attribute *must* be
directly specified. (This is analogous to the rule for functions
with controlling results.)
Furthermore, I would suggest that Output and Input piggy back automatically
on Write and Read, even for limited types:
If the Read attribute of a type can legally be called, then the Input
attribute has a non-abstract default implementation; similarly,
if the Write attribute of a type can legally be called, then
the Output attribute has a non-abstract default implementation.
> ... For an
> attribute_definition_clause specifying one of these attributes, the subtype
> of the Item parameter shall be the base subtype if scalar, and the first
> subtype otherwise. The same rule applies to the result of the Input
> function.
>
>
> (The changes previously proposed for 13.13.2(26-27) are removed.)
> ...
> 13.13.2(36) needed wording to allow calling Read and Write for limited type
> extensions when all of the
> attributes that make up the extension exist.
See above for comments on the "privacy violation" aspects of this
proposal. I think it can be fixed by adopting rules analogous to
those for functions with controlling results.
****************************************************************
From: Randy Brukardt
Sent: Friday, June 02, 2000 5:12 PM
> > Replace 13.1(15) by the following (the first paragraph is unchanged from the
> > previous Corrigendum):
> >
> > A derived type inherits each type-related aspect of representation of its
> > parent type that was directly specified before the declaration of the
> > derived type, or (in the case where the parent is derived) that was
> > inherited by the parent type from the grandparent type. A derived subtype
> > inherits each subtype-specific aspect of representation of its parent
> > subtype that was directly specified before the declaration of the derived
> > type, or (in the case where the parent is derived) that was inherited by the
> > parent subtype from the grandparent subtype, but only if the parent subtype
> > statically matches the first subtype of the parent type. An inherited aspect
> > of representation is overridden by a subsequent representation item that
> > specifies the same aspect of the type or subtype.
> >
> > In contrast, whether operational aspects are inherited for a derived type
> > depends on the specific aspect. When operational aspects are inherited for a
> > derived type, aspects that were directly specified before the declaration of
> > the derived type, or (in the case where the parent is derived) that were
> > inherited by the parent type from the grandparent type are inherited. An
> > inherited operational aspect is overridden by a subsequent operational item
> > that specifies the same aspect of the type.
>
> Do you think it would be useful to establish a default?
> E.g., unless stated otherwise in this standard, operational attributes
> are (not?) inherited by derived types.
Not really. It wouldn't save much more than one line in the current situation
(the added line in 13.3(75).) OTOH, it might be helpful if we ever try to add
another one of these. What does everyone else think?
> I wonder whether this whole thing could be simplified by defining something
> like "an aspect supports inheritance" to mean all of the gobbledygook
> about being specified before the point of derivation. Then there is
> no need to repeat all that stuff everytime. Otherwise, I fear there
> will be little bugs in your wording (see below for examples) when
> all we are trying to say is that it supports inheritance.
I thought that too; in fact, that was what I originally tried to do. And failed
to come up with anything that made sense. That was partially because I couldn't
come up with a term that seemed to have the right meaning. "An aspect supports
inheritance" probably would work for defining the term, but I don't see how to
use it after it was defined.
I was thinking that these two paragraphs defines formally what it means to
inherit an aspect. Then the use of the word "inherits" in other places was meant
to invoke these paragraphs.
I suppose we could try something like:
---
If a type related aspect is @i<inherited> @defn2(inherit, an aspect) for a
derived type, only aspects that were directly specified before the declaration
of the derived type, or (in the case where the parent is derived) that were
inherited by the parent type from the grandparent type are inherited. If a
subtype related aspect is @i<inherited> for a derived subtype, only aspects of
the parent subtype that were directly specified before the declaration of the
derived type, or (in the case where the parent is derived) that were inherited
by the parent type from the grandparent type, but only if the parent subtype
statically matches the first subtype of the parent type are inherited. An
inherited aspect is overridden by a subsequent aspect item that specifies the
same aspect of the type or subtype.
Aspects of representation are always inherited [as described above]. In
contrast, whether operational aspects are inherited depends on the specific
aspect.
----
This wording could stand improvement! If you don't like this, please suggest
something better! Please? :-)
> > Add after 13.1(18):
> >
> > If an operational aspect is specified for an entity (meaning that it is
> > either directly specified or inherited), then that aspect of the entity is
> > as specified. Otherwise, the aspect of the entity has the default value
> > determined by the specific aspect.
>
> Is the above paragraph really necessary? This sounds like a "to be pedantic"
> section to be included in the AARM only. Perhaps if it was combined
> with establishing a default rule on operational attribute inheritance,
> it wouldn't sound so silly.
Well, it's necessary, because you pointed out that "specified" has a specific
meaning. However, that meaning is only defined for representation aspects in
13.1(16-18), and we can't reuse those paragraphs to define it for operational
aspects (because of 13.1(18), which is just outright wrong for stream attributes
[and always has been - there should have been an AI on that, too, except that no
one ever really believed it.]) And we need to use "specified" in 13.13.2, so
leaving it undefined is not really an option.
Without the definition of "specified", it's pretty silly, but then again, so are
13.1(16-18), and someone thought *they* needed to be in the RM.
A suggestion for an improvement here is welcome as well...
> > Replace 13.13.2(9) by:
> >
> > For untagged derived types, the Write or Read attribute of the parent type
> > is inherited if it was directly specified for some ancestor type; otherwise,
> > the default implementation of the attribute is used. For other derived
> > types, the Write or Read attribute is not inherited; the default
> > implementation is always used.
>
> Why say "For other derived types" when "For tagged derived types" is
> equivalent?
Because that was the way it previously was done (except in reverse). I certainly
have no objection to this change (I'll make it in the AI).
> Another reason to switch to this wording is that the above
> paragraph has "otherwise..." and then "For other ..."
> That seems bound to cause confusion.
> Perhaps even better than "For tagged derived types" might be
> "For type extensions..."
I don't like that change, because it always leads me to ask "what about tagged
derived types that aren't extensions?". Of course, after thinking about it, I
remember that there aren't any such things, but it *always* breaks my train of
thought.
> This paragraph also seems to have one of the "little bugs" I mentioned
> above because it says it is "inherited if it was directly specified
> for some ancestor type" but omits the discussion about the specification
> happening before the derivation. Again, I think switching to something
> simple like "For untagged derived types, the Write and Read attributes
> support inheritance; for tagged derived types, the attributes are
> not inherited."
No, that phrase "if it was directly specified for some ancestor type" is
intended to be ADDED to all of the stuff in 13.1(15/1). It is trying to deal
with the changing discriminants problem, which means we never want to inherit a
default implemented aspect. (That's point 5 of AI-00195.)
It seems that the revised wording for 13.1(15/1) seems to say that only
specified aspects are inherited. Indeed, the original wording seems to say this
as well. In that case, point 5 of AI-00195 is just a confirmation -- it doesn't
change anything except some poorly worded discussion material in AI-00108.
Assuming the previously proposed change for 13.1(15/1), and assuming that
default values for aspects are never inherited, then we could simply say:
---
For untagged derived types, the Write or Read attribute of the parent type is
inherited as specified in 13.1; otherwise, the default implementation of the
attribute is used. For tagged derived types, the Write or Read attribute is not
inherited; the default implementation is always used.
---
Is this better?
> > The default implementation of Write and Read attributes is defined as
> > follows:
> > For elementary types, the representation in terms of stream elements is
> > implementation defined. For composite types, the Write or Read attribute for
> > each component is called in a canonical order. The canonical order of
> > components is last dimension varying fastest for an array, and positional
> > aggregate order for a record. Bounds are not included in the stream if T is
> > an array type. If T is a discriminated type, discriminants are included only
> > if they have defaults. If T is a tagged type, the tag is not included. For
> > type extensions, the Write or Read attribute for the parent type is called,
> > followed by the Write or Read attribute of each non-inherited component, in
> > canonical order.
>
> Remember that discriminants are also "components." For tagged types,
> they never have defaults, so it is safe to say "... of each non-inherited
> non-discriminant component..." (safe to say, yes; easy to say, no ;-).
> Or even better: "... of each component of the extension part ..."
Well, that wording is unchanged from the last three versions of this AI...but
you're right of course. I've changed it to the latter version.
> > Replace 13.13.2(25) by:
> >
> > For untagged derived types, the Output or Input attribute of the parent type
> > is inherited if it was directly specified for some ancestor type; otherwise,
> > the default implementation of the attribute is used. For other derived
> > types, the Output or Input attribute is not inherited; the default
> > implementation is always used.
>
> Again, why not say "For tagged derived types..." (or "For type extensions...").
> Also another one of the "little bugs" appears here. Again, an
> alternative is "For untagged derived types, the Output and Input
> attributes support inheritance; for tagged derived types, the
> Output and Input attributes are not inherited."
I would use (with all of the caveats above):
----
For untagged derived types, the Output or Input attribute of the parent type is
inherited as specified in 13.1; otherwise, the default implementation of the
attribute is used. For tagged derived types, the Output or Input attribute is
not inherited; the default implementation is always used.
----
> > Replace 13.13.2(36) by:
> >
> > The stream-oriented attributes may be specified for any type via an
> > attribute_definition_clause. All nonlimited types have default
> > implementations for these operations. An attribute_reference for one of
> > these attributes is illegal if the type is limited, unless the attribute has
> > been specified by an attribute_definition_clause or (for a type extension)
> > all of the attributes called by the default implementation can be referenced
> > by this rule.
>
> This doesn't seem quite right. Suppose the type is a limited private
> extension of a type with specified stream attributes. How do you
> know whether it is legal to call the attributes on the extension?
I wanted to define this in 13.13.2(9) so there wasn't a problem, but that would
have caused nasty forward reference. I then tried here, which I didn't think
about much .
> I suggest the following: If a limited tagged type specifies a Write or Read
> attribute, then the corresponding attribute may be legally called
> on any non-abstract descendant. However, the default implementation of the
> stream attribute on such a descendant is (effectively) abstract if its
> parent type or an extension component does not have a legally callable
> corresponding attribute, in which case the attribute *must* be
> directly specified. (This is analogous to the rule for functions
> with controlling results.)
OK, let's try the following:
The stream-oriented attributes may be specified for any type via an
attribute_definition_clause. All nonlimited types have default
implementations for these operations. An attribute_reference for one of
these attributes is illegal if the type is limited, unless the attribute has
been specified by an attribute_definition_clause or (for a type extension)
the attribute has been directly specified for an ancestor type.
Then add the following to 13.13.2(9):
For a limited type extension, if the attribute of any ancestor type has been
directly specified and the attribute of any ancestor type of any of the limited
extension components has not been specified, the attribute of @i<T> shall be
directly specified.
---
This is bit different than Tucker's suggestion, mainly so that there is no
requirement to specify an attribute if the parent attribute wasn't specified.
I also used "specified" (in the sense of 13.1(18/1) - the paragraph Tucker would
like to get rid of) rather than "callable" - which would require a definition.
This gets a bit messy because limited type extension's attributes can be
callable without being "specified" (inherited or directly specified); but in
that case, some ancestor type must have been directly specified.
> Furthermore, I would suggest that Output and Input piggy back automatically
> on Write and Read, even for limited types:
> If the Read attribute of a type can legally be called, then the Input
> attribute has a non-abstract default implementation; similarly,
> if the Write attribute of a type can legally be called, then
> the Output attribute has a non-abstract default implementation.
This seems like a good idea, but it's going well beyond the AI, or even what is
currently in AI-00195. I don't want to bog the corrigendum down at the last
minute with good ideas... I suggest that we add that to AI-195.
Clearly, this wouldn't conflict with the current wording (which defines that
these always use the default implementation, but leaves them uncallable for
limited types). But I'm not sure it is useful for the implementation burden --
Input is a function after all, and limited functions aren't very useful.
****************************************************************
From: Randy Brukardt
Sent: Friday, July 07, 2000 7:44 PM
While editing DR-40, I noticed a minor glitch in the last sentence of
13.13.2(9). The problem is that the sentence twice uses "ancestor type" without
identifying what type the ancestor type is of (and the two uses are different).
I suggest adding a few extra words to fix this (the insertions are marked with
{}):
For a limited type extension, if the attribute of any ancestor type {of @i<T>}
has been directly specified and the attribute of any ancestor type {of the type}
of any of the extension components which are of a limited type has not been
specified, the attribute of @i<T> shall be directly specified.
This sentence is a real mouthful, but I believe it has the correct effect. If
anyone has an improvement to this sentence, or an objection to my change, please
speak up *now*.
Randy.
****************************************************************
Questions? Ask the ACAA Technical Agent