Skip to content

Commit

Permalink
simplify Copy implementation error reporting
Browse files Browse the repository at this point in the history
Span the affected fields instead of reporting the field/variant name.
  • Loading branch information
arielb1 committed Jan 3, 2017
1 parent e41920a commit 4cab293
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 73 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
30 changes: 8 additions & 22 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,7 +144,7 @@ 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::NotSpecializable).enter(|infcx| {
let (adt, substs) = match self_type.sty {
Expand All @@ -161,23 +160,10 @@ impl<'tcx> ParameterEnvironment<'tcx> {
}
};

match adt.adt_kind() {
AdtKind::Struct | AdtKind::Union => {
for field in adt.all_fields() {
if !field_implements_copy(field) {
return Err(CopyImplementationError::InfrigingField(
field.name))
}
}
}
AdtKind::Enum => {
for variant in &adt.variants {
for field in &variant.fields {
if !field_implements_copy(field) {
return Err(CopyImplementationError::InfrigingVariant(
variant.name))
}
}
for variant in &adt.variants {
for field in &variant.fields {
if !field_implements_copy(field) {
return Err(CopyImplementationError::InfrigingField(field));
}
}
}
Expand Down
17 changes: 5 additions & 12 deletions src/librustc_typeck/coherence/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,15 +121,7 @@ fn visit_implementation_of_copy<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_did:

match param_env.can_type_implement_copy(tcx, self_type, span) {
Ok(()) => {}
Err(CopyImplementationError::InfrigingField(name)) => {
struct_span_err!(tcx.sess,
span,
E0204,
"the trait `Copy` may not be implemented for this type")
.span_label(span, &format!("field `{}` does not implement `Copy`", name))
.emit()
}
Err(CopyImplementationError::InfrigingVariant(name)) => {
Err(CopyImplementationError::InfrigingField(field)) => {
let item = tcx.map.expect_item(impl_node_id);
let span = if let ItemImpl(.., Some(ref tr), _, _) = item.node {
tr.path.span
Expand All @@ -139,10 +131,11 @@ fn visit_implementation_of_copy<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_did:

struct_span_err!(tcx.sess,
span,
E0205,
E0204,
"the trait `Copy` may not be implemented for this type")
.span_label(span,
&format!("variant `{}` does not implement `Copy`", name))
.span_label(
tcx.def_span(field.did),
&"this field does not implement `Copy`")
.emit()
}
Err(CopyImplementationError::NotAnAdt) => {
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_typeck/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2300,6 +2300,7 @@ This fails because `&mut T` is not `Copy`, even when `T` is `Copy` (this
differs from the behavior for `&T`, which is always `Copy`).
"##,

/*
E0205: r##"
An attempt to implement the `Copy` trait for an enum failed because one of the
variants does not implement `Copy`. To fix this, you must implement `Copy` for
Expand Down Expand Up @@ -2329,6 +2330,7 @@ enum Foo<'a> {
This fails because `&mut T` is not `Copy`, even when `T` is `Copy` (this
differs from the behavior for `&T`, which is always `Copy`).
"##,
*/

E0206: r##"
You can only implement `Copy` for a struct or enum. Both of the following
Expand Down
30 changes: 0 additions & 30 deletions src/test/compile-fail/E0205.rs

This file was deleted.

18 changes: 13 additions & 5 deletions src/test/compile-fail/E0204.rs → src/test/ui/span/E0204.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,24 @@ struct Foo {
}

impl Copy for Foo { }
//~^ ERROR E0204
//~| NOTE field `foo` does not implement `Copy`

#[derive(Copy)]
//~^ ERROR E0204
//~| NOTE field `ty` does not implement `Copy`
//~| NOTE in this expansion of #[derive(Copy)]
struct Foo2<'a> {
ty: &'a mut bool,
}

enum EFoo {
Bar { x: Vec<u32> },
Baz,
}

impl Copy for EFoo { }

#[derive(Copy)]
enum EFoo2<'a> {
Bar(&'a mut bool),
Baz,
}

fn main() {
}
38 changes: 38 additions & 0 deletions src/test/ui/span/E0204.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
error[E0204]: the trait `Copy` may not be implemented for this type
--> $DIR/E0204.rs:29:10
|
29 | #[derive(Copy)]
| ^^^^
30 | enum EFoo2<'a> {
31 | Bar(&'a mut bool),
| ------------- this field does not implement `Copy`

error[E0204]: the trait `Copy` may not be implemented for this type
--> $DIR/E0204.rs:17:10
|
17 | #[derive(Copy)]
| ^^^^
18 | struct Foo2<'a> {
19 | ty: &'a mut bool,
| ---------------- this field does not implement `Copy`

error[E0204]: the trait `Copy` may not be implemented for this type
--> $DIR/E0204.rs:27:6
|
23 | Bar { x: Vec<u32> },
| ----------- this field does not implement `Copy`
...
27 | impl Copy for EFoo { }
| ^^^^

error[E0204]: the trait `Copy` may not be implemented for this type
--> $DIR/E0204.rs:15:6
|
12 | foo: Vec<u32>,
| ------------- this field does not implement `Copy`
...
15 | impl Copy for Foo { }
| ^^^^

error: aborting due to 4 previous errors

0 comments on commit 4cab293

Please sign in to comment.