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