mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Replace AscribeUserType and ExpandedConstant with per-node data
This commit is contained in:
@@ -778,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,
|
||||
@@ -847,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.
|
||||
|
||||
@@ -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()
|
||||
@@ -884,9 +857,10 @@ fn visit_primary_bindings_special(
|
||||
// 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.kind {
|
||||
PatKind::AscribeUserType { ref ascription, .. } => {
|
||||
let base_user_tys = std::iter::once(ascription)
|
||||
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.
|
||||
@@ -943,15 +917,6 @@ fn visit_primary_bindings_special(
|
||||
visit_subpat(self, subpattern, &ProjectedUserTypesNode::None, f);
|
||||
}
|
||||
|
||||
PatKind::AscribeUserType { ref subpattern, ascription: _ } => {
|
||||
// The ascription was already handled above, so just recurse to the subpattern.
|
||||
visit_subpat(self, 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);
|
||||
|
||||
@@ -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 == '_')
|
||||
|
||||
@@ -186,14 +186,9 @@ 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.
|
||||
thir_pat = Box::new(Pat {
|
||||
ty: thir_pat.ty,
|
||||
span: thir_pat.span,
|
||||
kind: PatKind::ExpandedConstant { def_id: uv.def, subpattern: thir_pat },
|
||||
extra: None,
|
||||
});
|
||||
thir_pat.extra.get_or_insert_default().expanded_const = Some(uv.def);
|
||||
thir_pat
|
||||
}
|
||||
|
||||
|
||||
@@ -71,15 +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,
|
||||
},
|
||||
extra: None,
|
||||
});
|
||||
thir_pat
|
||||
.extra
|
||||
.get_or_insert_default()
|
||||
.ascriptions
|
||||
.push(Ascription { annotation, variance: ty::Covariant });
|
||||
}
|
||||
|
||||
if let Some(m) = pcx.rust_2024_migration {
|
||||
@@ -171,23 +167,11 @@ fn lower_pattern_range_endpoint(
|
||||
// Lower the endpoint into a temporary `thir::Pat` that will then be
|
||||
// deconstructed to obtain the constant value and other data.
|
||||
let endpoint_pat: Box<Pat<'tcx>> = self.lower_pat_expr(pat, expr);
|
||||
let box Pat { mut kind, .. } = endpoint_pat;
|
||||
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.
|
||||
@@ -313,15 +297,8 @@ fn lower_pattern_range(
|
||||
// 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 {
|
||||
thir_pat = Box::new(Pat {
|
||||
ty,
|
||||
span,
|
||||
kind: PatKind::AscribeUserType { ascription, subpattern: thir_pat },
|
||||
extra: None,
|
||||
});
|
||||
}
|
||||
// `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>.
|
||||
@@ -619,15 +596,11 @@ fn lower_variant_or_leaf(
|
||||
span,
|
||||
inferred_ty: self.typeck_results.node_type(hir_id),
|
||||
};
|
||||
thir_pat = Box::new(Pat {
|
||||
ty,
|
||||
span,
|
||||
kind: PatKind::AscribeUserType {
|
||||
subpattern: thir_pat,
|
||||
ascription: Ascription { annotation, variance: ty::Covariant },
|
||||
},
|
||||
extra: None,
|
||||
});
|
||||
thir_pat
|
||||
.extra
|
||||
.get_or_insert_default()
|
||||
.ascriptions
|
||||
.push(Ascription { annotation, variance: ty::Covariant });
|
||||
}
|
||||
|
||||
thir_pat
|
||||
@@ -684,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, extra: None });
|
||||
// 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
|
||||
|
||||
@@ -725,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);
|
||||
@@ -796,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