@@ -30,11 +30,12 @@ use rustc_middle::mir::visit::Visitor as _;
30
30
use rustc_middle:: mir:: {
31
31
traversal, AnalysisPhase , Body , ClearCrossCrate , ConstQualifs , Constant , LocalDecl , MirPass ,
32
32
MirPhase , Operand , Place , ProjectionElem , Promoted , RuntimePhase , Rvalue , SourceInfo ,
33
- Statement , StatementKind , TerminatorKind ,
33
+ Statement , StatementKind , TerminatorKind , START_BLOCK ,
34
34
} ;
35
35
use rustc_middle:: ty:: query:: Providers ;
36
36
use rustc_middle:: ty:: { self , TyCtxt , TypeVisitableExt } ;
37
37
use rustc_span:: sym;
38
+ use rustc_trait_selection:: traits;
38
39
39
40
#[ macro_use]
40
41
mod pass_manager;
@@ -389,6 +390,50 @@ fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> &
389
390
body. tainted_by_errors = Some ( error_reported) ;
390
391
}
391
392
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
+
392
437
run_analysis_to_runtime_passes ( tcx, & mut body) ;
393
438
394
439
tcx. alloc_steal_mir ( body)
0 commit comments