Closed
Description
pub fn p() -> uint { for 1.times { return break; } 0 }
pub fn p2() -> ~[u8] { for 1.times { return break; } ~[] }
pub fn ok() -> uint { for 1.times { return 123456789; } 0 }
fn main() {
let y = p2(); // +
println(fmt!("%?", p()));
// *
println(fmt!("%?", y));
}
Without optimisations:
140330640183752
/bin/bash: line 1: 30823 Segmentation fault ./return-break
Or, if the let
marked with +
is moved to the *
.
140236804280776
~[]
*** Error in `./return-break': free(): invalid pointer: 0x0000000000a02020 ***
[... snip ...]
With -O
(the position of the let
doesn't matter):
0
/bin/bash: line 1: 30884 Segmentation fault ./return-break
Delving in to the unoptimised asm, the only difference between p
and ok
is:
; p
.LBB2_4:
#APP
# return break ; (return-break.rs:1:35: 1:48)
#NO_APP
movq -24(%rbp), %rax
movb $1, (%rax)
movb $0, -1(%rbp) ; once, for `return`
movb $0, -1(%rbp) ; twice, for `break`
jmp .LBB2_1
; ok
.LBB16_4:
#APP
# return 123456789; (return-break.rs:4:36: 4:52)
#NO_APP
movq -24(%rbp), %rax
movb $1, (%rax)
movb $0, -1(%rbp)
movq -32(%rbp), %rcx
movq $123456789, (%rcx)
jmp .LBB16_1
So it looks like the calling code assumes that (%rcx)
/(-32(%rbp))
is filled as the return value, but it's not. Presumably return break
should be a compile error (or be equivalent to break
), as should more complicated code like
return match foo {
Bar => break,
Baz => 2
}
since it also has the same problem.