Skip to content

Commit ac3bd4b

Browse files
authored
Rollup merge of rust-lang#90801 - b-naber:missing_normalization_equate_inputs_output, r=jackh726
Normalize both arguments of `equate_normalized_input_or_output` Fixes rust-lang#90638 Fixes rust-lang#90612 Temporary fix for a more complex underlying problem stemming from an inability to normalize closure substs during typecheck. r? ````@jackh726````
2 parents 3cd3b7a + 7a4aa65 commit ac3bd4b

File tree

4 files changed

+121
-24
lines changed

4 files changed

+121
-24
lines changed

compiler/rustc_borrowck/src/type_check/input_output.rs

+38-22
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,16 @@
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;
1011
use rustc_index::vec::Idx;
1112
use rustc_infer::infer::LateBoundRegionConversionTime;
1213
use rustc_middle::mir::*;
13-
use rustc_middle::traits::ObligationCause;
14-
use rustc_middle::ty::{self, Ty};
14+
use rustc_middle::ty::Ty;
1515
use rustc_span::Span;
16-
use rustc_trait_selection::traits::query::normalize::AtExt;
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;
1720

1821
use crate::universal_regions::UniversalRegions;
1922

@@ -30,6 +33,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
3033
let (&normalized_output_ty, normalized_input_tys) =
3134
normalized_inputs_and_output.split_last().unwrap();
3235

36+
debug!(?normalized_output_ty);
37+
debug!(?normalized_input_tys);
38+
3339
let mir_def_id = body.source.def_id().expect_local();
3440

3541
// If the user explicitly annotated the input types, extract
@@ -75,10 +81,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
7581
.delay_span_bug(body.span, "found more normalized_input_ty than local_decls");
7682
break;
7783
}
84+
7885
// In MIR, argument N is stored in local N+1.
7986
let local = Local::new(argument_index + 1);
8087

8188
let mir_input_ty = body.local_decls[local].ty;
89+
8290
let mir_input_span = body.local_decls[local].source_info.span;
8391
self.equate_normalized_input_or_output(
8492
normalized_input_ty,
@@ -100,6 +108,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
100108
// If the user explicitly annotated the input types, enforce those.
101109
let user_provided_input_ty =
102110
self.normalize(user_provided_input_ty, Locations::All(mir_input_span));
111+
103112
self.equate_normalized_input_or_output(
104113
user_provided_input_ty,
105114
mir_input_ty,
@@ -167,30 +176,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
167176
// `rustc_traits::normalize_after_erasing_regions`. Ideally, we'd
168177
// like to normalize *before* inserting into `local_decls`, but
169178
// doing so ends up causing some other trouble.
170-
let b = match self
171-
.infcx
172-
.at(&ObligationCause::dummy(), ty::ParamEnv::empty())
173-
.normalize(b)
174-
{
175-
Ok(n) => {
176-
debug!("equate_inputs_and_outputs: {:?}", n);
177-
if n.obligations.iter().all(|o| {
178-
matches!(
179-
o.predicate.kind().skip_binder(),
180-
ty::PredicateKind::RegionOutlives(_)
181-
| ty::PredicateKind::TypeOutlives(_)
182-
)
183-
}) {
184-
n.value
185-
} else {
186-
b
187-
}
188-
}
179+
let b = match self.normalize_and_add_constraints(b) {
180+
Ok(n) => n,
189181
Err(_) => {
190182
debug!("equate_inputs_and_outputs: NoSolution");
191183
b
192184
}
193185
};
186+
194187
// Note: if we have to introduce new placeholders during normalization above, then we won't have
195188
// added those universes to the universe info, which we would want in `relate_tys`.
196189
if let Err(terr) =
@@ -207,4 +200,27 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
207200
}
208201
}
209202
}
203+
204+
pub(crate) fn normalize_and_add_constraints(&mut self, t: Ty<'tcx>) -> Fallible<Ty<'tcx>> {
205+
let TypeOpOutput { output: norm_ty, constraints, .. } =
206+
self.param_env.and(type_op::normalize::Normalize::new(t)).fully_perform(self.infcx)?;
207+
208+
debug!("{:?} normalized to {:?}", t, norm_ty);
209+
210+
for data in constraints.into_iter().collect::<Vec<_>>() {
211+
ConstraintConversion::new(
212+
self.infcx,
213+
&self.borrowck_context.universal_regions,
214+
&self.region_bound_pairs,
215+
Some(self.implicit_region_bound),
216+
self.param_env,
217+
Locations::All(DUMMY_SP),
218+
ConstraintCategory::Internal,
219+
&mut self.borrowck_context.constraints,
220+
)
221+
.convert_all(&*data);
222+
}
223+
224+
Ok(norm_ty)
225+
}
210226
}

compiler/rustc_borrowck/src/type_check/mod.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -893,11 +893,11 @@ struct TypeChecker<'a, 'tcx> {
893893
}
894894

895895
struct BorrowCheckContext<'a, 'tcx> {
896-
universal_regions: &'a UniversalRegions<'tcx>,
896+
pub(crate) universal_regions: &'a UniversalRegions<'tcx>,
897897
location_table: &'a LocationTable,
898898
all_facts: &'a mut Option<AllFacts>,
899899
borrow_set: &'a BorrowSet<'tcx>,
900-
constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
900+
pub(crate) constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
901901
upvars: &'a [Upvar<'tcx>],
902902
}
903903

@@ -1157,6 +1157,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
11571157
self.relate_types(sup, ty::Variance::Contravariant, sub, locations, category)
11581158
}
11591159

1160+
#[instrument(skip(self, category), level = "debug")]
11601161
fn eq_types(
11611162
&mut self,
11621163
expected: Ty<'tcx>,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// check-pass
2+
3+
#![feature(generic_associated_types)]
4+
5+
use std::marker::PhantomData;
6+
7+
trait Family: Sized {
8+
type Item<'a>;
9+
10+
fn apply_all<F>(&self, f: F)
11+
where
12+
F: FamilyItemFn<Self> { }
13+
}
14+
15+
struct Array<T>(PhantomData<T>);
16+
17+
impl<T: 'static> Family for Array<T> {
18+
type Item<'a> = &'a T;
19+
}
20+
21+
trait FamilyItemFn<T: Family> {
22+
fn apply(&self, item: T::Item<'_>);
23+
}
24+
25+
impl<T, F> FamilyItemFn<T> for F
26+
where
27+
T: Family,
28+
for<'a> F: Fn(T::Item<'a>)
29+
{
30+
fn apply(&self, item: T::Item<'_>) {
31+
(*self)(item);
32+
}
33+
}
34+
35+
fn process<T: 'static>(array: Array<T>) {
36+
// Works
37+
array.apply_all(|x: &T| { });
38+
39+
// ICE: NoSolution
40+
array.apply_all(|x: <Array<T> as Family>::Item<'_>| { });
41+
}
42+
43+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//check-pass
2+
3+
#![feature(generic_associated_types)]
4+
5+
trait Yokeable<'a>: 'static {
6+
type Output: 'a;
7+
}
8+
9+
trait IsCovariant<'a> {}
10+
11+
struct Yoke<Y: for<'a> Yokeable<'a>> {
12+
data: Y,
13+
}
14+
15+
impl<Y: for<'a> Yokeable<'a>> Yoke<Y> {
16+
fn project<Y2: for<'a> Yokeable<'a>>(&self, _f: for<'a> fn(<Y as Yokeable<'a>>::Output, &'a ())
17+
-> <Y2 as Yokeable<'a>>::Output) -> Yoke<Y2> {
18+
19+
unimplemented!()
20+
}
21+
}
22+
23+
fn _upcast<Y>(x: Yoke<Y>) -> Yoke<Box<dyn IsCovariant<'static> + 'static>> where
24+
Y: for<'a> Yokeable<'a>,
25+
for<'a> <Y as Yokeable<'a>>::Output: IsCovariant<'a>
26+
{
27+
x.project(|data, _| {
28+
Box::new(data)
29+
})
30+
}
31+
32+
33+
impl<'a> Yokeable<'a> for Box<dyn IsCovariant<'static> + 'static> {
34+
type Output = Box<dyn IsCovariant<'a> + 'a>;
35+
}
36+
37+
fn main() {}

0 commit comments

Comments
 (0)