Version 1.1 of ais/ai-00218.txt

Unformatted version of ais/ai-00218.txt version 1.1
Other versions for file ais/ai-00218.txt

!standard 8.3(9-13)          99-03-23 EI95-00001/01
!standard 6.1(1)
!class enhancement 99-03-23
!status work item 99-03-23
!status received 99-03-23
!priority Medium
!difficulty Medium
!subject Accidental overloading when overriding
In order to reduce problems with overriding of primitive operations, additional syntax and a pragma is introduced.
Subtle bugs result from mistakes in the profile of an overriding subprogram. For example:
package Root is type Root_Type is tagged .; procedure Do_Something (Object : in out Root_Type; Data : in Natural); -- (1) end Root;
with Root; package Leaf is type Derived_Type is new Root.Root_Type with null record; procedure Do_Something (Object : in out Root_Type; Data : in Boolean); -- (2) end Leaf;
with Leaf; procedure Sample is Obj : Leaf.Derived_Type; begin Leaf.Do_Something (Obj, 10); -- Calls (1). end Sample;
Assume the program intended (2) to override (1), but made a subtle declaration error. Because (1) and (2) are not homographs, the declaration of (2) is legal. However, (2) does not override (1), as intended. Therefore, the call in Sample calls the wrong routine. The resulting bug is very difficult to find, especially because the programmer will probably look at this call several times before even thinking that the wrong routine might be called. The bug is even harder to find when the call is dispatching, because the reason that the wrong routine is being called is not obvious. The problem has generated many "bug" reports to compiler writers, including ones from in their own development teams.
The problem also makes maintenance of object-oriented Ada 95 code much more difficult. Consider a maintenance change to the root class which adds a parameter to Do_Something. All extensions of Root_Type that override Do_Something will now silently overload it instead. The change probably will break all existing code, yet provide no warnings of the problem.
A rarer, but similar problem can occur when a routine accidentally overrides another. In this case, an inappropriate routine may be called via dispatching, and may cause the failure of an abstraction.
In both of these cases, the Ada compiler is being actively harmful to the programmer, violating the Ada design principles of least surprise.
The problem of accidental overloading rather than overriding can be minimized if the Ada compiler knows when the programmer wishes to override a routine. Similarly, accidental overriding can be minimized if the Ada compiler knows that the programmer has declared all intentional overriding.
Unfortunately, a complete solution to this problem with be incompatible with existing Ada 95 code. Therefore, we have to introduce an optional solution which applies only when the programmer asks for it.
Therefore, we introduce additional syntax and a pragma.
Replace paragraph 2 of section 6.1 by:
overriding_subprogram_declaration ::= subprogram_specification declare new;
subprogram_declaration ::= subprogram_specification; | overriding_subprogram_declaration
Add to 8.3 after paragraph 1:
The form of a pragma Explicit_Overriding is as follows:
pragma Explicit_Overriding (type_name);
Add to 8.3 after paragraph 26:
The type_name in a pragma Explicit_Overriding must name a type already declared in the same declarative part.
An explicit declaration of an overriding_subprogram_declaration is illegal if it does not override the implicit declaration of a primitive subprogram.
For a primitive subprogram inherited by a type to which a pragma Explicit_Overriding applies, an overriding explicit declaration shall be an overriding_subprogram_declaration.
We add the new syntax in such a way that all of the rules about subprogram_declarations need not be changed.
We looked at a pragma instead of a syntax change, but it runs into problems with overloading. The main program is that for a constructor, it is common to intentionally add an overloading of the constructor. If we have pragma Is_Overriding (Create); such a overloading for Create would be illegal. Using a non- overloading interpretation of the identifier would be different than for all other Ada pragmas which take subprogram identifiers. The alternative of using a "must follow" rule and no identifier in the pragma is also unpleasant, since no other language defined pragmas work this way. It also would make it easy for the pragma to get separated from the declaration during cut-and-paste operations, leading to various errors.


Questions? Ask the ACAA Technical Agent