D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 2051 - interfaces should allow private methods
Summary: interfaces should allow private methods
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P2 normal
Assignee: No Owner
URL:
Keywords: accepts-invalid
: 6170 (view as issue list)
Depends on:
Blocks:
 
Reported: 2008-04-28 02:08 UTC by Andrei Alexandrescu
Modified: 2020-12-03 23:58 UTC (History)
4 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Andrei Alexandrescu 2008-04-28 02:08:43 UTC
Consider: 

interface Foo
{
    private void bar();
}

class Bar : Foo
{
}

void main()
{
    Foo bar = new Bar;
    bar.bar;
}

This code has a link-time error. Removing "private" yields (correctly) a compile-time error. So we have a bug already :o).

Adding a function void bar() {} to Bar keeps the link-time error in vigor, whether or not the function is private. 

Now, if we want D to allow Sutter's NVI idiom (http://www.gotw.ca/publications/mill18.htm) easily, it would need to enact the following rules:

* A private method in an interface is part of that interface's table of signatures.

* A class implementing a private method in an interface cannot graduate its visibility (e.g. protected or public).

With these rules in place, D would support NVI very naturally. I think that's a powerful paradigm that would lead to very expressive and robust interfaces.
Comment 1 Robert Fraser 2008-04-28 05:20:34 UTC
d-bugmail@puremagic.com wrote:
> Consider: 
> 
> interface Foo
> {
>     private void bar();
> }
> 
> class Bar : Foo
> {
> }
> 
> void main()
> {
>     Foo bar = new Bar;
>     bar.bar;
> }
> 
> This code has a link-time error. Removing "private" yields (correctly) a
> compile-time error. So we have a bug already :o).

The error occurs because there's no implementation anywhere, so the 
vtable can't be completed. I'm assuming you're suggesting that this 
should be turned into a runtime error if no implementation is present 
anywhere, but this would be so much harder to update stuff once an 
interface is updated. I can't see any advantages of making this error 
runtime.

Comment 2 Christian Kamm 2008-04-28 07:16:33 UTC
By the current D spec private functions are never virtual. I'm pretty sure that's why having a private function in an interface won't work.
Comment 3 Andrei Alexandrescu 2008-04-28 11:15:58 UTC
(In reply to comment #1)
> d-bugmail@puremagic.com wrote:
> > Consider: 
> > 
> > interface Foo
> > {
> >     private void bar();
> > }
> > 
> > class Bar : Foo
> > {
> > }
> > 
> > void main()
> > {
> >     Foo bar = new Bar;
> >     bar.bar;
> > }
> > 
> > This code has a link-time error. Removing "private" yields (correctly) a
> > compile-time error. So we have a bug already :o).
> 
> The error occurs because there's no implementation anywhere, so the 
> vtable can't be completed. I'm assuming you're suggesting that this 
> should be turned into a runtime error if no implementation is present 
> anywhere, but this would be so much harder to update stuff once an 
> interface is updated. I can't see any advantages of making this error 
> runtime.

The rest of my post clarifies my intent, which is not to make the error runtime.
Comment 4 Andrei Alexandrescu 2008-04-28 11:27:03 UTC
(In reply to comment #2)
> By the current D spec private functions are never virtual. I'm pretty sure
> that's why having a private function in an interface won't work.

That explains part of the odd behavior - the compiler has a conflict of interest of sorts. 

Now that I think of it, probably protected functions in an interface should be enough. Consider:

interface Foo
{
    protected void bar();
}

class Bar : Foo
{
    void bar() {}
}

void main()
{
    Foo bar = new Bar;
    bar.bar;
}

This goes through, and is probably enough to make NVI work. There is the minor annoyance that the class Bar can graduate visibility from protected to public, but if it wants to, no language rule can stop it (e.g. Bar could expose the method under a different name).

I will leave the bug opened because at a minimum the linker error should be really a compile-time error. Alternatively, private functions in interfaces could be allowed because they are technically final. Thanks all for your comments.
Comment 5 yebblies 2012-01-29 20:10:49 UTC
*** Issue 6170 has been marked as a duplicate of this issue. ***
Comment 6 yebblies 2012-01-29 20:13:29 UTC
This is intentional, as by D's compilation model the body of the function may be provided in another object file.  eg. When using .di files.

The original bug has been fixed by allowing final methods in interfaces.
Comment 7 Dlang Bot 2020-12-03 23:58:53 UTC
dlang/dub pull request #2052 "Fix #2051: Running unit tests from DUB single file packages fails" was merged into master:

- fd32d4d314c9052b0013aa867f24a2711c0554d0 by drug007:
  Fix #2051 "Running unittests from dub single file packages fails"
  
  Performing test command dub imports every source file as module to build the project excluding the main source file. But this excluding may fail and in this case dub try to import the main source file as module. Single file package building fails because the main source file does not belong to any import path. Now both the current file and the main source file paths are compared in relative form to prevent importing the main source file as module.

https://github.com/dlang/dub/pull/2052