Skip to content

Commit

Permalink
Auto merge of rust-lang#115887 - RalfJung:pat, r=oli-obk
Browse files Browse the repository at this point in the history
thir::pattern: update some comments and error type names

Follow-up to [these comments](rust-lang#105750 (review)). Please carefully fact-check, I'm new to this area of the compiler!
  • Loading branch information
bors committed Sep 27, 2023
2 parents 92009f2 + 12a1b55 commit c4ce33c
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 17 deletions.
16 changes: 10 additions & 6 deletions compiler/rustc_middle/src/thir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -732,12 +732,16 @@ pub enum PatKind<'tcx> {
},

/// One of the following:
/// * `&str`, which will be handled as a string pattern and thus exhaustiveness
/// checking will detect if you use the same string twice in different patterns.
/// * integer, bool, char or float, which will be handled by exhaustiveness to cover exactly
/// its own value, similar to `&str`, but these values are much simpler.
/// * Opaque constants, that must not be matched structurally. So anything that does not derive
/// `PartialEq` and `Eq`.
/// * `&str` (represented as a valtree), which will be handled as a string pattern and thus
/// exhaustiveness checking will detect if you use the same string twice in different
/// patterns.
/// * integer, bool, char or float (represented as a valtree), which will be handled by
/// exhaustiveness to cover exactly its own value, similar to `&str`, but these values are
/// much simpler.
/// * Opaque constants (represented as `mir::ConstValue`), that must not be matched
/// structurally. So anything that does not derive `PartialEq` and `Eq`.
///
/// These are always compared with the matched place using (the semantics of) `PartialEq`.
Constant {
value: mir::Const<'tcx>,
},
Expand Down
28 changes: 17 additions & 11 deletions compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
/// Converts an evaluated constant to a pattern (if possible).
/// This means aggregate values (like structs and enums) are converted
/// to a pattern that matches the value (as if you'd compared via structural equality).
///
/// `cv` must be a valtree or a `mir::ConstValue`.
#[instrument(level = "debug", skip(self), ret)]
pub(super) fn const_to_pat(
&self,
Expand Down Expand Up @@ -64,12 +66,10 @@ struct ConstToPat<'tcx> {
}

/// This error type signals that we encountered a non-struct-eq situation.
/// We bubble this up in order to get back to the reference destructuring and make that emit
/// a const pattern instead of a deref pattern. This allows us to simply call `PartialEq::eq`
/// on such patterns (since that function takes a reference) and not have to jump through any
/// hoops to get a reference to the value.
/// We will fall back to calling `PartialEq::eq` on such patterns,
/// and exhaustiveness checking will consider them as matching nothing.
#[derive(Debug)]
struct FallbackToConstRef;
struct FallbackToOpaqueConst;

impl<'tcx> ConstToPat<'tcx> {
fn new(
Expand Down Expand Up @@ -136,7 +136,7 @@ impl<'tcx> ConstToPat<'tcx> {
}
ty::ConstKind::Value(valtree) => self
.recur(valtree, cv.ty(), mir_structural_match_violation.unwrap_or(false))
.unwrap_or_else(|_| {
.unwrap_or_else(|_: FallbackToOpaqueConst| {
Box::new(Pat {
span: self.span,
ty: cv.ty(),
Expand Down Expand Up @@ -285,7 +285,7 @@ impl<'tcx> ConstToPat<'tcx> {
fn field_pats(
&self,
vals: impl Iterator<Item = (ValTree<'tcx>, Ty<'tcx>)>,
) -> Result<Vec<FieldPat<'tcx>>, FallbackToConstRef> {
) -> Result<Vec<FieldPat<'tcx>>, FallbackToOpaqueConst> {
vals.enumerate()
.map(|(idx, (val, ty))| {
let field = FieldIdx::new(idx);
Expand All @@ -303,7 +303,7 @@ impl<'tcx> ConstToPat<'tcx> {
cv: ValTree<'tcx>,
ty: Ty<'tcx>,
mir_structural_match_violation: bool,
) -> Result<Box<Pat<'tcx>>, FallbackToConstRef> {
) -> Result<Box<Pat<'tcx>>, FallbackToOpaqueConst> {
let id = self.id;
let span = self.span;
let tcx = self.tcx();
Expand All @@ -318,7 +318,7 @@ impl<'tcx> ConstToPat<'tcx> {
span,
FloatPattern,
);
return Err(FallbackToConstRef);
return Err(FallbackToOpaqueConst);
}
// If the type is not structurally comparable, just emit the constant directly,
// causing the pattern match code to treat it opaquely.
Expand All @@ -342,18 +342,20 @@ impl<'tcx> ConstToPat<'tcx> {
// Since we are behind a reference, we can just bubble the error up so we get a
// constant at reference type, making it easy to let the fallback call
// `PartialEq::eq` on it.
return Err(FallbackToConstRef);
return Err(FallbackToOpaqueConst);
}
ty::FnDef(..) => {
self.saw_const_match_error.set(true);
tcx.sess.emit_err(InvalidPattern { span, non_sm_ty: ty });
// We errored, so the pattern we generate is irrelevant.
PatKind::Wild
}
ty::Adt(adt_def, _) if !self.type_marked_structural(ty) => {
debug!("adt_def {:?} has !type_marked_structural for cv.ty: {:?}", adt_def, ty,);
self.saw_const_match_error.set(true);
let err = TypeNotStructural { span, non_sm_ty: ty };
tcx.sess.emit_err(err);
// We errored, so the pattern we generate is irrelevant.
PatKind::Wild
}
ty::Adt(adt_def, args) if adt_def.is_enum() => {
Expand Down Expand Up @@ -423,13 +425,15 @@ impl<'tcx> ConstToPat<'tcx> {
IndirectStructuralMatch { non_sm_ty: *pointee_ty },
);
}
return Err(FallbackToConstRef);
return Err(FallbackToOpaqueConst);
} else {
if !self.saw_const_match_error.get() {
self.saw_const_match_error.set(true);
let err = TypeNotStructural { span, non_sm_ty: *pointee_ty };
tcx.sess.emit_err(err);
}
tcx.sess.delay_span_bug(span, "`saw_const_match_error` set but no error?");
// We errored, so the pattern we generate is irrelevant.
PatKind::Wild
}
}
Expand All @@ -442,6 +446,7 @@ impl<'tcx> ConstToPat<'tcx> {
tcx.sess.emit_err(err);

// FIXME: introduce PatKind::Error to silence follow up diagnostics due to unreachable patterns.
// We errored, so the pattern we generate is irrelevant.
PatKind::Wild
} else {
let old = self.behind_reference.replace(true);
Expand Down Expand Up @@ -472,6 +477,7 @@ impl<'tcx> ConstToPat<'tcx> {
self.saw_const_match_error.set(true);
let err = InvalidPattern { span, non_sm_ty: ty };
tcx.sess.emit_err(err);
// We errored, so the pattern we generate is irrelevant.
PatKind::Wild
}
};
Expand Down

0 comments on commit c4ce33c

Please sign in to comment.