Version 1.6 of ai05s/ai05-0097-1.txt

Unformatted version of ai05s/ai05-0097-1.txt version 1.6
Other versions for file ai05s/ai05-0097-1.txt

!standard 3.9.3(4/2)          08-10-18 AI05-0097-1/03
!class binding interpretation 08-05-23
!status Amendment 2012 08-11-26
!status WG9 Approved 08-10-31
!status ARG Approved 8-0-0 08-06-22
!status work item 08-05-23
!status received 06-04-08
!priority Low
!difficulty Easy
!qualifier Omission
!subject 3.9.3(4) includes abstract null extensions
!summary
The rules of 3.9.3(4-6) are corrected so that abstract null extensions are not excluded.
!question
Consider the following:
package P is type Generator is tagged record ...
function Create return Generator; ... end P;
---
with P; package Q is type Windmill is abstract new P.Generator with null record; -- Inherits a concrete Create here(!!) end Q;
---
with P, Q; procedure Main is Obj : P.Generator'Class := Q.Create; begin ...
The inherited Create is concrete, because the parent's Create is concrete, and 3.9.3(4/2) does not include functions with controlling results of null extensions. Thus the rules that ordinarily make functions like this abstract do not apply to this one.
But something must be wrong here, because Q.Create is creating an object of an abstract type! What is the intent here? (Q.Create is abstract.)
!wording
Modify 3.9.3(4/2) as follows:
If a type has an implicitly declared primitive subprogram that is inherited or is the predefined equality operator, and the corresponding primitive subprogram of the parent or ancestor type is abstract or is a function with a controlling access result, or if a type other than a {non-abstract} null extension inherits a function with a controlling result, then:
!discussion
An alternative would have been to declare the call illegal as this call is equivalent to an extension aggregate by 3.4(27/2) and that extension aggregate would be illegal by 3.9.3(8). But that's uncomfortable, as 3.9.3(8) says "aggregate" syntactically, and there is no aggregate syntax in this call. Moreover, it would make the detection of the error quite late.
There is a possible use for detecting the error late (using the declarations of the question):
with Q; package R is type Pump is new Q.Windmill with null record; -- Inherits a concrete Create here with the current rule, but would -- have to override Create with the proposed change (as the original -- Create would be abstract). end R;
but this is thought to be pretty pathological. A user shouldn't be expecting concrete subprograms to be inherited from an abstract type. So we make the original type declaration illegal.
!corrigendum 3.9.3(4/2)
Replace the paragraph:
If a type has an implicitly declared primitive subprogram that is inherited or is the predefined equality operator, and the corresponding primitive subprogram of the parent or ancestor type is abstract or is a function with a controlling access result, or if a type other than a null extension inherits a function with a controlling result, then:
by:
If a type has an implicitly declared primitive subprogram that is inherited or is the predefined equality operator, and the corresponding primitive subprogram of the parent or ancestor type is abstract or is a function with a controlling access result, or if a type other than a non-abstract null extension inherits a function with a controlling result, then:
!ACATS Test
A ACATS B-Test like the example in the question should be created.
!appendix

From: Randy Brukardt
Sent: Tuesday, April 8, 2008  5:21 PM

I'm working on an ACATS test for 3.9.3(4/2), and one of the test cases I
had looked like:

    package P is
       type Generator is tagged record ...

       function Create return Generator;
       ...
    end P;


---

    with P;
    package Q is
        type Windmill is abstract new P.Generator with null record;
        -- Inherits a concrete Create here(!!)
    end Q;

---

    with P, Q;
    procedure Main is
        Obj : P.Generator'Class := Q.Create;
    begin
        ...


The inherited Create is concrete, because the parent's Create is concrete,
and 3.9.3(4/2) does not include functions with controlling results of
null extensions. Thus the rules which ordinarily make function like this
abstract do not apply to this one.

But something must be wrong here, because Q.Create is creating an object
 of an abstract type! 3.4(27/2) say that this call is the equivalent of
an extension aggregate, so I suppose we could reject this on the basis that
3.9.3(8) says such aggregates are illegal. But that's uncomfortable, as
3.9.3(8) uses aggregate syntactically, and there is no obvious use of an
aggregate syntactically here. (If that's the intent, there ought to be AARM
note saying so somewhere.)

I wonder if 3.9.3(4/2) should say "type other than a {non-abstract} null extension".
Then the inherited Create would be abstract and the call would be illegal
for that straightforward reason. But note that that is subtly incompatible
with the current rule. Consider:

    with Q;
    package R is
        type Pump is new Q.Windmill with null record;
        -- Inherits a concrete Create here with the current rule, but would
        -- have to override Create with the proposed change (as the original
        -- Create would be abstract).
    end R;

Not sure what the right answer is here. It would be nice to know so I can
revise the test appropriately. (AI-391 does not seem to have considered this
question.)

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

From: Edmond Schonberg
Sent: Tuesday, April 8, 2008  5:38 PM

>   with Q;
>   package R is
>       type Pump is new Q.Windmill with null record;
>       -- Inherits a concrete Create here with the current rule, but would
>       -- have to override Create with the proposed change (as the original
>       -- Create would be abstract).
>   end R;

But that seems reasonable. If the parent was declared abstract its
constructors should all be abstract. I don't see the interest in having
some re-emergence of a concrete constructor from an ancestor here. Your
proposed addition:  "{non-abstract} null extension" seems fine to me.

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

From: Pascal Leroy
Sent: Wednesday, April 9, 2008  6:33 AM

>   with P;
>   package Q is
>       type Windmill is abstract new P.Generator with null record;
>       -- Inherits a concrete Create here(!!)
>   end Q;

As things stand now, I believe that this is actually illegal because
of the last sentence of 3.9.3(8): "If the result type of a function is
abstract, then the function shall be abstract". Presumably this rule
applies to all functions, even the implicitly-declared ones. However, this
is not an acceptable resolution, because it would make existing code
illegal (including Ada 95 code).
 
> I wonder if 3.9.3(4/2) should say "type other than a {non-abstract} null
> extension".

Yes, it should.
 
> Then the inherited Create would be abstract and the call would
> be illegal for that straightforward reason. But note that that is subtly
> incompatible with the current rule. Consider:
>
>   with Q;
>   package R is
>       type Pump is new Q.Windmill with null record;
>       -- Inherits a concrete Create here with the current rule, but would
>       -- have to override Create with the proposed change (as the original
>       -- Create would be abstract).
>   end R;

No incompatibility here, Q is illegal for the reason explained above.

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

Questions? Ask the ACAA Technical Agent