Skip to content

Commit afd620f

Browse files
authored
Rollup merge of rust-lang#147152 - lcnr:instantiate-pre-sized-check, r=BoxyUwU
builtin `Fn`-trait impls: instantiate binder before the return type `Sized` check fixes - rust-lang/trait-system-refactor-initiative#220 - rust-lang/trait-system-refactor-initiative#204 r? `@BoxyUwU`
2 parents b310eb9 + 07806a1 commit afd620f

File tree

7 files changed

+134
-131
lines changed

7 files changed

+134
-131
lines changed

compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -664,7 +664,7 @@ fn coroutine_closure_to_ambiguous_coroutine<I: Interner>(
664664
pub(in crate::solve) fn extract_fn_def_from_const_callable<I: Interner>(
665665
cx: I,
666666
self_ty: I::Ty,
667-
) -> Result<(ty::Binder<I, (I::FnInputTys, I::Ty)>, I::FunctionId, I::GenericArgs), NoSolution> {
667+
) -> Result<(ty::Binder<I, (I::Ty, I::Ty)>, I::FunctionId, I::GenericArgs), NoSolution> {
668668
match self_ty.kind() {
669669
ty::FnDef(def_id, args) => {
670670
let sig = cx.fn_sig(def_id);
@@ -673,7 +673,8 @@ pub(in crate::solve) fn extract_fn_def_from_const_callable<I: Interner>(
673673
&& cx.fn_is_const(def_id)
674674
{
675675
Ok((
676-
sig.instantiate(cx, args).map_bound(|sig| (sig.inputs(), sig.output())),
676+
sig.instantiate(cx, args)
677+
.map_bound(|sig| (Ty::new_tup(cx, sig.inputs().as_slice()), sig.output())),
677678
def_id,
678679
args,
679680
))

compiler/rustc_next_trait_solver/src/solve/effect_goals.rs

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -234,12 +234,12 @@ where
234234
let self_ty = goal.predicate.self_ty();
235235
let (inputs_and_output, def_id, args) =
236236
structural_traits::extract_fn_def_from_const_callable(cx, self_ty)?;
237+
let (inputs, output) = ecx.instantiate_binder_with_infer(inputs_and_output);
237238

238239
// A built-in `Fn` impl only holds if the output is sized.
239240
// (FIXME: technically we only need to check this if the type is a fn ptr...)
240-
let output_is_sized_pred = inputs_and_output.map_bound(|(_, output)| {
241-
ty::TraitRef::new(cx, cx.require_trait_lang_item(SolverTraitLangItem::Sized), [output])
242-
});
241+
let output_is_sized_pred =
242+
ty::TraitRef::new(cx, cx.require_trait_lang_item(SolverTraitLangItem::Sized), [output]);
243243
let requirements = cx
244244
.const_conditions(def_id.into())
245245
.iter_instantiated(cx, args)
@@ -251,15 +251,12 @@ where
251251
})
252252
.chain([(GoalSource::ImplWhereBound, goal.with(cx, output_is_sized_pred))]);
253253

254-
let pred = inputs_and_output
255-
.map_bound(|(inputs, _)| {
256-
ty::TraitRef::new(
257-
cx,
258-
goal.predicate.def_id(),
259-
[goal.predicate.self_ty(), Ty::new_tup(cx, inputs.as_slice())],
260-
)
261-
})
262-
.to_host_effect_clause(cx, goal.predicate.constness);
254+
let pred = ty::Binder::dummy(ty::TraitRef::new(
255+
cx,
256+
goal.predicate.def_id(),
257+
[goal.predicate.self_ty(), inputs],
258+
))
259+
.to_host_effect_clause(cx, goal.predicate.constness);
263260

264261
Self::probe_and_consider_implied_clause(
265262
ecx,

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: 57 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -451,23 +451,22 @@ where
451451
return ecx.forced_ambiguity(MaybeCause::Ambiguity);
452452
}
453453
};
454+
let (inputs, output) = ecx.instantiate_binder_with_infer(tupled_inputs_and_output);
454455

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,
@@ -497,76 +496,56 @@ where
497496
goal_kind,
498497
env_region,
499498
)?;
499+
let AsyncCallableRelevantTypes {
500+
tupled_inputs_ty,
501+
output_coroutine_ty,
502+
coroutine_return_ty,
503+
} = ecx.instantiate_binder_with_infer(tupled_inputs_and_output_and_coroutine);
500504

501505
// A built-in `AsyncFn` impl only holds if the output is sized.
502506
// (FIXME: technically we only need to check this if the type is a fn ptr...)
503-
let output_is_sized_pred = tupled_inputs_and_output_and_coroutine.map_bound(
504-
|AsyncCallableRelevantTypes { output_coroutine_ty: output_ty, .. }| {
505-
ty::TraitRef::new(
506-
cx,
507-
cx.require_trait_lang_item(SolverTraitLangItem::Sized),
508-
[output_ty],
509-
)
510-
},
507+
let output_is_sized_pred = ty::TraitRef::new(
508+
cx,
509+
cx.require_trait_lang_item(SolverTraitLangItem::Sized),
510+
[output_coroutine_ty],
511511
);
512512

513-
let pred = tupled_inputs_and_output_and_coroutine
514-
.map_bound(
515-
|AsyncCallableRelevantTypes {
516-
tupled_inputs_ty,
517-
output_coroutine_ty,
518-
coroutine_return_ty,
519-
}| {
520-
let (projection_term, term) = if cx
521-
.is_lang_item(goal.predicate.def_id(), SolverLangItem::CallOnceFuture)
522-
{
523-
(
524-
ty::AliasTerm::new(
525-
cx,
526-
goal.predicate.def_id(),
527-
[goal.predicate.self_ty(), tupled_inputs_ty],
528-
),
529-
output_coroutine_ty.into(),
530-
)
531-
} else if cx
532-
.is_lang_item(goal.predicate.def_id(), SolverLangItem::CallRefFuture)
533-
{
534-
(
535-
ty::AliasTerm::new(
536-
cx,
537-
goal.predicate.def_id(),
538-
[
539-
I::GenericArg::from(goal.predicate.self_ty()),
540-
tupled_inputs_ty.into(),
541-
env_region.into(),
542-
],
543-
),
544-
output_coroutine_ty.into(),
545-
)
546-
} else if cx
547-
.is_lang_item(goal.predicate.def_id(), SolverLangItem::AsyncFnOnceOutput)
548-
{
549-
(
550-
ty::AliasTerm::new(
551-
cx,
552-
goal.predicate.def_id(),
553-
[
554-
I::GenericArg::from(goal.predicate.self_ty()),
555-
tupled_inputs_ty.into(),
556-
],
557-
),
558-
coroutine_return_ty.into(),
559-
)
560-
} else {
561-
panic!(
562-
"no such associated type in `AsyncFn*`: {:?}",
563-
goal.predicate.def_id()
564-
)
565-
};
566-
ty::ProjectionPredicate { projection_term, term }
567-
},
568-
)
569-
.upcast(cx);
513+
let (projection_term, term) =
514+
if cx.is_lang_item(goal.predicate.def_id(), SolverLangItem::CallOnceFuture) {
515+
(
516+
ty::AliasTerm::new(
517+
cx,
518+
goal.predicate.def_id(),
519+
[goal.predicate.self_ty(), tupled_inputs_ty],
520+
),
521+
output_coroutine_ty.into(),
522+
)
523+
} else if cx.is_lang_item(goal.predicate.def_id(), SolverLangItem::CallRefFuture) {
524+
(
525+
ty::AliasTerm::new(
526+
cx,
527+
goal.predicate.def_id(),
528+
[
529+
I::GenericArg::from(goal.predicate.self_ty()),
530+
tupled_inputs_ty.into(),
531+
env_region.into(),
532+
],
533+
),
534+
output_coroutine_ty.into(),
535+
)
536+
} else if cx.is_lang_item(goal.predicate.def_id(), SolverLangItem::AsyncFnOnceOutput) {
537+
(
538+
ty::AliasTerm::new(
539+
cx,
540+
goal.predicate.def_id(),
541+
[goal.predicate.self_ty(), tupled_inputs_ty],
542+
),
543+
coroutine_return_ty.into(),
544+
)
545+
} else {
546+
panic!("no such associated type in `AsyncFn*`: {:?}", goal.predicate.def_id())
547+
};
548+
let pred = ty::ProjectionPredicate { projection_term, term }.upcast(cx);
570549

571550
Self::probe_and_consider_implied_clause(
572551
ecx,

compiler/rustc_next_trait_solver/src/solve/trait_goals.rs

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -369,18 +369,16 @@ where
369369
return ecx.forced_ambiguity(MaybeCause::Ambiguity);
370370
}
371371
};
372+
let (inputs, output) = ecx.instantiate_binder_with_infer(tupled_inputs_and_output);
372373

373374
// A built-in `Fn` impl only holds if the output is sized.
374375
// (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-
});
376+
let output_is_sized_pred =
377+
ty::TraitRef::new(cx, cx.require_trait_lang_item(SolverTraitLangItem::Sized), [output]);
378378

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);
379+
let pred =
380+
ty::TraitRef::new(cx, goal.predicate.def_id(), [goal.predicate.self_ty(), inputs])
381+
.upcast(cx);
384382
Self::probe_and_consider_implied_clause(
385383
ecx,
386384
CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
@@ -408,28 +406,26 @@ where
408406
// This region doesn't matter because we're throwing away the coroutine type
409407
Region::new_static(cx),
410408
)?;
409+
let AsyncCallableRelevantTypes {
410+
tupled_inputs_ty,
411+
output_coroutine_ty,
412+
coroutine_return_ty: _,
413+
} = ecx.instantiate_binder_with_infer(tupled_inputs_and_output_and_coroutine);
411414

412415
// A built-in `AsyncFn` impl only holds if the output is sized.
413416
// (FIXME: technically we only need to check this if the type is a fn ptr...)
414-
let output_is_sized_pred = tupled_inputs_and_output_and_coroutine.map_bound(
415-
|AsyncCallableRelevantTypes { output_coroutine_ty, .. }| {
416-
ty::TraitRef::new(
417-
cx,
418-
cx.require_trait_lang_item(SolverTraitLangItem::Sized),
419-
[output_coroutine_ty],
420-
)
421-
},
417+
let output_is_sized_pred = ty::TraitRef::new(
418+
cx,
419+
cx.require_trait_lang_item(SolverTraitLangItem::Sized),
420+
[output_coroutine_ty],
422421
);
423422

424-
let pred = tupled_inputs_and_output_and_coroutine
425-
.map_bound(|AsyncCallableRelevantTypes { tupled_inputs_ty, .. }| {
426-
ty::TraitRef::new(
427-
cx,
428-
goal.predicate.def_id(),
429-
[goal.predicate.self_ty(), tupled_inputs_ty],
430-
)
431-
})
432-
.upcast(cx);
423+
let pred = ty::TraitRef::new(
424+
cx,
425+
goal.predicate.def_id(),
426+
[goal.predicate.self_ty(), tupled_inputs_ty],
427+
)
428+
.upcast(cx);
433429
Self::probe_and_consider_implied_clause(
434430
ecx,
435431
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)