-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
escape analysis broken with lent
#14557
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
Comments
just curious, is |
Yes. |
I think we need some kind of annotation here, bc the convention (1st param escapes for var result from https://nim-lang.github.io/Nim/manual.html#procedures-var-return-type) doesn't translate well here. is it time for memory tracking using
I'm thinking of something like this could also be used to implement memory safe openArray/slices it may even help with #8463 (comment) to track that a memory location came from RODATA, to prevent SIGBUS at CT... and then this in turn could allow static const data (nim-lang/RFCs#126 (comment)) exampletype Slice[T] = object
ptr T
n: int
var myGlobal: Slice[char]
proc fn =
var buf: array[10, char]
# fill buf
let path = buf.sliced(2..5)
doAssert type(path) is Slice[char from buf]
let (dir, name, ext) = path.splitFile() # these are all pointing inside buf
doAssert $ext == ".nim"
var myLocal: Slice[char from buf]
myLocal = dir # ok
myGlobal = dir # Error: 'a' escapes its stack frame |
I don't understand why it cannot work with the first parameter as |
when true:
type A = array[10,float]
proc getByIndex(index: int): lent A =
var a {.global.}: A
var b {.global.}: A
if index == 0: result = a else: result = b
proc fn(index: int): lent A =
result = getByIndex(index)
proc main() =
let s = fn(0)
echo s
echo fn(1)
main() |
So what? You cannot |
could you provide more details? the code i gave in #14557 (comment) works today, is sound and should keep working, but the first parameter rule would make it not work IIUC. also, down the line I really want to express something like this (but i can move this out to a separate thread): when true:
type A = array[10,float]
type Slice[T,sym] = object
n: int
data: ptr[T, sym]
proc slice[N,T] (a: array[N, T]): Slice[T,a]
result.n = a.len
result.data = a[0].safeAddr # safeAddr is a new magic that returns a ptr[T,sym]
proc main: Slice[char] =
var buf: array[10,char]
var s = buf.slice
var s2 = s[0..3]
doAssert s[0].addr == s2[0].addr
let mytup = (s, s2, "foo") # tuple[Slice[char, buf], Slice[char, buf], string]
# return s2 # error
return s2.dup # ok
main() there's obviously some hand waving there but the idea should be clear (safe slices that can be embedded in arbitrary types); the tracking is done by attaching a symbol in the type, and it should compose, eg: is there a simpler way to express it? Do you have anything in mind that is along those lines? |
There is an RFC for more borrowing. Anyhow, IMO |
ok how about the following, which doesn't change anything in the type system (no proc byLent*[T](a: T): lent T {.escapes: [a].} =
a
proc byLent*[T](a: T, b: T, c: T): lent T {.escapes: [a, c].} =
if cond: a else: c
proc byLent*[T](a: T): lent T {.escapes: [].} =
someGlobal => this keeps all the analysis local and it should be pretty close to existing code that does escape analysis come to think of it, this might also be enough to enable the |
Why can't we simply fix the bug and introduce more borrowing later? |
as a temporary measure until something like this would stay legal: proc byLent*[T](a: T): lent T = a
proc fn(a: T, b: T): lent T = # ditto with proc fn(a: var T, b: T): lent T
var c: T
# result = byLent(c) # good: CT error
result = byLent(a) # ok
# result = byLent(b) # bad: not ok, can only return address derived from 1st param the downside is it would also prevent many useful valid cases eg #14557 (comment) it's fine as a temporary measure. I quite like |
@timotheecour As Araq already said |
Nah, |
Well yeah, that's what the compiler should have done to begin with. |
escape analysis broken with
lent
the
lent
analog of https://nim-lang.github.io/Nim/manual.html#procedures-var-return-type is unsafe:Example
Current Output
random stack garbage
Expected Output
result = byLent(a)
should proabably give:Error: 'a' escapes its stack frame
.escape analysis should track that
byLent
implicit address comes froma
which is stack variable, and prevent leaking toresult
Additional Information
devel 4301a3d 1.3.5
The text was updated successfully, but these errors were encountered: