Bug 11900 – Implicit cast of string literal -> char* causing ambiguous call

Status
NEW
Severity
enhancement
Priority
P3
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2014-01-10T19:09:45Z
Last change time
2024-12-13T18:15:57Z
Assigned to
No Owner
Creator
Manu
Moved to GitHub: dmd#18755 →

Comments

Comment #0 by turkeyman — 2014-01-10T19:09:45Z
2 overloads exist: void func(const(char)* str); void func(const(char)[] str); Called with literal string: func("literal"); Complains; matches both, I don't think this is right... Calles with a 'string': string x = "not literal"; func(s); Matches the array version, as expected. I appreciate the convenience of the automatic string literal -> const(char)* cast. But in this case, surely it should just choose the array version of the function, like it does when calling with a 'string' variable? The convenience should be just that, a convenience, not a hard rule...?
Comment #1 by jakobovrum — 2014-01-10T22:33:06Z
(In reply to comment #0) > 2 overloads exist: > void func(const(char)* str); > void func(const(char)[] str); It seems like the domain of overloading more-so than string literal behaviour; I think it would require the addition of a special case rule to the overload resolution rule set. I could be wrong; maybe there are other cases where it is ambiguous (type inference? IFTI?). I tend to think that this overload set is bad interface design, so the motivation for the language change is questionable (but I'm not necessarily against it). Typically I see these overloads used for covering up a costly "dumb" `toStringz` conversion, which I think is really smelly design, but it may be that we have no appealing alternative. Maybe we should work on smartening up `toStringz` to automatically detect string literals and other guaranteed null-terminated allocations, or maybe we should add a std.typecons.CString type constructor so the user can guarantee null-termination manually. Anyway, just an observation, I'm not necessarily against the proposed amendment as long as it's not done in a knee-jerk fashion (such as silently adding a special case to DMD without updating the spec).
Comment #2 by turkeyman — 2014-01-10T22:59:14Z
(In reply to comment #1) > (In reply to comment #0) > > 2 overloads exist: > > void func(const(char)* str); > > void func(const(char)[] str); > > It seems like the domain of overloading more-so than string literal behaviour; > I think it would require the addition of a special case rule to the overload > resolution rule set. I could be wrong; maybe there are other cases where it is > ambiguous (type inference? IFTI?). > > I tend to think that this overload set is bad interface design, so the > motivation for the language change is questionable (but I'm not necessarily > against it). Typically I see these overloads used for covering up a costly > "dumb" `toStringz` conversion, which I think is really smelly design, but it > may be that we have no appealing alternative. Maybe we should work on > smartening up `toStringz` to automatically detect string literals and other > guaranteed null-terminated allocations, or maybe we should add a > std.typecons.CString type constructor so the user can guarantee > null-termination manually. > > Anyway, just an observation, I'm not necessarily against the proposed amendment > as long as it's not done in a knee-jerk fashion (such as silently adding a > special case to DMD without updating the spec). Well it's kinda like you say, this overload set is very common, if you have a C function, and you want to produce a D wrapper which receives a string and calls through using toStringz. Otherwise you find yourself typing toStringz all over the place, and it interferes with fp/delegates/generic code that deals with strings.
Comment #3 by jakobovrum — 2014-01-10T23:22:19Z
(In reply to comment #2) > Well it's kinda like you say, this overload set is very common, if you have a C > function, and you want to produce a D wrapper which receives a string and calls > through using toStringz. The ambiguity with string literal arguments probably means it's not overly common at this stage, but regardless, its popularity does not justify its use. We have no obligation to make concessions to enable bad code. > Otherwise you find yourself typing toStringz all over > the place, and it interferes with fp/delegates/generic code that deals with > strings. Yes, this is an unappealing alternative. I just think/hope it's not the only alternative.
Comment #4 by turkeyman — 2014-01-11T01:21:24Z
(In reply to comment #3) > (In reply to comment #2) > > Well it's kinda like you say, this overload set is very common, if you have a C > > function, and you want to produce a D wrapper which receives a string and calls > > through using toStringz. > > The ambiguity with string literal arguments probably means it's not overly > common at this stage, but regardless, its popularity does not justify its use. > We have no obligation to make concessions to enable bad code. How is it a concession? It seems to me like the concession was already made to make interacting with C functions easier. I'd say if anything, this is a bug that stems from that decision. There's nowhere else in D where a dynamic array can implicitly convert to a pointer... why does it happen ONLY in the case of a string literal?
Comment #5 by jakobovrum — 2014-01-11T01:34:43Z
(In reply to comment #4) > (In reply to comment #3) > > (In reply to comment #2) > > > Well it's kinda like you say, this overload set is very common, if you have a C > > > function, and you want to produce a D wrapper which receives a string and calls > > > through using toStringz. > > > > The ambiguity with string literal arguments probably means it's not overly > > common at this stage, but regardless, its popularity does not justify its use. > > We have no obligation to make concessions to enable bad code. > > How is it a concession? It seems to me like the concession was already made to > make interacting with C functions easier. I'd say if anything, this is a bug > that stems from that decision. It complicates overloading rules. > There's nowhere else in D where a dynamic array can implicitly convert to a > pointer... why does it happen ONLY in the case of a string literal? String literals are not dynamic arrays of a particular type. They are polysemous: they can be UTF-8, UTF-16 or UTF-32 strings; to wit, there is no place in the language where implicit conversion happens between dynamic arrays of different code unit element types, either.
Comment #6 by simen.kjaras — 2018-02-01T07:10:34Z
*** Issue 15529 has been marked as a duplicate of this issue. ***
Comment #7 by iamthewilsonator — 2019-05-26T08:21:53Z
One way to work around this is to declare an overload that takes a string (which the literals will prefer) that simple forwards to the const[] case.
Comment #8 by nick — 2023-07-14T12:24:56Z
The spec does say: > String literals can implicitly convert to any of the following types, *they have equal weight* https://dlang.org/spec/expression.html#string_literals So changing this to an enhancement.
Comment #9 by nick — 2023-07-14T12:33:46Z
*** Issue 18875 has been marked as a duplicate of this issue. ***
Comment #10 by robert.schadek — 2024-12-13T18:15:57Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/18755 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB