simplify Copy implementation error reporting

Span the affected fields instead of reporting the field/variant name.
This commit is contained in:
Ariel Ben-Yehuda 2017-01-03 23:54:12 +02:00
parent e41920a1c3
commit 4cab2931c8
7 changed files with 68 additions and 73 deletions

View File

@ -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`?
///

View File

@ -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};
@ -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
}
@ -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 {
@ -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));
}
}
}

View File

@ -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
@ -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) => {

View File

@ -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
@ -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

View File

@ -1,30 +0,0 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
enum Foo {
Bar(Vec<u32>),
Baz,
}
impl Copy for Foo { }
//~^ ERROR the trait `Copy` may not be implemented for this type
//~| NOTE variant `Bar` does not implement `Copy`
#[derive(Copy)]
//~^ ERROR the trait `Copy` may not be implemented for this type
//~| NOTE variant `Bar` does not implement `Copy`
//~| NOTE in this expansion of #[derive(Copy)]
enum Foo2<'a> {
Bar(&'a mut bool),
Baz,
}
fn main() {
}

View File

@ -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() {
}

View File

@ -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