Recover when failing to normalize closure signature.

This commit is contained in:
Camille GILLOT 2022-02-04 23:18:28 +01:00
parent 2e45cd4b69
commit 0161ecd13f
7 changed files with 34 additions and 9 deletions

View File

@ -686,6 +686,7 @@ fn codegen_stmt<'tcx>(
substs, substs,
ty::ClosureKind::FnOnce, ty::ClosureKind::FnOnce,
) )
.expect("failed to normalize and resolve closure during codegen")
.polymorphize(fx.tcx); .polymorphize(fx.tcx);
let func_ref = fx.get_function_ref(instance); let func_ref = fx.get_function_ref(instance);
let func_addr = fx.bcx.ins().func_addr(fx.pointer_type, func_ref); let func_addr = fx.bcx.ins().func_addr(fx.pointer_type, func_ref);

View File

@ -213,6 +213,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
substs, substs,
ty::ClosureKind::FnOnce, ty::ClosureKind::FnOnce,
) )
.expect("failed to normalize and resolve closure during codegen")
.polymorphize(bx.cx().tcx()); .polymorphize(bx.cx().tcx());
OperandValue::Immediate(bx.cx().get_fn_addr(instance)) OperandValue::Immediate(bx.cx().get_fn_addr(instance))
} }

View File

@ -100,7 +100,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
def_id, def_id,
substs, substs,
ty::ClosureKind::FnOnce, ty::ClosureKind::FnOnce,
); )
.ok_or_else(|| err_inval!(TooGeneric))?;
let fn_ptr = self.create_fn_alloc_ptr(FnVal::Instance(instance)); let fn_ptr = self.create_fn_alloc_ptr(FnVal::Instance(instance));
self.write_pointer(fn_ptr, dest)?; self.write_pointer(fn_ptr, dest)?;
} }

View File

@ -496,12 +496,12 @@ impl<'tcx> Instance<'tcx> {
def_id: DefId, def_id: DefId,
substs: ty::SubstsRef<'tcx>, substs: ty::SubstsRef<'tcx>,
requested_kind: ty::ClosureKind, requested_kind: ty::ClosureKind,
) -> Instance<'tcx> { ) -> Option<Instance<'tcx>> {
let actual_kind = substs.as_closure().kind(); let actual_kind = substs.as_closure().kind();
match needs_fn_once_adapter_shim(actual_kind, requested_kind) { match needs_fn_once_adapter_shim(actual_kind, requested_kind) {
Ok(true) => Instance::fn_once_adapter_instance(tcx, def_id, substs), Ok(true) => Instance::fn_once_adapter_instance(tcx, def_id, substs),
_ => Instance::new(def_id, substs), _ => Some(Instance::new(def_id, substs)),
} }
} }
@ -515,7 +515,7 @@ impl<'tcx> Instance<'tcx> {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
closure_did: DefId, closure_did: DefId,
substs: ty::SubstsRef<'tcx>, substs: ty::SubstsRef<'tcx>,
) -> Instance<'tcx> { ) -> Option<Instance<'tcx>> {
debug!("fn_once_adapter_shim({:?}, {:?})", closure_did, substs); debug!("fn_once_adapter_shim({:?}, {:?})", closure_did, substs);
let fn_once = tcx.require_lang_item(LangItem::FnOnce, None); let fn_once = tcx.require_lang_item(LangItem::FnOnce, None);
let call_once = tcx let call_once = tcx
@ -531,12 +531,13 @@ impl<'tcx> Instance<'tcx> {
let self_ty = tcx.mk_closure(closure_did, substs); let self_ty = tcx.mk_closure(closure_did, substs);
let sig = substs.as_closure().sig(); let sig = substs.as_closure().sig();
let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), sig); let sig =
tcx.try_normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), sig).ok()?;
assert_eq!(sig.inputs().len(), 1); assert_eq!(sig.inputs().len(), 1);
let substs = tcx.mk_substs_trait(self_ty, &[sig.inputs()[0].into()]); let substs = tcx.mk_substs_trait(self_ty, &[sig.inputs()[0].into()]);
debug!("fn_once_adapter_shim: self_ty={:?} sig={:?}", self_ty, sig); debug!("fn_once_adapter_shim: self_ty={:?} sig={:?}", self_ty, sig);
Instance { def, substs } Some(Instance { def, substs })
} }
/// Depending on the kind of `InstanceDef`, the MIR body associated with an /// Depending on the kind of `InstanceDef`, the MIR body associated with an

View File

@ -112,6 +112,26 @@ impl<'tcx> TyCtxt<'tcx> {
self.normalize_erasing_regions(param_env, value) self.normalize_erasing_regions(param_env, value)
} }
/// If you have a `Binder<'tcx, T>`, you can do this to strip out the
/// late-bound regions and then normalize the result, yielding up
/// a `T` (with regions erased). This is appropriate when the
/// binder is being instantiated at the call site.
///
/// N.B., currently, higher-ranked type bounds inhibit
/// normalization. Therefore, each time we erase them in
/// codegen, we need to normalize the contents.
pub fn try_normalize_erasing_late_bound_regions<T>(
self,
param_env: ty::ParamEnv<'tcx>,
value: ty::Binder<'tcx, T>,
) -> Result<T, NormalizationError<'tcx>>
where
T: TypeFoldable<'tcx>,
{
let value = self.erase_late_bound_regions(value);
self.try_normalize_erasing_regions(param_env, value)
}
/// Monomorphizes a type from the AST by first applying the /// Monomorphizes a type from the AST by first applying the
/// in-scope substitutions and then normalizing any associated /// in-scope substitutions and then normalizing any associated
/// types. /// types.

View File

@ -730,7 +730,8 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
def_id, def_id,
substs, substs,
ty::ClosureKind::FnOnce, ty::ClosureKind::FnOnce,
); )
.expect("failed to normalize and resolve closure during codegen");
if should_codegen_locally(self.tcx, &instance) { if should_codegen_locally(self.tcx, &instance) {
self.output.push(create_fn_mono_item(self.tcx, instance, span)); self.output.push(create_fn_mono_item(self.tcx, instance, span));
} }

View File

@ -332,12 +332,12 @@ fn resolve_associated_item<'tcx>(
}), }),
traits::ImplSource::Closure(closure_data) => { traits::ImplSource::Closure(closure_data) => {
let trait_closure_kind = tcx.fn_trait_kind_from_lang_item(trait_id).unwrap(); let trait_closure_kind = tcx.fn_trait_kind_from_lang_item(trait_id).unwrap();
Some(Instance::resolve_closure( Instance::resolve_closure(
tcx, tcx,
closure_data.closure_def_id, closure_data.closure_def_id,
closure_data.substs, closure_data.substs,
trait_closure_kind, trait_closure_kind,
)) )
} }
traits::ImplSource::FnPointer(ref data) => match data.fn_ty.kind() { traits::ImplSource::FnPointer(ref data) => match data.fn_ty.kind() {
ty::FnDef(..) | ty::FnPtr(..) => Some(Instance { ty::FnDef(..) | ty::FnPtr(..) => Some(Instance {