librustc: Make Copy opt-in.

This change makes the compiler no longer infer whether types (structures
and enumerations) implement the `Copy` trait (and thus are implicitly
copyable). Rather, you must implement `Copy` yourself via `impl Copy for
MyType {}`.

A new warning has been added, `missing_copy_implementations`, to warn
you if a non-generic public type has been added that could have
implemented `Copy` but didn't.

For convenience, you may *temporarily* opt out of this behavior by using
`#![feature(opt_out_copy)]`. Note though that this feature gate will never be
accepted and will be removed by the time that 1.0 is released, so you should
transition your code away from using it.

This breaks code like:

    #[deriving(Show)]
    struct Point2D {
        x: int,
        y: int,
    }

    fn main() {
        let mypoint = Point2D {
            x: 1,
            y: 1,
        };
        let otherpoint = mypoint;
        println!("{}{}", mypoint, otherpoint);
    }

Change this code to:

    #[deriving(Show)]
    struct Point2D {
        x: int,
        y: int,
    }

    impl Copy for Point2D {}

    fn main() {
        let mypoint = Point2D {
            x: 1,
            y: 1,
        };
        let otherpoint = mypoint;
        println!("{}{}", mypoint, otherpoint);
    }

This is the backwards-incompatible part of #13231.

Part of RFC #3.

[breaking-change]
This commit is contained in:
Niko Matsakis 2014-12-05 17:01:33 -08:00
parent c7a9b49d1b
commit 096a28607f
277 changed files with 2182 additions and 513 deletions

View file

@ -17,6 +17,7 @@ pub use self::Ordering::*;
use intrinsics;
use std::kinds::marker;
use cell::UnsafeCell;
use kinds::Copy;
/// A boolean type which can be safely shared between threads.
#[stable]
@ -81,6 +82,8 @@ pub enum Ordering {
SeqCst,
}
impl Copy for Ordering {}
/// An `AtomicBool` initialized to `false`.
#[unstable = "may be renamed, pending conventions for static initalizers"]
pub const INIT_ATOMIC_BOOL: AtomicBool =

View file

@ -519,3 +519,4 @@ impl Iterator<char> for DefaultEscapedChars {
}
}
}

View file

@ -43,9 +43,8 @@
pub use self::Ordering::*;
use kinds::Sized;
use option::Option;
use option::Option::{Some, None};
use kinds::{Copy, Sized};
use option::{Option, Some, None};
/// Trait for values that can be compared for equality and inequality.
///
@ -106,6 +105,8 @@ pub enum Ordering {
Greater = 1i,
}
impl Copy for Ordering {}
impl Ordering {
/// Reverse the `Ordering`, so that `Less` becomes `Greater` and
/// vice versa.

View file

@ -46,6 +46,8 @@ pub type Result = result::Result<(), Error>;
#[experimental = "core and I/O reconciliation may alter this definition"]
pub struct Error;
impl Copy for Error {}
/// A collection of methods that are required to format a message into a stream.
///
/// This trait is the type which this modules requires when formatting
@ -135,6 +137,8 @@ impl<'a> Argument<'a> {
}
}
impl<'a> Copy for Argument<'a> {}
impl<'a> Arguments<'a> {
/// When using the format_args!() macro, this function is used to generate the
/// Arguments structure.

View file

@ -16,6 +16,7 @@
use fmt;
use iter::DoubleEndedIteratorExt;
use kinds::Copy;
use num::{Int, cast};
use slice::SlicePrelude;
@ -114,6 +115,8 @@ pub struct Radix {
base: u8,
}
impl Copy for Radix {}
impl Radix {
fn new(base: u8) -> Radix {
assert!(2 <= base && base <= 36, "the base must be in the range of 2..36: {}", base);
@ -136,6 +139,8 @@ impl GenericRadix for Radix {
#[unstable = "may be renamed or move to a different module"]
pub struct RadixFmt<T, R>(T, R);
impl<T,R> Copy for RadixFmt<T,R> where T: Copy, R: Copy {}
/// Constructs a radix formatter in the range of `2..36`.
///
/// # Example

View file

@ -20,6 +20,7 @@ pub use self::Alignment::*;
pub use self::Count::*;
pub use self::Position::*;
pub use self::Flag::*;
use kinds::Copy;
#[doc(hidden)]
pub struct Argument<'a> {
@ -27,6 +28,8 @@ pub struct Argument<'a> {
pub format: FormatSpec,
}
impl<'a> Copy for Argument<'a> {}
#[doc(hidden)]
pub struct FormatSpec {
pub fill: char,
@ -36,6 +39,8 @@ pub struct FormatSpec {
pub width: Count,
}
impl Copy for FormatSpec {}
/// Possible alignments that can be requested as part of a formatting directive.
#[deriving(PartialEq)]
pub enum Alignment {
@ -49,16 +54,22 @@ pub enum Alignment {
AlignUnknown,
}
impl Copy for Alignment {}
#[doc(hidden)]
pub enum Count {
CountIs(uint), CountIsParam(uint), CountIsNextParam, CountImplied,
}
impl Copy for Count {}
#[doc(hidden)]
pub enum Position {
ArgumentNext, ArgumentIs(uint)
}
impl Copy for Position {}
/// Flags which can be passed to formatting via a directive.
///
/// These flags are discovered through the `flags` field of the `Formatter`
@ -78,3 +89,5 @@ pub enum Flag {
/// being aware of the sign to be printed.
FlagSignAwareZeroPad,
}
impl Copy for Flag {}

View file

@ -42,6 +42,8 @@
#![experimental]
#![allow(missing_docs)]
use kinds::Copy;
pub type GlueFn = extern "Rust" fn(*const i8);
#[lang="ty_desc"]
@ -59,6 +61,8 @@ pub struct TyDesc {
pub name: &'static str,
}
impl Copy for TyDesc {}
extern "rust-intrinsic" {
// NB: These intrinsics take unsafe pointers because they mutate aliased
@ -539,6 +543,8 @@ pub struct TypeId {
t: u64,
}
impl Copy for TypeId {}
impl TypeId {
/// Returns the `TypeId` of the type this generic function has been instantiated with
pub fn of<T: 'static>() -> TypeId {

View file

@ -59,6 +59,7 @@ pub use self::MinMaxResult::*;
use clone::Clone;
use cmp;
use cmp::Ord;
use kinds::Copy;
use mem;
use num::{ToPrimitive, Int};
use ops::{Add, Deref};
@ -1166,7 +1167,8 @@ pub struct Cycle<T> {
iter: T,
}
#[unstable = "trait is unstable"]
impl<T:Copy> Copy for Cycle<T> {}
impl<A, T: Clone + Iterator<A>> Iterator<A> for Cycle<T> {
#[inline]
fn next(&mut self) -> Option<A> {
@ -1576,7 +1578,8 @@ pub struct Peekable<A, T> {
peeked: Option<A>,
}
#[unstable = "trait is unstable"]
impl<T:Copy,A:Copy> Copy for Peekable<A,T> {}
impl<A, T: Iterator<A>> Iterator<A> for Peekable<A, T> {
#[inline]
fn next(&mut self) -> Option<A> {
@ -2115,6 +2118,8 @@ pub struct Counter<A> {
step: A,
}
impl<A:Copy> Copy for Counter<A> {}
/// Creates a new counter with the specified start/step
#[inline]
#[unstable = "may be renamed"]
@ -2146,6 +2151,8 @@ pub struct Range<A> {
one: A,
}
impl<A:Copy> Copy for Range<A> {}
/// Returns an iterator over the given range [start, stop) (that is, starting
/// at start (inclusive), and ending at stop (exclusive)).
///

View file

@ -91,6 +91,8 @@ pub trait Sync for Sized? {
/// implemented using unsafe code. In that case, you may want to embed
/// some of the marker types below into your type.
pub mod marker {
use super::Copy;
/// A marker type whose type parameter `T` is considered to be
/// covariant with respect to the type itself. This is (typically)
/// used to indicate that an instance of the type `T` is being stored
@ -132,6 +134,8 @@ pub mod marker {
#[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct CovariantType<T>;
impl<T> Copy for CovariantType<T> {}
/// A marker type whose type parameter `T` is considered to be
/// contravariant with respect to the type itself. This is (typically)
/// used to indicate that an instance of the type `T` will be consumed
@ -175,6 +179,8 @@ pub mod marker {
#[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct ContravariantType<T>;
impl<T> Copy for ContravariantType<T> {}
/// A marker type whose type parameter `T` is considered to be
/// invariant with respect to the type itself. This is (typically)
/// used to indicate that instances of the type `T` may be read or
@ -200,6 +206,8 @@ pub mod marker {
#[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct InvariantType<T>;
impl<T> Copy for InvariantType<T> {}
/// As `CovariantType`, but for lifetime parameters. Using
/// `CovariantLifetime<'a>` indicates that it is ok to substitute
/// a *longer* lifetime for `'a` than the one you originally
@ -220,6 +228,8 @@ pub mod marker {
#[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct CovariantLifetime<'a>;
impl<'a> Copy for CovariantLifetime<'a> {}
/// As `ContravariantType`, but for lifetime parameters. Using
/// `ContravariantLifetime<'a>` indicates that it is ok to
/// substitute a *shorter* lifetime for `'a` than the one you
@ -236,6 +246,8 @@ pub mod marker {
#[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct ContravariantLifetime<'a>;
impl<'a> Copy for ContravariantLifetime<'a> {}
/// As `InvariantType`, but for lifetime parameters. Using
/// `InvariantLifetime<'a>` indicates that it is not ok to
/// substitute any other lifetime for `'a` besides its original
@ -253,6 +265,7 @@ pub mod marker {
/// their instances remain thread-local.
#[lang="no_send_bound"]
#[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
#[allow(missing_copy_implementations)]
pub struct NoSend;
/// A type which is considered "not POD", meaning that it is not
@ -260,6 +273,7 @@ pub mod marker {
/// ensure that they are never copied, even if they lack a destructor.
#[lang="no_copy_bound"]
#[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
#[allow(missing_copy_implementations)]
pub struct NoCopy;
/// A type which is considered "not sync", meaning that
@ -267,11 +281,14 @@ pub mod marker {
/// shared between tasks.
#[lang="no_sync_bound"]
#[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
#[allow(missing_copy_implementations)]
pub struct NoSync;
/// A type which is considered managed by the GC. This is typically
/// embedded in other types.
#[lang="managed_bound"]
#[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
#[allow(missing_copy_implementations)]
pub struct Managed;
}

View file

@ -56,7 +56,7 @@
html_playground_url = "http://play.rust-lang.org/")]
#![no_std]
#![allow(unknown_features)]
#![allow(unknown_features, raw_pointer_deriving)]
#![feature(globs, intrinsics, lang_items, macro_rules, phase)]
#![feature(simd, unsafe_destructor, slicing_syntax)]
#![feature(default_type_params)]

View file

@ -1240,6 +1240,8 @@ pub enum FPCategory {
FPNormal,
}
impl Copy for FPCategory {}
/// A built-in floating point number.
// FIXME(#5527): In a future version of Rust, many of these functions will
// become constants.

View file

@ -90,6 +90,8 @@ pub trait Drop {
/// ```rust
/// struct Foo;
///
/// impl Copy for Foo {}
///
/// impl Add<Foo, Foo> for Foo {
/// fn add(&self, _rhs: &Foo) -> Foo {
/// println!("Adding!");
@ -128,6 +130,8 @@ add_impl!(uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64)
/// ```rust
/// struct Foo;
///
/// impl Copy for Foo {}
///
/// impl Sub<Foo, Foo> for Foo {
/// fn sub(&self, _rhs: &Foo) -> Foo {
/// println!("Subtracting!");
@ -166,6 +170,8 @@ sub_impl!(uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64)
/// ```rust
/// struct Foo;
///
/// impl Copy for Foo {}
///
/// impl Mul<Foo, Foo> for Foo {
/// fn mul(&self, _rhs: &Foo) -> Foo {
/// println!("Multiplying!");
@ -204,6 +210,8 @@ mul_impl!(uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64)
/// ```
/// struct Foo;
///
/// impl Copy for Foo {}
///
/// impl Div<Foo, Foo> for Foo {
/// fn div(&self, _rhs: &Foo) -> Foo {
/// println!("Dividing!");
@ -242,6 +250,8 @@ div_impl!(uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64)
/// ```
/// struct Foo;
///
/// impl Copy for Foo {}
///
/// impl Rem<Foo, Foo> for Foo {
/// fn rem(&self, _rhs: &Foo) -> Foo {
/// println!("Remainder-ing!");
@ -294,6 +304,8 @@ rem_float_impl!(f64, fmod)
/// ```
/// struct Foo;
///
/// impl Copy for Foo {}
///
/// impl Neg<Foo> for Foo {
/// fn neg(&self) -> Foo {
/// println!("Negating!");
@ -348,6 +360,8 @@ neg_uint_impl!(u64, i64)
/// ```
/// struct Foo;
///
/// impl Copy for Foo {}
///
/// impl Not<Foo> for Foo {
/// fn not(&self) -> Foo {
/// println!("Not-ing!");
@ -387,6 +401,8 @@ not_impl!(bool uint u8 u16 u32 u64 int i8 i16 i32 i64)
/// ```
/// struct Foo;
///
/// impl Copy for Foo {}
///
/// impl BitAnd<Foo, Foo> for Foo {
/// fn bitand(&self, _rhs: &Foo) -> Foo {
/// println!("Bitwise And-ing!");
@ -425,6 +441,8 @@ bitand_impl!(bool uint u8 u16 u32 u64 int i8 i16 i32 i64)
/// ```
/// struct Foo;
///
/// impl Copy for Foo {}
///
/// impl BitOr<Foo, Foo> for Foo {
/// fn bitor(&self, _rhs: &Foo) -> Foo {
/// println!("Bitwise Or-ing!");
@ -463,6 +481,8 @@ bitor_impl!(bool uint u8 u16 u32 u64 int i8 i16 i32 i64)
/// ```
/// struct Foo;
///
/// impl Copy for Foo {}
///
/// impl BitXor<Foo, Foo> for Foo {
/// fn bitxor(&self, _rhs: &Foo) -> Foo {
/// println!("Bitwise Xor-ing!");
@ -501,6 +521,8 @@ bitxor_impl!(bool uint u8 u16 u32 u64 int i8 i16 i32 i64)
/// ```
/// struct Foo;
///
/// impl Copy for Foo {}
///
/// impl Shl<Foo, Foo> for Foo {
/// fn shl(&self, _rhs: &Foo) -> Foo {
/// println!("Shifting left!");
@ -541,6 +563,8 @@ shl_impl!(uint u8 u16 u32 u64 int i8 i16 i32 i64)
/// ```
/// struct Foo;
///
/// impl Copy for Foo {}
///
/// impl Shr<Foo, Foo> for Foo {
/// fn shr(&self, _rhs: &Foo) -> Foo {
/// println!("Shifting right!");
@ -580,6 +604,8 @@ shr_impl!(uint u8 u16 u32 u64 int i8 i16 i32 i64)
/// ```
/// struct Foo;
///
/// impl Copy for Foo {}
///
/// impl Index<Foo, Foo> for Foo {
/// fn index<'a>(&'a self, _index: &Foo) -> &'a Foo {
/// println!("Indexing!");
@ -608,6 +634,8 @@ pub trait Index<Sized? Index, Sized? Result> for Sized? {
/// ```
/// struct Foo;
///
/// impl Copy for Foo {}
///
/// impl IndexMut<Foo, Foo> for Foo {
/// fn index_mut<'a>(&'a mut self, _index: &Foo) -> &'a mut Foo {
/// println!("Indexing!");
@ -636,6 +664,8 @@ pub trait IndexMut<Sized? Index, Sized? Result> for Sized? {
/// ```ignore
/// struct Foo;
///
/// impl Copy for Foo {}
///
/// impl Slice<Foo, Foo> for Foo {
/// fn as_slice_<'a>(&'a self) -> &'a Foo {
/// println!("Slicing!");
@ -682,6 +712,8 @@ pub trait Slice<Sized? Idx, Sized? Result> for Sized? {
/// ```ignore
/// struct Foo;
///
/// impl Copy for Foo {}
///
/// impl SliceMut<Foo, Foo> for Foo {
/// fn as_mut_slice_<'a>(&'a mut self) -> &'a mut Foo {
/// println!("Slicing!");

View file

@ -147,7 +147,9 @@ pub use self::Option::*;
use cmp::{Eq, Ord};
use default::Default;
use iter::{Iterator, IteratorExt, DoubleEndedIterator, FromIterator, ExactSizeIterator};
use iter::{Iterator, IteratorExt, DoubleEndedIterator, FromIterator};
use iter::{ExactSizeIterator};
use kinds::Copy;
use mem;
use result::Result;
use result::Result::{Ok, Err};
@ -857,3 +859,6 @@ impl<A, V: FromIterator<A>> FromIterator<Option<A>> for Option<V> {
}
}
}
impl<T:Copy> Copy for Option<T> {}

View file

@ -437,3 +437,4 @@ impl<T> PartialOrd for *mut T {
#[inline]
fn ge(&self, other: &*mut T) -> bool { *self >= *other }
}

View file

@ -18,6 +18,7 @@
//!
//! Their definition should always match the ABI defined in `rustc::back::abi`.
use kinds::Copy;
use mem;
use kinds::Sized;
@ -28,6 +29,8 @@ pub struct Slice<T> {
pub len: uint,
}
impl<T> Copy for Slice<T> {}
/// The representation of a Rust closure
#[repr(C)]
pub struct Closure {
@ -35,6 +38,8 @@ pub struct Closure {
pub env: *mut (),
}
impl Copy for Closure {}
/// The representation of a Rust procedure (`proc()`)
#[repr(C)]
pub struct Procedure {
@ -42,6 +47,8 @@ pub struct Procedure {
pub env: *mut (),
}
impl Copy for Procedure {}
/// The representation of a Rust trait object.
///
/// This struct does not have a `Repr` implementation
@ -52,6 +59,8 @@ pub struct TraitObject {
pub vtable: *mut (),
}
impl Copy for TraitObject {}
/// This trait is meant to map equivalences between raw structs and their
/// corresponding rust values.
pub trait Repr<T> for Sized? {

View file

@ -232,6 +232,7 @@
pub use self::Result::*;
use kinds::Copy;
use std::fmt::Show;
use slice;
use slice::AsSlice;
@ -916,3 +917,7 @@ pub fn fold<T,
}
Ok(init)
}
#[cfg(not(stage0))]
impl<T:Copy,U:Copy> Copy for Result<T,U> {}

View file

@ -37,6 +37,8 @@
#![allow(non_camel_case_types)]
#![allow(missing_docs)]
use kinds::Copy;
#[experimental]
#[simd]
#[deriving(Show)]
@ -46,6 +48,8 @@ pub struct i8x16(pub i8, pub i8, pub i8, pub i8,
pub i8, pub i8, pub i8, pub i8,
pub i8, pub i8, pub i8, pub i8);
impl Copy for i8x16 {}
#[experimental]
#[simd]
#[deriving(Show)]
@ -53,18 +57,24 @@ pub struct i8x16(pub i8, pub i8, pub i8, pub i8,
pub struct i16x8(pub i16, pub i16, pub i16, pub i16,
pub i16, pub i16, pub i16, pub i16);
impl Copy for i16x8 {}
#[experimental]
#[simd]
#[deriving(Show)]
#[repr(C)]
pub struct i32x4(pub i32, pub i32, pub i32, pub i32);
impl Copy for i32x4 {}
#[experimental]
#[simd]
#[deriving(Show)]
#[repr(C)]
pub struct i64x2(pub i64, pub i64);
impl Copy for i64x2 {}
#[experimental]
#[simd]
#[deriving(Show)]
@ -74,6 +84,8 @@ pub struct u8x16(pub u8, pub u8, pub u8, pub u8,
pub u8, pub u8, pub u8, pub u8,
pub u8, pub u8, pub u8, pub u8);
impl Copy for u8x16 {}
#[experimental]
#[simd]
#[deriving(Show)]
@ -81,26 +93,37 @@ pub struct u8x16(pub u8, pub u8, pub u8, pub u8,
pub struct u16x8(pub u16, pub u16, pub u16, pub u16,
pub u16, pub u16, pub u16, pub u16);
impl Copy for u16x8 {}
#[experimental]
#[simd]
#[deriving(Show)]
#[repr(C)]
pub struct u32x4(pub u32, pub u32, pub u32, pub u32);
impl Copy for u32x4 {}
#[experimental]
#[simd]
#[deriving(Show)]
#[repr(C)]
pub struct u64x2(pub u64, pub u64);
impl Copy for u64x2 {}
#[experimental]
#[simd]
#[deriving(Show)]
#[repr(C)]
pub struct f32x4(pub f32, pub f32, pub f32, pub f32);
impl Copy for f32x4 {}
#[experimental]
#[simd]
#[deriving(Show)]
#[repr(C)]
pub struct f64x2(pub f64, pub f64);
impl Copy for f64x2 {}

View file

@ -41,6 +41,7 @@ use cmp::Ordering::{Less, Equal, Greater};
use cmp;
use default::Default;
use iter::*;
use kinds::Copy;
use num::Int;
use ops;
use option::Option;
@ -1157,6 +1158,8 @@ impl<'a, T> Items<'a, T> {
}
}
impl<'a,T> Copy for Items<'a,T> {}
iterator!{struct Items -> *const T, &'a T}
#[experimental = "needs review"]
@ -1607,6 +1610,8 @@ pub enum BinarySearchResult {
NotFound(uint)
}
impl Copy for BinarySearchResult {}
#[experimental = "needs review"]
impl BinarySearchResult {
/// Converts a `Found` to `Some`, `NotFound` to `None`.
@ -1920,3 +1925,4 @@ impl_int_slice!(u16, i16)
impl_int_slice!(u32, i32)
impl_int_slice!(u64, i64)
impl_int_slice!(uint, int)

View file

@ -26,7 +26,7 @@ use default::Default;
use iter::{Map, Iterator, IteratorExt, DoubleEndedIterator};
use iter::{DoubleEndedIteratorExt, ExactSizeIterator};
use iter::range;
use kinds::Sized;
use kinds::{Copy, Sized};
use mem;
use num::Int;
use option::Option;
@ -176,6 +176,8 @@ pub struct Chars<'a> {
iter: slice::Items<'a, u8>
}
impl<'a> Copy for Chars<'a> {}
// Return the initial codepoint accumulator for the first byte.
// The first byte is special, only want bottom 5 bits for width 2, 4 bits
// for width 3, and 3 bits for width 4
@ -996,6 +998,8 @@ pub enum Utf16Item {
LoneSurrogate(u16)
}
impl Copy for Utf16Item {}
impl Utf16Item {
/// Convert `self` to a `char`, taking `LoneSurrogate`s to the
/// replacement character (U+FFFD).
@ -1139,6 +1143,8 @@ pub struct CharRange {
pub next: uint,
}
impl Copy for CharRange {}
/// Mask of the value bits of a continuation byte
const CONT_MASK: u8 = 0b0011_1111u8;
/// Value of the tag bits (tag mask is !CONT_MASK) of a continuation byte
@ -2315,3 +2321,4 @@ impl StrPrelude for str {
impl<'a> Default for &'a str {
fn default() -> &'a str { "" }
}