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