CVS difference for ais/ai-00200.txt

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

--- ais/ai-00200.txt	1999/03/20 00:13:19	1.2
+++ ais/ai-00200.txt	2004/04/06 19:56:57	1.3
@@ -1,12 +1,14 @@
-!standard 03.02.03 (07)                               99-03-14  AI95-00200/01
+!standard 03.02.03 (07)                               04-03-23  AI95-00200/02
 !class binding interpretation 98-03-27
+!status Amendment 200Y 04-03-24
+!status ARG Approved 9-0-0  04-03-05
 !status work item 99-03-14
 !status received 98-03-27
 !priority Low
 !difficulty Medium
 !subject Generic formal subprograms as dispatching operations
 
-!summary 99-03-14
+!summary
 
 Generic formal subprograms are never primitive operations and hence
 cannot be dispatching operations, even though they can potentially
@@ -14,11 +16,11 @@
 The primitive operations of a formal type comprise only the predefined
 operators and implicitly declared subprograms of the formal type.
 
-!question 99-03-14
+!question
 
 The definition of primitive subprograms in 3.2.3(7) suggests that the copies
 of generic formal subprograms in an instance can be dispatching operations if
-they override any implicitly declared primitive subprograms there.  It is
+they override any implicitly declared primitive subprograms there. It is
 unclear how dispatching calls on such subprograms should be performed.
 
 For example:
@@ -47,14 +49,14 @@
    package I3 is new G(Root, Bar, Bar);
 
 In each of the instances of G, the declaration of T declares a new view of
-Root by RM95 12.3(15).  The predefined "=" operator (1) is copied and is
-considered primitive by RM95 12.5.1(21) and RM95 3.2.3(3).  Likewise, the Foo
+Root by RM95 12.3(15). The predefined "=" operator (1) is copied and is
+considered primitive by RM95 12.5.1(21) and RM95 3.2.3(3). Likewise, the Foo
 function (2) is copied and is considered primitive by RM95 12.5.1(21) and
-RM95 3.2.3(4).  The user-defined "=" operator (3) and Foo function (4)
+RM95 3.2.3(4). The user-defined "=" operator (3) and Foo function (4)
 declare new views of the generic actual subprograms specified for each
-instance.  The "=" (3) and Foo (4) operations are declared in the same
+instance. The "=" (3) and Foo (4) operations are declared in the same
 declarative region as the predefined ones (1) and (2) and override them by
-RM95 8.3(10).  So, it seems that it should be considered primitive, too, by
+RM95 8.3(10). So, it seems that it should be considered primitive, too, by
 RM95 3.2.3(7).
 
 Because the "=" (3) and Foo (4) operations are primitive operations of (a
@@ -120,23 +122,23 @@
 [The calls are illegal because the invoked subprograms are not dispatching
 operations.]
 
-!recommendation 99-03-14
+!recommendation
 
 The rule given in 3.2.3(7) is not intended to apply to subprograms that
 override the implicitly declared primitive subprograms of a generic
-formal type.  The only operations that are primitive subprograms
+formal type. The only operations that are primitive subprograms
 of a formal type are the subprograms implicitly declared at the point
 of the formal type declaration.
 
 In particular, a formal subprogram that overrides a primitive operation
 of a formal type is not a primitive operation of the type, and thus
-is not a dispatching operation of the type.  Similarly, a subprogram
+is not a dispatching operation of the type. Similarly, a subprogram
 declared immediately within the package specification of a generic
 formal package declaration and overrides a primitive operation of a
 formal type of the generic is not a primitive of the type, even though
 it occurs within the same declarative region as the formal type.
 
-!wording 99-03-14
+!wording
 
 Revise 3.2.3(7) to make it clear that the rule does not apply to
 generic formal types, e.g.:
@@ -146,7 +148,7 @@
   region as the type and that override (see 8.3) other implicitly
   declared primitive subprograms of the type."
 
-!discussion 99-03-14
+!discussion
 
 The principal question asked by the submitter is whether formal
 subprograms can ever be dispatching operations of a formal type.
@@ -176,24 +178,24 @@
 actual type (as for one of the instantiations in the examples of the
 !question section), then it would not be sensible for this actual
 subprogram to suddenly become a dispatching primitive simply because
-it was used in an instantiation.  How would the actual subprogram be
+it was used in an instantiation. How would the actual subprogram be
 incorporated into the dispatch table of the actual type, and what would
 it even mean to have two subprograms associated with the same dispatch
 table entry?
 
 The submitter also raises a similar question for the situation where
 primitives of a formal type are overridden by subprograms declared in
-the specification of a formal package.  By 3.2.3(7) it would appear
+the specification of a formal package. By 3.2.3(7) it would appear
 that the overriding subprograms become primitives of the formal type
 since the subprograms are declared immediately within the same
-declarative region as the formal type.  Again, it was not the intent
+declarative region as the formal type. Again, it was not the intent
 that such overriding operations should become primitives of a formal
 type.
 
 Note that even though the implicitly declared primitive subprograms of
 a formal type can be overridden, this does not mean that an overriding
 operation is a primitive of the type, even though that is normally the
-case for overridings of operations of nonformal types.  In particular,
+case for overridings of operations of nonformal types. In particular,
 this means that a derivation from the formal type will not inherit such
 overriding operations, but as usual will inherit the primitives of the
 formal type, even though some of them may be hidden at the point of
@@ -201,9 +203,25 @@
 
 The fix for this wording problem is simply to specify that the rule
 of 3.2.3(7) only applies to nonformal types.
+
+!corrigendum 3.2.3(07)
+
+@drepl
+@xbullet<Any subprograms not covered above that are explicitly declared
+immediately within the same declarative region as the type and that override
+(see 8.3) other implicitly declared primitive subprograms of the type.>
+@dby
+@xbullet<In the case of a nonformal type, any subprograms not covered above
+that are explicitly declared immediately within the same declarative region as
+the type and that override (see 8.3) other implicitly declared primitive
+subprograms of the type.>
 
-!appendix 98-03-27
+!ACATS Test
 
+Tests covering cases like those in the examples should be created.
+
+!appendix
+
 !section 3.2.3(7)
 !subject Generic formal subprograms as dispatching operations
 !reference RM95-3.2.3(7)
@@ -615,3 +633,439 @@
 -Tuck
 
 ****************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, March 16, 2004  5:43 PM
+
+Someone posted the following program on comp.lang.ada:
+
+package Pkg1 is
+   type T_Event is abstract tagged null record;
+   function Priority (Event : T_Event) return Natural is abstract;
+end Pkg1;
+
+-- ---------------------------------------------------------------
+with Pkg1;
+generic
+   type T_Event (<>) is new Pkg1.T_Event with private;
+package Pkg2 is
+   function Priority (Event : in T_Event) return Natural;
+
+   -- OK for GNAT 3.16a (20030120)
+   -- KO for ObjectAda (tm) Version 7.2.1 :
+   --
+   --      7    function Priority (Event : in T_Event) return Natural;
+   --                    *
+   --  *****Error: LRM:3.9.2(13) a primitive subprogram of a tagged type may
+not be
+   --  *****        declared after the type is frozen
+
+end Pkg2;
+
+---
+
+This seems to show a language hole (or, at least what will be a hole if
+AI-359 is adopted).
+
+The inherited Priority routine is primitive by 3.2.3. 8.3 then says that the
+new declaration overrides it. Of course, this is bogus, because the type is
+not even declared in this scope, so any such overriding has to be illegal -
+it can't be implemented. But I can't find any reason for that. OA says that
+the type is frozen, but there really isn't any reason to assume that (and
+AI-359 would certainly make that not true in some cases). Even if the type
+was not frozen, we'd still want this to be illegal.
+
+So I don't see why this is illegal, but it's clear that it ought to be.
+
+****************************************************************
+
+From: Adam Beneschan
+Sent: Tuesday, March 16, 2004  6:26 PM
+
+I'm somewhat confused.  Suppose you declare another package that
+instantiates Pkg2:
+
+with Pkg1, Pkg2;
+package Pkg3 is
+   type U_Event is new Pkg1.T_Event with null record;
+   -- Implicitly declares the following:
+   -- function Priority (Event : U_Event) return Natural is
+   --    <shall-be-overridden>;
+   package New_Pkg2 is new Pkg2 (U_Event);
+end Pkg3;
+
+The way generics work, it should be equivalent to this:
+
+with Pkg1, Pkg2;
+package Pkg3_Equivalent is
+   type U_Event is new Pkg1.T_Event with null record;
+   -- Implicitly declares the following:
+   -- function Priority (Event : U_Event) return Natural is   --[A]
+   --    <shall-be-overridden>;
+   package New_Pkg2 is
+      function Priority (Event : in U_Event) return Natural;  --[B]
+   end New_Pkg2;
+end Pkg3_Equivalent;
+
+and the function marked [B] is not in the same declarative region as
+the declaration of U_Event, so it's not a primitive subprogram of
+U_Event, and there's no overriding, and no reason anything should be
+illegal.  Neither 3.2.3 nor 8.3(9-13) would apply.  [8.3(13) appears
+to apply only to a derived types and associated implicit subprograms
+declared *in* the package spec, not to generic formal derived types
+nor their inherited programs declared in the generic formal part.]
+
+Perhaps the definition of "declarative region" is busted when it comes
+to generics?  Looking at just the generic package:
+
+    generic
+       type T_Event (<>) is new Pkg1.T_Event with private;
+    package Pkg2 is
+       function Priority (Event : in T_Event) return Natural;  --[C]
+    end Pkg2;
+
+As with the Pkg3_Equivalent example, the declaration marked [C] is
+*inside* the package Pkg2, while the type T_Event and any inherited
+subprograms are *outside* the package.  At least that's what happens
+when the package is instantiated, or what *should* happen.
+
+It seems to me that a generic package such as the above ought to be
+considered two declarative regions, with one including the entire
+construct (including the formal part), and the second including the
+entire construct excluding the generic formal part (and including the
+package body), with the second one being considered an inner
+declarative region.  Would this solve the problem?  Would this create
+additional problems?  Is there something in the RM that already
+accomplishes something like this?  I can't find it in 8.1.
+
+****************************************************************
+
+From: Gary Dismukes
+Sent: Tuesday, March 16, 2004  6:47 PM
+
+I agree that the rules seem to allow this.  One way to fix it would
+be to somehow change the overriding rules so that it's still legal
+but doesn't override, but it seems like a bad idea to permit this
+confusing declaration, so I agree that it should be made illegal.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Tuesday, March 16, 2004  8:07 PM
+
+...
+> This seems to show a language hole (or, at least what will be a hole if
+> AI-359 is adopted).
+
+I agree it is a whole, but it is one that has been there for a long
+time, and it seems clear to me that:
+
+  The explicit declaration is hiding from all visibility the primitive
+  subprogram of the formal, but is *not* a primitive of the formal.
+
+Consider the case:
+
+    generic
+        type T is private;
+        with function "="(Left, Right : Boolean) return Boolean is <>;
+    package Some_Generic is ...
+
+This is a common paradigm, but we all "know" that the formal
+function doesn't become a primitive subprogram as a result
+of this construct, even though clearly it is hiding from
+all visibility the implicitly defined "=" of the formal T.
+
+So I think that 3.2.3(7) needs to say that such an overriding
+does *not* produce a new primitive of a formal type.
+
+The message from ObjectAda seems sort of reasonable if the
+declaration were to create a new primitive, because the
+*formal* seems clearly "frozen" (even if the actual might
+not be by AI-359), but I think we should legislate against
+making this a primitive.
+
+> The inherited Priority routine is primitive by 3.2.3. 8.3 then says that the
+> new declaration overrides it. Of course, this is bogus, because the type is
+> not even declared in this scope, so any such overriding has to be illegal -
+> it can't be implemented. But I can't find any reason for that. OA says that
+> the type is frozen, but there really isn't any reason to assume that (and
+> AI-359 would certainly make that not true in some cases). Even if the type
+> was not frozen, we'd still want this to be illegal.
+>
+> So I don't see why this is illegal, but it's clear that it ought to be.
+
+I'm not convinced, given the very common paradigm of having
+formal subprograms that "override" predefined operators,
+without becoming primitives.
+
+****************************************************************
+
+From: Gary Dismukes
+Sent: Wednesday, March 17, 2004  1:06 PM
+
+Given what you pointed out about formal overriding, I now agree
+that this should be allowed, and that this should be fixed by
+changing the rules to make such overridings nonprimitve.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Friday, March 19, 2004  2:09 PM
+
+(* I've moved the following discussion from comp.lang.ada to here, so it is
+on the permanent record *)
+
+"Adam Beneschan" <adam@irvine.com> wrote (on comp.lang.ada):
+> "Randy Brukardt" <randy@rrsoftware.com> wrote:
+
+> > That's so that a type declared
+> > in a body can have overriding routines, even though it can't have
+> > primitives. Scopes have absolutely nothing to do with overriding (look at
+> > 8.3 again if you don't believe me).
+>
+> Sorry, I looked at it and I still don't believe you.  8.3(9) says that
+> a declaration can override another homograph if the declaration
+> "occurs immediately within the same declarative region", etc.  The
+> term "immediately within a declarative region" is defined by 8.1(13)
+> and most definitely has to do with scopes.  If you declare a routine
+> in a nested inner package, it cannot override a routine declared
+> (implicitly or explicitly) in an outer package, because the routine in
+> the inner package is not *immediately* declared in the same
+> declarative region as the routine declared in the outer package.
+
+The inherited routine *is* in this scope, because it belongs to and is
+declared with the formal type (which is in this scope). When I said that
+scopes don't matter, I was referring to the fact that the scope where the
+inherited routine originally comes from isn't significant. That was a bad
+choice of words.
+
+In any case, both the inherited declaration and the explicit declaration are
+in the scope of the generic spec. 8.3(9/1) says that the inherited
+declaration is overridable.
+
+> > Similarly, primitiveness has nothing to do with it.
+>
+> Primitiveness has nothing to do with whether a routine is overriding;
+> but since the compiler in the original example reported an error
+> because it thought the declared routine was primtive, it's certainly
+> relevant to the problem.  Again, I'm probably just not understanding
+> you correctly.
+
+The compiler in the original example reported an error. The reason seems
+bogus, but I didn't pay much attention to the reason reported; compilers
+often give the wrong reason when reporting an error in a corner case. And
+this certainly is a corner case.
+
+> > I think it should be illegal simply because it is very confusing. This looks
+> > like an overriding routine, but it is not.
+>
+> Now I'm convinced that I'm lost.  I thought you were disagreeing with
+> me when I said the function (i.e. the Priority explicitly declared in
+> the generic) is not an overriding routine?
+
+I think everyone agrees that this *should not be* an overriding routine. (We
+don't want retro-active overriding, which would require changing the tag.)
+However, the current language wording says that it *is* an overriding
+routine. I presume that we will fix the wording of the language so this is
+not true.
+
+The question is how to do this? My preference is to say that routines
+inherited along with a formal type are not overridable. That makes this
+example illegal, because you'd then have two homographs in the same scope.
+(It's also the easiest wording change I can think of.)
+
+Tucker suggests that this should be allowed, because the new operation is
+not a primitive of the formal. I certainly agree that it is not primitive,
+and the language already says that (a formal type is not declared
+immediately in a package specification 3.2.3(6)). But it *still* is
+overriding, because that has nothing to do with primitiveness (so that types
+declared in scopes without primitive operations still have override
+operations such as Finalize).
+
+3.2.3(7) does say that overriding operations are primitive. And that's an
+important rule in my view. Tucker seems to want to introduce a new kind
+overriding that is not primitive. That's a significant change in a compiler;
+I know that we don't have any separate indication of primitiveness in our
+symboltable (it is deduced from the overriding state).
+
+This minor language glitch does not seem significant enough to justify
+forcing vendors to reorganize their symboltables (or worse, to cause them to
+ignore the AI and its implications). Thus, I'd rather the construct be
+illegal:
+   -- To reduce user confusion;
+   -- To prevent the need to have non-primitive overriding of tagged types
+in compilers.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Friday, March 19, 2004  2:56 PM
+
+> ...
+> Tucker suggests that this should be allowed, because the new operation is
+> not a primitive of the formal. I certainly agree that it is not primitive,
+> and the language already says that (a formal type is not declared
+> immediately in a package specification 3.2.3(6)). But it *still* is
+> overriding, because that has nothing to do with primitiveness (so that types
+> declared in scopes without primitive operations still have override
+> operations such as Finalize).
+
+I argued by analogy with something which is done
+pretty frequently in Ada 95:
+
+    generic
+        type T is private;
+        with function "="(Left, Right) return Boolean is <>;
+    package ...
+
+This seems almost exactly the same problem, except that the overriding
+is even "closer" to the formal type, but *still* it doesn't become
+a primitive.  If you derive from T, you should *not* get this formal
+"=" subprogram.  You should get the implicitly declared one.
+So this formal subprogram is *not* a primitive, even though it
+hides from all visibility the implicitly declared "=",
+since you cannot name this implicitly declared one, even using
+expanded name notation.  If we don't want to call it overridden,
+we could invent a new word, or just say it is hidden from all
+visibility and leave it at that.
+
+> 3.2.3(7) does say that overriding operations are primitive. And that's an
+> important rule in my view. Tucker seems to want to introduce a new kind
+> overriding that is not primitive. That's a significant change in a compiler;
+> I know that we don't have any separate indication of primitiveness in our
+> symboltable (it is deduced from the overriding state).
+>
+> This minor language glitch does not seem significant enough to justify
+> forcing vendors to reorganize their symboltables (or worse, to cause them to
+> ignore the AI and its implications). Thus, I'd rather the construct be
+> illegal:
+>    -- To reduce user confusion;
+>    -- To prevent the need to have non-primitive overriding of tagged types
+> in compilers.
+
+I think you need to address the issue of formal subprograms that
+hide implicitly declared primitives.  I personally believe that
+subprograms declared in the visible part should have the same
+rule as the formals declared in the formal part.  That is,
+they can hide-from-all-visibility the implicitly declared primitive,
+without becoming primitives.
+
+I suppose the underlying model is that a formal type declaration
+is really declaring a subtype, not a new type, and then implicitly
+declaring renames of all the primitive subprograms.  Overriding these
+renames with formal subprograms or subprograms declared in the
+visible part doesn't make the new subprograms primitives, since
+they are really just overriding renames of the primitives, not
+the primitives themselves.
+
+****************************************************************
+
+From: Adam Beneschan
+Sent: Friday, March 19, 2004  8:05 PM
+
+> The inherited routine *is* in this scope, because it belongs to and is
+> declared with the formal type (which is in this scope). When I said that
+> scopes don't matter, I was referring to the fact that the scope where the
+> inherited routine originally comes from isn't significant. That was a bad
+> choice of words.
+
+OK, thanks for the explanation (and the one about the "primitive"
+error message).  While we're discussing "bad choice of language", I
+probably ought to point out that my original c.l.a post on the thread
+was an attempt to summarize very briefly what I had previously said on
+Ada-Comment, so there were probably important details left out.
+
+I'd like to clarify my thinking on this issue:
+
+   generic
+       type T is new Root_T with private;
+       -- procedure Operation (X : in T);  [implicitly inherited]
+   package Pkg2 is
+        procedure Operation (X : in T);
+   end Pkg2;
+
+The way I look at generics (and the way 12.3(13) seems to look at
+them) is that when you instantiate, it's as if you declared a new copy
+of the package at the point where you instantiate.  (Of course, some
+compilers generate code that way and some don't, but that's not
+relevant here.)  Thus, when you say something like "package New_Pkg2
+is new Pkg2", it's as if you had declared a nested package New_Pkg2
+and declared Operation inside it.  If you had done this, there would
+be no way that this explicit Operation would be in the same scope as
+the actual type and the inherited operation (they might not even be in
+the same compilation unit).
+
+My gut feeling on this is that, broadly, the language rules in effect
+when the generic is compiled ought to parallel the language rules that
+would be in effect when a copy of the template is made.  That's a
+gross oversimplification, of course, since the same outer declarations
+won't be visible in both places.  However, my gut feeling is that if
+the language says that, IN THE GENERIC, T and the explicit Operation
+are in the same scope, while in an instance this is not going to
+happen, then there's something wrong with the language---since the
+structure that the language is looking at when the generic is declared
+is not "topologically equivalent" to the structure created when the
+generic is instantiated.  OK, I realize this is quite vague.  I don't
+know how to express this well.
+
+But my conclusion from this is that the language is flawed if it says
+that the formal type T and the explicit Operation are immediately in
+the same declarative region.  It does seem to say this, as you say:
+
+> In any case, both the inherited declaration and the explicit declaration are
+> in the scope [of] the generic spec. 8.3(9/1) says that the inherited
+> declaration is overridable.
+
+but it doesn't seem right.  They should be in different scopes.
+
+My previous Ada-Comment post suggested that the generic ought to be
+considered two declarative regions, with the region starting at
+"package Pkg2 is" (and including the body of Pkg2) should be
+considered "inner" to the region that includes the generic formals
+(and the implicit inherited operation).  This would solve the problem,
+plus it fits in nicely with one possibility that Tucker suggested (if
+I understood him correctly), that the explicit Operation should hide
+the implicit one from all visibility, rather than overriding it.  I
+don't know whether this particular change would cause more problems
+than it solves; but I do think that simply legislating that the
+explicit Operation should not be an overriding procedure is a fine
+solution, since it seems consistent with how I think generics work.
+
+On the other hand, if there's a belief that anyone who writes code
+like the above has to be confused about how generics or tagged types
+work, and that we should make it illegal since the user is probably
+expecting something they're not going to get anyway, I'm not going to
+object.  I don't see any particular use for the above sort of
+construct anyway.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, March 23, 2004  6:51 PM
+
+Adam wrote:
+
+> OK, thanks for the explanation (and the one about the "primitive"
+> error message).  While we're discussing "bad choice of language", I
+> probably ought to point out that my original c.l.a post on the thread
+> was an attempt to summarize very briefly what I had previously said on
+> Ada-Comment, so there were probably important details left out.
+
+In working on the minutes of the Phoenix ARG meeting, I discovered that we
+approved AI-200 (an ancient AI that was previously tabled and since was
+forgotten). It turns out to be on exactly this issue, even with similar
+examples.
+
+The AI goes into much discussion on these issues, and concludes to modify
+3.2.3(7) to not apply to formal types. (So there is a language hole.)
+
+I'm still concerned about Tucker's "hidden from all visibility" for the
+original operations. I don't see how that follows from the language rules
+(the language still describes them as "overriding", after all).
+
+It's interesting that no one here remembered this AI, less than two weeks
+after we voted to approve it. Which makes me wonder how well we understood
+it when we approved it!
+
+****************************************************************
+

Questions? Ask the ACAA Technical Agent