@@ -30,11 +30,12 @@ use rustc_middle::mir::visit::Visitor as _;
3030use rustc_middle:: mir:: {
3131 traversal, AnalysisPhase , Body , ClearCrossCrate , ConstQualifs , Constant , LocalDecl , MirPass ,
3232 MirPhase , Operand , Place , ProjectionElem , Promoted , RuntimePhase , Rvalue , SourceInfo ,
33- Statement , StatementKind , TerminatorKind ,
33+ Statement , StatementKind , TerminatorKind , START_BLOCK ,
3434} ;
3535use rustc_middle:: ty:: query:: Providers ;
3636use rustc_middle:: ty:: { self , TyCtxt , TypeVisitableExt } ;
3737use rustc_span:: sym;
38+ use rustc_trait_selection:: traits;
3839
3940#[ macro_use]
4041mod pass_manager;
@@ -389,6 +390,50 @@ fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> &
389390 body. tainted_by_errors = Some ( error_reported) ;
390391 }
391392
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+
392437 run_analysis_to_runtime_passes ( tcx, & mut body) ;
393438
394439 tcx. alloc_steal_mir ( body)
0 commit comments