|
2 | 2 | //!
|
3 | 3 | //! See the `Qualif` trait for more info.
|
4 | 4 |
|
| 5 | +use rustc_infer::infer::TyCtxtInferExt; |
5 | 6 | use rustc_middle::mir::*;
|
6 | 7 | use rustc_middle::ty::{self, subst::SubstsRef, AdtDef, Ty};
|
7 | 8 | use rustc_span::DUMMY_SP;
|
| 9 | +use rustc_trait_selection::traits; |
8 | 10 |
|
9 | 11 | use super::ConstCx;
|
10 | 12 |
|
11 | 13 | pub fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> ConstQualifs {
|
12 | 14 | ConstQualifs {
|
13 | 15 | has_mut_interior: HasMutInterior::in_any_value_of_ty(cx, ty),
|
14 | 16 | needs_drop: NeedsDrop::in_any_value_of_ty(cx, ty),
|
| 17 | + custom_eq: CustomEq::in_any_value_of_ty(cx, ty), |
15 | 18 | }
|
16 | 19 | }
|
17 | 20 |
|
@@ -108,6 +111,39 @@ impl Qualif for NeedsDrop {
|
108 | 111 | }
|
109 | 112 | }
|
110 | 113 |
|
| 114 | +/// A constant that cannot be used as part of a pattern in a `match` expression. |
| 115 | +pub struct CustomEq; |
| 116 | + |
| 117 | +impl Qualif for CustomEq { |
| 118 | + const ANALYSIS_NAME: &'static str = "flow_custom_eq"; |
| 119 | + |
| 120 | + fn in_qualifs(qualifs: &ConstQualifs) -> bool { |
| 121 | + qualifs.custom_eq |
| 122 | + } |
| 123 | + |
| 124 | + fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool { |
| 125 | + // If *any* component of a composite data type does not implement `Structural{Partial,}Eq`, |
| 126 | + // we know that at least some values of that type are not structural-match. I say "some" |
| 127 | + // because that component may be part of an enum variant (e.g., |
| 128 | + // `Option::<NonStructuralMatchTy>::Some`), in which case some values of this type may be |
| 129 | + // structural-match (`Option::None`). |
| 130 | + let id = cx.tcx.hir().local_def_id_to_hir_id(cx.def_id.as_local().unwrap()); |
| 131 | + traits::search_for_structural_match_violation(id, cx.body.span, cx.tcx, ty).is_some() |
| 132 | + } |
| 133 | + |
| 134 | + fn in_adt_inherently( |
| 135 | + cx: &ConstCx<'_, 'tcx>, |
| 136 | + adt: &'tcx AdtDef, |
| 137 | + substs: SubstsRef<'tcx>, |
| 138 | + ) -> bool { |
| 139 | + let ty = cx.tcx.mk_ty(ty::Adt(adt, substs)); |
| 140 | + let id = cx.tcx.hir().local_def_id_to_hir_id(cx.def_id.as_local().unwrap()); |
| 141 | + cx.tcx |
| 142 | + .infer_ctxt() |
| 143 | + .enter(|infcx| !traits::type_marked_structural(id, cx.body.span, &infcx, ty)) |
| 144 | + } |
| 145 | +} |
| 146 | + |
111 | 147 | // FIXME: Use `mir::visit::Visitor` for the `in_*` functions if/when it supports early return.
|
112 | 148 |
|
113 | 149 | /// Returns `true` if this `Rvalue` contains qualif `Q`.
|
|
0 commit comments