Skip to content

Commit edba9b2

Browse files
committed
check normalization overflow in monomorphization
1 parent 52618eb commit edba9b2

File tree

2 files changed

+36
-0
lines changed

2 files changed

+36
-0
lines changed

compiler/rustc_middle/src/query/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2709,6 +2709,11 @@ rustc_queries! {
27092709
cache_on_disk_if { true }
27102710
}
27112711

2712+
query has_normalization_error_in_mono(key: ty::Instance<'tcx>) -> bool {
2713+
desc { "checking whether {}'s body has post-analysis normalization error", key }
2714+
cache_on_disk_if { true }
2715+
}
2716+
27122717
query size_estimate(key: ty::Instance<'tcx>) -> usize {
27132718
desc { "estimating codegen size of `{}`", key }
27142719
cache_on_disk_if { true }

compiler/rustc_monomorphize/src/collector.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,23 @@ fn collect_items_rec<'tcx>(
473473
recursion_limit,
474474
));
475475

476+
// Plenty of code paths later assume that everything can be normalized.
477+
// Check normalization here to provide better diagnostics.
478+
// Normalization errors here are usually due to trait solving overflow.
479+
// FIXME: I assume that there are few type errors at post-analysis stage, but not
480+
// entirely sure.
481+
if tcx.has_normalization_error_in_mono(instance) {
482+
let def_id = instance.def_id();
483+
let def_span = tcx.def_span(def_id);
484+
let def_path_str = tcx.def_path_str(def_id);
485+
tcx.dcx().emit_fatal(RecursionLimit {
486+
span: starting_item.span,
487+
instance,
488+
def_span,
489+
def_path_str,
490+
});
491+
}
492+
476493
rustc_data_structures::stack::ensure_sufficient_stack(|| {
477494
let (used, mentioned) = tcx.items_of_instance((instance, mode));
478495
used_items.extend(used.into_iter().copied());
@@ -603,6 +620,19 @@ fn collect_items_rec<'tcx>(
603620
}
604621
}
605622

623+
// Check whether we can normalize the MIR body. Make it a query since decoding MIR from disk cache
624+
// may be expensive.
625+
fn has_normalization_error_in_mono<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> bool {
626+
let body = tcx.instance_mir(instance.def);
627+
instance
628+
.try_instantiate_mir_and_normalize_erasing_regions(
629+
tcx,
630+
ty::TypingEnv::fully_monomorphized(),
631+
ty::EarlyBinder::bind(body),
632+
)
633+
.is_err()
634+
}
635+
606636
fn check_recursion_limit<'tcx>(
607637
tcx: TyCtxt<'tcx>,
608638
instance: Instance<'tcx>,
@@ -1770,4 +1800,5 @@ pub(crate) fn collect_crate_mono_items<'tcx>(
17701800
pub(crate) fn provide(providers: &mut Providers) {
17711801
providers.hooks.should_codegen_locally = should_codegen_locally;
17721802
providers.items_of_instance = items_of_instance;
1803+
providers.has_normalization_error_in_mono = has_normalization_error_in_mono;
17731804
}

0 commit comments

Comments
 (0)