auto merge of : pcwalton/rust/pod, r=pcwalton

This will be used for the new `Cell`.

r? @nikomatsakis
This commit is contained in:
bors 2013-12-16 22:56:45 -08:00
commit 2c41a823cc
10 changed files with 303 additions and 49 deletions

@ -3329,6 +3329,12 @@ The kinds are:
This kind includes scalars, owning pointers, owned closures, and
structural types containing only other owned types.
All `Send` types are `'static`.
`Pod`
: Types of this kind consist of "Plain Old Data"
which can be copied by simply moving bits.
All values of this kind can be implicitly copied.
This kind includes scalars and immutable references,
as well as structural types containing other `Pod` types.
`'static`
: Types of this kind do not contain any borrowed pointers;
this can be a useful guarantee for code

@ -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",
}
}
}

@ -14,6 +14,71 @@ use prelude::*;
use cast;
use util::NonCopyable;
#[cfg(stage0)]
use unstable::intrinsics;
/// A mutable memory location that admits only `Pod` data.
#[no_freeze]
#[deriving(Clone)]
pub struct Cell<T> {
priv value: T,
}
// NB: For `stage0`, we omit the `Pod` bound. This is unsound but will help
// us get started on removing `@mut` from `rustc`.
#[cfg(stage0)]
impl<T> Cell<T> {
/// Creates a new `Cell` containing the given value.
pub fn new(value: T) -> Cell<T> {
Cell {
value: value,
}
}
/// Returns a copy of the contained value.
#[inline]
pub fn get(&self) -> T {
unsafe {
let mut result = intrinsics::uninit();
intrinsics::copy_nonoverlapping_memory(&mut result, &self.value, 1);
result
}
}
/// Sets the contained value.
#[inline]
pub fn set(&self, value: T) {
unsafe {
intrinsics::copy_nonoverlapping_memory(cast::transmute_mut(&self.value), &value, 1)
}
}
}
#[cfg(not(stage0))]
impl<T: ::kinds::Pod> Cell<T> {
/// Creates a new `Cell` containing the given value.
pub fn new(value: T) -> Cell<T> {
Cell {
value: value,
}
}
/// Returns a copy of the contained value.
#[inline]
pub fn get(&self) -> T {
self.value
}
/// Sets the contained value.
#[inline]
pub fn set(&self, value: T) {
unsafe {
*cast::transmute_mut(&self.value) = value
}
}
}
/// A mutable memory location with dynamically checked borrow rules
#[no_freeze]
pub struct RefCell<T> {
@ -132,6 +197,30 @@ impl<T> RefCell<T> {
let mut ptr = self.borrow_mut();
blk(ptr.get())
}
/// Sets the value, replacing what was there.
///
/// # Failure
///
/// Fails if the value is currently borrowed.
#[inline]
pub fn set(&self, value: T) {
let mut reference = self.borrow_mut();
*reference.get() = value
}
}
impl<T:Clone> RefCell<T> {
/// Returns a copy of the contained value.
///
/// # Failure
///
/// Fails if the value is currently mutably borrowed.
#[inline]
pub fn get(&self) -> T {
let reference = self.borrow();
(*reference.get()).clone()
}
}
impl<T: Clone> Clone for RefCell<T> {
@ -202,6 +291,17 @@ impl<'b, T> RefMut<'b, T> {
mod test {
use super::*;
#[test]
fn smoketest_cell() {
let x = Cell::new(10);
assert_eq!(x.get(), 10);
x.set(20);
assert_eq!(x.get(), 20);
let y = Cell::new((30, 40));
assert_eq!(y.get(), (30, 40));
}
#[test]
fn double_imm_borrow() {
let x = RefCell::new(0);

@ -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;

@ -0,0 +1,86 @@
// 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.
#[feature(managed_boxes)];
use std::rc::Rc;
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`
// managed or ref counted types are not ok
assert_pod::<@int>(); //~ ERROR does not fulfill `Pod`
assert_pod::<Rc<int>>(); //~ ERROR does not fulfill `Pod`
}
pub fn main() {
}

@ -0,0 +1,15 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Tests that type parameters with the `Pod` are implicitly copyable.
#[allow(dead_code)];
fn can_copy_pod<T:Pod>(v: T) {
let _a = v;
let _b = v;
}
pub fn main() {}