Version 1.2 of ais/ai-00202.txt

Unformatted version of ais/ai-00202.txt version 1.2
Other versions for file ais/ai-00202.txt

!standard 12.05.01 (21)          98-10-02 AI95-00202/01
!class binding interpretation 98-03-27
!status work item 98-10-02
!status received 98-03-27
!priority Medium
!difficulty Hard
!subject Primitives of formal type derived from another formal type
!summary 98-10-02
When the ancestor type of a formal derived type is itself a formal type, then within an instance, the copies of the formal derived type's inherited primitive operations declare views of the formal ancestor type's operations.
!question 98-10-02
In an instance of a generic where a formal derived type whose ancestor type is another formal type, the rules regarding the meanings of the implicit declarations for the formal derived type produce a peculiar result.
Consider the following example:
package P1 is type R1 is record .. end record; procedure S (x : R1); -- (1) end P1; use P1;
generic type F2 is new R1; -- implicit: procedure S (x : F2); -- (2) type F3 is new F2; -- implicit: procedure S (x : F3); -- (3) procedure G (o2 : F2; o3 : F3); procedure G (o2 : F2; o3 : F3) is begin S(o2); S(o3); -- Peculiar result end G;
package P2 is type R2 is new R1; -- implicit: procedure S (x : R2); -- (4) procedure S (x : R2); -- (5) end P2; use P2;
package P3 is type R3 is new R2; -- implicit: procedure S (x : R3); -- (6) procedure S (x : R3); -- (7) end P3; use P3;
procedure I is new G(R2, R3);
In the instance I, the implicit declarations of S which operate on F2 and F3, respectively are the corresponding primitive subprograms of the ancestor types of each type, as stated in RM95 12.5.1(21). The ancestor type of F2 is R1, so the implicit declaration of S that operates on F2 (2) is a view of the corresponding primitive subprogram of R1 (1).
The ancestor type of F3 is the type of the subtype denoted by the name F2 in the instance, which is R2. So, the implicit declaration of S that operates on F3 (3) is a view of the corresponding primitive subprogram of R2 (5). But, the annotation in AARM 12.5.1(21.a) indicates that the reason the primitives of a formal derived type in an instance are views of its ancestor's primitives is because the primitives of its actual type might not be subtype conformant with those of its ancestor type. This intention could be violated if the primitive S (3) is a view of the primitive S (5).
Is it the intent that the primitive S (3) should instead declare a view of S (1)? (Yes.)
In general, when the ancestor type of a formal derived type is itself another formal type, then within an instance does the derived type acquire the primitive operations of the formal ancestor type or the primitive operations of the ancestor type's corresponding actual type? (The derived type within the instance declares copies that are views of the operations of the formal ancestor type.)
!recommendation 98-10-02
When the ancestor type of a formal derived type is itself a formal type, then within an instance, the copies of the formal derived type's inherited primitive operations declare views of the formal ancestor type's operations, not views of the operations of the ancestor's corresponding actual type as suggested by 12.5.1(21).
!wording 98-10-02
??? Revise 12.5.1(21) to say:
"... In an instance, the copy of such an implicit declaration declares
a view of the corresponding primitive subprogram {declared for the ancestor type in the generic unit} [of the ancestor], ..."
???
!discussion 98-10-02
The rule that defines the meaning of inherited operations of formal derived types (RM95-12.5.1(21)) states:
"For a formal derived type, the predefined operators and inherited
user-defined subprograms are determined by the ancestor type, and are implicitly declared at the earliest place, if any, within the immediate scope of the formal type, where the corresponding primitive subprogram of the ancestor is visible (see 7.3.1). In an instance, the copy of such an implicit declaration declares a view of the corresponding primitive subprogram of the ancestor, even if this primitive has been overridden for the actual type."
The second sentence asserts that the instance view of a formal derived type's primitive subprograms come from the ancestor type. This rule is designed to avoid the semantic problems that could arise for an untagged formal derived type when the corresponding actual type has an overriding primitive subprogram that is not subtype conformant with the operation inherited from the ancestor. For instance, the subtypes or modes of the actual subprogram might differ from that of the inherited subprogram leading to nonsense for calls made to the formal derived type's subprograms from within the generic.
However, the wording of 12.5.1(21) does not properly account for the case where the ancestor of the formal derived type is itself a formal type. Consider this example adapted from the example in the !question section:
package P1 is type R1 is new Integer; procedure S (X : in R1); -- (1) end P1; use P1;
generic type F2 is new R1; -- implicit: procedure S (X : F2); -- (2) type F3 is new F2; -- implicit: procedure S (X : F3); -- (3) procedure G (O2 : F2; O3 : F3); procedure G (O2 : F2; O3 : F3) is begin S(O2); -- (4) OK: calls view of R1's procedure S S(O3); -- (5) Call with constant actual: legal? end G;
package P2 is type R2 is new R1; procedure S (X : in out R2); -- (6) Mode changes to 'in out' end P2; use P2;
package P3 is type R3 is new R2; procedure S (x : in R3); -- (7) end P3; use P3;
procedure Instance is new G(R2, R3);
The call to S for type F2 works fine, since 12.5.1(21) defines this to call the version of S inherited from type R1. So even though the subprogram S associated with the actual type R2 has a parameter of mode 'in out', in the instance the call at (4) will invoke the inherited subprogram S for type R1, which has an 'in' mode parameter.
However, according to 12.5.1(21), the copy for procedure S for formal type F3 in Instance should be taken as a view of the corresponding operation of the ancestor type, and in the instance "the ancestor type" is interpreted as being a copy of the actual type associated with the formal ancestor (by virtue of the rules for generic instances in 12.3(5)). Thus, since the actual for the formal ancestor type F2 is R2, the call at (5) should map into a call to the procedure S belonging to R2. But the S declared at (7) has a parameter of mode 'in out', and that is inconsistent with the call at (5), which passes a constant (the in parameter O3) as an actual. Thus we would have a generic contract model violation for calls within the body of the generic G.
Clearly the call at (5) should also result in a call to the procedure S declared at (1). In general we want the subprogram inherited by a formal derived type in an instance to correspond to a subprogram of known profile belonging to some ancestor of the immediate ancestor of the formal derived type in question (the nearest ancestor with a corresponding explicit subprogram). A possible wording that expresses this intent is to say that the copy of an inherited subprogram of a formal derived type declares a view of the corresponding primitive subprogram declared for the ancestor type in the generic unit. This implicitly accounts for the potentially transitive nature of the required view. [The wording may need some adjustment though, since technically it doesn't seem completely legitimate to refer to a primitive subprogram of a formal ancestor type when in the context of an instance, but the intended interpretation is clear enough.]
!appendix

!section 12.5.1(21)
!subject Primitives of formal type derived from another formal type
!reference RM95-12.5.1(21)
!reference AARM-12.5.1(21.a)
!from Todd Allen 98-02-27
!keywords generic formal derived type, ancestor subtype, primitive
!reference 1998-15814.a Todd Allen 1998-2-27>>
!discussion

In an instance of a generic where a formal derived type whose ancestor type
is another formal type, the rules regarding the meanings of the implicit
declarations for the formal derived type produce a peculiar result.

Consider the following example:

   package P1 is
      type R1 is record .. end record;
      procedure S (x : R1);                  -- (1)
   end P1;
   use P1;

   generic
      type F2 is new R1;
      -- implicit: procedure S (x : F2);     -- (2)
      type F3 is new F2;
      -- implicit: procedure S (x : F3);     -- (3)
   procedure G (o2 : F2; o3 : F3);
   procedure G (o2 : F2; o3 : F3) is
   begin
      S(o2);
      S(o3);                                 -- Peculiar result
   end G;

   package P2 is
      type R2 is new R1;
      -- implicit: procedure S (x : R2);     -- (4)
      procedure S (x : R2);                  -- (5)
   end P2;
   use P2;

   package P3 is
      type R3 is new R2;
      -- implicit: procedure S (x : R3);     -- (6)
      procedure S (x : r3);                  -- (7)
   end P3;
   use P3;

   procedure I is new G(R2, R3);

In the instance I, the implicit declarations of S which operate on F2 and F3,
respectively are the corresponding primitive subprograms of the ancestor
types of each type, as stated in RM95 12.5.1(21).  The ancestor type of F2 is
R1, so the implicit declaration of S that operates on F2 (2) is a view of the
corresponding primitive subprogram of R1 (1).

The ancestor type of F3 is the type of the subtype denoted by the name F2 in
the instance, which is R2.  So, the implicit declaration of S that operates
on F3 (3) is a view of the corresponding primitive subprogram of R2 (5).
But, the annotation in AARM 12.5.1(21.a) indicates that the reason the
primitives of a formal derived type in an instance are views of its
ancestor's primitives is because the primitives of its actual type might not
be subtype conformant with those of its ancestor type.  This intention could
be violated if the primitive S (3) is a view of the primitive S (5).  Our
belief is that intent was that the primitive S (3) should instead declare a
view of S (1).

--
Todd Allen
Concurrent Computer Corporation
Fort Lauderdale, FL  33309

****************************************************************

Questions? Ask the ACAA Technical Agent