diff --git a/src/doc/reference.md b/src/doc/reference.md index a772d98583e49..100117ca65455 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -1705,6 +1705,7 @@ specific type. Implementations are defined with the keyword `impl`. ``` +# use std::marker::Pod; # #[derive(Copy)] # struct Point {x: f64, y: f64}; # type Surface = i32; @@ -1716,6 +1717,7 @@ struct Circle { center: Point, } +impl Pod for Circle {} impl Copy for Circle {} impl Shape for Circle { diff --git a/src/libcollections/enum_set.rs b/src/libcollections/enum_set.rs index 4c966c0d44b4d..baa9fe9ecab52 100644 --- a/src/libcollections/enum_set.rs +++ b/src/libcollections/enum_set.rs @@ -31,6 +31,8 @@ pub struct EnumSet { marker: marker::PhantomData, } +#[cfg(not(stage0))] +impl marker::Pod for EnumSet {} impl Copy for EnumSet {} #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcollections/linked_list.rs b/src/libcollections/linked_list.rs index 5ca3cb380583b..5cec2096ce398 100644 --- a/src/libcollections/linked_list.rs +++ b/src/libcollections/linked_list.rs @@ -31,6 +31,8 @@ use core::hash::{Hasher, Hash}; use core::iter::{self, FromIterator, IntoIterator}; use core::mem; use core::ptr; +#[cfg(not(stage0))] +use core::marker::Pod; #[deprecated(since = "1.0.0", reason = "renamed to LinkedList")] #[unstable(feature = "collections")] @@ -50,6 +52,8 @@ struct Rawlink { p: *mut T, } +#[cfg(not(stage0))] +impl Pod for Rawlink {} impl Copy for Rawlink {} unsafe impl Send for Rawlink {} unsafe impl Sync for Rawlink {} diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index b8a22c30f9e1e..d5cdaa2e3513d 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -141,10 +141,18 @@ #![stable(feature = "rust1", since = "1.0.0")] +// TODO(japaric) update docs + use clone::Clone; use cmp::PartialEq; use default::Default; -use marker::{Copy, Send, Sync}; +#[cfg(not(stage0))] +use mem; +#[cfg(stage0)] +use marker::Copy; +use marker::{Send, Sync}; +#[cfg(not(stage0))] +use marker::Pod; use ops::{Deref, DerefMut, Drop}; use option::Option; use option::Option::{None, Some}; @@ -157,6 +165,7 @@ pub struct Cell { value: UnsafeCell, } +#[cfg(stage0)] impl Cell { /// Creates a new `Cell` containing the given value. /// @@ -232,9 +241,88 @@ impl Cell { } } +#[cfg(not(stage0))] +impl Cell { + /// Creates a new `Cell` containing the given value. + /// + /// # Examples + /// + /// ``` + /// use std::cell::Cell; + /// + /// let c = Cell::new(5); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn new(value: T) -> Cell { + Cell { + value: UnsafeCell::new(value), + } + } + + /// Returns a copy of the contained value. + /// + /// # Examples + /// + /// ``` + /// use std::cell::Cell; + /// + /// let c = Cell::new(5); + /// + /// let five = c.get(); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn get(&self) -> T { + unsafe { + mem::transmute_copy(mem::transmute::<_, &T>(self.value.get())) + } + } + + /// Sets the contained value. + /// + /// # Examples + /// + /// ``` + /// use std::cell::Cell; + /// + /// let c = Cell::new(5); + /// + /// c.set(10); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn set(&self, value: T) { + unsafe { + *self.value.get() = value; + } + } + + /// Get a reference to the underlying `UnsafeCell`. + /// + /// # Unsafety + /// + /// This function is `unsafe` because `UnsafeCell`'s field is public. + /// + /// # Examples + /// + /// ``` + /// use std::cell::Cell; + /// + /// let c = Cell::new(5); + /// + /// let uc = unsafe { c.as_unsafe_cell() }; + /// ``` + #[inline] + #[unstable(feature = "core")] + pub unsafe fn as_unsafe_cell<'a>(&'a self) -> &'a UnsafeCell { + &self.value + } +} + #[stable(feature = "rust1", since = "1.0.0")] unsafe impl Send for Cell where T: Send {} +#[cfg(stage0)] #[stable(feature = "rust1", since = "1.0.0")] impl Clone for Cell { fn clone(&self) -> Cell { @@ -242,6 +330,15 @@ impl Clone for Cell { } } +#[cfg(not(stage0))] +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Cell { + fn clone(&self) -> Cell { + Cell::new(self.get()) + } +} + +#[cfg(stage0)] #[stable(feature = "rust1", since = "1.0.0")] impl Default for Cell { #[stable(feature = "rust1", since = "1.0.0")] @@ -250,6 +347,16 @@ impl Default for Cell { } } +#[cfg(not(stage0))] +#[stable(feature = "rust1", since = "1.0.0")] +impl Default for Cell { + #[stable(feature = "rust1", since = "1.0.0")] + fn default() -> Cell { + Cell::new(Default::default()) + } +} + +#[cfg(stage0)] #[stable(feature = "rust1", since = "1.0.0")] impl PartialEq for Cell { fn eq(&self, other: &Cell) -> bool { @@ -257,6 +364,14 @@ impl PartialEq for Cell { } } +#[cfg(not(stage0))] +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq for Cell { + fn eq(&self, other: &Cell) -> bool { + self.get() == other.get() + } +} + /// A mutable memory location with dynamically checked borrow rules /// /// See the [module-level documentation](index.html) for more. diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index 868a671b9560e..5bc91fffc6391 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -51,6 +51,7 @@ pub trait Sized : MarkerTrait { // Empty. } +#[cfg(stage0)] /// Types that can be copied by simply copying bits (i.e. `memcpy`). /// /// By default, variable bindings have 'move semantics.' In other @@ -156,6 +157,20 @@ pub trait Copy : MarkerTrait { // Empty. } +/// TODO(japaric) docs +#[cfg(not(stage0))] +#[lang="copy"] +pub trait Copy: Pod { + // Empty +} + +/// TODO(japaric) docs +#[cfg(not(stage0))] +#[lang="pod"] +pub trait Pod: MarkerTrait { + // Empty +} + /// Types that can be safely shared between threads when aliased. /// /// The precise definition is: a type `T` is `Sync` if `&T` is @@ -258,6 +273,8 @@ macro_rules! impls{ } } + #[cfg(not(stage0))] + impl Pod for $t { } impl Copy for $t { } impl Clone for $t { diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index 4116d8be9fb5c..192f5d65d2d65 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -977,6 +977,7 @@ impl fmt::Debug for RangeFull { } } +#[cfg(stage0)] /// A (half-open) range which is bounded at both ends. #[derive(Clone, PartialEq, Eq)] #[lang="range"] @@ -988,6 +989,18 @@ pub struct Range { pub end: Idx, } +#[cfg(not(stage0))] +/// A (half-open) range which is bounded at both ends. +#[derive(Clone, Eq, PartialEq, Pod)] +#[lang="range"] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Range { + /// The lower bound of the range (inclusive). + pub start: Idx, + /// The upper bound of the range (exclusive). + pub end: Idx, +} + #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for Range { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { diff --git a/src/libcore/raw.rs b/src/libcore/raw.rs index 35dfc76268727..88be8665387ef 100644 --- a/src/libcore/raw.rs +++ b/src/libcore/raw.rs @@ -19,6 +19,8 @@ //! Their definition should always match the ABI defined in `rustc::back::abi`. use marker::Copy; +#[cfg(not(stage0))] +use marker::Pod; use mem; /// The representation of a slice like `&[T]`. @@ -62,6 +64,8 @@ pub struct Slice { } impl Copy for Slice {} +#[cfg(not(stage0))] +impl Pod for Slice {} /// The representation of an old closure. #[repr(C)] diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index b33839f33e820..d97e88302ba7c 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -891,9 +891,12 @@ fn parse_builtin_bounds_(st: &mut PState, _conv: &mut F) -> ty::BuiltinBounds 'Z' => { builtin_bounds.insert(ty::BoundSized); } - 'P' => { + 'C' => { builtin_bounds.insert(ty::BoundCopy); } + 'P' => { + builtin_bounds.insert(ty::BoundPod); + } 'T' => { builtin_bounds.insert(ty::BoundSync); } diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index 86f1605b8bfaa..d1356ab99e078 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -365,7 +365,8 @@ pub fn enc_builtin_bounds(w: &mut Encoder, _cx: &ctxt, bs: &ty::BuiltinBounds) { match bound { ty::BoundSend => mywrite!(w, "S"), ty::BoundSized => mywrite!(w, "Z"), - ty::BoundCopy => mywrite!(w, "P"), + ty::BoundCopy => mywrite!(w, "C"), + ty::BoundPod => mywrite!(w, "P"), ty::BoundSync => mywrite!(w, "T"), } } diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 3525d46a1f2f1..67e83fba019c4 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -95,6 +95,7 @@ impl LanguageItems { ty::BoundSend => self.require(SendTraitLangItem), ty::BoundSized => self.require(SizedTraitLangItem), ty::BoundCopy => self.require(CopyTraitLangItem), + ty::BoundPod => self.require(PodTraitLangItem), ty::BoundSync => self.require(SyncTraitLangItem), } } @@ -106,6 +107,8 @@ impl LanguageItems { Some(ty::BoundSized) } else if Some(id) == self.copy_trait() { Some(ty::BoundCopy) + } else if Some(id) == self.pod_trait() { + Some(ty::BoundPod) } else if Some(id) == self.sync_trait() { Some(ty::BoundSync) } else { @@ -242,6 +245,7 @@ lets_do_this! { SendTraitLangItem, "send", send_trait; SizedTraitLangItem, "sized", sized_trait; CopyTraitLangItem, "copy", copy_trait; + PodTraitLangItem, "pod", pod_trait; SyncTraitLangItem, "sync", sync_trait; DropTraitLangItem, "drop", drop_trait; diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 1f02f13a4a178..c988440d21a98 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -86,6 +86,8 @@ use syntax::print::pprust; use syntax::parse::token; use std::cell::RefCell; +#[cfg(not(stage0))] +use std::marker::Pod; use std::rc::Rc; #[derive(Clone, PartialEq, Debug)] @@ -260,6 +262,8 @@ pub struct MemCategorizationContext<'t,TYPER:'t> { typer: &'t TYPER } +#[cfg(not(stage0))] +impl<'t,TYPER:'t> Pod for MemCategorizationContext<'t,TYPER> {} impl<'t,TYPER:'t> Copy for MemCategorizationContext<'t,TYPER> {} pub type McResult = Result; diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 7dfbccea0dccd..08891ef6c61d6 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -817,16 +817,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // and applicable impls. There is a certain set of precedence rules here. match self.tcx().lang_items.to_builtin_kind(obligation.predicate.def_id()) { - Some(ty::BoundCopy) => { + Some(bound @ ty::BoundCopy) | Some(bound @ ty::BoundPod) => { debug!("obligation self ty is {}", obligation.predicate.0.self_ty().repr(self.tcx())); - // User-defined copy impls are permitted, but only for + // User-defined copy/pod impls are permitted, but only for // structs and enums. try!(self.assemble_candidates_from_impls(obligation, &mut candidates)); // For other types, we'll use the builtin rules. - try!(self.assemble_builtin_bound_candidates(ty::BoundCopy, + try!(self.assemble_builtin_bound_candidates(bound, stack, &mut candidates)); } @@ -1362,7 +1362,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // BUILTIN BOUNDS // // These cover the traits that are built-in to the language - // itself. This includes `Copy` and `Sized` for sure. For the + // itself. This includes `Copy`, `Pod` and `Sized` for sure. For the // moment, it also includes `Send` / `Sync` and a few others, but // those will hopefully change to library-defined traits in the // future. @@ -1415,7 +1415,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::ty_uniq(_) => { // Box match bound { - ty::BoundCopy => Err(Unimplemented), + ty::BoundCopy | ty::BoundPod => Err(Unimplemented), ty::BoundSized => Ok(If(Vec::new())), @@ -1427,7 +1427,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::ty_ptr(..) => { // *const T, *mut T match bound { - ty::BoundCopy | ty::BoundSized => Ok(If(Vec::new())), + ty::BoundCopy | ty::BoundPod | ty::BoundSized => Ok(If(Vec::new())), ty::BoundSync | ty::BoundSend => { self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()"); @@ -1438,7 +1438,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::ty_trait(ref data) => { match bound { ty::BoundSized => Err(Unimplemented), - ty::BoundCopy => { + ty::BoundCopy | ty::BoundPod => { if data.bounds.builtin_bounds.contains(&bound) { Ok(If(Vec::new())) } else { @@ -1466,7 +1466,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::ty_rptr(_, ty::mt { ty: _, mutbl }) => { // &mut T or &T match bound { - ty::BoundCopy => { + ty::BoundCopy | ty::BoundPod => { match mutbl { // &mut T is affine and hence never `Copy` ast::MutMutable => Err(Unimplemented), @@ -1487,9 +1487,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::ty_vec(element_ty, ref len) => { // [T, ..n] and [T] match bound { - ty::BoundCopy => { + ty::BoundCopy | ty::BoundPod => { match *len { - // [T, ..n] is copy iff T is copy + // [T, ..n] is copy iff T is copy, likewise with pod Some(_) => Ok(If(vec![element_ty])), // [T] is unsized and hence affine @@ -1518,7 +1518,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()"); } - ty::BoundCopy | ty::BoundSized => Err(Unimplemented), + ty::BoundCopy | ty::BoundPod | ty::BoundSized => Err(Unimplemented), } } @@ -1612,7 +1612,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // First check for markers and other nonsense. match bound { // Fallback to whatever user-defined impls exist in this case. - ty::BoundCopy => Ok(ParameterBuiltin), + ty::BoundCopy | ty::BoundPod => Ok(ParameterBuiltin), // Sized if all the component types are sized. ty::BoundSized => Ok(If(types)), diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index add829074c4f0..d3549c1157a95 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -36,7 +36,7 @@ pub use self::IntVarValue::*; pub use self::ExprAdjustment::*; pub use self::vtable_origin::*; pub use self::MethodOrigin::*; -pub use self::CopyImplementationError::*; +pub use self::PodImplementationError::*; use back::svh::Svh; use session::Session; @@ -834,6 +834,11 @@ pub struct ctxt<'tcx> { /// results are dependent on the parameter environment. pub type_impls_copy_cache: RefCell,bool>>, + /// Caches whether types are known to impl Pod. Note that type + /// parameters are never placed into this cache, because their + /// results are dependent on the parameter environment. + pub type_impls_pod_cache: RefCell,bool>>, + /// Caches whether types are known to impl Sized. Note that type /// parameters are never placed into this cache, because their /// results are dependent on the parameter environment. @@ -1601,6 +1606,7 @@ pub enum BuiltinBound { BoundSend, BoundSized, BoundCopy, + BoundPod, BoundSync, } @@ -2612,6 +2618,7 @@ pub fn mk_ctxt<'tcx>(s: Session, selection_cache: traits::SelectionCache::new(), repr_hint_cache: RefCell::new(DefIdMap()), type_impls_copy_cache: RefCell::new(HashMap::new()), + type_impls_pod_cache: RefCell::new(HashMap::new()), type_impls_sized_cache: RefCell::new(HashMap::new()), object_safety_cache: RefCell::new(DefIdMap()), const_qualif_map: RefCell::new(NodeMap()), @@ -3747,7 +3754,7 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents { let mut tc = TC::All - TC::InteriorParam; for bound in &bounds.builtin_bounds { tc = tc - match bound { - BoundSync | BoundSend | BoundCopy => TC::None, + BoundSync | BoundSend | BoundCopy | BoundPod => TC::None, BoundSized => TC::Nonsized, }; } @@ -3803,6 +3810,15 @@ pub fn type_moves_by_default<'a,'tcx>(param_env: &ParameterEnvironment<'a,'tcx>, !type_impls_bound(param_env, &tcx.type_impls_copy_cache, ty, ty::BoundCopy, span) } +pub fn type_is_pod<'a,'tcx>(param_env: &ParameterEnvironment<'a,'tcx>, + span: Span, + ty: Ty<'tcx>) + -> bool +{ + let tcx = param_env.tcx; + !type_impls_bound(param_env, &tcx.type_impls_pod_cache, ty, ty::BoundPod, span) +} + pub fn type_is_sized<'a,'tcx>(param_env: &ParameterEnvironment<'a,'tcx>, span: Span, ty: Ty<'tcx>) @@ -6968,17 +6984,17 @@ pub fn make_substs_for_receiver_types<'tcx>(tcx: &ty::ctxt<'tcx>, } #[derive(Copy)] -pub enum CopyImplementationError { - FieldDoesNotImplementCopy(ast::Name), - VariantDoesNotImplementCopy(ast::Name), +pub enum PodImplementationError { + FieldDoesNotImplementPod(ast::Name), + VariantDoesNotImplementPod(ast::Name), TypeIsStructural, TypeHasDestructor, } -pub fn can_type_implement_copy<'a,'tcx>(param_env: &ParameterEnvironment<'a, 'tcx>, - span: Span, - self_type: Ty<'tcx>) - -> Result<(),CopyImplementationError> +pub fn can_type_implement_pod<'a,'tcx>(param_env: &ParameterEnvironment<'a, 'tcx>, + span: Span, + self_type: Ty<'tcx>) + -> Result<(), PodImplementationError> { let tcx = param_env.tcx; @@ -6986,8 +7002,8 @@ pub fn can_type_implement_copy<'a,'tcx>(param_env: &ParameterEnvironment<'a, 'tc ty::ty_struct(struct_did, substs) => { let fields = ty::struct_fields(tcx, struct_did, substs); for field in &fields { - if type_moves_by_default(param_env, span, field.mt.ty) { - return Err(FieldDoesNotImplementCopy(field.name)) + if type_is_pod(param_env, span, field.mt.ty) { + return Err(FieldDoesNotImplementPod(field.name)) } } struct_did @@ -6998,8 +7014,8 @@ pub fn can_type_implement_copy<'a,'tcx>(param_env: &ParameterEnvironment<'a, 'tc for variant_arg_type in &variant.args { let substd_arg_type = variant_arg_type.subst(tcx, substs); - if type_moves_by_default(param_env, span, substd_arg_type) { - return Err(VariantDoesNotImplementCopy(variant.name)) + if type_is_pod(param_env, span, substd_arg_type) { + return Err(VariantDoesNotImplementPod(variant.name)) } } } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 09a1225441477..21d0f9e4c096b 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -789,6 +789,7 @@ impl<'tcx> Repr<'tcx> for ty::BuiltinBounds { ty::BoundSend => "Send".to_string(), ty::BoundSized => "Sized".to_string(), ty::BoundCopy => "Copy".to_string(), + ty::BoundPod => "Pod".to_string(), ty::BoundSync => "Sync".to_string(), }); } @@ -1181,6 +1182,7 @@ impl<'tcx> UserString<'tcx> for ty::BuiltinBound { ty::BoundSend => "Send".to_string(), ty::BoundSized => "Sized".to_string(), ty::BoundCopy => "Copy".to_string(), + ty::BoundPod => "Pod".to_string(), ty::BoundSync => "Sync".to_string(), } } diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 1eea52fe1bb20..81e039038e3f2 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -605,10 +605,12 @@ impl LintPass for RawPointerDerive { } let did = match item.node { ast::ItemImpl(_, _, _, ref t_ref_opt, _, _) => { - // Deriving the Copy trait does not cause a warning + // Deriving the Copy/Pod trait does not cause a warning if let &Some(ref trait_ref) = t_ref_opt { let def_id = ty::trait_ref_to_def_id(cx.tcx, trait_ref); - if Some(def_id) == cx.tcx.lang_items.copy_trait() { + if Some(def_id) == cx.tcx.lang_items.copy_trait() || + Some(def_id) == cx.tcx.lang_items.pod_trait() + { return; } } @@ -1674,11 +1676,11 @@ impl LintPass for MissingCopyImplementations { if !ty::type_moves_by_default(¶meter_environment, item.span, ty) { return; } - if ty::can_type_implement_copy(¶meter_environment, item.span, ty).is_ok() { + if ty::can_type_implement_pod(¶meter_environment, item.span, ty).is_ok() { cx.span_lint(MISSING_COPY_IMPLEMENTATIONS, item.span, - "type could implement `Copy`; consider adding `impl \ - Copy`") + "type could implement `Pod`; consider adding `impl \ + Pod`") } } } diff --git a/src/librustc_llvm/diagnostic.rs b/src/librustc_llvm/diagnostic.rs index aca4d265bc963..c325f3d5b7a85 100644 --- a/src/librustc_llvm/diagnostic.rs +++ b/src/librustc_llvm/diagnostic.rs @@ -69,14 +69,13 @@ impl OptimizationDiagnostic { } } +#[derive(Copy)] pub struct InlineAsmDiagnostic { pub cookie: c_uint, pub message: TwineRef, pub instruction: ValueRef, } -impl Copy for InlineAsmDiagnostic {} - impl InlineAsmDiagnostic { unsafe fn unpack(di: DiagnosticInfoRef) -> InlineAsmDiagnostic { diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index cffd74ccd7218..aee5e11fec379 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -231,6 +231,7 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>( Some(ty::BoundSend) | Some(ty::BoundSized) | Some(ty::BoundCopy) | + Some(ty::BoundPod) | Some(ty::BoundSync) => false, _ => true, } diff --git a/src/librustc_typeck/check/wf.rs b/src/librustc_typeck/check/wf.rs index 8185f48cb8c70..5ee8c6bd1f70e 100644 --- a/src/librustc_typeck/check/wf.rs +++ b/src/librustc_typeck/check/wf.rs @@ -266,7 +266,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { } } - if fcx.tcx().lang_items.copy_trait() == Some(trait_ref.def_id) { + if fcx.tcx().lang_items.pod_trait() == Some(trait_ref.def_id) { // This is checked in coherence. return } diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 9a8545f3dd515..4c24d35ad9dd6 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -141,8 +141,8 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { // the coherence tables contain the trait -> type mappings. self.populate_destructor_table(); - // Check to make sure implementations of `Copy` are legal. - self.check_implementations_of_copy(); + // Check to make sure implementations of `Pod` are legal. + self.check_implementations_of_pod(); } fn check_implementation(&self, item: &Item, opt_trait: Option<&TraitRef>) { @@ -429,21 +429,21 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { } } - /// Ensures that implementations of the built-in trait `Copy` are legal. - fn check_implementations_of_copy(&self) { + /// Ensures that implementations of the built-in trait `Pod` are legal. + fn check_implementations_of_pod(&self) { let tcx = self.crate_context.tcx; - let copy_trait = match tcx.lang_items.copy_trait() { + let pod_trait = match tcx.lang_items.pod_trait() { Some(id) => id, None => return, }; let trait_impls = match tcx.trait_impls .borrow() - .get(©_trait) + .get(&pod_trait) .cloned() { None => { - debug!("check_implementations_of_copy(): no types with \ - implementations of `Copy` found"); + debug!("check_implementations_of_pod(): no types with \ + implementations of `Pod` found"); return } Some(found_impls) => found_impls @@ -453,17 +453,17 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { let trait_impls = trait_impls.borrow().clone(); for &impl_did in &trait_impls { - debug!("check_implementations_of_copy: impl_did={}", + debug!("check_implementations_of_pod: impl_did={}", impl_did.repr(tcx)); if impl_did.krate != ast::LOCAL_CRATE { - debug!("check_implementations_of_copy(): impl not in this \ + debug!("check_implementations_of_pod(): impl not in this \ crate"); continue } let self_type = self.get_self_type_for_implementation(impl_did); - debug!("check_implementations_of_copy: self_type={} (bound)", + debug!("check_implementations_of_pod: self_type={} (bound)", self_type.repr(tcx)); let span = tcx.map.span(impl_did.node); @@ -471,34 +471,34 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { let self_type = self_type.ty.subst(tcx, ¶m_env.free_substs); assert!(!self_type.has_escaping_regions()); - debug!("check_implementations_of_copy: self_type={} (free)", + debug!("check_implementations_of_pod: self_type={} (free)", self_type.repr(tcx)); - match ty::can_type_implement_copy(¶m_env, span, self_type) { + match ty::can_type_implement_pod(¶m_env, span, self_type) { Ok(()) => {} - Err(ty::FieldDoesNotImplementCopy(name)) => { + Err(ty::FieldDoesNotImplementPod(name)) => { span_err!(tcx.sess, span, E0204, - "the trait `Copy` may not be \ + "the trait `Pod` may not be \ implemented for this type; field \ - `{}` does not implement `Copy`", + `{}` does not implement `Pod`", token::get_name(name)) } - Err(ty::VariantDoesNotImplementCopy(name)) => { + Err(ty::VariantDoesNotImplementPod(name)) => { span_err!(tcx.sess, span, E0205, - "the trait `Copy` may not be \ + "the trait `Pod` may not be \ implemented for this type; variant \ - `{}` does not implement `Copy`", + `{}` does not implement `Pod`", token::get_name(name)) } Err(ty::TypeIsStructural) => { span_err!(tcx.sess, span, E0206, - "the trait `Copy` may not be implemented \ + "the trait `Pod` may not be implemented \ for this type; type is not a structure or \ enumeration") } Err(ty::TypeHasDestructor) => { span_err!(tcx.sess, span, E0184, - "the trait `Copy` may not be implemented for this type; \ + "the trait `Pod` may not be implemented for this type; \ the type has a destructor"); } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index c39451b15ada5..8a080c0247d26 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -597,6 +597,9 @@ impl Clean for ty::BuiltinBound { ty::BoundCopy => (tcx.lang_items.copy_trait().unwrap(), external_path(cx, "Copy", None, vec![], &empty)), + ty::BoundPod => + (tcx.lang_items.pod_trait().unwrap(), + external_path(cx, "Pod", None, vec![], &empty)), ty::BoundSync => (tcx.lang_items.sync_trait().unwrap(), external_path(cx, "Sync", None, vec![], &empty)), diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs index 69fd0a57d5f38..d2b64c00669d1 100644 --- a/src/libstd/collections/hash/table.rs +++ b/src/libstd/collections/hash/table.rs @@ -17,6 +17,8 @@ use cmp; use hash::{Hash, Hasher}; use iter::{Iterator, IteratorExt, ExactSizeIterator, count}; use marker::{Copy, Send, Sync, Sized, self}; +#[cfg(not(stage0))] +use marker::Pod; use mem::{min_align_of, size_of}; use mem; use num::{Int, UnsignedInt}; @@ -87,6 +89,8 @@ struct RawBucket { _marker: marker::PhantomData<(K,V)>, } +#[cfg(not(stage0))] +impl Pod for RawBucket {} impl Copy for RawBucket {} pub struct Bucket { @@ -95,6 +99,9 @@ pub struct Bucket { table: M } +// XXX(japaric) needs auditing +#[cfg(not(stage0))] +impl Pod for Bucket {} impl Copy for Bucket {} pub struct EmptyBucket { diff --git a/src/libsyntax/ext/deriving/bounds.rs b/src/libsyntax/ext/deriving/bounds.rs index e408c99935d1c..13dbef26d4d93 100644 --- a/src/libsyntax/ext/deriving/bounds.rs +++ b/src/libsyntax/ext/deriving/bounds.rs @@ -15,38 +15,77 @@ use ext::deriving::generic::*; use ext::deriving::generic::ty::*; use ptr::P; -pub fn expand_deriving_unsafe_bound(cx: &mut ExtCtxt, - span: Span, - _: &MetaItem, - _: &Item, - _: F) where - F: FnOnce(P), -{ +pub fn expand_deriving_unsafe_bound(cx: &mut ExtCtxt, + span: Span, + _: &MetaItem, + _: &Item, + _: &mut FnMut(P)) { cx.span_err(span, "this unsafe trait should be implemented explicitly"); } -pub fn expand_deriving_copy(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: F) where - F: FnOnce(P), -{ - let path = Path::new(vec![ +pub fn expand_deriving_copy(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: &mut FnMut(P)) { + let pod_path = Path::new(vec![ + if cx.use_std { "std" } else { "core" }, + "marker", + "Pod", + ]); + + let trait_def = TraitDef { + span: span, + attributes: Vec::new(), + path: pod_path.clone(), + additional_bounds: Vec::new(), + bound_self: true, + generics: LifetimeBounds::empty(), + methods: Vec::new(), + associated_types: Vec::new(), + }; + + // impl Pod for Foo {} + trait_def.expand(cx, mitem, item, push); + + let copy_path = Path::new(vec![ if cx.use_std { "std" } else { "core" }, "marker", "Copy", ]); + let trait_def = TraitDef { + path: copy_path, + additional_bounds: vec![Ty::Literal(pod_path)], + bound_self: false, + .. trait_def + }; + + // impl Copy for Foo {} + trait_def.expand(cx, mitem, item, push); +} + +pub fn expand_deriving_pod(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: &mut FnMut(P)) { + let path = Path::new(vec![ + if cx.use_std { "std" } else { "core" }, + "marker", + "Pod", + ]); + let trait_def = TraitDef { span: span, attributes: Vec::new(), path: path, additional_bounds: Vec::new(), + bound_self: true, generics: LifetimeBounds::empty(), methods: Vec::new(), associated_types: Vec::new(), }; - trait_def.expand(cx, mitem, item, push) + trait_def.expand(cx, mitem, item, push); } diff --git a/src/libsyntax/ext/deriving/clone.rs b/src/libsyntax/ext/deriving/clone.rs index f89f3ab55f3f9..22675cac6ccba 100644 --- a/src/libsyntax/ext/deriving/clone.rs +++ b/src/libsyntax/ext/deriving/clone.rs @@ -17,19 +17,18 @@ use ext::deriving::generic::ty::*; use parse::token::InternedString; use ptr::P; -pub fn expand_deriving_clone(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: F) where - F: FnOnce(P), -{ +pub fn expand_deriving_clone(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: &mut FnMut(P)) { let inline = cx.meta_word(span, InternedString::new("inline")); let attrs = vec!(cx.attribute(span, inline)); let trait_def = TraitDef { span: span, attributes: Vec::new(), path: path_std!(cx, core::clone::Clone), + bound_self: true, additional_bounds: Vec::new(), generics: LifetimeBounds::empty(), methods: vec!( diff --git a/src/libsyntax/ext/deriving/cmp/eq.rs b/src/libsyntax/ext/deriving/cmp/eq.rs index c02af437b1c7b..af218758b0f62 100644 --- a/src/libsyntax/ext/deriving/cmp/eq.rs +++ b/src/libsyntax/ext/deriving/cmp/eq.rs @@ -17,13 +17,11 @@ use ext::deriving::generic::ty::*; use parse::token::InternedString; use ptr::P; -pub fn expand_deriving_eq(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: F) where - F: FnOnce(P), -{ +pub fn expand_deriving_eq(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: &mut FnMut(P)) { // structures are equal if all fields are equal, and non equal, if // any fields are not equal or if the enum variants are different fn cs_eq(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P { @@ -83,6 +81,7 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt, span: span, attributes: Vec::new(), path: path_std!(cx, core::cmp::PartialEq), + bound_self: true, additional_bounds: Vec::new(), generics: LifetimeBounds::empty(), methods: vec!( diff --git a/src/libsyntax/ext/deriving/cmp/ord.rs b/src/libsyntax/ext/deriving/cmp/ord.rs index b2b2654801863..e7dc2e5bd1010 100644 --- a/src/libsyntax/ext/deriving/cmp/ord.rs +++ b/src/libsyntax/ext/deriving/cmp/ord.rs @@ -20,13 +20,11 @@ use ext::deriving::generic::ty::*; use parse::token::InternedString; use ptr::P; -pub fn expand_deriving_ord(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: F) where - F: FnOnce(P), -{ +pub fn expand_deriving_ord(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: &mut FnMut(P)) { macro_rules! md { ($name:expr, $op:expr, $equal:expr) => { { let inline = cx.meta_word(span, InternedString::new("inline")); @@ -70,6 +68,7 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt, span: span, attributes: vec![], path: path_std!(cx, core::cmp::PartialOrd), + bound_self: true, additional_bounds: vec![], generics: LifetimeBounds::empty(), methods: vec![ diff --git a/src/libsyntax/ext/deriving/cmp/totaleq.rs b/src/libsyntax/ext/deriving/cmp/totaleq.rs index 83164d242e8fb..43e933bd3cb1c 100644 --- a/src/libsyntax/ext/deriving/cmp/totaleq.rs +++ b/src/libsyntax/ext/deriving/cmp/totaleq.rs @@ -17,13 +17,11 @@ use ext::deriving::generic::ty::*; use parse::token::InternedString; use ptr::P; -pub fn expand_deriving_totaleq(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: F) where - F: FnOnce(P), -{ +pub fn expand_deriving_totaleq(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: &mut FnMut(P)) { fn cs_total_eq_assert(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P { cs_same_method(|cx, span, exprs| { // create `a.(); b.(); c.(); ...` @@ -48,6 +46,7 @@ pub fn expand_deriving_totaleq(cx: &mut ExtCtxt, span: span, attributes: Vec::new(), path: path_std!(cx, core::cmp::Eq), + bound_self: true, additional_bounds: Vec::new(), generics: LifetimeBounds::empty(), methods: vec!( diff --git a/src/libsyntax/ext/deriving/cmp/totalord.rs b/src/libsyntax/ext/deriving/cmp/totalord.rs index 1de955856e712..4f84aab412c1a 100644 --- a/src/libsyntax/ext/deriving/cmp/totalord.rs +++ b/src/libsyntax/ext/deriving/cmp/totalord.rs @@ -18,19 +18,18 @@ use ext::deriving::generic::ty::*; use parse::token::InternedString; use ptr::P; -pub fn expand_deriving_totalord(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: F) where - F: FnOnce(P), -{ +pub fn expand_deriving_totalord(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: &mut FnMut(P)) { let inline = cx.meta_word(span, InternedString::new("inline")); let attrs = vec!(cx.attribute(span, inline)); let trait_def = TraitDef { span: span, attributes: Vec::new(), path: path_std!(cx, core::cmp::Ord), + bound_self: true, additional_bounds: Vec::new(), generics: LifetimeBounds::empty(), methods: vec!( diff --git a/src/libsyntax/ext/deriving/decodable.rs b/src/libsyntax/ext/deriving/decodable.rs index 6ce68948e4b01..70e5395efc4ca 100644 --- a/src/libsyntax/ext/deriving/decodable.rs +++ b/src/libsyntax/ext/deriving/decodable.rs @@ -21,34 +21,28 @@ use parse::token::InternedString; use parse::token; use ptr::P; -pub fn expand_deriving_rustc_decodable(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: F) where - F: FnOnce(P), -{ +pub fn expand_deriving_rustc_decodable(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: &mut FnMut(P)) { expand_deriving_decodable_imp(cx, span, mitem, item, push, "rustc_serialize") } -pub fn expand_deriving_decodable(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: F) where - F: FnOnce(P), -{ +pub fn expand_deriving_decodable(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: &mut FnMut(P)) { expand_deriving_decodable_imp(cx, span, mitem, item, push, "serialize") } -fn expand_deriving_decodable_imp(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: F, - krate: &'static str) where - F: FnOnce(P), -{ +fn expand_deriving_decodable_imp(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: &mut FnMut(P), + krate: &'static str) { if !cx.use_std { // FIXME(#21880): lift this requirement. cx.span_err(span, "this trait cannot be derived with #![no_std]"); @@ -59,6 +53,7 @@ fn expand_deriving_decodable_imp(cx: &mut ExtCtxt, span: span, attributes: Vec::new(), path: Path::new_(vec!(krate, "Decodable"), None, vec!(), true), + bound_self: true, additional_bounds: Vec::new(), generics: LifetimeBounds::empty(), methods: vec!( diff --git a/src/libsyntax/ext/deriving/default.rs b/src/libsyntax/ext/deriving/default.rs index f9991a233547c..9915ee1afc6d9 100644 --- a/src/libsyntax/ext/deriving/default.rs +++ b/src/libsyntax/ext/deriving/default.rs @@ -17,19 +17,18 @@ use ext::deriving::generic::ty::*; use parse::token::InternedString; use ptr::P; -pub fn expand_deriving_default(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: F) where - F: FnOnce(P), -{ +pub fn expand_deriving_default(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: &mut FnMut(P)) { let inline = cx.meta_word(span, InternedString::new("inline")); let attrs = vec!(cx.attribute(span, inline)); let trait_def = TraitDef { span: span, attributes: Vec::new(), path: path_std!(cx, core::default::Default), + bound_self: true, additional_bounds: Vec::new(), generics: LifetimeBounds::empty(), methods: vec!( diff --git a/src/libsyntax/ext/deriving/encodable.rs b/src/libsyntax/ext/deriving/encodable.rs index d7961d7da00f1..6c178693af441 100644 --- a/src/libsyntax/ext/deriving/encodable.rs +++ b/src/libsyntax/ext/deriving/encodable.rs @@ -97,34 +97,28 @@ use ext::deriving::generic::ty::*; use parse::token; use ptr::P; -pub fn expand_deriving_rustc_encodable(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: F) where - F: FnOnce(P), -{ +pub fn expand_deriving_rustc_encodable(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: &mut FnMut(P)) { expand_deriving_encodable_imp(cx, span, mitem, item, push, "rustc_serialize") } -pub fn expand_deriving_encodable(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: F) where - F: FnOnce(P), -{ +pub fn expand_deriving_encodable(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: &mut FnMut(P)) { expand_deriving_encodable_imp(cx, span, mitem, item, push, "serialize") } -fn expand_deriving_encodable_imp(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: F, - krate: &'static str) where - F: FnOnce(P), -{ +fn expand_deriving_encodable_imp(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: &mut FnMut(P), + krate: &'static str) { if !cx.use_std { // FIXME(#21880): lift this requirement. cx.span_err(span, "this trait cannot be derived with #![no_std]"); @@ -135,6 +129,7 @@ fn expand_deriving_encodable_imp(cx: &mut ExtCtxt, span: span, attributes: Vec::new(), path: Path::new_(vec!(krate, "Encodable"), None, vec!(), true), + bound_self: true, additional_bounds: Vec::new(), generics: LifetimeBounds::empty(), methods: vec!( diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index 9cd965a8138e0..ff9e07f1a24ef 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -220,8 +220,10 @@ pub struct TraitDef<'a> { /// Path of the trait, including any type parameters pub path: Path<'a>, - /// Additional bounds required of any type parameters of the type, - /// other than the current trait + /// Whether to include itself as a bound on the type parameters + pub bound_self: bool, + + /// Additional bounds required of any type parameters of the type pub additional_bounds: Vec>, /// Any extra lifetimes and/or bounds, e.g. `D: serialize::Decoder` @@ -334,13 +336,11 @@ pub fn combine_substructure<'a>(f: CombineSubstructureFunc<'a>) impl<'a> TraitDef<'a> { - pub fn expand(&self, - cx: &mut ExtCtxt, - mitem: &ast::MetaItem, - item: &ast::Item, - push: F) where - F: FnOnce(P), - { + pub fn expand(&self, + cx: &mut ExtCtxt, + mitem: &ast::MetaItem, + item: &ast::Item, + push: &mut FnMut(P)) { let newitem = match item.node { ast::ItemStruct(ref struct_def, ref generics) => { self.expand_struct_def(cx, @@ -424,7 +424,9 @@ impl<'a> TraitDef<'a> { }).collect(); // require the current trait - bounds.push(cx.typarambound(trait_path.clone())); + if self.bound_self { + bounds.push(cx.typarambound(trait_path.clone())); + } // also add in any bounds from the declaration for declared_bound in &*ty_param.bounds { diff --git a/src/libsyntax/ext/deriving/hash.rs b/src/libsyntax/ext/deriving/hash.rs index da80c7a0e6d15..a0455af7b5dd5 100644 --- a/src/libsyntax/ext/deriving/hash.rs +++ b/src/libsyntax/ext/deriving/hash.rs @@ -16,13 +16,11 @@ use ext::deriving::generic::*; use ext::deriving::generic::ty::*; use ptr::P; -pub fn expand_deriving_hash(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: F) where - F: FnOnce(P), -{ +pub fn expand_deriving_hash(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: &mut FnMut(P)) { let path = Path::new_(pathvec_std!(cx, core::hash::Hash), None, vec!(), true); @@ -31,6 +29,7 @@ pub fn expand_deriving_hash(cx: &mut ExtCtxt, span: span, attributes: Vec::new(), path: path, + bound_self: true, additional_bounds: Vec::new(), generics: LifetimeBounds::empty(), methods: vec!( diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs index 2631c28cf2fe9..80d0bf2ab1195 100644 --- a/src/libsyntax/ext/deriving/mod.rs +++ b/src/libsyntax/ext/deriving/mod.rs @@ -141,7 +141,7 @@ macro_rules! derive_traits { item: &Item, push: &mut FnMut(P)) { warn_if_deprecated(ecx, sp, $name); - $func(ecx, sp, mitem, item, |i| push(i)); + $func(ecx, sp, mitem, item, push); } } @@ -189,6 +189,7 @@ derive_traits! { "Send" => bounds::expand_deriving_unsafe_bound, "Sync" => bounds::expand_deriving_unsafe_bound, "Copy" => bounds::expand_deriving_copy, + "Pod" => bounds::expand_deriving_pod, // deprecated "Show" => show::expand_deriving_show, diff --git a/src/libsyntax/ext/deriving/primitive.rs b/src/libsyntax/ext/deriving/primitive.rs index b2d0a9f6b51ad..2ac7cfec82a22 100644 --- a/src/libsyntax/ext/deriving/primitive.rs +++ b/src/libsyntax/ext/deriving/primitive.rs @@ -18,19 +18,18 @@ use ext::deriving::generic::ty::*; use parse::token::InternedString; use ptr::P; -pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: F) where - F: FnOnce(P), -{ +pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: &mut FnMut(P)) { let inline = cx.meta_word(span, InternedString::new("inline")); let attrs = vec!(cx.attribute(span, inline)); let trait_def = TraitDef { span: span, attributes: Vec::new(), path: path_std!(cx, core::num::FromPrimitive), + bound_self: true, additional_bounds: Vec::new(), generics: LifetimeBounds::empty(), methods: vec!( diff --git a/src/libsyntax/ext/deriving/rand.rs b/src/libsyntax/ext/deriving/rand.rs index 8a764fded6fd9..cd671951c2435 100644 --- a/src/libsyntax/ext/deriving/rand.rs +++ b/src/libsyntax/ext/deriving/rand.rs @@ -17,13 +17,11 @@ use ext::deriving::generic::*; use ext::deriving::generic::ty::*; use ptr::P; -pub fn expand_deriving_rand(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: F) where - F: FnOnce(P), -{ +pub fn expand_deriving_rand(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: &mut FnMut(P)) { cx.span_warn(span, "`#[derive(Rand)]` is deprecated in favour of `#[derive_Rand]` from \ `rand_macros` on crates.io"); @@ -38,6 +36,7 @@ pub fn expand_deriving_rand(cx: &mut ExtCtxt, span: span, attributes: Vec::new(), path: path!(std::rand::Rand), + bound_self: true, additional_bounds: Vec::new(), generics: LifetimeBounds::empty(), methods: vec!( diff --git a/src/libsyntax/ext/deriving/show.rs b/src/libsyntax/ext/deriving/show.rs index ce89c541fd44b..b0e69d948f1e0 100644 --- a/src/libsyntax/ext/deriving/show.rs +++ b/src/libsyntax/ext/deriving/show.rs @@ -21,13 +21,11 @@ use ptr::P; use std::collections::HashMap; -pub fn expand_deriving_show(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: F) where - F: FnOnce(P), -{ +pub fn expand_deriving_show(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: &mut FnMut(P)) { // &mut ::std::fmt::Formatter let fmtr = Ptr(box Literal(path_std!(cx, core::fmt::Formatter)), Borrowed(None, ast::MutMutable)); @@ -36,6 +34,7 @@ pub fn expand_deriving_show(cx: &mut ExtCtxt, span: span, attributes: Vec::new(), path: path_std!(cx, core::fmt::Debug), + bound_self: true, additional_bounds: Vec::new(), generics: LifetimeBounds::empty(), methods: vec![ diff --git a/src/test/compile-fail/exclusive-drop-and-copy.rs b/src/test/compile-fail/exclusive-drop-and-copy.rs index f47f14d587992..d75b0f4651305 100644 --- a/src/test/compile-fail/exclusive-drop-and-copy.rs +++ b/src/test/compile-fail/exclusive-drop-and-copy.rs @@ -12,14 +12,14 @@ // issue #20126 -#[derive(Copy)] //~ ERROR the trait `Copy` may not be implemented +#[derive(Copy)] //~ ERROR the trait `Pod` may not be implemented struct Foo; impl Drop for Foo { fn drop(&mut self) {} } -#[derive(Copy)] //~ ERROR the trait `Copy` may not be implemented +#[derive(Copy)] //~ ERROR the trait `Pod` may not be implemented struct Bar(::std::marker::PhantomData); #[unsafe_destructor] diff --git a/src/test/compile-fail/opt-in-copy.rs b/src/test/compile-fail/opt-in-copy.rs index 56f71c844ac29..97813be3e33a6 100644 --- a/src/test/compile-fail/opt-in-copy.rs +++ b/src/test/compile-fail/opt-in-copy.rs @@ -15,7 +15,7 @@ struct IWantToCopyThis { } impl Copy for IWantToCopyThis {} -//~^ ERROR the trait `Copy` may not be implemented for this type +//~^ ERROR the trait `core::marker::Pod` is not implemented enum CantCopyThisEither { A, @@ -27,7 +27,7 @@ enum IWantToCopyThisToo { } impl Copy for IWantToCopyThisToo {} -//~^ ERROR the trait `Copy` may not be implemented for this type +//~^ ERROR the trait `core::marker::Pod` is not implemented fn main() {} diff --git a/src/test/compile-fail/pod-is-not-implicitly-copyable.rs b/src/test/compile-fail/pod-is-not-implicitly-copyable.rs new file mode 100644 index 0000000000000..d5ac13a999efe --- /dev/null +++ b/src/test/compile-fail/pod-is-not-implicitly-copyable.rs @@ -0,0 +1,20 @@ +// Copyright 2015 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. + +use std::marker::Pod; + +fn drop(_: T) {} + +fn double_move(x: T) { + drop(x); + drop(x); //~ ERROR use of moved value: `x` +} + +fn main() {} diff --git a/src/test/compile-fail/type-with-destructor-cant-impl-pod.rs b/src/test/compile-fail/type-with-destructor-cant-impl-pod.rs new file mode 100644 index 0000000000000..0a752b6554e1a --- /dev/null +++ b/src/test/compile-fail/type-with-destructor-cant-impl-pod.rs @@ -0,0 +1,26 @@ +// Copyright 2015 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. + +use std::marker::Pod; + +struct Atom { + data: u64, +} + +impl Drop for Atom { + fn drop(&mut self) { + // decrease refcount + } +} + +impl Pod for Atom {} +//~^ error: the trait `Pod` may not be implemented for this type; the type has a destructor + +fn main() {} diff --git a/src/test/run-make/simd-ffi/simd.rs b/src/test/run-make/simd-ffi/simd.rs index f418d5d1fb74f..1defb2adbb295 100644 --- a/src/test/run-make/simd-ffi/simd.rs +++ b/src/test/run-make/simd-ffi/simd.rs @@ -75,6 +75,9 @@ pub trait Sized : PhantomFn {} #[lang = "copy"] pub trait Copy : PhantomFn {} +#[lang = "pod"] +pub trait Pod : PhantomFn {} + #[lang="phantom_fn"] pub trait PhantomFn { } impl PhantomFn for U { } @@ -82,5 +85,6 @@ impl PhantomFn for U { } mod core { pub mod marker { pub use Copy; + pub use Pod; } } diff --git a/src/test/run-pass/copy-out-of-array-1.rs b/src/test/run-pass/copy-out-of-array-1.rs index 2b57c1ea0da69..3687992993ed2 100644 --- a/src/test/run-pass/copy-out-of-array-1.rs +++ b/src/test/run-pass/copy-out-of-array-1.rs @@ -12,8 +12,11 @@ // // (Compare with compile-fail/move-out-of-array-1.rs) +use std::marker::Pod; + struct C { _x: u8 } +impl Pod for C { } impl Copy for C { } fn main() { diff --git a/src/test/run-pass/derive-copy-on-pod-type.rs b/src/test/run-pass/derive-copy-on-pod-type.rs new file mode 100644 index 0000000000000..8f8ab18fe47ab --- /dev/null +++ b/src/test/run-pass/derive-copy-on-pod-type.rs @@ -0,0 +1,23 @@ +// Copyright 2015 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. + +// This is not implicitly copyable +#[derive(Pod)] +struct Stuff { + x: u8, +} + +// But this can be implicitly copyable +#[derive(Copy)] +struct Copyable { + pod: Stuff, +} + +fn main() {} diff --git a/src/test/run-pass/issue-22536-copy-mustnt-zero.rs b/src/test/run-pass/issue-22536-copy-mustnt-zero.rs index b3492180a5829..530010eaf94f1 100644 --- a/src/test/run-pass/issue-22536-copy-mustnt-zero.rs +++ b/src/test/run-pass/issue-22536-copy-mustnt-zero.rs @@ -11,6 +11,8 @@ // Regression test for Issue #22536: If a type implements Copy, then // moving it must not zero the original memory. +use std::marker::Pod; + trait Resources { type Buffer: Copy; fn foo(&self) {} @@ -19,12 +21,14 @@ trait Resources { struct BufferHandle { raw: ::Buffer, } +impl Pod for BufferHandle {} impl Copy for BufferHandle {} enum Res {} impl Resources for Res { type Buffer = u32; } +impl Pod for Res { } impl Copy for Res { } fn main() { diff --git a/src/test/run-pass/regions-early-bound-used-in-bound.rs b/src/test/run-pass/regions-early-bound-used-in-bound.rs index a3602c5fbec14..c9dc248a16a10 100644 --- a/src/test/run-pass/regions-early-bound-used-in-bound.rs +++ b/src/test/run-pass/regions-early-bound-used-in-bound.rs @@ -11,6 +11,8 @@ // Tests that you can use a fn lifetime parameter as part of // the value for a type parameter in a bound. +use std::marker::Pod; + trait GetRef<'a, T> { fn get(&self) -> &'a T; } @@ -19,6 +21,7 @@ struct Box<'a, T:'a> { t: &'a T } +impl<'a,T:'a> Pod for Box<'a,T> {} impl<'a,T:'a> Copy for Box<'a,T> {} impl<'a,T:Clone> GetRef<'a,T> for Box<'a,T> {