From fcf6afb82dc1e9f80a6260467026adc11d5c9529 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Fri, 18 Mar 2022 10:46:15 -0700 Subject: [PATCH] cmd/compile: pointers to notinheap types need their own shape They should not share a shape with regular pointers. We could coalesce multiple pointer-to-not-in-heap types, but doesn't seem worth it - just make them fully stenciled. Fixes #51733 Change-Id: Ie8158177226fbc46a798e71c51897a82f15153df Reviewed-on: https://go-review.googlesource.com/c/go/+/393895 Trust: Keith Randall Run-TryBot: Keith Randall TryBot-Result: Gopher Robot Reviewed-by: David Chase --- src/cmd/compile/internal/typecheck/subr.go | 2 +- test/typeparam/issue51733.go | 32 ++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 test/typeparam/issue51733.go diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index bc390158465..311c5858b2c 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -1532,7 +1532,7 @@ func Shapify(t *types.Type, index int, tparam *types.Type) *types.Type { // Note: pointers to arrays are special because of slice-to-array-pointer // conversions. See issue 49295. if u.Kind() == types.TPTR && u.Elem().Kind() != types.TARRAY && - tparam.Bound().StructuralType() == nil { + tparam.Bound().StructuralType() == nil && !u.Elem().NotInHeap() { u = types.Types[types.TUINT8].PtrTo() } diff --git a/test/typeparam/issue51733.go b/test/typeparam/issue51733.go new file mode 100644 index 00000000000..03624f18655 --- /dev/null +++ b/test/typeparam/issue51733.go @@ -0,0 +1,32 @@ +// run + +// 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 main + +import ( + "log" + "unsafe" +) + +//go:notinheap +type S struct{} + +func main() { + p := (*S)(unsafe.Pointer(uintptr(0x8000))) + var v any = p + p2 := v.(*S) + if p != p2 { + log.Fatalf("%p != %p", unsafe.Pointer(p), unsafe.Pointer(p2)) + } + p2 = typeAssert[*S](v) + if p != p2 { + log.Fatalf("%p != %p from typeAssert", unsafe.Pointer(p), unsafe.Pointer(p2)) + } +} + +func typeAssert[T any](v any) T { + return v.(T) +}