]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_middle/src/thir.rs
Box `CanonicalUserTypeAnnotation::CanonicalUserType`.
[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::middle::region;
19 use rustc_middle::mir::interpret::AllocId;
20 use rustc_middle::mir::{self, BinOp, BorrowKind, FakeReadCause, Field, Mutability, UnOp};
21 use rustc_middle::ty::adjustment::PointerCast;
22 use rustc_middle::ty::subst::SubstsRef;
23 use rustc_middle::ty::{self, AdtDef, Ty, UpvarSubsts};
24 use rustc_middle::ty::{CanonicalUserType, CanonicalUserTypeAnnotation};
25 use rustc_span::def_id::LocalDefId;
26 use rustc_span::{Span, Symbol, DUMMY_SP};
27 use rustc_target::abi::VariantIdx;
28 use rustc_target::asm::InlineAsmRegOrRegClass;
29 use std::fmt;
30 use std::ops::Index;
31
32 pub mod visit;
33
34 macro_rules! thir_with_elements {
35     ($($name:ident: $id:ty => $value:ty => $format:literal,)*) => {
36         $(
37             newtype_index! {
38                 #[derive(HashStable)]
39                 pub struct $id {
40                     DEBUG_FORMAT = $format
41                 }
42             }
43         )*
44
45         /// A container for a THIR body.
46         ///
47         /// This can be indexed directly by any THIR index (e.g. [`ExprId`]).
48         #[derive(Debug, HashStable, Clone)]
49         pub struct Thir<'tcx> {
50             $(
51                 pub $name: IndexVec<$id, $value>,
52             )*
53         }
54
55         impl<'tcx> Thir<'tcx> {
56             pub fn new() -> Thir<'tcx> {
57                 Thir {
58                     $(
59                         $name: IndexVec::new(),
60                     )*
61                 }
62             }
63         }
64
65         $(
66             impl<'tcx> Index<$id> for Thir<'tcx> {
67                 type Output = $value;
68                 fn index(&self, index: $id) -> &Self::Output {
69                     &self.$name[index]
70                 }
71             }
72         )*
73     }
74 }
75
76 thir_with_elements! {
77     arms: ArmId => Arm<'tcx> => "a{}",
78     blocks: BlockId => Block => "b{}",
79     exprs: ExprId => Expr<'tcx> => "e{}",
80     stmts: StmtId => Stmt<'tcx> => "s{}",
81 }
82
83 #[derive(Copy, Clone, Debug, HashStable)]
84 pub enum LintLevel {
85     Inherited,
86     Explicit(hir::HirId),
87 }
88
89 #[derive(Clone, Debug, HashStable)]
90 pub struct Block {
91     /// Whether the block itself has a label. Used by `label: {}`
92     /// and `try` blocks.
93     ///
94     /// This does *not* include labels on loops, e.g. `'label: loop {}`.
95     pub targeted_by_break: bool,
96     pub region_scope: region::Scope,
97     pub opt_destruction_scope: Option<region::Scope>,
98     /// The span of the block, including the opening braces,
99     /// the label, and the `unsafe` keyword, if present.
100     pub span: Span,
101     /// The statements in the blocK.
102     pub stmts: Box<[StmtId]>,
103     /// The trailing expression of the block, if any.
104     pub expr: Option<ExprId>,
105     pub safety_mode: BlockSafety,
106 }
107
108 type UserTy<'tcx> = Option<Box<CanonicalUserType<'tcx>>>;
109
110 #[derive(Clone, Debug, HashStable)]
111 pub struct AdtExpr<'tcx> {
112     /// The ADT we're constructing.
113     pub adt_def: AdtDef<'tcx>,
114     /// The variant of the ADT.
115     pub variant_index: VariantIdx,
116     pub substs: SubstsRef<'tcx>,
117
118     /// Optional user-given substs: for something like `let x =
119     /// Bar::<T> { ... }`.
120     pub user_ty: UserTy<'tcx>,
121
122     pub fields: Box<[FieldExpr]>,
123     /// The base, e.g. `Foo {x: 1, .. base}`.
124     pub base: Option<FruInfo<'tcx>>,
125 }
126
127 #[derive(Clone, Debug, HashStable)]
128 pub struct ClosureExpr<'tcx> {
129     pub closure_id: LocalDefId,
130     pub substs: UpvarSubsts<'tcx>,
131     pub upvars: Box<[ExprId]>,
132     pub movability: Option<hir::Movability>,
133     pub fake_reads: Vec<(ExprId, FakeReadCause, hir::HirId)>,
134 }
135
136 #[derive(Clone, Debug, HashStable)]
137 pub struct InlineAsmExpr<'tcx> {
138     pub template: &'tcx [InlineAsmTemplatePiece],
139     pub operands: Box<[InlineAsmOperand<'tcx>]>,
140     pub options: InlineAsmOptions,
141     pub line_spans: &'tcx [Span],
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(Clone, Debug, HashStable)]
154 pub struct Stmt<'tcx> {
155     pub kind: StmtKind<'tcx>,
156     pub opt_destruction_scope: Option<region::Scope>,
157 }
158
159 #[derive(Clone, 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: Box<Pat<'tcx>>,
184
185         /// `let pat: ty = <INIT>`
186         initializer: Option<ExprId>,
187
188         /// `let pat: ty = <INIT> else { <ELSE> }
189         else_block: Option<BlockId>,
190
191         /// The lint level for this `let` statement.
192         lint_level: LintLevel,
193     },
194 }
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: Box<Pat<'tcx>>,
305     },
306     /// A `match` expression.
307     Match {
308         scrutinee: ExprId,
309         arms: Box<[ArmId]>,
310     },
311     /// A block.
312     Block {
313         block: BlockId,
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<AdtExpr<'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: UserTy<'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: UserTy<'tcx>,
405     },
406     /// A closure definition.
407     Closure(Box<ClosureExpr<'tcx>>),
408     /// A literal.
409     Literal {
410         lit: &'tcx hir::Lit,
411         neg: bool,
412     },
413     /// For literals that don't correspond to anything in the HIR
414     NonHirLiteral {
415         lit: ty::ScalarInt,
416         user_ty: UserTy<'tcx>,
417     },
418     /// A literal of a ZST type.
419     ZstLiteral {
420         user_ty: UserTy<'tcx>,
421     },
422     /// Associated constants and named constants
423     NamedConst {
424         def_id: DefId,
425         substs: SubstsRef<'tcx>,
426         user_ty: UserTy<'tcx>,
427     },
428     ConstParam {
429         param: ty::ParamConst,
430         def_id: DefId,
431     },
432     // FIXME improve docs for `StaticRef` by distinguishing it from `NamedConst`
433     /// A literal containing the address of a `static`.
434     ///
435     /// This is only distinguished from `Literal` so that we can register some
436     /// info for diagnostics.
437     StaticRef {
438         alloc_id: AllocId,
439         ty: Ty<'tcx>,
440         def_id: DefId,
441     },
442     /// Inline assembly, i.e. `asm!()`.
443     InlineAsm(Box<InlineAsmExpr<'tcx>>),
444     /// An expression taking a reference to a thread local.
445     ThreadLocalRef(DefId),
446     /// A `yield` expression.
447     Yield {
448         value: ExprId,
449     },
450 }
451
452 /// Represents the association of a field identifier and an expression.
453 ///
454 /// This is used in struct constructors.
455 #[derive(Clone, Debug, HashStable)]
456 pub struct FieldExpr {
457     pub name: Field,
458     pub expr: ExprId,
459 }
460
461 #[derive(Clone, Debug, HashStable)]
462 pub struct FruInfo<'tcx> {
463     pub base: ExprId,
464     pub field_types: Box<[Ty<'tcx>]>,
465 }
466
467 /// A `match` arm.
468 #[derive(Clone, Debug, HashStable)]
469 pub struct Arm<'tcx> {
470     pub pattern: Box<Pat<'tcx>>,
471     pub guard: Option<Guard<'tcx>>,
472     pub body: ExprId,
473     pub lint_level: LintLevel,
474     pub scope: region::Scope,
475     pub span: Span,
476 }
477
478 /// A `match` guard.
479 #[derive(Clone, Debug, HashStable)]
480 pub enum Guard<'tcx> {
481     If(ExprId),
482     IfLet(Box<Pat<'tcx>>, ExprId),
483 }
484
485 #[derive(Copy, Clone, Debug, HashStable)]
486 pub enum LogicalOp {
487     /// The `&&` operator.
488     And,
489     /// The `||` operator.
490     Or,
491 }
492
493 #[derive(Clone, Debug, HashStable)]
494 pub enum InlineAsmOperand<'tcx> {
495     In {
496         reg: InlineAsmRegOrRegClass,
497         expr: ExprId,
498     },
499     Out {
500         reg: InlineAsmRegOrRegClass,
501         late: bool,
502         expr: Option<ExprId>,
503     },
504     InOut {
505         reg: InlineAsmRegOrRegClass,
506         late: bool,
507         expr: ExprId,
508     },
509     SplitInOut {
510         reg: InlineAsmRegOrRegClass,
511         late: bool,
512         in_expr: ExprId,
513         out_expr: Option<ExprId>,
514     },
515     Const {
516         value: mir::ConstantKind<'tcx>,
517         span: Span,
518     },
519     SymFn {
520         value: mir::ConstantKind<'tcx>,
521         span: Span,
522     },
523     SymStatic {
524         def_id: DefId,
525     },
526 }
527
528 #[derive(Copy, Clone, Debug, PartialEq, HashStable)]
529 pub enum BindingMode {
530     ByValue,
531     ByRef(BorrowKind),
532 }
533
534 #[derive(Clone, Debug, HashStable)]
535 pub struct FieldPat<'tcx> {
536     pub field: Field,
537     pub pattern: Box<Pat<'tcx>>,
538 }
539
540 #[derive(Clone, Debug, HashStable)]
541 pub struct Pat<'tcx> {
542     pub ty: Ty<'tcx>,
543     pub span: Span,
544     pub kind: PatKind<'tcx>,
545 }
546
547 impl<'tcx> Pat<'tcx> {
548     pub fn wildcard_from_ty(ty: Ty<'tcx>) -> Self {
549         Pat { ty, span: DUMMY_SP, kind: PatKind::Wild }
550     }
551 }
552
553 #[derive(Clone, Debug, HashStable)]
554 pub struct Ascription<'tcx> {
555     pub annotation: CanonicalUserTypeAnnotation<'tcx>,
556     /// Variance to use when relating the `user_ty` to the **type of the value being
557     /// matched**. Typically, this is `Variance::Covariant`, since the value being matched must
558     /// have a type that is some subtype of the ascribed type.
559     ///
560     /// Note that this variance does not apply for any bindings within subpatterns. The type
561     /// assigned to those bindings must be exactly equal to the `user_ty` given here.
562     ///
563     /// The only place where this field is not `Covariant` is when matching constants, where
564     /// we currently use `Contravariant` -- this is because the constant type just needs to
565     /// be "comparable" to the type of the input value. So, for example:
566     ///
567     /// ```text
568     /// match x { "foo" => .. }
569     /// ```
570     ///
571     /// requires that `&'static str <: T_x`, where `T_x` is the type of `x`. Really, we should
572     /// probably be checking for a `PartialEq` impl instead, but this preserves the behavior
573     /// of the old type-check for now. See #57280 for details.
574     pub variance: ty::Variance,
575 }
576
577 #[derive(Clone, Debug, HashStable)]
578 pub enum PatKind<'tcx> {
579     /// A wildcard pattern: `_`.
580     Wild,
581
582     AscribeUserType {
583         ascription: Ascription<'tcx>,
584         subpattern: Box<Pat<'tcx>>,
585     },
586
587     /// `x`, `ref x`, `x @ P`, etc.
588     Binding {
589         mutability: Mutability,
590         name: Symbol,
591         mode: BindingMode,
592         var: LocalVarId,
593         ty: Ty<'tcx>,
594         subpattern: Option<Box<Pat<'tcx>>>,
595         /// Is this the leftmost occurrence of the binding, i.e., is `var` the
596         /// `HirId` of this pattern?
597         is_primary: bool,
598     },
599
600     /// `Foo(...)` or `Foo{...}` or `Foo`, where `Foo` is a variant name from an ADT with
601     /// multiple variants.
602     Variant {
603         adt_def: AdtDef<'tcx>,
604         substs: SubstsRef<'tcx>,
605         variant_index: VariantIdx,
606         subpatterns: Vec<FieldPat<'tcx>>,
607     },
608
609     /// `(...)`, `Foo(...)`, `Foo{...}`, or `Foo`, where `Foo` is a variant name from an ADT with
610     /// a single variant.
611     Leaf {
612         subpatterns: Vec<FieldPat<'tcx>>,
613     },
614
615     /// `box P`, `&P`, `&mut P`, etc.
616     Deref {
617         subpattern: Box<Pat<'tcx>>,
618     },
619
620     /// One of the following:
621     /// * `&str`, which will be handled as a string pattern and thus exhaustiveness
622     ///   checking will detect if you use the same string twice in different patterns.
623     /// * integer, bool, char or float, which will be handled by exhaustiveness to cover exactly
624     ///   its own value, similar to `&str`, but these values are much simpler.
625     /// * Opaque constants, that must not be matched structurally. So anything that does not derive
626     ///   `PartialEq` and `Eq`.
627     Constant {
628         value: mir::ConstantKind<'tcx>,
629     },
630
631     Range(Box<PatRange<'tcx>>),
632
633     /// Matches against a slice, checking the length and extracting elements.
634     /// irrefutable when there is a slice pattern and both `prefix` and `suffix` are empty.
635     /// e.g., `&[ref xs @ ..]`.
636     Slice {
637         prefix: Vec<Box<Pat<'tcx>>>,
638         slice: Option<Box<Pat<'tcx>>>,
639         suffix: Vec<Box<Pat<'tcx>>>,
640     },
641
642     /// Fixed match against an array; irrefutable.
643     Array {
644         prefix: Vec<Box<Pat<'tcx>>>,
645         slice: Option<Box<Pat<'tcx>>>,
646         suffix: Vec<Box<Pat<'tcx>>>,
647     },
648
649     /// An or-pattern, e.g. `p | q`.
650     /// Invariant: `pats.len() >= 2`.
651     Or {
652         pats: Vec<Box<Pat<'tcx>>>,
653     },
654 }
655
656 #[derive(Clone, Debug, PartialEq, HashStable)]
657 pub struct PatRange<'tcx> {
658     pub lo: mir::ConstantKind<'tcx>,
659     pub hi: mir::ConstantKind<'tcx>,
660     pub end: RangeEnd,
661 }
662
663 impl<'tcx> fmt::Display for Pat<'tcx> {
664     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
665         // Printing lists is a chore.
666         let mut first = true;
667         let mut start_or_continue = |s| {
668             if first {
669                 first = false;
670                 ""
671             } else {
672                 s
673             }
674         };
675         let mut start_or_comma = || start_or_continue(", ");
676
677         match self.kind {
678             PatKind::Wild => write!(f, "_"),
679             PatKind::AscribeUserType { ref subpattern, .. } => write!(f, "{}: _", subpattern),
680             PatKind::Binding { mutability, name, mode, ref subpattern, .. } => {
681                 let is_mut = match mode {
682                     BindingMode::ByValue => mutability == Mutability::Mut,
683                     BindingMode::ByRef(bk) => {
684                         write!(f, "ref ")?;
685                         matches!(bk, BorrowKind::Mut { .. })
686                     }
687                 };
688                 if is_mut {
689                     write!(f, "mut ")?;
690                 }
691                 write!(f, "{}", name)?;
692                 if let Some(ref subpattern) = *subpattern {
693                     write!(f, " @ {}", subpattern)?;
694                 }
695                 Ok(())
696             }
697             PatKind::Variant { ref subpatterns, .. } | PatKind::Leaf { ref subpatterns } => {
698                 let variant = match self.kind {
699                     PatKind::Variant { adt_def, variant_index, .. } => {
700                         Some(adt_def.variant(variant_index))
701                     }
702                     _ => self.ty.ty_adt_def().and_then(|adt| {
703                         if !adt.is_enum() { Some(adt.non_enum_variant()) } else { None }
704                     }),
705                 };
706
707                 if let Some(variant) = variant {
708                     write!(f, "{}", variant.name)?;
709
710                     // Only for Adt we can have `S {...}`,
711                     // which we handle separately here.
712                     if variant.ctor_kind == CtorKind::Fictive {
713                         write!(f, " {{ ")?;
714
715                         let mut printed = 0;
716                         for p in subpatterns {
717                             if let PatKind::Wild = p.pattern.kind {
718                                 continue;
719                             }
720                             let name = variant.fields[p.field.index()].name;
721                             write!(f, "{}{}: {}", start_or_comma(), name, p.pattern)?;
722                             printed += 1;
723                         }
724
725                         if printed < variant.fields.len() {
726                             write!(f, "{}..", start_or_comma())?;
727                         }
728
729                         return write!(f, " }}");
730                     }
731                 }
732
733                 let num_fields = variant.map_or(subpatterns.len(), |v| v.fields.len());
734                 if num_fields != 0 || variant.is_none() {
735                     write!(f, "(")?;
736                     for i in 0..num_fields {
737                         write!(f, "{}", start_or_comma())?;
738
739                         // Common case: the field is where we expect it.
740                         if let Some(p) = subpatterns.get(i) {
741                             if p.field.index() == i {
742                                 write!(f, "{}", p.pattern)?;
743                                 continue;
744                             }
745                         }
746
747                         // Otherwise, we have to go looking for it.
748                         if let Some(p) = subpatterns.iter().find(|p| p.field.index() == i) {
749                             write!(f, "{}", p.pattern)?;
750                         } else {
751                             write!(f, "_")?;
752                         }
753                     }
754                     write!(f, ")")?;
755                 }
756
757                 Ok(())
758             }
759             PatKind::Deref { ref subpattern } => {
760                 match self.ty.kind() {
761                     ty::Adt(def, _) if def.is_box() => write!(f, "box ")?,
762                     ty::Ref(_, _, mutbl) => {
763                         write!(f, "&{}", mutbl.prefix_str())?;
764                     }
765                     _ => bug!("{} is a bad Deref pattern type", self.ty),
766                 }
767                 write!(f, "{}", subpattern)
768             }
769             PatKind::Constant { value } => write!(f, "{}", value),
770             PatKind::Range(box PatRange { lo, hi, end }) => {
771                 write!(f, "{}", lo)?;
772                 write!(f, "{}", end)?;
773                 write!(f, "{}", hi)
774             }
775             PatKind::Slice { ref prefix, ref slice, ref suffix }
776             | PatKind::Array { ref prefix, ref slice, ref suffix } => {
777                 write!(f, "[")?;
778                 for p in prefix {
779                     write!(f, "{}{}", start_or_comma(), p)?;
780                 }
781                 if let Some(ref slice) = *slice {
782                     write!(f, "{}", start_or_comma())?;
783                     match slice.kind {
784                         PatKind::Wild => {}
785                         _ => write!(f, "{}", slice)?,
786                     }
787                     write!(f, "..")?;
788                 }
789                 for p in suffix {
790                     write!(f, "{}{}", start_or_comma(), p)?;
791                 }
792                 write!(f, "]")
793             }
794             PatKind::Or { ref pats } => {
795                 for pat in pats {
796                     write!(f, "{}{}", start_or_continue(" | "), pat)?;
797                 }
798                 Ok(())
799             }
800         }
801     }
802 }
803
804 // Some nodes are used a lot. Make sure they don't unintentionally get bigger.
805 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
806 mod size_asserts {
807     use super::*;
808     // These are in alphabetical order, which is easy to maintain.
809     static_assert_size!(Block, 56);
810     static_assert_size!(Expr<'_>, 64);
811     static_assert_size!(ExprKind<'_>, 40);
812     static_assert_size!(Pat<'_>, 80);
813     static_assert_size!(PatKind<'_>, 64);
814     static_assert_size!(Stmt<'_>, 56);
815     static_assert_size!(StmtKind<'_>, 48);
816 }