cmd/internal/gc: improve "type *X has no field or method M" message · golang/go@d4bb72b (original) (raw)
`@@ -915,11 +915,26 @@ OpSwitch:
`
915
915
`return
`
916
916
` }
`
917
917
``
918
``
`-
if !lookdot(n, t, 0) {
`
919
``
`-
if lookdot(n, t, 1) {
`
``
918
`+
if lookdot(n, t, 0) == nil {
`
``
919
`+
// Legitimate field or method lookup failed, try to explain the error
`
``
920
`+
switch {
`
``
921
`+
case isnilinter(t):
`
``
922
`+
Yyerror("%v undefined (type %v is interface with no methods)", n, n.Left.Type)
`
``
923
+
``
924
`+
case Isptr[t.Etype] && Isinter(t.Type):
`
``
925
`+
// Pointer to interface is almost always a mistake.
`
``
926
`+
Yyerror("%v undefined (type %v is pointer to interface, not interface)", n, n.Left.Type)
`
``
927
+
``
928
`+
case lookdot(n, t, 1) != nil:
`
``
929
`+
// Field or method matches by name, but it is not exported.
`
920
930
`Yyerror("%v undefined (cannot refer to unexported field or method %v)", n, n.Right.Sym)
`
921
``
`-
} else {
`
922
``
`-
Yyerror("%v undefined (type %v has no field or method %v)", n, n.Left.Type, n.Right.Sym)
`
``
931
+
``
932
`+
default:
`
``
933
`+
if mt := lookdot(n, t, 2); mt != nil { // Case-insensitive lookup.
`
``
934
`+
Yyerror("%v undefined (type %v has no field or method %v, but does have %v)", n, n.Left.Type, n.Right.Sym, mt.Sym)
`
``
935
`+
} else {
`
``
936
`+
Yyerror("%v undefined (type %v has no field or method %v)", n, n.Left.Type, n.Right.Sym)
`
``
937
`+
}
`
923
938
` }
`
924
939
`n.Type = nil
`
925
940
`return
`
`@@ -2391,6 +2406,9 @@ func lookdot1(errnode *Node, s *Sym, t *Type, f *Type, dostrcmp int) *Type {
`
2391
2406
`if dostrcmp != 0 && f.Sym.Name == s.Name {
`
2392
2407
`return f
`
2393
2408
` }
`
``
2409
`+
if dostrcmp == 2 && strings.EqualFold(f.Sym.Name, s.Name) {
`
``
2410
`+
return f
`
``
2411
`+
}
`
2394
2412
`if f.Sym != s {
`
2395
2413
`continue
`
2396
2414
` }
`
`@@ -2461,7 +2479,7 @@ func derefall(t *Type) *Type {
`
2461
2479
`return t
`
2462
2480
`}
`
2463
2481
``
2464
``
`-
func lookdot(n *Node, t *Type, dostrcmp int) bool {
`
``
2482
`+
func lookdot(n *Node, t *Type, dostrcmp int) *Type {
`
2465
2483
`s := n.Right.Sym
`
2466
2484
``
2467
2485
`dowidth(t)
`
`@@ -2481,6 +2499,10 @@ func lookdot(n *Node, t *Type, dostrcmp int) bool {
`
2481
2499
` }
`
2482
2500
``
2483
2501
`if f1 != nil {
`
``
2502
`+
if dostrcmp > 1 {
`
``
2503
`+
// Already in the process of diagnosing an error.
`
``
2504
`+
return f1
`
``
2505
`+
}
`
2484
2506
`if f2 != nil {
`
2485
2507
`Yyerror("%v is both field and method", n.Right.Sym)
`
2486
2508
` }
`
`@@ -2500,10 +2522,14 @@ func lookdot(n *Node, t *Type, dostrcmp int) bool {
`
2500
2522
`n.Op = ODOTINTER
`
2501
2523
` }
`
2502
2524
``
2503
``
`-
return true
`
``
2525
`+
return f1
`
2504
2526
` }
`
2505
2527
``
2506
2528
`if f2 != nil {
`
``
2529
`+
if dostrcmp > 1 {
`
``
2530
`+
// Already in the process of diagnosing an error.
`
``
2531
`+
return f2
`
``
2532
`+
}
`
2507
2533
`tt := n.Left.Type
`
2508
2534
`dowidth(tt)
`
2509
2535
`rcvr := getthisx(f2.Type).Type.Type
`
`@@ -2543,7 +2569,7 @@ func lookdot(n *Node, t *Type, dostrcmp int) bool {
`
2543
2569
`// It is invalid to automatically dereference a named pointer type when selecting a method.
`
2544
2570
`// Make n->left == ll to clarify error message.
`
2545
2571
`n.Left = ll
`
2546
``
`-
return false
`
``
2572
`+
return nil
`
2547
2573
` }
`
2548
2574
` }
`
2549
2575
``
`@@ -2554,10 +2580,10 @@ func lookdot(n *Node, t *Type, dostrcmp int) bool {
`
2554
2580
`// print("lookdot found [%p] %T\n", f2->type, f2->type);
`
2555
2581
`n.Op = ODOTMETH
`
2556
2582
``
2557
``
`-
return true
`
``
2583
`+
return f2
`
2558
2584
` }
`
2559
2585
``
2560
``
`-
return false
`
``
2586
`+
return nil
`
2561
2587
`}
`
2562
2588
``
2563
2589
`func nokeys(l *NodeList) bool {
`