Skip to content

Commit ec8b515

Browse files
authored
Rollup merge of rust-lang#99818 - aliemjay:fix-closure-normalize, r=jackh726
don't ICE when normalizing closure input tys We were ICEing while rendering diagnostics because `universe_causes` is expected to track every universe created in the typeck's infcx. `normalize_and_add_constraints` doesn't update `universe_causes` when creating new universes, causing an ICE. Remove it! Add spans to better track normalization constraints. Fix couple places where `universe_causes` is not updated correctly to track newly added universes. Fixes rust-lang#102800 ~Fixess rust-lang#99665~ (UPDATE: no longer true; the issue has a different failure path than when this PR was created and should be fixed by rust-lang#101708, but the changes in this PR are still correct and should prevent potential future ICEs)
2 parents c27948d + fc3d7eb commit ec8b515

6 files changed

+150
-58
lines changed

compiler/rustc_borrowck/src/type_check/canonical.rs

+6-11
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
5252
Some(error_info) => error_info.to_universe_info(old_universe),
5353
None => UniverseInfo::other(),
5454
};
55-
for u in old_universe..universe {
56-
self.borrowck_context
57-
.constraints
58-
.universe_causes
59-
.insert(u + 1, universe_info.clone());
55+
for u in (old_universe + 1)..=universe {
56+
self.borrowck_context.constraints.universe_causes.insert(u, universe_info.clone());
6057
}
6158
}
6259

@@ -71,15 +68,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
7168
where
7269
T: TypeFoldable<'tcx>,
7370
{
71+
let old_universe = self.infcx.universe();
72+
7473
let (instantiated, _) =
7574
self.infcx.instantiate_canonical_with_fresh_inference_vars(span, canonical);
7675

77-
for u in 0..canonical.max_universe.as_u32() {
78-
let info = UniverseInfo::other();
79-
self.borrowck_context
80-
.constraints
81-
.universe_causes
82-
.insert(ty::UniverseIndex::from_u32(u), info);
76+
for u in (old_universe + 1)..=self.infcx.universe() {
77+
self.borrowck_context.constraints.universe_causes.insert(u, UniverseInfo::other());
8378
}
8479

8580
instantiated

compiler/rustc_borrowck/src/type_check/free_region_relations.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ use rustc_infer::infer::InferCtxt;
88
use rustc_middle::mir::ConstraintCategory;
99
use rustc_middle::traits::query::OutlivesBound;
1010
use rustc_middle::ty::{self, RegionVid, Ty};
11-
use rustc_span::DUMMY_SP;
1211
use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
1312
use std::rc::Rc;
1413
use type_op::TypeOpOutput;
@@ -219,6 +218,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
219218
}
220219

221220
pub(crate) fn create(mut self) -> CreateResult<'tcx> {
221+
let span = self.infcx.tcx.def_span(self.universal_regions.defining_ty.def_id());
222222
let unnormalized_input_output_tys = self
223223
.universal_regions
224224
.unnormalized_input_tys
@@ -250,7 +250,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
250250
self.infcx
251251
.tcx
252252
.sess
253-
.delay_span_bug(DUMMY_SP, &format!("failed to normalize {:?}", ty));
253+
.delay_span_bug(span, &format!("failed to normalize {:?}", ty));
254254
TypeOpOutput {
255255
output: self.infcx.tcx.ty_error(),
256256
constraints: None,
@@ -301,8 +301,8 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
301301
&self.region_bound_pairs,
302302
self.implicit_region_bound,
303303
self.param_env,
304-
Locations::All(DUMMY_SP),
305-
DUMMY_SP,
304+
Locations::All(span),
305+
span,
306306
ConstraintCategory::Internal,
307307
&mut self.constraints,
308308
)

compiler/rustc_borrowck/src/type_check/input_output.rs

+2-37
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,11 @@
77
//! `RETURN_PLACE` the MIR arguments) are always fully normalized (and
88
//! contain revealed `impl Trait` values).
99
10-
use crate::type_check::constraint_conversion::ConstraintConversion;
1110
use rustc_index::vec::Idx;
1211
use rustc_infer::infer::LateBoundRegionConversionTime;
1312
use rustc_middle::mir::*;
1413
use rustc_middle::ty::Ty;
1514
use rustc_span::Span;
16-
use rustc_span::DUMMY_SP;
17-
use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
18-
use rustc_trait_selection::traits::query::Fallible;
19-
use type_op::TypeOpOutput;
2015

2116
use crate::universal_regions::UniversalRegions;
2217

@@ -185,7 +180,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
185180
}
186181
}
187182

188-
#[instrument(skip(self, span), level = "debug")]
183+
#[instrument(skip(self), level = "debug")]
189184
fn equate_normalized_input_or_output(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, span: Span) {
190185
if let Err(_) =
191186
self.eq_types(a, b, Locations::All(span), ConstraintCategory::BoringNoLocation)
@@ -194,13 +189,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
194189
// `rustc_traits::normalize_after_erasing_regions`. Ideally, we'd
195190
// like to normalize *before* inserting into `local_decls`, but
196191
// doing so ends up causing some other trouble.
197-
let b = match self.normalize_and_add_constraints(b) {
198-
Ok(n) => n,
199-
Err(_) => {
200-
debug!("equate_inputs_and_outputs: NoSolution");
201-
b
202-
}
203-
};
192+
let b = self.normalize(b, Locations::All(span));
204193

205194
// Note: if we have to introduce new placeholders during normalization above, then we won't have
206195
// added those universes to the universe info, which we would want in `relate_tys`.
@@ -218,28 +207,4 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
218207
}
219208
}
220209
}
221-
222-
pub(crate) fn normalize_and_add_constraints(&mut self, t: Ty<'tcx>) -> Fallible<Ty<'tcx>> {
223-
let TypeOpOutput { output: norm_ty, constraints, .. } =
224-
self.param_env.and(type_op::normalize::Normalize::new(t)).fully_perform(self.infcx)?;
225-
226-
debug!("{:?} normalized to {:?}", t, norm_ty);
227-
228-
for data in constraints {
229-
ConstraintConversion::new(
230-
self.infcx,
231-
&self.borrowck_context.universal_regions,
232-
&self.region_bound_pairs,
233-
self.implicit_region_bound,
234-
self.param_env,
235-
Locations::All(DUMMY_SP),
236-
DUMMY_SP,
237-
ConstraintCategory::Internal,
238-
&mut self.borrowck_context.constraints,
239-
)
240-
.convert_all(&*data);
241-
}
242-
243-
Ok(norm_ty)
244-
}
245210
}

compiler/rustc_borrowck/src/type_check/mod.rs

+3-6
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,6 @@ pub(crate) fn type_check<'mir, 'tcx>(
138138
use_polonius: bool,
139139
) -> MirTypeckResults<'tcx> {
140140
let implicit_region_bound = infcx.tcx.mk_region(ty::ReVar(universal_regions.fr_fn_body));
141-
let mut universe_causes = FxHashMap::default();
142-
universe_causes.insert(ty::UniverseIndex::from_u32(0), UniverseInfo::other());
143141
let mut constraints = MirTypeckRegionConstraints {
144142
placeholder_indices: PlaceholderIndices::default(),
145143
placeholder_index_to_region: IndexVec::default(),
@@ -148,7 +146,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
148146
member_constraints: MemberConstraintSet::default(),
149147
closure_bounds_mapping: Default::default(),
150148
type_tests: Vec::default(),
151-
universe_causes,
149+
universe_causes: FxHashMap::default(),
152150
};
153151

154152
let CreateResult {
@@ -165,9 +163,8 @@ pub(crate) fn type_check<'mir, 'tcx>(
165163

166164
debug!(?normalized_inputs_and_output);
167165

168-
for u in ty::UniverseIndex::ROOT..infcx.universe() {
169-
let info = UniverseInfo::other();
170-
constraints.universe_causes.insert(u, info);
166+
for u in ty::UniverseIndex::ROOT..=infcx.universe() {
167+
constraints.universe_causes.insert(u, UniverseInfo::other());
171168
}
172169

173170
let mut borrowck_context = BorrowCheckContext {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Regression test for #102800
2+
//
3+
// Here we are generating higher-ranked region constraints when normalizing and relating closure
4+
// input types. Previously this was an ICE in the error path because we didn't register enough
5+
// diagnostic information to render the higher-ranked subtyping error.
6+
7+
// check-fail
8+
9+
trait Trait {
10+
type Ty;
11+
}
12+
13+
impl Trait for &'static () {
14+
type Ty = ();
15+
}
16+
17+
fn main() {
18+
let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
19+
//~^ ERROR lifetime may not live long enough
20+
//~| ERROR higher-ranked subtype error
21+
//~| ERROR higher-ranked subtype error
22+
//~| ERROR implementation of `Trait` is not general enough
23+
//~| ERROR implementation of `Trait` is not general enough
24+
//~| ERROR implementation of `Trait` is not general enough
25+
//~| ERROR implementation of `Trait` is not general enough
26+
//~| ERROR implementation of `Trait` is not general enough
27+
//~| ERROR implementation of `Trait` is not general enough
28+
//~| ERROR implementation of `Trait` is not general enough
29+
//~| ERROR implementation of `Trait` is not general enough
30+
//~| ERROR implementation of `Trait` is not general enough
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
error: lifetime may not live long enough
2+
--> $DIR/closure-malformed-projection-input-issue-102800.rs:18:48
3+
|
4+
LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
5+
| ^-^
6+
| ||
7+
| |has type `<&'1 () as Trait>::Ty`
8+
| requires that `'1` must outlive `'static`
9+
10+
error: higher-ranked subtype error
11+
--> $DIR/closure-malformed-projection-input-issue-102800.rs:18:48
12+
|
13+
LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
14+
| ^^^
15+
16+
error: higher-ranked subtype error
17+
--> $DIR/closure-malformed-projection-input-issue-102800.rs:18:48
18+
|
19+
LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
20+
| ^^^
21+
22+
error: implementation of `Trait` is not general enough
23+
--> $DIR/closure-malformed-projection-input-issue-102800.rs:18:48
24+
|
25+
LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
26+
| ^^^^^^ implementation of `Trait` is not general enough
27+
|
28+
= note: `&'0 ()` must implement `Trait`, for any lifetime `'0`...
29+
= note: ...but `Trait` is actually implemented for the type `&'static ()`
30+
31+
error: implementation of `Trait` is not general enough
32+
--> $DIR/closure-malformed-projection-input-issue-102800.rs:18:12
33+
|
34+
LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
35+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Trait` is not general enough
36+
|
37+
= note: `&'0 ()` must implement `Trait`, for any lifetime `'0`...
38+
= note: ...but `Trait` is actually implemented for the type `&'static ()`
39+
40+
error: implementation of `Trait` is not general enough
41+
--> $DIR/closure-malformed-projection-input-issue-102800.rs:18:12
42+
|
43+
LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
44+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Trait` is not general enough
45+
|
46+
= note: `&'0 ()` must implement `Trait`, for any lifetime `'0`...
47+
= note: ...but `Trait` is actually implemented for the type `&'static ()`
48+
49+
error: implementation of `Trait` is not general enough
50+
--> $DIR/closure-malformed-projection-input-issue-102800.rs:18:12
51+
|
52+
LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
53+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Trait` is not general enough
54+
|
55+
= note: `&'0 ()` must implement `Trait`, for any lifetime `'0`...
56+
= note: ...but `Trait` is actually implemented for the type `&'static ()`
57+
58+
error: implementation of `Trait` is not general enough
59+
--> $DIR/closure-malformed-projection-input-issue-102800.rs:18:12
60+
|
61+
LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
62+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Trait` is not general enough
63+
|
64+
= note: `&'0 ()` must implement `Trait`, for any lifetime `'0`...
65+
= note: ...but `Trait` is actually implemented for the type `&'static ()`
66+
67+
error: implementation of `Trait` is not general enough
68+
--> $DIR/closure-malformed-projection-input-issue-102800.rs:18:48
69+
|
70+
LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
71+
| ^^^^^^ implementation of `Trait` is not general enough
72+
|
73+
= note: `&'0 ()` must implement `Trait`, for any lifetime `'0`...
74+
= note: ...but `Trait` is actually implemented for the type `&'static ()`
75+
76+
error: implementation of `Trait` is not general enough
77+
--> $DIR/closure-malformed-projection-input-issue-102800.rs:18:48
78+
|
79+
LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
80+
| ^^^^^^ implementation of `Trait` is not general enough
81+
|
82+
= note: `&'0 ()` must implement `Trait`, for any lifetime `'0`...
83+
= note: ...but `Trait` is actually implemented for the type `&'static ()`
84+
85+
error: implementation of `Trait` is not general enough
86+
--> $DIR/closure-malformed-projection-input-issue-102800.rs:18:48
87+
|
88+
LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
89+
| ^^^^^^ implementation of `Trait` is not general enough
90+
|
91+
= note: `&'0 ()` must implement `Trait`, for any lifetime `'0`...
92+
= note: ...but `Trait` is actually implemented for the type `&'static ()`
93+
94+
error: implementation of `Trait` is not general enough
95+
--> $DIR/closure-malformed-projection-input-issue-102800.rs:18:48
96+
|
97+
LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
98+
| ^^^^^^ implementation of `Trait` is not general enough
99+
|
100+
= note: `&'0 ()` must implement `Trait`, for any lifetime `'0`...
101+
= note: ...but `Trait` is actually implemented for the type `&'static ()`
102+
103+
error: aborting due to 12 previous errors
104+

0 commit comments

Comments
 (0)