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

@ -14,11 +14,15 @@ struct Foo {
bar2: Bar
}
impl Copy for Foo {}
struct Bar {
int1: int,
int2: int,
}
impl Copy for Bar {}
fn make_foo() -> Box<Foo> { panic!() }
fn borrow_same_field_twice_mut_mut() {

View file

@ -13,11 +13,15 @@ struct Foo {
bar2: Bar
}
impl Copy for Foo {}
struct Bar {
int1: int,
int2: int,
}
impl Copy for Bar {}
fn make_foo() -> Foo { panic!() }
fn borrow_same_field_twice_mut_mut() {

View file

@ -1,35 +0,0 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
enum Either<T, U> { Left(T), Right(U) }
fn f(x: &mut Either<int,f64>, y: &Either<int,f64>) -> int {
match *y {
Either::Left(ref z) => {
*x = Either::Right(1.0);
*z
}
_ => panic!()
}
}
fn g() {
let mut x: Either<int,f64> = Either::Left(3);
println!("{}", f(&mut x, &x)); //~ ERROR cannot borrow
}
fn h() {
let mut x: Either<int,f64> = Either::Left(3);
let y: &Either<int, f64> = &x;
let z: &mut Either<int, f64> = &mut x; //~ ERROR cannot borrow
*z = *y;
}
fn main() {}

View file

@ -9,6 +9,9 @@
// except according to those terms.
struct A { a: int, b: int }
impl Copy for A {}
struct B { a: int, b: Box<int> }
fn var_copy_after_var_borrow() {

View file

@ -16,6 +16,8 @@ use std::fmt::Show;
struct S;
impl Copy for S {}
impl Index<uint, str> for S {
fn index<'a>(&'a self, _: &uint) -> &'a str {
"hello"
@ -24,6 +26,8 @@ impl Index<uint, str> for S {
struct T;
impl Copy for T {}
impl Index<uint, Show + 'static> for T {
fn index<'a>(&'a self, idx: &uint) -> &'a (Show + 'static) {
static x: uint = 42;
@ -33,7 +37,8 @@ impl Index<uint, Show + 'static> for T {
fn main() {
S[0];
//~^ ERROR E0161
//~^ ERROR cannot move out of dereference
//~^^ ERROR E0161
T[0];
//~^ ERROR cannot move out of dereference
//~^^ ERROR E0161

View file

@ -13,8 +13,10 @@
pub fn main() {
let _x: Box<str> = box *"hello world";
//~^ ERROR E0161
//~^^ ERROR cannot move out of dereference
let array: &[int] = &[1, 2, 3];
let _x: Box<[int]> = box *array;
//~^ ERROR E0161
//~^^ ERROR cannot move out of dereference
}

View file

@ -13,5 +13,6 @@
fn main() {
(|| box *[0u].as_slice())();
//~^ ERROR cannot move a value of type [uint]
//~^ ERROR cannot move out of dereference
//~^^ ERROR cannot move a value of type [uint]
}

View file

@ -14,6 +14,7 @@
use std::rc::Rc;
fn assert_copy<T:Copy>() { }
trait Dummy { }
struct MyStruct {
@ -21,6 +22,8 @@ struct MyStruct {
y: int,
}
impl Copy for MyStruct {}
struct MyNoncopyStruct {
x: Box<char>,
}

View file

@ -12,6 +12,7 @@
#![allow(unused_variables)]
#![allow(non_camel_case_types)]
#![allow(non_upper_case_globals)]
#![allow(missing_copy_implementations)]
#![deny(dead_code)]
#![crate_type="lib"]

View file

@ -13,6 +13,7 @@
#![feature(globs)]
#![deny(missing_docs)]
#![allow(dead_code)]
#![allow(missing_copy_implementations)]
//! Some garbage docs for the crate here
#![doc="More garbage"]

View file

@ -0,0 +1,33 @@
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
struct CantCopyThis;
struct IWantToCopyThis {
but_i_cant: CantCopyThis,
}
impl Copy for IWantToCopyThis {}
//~^ ERROR the trait `Copy` may not be implemented for this type
enum CantCopyThisEither {
A,
B,
}
enum IWantToCopyThisToo {
ButICant(CantCopyThisEither),
}
impl Copy for IWantToCopyThisToo {}
//~^ ERROR the trait `Copy` may not be implemented for this type
fn main() {}

View file

@ -1,43 +0,0 @@
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// A zero-dependency test that covers some basic traits, default
// methods, etc. When mucking about with basic type system stuff I
// often encounter problems in the iterator trait, so it's useful to
// have hanging around. -nmatsakis
// error-pattern: requires `start` lang_item
#![no_std]
#![feature(lang_items)]
#[lang = "sized"]
pub trait Sized for Sized? {
// Empty.
}
pub mod std {
pub mod clone {
pub trait Clone {
fn clone(&self) -> Self;
}
}
}
pub struct ContravariantLifetime<'a>;
impl <'a> ::std::clone::Clone for ContravariantLifetime<'a> {
#[inline]
fn clone(&self) -> ContravariantLifetime<'a> {
match *self { ContravariantLifetime => ContravariantLifetime, }
}
}
fn main() { }

View file

@ -1,39 +0,0 @@
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// A zero-dependency test that covers some basic traits, default
// methods, etc. When mucking about with basic type system stuff I
// often encounter problems in the iterator trait, so it's useful to
// have hanging around. -nmatsakis
// error-pattern: requires `start` lang_item
#![no_std]
#![feature(lang_items)]
#[lang = "sized"]
pub trait Sized for Sized? {
// Empty.
}
#[unstable = "Definition may change slightly after trait reform"]
pub trait PartialEq for Sized? {
/// This method tests for `self` and `other` values to be equal, and is used by `==`.
fn eq(&self, other: &Self) -> bool;
}
#[unstable = "Trait is unstable."]
impl<'a, Sized? T: PartialEq> PartialEq for &'a T {
#[inline]
fn eq(&self, other: & &'a T) -> bool { PartialEq::eq(*self, *other) }
}
fn main() { }