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