Bug 1536 – Literal '0' is improperly used to deduce an implicit template parameter
Status
RESOLVED
Resolution
WONTFIX
Severity
enhancement
Priority
P2
Component
dmd
Product
D
Version
D1 (retired)
Platform
All
OS
All
Creation time
2007-09-28T13:09:44Z
Last change time
2019-08-21T11:11:06Z
Assigned to
No Owner
Creator
Russ Lewis
Comments
Comment #0 by webmaster — 2007-09-28T13:09:44Z
EXAMPLE CODE
void delegate() CurryAll(A...)(void delegate(A) dg, A args)
{
return null; // dummy function
}
struct S
{
void foo()
{
uint u = 0;
int i = 0;
// these work
auto a = CurryAll (&this.baz, 0);
auto b = CurryAll!(uint)(&this.bar, 0);
auto c = CurryAll (&this.bar, u);
auto d = CurryAll (&this.baz, i);
auto e = CurryAll!(uint)(&this.bar, i);
auto f = CurryAll!( int)(&this.baz, u);
// these don't
auto z = CurryAll (&this.bar, 0);
}
void bar(uint u) { return; }
void baz( int i) { return; }
}
DMD OUTPUT
implicit_instantiation_and_implicit_cast.d(21): function implicit_instantiation_and_implicit_cast.CurryAll!(int).CurryAll (void delegate(int i),(int _param_1)) does not match parameter types (void delegate((uint _param_1)),int)
implicit_instantiation_and_implicit_cast.d(21): Error: cannot implicitly convert expression (&(*this).bar) of type void delegate((uint _param_1)) to void delegate(int i)
ANALYSIS
It appears that when DMD encounters the literal '0', it is jumping to the conclusion that that literal '0' *must* be of type int, even though it could be other types (uint, real, etc.). In the case of the example z from above, this is bad because the delegate argument quite clearly requires that the template be deduced to have parameter uint.
Comment #1 by regan — 2007-09-28T13:17:39Z
A decimal literal within the range of 0 .. 2_147_483_647 is assumed to be of type int, it's in the docs:
http://www.digitalmars.com/d/lex.html#integerliteral
"The type of the integer is resolved as follows:
Decimal Literal Type
0 .. 2_147_483_647 int
2_147_483_648 .. 9_223_372_036_854_775_807L long
Decimal Literal, L Suffix Type
0L .. 9_223_372_036_854_775_807L long
Decimal Literal, U Suffix Type
0U .. 4_294_967_296U uint
4_294_967_296U .. 18_446_744_073_709_551_615UL ulong
Decimal Literal, UL Suffix Type
0UL .. 18_446_744_073_709_551_615UL ulong
"
Comment #2 by webmaster — 2007-09-28T13:25:42Z
Seems that I was wrong about what is written in the spec; I thought that the type of literal was considered ambiguous until it was forced, by context, to be something (such as assigning it to a variable, or passing it as a parameter).
So, let's make this bug more of a question about the language itself: Perhaps we need to change integer literals to have their type inferred from context, just like string literals. IMHO, the code below looks pretty simple and seems like it *ought* to work. Is there a technical reason (other than just "it is easier") why integer literals *shouldn't* be polysemous?
Comment #3 by clugdbug — 2012-09-26T01:04:53Z
This example is unnecessarily complicated.
void CurryAll(A)(A x, A y)
{ }
void foo()
{
uint u = 0;
CurryAll(u, 0);
}
Comment #4 by razvan.nitu1305 — 2019-08-21T11:11:06Z
In the initial bug report there is an easy workaround: simply use `0u` and it will work; easy and obvious.
Closing as invalid.