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, 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::{
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::errors::*;
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};
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);
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 box 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(&["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, 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::Box(subpattern) => PatKind::DerefPattern {
356 subpattern: self.lower_pattern(subpattern),
357 borrow: DerefPatBorrowMode::Box,
358 },
359
360 hir::PatKind::Slice(prefix, slice, suffix) => {
361 return self.slice_or_array_pattern(pat, prefix, slice, suffix);
362 }
363
364 hir::PatKind::Tuple(pats, ddpos) => {
365 let ty::Tuple(tys) = ty.kind() else {
366 span_bug!(pat.span, "unexpected type for tuple pattern: {:?}", ty);
367 };
368 let subpatterns = self.lower_tuple_subpats(pats, tys.len(), ddpos);
369 PatKind::Leaf { subpatterns }
370 }
371
372 hir::PatKind::Binding(explicit_ba, id, ident, sub) => {
373 let mut thir_pat_span = span;
374 if let Some(ident_span) = ident.span.find_ancestor_inside(span) {
375 thir_pat_span = span.with_hi(ident_span.hi());
376 }
377
378 let mode = *self
379 .typeck_results
380 .pat_binding_modes()
381 .get(pat.hir_id)
382 .expect("missing binding mode");
383
384 if let Some(s) = &mut self.rust_2024_migration {
385 s.visit_binding(pat.span, mode, explicit_ba, ident);
386 }
387
388 let var_ty = ty;
391 let mut thir_pat_ty = ty;
392 if let hir::ByRef::Yes(pinnedness, _) = mode.0 {
393 match pinnedness {
394 hir::Pinnedness::Pinned
395 if let Some(pty) = ty.pinned_ty()
396 && let &ty::Ref(_, rty, _) = pty.kind() =>
397 {
398 thir_pat_ty = rty;
399 }
400 hir::Pinnedness::Not if let &ty::Ref(_, rty, _) = ty.kind() => {
401 thir_pat_ty = rty;
402 }
403 _ => bug!("`ref {}` has wrong type {}", ident, ty),
404 }
405 };
406
407 let kind = PatKind::Binding {
408 mode,
409 name: ident.name,
410 var: LocalVarId(id),
411 ty: var_ty,
412 subpattern: self.lower_opt_pattern(sub),
413 is_primary: id == pat.hir_id,
414 is_shorthand: false,
415 };
416 return Box::new(Pat { ty: thir_pat_ty, span: thir_pat_span, kind, extra: None });
419 }
420
421 hir::PatKind::TupleStruct(ref qpath, pats, ddpos) => {
422 let res = self.typeck_results.qpath_res(qpath, pat.hir_id);
423 let ty::Adt(adt_def, _) = ty.kind() else {
424 span_bug!(pat.span, "tuple struct pattern not applied to an ADT {:?}", ty);
425 };
426 let variant_def = adt_def.variant_of_res(res);
427 let subpatterns = self.lower_tuple_subpats(pats, variant_def.fields.len(), ddpos);
428 return self.lower_variant_or_leaf(pat, None, res, subpatterns);
429 }
430
431 hir::PatKind::Struct(ref qpath, fields, _) => {
432 let res = self.typeck_results.qpath_res(qpath, pat.hir_id);
433 let subpatterns = fields
434 .iter()
435 .map(|field| {
436 let mut pattern = *self.lower_pattern(field.pat);
437 if let PatKind::Binding { ref mut is_shorthand, .. } = pattern.kind {
438 *is_shorthand = field.is_shorthand;
439 }
440 let field = self.typeck_results.field_index(field.hir_id);
441 FieldPat { field, pattern }
442 })
443 .collect();
444
445 return self.lower_variant_or_leaf(pat, None, res, subpatterns);
446 }
447
448 hir::PatKind::Or(pats) => PatKind::Or { pats: self.lower_patterns(pats) },
449
450 hir::PatKind::Guard(pat, condition) => PatKind::Guard {
451 subpattern: self.lower_pattern(pat),
452 condition: self.upper.mirror_expr(condition),
453 },
454
455 hir::PatKind::Err(guar) => PatKind::Error(guar),
456 };
457
458 Box::new(Pat { span, ty, kind, extra: None })
461 }
462
463 fn lower_tuple_subpats(
464 &mut self,
465 pats: &'tcx [hir::Pat<'tcx>],
466 expected_len: usize,
467 gap_pos: hir::DotDotPos,
468 ) -> Vec<FieldPat<'tcx>> {
469 pats.iter()
470 .enumerate_and_adjust(expected_len, gap_pos)
471 .map(|(i, subpattern)| FieldPat {
472 field: FieldIdx::new(i),
473 pattern: *self.lower_pattern(subpattern),
474 })
475 .collect()
476 }
477
478 fn lower_patterns(&mut self, pats: &'tcx [hir::Pat<'tcx>]) -> Box<[Pat<'tcx>]> {
479 pats.iter().map(|p| *self.lower_pattern(p)).collect()
480 }
481
482 fn lower_opt_pattern(&mut self, pat: Option<&'tcx hir::Pat<'tcx>>) -> Option<Box<Pat<'tcx>>> {
483 pat.map(|p| self.lower_pattern(p))
484 }
485
486 fn slice_or_array_pattern(
487 &mut self,
488 pat: &'tcx hir::Pat<'tcx>,
489 prefix: &'tcx [hir::Pat<'tcx>],
490 slice: Option<&'tcx hir::Pat<'tcx>>,
491 suffix: &'tcx [hir::Pat<'tcx>],
492 ) -> Box<Pat<'tcx>> {
493 let ty = self.typeck_results.node_type(pat.hir_id);
494 let span = pat.span;
495
496 let prefix = self.lower_patterns(prefix);
497 let slice = self.lower_opt_pattern(slice);
498 let suffix = self.lower_patterns(suffix);
499 let kind = match ty.kind() {
500 ty::Slice(..) => PatKind::Slice { prefix, slice, suffix },
502 ty::Array(_, len) => {
504 let len = len
505 .try_to_target_usize(self.tcx)
506 .expect("expected len of array pat to be definite");
507 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);
508 PatKind::Array { prefix, slice, suffix }
509 }
510 _ => ::rustc_middle::util::bug::span_bug_fmt(span,
format_args!("bad slice pattern type {0:?}", ty))span_bug!(span, "bad slice pattern type {ty:?}"),
511 };
512 Box::new(Pat { ty, span, kind, extra: None })
513 }
514
515 fn lower_variant_or_leaf(
516 &mut self,
517 pat: &'tcx hir::Pat<'tcx>,
518 expr: Option<&'tcx hir::PatExpr<'tcx>>,
519 res: Res,
520 subpatterns: Vec<FieldPat<'tcx>>,
521 ) -> Box<Pat<'tcx>> {
522 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!(
524 (pat.kind, expr),
525 (hir::PatKind::Expr(..) | hir::PatKind::Range(..), Some(_))
526 | (hir::PatKind::Struct(..) | hir::PatKind::TupleStruct(..), None)
527 );
528
529 let (hir_id, span) = match expr {
532 Some(expr) => (expr.hir_id, expr.span),
533 None => (pat.hir_id, pat.span),
534 };
535 let ty = self.typeck_results.node_type(hir_id);
536
537 let res = match res {
538 Res::Def(DefKind::Ctor(CtorOf::Variant, ..), variant_ctor_id) => {
539 let variant_id = self.tcx.parent(variant_ctor_id);
540 Res::Def(DefKind::Variant, variant_id)
541 }
542 res => res,
543 };
544
545 let kind = match res {
546 Res::Def(DefKind::Variant, variant_id) => {
547 let enum_id = self.tcx.parent(variant_id);
548 let adt_def = self.tcx.adt_def(enum_id);
549 if adt_def.is_enum() {
550 let args = match ty.kind() {
551 ty::Adt(_, args) | ty::FnDef(_, args) => args,
552 ty::Error(e) => {
553 return Box::new(Pat {
555 ty,
556 span,
557 kind: PatKind::Error(*e),
558 extra: None,
559 });
560 }
561 _ => ::rustc_middle::util::bug::bug_fmt(format_args!("inappropriate type for def: {0:?}",
ty))bug!("inappropriate type for def: {:?}", ty),
562 };
563 PatKind::Variant {
564 adt_def,
565 args,
566 variant_index: adt_def.variant_index_with_id(variant_id),
567 subpatterns,
568 }
569 } else {
570 PatKind::Leaf { subpatterns }
571 }
572 }
573
574 Res::Def(
575 DefKind::Struct
576 | DefKind::Ctor(CtorOf::Struct, ..)
577 | DefKind::Union
578 | DefKind::TyAlias
579 | DefKind::AssocTy,
580 _,
581 )
582 | Res::SelfTyParam { .. }
583 | Res::SelfTyAlias { .. }
584 | Res::SelfCtor(..) => PatKind::Leaf { subpatterns },
585 _ => {
586 let e = match res {
587 Res::Def(DefKind::ConstParam, def_id) => {
588 let const_span = self.tcx.def_span(def_id);
589 self.tcx.dcx().emit_err(ConstParamInPattern { span, const_span })
590 }
591 Res::Def(DefKind::Static { .. }, def_id) => {
592 let static_span = self.tcx.def_span(def_id);
593 self.tcx.dcx().emit_err(StaticInPattern { span, static_span })
594 }
595 _ => self.tcx.dcx().emit_err(NonConstPath { span }),
596 };
597 PatKind::Error(e)
598 }
599 };
600 let mut thir_pat = Box::new(Pat { ty, span, kind, extra: None });
601
602 if let Some(user_ty) = self.user_args_applied_to_ty_of_hir_id(hir_id) {
603 {
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:603",
"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(603u32),
::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");
604 let annotation = CanonicalUserTypeAnnotation {
605 user_ty: Box::new(user_ty),
606 span,
607 inferred_ty: self.typeck_results.node_type(hir_id),
608 };
609 thir_pat
610 .extra
611 .get_or_insert_default()
612 .ascriptions
613 .push(Ascription { annotation, variance: ty::Covariant });
614 }
615
616 thir_pat
617 }
618
619 fn user_args_applied_to_ty_of_hir_id(
620 &self,
621 hir_id: hir::HirId,
622 ) -> Option<ty::CanonicalUserType<'tcx>> {
623 crate::thir::util::user_args_applied_to_ty_of_hir_id(self.tcx, self.typeck_results, hir_id)
624 }
625
626 #[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(629u32),
::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")]
630 fn lower_path(
631 &mut self,
632 pat: &'tcx hir::Pat<'tcx>, expr: &'tcx hir::PatExpr<'tcx>,
634 qpath: &hir::QPath<'_>,
635 ) -> Box<Pat<'tcx>> {
636 assert_matches!(pat.kind, hir::PatKind::Expr(..) | hir::PatKind::Range(..));
637
638 let id = expr.hir_id;
639 let span = expr.span;
640 let ty = self.typeck_results.node_type(id);
641 let res = self.typeck_results.qpath_res(qpath, id);
642
643 let (def_id, user_ty) = match res {
644 Res::Def(DefKind::Const { .. }, def_id)
645 | Res::Def(DefKind::AssocConst { .. }, def_id) => {
646 (def_id, self.typeck_results.user_provided_types().get(id))
647 }
648
649 _ => {
650 return self.lower_variant_or_leaf(pat, Some(expr), res, vec![]);
653 }
654 };
655
656 let args = self.typeck_results.node_args(id);
658 let c = ty::Const::new_unevaluated(self.tcx, ty::UnevaluatedConst { def: def_id, args });
661 let mut pattern = self.const_to_pat(c, ty, id, span);
662
663 if let Some(&user_ty) = user_ty {
666 let annotation = CanonicalUserTypeAnnotation {
667 user_ty: Box::new(user_ty),
668 span,
669 inferred_ty: self.typeck_results.node_type(id),
670 };
671 pattern
674 .extra
675 .get_or_insert_default()
676 .ascriptions
677 .push(Ascription { annotation, variance: ty::Contravariant });
678 }
679
680 pattern
681 }
682
683 fn lower_pat_expr(
687 &mut self,
688 pat: &'tcx hir::Pat<'tcx>, expr: &'tcx hir::PatExpr<'tcx>,
690 ) -> Box<Pat<'tcx>> {
691 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(..));
692 match &expr.kind {
693 hir::PatExprKind::Path(qpath) => self.lower_path(pat, expr, qpath),
694 hir::PatExprKind::Lit { lit, negated } => {
695 let pat_ty = self.typeck_results.node_type(pat.hir_id);
705 let lit_input = LitToConstInput { lit: lit.node, ty: Some(pat_ty), neg: *negated };
706 let constant = const_lit_matches_ty(self.tcx, &lit.node, pat_ty, *negated)
707 .then(|| self.tcx.at(expr.span).lit_to_const(lit_input))
708 .flatten()
709 .map(|v| ty::Const::new_value(self.tcx, v.valtree, pat_ty))
710 .unwrap_or_else(|| {
711 ty::Const::new_error_with_message(
712 self.tcx,
713 expr.span,
714 "literal does not match expected type",
715 )
716 });
717 self.const_to_pat(constant, pat_ty, expr.hir_id, lit.span)
718 }
719 }
720 }
721}