D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 4576 - [tdpl] 0/1 argument calls to overloaded function is allowed in presence of variadic function
Summary: [tdpl] 0/1 argument calls to overloaded function is allowed in presence of va...
Status: RESOLVED INVALID
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: Other All
: P2 normal
Assignee: No Owner
URL:
Keywords: accepts-invalid, TDPL
Depends on:
Blocks:
 
Reported: 2010-08-03 12:27 UTC by Andrej Mitrovic
Modified: 2022-08-15 12:20 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-03 12:27:15 UTC
According to TDPL, this should be an ambiguous call and issue a compiler error:

import std.algorithm, std.array, std.stdio;          

@property bool empty(T)(T[] a) { return a.length == 0; }
@property ref T front(T)(T[] a) { return a[0]; }
void popFront(T)(ref T[] a) { a = a[1 .. $]; }

V reduce(alias fun, V, R)(V x, R range)
{
    for ( ; !range.empty; range.popFront()) {
        x = fun(x, range.front);
    }
    return x;
}

double average() { return 2.0; }
double average(double) { return 3.0; }

// compute the avg of a set of numbers, passable directly or via an array
double average(double[] values...)
{
    if (values.empty)
    {
        throw new Exception("Average of zero elements is undefined");
    }
    return reduce!((a, b) { return a + b; })(0.0, values) / values.length;
}

unittest {
    average();  // This should not compile, but does
    
    writeln(average());  // calls average(), returns 2.0
    writeln(average(0)); // calls average(double), returns 3.0
    
    assert(average(0) == 0);  // fails, since it calls average() which returns 2.0
    assert(average(1, 2) == 1.5);
    assert(average(1, 2, 3) == 2);
    
    // passing arrays and slices works too
    double[] v = [1, 2, 3];
    assert(average(v) == 2);
}

void main() { }
Comment 1 Andrej Mitrovic 2010-08-03 12:29:27 UTC
Sorry for the mixed comments between TDPL and the ones I've added. The average(); call should issue a compiler error. And a 1-argument call average(0) should issue an error as well.
Comment 2 nfxjfg 2010-08-03 12:42:42 UTC
Keywords go into keyword field.
Comment 3 Andrej Mitrovic 2010-08-03 12:54:15 UTC
(In reply to comment #2)
> Keywords go into keyword field.

Ah, thanks!
Comment 4 Andrej Mitrovic 2013-09-17 12:48:04 UTC
Reduced test-case:

-----
void test(int[] arr...) { assert(1); }
void test() { assert(0); }  // hijacks (shadows) above function

void main()
{
    test();  // should fail at CT, not RT.
}
-----

Comment out the second function and the first one will be called. The `test()` call should be ambiguous and issue a compile-time error.
Comment 5 RazvanN 2022-08-15 12:20:28 UTC
(In reply to Andrej Mitrovic from comment #4)
> Reduced test-case:
> 
> -----
> void test(int[] arr...) { assert(1); }
> void test() { assert(0); }  // hijacks (shadows) above function
> 
> void main()
> {
>     test();  // should fail at CT, not RT.
> }
> -----
> 
> Comment out the second function and the first one will be called. The
> `test()` call should be ambiguous and issue a compile-time error.

The compiler sees that both functions match, however, the non-variadic one is more specialized and the variadic one. This is all described very well in the spec [1]. More specifically, point 5 in the section that I linked.

Closing as invalid.

[1] https://dlang.org/spec/function.html#function-overloading