diff --git a/src/etc/kate/rust.xml b/src/etc/kate/rust.xml
index 6a751bd1c8588..44d0ce1a27fc5 100644
--- a/src/etc/kate/rust.xml
+++ b/src/etc/kate/rust.xml
@@ -49,6 +49,7 @@
- Copy
- Send
- Owned
+ - Sized
- Eq
- Ord
- Num
diff --git a/src/etc/vim/syntax/rust.vim b/src/etc/vim/syntax/rust.vim
index cd794df0a8d89..5c08fdfecca55 100644
--- a/src/etc/vim/syntax/rust.vim
+++ b/src/etc/vim/syntax/rust.vim
@@ -44,7 +44,7 @@ syn keyword rustType size_t ptrdiff_t clock_t time_t
syn keyword rustType c_longlong c_ulonglong intptr_t uintptr_t
syn keyword rustType off_t dev_t ino_t pid_t mode_t ssize_t
-syn keyword rustTrait Const Copy Send Owned " inherent traits
+syn keyword rustTrait Const Copy Send Owned Sized " inherent traits
syn keyword rustTrait Eq Ord Num Ptr
syn keyword rustTrait Drop Add Sub Mul Quot Rem Neg BitAnd BitOr
syn keyword rustTrait BitXor Shl Shr Index
diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs
index f26a52cd8cd33..33e033ace4835 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 eb76b15dd28e8..947c68634148e 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 3a0f6f5c10aa4..be1aa957666fa 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, ..37]
+ items: [Option, ..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 8815259b3cc7b..b0903f78db562 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 390ba2dc0de53..57e2a562b20f5 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 69e0f85522abb..5c5cc98bb9c3a 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 b6c22f29c3e5a..05c963a32cc73 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 07864ce419e62..4dcef60781f5d 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};
diff --git a/src/test/compile-fail/unsized-bare-typaram.rs b/src/test/compile-fail/unsized-bare-typaram.rs
new file mode 100644
index 0000000000000..ff9d379c30f5e
--- /dev/null
+++ b/src/test/compile-fail/unsized-bare-typaram.rs
@@ -0,0 +1,14 @@
+// Copyright 2012 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.
+
+// error-pattern: instantiating a type parameter with an incompatible type
+fn bar() { }
+fn foo() { bar::() }
+fn main() { }
diff --git a/src/test/compile-fail/unsized-enum.rs b/src/test/compile-fail/unsized-enum.rs
new file mode 100644
index 0000000000000..df7d82f0b2590
--- /dev/null
+++ b/src/test/compile-fail/unsized-enum.rs
@@ -0,0 +1,14 @@
+// Copyright 2012 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.
+
+// error-pattern: instantiating a type parameter with an incompatible type
+fn bar() { }
+fn foo() { bar::