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