cmd/compile: propagate go:notinheap implicitly

//go:notinheap
type T int

type U T

We already correctly propagate the notinheap-ness of T to U.  But we
have an assertion in the typechecker that if there's no explicit
//go:notinheap associated with U, then report an error. Get rid of
that error so that implicit propagation is allowed.

Adjust the tests so that we make sure that uses of types like U
do correctly report an error when U is used in a context that might
cause a Go heap allocation.

Fixes #41451

Update #40954
Update #41432

Change-Id: I1692bc7cceff21ebb3f557f3748812a40887118d
Reviewed-on: https://go-review.googlesource.com/c/go/+/255637
Run-TryBot: Keith Randall <khr@golang.org>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Trust: Cuong Manh Le <cuong.manhle.vn@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
This commit is contained in:
Keith Randall 2020-09-17 09:55:23 -07:00
parent 6796a7fb12
commit 22053790fa
3 changed files with 26 additions and 26 deletions

View file

@ -2068,12 +2068,6 @@ func typecheck1(n *Node, top int) (res *Node) {
ok |= ctxStmt
n.Left = typecheck(n.Left, ctxType)
checkwidth(n.Left.Type)
if n.Left.Type != nil && n.Left.Type.NotInHeap() && !n.Left.Name.Param.Alias && n.Left.Name.Param.Pragma&NotInHeap == 0 {
// The type contains go:notinheap types, so it
// must be marked as such (alternatively, we
// could silently propagate go:notinheap).
yyerror("type %v must be go:notinheap", n.Left.Type)
}
}
t := n.Type

View file

@ -11,18 +11,6 @@ package p
//go:notinheap
type nih struct{}
// Types embedding notinheap types must be notinheap.
type embed1 struct { // ERROR "must be go:notinheap"
x nih
}
type embed2 [1]nih // ERROR "must be go:notinheap"
type embed3 struct { // ERROR "must be go:notinheap"
x [1]nih
}
type embed4 map[nih]int // ERROR "incomplete \(or unallocatable\) map key not allowed"
type embed5 map[int]nih // ERROR "incomplete \(or unallocatable\) map value not allowed"
@ -52,14 +40,6 @@ type t3 byte
//go:notinheap
type t4 rune
// Type aliases inherit the go:notinheap-ness of the type they alias.
type nihAlias = nih
type embedAlias1 struct { // ERROR "must be go:notinheap"
x nihAlias
}
type embedAlias2 [1]nihAlias // ERROR "must be go:notinheap"
var sink interface{}
func i() {

View file

@ -32,6 +32,25 @@ var y3 *[1]nih
var z []nih
var w []nih
var n int
var sink interface{}
type embed1 struct { // implicitly notinheap
x nih
}
type embed2 [1]nih // implicitly notinheap
type embed3 struct { // implicitly notinheap
x [1]nih
}
// Type aliases inherit the go:notinheap-ness of the type they alias.
type nihAlias = nih
type embedAlias1 struct { // implicitly notinheap
x nihAlias
}
type embedAlias2 [1]nihAlias // implicitly notinheap
func g() {
y = new(nih) // ERROR "can't be allocated in Go"
@ -39,6 +58,13 @@ func g() {
y3 = new([1]nih) // ERROR "can't be allocated in Go"
z = make([]nih, 1) // ERROR "can't be allocated in Go"
z = append(z, x) // ERROR "can't be allocated in Go"
sink = new(embed1) // ERROR "can't be allocated in Go"
sink = new(embed2) // ERROR "can't be allocated in Go"
sink = new(embed3) // ERROR "can't be allocated in Go"
sink = new(embedAlias1) // ERROR "can't be allocated in Go"
sink = new(embedAlias2) // ERROR "can't be allocated in Go"
// Test for special case of OMAKESLICECOPY
x := make([]nih, n) // ERROR "can't be allocated in Go"
copy(x, z)