|
28 | 28 |
|
29 | 29 | use rustc_middle::mir::{Body, START_BLOCK, TerminatorKind}; |
30 | 30 | use rustc_middle::ty::{TyCtxt, TypeFlags, TypeVisitableExt}; |
| 31 | +use rustc_span::def_id::DefId; |
31 | 32 | use rustc_trait_selection::traits; |
32 | 33 | use tracing::trace; |
33 | 34 |
|
34 | 35 | use crate::pass_manager::MirPass; |
35 | 36 |
|
36 | 37 | pub(crate) struct ImpossiblePredicates; |
37 | 38 |
|
| 39 | +fn has_impossible_predicates(tcx: TyCtxt<'_>, def_id: DefId) -> bool { |
| 40 | + let predicates = tcx.predicates_of(def_id).instantiate_identity(tcx); |
| 41 | + tracing::trace!(?predicates); |
| 42 | + let predicates = predicates.predicates.into_iter().filter(|p| { |
| 43 | + !p.has_type_flags( |
| 44 | + // Only consider global clauses to simplify. |
| 45 | + TypeFlags::HAS_FREE_LOCAL_NAMES |
| 46 | + // Clauses that refer to unevaluated constants as they cause cycles. |
| 47 | + | TypeFlags::HAS_CT_PROJECTION, |
| 48 | + ) |
| 49 | + }); |
| 50 | + let predicates: Vec<_> = traits::elaborate(tcx, predicates).collect(); |
| 51 | + tracing::trace!(?predicates); |
| 52 | + predicates.references_error() || traits::impossible_predicates(tcx, predicates) |
| 53 | +} |
| 54 | + |
38 | 55 | impl<'tcx> MirPass<'tcx> for ImpossiblePredicates { |
39 | 56 | #[tracing::instrument(level = "trace", skip(self, tcx, body))] |
40 | 57 | fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { |
41 | 58 | tracing::trace!(def_id = ?body.source.def_id()); |
42 | | - let predicates = tcx.predicates_of(body.source.def_id()).instantiate_identity(tcx); |
43 | | - tracing::trace!(?predicates); |
44 | | - let predicates = predicates.predicates.into_iter().filter(|p| { |
45 | | - !p.has_type_flags( |
46 | | - // Only consider global clauses to simplify. |
47 | | - TypeFlags::HAS_FREE_LOCAL_NAMES |
48 | | - // Clauses that refer to unevaluated constants as they cause cycles. |
49 | | - | TypeFlags::HAS_CT_PROJECTION, |
50 | | - ) |
51 | | - }); |
52 | | - let predicates: Vec<_> = traits::elaborate(tcx, predicates).collect(); |
53 | | - tracing::trace!(?predicates); |
54 | | - if predicates.references_error() || traits::impossible_predicates(tcx, predicates) { |
| 59 | + let impossible = body.tainted_by_errors.is_some() |
| 60 | + || has_impossible_predicates(tcx, body.source.def_id()); |
| 61 | + if impossible { |
55 | 62 | trace!("found unsatisfiable predicates"); |
56 | 63 | // Clear the body to only contain a single `unreachable` statement. |
57 | 64 | let bbs = body.basic_blocks.as_mut(); |
|
0 commit comments