Skip to content

Commit 0cccb46

Browse files
committed
auto merge of #20631 : huonw/rust/no-drop-and-copy, r=nikomatsakis
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 #20126.
2 parents 9f1ead8 + 3c1ca17 commit 0cccb46

File tree

5 files changed

+46
-3
lines changed

5 files changed

+46
-3
lines changed

src/librustc/middle/ty.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6907,6 +6907,7 @@ pub enum CopyImplementationError {
69076907
FieldDoesNotImplementCopy(ast::Name),
69086908
VariantDoesNotImplementCopy(ast::Name),
69096909
TypeIsStructural,
6910+
TypeHasDestructor,
69106911
}
69116912

69126913
pub fn can_type_implement_copy<'a,'tcx>(param_env: &ParameterEnvironment<'a, 'tcx>,
@@ -6916,14 +6917,15 @@ pub fn can_type_implement_copy<'a,'tcx>(param_env: &ParameterEnvironment<'a, 'tc
69166917
{
69176918
let tcx = param_env.tcx;
69186919

6919-
match self_type.sty {
6920+
let did = match self_type.sty {
69206921
ty::ty_struct(struct_did, substs) => {
69216922
let fields = ty::struct_fields(tcx, struct_did, substs);
69226923
for field in fields.iter() {
69236924
if type_moves_by_default(param_env, span, field.mt.ty) {
69246925
return Err(FieldDoesNotImplementCopy(field.name))
69256926
}
69266927
}
6928+
struct_did
69276929
}
69286930
ty::ty_enum(enum_did, substs) => {
69296931
let enum_variants = ty::enum_variants(tcx, enum_did);
@@ -6936,8 +6938,13 @@ pub fn can_type_implement_copy<'a,'tcx>(param_env: &ParameterEnvironment<'a, 'tc
69366938
}
69376939
}
69386940
}
6941+
enum_did
69396942
}
69406943
_ => return Err(TypeIsStructural),
6944+
};
6945+
6946+
if ty::has_dtor(tcx, did) {
6947+
return Err(TypeHasDestructor)
69416948
}
69426949

69436950
Ok(())

src/librustc_typeck/coherence/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,11 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
507507
for this type; type is not a structure or \
508508
enumeration")
509509
}
510+
Err(ty::TypeHasDestructor) => {
511+
span_err!(tcx.sess, span, E0184,
512+
"the trait `Copy` may not be implemented for this type; \
513+
the type has a destructor");
514+
}
510515
}
511516
}
512517
}

src/librustc_typeck/diagnostics.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,5 +157,6 @@ register_diagnostics! {
157157
E0180,
158158
E0181,
159159
E0182,
160-
E0183
160+
E0183,
161+
E0184
161162
}

src/test/compile-fail/drop-on-non-struct.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
impl Drop for int {
11+
impl<'a> Drop for &'a mut int {
1212
//~^ ERROR the Drop trait may only be implemented on structures
1313
//~^^ ERROR E0117
1414
fn drop(&mut self) {
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(unsafe_destructor)]
12+
13+
// issue #20126
14+
15+
#[derive(Copy)] //~ ERROR the trait `Copy` may not be implemented
16+
struct Foo;
17+
18+
impl Drop for Foo {
19+
fn drop(&mut self) {}
20+
}
21+
22+
#[derive(Copy)] //~ ERROR the trait `Copy` may not be implemented
23+
struct Bar<T>;
24+
25+
#[unsafe_destructor]
26+
impl<T> Drop for Bar<T> {
27+
fn drop(&mut self) {}
28+
}
29+
30+
fn main() {}

0 commit comments

Comments
 (0)