Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show span for trait that doesn't implement Copy #37493

Closed

Conversation

estebank
Copy link
Contributor

Point at span for trait that doesn't implement Copy.

Given the following code:

struct NoCopy;

enum Test {
    MyVariant(NoCopy)
}

impl Copy for Test {}

fn main() {}

show the following output:

error[E0205]: the trait `Copy` may not be implemented for this type
 --> file.rs:7:6
  |
4 |     MyVariant(NoCopy)
  |     ----------------- `MyVariant` defined here
...
7 | impl Copy for Test {}
  |      ^^^^ variant `MyVariant` does not implement `Copy`

error: aborting due to previous error

Re: #19950.

@rust-highfive
Copy link
Collaborator

Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @Aatch (or someone else) soon.

If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes.

Please see the contribution instructions for more information.

@estebank
Copy link
Contributor Author

The current output is:

error[E0205]: the trait `Copy` may not be implemented for this type
 --> <anon>:7:6
  |
7 | impl Copy for Test {}
  |      ^^^^ variant `MyVariant` does not implement `Copy`

error: aborting due to previous error

@estebank estebank force-pushed the point-to-missing-copy-span-19950 branch 2 times, most recently from 9a416ad to 9575724 Compare October 31, 2016 19:07
@estebank
Copy link
Contributor Author

estebank commented Nov 7, 2016

r? @jonathandturner

@rust-highfive rust-highfive assigned sophiajt and unassigned Aatch Nov 7, 2016
@sophiajt
Copy link
Contributor

sophiajt commented Nov 8, 2016

Cool. Yeah, I like this, I think. Does it work for things that aren't enum variants also?

Looking at the code, I was a little confused:

    pub fn span_if_local(&self, id: DefId) -> Option<Span> {
        self.as_local_node_id(id).map(|id| self.span(id))
    }

    pub fn span_if_local_opt(&self, id: DefId) -> Option<Span> {
        self.as_local_node_id(id).and_then(|id| self.opt_span(id))
    }

Do we need the new function you're adding? Seem similar

@estebank
Copy link
Contributor Author

estebank commented Nov 8, 2016

Do we need the new function you're adding? Seem similar

@jonathandturner during my testing if I found cases where an id would be used that could not be returned by self.span, causing a panic. I didn't replace span_if_local with the body you see in ..._opt because I was unsure wether this behavior was intended and relied upon in other parts of the codebase. If it isn't, then using opt_span(_) instead of span(_) would be better.

Does it work for things that aren't enum variants also?

It should work for structs too. I can add an unittest for that case if you want.

@estebank estebank force-pushed the point-to-missing-copy-span-19950 branch 2 times, most recently from b4a9ca1 to fdc8777 Compare November 10, 2016 05:43
@alexcrichton alexcrichton added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Nov 10, 2016
@estebank
Copy link
Contributor Author

@jonathandturner left only span_if_local but with the non-panic behavior. Added UI test.

this type");
err.span_label(span, &format!("field `{}` does not implement `Copy`", name));
if let Some(def_span) = tcx.map.span_if_local(did) {
err.span_label(def_span, &format!("`{}` defined here", name));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see tests for this "defined here" branch. There's a test for variant "defined here" case, but not for fields. Can you add one if there aren't?

@brson
Copy link
Contributor

brson commented Nov 11, 2016

Although I think this improvement is fine as is, some thoughts about this example:

error[E0205]: the trait `Copy` may not be implemented for this type
 --> file.rs:7:6
  |
4 |     MyVariant(NoCopy)
  |     ----------------- `MyVariant` defined here
...
7 | impl Copy for Test {}
  |      ^^^^ variant `MyVariant` does not implement `Copy`

It's peculiar that the subject of the error, the type "Test", is mentioned in an extremely non-prominent way. The main error text, "may not be implemented for this type", makes it sound like a type is the most important thing in this error, but the two snippets printed are about variants, and don't mention the type.

Underlining Copy with the annotation "variant MyVariant does not implement Copy" is not as clear is it could be. What's the relationship between "Copy" in impl Copy for Test and MyVariant.

When the variant is defined before the impl, as in this example, the first snippet is no longer pointing to the subject of the error, that is, impl Copy for Test. I found that confusing. I'm seeing an error about an impl Copy and a type, being shown a variant of something, then an impl Copy of a type that is the subject of the error, then a statement that "MyVariant does not implement Copy". It doesn't quite all connect.

Considering the information at hand I might find something like the following more illuminating:

error[E0205]: the trait `Copy` may not be implemented for type `Test`
 --> file.rs:7:6
  |
7 | impl Copy for Test {}
...
4 |     MyVariant(NoCopy)
  |     ----------------- because `Test` variant `MyVariant` does not implement `Copy`

then maybe even "because NoCopy does not implement Copy. To make Test Copy, derive Copy for etc."

I'm not sure how correct it is to say that a variant implements a trait, since variants are not types.

@brson
Copy link
Contributor

brson commented Nov 11, 2016

Oh, here's another try:

error[E0205]: enum variant `Test::MyVariant` does not implement `Copy`
 --> file.rs:7:6
  |
4 |     MyVariant(NoCopy)
  |                        ---- because `NoCopy` is not `Copy`
...
7 | impl Copy for Test {}
  |      ^^^^ required because `Copy` is implemented for `Test` here

This makes it about the variant, assuming that the solution is to make NoCopy copy, and that's what they should look at.

I don't know if that's true or not though. Just some ideas.

The more important case anyway is the one where impl Copy isn't written explicitly but derived. Can you add a test case that uses #[derive(Copy)] and generates these errors?

@estebank
Copy link
Contributor Author

@brson changed the output to:

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
   |
23 | impl Copy for Bar {}
   | ^^^^^^^^^^^^^^^^^^^^ field `item` doesn't implement `Copy`

How does that look?

The more important case anyway is the one where impl Copy isn't written explicitly but derived. Can you add a test case that uses #[derive(Copy)] and generates these errors?

There's already a non ui test for it

@sophiajt
Copy link
Contributor

I'd say this is probably getting close enough. The one question I had looking at it comparing the two was here:

error[E0204]: the trait `Copy` may not be implemented for type `Bar`
  --> $DIR/issue-19950.rs:23:1
   |
23 | impl Copy for Bar {}
   | ^^^^^^^^^^^^^^^^^^^^ field `item` doesn't implement `Copy`

In the E0205 case we show where the problem is, but here you have to go find where item is defined. Is there any way to show that with a secondary label like the E0205 case?

@estebank
Copy link
Contributor Author

I've been trying to get the field item to be shown, but for some reason it (ItemStruct) is not part of the Map, while MyVariant (EntryVariant) is. That's why I'm not showing the definition. I'm looking at fixing that.

@estebank estebank force-pushed the point-to-missing-copy-span-19950 branch from 27ef67e to df8a29a Compare November 13, 2016 01:28
@estebank
Copy link
Contributor Author

So I've found that struct items are never part of the Map. I've made it so that they're added, pointing to the struct's Node, as I haven't been able to find a clean way to add an EntryStructField. Is it ok if I create a different PR to properly add support for this, given the current output:

error[E0205]: the trait `Copy` may not be implemented for type `Foo`
 --> foo.rs:7:6
  |
4 |         MyVariant(NoCopy)
  |         ----------------- this variant doesn't implement `Copy`
...
7 | impl Copy for Foo {}
  |      ^^^^ variant `Foo::MyVariant` doesn't implement `Copy`

error[E0204]: the trait `Copy` may not be implemented for type `Bar`
  --> foo.rs:13:1
   |
9  | struct Bar {
   | - field `item` in this struct doesn't implement `Copy`
...
13 | impl Copy for Bar {}
   | ^^^^^^^^^^^^^^^^^^^^ field `item` doesn't implement `Copy`

error: aborting due to 2 previous errors

I am intrigued as to the rationale for variants to be indexed, while struct fields aren't.

@estebank estebank force-pushed the point-to-missing-copy-span-19950 branch from df8a29a to c19113b Compare November 13, 2016 03:09
} else {
// This should be replaced with `visit_struct_field` once there's a Node
// for struct fields. In the meantime, register the parent node to have
// something to point to.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ugh, this. I think I've added nodes for fields in at least two branches already.
Do you mind waiting for #37676? It could land in less than a week and has the correct fix.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hadn't seen that PR. That's quite a refactor! I have no problem waiting for it.

@estebank estebank force-pushed the point-to-missing-copy-span-19950 branch from c19113b to 9c8f7fa Compare November 28, 2016 23:48
@estebank
Copy link
Contributor Author

@jonathandturner, @eddyb: after #37676 landing, now both cases point to the element (variant/field) that doesn't implement Copy:

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`

@sophiajt
Copy link
Contributor

@estebank - interesting. so if that's true, does that mean the main issue here got fixed?

@estebank
Copy link
Contributor Author

@jonathandturner #37676 added spans for struct fields to the map, which allows me to point at the correct field in this error.

The current output doesn't point at the field or variant that doesn't implement Copy:

error[E0205]: the trait `Copy` may not be implemented for this type
 --> <anon>:7:6
  |
7 | impl Copy for Foo {}
  |      ^^^^ variant `MyVariant` does not implement `Copy`

error[E0204]: the trait `Copy` may not be implemented for this type
  --> <anon>:13:1
   |
13 | impl Copy for Bar {}
   | ^^^^^^^^^^^^^^^^^^^^ field `item` does not implement `Copy`

@sophiajt
Copy link
Contributor

sophiajt commented Nov 29, 2016

Oh I got it! That's awesome then. Ready for review?

@estebank
Copy link
Contributor Author

Yeah! 👍

@estebank estebank force-pushed the point-to-missing-copy-span-19950 branch from 2b35c63 to 7ba99a4 Compare November 30, 2016 02:26
name,
self_type));
&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`");
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking something more like:

if let Some(def_span) = tcx.map.span_if_local(did) {
    err.span_label(def_span, &"this field doesn't implement `Copy`");
    err.span_label(span, &format!("field `{}` doesn't implement `Copy`", name));
} else {
    err.span_label(span,
                   &format!("field `{}` in struct `{}` doesn't implement `Copy`",
                            name,
                            self_type));
}

That way, in the case we don't have the def_span available, we can still give them a little more hint as to where it's coming from.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jonathandturner We should talk about a transition plan: ideally, span_if_local wouldn't exist after #37954, as every DefId has an associated Span.
The problem is that there's no source available and there's a few ways in which we could approach this (including embedding the full source in metadata).
In any case, long-term I'd like to not have code that branches out like this, but rather generate "field bar of struct Foo" from just its DefId, and point to its span if local, unless we can somehow show the source itself.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah okay, got it. We can experiment with that later, but sounds like that'll affect more than just this PR. I don't want to hold this one up while we figure out the bigger picture.

@sophiajt
Copy link
Contributor

sophiajt commented Dec 1, 2016

@bors r+

@bors
Copy link
Contributor

bors commented Dec 1, 2016

📌 Commit 7ba99a4 has been approved by jonathandturner

@bors
Copy link
Contributor

bors commented Dec 1, 2016

⌛ Testing commit 7ba99a4 with merge c75925e...

@bors
Copy link
Contributor

bors commented Dec 1, 2016

💔 Test failed - auto-win-gnu-32-opt-rustbuild

@estebank estebank force-pushed the point-to-missing-copy-span-19950 branch from 7ba99a4 to 44edb55 Compare December 1, 2016 08:02
@estebank
Copy link
Contributor Author

estebank commented Dec 1, 2016

Had to rebase against master to fix error. Tests have completed, I'll be needing a new r+, @jonathandturner.

@sophiajt
Copy link
Contributor

sophiajt commented Dec 2, 2016

@bors r+

@bors
Copy link
Contributor

bors commented Dec 2, 2016

📌 Commit 44edb55 has been approved by jonathandturner

@bors
Copy link
Contributor

bors commented Dec 2, 2016

⌛ Testing commit 44edb55 with merge a1b0040...

@bors
Copy link
Contributor

bors commented Dec 2, 2016

💔 Test failed - auto-win-gnu-32-opt-rustbuild

@sophiajt
Copy link
Contributor

sophiajt commented Dec 2, 2016

Failure seems legit:

------------------------------------------
stderr:
------------------------------------------
error[E0204]: the trait `Copy` may not be implemented for type `Bar`
  --> C:\bot\slave\auto-win-gnu-32-opt-rustbuild\build\src/test\ui\span\issue-19950.rs:23:1
   |
20 |     item: NoCopy,
   |     ------------ this field doesn't implement `Copy`
...
23 | impl Copy for Bar {}
   | ^^^^^^^^^^^^^^^^^^^^ field `item` doesn't implement `Copy`

error[E0205]: the trait `Copy` may not be implemented for type `Foo`
  --> C:\bot\slave\auto-win-gnu-32-opt-rustbuild\build\src/test\ui\span\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: aborting due to 2 previous errors


------------------------------------------

thread '[ui] ui\span\issue-19950.rs' panicked at 'explicit panic', C:\bot\slave\auto-win-gnu-32-opt-rustbuild\build\src\tools\compiletest\src\runtest.rs:2407
note: Run with `RUST_BACKTRACE=1` for a backtrace.


failures:
    [ui] ui\span\issue-19950.rs

@estebank
Copy link
Contributor Author

estebank commented Dec 5, 2016

Just took a look at it and this was caused because the ordering of messages is not consistent across platforms. Is it ok if I split this test case into two separate files while I work on ordering the output of errors in a separate PR?

@estebank estebank force-pushed the point-to-missing-copy-span-19950 branch 2 times, most recently from 83ffdbc to a8e24a2 Compare December 5, 2016 05:55
@sophiajt
Copy link
Contributor

sophiajt commented Dec 6, 2016

@estebank - are you saying that a single test might give multiple results non-deterministically? If that's the case, that sounds bad (and something we should definitely fix)

@estebank
Copy link
Contributor Author

estebank commented Dec 6, 2016

@jonathandturner The error was that the order of the errors was swapped. Given it failed only in win32 that made me think that the order the errors are emitted is different in different platforms (even though that makes little sense). I think more likely there was a change in the emit order between the time it got tested by travis and the time it go tested by bors.

@bors
Copy link
Contributor

bors commented Dec 16, 2016

☔ The latest upstream changes (presumably #38357) made this pull request unmergeable. Please resolve the merge conflicts.

@estebank estebank force-pushed the point-to-missing-copy-span-19950 branch from a8e24a2 to 8c640fe Compare December 20, 2016 18:53
@bors
Copy link
Contributor

bors commented Dec 21, 2016

☔ The latest upstream changes (presumably #38499) made this pull request unmergeable. Please resolve the merge conflicts.

@estebank estebank force-pushed the point-to-missing-copy-span-19950 branch from 8c640fe to 8d5c21a Compare December 22, 2016 05:31
@bors
Copy link
Contributor

bors commented Dec 28, 2016

☔ The latest upstream changes (presumably #38449) made this pull request unmergeable. Please resolve the merge conflicts.

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`
```
@estebank estebank force-pushed the point-to-missing-copy-span-19950 branch from 8d5c21a to d9d75b5 Compare December 28, 2016 23:30
@bors
Copy link
Contributor

bors commented Jan 5, 2017

☔ The latest upstream changes (presumably #38152) made this pull request unmergeable. Please resolve the merge conflicts.

@arielb1
Copy link
Contributor

arielb1 commented Jan 5, 2017

Superseded by #38152.

Sorry, didn't notice this PR was open. Thanks for the PR!

@arielb1 arielb1 closed this Jan 5, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants