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