Skip to content

Commit 8ab71ab

Browse files
committed
Auto merge of #100980 - compiler-errors:normalize-opaque-w-bound-vars, r=lcnr
Normalize opaques w/ bound vars First, we reenable normalization of opaque types with escaping late bound regions to fix rust-lang/miri#2433. This essentially reverts #89285. Second, we mitigate the perf regression found in #88862 by simplifying the way that we relate (sub and eq) GeneratorWitness types. This relies on the fact that we construct these GeneratorWitness types somewhat particularly (with all free regions found in the witness types replaced with late bound regions) -- but those bound regions really should be treated as existential regions, not universal ones. Those two facts leads me to believe that we do not need to use the full `higher_ranked_sub` machinery to relate two generator witnesses. I'm pretty confident that this is correct, but I'm glad to discuss this further.
2 parents c10f7d7 + 3fc328d commit 8ab71ab

File tree

7 files changed

+43
-24
lines changed

7 files changed

+43
-24
lines changed

compiler/rustc_infer/src/infer/equate.rs

+19
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,25 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
110110
.obligations,
111111
);
112112
}
113+
// Optimization of GeneratorWitness relation since we know that all
114+
// free regions are replaced with bound regions during construction.
115+
// This greatly speeds up equating of GeneratorWitness.
116+
(&ty::GeneratorWitness(a_types), &ty::GeneratorWitness(b_types)) => {
117+
let a_types = infcx.tcx.anonymize_bound_vars(a_types);
118+
let b_types = infcx.tcx.anonymize_bound_vars(b_types);
119+
if a_types.bound_vars() == b_types.bound_vars() {
120+
let (a_types, b_types) = infcx.replace_bound_vars_with_placeholders(
121+
a_types.map_bound(|a_types| (a_types, b_types.skip_binder())),
122+
);
123+
for (a, b) in std::iter::zip(a_types, b_types) {
124+
self.relate(a, b)?;
125+
}
126+
} else {
127+
return Err(ty::error::TypeError::Sorts(ty::relate::expected_found(
128+
self, a, b,
129+
)));
130+
}
131+
}
113132

114133
_ => {
115134
self.fields.infcx.super_combine_tys(self, a, b)?;

compiler/rustc_infer/src/infer/sub.rs

+18
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,24 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
164164
);
165165
Ok(ga)
166166
}
167+
// Optimization of GeneratorWitness relation since we know that all
168+
// free regions are replaced with bound regions during construction.
169+
// This greatly speeds up subtyping of GeneratorWitness.
170+
(&ty::GeneratorWitness(a_types), &ty::GeneratorWitness(b_types)) => {
171+
let a_types = infcx.tcx.anonymize_bound_vars(a_types);
172+
let b_types = infcx.tcx.anonymize_bound_vars(b_types);
173+
if a_types.bound_vars() == b_types.bound_vars() {
174+
let (a_types, b_types) = infcx.replace_bound_vars_with_placeholders(
175+
a_types.map_bound(|a_types| (a_types, b_types.skip_binder())),
176+
);
177+
for (a, b) in std::iter::zip(a_types, b_types) {
178+
self.relate(a, b)?;
179+
}
180+
Ok(a)
181+
} else {
182+
Err(ty::error::TypeError::Sorts(ty::relate::expected_found(self, a, b)))
183+
}
184+
}
167185

168186
_ => {
169187
self.fields.infcx.super_combine_tys(self, a, b)?;

compiler/rustc_trait_selection/src/traits/project.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
499499
// This is really important. While we *can* handle this, this has
500500
// severe performance implications for large opaque types with
501501
// late-bound regions. See `issue-88862` benchmark.
502-
ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => {
502+
ty::Opaque(def_id, substs) => {
503503
// Only normalize `impl Trait` outside of type inference, usually in codegen.
504504
match self.param_env.reveal() {
505505
Reveal::UserFacing => ty.super_fold_with(self),

compiler/rustc_trait_selection/src/traits/query/normalize.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
198198
// This is really important. While we *can* handle this, this has
199199
// severe performance implications for large opaque types with
200200
// late-bound regions. See `issue-88862` benchmark.
201-
ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => {
201+
ty::Opaque(def_id, substs) => {
202202
// Only normalize `impl Trait` outside of type inference, usually in codegen.
203203
match self.param_env.reveal() {
204204
Reveal::UserFacing => ty.try_super_fold_with(self),

compiler/rustc_typeck/src/check/generator_interior.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,8 @@ pub fn resolve_interior<'a, 'tcx>(
218218
.filter_map(|mut cause| {
219219
// Erase regions and canonicalize late-bound regions to deduplicate as many types as we
220220
// can.
221-
let erased = fcx.tcx.erase_regions(cause.ty);
221+
let ty = fcx.normalize_associated_types_in(cause.span, cause.ty);
222+
let erased = fcx.tcx.erase_regions(ty);
222223
if captured_tys.insert(erased) {
223224
// Replace all regions inside the generator interior with late bound regions.
224225
// Note that each region slot in the types gets a new fresh late bound region,
@@ -263,7 +264,7 @@ pub fn resolve_interior<'a, 'tcx>(
263264
// Unify the type variable inside the generator with the new witness
264265
match fcx.at(&fcx.misc(body.value.span), fcx.param_env).eq(interior, witness) {
265266
Ok(ok) => fcx.register_infer_ok_obligations(ok),
266-
_ => bug!(),
267+
_ => bug!("failed to relate {interior} and {witness}"),
267268
}
268269
}
269270

src/test/ui/higher-rank-trait-bounds/issue-95034.rs

+1-19
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,5 @@
1-
// known-bug: #95034
2-
// failure-status: 101
1+
// check-pass
32
// compile-flags: --edition=2021 --crate-type=lib
4-
// rustc-env:RUST_BACKTRACE=0
5-
6-
// normalize-stderr-test "thread 'rustc' panicked.*" -> "thread 'rustc' panicked"
7-
// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> ""
8-
// normalize-stderr-test "\nerror: internal compiler error.*\n\n" -> ""
9-
// normalize-stderr-test "note:.*unexpectedly panicked.*\n\n" -> ""
10-
// normalize-stderr-test "note: we would appreciate a bug report.*\n\n" -> ""
11-
// normalize-stderr-test "note: compiler flags.*\n\n" -> ""
12-
// normalize-stderr-test "note: rustc.*running on.*\n\n" -> ""
13-
// normalize-stderr-test "query stack during panic:\n" -> ""
14-
// normalize-stderr-test "we're just showing a limited slice of the query stack\n" -> ""
15-
// normalize-stderr-test "end of query stack\n" -> ""
16-
// normalize-stderr-test "#.*\n" -> ""
17-
18-
// This should not ICE.
19-
20-
// Refer to the issue for more minimized versions.
213

224
use std::{
235
future::Future,

src/test/ui/higher-rank-trait-bounds/issue-95034.stderr

-1
This file was deleted.

0 commit comments

Comments
 (0)