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