Open gianzellweger opened 1 year ago
@gianzellweger when you have a moment can you please provide a minimal code snippet inline that we can run rustfmt on with your configuration to reproduce the issue. something like:
fn main() {
// code that reproduces the issue
}
Without an example code snippet there's very little we can do to help.
@ytmimi Is there a way to see which code it was trying to format? The entire project has about 2000 LOC and I do not think that satisfies the "minimal code snippet" requirement. I also tried it with another project and there it worked like intended.
@gianzellweger first, I want to say thanks for bringing this to our attention. If you can try to narrow it down that would be great. Just looking at the logs you've provided I think this might be a duplicate of #4968
@ytmimi I have now narrowed it down to a single file (which is still 1000 lines, so not a helpful progression) and I have tried deactivating every single configuration on its own. The panic only goes away if I remove error_on_unformatted
, everything else still produces the panic. Is there anything else I should try?
Normally I'd recommend running rustfmt with RUSTFMT_LOG=debug
. The extra info might help you narrow it down, but I think there might be an issue with logging with the most recent released version that won't be resolved until we sync this repo back up with the upstream rust-lang/rust repo. I was also going to say that you could have run rustfmt with -v
to figure out what file, but you already narrowed it down.
Any chance you can share a link to the file?
@ytmimi How about I instead narrow it down to the specific piece of code? There's only about 10-20 functions which I can comment out separately until the error goes away.
@ytmimi The cause either appears multiple times in this one file or the cause is something else entirely. I will link the code below. If you need anything else, feel free to comment. Thank you and good luck. main.rs
Alright, I had a look at this and I think I've got it. In your case the error is happening in the component_tab
function on the line that starts with format!("{:name_width$} {:temperature_width$.2}°C {:critical_width$}",
. The issue is that there's a trailing space at the end of the line and you're using a °C
unicode character. removing the whitespace will prevent the panic.
@ytmimi That fixed it, thank you so much. Can we agree that this isn't optimal behavior from rustfmt and could be improved? Not trying to put any pressure on anybody.
@gianzellweger this particular issue will almost certainly be resolved once we add support for let-chains
. The underlying issue here has more to do with not properly handling the size of the unicode char correctly. Similar issues have been reported before.
Here's a bit of a deep dive explanation into what's happening in this case:
fn fail() {
if let Some(x) = x && y {
format!("{:name_width$} {:temperature_width$.2}°C {:critical_width$}")
// ^
// |
// |
// trailing whitespace
}
}
and here's a screenshot that highlights the whitespace at the end:
The issue is that rustfmt doesn't currently support formatting let-chains
so when rustfmt reaches any let-chain
in the code the best it can do is copy the entire Span
of the AST node into the output buffer and move on with formatting.
At the end of the formatting process rustfmt does a pass over that output buffer to see if there are instances of trailing whitespace or lines that exceed the max_width
, and in this case the panic is happening during this reporting process. The panic in annotate-snippets
is a direct result of not handling the unicode char length properly.
@ytmimi That makes a lot of sense, as my code uses let-chains. Is there any issue that tracks the progress of this or has this implementation not started at all? Thank you once more.
The example input from https://github.com/rust-lang/rustfmt/issues/5888 is also really helpful at highlighting this issue:
pub(crate) fn sanity_needs_ocr<T: HasWord + HasRect>(collection: &[T]) -> bool {
let needs_ocr = collection.is_empty()
// the presence of 'UNICODE REPLACEMENT CHARACTER'
|| collection.iter().any(|c| c.text().contains('�'))
// (yes, empty pages will also be OCR'd)
|| collection_is_void_of_text(collection)
|| is_gibberish(&collection.to_rendered_text());
#[cfg(debug_assertions)]
if needs_ocr {
tracing::trace!(
"sanity check failed, with text: {:?}",
collection.to_rendered_text()
);
}
needs_ocr
}
and here's my explanation of the problem: https://github.com/rust-lang/rustfmt/issues/5888#issuecomment-1682925447
I found a much smaller example that triggers the same error:
#![allow(incomplete_features)]
#![feature(
try_blocks,
never_type,
min_specialization,
exclusive_range_pattern,
lazy_cell
)]
Putting that as input into rustfmt --edition 2021 --verbose --config max_width=10,use_small_heuristics=Off,error_on_line_overflow=true
will create this error:
There's no let-chains
or non-ascii characters in this snippet.
@danielhuang thanks! The tab characters are what's causing the panic. Similar issues have been reported before. An explanation of what's going on can be found at https://github.com/rust-lang/rustfmt/issues/4968#issuecomment-949461340, and there are PRs already open to resolve your case.
I recently looked through all the features of Rustfmt and picked a few options where I preferred some option over the default. When trying this new mix, however, I got an error. I have attached both the log and my configuration. rustc-ice-2023-08-02T21:08:46.715244Z-75321.txt rustfmt.toml