diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index 9a3d00e33d9..50730d0ed86 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -915,26 +915,57 @@ fn type_needs_unwind_cleanup(cx: ctxt, ty: t) -> bool { none { } } - // Prevent infinite recursion - cx.needs_unwind_cleanup_cache.insert(ty, false); + let tycache = new_ty_hash(); + let needs_unwind_cleanup = + type_needs_unwind_cleanup_(cx, ty, tycache, false); + cx.needs_unwind_cleanup_cache.insert(ty, needs_unwind_cleanup); + ret needs_unwind_cleanup; +} +fn type_needs_unwind_cleanup_(cx: ctxt, ty: t, + tycache: map::hashmap, + encountered_box: bool) -> bool { + + // Prevent infinite recursion + alt tycache.find(ty) { + some(_) { ret false; } + none { tycache.insert(ty, ()); } + } + + let mut encountered_box = encountered_box; let mut needs_unwind_cleanup = false; maybe_walk_ty(ty) {|ty| alt get(ty).struct { + ty_box(_) | ty_opaque_box { + encountered_box = true; + true + } ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) | - ty_box(_) | ty_rec(_) | ty_tup(_) { + ty_rec(_) | ty_tup(_) | ty_ptr(_) { true } ty_enum(did, tps) { for v in *enum_variants(cx, did) { for aty in v.args { let t = substitute_type_params(cx, tps, aty); - needs_unwind_cleanup |= type_needs_unwind_cleanup(cx, t); + needs_unwind_cleanup |= + type_needs_unwind_cleanup_(cx, t, tycache, + encountered_box); } } !needs_unwind_cleanup } + ty_uniq(_) | ty_str | ty_vec(_) | ty_res(_, _, _) { + // Once we're inside a box, the annihilator will find + // it and destroy it. + if !encountered_box { + needs_unwind_cleanup = true; + false + } else { + true + } + } _ { needs_unwind_cleanup = true; false @@ -942,8 +973,6 @@ fn type_needs_unwind_cleanup(cx: ctxt, ty: t) -> bool { } } - cx.needs_unwind_cleanup_cache.insert(ty, needs_unwind_cleanup); - ret needs_unwind_cleanup; } diff --git a/src/test/run-fail/unwind-box-fn-unique.rs b/src/test/run-fail/unwind-box-fn-unique.rs new file mode 100644 index 00000000000..b164338c63c --- /dev/null +++ b/src/test/run-fail/unwind-box-fn-unique.rs @@ -0,0 +1,14 @@ +// error-pattern:fail + +fn failfn() { + fail; +} + +fn main() { + let y = ~0; + let x = @fn~() { + log(error, y); + }; + failfn(); + log(error, x); +} \ No newline at end of file diff --git a/src/test/run-fail/unwind-box-fn.rs b/src/test/run-fail/unwind-box-fn.rs new file mode 100644 index 00000000000..645822f292b --- /dev/null +++ b/src/test/run-fail/unwind-box-fn.rs @@ -0,0 +1,14 @@ +// error-pattern:fail + +fn failfn() { + fail; +} + +fn main() { + let y = ~0; + let x = @fn@() { + log(error, y); + }; + failfn(); + log(error, x); +} \ No newline at end of file diff --git a/src/test/run-fail/unwind-box-iface.rs b/src/test/run-fail/unwind-box-iface.rs new file mode 100644 index 00000000000..b9c674bd008 --- /dev/null +++ b/src/test/run-fail/unwind-box-iface.rs @@ -0,0 +1,19 @@ +// error-pattern:fail + +fn failfn() { + fail; +} + +iface i { + fn foo(); +} + +impl of i for ~int { + fn foo() { } +} + +fn main() { + let x = ~0 as i; + failfn(); + log(error, x); +} \ No newline at end of file diff --git a/src/test/run-fail/unwind-box-res.rs b/src/test/run-fail/unwind-box-res.rs new file mode 100644 index 00000000000..e076f891031 --- /dev/null +++ b/src/test/run-fail/unwind-box-res.rs @@ -0,0 +1,18 @@ +// error-pattern:fail + +fn failfn() { + fail; +} + +resource r(v: *int) unsafe { + let v2: ~int = unsafe::reinterpret_cast(v); +} + +fn main() unsafe { + let i1 = ~0; + let i1p = unsafe::reinterpret_cast(i1); + unsafe::forget(i1); + let x = @r(i1p); + failfn(); + log(error, x); +} \ No newline at end of file diff --git a/src/test/run-fail/unwind-box-str.rs b/src/test/run-fail/unwind-box-str.rs new file mode 100644 index 00000000000..e0cd34b784b --- /dev/null +++ b/src/test/run-fail/unwind-box-str.rs @@ -0,0 +1,11 @@ +// error-pattern:fail + +fn failfn() { + fail; +} + +fn main() { + let x = @"hi"; + failfn(); + log(error, x); +} \ No newline at end of file diff --git a/src/test/run-fail/unwind-box-unique-unique.rs b/src/test/run-fail/unwind-box-unique-unique.rs new file mode 100644 index 00000000000..023910eeecd --- /dev/null +++ b/src/test/run-fail/unwind-box-unique-unique.rs @@ -0,0 +1,11 @@ +// error-pattern:fail + +fn failfn() { + fail; +} + +fn main() { + let x = @~~0; + failfn(); + log(error, x); +} \ No newline at end of file diff --git a/src/test/run-fail/unwind-box-unique.rs b/src/test/run-fail/unwind-box-unique.rs new file mode 100644 index 00000000000..18ed2768fa8 --- /dev/null +++ b/src/test/run-fail/unwind-box-unique.rs @@ -0,0 +1,11 @@ +// error-pattern:fail + +fn failfn() { + fail; +} + +fn main() { + let x = @~0; + failfn(); + log(error, x); +} \ No newline at end of file diff --git a/src/test/run-fail/unwind-box-vec.rs b/src/test/run-fail/unwind-box-vec.rs new file mode 100644 index 00000000000..7aa411ab017 --- /dev/null +++ b/src/test/run-fail/unwind-box-vec.rs @@ -0,0 +1,11 @@ +// error-pattern:fail + +fn failfn() { + fail; +} + +fn main() { + let x = @[0, 1, 2, 3, 4, 5]; + failfn(); + log(error, x); +} \ No newline at end of file