From facb5c08c6c26963208fcb52869eff99efcb058b Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Fri, 1 Jun 2012 17:06:27 -0700 Subject: [PATCH] Enforce rule that classes with dtors aren't copyable The test for this is copy-a-resource. --- src/rustc/middle/ty.rs | 16 +++++++++++++--- src/test/compile-fail/copy-a-resource.rs | 6 +++++- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index 385159bbfbcf..95ed681c4814 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -45,6 +45,7 @@ export field_idx; export get_field; export get_fields; export get_element_type; +export has_dtor; export is_binopable; export is_pred_ty; export lookup_class_field, lookup_class_fields; @@ -1288,7 +1289,7 @@ fn type_needs_unwind_cleanup_(cx: ctxt, ty: t, enum kind { kind_(u32) } -// *ALL* implicity copiable things must be copiable +// *ALL* implicitly copiable things must be copiable const KIND_MASK_COPY : u32 = 0b00000000000000000000000000000001u32; const KIND_MASK_SEND : u32 = 0b00000000000000000000000000000010u32; const KIND_MASK_CONST : u32 = 0b00000000000000000000000000000100u32; @@ -1495,15 +1496,20 @@ fn type_kind(cx: ctxt, ty: t) -> kind { } lowest } - // FIXME: (tjc) there are rules about when classes are copyable/ - // sendable, but I'm just treating them like records (#1726) ty_class(did, substs) { + // Classes are sendable if all their fields are sendable, + // likewise for copyable... // also factor out this code, copied from the records case let mut lowest = kind_top(); let flds = class_items_as_fields(cx, did, substs); for flds.each {|f| lowest = lower_kind(lowest, mutable_type_kind(cx, f.mt)); } + // ...but classes with dtors are never copyable (they can be + // sendable) + if ty::has_dtor(cx, did) { + lowest = lower_kind(lowest, kind_noncopyable()); + } lowest } // Tuples lower to the lowest of their members. @@ -2562,6 +2568,10 @@ fn ty_dtor(cx: ctxt, class_id: def_id) -> option { } } +fn has_dtor(cx: ctxt, class_id: def_id) -> bool { + option::is_some(ty_dtor(cx, class_id)) +} + fn item_path(cx: ctxt, id: ast::def_id) -> ast_map::path { if id.crate != ast::local_crate { csearch::get_item_path(cx, id) diff --git a/src/test/compile-fail/copy-a-resource.rs b/src/test/compile-fail/copy-a-resource.rs index c37ccd29f0db..6eeb4ea2ed44 100644 --- a/src/test/compile-fail/copy-a-resource.rs +++ b/src/test/compile-fail/copy-a-resource.rs @@ -1,5 +1,9 @@ // error-pattern: copying a noncopyable value -resource foo(i: int) { } +class foo { + let i: int; + new(i:int) { self.i = i; } + drop {} +} fn main() { let x <- foo(10); let y = x; log(error, x); }