Based on a golang-nuts thread.
var (
x struct{}
y *int = (*int)(unsafe.Pointer(&x))
)
*y = 42
The spec says about unsafe.Pointer
:
A
Pointer
is a pointer type but aPointer
value may not be dereferenced. Any pointer or value of core typeuintptr
can be converted to a type of core typePointer
and vice versa. The effect of converting betweenPointer
anduintptr
is implementation-defined.
Notably, while this does specify that conversion between unsafe.Pointer
and uintptr
is implementation-defined, it doesn't contain the same caveat for conversion between unsafe.Pointer
and other pointers (like *int
in the example above). So the spec does not give any way to reason about the behavior of the above program - not even that it is implementation defined.
The unsafe.Pointer
rules do of course rule that program out, so the implementation-defined rules do allow us to reason about the program. But, technically speaking, we are not giving it purview to do that.
I would propose to change "The effect of converting between Pointer and uintptr is implementation-defined" to "The effect of such conversions is implementation-defined".
Comment From: gabyhelp
Similar Issues
- spec: allow P(x) with type P unsafe.Pointer #4679
- unsafe: allow conversion of uintptr to unsafe.Pointer when it points to non-Go memory #58625
- Incomplete documentation for unsafe.Pointer #1433
- spec: clarify if a type with underlying unsafe.Pointer type can be used for unsafe conversions #19306
- unable to use unsafe.Pointer as pointer to C struct in Go 1.8 #19181
- cmd/cgo: a type alias of unsafe.Pointer is not treated as unsafe.Pointer #67333
- affected/package: types convert: Why do []interface{} and interface{} behave differently when they convert the same variable c? #59863
- Conversion of a pointer type to source type #64032
- proposal: spec: disallow T\<->uintptr conversion for type T unsafe.Pointer #20171
- cmd/compile: compiler assumes `[2]T` does not alias with `struct{a, b T}` which might be allowed by the `unsafe` package #65535
(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)
Comment From: mauri870
cc @griesemer per https://dev.golang.org/owners
Comment From: ruyi789
You shouldn't use this API if you want to be safe, because that's how it's used and it doesn't report errors. That's the very practical value of it.
You might consider using it this way or staying away from it, but what's wrong with it?
```
func Generic_ToE any, T any (r T) { return (T)(unsafe.Pointer(val)) } func Generic_To2E any, T any (r T) { return (T)(unsafe.Pointer(val)) } func Generic_To3E any, T any (r T) { return (T)(unsafe.Pointer(&val)) }
Comment From: griesemer
@Merovius We probably were (implicitly) assuming that since an unsafe.Pointer
is a pointer type, any conversion between pointer types only changes the types but doesn't really "do" anything at runtime - which is of course what happens but we (probably) don't want to write that down, yet we need to write something about it. I think your suggestion seems fine, thanks.
Comment From: gopherbot
Change https://go.dev/cl/593755 mentions this issue: spec: clarify prose about unsafe pointer conversions