mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-28 20:16:58 +03:00
Rollup merge of #150788 - thir-pat, r=Nadrieril
THIR patterns: Replace `AscribeUserType` and `ExpandedConstant` wrappers with per-node data This PR removes the `AscribeUserType` and `ExpandedConstant` variants from `thir::PatKind`, and replaces them with an `Option<Box<PatExtra>>` field attached to every `thir::Pat`. ### Why remove these variants? Unlike other THIR pattern kinds, these variants are mere “wrappers” that exist to attach some additional information to an underlying pattern node. There are several places where code that consumes THIR patterns needs to carefully “unpeel” any wrapper nodes, in order to match on the underlying pattern. This is clunky, and easy to forget to do, especially since it's not always obvious where the wrapper nodes can and can't appear. Attaching the data to an optional per-node field makes it easier for consuming code to simply ignore the extra data when it is not relevant. (One downside is that it is now easier to accidentally ignore the extra data when it *is* relevant, but I think that's generally a favourable tradeoff.) ### Impact After this change, THIR pattern trees should be “logically identical” to the previous THIR pattern trees, in the sense that information that was carried by wrapper nodes should now be directly attached to the non-wrapper nodes that were being wrapped. Types and spans associated with THIR pattern nodes should (hopefully!) still be accurate. There should be no change to the output of THIR-based checks or MIR building.
This commit is contained in:
@@ -643,10 +643,26 @@ pub struct FieldPat<'tcx> {
|
||||
pub pattern: Pat<'tcx>,
|
||||
}
|
||||
|
||||
/// Additional per-node data that is not present on most THIR pattern nodes.
|
||||
#[derive(Clone, Debug, Default, HashStable, TypeVisitable)]
|
||||
pub struct PatExtra<'tcx> {
|
||||
/// If present, this node represents 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.
|
||||
pub expanded_const: Option<DefId>,
|
||||
|
||||
/// User-written types that must be preserved into MIR so that they can be
|
||||
/// checked.
|
||||
pub ascriptions: Vec<Ascription<'tcx>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, HashStable, TypeVisitable)]
|
||||
pub struct Pat<'tcx> {
|
||||
pub ty: Ty<'tcx>,
|
||||
pub span: Span,
|
||||
pub extra: Option<Box<PatExtra<'tcx>>>,
|
||||
pub kind: PatKind<'tcx>,
|
||||
}
|
||||
|
||||
@@ -762,11 +778,6 @@ pub enum PatKind<'tcx> {
|
||||
/// A wildcard pattern: `_`.
|
||||
Wild,
|
||||
|
||||
AscribeUserType {
|
||||
ascription: Ascription<'tcx>,
|
||||
subpattern: Box<Pat<'tcx>>,
|
||||
},
|
||||
|
||||
/// `x`, `ref x`, `x @ P`, etc.
|
||||
Binding {
|
||||
name: Symbol,
|
||||
@@ -831,21 +842,6 @@ pub enum PatKind<'tcx> {
|
||||
value: ty::Value<'tcx>,
|
||||
},
|
||||
|
||||
/// 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.
|
||||
subpattern: Box<Pat<'tcx>>,
|
||||
},
|
||||
|
||||
Range(Arc<PatRange<'tcx>>),
|
||||
|
||||
/// Matches against a slice, checking the length and extracting elements.
|
||||
@@ -1119,7 +1115,7 @@ mod size_asserts {
|
||||
static_assert_size!(Block, 48);
|
||||
static_assert_size!(Expr<'_>, 64);
|
||||
static_assert_size!(ExprKind<'_>, 40);
|
||||
static_assert_size!(Pat<'_>, 64);
|
||||
static_assert_size!(Pat<'_>, 72);
|
||||
static_assert_size!(PatKind<'_>, 48);
|
||||
static_assert_size!(Stmt<'_>, 48);
|
||||
static_assert_size!(StmtKind<'_>, 48);
|
||||
|
||||
@@ -259,7 +259,7 @@ pub(crate) fn for_each_immediate_subpat<'a, 'tcx>(
|
||||
pat: &'a Pat<'tcx>,
|
||||
mut callback: impl FnMut(&'a Pat<'tcx>),
|
||||
) {
|
||||
let Pat { kind, ty: _, span: _ } = pat;
|
||||
let Pat { kind, ty: _, span: _, extra: _ } = pat;
|
||||
match kind {
|
||||
PatKind::Missing
|
||||
| PatKind::Wild
|
||||
@@ -269,11 +269,9 @@ pub(crate) fn for_each_immediate_subpat<'a, 'tcx>(
|
||||
| PatKind::Never
|
||||
| PatKind::Error(_) => {}
|
||||
|
||||
PatKind::AscribeUserType { subpattern, .. }
|
||||
| PatKind::Binding { subpattern: Some(subpattern), .. }
|
||||
PatKind::Binding { subpattern: Some(subpattern), .. }
|
||||
| PatKind::Deref { subpattern }
|
||||
| PatKind::DerefPattern { subpattern, .. }
|
||||
| PatKind::ExpandedConstant { subpattern, .. } => callback(subpattern),
|
||||
| PatKind::DerefPattern { subpattern, .. } => callback(subpattern),
|
||||
|
||||
PatKind::Variant { subpatterns, .. } | PatKind::Leaf { subpatterns } => {
|
||||
for field_pat in subpatterns {
|
||||
|
||||
@@ -287,22 +287,14 @@ fn parse_let_statement(&mut self, stmt_id: StmtId) -> PResult<(LocalVarId, Ty<'t
|
||||
self.parse_var(pattern)
|
||||
}
|
||||
|
||||
fn parse_var(&mut self, mut pat: &Pat<'tcx>) -> PResult<(LocalVarId, Ty<'tcx>, Span)> {
|
||||
// Make sure we throw out any `AscribeUserType` we find
|
||||
loop {
|
||||
match &pat.kind {
|
||||
PatKind::Binding { var, ty, .. } => break Ok((*var, *ty, pat.span)),
|
||||
PatKind::AscribeUserType { subpattern, .. } => {
|
||||
pat = subpattern;
|
||||
}
|
||||
_ => {
|
||||
break Err(ParseError {
|
||||
span: pat.span,
|
||||
item_description: format!("{:?}", pat.kind),
|
||||
expected: "local".to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
fn parse_var(&mut self, pat: &Pat<'tcx>) -> PResult<(LocalVarId, Ty<'tcx>, Span)> {
|
||||
match &pat.kind {
|
||||
PatKind::Binding { var, ty, .. } => Ok((*var, *ty, pat.span)),
|
||||
_ => Err(ParseError {
|
||||
span: pat.span,
|
||||
item_description: format!("{:?}", pat.kind),
|
||||
expected: "local".to_string(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -144,11 +144,6 @@ fn parse_match(&self, arms: &[ArmId], span: Span) -> PResult<SwitchTargets> {
|
||||
let arm = &self.thir[*arm];
|
||||
let value = match arm.pattern.kind {
|
||||
PatKind::Constant { value } => value,
|
||||
PatKind::ExpandedConstant { ref subpattern, def_id: _ }
|
||||
if let PatKind::Constant { value } = subpattern.kind =>
|
||||
{
|
||||
value
|
||||
}
|
||||
_ => {
|
||||
return Err(ParseError {
|
||||
span: arm.pattern.span,
|
||||
|
||||
@@ -133,6 +133,20 @@ pub(super) fn for_pattern(
|
||||
}
|
||||
|
||||
let place = place_builder.try_to_place(cx);
|
||||
|
||||
// Apply any type ascriptions to the value at `match_pair.place`.
|
||||
if let Some(place) = place
|
||||
&& let Some(extra) = &pattern.extra
|
||||
{
|
||||
for &Ascription { ref annotation, variance } in &extra.ascriptions {
|
||||
extra_data.ascriptions.push(super::Ascription {
|
||||
source: place,
|
||||
annotation: annotation.clone(),
|
||||
variance,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let mut subpairs = Vec::new();
|
||||
let testable_case = match pattern.kind {
|
||||
PatKind::Missing | PatKind::Wild | PatKind::Error(_) => None,
|
||||
@@ -195,28 +209,6 @@ pub(super) fn for_pattern(
|
||||
Some(TestableCase::Constant { value, kind: const_kind })
|
||||
}
|
||||
|
||||
PatKind::AscribeUserType {
|
||||
ascription: Ascription { ref annotation, variance },
|
||||
ref subpattern,
|
||||
..
|
||||
} => {
|
||||
MatchPairTree::for_pattern(
|
||||
place_builder,
|
||||
subpattern,
|
||||
cx,
|
||||
&mut subpairs,
|
||||
extra_data,
|
||||
);
|
||||
|
||||
// Apply the type ascription to the value at `match_pair.place`
|
||||
if let Some(source) = place {
|
||||
let annotation = annotation.clone();
|
||||
extra_data.ascriptions.push(super::Ascription { source, annotation, variance });
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
PatKind::Binding { mode, var, is_shorthand, ref subpattern, .. } => {
|
||||
// In order to please the borrow checker, when lowering a pattern
|
||||
// like `x @ subpat` we must establish any bindings in `subpat`
|
||||
@@ -263,11 +255,6 @@ pub(super) fn for_pattern(
|
||||
None
|
||||
}
|
||||
|
||||
PatKind::ExpandedConstant { subpattern: ref pattern, .. } => {
|
||||
MatchPairTree::for_pattern(place_builder, pattern, cx, &mut subpairs, extra_data);
|
||||
None
|
||||
}
|
||||
|
||||
PatKind::Array { ref prefix, ref slice, ref suffix } => {
|
||||
cx.prefix_slice_suffix(
|
||||
&mut subpairs,
|
||||
|
||||
@@ -576,7 +576,8 @@ pub(super) fn expr_into_pattern(
|
||||
initializer_id: ExprId,
|
||||
) -> BlockAnd<()> {
|
||||
match irrefutable_pat.kind {
|
||||
// Optimize the case of `let x = ...` to write directly into `x`
|
||||
// Optimize `let x = ...` and `let x: T = ...` to write directly into `x`,
|
||||
// and then require that `T == typeof(x)` if present.
|
||||
PatKind::Binding { mode: BindingMode(ByRef::No, _), var, subpattern: None, .. } => {
|
||||
let place = self.storage_live_binding(
|
||||
block,
|
||||
@@ -592,43 +593,14 @@ pub(super) fn expr_into_pattern(
|
||||
let source_info = self.source_info(irrefutable_pat.span);
|
||||
self.cfg.push_fake_read(block, source_info, FakeReadCause::ForLet(None), place);
|
||||
|
||||
self.schedule_drop_for_binding(var, irrefutable_pat.span, OutsideGuard);
|
||||
block.unit()
|
||||
}
|
||||
let ascriptions: &[_] =
|
||||
try { irrefutable_pat.extra.as_deref()?.ascriptions.as_slice() }
|
||||
.unwrap_or_default();
|
||||
for thir::Ascription { annotation, variance: _ } in ascriptions {
|
||||
let ty_source_info = self.source_info(annotation.span);
|
||||
|
||||
// Optimize the case of `let x: T = ...` to write directly
|
||||
// into `x` and then require that `T == typeof(x)`.
|
||||
PatKind::AscribeUserType {
|
||||
ref subpattern,
|
||||
ascription: thir::Ascription { ref annotation, variance: _ },
|
||||
} if let PatKind::Binding {
|
||||
mode: BindingMode(ByRef::No, _),
|
||||
var,
|
||||
subpattern: None,
|
||||
..
|
||||
} = subpattern.kind =>
|
||||
{
|
||||
let place = self.storage_live_binding(
|
||||
block,
|
||||
var,
|
||||
irrefutable_pat.span,
|
||||
false,
|
||||
OutsideGuard,
|
||||
ScheduleDrops::Yes,
|
||||
);
|
||||
block = self.expr_into_dest(place, block, initializer_id).into_block();
|
||||
|
||||
// Inject a fake read, see comments on `FakeReadCause::ForLet`.
|
||||
let pattern_source_info = self.source_info(irrefutable_pat.span);
|
||||
let cause_let = FakeReadCause::ForLet(None);
|
||||
self.cfg.push_fake_read(block, pattern_source_info, cause_let, place);
|
||||
|
||||
let ty_source_info = self.source_info(annotation.span);
|
||||
|
||||
let base = self.canonical_user_type_annotations.push(annotation.clone());
|
||||
self.cfg.push(
|
||||
block,
|
||||
Statement::new(
|
||||
let base = self.canonical_user_type_annotations.push(annotation.clone());
|
||||
let stmt = Statement::new(
|
||||
ty_source_info,
|
||||
StatementKind::AscribeUserType(
|
||||
Box::new((place, UserTypeProjection { base, projs: Vec::new() })),
|
||||
@@ -648,8 +620,9 @@ pub(super) fn expr_into_pattern(
|
||||
// `<expr>`.
|
||||
ty::Invariant,
|
||||
),
|
||||
),
|
||||
);
|
||||
);
|
||||
self.cfg.push(block, stmt);
|
||||
}
|
||||
|
||||
self.schedule_drop_for_binding(var, irrefutable_pat.span, OutsideGuard);
|
||||
block.unit()
|
||||
@@ -879,6 +852,26 @@ fn visit_primary_bindings_special(
|
||||
&ProjectedUserTypesNode<'_>,
|
||||
),
|
||||
) {
|
||||
// Ascriptions correspond to user-written types like `let A::<'a>(_): A<'static> = ...;`.
|
||||
//
|
||||
// Caution: Pushing user types here is load-bearing even for
|
||||
// patterns containing no bindings, to ensure that the type ends
|
||||
// up represented in MIR _somewhere_.
|
||||
let user_tys = match pattern.extra.as_deref() {
|
||||
Some(PatExtra { ascriptions, .. }) if !ascriptions.is_empty() => {
|
||||
let base_user_tys = ascriptions
|
||||
.iter()
|
||||
.map(|thir::Ascription { annotation, variance: _ }| {
|
||||
// Note that the variance doesn't apply here, as we are tracking the effect
|
||||
// of user types on any bindings contained with subpattern.
|
||||
self.canonical_user_type_annotations.push(annotation.clone())
|
||||
})
|
||||
.collect();
|
||||
&user_tys.push_user_types(base_user_tys)
|
||||
}
|
||||
_ => user_tys,
|
||||
};
|
||||
|
||||
// Avoid having to write the full method name at each recursive call.
|
||||
let visit_subpat = |this: &mut Self, subpat, user_tys: &_, f: &mut _| {
|
||||
this.visit_primary_bindings_special(subpat, user_tys, f)
|
||||
@@ -924,31 +917,6 @@ fn visit_primary_bindings_special(
|
||||
visit_subpat(self, subpattern, &ProjectedUserTypesNode::None, f);
|
||||
}
|
||||
|
||||
PatKind::AscribeUserType {
|
||||
ref subpattern,
|
||||
ascription: thir::Ascription { ref annotation, variance: _ },
|
||||
} => {
|
||||
// This corresponds to something like
|
||||
//
|
||||
// ```
|
||||
// let A::<'a>(_): A<'static> = ...;
|
||||
// ```
|
||||
//
|
||||
// Note that the variance doesn't apply here, as we are tracking the effect
|
||||
// of `user_ty` on any bindings contained with subpattern.
|
||||
|
||||
// Caution: Pushing this user type here is load-bearing even for
|
||||
// patterns containing no bindings, to ensure that the type ends
|
||||
// up represented in MIR _somewhere_.
|
||||
let base_user_ty = self.canonical_user_type_annotations.push(annotation.clone());
|
||||
let subpattern_user_tys = user_tys.push_user_type(base_user_ty);
|
||||
visit_subpat(self, subpattern, &subpattern_user_tys, f)
|
||||
}
|
||||
|
||||
PatKind::ExpandedConstant { ref subpattern, .. } => {
|
||||
visit_subpat(self, subpattern, user_tys, f)
|
||||
}
|
||||
|
||||
PatKind::Leaf { ref subpatterns } => {
|
||||
for subpattern in subpatterns {
|
||||
let subpattern_user_tys = user_tys.leaf(subpattern.field);
|
||||
|
||||
@@ -8,15 +8,20 @@
|
||||
use std::iter;
|
||||
|
||||
use rustc_abi::{FieldIdx, VariantIdx};
|
||||
use rustc_data_structures::smallvec::SmallVec;
|
||||
use rustc_middle::mir::{ProjectionElem, UserTypeProjection, UserTypeProjections};
|
||||
use rustc_middle::ty::{AdtDef, UserTypeAnnotationIndex};
|
||||
use rustc_span::Symbol;
|
||||
|
||||
/// A single `thir::Pat` node should almost never have more than 0-2 user types.
|
||||
/// We can store up to 4 inline in the same size as an ordinary `Vec`.
|
||||
pub(crate) type UserTypeIndices = SmallVec<[UserTypeAnnotationIndex; 4]>;
|
||||
|
||||
/// One of a list of "operations" that can be used to lazily build projections
|
||||
/// of user-specified types.
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Debug)]
|
||||
pub(crate) enum ProjectedUserTypesOp {
|
||||
PushUserType { base: UserTypeAnnotationIndex },
|
||||
PushUserTypes { base_types: UserTypeIndices },
|
||||
|
||||
Index,
|
||||
Subslice { from: u64, to: u64 },
|
||||
@@ -32,9 +37,10 @@ pub(crate) enum ProjectedUserTypesNode<'a> {
|
||||
}
|
||||
|
||||
impl<'a> ProjectedUserTypesNode<'a> {
|
||||
pub(crate) fn push_user_type(&'a self, base: UserTypeAnnotationIndex) -> Self {
|
||||
// Pushing a base user type always causes the chain to become non-empty.
|
||||
Self::Chain { parent: self, op: ProjectedUserTypesOp::PushUserType { base } }
|
||||
pub(crate) fn push_user_types(&'a self, base_types: UserTypeIndices) -> Self {
|
||||
assert!(!base_types.is_empty());
|
||||
// Pushing one or more base user types always causes the chain to become non-empty.
|
||||
Self::Chain { parent: self, op: ProjectedUserTypesOp::PushUserTypes { base_types } }
|
||||
}
|
||||
|
||||
/// Push another projection op onto the chain, but only if it is already non-empty.
|
||||
@@ -94,16 +100,19 @@ pub(crate) fn build_user_type_projections(&self) -> Option<Box<UserTypeProjectio
|
||||
return None;
|
||||
}
|
||||
|
||||
let ops_reversed = self.iter_ops_reversed().cloned().collect::<Vec<_>>();
|
||||
let ops_reversed = self.iter_ops_reversed().collect::<Vec<_>>();
|
||||
// The "first" op should always be `PushUserType`.
|
||||
// Other projections are only added if there is at least one user type.
|
||||
assert_matches!(ops_reversed.last(), Some(ProjectedUserTypesOp::PushUserType { .. }));
|
||||
assert_matches!(ops_reversed.last(), Some(ProjectedUserTypesOp::PushUserTypes { .. }));
|
||||
|
||||
let mut projections = vec![];
|
||||
for op in ops_reversed.into_iter().rev() {
|
||||
match op {
|
||||
ProjectedUserTypesOp::PushUserType { base } => {
|
||||
projections.push(UserTypeProjection { base, projs: vec![] })
|
||||
match *op {
|
||||
ProjectedUserTypesOp::PushUserTypes { ref base_types } => {
|
||||
assert!(!base_types.is_empty());
|
||||
for &base in base_types {
|
||||
projections.push(UserTypeProjection { base, projs: vec![] })
|
||||
}
|
||||
}
|
||||
|
||||
ProjectedUserTypesOp::Index => {
|
||||
|
||||
@@ -342,8 +342,6 @@ fn visit_pat(&mut self, pat: &'a Pat<'tcx>) {
|
||||
PatKind::Wild |
|
||||
// these just wrap other patterns, which we recurse on below.
|
||||
PatKind::Or { .. } |
|
||||
PatKind::ExpandedConstant { .. } |
|
||||
PatKind::AscribeUserType { .. } |
|
||||
PatKind::Error(_) => {}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -680,20 +680,13 @@ fn check_binding_is_irrefutable(
|
||||
let mut interpreted_as_const = None;
|
||||
let mut interpreted_as_const_sugg = None;
|
||||
|
||||
// These next few matches want to peek through `AscribeUserType` to see
|
||||
// the underlying pattern.
|
||||
let mut unpeeled_pat = pat;
|
||||
while let PatKind::AscribeUserType { ref subpattern, .. } = unpeeled_pat.kind {
|
||||
unpeeled_pat = subpattern;
|
||||
}
|
||||
|
||||
if let Some(def_id) = is_const_pat_that_looks_like_binding(self.tcx, unpeeled_pat) {
|
||||
if let Some(def_id) = is_const_pat_that_looks_like_binding(self.tcx, 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.
|
||||
interpreted_as_const = Some(InterpretedAsConst { span, variable: variable.clone() });
|
||||
interpreted_as_const_sugg = Some(InterpretedAsConstSugg { span: pat.span, variable });
|
||||
} else if let PatKind::Constant { .. } = unpeeled_pat.kind
|
||||
} else if let PatKind::Constant { .. } = pat.kind
|
||||
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(pat.span)
|
||||
{
|
||||
// If the pattern to match is an integer literal:
|
||||
@@ -1213,7 +1206,7 @@ fn is_const_pat_that_looks_like_binding<'tcx>(tcx: TyCtxt<'tcx>, pat: &Pat<'tcx>
|
||||
// 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
|
||||
if let Some(def_id) = try { pat.extra.as_deref()?.expanded_const? }
|
||||
&& 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 == '_')
|
||||
|
||||
@@ -90,7 +90,7 @@ fn mk_err(&self, mut err: Diag<'_>, ty: Ty<'tcx>) -> Box<Pat<'tcx>> {
|
||||
);
|
||||
}
|
||||
}
|
||||
Box::new(Pat { span: self.span, ty, kind: PatKind::Error(err.emit()) })
|
||||
Box::new(Pat { span: self.span, ty, kind: PatKind::Error(err.emit()), extra: None })
|
||||
}
|
||||
|
||||
fn unevaluated_to_pat(
|
||||
@@ -174,10 +174,10 @@ fn unevaluated_to_pat(
|
||||
}
|
||||
};
|
||||
|
||||
// Convert the valtree to a const.
|
||||
let inlined_const_as_pat = self.valtree_to_pat(valtree, ty);
|
||||
// Lower the valtree to a THIR pattern.
|
||||
let mut thir_pat = self.valtree_to_pat(valtree, ty);
|
||||
|
||||
if !inlined_const_as_pat.references_error() {
|
||||
if !thir_pat.references_error() {
|
||||
// Always check for `PartialEq` if we had no other errors yet.
|
||||
if !type_has_partial_eq_impl(self.tcx, typing_env, ty).has_impl {
|
||||
let mut err = self.tcx.dcx().create_err(TypeNotPartialEq { span: self.span, ty });
|
||||
@@ -186,10 +186,10 @@ fn unevaluated_to_pat(
|
||||
}
|
||||
}
|
||||
|
||||
// Wrap the pattern in a marker node to indicate that it is the result of lowering a
|
||||
// Mark the pattern to indicate that it is the result of lowering a named
|
||||
// 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 })
|
||||
thir_pat.extra.get_or_insert_default().expanded_const = Some(uv.def);
|
||||
thir_pat
|
||||
}
|
||||
|
||||
fn field_pats(
|
||||
@@ -351,7 +351,7 @@ fn valtree_to_pat(&self, cv: ValTree<'tcx>, ty: Ty<'tcx>) -> Box<Pat<'tcx>> {
|
||||
}
|
||||
};
|
||||
|
||||
Box::new(Pat { span, ty, kind })
|
||||
Box::new(Pat { span, ty, kind, extra: None })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -71,14 +71,11 @@ pub(super) fn pat_from_hir<'tcx>(
|
||||
span: let_stmt_type.span,
|
||||
inferred_ty: typeck_results.node_type(let_stmt_type.hir_id),
|
||||
};
|
||||
thir_pat = Box::new(Pat {
|
||||
ty: thir_pat.ty,
|
||||
span: thir_pat.span,
|
||||
kind: PatKind::AscribeUserType {
|
||||
ascription: Ascription { annotation, variance: ty::Covariant },
|
||||
subpattern: thir_pat,
|
||||
},
|
||||
});
|
||||
thir_pat
|
||||
.extra
|
||||
.get_or_insert_default()
|
||||
.ascriptions
|
||||
.push(Ascription { annotation, variance: ty::Covariant });
|
||||
}
|
||||
|
||||
if let Some(m) = pcx.rust_2024_migration {
|
||||
@@ -142,7 +139,7 @@ fn lower_pattern(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> {
|
||||
}
|
||||
PatAdjust::PinDeref => PatKind::Deref { subpattern: thir_pat },
|
||||
};
|
||||
Box::new(Pat { span, ty: adjust.source, kind })
|
||||
Box::new(Pat { span, ty: adjust.source, kind, extra: None })
|
||||
});
|
||||
|
||||
if let Some(s) = &mut self.rust_2024_migration
|
||||
@@ -167,25 +164,14 @@ fn lower_pattern_range_endpoint(
|
||||
// Return None in that case; the caller will use NegInfinity or PosInfinity instead.
|
||||
let Some(expr) = expr else { return Ok(None) };
|
||||
|
||||
// Lower the endpoint into a temporary `PatKind` that will then be
|
||||
// Lower the endpoint into a temporary `thir::Pat` that will then be
|
||||
// deconstructed to obtain the constant value and other data.
|
||||
let mut kind: PatKind<'tcx> = self.lower_pat_expr(pat, expr);
|
||||
let endpoint_pat: Box<Pat<'tcx>> = self.lower_pat_expr(pat, expr);
|
||||
let box Pat { ref kind, extra, .. } = endpoint_pat;
|
||||
|
||||
// Unpeel any ascription or inline-const wrapper nodes.
|
||||
loop {
|
||||
match kind {
|
||||
PatKind::AscribeUserType { ascription, subpattern } => {
|
||||
ascriptions.push(ascription);
|
||||
kind = subpattern.kind;
|
||||
}
|
||||
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,
|
||||
}
|
||||
// Preserve any ascriptions from endpoint constants.
|
||||
if let Some(extra) = extra {
|
||||
ascriptions.extend(extra.ascriptions);
|
||||
}
|
||||
|
||||
// The unpeeled kind should now be a constant, giving us the endpoint value.
|
||||
@@ -250,7 +236,7 @@ fn lower_pattern_range(
|
||||
lo_expr: Option<&'tcx hir::PatExpr<'tcx>>,
|
||||
hi_expr: Option<&'tcx hir::PatExpr<'tcx>>,
|
||||
end: RangeEnd,
|
||||
) -> Result<PatKind<'tcx>, ErrorGuaranteed> {
|
||||
) -> Result<Box<Pat<'tcx>>, ErrorGuaranteed> {
|
||||
let ty = self.typeck_results.node_type(pat.hir_id);
|
||||
let span = pat.span;
|
||||
|
||||
@@ -306,27 +292,28 @@ fn lower_pattern_range(
|
||||
return Err(e);
|
||||
}
|
||||
}
|
||||
let mut thir_pat = Box::new(Pat { ty, span, kind, extra: None });
|
||||
|
||||
// If we are handling a range with associated constants (e.g.
|
||||
// `Foo::<'a>::A..=Foo::B`), we need to put the ascriptions for the associated
|
||||
// constants somewhere. Have them on the range pattern.
|
||||
for ascription in ascriptions {
|
||||
let subpattern = Box::new(Pat { span, ty, kind });
|
||||
kind = PatKind::AscribeUserType { ascription, subpattern };
|
||||
}
|
||||
// `PatKind::ExpandedConstant` wrappers from range endpoints used to
|
||||
thir_pat.extra.get_or_insert_default().ascriptions.extend(ascriptions);
|
||||
// IDs of expanded constants 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)
|
||||
Ok(thir_pat)
|
||||
}
|
||||
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> {
|
||||
let mut ty = self.typeck_results.node_type(pat.hir_id);
|
||||
let mut span = pat.span;
|
||||
let ty = self.typeck_results.node_type(pat.hir_id);
|
||||
let span = pat.span;
|
||||
|
||||
// Some of these match arms return a `Box<Pat>` early, while others
|
||||
// evaluate to a `PatKind` that will become a `Box<Pat>` at the end of
|
||||
// this function.
|
||||
let kind = match pat.kind {
|
||||
hir::PatKind::Missing => PatKind::Missing,
|
||||
|
||||
@@ -334,10 +321,13 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tc
|
||||
|
||||
hir::PatKind::Never => PatKind::Never,
|
||||
|
||||
hir::PatKind::Expr(value) => self.lower_pat_expr(pat, value),
|
||||
hir::PatKind::Expr(value) => return self.lower_pat_expr(pat, value),
|
||||
|
||||
hir::PatKind::Range(lo_expr, hi_expr, end) => {
|
||||
self.lower_pattern_range(pat, lo_expr, hi_expr, end).unwrap_or_else(PatKind::Error)
|
||||
match self.lower_pattern_range(pat, lo_expr, hi_expr, end) {
|
||||
Ok(thir_pat) => return thir_pat,
|
||||
Err(e) => PatKind::Error(e),
|
||||
}
|
||||
}
|
||||
|
||||
hir::PatKind::Deref(subpattern) => {
|
||||
@@ -360,7 +350,7 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tc
|
||||
},
|
||||
|
||||
hir::PatKind::Slice(prefix, slice, suffix) => {
|
||||
self.slice_or_array_pattern(pat, prefix, slice, suffix)
|
||||
return self.slice_or_array_pattern(pat, prefix, slice, suffix);
|
||||
}
|
||||
|
||||
hir::PatKind::Tuple(pats, ddpos) => {
|
||||
@@ -372,8 +362,9 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tc
|
||||
}
|
||||
|
||||
hir::PatKind::Binding(explicit_ba, id, ident, sub) => {
|
||||
let mut thir_pat_span = span;
|
||||
if let Some(ident_span) = ident.span.find_ancestor_inside(span) {
|
||||
span = span.with_hi(ident_span.hi());
|
||||
thir_pat_span = span.with_hi(ident_span.hi());
|
||||
}
|
||||
|
||||
let mode = *self
|
||||
@@ -389,22 +380,23 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tc
|
||||
// A ref x pattern is the same node used for x, and as such it has
|
||||
// x's type, which is &T, where we want T (the type being matched).
|
||||
let var_ty = ty;
|
||||
let mut thir_pat_ty = ty;
|
||||
if let hir::ByRef::Yes(pinnedness, _) = mode.0 {
|
||||
match pinnedness {
|
||||
hir::Pinnedness::Pinned
|
||||
if let Some(pty) = ty.pinned_ty()
|
||||
&& let &ty::Ref(_, rty, _) = pty.kind() =>
|
||||
{
|
||||
ty = rty;
|
||||
thir_pat_ty = rty;
|
||||
}
|
||||
hir::Pinnedness::Not if let &ty::Ref(_, rty, _) = ty.kind() => {
|
||||
ty = rty;
|
||||
thir_pat_ty = rty;
|
||||
}
|
||||
_ => bug!("`ref {}` has wrong type {}", ident, ty),
|
||||
}
|
||||
};
|
||||
|
||||
PatKind::Binding {
|
||||
let kind = PatKind::Binding {
|
||||
mode,
|
||||
name: ident.name,
|
||||
var: LocalVarId(id),
|
||||
@@ -412,7 +404,10 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tc
|
||||
subpattern: self.lower_opt_pattern(sub),
|
||||
is_primary: id == pat.hir_id,
|
||||
is_shorthand: false,
|
||||
}
|
||||
};
|
||||
// We might have modified the type or span, so use the modified
|
||||
// values in the THIR pattern node.
|
||||
return Box::new(Pat { ty: thir_pat_ty, span: thir_pat_span, kind, extra: None });
|
||||
}
|
||||
|
||||
hir::PatKind::TupleStruct(ref qpath, pats, ddpos) => {
|
||||
@@ -422,7 +417,7 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tc
|
||||
};
|
||||
let variant_def = adt_def.variant_of_res(res);
|
||||
let subpatterns = self.lower_tuple_subpats(pats, variant_def.fields.len(), ddpos);
|
||||
self.lower_variant_or_leaf(pat, None, res, subpatterns)
|
||||
return self.lower_variant_or_leaf(pat, None, res, subpatterns);
|
||||
}
|
||||
|
||||
hir::PatKind::Struct(ref qpath, fields, _) => {
|
||||
@@ -439,7 +434,7 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tc
|
||||
})
|
||||
.collect();
|
||||
|
||||
self.lower_variant_or_leaf(pat, None, res, subpatterns)
|
||||
return self.lower_variant_or_leaf(pat, None, res, subpatterns);
|
||||
}
|
||||
|
||||
hir::PatKind::Or(pats) => PatKind::Or { pats: self.lower_patterns(pats) },
|
||||
@@ -450,7 +445,9 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tc
|
||||
hir::PatKind::Err(guar) => PatKind::Error(guar),
|
||||
};
|
||||
|
||||
Box::new(Pat { span, ty, kind })
|
||||
// For pattern kinds that haven't already returned, create a `thir::Pat`
|
||||
// with the HIR pattern node's type and span.
|
||||
Box::new(Pat { span, ty, kind, extra: None })
|
||||
}
|
||||
|
||||
fn lower_tuple_subpats(
|
||||
@@ -482,13 +479,14 @@ fn slice_or_array_pattern(
|
||||
prefix: &'tcx [hir::Pat<'tcx>],
|
||||
slice: Option<&'tcx hir::Pat<'tcx>>,
|
||||
suffix: &'tcx [hir::Pat<'tcx>],
|
||||
) -> PatKind<'tcx> {
|
||||
) -> Box<Pat<'tcx>> {
|
||||
let ty = self.typeck_results.node_type(pat.hir_id);
|
||||
let span = pat.span;
|
||||
|
||||
let prefix = self.lower_patterns(prefix);
|
||||
let slice = self.lower_opt_pattern(slice);
|
||||
let suffix = self.lower_patterns(suffix);
|
||||
match ty.kind() {
|
||||
let kind = match ty.kind() {
|
||||
// Matching a slice, `[T]`.
|
||||
ty::Slice(..) => PatKind::Slice { prefix, slice, suffix },
|
||||
// Fixed-length array, `[T; len]`.
|
||||
@@ -499,8 +497,9 @@ fn slice_or_array_pattern(
|
||||
assert!(len >= prefix.len() as u64 + suffix.len() as u64);
|
||||
PatKind::Array { prefix, slice, suffix }
|
||||
}
|
||||
_ => span_bug!(pat.span, "bad slice pattern type {ty:?}"),
|
||||
}
|
||||
_ => span_bug!(span, "bad slice pattern type {ty:?}"),
|
||||
};
|
||||
Box::new(Pat { ty, span, kind, extra: None })
|
||||
}
|
||||
|
||||
fn lower_variant_or_leaf(
|
||||
@@ -509,7 +508,7 @@ fn lower_variant_or_leaf(
|
||||
expr: Option<&'tcx hir::PatExpr<'tcx>>,
|
||||
res: Res,
|
||||
subpatterns: Vec<FieldPat<'tcx>>,
|
||||
) -> PatKind<'tcx> {
|
||||
) -> Box<Pat<'tcx>> {
|
||||
// Check whether the caller should have provided an `expr` for this pattern kind.
|
||||
assert_matches!(
|
||||
(pat.kind, expr),
|
||||
@@ -533,7 +532,7 @@ fn lower_variant_or_leaf(
|
||||
res => res,
|
||||
};
|
||||
|
||||
let mut kind = match res {
|
||||
let kind = match res {
|
||||
Res::Def(DefKind::Variant, variant_id) => {
|
||||
let enum_id = self.tcx.parent(variant_id);
|
||||
let adt_def = self.tcx.adt_def(enum_id);
|
||||
@@ -542,7 +541,12 @@ fn lower_variant_or_leaf(
|
||||
ty::Adt(_, args) | ty::FnDef(_, args) => args,
|
||||
ty::Error(e) => {
|
||||
// Avoid ICE (#50585)
|
||||
return PatKind::Error(*e);
|
||||
return Box::new(Pat {
|
||||
ty,
|
||||
span,
|
||||
kind: PatKind::Error(*e),
|
||||
extra: None,
|
||||
});
|
||||
}
|
||||
_ => bug!("inappropriate type for def: {:?}", ty),
|
||||
};
|
||||
@@ -583,21 +587,23 @@ fn lower_variant_or_leaf(
|
||||
PatKind::Error(e)
|
||||
}
|
||||
};
|
||||
let mut thir_pat = Box::new(Pat { ty, span, kind, extra: None });
|
||||
|
||||
if let Some(user_ty) = self.user_args_applied_to_ty_of_hir_id(hir_id) {
|
||||
debug!("lower_variant_or_leaf: kind={:?} user_ty={:?} span={:?}", kind, user_ty, span);
|
||||
debug!(?thir_pat, ?user_ty, ?span, "lower_variant_or_leaf: applying ascription");
|
||||
let annotation = CanonicalUserTypeAnnotation {
|
||||
user_ty: Box::new(user_ty),
|
||||
span,
|
||||
inferred_ty: self.typeck_results.node_type(hir_id),
|
||||
};
|
||||
kind = PatKind::AscribeUserType {
|
||||
subpattern: Box::new(Pat { span, ty, kind }),
|
||||
ascription: Ascription { annotation, variance: ty::Covariant },
|
||||
};
|
||||
thir_pat
|
||||
.extra
|
||||
.get_or_insert_default()
|
||||
.ascriptions
|
||||
.push(Ascription { annotation, variance: ty::Covariant });
|
||||
}
|
||||
|
||||
kind
|
||||
thir_pat
|
||||
}
|
||||
|
||||
fn user_args_applied_to_ty_of_hir_id(
|
||||
@@ -632,8 +638,7 @@ fn lower_path(
|
||||
_ => {
|
||||
// The path isn't the name of a constant, so it must actually
|
||||
// be a unit struct or unit variant (e.g. `Option::None`).
|
||||
let kind = self.lower_variant_or_leaf(pat, Some(expr), res, vec![]);
|
||||
return Box::new(Pat { span, ty, kind });
|
||||
return self.lower_variant_or_leaf(pat, Some(expr), res, vec![]);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -652,16 +657,13 @@ fn lower_path(
|
||||
span,
|
||||
inferred_ty: self.typeck_results.node_type(id),
|
||||
};
|
||||
let kind = PatKind::AscribeUserType {
|
||||
subpattern: pattern,
|
||||
ascription: Ascription {
|
||||
annotation,
|
||||
// Note that we use `Contravariant` here. See the
|
||||
// `variance` field documentation for details.
|
||||
variance: ty::Contravariant,
|
||||
},
|
||||
};
|
||||
pattern = Box::new(Pat { span, kind, ty });
|
||||
// Note that we use `Contravariant` here. See the
|
||||
// `variance` field documentation for details.
|
||||
pattern
|
||||
.extra
|
||||
.get_or_insert_default()
|
||||
.ascriptions
|
||||
.push(Ascription { annotation, variance: ty::Contravariant });
|
||||
}
|
||||
|
||||
pattern
|
||||
@@ -674,10 +676,10 @@ fn lower_pat_expr(
|
||||
&mut self,
|
||||
pat: &'tcx hir::Pat<'tcx>, // Pattern that directly contains `expr`
|
||||
expr: &'tcx hir::PatExpr<'tcx>,
|
||||
) -> PatKind<'tcx> {
|
||||
) -> Box<Pat<'tcx>> {
|
||||
assert_matches!(pat.kind, hir::PatKind::Expr(..) | hir::PatKind::Range(..));
|
||||
match &expr.kind {
|
||||
hir::PatExprKind::Path(qpath) => self.lower_path(pat, expr, qpath).kind,
|
||||
hir::PatExprKind::Path(qpath) => self.lower_path(pat, expr, qpath),
|
||||
hir::PatExprKind::Lit { lit, negated } => {
|
||||
// We handle byte string literal patterns by using the pattern's type instead of the
|
||||
// literal's type in `const_to_pat`: if the literal `b"..."` matches on a slice reference,
|
||||
@@ -691,7 +693,7 @@ fn lower_pat_expr(
|
||||
let pat_ty = self.typeck_results.node_type(pat.hir_id);
|
||||
let lit_input = LitToConstInput { lit: lit.node, ty: pat_ty, neg: *negated };
|
||||
let constant = self.tcx.at(expr.span).lit_to_const(lit_input);
|
||||
self.const_to_pat(constant, pat_ty, expr.hir_id, lit.span).kind
|
||||
self.const_to_pat(constant, pat_ty, expr.hir_id, lit.span)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,6 +73,24 @@ fn into_buffer(self) -> String {
|
||||
self.fmt
|
||||
}
|
||||
|
||||
fn print_list<T>(
|
||||
&mut self,
|
||||
label: &str,
|
||||
list: &[T],
|
||||
depth_lvl: usize,
|
||||
print_fn: impl Fn(&mut Self, &T, usize),
|
||||
) {
|
||||
if list.is_empty() {
|
||||
print_indented!(self, format_args!("{label}: []"), depth_lvl);
|
||||
} else {
|
||||
print_indented!(self, format_args!("{label}: ["), depth_lvl);
|
||||
for item in list {
|
||||
print_fn(self, item, depth_lvl + 1)
|
||||
}
|
||||
print_indented!(self, "]", depth_lvl);
|
||||
}
|
||||
}
|
||||
|
||||
fn print_param(&mut self, param: &Param<'tcx>, depth_lvl: usize) {
|
||||
let Param { pat, ty, ty_span, self_kind, hir_id } = param;
|
||||
|
||||
@@ -663,15 +681,37 @@ fn print_arm(&mut self, arm_id: ArmId, depth_lvl: usize) {
|
||||
}
|
||||
|
||||
fn print_pat(&mut self, pat: &Pat<'tcx>, depth_lvl: usize) {
|
||||
let &Pat { ty, span, ref kind } = pat;
|
||||
let &Pat { ty, span, ref kind, ref extra } = pat;
|
||||
|
||||
print_indented!(self, "Pat: {", depth_lvl);
|
||||
print_indented!(self, format!("ty: {:?}", ty), depth_lvl + 1);
|
||||
print_indented!(self, format!("span: {:?}", span), depth_lvl + 1);
|
||||
self.print_pat_extra(extra.as_deref(), depth_lvl + 1);
|
||||
self.print_pat_kind(kind, depth_lvl + 1);
|
||||
print_indented!(self, "}", depth_lvl);
|
||||
}
|
||||
|
||||
fn print_pat_extra(&mut self, extra: Option<&PatExtra<'tcx>>, depth_lvl: usize) {
|
||||
let Some(extra) = extra else {
|
||||
// Skip printing in the common case of a pattern node with no extra data.
|
||||
return;
|
||||
};
|
||||
|
||||
let PatExtra { expanded_const, ascriptions } = extra;
|
||||
|
||||
print_indented!(self, "extra: PatExtra {", depth_lvl);
|
||||
print_indented!(self, format_args!("expanded_const: {expanded_const:?}"), depth_lvl + 1);
|
||||
self.print_list(
|
||||
"ascriptions",
|
||||
ascriptions,
|
||||
depth_lvl + 1,
|
||||
|this, ascription, depth_lvl| {
|
||||
print_indented!(this, format_args!("{ascription:?}"), depth_lvl);
|
||||
},
|
||||
);
|
||||
print_indented!(self, "}", depth_lvl);
|
||||
}
|
||||
|
||||
fn print_pat_kind(&mut self, pat_kind: &PatKind<'tcx>, depth_lvl: usize) {
|
||||
print_indented!(self, "kind: PatKind {", depth_lvl);
|
||||
|
||||
@@ -685,13 +725,6 @@ fn print_pat_kind(&mut self, pat_kind: &PatKind<'tcx>, depth_lvl: usize) {
|
||||
PatKind::Never => {
|
||||
print_indented!(self, "Never", depth_lvl + 1);
|
||||
}
|
||||
PatKind::AscribeUserType { ascription, subpattern } => {
|
||||
print_indented!(self, "AscribeUserType: {", depth_lvl + 1);
|
||||
print_indented!(self, format!("ascription: {:?}", ascription), depth_lvl + 2);
|
||||
print_indented!(self, "subpattern: ", depth_lvl + 2);
|
||||
self.print_pat(subpattern, depth_lvl + 3);
|
||||
print_indented!(self, "}", depth_lvl + 1);
|
||||
}
|
||||
PatKind::Binding { name, mode, var, ty, subpattern, is_primary, is_shorthand } => {
|
||||
print_indented!(self, "Binding {", depth_lvl + 1);
|
||||
print_indented!(self, format!("name: {:?}", name), depth_lvl + 2);
|
||||
@@ -756,13 +789,6 @@ fn print_pat_kind(&mut self, pat_kind: &PatKind<'tcx>, depth_lvl: usize) {
|
||||
print_indented!(self, format!("value: {}", value), depth_lvl + 2);
|
||||
print_indented!(self, "}", depth_lvl + 1);
|
||||
}
|
||||
PatKind::ExpandedConstant { def_id, subpattern } => {
|
||||
print_indented!(self, "ExpandedConstant {", depth_lvl + 1);
|
||||
print_indented!(self, format!("def_id: {def_id:?}"), depth_lvl + 2);
|
||||
print_indented!(self, "subpattern:", depth_lvl + 2);
|
||||
self.print_pat(subpattern, depth_lvl + 2);
|
||||
print_indented!(self, "}", depth_lvl + 1);
|
||||
}
|
||||
PatKind::Range(pat_range) => {
|
||||
print_indented!(self, format!("Range ( {:?} )", pat_range), depth_lvl + 1);
|
||||
}
|
||||
|
||||
@@ -462,8 +462,6 @@ pub fn lower_pat(&self, pat: &'p Pat<'tcx>) -> DeconstructedPat<'p, 'tcx> {
|
||||
let arity;
|
||||
let fields: Vec<_>;
|
||||
match &pat.kind {
|
||||
PatKind::AscribeUserType { subpattern, .. }
|
||||
| PatKind::ExpandedConstant { subpattern, .. } => return self.lower_pat(subpattern),
|
||||
PatKind::Binding { subpattern: Some(subpat), .. } => return self.lower_pat(subpat),
|
||||
PatKind::Missing | PatKind::Binding { subpattern: None, .. } | PatKind::Wild => {
|
||||
ctor = Wildcard;
|
||||
|
||||
Reference in New Issue
Block a user