Skip to content

Commit 00ddbc8

Browse files
Auto merge of #147152 - lcnr:instantiate-pre-sized-check, r=<try>
builtin `Fn`-trait impls: instantiate binder before the return type `Sized` check
2 parents 128b36a + 2801aa4 commit 00ddbc8

File tree

5 files changed

+63
-35
lines changed

5 files changed

+63
-35
lines changed

compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -633,28 +633,19 @@ where
633633
// the certainty of all the goals.
634634
#[instrument(level = "trace", skip(self))]
635635
pub(super) fn try_evaluate_added_goals(&mut self) -> Result<Certainty, NoSolution> {
636-
let mut response = Ok(Certainty::overflow(false));
637636
for _ in 0..FIXPOINT_STEP_LIMIT {
638-
// FIXME: This match is a bit ugly, it might be nice to change the inspect
639-
// stuff to use a closure instead. which should hopefully simplify this a bit.
640637
match self.evaluate_added_goals_step() {
641-
Ok(Some(cert)) => {
642-
response = Ok(cert);
643-
break;
644-
}
645638
Ok(None) => {}
639+
Ok(Some(cert)) => return Ok(cert),
646640
Err(NoSolution) => {
647-
response = Err(NoSolution);
648-
break;
641+
self.tainted = Err(NoSolution);
642+
return Err(NoSolution);
649643
}
650644
}
651645
}
652646

653-
if response.is_err() {
654-
self.tainted = Err(NoSolution);
655-
}
656-
657-
response
647+
debug!("try_evaluate_added_goals: encountered overflow");
648+
Ok(Certainty::overflow(false))
658649
}
659650

660651
/// Iterate over all added goals: returning `Ok(Some(_))` in case we can stop rerunning.

compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -452,22 +452,21 @@ where
452452
}
453453
};
454454

455+
let (inputs, output) = ecx.instantiate_binder_with_infer(tupled_inputs_and_output);
455456
// A built-in `Fn` impl only holds if the output is sized.
456457
// (FIXME: technically we only need to check this if the type is a fn ptr...)
457-
let output_is_sized_pred = tupled_inputs_and_output.map_bound(|(_, output)| {
458-
ty::TraitRef::new(cx, cx.require_trait_lang_item(SolverTraitLangItem::Sized), [output])
459-
});
458+
let output_is_sized_pred =
459+
ty::TraitRef::new(cx, cx.require_trait_lang_item(SolverTraitLangItem::Sized), [output]);
460460

461-
let pred = tupled_inputs_and_output
462-
.map_bound(|(inputs, output)| ty::ProjectionPredicate {
463-
projection_term: ty::AliasTerm::new(
464-
cx,
465-
goal.predicate.def_id(),
466-
[goal.predicate.self_ty(), inputs],
467-
),
468-
term: output.into(),
469-
})
470-
.upcast(cx);
461+
let pred = ty::ProjectionPredicate {
462+
projection_term: ty::AliasTerm::new(
463+
cx,
464+
goal.predicate.def_id(),
465+
[goal.predicate.self_ty(), inputs],
466+
),
467+
term: output.into(),
468+
}
469+
.upcast(cx);
471470

472471
Self::probe_and_consider_implied_clause(
473472
ecx,

compiler/rustc_next_trait_solver/src/solve/trait_goals.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -370,17 +370,16 @@ where
370370
}
371371
};
372372

373+
let (inputs, output) = ecx.instantiate_binder_with_infer(tupled_inputs_and_output);
374+
373375
// A built-in `Fn` impl only holds if the output is sized.
374376
// (FIXME: technically we only need to check this if the type is a fn ptr...)
375-
let output_is_sized_pred = tupled_inputs_and_output.map_bound(|(_, output)| {
376-
ty::TraitRef::new(cx, cx.require_trait_lang_item(SolverTraitLangItem::Sized), [output])
377-
});
377+
let output_is_sized_pred =
378+
ty::TraitRef::new(cx, cx.require_trait_lang_item(SolverTraitLangItem::Sized), [output]);
378379

379-
let pred = tupled_inputs_and_output
380-
.map_bound(|(inputs, _)| {
381-
ty::TraitRef::new(cx, goal.predicate.def_id(), [goal.predicate.self_ty(), inputs])
382-
})
383-
.upcast(cx);
380+
let pred =
381+
ty::TraitRef::new(cx, goal.predicate.def_id(), [goal.predicate.self_ty(), inputs])
382+
.upcast(cx);
384383
Self::probe_and_consider_implied_clause(
385384
ecx,
386385
CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//@ ignore-compare-mode-next-solver
2+
//@ compile-flags: -Znext-solver
3+
//@ check-pass
4+
5+
// Regression test for trait-system-refactor-initiative#220. Builtin `Fn`-trait
6+
// candidates required `for<'latebound> Output<'latebound>: Sized` which ended
7+
// up resulting in overflow if the return type is an opaque in the defining scope.
8+
//
9+
// We now eagerly instantiate the binder of the function definition which avoids
10+
// that overflow by relating the lifetime of the opaque to something from the
11+
// input.
12+
fn flat_map<T, F, I, G>(_: F, _: G)
13+
where
14+
F: FnOnce(T) -> I,
15+
I: Iterator,
16+
G: Fn(<I as Iterator>::Item) -> usize,
17+
{
18+
}
19+
20+
fn rarw<'a>(_: &'a ()) -> impl Iterator<Item = &'a str> {
21+
flat_map(rarw, |x| x.len());
22+
std::iter::empty()
23+
}
24+
25+
fn main() {}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//@ ignore-compare-mode-next-solver
2+
//@ compile-flags: -Znext-solver
3+
//@ check-pass
4+
5+
// Regression test for trait-system-refactor-initiative#204, see
6+
// the sibling test for more details.
7+
8+
fn constrain<'a, F: FnOnce(&'a ())>(_: F) {}
9+
fn foo<'a>(_: &'a ()) -> impl Sized + use<'a> {
10+
constrain(foo);
11+
()
12+
}
13+
14+
fn main() {}

0 commit comments

Comments
 (0)