1mod check_match;
4mod const_to_pat;
5mod migration;
6
7use std::cmp::Ordering;
8use std::sync::Arc;
9
10use rustc_abi::{FieldIdx, Integer};
11use rustc_data_structures::assert_matches;
12use rustc_errors::codes::*;
13use rustc_hir::def::{CtorOf, DefKind, Res};
14use rustc_hir::pat_util::EnumerateAndAdjustIterator;
15use rustc_hir::{self as hir, RangeEnd};
16use rustc_index::Idx;
17use rustc_middle::mir::interpret::LitToConstInput;
18use rustc_middle::thir::{
19 Ascription, DerefPatBorrowMode, FieldPat, LocalVarId, Pat, PatKind, PatRange, PatRangeBoundary,
20};
21use rustc_middle::ty::adjustment::{PatAdjust, PatAdjustment};
22use rustc_middle::ty::layout::IntegerExt;
23use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt};
24use rustc_middle::{bug, span_bug};
25use rustc_span::ErrorGuaranteed;
26use tracing::{debug, instrument};
27
28pub(crate) use self::check_match::check_match;
29use self::migration::PatMigration;
30use crate::errors::*;
31
32struct PatCtxt<'tcx> {
34 tcx: TyCtxt<'tcx>,
35 typing_env: ty::TypingEnv<'tcx>,
36 typeck_results: &'tcx ty::TypeckResults<'tcx>,
37
38 rust_2024_migration: Option<PatMigration<'tcx>>,
40}
41
42x;#[instrument(level = "debug", skip(tcx, typing_env, typeck_results), ret)]
43pub(super) fn pat_from_hir<'tcx>(
44 tcx: TyCtxt<'tcx>,
45 typing_env: ty::TypingEnv<'tcx>,
46 typeck_results: &'tcx ty::TypeckResults<'tcx>,
47 pat: &'tcx hir::Pat<'tcx>,
48 let_stmt_type: Option<&hir::Ty<'tcx>>,
50) -> Box<Pat<'tcx>> {
51 let mut pcx = PatCtxt {
52 tcx,
53 typing_env,
54 typeck_results,
55 rust_2024_migration: typeck_results
56 .rust_2024_migration_desugared_pats()
57 .get(pat.hir_id)
58 .map(PatMigration::new),
59 };
60
61 let mut thir_pat = pcx.lower_pattern(pat);
62
63 if let Some(let_stmt_type) = let_stmt_type
66 && let Some(&user_ty) = typeck_results.user_provided_types().get(let_stmt_type.hir_id)
67 {
68 debug!(?user_ty);
69 let annotation = CanonicalUserTypeAnnotation {
70 user_ty: Box::new(user_ty),
71 span: let_stmt_type.span,
72 inferred_ty: typeck_results.node_type(let_stmt_type.hir_id),
73 };
74 thir_pat
75 .extra
76 .get_or_insert_default()
77 .ascriptions
78 .push(Ascription { annotation, variance: ty::Covariant });
79 }
80
81 if let Some(m) = pcx.rust_2024_migration {
82 m.emit(tcx, pat.hir_id);
83 }
84
85 thir_pat
86}
87
88impl<'tcx> PatCtxt<'tcx> {
89 fn lower_pattern(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> {
90 let adjustments: &[PatAdjustment<'tcx>] =
91 self.typeck_results.pat_adjustments().get(pat.hir_id).map_or(&[], |v| &**v);
92
93 let mut opt_old_mode_span = None;
97 if let Some(s) = &mut self.rust_2024_migration
98 && adjustments.iter().any(|adjust| adjust.kind == PatAdjust::BuiltinDeref)
99 {
100 opt_old_mode_span = s.visit_implicit_derefs(pat.span, adjustments);
101 }
102
103 let unadjusted_pat = match pat.kind {
123 hir::PatKind::Ref(inner, _, _)
124 if self.typeck_results.skipped_ref_pats().contains(pat.hir_id) =>
125 {
126 self.lower_pattern(inner)
127 }
128 _ => self.lower_pattern_unadjusted(pat),
129 };
130
131 let adjusted_pat = adjustments.iter().rev().fold(unadjusted_pat, |thir_pat, adjust| {
132 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_mir_build/src/thir/pattern/mod.rs:132",
"rustc_mir_build::thir::pattern", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_mir_build/src/thir/pattern/mod.rs"),
::tracing_core::__macro_support::Option::Some(132u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_build::thir::pattern"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("{0:?}: wrapping pattern with adjustment {1:?}",
thir_pat, adjust) as &dyn Value))])
});
} else { ; }
};debug!("{:?}: wrapping pattern with adjustment {:?}", thir_pat, adjust);
133 let span = thir_pat.span;
134 let kind = match adjust.kind {
135 PatAdjust::BuiltinDeref => {
136 PatKind::Deref { pin: hir::Pinnedness::Not, subpattern: thir_pat }
137 }
138 PatAdjust::OverloadedDeref => {
139 let borrow = self.typeck_results.deref_pat_borrow_mode(adjust.source, pat);
140 PatKind::DerefPattern { subpattern: thir_pat, borrow }
141 }
142 PatAdjust::PinDeref => {
143 PatKind::Deref { pin: hir::Pinnedness::Pinned, subpattern: thir_pat }
144 }
145 };
146 Box::new(Pat { span, ty: adjust.source, kind, extra: None })
147 });
148
149 if let Some(s) = &mut self.rust_2024_migration
150 && adjustments.iter().any(|adjust| adjust.kind == PatAdjust::BuiltinDeref)
151 {
152 s.leave_ref(opt_old_mode_span);
153 }
154
155 adjusted_pat
156 }
157
158 fn lower_pattern_range_endpoint(
159 &mut self,
160 pat: &'tcx hir::Pat<'tcx>, expr: Option<&'tcx hir::PatExpr<'tcx>>,
162 ascriptions: &mut Vec<Ascription<'tcx>>,
164 ) -> Result<Option<PatRangeBoundary<'tcx>>, ErrorGuaranteed> {
165 match pat.kind {
hir::PatKind::Range(..) => {}
ref left_val => {
::core::panicking::assert_matches_failed(left_val,
"hir::PatKind::Range(..)", ::core::option::Option::None);
}
};assert_matches!(pat.kind, hir::PatKind::Range(..));
166
167 let Some(expr) = expr else { return Ok(None) };
170
171 let endpoint_pat: Box<Pat<'tcx>> = self.lower_pat_expr(pat, expr);
174 let box Pat { ref kind, extra, .. } = endpoint_pat;
175
176 if let Some(extra) = extra {
178 ascriptions.extend(extra.ascriptions);
179 }
180
181 let PatKind::Constant { value } = kind else {
183 let msg =
184 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("found bad range pattern endpoint `{0:?}` outside of error recovery",
expr))
})format!("found bad range pattern endpoint `{expr:?}` outside of error recovery");
185 return Err(self.tcx.dcx().span_delayed_bug(expr.span, msg));
186 };
187 Ok(Some(PatRangeBoundary::Finite(value.valtree)))
188 }
189
190 fn error_on_literal_overflow(
196 &self,
197 expr: Option<&'tcx hir::PatExpr<'tcx>>,
198 ty: Ty<'tcx>,
199 ) -> Result<(), ErrorGuaranteed> {
200 use rustc_ast::ast::LitKind;
201
202 let Some(expr) = expr else {
203 return Ok(());
204 };
205 let span = expr.span;
206
207 let hir::PatExprKind::Lit { lit, negated } = expr.kind else {
211 return Ok(());
212 };
213 let LitKind::Int(lit_val, _) = lit.node else {
214 return Ok(());
215 };
216 let (min, max): (i128, u128) = match ty.kind() {
217 ty::Int(ity) => {
218 let size = Integer::from_int_ty(&self.tcx, *ity).size();
219 (size.signed_int_min(), size.signed_int_max() as u128)
220 }
221 ty::Uint(uty) => {
222 let size = Integer::from_uint_ty(&self.tcx, *uty).size();
223 (0, size.unsigned_int_max())
224 }
225 _ => {
226 return Ok(());
227 }
228 };
229 if (negated && lit_val > max + 1) || (!negated && lit_val > max) {
232 return Err(self.tcx.dcx().emit_err(LiteralOutOfRange { span, ty, min, max }));
233 }
234 Ok(())
235 }
236
237 fn lower_pattern_range(
238 &mut self,
239 pat: &'tcx hir::Pat<'tcx>,
240 lo_expr: Option<&'tcx hir::PatExpr<'tcx>>,
241 hi_expr: Option<&'tcx hir::PatExpr<'tcx>>,
242 end: RangeEnd,
243 ) -> Result<Box<Pat<'tcx>>, ErrorGuaranteed> {
244 let ty = self.typeck_results.node_type(pat.hir_id);
245 let span = pat.span;
246
247 if lo_expr.is_none() && hi_expr.is_none() {
248 let msg = "found twice-open range pattern (`..`) outside of error recovery";
249 self.tcx.dcx().span_bug(span, msg);
250 }
251
252 let mut ascriptions = ::alloc::vec::Vec::new()vec![];
254 let mut lower_endpoint =
255 |expr| self.lower_pattern_range_endpoint(pat, expr, &mut ascriptions);
256
257 let lo = lower_endpoint(lo_expr)?.unwrap_or(PatRangeBoundary::NegInfinity);
258 let hi = lower_endpoint(hi_expr)?.unwrap_or(PatRangeBoundary::PosInfinity);
259
260 let cmp = lo.compare_with(hi, ty, self.tcx);
261 let mut kind = PatKind::Range(Arc::new(PatRange { lo, hi, end, ty }));
262 match (end, cmp) {
263 (RangeEnd::Excluded, Some(Ordering::Less)) => {}
265 (RangeEnd::Included, Some(Ordering::Less)) => {}
267 (RangeEnd::Included, Some(Ordering::Equal)) if lo.is_finite() && hi.is_finite() => {
269 let value = ty::Value { ty, valtree: lo.as_finite().unwrap() };
270 kind = PatKind::Constant { value };
271 }
272 (RangeEnd::Included, Some(Ordering::Equal)) if !lo.is_finite() => {}
274 (RangeEnd::Included, Some(Ordering::Equal)) if !hi.is_finite() => {}
277 _ => {
279 self.error_on_literal_overflow(lo_expr, ty)?;
281 self.error_on_literal_overflow(hi_expr, ty)?;
282 let e = match end {
283 RangeEnd::Included => {
284 self.tcx.dcx().emit_err(LowerRangeBoundMustBeLessThanOrEqualToUpper {
285 span,
286 teach: self.tcx.sess.teach(E0030),
287 })
288 }
289 RangeEnd::Excluded if lo_expr.is_none() => {
290 self.tcx.dcx().emit_err(UpperRangeBoundCannotBeMin { span })
291 }
292 RangeEnd::Excluded => {
293 self.tcx.dcx().emit_err(LowerRangeBoundMustBeLessThanUpper { span })
294 }
295 };
296 return Err(e);
297 }
298 }
299 let mut thir_pat = Box::new(Pat { ty, span, kind, extra: None });
300
301 thir_pat.extra.get_or_insert_default().ascriptions.extend(ascriptions);
305 Ok(thir_pat)
311 }
312
313 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("lower_pattern_unadjusted",
"rustc_mir_build::thir::pattern", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_mir_build/src/thir/pattern/mod.rs"),
::tracing_core::__macro_support::Option::Some(313u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_build::thir::pattern"),
::tracing_core::field::FieldSet::new(&["pat"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&pat)
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: Box<Pat<'tcx>> = loop {};
return __tracing_attr_fake_return;
}
{
let ty = self.typeck_results.node_type(pat.hir_id);
let span = pat.span;
let kind =
match pat.kind {
hir::PatKind::Missing => PatKind::Missing,
hir::PatKind::Wild => PatKind::Wild,
hir::PatKind::Never => PatKind::Never,
hir::PatKind::Expr(value) =>
return self.lower_pat_expr(pat, value),
hir::PatKind::Range(lo_expr, hi_expr, end) => {
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) => {
let borrow =
self.typeck_results.deref_pat_borrow_mode(ty, subpattern);
PatKind::DerefPattern {
subpattern: self.lower_pattern(subpattern),
borrow,
}
}
hir::PatKind::Ref(subpattern, pin, _) => {
let opt_old_mode_span =
self.rust_2024_migration.as_mut().and_then(|s|
s.visit_explicit_deref());
let subpattern = self.lower_pattern(subpattern);
if let Some(s) = &mut self.rust_2024_migration {
s.leave_ref(opt_old_mode_span);
}
PatKind::Deref { pin, subpattern }
}
hir::PatKind::Box(subpattern) =>
PatKind::DerefPattern {
subpattern: self.lower_pattern(subpattern),
borrow: DerefPatBorrowMode::Box,
},
hir::PatKind::Slice(prefix, slice, suffix) => {
return self.slice_or_array_pattern(pat, prefix, slice,
suffix);
}
hir::PatKind::Tuple(pats, ddpos) => {
let ty::Tuple(tys) =
ty.kind() else {
::rustc_middle::util::bug::span_bug_fmt(pat.span,
format_args!("unexpected type for tuple pattern: {0:?}",
ty));
};
let subpatterns =
self.lower_tuple_subpats(pats, tys.len(), ddpos);
PatKind::Leaf { subpatterns }
}
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) {
thir_pat_span = span.with_hi(ident_span.hi());
}
let mode =
*self.typeck_results.pat_binding_modes().get(pat.hir_id).expect("missing binding mode");
if let Some(s) = &mut self.rust_2024_migration {
s.visit_binding(pat.span, mode, explicit_ba, ident);
}
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() => {
thir_pat_ty = rty;
}
hir::Pinnedness::Not if let &ty::Ref(_, rty, _) = ty.kind()
=> {
thir_pat_ty = rty;
}
_ =>
::rustc_middle::util::bug::bug_fmt(format_args!("`ref {0}` has wrong type {1}",
ident, ty)),
}
};
let kind =
PatKind::Binding {
mode,
name: ident.name,
var: LocalVarId(id),
ty: var_ty,
subpattern: self.lower_opt_pattern(sub),
is_primary: id == pat.hir_id,
is_shorthand: false,
};
return Box::new(Pat {
ty: thir_pat_ty,
span: thir_pat_span,
kind,
extra: None,
});
}
hir::PatKind::TupleStruct(ref qpath, pats, ddpos) => {
let res = self.typeck_results.qpath_res(qpath, pat.hir_id);
let ty::Adt(adt_def, _) =
ty.kind() else {
::rustc_middle::util::bug::span_bug_fmt(pat.span,
format_args!("tuple struct pattern not applied to an ADT {0:?}",
ty));
};
let variant_def = adt_def.variant_of_res(res);
let subpatterns =
self.lower_tuple_subpats(pats, variant_def.fields.len(),
ddpos);
return self.lower_variant_or_leaf(pat, None, res,
subpatterns);
}
hir::PatKind::Struct(ref qpath, fields, _) => {
let res = self.typeck_results.qpath_res(qpath, pat.hir_id);
let subpatterns =
fields.iter().map(|field|
{
let mut pattern = *self.lower_pattern(field.pat);
if let PatKind::Binding { ref mut is_shorthand, .. } =
pattern.kind {
*is_shorthand = field.is_shorthand;
}
let field = self.typeck_results.field_index(field.hir_id);
FieldPat { field, pattern }
}).collect();
return self.lower_variant_or_leaf(pat, None, res,
subpatterns);
}
hir::PatKind::Or(pats) =>
PatKind::Or { pats: self.lower_patterns(pats) },
hir::PatKind::Guard(pat, _) => self.lower_pattern(pat).kind,
hir::PatKind::Err(guar) => PatKind::Error(guar),
};
Box::new(Pat { span, ty, kind, extra: None })
}
}
}#[instrument(skip(self), level = "debug")]
314 fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> {
315 let ty = self.typeck_results.node_type(pat.hir_id);
316 let span = pat.span;
317
318 let kind = match pat.kind {
322 hir::PatKind::Missing => PatKind::Missing,
323
324 hir::PatKind::Wild => PatKind::Wild,
325
326 hir::PatKind::Never => PatKind::Never,
327
328 hir::PatKind::Expr(value) => return self.lower_pat_expr(pat, value),
329
330 hir::PatKind::Range(lo_expr, hi_expr, end) => {
331 match self.lower_pattern_range(pat, lo_expr, hi_expr, end) {
332 Ok(thir_pat) => return thir_pat,
333 Err(e) => PatKind::Error(e),
334 }
335 }
336
337 hir::PatKind::Deref(subpattern) => {
338 let borrow = self.typeck_results.deref_pat_borrow_mode(ty, subpattern);
339 PatKind::DerefPattern { subpattern: self.lower_pattern(subpattern), borrow }
340 }
341 hir::PatKind::Ref(subpattern, pin, _) => {
342 let opt_old_mode_span =
344 self.rust_2024_migration.as_mut().and_then(|s| s.visit_explicit_deref());
345 let subpattern = self.lower_pattern(subpattern);
346 if let Some(s) = &mut self.rust_2024_migration {
347 s.leave_ref(opt_old_mode_span);
348 }
349 PatKind::Deref { pin, subpattern }
350 }
351 hir::PatKind::Box(subpattern) => PatKind::DerefPattern {
352 subpattern: self.lower_pattern(subpattern),
353 borrow: DerefPatBorrowMode::Box,
354 },
355
356 hir::PatKind::Slice(prefix, slice, suffix) => {
357 return self.slice_or_array_pattern(pat, prefix, slice, suffix);
358 }
359
360 hir::PatKind::Tuple(pats, ddpos) => {
361 let ty::Tuple(tys) = ty.kind() else {
362 span_bug!(pat.span, "unexpected type for tuple pattern: {:?}", ty);
363 };
364 let subpatterns = self.lower_tuple_subpats(pats, tys.len(), ddpos);
365 PatKind::Leaf { subpatterns }
366 }
367
368 hir::PatKind::Binding(explicit_ba, id, ident, sub) => {
369 let mut thir_pat_span = span;
370 if let Some(ident_span) = ident.span.find_ancestor_inside(span) {
371 thir_pat_span = span.with_hi(ident_span.hi());
372 }
373
374 let mode = *self
375 .typeck_results
376 .pat_binding_modes()
377 .get(pat.hir_id)
378 .expect("missing binding mode");
379
380 if let Some(s) = &mut self.rust_2024_migration {
381 s.visit_binding(pat.span, mode, explicit_ba, ident);
382 }
383
384 let var_ty = ty;
387 let mut thir_pat_ty = ty;
388 if let hir::ByRef::Yes(pinnedness, _) = mode.0 {
389 match pinnedness {
390 hir::Pinnedness::Pinned
391 if let Some(pty) = ty.pinned_ty()
392 && let &ty::Ref(_, rty, _) = pty.kind() =>
393 {
394 thir_pat_ty = rty;
395 }
396 hir::Pinnedness::Not if let &ty::Ref(_, rty, _) = ty.kind() => {
397 thir_pat_ty = rty;
398 }
399 _ => bug!("`ref {}` has wrong type {}", ident, ty),
400 }
401 };
402
403 let kind = PatKind::Binding {
404 mode,
405 name: ident.name,
406 var: LocalVarId(id),
407 ty: var_ty,
408 subpattern: self.lower_opt_pattern(sub),
409 is_primary: id == pat.hir_id,
410 is_shorthand: false,
411 };
412 return Box::new(Pat { ty: thir_pat_ty, span: thir_pat_span, kind, extra: None });
415 }
416
417 hir::PatKind::TupleStruct(ref qpath, pats, ddpos) => {
418 let res = self.typeck_results.qpath_res(qpath, pat.hir_id);
419 let ty::Adt(adt_def, _) = ty.kind() else {
420 span_bug!(pat.span, "tuple struct pattern not applied to an ADT {:?}", ty);
421 };
422 let variant_def = adt_def.variant_of_res(res);
423 let subpatterns = self.lower_tuple_subpats(pats, variant_def.fields.len(), ddpos);
424 return self.lower_variant_or_leaf(pat, None, res, subpatterns);
425 }
426
427 hir::PatKind::Struct(ref qpath, fields, _) => {
428 let res = self.typeck_results.qpath_res(qpath, pat.hir_id);
429 let subpatterns = fields
430 .iter()
431 .map(|field| {
432 let mut pattern = *self.lower_pattern(field.pat);
433 if let PatKind::Binding { ref mut is_shorthand, .. } = pattern.kind {
434 *is_shorthand = field.is_shorthand;
435 }
436 let field = self.typeck_results.field_index(field.hir_id);
437 FieldPat { field, pattern }
438 })
439 .collect();
440
441 return self.lower_variant_or_leaf(pat, None, res, subpatterns);
442 }
443
444 hir::PatKind::Or(pats) => PatKind::Or { pats: self.lower_patterns(pats) },
445
446 hir::PatKind::Guard(pat, _) => self.lower_pattern(pat).kind,
448
449 hir::PatKind::Err(guar) => PatKind::Error(guar),
450 };
451
452 Box::new(Pat { span, ty, kind, extra: None })
455 }
456
457 fn lower_tuple_subpats(
458 &mut self,
459 pats: &'tcx [hir::Pat<'tcx>],
460 expected_len: usize,
461 gap_pos: hir::DotDotPos,
462 ) -> Vec<FieldPat<'tcx>> {
463 pats.iter()
464 .enumerate_and_adjust(expected_len, gap_pos)
465 .map(|(i, subpattern)| FieldPat {
466 field: FieldIdx::new(i),
467 pattern: *self.lower_pattern(subpattern),
468 })
469 .collect()
470 }
471
472 fn lower_patterns(&mut self, pats: &'tcx [hir::Pat<'tcx>]) -> Box<[Pat<'tcx>]> {
473 pats.iter().map(|p| *self.lower_pattern(p)).collect()
474 }
475
476 fn lower_opt_pattern(&mut self, pat: Option<&'tcx hir::Pat<'tcx>>) -> Option<Box<Pat<'tcx>>> {
477 pat.map(|p| self.lower_pattern(p))
478 }
479
480 fn slice_or_array_pattern(
481 &mut self,
482 pat: &'tcx hir::Pat<'tcx>,
483 prefix: &'tcx [hir::Pat<'tcx>],
484 slice: Option<&'tcx hir::Pat<'tcx>>,
485 suffix: &'tcx [hir::Pat<'tcx>],
486 ) -> Box<Pat<'tcx>> {
487 let ty = self.typeck_results.node_type(pat.hir_id);
488 let span = pat.span;
489
490 let prefix = self.lower_patterns(prefix);
491 let slice = self.lower_opt_pattern(slice);
492 let suffix = self.lower_patterns(suffix);
493 let kind = match ty.kind() {
494 ty::Slice(..) => PatKind::Slice { prefix, slice, suffix },
496 ty::Array(_, len) => {
498 let len = len
499 .try_to_target_usize(self.tcx)
500 .expect("expected len of array pat to be definite");
501 if !(len >= prefix.len() as u64 + suffix.len() as u64) {
::core::panicking::panic("assertion failed: len >= prefix.len() as u64 + suffix.len() as u64")
};assert!(len >= prefix.len() as u64 + suffix.len() as u64);
502 PatKind::Array { prefix, slice, suffix }
503 }
504 _ => ::rustc_middle::util::bug::span_bug_fmt(span,
format_args!("bad slice pattern type {0:?}", ty))span_bug!(span, "bad slice pattern type {ty:?}"),
505 };
506 Box::new(Pat { ty, span, kind, extra: None })
507 }
508
509 fn lower_variant_or_leaf(
510 &mut self,
511 pat: &'tcx hir::Pat<'tcx>,
512 expr: Option<&'tcx hir::PatExpr<'tcx>>,
513 res: Res,
514 subpatterns: Vec<FieldPat<'tcx>>,
515 ) -> Box<Pat<'tcx>> {
516 match (pat.kind, expr) {
(hir::PatKind::Expr(..) | hir::PatKind::Range(..), Some(_)) |
(hir::PatKind::Struct(..) | hir::PatKind::TupleStruct(..), None) => {}
ref left_val => {
::core::panicking::assert_matches_failed(left_val,
"(hir::PatKind::Expr(..) | hir::PatKind::Range(..), Some(_)) |\n(hir::PatKind::Struct(..) | hir::PatKind::TupleStruct(..), None)",
::core::option::Option::None);
}
};assert_matches!(
518 (pat.kind, expr),
519 (hir::PatKind::Expr(..) | hir::PatKind::Range(..), Some(_))
520 | (hir::PatKind::Struct(..) | hir::PatKind::TupleStruct(..), None)
521 );
522
523 let (hir_id, span) = match expr {
526 Some(expr) => (expr.hir_id, expr.span),
527 None => (pat.hir_id, pat.span),
528 };
529 let ty = self.typeck_results.node_type(hir_id);
530
531 let res = match res {
532 Res::Def(DefKind::Ctor(CtorOf::Variant, ..), variant_ctor_id) => {
533 let variant_id = self.tcx.parent(variant_ctor_id);
534 Res::Def(DefKind::Variant, variant_id)
535 }
536 res => res,
537 };
538
539 let kind = match res {
540 Res::Def(DefKind::Variant, variant_id) => {
541 let enum_id = self.tcx.parent(variant_id);
542 let adt_def = self.tcx.adt_def(enum_id);
543 if adt_def.is_enum() {
544 let args = match ty.kind() {
545 ty::Adt(_, args) | ty::FnDef(_, args) => args,
546 ty::Error(e) => {
547 return Box::new(Pat {
549 ty,
550 span,
551 kind: PatKind::Error(*e),
552 extra: None,
553 });
554 }
555 _ => ::rustc_middle::util::bug::bug_fmt(format_args!("inappropriate type for def: {0:?}",
ty))bug!("inappropriate type for def: {:?}", ty),
556 };
557 PatKind::Variant {
558 adt_def,
559 args,
560 variant_index: adt_def.variant_index_with_id(variant_id),
561 subpatterns,
562 }
563 } else {
564 PatKind::Leaf { subpatterns }
565 }
566 }
567
568 Res::Def(
569 DefKind::Struct
570 | DefKind::Ctor(CtorOf::Struct, ..)
571 | DefKind::Union
572 | DefKind::TyAlias
573 | DefKind::AssocTy,
574 _,
575 )
576 | Res::SelfTyParam { .. }
577 | Res::SelfTyAlias { .. }
578 | Res::SelfCtor(..) => PatKind::Leaf { subpatterns },
579 _ => {
580 let e = match res {
581 Res::Def(DefKind::ConstParam, def_id) => {
582 let const_span = self.tcx.def_span(def_id);
583 self.tcx.dcx().emit_err(ConstParamInPattern { span, const_span })
584 }
585 Res::Def(DefKind::Static { .. }, def_id) => {
586 let static_span = self.tcx.def_span(def_id);
587 self.tcx.dcx().emit_err(StaticInPattern { span, static_span })
588 }
589 _ => self.tcx.dcx().emit_err(NonConstPath { span }),
590 };
591 PatKind::Error(e)
592 }
593 };
594 let mut thir_pat = Box::new(Pat { ty, span, kind, extra: None });
595
596 if let Some(user_ty) = self.user_args_applied_to_ty_of_hir_id(hir_id) {
597 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_mir_build/src/thir/pattern/mod.rs:597",
"rustc_mir_build::thir::pattern", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_mir_build/src/thir/pattern/mod.rs"),
::tracing_core::__macro_support::Option::Some(597u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_build::thir::pattern"),
::tracing_core::field::FieldSet::new(&["message",
"thir_pat", "user_ty", "span"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("lower_variant_or_leaf: applying ascription")
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&thir_pat)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&user_ty) as
&dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&span) as
&dyn Value))])
});
} else { ; }
};debug!(?thir_pat, ?user_ty, ?span, "lower_variant_or_leaf: applying ascription");
598 let annotation = CanonicalUserTypeAnnotation {
599 user_ty: Box::new(user_ty),
600 span,
601 inferred_ty: self.typeck_results.node_type(hir_id),
602 };
603 thir_pat
604 .extra
605 .get_or_insert_default()
606 .ascriptions
607 .push(Ascription { annotation, variance: ty::Covariant });
608 }
609
610 thir_pat
611 }
612
613 fn user_args_applied_to_ty_of_hir_id(
614 &self,
615 hir_id: hir::HirId,
616 ) -> Option<ty::CanonicalUserType<'tcx>> {
617 crate::thir::util::user_args_applied_to_ty_of_hir_id(self.tcx, self.typeck_results, hir_id)
618 }
619
620 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("lower_path",
"rustc_mir_build::thir::pattern", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_mir_build/src/thir/pattern/mod.rs"),
::tracing_core::__macro_support::Option::Some(623u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_build::thir::pattern"),
::tracing_core::field::FieldSet::new(&["pat", "expr",
"qpath"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&pat)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&expr)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&qpath)
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: Box<Pat<'tcx>> = loop {};
return __tracing_attr_fake_return;
}
{
match pat.kind {
hir::PatKind::Expr(..) | hir::PatKind::Range(..) => {}
ref left_val => {
::core::panicking::assert_matches_failed(left_val,
"hir::PatKind::Expr(..) | hir::PatKind::Range(..)",
::core::option::Option::None);
}
};
let id = expr.hir_id;
let span = expr.span;
let ty = self.typeck_results.node_type(id);
let res = self.typeck_results.qpath_res(qpath, id);
let (def_id, user_ty) =
match res {
Res::Def(DefKind::Const, def_id) |
Res::Def(DefKind::AssocConst, def_id) => {
(def_id, self.typeck_results.user_provided_types().get(id))
}
_ => {
return self.lower_variant_or_leaf(pat, Some(expr), res,
::alloc::vec::Vec::new());
}
};
let args = self.typeck_results.node_args(id);
let c =
ty::Const::new_unevaluated(self.tcx,
ty::UnevaluatedConst { def: def_id, args });
let mut pattern = self.const_to_pat(c, ty, id, span);
if let Some(&user_ty) = user_ty {
let annotation =
CanonicalUserTypeAnnotation {
user_ty: Box::new(user_ty),
span,
inferred_ty: self.typeck_results.node_type(id),
};
pattern.extra.get_or_insert_default().ascriptions.push(Ascription {
annotation,
variance: ty::Contravariant,
});
}
pattern
}
}
}#[instrument(skip(self), level = "debug")]
624 fn lower_path(
625 &mut self,
626 pat: &'tcx hir::Pat<'tcx>, expr: &'tcx hir::PatExpr<'tcx>,
628 qpath: &hir::QPath<'_>,
629 ) -> Box<Pat<'tcx>> {
630 assert_matches!(pat.kind, hir::PatKind::Expr(..) | hir::PatKind::Range(..));
631
632 let id = expr.hir_id;
633 let span = expr.span;
634 let ty = self.typeck_results.node_type(id);
635 let res = self.typeck_results.qpath_res(qpath, id);
636
637 let (def_id, user_ty) = match res {
638 Res::Def(DefKind::Const, def_id) | Res::Def(DefKind::AssocConst, def_id) => {
639 (def_id, self.typeck_results.user_provided_types().get(id))
640 }
641
642 _ => {
643 return self.lower_variant_or_leaf(pat, Some(expr), res, vec![]);
646 }
647 };
648
649 let args = self.typeck_results.node_args(id);
651 let c = ty::Const::new_unevaluated(self.tcx, ty::UnevaluatedConst { def: def_id, args });
654 let mut pattern = self.const_to_pat(c, ty, id, span);
655
656 if let Some(&user_ty) = user_ty {
659 let annotation = CanonicalUserTypeAnnotation {
660 user_ty: Box::new(user_ty),
661 span,
662 inferred_ty: self.typeck_results.node_type(id),
663 };
664 pattern
667 .extra
668 .get_or_insert_default()
669 .ascriptions
670 .push(Ascription { annotation, variance: ty::Contravariant });
671 }
672
673 pattern
674 }
675
676 fn lower_pat_expr(
680 &mut self,
681 pat: &'tcx hir::Pat<'tcx>, expr: &'tcx hir::PatExpr<'tcx>,
683 ) -> Box<Pat<'tcx>> {
684 match pat.kind {
hir::PatKind::Expr(..) | hir::PatKind::Range(..) => {}
ref left_val => {
::core::panicking::assert_matches_failed(left_val,
"hir::PatKind::Expr(..) | hir::PatKind::Range(..)",
::core::option::Option::None);
}
};assert_matches!(pat.kind, hir::PatKind::Expr(..) | hir::PatKind::Range(..));
685 match &expr.kind {
686 hir::PatExprKind::Path(qpath) => self.lower_path(pat, expr, qpath),
687 hir::PatExprKind::Lit { lit, negated } => {
688 let pat_ty = self.typeck_results.node_type(pat.hir_id);
698 let lit_input = LitToConstInput { lit: lit.node, ty: pat_ty, neg: *negated };
699 let constant = self.tcx.at(expr.span).lit_to_const(lit_input);
700 self.const_to_pat(constant, pat_ty, expr.hir_id, lit.span)
701 }
702 }
703 }
704}