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 <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
Robert Griesemer 2022-01-12 14:01:44 -08:00
parent 626f13d0ca
commit fa4df6597e
8 changed files with 108 additions and 4 deletions

View File

@ -531,6 +531,11 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr) {
obj, index, indirect = LookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, sel)
if obj == nil {
// Don't report another error if the underlying type was invalid (issue #49541).
if under(x.typ) == Typ[Invalid] {
goto Error
}
if index != nil {
// TODO(gri) should provide actual type where the conflict happens
check.errorf(e.Sel, "ambiguous selector %s.%s", x.expr, sel)

View File

@ -161,7 +161,10 @@ func (check *Checker) implements(V, T Type, qf Qualifier) error {
Vu := under(V)
Tu := under(T)
if Vu == Typ[Invalid] || Tu == Typ[Invalid] {
return nil
return nil // avoid follow-on errors
}
if p, _ := Vu.(*Pointer); p != nil && under(p.base) == Typ[Invalid] {
return nil // avoid follow-on errors (see issue #49541 for an example)
}
errorf := func(format string, args ...interface{}) error {

View File

@ -0,0 +1,44 @@
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package p
type S[A, B any] struct {
f int
}
func (S[A, B]) m() {}
// TODO(gri) We should only report one error below. See issue #50588.
func _[A any](s S /* ERROR cannot infer B */ /* ERROR got 1 arguments but 2 type parameters */ [A]) {
// we should see no follow-on errors below
s.f = 1
s.m()
}
// another test case from the issue
func _() {
X(Interface[*F /* ERROR cannot infer B */ /* ERROR got 1 arguments but 2 type parameters */ [string]](Impl{}))
}
func X[Q Qer](fs Interface[Q]) {
}
type Impl struct{}
func (Impl) M() {}
type Interface[Q Qer] interface {
M()
}
type Qer interface {
Q()
}
type F[A, B any] struct{}
func (f *F[A, B]) Q() {}

View File

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

View File

@ -533,6 +533,11 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) {
obj, index, indirect = LookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, sel)
if obj == nil {
// Don't report another error if the underlying type was invalid (issue #49541).
if under(x.typ) == Typ[Invalid] {
goto Error
}
if index != nil {
// TODO(gri) should provide actual type where the conflict happens
check.errorf(e.Sel, _AmbiguousSelector, "ambiguous selector %s.%s", x.expr, sel)

View File

@ -161,7 +161,10 @@ func (check *Checker) implements(V, T Type, qf Qualifier) error {
Vu := under(V)
Tu := under(T)
if Vu == Typ[Invalid] || Tu == Typ[Invalid] {
return nil
return nil // avoid follow-on errors
}
if p, _ := Vu.(*Pointer); p != nil && under(p.base) == Typ[Invalid] {
return nil // avoid follow-on errors (see issue #49541 for an example)
}
errorf := func(format string, args ...any) error {

View File

@ -0,0 +1,44 @@
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package p
type S[A, B any] struct {
f int
}
func (S[A, B]) m() {}
// TODO(gri) We should only report one error below. See issue #50588.
func _[A any](s S /* ERROR cannot infer B */ /* ERROR got 1 arguments but 2 type parameters */ [A]) {
// we should see no follow-on errors below
s.f = 1
s.m()
}
// another test case from the issue
func _() {
X(Interface[*F /* ERROR cannot infer B */ /* ERROR got 1 arguments but 2 type parameters */ [string]](Impl{}))
}
func X[Q Qer](fs Interface[Q]) {
}
type Impl struct{}
func (Impl) M() {}
type Interface[Q Qer] interface {
M()
}
type Qer interface {
Q()
}
type F[A, B any] struct{}
func (f *F[A, B]) Q() {}

View File

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