simplify Copy implementation error reporting
Span the affected fields instead of reporting the field/variant name.
This commit is contained in:
parent
e41920a1c3
commit
4cab2931c8
@ -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`?
|
||||
///
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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) => {
|
||||
|
@ -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
|
||||
|
@ -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() {
|
||||
}
|
@ -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
src/test/ui/span/E0204.stderr
Normal file
38
src/test/ui/span/E0204.stderr
Normal 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
|
||||
|
Loading…
Reference in New Issue
Block a user