CVS difference for ai05s/ai05-0115-1.txt
--- ai05s/ai05-0115-1.txt 2011/03/22 05:07:08 1.10
+++ ai05s/ai05-0115-1.txt 2011/04/01 06:38:28 1.11
@@ -1,4 +1,4 @@
-!standard 4.3.2(5/2) 11-03-16 AI05-0115-1/06
+!standard 4.3.2(5/2) 11-03-30 AI05-0115-1/07
!standard 7.3.1(5/1)
!class binding interpretation 08-10-15
!status work item 08-10-15
@@ -100,6 +100,19 @@
!wording
+Add after 3.9(12.2):
+
+ For the purposes of the dynamic semantics of functions Descendant_Tag
+ and Is_Descendant_At_Same_Level, a tagged type T2 is a /descendant/ of
+ a type T1 if it is the same as T1, or if its parent type or one of its
+ progenitor types is a descendant of type T1 by this rule [Redundant:,
+ even if at the point of the declaration of T2, one of the derivations
+ in the chain is not visible].
+
+ AARM Discussion: In other contexts, "descendant" is dependent on visibility,
+ and the particular view a derived type has of its parent type. See RM 7.3.1.
+
+
Modify 4.3.2(5/2):
If the ancestor_part is a subtype_mark, it shall denote a specific
@@ -158,6 +171,61 @@
can never take advantage of having "more" visibility than that of your
parent type.
+The reference manual was scanned to see whether this change to the definition
+of "descendant" would have adverse affects. It was determined that it fixed
+other potential holes in the language -- see below for more details. It
+was also decided that the definition of "descendant" for the purposes of
+the run-time semantics of functions like Ada.Tags.Descendant_Tags should
+not depend on "views" even though the static semantics now more-clearly does.
+
+To be precise about where this change has effects:
+
+ In 3.4.1(9-10) we define "derivation class," "ancestor," and "cover," in
+ terms of type derivation and/or descendant. In all cases, this refined
+ definition of "descendant" would have an impact on the question of whether
+ a given type is in a particular derivation class, whether it is covered
+ by the class-wide type of that class, whether the root of the derivation
+ class is an ancestor, etc.
+
+ In 4.6(21-24) on type conversion, there are several uses of the terms
+ "ancestor" and "descended from." With this refined definition of
+ "descendant," these rules would preclude converting to an ancestor of
+ which the parent is not aware. AI95-00157 addresses the question of
+ whether you must use conversion to a grandparent type to gain access
+ to a component that the grandchild type inherits from the grandparent,
+ but which its immediate parent cannot see. Here we disallow even the
+ conversion to an ancestor if the parent did not "know" about the ancestor.
+
+ In 8.6(21, 25, 25.1, 27.1) whether one type "covers" another affects
+ both name resolution and legality. With the refined definition of
+ "descendant," whether a given class-wide type covers a particular
+ type depends on the visibility of the chain of derivation to the
+ parent type.
+
+ In 12.5.1(5.1/3), an actual type for a formal derived type is required
+ to be a descendant of the specified ancestor type and of the specified
+ progenitors. The refined definition of "descendant" requires that the
+ chain of derivation be visible to the view of the parent of the actual
+ type from which the current view of the actual type is derived. If at
+ the point of the instantiation, more is visible than at the point
+ where this view of the parent type was declared, no use of that
+ information may be made in determining legality.
+
+One could argue that these cases are potential sources of
+incompatibility. An alternative approach would be to say that a type is
+considered a descendant of a type at any place where the entire chain of
+derivation is visible. But it *inherits* characteristics only from
+ancestors from which its parent inherits characteristics. Convertibility
+and matching/covering/etc. would be an exception. Effectively a type
+can be a descendant of what we might call the "incomplete" view of some
+ancestor. No characteristics come from it, other than the ability to
+convert (explicitly or implicitly due to being "covered") or to pass as
+an actual in a generic instantiation.
+
+See the !example section below for more detailed discussion of how this
+"refined" definition of ancestor relates to the original question,
+namely the legality of various aggregates.
+
---
We added a separate rule about ancestors with unknown discriminants. It is
@@ -2207,6 +2275,15 @@
****************************************************************
+From: Tucker Taft
+Sent: Thursday, March 17, 2011 9:07 AM
+
+I did a preliminary review and didn't find any problems, other than your
+run-time issue in Ada.Tags. I just didn't have time to do a formal writeup of
+each occurrence.
+
+****************************************************************
+
From: Edmond Schonberg
Sent: Sunday, March 20, 2011 9:00 AM
@@ -2283,5 +2360,140 @@
Please make sure that you report this to the ACAA Technical Agent so I can put
it on the pile of ACATS tests needing fixes for Ada 2012.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Thursday, March 31, 2011 10:50 PM
+
+[Attached to version /07 of the AI.]
+
+I have added to the discussion here the results of scanning the standard for
+uses of "descendant," "descended from," "ancestor," "covers," etc.
+
+The implications are that there are various places where the "ancestry" of a
+type affects legality and overload resolution. I believe we want to stick with
+the basic rule that essentially all "characteristics" are inherited "through"
+the immediate parent, and if a derived type happens to know more than its parent
+type about its ancestry, it can't use that information, for example, to refer to
+a component that its parent couldn't see.
+
+However, when it comes to things like type conversion, generic instantiation as
+an actual for a formal derived type, "coverage" by a class-wide type, etc., I
+could imagine having a more flexible rule. That is, if a type knows it is
+derived indirectly from some type, even though its parent type does *not* know
+that fact, it can at a minimum be convertible to that "secret" ancestor.
+
+I didn't write the wording that way, but we might want to consider it. One way
+I imagined doing that was saying that in cases like that, the child type is
+essentially a descendant of an "incomplete" view of the ancestor. It inherits no
+characteristics from that ancestor, other than the right to be converted to it,
+or to match it for the purposes of formal derived types, or things like that
+('Class coverage, etc.). I have some suspicion that this approach would be more
+compatible with what most compilers do today, and it doesn't seem to cause any
+trouble. This is in contrast to inheriting characteristics from such a secret
+ancestor, as you could get into real trouble if you could see a component of a
+secret ancestor that had the same name as a component of your parent type
+(unbeknownst to the parent type).
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Friday, April 1, 2011 12:35 AM
+
+> I have added to the discussion here the results of scanning the
+> standard for uses of "descendant,"
+> "descended from," "ancestor," "covers," etc.
+
+Thanks for doing this analysis. It went far beyond what I was contemplating
+(although it appears to have been necessary).
+
+> The implications are that there are various places where the
+> "ancestry" of a type affects legality and overload resolution. I
+> believe we want to stick with the basic rule that essentially all
+> "characteristics" are inherited "through" the immediate parent, and if
+> a derived type happens to know more than its parent type about its
+> ancestry, it can't use that information, for example, to refer to a
+> component that its parent couldn't see.
+>
+> However, when it comes to things like type conversion, generic
+> instantiation as an actual for a formal derived type, "coverage" by a
+> class-wide type, etc., I could imagine having a more flexible rule.
+> That is, if a type knows it is derived indirectly from some type, even
+> though its parent type does
+> *not* know that fact, it can at a minimum be convertible to that
+> "secret" ancestor.
+
+I think this shows that I was right that there are far-reaching effects.
+
+> I didn't write the wording that way, but we might want to consider it.
+> One way I imagined doing that was saying that in cases like that, the
+> child type is essentially a descendant of an "incomplete" view of the
+> ancestor.
+> It inherits no characteristics from that ancestor, other than the
+> right to be converted to it, or to match it for the purposes of formal
+> derived types, or things like that ('Class coverage, etc.).
+> I have some suspicion that this approach would be more compatible with
+> what most compilers do today, and it doesn't seem to cause any
+> trouble. This is in contrast to inheriting characteristics from such
+> a secret ancestor, as you could get into real trouble if you could see
+> a component of a secret ancestor that had the same name as a component
+> of your parent type (unbeknownst to the parent type).
+
+My immediate, unverified thought is that the rules you currently have could do
+some real harm to the implementation of Claw and its tools (although I couldn't
+know for sure without having a compiler that strictly implemented the rules).
+Conversions to Root_Window_Type'Class are quite common, and if there is a type
+for which that ancestry isn't "visible", we'd have trouble. Similarly for
+Root_Dialog_Type'Class. I realize that there would always be a chain of
+conversions that would be legal, but that would be ugly.
+
+Let me write a quick example of what you are talking about to see if I
+understand properly.
+
+ package P1 is
+ type Root is abstract tagged ...;
+ procedure Draw (W : Root'Class);
+ end P1;
+
+ package P1.P2 is
+ type Subroot is abstract private;
+ procedure Paint (W : Subroot'Class);
+ private
+ type Subroot is new Root with ...;
+ end P1.P2;
+
+ package P1.P2.P3 is
+ type A_Win is new Root with private;
+ private
+ type A_Win is new Subroot with ...
+ end P1.P2.P3;
+
+ with P1.P2.P3;
+ package P1.P2.P4 is
+ type B_Win is new A_Win with ...;
+ procedure Test (W : B_Win);
+ end P1.P2.P4;
+
+ with P1.P2.P4;
+ procedure Unrelated is
+ W : P1.P2.P4.B_Win;
+ begin
+ P1.Draw (W); -- Legal (?)
+ P1.P2.Paint (W); -- Illegal (?)
+ end Unrelated;
+
+ package body P1.P2.P4 is
+ procedure Test (W : B_Win) is
+ begin
+ P1.Draw (W); -- Legal.
+ P1.Draw (A_Win(W)); -- Legal.
+ P1.P2.Draw (W); -- Illegal.
+ P1.P2.Draw (A_Win(W)); -- Legal.
+ end Test;
+ end P1.P2.P4;
+
+Humm, I don't seem to have managed to create the situation you are worried
+about. Could you show an example??
****************************************************************
Questions? Ask the ACAA Technical Agent