From d9d75b5626f895334248fbc272767bbfe021e2e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 30 Oct 2016 21:46:13 -0700 Subject: [PATCH] Show span for trait that doesn't implement `Copy` Change error message to ```nocode error[E0205]: the trait `Copy` may not be implemented for type `Foo` --> $DIR/issue-19950.rs:17:6 | 14 | MyVariant(NoCopy) | ----------------- this variant doesn't implement `Copy` ... 17 | impl Copy for Foo {} | ^^^^ variant `Foo::MyVariant` doesn't implement `Copy` error[E0204]: the trait `Copy` may not be implemented for type `Bar` --> $DIR/issue-19950.rs:23:1 | 20 | item: NoCopy, | ------------ this field doesn't implement `Copy` ... 23 | impl Copy for Bar {} | ^^^^^^^^^^^^^^^^^^^^ field `item` in struct `Bar` doesn't implement `Copy` ``` --- src/librustc/hir/map/collector.rs | 6 ++-- src/librustc/hir/map/definitions.rs | 13 +++++++ src/librustc/ty/util.rs | 8 ++--- src/librustc_typeck/coherence/mod.rs | 44 +++++++++++++++-------- src/test/compile-fail/E0204.rs | 6 ++-- src/test/compile-fail/E0205.rs | 10 +++--- src/test/compile-fail/issue-27340.rs | 2 +- src/test/compile-fail/opt-in-copy.rs | 4 +-- src/test/compile-fail/union/union-copy.rs | 2 +- src/test/ui/span/issue-19950-1.rs | 19 ++++++++++ src/test/ui/span/issue-19950-1.stderr | 11 ++++++ src/test/ui/span/issue-19950-2.rs | 19 ++++++++++ src/test/ui/span/issue-19950-2.stderr | 11 ++++++ 13 files changed, 123 insertions(+), 32 deletions(-) create mode 100644 src/test/ui/span/issue-19950-1.rs create mode 100644 src/test/ui/span/issue-19950-1.stderr create mode 100644 src/test/ui/span/issue-19950-2.rs create mode 100644 src/test/ui/span/issue-19950-2.stderr diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index a6ffe7cea5592..83ccd67bdf63b 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -26,7 +26,7 @@ pub struct NodeCollector<'ast> { /// If true, completely ignore nested items. We set this when loading /// HIR from metadata, since in that case we only want the HIR for /// one specific item (and not the ones nested inside of it). - pub ignore_nested_items: bool + pub ignore_nested_items: bool, } impl<'ast> NodeCollector<'ast> { @@ -35,7 +35,7 @@ impl<'ast> NodeCollector<'ast> { krate: krate, map: vec![], parent_node: CRATE_NODE_ID, - ignore_nested_items: false + ignore_nested_items: false, }; collector.insert_entry(CRATE_NODE_ID, RootCrate); @@ -51,7 +51,7 @@ impl<'ast> NodeCollector<'ast> { krate: krate, map: map, parent_node: parent_node, - ignore_nested_items: true + ignore_nested_items: true, }; collector.insert_entry(parent_node, RootInlinedParent(parent)); diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index b28c5e80ea3c3..596b3f7247df5 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -18,6 +18,7 @@ use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::StableHasher; use serialize::{Encodable, Decodable, Encoder, Decoder}; +use std::fmt; use std::fmt::Write; use std::hash::{Hash, Hasher}; use syntax::ast; @@ -220,6 +221,18 @@ impl DefPath { } } +impl fmt::Display for DefPath { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + for (i, component) in self.data.iter().enumerate() { + write!(f, + "{}{}", + if i == 0 { "" } else {"::"}, + component.data.as_interned_str())?; + } + Ok(()) + } +} + #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub enum DefPathData { // Root: these should only be used for the root nodes, because diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index b4ac6b9d2502e..079e5c56a3565 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -115,8 +115,8 @@ impl IntTypeExt for attr::IntType { #[derive(Copy, Clone)] pub enum CopyImplementationError { - InfrigingField(Name), - InfrigingVariant(Name), + InfrigingField(DefId, Name), + InfrigingVariant(DefId, Name), NotAnAdt, HasDestructor } @@ -149,7 +149,7 @@ impl<'tcx> ParameterEnvironment<'tcx> { let field_ty = field.ty(tcx, substs); if infcx.type_moves_by_default(field_ty, span) { return Err(CopyImplementationError::InfrigingField( - field.name)) + field.did, field.name)) } } adt @@ -160,7 +160,7 @@ impl<'tcx> ParameterEnvironment<'tcx> { let field_ty = field.ty(tcx, substs); if infcx.type_moves_by_default(field_ty, span) { return Err(CopyImplementationError::InfrigingVariant( - variant.name)) + variant.did, variant.name)) } } } diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 3bbe5aa1fef37..a9e129f9f0009 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -253,29 +253,43 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { 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::InfrigingField(did, name)) => { + let mut err = struct_span_err!(tcx.sess, + span, + E0204, + "the trait `Copy` may not be implemented for \ + type `{}`", + self_type); + err.span_label(span, + &format!("field `{}` doesn't implement `Copy`", + name)); + if let Some(def_span) = tcx.map.span_if_local(did) { + err.span_label(def_span, &"this field doesn't implement `Copy`"); + } + err.emit() } - Err(CopyImplementationError::InfrigingVariant(name)) => { + Err(CopyImplementationError::InfrigingVariant(did, _)) => { let item = tcx.map.expect_item(impl_node_id); + let item_def_path = tcx.map.def_path(did); let span = if let ItemImpl(.., Some(ref tr), _, _) = item.node { tr.path.span } else { span }; - struct_span_err!(tcx.sess, - span, - E0205, - "the trait `Copy` may not be implemented for this type") - .span_label(span, - &format!("variant `{}` does not implement `Copy`", name)) - .emit() + let mut err = struct_span_err!(tcx.sess, + span, + E0205, + "the trait `Copy` may not be implemented for \ + type `{}`", + self_type); + err.span_label(span, + &format!("variant `{}` doesn't implement `Copy`", + item_def_path)); + if let Some(def_span) = tcx.map.span_if_local(did) { + err.span_label(def_span, &"this variant doesn't implement `Copy`"); + } + err.emit() } Err(CopyImplementationError::NotAnAdt) => { let item = tcx.map.expect_item(impl_node_id); diff --git a/src/test/compile-fail/E0204.rs b/src/test/compile-fail/E0204.rs index 0f108a17c95db..41c319f0ede7a 100644 --- a/src/test/compile-fail/E0204.rs +++ b/src/test/compile-fail/E0204.rs @@ -10,18 +10,20 @@ struct Foo { foo: Vec, + //~^ this field doesn't implement `Copy` } impl Copy for Foo { } //~^ ERROR E0204 -//~| NOTE field `foo` does not implement `Copy` +//~| NOTE field `foo` doesn't implement `Copy` #[derive(Copy)] //~^ ERROR E0204 -//~| NOTE field `ty` does not implement `Copy` +//~| NOTE field `ty` doesn't implement `Copy` //~| NOTE in this expansion of #[derive(Copy)] struct Foo2<'a> { ty: &'a mut bool, + //~^ this field doesn't implement `Copy` } fn main() { diff --git a/src/test/compile-fail/E0205.rs b/src/test/compile-fail/E0205.rs index c73e753430105..dee8be82743ce 100644 --- a/src/test/compile-fail/E0205.rs +++ b/src/test/compile-fail/E0205.rs @@ -10,19 +10,21 @@ enum Foo { Bar(Vec), + //~^ NOTE this variant doesn't implement `Copy` Baz, } impl Copy for Foo { } -//~^ ERROR the trait `Copy` may not be implemented for this type -//~| NOTE variant `Bar` does not implement `Copy` +//~^ ERROR the trait `Copy` may not be implemented for type `Foo` +//~| NOTE variant `Foo::Bar` doesn't implement `Copy` #[derive(Copy)] -//~^ ERROR the trait `Copy` may not be implemented for this type -//~| NOTE variant `Bar` does not implement `Copy` +//~^ ERROR the trait `Copy` may not be implemented for type `Foo2<'a>` +//~| NOTE variant `Foo2::Bar` doesn't implement `Copy` //~| NOTE in this expansion of #[derive(Copy)] enum Foo2<'a> { Bar(&'a mut bool), + //~^ NOTE this variant doesn't implement `Copy` Baz, } diff --git a/src/test/compile-fail/issue-27340.rs b/src/test/compile-fail/issue-27340.rs index ce3fa487d4e02..f409adf4367d1 100644 --- a/src/test/compile-fail/issue-27340.rs +++ b/src/test/compile-fail/issue-27340.rs @@ -10,7 +10,7 @@ struct Foo; #[derive(Copy, Clone)] -//~^ ERROR the trait `Copy` may not be implemented for this type +//~^ ERROR the trait `Copy` may not be implemented for type `Bar` struct Bar(Foo); fn main() {} diff --git a/src/test/compile-fail/opt-in-copy.rs b/src/test/compile-fail/opt-in-copy.rs index bc18b52a0c1c9..881ad57f4e63c 100644 --- a/src/test/compile-fail/opt-in-copy.rs +++ b/src/test/compile-fail/opt-in-copy.rs @@ -15,7 +15,7 @@ struct IWantToCopyThis { } impl Copy for IWantToCopyThis {} -//~^ ERROR the trait `Copy` may not be implemented for this type +//~^ ERROR the trait `Copy` may not be implemented for type `IWantToCopyThis` enum CantCopyThisEither { A, @@ -27,6 +27,6 @@ enum IWantToCopyThisToo { } impl Copy for IWantToCopyThisToo {} -//~^ ERROR the trait `Copy` may not be implemented for this type +//~^ ERROR the trait `Copy` may not be implemented for type `IWantToCopyThisToo` fn main() {} diff --git a/src/test/compile-fail/union/union-copy.rs b/src/test/compile-fail/union/union-copy.rs index 9014b3f2956b7..176ef97c04574 100644 --- a/src/test/compile-fail/union/union-copy.rs +++ b/src/test/compile-fail/union/union-copy.rs @@ -21,6 +21,6 @@ union W { } impl Copy for U {} // OK -impl Copy for W {} //~ ERROR the trait `Copy` may not be implemented for this type +impl Copy for W {} //~ ERROR the trait `Copy` may not be implemented for type `W` fn main() {} diff --git a/src/test/ui/span/issue-19950-1.rs b/src/test/ui/span/issue-19950-1.rs new file mode 100644 index 0000000000000..af79414b2f71e --- /dev/null +++ b/src/test/ui/span/issue-19950-1.rs @@ -0,0 +1,19 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct NoCopy; + +struct Bar { + item: NoCopy, +} + +impl Copy for Bar {} + +fn main() {} diff --git a/src/test/ui/span/issue-19950-1.stderr b/src/test/ui/span/issue-19950-1.stderr new file mode 100644 index 0000000000000..45a4d2f77ff83 --- /dev/null +++ b/src/test/ui/span/issue-19950-1.stderr @@ -0,0 +1,11 @@ +error[E0204]: the trait `Copy` may not be implemented for type `Bar` + --> $DIR/issue-19950-1.rs:17:1 + | +14 | item: NoCopy, + | ------------ this field doesn't implement `Copy` +... +17 | impl Copy for Bar {} + | ^^^^^^^^^^^^^^^^^^^^ field `item` doesn't implement `Copy` + +error: aborting due to previous error + diff --git a/src/test/ui/span/issue-19950-2.rs b/src/test/ui/span/issue-19950-2.rs new file mode 100644 index 0000000000000..c71942dabc95d --- /dev/null +++ b/src/test/ui/span/issue-19950-2.rs @@ -0,0 +1,19 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct NoCopy; + +enum Foo { + MyVariant(NoCopy) +} + +impl Copy for Foo {} + +fn main() {} diff --git a/src/test/ui/span/issue-19950-2.stderr b/src/test/ui/span/issue-19950-2.stderr new file mode 100644 index 0000000000000..4095a8041f668 --- /dev/null +++ b/src/test/ui/span/issue-19950-2.stderr @@ -0,0 +1,11 @@ +error[E0205]: the trait `Copy` may not be implemented for type `Foo` + --> $DIR/issue-19950-2.rs:17:6 + | +14 | MyVariant(NoCopy) + | ----------------- this variant doesn't implement `Copy` +... +17 | impl Copy for Foo {} + | ^^^^ variant `Foo::MyVariant` doesn't implement `Copy` + +error: aborting due to previous error +