• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
11 use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
12 use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg};
13 use rustc_hir as hir;
14 use rustc_hir::def_id::DefId;
15 use rustc_hir::RangeEnd;
16 use rustc_index::newtype_index;
17 use rustc_index::IndexVec;
18 use rustc_middle::middle::region;
19 use rustc_middle::mir::interpret::AllocId;
20 use rustc_middle::mir::{self, BinOp, BorrowKind, FakeReadCause, Mutability, UnOp};
21 use rustc_middle::ty::adjustment::PointerCoercion;
22 use rustc_middle::ty::subst::SubstsRef;
23 use rustc_middle::ty::{self, AdtDef, FnSig, List, Ty, UpvarSubsts};
24 use rustc_middle::ty::{CanonicalUserType, CanonicalUserTypeAnnotation};
25 use rustc_span::def_id::LocalDefId;
26 use rustc_span::{sym, Span, Symbol, DUMMY_SP};
27 use rustc_target::abi::{FieldIdx, VariantIdx};
28 use rustc_target::asm::InlineAsmRegOrRegClass;
29 use std::fmt;
30 use std::ops::Index;
31 
32 pub mod visit;
33 
34 macro_rules! thir_with_elements {
35     (
36         $($field_name:ident: $field_ty:ty,)*
37 
38     @elements:
39         $($name:ident: $id:ty => $value:ty => $format:literal,)*
40     ) => {
41         $(
42             newtype_index! {
43                 #[derive(HashStable)]
44                 #[debug_format = $format]
45                 pub struct $id {}
46             }
47         )*
48 
49         /// A container for a THIR body.
50         ///
51         /// This can be indexed directly by any THIR index (e.g. [`ExprId`]).
52         #[derive(Debug, HashStable, Clone)]
53         pub struct Thir<'tcx> {
54             $(
55                 pub $field_name: $field_ty,
56             )*
57             $(
58                 pub $name: IndexVec<$id, $value>,
59             )*
60         }
61 
62         impl<'tcx> Thir<'tcx> {
63             pub fn new($($field_name: $field_ty,)*) -> Thir<'tcx> {
64                 Thir {
65                     $(
66                         $field_name,
67                     )*
68                     $(
69                         $name: IndexVec::new(),
70                     )*
71                 }
72             }
73         }
74 
75         $(
76             impl<'tcx> Index<$id> for Thir<'tcx> {
77                 type Output = $value;
78                 fn index(&self, index: $id) -> &Self::Output {
79                     &self.$name[index]
80                 }
81             }
82         )*
83     }
84 }
85 
86 pub const UPVAR_ENV_PARAM: ParamId = ParamId::from_u32(0);
87 
88 thir_with_elements! {
89     body_type: BodyTy<'tcx>,
90 
91 @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)]
100 pub enum BodyTy<'tcx> {
101     Const(Ty<'tcx>),
102     Fn(FnSig<'tcx>),
103 }
104 
105 /// Description of a type-checked function parameter.
106 #[derive(Clone, Debug, HashStable)]
107 pub struct Param<'tcx> {
108     /// The pattern that appears in the parameter list, or None for implicit parameters.
109     pub pat: Option<Box<Pat<'tcx>>>,
110     /// The possibly inferred type.
111     pub ty: Ty<'tcx>,
112     /// Span of the explicitly provided type, or None if inferred for closures.
113     pub ty_span: Option<Span>,
114     /// Whether this param is `self`, and how it is bound.
115     pub self_kind: Option<hir::ImplicitSelfKind>,
116     /// HirId for lints.
117     pub hir_id: Option<hir::HirId>,
118 }
119 
120 #[derive(Copy, Clone, Debug, HashStable)]
121 pub enum LintLevel {
122     Inherited,
123     Explicit(hir::HirId),
124 }
125 
126 #[derive(Clone, Debug, HashStable)]
127 pub struct Block {
128     /// Whether the block itself has a label. Used by `label: {}`
129     /// and `try` blocks.
130     ///
131     /// This does *not* include labels on loops, e.g. `'label: loop {}`.
132     pub targeted_by_break: bool,
133     pub region_scope: region::Scope,
134     pub opt_destruction_scope: Option<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 
145 type UserTy<'tcx> = Option<Box<CanonicalUserType<'tcx>>>;
146 
147 #[derive(Clone, Debug, HashStable)]
148 pub 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 substs: SubstsRef<'tcx>,
154 
155     /// Optional user-given substs: 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: Option<FruInfo<'tcx>>,
162 }
163 
164 #[derive(Clone, Debug, HashStable)]
165 pub struct ClosureExpr<'tcx> {
166     pub closure_id: LocalDefId,
167     pub substs: UpvarSubsts<'tcx>,
168     pub upvars: Box<[ExprId]>,
169     pub movability: Option<hir::Movability>,
170     pub fake_reads: Vec<(ExprId, FakeReadCause, hir::HirId)>,
171 }
172 
173 #[derive(Clone, Debug, HashStable)]
174 pub struct InlineAsmExpr<'tcx> {
175     pub template: &'tcx [InlineAsmTemplatePiece],
176     pub operands: Box<[InlineAsmOperand<'tcx>]>,
177     pub options: InlineAsmOptions,
178     pub line_spans: &'tcx [Span],
179 }
180 
181 #[derive(Copy, Clone, Debug, HashStable)]
182 pub enum BlockSafety {
183     Safe,
184     /// A compiler-generated unsafe block
185     BuiltinUnsafe,
186     /// An `unsafe` block. The `HirId` is the ID of the block.
187     ExplicitUnsafe(hir::HirId),
188 }
189 
190 #[derive(Clone, Debug, HashStable)]
191 pub struct Stmt<'tcx> {
192     pub kind: StmtKind<'tcx>,
193     pub opt_destruction_scope: Option<region::Scope>,
194 }
195 
196 #[derive(Clone, Debug, HashStable)]
197 pub enum StmtKind<'tcx> {
198     /// An expression with a trailing semicolon.
199     Expr {
200         /// The scope for this statement; may be used as lifetime of temporaries.
201         scope: region::Scope,
202 
203         /// The expression being evaluated in this statement.
204         expr: ExprId,
205     },
206 
207     /// A `let` binding.
208     Let {
209         /// The scope for variables bound in this `let`; it covers this and
210         /// all the remaining statements in the block.
211         remainder_scope: region::Scope,
212 
213         /// The scope for the initialization itself; might be used as
214         /// lifetime of temporaries.
215         init_scope: region::Scope,
216 
217         /// `let <PAT> = ...`
218         ///
219         /// If a type annotation is included, it is added as an ascription pattern.
220         pattern: Box<Pat<'tcx>>,
221 
222         /// `let pat: ty = <INIT>`
223         initializer: Option<ExprId>,
224 
225         /// `let pat: ty = <INIT> else { <ELSE> }`
226         else_block: Option<BlockId>,
227 
228         /// The lint level for this `let` statement.
229         lint_level: LintLevel,
230 
231         /// Span of the `let <PAT> = <INIT>` part.
232         span: Span,
233     },
234 }
235 
236 #[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)]
237 pub struct LocalVarId(pub hir::HirId);
238 
239 /// A THIR expression.
240 #[derive(Clone, Debug, HashStable)]
241 pub struct Expr<'tcx> {
242     /// kind of expression
243     pub kind: ExprKind<'tcx>,
244 
245     /// The type of this expression
246     pub ty: Ty<'tcx>,
247 
248     /// The lifetime of this expression if it should be spilled into a
249     /// temporary; should be `None` only if in a constant context
250     pub temp_lifetime: Option<region::Scope>,
251 
252     /// span of the expression in the source
253     pub span: Span,
254 }
255 
256 #[derive(Clone, Debug, HashStable)]
257 pub enum ExprKind<'tcx> {
258     /// `Scope`s are used to explicitly mark destruction scopes,
259     /// and to track the `HirId` of the expressions within the scope.
260     Scope {
261         region_scope: region::Scope,
262         lint_level: LintLevel,
263         value: ExprId,
264     },
265     /// A `box <value>` expression.
266     Box {
267         value: ExprId,
268     },
269     /// An `if` expression.
270     If {
271         if_then_scope: region::Scope,
272         cond: ExprId,
273         then: ExprId,
274         else_opt: Option<ExprId>,
275     },
276     /// A function call. Method calls and overloaded operators are converted to plain function calls.
277     Call {
278         /// The type of the function. This is often a [`FnDef`] or a [`FnPtr`].
279         ///
280         /// [`FnDef`]: ty::TyKind::FnDef
281         /// [`FnPtr`]: ty::TyKind::FnPtr
282         ty: Ty<'tcx>,
283         /// The function itself.
284         fun: ExprId,
285         /// The arguments passed to the function.
286         ///
287         /// Note: in some cases (like calling a closure), the function call `f(...args)` gets
288         /// rewritten as a call to a function trait method (e.g. `FnOnce::call_once(f, (...args))`).
289         args: Box<[ExprId]>,
290         /// Whether this is from an overloaded operator rather than a
291         /// function call from HIR. `true` for overloaded function call.
292         from_hir_call: bool,
293         /// The span of the function, without the dot and receiver
294         /// (e.g. `foo(a, b)` in `x.foo(a, b)`).
295         fn_span: Span,
296     },
297     /// A *non-overloaded* dereference.
298     Deref {
299         arg: ExprId,
300     },
301     /// A *non-overloaded* binary operation.
302     Binary {
303         op: BinOp,
304         lhs: ExprId,
305         rhs: ExprId,
306     },
307     /// A logical operation. This is distinct from `BinaryOp` because
308     /// the operands need to be lazily evaluated.
309     LogicalOp {
310         op: LogicalOp,
311         lhs: ExprId,
312         rhs: ExprId,
313     },
314     /// A *non-overloaded* unary operation. Note that here the deref (`*`)
315     /// operator is represented by `ExprKind::Deref`.
316     Unary {
317         op: UnOp,
318         arg: ExprId,
319     },
320     /// A cast: `<source> as <type>`. The type we cast to is the type of
321     /// the parent expression.
322     Cast {
323         source: ExprId,
324     },
325     Use {
326         source: ExprId,
327     }, // Use a lexpr to get a vexpr.
328     /// A coercion from `!` to any type.
329     NeverToAny {
330         source: ExprId,
331     },
332     /// A pointer coercion. More information can be found in [`PointerCoercion`].
333     /// Pointer casts that cannot be done by coercions are represented by [`ExprKind::Cast`].
334     PointerCoercion {
335         cast: PointerCoercion,
336         source: ExprId,
337     },
338     /// A `loop` expression.
339     Loop {
340         body: ExprId,
341     },
342     Let {
343         expr: ExprId,
344         pat: Box<Pat<'tcx>>,
345     },
346     /// A `match` expression.
347     Match {
348         scrutinee: ExprId,
349         arms: Box<[ArmId]>,
350     },
351     /// A block.
352     Block {
353         block: BlockId,
354     },
355     /// An assignment: `lhs = rhs`.
356     Assign {
357         lhs: ExprId,
358         rhs: ExprId,
359     },
360     /// A *non-overloaded* operation assignment, e.g. `lhs += rhs`.
361     AssignOp {
362         op: BinOp,
363         lhs: ExprId,
364         rhs: ExprId,
365     },
366     /// Access to a field of a struct, a tuple, an union, or an enum.
367     Field {
368         lhs: ExprId,
369         /// Variant containing the field.
370         variant_index: VariantIdx,
371         /// This can be a named (`.foo`) or unnamed (`.0`) field.
372         name: FieldIdx,
373     },
374     /// A *non-overloaded* indexing operation.
375     Index {
376         lhs: ExprId,
377         index: ExprId,
378     },
379     /// A local variable.
380     VarRef {
381         id: LocalVarId,
382     },
383     /// Used to represent upvars mentioned in a closure/generator
384     UpvarRef {
385         /// DefId of the closure/generator
386         closure_def_id: DefId,
387 
388         /// HirId of the root variable
389         var_hir_id: LocalVarId,
390     },
391     /// A borrow, e.g. `&arg`.
392     Borrow {
393         borrow_kind: BorrowKind,
394         arg: ExprId,
395     },
396     /// A `&raw [const|mut] $place_expr` raw borrow resulting in type `*[const|mut] T`.
397     AddressOf {
398         mutability: hir::Mutability,
399         arg: ExprId,
400     },
401     /// A `break` expression.
402     Break {
403         label: region::Scope,
404         value: Option<ExprId>,
405     },
406     /// A `continue` expression.
407     Continue {
408         label: region::Scope,
409     },
410     /// A `return` expression.
411     Return {
412         value: Option<ExprId>,
413     },
414     /// A `become` expression.
415     Become {
416         value: ExprId,
417     },
418     /// An inline `const` block, e.g. `const {}`.
419     ConstBlock {
420         did: DefId,
421         substs: SubstsRef<'tcx>,
422     },
423     /// An array literal constructed from one repeated element, e.g. `[1; 5]`.
424     Repeat {
425         value: ExprId,
426         count: ty::Const<'tcx>,
427     },
428     /// An array, e.g. `[a, b, c, d]`.
429     Array {
430         fields: Box<[ExprId]>,
431     },
432     /// A tuple, e.g. `(a, b, c, d)`.
433     Tuple {
434         fields: Box<[ExprId]>,
435     },
436     /// An ADT constructor, e.g. `Foo {x: 1, y: 2}`.
437     Adt(Box<AdtExpr<'tcx>>),
438     /// A type ascription on a place.
439     PlaceTypeAscription {
440         source: ExprId,
441         /// Type that the user gave to this expression
442         user_ty: UserTy<'tcx>,
443     },
444     /// A type ascription on a value, e.g. `42: i32`.
445     ValueTypeAscription {
446         source: ExprId,
447         /// Type that the user gave to this expression
448         user_ty: UserTy<'tcx>,
449     },
450     /// A closure definition.
451     Closure(Box<ClosureExpr<'tcx>>),
452     /// A literal.
453     Literal {
454         lit: &'tcx hir::Lit,
455         neg: bool,
456     },
457     /// For literals that don't correspond to anything in the HIR
458     NonHirLiteral {
459         lit: ty::ScalarInt,
460         user_ty: UserTy<'tcx>,
461     },
462     /// A literal of a ZST type.
463     ZstLiteral {
464         user_ty: UserTy<'tcx>,
465     },
466     /// Associated constants and named constants
467     NamedConst {
468         def_id: DefId,
469         substs: SubstsRef<'tcx>,
470         user_ty: UserTy<'tcx>,
471     },
472     ConstParam {
473         param: ty::ParamConst,
474         def_id: DefId,
475     },
476     // FIXME improve docs for `StaticRef` by distinguishing it from `NamedConst`
477     /// A literal containing the address of a `static`.
478     ///
479     /// This is only distinguished from `Literal` so that we can register some
480     /// info for diagnostics.
481     StaticRef {
482         alloc_id: AllocId,
483         ty: Ty<'tcx>,
484         def_id: DefId,
485     },
486     /// Inline assembly, i.e. `asm!()`.
487     InlineAsm(Box<InlineAsmExpr<'tcx>>),
488     /// Field offset (`offset_of!`)
489     OffsetOf {
490         container: Ty<'tcx>,
491         fields: &'tcx List<FieldIdx>,
492     },
493     /// An expression taking a reference to a thread local.
494     ThreadLocalRef(DefId),
495     /// A `yield` expression.
496     Yield {
497         value: ExprId,
498     },
499 }
500 
501 /// Represents the association of a field identifier and an expression.
502 ///
503 /// This is used in struct constructors.
504 #[derive(Clone, Debug, HashStable)]
505 pub struct FieldExpr {
506     pub name: FieldIdx,
507     pub expr: ExprId,
508 }
509 
510 #[derive(Clone, Debug, HashStable)]
511 pub struct FruInfo<'tcx> {
512     pub base: ExprId,
513     pub field_types: Box<[Ty<'tcx>]>,
514 }
515 
516 /// A `match` arm.
517 #[derive(Clone, Debug, HashStable)]
518 pub struct Arm<'tcx> {
519     pub pattern: Box<Pat<'tcx>>,
520     pub guard: Option<Guard<'tcx>>,
521     pub body: ExprId,
522     pub lint_level: LintLevel,
523     pub scope: region::Scope,
524     pub span: Span,
525 }
526 
527 /// A `match` guard.
528 #[derive(Clone, Debug, HashStable)]
529 pub enum Guard<'tcx> {
530     If(ExprId),
531     IfLet(Box<Pat<'tcx>>, ExprId),
532 }
533 
534 #[derive(Copy, Clone, Debug, HashStable)]
535 pub enum LogicalOp {
536     /// The `&&` operator.
537     And,
538     /// The `||` operator.
539     Or,
540 }
541 
542 #[derive(Clone, Debug, HashStable)]
543 pub enum InlineAsmOperand<'tcx> {
544     In {
545         reg: InlineAsmRegOrRegClass,
546         expr: ExprId,
547     },
548     Out {
549         reg: InlineAsmRegOrRegClass,
550         late: bool,
551         expr: Option<ExprId>,
552     },
553     InOut {
554         reg: InlineAsmRegOrRegClass,
555         late: bool,
556         expr: ExprId,
557     },
558     SplitInOut {
559         reg: InlineAsmRegOrRegClass,
560         late: bool,
561         in_expr: ExprId,
562         out_expr: Option<ExprId>,
563     },
564     Const {
565         value: mir::ConstantKind<'tcx>,
566         span: Span,
567     },
568     SymFn {
569         value: mir::ConstantKind<'tcx>,
570         span: Span,
571     },
572     SymStatic {
573         def_id: DefId,
574     },
575 }
576 
577 #[derive(Copy, Clone, Debug, PartialEq, HashStable)]
578 pub enum BindingMode {
579     ByValue,
580     ByRef(BorrowKind),
581 }
582 
583 #[derive(Clone, Debug, HashStable)]
584 pub struct FieldPat<'tcx> {
585     pub field: FieldIdx,
586     pub pattern: Box<Pat<'tcx>>,
587 }
588 
589 #[derive(Clone, Debug, HashStable)]
590 pub struct Pat<'tcx> {
591     pub ty: Ty<'tcx>,
592     pub span: Span,
593     pub kind: PatKind<'tcx>,
594 }
595 
596 impl<'tcx> Pat<'tcx> {
wildcard_from_ty(ty: Ty<'tcx>) -> Self597     pub fn wildcard_from_ty(ty: Ty<'tcx>) -> Self {
598         Pat { ty, span: DUMMY_SP, kind: PatKind::Wild }
599     }
600 
simple_ident(&self) -> Option<Symbol>601     pub fn simple_ident(&self) -> Option<Symbol> {
602         match self.kind {
603             PatKind::Binding { name, mode: BindingMode::ByValue, subpattern: None, .. } => {
604                 Some(name)
605             }
606             _ => None,
607         }
608     }
609 
610     /// Call `f` on every "binding" in a pattern, e.g., on `a` in
611     /// `match foo() { Some(a) => (), None => () }`
each_binding(&self, mut f: impl FnMut(Symbol, BindingMode, Ty<'tcx>, Span))612     pub fn each_binding(&self, mut f: impl FnMut(Symbol, BindingMode, Ty<'tcx>, Span)) {
613         self.walk_always(|p| {
614             if let PatKind::Binding { name, mode, ty, .. } = p.kind {
615                 f(name, mode, ty, p.span);
616             }
617         });
618     }
619 
620     /// Walk the pattern in left-to-right order.
621     ///
622     /// If `it(pat)` returns `false`, the children are not visited.
walk(&self, mut it: impl FnMut(&Pat<'tcx>) -> bool)623     pub fn walk(&self, mut it: impl FnMut(&Pat<'tcx>) -> bool) {
624         self.walk_(&mut it)
625     }
626 
walk_(&self, it: &mut impl FnMut(&Pat<'tcx>) -> bool)627     fn walk_(&self, it: &mut impl FnMut(&Pat<'tcx>) -> bool) {
628         if !it(self) {
629             return;
630         }
631 
632         use PatKind::*;
633         match &self.kind {
634             Wild | Range(..) | Binding { subpattern: None, .. } | Constant { .. } => {}
635             AscribeUserType { subpattern, .. }
636             | Binding { subpattern: Some(subpattern), .. }
637             | Deref { subpattern } => subpattern.walk_(it),
638             Leaf { subpatterns } | Variant { subpatterns, .. } => {
639                 subpatterns.iter().for_each(|field| field.pattern.walk_(it))
640             }
641             Or { pats } => pats.iter().for_each(|p| p.walk_(it)),
642             Array { box ref prefix, ref slice, box ref suffix }
643             | Slice { box ref prefix, ref slice, box ref suffix } => {
644                 prefix.iter().chain(slice.iter()).chain(suffix.iter()).for_each(|p| p.walk_(it))
645             }
646         }
647     }
648 
649     /// Walk the pattern in left-to-right order.
650     ///
651     /// If you always want to recurse, prefer this method over `walk`.
walk_always(&self, mut it: impl FnMut(&Pat<'tcx>))652     pub fn walk_always(&self, mut it: impl FnMut(&Pat<'tcx>)) {
653         self.walk(|p| {
654             it(p);
655             true
656         })
657     }
658 }
659 
660 impl<'tcx> IntoDiagnosticArg for Pat<'tcx> {
into_diagnostic_arg(self) -> DiagnosticArgValue<'static>661     fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
662         format!("{}", self).into_diagnostic_arg()
663     }
664 }
665 
666 #[derive(Clone, Debug, HashStable)]
667 pub struct Ascription<'tcx> {
668     pub annotation: CanonicalUserTypeAnnotation<'tcx>,
669     /// Variance to use when relating the `user_ty` to the **type of the value being
670     /// matched**. Typically, this is `Variance::Covariant`, since the value being matched must
671     /// have a type that is some subtype of the ascribed type.
672     ///
673     /// Note that this variance does not apply for any bindings within subpatterns. The type
674     /// assigned to those bindings must be exactly equal to the `user_ty` given here.
675     ///
676     /// The only place where this field is not `Covariant` is when matching constants, where
677     /// we currently use `Contravariant` -- this is because the constant type just needs to
678     /// be "comparable" to the type of the input value. So, for example:
679     ///
680     /// ```text
681     /// match x { "foo" => .. }
682     /// ```
683     ///
684     /// requires that `&'static str <: T_x`, where `T_x` is the type of `x`. Really, we should
685     /// probably be checking for a `PartialEq` impl instead, but this preserves the behavior
686     /// of the old type-check for now. See #57280 for details.
687     pub variance: ty::Variance,
688 }
689 
690 #[derive(Clone, Debug, HashStable)]
691 pub enum PatKind<'tcx> {
692     /// A wildcard pattern: `_`.
693     Wild,
694 
695     AscribeUserType {
696         ascription: Ascription<'tcx>,
697         subpattern: Box<Pat<'tcx>>,
698     },
699 
700     /// `x`, `ref x`, `x @ P`, etc.
701     Binding {
702         mutability: Mutability,
703         name: Symbol,
704         mode: BindingMode,
705         var: LocalVarId,
706         ty: Ty<'tcx>,
707         subpattern: Option<Box<Pat<'tcx>>>,
708         /// Is this the leftmost occurrence of the binding, i.e., is `var` the
709         /// `HirId` of this pattern?
710         is_primary: bool,
711     },
712 
713     /// `Foo(...)` or `Foo{...}` or `Foo`, where `Foo` is a variant name from an ADT with
714     /// multiple variants.
715     Variant {
716         adt_def: AdtDef<'tcx>,
717         substs: SubstsRef<'tcx>,
718         variant_index: VariantIdx,
719         subpatterns: Vec<FieldPat<'tcx>>,
720     },
721 
722     /// `(...)`, `Foo(...)`, `Foo{...}`, or `Foo`, where `Foo` is a variant name from an ADT with
723     /// a single variant.
724     Leaf {
725         subpatterns: Vec<FieldPat<'tcx>>,
726     },
727 
728     /// `box P`, `&P`, `&mut P`, etc.
729     Deref {
730         subpattern: Box<Pat<'tcx>>,
731     },
732 
733     /// One of the following:
734     /// * `&str`, which will be handled as a string pattern and thus exhaustiveness
735     ///   checking will detect if you use the same string twice in different patterns.
736     /// * integer, bool, char or float, which will be handled by exhaustiveness to cover exactly
737     ///   its own value, similar to `&str`, but these values are much simpler.
738     /// * Opaque constants, that must not be matched structurally. So anything that does not derive
739     ///   `PartialEq` and `Eq`.
740     Constant {
741         value: mir::ConstantKind<'tcx>,
742     },
743 
744     Range(Box<PatRange<'tcx>>),
745 
746     /// Matches against a slice, checking the length and extracting elements.
747     /// irrefutable when there is a slice pattern and both `prefix` and `suffix` are empty.
748     /// e.g., `&[ref xs @ ..]`.
749     Slice {
750         prefix: Box<[Box<Pat<'tcx>>]>,
751         slice: Option<Box<Pat<'tcx>>>,
752         suffix: Box<[Box<Pat<'tcx>>]>,
753     },
754 
755     /// Fixed match against an array; irrefutable.
756     Array {
757         prefix: Box<[Box<Pat<'tcx>>]>,
758         slice: Option<Box<Pat<'tcx>>>,
759         suffix: Box<[Box<Pat<'tcx>>]>,
760     },
761 
762     /// An or-pattern, e.g. `p | q`.
763     /// Invariant: `pats.len() >= 2`.
764     Or {
765         pats: Box<[Box<Pat<'tcx>>]>,
766     },
767 }
768 
769 #[derive(Clone, Debug, PartialEq, HashStable)]
770 pub struct PatRange<'tcx> {
771     pub lo: mir::ConstantKind<'tcx>,
772     pub hi: mir::ConstantKind<'tcx>,
773     pub end: RangeEnd,
774 }
775 
776 impl<'tcx> fmt::Display for Pat<'tcx> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result777     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
778         // Printing lists is a chore.
779         let mut first = true;
780         let mut start_or_continue = |s| {
781             if first {
782                 first = false;
783                 ""
784             } else {
785                 s
786             }
787         };
788         let mut start_or_comma = || start_or_continue(", ");
789 
790         match self.kind {
791             PatKind::Wild => write!(f, "_"),
792             PatKind::AscribeUserType { ref subpattern, .. } => write!(f, "{}: _", subpattern),
793             PatKind::Binding { mutability, name, mode, ref subpattern, .. } => {
794                 let is_mut = match mode {
795                     BindingMode::ByValue => mutability == Mutability::Mut,
796                     BindingMode::ByRef(bk) => {
797                         write!(f, "ref ")?;
798                         matches!(bk, BorrowKind::Mut { .. })
799                     }
800                 };
801                 if is_mut {
802                     write!(f, "mut ")?;
803                 }
804                 write!(f, "{}", name)?;
805                 if let Some(ref subpattern) = *subpattern {
806                     write!(f, " @ {}", subpattern)?;
807                 }
808                 Ok(())
809             }
810             PatKind::Variant { ref subpatterns, .. } | PatKind::Leaf { ref subpatterns } => {
811                 let variant_and_name = match self.kind {
812                     PatKind::Variant { adt_def, variant_index, .. } => ty::tls::with(|tcx| {
813                         let variant = adt_def.variant(variant_index);
814                         let adt_did = adt_def.did();
815                         let name = if tcx.get_diagnostic_item(sym::Option) == Some(adt_did)
816                             || tcx.get_diagnostic_item(sym::Result) == Some(adt_did)
817                         {
818                             variant.name.to_string()
819                         } else {
820                             format!("{}::{}", tcx.def_path_str(adt_def.did()), variant.name)
821                         };
822                         Some((variant, name))
823                     }),
824                     _ => self.ty.ty_adt_def().and_then(|adt_def| {
825                         if !adt_def.is_enum() {
826                             ty::tls::with(|tcx| {
827                                 Some((adt_def.non_enum_variant(), tcx.def_path_str(adt_def.did())))
828                             })
829                         } else {
830                             None
831                         }
832                     }),
833                 };
834 
835                 if let Some((variant, name)) = &variant_and_name {
836                     write!(f, "{}", name)?;
837 
838                     // Only for Adt we can have `S {...}`,
839                     // which we handle separately here.
840                     if variant.ctor.is_none() {
841                         write!(f, " {{ ")?;
842 
843                         let mut printed = 0;
844                         for p in subpatterns {
845                             if let PatKind::Wild = p.pattern.kind {
846                                 continue;
847                             }
848                             let name = variant.fields[p.field].name;
849                             write!(f, "{}{}: {}", start_or_comma(), name, p.pattern)?;
850                             printed += 1;
851                         }
852 
853                         if printed < variant.fields.len() {
854                             write!(f, "{}..", start_or_comma())?;
855                         }
856 
857                         return write!(f, " }}");
858                     }
859                 }
860 
861                 let num_fields =
862                     variant_and_name.as_ref().map_or(subpatterns.len(), |(v, _)| v.fields.len());
863                 if num_fields != 0 || variant_and_name.is_none() {
864                     write!(f, "(")?;
865                     for i in 0..num_fields {
866                         write!(f, "{}", start_or_comma())?;
867 
868                         // Common case: the field is where we expect it.
869                         if let Some(p) = subpatterns.get(i) {
870                             if p.field.index() == i {
871                                 write!(f, "{}", p.pattern)?;
872                                 continue;
873                             }
874                         }
875 
876                         // Otherwise, we have to go looking for it.
877                         if let Some(p) = subpatterns.iter().find(|p| p.field.index() == i) {
878                             write!(f, "{}", p.pattern)?;
879                         } else {
880                             write!(f, "_")?;
881                         }
882                     }
883                     write!(f, ")")?;
884                 }
885 
886                 Ok(())
887             }
888             PatKind::Deref { ref subpattern } => {
889                 match self.ty.kind() {
890                     ty::Adt(def, _) if def.is_box() => write!(f, "box ")?,
891                     ty::Ref(_, _, mutbl) => {
892                         write!(f, "&{}", mutbl.prefix_str())?;
893                     }
894                     _ => bug!("{} is a bad Deref pattern type", self.ty),
895                 }
896                 write!(f, "{}", subpattern)
897             }
898             PatKind::Constant { value } => write!(f, "{}", value),
899             PatKind::Range(box PatRange { lo, hi, end }) => {
900                 write!(f, "{}", lo)?;
901                 write!(f, "{}", end)?;
902                 write!(f, "{}", hi)
903             }
904             PatKind::Slice { ref prefix, ref slice, ref suffix }
905             | PatKind::Array { ref prefix, ref slice, ref suffix } => {
906                 write!(f, "[")?;
907                 for p in prefix.iter() {
908                     write!(f, "{}{}", start_or_comma(), p)?;
909                 }
910                 if let Some(ref slice) = *slice {
911                     write!(f, "{}", start_or_comma())?;
912                     match slice.kind {
913                         PatKind::Wild => {}
914                         _ => write!(f, "{}", slice)?,
915                     }
916                     write!(f, "..")?;
917                 }
918                 for p in suffix.iter() {
919                     write!(f, "{}{}", start_or_comma(), p)?;
920                 }
921                 write!(f, "]")
922             }
923             PatKind::Or { ref pats } => {
924                 for pat in pats.iter() {
925                     write!(f, "{}{}", start_or_continue(" | "), pat)?;
926                 }
927                 Ok(())
928             }
929         }
930     }
931 }
932 
933 // Some nodes are used a lot. Make sure they don't unintentionally get bigger.
934 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
935 mod size_asserts {
936     use super::*;
937     // tidy-alphabetical-start
938     static_assert_size!(Block, 56);
939     static_assert_size!(Expr<'_>, 64);
940     static_assert_size!(ExprKind<'_>, 40);
941     static_assert_size!(Pat<'_>, 64);
942     static_assert_size!(PatKind<'_>, 48);
943     static_assert_size!(Stmt<'_>, 56);
944     static_assert_size!(StmtKind<'_>, 48);
945     // tidy-alphabetical-end
946 }
947