Skip to content

Commit 8ba4cfc

Browse files
committed
Require that types cannot implement both Drop and Copy.
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.
1 parent c7dd3c4 commit 8ba4cfc

File tree

3 files changed

+42
-8
lines changed

3 files changed

+42
-8
lines changed

src/librustc_typeck/coherence/mod.rs

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -387,21 +387,23 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
387387
Some(id) => id, None => { return }
388388
};
389389

390-
let impl_items = tcx.impl_items.borrow();
391390
let trait_impls = match tcx.trait_impls.borrow().get(&drop_trait).cloned() {
392391
None => return, // No types with (new-style) dtors present.
393392
Some(found_impls) => found_impls
394393
};
395394

396395
for &impl_did in trait_impls.borrow().iter() {
397-
let items = &(*impl_items)[impl_did];
398-
if items.len() < 1 {
399-
// We'll error out later. For now, just don't ICE.
400-
continue;
401-
}
402-
let method_def_id = items[0];
396+
let method_def_id = {
397+
let items = &tcx.impl_items.borrow()[impl_did];
398+
if items.len() < 1 {
399+
// We'll error out later. For now, just don't ICE.
400+
continue;
401+
}
402+
items[0]
403+
};
403404

404405
let self_type = self.get_self_type_for_implementation(impl_did);
406+
405407
match self_type.ty.sty {
406408
ty::ty_enum(type_def_id, _) |
407409
ty::ty_struct(type_def_id, _) |
@@ -434,6 +436,16 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
434436
}
435437
}
436438
}
439+
440+
if impl_did.krate == ast::LOCAL_CRATE {
441+
let span = tcx.map.span(impl_did.node);
442+
let param_env = ParameterEnvironment::for_item(tcx, impl_did.node);
443+
if !ty::type_moves_by_default(&param_env, span, self_type.ty) {
444+
span_err!(tcx.sess, span, E0184,
445+
"the `Drop` trait may not be implemented on \
446+
a type that implements `Copy`")
447+
}
448+
}
437449
}
438450
}
439451

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
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
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+
// issue #20126
12+
13+
#[derive(Copy)]
14+
struct Foo;
15+
16+
impl Drop for Foo {
17+
//~^ ERROR the `Drop` trait may not be implemented on a type that implements `Copy`
18+
fn drop(&mut self) {}
19+
}
20+
21+
fn main() {}

0 commit comments

Comments
 (0)