diff options
| author | bors <bors@rust-lang.org> | 2025-08-15 18:52:12 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2025-08-15 18:52:12 +0000 |
| commit | cd7cbe818e4a66d46fe2df993d1b8518eba8a5cd (patch) | |
| tree | 083a9ef7740f16b0fd86ed1b2468387c81ae22ff /compiler | |
| parent | 8b1889cc22439e02cf03cd8cff9764a307b21193 (diff) | |
| parent | cde14e65bf4d072ab38cf7e909113979b12ae044 (diff) | |
| download | rust-cd7cbe818e4a66d46fe2df993d1b8518eba8a5cd.tar.gz rust-cd7cbe818e4a66d46fe2df993d1b8518eba8a5cd.zip | |
Auto merge of #142071 - lcnr:revealing-use, r=compiler-errors
`apply_member_constraints`: fix placeholder check
Checking whether the member region is *an existential region from a higher universe* is just wrong and I am pretty sure we've added that check by accident as the naming was just horribly confusing before rust-lang/rust#140466.
I've encountered this issue separately while working on rust-lang/rust#139587, but feel like it's probably easier to separately FCP this change. This allows the following code to compile
```rust
trait Proj<'a> {
type Assoc;
}
impl<'a, 'b, F: FnOnce() -> &'b ()> Proj<'a> for F {
type Assoc = ();
}
fn is_proj<F: for<'a> Proj<'a>>(f: F) {}
fn define<'a>() -> impl Sized + use<'a> {
// This adds a use of `opaque::<'a>` with hidden type `&'unconstrained_b ()`.
// 'unconstrained_b is an inference variable from a higher universe as it gets
// created inside of the binder of `F: for<'a> Proj<'a>`. This previously
// caused us to not apply member constraints. We now do, constraining
// it to `'a`.
is_proj(define::<'a>);
&()
}
fn main() {}
```
This should not be breaking change, even in theory. Applying member constraints is incomplete in rare circumstances which means that applying them in more cases can cause spurious errors, cc rust-lang/rust#140569/rust-lang/rust#142073. However, as we always skipped these member regions in `apply_member_constraints` the skipped region is guaranteed to cause an error in `check_member_constraints` later on.
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_borrowck/src/handle_placeholders.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_borrowck/src/region_infer/mod.rs | 9 |
2 files changed, 12 insertions, 1 deletions
diff --git a/compiler/rustc_borrowck/src/handle_placeholders.rs b/compiler/rustc_borrowck/src/handle_placeholders.rs index 34599ac55b8..1614c112ab5 100644 --- a/compiler/rustc_borrowck/src/handle_placeholders.rs +++ b/compiler/rustc_borrowck/src/handle_placeholders.rs @@ -103,6 +103,10 @@ impl RegionTracker { self.max_nameable_universe } + pub(crate) fn max_placeholder_universe_reached(self) -> UniverseIndex { + self.max_placeholder_universe_reached + } + fn merge_min_max_seen(&mut self, other: &Self) { self.max_placeholder_universe_reached = std::cmp::max( self.max_placeholder_universe_reached, diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index b0c31ac9601..c76c5c17431 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -713,7 +713,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { // If the member region lives in a higher universe, we currently choose // the most conservative option by leaving it unchanged. - if !self.max_nameable_universe(scc).is_root() { + if !self.max_placeholder_universe_reached(scc).is_root() { return; } @@ -1376,6 +1376,13 @@ impl<'tcx> RegionInferenceContext<'tcx> { self.scc_annotations[scc].max_nameable_universe() } + pub(crate) fn max_placeholder_universe_reached( + &self, + scc: ConstraintSccIndex, + ) -> UniverseIndex { + self.scc_annotations[scc].max_placeholder_universe_reached() + } + /// Checks the final value for the free region `fr` to see if it /// grew too large. In particular, examine what `end(X)` points /// wound up in `fr`'s final value; for each `end(X)` where `X != |
