From b8a53b5a4cb594326ec90feb960d018e7ae23f2a Mon Sep 17 00:00:00 2001 From: Ben Blum Date: Thu, 30 May 2013 20:03:01 -0400 Subject: [PATCH] Add 'Sized' builtin kind; doesn't do anything yet --- src/librustc/metadata/tydecode.rs | 3 + src/librustc/metadata/tyencode.rs | 1 + src/librustc/middle/lang_items.rs | 144 ++++++++++++++------------ src/librustc/middle/ty.rs | 66 ++++++++++-- src/librustc/middle/typeck/astconv.rs | 3 + src/librustc/util/ppaux.rs | 4 +- src/libstd/kinds.rs | 5 + src/libstd/prelude.rs | 2 +- 8 files changed, 147 insertions(+), 81 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 + BitAndTraitLangItem, // 13 + BitOrTraitLangItem, // 14 + ShlTraitLangItem, // 15 + ShrTraitLangItem, // 16 + IndexTraitLangItem, // 17 - EqTraitLangItem, // 17 - OrdTraitLangItem, // 18 + EqTraitLangItem, // 18 + OrdTraitLangItem, // 19 - 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 + 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, // 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 => "sized", - 3 => "drop", + 4 => "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", + 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", - 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", + 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", - 36 => "start", + 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};