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

Suggest removing &s #48834

Merged
merged 12 commits into from
Mar 20, 2018
Merged

Suggest removing &s #48834

merged 12 commits into from
Mar 20, 2018

Conversation

ysiraichi
Copy link
Contributor

This implements the error message discussed in #47744.
We check whether removing each & yields a type that satisfies the requested obligation.
Also, it was created a new NodeId field in ObligationCause in order to iterate through the &s. The way it's implemented now, it iterates through the obligation snippet and counts the number of &.

r? @estebank

@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 @estebank (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 Mar 8, 2018
@estebank
Copy link
Contributor

estebank commented Mar 8, 2018

(I know this is WIP, I'll look at it later. Please add a couple of tests.)

[00:05:37] tidy error: /checkout/src/librustc_lint/builtin.rs:1026: line longer than 100 chars
[00:05:37] tidy error: /checkout/src/librustc_mir/borrow_check/nll/region_infer/mod.rs:1214: line longer than 100 chars
[00:05:38] tidy error: /checkout/src/librustc/traits/select.rs:3322: line longer than 100 chars
[00:05:38] tidy error: /checkout/src/librustc/infer/anon_types/mod.rs:632: line longer than 100 chars
[00:05:38] tidy error: /checkout/src/librustc_typeck/check/mod.rs:4646: line longer than 100 chars
[00:05:38] tidy error: /checkout/src/librustc_typeck/check/mod.rs:4861: line longer than 100 chars
[00:05:38] tidy error: /checkout/src/librustc_typeck/check/compare_method.rs:220: line longer than 100 chars
[00:05:38] tidy error: /checkout/src/librustc_typeck/check/method/confirm.rs:408: line longer than 100 chars
[00:05:38] tidy error: /checkout/src/librustc_typeck/lib.rs:231: line longer than 100 chars
[00:05:38] tidy error: /checkout/src/librustc_typeck/lib.rs:283: line longer than 100 chars
[00:05:39] some tidy checks failed

for c in snippet.chars() {
if c == '&' {
refs_number += 1;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

} else if !c.is_whitespace() {
    break;
}

to avoid iterating over the entire snippet (which can be arbitrarily large) and to account for code like & & & x.

Copy link
Contributor

Choose a reason for hiding this comment

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

This can be written as

let refs_number = snippet.chars().take_while(|c| c == '&' || !c.is_whitespace()).filter(|c| c == '&').count();

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Shouldn't it be:

let refs_number = snippet.chars().filter(|c| !c.is_whitespace()).take_while(|c| c == '&').count();

Copy link
Contributor

Choose a reason for hiding this comment

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

I made a mistake, you want either & or whitespace, my code gives you only &. Your code would indeed work.

}
} else {
break;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

wrong indentation

@@ -826,17 +829,23 @@ impl<'tcx,O> Obligation<'tcx,O> {
impl<'tcx> ObligationCause<'tcx> {
pub fn new(span: Span,
body_id: ast::NodeId,
node_id: ast::NodeId,
Copy link
Contributor

Choose a reason for hiding this comment

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

I haven't found any call to new that didn't use the same thing for body_id and node_id. Did I miss something?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For now, I changed the code so that I could later fill node_id with the appropriate node (so that I wouldn't have to iterate the snippet).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

By the way, are we going to leave these changes (adding node_id to ObligationCause) even if we are not really using it (yet)?

Copy link
Contributor

Choose a reason for hiding this comment

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

Given it'd be dead code, lets remove it and land this PR. We can make that change again once the node_id is actually used.


if selcx.evaluate_obligation(&new_obligation) {
let suggest_snippet = snippet.chars()
.skip(refs_number)
Copy link
Contributor

Choose a reason for hiding this comment

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

This doesn't account for possible whitespace between the &: & & & x, for example.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh. You are right! I will fix it.

.collect::<String>();

err.span_suggestion(span,
"consider removing `&`s like",
Copy link
Contributor

Choose a reason for hiding this comment

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

This is a bit more vague than I'd like, can we teak the sentence depending on the amount of &s that should be removed?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

How does "consider removing N references &", where N is the number of references to be removed?

Copy link
Contributor

@estebank estebank left a comment

Choose a reason for hiding this comment

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

Added some comments to handle some corner cases. Like it a lot and can't wait to see it merged!

let suggest_snippet = snippet.chars()
.filter(|c| !c.is_whitespace())
.skip(remove_refs)
.collect::<String>();
Copy link
Contributor

Choose a reason for hiding this comment

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

Wouldn't this turn something like & ( a, b ) into (a,b) or & & & & v .iter() .enumerate() into v.iter().enumerate()?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes... It would. That was what I was going for, though. Is it bad?

Copy link
Contributor

Choose a reason for hiding this comment

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

So, for things like tuples, arrays and slices, we would like to keep the current formatting. For things like very long chains of method calls split each on its own line (because having them all in the same line would be over 100 chars wide) we would also like to keep the formatting.

I think you should instead advance the iterator while the char is whitespace or &, and return the everything after that. That way you trim the beginning the way you want, but keep the rest of the code with the current formatting.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed.

fn main() {
let v = vec![0, 1, 2, 3];

for (i, n) in & & & & &v.iter().enumerate() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you also add another test where the above uses multiple lines?

for (i, n) in & & & &v
    .iter()
    .enumerate()
{
    println!("{} {}", i, n);
}

@bors
Copy link
Contributor

bors commented Mar 13, 2018

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

|
LL | for (i, n) in v
LL | .iter()
LL | .enumerate() {
Copy link
Contributor

Choose a reason for hiding this comment

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

😍

| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| `&&&&&std::iter::Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator; maybe try calling `.iter()` or a similar method
| help: consider removing 5 references `&`: `v.iter().enumerate()`
Copy link
Contributor

Choose a reason for hiding this comment

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

After travis passes, I'm happy to merge, but I think we could tweak this wording slightly to make it clearer.

@nikomatsakis, @Mark-Simulacrum are you ok with this wording, or would you prefer something like

consider removing 5 `&`-references

or

consider removing the 5 leading `&`

Copy link
Member

Choose a reason for hiding this comment

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

I think we definitely want the "references" in there, and I think we should remove v.iter().enumerate() from the help since it somewhat looks odd (since it's not what we're removing). Otherwise though I think this is good as-is.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What about using node_id from ObligationCause? I am still searching only for occurrences of & in the snippet.
In case we don't need to use node_id, I should remove it from the codebase. Don't you think?

Copy link
Contributor

Choose a reason for hiding this comment

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

@Mark-Simulacrum we could replace the span_suggestion with span_suggestion_short so that the code is not being shown in the label when displayed inline, the suggestion is displayed in full when it is shown on its own (like the multiline case above) and the tooling will be able to apply the correct output as it would now.

@ysiraichi would you mind doing that change? Once that is done, r=me.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure... Which one?

Copy link
Contributor

@estebank estebank Mar 14, 2018

Choose a reason for hiding this comment

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

span_suggestion -> span_suggestion_short and

consider removing the 5 leading `&`-references

This line would end up looking like this:

LL |     for (i, n) in & & & & &v.iter().enumerate() {
   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |                   |
   |                   `&&&&&std::iter::Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator; maybe try calling `.iter()` or a similar method
   |                   help: consider removing the 5 leading `&`-references

If you had the extra time and felt it was worth it, it'd be great to change the suggestion's span to be

LL |     for (i, n) in & & & & &v.iter().enumerate() {
   |                   ---------^^^^^^^^^^^^^^^^^^^^^
   |                   |
   |                   `&&&&&std::iter::Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator; maybe try calling `.iter()` or a similar method
   |                   help: consider removing the 5 leading `&`-references

so that the suggestion will have a different color. That being said, I won't block this PR on that. If do change the span, the the replacement content would be an empty String.

@estebank estebank changed the title WIP: suggest removing &s Suggest removing &s Mar 14, 2018
@bors
Copy link
Contributor

bors commented Mar 15, 2018

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

@estebank estebank added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Mar 16, 2018
sp
}
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not sure if I should have done this here or inlined it in the function suggest_remove_refs. It seemed right to do it here... I am considering two options now:

  • inline this function into the only place it's being used; or
  • use this function in functions like span_until_whitespace which may use it.

@estebank what do you think?

Copy link
Contributor

Choose a reason for hiding this comment

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

It's good to separate it, it makes the code above easier to follow.

The latter option sounds good to me if you don't mind doing it :)

sp
}
}

Copy link
Contributor

Choose a reason for hiding this comment

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

It's good to separate it, it makes the code above easier to follow.

The latter option sounds good to me if you don't mind doing it :)

| ---------^^^^^^^^^^^^^^^^^^^^
| |
| `&&&&&std::iter::Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator; maybe try calling `.iter()` or a similar method
| help: consider removing 5 leading `&`-references
Copy link
Contributor

Choose a reason for hiding this comment

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

The output is great!

Copy link
Contributor

Choose a reason for hiding this comment

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

yeah, this is good

- `suggest_snippet` handling space between refs;
- Suggest message changing according to the number of refs that should
be removed.
Suggesting snippet without changing the original formatting of the code.
- `span_suggestion` changed to `span_suggestion_short`;
- `Span` used changed to contain only `&` refs;
- Tests passing.
- Using `span_take_while` to implement others.
@estebank
Copy link
Contributor

@bors r+ rollup

@bors
Copy link
Contributor

bors commented Mar 19, 2018

📌 Commit 736ba43 has been approved by 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-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Mar 19, 2018
kennytm added a commit to kennytm/rust that referenced this pull request Mar 19, 2018
…ebank

Suggest removing `&`s

This implements the error message discussed in rust-lang#47744.
We check whether removing each `&` yields a type that satisfies the requested obligation.
Also, it was created a new `NodeId` field in `ObligationCause` in order to iterate through the `&`s. The way it's implemented now, it iterates through the obligation snippet and counts the number of `&`.

r? @estebank
bors added a commit that referenced this pull request Mar 20, 2018
Rollup of 17 pull requests

- Successful merges: #46518, #48810, #48834, #48902, #49004, #49092, #49096, #49099, #49104, #49125, #49139, #49152, #49157, #49161, #49166, #49176, #49184
- Failed merges:
@bors bors merged commit 736ba43 into rust-lang:master Mar 20, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
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.

6 participants