Skip to content

Commit 34f1de8

Browse files
authored
Rollup merge of #104841 - compiler-errors:fishy-bound-var, r=jackh726
Assert that we don't capture escaping bound vars in `Fn` trait selection Fixes #104825
2 parents f00c3f0 + d945967 commit 34f1de8

File tree

3 files changed

+25
-24
lines changed

3 files changed

+25
-24
lines changed

compiler/rustc_trait_selection/src/traits/select/confirmation.rs

+13-16
Original file line numberDiff line numberDiff line change
@@ -605,8 +605,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
605605
{
606606
debug!(?obligation, "confirm_fn_pointer_candidate");
607607

608-
// Okay to skip binder; it is reintroduced below.
609-
let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
608+
let self_ty = self
609+
.infcx
610+
.shallow_resolve(obligation.self_ty().no_bound_vars())
611+
.expect("fn pointer should not capture bound vars from predicate");
610612
let sig = self_ty.fn_sig(self.tcx());
611613
let trait_ref = closure_trait_ref_and_return_type(
612614
self.tcx(),
@@ -621,15 +623,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
621623

622624
// Confirm the `type Output: Sized;` bound that is present on `FnOnce`
623625
let cause = obligation.derived_cause(BuiltinDerivedObligation);
624-
// The binder on the Fn obligation is "less" important than the one on
625-
// the signature, as evidenced by how we treat it during projection.
626-
// The safe thing to do here is to liberate it, though, which should
627-
// have no worse effect than skipping the binder here.
628-
let liberated_fn_ty =
629-
self.infcx.replace_bound_vars_with_placeholders(obligation.predicate.rebind(self_ty));
630-
let output_ty = self
631-
.infcx
632-
.replace_bound_vars_with_placeholders(liberated_fn_ty.fn_sig(self.tcx()).output());
626+
let output_ty = self.infcx.replace_bound_vars_with_placeholders(sig.output());
633627
let output_ty = normalize_with_depth_to(
634628
self,
635629
obligation.param_env,
@@ -693,16 +687,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
693687

694688
let gen_sig = substs.as_generator().poly_sig();
695689

696-
// (1) Feels icky to skip the binder here, but OTOH we know
697-
// that the self-type is an generator type and hence is
690+
// NOTE: The self-type is a generator type and hence is
698691
// in fact unparameterized (or at least does not reference any
699-
// regions bound in the obligation). Still probably some
700-
// refactoring could make this nicer.
692+
// regions bound in the obligation).
693+
let self_ty = obligation
694+
.predicate
695+
.self_ty()
696+
.no_bound_vars()
697+
.expect("unboxed closure type should not capture bound vars from the predicate");
701698

702699
let trait_ref = super::util::generator_trait_ref_and_outputs(
703700
self.tcx(),
704701
obligation.predicate.def_id(),
705-
obligation.predicate.skip_binder().self_ty(), // (1)
702+
self_ty,
706703
gen_sig,
707704
)
708705
.map_bound(|(trait_ref, ..)| trait_ref);

compiler/rustc_trait_selection/src/traits/select/mod.rs

+9-5
Original file line numberDiff line numberDiff line change
@@ -2271,15 +2271,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
22712271

22722272
debug!(?closure_sig);
22732273

2274-
// (1) Feels icky to skip the binder here, but OTOH we know
2275-
// that the self-type is an unboxed closure type and hence is
2274+
// NOTE: The self-type is an unboxed closure type and hence is
22762275
// in fact unparameterized (or at least does not reference any
2277-
// regions bound in the obligation). Still probably some
2278-
// refactoring could make this nicer.
2276+
// regions bound in the obligation).
2277+
let self_ty = obligation
2278+
.predicate
2279+
.self_ty()
2280+
.no_bound_vars()
2281+
.expect("unboxed closure type should not capture bound vars from the predicate");
2282+
22792283
closure_trait_ref_and_return_type(
22802284
self.tcx(),
22812285
obligation.predicate.def_id(),
2282-
obligation.predicate.skip_binder().self_ty(), // (1)
2286+
self_ty,
22832287
closure_sig,
22842288
util::TupleArgumentsFlag::No,
22852289
)

compiler/rustc_trait_selection/src/traits/util.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -298,11 +298,11 @@ pub fn closure_trait_ref_and_return_type<'tcx>(
298298
sig: ty::PolyFnSig<'tcx>,
299299
tuple_arguments: TupleArgumentsFlag,
300300
) -> ty::Binder<'tcx, (ty::TraitRef<'tcx>, Ty<'tcx>)> {
301+
assert!(!self_ty.has_escaping_bound_vars());
301302
let arguments_tuple = match tuple_arguments {
302303
TupleArgumentsFlag::No => sig.skip_binder().inputs()[0],
303304
TupleArgumentsFlag::Yes => tcx.intern_tup(sig.skip_binder().inputs()),
304305
};
305-
debug_assert!(!self_ty.has_escaping_bound_vars());
306306
let trait_ref = tcx.mk_trait_ref(fn_trait_def_id, [self_ty, arguments_tuple]);
307307
sig.map_bound(|sig| (trait_ref, sig.output()))
308308
}
@@ -313,7 +313,7 @@ pub fn generator_trait_ref_and_outputs<'tcx>(
313313
self_ty: Ty<'tcx>,
314314
sig: ty::PolyGenSig<'tcx>,
315315
) -> ty::Binder<'tcx, (ty::TraitRef<'tcx>, Ty<'tcx>, Ty<'tcx>)> {
316-
debug_assert!(!self_ty.has_escaping_bound_vars());
316+
assert!(!self_ty.has_escaping_bound_vars());
317317
let trait_ref = tcx.mk_trait_ref(fn_trait_def_id, [self_ty, sig.skip_binder().resume_ty]);
318318
sig.map_bound(|sig| (trait_ref, sig.yield_ty, sig.return_ty))
319319
}
@@ -324,7 +324,7 @@ pub fn future_trait_ref_and_outputs<'tcx>(
324324
self_ty: Ty<'tcx>,
325325
sig: ty::PolyGenSig<'tcx>,
326326
) -> ty::Binder<'tcx, (ty::TraitRef<'tcx>, Ty<'tcx>)> {
327-
debug_assert!(!self_ty.has_escaping_bound_vars());
327+
assert!(!self_ty.has_escaping_bound_vars());
328328
let trait_ref = tcx.mk_trait_ref(fn_trait_def_id, [self_ty]);
329329
sig.map_bound(|sig| (trait_ref, sig.return_ty))
330330
}

0 commit comments

Comments
 (0)