about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/metadata/tydecode.rs3
-rw-r--r--src/librustc/metadata/tyencode.rs1
-rw-r--r--src/librustc/middle/lang_items.rs158
-rw-r--r--src/librustc/middle/ty.rs66
-rw-r--r--src/librustc/middle/typeck/astconv.rs3
-rw-r--r--src/librustc/util/ppaux.rs4
-rw-r--r--src/libstd/kinds.rs5
-rw-r--r--src/libstd/prelude.rs2
8 files changed, 154 insertions, 88 deletions
diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs
index f26a52cd8cd..33e033ace48 100644
--- a/src/librustc/metadata/tydecode.rs
+++ b/src/librustc/metadata/tydecode.rs
@@ -569,6 +569,9 @@ fn parse_bounds(st: @mut PState, conv: conv_did) -> ty::ParamBounds {
             'O' => {
                 param_bounds.builtin_bounds.add(ty::BoundStatic);
             }
+            'Z' => {
+                param_bounds.builtin_bounds.add(ty::BoundSized);
+            }
             'I' => {
                 param_bounds.trait_bounds.push(@parse_trait_ref(st, conv));
             }
diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs
index eb76b15dd28..947c6863414 100644
--- a/src/librustc/metadata/tyencode.rs
+++ b/src/librustc/metadata/tyencode.rs
@@ -403,6 +403,7 @@ fn enc_bounds(w: @io::Writer, cx: @ctxt, bs: &ty::ParamBounds) {
             ty::BoundCopy => w.write_char('C'),
             ty::BoundConst => w.write_char('K'),
             ty::BoundStatic => w.write_char('O'),
+            ty::BoundSized => w.write_char('Z'),
         }
     }
 
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index 3a0f6f5c10a..be1aa957666 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -36,55 +36,56 @@ pub enum LangItem {
     ConstTraitLangItem,         // 0
     CopyTraitLangItem,          // 1
     OwnedTraitLangItem,         // 2
+    SizedTraitLangItem,         // 3
 
-    DropTraitLangItem,          // 3
+    DropTraitLangItem,          // 4
 
-    AddTraitLangItem,           // 4
-    SubTraitLangItem,           // 5
-    MulTraitLangItem,           // 6
-    DivTraitLangItem,           // 7
-    RemTraitLangItem,           // 8
-    NegTraitLangItem,           // 9
-    NotTraitLangItem,           // 10
+    AddTraitLangItem,           // 5
+    SubTraitLangItem,           // 6
+    MulTraitLangItem,           // 7
+    DivTraitLangItem,           // 8
+    RemTraitLangItem,           // 9
+    NegTraitLangItem,           // 10
+    NotTraitLangItem,           // 11
     BitXorTraitLangItem,        // 11
-    BitAndTraitLangItem,        // 12
-    BitOrTraitLangItem,         // 13
-    ShlTraitLangItem,           // 14
-    ShrTraitLangItem,           // 15
-    IndexTraitLangItem,         // 16
-
-    EqTraitLangItem,            // 17
-    OrdTraitLangItem,           // 18
-
-    StrEqFnLangItem,            // 19
-    UniqStrEqFnLangItem,        // 20
-    AnnihilateFnLangItem,       // 21
-    LogTypeFnLangItem,          // 22
-    FailFnLangItem,             // 23
-    FailBoundsCheckFnLangItem,  // 24
-    ExchangeMallocFnLangItem,   // 25
-    ExchangeFreeFnLangItem,     // 26
-    MallocFnLangItem,           // 27
-    FreeFnLangItem,             // 28
-    BorrowAsImmFnLangItem,      // 29
-    BorrowAsMutFnLangItem,      // 30
-    ReturnToMutFnLangItem,      // 31
-    CheckNotBorrowedFnLangItem, // 32
-    StrDupUniqFnLangItem,       // 33
-    RecordBorrowFnLangItem,     // 34
-    UnrecordBorrowFnLangItem,   // 35
-
-    StartFnLangItem,            // 36
+    BitAndTraitLangItem,        // 13
+    BitOrTraitLangItem,         // 14
+    ShlTraitLangItem,           // 15
+    ShrTraitLangItem,           // 16
+    IndexTraitLangItem,         // 17
+
+    EqTraitLangItem,            // 18
+    OrdTraitLangItem,           // 19
+
+    StrEqFnLangItem,            // 20
+    UniqStrEqFnLangItem,        // 21
+    AnnihilateFnLangItem,       // 22
+    LogTypeFnLangItem,          // 23
+    FailFnLangItem,             // 24
+    FailBoundsCheckFnLangItem,  // 25
+    ExchangeMallocFnLangItem,   // 26
+    ExchangeFreeFnLangItem,     // 27
+    MallocFnLangItem,           // 28
+    FreeFnLangItem,             // 29
+    BorrowAsImmFnLangItem,      // 30
+    BorrowAsMutFnLangItem,      // 31
+    ReturnToMutFnLangItem,      // 32
+    CheckNotBorrowedFnLangItem, // 33
+    StrDupUniqFnLangItem,       // 34
+    RecordBorrowFnLangItem,     // 35
+    UnrecordBorrowFnLangItem,   // 36
+
+    StartFnLangItem,            // 37
 }
 
 pub struct LanguageItems {
-    items: [Option<def_id>, ..37]
+    items: [Option<def_id>, ..38]
 }
 
 pub impl LanguageItems {
     pub fn new() -> LanguageItems {
         LanguageItems {
-            items: [ None, ..37 ]
+            items: [ None, ..38 ]
         }
     }
 
@@ -97,44 +98,45 @@ pub impl LanguageItems {
             0  => "const",
             1  => "copy",
             2  => "owned",
-
-            3  => "drop",
-
-            4  => "add",
-            5  => "sub",
-            6  => "mul",
-            7  => "div",
-            8  => "rem",
-            9 => "neg",
-            10 => "not",
-            11 => "bitxor",
-            12 => "bitand",
-            13 => "bitor",
-            14 => "shl",
-            15 => "shr",
-            16 => "index",
-            17 => "eq",
-            18 => "ord",
-
-            19 => "str_eq",
-            20 => "uniq_str_eq",
-            21 => "annihilate",
-            22 => "log_type",
-            23 => "fail_",
-            24 => "fail_bounds_check",
-            25 => "exchange_malloc",
-            26 => "exchange_free",
-            27 => "malloc",
-            28 => "free",
-            29 => "borrow_as_imm",
-            30 => "borrow_as_mut",
-            31 => "return_to_mut",
-            32 => "check_not_borrowed",
-            33 => "strdup_uniq",
-            34 => "record_borrow",
-            35 => "unrecord_borrow",
-
-            36 => "start",
+            3  => "sized",
+
+            4  => "drop",
+
+            5  => "add",
+            6  => "sub",
+            7  => "mul",
+            8  => "div",
+            9  => "rem",
+            10 => "neg",
+            11 => "not",
+            12 => "bitxor",
+            13 => "bitand",
+            14 => "bitor",
+            15 => "shl",
+            16 => "shr",
+            17 => "index",
+            18 => "eq",
+            19 => "ord",
+
+            20 => "str_eq",
+            21 => "uniq_str_eq",
+            22 => "annihilate",
+            23 => "log_type",
+            24 => "fail_",
+            25 => "fail_bounds_check",
+            26 => "exchange_malloc",
+            27 => "exchange_free",
+            28 => "malloc",
+            29 => "free",
+            30 => "borrow_as_imm",
+            31 => "borrow_as_mut",
+            32 => "return_to_mut",
+            33 => "check_not_borrowed",
+            34 => "strdup_uniq",
+            35 => "record_borrow",
+            36 => "unrecord_borrow",
+
+            37 => "start",
 
             _ => "???"
         }
@@ -151,6 +153,9 @@ pub impl LanguageItems {
     pub fn owned_trait(&const self) -> def_id {
         self.items[OwnedTraitLangItem as uint].get()
     }
+    pub fn sized_trait(&const self) -> def_id {
+        self.items[SizedTraitLangItem as uint].get()
+    }
 
     pub fn drop_trait(&const self) -> def_id {
         self.items[DropTraitLangItem as uint].get()
@@ -267,6 +272,7 @@ fn LanguageItemCollector(crate: @crate,
     item_refs.insert(@~"const", ConstTraitLangItem as uint);
     item_refs.insert(@~"copy", CopyTraitLangItem as uint);
     item_refs.insert(@~"owned", OwnedTraitLangItem as uint);
+    item_refs.insert(@~"sized", SizedTraitLangItem as uint);
 
     item_refs.insert(@~"drop", DropTraitLangItem as uint);
 
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 8815259b3cc..b0903f78db5 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -683,6 +683,7 @@ pub enum BuiltinBound {
     BoundStatic,
     BoundOwned,
     BoundConst,
+    BoundSized,
 }
 
 pub fn EmptyBuiltinBounds() -> BuiltinBounds {
@@ -695,6 +696,7 @@ pub fn AllBuiltinBounds() -> BuiltinBounds {
     set.add(BoundStatic);
     set.add(BoundOwned);
     set.add(BoundConst);
+    set.add(BoundSized);
     set
 }
 
@@ -1826,7 +1828,8 @@ pub impl TypeContents {
             BoundCopy => self.is_copy(cx),
             BoundStatic => self.is_static(cx),
             BoundConst => self.is_const(cx),
-            BoundOwned => self.is_owned(cx)
+            BoundOwned => self.is_owned(cx),
+            BoundSized => self.is_sized(cx),
         }
     }
 
@@ -1871,6 +1874,14 @@ pub impl TypeContents {
         TC_MUTABLE
     }
 
+    fn is_sized(&self, cx: ctxt) -> bool {
+        !self.intersects(TypeContents::dynamically_sized(cx))
+    }
+
+    fn dynamically_sized(_cx: ctxt) -> TypeContents {
+        TC_DYNAMIC_SIZE
+    }
+
     fn moves_by_default(&self, cx: ctxt) -> bool {
         self.intersects(TypeContents::nonimplicitly_copyable(cx))
     }
@@ -1944,8 +1955,11 @@ 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};
 
+/// Is a bare vector, str, function, trait, etc (only relevant at top level).
+static TC_DYNAMIC_SIZE: TypeContents =     TypeContents{bits: 0b1000_0000_0000};
+
 /// All possible contents.
-static TC_ALL: TypeContents =              TypeContents{bits: 0b0111_1111_1111};
+static TC_ALL: TypeContents =              TypeContents{bits: 0b1111_1111_1111};
 
 pub fn type_is_copyable(cx: ctxt, t: ty::t) -> bool {
     type_contents(cx, t).is_copy(cx)
@@ -2029,7 +2043,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
             }
 
             ty_box(mt) => {
-                TC_MANAGED + nonowned(tc_mt(cx, mt, cache))
+                TC_MANAGED + statically_sized(nonowned(tc_mt(cx, mt, cache)))
             }
 
             ty_trait(_, _, UniqTraitStore, _) => {
@@ -2049,28 +2063,35 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
 
             ty_rptr(r, mt) => {
                 borrowed_contents(r, mt.mutbl) +
-                    nonowned(tc_mt(cx, mt, cache))
+                    statically_sized(nonowned(tc_mt(cx, mt, cache)))
             }
 
             ty_uniq(mt) => {
-                TC_OWNED_POINTER + tc_mt(cx, mt, cache)
+                TC_OWNED_POINTER + statically_sized(tc_mt(cx, mt, cache))
             }
 
             ty_evec(mt, vstore_uniq) => {
-                TC_OWNED_VEC + tc_mt(cx, mt, cache)
+                TC_OWNED_VEC + statically_sized(tc_mt(cx, mt, cache))
             }
 
             ty_evec(mt, vstore_box) => {
-                TC_MANAGED + nonowned(tc_mt(cx, mt, cache))
+                TC_MANAGED + statically_sized(nonowned(tc_mt(cx, mt, cache)))
             }
 
             ty_evec(mt, vstore_slice(r)) => {
                 borrowed_contents(r, mt.mutbl) +
-                    nonowned(tc_mt(cx, mt, cache))
+                    statically_sized(nonowned(tc_mt(cx, mt, cache)))
             }
 
             ty_evec(mt, vstore_fixed(_)) => {
-                tc_mt(cx, mt, cache)
+                let contents = tc_mt(cx, mt, cache);
+                // FIXME(#6308) Uncomment this when construction of such
+                // vectors is prevented earlier in compilation.
+                // if !contents.is_sized(cx) {
+                //     cx.sess.bug("Fixed-length vector of unsized type \
+                //                  should be impossible");
+                // }
+                contents
             }
 
             ty_estr(vstore_box) => {
@@ -2145,7 +2166,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
             }
 
             ty_opaque_box => TC_MANAGED,
-            ty_unboxed_vec(mt) => tc_mt(cx, mt, cache),
+            ty_unboxed_vec(mt) => TC_DYNAMIC_SIZE + tc_mt(cx, mt, cache),
             ty_opaque_closure_ptr(sigil) => {
                 match sigil {
                     ast::BorrowedSigil => TC_BORROWED_POINTER,
@@ -2212,6 +2233,14 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
         TypeContents {bits: pointee.bits & mask}
     }
 
+    fn statically_sized(pointee: TypeContents) -> TypeContents {
+        /*!
+         * If a dynamically-sized type is found behind a pointer, we should
+         * restore the 'Sized' kind to the pointer and things that contain it.
+         */
+        TypeContents {bits: pointee.bits & !TC_DYNAMIC_SIZE.bits}
+    }
+
     fn closure_contents(cty: &ClosureTy) -> TypeContents {
         let st = match cty.sigil {
             ast::BorrowedSigil => TC_BORROWED_POINTER,
@@ -2240,6 +2269,8 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
                 BoundStatic => TypeContents::nonstatic(cx),
                 BoundOwned => TypeContents::nonowned(cx),
                 BoundConst => TypeContents::nonconst(cx),
+                // The dynamic-size bit can be removed at pointer-level, etc.
+                BoundSized => TypeContents::dynamically_sized(cx),
             };
         }
 
@@ -2509,6 +2540,21 @@ pub fn type_is_enum(ty: t) -> bool {
     }
 }
 
+// Is the type's representation size known at compile time?
+pub fn type_is_sized(cx: ctxt, ty: ty::t) -> bool {
+    match get(ty).sty {
+        // FIXME(#6308) add trait, vec, str, etc here.
+        ty_param(p) => {
+            let param_def = cx.ty_param_defs.get(&p.def_id.node);
+            if param_def.bounds.builtin_bounds.contains_elem(BoundSized) {
+                return true;
+            }
+            return false;
+        },
+        _ => return true,
+    }
+}
+
 // Whether a type is enum like, that is a enum type with only nullary
 // constructors
 pub fn type_is_c_like_enum(cx: ctxt, ty: t) -> bool {
diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs
index 390ba2dc0de..57e2a562b20 100644
--- a/src/librustc/middle/typeck/astconv.rs
+++ b/src/librustc/middle/typeck/astconv.rs
@@ -782,6 +782,9 @@ pub fn try_add_builtin_trait(tcx: ty::ctxt,
     } else if trait_def_id == li.const_trait() {
         builtin_bounds.add(ty::BoundConst);
         true
+    } else if trait_def_id == li.sized_trait() {
+        builtin_bounds.add(ty::BoundSized);
+        true
     } else {
         false
     }
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 69e0f85522a..5c5cc98bb9c 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -563,6 +563,7 @@ impl Repr for ty::ParamBounds {
                 ty::BoundStatic => ~"'static",
                 ty::BoundOwned => ~"Owned",
                 ty::BoundConst => ~"Const",
+                ty::BoundSized => ~"Sized",
             });
         }
         for self.trait_bounds.each |t| {
@@ -767,7 +768,8 @@ impl UserString for ty::BuiltinBound {
             ty::BoundCopy => ~"Copy",
             ty::BoundStatic => ~"'static",
             ty::BoundOwned => ~"Owned",
-            ty::BoundConst => ~"Const"
+            ty::BoundConst => ~"Const",
+            ty::BoundSized => ~"Sized",
         }
     }
 }
diff --git a/src/libstd/kinds.rs b/src/libstd/kinds.rs
index b6c22f29c3e..05c963a32cc 100644
--- a/src/libstd/kinds.rs
+++ b/src/libstd/kinds.rs
@@ -53,3 +53,8 @@ pub trait Owned {
 pub trait Const {
     // Empty.
 }
+
+#[lang="sized"]
+pub trait Sized {
+    // Empty.
+}
diff --git a/src/libstd/prelude.rs b/src/libstd/prelude.rs
index 07864ce419e..4dcef60781f 100644
--- a/src/libstd/prelude.rs
+++ b/src/libstd/prelude.rs
@@ -12,7 +12,7 @@
 
 // Reexported core operators
 pub use either::{Either, Left, Right};
-pub use kinds::{Const, Copy, Owned};
+pub use kinds::{Const, Copy, Owned, Sized};
 pub use ops::{Add, Sub, Mul, Div, Rem, Neg, Not};
 pub use ops::{BitAnd, BitOr, BitXor};
 pub use ops::{Drop};