@@ -38,6 +38,7 @@ use rustc_middle::mir::{
3838 SourceInfo , Statement , StatementKind , TerminatorKind , START_BLOCK ,
3939} ;
4040use rustc_middle:: query:: Providers ;
41+ use rustc_middle:: traits:: util:: HasImpossiblePredicates ;
4142use rustc_middle:: ty:: { self , TyCtxt , TypeVisitableExt } ;
4243use rustc_span:: { source_map:: Spanned , sym, DUMMY_SP } ;
4344use rustc_trait_selection:: traits;
@@ -137,6 +138,8 @@ pub fn provide(providers: &mut Providers) {
137138 is_ctfe_mir_available : |tcx, did| is_mir_available ( tcx, did) ,
138139 mir_callgraph_reachable : inline:: cycle:: mir_callgraph_reachable,
139140 mir_inliner_callees : inline:: cycle:: mir_inliner_callees,
141+ const_prop_lint,
142+ const_prop_lint_promoteds,
140143 promoted_mir,
141144 deduced_param_attrs : deduce_param_attrs:: deduced_param_attrs,
142145 ..* providers
@@ -393,6 +396,39 @@ fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: LocalDefId) -> Body<'_> {
393396 body
394397}
395398
399+ fn const_prop_lint ( tcx : TyCtxt < ' _ > , def : LocalDefId ) -> Result < ( ) , HasImpossiblePredicates > {
400+ let ( body, _) = tcx. mir_promoted ( def) ;
401+ let body = body. borrow ( ) ;
402+
403+ let mir_borrowck = tcx. mir_borrowck ( def) ;
404+
405+ check_impossible_predicates ( tcx, def) ?;
406+ if mir_borrowck. tainted_by_errors . is_none ( ) && body. tainted_by_errors . is_none ( ) {
407+ const_prop_lint:: ConstPropLint . run_lint ( tcx, & body) ;
408+ }
409+ Ok ( ( ) )
410+ }
411+
412+ fn const_prop_lint_promoteds (
413+ tcx : TyCtxt < ' _ > ,
414+ def : LocalDefId ,
415+ ) -> Result < ( ) , HasImpossiblePredicates > {
416+ let ( _, promoteds) = tcx. mir_promoted ( def) ;
417+ let promoteds = promoteds. borrow ( ) ;
418+
419+ let mir_borrowck = tcx. mir_borrowck ( def) ;
420+
421+ check_impossible_predicates ( tcx, def) ?;
422+ if mir_borrowck. tainted_by_errors . is_none ( ) {
423+ for body in & * promoteds {
424+ if body. tainted_by_errors . is_none ( ) {
425+ const_prop_lint:: ConstPropLint . run_lint ( tcx, & body) ;
426+ }
427+ }
428+ }
429+ Ok ( ( ) )
430+ }
431+
396432/// Obtain just the main MIR (no promoteds) and run some cleanups on it. This also runs
397433/// mir borrowck *before* doing so in order to ensure that borrowck can be run and doesn't
398434/// end up missing the source MIR due to stealing happening.
@@ -401,6 +437,7 @@ fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> &
401437 tcx. ensure_with_value ( ) . mir_coroutine_witnesses ( def) ;
402438 }
403439 let mir_borrowck = tcx. mir_borrowck ( def) ;
440+ let impossible_predicates = tcx. const_prop_lint ( def) ;
404441
405442 let is_fn_like = tcx. def_kind ( def) . is_fn_like ( ) ;
406443 if is_fn_like {
@@ -415,7 +452,30 @@ fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> &
415452 if let Some ( error_reported) = mir_borrowck. tainted_by_errors {
416453 body. tainted_by_errors = Some ( error_reported) ;
417454 }
455+ if impossible_predicates. is_err ( ) {
456+ trace ! ( "found unsatisfiable predicates for {:?}" , body. source) ;
457+ // Clear the body to only contain a single `unreachable` statement.
458+ let bbs = body. basic_blocks . as_mut ( ) ;
459+ bbs. raw . truncate ( 1 ) ;
460+ bbs[ START_BLOCK ] . statements . clear ( ) ;
461+ bbs[ START_BLOCK ] . terminator_mut ( ) . kind = TerminatorKind :: Unreachable ;
462+ body. var_debug_info . clear ( ) ;
463+ body. local_decls . raw . truncate ( body. arg_count + 1 ) ;
464+ }
418465
466+ run_analysis_to_runtime_passes ( tcx, & mut body) ;
467+
468+ // Now that drop elaboration has been performed, we can check for
469+ // unconditional drop recursion.
470+ rustc_mir_build:: lints:: check_drop_recursion ( tcx, & body) ;
471+
472+ tcx. alloc_steal_mir ( body)
473+ }
474+
475+ fn check_impossible_predicates (
476+ tcx : TyCtxt < ' _ > ,
477+ def : LocalDefId ,
478+ ) -> Result < ( ) , HasImpossiblePredicates > {
419479 // Check if it's even possible to satisfy the 'where' clauses
420480 // for this item.
421481 //
@@ -445,28 +505,15 @@ fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> &
445505 // the normalization code (leading to cycle errors), since
446506 // it's usually never invoked in this way.
447507 let predicates = tcx
448- . predicates_of ( body . source . def_id ( ) )
508+ . predicates_of ( def )
449509 . predicates
450510 . iter ( )
451511 . filter_map ( |( p, _) | if p. is_global ( ) { Some ( * p) } else { None } ) ;
452512 if traits:: impossible_predicates ( tcx, traits:: elaborate ( tcx, predicates) . collect ( ) ) {
453- trace ! ( "found unsatisfiable predicates for {:?}" , body. source) ;
454- // Clear the body to only contain a single `unreachable` statement.
455- let bbs = body. basic_blocks . as_mut ( ) ;
456- bbs. raw . truncate ( 1 ) ;
457- bbs[ START_BLOCK ] . statements . clear ( ) ;
458- bbs[ START_BLOCK ] . terminator_mut ( ) . kind = TerminatorKind :: Unreachable ;
459- body. var_debug_info . clear ( ) ;
460- body. local_decls . raw . truncate ( body. arg_count + 1 ) ;
513+ Err ( HasImpossiblePredicates )
514+ } else {
515+ Ok ( ( ) )
461516 }
462-
463- run_analysis_to_runtime_passes ( tcx, & mut body) ;
464-
465- // Now that drop elaboration has been performed, we can check for
466- // unconditional drop recursion.
467- rustc_mir_build:: lints:: check_drop_recursion ( tcx, & body) ;
468-
469- tcx. alloc_steal_mir ( body)
470517}
471518
472519// Made public such that `mir_drops_elaborated_and_const_checked` can be overridden
@@ -533,7 +580,6 @@ fn run_runtime_lowering_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
533580 & elaborate_box_derefs:: ElaborateBoxDerefs ,
534581 & coroutine:: StateTransform ,
535582 & add_retag:: AddRetag ,
536- & Lint ( const_prop_lint:: ConstPropLint ) ,
537583 ] ;
538584 pm:: run_passes_no_validate ( tcx, body, passes, Some ( MirPhase :: Runtime ( RuntimePhase :: Initial ) ) ) ;
539585}
@@ -678,6 +724,7 @@ fn promoted_mir(tcx: TyCtxt<'_>, def: LocalDefId) -> &IndexVec<Promoted, Body<'_
678724 }
679725
680726 tcx. ensure_with_value ( ) . mir_borrowck ( def) ;
727+ tcx. ensure ( ) . const_prop_lint_promoteds ( def) ;
681728 let mut promoted = tcx. mir_promoted ( def) . 1 . steal ( ) ;
682729
683730 for body in & mut promoted {
0 commit comments