-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Suggest removing &
s
#48834
Conversation
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. |
(I know this is WIP, I'll look at it later. Please add a couple of tests.)
|
for c in snippet.chars() { | ||
if c == '&' { | ||
refs_number += 1; | ||
} |
There was a problem hiding this comment.
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
.
There was a problem hiding this comment.
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();
There was a problem hiding this comment.
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();
There was a problem hiding this comment.
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; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wrong indentation
src/librustc/traits/mod.rs
Outdated
@@ -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, |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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).
There was a problem hiding this comment.
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)?
There was a problem hiding this comment.
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.
188435c
to
ff9d9b3
Compare
|
||
if selcx.evaluate_obligation(&new_obligation) { | ||
let suggest_snippet = snippet.chars() | ||
.skip(refs_number) |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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", |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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?
There was a problem hiding this 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>(); |
There was a problem hiding this comment.
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()
?
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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() { |
There was a problem hiding this comment.
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);
}
☔ The latest upstream changes (presumably #48411) made this pull request unmergeable. Please resolve the merge conflicts. |
5b23275
to
5503560
Compare
| | ||
LL | for (i, n) in v | ||
LL | .iter() | ||
LL | .enumerate() { |
There was a problem hiding this comment.
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()` |
There was a problem hiding this comment.
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 `&`
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure... Which one?
There was a problem hiding this comment.
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
.
☔ The latest upstream changes (presumably #47630) made this pull request unmergeable. Please resolve the merge conflicts. |
46a06e9
to
311e9ac
Compare
src/libsyntax/codemap.rs
Outdated
sp | ||
} | ||
} | ||
|
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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 :)
src/libsyntax/codemap.rs
Outdated
sp | ||
} | ||
} | ||
|
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The output is great!
There was a problem hiding this comment.
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.
c6e5ae8
to
736ba43
Compare
@bors r+ rollup |
📌 Commit 736ba43 has been approved by |
…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
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 inObligationCause
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