Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[moved] let a = someConst.unsafeAddr is buggy #552

Closed
timotheecour opened this issue Jan 22, 2021 · 0 comments
Closed

[moved] let a = someConst.unsafeAddr is buggy #552

timotheecour opened this issue Jan 22, 2021 · 0 comments

Comments

@timotheecour
Copy link
Owner

timotheecour commented Jan 22, 2021

this PR nim-lang#15466 enabled one to write let a = someConst.unsafeAddr; however this feature is buggy

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]
[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 that (transitively) contain ref/ptr; it still needs nim-lang#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

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

links

EDIT => nim-lang#16794

@timotheecour timotheecour changed the title let a = someConst.unsafeAddr is buggy [moved] let a = someConst.unsafeAddr is buggy Jan 22, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant