fn pointers don't implement Fn/FnMut/FnOnce traits if its return type is unsized

This commit is contained in:
Michael Goulet 2022-08-03 03:30:17 +00:00
parent 98e1f041b6
commit 3b573c9b98
5 changed files with 96 additions and 2 deletions

View file

@ -617,7 +617,36 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
)
.map_bound(|(trait_ref, _)| trait_ref);
let nested = self.confirm_poly_trait_refs(obligation, trait_ref)?;
let mut nested = self.confirm_poly_trait_refs(obligation, trait_ref)?;
// Confirm the `type Output: Sized;` bound that is present on `FnOnce`
let cause = obligation.derived_cause(BuiltinDerivedObligation);
// The binder on the Fn obligation is "less" important than the one on
// the signature, as evidenced by how we treat it during projection.
// The safe thing to do here is to liberate it, though, which should
// have no worse effect than skipping the binder here.
let liberated_fn_ty = self.infcx.replace_bound_vars_with_placeholders(obligation.self_ty());
let output_ty = self
.infcx
.replace_bound_vars_with_placeholders(liberated_fn_ty.fn_sig(self.tcx()).output());
let output_ty = normalize_with_depth_to(
self,
obligation.param_env,
cause.clone(),
obligation.recursion_depth,
output_ty,
&mut nested,
);
let tr = ty::Binder::dummy(ty::TraitRef::new(
self.tcx().require_lang_item(LangItem::Sized, None),
self.tcx().mk_substs_trait(output_ty, &[]),
));
nested.push(Obligation::new(
cause,
obligation.param_env,
tr.to_poly_trait_predicate().to_predicate(self.tcx()),
));
Ok(ImplSourceFnPointerData { fn_ty: self_ty, nested })
}