Bug 21917 – Unused default values for IFTI parameters should not be typechecked against the IFTI-inferred type

Status
NEW
Severity
enhancement
Priority
P4
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2021-05-13T05:04:45Z
Last change time
2024-12-13T19:16:23Z
Assigned to
No Owner
Creator
Vladimir Panteleev
See also
https://issues.dlang.org/show_bug.cgi?id=24831
Moved to GitHub: dmd#19926 →

Comments

Comment #0 by dlang-bugzilla — 2021-05-13T05:04:45Z
This should work: ////////// test.d ///////// void fun(T)(T value = "hi") { } void main() { fun(); // OK fun("hello"); // OK fun(42); // Error } /////////////////////////// The reason for why it should work is that e.g. we can't pass a range as a `fun` argument. A workaround is to declare an overload, but that doesn't scale well with the number of parameters.
Comment #1 by dlang-bugzilla — 2021-05-13T05:59:22Z
Looks like there is code to do this when resolving overloads: https://github.com/dlang/dmd/blob/master/src/dmd/dtemplate.d#L1175-L1177 Indeed, the example above works if modified simply by adding an overload: void fun()(float a) {}
Comment #2 by dlang-bugzilla — 2021-05-13T06:00:55Z
(In reply to Vladimir Panteleev from comment #1) > Indeed, the example above works if modified simply by adding an overload: > > void fun()(float a) {} Oops, never mind that, the compiler just casts int to float.
Comment #3 by dkorpel — 2024-10-23T10:20:56Z
*** Issue 24828 has been marked as a duplicate of this issue. ***
Comment #4 by maxsamukha — 2024-10-23T10:48:09Z
Why is this marked as enhancement with a low priority? It's a fundumental that doesn't work.
Comment #5 by maxsamukha — 2024-10-23T10:48:46Z
(In reply to Max Samukha from comment #4) > Why is this marked as enhancement with a low priority? It's a fundumental > that doesn't work. *fundamental
Comment #6 by nick — 2024-10-23T11:07:02Z
> Looks like there is code to do this when resolving overloads: I think that's now in templatesem.d, matchWithInstance: // Shouldn't run semantic on default arguments and return type. foreach (ref param; *tf.parameterList.parameters) param.defaultArg = null;
Comment #7 by dkorpel — 2024-10-23T11:36:59Z
(In reply to Max Samukha from comment #4) > Why is this marked as enhancement with a low priority? It's a fundumental > that doesn't work. A bug would be if the behavior doesn't follow the spec. The spec says: > Default parameters are resolved and semantically checked in the context of the function declaration. After template substitution, this issue's function looks like this: ``` void fun(int value = "hi") ``` In the context of that function, the compiler is correctly issuing an error, so changing the behavior would be an enhancement. The lower priority could have been assigned because there's a workaround for it, I'm not sure. I wouldn't worry too much about it, issues are rarely sorted by bugzilla priority. The best way to get an issue fixed is to champion it, raise attention to it, or to work out the fix as detailed as possible so it's easy to implement. In this case, one fix would be to lazily evaluate default arguments at the call site instead of the function declaration site, but that would break semantics of existing code. Another fix would be to strip default arguments with semantic errors after template instantiation. That doesn't look like a breaking change: ``` void foo(T)(T x) {} void foo(T)(T x = 3) {} void main() { foo("a"); } ``` This gives an error "foo called with argument types `(string)` matches both ...", showing that default arguments are not considered for overload resolution.
Comment #8 by maxsamukha — 2024-10-23T14:01:06Z
(In reply to Dennis from comment #7) > > This gives an error "foo called with argument types `(string)` matches both > ...", showing that default arguments are not considered for overload > resolution. Thank you for the explanation! The current semantics makes sense to me now. The fix that strips default arguments doesn't seem the right way to go. What's the reason for this error: void foo(T)(T a = T.init); // Error: undefined identifier `T` void main() { foo(0); foo("x"); foo(); } ? It works with a default argument for the type parameter: void foo(T = int)(T a = T.init); // ok I'd be absolutely happy if this were fixed.
Comment #9 by maxsamukha — 2024-10-23T14:12:30Z
(In reply to Max Samukha from comment #8) > > What's the reason for this error: > See it now. Never mind. All seems good.
Comment #10 by maxsamukha — 2024-10-23T15:56:49Z
(In reply to Max Samukha from comment #9) > All seems good. Unfortunately, no. This compiles ok: void foo(T = int)(T a = T.init) { } void main() { foo(); foo("x"); } But if there's another template parameter, the compiler tries to reuse the previous instantiation and fails: void foo(U, T = int)(T a = T.init) { } void main() { foo!bool(0); foo!bool("x"); } Is this a bug?
Comment #11 by maxsamukha — 2024-10-23T15:58:29Z
(In reply to Max Samukha from comment #10) > void foo(U, T = int)(T a = T.init) > { > } > > void main() > { > foo!bool(0); > foo!bool("x"); > } > Error: function `foo` is not callable using argument types `(string)`
Comment #12 by robert.schadek — 2024-12-13T19:16:23Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/19926 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB