Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions compiler/rustc_middle/src/thir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -832,18 +832,18 @@ pub enum PatKind<'tcx> {
value: ty::Value<'tcx>,
},

/// Pattern obtained by converting a constant (inline or named) to its pattern
/// representation using `const_to_pat`. This is used for unsafety checking.
/// Wrapper node representing a named constant that was lowered to a pattern
/// using `const_to_pat`.
///
/// This is used by some diagnostics for non-exhaustive matches, to map
/// the pattern node back to the `DefId` of its original constant.
///
/// FIXME(#150498): Can we make this an `Option<DefId>` field on `Pat`
/// instead, so that non-diagnostic code can ignore it more easily?
ExpandedConstant {
/// [DefId] of the constant item.
def_id: DefId,
/// The pattern that the constant lowered to.
///
/// HACK: we need to keep the `DefId` of inline constants around for unsafety checking;
/// therefore when a range pattern contains inline constants, we re-wrap the range pattern
/// with the `ExpandedConstant` nodes that correspond to the range endpoints. Hence
/// `subpattern` may actually be a range pattern, and `def_id` be the constant for one of
/// its endpoints.
subpattern: Box<Pat<'tcx>>,
},

Expand Down
8 changes: 0 additions & 8 deletions compiler/rustc_mir_build/src/check_unsafety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -410,14 +410,6 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
visit::walk_pat(self, pat);
self.inside_adt = old_inside_adt;
}
PatKind::ExpandedConstant { def_id, .. } => {
if let Some(def) = def_id.as_local()
&& matches!(self.tcx.def_kind(def_id), DefKind::InlineConst)
{
self.visit_inner_body(def);
}
visit::walk_pat(self, pat);
}
_ => {
visit::walk_pat(self, pat);
}
Expand Down
36 changes: 23 additions & 13 deletions compiler/rustc_mir_build/src/thir/pattern/check_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_errors::codes::*;
use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan, struct_span_code_err};
use rustc_hir::def::*;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::{self as hir, BindingMode, ByRef, HirId, MatchSource};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::Level;
Expand Down Expand Up @@ -687,12 +687,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
unpeeled_pat = subpattern;
}

if let PatKind::ExpandedConstant { def_id, .. } = unpeeled_pat.kind
&& let DefKind::Const = self.tcx.def_kind(def_id)
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(pat.span)
// We filter out paths with multiple path::segments.
&& snippet.chars().all(|c| c.is_alphanumeric() || c == '_')
{
if let Some(def_id) = is_const_pat_that_looks_like_binding(self.tcx, unpeeled_pat) {
let span = self.tcx.def_span(def_id);
let variable = self.tcx.item_name(def_id).to_string();
// When we encounter a constant as the binding name, point at the `const` definition.
Expand Down Expand Up @@ -1209,6 +1204,26 @@ fn pat_is_catchall(pat: &DeconstructedPat<'_, '_>) -> bool {
}
}

/// If the given pattern is a named constant that looks like it could have been
/// intended to be a binding, returns the `DefId` of the named constant.
///
/// Diagnostics use this to give more detailed suggestions for non-exhaustive
/// matches.
fn is_const_pat_that_looks_like_binding<'tcx>(tcx: TyCtxt<'tcx>, pat: &Pat<'tcx>) -> Option<DefId> {
// The pattern must be a named constant, and the name that appears in
// the pattern's source text must resemble a plain identifier without any
// `::` namespace separators or other non-identifier characters.
if let PatKind::ExpandedConstant { def_id, .. } = pat.kind
&& matches!(tcx.def_kind(def_id), DefKind::Const)
&& let Ok(snippet) = tcx.sess.source_map().span_to_snippet(pat.span)
&& snippet.chars().all(|c| c.is_alphanumeric() || c == '_')
{
Some(def_id)
} else {
None
}
}

/// Report that a match is not exhaustive.
fn report_non_exhaustive_match<'p, 'tcx>(
cx: &PatCtxt<'p, 'tcx>,
Expand Down Expand Up @@ -1303,12 +1318,7 @@ fn report_non_exhaustive_match<'p, 'tcx>(

for &arm in arms {
let arm = &thir.arms[arm];
if let PatKind::ExpandedConstant { def_id, .. } = arm.pattern.kind
&& !matches!(cx.tcx.def_kind(def_id), DefKind::InlineConst)
&& let Ok(snippet) = cx.tcx.sess.source_map().span_to_snippet(arm.pattern.span)
// We filter out paths with multiple path::segments.
&& snippet.chars().all(|c| c.is_alphanumeric() || c == '_')
{
if let Some(def_id) = is_const_pat_that_looks_like_binding(cx.tcx, &arm.pattern) {
let const_name = cx.tcx.item_name(def_id);
err.span_label(
arm.pattern.span,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ impl<'tcx> ConstToPat<'tcx> {
}

// Wrap the pattern in a marker node to indicate that it is the result of lowering a
// constant. This is used for diagnostics, and for unsafety checking of inline const blocks.
// constant. This is used for diagnostics.
let kind = PatKind::ExpandedConstant { subpattern: inlined_const_as_pat, def_id: uv.def };
Box::new(Pat { kind, ty, span: self.span })
}
Expand Down
24 changes: 11 additions & 13 deletions compiler/rustc_mir_build/src/thir/pattern/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ use rustc_middle::ty::adjustment::{PatAdjust, PatAdjustment};
use rustc_middle::ty::layout::IntegerExt;
use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt};
use rustc_middle::{bug, span_bug};
use rustc_span::def_id::DefId;
use rustc_span::{ErrorGuaranteed, Span};
use tracing::{debug, instrument};

Expand Down Expand Up @@ -131,9 +130,8 @@ impl<'tcx> PatCtxt<'tcx> {
fn lower_pattern_range_endpoint(
&mut self,
expr: Option<&'tcx hir::PatExpr<'tcx>>,
// Out-parameters collecting extra data to be reapplied by the caller
// Out-parameter collecting extra data to be reapplied by the caller
ascriptions: &mut Vec<Ascription<'tcx>>,
expanded_consts: &mut Vec<DefId>,
) -> Result<Option<PatRangeBoundary<'tcx>>, ErrorGuaranteed> {
let Some(expr) = expr else { return Ok(None) };

Expand All @@ -148,8 +146,10 @@ impl<'tcx> PatCtxt<'tcx> {
ascriptions.push(ascription);
kind = subpattern.kind;
}
PatKind::ExpandedConstant { def_id, subpattern } => {
expanded_consts.push(def_id);
PatKind::ExpandedConstant { def_id: _, subpattern } => {
// Expanded-constant nodes are currently only needed by
// diagnostics that don't apply to range patterns, so we
// can just discard them here.
kind = subpattern.kind;
}
_ => break,
Expand Down Expand Up @@ -227,10 +227,7 @@ impl<'tcx> PatCtxt<'tcx> {

// Collect extra data while lowering the endpoints, to be reapplied later.
let mut ascriptions = vec![];
let mut expanded_consts = vec![];

let mut lower_endpoint =
|expr| self.lower_pattern_range_endpoint(expr, &mut ascriptions, &mut expanded_consts);
let mut lower_endpoint = |expr| self.lower_pattern_range_endpoint(expr, &mut ascriptions);

let lo = lower_endpoint(lo_expr)?.unwrap_or(PatRangeBoundary::NegInfinity);
let hi = lower_endpoint(hi_expr)?.unwrap_or(PatRangeBoundary::PosInfinity);
Expand Down Expand Up @@ -282,10 +279,11 @@ impl<'tcx> PatCtxt<'tcx> {
let subpattern = Box::new(Pat { span, ty, kind });
kind = PatKind::AscribeUserType { ascription, subpattern };
}
for def_id in expanded_consts {
let subpattern = Box::new(Pat { span, ty, kind });
kind = PatKind::ExpandedConstant { def_id, subpattern };
}
// `PatKind::ExpandedConstant` wrappers from range endpoints used to
// also be preserved here, but that was only needed for unsafeck of
// inline `const { .. }` patterns, which were removed by
// <https://github.com/rust-lang/rust/pull/138492>.

Ok(kind)
}

Expand Down
Loading