rustdoc: Add a new lint for broken inline code
This patch adds `rustdoc::unescaped_backticks`, a new rustdoc lint that will detect broken inline code nodes.
The lint woks by finding stray backticks and with some heuristics tries to guess where the second backtick might be missing.
Here is how it looks:
```rust
#![warn(rustdoc::unescaped_backticks)]
/// `add(a, b) is the same as `add(b, a)`.
pub fn add(a: i32, b: i32) -> i32 { a + b }
```
```text
warning: unescaped backtick
--> src/lib.rs:3:41
|
3 | /// `add(a, b) is the same as `add(b, a)`.
| ^
|
help: a previous inline code might be longer than expected
|
3 | /// `add(a, b)` is the same as `add(b, a)`.
| +
help: if you meant to use a literal backtick, escape it
|
3 | /// `add(a, b) is the same as `add(b, a)\`.
| +
```
If we can't get proper spans, for example if the doc comment comes from a macro expansion, we print the suggestion in help messages instead. Here's a [real-world example](https://docs.rs/tracing-subscriber/0.3.17/tracing_subscriber/layer/trait.Filter.html#method.max_level_hint):
```text
warning: unescaped backtick
--> /tracing-subscriber-0.3.17/src/layer/mod.rs:1400:9
|
1400 | / /// Returns an optional hint of the highest [verbosity level][level] that
1401 | | /// this `Filter` will enable.
1402 | | ///
1403 | | /// If this method returns a [`LevelFilter`], it will be used as a hint to
... |
1427 | | /// [`Interest`]: tracing_core::subscriber::Interest
1428 | | /// [rebuild]: tracing_core::callsite::rebuild_interest_cache
| |_____________________________________________________________________^
|
= help: a previous inline code might be longer than expected
change: Therefore, if the `Filter will change the value returned by this
to this: Therefore, if the `Filter` will change the value returned by this
= help: if you meant to use a literal backtick, escape it
change: [`rebuild_interest_cache`][rebuild] is called after the value of the max
to this: [`rebuild_interest_cache\`][rebuild] is called after the value of the max
```
You can find more examples [here](https://gist.github.com/lukas-code/7678ddf5c608aee97b3a669de80d3465).
A limitation of the current implementation is, that it cannot suggest removing misplaced backticks, for example [here](https://docs.rs/tikv-jemalloc-sys/0.5.3+5.3.0-patched/tikv_jemalloc_sys/fn.mallctl.html).
The lint is allowed by default ~~and nightly-only~~ for now, ~~but without a feature gate. This is similar to how `rustdoc::invalid_html_tags` and `rustdoc::bare_urls` were handled.~~
Improve niche placement by trying two strategies and picking the better result
Fixes#104807Fixes#105371
Determining which sort order is better requires calculating the struct size (so we can calculate the niche offset). But that in turn depends on the field order, so happens after sorting. So the simple way to solve that is to run the whole thing twice and pick the better result.
1st commit is just code motion, the meat is in the later ones.
Don't duplicate anonymous lifetimes for async fn in traits
`record_lifetime_params_for_async` needs to be called outside of the scope of the function, or else it'll end up collecting anonymous lifetimes twice (those on the function and those within the `AnonymousCreateParameter` rib). This matches how `record_lifetime_params_for_async` is being used for functions with bodies below.
This fixes (partially) #110963 when the lifetimes are late-bound, but does not do so when the lifetimes are early-bound (as seen from the known-bug that I added).
Clear response values for overflow in new solver
When we have an overflow, return a trivial query response. This fixes an ICE with the code described in #110544:
```rust
trait Trait {}
struct W<T>(T);
impl<T, U> Trait for W<(W<T>, W<U>)>
where
W<T>: Trait,
W<U>: Trait,
{}
fn impls<T: Trait>() {}
fn main() {
impls::<W<_>>()
}
```
Where, while proving `W<?0>: Trait`, we overflow but still apply the query response of `?0 = (W<?1>, W<?2>)`. Then while re-processing the query to validate that our evaluation result was stable, we get a different query response that looks like `?1 = (W<?3>, W<?4>), ?2 = (W<?5>, W<?6>)`, and so we trigger the ICE.
Also, by returning a trivial query response we also avoid the infinite-loop/OOM behavior of the old solver.
r? ``@lcnr``
Rollup of 8 pull requests
Successful merges:
- #110877 (Provide better type hints when a type doesn't support a binary operator)
- #110917 (only error combining +whole-archive and +bundle for rlibs)
- #110921 (Use `NonNull::new_unchecked` and `NonNull::len` in `rustc_arena`.)
- #110927 (Encoder/decoder cleanups)
- #110944 (share BinOp::Offset between CTFE and Miri)
- #110948 (run-make test: using single quotes to not trigger the shell)
- #110957 (Fix an ICE in conflict error diagnostics)
- #110960 (fix false negative for `unused_mut`)
Failed merges:
r? `@ghost`
`@rustbot` modify labels: rollup
For start-biased layout we want to avoid overpromoting so that
the niche doesn't get pushed back.
For end-biased layout we want to avoid promoting fields that
may contain one of the niches of interest.
fix false negative for `unused_mut`
fixes https://github.com/rust-lang/rust/issues/110849
We want to avoid double diagnostics for code like this, but only if an error actually occurs:
```rust
fn main() {
let mut x: (i32, i32);
x.0 = 1;
}
```
The first commit fixes the lint and the second one removes all the unused `mut`s it found.
run-make test: using single quotes to not trigger the shell
This test got added in #110801.
I'm no expert on Makefiles, but IIUC this command is passed to the shell, which usually tries to execute commands specified in between backticks in double-quoted strings.
Using single quotes should fix this, I think. (Note: Waiting for CI to test this, since I only have a web browser available right now).
r? ``@jyn514``
cc ``@WaffleLapkin``
Since this is breaking our build bot, even if it is not directly LLVM related: ``@rustbot`` label: +llvm-main
Provide better type hints when a type doesn't support a binary operator
For example, when checking whether `vec![A] == vec![A]` holds, we first evaluate the LHS's ty, then probe for any `PartialEq` implementations for that. If none is found, we report an error by evaluating `Vec<A>: PartialEq<?0>` for fulfillment errors, but the RHS is not yet evaluated and remains an inference variable `?0`!
To fix this, we evaluate the RHS and equate it to that RHS infer var `?0`, so that we are able to provide more detailed fulfillment errors for why `Vec<A>: PartialEq<Vec<A>>` doesn't hold (namely, the nested obligation `A: PartialEq<A>` doesn't hold).
Fixes#95285Fixes#110867
Use MIR's `Offset` for pointer `add` too
~~Status: draft while waiting for #110822 to land, since this is built atop that.~~
~~r? `@ghost~~`
Canonical Rust code has mostly moved to `add`/`sub` on pointers, which take `usize`, instead of `offset` which takes `isize`. (And, relatedly, when `sub_ptr` was added it turned out it replaced every single in-tree use of `offset_from`, because `usize` is just so much more useful than `isize` in Rust.)
Unfortunately, `intrinsics::offset` could only accept `*const` and `isize`, so there's a *huge* amount of type conversions back and forth being done. They're identity conversions in the backend, but still end up producing quite a lot of unhelpful MIR.
This PR changes `intrinsics::offset` to accept `*const` *and* `*mut` along with `isize` *and* `usize`. Conveniently, the backends and CTFE already handle this, since MIR's `BinOp::Offset` [already supports all four combinations](adaac6b166/compiler/rustc_const_eval/src/transform/validate.rs (L523-L528)).
To demonstrate the difference, I added some `mir-opt/pre-codegen/` tests around slice indexing. Here's the difference to `[T]::get_mut`, since it uses `<*mut _>::add` internally:
```diff
`@@` -79,30 +70,21 `@@` fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> {
StorageLive(_12); // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
StorageLive(_9); // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
_9 = _8 as *mut u32 (PtrToPtr); // scope 11 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
- StorageLive(_13); // scope 13 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
- _13 = _2 as isize (IntToInt); // scope 13 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
- StorageLive(_14); // scope 15 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
- StorageLive(_15); // scope 15 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
- _15 = _9 as *const u32 (Pointer(MutToConstPointer)); // scope 15 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
- _14 = Offset(move _15, _13); // scope 15 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
- StorageDead(_15); // scope 15 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
- _7 = move _14 as *mut u32 (PtrToPtr); // scope 15 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
- StorageDead(_14); // scope 15 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
- StorageDead(_13); // scope 13 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+ _7 = Offset(_9, _2); // scope 13 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
StorageDead(_9); // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
StorageDead(_12); // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
StorageDead(_11); // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
```
1c1c8e442a (diff-a841b6a4538657add3f39bc895744331453d0625e7aace128b1f604f0b63c8fdR80)
Add some missing built-in lints
(and also sort them, so this is best reviewed one commit at a time)
Fixes#110911
I wonder if there's a good way to detect when a lint is built-in (i.e. not associated to a lint pass). If so, it needs to be added to this list, or else we're unable to `allow` or `deny` it. Leaving that for future work, I guess...
Migrate trivially translatable `rustc_parse` diagnostics
cc #100717
Migrate diagnostics in `rustc_parse` which are emitted in a single statement. I worked on this by expanding the lint introduced in #108760, although that isn't included here as there is much more work to be done to satisfy it
More core::fmt::rt cleanup.
- Removes the `V1` suffix from the `Argument` and `Flag` types.
- Moves more of the format_args lang items into the `core::fmt::rt` module. (The only remaining lang item in `core::fmt` is `Arguments` itself, which is a public type.)
Part of https://github.com/rust-lang/rust/issues/99012
Follow-up to https://github.com/rust-lang/rust/pull/110616
Make `method-not-found-generic-arg-elision.rs` error message not path dependent
Every time I bless `tests/ui/methods/method-not-found-generic-arg-elision.rs`, I get some nonsense "type is too long" + "written to disk" that shows up and have to manually revert because the combination of my rustc repo path + the UI test directory hits the length limit for printing types spilling to disk (since this happens before UI test path sanitization).
The fact that we use a closure in this test doesn't have to do with the UI test, so just box the closure to make the type name smaller and not path dependent.
`IntoFuture::into_future` is no longer unstable
We don't need to gate the `IntoFuture::into_future` call in `.await` lowering anymore.
``@bors`` rollup