Add 'Sized' builtin kind; doesn't do anything yet

This commit is contained in:
Ben Blum 2013-05-30 20:03:01 -04:00
parent 237dce12c9
commit b8a53b5a4c
8 changed files with 147 additions and 81 deletions

View File

@ -569,6 +569,9 @@ fn parse_bounds(st: @mut PState, conv: conv_did) -> ty::ParamBounds {
'O' => { 'O' => {
param_bounds.builtin_bounds.add(ty::BoundStatic); param_bounds.builtin_bounds.add(ty::BoundStatic);
} }
'Z' => {
param_bounds.builtin_bounds.add(ty::BoundSized);
}
'I' => { 'I' => {
param_bounds.trait_bounds.push(@parse_trait_ref(st, conv)); param_bounds.trait_bounds.push(@parse_trait_ref(st, conv));
} }

View File

@ -403,6 +403,7 @@ fn enc_bounds(w: @io::Writer, cx: @ctxt, bs: &ty::ParamBounds) {
ty::BoundCopy => w.write_char('C'), ty::BoundCopy => w.write_char('C'),
ty::BoundConst => w.write_char('K'), ty::BoundConst => w.write_char('K'),
ty::BoundStatic => w.write_char('O'), ty::BoundStatic => w.write_char('O'),
ty::BoundSized => w.write_char('Z'),
} }
} }

View File

@ -36,55 +36,56 @@ pub enum LangItem {
ConstTraitLangItem, // 0 ConstTraitLangItem, // 0
CopyTraitLangItem, // 1 CopyTraitLangItem, // 1
OwnedTraitLangItem, // 2 OwnedTraitLangItem, // 2
SizedTraitLangItem, // 3
DropTraitLangItem, // 3 DropTraitLangItem, // 4
AddTraitLangItem, // 4 AddTraitLangItem, // 5
SubTraitLangItem, // 5 SubTraitLangItem, // 6
MulTraitLangItem, // 6 MulTraitLangItem, // 7
DivTraitLangItem, // 7 DivTraitLangItem, // 8
RemTraitLangItem, // 8 RemTraitLangItem, // 9
NegTraitLangItem, // 9 NegTraitLangItem, // 10
NotTraitLangItem, // 10 NotTraitLangItem, // 11
BitXorTraitLangItem, // 11 BitXorTraitLangItem, // 11
BitAndTraitLangItem, // 12 BitAndTraitLangItem, // 13
BitOrTraitLangItem, // 13 BitOrTraitLangItem, // 14
ShlTraitLangItem, // 14 ShlTraitLangItem, // 15
ShrTraitLangItem, // 15 ShrTraitLangItem, // 16
IndexTraitLangItem, // 16 IndexTraitLangItem, // 17
EqTraitLangItem, // 17 EqTraitLangItem, // 18
OrdTraitLangItem, // 18 OrdTraitLangItem, // 19
StrEqFnLangItem, // 19 StrEqFnLangItem, // 20
UniqStrEqFnLangItem, // 20 UniqStrEqFnLangItem, // 21
AnnihilateFnLangItem, // 21 AnnihilateFnLangItem, // 22
LogTypeFnLangItem, // 22 LogTypeFnLangItem, // 23
FailFnLangItem, // 23 FailFnLangItem, // 24
FailBoundsCheckFnLangItem, // 24 FailBoundsCheckFnLangItem, // 25
ExchangeMallocFnLangItem, // 25 ExchangeMallocFnLangItem, // 26
ExchangeFreeFnLangItem, // 26 ExchangeFreeFnLangItem, // 27
MallocFnLangItem, // 27 MallocFnLangItem, // 28
FreeFnLangItem, // 28 FreeFnLangItem, // 29
BorrowAsImmFnLangItem, // 29 BorrowAsImmFnLangItem, // 30
BorrowAsMutFnLangItem, // 30 BorrowAsMutFnLangItem, // 31
ReturnToMutFnLangItem, // 31 ReturnToMutFnLangItem, // 32
CheckNotBorrowedFnLangItem, // 32 CheckNotBorrowedFnLangItem, // 33
StrDupUniqFnLangItem, // 33 StrDupUniqFnLangItem, // 34
RecordBorrowFnLangItem, // 34 RecordBorrowFnLangItem, // 35
UnrecordBorrowFnLangItem, // 35 UnrecordBorrowFnLangItem, // 36
StartFnLangItem, // 36 StartFnLangItem, // 37
} }
pub struct LanguageItems { pub struct LanguageItems {
items: [Option<def_id>, ..37] items: [Option<def_id>, ..38]
} }
pub impl LanguageItems { pub impl LanguageItems {
pub fn new() -> LanguageItems { pub fn new() -> LanguageItems {
LanguageItems { LanguageItems {
items: [ None, ..37 ] items: [ None, ..38 ]
} }
} }
@ -97,44 +98,45 @@ pub impl LanguageItems {
0 => "const", 0 => "const",
1 => "copy", 1 => "copy",
2 => "owned", 2 => "owned",
3 => "sized",
3 => "drop", 4 => "drop",
4 => "add", 5 => "add",
5 => "sub", 6 => "sub",
6 => "mul", 7 => "mul",
7 => "div", 8 => "div",
8 => "rem", 9 => "rem",
9 => "neg", 10 => "neg",
10 => "not", 11 => "not",
11 => "bitxor", 12 => "bitxor",
12 => "bitand", 13 => "bitand",
13 => "bitor", 14 => "bitor",
14 => "shl", 15 => "shl",
15 => "shr", 16 => "shr",
16 => "index", 17 => "index",
17 => "eq", 18 => "eq",
18 => "ord", 19 => "ord",
19 => "str_eq", 20 => "str_eq",
20 => "uniq_str_eq", 21 => "uniq_str_eq",
21 => "annihilate", 22 => "annihilate",
22 => "log_type", 23 => "log_type",
23 => "fail_", 24 => "fail_",
24 => "fail_bounds_check", 25 => "fail_bounds_check",
25 => "exchange_malloc", 26 => "exchange_malloc",
26 => "exchange_free", 27 => "exchange_free",
27 => "malloc", 28 => "malloc",
28 => "free", 29 => "free",
29 => "borrow_as_imm", 30 => "borrow_as_imm",
30 => "borrow_as_mut", 31 => "borrow_as_mut",
31 => "return_to_mut", 32 => "return_to_mut",
32 => "check_not_borrowed", 33 => "check_not_borrowed",
33 => "strdup_uniq", 34 => "strdup_uniq",
34 => "record_borrow", 35 => "record_borrow",
35 => "unrecord_borrow", 36 => "unrecord_borrow",
36 => "start", 37 => "start",
_ => "???" _ => "???"
} }
@ -151,6 +153,9 @@ pub impl LanguageItems {
pub fn owned_trait(&const self) -> def_id { pub fn owned_trait(&const self) -> def_id {
self.items[OwnedTraitLangItem as uint].get() 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 { pub fn drop_trait(&const self) -> def_id {
self.items[DropTraitLangItem as uint].get() self.items[DropTraitLangItem as uint].get()
@ -267,6 +272,7 @@ fn LanguageItemCollector(crate: @crate,
item_refs.insert(@~"const", ConstTraitLangItem as uint); item_refs.insert(@~"const", ConstTraitLangItem as uint);
item_refs.insert(@~"copy", CopyTraitLangItem as uint); item_refs.insert(@~"copy", CopyTraitLangItem as uint);
item_refs.insert(@~"owned", OwnedTraitLangItem as uint); item_refs.insert(@~"owned", OwnedTraitLangItem as uint);
item_refs.insert(@~"sized", SizedTraitLangItem as uint);
item_refs.insert(@~"drop", DropTraitLangItem as uint); item_refs.insert(@~"drop", DropTraitLangItem as uint);

View File

@ -683,6 +683,7 @@ pub enum BuiltinBound {
BoundStatic, BoundStatic,
BoundOwned, BoundOwned,
BoundConst, BoundConst,
BoundSized,
} }
pub fn EmptyBuiltinBounds() -> BuiltinBounds { pub fn EmptyBuiltinBounds() -> BuiltinBounds {
@ -695,6 +696,7 @@ pub fn AllBuiltinBounds() -> BuiltinBounds {
set.add(BoundStatic); set.add(BoundStatic);
set.add(BoundOwned); set.add(BoundOwned);
set.add(BoundConst); set.add(BoundConst);
set.add(BoundSized);
set set
} }
@ -1826,7 +1828,8 @@ pub impl TypeContents {
BoundCopy => self.is_copy(cx), BoundCopy => self.is_copy(cx),
BoundStatic => self.is_static(cx), BoundStatic => self.is_static(cx),
BoundConst => self.is_const(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 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 { fn moves_by_default(&self, cx: ctxt) -> bool {
self.intersects(TypeContents::nonimplicitly_copyable(cx)) 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]` /// Contains a type marked with `#[non_owned]`
static TC_NON_OWNED: TypeContents = TypeContents{bits: 0b0100_0000_0000}; 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. /// 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 { pub fn type_is_copyable(cx: ctxt, t: ty::t) -> bool {
type_contents(cx, t).is_copy(cx) type_contents(cx, t).is_copy(cx)
@ -2029,7 +2043,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
} }
ty_box(mt) => { ty_box(mt) => {
TC_MANAGED + nonowned(tc_mt(cx, mt, cache)) TC_MANAGED + statically_sized(nonowned(tc_mt(cx, mt, cache)))
} }
ty_trait(_, _, UniqTraitStore, _) => { ty_trait(_, _, UniqTraitStore, _) => {
@ -2049,28 +2063,35 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
ty_rptr(r, mt) => { ty_rptr(r, mt) => {
borrowed_contents(r, mt.mutbl) + borrowed_contents(r, mt.mutbl) +
nonowned(tc_mt(cx, mt, cache)) statically_sized(nonowned(tc_mt(cx, mt, cache)))
} }
ty_uniq(mt) => { 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) => { 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) => { 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)) => { ty_evec(mt, vstore_slice(r)) => {
borrowed_contents(r, mt.mutbl) + borrowed_contents(r, mt.mutbl) +
nonowned(tc_mt(cx, mt, cache)) statically_sized(nonowned(tc_mt(cx, mt, cache)))
} }
ty_evec(mt, vstore_fixed(_)) => { 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) => { ty_estr(vstore_box) => {
@ -2145,7 +2166,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
} }
ty_opaque_box => TC_MANAGED, 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) => { ty_opaque_closure_ptr(sigil) => {
match sigil { match sigil {
ast::BorrowedSigil => TC_BORROWED_POINTER, ast::BorrowedSigil => TC_BORROWED_POINTER,
@ -2212,6 +2233,14 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
TypeContents {bits: pointee.bits & mask} 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 { fn closure_contents(cty: &ClosureTy) -> TypeContents {
let st = match cty.sigil { let st = match cty.sigil {
ast::BorrowedSigil => TC_BORROWED_POINTER, ast::BorrowedSigil => TC_BORROWED_POINTER,
@ -2240,6 +2269,8 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
BoundStatic => TypeContents::nonstatic(cx), BoundStatic => TypeContents::nonstatic(cx),
BoundOwned => TypeContents::nonowned(cx), BoundOwned => TypeContents::nonowned(cx),
BoundConst => TypeContents::nonconst(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 // Whether a type is enum like, that is a enum type with only nullary
// constructors // constructors
pub fn type_is_c_like_enum(cx: ctxt, ty: t) -> bool { pub fn type_is_c_like_enum(cx: ctxt, ty: t) -> bool {

View File

@ -782,6 +782,9 @@ pub fn try_add_builtin_trait(tcx: ty::ctxt,
} else if trait_def_id == li.const_trait() { } else if trait_def_id == li.const_trait() {
builtin_bounds.add(ty::BoundConst); builtin_bounds.add(ty::BoundConst);
true true
} else if trait_def_id == li.sized_trait() {
builtin_bounds.add(ty::BoundSized);
true
} else { } else {
false false
} }

View File

@ -563,6 +563,7 @@ impl Repr for ty::ParamBounds {
ty::BoundStatic => ~"'static", ty::BoundStatic => ~"'static",
ty::BoundOwned => ~"Owned", ty::BoundOwned => ~"Owned",
ty::BoundConst => ~"Const", ty::BoundConst => ~"Const",
ty::BoundSized => ~"Sized",
}); });
} }
for self.trait_bounds.each |t| { for self.trait_bounds.each |t| {
@ -767,7 +768,8 @@ impl UserString for ty::BuiltinBound {
ty::BoundCopy => ~"Copy", ty::BoundCopy => ~"Copy",
ty::BoundStatic => ~"'static", ty::BoundStatic => ~"'static",
ty::BoundOwned => ~"Owned", ty::BoundOwned => ~"Owned",
ty::BoundConst => ~"Const" ty::BoundConst => ~"Const",
ty::BoundSized => ~"Sized",
} }
} }
} }

View File

@ -53,3 +53,8 @@ pub trait Owned {
pub trait Const { pub trait Const {
// Empty. // Empty.
} }
#[lang="sized"]
pub trait Sized {
// Empty.
}

View File

@ -12,7 +12,7 @@
// Reexported core operators // Reexported core operators
pub use either::{Either, Left, Right}; 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::{Add, Sub, Mul, Div, Rem, Neg, Not};
pub use ops::{BitAnd, BitOr, BitXor}; pub use ops::{BitAnd, BitOr, BitXor};
pub use ops::{Drop}; pub use ops::{Drop};