]> Cypherpunks.ru repositories - gostls13.git/commitdiff
go/types, types2: don't verify infer result if no Config.Error is given
authorRobert Griesemer <gri@golang.org>
Tue, 15 Aug 2023 21:17:02 +0000 (14:17 -0700)
committerGopher Robot <gobot@golang.org>
Tue, 15 Aug 2023 22:07:57 +0000 (22:07 +0000)
With no error handler installed, an error leads to an (internal panic
and) immediate abort of type checking. Not all invariants hold up in
this case, but it also doesn't matter.

In Checker.infer, verify result conditions always if an error handler
is installed, but only then.

Fixes #61938.

Change-Id: I4d3d61bbccc696a75639fee5010f5d3cef17e855
Reviewed-on: https://go-review.googlesource.com/c/go/+/519775
Reviewed-by: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Griesemer <gri@google.com>
Auto-Submit: Robert Griesemer <gri@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@google.com>
src/cmd/compile/internal/types2/infer.go
src/cmd/compile/internal/types2/issues_test.go
src/go/types/infer.go
src/go/types/issues_test.go

index 44d66eb516e94cacc6e9808f4ffe1cfe014e43e7..e81721047920ca355f7ba8901fc31ac7d718a9e2 100644 (file)
@@ -27,7 +27,11 @@ const enableReverseTypeInference = true // disable for debugging
 // If successful, infer returns the complete list of given and inferred type arguments, one for each
 // type parameter. Otherwise the result is nil and appropriate errors will be reported.
 func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type, params *Tuple, args []*operand) (inferred []Type) {
-       if debug {
+       // Don't verify result conditions if there's no error handler installed:
+       // in that case, an error leads to an exit panic and the result value may
+       // be incorrect. But in that case it doesn't matter because callers won't
+       // be able to use it either.
+       if check.conf.Error != nil {
                defer func() {
                        assert(inferred == nil || len(inferred) == len(tparams) && !containsNil(inferred))
                }()
index 9f67ad09025116deef80945bd08d12c88b66f352..bcebc2f2c05361f1a9a1a5104f8e9caf34d4fc2b 100644 (file)
@@ -920,3 +920,19 @@ func _() {
        var conf Config
        conf.Check(f.PkgName.Value, []*syntax.File{f}, nil) // must not panic
 }
+
+func TestIssue61938(t *testing.T) {
+       const src = `
+package p
+
+func f[T any]() {}
+func _()        { f() }
+`
+       // no error handler provided (this issue)
+       var conf Config
+       typecheck(src, &conf, nil) // must not panic
+
+       // with error handler (sanity check)
+       conf.Error = func(error) {}
+       typecheck(src, &conf, nil) // must not panic
+}
index 7c7898435ba6b1f72295095e2aa958214b954cf3..387695c16c79666969b924d52e92209206c4665b 100644 (file)
@@ -29,7 +29,11 @@ const enableReverseTypeInference = true // disable for debugging
 // If successful, infer returns the complete list of given and inferred type arguments, one for each
 // type parameter. Otherwise the result is nil and appropriate errors will be reported.
 func (check *Checker) infer(posn positioner, tparams []*TypeParam, targs []Type, params *Tuple, args []*operand) (inferred []Type) {
-       if debug {
+       // Don't verify result conditions if there's no error handler installed:
+       // in that case, an error leads to an exit panic and the result value may
+       // be incorrect. But in that case it doesn't matter because callers won't
+       // be able to use it either.
+       if check.conf.Error != nil {
                defer func() {
                        assert(inferred == nil || len(inferred) == len(tparams) && !containsNil(inferred))
                }()
index 64e1c20d7eb1c31198dd13f8c857e6f05272923e..bdc1a388d805f5c4846be3c2ba21ffca645abc8d 100644 (file)
@@ -930,3 +930,19 @@ func _() {
        var conf Config
        conf.Check(f.Name.Name, fset, []*ast.File{f}, nil) // must not panic
 }
+
+func TestIssue61938(t *testing.T) {
+       const src = `
+package p
+
+func f[T any]() {}
+func _()        { f() }
+`
+       // no error handler provided (this issue)
+       var conf Config
+       typecheck(src, &conf, nil) // must not panic
+
+       // with error handler (sanity check)
+       conf.Error = func(error) {}
+       typecheck(src, &conf, nil) // must not panic
+}