And subsequently using This_C for all calls. At first I thought it was just a kink on an inexperienced Ada developer and used This instead. That worked just as fine. But then I came across this one:
src/adacl-sar-filter.adb|44 col 14 error| call to abstract procedure must be dispatching
with line 44 looking like this:
This.Filter_Line (Element);
Changing to one of the following and it works again:
Now I wonder if my younger self knew something I have forgotten and should indeed use This_C aka Object'Class (This) all the time to make sure calls are dispatching.
Redispatch is arguably always a type error because the specific type has been established by the prior dispatch, so you must call primitive operations of exactly that type.
(One of the major advantages of Ada’s OO model over C++'s one is that you must explicitly force redispatch in Ada when C++ does that by default except for constructors and destructors. There type violation is so apparent, that they must make a special exemption for them!)
In your specific case you seem to call an abstract primitive operation from a non-abstract one. Consider making the second primitive operation a class-wide subprogram. The rationale: since its implementation dispatches, it has the same body for all derived types = acts on the whole class = class-wide.
Also note that GNAT does seem to get confused sometimes depending on how the actual type for Thing gets declared. For example, completing a public extension of an synchronized interface with a protected type or task can sometimes generate that error when calling a function for the interface. I don’t know for sure if it is a GNAT bug or a bug in the RM (see here and here for some discourse I had on this exact error years ago).
package Example is
type An_Interface is synchronized interface;
procedure P1 (Self : in out An_Interface) is abstract;
type Instance is synchronized new An_Interface with private;
overriding procedure P1 (Self : in out Instance);
private
-- Instance full view is a protected type
protected type Instance is new An_Interface with
-- overriding procedure P1; -- Already overridden in the public view
private
end Instance;
end Example;
package body Example is
protected body Instance is
procedure P1 is
begin
Put_Line ("Did Something");
end P1;
end Instance;
end Example;
or like this:
package Example is
type An_Interface is synchronized interface;
procedure P1 (Self : in out An_Interface) is abstract;
type Instance is synchronized new An_Interface with private;
private
-- Instance full view is a protected type
protected type Instance is new An_Interface with
overriding procedure P1; -- Private overriding is legal
private
end Instance;
end Example;
package body Example is
protected body Instance is
procedure P1 is
begin
Put_Line ("Did Something");
end P1;
end Instance;
end Example;
And v.p1 must compile regardless because the type of v is not abstract.
It can also be argued that it is not a type error, but exactly in accord with how the programmer designed the program. YMMV. (Dmitry and I have had this discussion several times… :-))