Skip to content

Conversation

amandasystems
Copy link
Contributor

@amandasystems amandasystems commented Jun 17, 2025

This PR breaks out yet another part of #130227. It prepares for the removal of precise placeholder tracking by colocating detecting placeholder errors for higher-ranked relations (placeholders outliving existentials that can't name them, other placeholders) with the preprocessing step that adds outlives-static constraints. This also relieves that step from the burden of ensuring these errors are detected via propagation, and fully splits the logic into one part that rewrites the constraint graph to add edges to 'static and one that detects hard errors.

For stepping-on-toes reasons it is currently based on #140737, but can be rebased on regular master and merged separately nope that's a terrible idea actually, it relies on some of the tracking introduced there.

This step also makes region errors more fine-grained, which is useful to simplify the error reporting pipeline, which is currently based on a very brittle method of reconstructing an error event after the fact to figure out what went wrong. Doing that is left as future work, though.

This changes the logic of error reporting slightly to not emit errors for placeholder/higher kinded constraints if there are other borrowck errors. This somewhat lessens the flood of errors and was described as if anything an improvement by @nikomatsakis in informal review.

r? lcnr

Fixes: #146467

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jun 17, 2025
@rust-log-analyzer

This comment has been minimized.

@amandasystems
Copy link
Contributor Author

Wow, a merge conflict with upstream for a commit I JUST PUSHED, that's record time!

@amandasystems amandasystems force-pushed the early-placeholder-errors branch 2 times, most recently from fd18095 to 199f961 Compare June 17, 2025 15:11
@amandasystems amandasystems changed the title [WIP] Move placeholder error handling to before region inference Move placeholder error handling to before region inference Jun 25, 2025
@lcnr
Copy link
Contributor

lcnr commented Jul 3, 2025

@rustbot blocked

@rustbot rustbot added S-blocked Status: Blocked on something else such as an RFC or other implementation work. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jul 3, 2025
@amandasystems amandasystems force-pushed the early-placeholder-errors branch from 199f961 to 3a46042 Compare August 27, 2025 11:03
@rustbot

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@amandasystems amandasystems force-pushed the early-placeholder-errors branch from 3a46042 to 9b555d3 Compare August 27, 2025 19:44
@rustbot

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@amandasystems amandasystems force-pushed the early-placeholder-errors branch from 9b555d3 to f31393f Compare August 27, 2025 20:01
@amandasystems
Copy link
Contributor Author

@rustbot ready

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-blocked Status: Blocked on something else such as an RFC or other implementation work. labels Aug 27, 2025
Comment on lines -26 to +25
= note: `Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`...
= note: `Getter<'_>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'1>>`, for any two lifetimes `'0` and `'1`...
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hate this, but can't find a way around it. My gut feeling says it's another case of an order-dependent extraction procedure somewhere. For what it's worth, it wasn't in the earlier version of this code but it seems to have appeared after the recent changes to the base commit. Presumably the difference is from selecting smallest placeholder by rvid, etc. Help very much appreciated!

@amandasystems amandasystems force-pushed the early-placeholder-errors branch from f31393f to f542ec5 Compare September 3, 2025 09:17
error_element
{
let adjusted_universe =
error_placeholder.universe.as_u32().checked_sub(base_universe.as_u32());
Copy link
Contributor Author

@amandasystems amandasystems Sep 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the "checked sub" part is what really broke me here. Why are universes being adjusted? What's a base universe? And why can the subtraction sometimes overflow?!?!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the record, these are the only reads of base_universe on CanonicalTypeOpDeeplyNormalizeGoal, CanonicalTypeOpAscribeUserTypeGoal and InstantiateOpaqueType.

@rust-log-analyzer

This comment has been minimized.

@amandasystems amandasystems force-pushed the early-placeholder-errors branch from f542ec5 to 8269a42 Compare September 11, 2025 09:41
@rust-log-analyzer

This comment has been minimized.

@amandasystems
Copy link
Contributor Author

amandasystems commented Sep 11, 2025

The job pr-check-2 failed! Check out the build log: (web) (plain enhanced) (plain)
Click to see the possible cause of the failure (guessed by this bot)

 95 | |         constraints.clone(),
 96 | |         &universal_region_relations,
 97 | |         infcx,
 98 | |     );
    | |_____- argument #4 of type `&mut RegionErrors<'_>` is missing
    |
note: function defined here
   --> compiler/rustc_borrowck/src/handle_placeholders.rs:306:15
    |
306 | pub(crate) fn compute_sccs_applying_placeholder_outlives_constraints<'tcx>(
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...
310 |     errors_buffer: &mut RegionErrors<'tcx>,
    |     --------------------------------------
help: provide the argument
    |
 94 -     let lowered_constraints = compute_sccs_applying_placeholder_outlives_constraints(
 95 -         constraints.clone(),
 96 -         &universal_region_relations,
 97 -         infcx,
 98 -     );
 94 +     let lowered_constraints = compute_sccs_applying_placeholder_outlives_constraints(constraints.clone(), &universal_region_relations, infcx, /* &mut RegionErrors<'_> */);
    |

For more information about this error, try `rustc --explain E0061`.
[RUSTC-TIMING] rustc_borrowck test:false 4.478
error: could not compile `rustc_borrowck` (lib) due to 1 previous error

I don't understand where these errors come from. On my branch every single commit passes the ./x check command. What's emitting these? The error refers to a line that doesn't exist in a file that doesn't look like that during any commit in the PR.

@amandasystems amandasystems force-pushed the early-placeholder-errors branch from 8269a42 to e0b30fa Compare September 11, 2025 10:15
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Sep 24, 2025
fix 2 borrowck issues

fixes rust-lang#146467 cc `@amandasystems`

our understanding here is as follows: region constraints from computing implied bounds gets `ConstraintCategory::Internal`. If there's a higher-ranked subtyping errors while computing implied bounds we then ended up with only `ConstraintCategory::Internal` and `ConstraintCategory::OutlivesUnnameablePlaceholder(_)` constraints.

The path was something like
- `'placeholderU2: 'placeholderU1` (`Internal`)
- `'placeholderU1: 'static` (`OutlivesUnnameablePlaceholder('placeholderU2)`)

It's generally somewhat subtle here as ideally relating placeholders doesn't introduce `'static` constraints. Relating the placeholders themselves will always error regardless, cc rust-lang#142623.

---

separately fixes rust-lang#145925 (comment) by updating the location for deferred closure requirements inside of promoteds. I am not updating their category as doing so is 1) effort and 2) imo actually undesirable 🤔 see the comments in `TypeChecker::check_promoted` cc `@lqd`

r? lqd
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Sep 24, 2025
fix 2 borrowck issues

fixes rust-lang#146467 cc ``@amandasystems``

our understanding here is as follows: region constraints from computing implied bounds gets `ConstraintCategory::Internal`. If there's a higher-ranked subtyping errors while computing implied bounds we then ended up with only `ConstraintCategory::Internal` and `ConstraintCategory::OutlivesUnnameablePlaceholder(_)` constraints.

The path was something like
- `'placeholderU2: 'placeholderU1` (`Internal`)
- `'placeholderU1: 'static` (`OutlivesUnnameablePlaceholder('placeholderU2)`)

It's generally somewhat subtle here as ideally relating placeholders doesn't introduce `'static` constraints. Relating the placeholders themselves will always error regardless, cc rust-lang#142623.

---

separately fixes rust-lang#145925 (comment) by updating the location for deferred closure requirements inside of promoteds. I am not updating their category as doing so is 1) effort and 2) imo actually undesirable 🤔 see the comments in `TypeChecker::check_promoted` cc ``@lqd``

r? lqd
rust-timer added a commit that referenced this pull request Sep 24, 2025
Rollup merge of #146711 - lcnr:fix-placeholder-ice, r=lqd

fix 2 borrowck issues

fixes #146467 cc ``@amandasystems``

our understanding here is as follows: region constraints from computing implied bounds gets `ConstraintCategory::Internal`. If there's a higher-ranked subtyping errors while computing implied bounds we then ended up with only `ConstraintCategory::Internal` and `ConstraintCategory::OutlivesUnnameablePlaceholder(_)` constraints.

The path was something like
- `'placeholderU2: 'placeholderU1` (`Internal`)
- `'placeholderU1: 'static` (`OutlivesUnnameablePlaceholder('placeholderU2)`)

It's generally somewhat subtle here as ideally relating placeholders doesn't introduce `'static` constraints. Relating the placeholders themselves will always error regardless, cc #142623.

---

separately fixes #145925 (comment) by updating the location for deferred closure requirements inside of promoteds. I am not updating their category as doing so is 1) effort and 2) imo actually undesirable 🤔 see the comments in `TypeChecker::check_promoted` cc ``@lqd``

r? lqd
github-actions bot pushed a commit to rust-lang/rust-analyzer that referenced this pull request Sep 25, 2025
fix 2 borrowck issues

fixes rust-lang/rust#146467 cc ``@amandasystems``

our understanding here is as follows: region constraints from computing implied bounds gets `ConstraintCategory::Internal`. If there's a higher-ranked subtyping errors while computing implied bounds we then ended up with only `ConstraintCategory::Internal` and `ConstraintCategory::OutlivesUnnameablePlaceholder(_)` constraints.

The path was something like
- `'placeholderU2: 'placeholderU1` (`Internal`)
- `'placeholderU1: 'static` (`OutlivesUnnameablePlaceholder('placeholderU2)`)

It's generally somewhat subtle here as ideally relating placeholders doesn't introduce `'static` constraints. Relating the placeholders themselves will always error regardless, cc rust-lang/rust#142623.

---

separately fixes rust-lang/rust#145925 (comment) by updating the location for deferred closure requirements inside of promoteds. I am not updating their category as doing so is 1) effort and 2) imo actually undesirable 🤔 see the comments in `TypeChecker::check_promoted` cc ``@lqd``

r? lqd
@amandasystems amandasystems force-pushed the early-placeholder-errors branch from 23899d8 to 351a854 Compare September 25, 2025 14:06
@rustbot

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@amandasystems amandasystems force-pushed the early-placeholder-errors branch from 875cbf5 to 264683d Compare October 13, 2025 09:43
@rustbot
Copy link
Collaborator

rustbot commented Oct 13, 2025

This PR was rebased onto a different master commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@lcnr
Copy link
Contributor

lcnr commented Oct 13, 2025

@bors try @rust-timer queue

@rust-timer

This comment has been minimized.

@rust-bors

This comment has been minimized.

rust-bors bot added a commit that referenced this pull request Oct 13, 2025
Move placeholder error handling to before region inference
@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Oct 13, 2025
@rust-log-analyzer

This comment has been minimized.

@rust-bors
Copy link

rust-bors bot commented Oct 13, 2025

☀️ Try build successful (CI)
Build commit: 242f8ac (242f8ac02ecefa54679e01596e7e4764d5a32f64, parent: 35456985fab3419baf4bf111b8bbbd5e8565615d)

@rust-timer

This comment has been minimized.

@rust-timer
Copy link
Collaborator

Finished benchmarking commit (242f8ac): comparison URL.

Overall result: ❌ regressions - please read the text below

Benchmarking this pull request means it may be perf-sensitive – we'll automatically label it not fit for rolling up. You can override this, but we strongly advise not to, due to possible changes in compiler perf.

Next Steps: If you can justify the regressions found in this try perf run, please do so in sufficient writing along with @rustbot label: +perf-regression-triaged. If not, please fix the regressions and do another perf run. If its results are neutral or positive, the label will be automatically removed.

@bors rollup=never
@rustbot label: -S-waiting-on-perf +perf-regression

Instruction count

Our most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.

mean range count
Regressions ❌
(primary)
0.1% [0.1%, 0.2%] 12
Regressions ❌
(secondary)
0.2% [0.0%, 0.4%] 19
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) 0.1% [0.1%, 0.2%] 12

Max RSS (memory usage)

Results (primary -4.1%, secondary -0.3%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
0.8% [0.8%, 0.8%] 1
Improvements ✅
(primary)
-4.1% [-6.3%, -1.8%] 2
Improvements ✅
(secondary)
-1.4% [-1.4%, -1.4%] 1
All ❌✅ (primary) -4.1% [-6.3%, -1.8%] 2

Cycles

Results (secondary 0.4%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
4.3% [4.3%, 4.3%] 1
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-3.4% [-3.4%, -3.4%] 1
All ❌✅ (primary) - - 0

Binary size

Results (secondary 0.0%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
0.0% [0.0%, 0.0%] 1
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) - - 0

Bootstrap: 474.753s -> 473.062s (-0.36%)
Artifact size: 388.13 MiB -> 388.15 MiB (0.00%)

@rustbot rustbot added perf-regression Performance regression. and removed S-waiting-on-perf Status: Waiting on a perf run to be completed. labels Oct 13, 2025
Comment on lines +111 to +112
origin_a: ty::PlaceholderRegion,
origin_b: ty::PlaceholderRegion,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need these two origins? i feel like we should be able to just recompute them

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, all we need is the SCC annotation and the defintions.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, the definitions are of course enough.

Comment on lines 125 to 135
/// The smallest max nameable universe of all
/// regions reachable from this SCC.
min_max_nameable_universe: UniverseIndex,

/// The existential region with the smallest universe, if any.
min_universe_existential: Option<(UniverseIndex, RegionVid)>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this split seems odd to me. In a sense we'd want a single "min (max nameable universe) < placeholder universe" and then check the source of that "min (max nameable universe)" to figure out whether its

  • placeholder: placeholder
  • existential: placeholder
  • location: placeholder

Do we even care about location: placeholder? I

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we even care about location: placeholder? I

Some experiments I did suggested we do (otherwise we miss errors) but uh from what I've had explained to me we probably shouldn't? It's strange and I don't like it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But this points towards a potentially much nicer variant that's a state machine tracking precisely this.

diag: &mut Diag<'_>,
lower_bound: RegionVid,
) {
) -> Option<()> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Option<()>?

@amandasystems amandasystems force-pushed the early-placeholder-errors branch from 264683d to 05d58ab Compare October 15, 2025 11:15
@rust-log-analyzer
Copy link
Collaborator

The job tidy failed! Check out the build log: (web) (plain enhanced) (plain)

Click to see the possible cause of the failure (guessed by this bot)
-        placeholder_to_region: _
+        placeholder_to_region: _,
     } = constraints;
 
     let fr_static = universal_regions.fr_static;
fmt: checked 6478 files
Bootstrap failed while executing `test src/tools/tidy tidyselftest --extra-checks=py,cpp,js,spellcheck`
Build completed unsuccessfully in 0:00:48
  local time: Wed Oct 15 11:19:35 UTC 2025
  network time: Wed, 15 Oct 2025 11:19:36 GMT

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

perf-regression Performance regression. S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ICE Illegal placeholder constraint blamed; should have redirected to other region relation

6 participants