Skip to content

Commit e3b0a72

Browse files
Erase impl regions when checking for impossible to eagerly monomorphize items
1 parent 5bf139e commit e3b0a72

File tree

2 files changed

+48
-19
lines changed

2 files changed

+48
-19
lines changed

Diff for: compiler/rustc_monomorphize/src/collector.rs

+29-19
Original file line numberDiff line numberDiff line change
@@ -1326,27 +1326,40 @@ fn create_mono_items_for_default_impls<'tcx>(
13261326
return;
13271327
}
13281328

1329+
let Some(trait_ref) = tcx.impl_trait_ref(item.owner_id) else {
1330+
return;
1331+
};
1332+
1333+
// Lifetimes never affect trait selection, so we are allowed to eagerly
1334+
// instantiate an instance of an impl method if the impl (and method,
1335+
// which we check below) is only parameterized over lifetime. In that case,
1336+
// we use the ReErased, which has no lifetime information associated with
1337+
// it, to validate whether or not the impl is legal to instantiate at all.
1338+
let only_region_params = |param: &ty::GenericParamDef, _: &_| match param.kind {
1339+
GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
1340+
GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
1341+
unreachable!(
1342+
"`own_requires_monomorphization` check means that \
1343+
we should have no type/const params"
1344+
)
1345+
}
1346+
};
1347+
let impl_substs = InternalSubsts::for_item(tcx, item.owner_id.to_def_id(), only_region_params);
1348+
let trait_ref = trait_ref.subst(tcx, impl_substs);
1349+
13291350
// Unlike 'lazy' monomorphization that begins by collecting items transitively
13301351
// called by `main` or other global items, when eagerly monomorphizing impl
13311352
// items, we never actually check that the predicates of this impl are satisfied
13321353
// in a empty reveal-all param env (i.e. with no assumptions).
13331354
//
1334-
// Even though this impl has no substitutions, because we don't consider higher-
1335-
// ranked predicates such as `for<'a> &'a mut [u8]: Copy` to be trivially false,
1336-
// we must now check that the impl has no impossible-to-satisfy predicates.
1337-
if tcx.subst_and_check_impossible_predicates((
1338-
item.owner_id.to_def_id(),
1339-
&InternalSubsts::identity_for_item(tcx, item.owner_id.to_def_id()),
1340-
)) {
1355+
// Even though this impl has no type or const substitutions, because we don't
1356+
// consider higher-ranked predicates such as `for<'a> &'a mut [u8]: Copy` to
1357+
// be trivially false. We must now check that the impl has no impossible-to-satisfy
1358+
// predicates.
1359+
if tcx.subst_and_check_impossible_predicates((item.owner_id.to_def_id(), impl_substs)) {
13411360
return;
13421361
}
13431362

1344-
let Some(trait_ref) = tcx.impl_trait_ref(item.owner_id) else {
1345-
return;
1346-
};
1347-
1348-
let trait_ref = trait_ref.subst_identity();
1349-
13501363
let param_env = ty::ParamEnv::reveal_all();
13511364
let trait_ref = tcx.normalize_erasing_regions(param_env, trait_ref);
13521365
let overridden_methods = tcx.impl_item_implementor_ids(item.owner_id);
@@ -1359,12 +1372,9 @@ fn create_mono_items_for_default_impls<'tcx>(
13591372
continue;
13601373
}
13611374

1362-
let substs = InternalSubsts::for_item(tcx, method.def_id, |param, _| match param.kind {
1363-
GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
1364-
GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
1365-
trait_ref.substs[param.index as usize]
1366-
}
1367-
});
1375+
// As mentioned above, the method is legal to eagerly instantiate if it
1376+
// only has lifetime substitutions. This is validated by
1377+
let substs = trait_ref.substs.extend_to(tcx, method.def_id, only_region_params);
13681378
let instance = ty::Instance::expect_resolve(tcx, param_env, method.def_id, substs);
13691379

13701380
let mono_item = create_fn_mono_item(tcx, instance, DUMMY_SP);

Diff for: tests/ui/codegen/mono-impossible-2.rs

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//compile-flags: --crate-type=lib -Clink-dead-code=on
2+
// build-pass
3+
4+
// Make sure that we don't monomorphize the impossible method `<() as Visit>::visit`,
5+
// which does not hold under a reveal-all param env.
6+
7+
pub trait Visit {
8+
fn visit() {}
9+
}
10+
11+
pub trait Array {
12+
type Element;
13+
}
14+
15+
impl<'a> Visit for () where (): Array<Element = &'a ()> {}
16+
17+
impl Array for () {
18+
type Element = ();
19+
}

0 commit comments

Comments
 (0)