librustc: Implement a Pod
kind for types that can be memcpy
'd.
This will be used for the new `Cell`.
This commit is contained in:
parent
c2c2c4d6f3
commit
caf34b41c3
7 changed files with 174 additions and 49 deletions
|
@ -395,6 +395,7 @@ fn enc_bounds(w: @mut MemWriter, cx: @ctxt, bs: &ty::ParamBounds) {
|
|||
ty::BoundFreeze => mywrite!(w, "K"),
|
||||
ty::BoundStatic => mywrite!(w, "O"),
|
||||
ty::BoundSized => mywrite!(w, "Z"),
|
||||
ty::BoundPod => mywrite!(w, "P"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
use driver::session::Session;
|
||||
use metadata::csearch::each_lang_item;
|
||||
use metadata::cstore::iter_crate_data;
|
||||
use middle::ty::{BuiltinBound, BoundFreeze, BoundSend, BoundSized};
|
||||
use middle::ty::{BuiltinBound, BoundFreeze, BoundPod, BoundSend, BoundSized};
|
||||
use syntax::ast;
|
||||
use syntax::ast_util::local_def;
|
||||
use syntax::attr::AttrMetaMethods;
|
||||
|
@ -83,6 +83,8 @@ impl LanguageItems {
|
|||
Some(BoundSend)
|
||||
} else if Some(id) == self.sized_trait() {
|
||||
Some(BoundSized)
|
||||
} else if Some(id) == self.pod_trait() {
|
||||
Some(BoundPod)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -206,56 +208,58 @@ pub fn collect_language_items(crate: &ast::Crate,
|
|||
}
|
||||
|
||||
lets_do_this! {
|
||||
There are 41 lang items.
|
||||
There are 42 lang items.
|
||||
|
||||
// ID, Variant name, Name, Method name;
|
||||
0, FreezeTraitLangItem, "freeze", freeze_trait;
|
||||
1, SendTraitLangItem, "send", send_trait;
|
||||
2, SizedTraitLangItem, "sized", sized_trait;
|
||||
3, PodTraitLangItem, "pod", pod_trait;
|
||||
|
||||
3, DropTraitLangItem, "drop", drop_trait;
|
||||
4, DropTraitLangItem, "drop", drop_trait;
|
||||
|
||||
4, AddTraitLangItem, "add", add_trait;
|
||||
5, SubTraitLangItem, "sub", sub_trait;
|
||||
6, MulTraitLangItem, "mul", mul_trait;
|
||||
7, DivTraitLangItem, "div", div_trait;
|
||||
8, RemTraitLangItem, "rem", rem_trait;
|
||||
9, NegTraitLangItem, "neg", neg_trait;
|
||||
10, NotTraitLangItem, "not", not_trait;
|
||||
11, BitXorTraitLangItem, "bitxor", bitxor_trait;
|
||||
12, BitAndTraitLangItem, "bitand", bitand_trait;
|
||||
13, BitOrTraitLangItem, "bitor", bitor_trait;
|
||||
14, ShlTraitLangItem, "shl", shl_trait;
|
||||
15, ShrTraitLangItem, "shr", shr_trait;
|
||||
16, IndexTraitLangItem, "index", index_trait;
|
||||
5, AddTraitLangItem, "add", add_trait;
|
||||
6, SubTraitLangItem, "sub", sub_trait;
|
||||
7, MulTraitLangItem, "mul", mul_trait;
|
||||
8, DivTraitLangItem, "div", div_trait;
|
||||
9, RemTraitLangItem, "rem", rem_trait;
|
||||
10, NegTraitLangItem, "neg", neg_trait;
|
||||
11, NotTraitLangItem, "not", not_trait;
|
||||
12, BitXorTraitLangItem, "bitxor", bitxor_trait;
|
||||
13, BitAndTraitLangItem, "bitand", bitand_trait;
|
||||
14, BitOrTraitLangItem, "bitor", bitor_trait;
|
||||
15, ShlTraitLangItem, "shl", shl_trait;
|
||||
16, ShrTraitLangItem, "shr", shr_trait;
|
||||
17, IndexTraitLangItem, "index", index_trait;
|
||||
|
||||
17, EqTraitLangItem, "eq", eq_trait;
|
||||
18, OrdTraitLangItem, "ord", ord_trait;
|
||||
18, EqTraitLangItem, "eq", eq_trait;
|
||||
19, OrdTraitLangItem, "ord", ord_trait;
|
||||
|
||||
19, StrEqFnLangItem, "str_eq", str_eq_fn;
|
||||
20, UniqStrEqFnLangItem, "uniq_str_eq", uniq_str_eq_fn;
|
||||
21, FailFnLangItem, "fail_", fail_fn;
|
||||
22, FailBoundsCheckFnLangItem, "fail_bounds_check", fail_bounds_check_fn;
|
||||
23, ExchangeMallocFnLangItem, "exchange_malloc", exchange_malloc_fn;
|
||||
24, ClosureExchangeMallocFnLangItem, "closure_exchange_malloc", closure_exchange_malloc_fn;
|
||||
25, ExchangeFreeFnLangItem, "exchange_free", exchange_free_fn;
|
||||
26, MallocFnLangItem, "malloc", malloc_fn;
|
||||
27, FreeFnLangItem, "free", free_fn;
|
||||
28, BorrowAsImmFnLangItem, "borrow_as_imm", borrow_as_imm_fn;
|
||||
29, BorrowAsMutFnLangItem, "borrow_as_mut", borrow_as_mut_fn;
|
||||
30, ReturnToMutFnLangItem, "return_to_mut", return_to_mut_fn;
|
||||
31, CheckNotBorrowedFnLangItem, "check_not_borrowed", check_not_borrowed_fn;
|
||||
32, StrDupUniqFnLangItem, "strdup_uniq", strdup_uniq_fn;
|
||||
33, RecordBorrowFnLangItem, "record_borrow", record_borrow_fn;
|
||||
34, UnrecordBorrowFnLangItem, "unrecord_borrow", unrecord_borrow_fn;
|
||||
20, StrEqFnLangItem, "str_eq", str_eq_fn;
|
||||
21, UniqStrEqFnLangItem, "uniq_str_eq", uniq_str_eq_fn;
|
||||
22, FailFnLangItem, "fail_", fail_fn;
|
||||
23, FailBoundsCheckFnLangItem, "fail_bounds_check", fail_bounds_check_fn;
|
||||
24, ExchangeMallocFnLangItem, "exchange_malloc", exchange_malloc_fn;
|
||||
25, ClosureExchangeMallocFnLangItem, "closure_exchange_malloc", closure_exchange_malloc_fn;
|
||||
26, ExchangeFreeFnLangItem, "exchange_free", exchange_free_fn;
|
||||
27, MallocFnLangItem, "malloc", malloc_fn;
|
||||
28, FreeFnLangItem, "free", free_fn;
|
||||
29, BorrowAsImmFnLangItem, "borrow_as_imm", borrow_as_imm_fn;
|
||||
30, BorrowAsMutFnLangItem, "borrow_as_mut", borrow_as_mut_fn;
|
||||
31, ReturnToMutFnLangItem, "return_to_mut", return_to_mut_fn;
|
||||
32, CheckNotBorrowedFnLangItem, "check_not_borrowed", check_not_borrowed_fn;
|
||||
33, StrDupUniqFnLangItem, "strdup_uniq", strdup_uniq_fn;
|
||||
34, RecordBorrowFnLangItem, "record_borrow", record_borrow_fn;
|
||||
35, UnrecordBorrowFnLangItem, "unrecord_borrow", unrecord_borrow_fn;
|
||||
|
||||
35, StartFnLangItem, "start", start_fn;
|
||||
36, StartFnLangItem, "start", start_fn;
|
||||
|
||||
36, TyDescStructLangItem, "ty_desc", ty_desc;
|
||||
37, TyVisitorTraitLangItem, "ty_visitor", ty_visitor;
|
||||
38, OpaqueStructLangItem, "opaque", opaque;
|
||||
37, TyDescStructLangItem, "ty_desc", ty_desc;
|
||||
38, TyVisitorTraitLangItem, "ty_visitor", ty_visitor;
|
||||
39, OpaqueStructLangItem, "opaque", opaque;
|
||||
|
||||
39, EventLoopFactoryLangItem, "event_loop_factory", event_loop_factory;
|
||||
40, EventLoopFactoryLangItem, "event_loop_factory", event_loop_factory;
|
||||
|
||||
40, TypeIdLangItem, "type_id", type_id;
|
||||
41, TypeIdLangItem, "type_id", type_id;
|
||||
}
|
||||
|
||||
|
|
|
@ -737,6 +737,7 @@ pub enum BuiltinBound {
|
|||
BoundSend,
|
||||
BoundFreeze,
|
||||
BoundSized,
|
||||
BoundPod,
|
||||
}
|
||||
|
||||
pub fn EmptyBuiltinBounds() -> BuiltinBounds {
|
||||
|
@ -1805,6 +1806,9 @@ def_type_content_sets!(
|
|||
// Things that prevent values from being considered sized
|
||||
Nonsized = 0b0000__00000000__0001,
|
||||
|
||||
// Things that make values considered not POD (same as `Moves`)
|
||||
Nonpod = 0b0000__00001111__0000,
|
||||
|
||||
// Bits to set when a managed value is encountered
|
||||
//
|
||||
// [1] Do not set the bits TC::OwnsManaged or
|
||||
|
@ -1828,6 +1832,7 @@ impl TypeContents {
|
|||
BoundFreeze => self.is_freezable(cx),
|
||||
BoundSend => self.is_sendable(cx),
|
||||
BoundSized => self.is_sized(cx),
|
||||
BoundPod => self.is_pod(cx),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1859,6 +1864,10 @@ impl TypeContents {
|
|||
!self.intersects(TC::Nonsized)
|
||||
}
|
||||
|
||||
pub fn is_pod(&self, _: ctxt) -> bool {
|
||||
!self.intersects(TC::Nonpod)
|
||||
}
|
||||
|
||||
pub fn moves_by_default(&self, _: ctxt) -> bool {
|
||||
self.intersects(TC::Moves)
|
||||
}
|
||||
|
@ -1876,15 +1885,32 @@ impl TypeContents {
|
|||
*self & (TC::OwnsAll | TC::ReachesAll))
|
||||
}
|
||||
|
||||
pub fn other_pointer(&self, bits: TypeContents) -> TypeContents {
|
||||
pub fn reference(&self, bits: TypeContents) -> TypeContents {
|
||||
/*!
|
||||
* Includes only those bits that still apply
|
||||
* when indirected through a non-owning pointer (`&`, `@`)
|
||||
* when indirected through a reference (`&`)
|
||||
*/
|
||||
bits | (
|
||||
*self & TC::ReachesAll)
|
||||
}
|
||||
|
||||
pub fn managed_pointer(&self) -> TypeContents {
|
||||
/*!
|
||||
* Includes only those bits that still apply
|
||||
* when indirected through a managed pointer (`@`)
|
||||
*/
|
||||
TC::Managed | (
|
||||
*self & TC::ReachesAll)
|
||||
}
|
||||
|
||||
pub fn unsafe_pointer(&self) -> TypeContents {
|
||||
/*!
|
||||
* Includes only those bits that still apply
|
||||
* when indirected through an unsafe pointer (`*`)
|
||||
*/
|
||||
*self & TC::ReachesAll
|
||||
}
|
||||
|
||||
pub fn union<T>(v: &[T], f: |&T| -> TypeContents) -> TypeContents {
|
||||
v.iter().fold(TC::None, |tc, t| tc | f(t))
|
||||
}
|
||||
|
@ -1994,7 +2020,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
|
|||
}
|
||||
|
||||
ty_box(mt) => {
|
||||
tc_mt(cx, mt, cache).other_pointer(TC::Managed)
|
||||
tc_mt(cx, mt, cache).managed_pointer()
|
||||
}
|
||||
|
||||
ty_trait(_, _, store, mutbl, bounds) => {
|
||||
|
@ -2002,11 +2028,11 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
|
|||
}
|
||||
|
||||
ty_ptr(ref mt) => {
|
||||
tc_ty(cx, mt.ty, cache).other_pointer(TC::None)
|
||||
tc_ty(cx, mt.ty, cache).unsafe_pointer()
|
||||
}
|
||||
|
||||
ty_rptr(r, ref mt) => {
|
||||
tc_ty(cx, mt.ty, cache).other_pointer(
|
||||
tc_ty(cx, mt.ty, cache).reference(
|
||||
borrowed_contents(r, mt.mutbl))
|
||||
}
|
||||
|
||||
|
@ -2019,11 +2045,11 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
|
|||
}
|
||||
|
||||
ty_evec(mt, vstore_box) => {
|
||||
tc_mt(cx, mt, cache).other_pointer(TC::Managed)
|
||||
tc_mt(cx, mt, cache).managed_pointer()
|
||||
}
|
||||
|
||||
ty_evec(ref mt, vstore_slice(r)) => {
|
||||
tc_ty(cx, mt.ty, cache).other_pointer(
|
||||
tc_ty(cx, mt.ty, cache).reference(
|
||||
borrowed_contents(r, mt.mutbl))
|
||||
}
|
||||
|
||||
|
@ -2193,10 +2219,10 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
|
|||
contents.owned_pointer()
|
||||
}
|
||||
BoxTraitStore => {
|
||||
contents.other_pointer(TC::Managed)
|
||||
contents.managed_pointer()
|
||||
}
|
||||
RegionTraitStore(r) => {
|
||||
contents.other_pointer(borrowed_contents(r, mutbl))
|
||||
contents.reference(borrowed_contents(r, mutbl))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2213,6 +2239,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
|
|||
BoundSend => TC::Nonsendable,
|
||||
BoundFreeze => TC::Nonfreezable,
|
||||
BoundSized => TC::Nonsized,
|
||||
BoundPod => TC::Nonpod,
|
||||
};
|
||||
});
|
||||
return tc;
|
||||
|
|
|
@ -639,6 +639,7 @@ impl Repr for ty::ParamBounds {
|
|||
ty::BoundSend => ~"Send",
|
||||
ty::BoundFreeze => ~"Freeze",
|
||||
ty::BoundSized => ~"Sized",
|
||||
ty::BoundPod => ~"Pod",
|
||||
});
|
||||
}
|
||||
for t in self.trait_bounds.iter() {
|
||||
|
@ -926,6 +927,7 @@ impl UserString for ty::BuiltinBound {
|
|||
ty::BoundSend => ~"Send",
|
||||
ty::BoundFreeze => ~"Freeze",
|
||||
ty::BoundSized => ~"Sized",
|
||||
ty::BoundPod => ~"Pod",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,3 +37,13 @@ pub trait Freeze {
|
|||
pub trait Sized {
|
||||
// Empty.
|
||||
}
|
||||
|
||||
/// Types that can be copied by simply copying bits (i.e. `memcpy`).
|
||||
///
|
||||
/// The name "POD" stands for "Plain Old Data" and is borrowed from C++.
|
||||
#[cfg(not(stage0))]
|
||||
#[lang="pod"]
|
||||
pub trait Pod {
|
||||
// Empty.
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,9 @@ pub use ops::{Shl, Shr, Index};
|
|||
pub use option::{Option, Some, None};
|
||||
pub use result::{Result, Ok, Err};
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
pub use kinds::Pod;
|
||||
|
||||
// Reexported functions
|
||||
pub use from_str::from_str;
|
||||
pub use iter::range;
|
||||
|
|
78
src/test/compile-fail/kindck-pod.rs
Normal file
78
src/test/compile-fail/kindck-pod.rs
Normal file
|
@ -0,0 +1,78 @@
|
|||
// 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 <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.
|
||||
|
||||
// Test which of the builtin types are considered POD.
|
||||
|
||||
fn assert_pod<T:Pod>() { }
|
||||
trait Dummy { }
|
||||
|
||||
struct MyStruct {
|
||||
x: int,
|
||||
y: int,
|
||||
}
|
||||
|
||||
struct MyNonpodStruct {
|
||||
x: ~int,
|
||||
}
|
||||
|
||||
fn test<'a,T,U:Pod>(_: &'a int) {
|
||||
// lifetime pointers are ok...
|
||||
assert_pod::<&'static int>();
|
||||
assert_pod::<&'a int>();
|
||||
assert_pod::<&'a str>();
|
||||
assert_pod::<&'a [int]>();
|
||||
|
||||
// ...unless they are mutable
|
||||
assert_pod::<&'static mut int>(); //~ ERROR does not fulfill `Pod`
|
||||
assert_pod::<&'a mut int>(); //~ ERROR does not fulfill `Pod`
|
||||
|
||||
// ~ pointers are not ok
|
||||
assert_pod::<~int>(); //~ ERROR does not fulfill `Pod`
|
||||
assert_pod::<~str>(); //~ ERROR does not fulfill `Pod`
|
||||
assert_pod::<~[int]>(); //~ ERROR does not fulfill `Pod`
|
||||
assert_pod::<~&'a mut int>(); //~ ERROR does not fulfill `Pod`
|
||||
|
||||
// borrowed object types are generally ok
|
||||
assert_pod::<&'a Dummy>();
|
||||
assert_pod::<&'a Dummy:Pod>();
|
||||
assert_pod::<&'static Dummy:Pod>();
|
||||
|
||||
// owned object types are not ok
|
||||
assert_pod::<~Dummy>(); //~ ERROR does not fulfill `Pod`
|
||||
assert_pod::<~Dummy:Pod>(); //~ ERROR does not fulfill `Pod`
|
||||
|
||||
// mutable object types are not ok
|
||||
assert_pod::<&'a mut Dummy:Pod>(); //~ ERROR does not fulfill `Pod`
|
||||
|
||||
// closures are like an `&mut` object
|
||||
assert_pod::<||>(); //~ ERROR does not fulfill `Pod`
|
||||
|
||||
// unsafe ptrs are ok
|
||||
assert_pod::<*int>();
|
||||
assert_pod::<*&'a mut int>();
|
||||
|
||||
// regular old ints and such are ok
|
||||
assert_pod::<int>();
|
||||
assert_pod::<bool>();
|
||||
assert_pod::<()>();
|
||||
|
||||
// tuples are ok
|
||||
assert_pod::<(int,int)>();
|
||||
|
||||
// structs of POD are ok
|
||||
assert_pod::<MyStruct>();
|
||||
|
||||
// structs containing non-POD are not ok
|
||||
assert_pod::<MyNonpodStruct>(); //~ ERROR does not fulfill `Pod`
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue