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