rustc_middle/thir.rs
1//! THIR datatypes and definitions. See the [rustc dev guide] for more info.
2//!
3//! If you compare the THIR [`ExprKind`] to [`hir::ExprKind`], you will see it is
4//! a good bit simpler. In fact, a number of the more straight-forward
5//! MIR simplifications are already done in the lowering to THIR. For
6//! example, method calls and overloaded operators are absent: they are
7//! expected to be converted into [`ExprKind::Call`] instances.
8//!
9//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/thir.html
10
11use std::cmp::Ordering;
12use std::fmt;
13use std::ops::Index;
14use std::sync::Arc;
15
16use rustc_abi::{FieldIdx, Integer, Size, VariantIdx};
17use rustc_ast::{AsmMacro, InlineAsmOptions, InlineAsmTemplatePiece};
18use rustc_hir as hir;
19use rustc_hir::def_id::DefId;
20use rustc_hir::{BindingMode, ByRef, HirId, MatchSource, RangeEnd};
21use rustc_index::{IndexVec, newtype_index};
22use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeVisitable};
23use rustc_span::def_id::LocalDefId;
24use rustc_span::{ErrorGuaranteed, Span, Symbol};
25use rustc_target::asm::InlineAsmRegOrRegClass;
26use tracing::instrument;
27
28use crate::middle::region;
29use crate::mir::interpret::AllocId;
30use crate::mir::{
31 self, AssignOp, BackwardIncompatibleDropReason, BinOp, BorrowKind, FakeReadCause, UnOp,
32};
33use crate::thir::visit::for_each_immediate_subpat;
34use crate::ty::adjustment::PointerCoercion;
35use crate::ty::layout::IntegerExt;
36use crate::ty::{
37 self, AdtDef, CanonicalUserType, CanonicalUserTypeAnnotation, FnSig, GenericArgsRef, List, Ty,
38 TyCtxt, UpvarArgs,
39};
40
41pub mod visit;
42
43macro_rules! thir_with_elements {
44 (
45 $($name:ident: $id:ty => $value:ty => $format:literal,)*
46 ) => {
47 $(
48 newtype_index! {
49 #[derive(HashStable)]
50 #[debug_format = $format]
51 pub struct $id {}
52 }
53 )*
54
55 // Note: Making `Thir` implement `Clone` is useful for external tools that need access to
56 // THIR bodies even after the `Steal` query result has been stolen.
57 // One such tool is https://github.com/rust-corpus/qrates/.
58 /// A container for a THIR body.
59 ///
60 /// This can be indexed directly by any THIR index (e.g. [`ExprId`]).
61 #[derive(Debug, HashStable, Clone)]
62 pub struct Thir<'tcx> {
63 pub body_type: BodyTy<'tcx>,
64 $(
65 pub $name: IndexVec<$id, $value>,
66 )*
67 }
68
69 impl<'tcx> Thir<'tcx> {
70 pub fn new(body_type: BodyTy<'tcx>) -> Thir<'tcx> {
71 Thir {
72 body_type,
73 $(
74 $name: IndexVec::new(),
75 )*
76 }
77 }
78 }
79
80 $(
81 impl<'tcx> Index<$id> for Thir<'tcx> {
82 type Output = $value;
83 fn index(&self, index: $id) -> &Self::Output {
84 &self.$name[index]
85 }
86 }
87 )*
88 }
89}
90
91thir_with_elements! {
92 arms: ArmId => Arm<'tcx> => "a{}",
93 blocks: BlockId => Block => "b{}",
94 exprs: ExprId => Expr<'tcx> => "e{}",
95 stmts: StmtId => Stmt<'tcx> => "s{}",
96 params: ParamId => Param<'tcx> => "p{}",
97}
98
99#[derive(Debug, HashStable, Clone)]
100pub enum BodyTy<'tcx> {
101 Const(Ty<'tcx>),
102 Fn(FnSig<'tcx>),
103 GlobalAsm(Ty<'tcx>),
104}
105
106/// Description of a type-checked function parameter.
107#[derive(Clone, Debug, HashStable)]
108pub struct Param<'tcx> {
109 /// The pattern that appears in the parameter list, or None for implicit parameters.
110 pub pat: Option<Box<Pat<'tcx>>>,
111 /// The possibly inferred type.
112 pub ty: Ty<'tcx>,
113 /// Span of the explicitly provided type, or None if inferred for closures.
114 pub ty_span: Option<Span>,
115 /// Whether this param is `self`, and how it is bound.
116 pub self_kind: Option<hir::ImplicitSelfKind>,
117 /// HirId for lints.
118 pub hir_id: Option<HirId>,
119}
120
121#[derive(Copy, Clone, Debug, HashStable)]
122pub enum LintLevel {
123 Inherited,
124 Explicit(HirId),
125}
126
127#[derive(Clone, Debug, HashStable)]
128pub struct Block {
129 /// Whether the block itself has a label. Used by `label: {}`
130 /// and `try` blocks.
131 ///
132 /// This does *not* include labels on loops, e.g. `'label: loop {}`.
133 pub targeted_by_break: bool,
134 pub region_scope: region::Scope,
135 /// The span of the block, including the opening braces,
136 /// the label, and the `unsafe` keyword, if present.
137 pub span: Span,
138 /// The statements in the blocK.
139 pub stmts: Box<[StmtId]>,
140 /// The trailing expression of the block, if any.
141 pub expr: Option<ExprId>,
142 pub safety_mode: BlockSafety,
143}
144
145type UserTy<'tcx> = Option<Box<CanonicalUserType<'tcx>>>;
146
147#[derive(Clone, Debug, HashStable)]
148pub struct AdtExpr<'tcx> {
149 /// The ADT we're constructing.
150 pub adt_def: AdtDef<'tcx>,
151 /// The variant of the ADT.
152 pub variant_index: VariantIdx,
153 pub args: GenericArgsRef<'tcx>,
154
155 /// Optional user-given args: for something like `let x =
156 /// Bar::<T> { ... }`.
157 pub user_ty: UserTy<'tcx>,
158
159 pub fields: Box<[FieldExpr]>,
160 /// The base, e.g. `Foo {x: 1, ..base}`.
161 pub base: AdtExprBase<'tcx>,
162}
163
164#[derive(Clone, Debug, HashStable)]
165pub enum AdtExprBase<'tcx> {
166 /// A struct expression where all the fields are explicitly enumerated: `Foo { a, b }`.
167 None,
168 /// A struct expression with a "base", an expression of the same type as the outer struct that
169 /// will be used to populate any fields not explicitly mentioned: `Foo { ..base }`
170 Base(FruInfo<'tcx>),
171 /// A struct expression with a `..` tail but no "base" expression. The values from the struct
172 /// fields' default values will be used to populate any fields not explicitly mentioned:
173 /// `Foo { .. }`.
174 DefaultFields(Box<[Ty<'tcx>]>),
175}
176
177#[derive(Clone, Debug, HashStable)]
178pub struct ClosureExpr<'tcx> {
179 pub closure_id: LocalDefId,
180 pub args: UpvarArgs<'tcx>,
181 pub upvars: Box<[ExprId]>,
182 pub movability: Option<hir::Movability>,
183 pub fake_reads: Vec<(ExprId, FakeReadCause, HirId)>,
184}
185
186#[derive(Clone, Debug, HashStable)]
187pub struct InlineAsmExpr<'tcx> {
188 pub asm_macro: AsmMacro,
189 pub template: &'tcx [InlineAsmTemplatePiece],
190 pub operands: Box<[InlineAsmOperand<'tcx>]>,
191 pub options: InlineAsmOptions,
192 pub line_spans: &'tcx [Span],
193}
194
195#[derive(Copy, Clone, Debug, HashStable)]
196pub enum BlockSafety {
197 Safe,
198 /// A compiler-generated unsafe block
199 BuiltinUnsafe,
200 /// An `unsafe` block. The `HirId` is the ID of the block.
201 ExplicitUnsafe(HirId),
202}
203
204#[derive(Clone, Debug, HashStable)]
205pub struct Stmt<'tcx> {
206 pub kind: StmtKind<'tcx>,
207}
208
209#[derive(Clone, Debug, HashStable)]
210pub enum StmtKind<'tcx> {
211 /// An expression with a trailing semicolon.
212 Expr {
213 /// The scope for this statement; may be used as lifetime of temporaries.
214 scope: region::Scope,
215
216 /// The expression being evaluated in this statement.
217 expr: ExprId,
218 },
219
220 /// A `let` binding.
221 Let {
222 /// The scope for variables bound in this `let`; it covers this and
223 /// all the remaining statements in the block.
224 remainder_scope: region::Scope,
225
226 /// The scope for the initialization itself; might be used as
227 /// lifetime of temporaries.
228 init_scope: region::Scope,
229
230 /// `let <PAT> = ...`
231 ///
232 /// If a type annotation is included, it is added as an ascription pattern.
233 pattern: Box<Pat<'tcx>>,
234
235 /// `let pat: ty = <INIT>`
236 initializer: Option<ExprId>,
237
238 /// `let pat: ty = <INIT> else { <ELSE> }`
239 else_block: Option<BlockId>,
240
241 /// The lint level for this `let` statement.
242 lint_level: LintLevel,
243
244 /// Span of the `let <PAT> = <INIT>` part.
245 span: Span,
246 },
247}
248
249#[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)]
250pub struct LocalVarId(pub HirId);
251
252/// A THIR expression.
253#[derive(Clone, Debug, HashStable)]
254pub struct Expr<'tcx> {
255 /// kind of expression
256 pub kind: ExprKind<'tcx>,
257
258 /// The type of this expression
259 pub ty: Ty<'tcx>,
260
261 /// The lifetime of this expression if it should be spilled into a
262 /// temporary
263 pub temp_lifetime: TempLifetime,
264
265 /// span of the expression in the source
266 pub span: Span,
267}
268
269/// Temporary lifetime information for THIR expressions
270#[derive(Clone, Copy, Debug, HashStable)]
271pub struct TempLifetime {
272 /// Lifetime for temporaries as expected.
273 /// This should be `None` in a constant context.
274 pub temp_lifetime: Option<region::Scope>,
275 /// If `Some(lt)`, indicates that the lifetime of this temporary will change to `lt` in a future edition.
276 /// If `None`, then no changes are expected, or lints are disabled.
277 pub backwards_incompatible: Option<(region::Scope, BackwardIncompatibleDropReason)>,
278}
279
280#[derive(Clone, Debug, HashStable)]
281pub enum ExprKind<'tcx> {
282 /// `Scope`s are used to explicitly mark destruction scopes,
283 /// and to track the `HirId` of the expressions within the scope.
284 Scope {
285 region_scope: region::Scope,
286 lint_level: LintLevel,
287 value: ExprId,
288 },
289 /// A `box <value>` expression.
290 Box {
291 value: ExprId,
292 },
293 /// An `if` expression.
294 If {
295 if_then_scope: region::Scope,
296 cond: ExprId,
297 /// `then` is always `ExprKind::Block`.
298 then: ExprId,
299 /// If present, the `else_opt` expr is always `ExprKind::Block` (for
300 /// `else`) or `ExprKind::If` (for `else if`).
301 else_opt: Option<ExprId>,
302 },
303 /// A function call. Method calls and overloaded operators are converted to plain function calls.
304 Call {
305 /// The type of the function. This is often a [`FnDef`] or a [`FnPtr`].
306 ///
307 /// [`FnDef`]: ty::TyKind::FnDef
308 /// [`FnPtr`]: ty::TyKind::FnPtr
309 ty: Ty<'tcx>,
310 /// The function itself.
311 fun: ExprId,
312 /// The arguments passed to the function.
313 ///
314 /// Note: in some cases (like calling a closure), the function call `f(...args)` gets
315 /// rewritten as a call to a function trait method (e.g. `FnOnce::call_once(f, (...args))`).
316 args: Box<[ExprId]>,
317 /// Whether this is from an overloaded operator rather than a
318 /// function call from HIR. `true` for overloaded function call.
319 from_hir_call: bool,
320 /// The span of the function, without the dot and receiver
321 /// (e.g. `foo(a, b)` in `x.foo(a, b)`).
322 fn_span: Span,
323 },
324 /// A use expression `x.use`.
325 ByUse {
326 /// The expression on which use is applied.
327 expr: ExprId,
328 /// The span of use, without the dot and receiver
329 /// (e.g. `use` in `x.use`).
330 span: Span,
331 },
332 /// A *non-overloaded* dereference.
333 Deref {
334 arg: ExprId,
335 },
336 /// A *non-overloaded* binary operation.
337 Binary {
338 op: BinOp,
339 lhs: ExprId,
340 rhs: ExprId,
341 },
342 /// A logical operation. This is distinct from `BinaryOp` because
343 /// the operands need to be lazily evaluated.
344 LogicalOp {
345 op: LogicalOp,
346 lhs: ExprId,
347 rhs: ExprId,
348 },
349 /// A *non-overloaded* unary operation. Note that here the deref (`*`)
350 /// operator is represented by `ExprKind::Deref`.
351 Unary {
352 op: UnOp,
353 arg: ExprId,
354 },
355 /// A cast: `<source> as <type>`. The type we cast to is the type of
356 /// the parent expression.
357 Cast {
358 source: ExprId,
359 },
360 /// Forces its contents to be treated as a value expression, not a place
361 /// expression. This is inserted in some places where an operation would
362 /// otherwise be erased completely (e.g. some no-op casts), but we still
363 /// need to ensure that its operand is treated as a value and not a place.
364 Use {
365 source: ExprId,
366 },
367 /// A coercion from `!` to any type.
368 NeverToAny {
369 source: ExprId,
370 },
371 /// A pointer coercion. More information can be found in [`PointerCoercion`].
372 /// Pointer casts that cannot be done by coercions are represented by [`ExprKind::Cast`].
373 PointerCoercion {
374 cast: PointerCoercion,
375 source: ExprId,
376 /// Whether this coercion is written with an `as` cast in the source code.
377 is_from_as_cast: bool,
378 },
379 /// A `loop` expression.
380 Loop {
381 body: ExprId,
382 },
383 /// A `#[loop_match] loop { state = 'blk: { match state { ... } } }` expression.
384 LoopMatch {
385 /// The state variable that is updated.
386 /// The `match_data.scrutinee` is the same variable, but with a different span.
387 state: ExprId,
388 region_scope: region::Scope,
389 match_data: Box<LoopMatchMatchData>,
390 },
391 /// Special expression representing the `let` part of an `if let` or similar construct
392 /// (including `if let` guards in match arms, and let-chains formed by `&&`).
393 ///
394 /// This isn't considered a real expression in surface Rust syntax, so it can
395 /// only appear in specific situations, such as within the condition of an `if`.
396 ///
397 /// (Not to be confused with [`StmtKind::Let`], which is a normal `let` statement.)
398 Let {
399 expr: ExprId,
400 pat: Box<Pat<'tcx>>,
401 },
402 /// A `match` expression.
403 Match {
404 scrutinee: ExprId,
405 arms: Box<[ArmId]>,
406 match_source: MatchSource,
407 },
408 /// A block.
409 Block {
410 block: BlockId,
411 },
412 /// An assignment: `lhs = rhs`.
413 Assign {
414 lhs: ExprId,
415 rhs: ExprId,
416 },
417 /// A *non-overloaded* operation assignment, e.g. `lhs += rhs`.
418 AssignOp {
419 op: AssignOp,
420 lhs: ExprId,
421 rhs: ExprId,
422 },
423 /// Access to a field of a struct, a tuple, an union, or an enum.
424 Field {
425 lhs: ExprId,
426 /// Variant containing the field.
427 variant_index: VariantIdx,
428 /// This can be a named (`.foo`) or unnamed (`.0`) field.
429 name: FieldIdx,
430 },
431 /// A *non-overloaded* indexing operation.
432 Index {
433 lhs: ExprId,
434 index: ExprId,
435 },
436 /// A local variable.
437 VarRef {
438 id: LocalVarId,
439 },
440 /// Used to represent upvars mentioned in a closure/coroutine
441 UpvarRef {
442 /// DefId of the closure/coroutine
443 closure_def_id: DefId,
444
445 /// HirId of the root variable
446 var_hir_id: LocalVarId,
447 },
448 /// A borrow, e.g. `&arg`.
449 Borrow {
450 borrow_kind: BorrowKind,
451 arg: ExprId,
452 },
453 /// A `&raw [const|mut] $place_expr` raw borrow resulting in type `*[const|mut] T`.
454 RawBorrow {
455 mutability: hir::Mutability,
456 arg: ExprId,
457 },
458 /// A `break` expression.
459 Break {
460 label: region::Scope,
461 value: Option<ExprId>,
462 },
463 /// A `continue` expression.
464 Continue {
465 label: region::Scope,
466 },
467 /// A `#[const_continue] break` expression.
468 ConstContinue {
469 label: region::Scope,
470 value: ExprId,
471 },
472 /// A `return` expression.
473 Return {
474 value: Option<ExprId>,
475 },
476 /// A `become` expression.
477 Become {
478 value: ExprId,
479 },
480 /// An inline `const` block, e.g. `const {}`.
481 ConstBlock {
482 did: DefId,
483 args: GenericArgsRef<'tcx>,
484 },
485 /// An array literal constructed from one repeated element, e.g. `[1; 5]`.
486 Repeat {
487 value: ExprId,
488 count: ty::Const<'tcx>,
489 },
490 /// An array, e.g. `[a, b, c, d]`.
491 Array {
492 fields: Box<[ExprId]>,
493 },
494 /// A tuple, e.g. `(a, b, c, d)`.
495 Tuple {
496 fields: Box<[ExprId]>,
497 },
498 /// An ADT constructor, e.g. `Foo {x: 1, y: 2}`.
499 Adt(Box<AdtExpr<'tcx>>),
500 /// A type ascription on a place.
501 PlaceTypeAscription {
502 source: ExprId,
503 /// Type that the user gave to this expression
504 user_ty: UserTy<'tcx>,
505 user_ty_span: Span,
506 },
507 /// A type ascription on a value, e.g. `type_ascribe!(42, i32)` or `42 as i32`.
508 ValueTypeAscription {
509 source: ExprId,
510 /// Type that the user gave to this expression
511 user_ty: UserTy<'tcx>,
512 user_ty_span: Span,
513 },
514 /// An unsafe binder cast on a place, e.g. `unwrap_binder!(*ptr)`.
515 PlaceUnwrapUnsafeBinder {
516 source: ExprId,
517 },
518 /// An unsafe binder cast on a value, e.g. `unwrap_binder!(rvalue())`,
519 /// which makes a temporary.
520 ValueUnwrapUnsafeBinder {
521 source: ExprId,
522 },
523 /// Construct an unsafe binder, e.g. `wrap_binder(&ref)`.
524 WrapUnsafeBinder {
525 source: ExprId,
526 },
527 /// A closure definition.
528 Closure(Box<ClosureExpr<'tcx>>),
529 /// A literal.
530 Literal {
531 lit: hir::Lit,
532 neg: bool,
533 },
534 /// For literals that don't correspond to anything in the HIR
535 NonHirLiteral {
536 lit: ty::ScalarInt,
537 user_ty: UserTy<'tcx>,
538 },
539 /// A literal of a ZST type.
540 ZstLiteral {
541 user_ty: UserTy<'tcx>,
542 },
543 /// Associated constants and named constants
544 NamedConst {
545 def_id: DefId,
546 args: GenericArgsRef<'tcx>,
547 user_ty: UserTy<'tcx>,
548 },
549 ConstParam {
550 param: ty::ParamConst,
551 def_id: DefId,
552 },
553 // FIXME improve docs for `StaticRef` by distinguishing it from `NamedConst`
554 /// A literal containing the address of a `static`.
555 ///
556 /// This is only distinguished from `Literal` so that we can register some
557 /// info for diagnostics.
558 StaticRef {
559 alloc_id: AllocId,
560 ty: Ty<'tcx>,
561 def_id: DefId,
562 },
563 /// Inline assembly, i.e. `asm!()`.
564 InlineAsm(Box<InlineAsmExpr<'tcx>>),
565 /// Field offset (`offset_of!`)
566 OffsetOf {
567 container: Ty<'tcx>,
568 fields: &'tcx List<(VariantIdx, FieldIdx)>,
569 },
570 /// An expression taking a reference to a thread local.
571 ThreadLocalRef(DefId),
572 /// A `yield` expression.
573 Yield {
574 value: ExprId,
575 },
576}
577
578/// Represents the association of a field identifier and an expression.
579///
580/// This is used in struct constructors.
581#[derive(Clone, Debug, HashStable)]
582pub struct FieldExpr {
583 pub name: FieldIdx,
584 pub expr: ExprId,
585}
586
587#[derive(Clone, Debug, HashStable)]
588pub struct FruInfo<'tcx> {
589 pub base: ExprId,
590 pub field_types: Box<[Ty<'tcx>]>,
591}
592
593/// A `match` arm.
594#[derive(Clone, Debug, HashStable)]
595pub struct Arm<'tcx> {
596 pub pattern: Box<Pat<'tcx>>,
597 pub guard: Option<ExprId>,
598 pub body: ExprId,
599 pub lint_level: LintLevel,
600 pub scope: region::Scope,
601 pub span: Span,
602}
603
604/// The `match` part of a `#[loop_match]`
605#[derive(Clone, Debug, HashStable)]
606pub struct LoopMatchMatchData {
607 pub scrutinee: ExprId,
608 pub arms: Box<[ArmId]>,
609 pub span: Span,
610}
611
612#[derive(Copy, Clone, Debug, HashStable)]
613pub enum LogicalOp {
614 /// The `&&` operator.
615 And,
616 /// The `||` operator.
617 Or,
618}
619
620#[derive(Clone, Debug, HashStable)]
621pub enum InlineAsmOperand<'tcx> {
622 In {
623 reg: InlineAsmRegOrRegClass,
624 expr: ExprId,
625 },
626 Out {
627 reg: InlineAsmRegOrRegClass,
628 late: bool,
629 expr: Option<ExprId>,
630 },
631 InOut {
632 reg: InlineAsmRegOrRegClass,
633 late: bool,
634 expr: ExprId,
635 },
636 SplitInOut {
637 reg: InlineAsmRegOrRegClass,
638 late: bool,
639 in_expr: ExprId,
640 out_expr: Option<ExprId>,
641 },
642 Const {
643 value: mir::Const<'tcx>,
644 span: Span,
645 },
646 SymFn {
647 value: ExprId,
648 },
649 SymStatic {
650 def_id: DefId,
651 },
652 Label {
653 block: BlockId,
654 },
655}
656
657#[derive(Clone, Debug, HashStable, TypeVisitable)]
658pub struct FieldPat<'tcx> {
659 pub field: FieldIdx,
660 pub pattern: Pat<'tcx>,
661}
662
663#[derive(Clone, Debug, HashStable, TypeVisitable)]
664pub struct Pat<'tcx> {
665 pub ty: Ty<'tcx>,
666 pub span: Span,
667 pub kind: PatKind<'tcx>,
668}
669
670impl<'tcx> Pat<'tcx> {
671 pub fn simple_ident(&self) -> Option<Symbol> {
672 match self.kind {
673 PatKind::Binding {
674 name, mode: BindingMode(ByRef::No, _), subpattern: None, ..
675 } => Some(name),
676 _ => None,
677 }
678 }
679
680 /// Call `f` on every "binding" in a pattern, e.g., on `a` in
681 /// `match foo() { Some(a) => (), None => () }`
682 pub fn each_binding(&self, mut f: impl FnMut(Symbol, ByRef, Ty<'tcx>, Span)) {
683 self.walk_always(|p| {
684 if let PatKind::Binding { name, mode, ty, .. } = p.kind {
685 f(name, mode.0, ty, p.span);
686 }
687 });
688 }
689
690 /// Walk the pattern in left-to-right order.
691 ///
692 /// If `it(pat)` returns `false`, the children are not visited.
693 pub fn walk(&self, mut it: impl FnMut(&Pat<'tcx>) -> bool) {
694 self.walk_(&mut it)
695 }
696
697 fn walk_(&self, it: &mut impl FnMut(&Pat<'tcx>) -> bool) {
698 if !it(self) {
699 return;
700 }
701
702 for_each_immediate_subpat(self, |p| p.walk_(it));
703 }
704
705 /// Whether the pattern has a `PatKind::Error` nested within.
706 pub fn pat_error_reported(&self) -> Result<(), ErrorGuaranteed> {
707 let mut error = None;
708 self.walk(|pat| {
709 if let PatKind::Error(e) = pat.kind
710 && error.is_none()
711 {
712 error = Some(e);
713 }
714 error.is_none()
715 });
716 match error {
717 None => Ok(()),
718 Some(e) => Err(e),
719 }
720 }
721
722 /// Walk the pattern in left-to-right order.
723 ///
724 /// If you always want to recurse, prefer this method over `walk`.
725 pub fn walk_always(&self, mut it: impl FnMut(&Pat<'tcx>)) {
726 self.walk(|p| {
727 it(p);
728 true
729 })
730 }
731
732 /// Whether this a never pattern.
733 pub fn is_never_pattern(&self) -> bool {
734 let mut is_never_pattern = false;
735 self.walk(|pat| match &pat.kind {
736 PatKind::Never => {
737 is_never_pattern = true;
738 false
739 }
740 PatKind::Or { pats } => {
741 is_never_pattern = pats.iter().all(|p| p.is_never_pattern());
742 false
743 }
744 _ => true,
745 });
746 is_never_pattern
747 }
748}
749
750#[derive(Clone, Debug, HashStable, TypeVisitable)]
751pub struct Ascription<'tcx> {
752 pub annotation: CanonicalUserTypeAnnotation<'tcx>,
753 /// Variance to use when relating the `user_ty` to the **type of the value being
754 /// matched**. Typically, this is `Variance::Covariant`, since the value being matched must
755 /// have a type that is some subtype of the ascribed type.
756 ///
757 /// Note that this variance does not apply for any bindings within subpatterns. The type
758 /// assigned to those bindings must be exactly equal to the `user_ty` given here.
759 ///
760 /// The only place where this field is not `Covariant` is when matching constants, where
761 /// we currently use `Contravariant` -- this is because the constant type just needs to
762 /// be "comparable" to the type of the input value. So, for example:
763 ///
764 /// ```text
765 /// match x { "foo" => .. }
766 /// ```
767 ///
768 /// requires that `&'static str <: T_x`, where `T_x` is the type of `x`. Really, we should
769 /// probably be checking for a `PartialEq` impl instead, but this preserves the behavior
770 /// of the old type-check for now. See #57280 for details.
771 pub variance: ty::Variance,
772}
773
774#[derive(Clone, Debug, HashStable, TypeVisitable)]
775pub enum PatKind<'tcx> {
776 /// A missing pattern, e.g. for an anonymous param in a bare fn like `fn f(u32)`.
777 Missing,
778
779 /// A wildcard pattern: `_`.
780 Wild,
781
782 AscribeUserType {
783 ascription: Ascription<'tcx>,
784 subpattern: Box<Pat<'tcx>>,
785 },
786
787 /// `x`, `ref x`, `x @ P`, etc.
788 Binding {
789 name: Symbol,
790 #[type_visitable(ignore)]
791 mode: BindingMode,
792 #[type_visitable(ignore)]
793 var: LocalVarId,
794 ty: Ty<'tcx>,
795 subpattern: Option<Box<Pat<'tcx>>>,
796
797 /// Is this the leftmost occurrence of the binding, i.e., is `var` the
798 /// `HirId` of this pattern?
799 ///
800 /// (The same binding can occur multiple times in different branches of
801 /// an or-pattern, but only one of them will be primary.)
802 is_primary: bool,
803 },
804
805 /// `Foo(...)` or `Foo{...}` or `Foo`, where `Foo` is a variant name from an ADT with
806 /// multiple variants.
807 Variant {
808 adt_def: AdtDef<'tcx>,
809 args: GenericArgsRef<'tcx>,
810 variant_index: VariantIdx,
811 subpatterns: Vec<FieldPat<'tcx>>,
812 },
813
814 /// `(...)`, `Foo(...)`, `Foo{...}`, or `Foo`, where `Foo` is a variant name from an ADT with
815 /// a single variant.
816 Leaf {
817 subpatterns: Vec<FieldPat<'tcx>>,
818 },
819
820 /// `box P`, `&P`, `&mut P`, etc.
821 Deref {
822 subpattern: Box<Pat<'tcx>>,
823 },
824
825 /// Deref pattern, written `box P` for now.
826 DerefPattern {
827 subpattern: Box<Pat<'tcx>>,
828 /// Whether the pattern scrutinee needs to be borrowed in order to call `Deref::deref` or
829 /// `DerefMut::deref_mut`, and if so, which. This is `ByRef::No` for deref patterns on
830 /// boxes; they are lowered using a built-in deref rather than a method call, thus they
831 /// don't borrow the scrutinee.
832 #[type_visitable(ignore)]
833 borrow: ByRef,
834 },
835
836 /// One of the following:
837 /// * `&str`, which will be handled as a string pattern and thus
838 /// exhaustiveness checking will detect if you use the same string twice in different
839 /// patterns.
840 /// * integer, bool, char or float, which will be handled by
841 /// exhaustiveness to cover exactly its own value, similar to `&str`, but these values are
842 /// much simpler.
843 /// * raw pointers derived from integers, other raw pointers will have already resulted in an
844 // error.
845 /// * `String`, if `string_deref_patterns` is enabled.
846 Constant {
847 value: ty::Value<'tcx>,
848 },
849
850 /// Pattern obtained by converting a constant (inline or named) to its pattern
851 /// representation using `const_to_pat`. This is used for unsafety checking.
852 ExpandedConstant {
853 /// [DefId] of the constant item.
854 def_id: DefId,
855 /// The pattern that the constant lowered to.
856 ///
857 /// HACK: we need to keep the `DefId` of inline constants around for unsafety checking;
858 /// therefore when a range pattern contains inline constants, we re-wrap the range pattern
859 /// with the `ExpandedConstant` nodes that correspond to the range endpoints. Hence
860 /// `subpattern` may actually be a range pattern, and `def_id` be the constant for one of
861 /// its endpoints.
862 subpattern: Box<Pat<'tcx>>,
863 },
864
865 Range(Arc<PatRange<'tcx>>),
866
867 /// Matches against a slice, checking the length and extracting elements.
868 /// irrefutable when there is a slice pattern and both `prefix` and `suffix` are empty.
869 /// e.g., `&[ref xs @ ..]`.
870 Slice {
871 prefix: Box<[Pat<'tcx>]>,
872 slice: Option<Box<Pat<'tcx>>>,
873 suffix: Box<[Pat<'tcx>]>,
874 },
875
876 /// Fixed match against an array; irrefutable.
877 Array {
878 prefix: Box<[Pat<'tcx>]>,
879 slice: Option<Box<Pat<'tcx>>>,
880 suffix: Box<[Pat<'tcx>]>,
881 },
882
883 /// An or-pattern, e.g. `p | q`.
884 /// Invariant: `pats.len() >= 2`.
885 Or {
886 pats: Box<[Pat<'tcx>]>,
887 },
888
889 /// A never pattern `!`.
890 Never,
891
892 /// An error has been encountered during lowering. We probably shouldn't report more lints
893 /// related to this pattern.
894 Error(ErrorGuaranteed),
895}
896
897/// A range pattern.
898/// The boundaries must be of the same type and that type must be numeric.
899#[derive(Clone, Debug, PartialEq, HashStable, TypeVisitable)]
900pub struct PatRange<'tcx> {
901 /// Must not be `PosInfinity`.
902 pub lo: PatRangeBoundary<'tcx>,
903 /// Must not be `NegInfinity`.
904 pub hi: PatRangeBoundary<'tcx>,
905 #[type_visitable(ignore)]
906 pub end: RangeEnd,
907 pub ty: Ty<'tcx>,
908}
909
910impl<'tcx> PatRange<'tcx> {
911 /// Whether this range covers the full extent of possible values (best-effort, we ignore floats).
912 #[inline]
913 pub fn is_full_range(&self, tcx: TyCtxt<'tcx>) -> Option<bool> {
914 let (min, max, size, bias) = match *self.ty.kind() {
915 ty::Char => (0, std::char::MAX as u128, Size::from_bits(32), 0),
916 ty::Int(ity) => {
917 let size = Integer::from_int_ty(&tcx, ity).size();
918 let max = size.truncate(u128::MAX);
919 let bias = 1u128 << (size.bits() - 1);
920 (0, max, size, bias)
921 }
922 ty::Uint(uty) => {
923 let size = Integer::from_uint_ty(&tcx, uty).size();
924 let max = size.unsigned_int_max();
925 (0, max, size, 0)
926 }
927 _ => return None,
928 };
929
930 // We want to compare ranges numerically, but the order of the bitwise representation of
931 // signed integers does not match their numeric order. Thus, to correct the ordering, we
932 // need to shift the range of signed integers to correct the comparison. This is achieved by
933 // XORing with a bias (see pattern/deconstruct_pat.rs for another pertinent example of this
934 // pattern).
935 //
936 // Also, for performance, it's important to only do the second `try_to_bits` if necessary.
937 let lo_is_min = match self.lo {
938 PatRangeBoundary::NegInfinity => true,
939 PatRangeBoundary::Finite(value) => {
940 let lo = value.try_to_scalar_int().unwrap().to_bits(size) ^ bias;
941 lo <= min
942 }
943 PatRangeBoundary::PosInfinity => false,
944 };
945 if lo_is_min {
946 let hi_is_max = match self.hi {
947 PatRangeBoundary::NegInfinity => false,
948 PatRangeBoundary::Finite(value) => {
949 let hi = value.try_to_scalar_int().unwrap().to_bits(size) ^ bias;
950 hi > max || hi == max && self.end == RangeEnd::Included
951 }
952 PatRangeBoundary::PosInfinity => true,
953 };
954 if hi_is_max {
955 return Some(true);
956 }
957 }
958 Some(false)
959 }
960
961 #[inline]
962 pub fn contains(&self, value: ty::Value<'tcx>, tcx: TyCtxt<'tcx>) -> Option<bool> {
963 use Ordering::*;
964 debug_assert_eq!(value.ty, self.ty);
965 let ty = self.ty;
966 let value = PatRangeBoundary::Finite(value.valtree);
967 // For performance, it's important to only do the second comparison if necessary.
968 Some(
969 match self.lo.compare_with(value, ty, tcx)? {
970 Less | Equal => true,
971 Greater => false,
972 } && match value.compare_with(self.hi, ty, tcx)? {
973 Less => true,
974 Equal => self.end == RangeEnd::Included,
975 Greater => false,
976 },
977 )
978 }
979
980 #[inline]
981 pub fn overlaps(&self, other: &Self, tcx: TyCtxt<'tcx>) -> Option<bool> {
982 use Ordering::*;
983 debug_assert_eq!(self.ty, other.ty);
984 // For performance, it's important to only do the second comparison if necessary.
985 Some(
986 match other.lo.compare_with(self.hi, self.ty, tcx)? {
987 Less => true,
988 Equal => self.end == RangeEnd::Included,
989 Greater => false,
990 } && match self.lo.compare_with(other.hi, self.ty, tcx)? {
991 Less => true,
992 Equal => other.end == RangeEnd::Included,
993 Greater => false,
994 },
995 )
996 }
997}
998
999impl<'tcx> fmt::Display for PatRange<'tcx> {
1000 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1001 if let &PatRangeBoundary::Finite(valtree) = &self.lo {
1002 let value = ty::Value { ty: self.ty, valtree };
1003 write!(f, "{value}")?;
1004 }
1005 if let &PatRangeBoundary::Finite(valtree) = &self.hi {
1006 write!(f, "{}", self.end)?;
1007 let value = ty::Value { ty: self.ty, valtree };
1008 write!(f, "{value}")?;
1009 } else {
1010 // `0..` is parsed as an inclusive range, we must display it correctly.
1011 write!(f, "..")?;
1012 }
1013 Ok(())
1014 }
1015}
1016
1017/// A (possibly open) boundary of a range pattern.
1018/// If present, the const must be of a numeric type.
1019#[derive(Copy, Clone, Debug, PartialEq, HashStable, TypeVisitable)]
1020pub enum PatRangeBoundary<'tcx> {
1021 /// The type of this valtree is stored in the surrounding `PatRange`.
1022 Finite(ty::ValTree<'tcx>),
1023 NegInfinity,
1024 PosInfinity,
1025}
1026
1027impl<'tcx> PatRangeBoundary<'tcx> {
1028 #[inline]
1029 pub fn is_finite(self) -> bool {
1030 matches!(self, Self::Finite(..))
1031 }
1032 #[inline]
1033 pub fn as_finite(self) -> Option<ty::ValTree<'tcx>> {
1034 match self {
1035 Self::Finite(value) => Some(value),
1036 Self::NegInfinity | Self::PosInfinity => None,
1037 }
1038 }
1039 pub fn to_bits(self, ty: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> u128 {
1040 match self {
1041 Self::Finite(value) => value.try_to_scalar_int().unwrap().to_bits_unchecked(),
1042 Self::NegInfinity => {
1043 // Unwrap is ok because the type is known to be numeric.
1044 ty.numeric_min_and_max_as_bits(tcx).unwrap().0
1045 }
1046 Self::PosInfinity => {
1047 // Unwrap is ok because the type is known to be numeric.
1048 ty.numeric_min_and_max_as_bits(tcx).unwrap().1
1049 }
1050 }
1051 }
1052
1053 #[instrument(skip(tcx), level = "debug", ret)]
1054 pub fn compare_with(self, other: Self, ty: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> Option<Ordering> {
1055 use PatRangeBoundary::*;
1056 match (self, other) {
1057 // When comparing with infinities, we must remember that `0u8..` and `0u8..=255`
1058 // describe the same range. These two shortcuts are ok, but for the rest we must check
1059 // bit values.
1060 (PosInfinity, PosInfinity) => return Some(Ordering::Equal),
1061 (NegInfinity, NegInfinity) => return Some(Ordering::Equal),
1062
1063 // This code is hot when compiling matches with many ranges. So we
1064 // special-case extraction of evaluated scalars for speed, for types where
1065 // we can do scalar comparisons. E.g. `unicode-normalization` has
1066 // many ranges such as '\u{037A}'..='\u{037F}', and chars can be compared
1067 // in this way.
1068 (Finite(a), Finite(b)) if matches!(ty.kind(), ty::Int(_) | ty::Uint(_) | ty::Char) => {
1069 if let (Some(a), Some(b)) = (a.try_to_scalar_int(), b.try_to_scalar_int()) {
1070 let sz = ty.primitive_size(tcx);
1071 let cmp = match ty.kind() {
1072 ty::Uint(_) | ty::Char => a.to_uint(sz).cmp(&b.to_uint(sz)),
1073 ty::Int(_) => a.to_int(sz).cmp(&b.to_int(sz)),
1074 _ => unreachable!(),
1075 };
1076 return Some(cmp);
1077 }
1078 }
1079 _ => {}
1080 }
1081
1082 let a = self.to_bits(ty, tcx);
1083 let b = other.to_bits(ty, tcx);
1084
1085 match ty.kind() {
1086 ty::Float(ty::FloatTy::F16) => {
1087 use rustc_apfloat::Float;
1088 let a = rustc_apfloat::ieee::Half::from_bits(a);
1089 let b = rustc_apfloat::ieee::Half::from_bits(b);
1090 a.partial_cmp(&b)
1091 }
1092 ty::Float(ty::FloatTy::F32) => {
1093 use rustc_apfloat::Float;
1094 let a = rustc_apfloat::ieee::Single::from_bits(a);
1095 let b = rustc_apfloat::ieee::Single::from_bits(b);
1096 a.partial_cmp(&b)
1097 }
1098 ty::Float(ty::FloatTy::F64) => {
1099 use rustc_apfloat::Float;
1100 let a = rustc_apfloat::ieee::Double::from_bits(a);
1101 let b = rustc_apfloat::ieee::Double::from_bits(b);
1102 a.partial_cmp(&b)
1103 }
1104 ty::Float(ty::FloatTy::F128) => {
1105 use rustc_apfloat::Float;
1106 let a = rustc_apfloat::ieee::Quad::from_bits(a);
1107 let b = rustc_apfloat::ieee::Quad::from_bits(b);
1108 a.partial_cmp(&b)
1109 }
1110 ty::Int(ity) => {
1111 let size = rustc_abi::Integer::from_int_ty(&tcx, *ity).size();
1112 let a = size.sign_extend(a) as i128;
1113 let b = size.sign_extend(b) as i128;
1114 Some(a.cmp(&b))
1115 }
1116 ty::Uint(_) | ty::Char => Some(a.cmp(&b)),
1117 _ => bug!(),
1118 }
1119 }
1120}
1121
1122// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
1123#[cfg(target_pointer_width = "64")]
1124mod size_asserts {
1125 use rustc_data_structures::static_assert_size;
1126
1127 use super::*;
1128 // tidy-alphabetical-start
1129 static_assert_size!(Block, 48);
1130 static_assert_size!(Expr<'_>, 80);
1131 static_assert_size!(ExprKind<'_>, 40);
1132 static_assert_size!(Pat<'_>, 64);
1133 static_assert_size!(PatKind<'_>, 48);
1134 static_assert_size!(Stmt<'_>, 48);
1135 static_assert_size!(StmtKind<'_>, 48);
1136 // tidy-alphabetical-end
1137}