defer 목록을 '스코프가 아직 갚아야 할 것' 목록으로 일반화했다. defer 블록과 소유 값 해제가 같은 목록에 쓰인 순서대로 들어가고, 모든 이탈 경로가 역순으로 갚는다. 해제에는 값 옆에 플래그를 둔다. 값이 저장될 때 세우고 넘겨줄 때 지운다. 값이 아직 여기 있는 경로에서만 해제되는데, 그건 코드의 모양만 봐서는 알 수 없는 것이다. 검사기가 소유권을 넘기는 사용을 이미 표시해두므로 그것을 읽는다. !void 함수의 빈 return 은 성공이다. 줄 값도 없고 오류도 없다는 뜻인데 프론트엔드가 타입 불일치로 거부하고 있었다. 런타임이 할당/해제 횟수를 센다. owndrop 프로그램이 그 둘이 일치함을 실행으로 증명한다 -- 이른 반환, 이미 넘긴 값, 스코프 끝 전부.
29 lines
598 B
Plaintext
29 lines
598 B
Plaintext
// EXIT:0
|
|
// OUTPUT:balanced
|
|
unit owndrop;
|
|
import std.io;
|
|
import std.sys;
|
|
|
|
fn take(p: ^i32) -> void { mem.destroy(p); }
|
|
|
|
fn scoped() -> !void {
|
|
let a: ^i32 = try mem.create(1);
|
|
let b: ^i32 = try mem.create(2);
|
|
take(b);
|
|
}
|
|
|
|
fn early(flag: bool) -> !void {
|
|
let p: ^i32 = try mem.create(3);
|
|
if flag { return; }
|
|
take(p);
|
|
}
|
|
|
|
fn main() -> i32 {
|
|
scoped() catch |e| { return 1; };
|
|
early(true) catch |e| { return 2; };
|
|
early(false) catch |e| { return 3; };
|
|
if sys.allocs() == sys.frees() { io.print("balanced\n"); return 0; }
|
|
io.print("leaked\n");
|
|
return 4;
|
|
}
|