Version 1.2 of ais/ai-00396.txt
!standard 3.9.4(10/2) 05-01-27 AI95-00396/01
!class amendment 05-01-25
!status work item 05-01-25
!status received 05-01-25
!priority High
!difficulty Easy
!subject The "no hidden interfaces" rule
!summary
(See proposal.)
!problem
The "no hidden interfaces" rule of 3.9.4(10/2) is overly zealous. It should be
allowed to hide interfaces when the partial view is untagged. Also, the
justification for this rule in the AARM is obscure.
!proposal
Allow an untagged partial view to be complete by a tagged type that implements
some interfaces. Also improve the AARM justification.
!wording
Replace 3.9.4(10/2) by:
A full view shall only be a descendant of an interface type if the corresponding
partial view (if any) is untagged or is also a descendant of the interface type.
AARM Note:
Reason: Consider the following example:
package P is
package Pkg is
type Ifc is interface;
procedure Foo (X : Ifc) is abstract;
end Pkg;
type Parent_1 is tagged null record;
type T1 is new Parent_1 with private;
private
type Parent_2 is new Parent_1 and Pkg.Ifc with null record;
procedure Foo (X : Parent_2); --
type T1 is new Parent_2 with null record;
end P;
with P;
package P_Client is
type T2 is new P.T1 and P.Pkg.Ifc with null record;
procedure Foo (X : T2); --
X : T2;
end P_Client;
with P_Client;
package body P is
...
procedure Bar (X : T1'Class) is
begin
Pkg.Foo (X); --
end;
begin
Pkg.Foo (Pkg.Ifc'Class (P_Client.X)); --
Bar (T1'Class (P_Client.X));
end P;
If this example were legal (it is illegal because the completion of T1 is
descended from an interface that the partial view is not descended from), T2
would implement Ifc twice. Once in the visible part of P, and once in the
visible part of P_Client. We would need to decide how Foo #1 and Foo #2 relate
to each other. There are two options: either Foo #2 overrides Foo #1, or it
doesn't.
If Foo #2 overrides Foo #1, we have a problem because the client redefines a
behavior that it doesn't know about, and we try to avoid this at all costs, as
it would lead to a breakdown of whatever abstraction was implemented. If the
abstraction didn't expose that it implements Ifc, there must be a reason, and it
should be able to depend on the fact that no overriding takes place in clients.
Also, during maintenance, things may change and the full view might implement a
different set of interfaces. Furthermore, the situation is even worse if the
full type implements another interface Ifc2 that happens to have a conforming
Foo (otherwise unrelated, except for its name and profile).
If Foo #2 doesn't override Foo #1, there is some similarity with the case of
normal tagged private types, where a client can declare an operation that
happens to conform to some private operation, and that's OK, it gets a different
slot. The problem here is that T2 would implement Ifc in two different ways,
and through conversions to Ifc'Class we could end up with visibility on these
two different implementations. This is the "diamond inheritance" problem of C++
all over again, and we would need some kind of a preference rule to pick one
implementation. We don't want to go there (if we did, we might as well provide
full-fledged multiple inheritance).
Note that there wouldn't be any difficulty to implement the first option, so the
restriction is essentially methodological. The second option might be harder to
implement, depending on the language rules that we would choose.
End AARM Note.
!discussion
(See proposal.)
!example
--!corrigendum
!ACATS test
An ACATS C-Test should be created to test that an untagged private type can be
completed with a type that has interfaces.
!appendix
****************************************************************
Questions? Ask the ACAA Technical Agent