A couple simple borrowck cleanups
This PR has a couple simple renamings:
- it's been a long time since the mapping from `Location`s to `PointIndex`es was extracted from `RegionElements` into the `DenseLocationMap`, but only the types were renamed at the time. borrowck still refers to this map as `elements`. That's confusing, especially since sometimes we also use the mapping via `LivenessValues`, and makes more sense as `location_map` instead.
- to clarify `LocationTable` is not as general as it sounds, and is only for datalog polonius. In this branch I didn't rename the handful of `location_table` fields and params to `polonius_table`, but can do that to differentiate it even more from `location_map`. I did try it locally and it looks worthwhile, so if you'd prefer I can also push it here. (Or we could even switch these datalog types and fields to even more explicit names)
- to clarify the incomprehensible `AllFacts`, it is renamed to `PoloniusFacts`. These can be referred to as `facts` within the legacy polonius module, but as `polonius_facts` outside of it to make it clear that they're not about NLLs (nor are they about in-tree polonius but that'll be magically fixed when they're removed in the future)
r? `@matthewjasper`
Exhaustively handle expressions in patterns
We currently have this invariant in HIR that a `PatKind::Lit` or a `PatKind::Range` only contains
* `ExprKind::Lit`
* `ExprKind::UnOp(Neg, ExprKind::Lit)`
* `ExprKind::Path`
* `ExprKind::ConstBlock`
So I made `PatKind::Lit` and `PatKind::Range` stop containing `Expr`, and instead created a `PatLit` type whose `kind` enum only contains those variants.
The only place code got more complicated was in clippy, as it couldn't share as much anymore with `Expr` handling
It may be interesting on merging `ExprKind::{Path,Lit,ConstBlock}` in the future and using the same `PatLit` type (under a new name).
Then it should also be easier to eliminate any and all `UnOp(Neg, Lit) | Lit` matching that we have across the compiler. Some day we should fold the negation into the literal itself and just store it on the numeric literals
Run borrowck tests on BIDs and emit tail-expr-drop-order lints for violations
Fix#132861
r? `@nikomatsakis`
cc `@compiler-errors`
This patch enlarges the scope where the `tail-expr-drop-order` lint applies, so that all locals involved in tail expressions are inspected. This is necessary to run borrow-checking to capture the cases where it used to compile under Edition 2021 but is not going to pass borrow-checking from Edition 2024 onwards.
The way it works is to inspect each BID against the set of borrows that are still live. If the local involved in BID has a borrow index which happens to be live as well at the location of this BID statement, in the future this will be a borrow-checking violation. The lint will fire in this case.
Fixes#13913 .
changelog: [`manual_is_ascii_check`]: fix type suggestions for
references
Previously it only derived `char` and `u8` types, now it should always
annotate the lambda parameter with the correct type (e.g. `&char`).
I'm quite new to Rust and this is my first contact with clippy, so I'm
open for suggetions :)
Its original naming hides the fact that it's related to datalog
polonius, and bound to be deleted in the near future.
It also conflicts with the expected name for the actual NLL location
map, and prefixing it with its use will make the differentiation
possible.
`best_blame_constraint`: Blame better constraints when the region graph has cycles from invariance or `'static`
This fixes#132749 by changing which constraint is blamed for region errors in several cases. `best_blame_constraint` had a heuristic that tried to pinpoint the constraint causing an error by filtering out any constraints where the outliving region is unified with the ultimate target region being outlived. However, it used the SCCs of the region graph to do this, which is unreliable; in particular, if the target region is `'static`, or if there are cycles from the presence of invariant types, it was skipping over the constraints it should be blaming. As is the case in that issue, this could lead to confusing diagnostics. The simplest fix seems to work decently, judging by test stderr: this makes `best_blame_constraint` no longer filter constraints by their outliving region's SCC.
There are admittedly some quirks in the test output. In many cases, subdiagnostics that depend on the particular constraint being blamed have either started or stopped being emitted. After starting at this for quite a while, I think anything too fickle about whether it outputs based on the particular constraint being blamed should instead be looking at the constraint path as a whole, similar to what's done for [the placeholder-from-predicate note](https://github.com/rust-lang/rust/compare/master...dianne:rust:better-blame-constraints-for-static#diff-3c0de6462469af483c9ecdf2c4b00cb26192218ef2d5c62a0fde75107a74caaeR506).
Very many tests involving invariant types gained a note pointing out the types' invariance, but in a few cases it was lost. A particularly illustrative example is [tests/ui/lifetimes/copy_modulo_regions.stderr](https://github.com/rust-lang/rust/compare/master...dianne:rust:better-blame-constraints-for-static?expand=1#diff-96e1f8b29789b3c4ce2f77a5e0fba248829b97ef9d1ce39e7d2b4aa57b2cf4f0); I'd argue the new constraint is a better one to blame, but it lacks the variance diagnostic information that's elsewhere in the constraint path. If desired, I can try making that note check the whole path rather than just the blamed constraint.
The subdiagnostic [`BorrowExplanation::add_object_lifetime_default_note`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/diagnostics/explain_borrow/enum.BorrowExplanation.html#method.add_object_lifetime_default_note) depends on a `Cast` being blamed, so [a special case](https://github.com/rust-lang/rust/pull/133858/commits/364ca7f99c12fb5220e6b568ac391979317ce878) was necessary to keep it from disappearing from tests specifically testing for it. However, see the FIXME comment in that commit; I think the special case should be removed once that subdiagnostic works properly, but it's nontrivial enough to warrant a separate PR. Incidentally, this removes the note from a test where it was being added erroneously: in [tests/ui/borrowck/two-phase-surprise-no-conflict.stderr](https://github.com/rust-lang/rust/compare/master...dianne:rust:better-blame-constraints-for-static?expand=1#diff-8cf085af8203677de6575a45458c9e6b03412a927df879412adec7e4f7ff5e14), the object lifetime is explicitly provided and it's not `'static`.
"Elements" are `RegionElement`s. The dense location mapping was removed
from the element containers a while ago but didn't rename its use-sites.
Most of the old naming only used the mapping, and are better named
`location_map`.
arm: add unstable soft-float target feature
This has an actual usecase as mentioned [here](https://github.com/rust-lang/rust/issues/116344#issuecomment-2575324988), and with my recent ARM float ABI changes there shouldn't be any soundness concerns any more. We will reject enabling this feature on `hf` targets, but disabling it on non-`hf` targets is entirely fine -- the target feature refers to whether softfloat emulation is used for float instructions, and is independent of the ABI which we set separately via `llvm_floatabi`.
Cc ``@workingjubilee``
Convert typeck constraints in location-sensitive polonius
In this PR, we do a big chunk of the work of localizing regular outlives constraints.
The slightly annoying thing is handling effectful statements: usually the subset graph propagates loans at a single point between regions, and liveness propagates loans between points within a single region, but some statements have effects applied on exit.
This was also a problem before, in datalog polonius terms and Niko's solution at the time, this is about: the mid-point. The idea was to duplicate all MIR locations into two physical points, and orchestrate the effects with that. Somewhat easier to do, but double the CFG.
We've always believed we didn't _need_ midpoints in principle, as we can represent changes on exit as on happening entry to the successor, but there's some difficulty in tracking the position information at sufficient granularity through outlives relation (especially since we also have bidirectional edges and time-traveling now).
Now, that is surely what we should be doing in the future. In the mean time, I infer this from the kind of statement/terminator where an outlives constraint arose. It's not particularly complicated but some explanation will help clarify the code.
Assignments (in their various forms) are the quintessential example of these crossover cases: loans that would flow into the LHS would not be visible on entry to the point but on exit -- so we'll localize these edges to the successor. Let's look at a real-world example, involving invariance for bidirectional edges:
```rust
let mut _1: HashMap<i32, &'7 i32>;
let mut _3: &'9 mut HashMap<i32, &'10 i32>;
...
/* at bb1[3]: */ _3 = &'3 mut _1;
```
Here, typeck expectedly produces 3 outlives constraints today:
1. `'3 -> '9`
2. `'7 -> '10`
3. `'10 -> '7`
And we localize them like so,
1. `'3 -> '9` flows into the LHS and becomes: `3_bb1_3 -> 9_bb1_4`
2. `'7 -> '10` flows into the LHS and becomes: `7_bb1_3 -> 10_bb1_4`
3. `'10 -> '7` flows from the LHS and becomes: `10_bb1_4 -> 7_bb1_3` (time traveling 👌)
---
r? ``@jackh726``
To keep you entertained during the holidays I also threw in a couple of small changes removing cruft in the borrow checker.
We're actually getting there. The next PR will be the last one needed to get end-to-end tests working.
Condvar: implement wait_timeout for targets without threads
This always falls back to sleeping since there is no way to notify a condvar on a target without threads.
Even on a target that has no threads the following code is a legitimate use case:
```rust
use std::sync::{Condvar, Mutex};
use std::time::Duration;
fn main() {
let cv = Condvar::new();
let mutex = Mutex::new(());
let mut guard = mutex.lock().unwrap();
cv.notify_one();
let res;
(guard, res) = cv.wait_timeout(guard, Duration::from_secs(3)).unwrap();
assert!(res.timed_out());
}
```
Impl String::into_chars
Tracking issue - https://github.com/rust-lang/rust/issues/133125
r? `@programmerjake` `@kennytm` `@Amanieu`
This refers to https://github.com/rust-lang/libs-team/issues/268
Before adding tests and creating a tracking issue, I'd like to reach a consensus on the implementation direction and two questions:
1. Whether we'd add a `String::into_char_indices` method also?
2. See inline comment.
Rollup of 6 pull requests
Successful merges:
- #133810 (remove unnecessary `eval_verify_bound`)
- #134745 (Normalize each signature input/output in `typeck_with_fallback` with its own span)
- #134989 (Lower Guard Patterns to HIR.)
- #135149 (Use a post-monomorphization typing env when mangling components that come from impls)
- #135171 (rustdoc: use stable paths as preferred canonical paths)
- #135200 (rustfmt: drop nightly-gating of the `--style-edition` flag registration)
r? `@ghost`
`@rustbot` modify labels: rollup
rustfmt: drop nightly-gating of the `--style-edition` flag registration
Follow-up to [Stabilize `style_edition = "2024"` in-tree #134929](https://github.com/rust-lang/rust/pull/134929).
#134929 un-nightly-gated the *read* of `--style-edition`, but didn't also un-nightly-gate the *registration*/*declaration* of the `--style-edition` flag itself. Reading `--style-edition` on a non-nightly channel (e.g. beta) will thus panic because `--style-edition` is never declared.
This PR also un-nightly-gates the registration. Not sure how to write a regression test for this, because this *requires* the non-nightly / beta channel. Though existing tests do fail (albeit indirectly).
Checking if this fixes the panic against beta in https://github.com/rust-lang/rust/pull/135197.
r? rustfmt
rustdoc: use stable paths as preferred canonical paths
This accomplishes something like 16a4ad7d7b, but with the `rustc_allowed_through_unstable_modules` attribute instead of the path length.
Fixes#131676
Use a post-monomorphization typing env when mangling components that come from impls
When mangling associated methods of impls, we were previously using the wrong param-env. Instead of using a fully monomorphized param-env like we usually do in codegen, we were taking the post-analysis param-env, and treating it as an early binder to *re-substitute* the impl args. I've pointed out the problematic old code in an inline comment.
This would give us param-envs with possibly trivial predicates that would prevent normalization via param-env shadowing.
In the example test linked below, `tests/ui/symbol-names/normalize-in-param-env.rs`, this happens when we mangle the impl `impl<P: Point2> MyFrom<P::S> for P` with the substitution `P = Vec2`. Because the where clause of the impl is `P: Point2`, which elaborates to `[P: Point2, P: Point, <P as Point>::S projects-to <P as Point2>::S2]` and the fact that `impl Point2 for Vec2` normalizes `Vec2::S2` to `Vec2::S`, this causes a cycle.
The proper fix here is to use a fully monomorphized param-env for the case where the impl is properly substituted.
Fixes#135143
While #134081 uncovered this bug for legacy symbol mangling, it was preexisting for v0 symbol mangling. This PR fixes both. The test requires a "hack" because we strip the args of the instance we're printing for legacy symbol mangling except for drop glue, so we box a closure to ensure we generate drop glue.
r? oli-obk
Normalize each signature input/output in `typeck_with_fallback` with its own span
Applies the same hack as #106582 but to the args in typeck. Greatly improves normalization error spans from a signature.
remove unnecessary `eval_verify_bound`
This does not impact any tests. I feel like any cases where this could useful should instead be fixed by a general improvement to `eval_verify_bound` to avoid having to promote this `TypeTest` in the first place 🤔
r? types cc ``@nikomatsakis``