about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-05-07 01:27:38 -0700
committerbors <bors@rust-lang.org>2013-05-07 01:27:38 -0700
commitbdb52e58b43736b1351fa20a2b3dcff619a5fd09 (patch)
tree6873690a04e9827ccc9d6f4ad31ca5a3891da369
parent7b2020f2c3f51de0dd4dcfe4a107673eda6f25e7 (diff)
parente7f6c4c75406c3ecd117d7213e1be3438454b47e (diff)
downloadrust-bdb52e58b43736b1351fa20a2b3dcff619a5fd09.tar.gz
rust-bdb52e58b43736b1351fa20a2b3dcff619a5fd09.zip
auto merge of #6251 : thestinger/rust/non_owned, r=pcwalton
Also fixed the docstring on `TC_ONCE_CLOSURE` (was accidentally the same as `TC_MUTABLE`) and shifted the `TC_EMPTY_ENUM` bit left by one since whatever previously used that bit has been removed.
-rw-r--r--src/libcore/cell.rs1
-rw-r--r--src/librustc/middle/ty.rs67
-rw-r--r--src/test/compile-fail/mutable-enum.rs19
-rw-r--r--src/test/compile-fail/mutable-struct.rs19
-rw-r--r--src/test/compile-fail/non_owned-enum.rs19
-rw-r--r--src/test/compile-fail/non_owned-struct.rs19
6 files changed, 119 insertions, 25 deletions
diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs
index 959defeec04..c7f9e377571 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<T> {
     priv value: Option<T>
 }
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index d3875bad13a..892635416c2 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -1795,7 +1795,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 {
@@ -1849,40 +1849,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)
@@ -2024,14 +2027,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) => {
@@ -2040,7 +2042,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
@@ -2050,7 +2052,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) => {
@@ -2110,6 +2113,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
     {
@@ -3874,28 +3887,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 00000000000..2368e5eb5c5
--- /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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[mutable]
+enum Foo { A }
+
+fn bar<T: Const>(_: 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 00000000000..ee040506c40
--- /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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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: Const>(_: 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 00000000000..79c2be8183a
--- /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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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: Owned>(_: 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 00000000000..2d0bc9a7e8e
--- /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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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: Owned>(_: 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`
+}