]> Cypherpunks repositories - gostls13.git/commitdiff
go/types, types2: avoid field/method lookup error on invalid types
authorRobert Griesemer <gri@golang.org>
Wed, 12 Jan 2022 22:01:44 +0000 (14:01 -0800)
committerRobert Griesemer <gri@golang.org>
Tue, 18 Jan 2022 23:48:55 +0000 (23:48 +0000)
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>
src/cmd/compile/internal/types2/call.go
src/cmd/compile/internal/types2/instantiate.go
src/cmd/compile/internal/types2/testdata/fixedbugs/issue49541.go2 [new file with mode: 0644]
src/cmd/compile/internal/types2/typeset.go
src/go/types/call.go
src/go/types/instantiate.go
src/go/types/testdata/fixedbugs/issue49541.go2 [new file with mode: 0644]
src/go/types/typeset.go

index ea1c27aa2b4d10a4bbc4e4b7ff038a5c2d3a04d3..15a42ca3dc865f1064de314e36cf8046b5670fcd 100644 (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)
index b2e1087c41dae8d5c5c7a94110f6feb7112b34d1..5d5a660419319ac3f960901eaaa75f0457ead025 100644 (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 {
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49541.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49541.go2
new file mode 100644 (file)
index 0000000..b7bf12a
--- /dev/null
@@ -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() {}
index 0d8d02662bf623086f31abe5315f0b42379b50d1..8670c17861f16e66c8bb6b174a8cf7d1df4ff8c7 100644 (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)
index d5b83451c4199003b6db158dddb4240d92314462..aa87c48a65bcd8795380a97093b07350f8ad3a4e 100644 (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)
index e6a5cbf8ae30c8210dfd079cf57b6c4d8f463be2..1a0823575bd58c78d49ab8087792e3d8b633a95f 100644 (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 {
diff --git a/src/go/types/testdata/fixedbugs/issue49541.go2 b/src/go/types/testdata/fixedbugs/issue49541.go2
new file mode 100644 (file)
index 0000000..b7bf12a
--- /dev/null
@@ -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() {}
index 96f740e5cfeab299f5969d65564c559a762cb9aa..3739cd83d6c4e6866a9f5c757623f9a2252fd526 100644 (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)