www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 19096] New: [REG 2.061] Proper error messages are not shown

https://issues.dlang.org/show_bug.cgi?id=19096

          Issue ID: 19096
           Summary: [REG 2.061] Proper error messages are not shown for
                    templates that go beyond two deep, wrongly says no
                    template overload matches
           Product: D
           Version: D2
          Hardware: All
                OS: All
            Status: NEW
          Severity: regression
          Priority: P1
         Component: dmd
          Assignee: nobody puremagic.com
          Reporter: dbugz joakim.fea.st

I ran into this when refactoring std.conv.parse in Phobos and mistakenly had a
variable shadowing another. Suddenly, ldc started telling me that none of the
11 overloads matched anymore, with no clue what I'd done wrong. I resorted to
cutting and pasting the parse() function into a test file and removing all
template arguments and constraints, after which the compiler pointed out the
shadowed variable.

I reduced that down to this code that shows the ins and outs:

```
import std.range.primitives, std.traits;

Target parse(Target, Source)(ref Source source)
    if (isInputRange!Source && isSomeChar!(ElementType!Source) && !is(Source ==
enum) &&
        isFloatingPoint!Target && !is(Target == enum))
{
    bool anydigits = false;
    version(broken)
    {
        if ( anydigits )
        {
            bool anydigits = true;
        }
    }
    return 3.14;
}

template isExactSomeString(T)
{
    enum isExactSomeString = isSomeString!T && !is(T == enum);
}

private T toImpl(T, S)(S value)
if (isInputRange!S && isSomeChar!(ElementEncodingType!S) &&
    !isExactSomeString!T && is(typeof(parse!T(value))))
{
    bool anydigits = false;
    version(proper)
    {
        if ( anydigits )
        {
            bool anydigits = true;
        }
    }
    return parse!T(value);
}

void main()
{
    string foo = "3.14";
    version(correct) parse!real(foo);
    else toImpl!real(foo);
}
```

Ignoring all the version statements, this compiles fine with no shadowed
variables with dmd 2.081.1 for linux/x64. If there's a shadowed variable in the
toImpl() template called from main, enabled with `dmd -version=proper
shadow.d`, I get this useful error message:

frontend.d(32): Error: variable anydigits is shadowing variable
frontend.toImpl!(real, string).toImpl.anydigits
frontend.d(42): Error: template instance `frontend.toImpl!(real, string)` error
instantiating

However, if the shadowing problem goes two templates deep, enabled with `dmd
-version=broken shadow.d`, I get this weird error, it claims no overloads match
anymore:

frontend.d(42): Error: template frontend.toImpl cannot deduce function from
argument types !(real)(string), candidates are:
frontend.d(23):        frontend.toImpl(T, S)(S value) if (isInputRange!S &&
isSomeChar!(ElementEncodingType!S) && !isExactSomeString!T &&
is(typeof(parse!T(value))))

If I call that broken parse() template directly, enabled with `dmd
-version=correct -version=broken shadow.d`, now I get a useful error again:

frontend.d(12): Error: variable anydigits is shadowing variable
frontend.parse!(real, string).parse.anydigits
frontend.d(41): Error: template instance `frontend.parse!(real, string)` error
instantiating

This demonstrates how the frontend is throwing away the right error messages
once templates start getting nested, which can be seen in the similar bug 9179
and bug 13340 also.

run.dlang.io says this actually used to work up till dmd 2.061:

https://run.dlang.io/is/DpqFeg

Working with templates gets very annoying if it starts to gag these error
messages. I'm not sure why it would do this: are there actually template
overloads where multiple functions might work, so it just chooses the one that
compiles? In this case, I think only one overload should match, so I want the
error message for that one.

--
Jul 18 2018