diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 27e03d2bf3103..30b56a28a58fe 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -19,6 +19,7 @@ A dynamic, mutable location. Similar to a mutable option type, but friendlier. */ +#[mutable] pub struct Cell { priv value: Option } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index abf82c511e551..476ec2c11035b 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -1784,7 +1784,7 @@ pub impl TypeContents { } fn nonowned(_cx: ctxt) -> TypeContents { - TC_MANAGED + TC_BORROWED_POINTER + TC_MANAGED + TC_BORROWED_POINTER + TC_NON_OWNED } fn contains_managed(&self) -> bool { @@ -1838,40 +1838,43 @@ impl ToStr for TypeContents { } /// Constant for a type containing nothing of interest. -static TC_NONE: TypeContents = TypeContents{bits:0b0000_00000000}; +static TC_NONE: TypeContents = TypeContents{bits: 0b0000_0000_0000}; /// Contains a borrowed value with a lifetime other than static -static TC_BORROWED_POINTER: TypeContents = TypeContents{bits:0b0000_00000001}; +static TC_BORROWED_POINTER: TypeContents = TypeContents{bits: 0b0000_0000_0001}; /// Contains an owned pointer (~T) but not slice of some kind -static TC_OWNED_POINTER: TypeContents = TypeContents{bits:0b000000000010}; +static TC_OWNED_POINTER: TypeContents = TypeContents{bits: 0b0000_0000_0010}; /// Contains an owned vector ~[] or owned string ~str -static TC_OWNED_VEC: TypeContents = TypeContents{bits:0b000000000100}; +static TC_OWNED_VEC: TypeContents = TypeContents{bits: 0b0000_0000_0100}; /// Contains a ~fn() or a ~Trait, which is non-copyable. -static TC_OWNED_CLOSURE: TypeContents = TypeContents{bits:0b000000001000}; +static TC_OWNED_CLOSURE: TypeContents = TypeContents{bits: 0b0000_0000_1000}; /// Type with a destructor -static TC_DTOR: TypeContents = TypeContents{bits:0b000000010000}; +static TC_DTOR: TypeContents = TypeContents{bits: 0b0000_0001_0000}; /// Contains a managed value -static TC_MANAGED: TypeContents = TypeContents{bits:0b000000100000}; +static TC_MANAGED: TypeContents = TypeContents{bits: 0b0000_0010_0000}; /// &mut with any region -static TC_BORROWED_MUT: TypeContents = TypeContents{bits:0b000001000000}; +static TC_BORROWED_MUT: TypeContents = TypeContents{bits: 0b0000_0100_0000}; /// Mutable content, whether owned or by ref -static TC_MUTABLE: TypeContents = TypeContents{bits:0b000010000000}; +static TC_MUTABLE: TypeContents = TypeContents{bits: 0b0000_1000_0000}; -/// Mutable content, whether owned or by ref -static TC_ONCE_CLOSURE: TypeContents = TypeContents{bits:0b000100000000}; +/// One-shot closure +static TC_ONCE_CLOSURE: TypeContents = TypeContents{bits: 0b0001_0000_0000}; /// An enum with no variants. -static TC_EMPTY_ENUM: TypeContents = TypeContents{bits:0b010000000000}; +static TC_EMPTY_ENUM: TypeContents = TypeContents{bits: 0b0010_0000_0000}; + +/// Contains a type marked with `#[non_owned]` +static TC_NON_OWNED: TypeContents = TypeContents{bits: 0b0100_0000_0000}; /// All possible contents. -static TC_ALL: TypeContents = TypeContents{bits:0b011111111111}; +static TC_ALL: TypeContents = TypeContents{bits: 0b0111_1111_1111}; pub fn type_is_copyable(cx: ctxt, t: ty::t) -> bool { type_contents(cx, t).is_copy(cx) @@ -1939,7 +1942,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { let _i = indenter(); - let mut result = match get(ty).sty { + let result = match get(ty).sty { // Scalar and unique types are sendable, constant, and owned ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) | ty_bare_fn(_) | ty_ptr(_) => { @@ -2013,14 +2016,13 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { ty_struct(did, ref substs) => { let flds = struct_fields(cx, did, substs); - let flds_tc = flds.foldl( + let mut res = flds.foldl( TC_NONE, |tc, f| tc + tc_mt(cx, f.mt, cache)); if ty::has_dtor(cx, did) { - flds_tc + TC_DTOR - } else { - flds_tc + res += TC_DTOR; } + apply_tc_attr(cx, did, res) } ty_tup(ref tys) => { @@ -2029,7 +2031,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { ty_enum(did, ref substs) => { let variants = substd_enum_variants(cx, did, substs); - if variants.is_empty() { + let res = if variants.is_empty() { // we somewhat arbitrary declare that empty enums // are non-copyable TC_EMPTY_ENUM @@ -2039,7 +2041,8 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { *tc, |tc, arg_ty| *tc + tc_ty(cx, *arg_ty, cache)) }) - } + }; + apply_tc_attr(cx, did, res) } ty_param(p) => { @@ -2099,6 +2102,16 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { mc + tc_ty(cx, mt.ty, cache) } + fn apply_tc_attr(cx: ctxt, did: def_id, mut tc: TypeContents) -> TypeContents { + if has_attr(cx, did, "mutable") { + tc += TC_MUTABLE; + } + if has_attr(cx, did, "non_owned") { + tc += TC_NON_OWNED; + } + tc + } + fn borrowed_contents(region: ty::Region, mutbl: ast::mutability) -> TypeContents { @@ -3841,28 +3854,32 @@ pub fn lookup_trait_def(cx: ctxt, did: ast::def_id) -> @ty::TraitDef { } } -// Determine whether an item is annotated with #[packed] or not -pub fn lookup_packed(tcx: ctxt, - did: def_id) -> bool { +/// Determine whether an item is annotated with an attribute +pub fn has_attr(tcx: ctxt, did: def_id, attr: &str) -> bool { if is_local(did) { match tcx.items.find(&did.node) { Some( &ast_map::node_item(@ast::item { attrs: ref attrs, _ - }, _)) => attr::attrs_contains_name(*attrs, "packed"), + }, _)) => attr::attrs_contains_name(*attrs, attr), _ => tcx.sess.bug(fmt!("lookup_packed: %? is not an item", did)) } } else { let mut ret = false; do csearch::get_item_attrs(tcx.cstore, did) |meta_items| { - ret = attr::contains_name(meta_items, "packed"); + ret = attr::contains_name(meta_items, attr); } ret } } +/// Determine whether an item is annotated with `#[packed]` or not +pub fn lookup_packed(tcx: ctxt, did: def_id) -> bool { + has_attr(tcx, did, "packed") +} + // Look up a field ID, whether or not it's local // Takes a list of type substs in case the struct is generic pub fn lookup_field_type(tcx: ctxt, diff --git a/src/test/compile-fail/mutable-enum.rs b/src/test/compile-fail/mutable-enum.rs new file mode 100644 index 0000000000000..2368e5eb5c51f --- /dev/null +++ b/src/test/compile-fail/mutable-enum.rs @@ -0,0 +1,19 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[mutable] +enum Foo { A } + +fn bar(_: T) {} + +fn main() { + let x = A; + bar(x); //~ ERROR instantiating a type parameter with an incompatible type `Foo`, which does not fulfill `Const` +} diff --git a/src/test/compile-fail/mutable-struct.rs b/src/test/compile-fail/mutable-struct.rs new file mode 100644 index 0000000000000..ee040506c40bd --- /dev/null +++ b/src/test/compile-fail/mutable-struct.rs @@ -0,0 +1,19 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[mutable] +struct Foo { a: int } + +fn bar(_: T) {} + +fn main() { + let x = Foo { a: 5 }; + bar(x); //~ ERROR instantiating a type parameter with an incompatible type `Foo`, which does not fulfill `Const` +} diff --git a/src/test/compile-fail/non_owned-enum.rs b/src/test/compile-fail/non_owned-enum.rs new file mode 100644 index 0000000000000..79c2be8183a62 --- /dev/null +++ b/src/test/compile-fail/non_owned-enum.rs @@ -0,0 +1,19 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[non_owned] +enum Foo { A } + +fn bar(_: T) {} + +fn main() { + let x = A; + bar(x); //~ ERROR instantiating a type parameter with an incompatible type `Foo`, which does not fulfill `Owned` +} diff --git a/src/test/compile-fail/non_owned-struct.rs b/src/test/compile-fail/non_owned-struct.rs new file mode 100644 index 0000000000000..2d0bc9a7e8e46 --- /dev/null +++ b/src/test/compile-fail/non_owned-struct.rs @@ -0,0 +1,19 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[non_owned] +struct Foo { a: int } + +fn bar(_: T) {} + +fn main() { + let x = Foo { a: 5 }; + bar(x); //~ ERROR instantiating a type parameter with an incompatible type `Foo`, which does not fulfill `Owned` +}