Bug 8894 – 2.059: Lookup error message has become uninformative
Status
RESOLVED
Resolution
FIXED
Severity
regression
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2012-10-25T16:11:00Z
Last change time
2012-12-10T18:10:12Z
Keywords
diagnostic, pull
Assigned to
nobody
Creator
andrej.mitrovich
Comments
Comment #0 by andrej.mitrovich — 2012-10-25T16:11:17Z
module test;
struct Foo { }
void main()
{
Foo f;
auto x = f.x;
}
2.058:
$ dmd test.d
test.d(6): Error: no property 'x' for type 'Foo'
2.059:
$dmd test.d
test.d(6): Error: undefined identifier 'x'
Best guess: it's probably related to UFCS changes in 2.059.
Comment #1 by andrej.mitrovich — 2012-10-25T16:17:19Z
(In reply to comment #0)
> module test;
> struct Foo { }
>
> void main()
> {
> Foo f;
> auto x = f.x;
> }
>
> 2.058:
> $ dmd test.d
> test.d(6): Error: no property 'x' for type 'Foo'
>
> 2.059:
> $dmd test.d
> test.d(6): Error: undefined identifier 'x'
>
> Best guess: it's probably related to UFCS changes in 2.059.
It seems errors are gagged at this point in "Expression *Type::getProperty(Loc loc, Identifier *ident)" in file mtype.c:
if (this != Type::terror)
{
assert(global.gag); // << passes
if (s)
error(loc, "no property '%s' for type '%s', did you mean '%s'?", ident->toChars(), toChars(), s->toChars());
else
error(loc, "no property '%s' for type '%s'", ident->toChars(), toChars());
}
Comment #2 by andrej.mitrovich — 2012-10-25T16:24:25Z
(In reply to comment #1)
> It seems errors are gagged at this point in "Expression *Type::getProperty(Loc
> loc, Identifier *ident)" in file mtype.c:
The gagging starts in `DotIdExp::semantic(Scope *sc, int flag)` with a nice comment:
/* This would be much better if we added a "hasProperty" method to types,
* i.e. the gagging is a bad way.
*/
// ..
Type *t1 = e1->type;
unsigned errors = global.startGagging();
e = t1->dotExp(sc, e1, ident);
if (global.endGagging(errors)) // if failed to find the property
{
e1->type = t1; // kludge to restore type
e = resolveUFCSProperties(sc, this);
}
e = e->semantic(sc);
return e;
So it seems UFCS really is to blame. Type properties are checked first, then UFCS is checked, however if neither of them have a match then we should print out the property error rather than the UFCS error.
Comment #3 by andrej.mitrovich — 2012-10-26T12:35:01Z
I've been thinking.. maybe we could change the verrorPrint function to print to a buffer by default, and then print that to stdout/stderr from the caller function when gagging is off, but store the error to the global struct if gagging is on. That way we can recover the previous error messages if resolving UFCS failed.
Comment #4 by andrej.mitrovich — 2012-10-26T12:39:14Z
(In reply to comment #3)
> I've been thinking.. maybe we could change the verrorPrint function to print to
> a buffer by default, and then print that to stdout/stderr from the caller
> function when gagging is off, but store the error to the global struct if
> gagging is on. That way we can recover the previous error messages if resolving
> UFCS failed.
Essentially the code would then look something like this:
Type *t1 = e1->type;
unsigned errors = global.startGagging();
e = t1->dotExp(sc, e1, ident);
OutBuffer oldErrors; // new
if (global.endGagging(errors, &oldErrors)) // new
{
e1->type = t1; // kludge to restore type
errors = global.startGagging(); // new
e = resolveUFCSProperties(sc, this);
if(global.endGagging(errors)) // new
printErrors(&oldErrors); // new
}
e = e->semantic(sc);
return e;
"&oldErrors" would be an optional parameter where current errors are stored, as the old errors would be cleared on the call to endGagging.
Comment #5 by clugdbug — 2012-11-09T03:08:43Z
Easy way would be, if errors aren't gagged (so that we care about which error message occurs), to gag the UFCS attempt, and if it fails, make the property call again.