diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 94bf3368a0aaf..9e6e58ee16e8e 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -57,6 +57,8 @@ pub struct Arc { _ptr: *mut ArcInner, } +impl Share for Arc {} + /// A weak pointer to an `Arc`. /// /// Weak pointers will not keep the data inside of the `Arc` alive, and can be @@ -68,12 +70,16 @@ pub struct Weak { _ptr: *mut ArcInner, } +impl Share for Weak {} + struct ArcInner { strong: atomics::AtomicUint, weak: atomics::AtomicUint, data: T, } +impl Share for ArcInner {} + impl Arc { /// Create an atomically reference counted wrapper. #[inline] diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index ca7de131dc212..8c8cbf5964cce 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -196,6 +196,7 @@ mod std { pub use core::fmt; // necessary for fail!() pub use core::option; // necessary for fail!() pub use core::clone; // deriving(Clone) + pub use core::kinds; // deriving(Share,Send,Copy) pub use core::cmp; // deriving(Eq, Ord, etc.) pub use hash; // deriving(Hash) } diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 76f53c9b25749..3497d9abce10d 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -1,3 +1,4 @@ + // Copyright 2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. @@ -25,7 +26,7 @@ use str::{CharRange, StrAllocating}; use vec::Vec; /// A growable string stored as a UTF-8 encoded buffer. -#[deriving(Clone, PartialEq, PartialOrd, Eq, Ord)] +#[deriving(Clone, PartialEq, PartialOrd, Eq, Ord, Share)] pub struct String { vec: Vec, } diff --git a/src/libcollections/treemap.rs b/src/libcollections/treemap.rs index 02246c33317f1..6487f3de3642b 100644 --- a/src/libcollections/treemap.rs +++ b/src/libcollections/treemap.rs @@ -43,7 +43,7 @@ use vec::Vec; // These would be convenient since the methods work like `each` #[allow(missing_doc)] -#[deriving(Clone)] +#[deriving(Clone, Share)] pub struct TreeMap { root: Option>>, length: uint diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 61e732846a1a3..21bb0031d2263 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -58,6 +58,9 @@ pub struct Vec { ptr: *mut T } +impl Send for Vec {} +impl Share for Vec {} + impl Vec { /// Constructs a new, empty `Vec`. /// diff --git a/src/libcore/atomics.rs b/src/libcore/atomics.rs index 65ba11f89adc6..b64823688bc4f 100644 --- a/src/libcore/atomics.rs +++ b/src/libcore/atomics.rs @@ -15,24 +15,28 @@ use std::kinds::marker; use ty::Unsafe; /// An atomic boolean type. +#[deriving(Share)] pub struct AtomicBool { v: Unsafe, nocopy: marker::NoCopy } /// A signed atomic integer type, supporting basic atomic arithmetic operations +#[deriving(Share)] pub struct AtomicInt { v: Unsafe, nocopy: marker::NoCopy } /// An unsigned atomic integer type, supporting basic atomic arithmetic operations +#[deriving(Share)] pub struct AtomicUint { v: Unsafe, nocopy: marker::NoCopy } /// An unsafe atomic pointer. Only supports basic atomic operations +#[deriving(Share)] pub struct AtomicPtr { p: Unsafe, nocopy: marker::NoCopy diff --git a/src/libcore/bool.rs b/src/libcore/bool.rs index 146f29dd9f1da..8f47f6fd4f728 100644 --- a/src/libcore/bool.rs +++ b/src/libcore/bool.rs @@ -14,6 +14,9 @@ #![doc(primitive = "bool")] +#[cfg(not(stage0))] +use kinds::{Send, Share, Copy}; + use num::{Int, one, zero}; ///////////////////////////////////////////////////////////////////////////// @@ -35,6 +38,19 @@ pub fn to_bit(p: bool) -> N { if p { one() } else { zero() } } +///////////////////////////////////////////////////////////////////////////// +// Trait impls on `bool` +///////////////////////////////////////////////////////////////////////////// + +#[cfg(not(stage0))] +impl Send for bool { } + +#[cfg(not(stage0))] +impl Share for bool { } + +#[cfg(not(stage0))] +impl Copy for bool { } + #[cfg(test)] mod tests { use realstd::prelude::*; diff --git a/src/libcore/kinds.rs b/src/libcore/kinds.rs index 40b716181e6fc..d412da26c5c42 100644 --- a/src/libcore/kinds.rs +++ b/src/libcore/kinds.rs @@ -26,6 +26,9 @@ pub trait Send { // empty. } +#[cfg(not(stage0))] +impl Send for *T { } + /// Types with a constant size known at compile-time. #[lang="sized"] pub trait Sized { @@ -38,6 +41,13 @@ pub trait Copy { // Empty. } +#[cfg(not(stage0))] +impl Copy for *T { } + +#[cfg(not(stage0))] +impl<'a, T> Copy for &'a T { } + + /// Types that can be safely shared between tasks when aliased. /// /// The precise definition is: a type `T` is `Share` if `&T` is @@ -88,6 +98,15 @@ pub trait Share { // Empty } +#[cfg(not(stage0))] +impl Share for *T { } + +#[cfg(not(stage0))] +impl<'a,T:Share> Share for &'a T { } + +#[cfg(not(stage0))] +impl<'a,T:Share> Share for &'a mut T { } + /// 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 diff --git a/src/libcore/num/i16.rs b/src/libcore/num/i16.rs index b821ff60a730e..d8fa8ee677d66 100644 --- a/src/libcore/num/i16.rs +++ b/src/libcore/num/i16.rs @@ -12,5 +12,8 @@ #![doc(primitive = "i16")] +#[cfg(not(stage0))] +use kinds::{Share, Send, Copy}; + int_module!(i16, 16) diff --git a/src/libcore/num/i32.rs b/src/libcore/num/i32.rs index a8cab1f95b0af..f02a715b06ad2 100644 --- a/src/libcore/num/i32.rs +++ b/src/libcore/num/i32.rs @@ -12,5 +12,8 @@ #![doc(primitive = "i32")] +#[cfg(not(stage0))] +use kinds::{Share, Send, Copy}; + int_module!(i32, 32) diff --git a/src/libcore/num/i64.rs b/src/libcore/num/i64.rs index 6009b953bb4db..7cf2070133d4d 100644 --- a/src/libcore/num/i64.rs +++ b/src/libcore/num/i64.rs @@ -12,5 +12,8 @@ #![doc(primitive = "i64")] +#[cfg(not(stage0))] +use kinds::{Share, Send, Copy}; + int_module!(i64, 64) diff --git a/src/libcore/num/i8.rs b/src/libcore/num/i8.rs index b3a5557b20c7f..580403944cd63 100644 --- a/src/libcore/num/i8.rs +++ b/src/libcore/num/i8.rs @@ -12,5 +12,8 @@ #![doc(primitive = "i8")] +#[cfg(not(stage0))] +use kinds::{Share, Send, Copy}; + int_module!(i8, 8) diff --git a/src/libcore/num/int.rs b/src/libcore/num/int.rs index 06d64e73abd49..337e11a04b6e2 100644 --- a/src/libcore/num/int.rs +++ b/src/libcore/num/int.rs @@ -12,6 +12,9 @@ #![doc(primitive = "int")] +#[cfg(not(stage0))] +use kinds::{Share, Send, Copy}; + #[cfg(target_word_size = "32")] int_module!(int, 32) #[cfg(target_word_size = "64")] int_module!(int, 64) diff --git a/src/libcore/num/int_macros.rs b/src/libcore/num/int_macros.rs index 79734324706b2..161d1f3650e89 100644 --- a/src/libcore/num/int_macros.rs +++ b/src/libcore/num/int_macros.rs @@ -28,6 +28,15 @@ pub static MIN: $T = (-1 as $T) << (BITS - 1); // calling the `Bounded::max_value` function. pub static MAX: $T = !MIN; +#[cfg(not(stage0))] +impl Send for $T { } + +#[cfg(not(stage0))] +impl Share for $T { } + +#[cfg(not(stage0))] +impl Copy for $T { } + #[cfg(test)] mod tests { use prelude::*; diff --git a/src/libcore/num/u16.rs b/src/libcore/num/u16.rs index eb4bd427d5166..a8885282a975a 100644 --- a/src/libcore/num/u16.rs +++ b/src/libcore/num/u16.rs @@ -12,4 +12,7 @@ #![doc(primitive = "u16")] +#[cfg(not(stage0))] +use kinds::{Share, Send, Copy}; + uint_module!(u16, i16, 16) diff --git a/src/libcore/num/u32.rs b/src/libcore/num/u32.rs index 9522b2e86ac63..d669c4c0d04e3 100644 --- a/src/libcore/num/u32.rs +++ b/src/libcore/num/u32.rs @@ -12,5 +12,8 @@ #![doc(primitive = "u32")] +#[cfg(not(stage0))] +use kinds::{Share, Send, Copy}; + uint_module!(u32, i32, 32) diff --git a/src/libcore/num/u64.rs b/src/libcore/num/u64.rs index 7a654f4bffa0d..0b9241d75fcc6 100644 --- a/src/libcore/num/u64.rs +++ b/src/libcore/num/u64.rs @@ -12,5 +12,8 @@ #![doc(primitive = "u64")] +#[cfg(not(stage0))] +use kinds::{Share, Send, Copy}; + uint_module!(u64, i64, 64) diff --git a/src/libcore/num/u8.rs b/src/libcore/num/u8.rs index 6a42ce07e5d18..54223fcaeb6d7 100644 --- a/src/libcore/num/u8.rs +++ b/src/libcore/num/u8.rs @@ -12,5 +12,8 @@ #![doc(primitive = "u8")] +#[cfg(not(stage0))] +use kinds::{Share, Send, Copy}; + uint_module!(u8, i8, 8) diff --git a/src/libcore/num/uint.rs b/src/libcore/num/uint.rs index 2f539fff61ae6..871c01d15e6b5 100644 --- a/src/libcore/num/uint.rs +++ b/src/libcore/num/uint.rs @@ -12,5 +12,8 @@ #![doc(primitive = "uint")] +#[cfg(not(stage0))] +use kinds::{Share, Send, Copy}; + uint_module!(uint, int, ::int::BITS) diff --git a/src/libcore/num/uint_macros.rs b/src/libcore/num/uint_macros.rs index be1f960bcc3df..e7092edf37beb 100644 --- a/src/libcore/num/uint_macros.rs +++ b/src/libcore/num/uint_macros.rs @@ -19,6 +19,15 @@ pub static BYTES : uint = ($bits / 8); pub static MIN: $T = 0 as $T; pub static MAX: $T = 0 as $T - 1 as $T; +#[cfg(not(stage0))] +impl Send for $T { } + +#[cfg(not(stage0))] +impl Share for $T { } + +#[cfg(not(stage0))] +impl Copy for $T { } + #[cfg(test)] mod tests { use prelude::*; diff --git a/src/libcore/tuple.rs b/src/libcore/tuple.rs index c8cbd49aa890d..1e0fcd1737d60 100644 --- a/src/libcore/tuple.rs +++ b/src/libcore/tuple.rs @@ -64,6 +64,7 @@ use clone::Clone; #[cfg(not(test))] use cmp::*; #[cfg(not(test))] use default::Default; +use kinds::{Copy, Send, Share}; // macro for implementing n-ary tuple functions and operations macro_rules! tuple_impls { @@ -82,6 +83,10 @@ macro_rules! tuple_impls { $(fn $mutN<'a>(&'a mut self) -> &'a mut $T;)+ } + impl<$($T:Copy),+> Copy for ($($T,)+) {} + impl<$($T:Send),+> Send for ($($T,)+) {} + impl<$($T:Share),+> Share for ($($T,)+) {} + impl<$($T),+> $Tuple<$($T),+> for ($($T,)+) { $( #[inline] diff --git a/src/libcore/ty.rs b/src/libcore/ty.rs index 47a2005fef1e6..cdef40a1cf4ff 100644 --- a/src/libcore/ty.rs +++ b/src/libcore/ty.rs @@ -10,7 +10,7 @@ //! Types dealing with unsafe actions. -use kinds::marker; +use kinds::{Share,marker}; /// Unsafe type that wraps a type T and indicates unsafe interior operations on the /// wrapped type. Types with an `Unsafe` field are considered to have an *unsafe @@ -53,6 +53,8 @@ pub struct Unsafe { pub marker1: marker::InvariantType } +impl Share for Unsafe {} + impl Unsafe { /// Static constructor diff --git a/src/libnative/io/file_unix.rs b/src/libnative/io/file_unix.rs index edf2becc77760..f0e8f66e7a4d5 100644 --- a/src/libnative/io/file_unix.rs +++ b/src/libnative/io/file_unix.rs @@ -23,6 +23,7 @@ use io::util; pub type fd_t = libc::c_int; +#[deriving(Share)] struct Inner { fd: fd_t, close_on_drop: bool, diff --git a/src/libnative/io/net.rs b/src/libnative/io/net.rs index 5dfae8d9efe64..1adf7fa83e22e 100644 --- a/src/libnative/io/net.rs +++ b/src/libnative/io/net.rs @@ -252,6 +252,7 @@ pub struct TcpStream { write_deadline: u64, } +#[deriving(Share)] struct Inner { fd: sock_t, diff --git a/src/libnative/io/pipe_unix.rs b/src/libnative/io/pipe_unix.rs index db0d1743c7279..29bfbb23e062c 100644 --- a/src/libnative/io/pipe_unix.rs +++ b/src/libnative/io/pipe_unix.rs @@ -56,6 +56,7 @@ fn addr_to_sockaddr_un(addr: &CString) -> IoResult<(libc::sockaddr_storage, uint return Ok((storage, len)); } +#[deriving(Share)] struct Inner { fd: fd_t, diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs index 970ae36238bd6..22b4d24fb7fe2 100644 --- a/src/librustc/middle/kind.rs +++ b/src/librustc/middle/kind.rs @@ -401,10 +401,25 @@ pub fn check_builtin_bounds(cx: &Context, let kind = ty::type_contents(cx.tcx, ty); let mut missing = ty::empty_builtin_bounds(); for bound in bounds.iter() { - if !kind.meets_bound(cx.tcx, bound) { + // FIXME(flaper87): This is temporary. The reason + // this code is here is because we'll move one trait + // at a time. Remaining traits will still rely on + // TypeContents. + let meets_bound = match bound { + ty::BoundStatic => kind.is_static(cx.tcx), + ty::BoundSend => kind.is_sendable(cx.tcx), + ty::BoundSized => kind.is_sized(cx.tcx), + ty::BoundCopy => kind.is_copy(cx.tcx), + ty::BoundShare => { + ty::type_fulfills_share(cx.tcx, ty) + } + }; + + if !meets_bound { missing.add(bound); } } + if !missing.is_empty() { any_missing(missing); } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index c5e84b8e0c8f0..cfd333f14b33e 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -2148,8 +2148,9 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents { fn apply_lang_items(cx: &ctxt, did: ast::DefId, - tc: TypeContents) + mut tc: TypeContents) -> TypeContents { + tc = tc | TC::ReachesNoShare; if Some(did) == cx.lang_items.no_send_bound() { tc | TC::ReachesNonsendAnnot } else if Some(did) == cx.lang_items.managed_bound() { @@ -2157,7 +2158,9 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents { } else if Some(did) == cx.lang_items.no_copy_bound() { tc | TC::OwnsAffine } else if Some(did) == cx.lang_items.no_share_bound() { - tc | TC::ReachesNoShare + // Do nothing! We now consider everything NoShare, + // unless Share is explicitly implemented. + tc } else if Some(did) == cx.lang_items.unsafe_type() { // FIXME(#13231): This shouldn't be needed after // opt-in built-in bounds are implemented. @@ -3461,6 +3464,60 @@ pub fn provided_trait_methods(cx: &ctxt, id: ast::DefId) -> Vec> { } } +pub fn node_fulfills_trait(cx: &ctxt, id: ast::NodeId, trait_ref: Rc) -> bool { + let ty = node_id_to_type(cx, id); + type_fulfills_trait(cx, ty, trait_ref) +} + +pub fn type_fulfills_trait(cx: &ctxt, ty: ty::t, trait_ref: Rc) -> bool { + debug!("type_fulfills_trait(ty={}, trait_ref={})", + ty_to_str(cx, ty), trait_ref.repr(cx)) + + match ty::get(ty).sty { + ty_closure(ref c) => { + match cx.lang_items.to_builtin_kind(trait_ref.def_id) { + Some(bound) => { c.bounds.contains_elem(bound) } + None => false + } + } + ty_tup(ref tys) => { + tys.iter().all(|&typ| { + type_fulfills_trait(cx, typ, trait_ref.clone()) + }) + } + ty_param(ParamTy{def_id: did, ..}) => { + // NOTE(flaper87): This will likely change. It's still unsure + // what will happen w/ the BuiltinBounds but I'm leaning towards + // completely getting rid of them. + let tp_defs = cx.ty_param_defs.borrow(); + let tp_def = tp_defs.get(&did.node); + let bi_kind = cx.lang_items.to_builtin_kind(trait_ref.def_id); + + debug!("ty_param(builtin_bounds={:?}, trait_bounds={:?})", + tp_def.bounds.builtin_bounds, tp_def.bounds.trait_bounds) + tp_def.bounds.builtin_bounds.contains_elem(bi_kind.unwrap()) || + tp_def.bounds.trait_bounds.contains(&trait_ref) + } + _ => { + + let target_trait_ref = Rc::new(ty::TraitRef { + def_id: trait_ref.def_id, + substs: subst::Substs::new_trait(Vec::new(), + Vec::new(), + ty) + }); + + typeck::check::vtable::ty_trait_vtable(cx, ty, target_trait_ref).is_some() + } + } +} + +pub fn type_fulfills_share(cx: &ctxt, t: ty::t) -> bool { + let did = cx.lang_items.share_trait().unwrap(); + let tdef = lookup_trait_def(cx, did); + type_fulfills_trait(cx, t, tdef.trait_ref.clone()) +} + pub fn trait_supertraits(cx: &ctxt, id: ast::DefId) -> Rc>> { // Check the cache. match cx.supertraits.borrow().find(&id) { @@ -3485,6 +3542,10 @@ pub fn trait_ref_supertraits(cx: &ctxt, trait_ref: &ty::TraitRef) -> Vec bool { + cx.lang_items.to_builtin_kind(trait_ref.def_id).is_some() +} + fn lookup_locally_or_in_crate_store( descr: &str, def_id: ast::DefId, diff --git a/src/librustc/middle/typeck/check/bounds.rs b/src/librustc/middle/typeck/check/bounds.rs new file mode 100644 index 0000000000000..dadf8d88496de --- /dev/null +++ b/src/librustc/middle/typeck/check/bounds.rs @@ -0,0 +1,113 @@ +// Copyright 2012-2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + +/// Bounds Checkers +/// This runs after the type checker and enforces that built-in trait +/// implementations are fulfilled by the type they are implemented on. +/// For a `struct` to fulfill a built-in trait B, all its fields types +/// must have implement such trait. + +use middle::ty; +use middle::typeck::{CrateCtxt}; +use util::ppaux; +use syntax::ast; +use syntax::codemap::Span; +use syntax::visit::Visitor; +use syntax::visit; +use syntax::print::pprust; + + +struct BoundContext<'a> { + tcx: &'a ty::ctxt +} + +impl<'a> BoundContext<'a> { + fn report_error(&self, i: &ast::Item, note_span: Span, error: &str, msg: &str) { + self.tcx.sess.span_err(i.span, error); + self.tcx.sess.span_note(note_span, msg); + } +} + +impl<'a> Visitor<()> for BoundContext<'a> { + + fn visit_item(&mut self, i: &ast::Item, _: ()) { + match i.node { + ast::ItemImpl(_, Some(ref trait_ref), _, _) => { + let tref = ty::node_id_to_trait_ref(self.tcx, trait_ref.ref_id); + if !ty::is_built_in_trait(self.tcx, &*tref) { + return + } + + debug!("built-in trait implementation found: item={}", + pprust::item_to_str(i)) + + // `nty` is `Type` in `impl Trait for Type` + let nty = ty::node_id_to_type(self.tcx, i.id); + match ty::get(nty).sty { + ty::ty_struct(did, ref substs) => { + let fields = ty::lookup_struct_fields(self.tcx, did); + let span = self.tcx.map.span(did.node); + + for field in fields.iter() { + let fty = ty::lookup_field_type(self.tcx, did, field.id, substs); + if !ty::type_fulfills_trait(self.tcx, fty, tref.clone()) { + self.report_error(i, span, + format!("cannot implement the trait `{}` \ + on type `{}` because the field with type \ + `{}` doesn't fulfill such trait.", + ppaux::trait_ref_to_str(self.tcx, + &*tref), + ppaux::ty_to_str(self.tcx, nty), + ppaux::ty_to_str(self.tcx, fty)).as_slice(), + format!("field `{}`, declared in this struct", + ppaux::ty_to_str(self.tcx, fty)).as_slice()); + } + } + } + ty::ty_enum(did, ref substs) => { + let variants = ty::substd_enum_variants(self.tcx, did, substs); + for variant in variants.iter() { + let span = self.tcx.map.span(variant.id.node); + for arg in variant.args.iter() { + if !ty::type_fulfills_trait(self.tcx, *arg, tref.clone()) { + self.report_error(i, span, + format!("cannot implement the trait `{}` \ + on type `{}` because variant arg with type \ + `{}` doesn't fulfill such trait.", + ppaux::trait_ref_to_str(self.tcx, + &*tref), + ppaux::ty_to_str(self.tcx, nty), + ppaux::ty_to_str(self.tcx, *arg)).as_slice(), + format!("variant arg {}, declared here", + ppaux::ty_to_str(self.tcx, *arg)).as_slice()); + } + } + } + } + _ => { + self.tcx.sess.span_err(i.span, + format!("can only implement built-in trait \ + `{}` on a struct or enum", + ppaux::trait_ref_to_str(self.tcx, + &*tref)).as_slice()); + + } + } + } + _ => {} + } + } +} + +pub fn check_bounds(ccx: &CrateCtxt, krate: &ast::Crate) { + let mut visitor = BoundContext {tcx: ccx.tcx}; + visit::walk_crate(&mut visitor, krate, ()); +} diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 7b16248c2e6a2..b6ea004ea89c9 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -136,6 +136,7 @@ use syntax::visit; use syntax::visit::Visitor; use syntax; +pub mod bounds; pub mod _match; pub mod vtable; pub mod writeback; diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs index 6ac6cdce8590d..6e435486484a5 100644 --- a/src/librustc/middle/typeck/check/vtable.rs +++ b/src/librustc/middle/typeck/check/vtable.rs @@ -33,6 +33,7 @@ use std::rc::Rc; use std::collections::HashSet; use syntax::ast; use syntax::ast_util; +use syntax::codemap; use syntax::codemap::Span; use syntax::print::pprust::expr_to_str; use syntax::visit; @@ -857,6 +858,24 @@ pub fn trans_resolve_method(tcx: &ty::ctxt, id: ast::NodeId, false) } + +/// Resolve vtables for an `ty::t` after typeck has finished. +/// This is used by the built-in trait impl checker to verify +/// that a type `T` implements a built-in trait `B`. +pub fn ty_trait_vtable(tcx: &ty::ctxt, + ty: ty::t, + trait_ref: Rc) -> Option { + + + let vcx = VtableContext { + infcx: &infer::new_infer_ctxt(tcx), + param_env: &ty::construct_parameter_environment(tcx, &ty::Generics::empty(), + trait_ref.def_id.node) + }; + + lookup_vtable(&vcx, codemap::DUMMY_SP, ty, trait_ref, false) +} + impl<'a, 'b> visit::Visitor<()> for &'a FnCtxt<'b> { fn visit_expr(&mut self, ex: &ast::Expr, _: ()) { early_resolve_expr(ex, *self, false); diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index 55969b79b5241..748c903032278 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -1077,6 +1077,11 @@ fn ty_generics(ccx: &CrateCtxt, let ty = ty::mk_param(ccx.tcx, param_ty.space, param_ty.idx, param_ty.def_id); let trait_ref = instantiate_trait_ref(ccx, b, ty); + + // FIXME(flaper87): Eventually, we'll get rid of the builtin + // bounds EnumSet. When that happens, this will need to be + // changed in order to treat built-in bounds just like every + // other bound. if !ty::try_add_builtin_trait( ccx.tcx, trait_ref.def_id, &mut param_bounds.builtin_bounds) { diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs index bc2768ce214eb..c734b7012eb17 100644 --- a/src/librustc/middle/typeck/mod.rs +++ b/src/librustc/middle/typeck/mod.rs @@ -483,6 +483,9 @@ pub fn check_crate(tcx: &ty::ctxt, time(time_passes, "type checking", (), |_| check::check_item_types(&ccx, krate)); + time(time_passes, "bound checking", (), |_| + check::bounds::check_bounds(&ccx, krate)); + check_for_entry_fn(&ccx); tcx.sess.abort_if_errors(); } diff --git a/src/librustrt/exclusive.rs b/src/librustrt/exclusive.rs index 62313965768a6..7982d7ee0445a 100644 --- a/src/librustrt/exclusive.rs +++ b/src/librustrt/exclusive.rs @@ -21,6 +21,7 @@ use mutex; /// /// > **Note**: This type is not recommended for general use. The mutex provided /// > as part of `libsync` should almost always be favored. +#[deriving(Share)] pub struct Exclusive { lock: mutex::NativeMutex, data: Unsafe, diff --git a/src/librustrt/lib.rs b/src/librustrt/lib.rs index f5521886f52df..b16edccef52de 100644 --- a/src/librustrt/lib.rs +++ b/src/librustrt/lib.rs @@ -164,5 +164,5 @@ pub mod shouldnt_be_public { #[cfg(not(test))] mod std { - pub use core::{fmt, option, cmp}; + pub use core::{fmt, option, cmp, kinds}; } diff --git a/src/librustuv/queue.rs b/src/librustuv/queue.rs index a3694bfe9c2be..e9c6a4181d24d 100644 --- a/src/librustuv/queue.rs +++ b/src/librustuv/queue.rs @@ -37,6 +37,8 @@ enum Message { Decrement, } +#[deriving(Share)] +#[allow(raw_pointer_deriving)] struct State { handle: *uvll::uv_async_t, lock: NativeMutex, // see comments in async_cb for why this is needed @@ -51,6 +53,8 @@ pub struct QueuePool { } /// This type is used to send messages back to the original event loop. +#[deriving(Share)] +#[allow(raw_pointer_deriving)] pub struct Queue { queue: Arc, } diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index fa8d341e05de2..c179c0e5720dd 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -243,7 +243,7 @@ use std::vec::Vec; use Encodable; /// Represents a json value -#[deriving(Clone, PartialEq)] +#[deriving(Clone, PartialEq, Share)] pub enum Json { Number(f64), String(String), diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index a99fa016aef1d..64c47bc3e29fc 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -267,6 +267,7 @@ mod std { pub use clone; pub use cmp; pub use hash; + pub use kinds; pub use comm; // used for select!() pub use fmt; // used for any formatting strings diff --git a/src/libstd/path/posix.rs b/src/libstd/path/posix.rs index d98cfb7d8eece..7b2c2d4be05be 100644 --- a/src/libstd/path/posix.rs +++ b/src/libstd/path/posix.rs @@ -35,7 +35,7 @@ pub type StrComponents<'a> = Map<'a, &'a [u8], Option<&'a str>, Components<'a>>; /// Represents a POSIX file path -#[deriving(Clone)] +#[deriving(Clone,Share)] pub struct Path { repr: Vec, // assumed to never be empty or contain NULs sepidx: Option // index of the final separator in repr diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs index 4d6f8d0888f3e..1586eb929afea 100644 --- a/src/libstd/path/windows.rs +++ b/src/libstd/path/windows.rs @@ -73,7 +73,7 @@ pub type Components<'a> = Map<'a, Option<&'a str>, &'a [u8], // // The only error condition imposed here is valid utf-8. All other invalid paths are simply // preserved by the data structure; let the Windows API error out on them. -#[deriving(Clone)] +#[deriving(Clone,Share)] pub struct Path { repr: String, // assumed to never be empty prefix: Option, diff --git a/src/libsync/deque.rs b/src/libsync/deque.rs index f0184dc816417..c1d9cf624d78a 100644 --- a/src/libsync/deque.rs +++ b/src/libsync/deque.rs @@ -74,6 +74,7 @@ static K: int = 4; // The size in question is 1 << MIN_BITS static MIN_BITS: int = 7; +#[deriving(Share)] struct Deque { bottom: AtomicInt, top: AtomicInt, diff --git a/src/libsync/lib.rs b/src/libsync/lib.rs index a2f22bcaa6816..5038fe31e1aa8 100644 --- a/src/libsync/lib.rs +++ b/src/libsync/lib.rs @@ -76,5 +76,5 @@ mod lock; #[cfg(not(test))] mod std { - pub use core::{fmt, option, cmp, clone}; + pub use core::{fmt, option, cmp, clone, kinds}; } diff --git a/src/libsync/lock.rs b/src/libsync/lock.rs index 1fe8e8fc0db34..2fc1fdf635aa6 100644 --- a/src/libsync/lock.rs +++ b/src/libsync/lock.rs @@ -278,6 +278,8 @@ pub struct RWLock { data: Unsafe, } +impl Share for RWLock {} + /// A guard which is created by locking an rwlock in write mode. Through this /// guard the underlying data can be accessed. pub struct RWLockWriteGuard<'a, T> { diff --git a/src/libsync/mpmc_bounded_queue.rs b/src/libsync/mpmc_bounded_queue.rs index b700d57bc033d..e48936e55ff23 100644 --- a/src/libsync/mpmc_bounded_queue.rs +++ b/src/libsync/mpmc_bounded_queue.rs @@ -44,6 +44,7 @@ struct Node { value: Option, } +#[deriving(Share)] struct State { pad0: [u8, ..64], buffer: Vec>>, @@ -55,6 +56,7 @@ struct State { pad3: [u8, ..64], } +#[deriving(Share)] pub struct Queue { state: Arc>, } diff --git a/src/libsync/mpsc_queue.rs b/src/libsync/mpsc_queue.rs index 4bb0acf580c57..4ca809996eba5 100644 --- a/src/libsync/mpsc_queue.rs +++ b/src/libsync/mpsc_queue.rs @@ -69,6 +69,8 @@ struct Node { /// The multi-producer single-consumer structure. This is not cloneable, but it /// may be safely shared so long as it is guaranteed that there is only one /// popper at a time (many pushers are allowed). +#[deriving(Share)] +#[allow(raw_pointer_deriving)] pub struct Queue { head: AtomicPtr>, tail: Unsafe<*mut Node>, diff --git a/src/test/auxiliary/issue-2526.rs b/src/test/auxiliary/issue-2526.rs index c6ca0f3ed7bdd..f86796eac5d8b 100644 --- a/src/test/auxiliary/issue-2526.rs +++ b/src/test/auxiliary/issue-2526.rs @@ -36,6 +36,7 @@ fn init() -> arc_destruct { arc(context_res()) } +#[deriving(Share)] struct context_res { ctx : int, } diff --git a/src/test/compile-fail/builtin-superkinds-double-superkind.rs b/src/test/compile-fail/builtin-superkinds-double-superkind.rs index 7de38e6173be1..4ffc49fd7df68 100644 --- a/src/test/compile-fail/builtin-superkinds-double-superkind.rs +++ b/src/test/compile-fail/builtin-superkinds-double-superkind.rs @@ -13,10 +13,10 @@ trait Foo : Send+Share { } -impl Foo for (T,) { } //~ ERROR cannot implement this trait +impl Foo for (T,) { } //~ ERROR cannot implement this trait -impl Foo for (T,T) { } //~ ERROR cannot implement this trait +impl Foo for (T,T) { } //~ ERROR cannot implement this trait -impl Foo for (T,T,T) { } // (ok) +impl Foo for (T,T,T) { } // (ok) fn main() { } diff --git a/src/test/compile-fail/builtin-superkinds-in-metadata.rs b/src/test/compile-fail/builtin-superkinds-in-metadata.rs index 66809aa72dc8d..ffe3d39414ae7 100644 --- a/src/test/compile-fail/builtin-superkinds-in-metadata.rs +++ b/src/test/compile-fail/builtin-superkinds-in-metadata.rs @@ -19,6 +19,8 @@ use trait_superkinds_in_metadata::{RequiresRequiresShareAndSend, RequiresShare}; struct X(T); +impl Share for X {} + impl RequiresShare for X { } impl RequiresRequiresShareAndSend for X { } //~ ERROR cannot implement this trait diff --git a/src/test/compile-fail/mutable-enum-indirect.rs b/src/test/compile-fail/mutable-enum-indirect.rs index e480ebfd3781f..ca5d6712c74a4 100644 --- a/src/test/compile-fail/mutable-enum-indirect.rs +++ b/src/test/compile-fail/mutable-enum-indirect.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-test + // Tests that an `&` pointer to something inherently mutable is itself // to be considered mutable. @@ -15,9 +17,15 @@ use std::kinds::marker; enum Foo { A(marker::NoShare) } -fn bar(_: T) {} +trait Test {} + +impl<'a> Test for &'a Foo {} + +fn bar(_: T) {} fn main() { let x = A(marker::NoShare); - bar(&x); //~ ERROR type parameter with an incompatible type + bar(&x); + //FIXME(flaper87): Not yet + // ERROR type parameter with an incompatible type } diff --git a/src/test/compile-fail/typeck-bounds-share-impls.rs b/src/test/compile-fail/typeck-bounds-share-impls.rs new file mode 100644 index 0000000000000..e666d78aa55f6 --- /dev/null +++ b/src/test/compile-fail/typeck-bounds-share-impls.rs @@ -0,0 +1,36 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-tidy-linelength +// Verify that `Share` bounds are correctly enforced. + +struct MyStruct; + +struct NotShareStruct<'a> { + a: *MyStruct, // *-pointers are share if T is share + //b: &'a MyStruct, // &-pointers are share if T is share + //c: &'a mut MyStruct, // &mut-pointers are share if T is share + d: MyStruct +} + +impl<'a> Share for NotShareStruct<'a> {} +//~^ ERROR cannot implement the trait `core::kinds::Share` on type `NotShareStruct` because the field with type `MyStruct` doesn't fulfill such trait. + +enum Foo { + Var(MyStruct) +} + +fn share(_: T) {} + +fn main() { + share(Var(MyStruct)); + // FIXME(flaper87): This still doesn't typeck + //ERROR type parameter with an incompatible type +} diff --git a/src/test/compile-fail/typeck-bounds-type-impl.rs b/src/test/compile-fail/typeck-bounds-type-impl.rs new file mode 100644 index 0000000000000..9cb7ca519b5b8 --- /dev/null +++ b/src/test/compile-fail/typeck-bounds-type-impl.rs @@ -0,0 +1,102 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-tidy-linelength + +// Verify that built-in trait implementations are enforced recursively on +// a type. + +#![feature(struct_inherit)] + +trait DummyTrait {} + +struct ShareStruct; + +impl DummyTrait for ShareStruct {} +impl Share for ShareStruct {} + +struct SendShareStruct { + a: ShareStruct +} + +impl DummyTrait for SendShareStruct {} +impl Share for SendShareStruct {} + +impl Send for SendShareStruct {} +//~^ ERROR cannot implement the trait `core::kinds::Send` on type `SendShareStruct` because the field with type `ShareStruct` doesn't fulfill such trait. + +enum ShareEnum {} +impl Share for ShareEnum {} + +enum ShareSendEnum {} +impl Share for ShareSendEnum {} +impl Send for ShareSendEnum {} + +enum SendShareEnum { + MyShareEnumVariant(ShareEnum), + MyShareStructVariant(ShareStruct), + MyShareSendEnumVariant(ShareEnum, ShareSendEnum) +} + +impl Share for SendShareEnum {} +impl Send for SendShareEnum {} +//~^ ERROR cannot implement the trait `core::kinds::Send` on type `SendShareEnum` because variant arg with type `ShareEnum` doesn't fulfill such trait. +//~^^ ERROR cannot implement the trait `core::kinds::Send` on type `SendShareEnum` because variant arg with type `ShareStruct` doesn't fulfill such trait. +//~^^^ ERROR cannot implement the trait `core::kinds::Send` on type `SendShareEnum` because variant arg with type `ShareEnum` doesn't fulfill such trait. + +virtual struct Base { + a: ShareStruct +} + +struct InheritedShareStruct: Base; + +impl Share for InheritedShareStruct {} +impl Send for InheritedShareStruct {} +//~^ ERROR cannot implement the trait `core::kinds::Send` on type `InheritedShareStruct` because the field with type `ShareStruct` doesn't fulfill such trait. + +#[deriving(Send)] +//~^ ERROR cannot implement the trait `core::kinds::Send` on type `SendShareStruct2` because the field with type `ShareStruct` doesn't fulfill such trait. +struct SendShareStruct2 { + a: ShareStruct +} + + +type MyType = ||:'static -> ShareStruct; + +impl Share for MyType {} +//~^ ERROR can only implement built-in trait `core::kinds::Share` on a struct or enum + +struct ProcNoShareStruct { + a: proc() +} + +impl Share for ProcNoShareStruct {} +//~^ ERROR cannot implement the trait `core::kinds::Share` on type `ProcNoShareStruct` because the field with type `proc()` doesn't fulfill such trait. + +struct ProcShareStruct { + a: proc():Share +} + +impl Share for ProcShareStruct {} + +struct ClosureShareStruct { + a: ||:'static+Share +} + +impl Share for ClosureShareStruct {} + +struct ClosureNotShareStruct { + a: ||:'static +} + +impl Share for ClosureNotShareStruct {} +//~^ ERROR cannot implement the trait `core::kinds::Share` on type `ClosureNotShareStruct` because the field with type `'static ||:'static` doesn't fulfill such trait. + +fn main() {} diff --git a/src/test/compile-fail/typeck-unsafe-always-share.rs b/src/test/compile-fail/typeck-unsafe-always-share.rs index 6dec86ddf622f..18fa592d3f396 100644 --- a/src/test/compile-fail/typeck-unsafe-always-share.rs +++ b/src/test/compile-fail/typeck-unsafe-always-share.rs @@ -19,6 +19,8 @@ struct MyShare { u: Unsafe } +impl Share for MyShare {} + struct NoShare { m: marker::NoShare } diff --git a/src/test/run-pass/builtin-superkinds-capabilities-xc.rs b/src/test/run-pass/builtin-superkinds-capabilities-xc.rs index d52da21240064..4635f115556b6 100644 --- a/src/test/run-pass/builtin-superkinds-capabilities-xc.rs +++ b/src/test/run-pass/builtin-superkinds-capabilities-xc.rs @@ -20,6 +20,7 @@ use trait_superkinds_in_metadata::{RequiresRequiresShareAndSend, RequiresShare}; #[deriving(PartialEq)] struct X(T); +impl Share for X {} impl RequiresShare for X { } impl RequiresRequiresShareAndSend for X { } diff --git a/src/test/run-pass/builtin-superkinds-in-metadata.rs b/src/test/run-pass/builtin-superkinds-in-metadata.rs index ba57f095e1a99..1e06e6816e71a 100644 --- a/src/test/run-pass/builtin-superkinds-in-metadata.rs +++ b/src/test/run-pass/builtin-superkinds-in-metadata.rs @@ -19,6 +19,8 @@ use trait_superkinds_in_metadata::{RequiresCopy}; struct X(T); +impl Share for X {} + impl RequiresShare for X { } impl RequiresRequiresShareAndSend for X { } diff --git a/src/test/run-pass/trait-bounds-in-arc.rs b/src/test/run-pass/trait-bounds-in-arc.rs index 18a0e5d471c4a..feb5c8c071842 100644 --- a/src/test/run-pass/trait-bounds-in-arc.rs +++ b/src/test/run-pass/trait-bounds-in-arc.rs @@ -15,23 +15,27 @@ use std::sync::Arc; use std::task; +#[deriving(Share)] trait Pet { fn name(&self, blk: |&str|); fn num_legs(&self) -> uint; fn of_good_pedigree(&self) -> bool; } +#[deriving(Share)] struct Catte { num_whiskers: uint, name: String, } +#[deriving(Share)] struct Dogge { bark_decibels: uint, tricks_known: uint, name: String, } +#[deriving(Share)] struct Goldfyshe { swim_speed: uint, name: String, diff --git a/src/test/run-pass/typeck-bounds-type-impl.rs b/src/test/run-pass/typeck-bounds-type-impl.rs new file mode 100644 index 0000000000000..7c5ddb3d2bf3a --- /dev/null +++ b/src/test/run-pass/typeck-bounds-type-impl.rs @@ -0,0 +1,25 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Checks for built-in traits implementation + +#[deriving(Share, Send, Copy)] +struct Struct; + +#[deriving(Share, Send, Copy)] +struct SendShareStruct2 { + a: Struct +} + +struct ManualImpl; + +impl Share for ManualImpl {} + +fn main() {}