D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 2999 - Return-type overloading should be error
Summary: Return-type overloading should be error
Status: RESOLVED WORKSFORME
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
: 12454 (view as issue list)
Depends on: 1003
Blocks:
  Show dependency treegraph
 
Reported: 2009-05-17 06:12 UTC by Shin Fujishiro
Modified: 2019-09-10 09:11 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 Shin Fujishiro 2009-05-17 06:12:49 UTC
This code compiles without error:
--------------------
short foo() { return 1; }
int   foo() { return 2; }
--------------------
Yes, the above example is not so serious because if you try to use foo, the compiler will spit an error.

But it will be serious when function overriding is involved:
--------------------
interface I { short foo(); }
interface J { int   foo(); }
class C : I, J
{
    override short foo() { return 1; }
    override int   foo() { return 2; }
}
void main()
{
    I i = new C;
    J j = new C;
    writeln(i.foo);
    writeln(j.foo);
}
--------------------
The compiler silently accepts this code. And the result is:
--------------------
1
10289153
--------------------
Note that the lower 16-bit of 10289153 is 1. Thus, the short foo() is invoked.

If the declaration order of C.foo is reversed, the result becomes
--------------------
2
2
--------------------
In this case, int foo() is invoked.
Comment 1 Andrej Mitrovic 2012-01-21 18:03:49 UTC
The compiler doesn't accept this code anymore in 2.057, marking as fixed.
Comment 2 Andrej Mitrovic 2014-03-24 14:34:11 UTC
(In reply to comment #1)
> The compiler doesn't accept this code anymore in 2.057, marking as fixed.

I must have tested the second snippet but not the first, as the first still compiles:

-----
short foo() { return 1; }
int   foo() { return 2; }
-----
Comment 3 Andrej Mitrovic 2014-03-24 14:34:24 UTC
*** Issue 12454 has been marked as a duplicate of this issue. ***
Comment 4 hsteoh 2014-07-15 04:47:17 UTC
Wow this one is pretty funny:
-----
short foo() { return 1; }
int foo() { return 2; }
void main() {
	short s = foo();
	int i = foo();

	import std.stdio;
	writeln(s);
	writeln(i);
}
-----

Compiler output:
-----
test.d(4): Error: test.foo called with argument types () matches both:
test.d(1):     test.foo()
and:
test.d(2):     test.foo()
test.d(5): Error: test.foo called with argument types () matches both:
test.d(1):     test.foo()
and:
test.d(2):     test.foo()
-----

That's hilarious, since there's no way you can actually disambiguate between them! (Not that I know of, anyway.)
Comment 5 RazvanN 2019-09-10 09:11:19 UTC
Running the second examples now yields:

1
2

This is the expected behavior.

The first example still compiles. I assume that this is necessary in order to facilitate the compilation of the second example (for consistency reasons).
In D, you have to implement both foo methods, so you must have the ability of overloading based on return type. Note that instantiating a C and calling foo will output an error.

C c = new C;
writeln(c.foo());    // foo called with arguments () matches both definitions

Closing as WORKSFORME.