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

let changes value after initialization when initialized from loop iterator #24632

Open
etan-status opened this issue Jan 21, 2025 · 1 comment

Comments

@etan-status
Copy link
Contributor

Description

var xs: seq[proc()]

for mutableVal in 1 .. 5:
  let immutableVal = mutableVal
  xs.add proc() = echo $immutableVal

for x in xs:
  x()

Nim Version

% nim -v
Nim Compiler Version 2.0.14 [MacOSX: arm64]
Compiled at 2025-01-06
Copyright (c) 2006-2023 by Andreas Rumpf

git hash: bf4de6a
active boot switches: -d:release

Current Output

5
5
5
5
5

Expected Output

1
2
3
4
5

Known Workarounds

Use closureScope around the let immutableVal = mutableVal to ensure that let contents don't change after initialization.

Additional Information

Both in --mm:refc and --mm:orc.

@etan-status
Copy link
Contributor Author

etan-status commented Jan 21, 2025

Reason being that immutableVal shares the memory location across all loop iterations, as evident in

  echo $repr(cast[pointer](mutableVal.unsafeAddr))
  echo $repr(cast[pointer](immutableVal.unsafeAddr))

It's a bit like a use-after-free issue where the inner procs point to memory that has become invalid and now points somewhere else (to the new value), and we are just lucky that other code doesn't end up in those variables.

Maybe compiler should check lifetime analysis and automatically inject closureScope in that case or put error / warning if user tries to use a variable in an escaping way.

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