Skip to content

Commit

Permalink
go/types, types2: pointer base types cannot be type constraints
Browse files Browse the repository at this point in the history
Pointer types may appear in expressions *P and we don't know if
we have an indirection (P is a pointer value) or a pointer type
(P is a type) until we type-check P. Don't forget to check that
a type P must be an ordinary (not a constraint) type in this
special case.

Fixes #51578.

Change-Id: If782cc6dd2a602a498574c78c99e40c3b72274a5
Reviewed-on: https://go-review.googlesource.com/c/go/+/391275
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
  • Loading branch information
griesemer committed Mar 9, 2022
1 parent e189b5e commit 3a5e3d8
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 6 deletions.
1 change: 1 addition & 0 deletions src/cmd/compile/internal/types2/expr.go
Original file line number Diff line number Diff line change
Expand Up @@ -1642,6 +1642,7 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin
case invalid:
goto Error
case typexpr:
check.validVarType(e.X, x.typ)
x.typ = &Pointer{base: x.typ}
default:
var base Type
Expand Down
17 changes: 17 additions & 0 deletions src/cmd/compile/internal/types2/testdata/fixedbugs/issue51578.go2
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// 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

var _ = (*interface /* ERROR interface contains type constraints */ {int})(nil)

// abbreviated test case from issue

type TypeSet interface{ int | string }

func _() {
f((*TypeSet /* ERROR interface contains type constraints */)(nil))
}

func f(any) {}
10 changes: 7 additions & 3 deletions src/cmd/compile/internal/types2/typexpr.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,10 +147,16 @@ func (check *Checker) typ(e syntax.Expr) Type {
// constraint interface.
func (check *Checker) varType(e syntax.Expr) Type {
typ := check.definedType(e, nil)
check.validVarType(e, typ)
return typ
}

// validVarType reports an error if typ is a constraint interface.
// The expression e is used for error reporting, if any.
func (check *Checker) validVarType(e syntax.Expr, typ Type) {
// If we have a type parameter there's nothing to do.
if isTypeParam(typ) {
return typ
return
}

// We don't want to call under() or complete interfaces while we are in
Expand All @@ -169,8 +175,6 @@ func (check *Checker) varType(e syntax.Expr) Type {
}
}
})

return typ
}

// definedType is like typ but also accepts a type name def.
Expand Down
1 change: 1 addition & 0 deletions src/go/types/expr.go
Original file line number Diff line number Diff line change
Expand Up @@ -1588,6 +1588,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
case invalid:
goto Error
case typexpr:
check.validVarType(e.X, x.typ)
x.typ = &Pointer{base: x.typ}
default:
var base Type
Expand Down
17 changes: 17 additions & 0 deletions src/go/types/testdata/fixedbugs/issue51578.go2
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// 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

var _ = (*interface /* ERROR interface contains type constraints */ {int})(nil)

// abbreviated test case from issue

type TypeSet interface{ int | string }

func _() {
f((*TypeSet /* ERROR interface contains type constraints */)(nil))
}

func f(any) {}
10 changes: 7 additions & 3 deletions src/go/types/typexpr.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,10 +144,16 @@ func (check *Checker) typ(e ast.Expr) Type {
// constraint interface.
func (check *Checker) varType(e ast.Expr) Type {
typ := check.definedType(e, nil)
check.validVarType(e, typ)
return typ
}

// validVarType reports an error if typ is a constraint interface.
// The expression e is used for error reporting, if any.
func (check *Checker) validVarType(e ast.Expr, typ Type) {
// If we have a type parameter there's nothing to do.
if isTypeParam(typ) {
return typ
return
}

// We don't want to call under() or complete interfaces while we are in
Expand All @@ -165,8 +171,6 @@ func (check *Checker) varType(e ast.Expr) Type {
}
}
})

return typ
}

// definedType is like typ but also accepts a type name def.
Expand Down

0 comments on commit 3a5e3d8

Please sign in to comment.