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

Use ident.span instead of def_span in dead-code pass #65830

Merged
merged 5 commits into from
Nov 6, 2019

Conversation

Quantumplation
Copy link
Contributor

Hello! First time contributor! :)

This should fix #58729.

According to @estebank in the duplicate #63064, def_span scans forward on the line until it finds a {,
and if it can't find one, falls back to the span for the whole item. This
was apparently written before the identifier span was explicitly tracked on
each node.

This means that if an unused function signature spans multiple lines, the
entire function (potentially hundreds of lines) gets flagged as dead code.
This could, for example, cause IDEs to add error squiggly's to the whole
function.

By using the span from the ident instead, we narrow the scope of this in
most cases. In a wider sense, it's probably safe to use ident.span
instead of def_span in most locations throughout the whole code base,
but since this is my first contribution, I kept it small.

Some interesting points that came up while I was working on this:

  • I reorganized the tests a bit to bring some of the dead code ones all
    into the same location
  • A few tests were for things unrelated to dead code (like the
    path-lookahead for parens), so I added #![allow(dead_code)] and
    cleaned up the stderr file to reduce noise in the future
  • The same fix doesn't apply to const and static declarations. I tried
    adding these cases to the match expression, but that created a much
    wider change to tests and error messages, so I left it off until I
    could get some code review to validate the approach.

@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 @davidtwco (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.

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Oct 25, 2019
@rust-highfive

This comment has been minimized.

@rust-highfive

This comment has been minimized.

@Quantumplation
Copy link
Contributor Author

Hmm, more failures... I'm not sure if these tests ran when I ran tests locally... Fixing now!

@Quantumplation
Copy link
Contributor Author

I got a seemingly unrelated test failure when running locally. given the error message, it sounds like it might just be a test that's not intended to run on WSL? I'm not sure...

failures:

---- net::tcp::tests::double_bind stdout ----
thread '<unnamed>' panicked at 'This system (perhaps due to options set by TcpListener::bind) permits double binding: TcpListener { addr: V4(127.0.0.1:19613), fd: 8 } and TcpListener { addr: V4(127.0.0.1:19613), fd: 15 }', src/libstd/net/tcp.rs:1257:34


failures:
    net::tcp::tests::double_bind

test result: FAILED. 762 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out

This gets thrown here: https://github.com/rust-lang/rust/blob/master/src/libstd/net/tcp.rs#L1257

I'm going to push my changes and hope the build passes when running on the linux build server 😅

Copy link
Member

@davidtwco davidtwco left a comment

Choose a reason for hiding this comment

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

This looks good to me. If you don't mind, I'd prefer the last three commits (84ecd026184e4979beb43d1aaf1a4e83c44bacc1, 0e00a56746d868c81bad604bca107364ef775b12 and 9b5ca693fdf731beaf88332b813f90bf3f0031ca) be squashed into 1277650b5fed98c19ee56c2bcf68fdc9bacaf7b5.

@Quantumplation
Copy link
Contributor Author

Sure thing!

@davidtwco
Copy link
Member

Thanks @Quantumplation!

@bors r+

@bors
Copy link
Contributor

bors commented Oct 26, 2019

📌 Commit 94890d2 has been approved by davidtwco

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Oct 26, 2019
Centril added a commit to Centril/rust that referenced this pull request Oct 26, 2019
Use ident.span instead of def_span in dead-code pass

Hello! First time contributor! :)

This should fix rust-lang#58729.

According to @estebank in the duplicate rust-lang#63064, def_span scans forward on the line until it finds a {,
and if it can't find one, falls back to the span for the whole item. This
was apparently written before the identifier span was explicitly tracked on
each node.

This means that if an unused function signature spans multiple lines, the
entire function (potentially hundreds of lines) gets flagged as dead code.
This could, for example, cause IDEs to add error squiggly's to the whole
function.

By using the span from the ident instead, we narrow the scope of this in
most cases. In a wider sense, it's probably safe to use ident.span
instead of def_span in most locations throughout the whole code base,
but since this is my first contribution, I kept it small.

Some interesting points that came up while I was working on this:
- I reorganized the tests a bit to bring some of the dead code ones all
into the same location
- A few tests were for things unrelated to dead code (like the
path-lookahead for parens), so I added #![allow(dead_code)] and
cleaned up the stderr file to reduce noise in the future
- The same fix doesn't apply to const and static declarations. I tried
adding these cases to the match expression, but that created a much
wider change to tests and error messages, so I left it off until I
could get some code review to validate the approach.
Centril added a commit to Centril/rust that referenced this pull request Oct 26, 2019
Use ident.span instead of def_span in dead-code pass

Hello! First time contributor! :)

This should fix rust-lang#58729.

According to @estebank in the duplicate rust-lang#63064, def_span scans forward on the line until it finds a {,
and if it can't find one, falls back to the span for the whole item. This
was apparently written before the identifier span was explicitly tracked on
each node.

This means that if an unused function signature spans multiple lines, the
entire function (potentially hundreds of lines) gets flagged as dead code.
This could, for example, cause IDEs to add error squiggly's to the whole
function.

By using the span from the ident instead, we narrow the scope of this in
most cases. In a wider sense, it's probably safe to use ident.span
instead of def_span in most locations throughout the whole code base,
but since this is my first contribution, I kept it small.

Some interesting points that came up while I was working on this:
- I reorganized the tests a bit to bring some of the dead code ones all
into the same location
- A few tests were for things unrelated to dead code (like the
path-lookahead for parens), so I added #![allow(dead_code)] and
cleaned up the stderr file to reduce noise in the future
- The same fix doesn't apply to const and static declarations. I tried
adding these cases to the match expression, but that created a much
wider change to tests and error messages, so I left it off until I
could get some code review to validate the approach.
@Quantumplation
Copy link
Contributor Author

Quantumplation commented Oct 27, 2019

At @estebank's request, rebasing this onto master and re-blessing the tests

This test was actually about the unreachable_code flag, not dead_code,
so I renamed it for clarity (to prepare for the next commit, where I
plan to move a bunch of the dead_code tests to a single folder)
This helps organize the tests better.  I also renamed several of the tests to remove redundant dead-code in the path, and better match what they're testing
According to @estebank, def_span scans forward on the line until it finds a {,
and if it can't find one, fallse back to the span for the whole item.  This
was apparently written before the identifier span was explicitly tracked on
each node.

This means that if an unused function signature spans multiple lines, the
entire function (potentially hundreds of lines) gets flagged as dead code.
This could, for example, cause IDEs to add error squiggly's to the whole
function.

By using the span from the ident instead, we narrow the scope of this in
most cases.  In a wider sense, it's probably safe to use ident.span
instead of def_span in most locations throughout the whole code base,
but since this is my first contribution, I kept it small.

Some interesting points that came up while I was working on this:
 - I reorganized the tests a bit to bring some of the dead code ones all
   into the same location
 - A few tests were for things unrelated to dead code (like the
   path-lookahead for parens), so I added #![allow(dead_code)] and
   cleaned up the stderr file to reduce noise in the future
 - The same fix doesn't apply to const and static declarations.  I tried
   adding these cases to the match expression, but that created a much
   wider change to tests and error messages, so I left it off until I
   could get some code review to validate the approach.
@Quantumplation
Copy link
Contributor Author

Quantumplation commented Oct 27, 2019

I wasn't able to run tests to completion (same bind_address issue I mentioned above), but it got pretty far and no tests were updated. I'm not sure whether to push the rebase anyway.

@davidtwco
Copy link
Member

@bors r+

@bors
Copy link
Contributor

bors commented Oct 27, 2019

📌 Commit 7985510 has been approved by davidtwco

@Centril
Copy link
Contributor

Centril commented Oct 27, 2019

Possibly caused failure in #65854 (comment), @bors rollup=never

@Quantumplation
Copy link
Contributor Author

@Centril what is your recommended path to resolution on this?

@Centril
Copy link
Contributor

Centril commented Oct 27, 2019

@Quantumplation Check if something in your PR could have caused this, otherwise CI will tell us eventually.

@davidtwco
Copy link
Member

@Centril Hmm.. Looks like it passed without my changes, but I'm pretty baffled as to why my changes would cause failures. It doesn't look like an .stderr that I forgot to update, and all I did was change how the error message was printing. I'll try to dig deeper later today when I'm back at the computer I use for rust dev.

@Quantumplation Rust's CI merges with master before it runs any tests. If a new test was added in master that your patch would have affected, then it won't have an updated stderr (because your patch doesn't know about it). When @Centril attempted a rollup (combining lots of patches to merge all at once) yesterday, the failure looked like it might have been because of what I've just described happening with your patch.

That's probably why @estebank requested you rebase and re-bless. Since you did that, so long as more new tests haven't been added that would fail in the same way, your patch should be good to merge, which is why I re-approved it. But given that your patch seems susceptible to this sort of failure (as evidenced by it having happened), @Centril marked it as rollup=never, which means that it won't be combined with other small patches and landed all at once (since if it did cause a failure, it slows down other patches landing too).

tl;dr you probably don't need to do anything right now, by rebasing and re-blessing yesterday you've probably fixed the problem.

@Quantumplation
Copy link
Contributor Author

@davidtwco Ah, right, that makes sense. For some reason I thought this failed even after I rebased, but it didn't make it's way into a roll up, so everything makes sense again heh.

@bors
Copy link
Contributor

bors commented Nov 4, 2019

⌛ Testing commit 7985510 with merge 8ca4a7f8acf67dabd6d9cf9e60f8b282a297da99...

@rust-highfive
Copy link
Collaborator

The job dist-mipsel-linux of your PR failed (pretty log, raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.
2019-11-04T02:19:13.4048301Z [RUSTC-TIMING] rls_data test:false 2.245
2019-11-04T02:19:13.4071299Z    Compiling rand v0.7.0
2019-11-04T02:19:15.2308162Z [RUSTC-TIMING] parking_lot test:false 2.133
2019-11-04T02:19:15.2351709Z    Compiling rustc_macros v0.1.0 (/checkout/src/librustc_macros)
2019-11-04T02:19:15.6888992Z error: function is never used: `query`
2019-11-04T02:19:15.6889356Z   --> src/librustc_macros/src/query.rs:16:26
2019-11-04T02:19:15.6889609Z    |
2019-11-04T02:19:15.6890505Z 16 |     syn::custom_keyword!(query);
2019-11-04T02:19:15.6891430Z    |
2019-11-04T02:19:15.6891685Z    = note: `-D dead-code` implied by `-D warnings`
2019-11-04T02:19:15.6897365Z 
2019-11-04T02:19:15.6897365Z 
2019-11-04T02:19:15.6920029Z error: function is never used: `Keywords`
2019-11-04T02:19:15.6920368Z   --> src/librustc_macros/src/symbols.rs:13:26
2019-11-04T02:19:15.6920604Z    |
2019-11-04T02:19:15.6921022Z 13 |     syn::custom_keyword!(Keywords);
2019-11-04T02:19:15.6927087Z 
2019-11-04T02:19:15.6947147Z error: function is never used: `Symbols`
2019-11-04T02:19:15.6947453Z   --> src/librustc_macros/src/symbols.rs:14:26
2019-11-04T02:19:15.6947684Z    |
2019-11-04T02:19:15.6947684Z    |
2019-11-04T02:19:15.6947937Z 14 |     syn::custom_keyword!(Symbols);
2019-11-04T02:19:15.6990453Z 
2019-11-04T02:19:15.7037468Z error: aborting due to 3 previous errors
2019-11-04T02:19:15.7040769Z 
2019-11-04T02:19:15.7154498Z [RUSTC-TIMING] rustc_macros test:false 0.477
---
2019-11-04T02:19:16.7758521Z   local time: Mon Nov  4 02:19:16 UTC 2019
2019-11-04T02:19:17.0410112Z   network time: Mon, 04 Nov 2019 02:19:17 GMT
2019-11-04T02:19:17.0414067Z == end clock drift check ==
2019-11-04T02:19:18.2094184Z 
2019-11-04T02:19:18.2172886Z ##[error]Bash exited with code '1'.
2019-11-04T02:19:18.2227459Z ##[section]Starting: Checkout
2019-11-04T02:19:18.2229228Z ==============================================================================
2019-11-04T02:19:18.2229302Z Task         : Get sources
2019-11-04T02:19:18.2229387Z Description  : Get sources from a repository. Supports Git, TfsVC, and SVN repositories.

I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact @TimNN. (Feature Requests)

@bors
Copy link
Contributor

bors commented Nov 4, 2019

💔 Test failed - checks-azure

@bors bors added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Nov 4, 2019
@Quantumplation
Copy link
Contributor Author

After some digging, I think the test failure and the error message regression reported by @bjorn3 are caused by the same thing, i.e. a change in the macro expansion.

Specifically, see this line: https://github.com/rust-lang/rust/blob/master/src/librustc/lint/mod.rs#L681

Here, it uses the reported span alone to detect if the error is in an external macro. Previously, (I guess, I still don't understand well enough to say definitively), def_span(...) would return a span that other code would consider to be part of a macro. This would do two things:

  • trigger the "in this macro invocation" helper above
  • cause the error from the query, Keywords and Symbol unused symbols to be canceled.

One thing that's unclear to me is why query, Keywords, and Symbol are considered dead code in the first place: they're used elsewhere in the file (example: https://github.com/rust-lang/rust/blob/master/src/librustc_macros/src/query.rs#L153)

Until someone can weigh in on how to address this more thoroughly, I'll just revert to the old def_span call if item.span is in a macro. Exactly how to do that is TBD, while I poke around the code, but I'll be looking at these two places for hints, since this is how the two cases above detect macros:

https://github.com/rust-lang/rust/blob/master/src/librustc/lint/mod.rs#L898
https://github.com/rust-lang/rust/blob/master/src/libsyntax_pos/lib.rs#L133

@estebank
Copy link
Contributor

estebank commented Nov 4, 2019

but I'll be looking at these two places for hints, since this is how the two cases above detect macros:

I believe the later libsyntax_pos::is_macros would work for you.

If item.span is part of a macro invocation, this has several downstream
implications.  To name two that were found while working on this:

 - The dead-code error gets annotated with a "in this macro invocation"
 - Some errors get canceled if they refer to remote crates

Ideally, we should annotate item.ident.span with the same macro info,
but this is a larger change (see: rust-lang#66095), so for now we just fall
back to the old behavior if this item was generated by a macro.

I use span.macro_backtrace().len() to detect if it's part of a macro,
because that (among other things) is what is used by the code which
adds the "in this macro invocation" annotations mentioned above.
@Quantumplation
Copy link
Contributor Author

Sorry, had a bit of a mixup with my commits, forgot to configure user.name and user.email on a new setup so I had to force push :)

@estebank
Copy link
Contributor

estebank commented Nov 5, 2019

The hacky solution is ok by me.

macro_backtrace() allocates a vector, whereas source_callee() doesn't
but indicates the same thing.  Suggested by @estebank
@estebank
Copy link
Contributor

estebank commented Nov 6, 2019

@bors r=davidtwco,estebank

@bors
Copy link
Contributor

bors commented Nov 6, 2019

📌 Commit 6186ede has been approved by davidtwco,estebank

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Nov 6, 2019
@bors
Copy link
Contributor

bors commented Nov 6, 2019

⌛ Testing commit 6186ede with merge 61a551b...

bors added a commit that referenced this pull request Nov 6, 2019
Use ident.span instead of def_span in dead-code pass

Hello! First time contributor! :)

This should fix #58729.

According to @estebank in the duplicate #63064, def_span scans forward on the line until it finds a {,
and if it can't find one, falls back to the span for the whole item. This
was apparently written before the identifier span was explicitly tracked on
each node.

This means that if an unused function signature spans multiple lines, the
entire function (potentially hundreds of lines) gets flagged as dead code.
This could, for example, cause IDEs to add error squiggly's to the whole
function.

By using the span from the ident instead, we narrow the scope of this in
most cases. In a wider sense, it's probably safe to use ident.span
instead of def_span in most locations throughout the whole code base,
but since this is my first contribution, I kept it small.

Some interesting points that came up while I was working on this:
- I reorganized the tests a bit to bring some of the dead code ones all
into the same location
- A few tests were for things unrelated to dead code (like the
path-lookahead for parens), so I added #![allow(dead_code)] and
cleaned up the stderr file to reduce noise in the future
- The same fix doesn't apply to const and static declarations. I tried
adding these cases to the match expression, but that created a much
wider change to tests and error messages, so I left it off until I
could get some code review to validate the approach.
@bors
Copy link
Contributor

bors commented Nov 6, 2019

☀️ Test successful - checks-azure
Approved by: davidtwco,estebank
Pushing 61a551b to master...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merged-by-bors This PR was explicitly merged by bors. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Unused function warnings should return a span of only the function name
7 participants