1mod check_match;
4mod const_to_pat;
5mod migration;
6
7use std::assert_matches;
8use std::cmp::Ordering;
9use std::sync::Arc;
10
11use rustc_abi::{FieldIdx, Integer};
12use rustc_ast::LitKind;
13use rustc_errors::codes::*;
14use rustc_hir::def::{CtorOf, DefKind, Res};
15use rustc_hir::pat_util::EnumerateAndAdjustIterator;
16use rustc_hir::{self as hir, RangeEnd};
17use rustc_index::Idx;
18use rustc_middle::thir::{
19 Ascription, FieldPat, LocalVarId, Pat, PatKind, PatRange, PatRangeBoundary,
20};
21use rustc_middle::ty::adjustment::{PatAdjust, PatAdjustment};
22use rustc_middle::ty::layout::IntegerExt;
23use rustc_middle::ty::{
24 self, CanonicalUserTypeAnnotation, LitToConstInput, Ty, TyCtxt, const_lit_matches_ty,
25};
26use rustc_middle::{bug, span_bug};
27use rustc_span::ErrorGuaranteed;
28use tracing::{debug, instrument};
29
30pub(crate) use self::check_match::check_match;
31use self::migration::PatMigration;
32use crate::diagnostics::*;
33use crate::thir::cx::ThirBuildCx;
34
35struct PatCtxt<'tcx, 'ptcx> {
37 upper: &'ptcx mut ThirBuildCx<'tcx>,
38 tcx: TyCtxt<'tcx>,
39 typing_env: ty::TypingEnv<'tcx>,
40 typeck_results: &'tcx ty::TypeckResults<'tcx>,
41
42 rust_2024_migration: Option<PatMigration<'tcx>>,
44}
45
46x;#[instrument(level = "debug", skip(upper, tcx, typing_env, typeck_results), ret)]
47pub(super) fn pat_from_hir<'tcx, 'ptcx>(
48 upper: &'ptcx mut ThirBuildCx<'tcx>,
49 tcx: TyCtxt<'tcx>,
50 typing_env: ty::TypingEnv<'tcx>,
51 typeck_results: &'tcx ty::TypeckResults<'tcx>,
52 pat: &'tcx hir::Pat<'tcx>,
53 let_stmt_type: Option<&hir::Ty<'tcx>>,
55) -> Box<Pat<'tcx>> {
56 let mut pcx = PatCtxt {
57 upper,
58 tcx,
59 typing_env,
60 typeck_results,
61 rust_2024_migration: typeck_results
62 .rust_2024_migration_desugared_pats()
63 .get(pat.hir_id)
64 .map(PatMigration::new),
65 };
66
67 let mut thir_pat = pcx.lower_pattern(pat);
68
69 if let Some(let_stmt_type) = let_stmt_type
72 && let Some(&user_ty) = typeck_results.user_provided_types().get(let_stmt_type.hir_id)
73 {
74 debug!(?user_ty);
75 let annotation = CanonicalUserTypeAnnotation {
76 user_ty: Box::new(user_ty),
77 span: let_stmt_type.span,
78 inferred_ty: typeck_results.node_type(let_stmt_type.hir_id),
79 };
80 thir_pat
81 .extra
82 .get_or_insert_default()
83 .ascriptions
84 .push(Ascription { annotation, variance: ty::Covariant });
85 }
86
87 if let Some(m) = pcx.rust_2024_migration {
88 m.emit(tcx, pat.hir_id);
89 }
90
91 thir_pat
92}
93
94impl<'tcx, 'ptcx> PatCtxt<'tcx, 'ptcx> {
95 fn lower_pattern(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> {
96 let adjustments: &[PatAdjustment<'tcx>] =
97 self.typeck_results.pat_adjustments().get(pat.hir_id).map_or(&[], |v| &**v);
98
99 let mut opt_old_mode_span = None;
103 if let Some(s) = &mut self.rust_2024_migration
104 && adjustments.iter().any(|adjust| adjust.kind == PatAdjust::BuiltinDeref)
105 {
106 opt_old_mode_span = s.visit_implicit_derefs(pat.span, adjustments);
107 }
108
109 let unadjusted_pat = match pat.kind {
129 hir::PatKind::Ref(inner, _, _)
130 if self.typeck_results.skipped_ref_pats().contains(pat.hir_id) =>
131 {
132 self.lower_pattern(inner)
133 }
134 _ => self.lower_pattern_unadjusted(pat),
135 };
136
137 let adjusted_pat = adjustments.iter().rev().fold(unadjusted_pat, |thir_pat, adjust| {
138 {
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:138",
"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(138u32),
::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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("{0:?}: wrapping pattern with adjustment {1:?}",
thir_pat, adjust) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("{:?}: wrapping pattern with adjustment {:?}", thir_pat, adjust);
139 let span = thir_pat.span;
140 let kind = match adjust.kind {
141 PatAdjust::BuiltinDeref => {
142 PatKind::Deref { pin: hir::Pinnedness::Not, subpattern: thir_pat }
143 }
144 PatAdjust::OverloadedDeref => {
145 let borrow = self.typeck_results.deref_pat_borrow_mode(adjust.source, pat);
146 PatKind::DerefPattern { subpattern: thir_pat, borrow }
147 }
148 PatAdjust::PinDeref => {
149 PatKind::Deref { pin: hir::Pinnedness::Pinned, subpattern: thir_pat }
150 }
151 };
152 Box::new(Pat { span, ty: adjust.source, kind, extra: None })
153 });
154
155 if let Some(s) = &mut self.rust_2024_migration
156 && adjustments.iter().any(|adjust| adjust.kind == PatAdjust::BuiltinDeref)
157 {
158 s.leave_ref(opt_old_mode_span);
159 }
160
161 adjusted_pat
162 }
163
164 fn lower_pattern_range_endpoint(
165 &mut self,
166 pat: &'tcx hir::Pat<'tcx>, expr: Option<&'tcx hir::PatExpr<'tcx>>,
168 ascriptions: &mut Vec<Ascription<'tcx>>,
170 ) -> Result<Option<PatRangeBoundary<'tcx>>, ErrorGuaranteed> {
171 {
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(..));
172
173 let Some(expr) = expr else { return Ok(None) };
176
177 let endpoint_pat: Box<Pat<'tcx>> = self.lower_pat_expr(pat, expr);
180 let Pat { ref kind, extra, .. } = endpoint_pat;
181
182 if let Some(extra) = extra {
184 ascriptions.extend(extra.ascriptions);
185 }
186
187 let PatKind::Constant { value } = kind else {
189 let msg =
190 ::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");
191 return Err(self.tcx.dcx().span_delayed_bug(expr.span, msg));
192 };
193 Ok(Some(PatRangeBoundary::Finite(value.valtree)))
194 }
195
196 fn error_on_literal_overflow(
202 &self,
203 expr: Option<&'tcx hir::PatExpr<'tcx>>,
204 ty: Ty<'tcx>,
205 ) -> Result<(), ErrorGuaranteed> {
206 let Some(expr) = expr else {
207 return Ok(());
208 };
209 let span = expr.span;
210
211 let hir::PatExprKind::Lit { lit, negated } = expr.kind else {
215 return Ok(());
216 };
217 let LitKind::Int(lit_val, _) = lit.node else {
218 return Ok(());
219 };
220 let (min, max): (i128, u128) = match ty.kind() {
221 ty::Int(ity) => {
222 let size = Integer::from_int_ty(&self.tcx, *ity).size();
223 (size.signed_int_min(), size.signed_int_max() as u128)
224 }
225 ty::Uint(uty) => {
226 let size = Integer::from_uint_ty(&self.tcx, *uty).size();
227 (0, size.unsigned_int_max())
228 }
229 _ => {
230 return Ok(());
231 }
232 };
233 if (negated && lit_val > max + 1) || (!negated && lit_val > max) {
236 return Err(self.tcx.dcx().emit_err(LiteralOutOfRange { span, ty, min, max }));
237 }
238 Ok(())
239 }
240
241 fn lower_pattern_range(
242 &mut self,
243 pat: &'tcx hir::Pat<'tcx>,
244 lo_expr: Option<&'tcx hir::PatExpr<'tcx>>,
245 hi_expr: Option<&'tcx hir::PatExpr<'tcx>>,
246 end: RangeEnd,
247 ) -> Result<Box<Pat<'tcx>>, ErrorGuaranteed> {
248 let ty = self.typeck_results.node_type(pat.hir_id);
249 let span = pat.span;
250
251 if lo_expr.is_none() && hi_expr.is_none() {
252 let msg = "found twice-open range pattern (`..`) outside of error recovery";
253 self.tcx.dcx().span_bug(span, msg);
254 }
255
256 let mut ascriptions = ::alloc::vec::Vec::new()vec![];
258 let mut lower_endpoint =
259 |expr| self.lower_pattern_range_endpoint(pat, expr, &mut ascriptions);
260
261 let lo = lower_endpoint(lo_expr)?.unwrap_or(PatRangeBoundary::NegInfinity);
262 let hi = lower_endpoint(hi_expr)?.unwrap_or(PatRangeBoundary::PosInfinity);
263
264 let cmp = lo.compare_with(hi, ty, self.tcx);
265 let mut kind = PatKind::Range(Arc::new(PatRange { lo, hi, end, ty }));
266 match (end, cmp) {
267 (RangeEnd::Excluded, Some(Ordering::Less)) => {}
269 (RangeEnd::Included, Some(Ordering::Less)) => {}
271 (RangeEnd::Included, Some(Ordering::Equal)) if lo.is_finite() && hi.is_finite() => {
273 let value = ty::Value { ty, valtree: lo.as_finite().unwrap() };
274 kind = PatKind::Constant { value };
275 }
276 (RangeEnd::Included, Some(Ordering::Equal)) if !lo.is_finite() => {}
278 (RangeEnd::Included, Some(Ordering::Equal)) if !hi.is_finite() => {}
281 _ => {
283 self.error_on_literal_overflow(lo_expr, ty)?;
285 self.error_on_literal_overflow(hi_expr, ty)?;
286 let e = match end {
287 RangeEnd::Included => {
288 self.tcx.dcx().emit_err(LowerRangeBoundMustBeLessThanOrEqualToUpper {
289 span,
290 teach: self.tcx.sess.teach(E0030),
291 })
292 }
293 RangeEnd::Excluded if lo_expr.is_none() => {
294 self.tcx.dcx().emit_err(UpperRangeBoundCannotBeMin { span })
295 }
296 RangeEnd::Excluded => {
297 self.tcx.dcx().emit_err(LowerRangeBoundMustBeLessThanUpper { span })
298 }
299 };
300 return Err(e);
301 }
302 }
303 let mut thir_pat = Box::new(Pat { ty, span, kind, extra: None });
304
305 thir_pat.extra.get_or_insert_default().ascriptions.extend(ascriptions);
309 Ok(thir_pat)
315 }
316
317 #[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(317u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_build::thir::pattern"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("pat")
}> =
::tracing::__macro_support::FieldName::new("pat");
NAME.as_str()
}], ::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};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&pat)
as &dyn ::tracing::field::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::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, condition) =>
PatKind::Guard {
subpattern: self.lower_pattern(pat),
condition: self.upper.mirror_expr(condition),
},
hir::PatKind::Err(guar) => PatKind::Error(guar),
};
Box::new(Pat { span, ty, kind, extra: None })
}
}
}#[instrument(skip(self), level = "debug")]
318 fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> {
319 let ty = self.typeck_results.node_type(pat.hir_id);
320 let span = pat.span;
321
322 let kind = match pat.kind {
326 hir::PatKind::Missing => PatKind::Missing,
327
328 hir::PatKind::Wild => PatKind::Wild,
329
330 hir::PatKind::Never => PatKind::Never,
331
332 hir::PatKind::Expr(value) => return self.lower_pat_expr(pat, value),
333
334 hir::PatKind::Range(lo_expr, hi_expr, end) => {
335 match self.lower_pattern_range(pat, lo_expr, hi_expr, end) {
336 Ok(thir_pat) => return thir_pat,
337 Err(e) => PatKind::Error(e),
338 }
339 }
340
341 hir::PatKind::Deref(subpattern) => {
342 let borrow = self.typeck_results.deref_pat_borrow_mode(ty, subpattern);
343 PatKind::DerefPattern { subpattern: self.lower_pattern(subpattern), borrow }
344 }
345 hir::PatKind::Ref(subpattern, pin, _) => {
346 let opt_old_mode_span =
348 self.rust_2024_migration.as_mut().and_then(|s| s.visit_explicit_deref());
349 let subpattern = self.lower_pattern(subpattern);
350 if let Some(s) = &mut self.rust_2024_migration {
351 s.leave_ref(opt_old_mode_span);
352 }
353 PatKind::Deref { pin, subpattern }
354 }
355 hir::PatKind::Slice(prefix, slice, suffix) => {
356 return self.slice_or_array_pattern(pat, prefix, slice, suffix);
357 }
358
359 hir::PatKind::Tuple(pats, ddpos) => {
360 let ty::Tuple(tys) = ty.kind() else {
361 span_bug!(pat.span, "unexpected type for tuple pattern: {:?}", ty);
362 };
363 let subpatterns = self.lower_tuple_subpats(pats, tys.len(), ddpos);
364 PatKind::Leaf { subpatterns }
365 }
366
367 hir::PatKind::Binding(explicit_ba, id, ident, sub) => {
368 let mut thir_pat_span = span;
369 if let Some(ident_span) = ident.span.find_ancestor_inside(span) {
370 thir_pat_span = span.with_hi(ident_span.hi());
371 }
372
373 let mode = *self
374 .typeck_results
375 .pat_binding_modes()
376 .get(pat.hir_id)
377 .expect("missing binding mode");
378
379 if let Some(s) = &mut self.rust_2024_migration {
380 s.visit_binding(pat.span, mode, explicit_ba, ident);
381 }
382
383 let var_ty = ty;
386 let mut thir_pat_ty = ty;
387 if let hir::ByRef::Yes(pinnedness, _) = mode.0 {
388 match pinnedness {
389 hir::Pinnedness::Pinned
390 if let Some(pty) = ty.pinned_ty()
391 && let &ty::Ref(_, rty, _) = pty.kind() =>
392 {
393 thir_pat_ty = rty;
394 }
395 hir::Pinnedness::Not if let &ty::Ref(_, rty, _) = ty.kind() => {
396 thir_pat_ty = rty;
397 }
398 _ => bug!("`ref {}` has wrong type {}", ident, ty),
399 }
400 };
401
402 let kind = PatKind::Binding {
403 mode,
404 name: ident.name,
405 var: LocalVarId(id),
406 ty: var_ty,
407 subpattern: self.lower_opt_pattern(sub),
408 is_primary: id == pat.hir_id,
409 is_shorthand: false,
410 };
411 return Box::new(Pat { ty: thir_pat_ty, span: thir_pat_span, kind, extra: None });
414 }
415
416 hir::PatKind::TupleStruct(ref qpath, pats, ddpos) => {
417 let res = self.typeck_results.qpath_res(qpath, pat.hir_id);
418 let ty::Adt(adt_def, _) = ty.kind() else {
419 span_bug!(pat.span, "tuple struct pattern not applied to an ADT {:?}", ty);
420 };
421 let variant_def = adt_def.variant_of_res(res);
422 let subpatterns = self.lower_tuple_subpats(pats, variant_def.fields.len(), ddpos);
423 return self.lower_variant_or_leaf(pat, None, res, subpatterns);
424 }
425
426 hir::PatKind::Struct(ref qpath, fields, _) => {
427 let res = self.typeck_results.qpath_res(qpath, pat.hir_id);
428 let subpatterns = fields
429 .iter()
430 .map(|field| {
431 let mut pattern = *self.lower_pattern(field.pat);
432 if let PatKind::Binding { ref mut is_shorthand, .. } = pattern.kind {
433 *is_shorthand = field.is_shorthand;
434 }
435 let field = self.typeck_results.field_index(field.hir_id);
436 FieldPat { field, pattern }
437 })
438 .collect();
439
440 return self.lower_variant_or_leaf(pat, None, res, subpatterns);
441 }
442
443 hir::PatKind::Or(pats) => PatKind::Or { pats: self.lower_patterns(pats) },
444
445 hir::PatKind::Guard(pat, condition) => PatKind::Guard {
446 subpattern: self.lower_pattern(pat),
447 condition: self.upper.mirror_expr(condition),
448 },
449
450 hir::PatKind::Err(guar) => PatKind::Error(guar),
451 };
452
453 Box::new(Pat { span, ty, kind, extra: None })
456 }
457
458 fn lower_tuple_subpats(
459 &mut self,
460 pats: &'tcx [hir::Pat<'tcx>],
461 expected_len: usize,
462 gap_pos: hir::DotDotPos,
463 ) -> Vec<FieldPat<'tcx>> {
464 pats.iter()
465 .enumerate_and_adjust(expected_len, gap_pos)
466 .map(|(i, subpattern)| FieldPat {
467 field: FieldIdx::new(i),
468 pattern: *self.lower_pattern(subpattern),
469 })
470 .collect()
471 }
472
473 fn lower_patterns(&mut self, pats: &'tcx [hir::Pat<'tcx>]) -> Box<[Pat<'tcx>]> {
474 pats.iter().map(|p| *self.lower_pattern(p)).collect()
475 }
476
477 fn lower_opt_pattern(&mut self, pat: Option<&'tcx hir::Pat<'tcx>>) -> Option<Box<Pat<'tcx>>> {
478 pat.map(|p| self.lower_pattern(p))
479 }
480
481 fn slice_or_array_pattern(
482 &mut self,
483 pat: &'tcx hir::Pat<'tcx>,
484 prefix: &'tcx [hir::Pat<'tcx>],
485 slice: Option<&'tcx hir::Pat<'tcx>>,
486 suffix: &'tcx [hir::Pat<'tcx>],
487 ) -> Box<Pat<'tcx>> {
488 let ty = self.typeck_results.node_type(pat.hir_id);
489 let span = pat.span;
490
491 let prefix = self.lower_patterns(prefix);
492 let slice = self.lower_opt_pattern(slice);
493 let suffix = self.lower_patterns(suffix);
494 let kind = match ty.kind() {
495 ty::Slice(..) => PatKind::Slice { prefix, slice, suffix },
497 ty::Array(_, len) => {
499 let len = len
500 .try_to_target_usize(self.tcx)
501 .expect("expected len of array pat to be definite");
502 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);
503 PatKind::Array { prefix, slice, suffix }
504 }
505 _ => ::rustc_middle::util::bug::span_bug_fmt(span,
format_args!("bad slice pattern type {0:?}", ty))span_bug!(span, "bad slice pattern type {ty:?}"),
506 };
507 Box::new(Pat { ty, span, kind, extra: None })
508 }
509
510 fn lower_variant_or_leaf(
511 &mut self,
512 pat: &'tcx hir::Pat<'tcx>,
513 expr: Option<&'tcx hir::PatExpr<'tcx>>,
514 res: Res,
515 subpatterns: Vec<FieldPat<'tcx>>,
516 ) -> Box<Pat<'tcx>> {
517 {
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!(
519 (pat.kind, expr),
520 (hir::PatKind::Expr(..) | hir::PatKind::Range(..), Some(_))
521 | (hir::PatKind::Struct(..) | hir::PatKind::TupleStruct(..), None)
522 );
523
524 let (hir_id, span) = match expr {
527 Some(expr) => (expr.hir_id, expr.span),
528 None => (pat.hir_id, pat.span),
529 };
530 let ty = self.typeck_results.node_type(hir_id);
531
532 let res = match res {
533 Res::Def(DefKind::Ctor(CtorOf::Variant, ..), variant_ctor_id) => {
534 let variant_id = self.tcx.parent(variant_ctor_id);
535 Res::Def(DefKind::Variant, variant_id)
536 }
537 res => res,
538 };
539
540 let kind = match res {
541 Res::Def(DefKind::Variant, variant_id) => {
542 let enum_id = self.tcx.parent(variant_id);
543 let adt_def = self.tcx.adt_def(enum_id);
544 if adt_def.is_enum() {
545 let args = match ty.kind() {
546 ty::FnDef(_, args) => args.no_bound_vars().unwrap(),
547 ty::Adt(_, args) => args,
548 ty::Error(e) => {
549 return Box::new(Pat {
551 ty,
552 span,
553 kind: PatKind::Error(*e),
554 extra: None,
555 });
556 }
557 _ => ::rustc_middle::util::bug::bug_fmt(format_args!("inappropriate type for def: {0:?}",
ty))bug!("inappropriate type for def: {:?}", ty),
558 };
559 PatKind::Variant {
560 adt_def,
561 args,
562 variant_index: adt_def.variant_index_with_id(variant_id),
563 subpatterns,
564 }
565 } else {
566 PatKind::Leaf { subpatterns }
567 }
568 }
569
570 Res::Def(
571 DefKind::Struct
572 | DefKind::Ctor(CtorOf::Struct, ..)
573 | DefKind::Union
574 | DefKind::TyAlias
575 | DefKind::AssocTy,
576 _,
577 )
578 | Res::SelfTyParam { .. }
579 | Res::SelfTyAlias { .. }
580 | Res::SelfCtor(..) => PatKind::Leaf { subpatterns },
581 _ => {
582 let e = match res {
583 Res::Def(DefKind::ConstParam, def_id) => {
584 let const_span = self.tcx.def_span(def_id);
585 self.tcx.dcx().emit_err(ConstParamInPattern { span, const_span })
586 }
587 Res::Def(DefKind::Static { .. }, def_id) => {
588 let static_span = self.tcx.def_span(def_id);
589 self.tcx.dcx().emit_err(StaticInPattern { span, static_span })
590 }
591 _ => self.tcx.dcx().emit_err(NonConstPath { span }),
592 };
593 PatKind::Error(e)
594 }
595 };
596 let mut thir_pat = Box::new(Pat { ty, span, kind, extra: None });
597
598 if let Some(user_ty) = self.user_args_applied_to_ty_of_hir_id(hir_id) {
599 {
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:599",
"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(599u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_build::thir::pattern"),
::tracing_core::field::FieldSet::new(&["message",
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("thir_pat")
}> =
::tracing::__macro_support::FieldName::new("thir_pat");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("user_ty")
}> =
::tracing::__macro_support::FieldName::new("user_ty");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("span")
}> =
::tracing::__macro_support::FieldName::new("span");
NAME.as_str()
}], ::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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("lower_variant_or_leaf: applying ascription")
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&thir_pat)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&user_ty)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&span)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(?thir_pat, ?user_ty, ?span, "lower_variant_or_leaf: applying ascription");
600 let annotation = CanonicalUserTypeAnnotation {
601 user_ty: Box::new(user_ty),
602 span,
603 inferred_ty: self.typeck_results.node_type(hir_id),
604 };
605 thir_pat
606 .extra
607 .get_or_insert_default()
608 .ascriptions
609 .push(Ascription { annotation, variance: ty::Covariant });
610 }
611
612 thir_pat
613 }
614
615 fn user_args_applied_to_ty_of_hir_id(
616 &self,
617 hir_id: hir::HirId,
618 ) -> Option<ty::CanonicalUserType<'tcx>> {
619 crate::thir::util::user_args_applied_to_ty_of_hir_id(self.tcx, self.typeck_results, hir_id)
620 }
621
622 #[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(625u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_build::thir::pattern"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("pat")
}> =
::tracing::__macro_support::FieldName::new("pat");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("expr")
}> =
::tracing::__macro_support::FieldName::new("expr");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("qpath")
}> =
::tracing::__macro_support::FieldName::new("qpath");
NAME.as_str()
}], ::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};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&pat)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&expr)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&qpath)
as &dyn ::tracing::field::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_alias(self.tcx, ty::IsRigid::No,
ty::AliasConst::new(self.tcx,
ty::AliasConstKind::new_from_def_id(self.tcx, 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")]
626 fn lower_path(
627 &mut self,
628 pat: &'tcx hir::Pat<'tcx>, expr: &'tcx hir::PatExpr<'tcx>,
630 qpath: &hir::QPath<'_>,
631 ) -> Box<Pat<'tcx>> {
632 assert_matches!(pat.kind, hir::PatKind::Expr(..) | hir::PatKind::Range(..));
633
634 let id = expr.hir_id;
635 let span = expr.span;
636 let ty = self.typeck_results.node_type(id);
637 let res = self.typeck_results.qpath_res(qpath, id);
638
639 let (def_id, user_ty) = match res {
640 Res::Def(DefKind::Const { .. }, def_id)
641 | Res::Def(DefKind::AssocConst { .. }, def_id) => {
642 (def_id, self.typeck_results.user_provided_types().get(id))
643 }
644
645 _ => {
646 return self.lower_variant_or_leaf(pat, Some(expr), res, vec![]);
649 }
650 };
651
652 let args = self.typeck_results.node_args(id);
654 let c = ty::Const::new_alias(
657 self.tcx,
658 ty::IsRigid::No,
659 ty::AliasConst::new(
660 self.tcx,
661 ty::AliasConstKind::new_from_def_id(self.tcx, def_id),
662 args,
663 ),
664 );
665 let mut pattern = self.const_to_pat(c, ty, id, span);
666
667 if let Some(&user_ty) = user_ty {
670 let annotation = CanonicalUserTypeAnnotation {
671 user_ty: Box::new(user_ty),
672 span,
673 inferred_ty: self.typeck_results.node_type(id),
674 };
675 pattern
678 .extra
679 .get_or_insert_default()
680 .ascriptions
681 .push(Ascription { annotation, variance: ty::Contravariant });
682 }
683
684 pattern
685 }
686
687 fn lower_pat_expr(
691 &mut self,
692 pat: &'tcx hir::Pat<'tcx>, expr: &'tcx hir::PatExpr<'tcx>,
694 ) -> Box<Pat<'tcx>> {
695 {
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(..));
696 match &expr.kind {
697 hir::PatExprKind::Path(qpath) => self.lower_path(pat, expr, qpath),
698 hir::PatExprKind::Lit { lit, negated } => {
699 let pat_ty = self.typeck_results.node_type(pat.hir_id);
709 let lit_input = LitToConstInput { lit: lit.node, ty: Some(pat_ty), neg: *negated };
710 let constant = const_lit_matches_ty(self.tcx, &lit.node, pat_ty, *negated)
711 .then(|| self.tcx.at(expr.span).lit_to_const(lit_input))
712 .flatten()
713 .map(|v| ty::Const::new_value(self.tcx, v.valtree, pat_ty))
714 .unwrap_or_else(|| {
715 ty::Const::new_error_with_message(
716 self.tcx,
717 expr.span,
718 "literal does not match expected type",
719 )
720 });
721 self.const_to_pat(constant, pat_ty, expr.hir_id, lit.span)
722 }
723 }
724 }
725}