From 37154fb8b939e9f81d9feb8139c7879099fb5cd6 Mon Sep 17 00:00:00 2001 From: Flavio Percoco Date: Mon, 3 Mar 2014 23:27:46 +0100 Subject: [PATCH] Add a Share kind Fixes #11781 --- src/librustc/metadata/tydecode.rs | 3 ++ src/librustc/metadata/tyencode.rs | 1 + src/librustc/middle/lang_items.rs | 16 +++++---- src/librustc/middle/ty.rs | 58 +++++++++++++++++++------------ src/librustc/util/ppaux.rs | 2 ++ src/libstd/kinds.rs | 23 ++++++++++++ src/libstd/prelude.rs | 2 +- 7 files changed, 76 insertions(+), 29 deletions(-) diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index 1abbf1307c119..157cc8cd0f08d 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -603,6 +603,9 @@ fn parse_bounds(st: &mut PState, conv: conv_did) -> ty::ParamBounds { 'P' => { param_bounds.builtin_bounds.add(ty::BoundPod); } + 'T' => { + param_bounds.builtin_bounds.add(ty::BoundShare); + } 'I' => { param_bounds.trait_bounds.push(@parse_trait_ref(st, |x,y| conv(x,y))); } diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index 0934b6407fb74..792fca5eca679 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -410,6 +410,7 @@ fn enc_bounds(w: &mut MemWriter, cx: &ctxt, bs: &ty::ParamBounds) { ty::BoundStatic => mywrite!(w, "O"), ty::BoundSized => mywrite!(w, "Z"), ty::BoundPod => mywrite!(w, "P"), + ty::BoundShare => mywrite!(w, "T"), } } diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 3b322d0278762..4e16683bcba04 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -22,7 +22,7 @@ use driver::session::Session; use metadata::csearch::each_lang_item; -use middle::ty::{BuiltinBound, BoundFreeze, BoundPod, BoundSend, BoundSized}; +use middle::ty; use syntax::ast; use syntax::ast_util::local_def; use syntax::attr::AttrMetaMethods; @@ -82,15 +82,17 @@ impl LanguageItems { } } - pub fn to_builtin_kind(&self, id: ast::DefId) -> Option { + pub fn to_builtin_kind(&self, id: ast::DefId) -> Option { if Some(id) == self.freeze_trait() { - Some(BoundFreeze) + Some(ty::BoundFreeze) } else if Some(id) == self.send_trait() { - Some(BoundSend) + Some(ty::BoundSend) } else if Some(id) == self.sized_trait() { - Some(BoundSized) + Some(ty::BoundSized) } else if Some(id) == self.pod_trait() { - Some(BoundPod) + Some(ty::BoundPod) + } else if Some(id) == self.share_trait() { + Some(ty::BoundShare) } else { None } @@ -213,6 +215,7 @@ lets_do_this! { SendTraitLangItem, "send", send_trait; SizedTraitLangItem, "sized", sized_trait; PodTraitLangItem, "pod", pod_trait; + ShareTraitLangItem, "share", share_trait; DropTraitLangItem, "drop", drop_trait; @@ -274,5 +277,6 @@ lets_do_this! { NoFreezeItem, "no_freeze_bound", no_freeze_bound; NoSendItem, "no_send_bound", no_send_bound; NoPodItem, "no_pod_bound", no_pod_bound; + NoShareItem, "no_share_bound", no_share_bound; ManagedItem, "managed_bound", managed_bound; } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 61371cec49ea5..00ccadc68c600 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -850,6 +850,7 @@ pub enum BuiltinBound { BoundFreeze, BoundSized, BoundPod, + BoundShare, } pub fn EmptyBuiltinBounds() -> BuiltinBounds { @@ -862,6 +863,7 @@ pub fn AllBuiltinBounds() -> BuiltinBounds { set.add(BoundSend); set.add(BoundFreeze); set.add(BoundSized); + set.add(BoundShare); set } @@ -1872,31 +1874,32 @@ macro_rules! def_type_content_sets( def_type_content_sets!( mod TC { - None = 0b0000__00000000__0000, + None = 0b0000_0000__0000_0000__0000, // Things that are interior to the value (first nibble): - InteriorUnsized = 0b0000__00000000__0001, - // InteriorAll = 0b0000__00000000__1111, + InteriorUnsized = 0b0000_0000__0000_0000__0001, + // InteriorAll = 0b0000_0000__0000_0000__1111, // Things that are owned by the value (second and third nibbles): - OwnsOwned = 0b0000__00000001__0000, - OwnsDtor = 0b0000__00000010__0000, - OwnsManaged /* see [1] below */ = 0b0000__00000100__0000, - OwnsAffine = 0b0000__00001000__0000, - OwnsAll = 0b0000__11111111__0000, + OwnsOwned = 0b0000_0000__0000_0001__0000, + OwnsDtor = 0b0000_0000__0000_0010__0000, + OwnsManaged /* see [1] below */ = 0b0000_0000__0000_0100__0000, + OwnsAffine = 0b0000_0000__0000_1000__0000, + OwnsAll = 0b0000_0000__1111_1111__0000, // Things that are reachable by the value in any way (fourth nibble): - ReachesNonsendAnnot = 0b0001__00000000__0000, - ReachesBorrowed = 0b0010__00000000__0000, - // ReachesManaged /* see [1] below */ = 0b0100__00000000__0000, - ReachesMutable = 0b1000__00000000__0000, - ReachesAll = 0b1111__00000000__0000, + ReachesNonsendAnnot = 0b0000_0001__0000_0000__0000, + ReachesBorrowed = 0b0000_0010__0000_0000__0000, + // ReachesManaged /* see [1] below */ = 0b0000_0100__0000_0000__0000, + ReachesMutable = 0b0000_1000__0000_0000__0000, + ReachesNoShare = 0b0001_0000__0000_0000__0000, + ReachesAll = 0b0001_1111__0000_0000__0000, // Things that cause values to *move* rather than *copy* - Moves = 0b0000__00001011__0000, + Moves = 0b0000_0000__0000_1011__0000, // Things that mean drop glue is necessary - NeedsDrop = 0b0000__00000111__0000, + NeedsDrop = 0b0000_0000__0000_0111__0000, // Things that prevent values from being sent // @@ -1905,31 +1908,34 @@ def_type_content_sets!( // both ReachesManaged and OwnsManaged so that when // a parameter has a bound T:Send, we are able to deduce // that it neither reaches nor owns a managed pointer. - Nonsendable = 0b0111__00000100__0000, + Nonsendable = 0b0000_0111__0000_0100__0000, // Things that prevent values from being considered freezable - Nonfreezable = 0b1000__00000000__0000, + Nonfreezable = 0b0000_1000__0000_0000__0000, // Things that prevent values from being considered 'static - Nonstatic = 0b0010__00000000__0000, + Nonstatic = 0b0000_0010__0000_0000__0000, // Things that prevent values from being considered sized - Nonsized = 0b0000__00000000__0001, + Nonsized = 0b0000_0000__0000_0000__0001, + + // Things that prevent values from being shared + Nonsharable = 0b0001_0000__0000_0000__0000, // Things that make values considered not POD (would be same // as `Moves`, but for the fact that managed data `@` is // not considered POD) - Nonpod = 0b0000__00001111__0000, + Nonpod = 0b0000_0000__0000_1111__0000, // Bits to set when a managed value is encountered // // [1] Do not set the bits TC::OwnsManaged or // TC::ReachesManaged directly, instead reference // TC::Managed to set them both at once. - Managed = 0b0100__00000100__0000, + Managed = 0b0000_0100__0000_0100__0000, // All bits - All = 0b1111__11111111__1111 + All = 0b1111_1111__1111_1111__1111 } ) @@ -1945,6 +1951,7 @@ impl TypeContents { BoundSend => self.is_sendable(cx), BoundSized => self.is_sized(cx), BoundPod => self.is_pod(cx), + BoundShare => self.is_sharable(cx), } } @@ -1964,6 +1971,10 @@ impl TypeContents { !self.intersects(TC::Nonsendable) } + pub fn is_sharable(&self, _: &ctxt) -> bool { + !self.intersects(TC::Nonsharable) + } + pub fn owns_managed(&self) -> bool { self.intersects(TC::OwnsManaged) } @@ -2284,6 +2295,8 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents { tc | TC::Managed } else if Some(did) == cx.lang_items.no_pod_bound() { tc | TC::OwnsAffine + } else if Some(did) == cx.lang_items.no_share_bound() { + tc | TC::ReachesNoShare } else { tc } @@ -2362,6 +2375,7 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents { BoundFreeze => TC::Nonfreezable, BoundSized => TC::Nonsized, BoundPod => TC::Nonpod, + BoundShare => TC::Nonsharable, }; }); return tc; diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 7c03c1dc45dfb..2b6c6825c7e3f 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -674,6 +674,7 @@ impl Repr for ty::ParamBounds { ty::BoundFreeze => ~"Freeze", ty::BoundSized => ~"Sized", ty::BoundPod => ~"Pod", + ty::BoundShare => ~"Share", }); } for t in self.trait_bounds.iter() { @@ -961,6 +962,7 @@ impl UserString for ty::BuiltinBound { ty::BoundFreeze => ~"Freeze", ty::BoundSized => ~"Sized", ty::BoundPod => ~"Pod", + ty::BoundShare => ~"Share", } } } diff --git a/src/libstd/kinds.rs b/src/libstd/kinds.rs index da17119fd984c..b44616421d182 100644 --- a/src/libstd/kinds.rs +++ b/src/libstd/kinds.rs @@ -46,6 +46,22 @@ pub trait Pod { // Empty. } +/// Types that can be safely shared between threads, hence thread-safe. +#[cfg(stage0)] +pub trait Share { + // Empty +} + +#[cfg(stage0)] +impl Share for T {} + +/// Types that can be safely shared between threads, hence thread-safe. +#[cfg(not(stage0))] +#[lang="share"] +pub trait Share { + // Empty +} + /// Marker types are special types that are used with unsafe code to /// inform the compiler of special constraints. Marker types should /// only be needed when you are creating an abstraction that is @@ -232,6 +248,13 @@ pub mod marker { #[deriving(Eq,Clone)] pub struct NoPod; + /// A type which is considered "not sharable", meaning that + /// its contents are not threadsafe, hence they cannot be + /// shared between tasks. + #[lang="no_share_bound"] + #[deriving(Eq,Clone)] + pub struct NoShare; + /// A type which is considered managed by the GC. This is typically /// embedded in other types. #[lang="managed_bound"] diff --git a/src/libstd/prelude.rs b/src/libstd/prelude.rs index 0b1de74330d14..f3a5bd3d3b582 100644 --- a/src/libstd/prelude.rs +++ b/src/libstd/prelude.rs @@ -20,7 +20,7 @@ generally useful to many Rust programs. */ // Reexported core operators -pub use kinds::{Freeze, Pod, Send, Sized}; +pub use kinds::{Freeze, Pod, Send, Sized, Share}; pub use ops::{Add, Sub, Mul, Div, Rem, Neg, Not}; pub use ops::{BitAnd, BitOr, BitXor}; pub use ops::{Drop, Deref, DerefMut};