mirror of https://github.com/golang/go.git
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:
parent
626f13d0ca
commit
fa4df6597e
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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() {}
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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() {}
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue