Rollup merge of #109321 - compiler-errors:illegal-mono-w-regions, r=cjgillot
Erase impl regions when checking for impossible to eagerly monomorphize items We were inserting `ReErased` for method substs, but not for impl substs, leading to the call for `subst_and_check_impossible_predicates` being a bit weaker than it should be (since it ignores predicates that need substitution -- incl early-bound regions). Fixes #109297
This commit is contained in:
commit
64710790d6
2 changed files with 48 additions and 19 deletions
|
@ -1326,27 +1326,40 @@ fn create_mono_items_for_default_impls<'tcx>(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let Some(trait_ref) = tcx.impl_trait_ref(item.owner_id) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Lifetimes never affect trait selection, so we are allowed to eagerly
|
||||||
|
// instantiate an instance of an impl method if the impl (and method,
|
||||||
|
// which we check below) is only parameterized over lifetime. In that case,
|
||||||
|
// we use the ReErased, which has no lifetime information associated with
|
||||||
|
// it, to validate whether or not the impl is legal to instantiate at all.
|
||||||
|
let only_region_params = |param: &ty::GenericParamDef, _: &_| match param.kind {
|
||||||
|
GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
|
||||||
|
GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
|
||||||
|
unreachable!(
|
||||||
|
"`own_requires_monomorphization` check means that \
|
||||||
|
we should have no type/const params"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let impl_substs = InternalSubsts::for_item(tcx, item.owner_id.to_def_id(), only_region_params);
|
||||||
|
let trait_ref = trait_ref.subst(tcx, impl_substs);
|
||||||
|
|
||||||
// Unlike 'lazy' monomorphization that begins by collecting items transitively
|
// Unlike 'lazy' monomorphization that begins by collecting items transitively
|
||||||
// called by `main` or other global items, when eagerly monomorphizing impl
|
// called by `main` or other global items, when eagerly monomorphizing impl
|
||||||
// items, we never actually check that the predicates of this impl are satisfied
|
// items, we never actually check that the predicates of this impl are satisfied
|
||||||
// in a empty reveal-all param env (i.e. with no assumptions).
|
// in a empty reveal-all param env (i.e. with no assumptions).
|
||||||
//
|
//
|
||||||
// Even though this impl has no substitutions, because we don't consider higher-
|
// Even though this impl has no type or const substitutions, because we don't
|
||||||
// ranked predicates such as `for<'a> &'a mut [u8]: Copy` to be trivially false,
|
// consider higher-ranked predicates such as `for<'a> &'a mut [u8]: Copy` to
|
||||||
// we must now check that the impl has no impossible-to-satisfy predicates.
|
// be trivially false. We must now check that the impl has no impossible-to-satisfy
|
||||||
if tcx.subst_and_check_impossible_predicates((
|
// predicates.
|
||||||
item.owner_id.to_def_id(),
|
if tcx.subst_and_check_impossible_predicates((item.owner_id.to_def_id(), impl_substs)) {
|
||||||
&InternalSubsts::identity_for_item(tcx, item.owner_id.to_def_id()),
|
|
||||||
)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(trait_ref) = tcx.impl_trait_ref(item.owner_id) else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
let trait_ref = trait_ref.subst_identity();
|
|
||||||
|
|
||||||
let param_env = ty::ParamEnv::reveal_all();
|
let param_env = ty::ParamEnv::reveal_all();
|
||||||
let trait_ref = tcx.normalize_erasing_regions(param_env, trait_ref);
|
let trait_ref = tcx.normalize_erasing_regions(param_env, trait_ref);
|
||||||
let overridden_methods = tcx.impl_item_implementor_ids(item.owner_id);
|
let overridden_methods = tcx.impl_item_implementor_ids(item.owner_id);
|
||||||
|
@ -1359,12 +1372,9 @@ fn create_mono_items_for_default_impls<'tcx>(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let substs = InternalSubsts::for_item(tcx, method.def_id, |param, _| match param.kind {
|
// As mentioned above, the method is legal to eagerly instantiate if it
|
||||||
GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
|
// only has lifetime substitutions. This is validated by
|
||||||
GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
|
let substs = trait_ref.substs.extend_to(tcx, method.def_id, only_region_params);
|
||||||
trait_ref.substs[param.index as usize]
|
|
||||||
}
|
|
||||||
});
|
|
||||||
let instance = ty::Instance::expect_resolve(tcx, param_env, method.def_id, substs);
|
let instance = ty::Instance::expect_resolve(tcx, param_env, method.def_id, substs);
|
||||||
|
|
||||||
let mono_item = create_fn_mono_item(tcx, instance, DUMMY_SP);
|
let mono_item = create_fn_mono_item(tcx, instance, DUMMY_SP);
|
||||||
|
|
19
tests/ui/codegen/mono-impossible-2.rs
Normal file
19
tests/ui/codegen/mono-impossible-2.rs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
//compile-flags: --crate-type=lib -Clink-dead-code=on
|
||||||
|
// build-pass
|
||||||
|
|
||||||
|
// Make sure that we don't monomorphize the impossible method `<() as Visit>::visit`,
|
||||||
|
// which does not hold under a reveal-all param env.
|
||||||
|
|
||||||
|
pub trait Visit {
|
||||||
|
fn visit() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Array {
|
||||||
|
type Element;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Visit for () where (): Array<Element = &'a ()> {}
|
||||||
|
|
||||||
|
impl Array for () {
|
||||||
|
type Element = ();
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue