Skip to content

Commit

Permalink
check is violation ty included by const val
Browse files Browse the repository at this point in the history
  • Loading branch information
bvanjoi committed Nov 7, 2023
1 parent 4e0fb98 commit 8b4f040
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 2 deletions.
32 changes: 30 additions & 2 deletions compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use rustc_hir::def_id::DefId;
use rustc_index::Idx;
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
use rustc_infer::traits::Obligation;
use rustc_middle::mir;
use rustc_middle::mir::{self, ConstValue};
use rustc_middle::thir::{FieldPat, Pat, PatKind};
use rustc_middle::ty::{self, Ty, TyCtxt, ValTree};
use rustc_session::lint;
Expand Down Expand Up @@ -198,7 +198,7 @@ impl<'tcx> ConstToPat<'tcx> {
// We errored. Signal that in the pattern, so that follow up errors can be silenced.
let kind = PatKind::Error(e);
return Box::new(Pat { span: self.span, ty: cv.ty(), kind });
} else if let ty::Adt(..) = cv.ty().kind() && matches!(cv, mir::Const::Val(..)) {
} else if let ty::Adt(..) = cv.ty().kind() && let mir::Const::Val(const_val, const_ty) = cv && self.is_ty_included_by_const_val(const_val, const_ty, non_sm_ty) {
// This branch is only entered when the current `cv` is `mir::Const::Val`.
// This is because `mir::Const::ty` has already been handled by `Self::recur`
// and the invalid types may be ignored.
Expand Down Expand Up @@ -266,6 +266,34 @@ impl<'tcx> ConstToPat<'tcx> {
inlined_const_as_pat
}

// Check if `child` is included within the const value.
fn is_ty_included_by_const_val(
&self,
const_val: ConstValue<'tcx>,
parent: Ty<'tcx>,
child: Ty<'tcx>,
) -> bool {
if parent == self.tcx().normalize_erasing_regions(self.param_env, child) {
return true;
}
match parent.kind() {
ty::Adt(..) | ty::Tuple(_) | ty::Array(..) => {
let destructured = self
.tcx()
.try_destructure_mir_constant_for_user_output(
const_val,
self.tcx().normalize_erasing_regions(self.param_env, parent),
)
.unwrap();
destructured
.fields
.iter()
.any(|field| self.is_ty_included_by_const_val(field.0, field.1, child))
}
_ => false,
}
}

#[instrument(level = "trace", skip(self), ret)]
fn type_has_partial_eq_impl(&self, ty: Ty<'tcx>) -> bool {
// double-check there even *is* a semantic `PartialEq` to dispatch to.
Expand Down
21 changes: 21 additions & 0 deletions tests/ui/pattern/issue-117626.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// check-pass

#[derive(PartialEq)]
struct NonMatchable;

impl Eq for NonMatchable {}

#[derive(PartialEq, Eq)]
enum Foo {
A(NonMatchable),
B(*const u8),
}

const CONST: Foo = Foo::B(std::ptr::null());

fn main() {
match CONST {
CONST => 0,
_ => 1,
};
}

0 comments on commit 8b4f040

Please sign in to comment.