Skip to content

Commit

Permalink
Auto merge of rust-lang#38152 - arielb1:special-copy, r=nikomatsakis
Browse files Browse the repository at this point in the history
Fix associated types in copy implementations

Fixes an ICE and an error in checking copy implementations.

r? @nikomatsakis
  • Loading branch information
bors committed Jan 5, 2017
2 parents 2f56207 + 5fad51e commit 74e5b7d
Show file tree
Hide file tree
Showing 8 changed files with 455 additions and 437 deletions.
6 changes: 2 additions & 4 deletions src/libcore/marker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,12 +234,10 @@ pub trait Unsize<T: ?Sized> {
/// Generalizing the latter case, any type implementing [`Drop`] can't be `Copy`, because it's
/// managing some resource besides its own [`size_of::<T>()`] bytes.
///
/// If you try to implement `Copy` on a struct or enum containing non-`Copy` data, you will get a
/// compile-time error. Specifically, with structs you'll get [E0204] and with enums you'll get
/// [E0205].
/// If you try to implement `Copy` on a struct or enum containing non-`Copy` data, you will get
/// the error [E0204].
///
/// [E0204]: ../../error-index.html#E0204
/// [E0205]: ../../error-index.html#E0205
///
/// ## When *should* my type be `Copy`?
///
Expand Down
54 changes: 23 additions & 31 deletions src/librustc/ty/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use hir::map::DefPathData;
use infer::InferCtxt;
use hir::map as ast_map;
use traits::{self, Reveal};
use ty::{self, Ty, AdtKind, TyCtxt, TypeAndMut, TypeFlags, TypeFoldable};
use ty::{self, Ty, TyCtxt, TypeAndMut, TypeFlags, TypeFoldable};
use ty::{Disr, ParameterEnvironment};
use ty::fold::TypeVisitor;
use ty::layout::{Layout, LayoutError};
Expand Down Expand Up @@ -120,9 +120,8 @@ impl IntTypeExt for attr::IntType {


#[derive(Copy, Clone)]
pub enum CopyImplementationError {
InfrigingField(Name),
InfrigingVariant(Name),
pub enum CopyImplementationError<'tcx> {
InfrigingField(&'tcx ty::FieldDef),
NotAnAdt,
HasDestructor
}
Expand All @@ -145,37 +144,30 @@ pub enum Representability {
impl<'tcx> ParameterEnvironment<'tcx> {
pub fn can_type_implement_copy<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
self_type: Ty<'tcx>, span: Span)
-> Result<(),CopyImplementationError> {
-> Result<(), CopyImplementationError> {
// FIXME: (@jroesch) float this code up
tcx.infer_ctxt(None, Some(self.clone()), Reveal::ExactMatch).enter(|infcx| {
let adt = match self_type.sty {
ty::TyAdt(adt, substs) => match adt.adt_kind() {
AdtKind::Struct | AdtKind::Union => {
for field in adt.all_fields() {
let field_ty = field.ty(tcx, substs);
if infcx.type_moves_by_default(field_ty, span) {
return Err(CopyImplementationError::InfrigingField(
field.name))
}
}
adt
}
AdtKind::Enum => {
for variant in &adt.variants {
for field in &variant.fields {
let field_ty = field.ty(tcx, substs);
if infcx.type_moves_by_default(field_ty, span) {
return Err(CopyImplementationError::InfrigingVariant(
variant.name))
}
}
}
adt
}
},
tcx.infer_ctxt(None, Some(self.clone()), Reveal::NotSpecializable).enter(|infcx| {
let (adt, substs) = match self_type.sty {
ty::TyAdt(adt, substs) => (adt, substs),
_ => return Err(CopyImplementationError::NotAnAdt)
};

let field_implements_copy = |field: &ty::FieldDef| {
let cause = traits::ObligationCause::dummy();
match traits::fully_normalize(&infcx, cause, &field.ty(tcx, substs)) {
Ok(ty) => !infcx.type_moves_by_default(ty, span),
Err(..) => false
}
};

for variant in &adt.variants {
for field in &variant.fields {
if !field_implements_copy(field) {
return Err(CopyImplementationError::InfrigingField(field));
}
}
}

if adt.has_dtor() {
return Err(CopyImplementationError::HasDestructor);
}
Expand Down
Loading

0 comments on commit 74e5b7d

Please sign in to comment.