-
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
Tweak diagnostic for use
suggestion to blank text surrounding span.
#90941
Tweak diagnostic for use
suggestion to blank text surrounding span.
#90941
Conversation
(rust-highfive has picked a reviewer for you, use r? to override) |
I'd like to get @estebank 's take on this, if they have time. |
r? @estebank |
This comment has been minimized.
This comment has been minimized.
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've reread the PR a couple of times now, and I think I get all that it's doing, but will need to look at it again tomorrow morning.
The visual output looks obviously correct, but now I'm concern that applying the suggestion from the json output will still result in the original bug. Am I wrong to imagine that?
I'm not sure how much time it would take, but changing how we compute use_placement_span
would also be a potential fix for this, right? I'm guessing you already explored that. What did you find?
@@ -0,0 +1,63 @@ | |||
// aux-build:amputate-span.rs |
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 we make it run-rustfix
? That way we enforce that the emitted suggestion is actually valid.
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.
Adding // run-rustfix
to this test does not work out of the box. It ends up rewriting the code to the bad thing that we are trying to prevent:
#[amputate_span::drop_first_token]
/* what the
hey */ async use std::process::Command;
fn main() {
Command::new("git"); //~ ERROR [E0433]
}
and
#[amputate_span::drop_first_token]
/* what the
hey */ async use std::process::Command;
fn main() {
Command::new("git"); //~ ERROR [E0433]
}
I'm guessing that's because rustfix
does not know Transcription::Blanks
?
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 may be somewhat related to this FIXME from PR #85427 that originally stems from PR #44215. Fixing that might serve as an argument for moving away from the "infer the span from the given item's span" strategy, and using the span of the containing mod/crate instead, as discussed in my other comment
rust/src/test/ui/resolve/use_suggestion_placement.fixed
Lines 17 to 24 in 934624f
// FIXME: UsePlacementFinder is broken because active attributes are | |
// removed, and thus the `derive` attribute here is not in the AST. | |
// An inert attribute should work, though. | |
// #[derive(Debug)] | |
use std::path::Path; | |
#[allow(warnings)] | |
pub struct Foo; |
Yeah, I did explore this. I posted my findings in zulip, but here's the executive summary: Any span we choose here is going to be a heuristic (there's no way for us to infer what the end user would actually prefer, what (More long winded explanation follows.) In this case, the span of the item has yielded non-ideal results because the procedural macro has literally thrown away the token that holds the ideal starting point for the span. The only way we could try to correct for that within the compiler would be to use the span that was associated with the item prior to expansion, and I'm not sure that we can distinguish scenarios where is the right thing to do (versus ones where it would lead us astray). If you don't use the item (pre- or post-expansion) as the basis for the span, then you have to figure out what span you are going to use. I explored using the span of the mod/crate itself. The options there are either 1. the span of the mod/crate contents (which is readily available), or 2. the span of the whole module/crate (i.e. include the E.g. I tried option 1 (the span of the mod/crate contents), but that will cause you to emit suggestions like In the end, the approach I'm suggesting here just seemed best. It is relatively self-contained, and ends up having minimal perturbation to our test suite (and hopefully minimal change to end-users), because the only significant change to behavior is that with this change, the suggestion stops including things like trailing text from |
Our suggestion system is oriented around diff's to code, and in that context, if your spans are perfect, everything works out. But our spans are not always perfect, due to macros. In the specific case of issue 87613, the #[tokio::main] attribute macro works by rewriting an `async fn main` into an `fn main`, by just removing the `async` token. The problem is that the `async` text remains in the source code, and the span of the code rewritten by suggestion system happily transcribes all the text on the line of that `fn main` when generating a `use` suggestion, yielding the absurd looking `async use std::process::Command;` suggestion. This patch works around this whole problem by adding a way for suggestions to indicate that their transcriptions should not include the original source code; just its *whitespace*. This leads to a happy place where the suggested line numbers are correct and the indentation is usually also correct, while avoiding the `async use` output we would see before.
2551408
to
1055162
Compare
The job Click to see the possible cause of the failure (guessed by this bot)
|
match self.transcription { | ||
Transcription::Copy => text, | ||
Transcription::Blank => text.map(|s| { | ||
s.chars().map(|c| if c.is_whitespace() { c } else { ' ' }).collect() |
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.
If the goal is to preserve indentation, I think removing any non-whitespace characters may be better? For example, in the async fn
case, you probably want use
aligned with async
, not indented to the fn
.
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.
Well, then trailing ... */
comments (which would likewise get removed under your suggestion) end up messing up the indentation?
And I guess if the item is on the same line as its containing module, we might likewise have a problem:
mod m { fn foo() { Command::new("git"); } }
But I freely admit, both of these cases sound much more rare than #[tokio::main]
. :)
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 I'm gradually talking myself into going back and looking at deriving the span from the span of the containing mod/crate again, despite my earlier frustrations with that approach.)
Discussed this with some other members of T-compiler. Collectively agreed that this is not the right approach; the better solution here is to have the parser identify one spot (or more) where Closing this PR since I'm not planning to continue with it. |
Our suggestion system is oriented around diff's to code, and in that
context, if your spans are perfect, everything works out. But our
spans are not always perfect, due to macros.
In the specific case of issue #87613, the #[tokio::main] attribute
macro works by rewriting an
async fn main
into anfn main
, by justremoving the
async
token. The problem is that theasync
textremains in the source code, and the span of the code rewritten by
suggestion system happily transcribes all the text on the line of that
fn main
when generating ause
suggestion, yielding the absurdlooking
async use std::process::Command;
suggestion.This patch works around this whole problem by adding a way for
suggestions to indicate that their transcriptions should not include
the original source code; just its whitespace. This leads to a happy
place where the suggested line numbers are correct and the indentation
is usually also correct, while avoiding the
async use
output wewould see before.
Fix #87613