diagnostics: shorten paths of unique symbols
This is a step towards implementing a fix for #50310, and continuation of the discussion in [Pre-RFC: Nicer Types In Diagnostics - compiler - Rust Internals](https://internals.rust-lang.org/t/pre-rfc-nicer-types-in-diagnostics/11139). Impressed upon me from previous discussion in #21934 that an RFC for this is not needed, and I should just come up with code.
The recent improvements to `use` suggestions that I've contributed have given rise to this implementation. Contrary to previous suggestions, it's rather simple logic, and I believe it only reduces the amount of cognitive load that a developer would need when reading type errors.
-----
If a symbol name can only be imported from one place, and as long as it was not glob-imported anywhere in the current crate, we can trim its printed path to the last component.
This has wide implications on error messages with types, for example, shortening `std::vec::Vec` to just `Vec`, as long as there is no other `Vec` importable from anywhere.
If a symbol name can only be imported from one place for a type, and
as long as it was not glob-imported anywhere in the current crate, we
can trim its printed path and print only the name.
This has wide implications on error messages with types, for example,
shortening `std::vec::Vec` to just `Vec`, as long as there is no other
`Vec` importable anywhere.
This adds a new '-Z trim-diagnostic-paths=false' option to control this
feature.
On the good path, with no diagnosis printed, we should try to avoid
issuing this query, so we need to prevent trimmed_def_paths query on
several cases.
This change also relies on a previous commit that differentiates
between `Debug` and `Display` on various rustc types, where the latter
is trimmed and presented to the user and the former is not.
Previous implementation used the `Parser::parse_expr` function in order
to extract the format expression. If the first comma following the
format expression was mistakenly replaced with a dot, then the next
format expression was eaten by the function, because it looked as a
syntactically valid expression, which resulted in incorrectly spanned
error messages.
The way the format expression is exctracted is changed: we first look at
the first available token in the first argument supplied to the
`format!` macro call. If it is a string literal, then it is promoted as
a format expression immediatly, otherwise we fall back to the original
`parse_expr`-related method.
This allows us to ensure that the parser won't consume too much tokens
when a typo is made.
A test has been created so that it is ensured that the issue is properly
fixed.
This prevents accidental dereferences and so forth of the Void type, as well as
cleaning up the error message to reference Opaque rather than the more
complicated PhantomData type.
Previously:
error: invalid format string: invalid argument name `_x`
--> src/main.rs:2:16
|
2 | println!("{_x}", a=0);
| ^^ invalid argument name in format string
|
= note: argument names cannot start with an underscore
Not supporting identifiers starting with underscore appears to have been
an arbitrary limitation from 2013 in code that was most likely never
reviewed:
https://github.com/rust-lang/rust/pull/8245/files#diff-0347868ef389c805e97636623e4a4ea6R277
The error message was dutifully improved in #50610 but is there any
reason that leading underscore would be a special case?
This commit updates the format_args parser to accept identifiers with
leading underscores.
Add secondary span labels with no text to make it clear when there's a
mismatch bewteen the positional arguments in a format string and the
arguments to the macro. This shouldn't affect experienced users, but it
should make it easier for newcomers to more clearly understand how
`format!()` and `println!()` are supposed to be used.
```
error: 2 positional arguments in format string, but there is 1 argument
--> file8.rs:2:14
|
2 | format!("{} {}", 1);
| ^^ ^^ -
```
instead of
```
error: 2 positional arguments in format string, but there is 1 argument
--> file8.rs:2:14
|
2 | format!("{} {}", 1);
| ^^ ^^
```
Currently, we deal with escape sequences twice: once when we lex a
string, and a second time when we unescape literals. This PR aims to
remove this duplication, by introducing a new `unescape` mode as a
single source of truth for character escaping rules
When a format string has escaped whitespace characters format
arguments were shifted by one per each escaped character. Account
for these escaped characters when synthesizing the spans.
Fix#55155.
- Point at opening mismatched formatting brace
- Account for differences between raw and regular strings
- Account for differences between the code snippet and `InternedString`
- Add more tests
When encountering format string errors in a raw string, or regular
string literal with embedded newlines, account for the positional
change to use correct spans.
:drive by fix: 🚗
Prevent fmt::Arguments from being shared across threads
Fixes#45197
This is a **breaking change**! Without doing this it's very easy to create race conditions.
There's probably a way to do this without breaking valid use cases, but it would require quite an overhaul of the formatting machinery.
On cases of malformed format strings where a `{` hasn't been properly
escaped, like `println!("{");`, present a note explaining how to escape
the `{` char.