-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Description
this recent PR #15466 enabled one to write let a = someConst.unsafeAddr
; however this feature is very buggy, not documented, had 0 tests in the PR that introduced it and should be reverted; see upcoming proposal for a better and simpler way to solve nim-lang/RFCs#257 that has none of its drawbacks
Example 1
unsafeAddr doesn't work with most types
when true:
template fn(a) =
const b = a
let c = b.unsafeAddr
type A = object
a0: int
type B = ref A
fn [1,2]
fn @[1,2]
fn A(a0:1)
# these don't work: Error: expression has no address
# fn "ab"
# fn (1, 2)
# fn 1
# fn B(a0:1) # this one would work with const ref PR https://github.com/nim-lang/Nim/pull/15528
note that these would work with let c = b
instead of let c = b.unsafeAddr
Example 2
when true:
const a = [1,2]
proc fn =
let a1 = a.unsafeAddr
a1[][0] = 7
echo a1[]
echo a
static: fn()
fn()
vm:
[7, 2] # modified from [1,2]
[1, 2] # unmodified from [1,2]: inconsistent
rt:
SIGBUS
Example 3
# sub.nim
when true:
const a* = [1,2]
proc fn1* =
let a1 = a.unsafeAddr
let a2 = a.unsafeAddr
echo cast[int](a1)
echo cast[int](a2)
# main.nim
when true:
import sub
proc fn2* =
let a1 = a.unsafeAddr
let a2 = a.unsafeAddr
echo cast[int](a1)
echo cast[int](a2)
fn1()
fn2()
prints:
4416151424
4416151424
4416151440 # address of a returned is different depending on which module it was called from
4416151440
and this is generated in each module:
static NIM_CONST tyArray__HU7qaqKu9czJLT84iCBJnsA TM__CLoBuXEHTlg1in6VU6Aqdg_2 = {((NI) 1),
((NI) 2)}
unlike what was required in nim-lang/RFCs#257
Example 4
unsafeAddr
still doesn't help with types (including arrays) that (transitively) contain ref/ptr; it still needs #15528
Example 5
when defined case10:
const a = @[1,2]
proc fn* =
let a1 = a.unsafeAddr
let a2 = a.unsafeAddr
echo cast[int](a1)
echo cast[int](a2)
static: fn()
fn()
vm:
4378615304
4378615368 # different from previous line (inconsistent)
rt:
4382200032
4382200032 # same from previous line: inconsistent
Example 6
when true:
const a1 = @[1,2]
const a2 = [1,2]
proc fn* =
let b1 = a1.unsafeAddr
echo cast[int](b1) # ok
let b2 = a2.unsafeAddr
echo cast[int](b2) # Error: unhandled exception: 'intVal' is not accessible using discriminant
static: fn()
Example 7
when true:
const a = @[1,2]
let b = a.unsafeAddr
proc fn1 =
b[][0] = 7
echo b[]
fn1()
nim r main: SIGBUS
nim r -b:cpp main: prints @[7, 2]
Example 8
when true:
const a = [1,2]
let b = a.unsafeAddr
proc fn1 =
b[][0] = 7
echo b[]
fn1()
nim r main: prints [1, 2] with -d:danger, or SIGBUG without
nim r -b:cpp main: prints [7, 2] with or without -d:danger
Additional Information
1.5.1 2b5841c