Skip to content

Commit fa4df65

Browse files
committed
go/types, types2: avoid field/method lookup error on invalid types
Fixes #49541. Change-Id: I27a52d0722a7408758682e7ddcd608c0a6c4881b Reviewed-on: https://go-review.googlesource.com/c/go/+/378175 Trust: Robert Griesemer <[email protected]> Reviewed-by: Robert Findley <[email protected]>
1 parent 626f13d commit fa4df65

File tree

8 files changed

+108
-4
lines changed

8 files changed

+108
-4
lines changed

src/cmd/compile/internal/types2/call.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,11 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr) {
531531

532532
obj, index, indirect = LookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, sel)
533533
if obj == nil {
534+
// Don't report another error if the underlying type was invalid (issue #49541).
535+
if under(x.typ) == Typ[Invalid] {
536+
goto Error
537+
}
538+
534539
if index != nil {
535540
// TODO(gri) should provide actual type where the conflict happens
536541
check.errorf(e.Sel, "ambiguous selector %s.%s", x.expr, sel)

src/cmd/compile/internal/types2/instantiate.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,10 @@ func (check *Checker) implements(V, T Type, qf Qualifier) error {
161161
Vu := under(V)
162162
Tu := under(T)
163163
if Vu == Typ[Invalid] || Tu == Typ[Invalid] {
164-
return nil
164+
return nil // avoid follow-on errors
165+
}
166+
if p, _ := Vu.(*Pointer); p != nil && under(p.base) == Typ[Invalid] {
167+
return nil // avoid follow-on errors (see issue #49541 for an example)
165168
}
166169

167170
errorf := func(format string, args ...interface{}) error {
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Copyright 2022 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package p
6+
7+
type S[A, B any] struct {
8+
f int
9+
}
10+
11+
func (S[A, B]) m() {}
12+
13+
// TODO(gri) We should only report one error below. See issue #50588.
14+
15+
func _[A any](s S /* ERROR cannot infer B */ /* ERROR got 1 arguments but 2 type parameters */ [A]) {
16+
// we should see no follow-on errors below
17+
s.f = 1
18+
s.m()
19+
}
20+
21+
// another test case from the issue
22+
23+
func _() {
24+
X(Interface[*F /* ERROR cannot infer B */ /* ERROR got 1 arguments but 2 type parameters */ [string]](Impl{}))
25+
}
26+
27+
func X[Q Qer](fs Interface[Q]) {
28+
}
29+
30+
type Impl struct{}
31+
32+
func (Impl) M() {}
33+
34+
type Interface[Q Qer] interface {
35+
M()
36+
}
37+
38+
type Qer interface {
39+
Q()
40+
}
41+
42+
type F[A, B any] struct{}
43+
44+
func (f *F[A, B]) Q() {}

src/cmd/compile/internal/types2/typeset.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ func (s *_TypeSet) is(f func(*term) bool) bool {
135135

136136
// underIs calls f with the underlying types of the specific type terms
137137
// of s and reports whether all calls to f returned true. If there are
138-
// no specific terms, is returns the result of f(nil).
138+
// no specific terms, underIs returns the result of f(nil).
139139
func (s *_TypeSet) underIs(f func(Type) bool) bool {
140140
if !s.hasTerms() {
141141
return f(nil)

src/go/types/call.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,11 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) {
533533

534534
obj, index, indirect = LookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, sel)
535535
if obj == nil {
536+
// Don't report another error if the underlying type was invalid (issue #49541).
537+
if under(x.typ) == Typ[Invalid] {
538+
goto Error
539+
}
540+
536541
if index != nil {
537542
// TODO(gri) should provide actual type where the conflict happens
538543
check.errorf(e.Sel, _AmbiguousSelector, "ambiguous selector %s.%s", x.expr, sel)

src/go/types/instantiate.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,10 @@ func (check *Checker) implements(V, T Type, qf Qualifier) error {
161161
Vu := under(V)
162162
Tu := under(T)
163163
if Vu == Typ[Invalid] || Tu == Typ[Invalid] {
164-
return nil
164+
return nil // avoid follow-on errors
165+
}
166+
if p, _ := Vu.(*Pointer); p != nil && under(p.base) == Typ[Invalid] {
167+
return nil // avoid follow-on errors (see issue #49541 for an example)
165168
}
166169

167170
errorf := func(format string, args ...any) error {
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Copyright 2022 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package p
6+
7+
type S[A, B any] struct {
8+
f int
9+
}
10+
11+
func (S[A, B]) m() {}
12+
13+
// TODO(gri) We should only report one error below. See issue #50588.
14+
15+
func _[A any](s S /* ERROR cannot infer B */ /* ERROR got 1 arguments but 2 type parameters */ [A]) {
16+
// we should see no follow-on errors below
17+
s.f = 1
18+
s.m()
19+
}
20+
21+
// another test case from the issue
22+
23+
func _() {
24+
X(Interface[*F /* ERROR cannot infer B */ /* ERROR got 1 arguments but 2 type parameters */ [string]](Impl{}))
25+
}
26+
27+
func X[Q Qer](fs Interface[Q]) {
28+
}
29+
30+
type Impl struct{}
31+
32+
func (Impl) M() {}
33+
34+
type Interface[Q Qer] interface {
35+
M()
36+
}
37+
38+
type Qer interface {
39+
Q()
40+
}
41+
42+
type F[A, B any] struct{}
43+
44+
func (f *F[A, B]) Q() {}

src/go/types/typeset.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ func (s *_TypeSet) is(f func(*term) bool) bool {
133133

134134
// underIs calls f with the underlying types of the specific type terms
135135
// of s and reports whether all calls to f returned true. If there are
136-
// no specific terms, is returns the result of f(nil).
136+
// no specific terms, underIs returns the result of f(nil).
137137
func (s *_TypeSet) underIs(f func(Type) bool) bool {
138138
if !s.hasTerms() {
139139
return f(nil)

0 commit comments

Comments
 (0)