Skip to content

Commit

Permalink
Show span for trait that doesn't implement Copy
Browse files Browse the repository at this point in the history
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`
```
  • Loading branch information
estebank committed Dec 28, 2016
1 parent 4ecc85b commit d9d75b5
Show file tree
Hide file tree
Showing 13 changed files with 123 additions and 32 deletions.
6 changes: 3 additions & 3 deletions src/librustc/hir/map/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
Expand All @@ -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);

Expand All @@ -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));
Expand Down
13 changes: 13 additions & 0 deletions src/librustc/hir/map/definitions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
8 changes: 4 additions & 4 deletions src/librustc/ty/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down Expand Up @@ -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
Expand All @@ -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))
}
}
}
Expand Down
44 changes: 29 additions & 15 deletions src/librustc_typeck/coherence/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
6 changes: 4 additions & 2 deletions src/test/compile-fail/E0204.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,20 @@

struct Foo {
foo: Vec<u32>,
//~^ 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() {
Expand Down
10 changes: 6 additions & 4 deletions src/test/compile-fail/E0205.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,21 @@

enum Foo {
Bar(Vec<u32>),
//~^ 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,
}

Expand Down
2 changes: 1 addition & 1 deletion src/test/compile-fail/issue-27340.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {}
4 changes: 2 additions & 2 deletions src/test/compile-fail/opt-in-copy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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() {}
2 changes: 1 addition & 1 deletion src/test/compile-fail/union/union-copy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {}
19 changes: 19 additions & 0 deletions src/test/ui/span/issue-19950-1.rs
Original file line number Diff line number Diff line change
@@ -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 <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.

struct NoCopy;

struct Bar {
item: NoCopy,
}

impl Copy for Bar {}

fn main() {}
11 changes: 11 additions & 0 deletions src/test/ui/span/issue-19950-1.stderr
Original file line number Diff line number Diff line change
@@ -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

19 changes: 19 additions & 0 deletions src/test/ui/span/issue-19950-2.rs
Original file line number Diff line number Diff line change
@@ -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 <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.

struct NoCopy;

enum Foo {
MyVariant(NoCopy)
}

impl Copy for Foo {}

fn main() {}
11 changes: 11 additions & 0 deletions src/test/ui/span/issue-19950-2.stderr
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit d9d75b5

Please sign in to comment.