Ignore NLL boring locals in polonius diagnostics
Another easy one ``@jackh726`` (the diff is inflated by blessed test expectations don't worry :)
NLLs don't compute liveness for boring locals, and therefore cannot find them in causes explaining borrows. In polonius, we don't have this liveness optimization (we may be able to do something partially similar in the future, e.g. for function parameters and the like), so we do encounter these in diagnostics even though we don't want to. This PR:
- restructures the polonius context into per-phase data, in spirit as you requested in an earlier review
- stores the locals NLLs would consider boring into the errors/diagnostics data
- ignores these if a boring local is found when trying to explain borrows
This PR fixes around 80 cases of diagnostics differences between `-Zpolonius=next` and NLLs. I've also added explicit revisions to a few polonius tests (both for the in-tree implementation as well as the datalog implementation -- even if we'll eventually remove them). I didn't do this for all the "dead" expectations that were removed from #136112 for that same reason, it's fine. I'll soon/eventually add explicit revisions where they're needed: there's only a handful of tests left to fix.
r? ``@jackh726``
diagnostics: fix borrowck suggestions for if/while let conditionals
This code detects the case where one of the borrows is inside the let init expr while the other end is not. If that happens, we don't want to suggest adding a semicolon, because it won't work.
Fixes#133941
Make comma separated lists of anything easier to make for errors
Provide a new function `listify`, meant to be used in cases similar to `pluralize!`. When you have a slice of arbitrary elements that need to be presented to the user, `listify` allows you to turn that into a list of comma separated strings.
This reduces a lot of redundant logic that happens often in diagnostics.
Rework "long type names" printing logic
Make it so more type-system types can be printed in a shortened version (like `Predicate`s).
Centralize printing the information about the "full type name path".
Make the "long type path" for the file where long types are written part of `Diag`, so that it becomes easier to keep track of it, and ensure it will always will be printed out last in the diagnostic by making its addition to the output implicit.
Tweak the shortening of types in "expected/found" labels.
Remove dead file `note.rs`.
This code detects the case where one of the borrows is inside the
let init expr while the other end is not. If that happens, we don't
want to suggest adding a semicolon, because it won't work.
Implement MIR lowering for unsafe binders
This is the final bit of the unsafe binders puzzle. It implements MIR, CTFE, and codegen for unsafe binders, and enforces that (for now) they are `Copy`. Later on, I'll introduce a new trait that relaxes this requirement to being "is `Copy` or `ManuallyDrop<T>`" which more closely models how we treat union fields.
Namely, wrapping unsafe binders is now `Rvalue::WrapUnsafeBinder`, which acts much like an `Rvalue::Aggregate`. Unwrapping unsafe binders are implemented as a MIR projection `ProjectionElem::UnwrapUnsafeBinder`, which acts much like `ProjectionElem::Field`.
Tracking:
- https://github.com/rust-lang/rust/issues/130516
Make it so more type-system types can be printed in a shortened version (like `Predicate`s).
Centralize printing the information about the "full type name path".
Make the "long type path" for the file where long types are written part of `Diag`, so that it becomes easier to keep track of it, and ensure it will always will be printed out last in the diagnostic by making its addition to the output implicit.
Tweak the shortening of types in "expected/found" labels.
Remove dead file `note.rs`.
Provide a new function `listify`, meant to be used in cases similar to `pluralize!`. When you have a slice of arbitrary elements that need to be presented to the user, `listify` allows you to turn that into a list of comma separated strings.
This reduces a lot of redundant logic that happens often in diagnostics.
add constraint graph to polonius MIR dump
Another easy one while I work on diagnostics. This PR adds a mermaid visualization of the polonius constraint graph to the polonius MIR dump.
Adding kills is left to a future PR (until they're encoded in edges directly or I set up recording debugging info in and out of the analysis), because right now they're only computed during traversal.
[Here's](https://gistpreview.github.io/?096b0131e8258f9a3125c55c7ac369bc) how that looks.
r? `@matthewjasper` but as always feel free to reroll.
It's a function that does stuff with MIR and yet it weirdly has its own
module in `rustc_middle::util`. This commit moves it into
`rustc_middle::mir`, a more sensible home.
Simplify and consolidate the way we handle construct `OutlivesEnvironment` for lexical region resolution
This is best reviewed commit-by-commit. I tried to consolidate the API for lexical region resolution *first*, then change the API when it was finally behind a single surface.
r? lcnr or reassign
Tweak `&mut self` suggestion span
```
error[E0596]: cannot borrow `*self.s` as mutable, as it is behind a `&` reference
--> $DIR/issue-38147-1.rs:17:9
|
LL | self.s.push('x');
| ^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable
|
help: consider changing this to be a mutable reference
|
LL | fn f(&mut self) {
| +++
```
Note the suggestion to add `mut` instead of replacing the entire `&self` with `&mut self`.
Add mermaid graphs of NLL regions and SCCs to polonius MIR dump
This PR expands the polonius MIR dump again with a couple of mermaid charts ported from the graphviz version:
- the NLL region graph
- and the NLL SCCs
I still have done zero visual design on this until now, but [here's](https://gistpreview.github.io/?fbbf900fed2ad21108c7ca0353456398) how it looks (i.e. still bad) just to give an idea of the result.
r? `````@matthewjasper````` (feel free to reassign) or anyone
```
error[E0596]: cannot borrow `*self.s` as mutable, as it is behind a `&` reference
--> $DIR/issue-38147-1.rs:17:9
|
LL | self.s.push('x');
| ^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable
|
help: consider changing this to be a mutable reference
|
LL | fn f(&mut self) {
| +++
```
Note the suggestion to add `mut` instead of replacing the entire `&self` with `&mut self`.
Pass spans to `perform_locally_in_new_solver`
Nothing changes yet, but we may be able to use these spans in the future once we start dealing w the response region constraints better.
r? lcnr
Expand polonius MIR dump
This PR starts expanding the polonius MIR:
- switches to an HTML file, to show graphs in the same document as the MIR dump, share them more easily since it's a single file that can be hosted as a gist, and also to allow for interactivity in the near future.
- adds the regular NLL MIR + polonius constraints
- embeds a mermaid version of the CFG, similar to the graphviz one, but that needs a smaller js than `dot`'s emscripten js from graphvizonline
[Here's an example](https://gistpreview.github.io/?0c18f2a59b5e24ac0f96447aa34ffe00) of how it looks.
---
In future PRs: mermaid graphs of the NLL region graph, of the NLL SCCs, of the polonius localized outlives constraints, and the interactive polonius MIR dump.
r? ```@matthewjasper```
Use short ty string for move errors
```
error[E0382]: use of moved value: `x`
--> bay.rs:14:14
|
12 | fn foo(x: D) {
| - move occurs because `x` has type `(((..., ..., ..., ...), ..., ..., ...), ..., ..., ...)`, which does not implement the `Copy` trait
13 | let _a = x;
| - value moved here
14 | let _b = x; //~ ERROR use of moved value
| ^ value used here after move
|
= note: the full type name has been written to 'bay.long-type-14349227078439097973.txt'
= note: consider using `--verbose` to print the full type name to the console
help: consider cloning the value if the performance cost is acceptable
|
13 | let _a = x.clone();
| ++++++++
```
Address 4th case in #135919.
```
error[E0382]: use of moved value: `x`
--> bay.rs:14:14
|
12 | fn foo(x: D) {
| - move occurs because `x` has type `(((..., ..., ..., ...), ..., ..., ...), ..., ..., ...)`, which does not implement the `Copy` trait
13 | let _a = x;
| - value moved here
14 | let _b = x; //~ ERROR use of moved value
| ^ value used here after move
|
= note: the full type name has been written to 'bay.long-type-14349227078439097973.txt'
= note: consider using `--verbose` to print the full type name to the console
help: consider cloning the value if the performance cost is acceptable
|
13 | let _a = x.clone();
| ++++++++
```
Rollup of 7 pull requests
Successful merges:
- #133700 (const-eval: detect more pointers as definitely not-null)
- #135290 (Encode constraints that hold at all points as logical edges in location-sensitive polonius)
- #135478 (Run clippy for rustc_codegen_gcc on CI)
- #135583 (Move `std::pipe::*` into `std::io`)
- #135612 (Include x scripts in tarballs)
- #135624 (ci: mirror buildkit image to ghcr)
- #135661 (Stabilize `float_next_up_down`)
r? `@ghost`
`@rustbot` modify labels: rollup
Instead of materializing `Locations::All` constraints as physical edges
at all the points in the CFG, we record them as logical edges and only
materialize them during traversal as successors for a given node.
This fixes the slowness/hang in the `saturating-float-casts.rs` test.
Location-sensitive polonius prototype: endgame
This PR sets up the naive location-sensitive analysis end-to-end, and replaces the location-insensitive analysis. It's roughly all the in-progress work I wanted to land for the prototype, modulo cleanups I still want to do after the holidays, or the polonius debugger, and so on.
Here, we traverse the localized constraint graph, have to deal with kills and time-traveling (👌), and record that as loan liveness for the existing scope and active loans computations.
Then the near future looks like this, especially if the 2025h1 project goal is accepted:
- gradually bringing it up to completion
- analyzing and fixing the few remaining test failures
- going over the *numerous* fixmes in this prototype (one of which is similar to a hang on one test's millions and millions of constraints)
- trying to see how to lower the impact of the lack of NLL liveness optimization on diagnostics, and their categorization of local variables and temporaries (the vast majority of blessed expectations differences), as well as the couple ICEs trying to find an NLL constraint to blame for errors.
- dealing with the theoretical weakness around kills, conflating reachability for the two TCS, etc that is described ad nauseam in the code.
- switching the compare mode to the in-tree implementation, and blessing the diagnostics
- apart from the hang, it's not catastrophically slower on our test suite, so then we can try to enable it on CI
- checking crater, maybe trying to make it faster :3, etc.
I've tried to gradually introduce this PR's work over 4 commits, because it's kind of subtle/annoying, and Niko/I are not completely convinced yet. That one comment explaining the situation is maybe 30% of the PR 😓. Who knew that spacetime reachability and time-traveling could be mind bending.
I kinda found this late and the impact on this part of the computation was a bit unexpected to us. A bit more care/thought will be needed here. I've described my plan in the comments though. In any case, I believe we have the current implementation is a conservative approximation that shouldn't result in unsoundness but false positives at worst. So it feels fine for now.
r? ``@jackh726``
---
Fixes#127628 -- which was a assertion triggered for a difference in loan computation between NLLs and the location-insensitive analysis. That doesn't exist anymore so I've removed this crash test.
Make sure to scrape region constraints from deeply normalizing type outlives assumptions in borrowck
Otherwise we're just randomly registering these region relations into the infcx which isn't good
r? lcnr
Rollup of 6 pull requests
Successful merges:
- #129259 (Add inherent versions of MaybeUninit methods for slices)
- #135374 (Suggest typo fix when trait path expression is typo'ed)
- #135377 (Make MIR cleanup for functions with impossible predicates into a real MIR pass)
- #135378 (Remove a bunch of diagnostic stashing that doesn't do anything)
- #135397 (compiletest: add erroneous variant to `string_enum`s conversions error)
- #135398 (add more crash tests)
r? `@ghost`
`@rustbot` modify labels: rollup
Remove a bunch of diagnostic stashing that doesn't do anything
#121669 removed a bunch of conditional diagnostic stashing/canceling, but left around the `steal` calls which just emitted the error eagerly instead of canceling the diagnostic. I think that these no-op `steal` calls don't do much and are confusing to encounter, so let's remove them.
The net effect is:
1. We emit more duplicated errors, since stashing has the side effect of duplicating diagnostics. This is not a big deal, since outside of `-Zdeduplicate-diagnostics=no`, the errors are already being deduplicated by the compiler.
2. It changes the order of diagnostics, since we're no longer stashing and then later stealing the errors. I don't think this matters much for the changes that the UI test suite manifests, and it makes these errors less order dependent.
Cleanup `suggest_binding_for_closure_capture_self` diag in borrowck
Mostly grammar fix/improvement, but also a small cleanup to use iterators instead of for loops for collecting into a vector.
this addresses review comments while:
- keeping the symmetry between the NLL and Polonius out of scope
precomputers
- keeping the unstable `calculate_borrows_out_of_scope_at_location`
function to avoid churn for consumers
we're in in the endgame now
set up the location-sensitive analysis end to end:
- stop recording inflowing loans and loan liveness in liveness
- replace location-insensitive liveness data with live loans computed by
reachability
- remove equivalence between polonius scopes and NLL scopes, and only
run one scope computation
in NLLs some locals are marked live at all points if one of their
regions escapes the function but that doesn't work in a flow-sensitive
setting like polonius
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`
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](364ca7f99c) 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`.
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.
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``
This renames variables named `str` to other names, to make sure `str`
always refers to a type.
It's confusing to read code where `str` (or another standard type name)
is used as an identifier. It also produces misleading syntax
highlighting.
The SCCs of the region graph are not a reliable heuristic to use for blaming an interesting
constraint for diagnostics. For region errors, if the outlived region is `'static`, or the involved
types are invariant in their lifetiems, there will be cycles in the constraint graph containing both
the target region and the most interesting constraints to blame. To get better diagnostics in these
cases, this commit removes that heuristic.
`ExtraConstraintInfo` was used only for a single subdiagnostic, so this moves the logic for that
to its own function and eliminates the indirection. In order to do so cleanly, this also changes
the arguments to `BorrowExplanation::add_explanation_to_diagnostic`, which happens to simplify its
call sites.
Some small nits to the borrowck suggestions for mutating a map through index
1. Suggesting users to either use `.insert` or `.get_mut` (which do totally different things) can be a bit of a footgun, so let's make that a bit more nuanced.
2. I find the suggestion of `.get_mut(|val| { *val = whatever; })` to be a bit awkward. I changed this to be an if-let instead.
3. Fix a bug which was suppressing the structured suggestion for some mutations via the index operator on `HashMap`/`BTreeMap`.
r? estebank or reassign
borrowck diagnostics: make `add_move_error_suggestions` use the HIR rather than `SourceMap`
This PR aims to fix#132806 by rewriting `add_move_error_suggestions`[^1]. Previously, it manually scanned the source text to find a leading `&`, which isn't always going to produce a correct result (see: that issue). Admittedly, the HIR visitor in this PR introduces a lot of boilerplate, but hopefully the logic at its core isn't too complicated (I go over it in the comments). I also tried a simpler version that didn't use a HIR visitor and suggested adding `ref` always, but the `&ref x` suggestions really didn't look good. As a bonus for the added complexity though, it's now able to produce nice `&`-removing suggestions in more cases.
I tried to do this such that it avoids edition-dependent checks and its suggestions can be applied together with those from the match ergonomics 2024 migration lint. I haven't added tests for that since the details of match ergonomics 2024 are still being sorted out, but I can try if desired once that's finalized.
[^1]: In brief, it fires on patterns where users try to bind by-value in such a way that moves out of a reference to a non-Copy type (including slice references with non-copy elements). The suggestions are to change the binding's mode to be by-reference, either by removing[^2] an enclosing `&`/`&mut` or adding `ref` to the binding.
[^2]: Incidentally, I find the terminology of "consider removing the borrow" a bit confusing for a suggestion to remove a `&` pattern in order to make bindings borrow rather than move. I'm not sure what a good, concise way to explain that would be though, and that should go in a separate PR anyway.
- add a FIXME when looking for the region variance of unexpected regions
- drive-by: fix a doc comment link
- drive-by: simplify the variance match using exported variants instead
This context struct will hold data to help creating localized
constraints:
- the live regions, with the shape matching a CFG walk, indexed per
point
- the variance of these live regions, represented as the direction we'll
add the appropriate
We also add this structure to the mir typeck to record liveness data,
and make it responsible for localized constraint creation.
Avoid ICE in borrowck
Provide a fallback in `best_blame_constraint` when `find_constraint_paths_between_regions` doesn't have a result. This code is due a rework to avoid the letf-over `unwrap()`, but avoids the ICE caused by the repro.
Fix#133252.
Begin to implement type system layer of unsafe binders
Mostly TODOs, but there's a lot of match arms that are basically just noops so I wanted to split these out before I put up the MIR lowering/projection part of this logic.
r? oli-obk
Tracking:
- https://github.com/rust-lang/rust/issues/130516
cleanup `TypeVerifier`
We should merge it with the `TypeChecker` as we no longer bail in cases where it encounters an error since #111863.
It's quite inconsistent whether a check lives in the verifier or the `TypeChecker`, so this feels like a quite impactful cleanup. I expect that for this we may want to change the `TypeChecker` to also be a MIR visitor 🤔 this is non-trivial so I didn't fully do it in this PR.
Best reviewed commit by commit.
r? `@compiler-errors` feel free to reassign however
Foundations of location-sensitive polonius
I'd like to land the prototype I'm describing in the [polonius project goal](https://github.com/rust-lang/rust-project-goals/issues/118). It still is incomplete and naive and terrible but it's working "well enough" to consider landing.
I'd also like to make review easier by not opening a huge PR, but have a couple small-ish ones (the +/- line change summary of this PR looks big, but >80% is moving datalog to a single place).
This PR starts laying the foundation for that work:
- it refactors and collects 99% of the old datalog fact gen, which was spread around everywhere, into a single dedicated module. It's still present at 3 small places (one of which we should revert anyways) that are kinda deep within localized components and are not as easily extractable into the rest of fact gen, so it's fine for now.
- starts introducing the localized constraints, the building blocks of the naive way of implementing the location-sensitive analysis in-tree, which is roughly sketched out in https://smallcultfollowing.com/babysteps/blog/2023/09/22/polonius-part-1/ and https://smallcultfollowing.com/babysteps/blog/2023/09/29/polonius-part-2/ but with a different vibe than per-point environments described in these posts, just `r1@p: r2@q` constraints.
- sets up the skeleton of generating these localized constraints: converting NLL typeck constraints, and creating liveness constraints
- introduces the polonius dual to NLL MIR to help development and debugging. It doesn't do much currently but is a way to see these localized constraints: it's an NLL MIR dump + a dumb listing of the constraints, that can be dumped with `-Zdump-mir=polonius -Zpolonius=next`. Its current state is not intended to be a long-term thing, just for testing purposes -- I will replace its contents in the future with a different approach (an HTML+js file where we can more easily explore/filter/trace these constraints and loan reachability, have mermaid graphs of the usual graphviz dumps, etc).
I've started documenting the approach in this PR, I'll add more in the future. It's quite simple, and should be very clear when more constraints are introduced anyways.
r? `@matthewjasper`
Best reviewed per commit so that the datalog move is less bothersome to read, but if you'd prefer we separate that into a different PR, I can do that (and michael has offered to review these more mechanical changes if it'd help).
Provide a fallback in `best_blame_constraint` when `find_constraint_paths_between_regions` doesn't have a result. This code is due a rework to avoid the letf-over `unwrap()`, but avoids the ICE caused by the repro.
Fix#133252.
handle member constraints directly in the mir type checker
cleaner, faster, easier to change going forward :> fixes#109654
r? `@oli-obk` `@compiler-errors`
cleanup region handling: add `LateParamRegionKind`
The second commit is to enable a split between `BoundRegionKind` and `LateParamRegionKind`, by avoiding `BoundRegionKind` where it isn't necessary.
The third comment then adds `LateParamRegionKind` to avoid having the same late-param region for separate bound regions. This fixes#124021.
r? `@compiler-errors`