Skip to content

Commit

Permalink
Require that types cannot implement both Drop and Copy.
Browse files Browse the repository at this point in the history
Opt-in built-in traits allowed one to explicitly implement both `Drop`
and `Copy` for a type. This can theoretically make some sense, but the
current implementation means it is codegened totally incorrectly which
can lead to memory unsafety, so this feature is disabled for now.

Fixes rust-lang#20126.
  • Loading branch information
huonw committed Jan 7, 2015
1 parent c7dd3c4 commit 3c1ca17
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 3 deletions.
9 changes: 8 additions & 1 deletion src/librustc/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6891,6 +6891,7 @@ pub enum CopyImplementationError {
FieldDoesNotImplementCopy(ast::Name),
VariantDoesNotImplementCopy(ast::Name),
TypeIsStructural,
TypeHasDestructor,
}

pub fn can_type_implement_copy<'a,'tcx>(param_env: &ParameterEnvironment<'a, 'tcx>,
Expand All @@ -6900,14 +6901,15 @@ pub fn can_type_implement_copy<'a,'tcx>(param_env: &ParameterEnvironment<'a, 'tc
{
let tcx = param_env.tcx;

match self_type.sty {
let did = match self_type.sty {
ty::ty_struct(struct_did, substs) => {
let fields = ty::struct_fields(tcx, struct_did, substs);
for field in fields.iter() {
if type_moves_by_default(param_env, span, field.mt.ty) {
return Err(FieldDoesNotImplementCopy(field.name))
}
}
struct_did
}
ty::ty_enum(enum_did, substs) => {
let enum_variants = ty::enum_variants(tcx, enum_did);
Expand All @@ -6920,8 +6922,13 @@ pub fn can_type_implement_copy<'a,'tcx>(param_env: &ParameterEnvironment<'a, 'tc
}
}
}
enum_did
}
_ => return Err(TypeIsStructural),
};

if ty::has_dtor(tcx, did) {
return Err(TypeHasDestructor)
}

Ok(())
Expand Down
5 changes: 5 additions & 0 deletions src/librustc_typeck/coherence/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,11 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
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 type has a destructor");
}
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/librustc_typeck/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,5 +157,6 @@ register_diagnostics! {
E0180,
E0181,
E0182,
E0183
E0183,
E0184
}
2 changes: 1 addition & 1 deletion src/test/compile-fail/drop-on-non-struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

impl Drop for int {
impl<'a> Drop for &'a mut int {
//~^ ERROR the Drop trait may only be implemented on structures
//~^^ ERROR cannot provide an extension implementation
fn drop(&mut self) {
Expand Down
30 changes: 30 additions & 0 deletions src/test/compile-fail/exclusive-drop-and-copy.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// 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 <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.

#![feature(unsafe_destructor)]

// issue #20126

#[derive(Copy)] //~ ERROR the trait `Copy` may not be implemented
struct Foo;

impl Drop for Foo {
fn drop(&mut self) {}
}

#[derive(Copy)] //~ ERROR the trait `Copy` may not be implemented
struct Bar<T>;

#[unsafe_destructor]
impl<T> Drop for Bar<T> {
fn drop(&mut self) {}
}

fn main() {}

1 comment on commit 3c1ca17

@huonw
Copy link
Owner Author

@huonw huonw commented on 3c1ca17 Jan 7, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

r=nikomatsakis p=1

Please sign in to comment.