Fix the conflict problem between the diagnostics fixes of lint `unnecessary_qualification` and `unused_imports`
fixes#121331
For an `item` that triggers lint unnecessary_qualification, if the `use item` which imports this item is also trigger unused import, fixing the two lints at the same time may lead to the problem that the `item` cannot be found.
This PR will avoid reporting lint unnecessary_qualification when conflict occurs.
r? ``@petrochenkov``
coverage: Initial support for branch coverage instrumentation
(This is a review-ready version of the changes that were drafted in #118305.)
This PR adds support for branch coverage instrumentation, gated behind the unstable flag value `-Zcoverage-options=branch`. (Coverage instrumentation must also be enabled with `-Cinstrument-coverage`.)
During THIR-to-MIR lowering (MIR building), if branch coverage is enabled, we collect additional information about branch conditions and their corresponding then/else blocks. We inject special marker statements into those blocks, so that the `InstrumentCoverage` MIR pass can reliably identify them even after the initially-built MIR has been simplified and renumbered.
The rest of the changes are mostly just plumbing needed to gather up the information that was collected during MIR building, and include it in the coverage metadata that we embed in the final binary.
Note that `llvm-cov show` doesn't print branch coverage information in its source views by default; that needs to be explicitly enabled with `--show-branches=count` or similar.
---
The current implementation doesn't have any support for instrumenting `if let` or let-chains. I think it's still useful without that, and adding it would be non-trivial, so I'm happy to leave that for future work.
more eagerly instantiate binders
The old solver sometimes incorrectly used `sub`, change it to explicitly instantiate binders and use `eq` instead. While doing so I also moved the instantiation before the normalize calls. This caused some observable changes, will explain these inline. This PR therefore requires a crater run and an FCP.
r? types
Add a test that `f16` and `f128` are usable with the feature gate
enabled, as well as a test that user types with the same name as
primitives are not improperly gated.
Includes related tests and documentation pages.
Michael Goulet: Don't issue feature error in resolver for f16/f128
unless finalize
Co-authored-by: Michael Goulet <michael@errs.io>
Ungate the `UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES` lint
This was missed during stablisation of the `#[diagnostic]` attribute namespace.
Fixes#122446
add test ensuring simd codegen checks don't run when a static assertion failed
stdarch relies on this to ensure that SIMD indices are in bounds.
I would love to know why this works, but I can't figure out where codegen decides to not codegen a function if a required-const does not evaluate. `@oli-obk` `@bjorn3` do you have any idea?
rustdoc-search: depth limit `T<U>` -> `U` unboxing
Profiler output:
https://notriddle.com/rustdoc-html-demo-9/search-unbox-limit/ (the only significant change is that one of the `rust` tests went from 378416ms to 16ms).
This is a performance enhancement aimed at a problem I found while using type-driven search on the Rust compiler. It is caused by [`Interner`], a trait with 41 associated types, many of which recurse back to `Self` again.
This caused search.js to struggle. It eventually terminates, after about 10 minutes of turning my PC into a space header, but it's doing `41!` unifications and that's too slow.
[`Interner`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/trait.Interner.html
const-eval: organize and extend tests for required-consts
This includes some tests that are known-broken and hence disabled (due to https://github.com/rust-lang/rust/issues/107503).
r? `````@oli-obk`````
Add methods to create StableMIR constant
I've been experimenting with transforming the StableMIR to instrument the code with potential UB checks.
The modified body will only be used by our analysis tool, however, constants in StableMIR must be backed by rustc constants. Thus, I'm adding a few functions to build constants, such as building string and other primitives.
One question I have is whether we should create a global allocation instead for strings.
r? ``````@oli-obk``````
rustdoc-search: search types by higher-order functions
This feature extends rustdoc with syntax and search index information for searching function pointers and closures (Higher-Order Functions, or HOF). Part of https://github.com/rust-lang/rust/issues/60485
This PR adds two syntaxes: a high-level one for finding any kind of HOF, and a direct implementation of the parenthesized path syntax that Rust itself uses.
## Preview pages
| Query | Results |
|-------|---------|
| [`option<T>, (fnonce (T) -> bool) -> option<T>`][optionfilter] | `Option::filter` |
| [`option<T>, (T -> bool) -> option<T>`][optionfilter2] | `Option::filter` |
Updated chapter of the book: https://notriddle.com/rustdoc-html-demo-9/search-hof/rustdoc/read-documentation/search.html
[optionfilter]: https://notriddle.com/rustdoc-html-demo-9/search-hof/std/vec/struct.Vec.html?search=option<T>%2C+(fnonce+(T)+->+bool)+->+option<T>&filter-crate=std
[optionfilter2]: https://notriddle.com/rustdoc-html-demo-9/search-hof/std/vec/struct.Vec.html?search=option<T>%2C+(T+->+bool)+->+option<T>&filter-crate=std
## Motivation
When type-based search was first landed, it was directly [described as incomplete][a comment].
[a comment]: https://github.com/rust-lang/rust/pull/23289#issuecomment-79437386
Filling out the missing functionality is going to mean adding support for more of Rust's [type expression] syntax, such as references, raw pointers, function pointers, and closures. This PR adds function pointers and closures.
[type expression]: https://doc.rust-lang.org/reference/types.html#type-expressions
There's been demand for something "like Hoogle, but for Rust" expressed a few times [1](https://www.reddit.com/r/rust/comments/y8sbid/is_there_a_website_like_haskells_hoogle_for_rust/) [2](https://users.rust-lang.org/t/rust-equivalent-of-haskells-hoogle/102280) [3](https://internals.rust-lang.org/t/std-library-inclusion-policy/6852/2) [4](https://discord.com/channels/442252698964721669/448238009733742612/1109502307495858216). Some of them just don't realize what functionality already exists ([`Duration -> u64`](https://doc.rust-lang.org/nightly/std/?search=duration%20-%3E%20u64) already works), but a lot of them specifically want to search for higher-order functions like option combinators.
## Guide-level explanation (from the Rustdoc book)
To search for a function that accepts a function as a parameter, like `Iterator::all`, wrap the nested signature in parenthesis, as in [`Iterator<T>, (T -> bool) -> bool`][iterator-all]. You can also search for a specific closure trait, such as `Iterator<T>, (FnMut(T) -> bool) -> bool`, but you need to know which one you want.
[iterator-all]: https://notriddle.com/rustdoc-html-demo-9/search-hof/std/vec/struct.Vec.html?search=Iterator<T>%2C+(T+->+bool)+->+bool&filter-crate=std
## Reference-level description (also from the Rustdoc book)
### Primitives with Special Syntax
<table>
<thead>
<tr>
<th>Shorthand</th>
<th>Explicit names</th>
</tr>
</thead>
<tbody>
<tr><td colspan="2">Before this PR</td></tr>
<tr>
<td><code>[]</code></td>
<td><code>primitive:slice</code> and/or <code>primitive:array</code></td>
</tr>
<tr>
<td><code>[T]</code></td>
<td><code>primitive:slice<T></code> and/or <code>primitive:array<T></code></td>
</tr>
<tr>
<td><code>!</code></td>
<td><code>primitive:never</code></td>
</tr>
<tr>
<td><code>()</code></td>
<td><code>primitive:unit</code> and/or <code>primitive:tuple</code></td>
</tr>
<tr>
<td><code>(T)</code></td>
<td><code>T</code></td>
</tr>
<tr>
<td><code>(T,)</code></td>
<td><code>primitive:tuple<T></code></td>
</tr>
<tr><td colspan="2">After this PR</td></tr>
<tr>
<td><code>(T, U -> V, W)</code></td>
<td><code>fn(T, U) -> (V, W)</code>, Fn, FnMut, and FnOnce</td>
</tr>
</tbody>
</table>
The `->` operator has lower precedence than comma. If it's not wrapped in brackets, it delimits the return value for the function being searched for. To search for functions that take functions as parameters, use parenthesis.
### Search query grammar
```ebnf
ident = *(ALPHA / DIGIT / "_")
path = ident *(DOUBLE-COLON ident) [BANG]
slice-like = OPEN-SQUARE-BRACKET [ nonempty-arg-list ] CLOSE-SQUARE-BRACKET
tuple-like = OPEN-PAREN [ nonempty-arg-list ] CLOSE-PAREN
arg = [type-filter *WS COLON *WS] (path [generics] / slice-like / tuple-like)
type-sep = COMMA/WS *(COMMA/WS)
nonempty-arg-list = *(type-sep) arg *(type-sep arg) *(type-sep) [ return-args ]
generic-arg-list = *(type-sep) arg [ EQUAL arg ] *(type-sep arg [ EQUAL arg ]) *(type-sep)
normal-generics = OPEN-ANGLE-BRACKET [ generic-arg-list ] *(type-sep)
CLOSE-ANGLE-BRACKET
fn-like-generics = OPEN-PAREN [ nonempty-arg-list ] CLOSE-PAREN [ RETURN-ARROW arg ]
generics = normal-generics / fn-like-generics
return-args = RETURN-ARROW *(type-sep) nonempty-arg-list
exact-search = [type-filter *WS COLON] [ RETURN-ARROW ] *WS QUOTE ident QUOTE [ generics ]
type-search = [ nonempty-arg-list ]
query = *WS (exact-search / type-search) *WS
; unchanged parts of the grammar, like the full list of type filters, are omitted
```
## Future direction
### The remaining type expression grammar
As described in https://github.com/rust-lang/rust/pull/118194, this is another step in the type expression grammar: BareFunction, and the function-like mode of TypePath, are now supported.
* RawPointerType and ReferenceType actually are a priority.
* ImplTraitType and TraitObjectType (and ImplTraitTypeOneBound and TraitObjectTypeOneBound) aren't as much of a priority, since they desugar pretty easily.
### Search subtyping and traits
This is the other major factor that makes it less useful than it should be.
* `iterator<result<t>> -> result<t>` doesn't find `Result::from_iter`. You have to search [`intoiterator<result<t>> -> result<t>`](https://notriddle.com/rustdoc-html-demo-9/search-hof/std/vec/struct.Vec.html?search=intoiterator%3Cresult%3Ct%3E%3E%20-%3E%20result%3Ct%3E&filter-crate=std). Nobody's going to search for IntoIterator unless they basically already know about it and don't need the search engine anyway.
* Iterator combinators are usually structs that happen to implement Iterator, like `std::iter::Map`.
To solve these cases, it needs to look at trait implementations, knowing that Iterator is a "subtype of" IntoIterator, and Map is a "subtype of" Iterator, so `iterator -> result` is a subtype of `intoiterator -> result` and `iterator<t>, (t -> u) -> iterator<u>` is a subtype of [`iterator<t>, (t -> u) -> map<t -> u>`](https://notriddle.com/rustdoc-html-demo-9/search-hof/std/vec/struct.Vec.html?search=iterator%3Ct%3E%2C%20(t%20-%3E%20u)%20-%3E%20map%3Ct%20-%3E%20u%3E&filter-crate=std).
Downgrade const eval dangling ptr in final to future incompat lint
Short term band-aid for issue #121610, downgrading the prior hard error to a future-incompat lint (tracked in issue #122153).
Note we should not mark #121610 as resolved until after this (or something analogous) is beta backported.
When encountering a lifetime error on a type that *holds* a type that
doesn't implement `Clone`, explore the item's body for potential calls
to `.clone()` that are only cloning the reference `&T` instead of `T`
because `T: !Clone`. If we find this, suggest `T: Clone`.
```
error[E0502]: cannot borrow `*list` as mutable because it is also borrowed as immutable
--> $DIR/clone-on-ref.rs:7:5
|
LL | for v in list.iter() {
| ---- immutable borrow occurs here
LL | cloned_items.push(v.clone())
| ------- this call doesn't do anything, the result is still `&T` because `T` doesn't implement `Clone`
LL | }
LL | list.push(T::default());
| ^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
LL |
LL | drop(cloned_items);
| ------------ immutable borrow later used here
|
help: consider further restricting this bound
|
LL | fn foo<T: Default + Clone>(list: &mut Vec<T>) {
| +++++++
```
```
error[E0505]: cannot move out of `x` because it is borrowed
--> $DIR/clone-on-ref.rs:23:10
|
LL | fn qux(x: A) {
| - binding `x` declared here
LL | let a = &x;
| -- borrow of `x` occurs here
LL | let b = a.clone();
| ------- this call doesn't do anything, the result is still `&A` because `A` doesn't implement `Clone`
LL | drop(x);
| ^ move out of `x` occurs here
LL |
LL | println!("{b:?}");
| ----- borrow later used here
|
help: consider annotating `A` with `#[derive(Clone)]`
|
LL + #[derive(Clone)]
LL | struct A;
|
```
Safe Transmute: Require that source referent is smaller than destination
`BikeshedIntrinsicFrom` currently models transmute-via-union; i.e., it attempts to provide a `where` bound for this function:
```rust
pub unsafe fn transmute_via_union<Src, Dst>(src: Src) -> Dst {
use core::mem::*;
#[repr(C)]
union Transmute<T, U> {
src: ManuallyDrop<T>,
dst: ManuallyDrop<U>,
}
let transmute = Transmute { src: ManuallyDrop::new(src) };
// SAFETY: The caller must guarantee that the transmutation is safe.
let dst = transmute.dst;
ManuallyDrop::into_inner(dst)
}
```
A quirk of this model is that it admits padding extensions in value-to-value transmutation: The destination type can be bigger than the source type, so long as the excess consists of uninitialized bytes. However, this isn't permissible for reference-to-reference transmutations (introduced in #110662) — extra referent bytes cannot come from thin air.
This PR patches our analysis for reference-to-reference transmutations to require that the destination referent is no larger than the source referent.
r? `@compiler-errors`
pattern analysis: remove `MaybeInfiniteInt::JustAfterMax`
It was inherited from before half-open ranges, but it doesn't pull its weight anymore. We lose a tiny bit of diagnostic precision as can be seen in the test. I'm generally in favor of half-open ranges over explicit `x..=MAX` ranges anyway.