Skip to content

Commit 0ee32fb

Browse files
committed
Move unstatisfaction check earlier.
1 parent 0f85779 commit 0ee32fb

File tree

1 file changed

+44
-50
lines changed
  • compiler/rustc_mir_transform/src

1 file changed

+44
-50
lines changed

compiler/rustc_mir_transform/src/lib.rs

+44-50
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,50 @@ fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> &
390390
body.tainted_by_errors = Some(error_reported);
391391
}
392392

393+
// Check if it's even possible to satisfy the 'where' clauses
394+
// for this item.
395+
//
396+
// This branch will never be taken for any normal function.
397+
// However, it's possible to `#!feature(trivial_bounds)]` to write
398+
// a function with impossible to satisfy clauses, e.g.:
399+
// `fn foo() where String: Copy {}`
400+
//
401+
// We don't usually need to worry about this kind of case,
402+
// since we would get a compilation error if the user tried
403+
// to call it. However, since we optimize even without any
404+
// calls to the function, we need to make sure that it even
405+
// makes sense to try to evaluate the body.
406+
//
407+
// If there are unsatisfiable where clauses, then all bets are
408+
// off, and we just give up.
409+
//
410+
// We manually filter the predicates, skipping anything that's not
411+
// "global". We are in a potentially generic context
412+
// (e.g. we are evaluating a function without substituting generic
413+
// parameters, so this filtering serves two purposes:
414+
//
415+
// 1. We skip evaluating any predicates that we would
416+
// never be able prove are unsatisfiable (e.g. `<T as Foo>`
417+
// 2. We avoid trying to normalize predicates involving generic
418+
// parameters (e.g. `<T as Foo>::MyItem`). This can confuse
419+
// the normalization code (leading to cycle errors), since
420+
// it's usually never invoked in this way.
421+
let predicates = tcx
422+
.predicates_of(body.source.def_id())
423+
.predicates
424+
.iter()
425+
.filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None });
426+
if traits::impossible_predicates(tcx, traits::elaborate(tcx, predicates).collect()) {
427+
trace!("found unsatisfiable predicates for {:?}", body.source);
428+
// Clear the body to only contain a single `unreachable` statement.
429+
let bbs = body.basic_blocks.as_mut();
430+
bbs.raw.truncate(1);
431+
bbs[START_BLOCK].statements.clear();
432+
bbs[START_BLOCK].terminator_mut().kind = TerminatorKind::Unreachable;
433+
body.var_debug_info.clear();
434+
body.local_decls.raw.truncate(body.arg_count + 1);
435+
}
436+
393437
run_analysis_to_runtime_passes(tcx, &mut body);
394438

395439
tcx.alloc_steal_mir(body)
@@ -482,56 +526,6 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
482526
WithMinOptLevel(1, x)
483527
}
484528

485-
// Check if it's even possible to satisfy the 'where' clauses
486-
// for this item.
487-
// This branch will never be taken for any normal function.
488-
// However, it's possible to `#!feature(trivial_bounds)]` to write
489-
// a function with impossible to satisfy clauses, e.g.:
490-
// `fn foo() where String: Copy {}`
491-
//
492-
// We don't usually need to worry about this kind of case,
493-
// since we would get a compilation error if the user tried
494-
// to call it. However, since we optimize even without any
495-
// calls to the function, we need to make sure that it even
496-
// makes sense to try to evaluate the body.
497-
//
498-
// If there are unsatisfiable where clauses, then all bets are
499-
// off, and we just give up.
500-
//
501-
// We manually filter the predicates, skipping anything that's not
502-
// "global". We are in a potentially generic context
503-
// (e.g. we are evaluating a function without substituting generic
504-
// parameters, so this filtering serves two purposes:
505-
//
506-
// 1. We skip evaluating any predicates that we would
507-
// never be able prove are unsatisfiable (e.g. `<T as Foo>`
508-
// 2. We avoid trying to normalize predicates involving generic
509-
// parameters (e.g. `<T as Foo>::MyItem`). This can confuse
510-
// the normalization code (leading to cycle errors), since
511-
// it's usually never invoked in this way.
512-
let predicates = tcx
513-
.predicates_of(body.source.def_id())
514-
.predicates
515-
.iter()
516-
.filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None });
517-
if traits::impossible_predicates(tcx, traits::elaborate(tcx, predicates).collect()) {
518-
trace!("optimizations skipped for {:?}: found unsatisfiable predicates", body.source);
519-
// Clear the body to only contain a single `unreachable` statement.
520-
let bbs = body.basic_blocks.as_mut();
521-
bbs.raw.truncate(1);
522-
bbs[START_BLOCK].statements.clear();
523-
bbs[START_BLOCK].terminator_mut().kind = TerminatorKind::Unreachable;
524-
body.var_debug_info.clear();
525-
body.local_decls.raw.truncate(body.arg_count + 1);
526-
pm::run_passes(
527-
tcx,
528-
body,
529-
&[&reveal_all::RevealAll, &dump_mir::Marker("PreCodegen")],
530-
Some(MirPhase::Runtime(RuntimePhase::Optimized)),
531-
);
532-
return;
533-
}
534-
535529
// The main optimizations that we do on MIR.
536530
pm::run_passes(
537531
tcx,

0 commit comments

Comments
 (0)