Issue 21321 - Unimplemented interface method from abstract base class not detected
Summary: Unimplemented interface method from abstract base class not detected
Status: NEW
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P1 regression
Assignee: No Owner
URL:
Keywords: pull
: 22869 23653 (view as issue list)
Depends on:
Blocks:
 
Reported: 2020-10-17 11:25 UTC by Simon Naarmann
Modified: 2023-09-04 08:09 UTC (History)
6 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Simon Naarmann 2020-10-17 11:25:25 UTC
DMD 2.094.0 on 64-bit Linux.

    interface I {
        int f();
    }

    abstract class A : I {
    }

    class B : A {
    }

    void main()
    {
        I i = new B();
        i.f();
    }

This program compiles, links, and then segfaults at runtime once i.f() is called. The call to i.f() is necessary to trigger the segfault.

Expected instead: This program fails to compile.

The compiler should recognize class B as wrongly implemented because B doesn't implement int f(). This definition of class B shouldn't compile. (Or, if you disagree whether the definition of class B should compile, then, at the very least, the compiler should recognize B as abstract and the line "I i = new B();" should error. But I encourage that this empty definition of B itself be an error.)

The impact of this bug is that programs will compile even though their types do not satisfy their interfaces. This breaks a basic promise of the type system: We shouldn't have to call all possible methods in all possible derived classes at runtime merely to find what we should implement.

Workaround: Write "class B : A, I" instead of "class B : A", then we get the correct compiler error already for the definition of the class, even when we delete all code in main().

Related but different bug: "Unimplemented methods of interface are not reported as errors during compilation."
https://issues.dlang.org/show_bug.cgi?id=21184
In that bug, the program compiles, but fails to link.
Comment 1 Simon Naarmann 2021-05-01 21:19:15 UTC
With DMD 2.096.0, the bug still manifests when generating both x86 and x64, both on Linux and on Windows 7.
Comment 2 moonlightsentinel 2021-05-01 23:13:02 UTC
Will probably be fixed by https://github.com/dlang/dmd/pull/12232
Comment 3 Adam D. Ruppe 2021-05-09 02:24:24 UTC
I just hit this again too.

---
interface A {
        void foo();
}

abstract class B(CRTP) : A { }

class C : B!C {}

void main() {
        auto c = new C;
        c.foo();
}
---

Appears to be introduced recently:

2.079.1 to 2.092.1: Failure with output:
-----
onlineapp.d(7): Error: class `onlineapp.C` interface function `void foo()` is not implemented
onlineapp.d(7): Error: class `onlineapp.C` interface function `void foo()` is not implemented
-----

Since      2.093.1: Failure with output: Error: program killed by signal 11



As such I'm upping the severity of this to regression.
Comment 4 moonlightsentinel 2021-05-09 19:49:11 UTC
(In reply to Adam D. Ruppe from comment #3)
> As such I'm upping the severity of this to regression.

Regression introduced by https://github.com/dlang/dmd/pull/11191
(wow)
Comment 5 moonlightsentinel 2022-03-11 15:05:17 UTC
*** Issue 22869 has been marked as a duplicate of this issue. ***
Comment 6 Adam D. Ruppe 2022-11-13 19:10:22 UTC
And I hit it AGAIN today because in the interface, I wrote the wrong return type and used the right type in the class. The compiler SHOULD have said "original one not implemented" and drew my attention to it. Instead, it just randomly crashed with a null vtable entry.
Comment 7 Nick Treleaven 2023-01-29 09:46:21 UTC
*** Issue 23653 has been marked as a duplicate of this issue. ***
Comment 8 Dlang Bot 2023-02-02 18:38:05 UTC
@ntrel updated dlang/dmd pull request #14853 "Fix 2525: check all parent interfaces for overriden methods" fixing this issue:

- Fix Issue 21321 - Unimplemented interface method from abstract base class
  
  Add test case.
  Note: unimplemented abstract method not detected.

https://github.com/dlang/dmd/pull/14853