Skip to content

Commit 74e5b7d

Browse files
committed
Auto merge of #38152 - arielb1:special-copy, r=nikomatsakis
Fix associated types in copy implementations Fixes an ICE and an error in checking copy implementations. r? @nikomatsakis
2 parents 2f56207 + 5fad51e commit 74e5b7d

File tree

8 files changed

+455
-437
lines changed

8 files changed

+455
-437
lines changed

src/libcore/marker.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -234,12 +234,10 @@ pub trait Unsize<T: ?Sized> {
234234
/// Generalizing the latter case, any type implementing [`Drop`] can't be `Copy`, because it's
235235
/// managing some resource besides its own [`size_of::<T>()`] bytes.
236236
///
237-
/// If you try to implement `Copy` on a struct or enum containing non-`Copy` data, you will get a
238-
/// compile-time error. Specifically, with structs you'll get [E0204] and with enums you'll get
239-
/// [E0205].
237+
/// If you try to implement `Copy` on a struct or enum containing non-`Copy` data, you will get
238+
/// the error [E0204].
240239
///
241240
/// [E0204]: ../../error-index.html#E0204
242-
/// [E0205]: ../../error-index.html#E0205
243241
///
244242
/// ## When *should* my type be `Copy`?
245243
///

src/librustc/ty/util.rs

+23-31
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use hir::map::DefPathData;
1515
use infer::InferCtxt;
1616
use hir::map as ast_map;
1717
use traits::{self, Reveal};
18-
use ty::{self, Ty, AdtKind, TyCtxt, TypeAndMut, TypeFlags, TypeFoldable};
18+
use ty::{self, Ty, TyCtxt, TypeAndMut, TypeFlags, TypeFoldable};
1919
use ty::{Disr, ParameterEnvironment};
2020
use ty::fold::TypeVisitor;
2121
use ty::layout::{Layout, LayoutError};
@@ -120,9 +120,8 @@ impl IntTypeExt for attr::IntType {
120120

121121

122122
#[derive(Copy, Clone)]
123-
pub enum CopyImplementationError {
124-
InfrigingField(Name),
125-
InfrigingVariant(Name),
123+
pub enum CopyImplementationError<'tcx> {
124+
InfrigingField(&'tcx ty::FieldDef),
126125
NotAnAdt,
127126
HasDestructor
128127
}
@@ -145,37 +144,30 @@ pub enum Representability {
145144
impl<'tcx> ParameterEnvironment<'tcx> {
146145
pub fn can_type_implement_copy<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
147146
self_type: Ty<'tcx>, span: Span)
148-
-> Result<(),CopyImplementationError> {
147+
-> Result<(), CopyImplementationError> {
149148
// FIXME: (@jroesch) float this code up
150-
tcx.infer_ctxt(None, Some(self.clone()), Reveal::ExactMatch).enter(|infcx| {
151-
let adt = match self_type.sty {
152-
ty::TyAdt(adt, substs) => match adt.adt_kind() {
153-
AdtKind::Struct | AdtKind::Union => {
154-
for field in adt.all_fields() {
155-
let field_ty = field.ty(tcx, substs);
156-
if infcx.type_moves_by_default(field_ty, span) {
157-
return Err(CopyImplementationError::InfrigingField(
158-
field.name))
159-
}
160-
}
161-
adt
162-
}
163-
AdtKind::Enum => {
164-
for variant in &adt.variants {
165-
for field in &variant.fields {
166-
let field_ty = field.ty(tcx, substs);
167-
if infcx.type_moves_by_default(field_ty, span) {
168-
return Err(CopyImplementationError::InfrigingVariant(
169-
variant.name))
170-
}
171-
}
172-
}
173-
adt
174-
}
175-
},
149+
tcx.infer_ctxt(None, Some(self.clone()), Reveal::NotSpecializable).enter(|infcx| {
150+
let (adt, substs) = match self_type.sty {
151+
ty::TyAdt(adt, substs) => (adt, substs),
176152
_ => return Err(CopyImplementationError::NotAnAdt)
177153
};
178154

155+
let field_implements_copy = |field: &ty::FieldDef| {
156+
let cause = traits::ObligationCause::dummy();
157+
match traits::fully_normalize(&infcx, cause, &field.ty(tcx, substs)) {
158+
Ok(ty) => !infcx.type_moves_by_default(ty, span),
159+
Err(..) => false
160+
}
161+
};
162+
163+
for variant in &adt.variants {
164+
for field in &variant.fields {
165+
if !field_implements_copy(field) {
166+
return Err(CopyImplementationError::InfrigingField(field));
167+
}
168+
}
169+
}
170+
179171
if adt.has_dtor() {
180172
return Err(CopyImplementationError::HasDestructor);
181173
}

0 commit comments

Comments
 (0)