D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 4647 - [tdpl] Cannot explicitly call final interface method, ambiguous calls allowed
Summary: [tdpl] Cannot explicitly call final interface method, ambiguous calls allowed
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: Other All
: P2 major
Assignee: No Owner
URL:
Keywords: diagnostic, patch, rejects-valid
: 3759 6680 (view as issue list)
Depends on:
Blocks:
 
Reported: 2010-08-15 10:32 UTC by Andrej Mitrovic
Modified: 2012-01-30 18:34 UTC (History)
5 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Andrej Mitrovic 2010-08-15 10:32:38 UTC
Code on 2.048:

import std.stdio;

interface Timer
{
    final void run() { writeln("Timer.run()"); };
}

interface Application
{
    final void run() { writeln("Application.run()"); };
}

class TimedApp : Timer, Application
{
}

import std.stdio;

void main()
{
    auto app = new TimedApp;
    app.Timer.run();            // error, no Timer property
    app.Application.run();      // error, no Application property
    app.run();                  // This would call Timer.run() if the two calls
                                // above were commented out
}

The comments state what happens.

Note that if I changed the order of the TimedApp signature like so:

class TimedApp : Application, Timer

then the Application's run() method would be called instead of Timer's in the app.run() call.
Comment 1 Andrej Mitrovic 2010-08-15 12:04:34 UTC
Comment from Lukasz Wrzosek
>This:
>     app.Timer.run();            // error, no Timer property
>     app.Application.run();      // error, no Application property
>
>probably should be:
>    (cast(Timer)app).run();
>    (cast(Application)app).run();
>
>But app.run() is still ambiguous - should not compile.

I don't see why I would need a cast. I can explicitly call methods from inherited classes, like so:

import std.stdio;

class Base
{
    void test() { writeln("Base.test()"); };
}

class Derived : Base
{
    override void test() { writeln("Derived.test()");}
}

class SecondDerived : Derived
{
}

void main()
{
    auto var = new SecondDerived;
    var.Base.test();      // calls Base.test()
    var.Derived.test();   // calls Derived.test()
}

So why shouldn't I be able to do the same with interfaces? TDPL allows it, I think it should be allowed in DMD.
Comment 2 Lars T. Kyllingstad 2010-08-16 00:05:38 UTC
I don't have TDPL in front of me right now, but I, too, seem to remember that this should be allowed.  Raising the priority of this.
Comment 3 Kasumi Hanazuki 2011-10-25 12:38:15 UTC
*** Issue 6680 has been marked as a duplicate of this issue. ***
Comment 4 Kenji Hara 2011-12-24 02:18:52 UTC
Patch for app.Timer.run() / app.Application.run():
https://github.com/D-Programming-Language/dmd/pull/578

----

(In reply to comment #0)
> Note that if I changed the order of the TimedApp signature like so:
> 
> class TimedApp : Application, Timer
> 
> then the Application's run() method would be called instead of Timer's in the
> app.run() call.

I think the behavior is correct, because name lookup is depth-first.
Then app.run() depends on the order of derived bases.
Comment 6 yebblies 2012-01-30 18:34:12 UTC
*** Issue 3759 has been marked as a duplicate of this issue. ***