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