1 //! THIR datatypes and definitions. See the [rustc dev guide] for more info.
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.
9 //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/thir.html
11 use rustc_ast
::{InlineAsmOptions, InlineAsmTemplatePiece}
;
12 use rustc_errors
::{DiagnosticArgValue, IntoDiagnosticArg}
;
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, Mutability, UnOp}
;
21 use rustc_middle
::ty
::adjustment
::PointerCast
;
22 use rustc_middle
::ty
::subst
::SubstsRef
;
23 use rustc_middle
::ty
::{self, AdtDef, FnSig, Ty, UpvarSubsts}
;
24 use rustc_middle
::ty
::{CanonicalUserType, CanonicalUserTypeAnnotation}
;
25 use rustc_span
::def_id
::LocalDefId
;
26 use rustc_span
::{sym, Span, Symbol, DUMMY_SP}
;
27 use rustc_target
::abi
::{FieldIdx, VariantIdx}
;
28 use rustc_target
::asm
::InlineAsmRegOrRegClass
;
34 macro_rules
! thir_with_elements
{
36 $
($field_name
:ident
: $field_ty
:ty
,)*
39 $
($name
:ident
: $id
:ty
=> $value
:ty
=> $format
:literal
,)*
44 #[debug_format = $format]
49 /// A container for a THIR body.
51 /// This can be indexed directly by any THIR index (e.g. [`ExprId`]).
52 #[derive(Debug, HashStable, Clone)]
53 pub struct Thir
<'tcx
> {
55 pub $field_name
: $field_ty
,
58 pub $name
: IndexVec
<$id
, $value
>,
62 impl<'tcx
> Thir
<'tcx
> {
63 pub fn new($
($field_name
: $field_ty
,)*) -> Thir
<'tcx
> {
69 $name
: IndexVec
::new(),
76 impl<'tcx
> Index
<$id
> for Thir
<'tcx
> {
78 fn index(&self, index
: $id
) -> &Self::Output
{
86 pub const UPVAR_ENV_PARAM
: ParamId
= ParamId
::from_u32(0);
89 body_type
: BodyTy
<'tcx
>,
92 arms
: ArmId
=> Arm
<'tcx
> => "a{}",
93 blocks
: BlockId
=> Block
=> "b{}",
94 exprs
: ExprId
=> Expr
<'tcx
> => "e{}",
95 stmts
: StmtId
=> Stmt
<'tcx
> => "s{}",
96 params
: ParamId
=> Param
<'tcx
> => "p{}",
99 #[derive(Debug, HashStable, Clone)]
100 pub enum BodyTy
<'tcx
> {
105 /// Description of a type-checked function parameter.
106 #[derive(Clone, Debug, HashStable)]
107 pub struct Param
<'tcx
> {
108 /// The pattern that appears in the parameter list, or None for implicit parameters.
109 pub pat
: Option
<Box
<Pat
<'tcx
>>>,
110 /// The possibly inferred type.
112 /// Span of the explicitly provided type, or None if inferred for closures.
113 pub ty_span
: Option
<Span
>,
114 /// Whether this param is `self`, and how it is bound.
115 pub self_kind
: Option
<hir
::ImplicitSelfKind
>,
117 pub hir_id
: Option
<hir
::HirId
>,
120 #[derive(Copy, Clone, Debug, HashStable)]
123 Explicit(hir
::HirId
),
126 #[derive(Clone, Debug, HashStable)]
128 /// Whether the block itself has a label. Used by `label: {}`
129 /// and `try` blocks.
131 /// This does *not* include labels on loops, e.g. `'label: loop {}`.
132 pub targeted_by_break
: bool
,
133 pub region_scope
: region
::Scope
,
134 pub opt_destruction_scope
: Option
<region
::Scope
>,
135 /// The span of the block, including the opening braces,
136 /// the label, and the `unsafe` keyword, if present.
138 /// The statements in the blocK.
139 pub stmts
: Box
<[StmtId
]>,
140 /// The trailing expression of the block, if any.
141 pub expr
: Option
<ExprId
>,
142 pub safety_mode
: BlockSafety
,
145 type UserTy
<'tcx
> = Option
<Box
<CanonicalUserType
<'tcx
>>>;
147 #[derive(Clone, Debug, HashStable)]
148 pub struct AdtExpr
<'tcx
> {
149 /// The ADT we're constructing.
150 pub adt_def
: AdtDef
<'tcx
>,
151 /// The variant of the ADT.
152 pub variant_index
: VariantIdx
,
153 pub substs
: SubstsRef
<'tcx
>,
155 /// Optional user-given substs: for something like `let x =
156 /// Bar::<T> { ... }`.
157 pub user_ty
: UserTy
<'tcx
>,
159 pub fields
: Box
<[FieldExpr
]>,
160 /// The base, e.g. `Foo {x: 1, .. base}`.
161 pub base
: Option
<FruInfo
<'tcx
>>,
164 #[derive(Clone, Debug, HashStable)]
165 pub struct ClosureExpr
<'tcx
> {
166 pub closure_id
: LocalDefId
,
167 pub substs
: UpvarSubsts
<'tcx
>,
168 pub upvars
: Box
<[ExprId
]>,
169 pub movability
: Option
<hir
::Movability
>,
170 pub fake_reads
: Vec
<(ExprId
, FakeReadCause
, hir
::HirId
)>,
173 #[derive(Clone, Debug, HashStable)]
174 pub struct InlineAsmExpr
<'tcx
> {
175 pub template
: &'tcx
[InlineAsmTemplatePiece
],
176 pub operands
: Box
<[InlineAsmOperand
<'tcx
>]>,
177 pub options
: InlineAsmOptions
,
178 pub line_spans
: &'tcx
[Span
],
181 #[derive(Copy, Clone, Debug, HashStable)]
182 pub enum BlockSafety
{
184 /// A compiler-generated unsafe block
186 /// An `unsafe` block. The `HirId` is the ID of the block.
187 ExplicitUnsafe(hir
::HirId
),
190 #[derive(Clone, Debug, HashStable)]
191 pub struct Stmt
<'tcx
> {
192 pub kind
: StmtKind
<'tcx
>,
193 pub opt_destruction_scope
: Option
<region
::Scope
>,
196 #[derive(Clone, Debug, HashStable)]
197 pub enum StmtKind
<'tcx
> {
198 /// An expression with a trailing semicolon.
200 /// The scope for this statement; may be used as lifetime of temporaries.
201 scope
: region
::Scope
,
203 /// The expression being evaluated in this statement.
209 /// The scope for variables bound in this `let`; it covers this and
210 /// all the remaining statements in the block.
211 remainder_scope
: region
::Scope
,
213 /// The scope for the initialization itself; might be used as
214 /// lifetime of temporaries.
215 init_scope
: region
::Scope
,
217 /// `let <PAT> = ...`
219 /// If a type annotation is included, it is added as an ascription pattern.
220 pattern
: Box
<Pat
<'tcx
>>,
222 /// `let pat: ty = <INIT>`
223 initializer
: Option
<ExprId
>,
225 /// `let pat: ty = <INIT> else { <ELSE> }`
226 else_block
: Option
<BlockId
>,
228 /// The lint level for this `let` statement.
229 lint_level
: LintLevel
,
231 /// Span of the `let <PAT> = <INIT>` part.
236 #[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)]
237 #[derive(TypeFoldable, TypeVisitable)]
238 pub struct LocalVarId(pub hir
::HirId
);
240 /// A THIR expression.
241 #[derive(Clone, Debug, HashStable)]
242 pub struct Expr
<'tcx
> {
243 /// kind of expression
244 pub kind
: ExprKind
<'tcx
>,
246 /// The type of this expression
249 /// The lifetime of this expression if it should be spilled into a
250 /// temporary; should be `None` only if in a constant context
251 pub temp_lifetime
: Option
<region
::Scope
>,
253 /// span of the expression in the source
257 #[derive(Clone, Debug, HashStable)]
258 pub enum ExprKind
<'tcx
> {
259 /// `Scope`s are used to explicitly mark destruction scopes,
260 /// and to track the `HirId` of the expressions within the scope.
262 region_scope
: region
::Scope
,
263 lint_level
: LintLevel
,
266 /// A `box <value>` expression.
270 /// An `if` expression.
272 if_then_scope
: region
::Scope
,
275 else_opt
: Option
<ExprId
>,
277 /// A function call. Method calls and overloaded operators are converted to plain function calls.
279 /// The type of the function. This is often a [`FnDef`] or a [`FnPtr`].
281 /// [`FnDef`]: ty::TyKind::FnDef
282 /// [`FnPtr`]: ty::TyKind::FnPtr
284 /// The function itself.
286 /// The arguments passed to the function.
288 /// Note: in some cases (like calling a closure), the function call `f(...args)` gets
289 /// rewritten as a call to a function trait method (e.g. `FnOnce::call_once(f, (...args))`).
291 /// Whether this is from an overloaded operator rather than a
292 /// function call from HIR. `true` for overloaded function call.
294 /// The span of the function, without the dot and receiver
295 /// (e.g. `foo(a, b)` in `x.foo(a, b)`).
298 /// A *non-overloaded* dereference.
302 /// A *non-overloaded* binary operation.
308 /// A logical operation. This is distinct from `BinaryOp` because
309 /// the operands need to be lazily evaluated.
315 /// A *non-overloaded* unary operation. Note that here the deref (`*`)
316 /// operator is represented by `ExprKind::Deref`.
321 /// A cast: `<source> as <type>`. The type we cast to is the type of
322 /// the parent expression.
328 }, // Use a lexpr to get a vexpr.
329 /// A coercion from `!` to any type.
333 /// A pointer cast. More information can be found in [`PointerCast`].
338 /// A `loop` expression.
346 /// A `match` expression.
355 /// An assignment: `lhs = rhs`.
360 /// A *non-overloaded* operation assignment, e.g. `lhs += rhs`.
366 /// Access to a field of a struct, a tuple, an union, or an enum.
369 /// Variant containing the field.
370 variant_index
: VariantIdx
,
371 /// This can be a named (`.foo`) or unnamed (`.0`) field.
374 /// A *non-overloaded* indexing operation.
379 /// A local variable.
383 /// Used to represent upvars mentioned in a closure/generator
385 /// DefId of the closure/generator
386 closure_def_id
: DefId
,
388 /// HirId of the root variable
389 var_hir_id
: LocalVarId
,
391 /// A borrow, e.g. `&arg`.
393 borrow_kind
: BorrowKind
,
396 /// A `&raw [const|mut] $place_expr` raw borrow resulting in type `*[const|mut] T`.
398 mutability
: hir
::Mutability
,
401 /// A `break` expression.
403 label
: region
::Scope
,
404 value
: Option
<ExprId
>,
406 /// A `continue` expression.
408 label
: region
::Scope
,
410 /// A `return` expression.
412 value
: Option
<ExprId
>,
414 /// An inline `const` block, e.g. `const {}`.
417 substs
: SubstsRef
<'tcx
>,
419 /// An array literal constructed from one repeated element, e.g. `[1; 5]`.
422 count
: ty
::Const
<'tcx
>,
424 /// An array, e.g. `[a, b, c, d]`.
426 fields
: Box
<[ExprId
]>,
428 /// A tuple, e.g. `(a, b, c, d)`.
430 fields
: Box
<[ExprId
]>,
432 /// An ADT constructor, e.g. `Foo {x: 1, y: 2}`.
433 Adt(Box
<AdtExpr
<'tcx
>>),
434 /// A type ascription on a place.
435 PlaceTypeAscription
{
437 /// Type that the user gave to this expression
438 user_ty
: UserTy
<'tcx
>,
440 /// A type ascription on a value, e.g. `42: i32`.
441 ValueTypeAscription
{
443 /// Type that the user gave to this expression
444 user_ty
: UserTy
<'tcx
>,
446 /// A closure definition.
447 Closure(Box
<ClosureExpr
<'tcx
>>),
453 /// For literals that don't correspond to anything in the HIR
456 user_ty
: UserTy
<'tcx
>,
458 /// A literal of a ZST type.
460 user_ty
: UserTy
<'tcx
>,
462 /// Associated constants and named constants
465 substs
: SubstsRef
<'tcx
>,
466 user_ty
: UserTy
<'tcx
>,
469 param
: ty
::ParamConst
,
472 // FIXME improve docs for `StaticRef` by distinguishing it from `NamedConst`
473 /// A literal containing the address of a `static`.
475 /// This is only distinguished from `Literal` so that we can register some
476 /// info for diagnostics.
482 /// Inline assembly, i.e. `asm!()`.
483 InlineAsm(Box
<InlineAsmExpr
<'tcx
>>),
484 /// An expression taking a reference to a thread local.
485 ThreadLocalRef(DefId
),
486 /// A `yield` expression.
492 /// Represents the association of a field identifier and an expression.
494 /// This is used in struct constructors.
495 #[derive(Clone, Debug, HashStable)]
496 pub struct FieldExpr
{
501 #[derive(Clone, Debug, HashStable)]
502 pub struct FruInfo
<'tcx
> {
504 pub field_types
: Box
<[Ty
<'tcx
>]>,
508 #[derive(Clone, Debug, HashStable)]
509 pub struct Arm
<'tcx
> {
510 pub pattern
: Box
<Pat
<'tcx
>>,
511 pub guard
: Option
<Guard
<'tcx
>>,
513 pub lint_level
: LintLevel
,
514 pub scope
: region
::Scope
,
519 #[derive(Clone, Debug, HashStable)]
520 pub enum Guard
<'tcx
> {
522 IfLet(Box
<Pat
<'tcx
>>, ExprId
),
525 #[derive(Copy, Clone, Debug, HashStable)]
527 /// The `&&` operator.
529 /// The `||` operator.
533 #[derive(Clone, Debug, HashStable)]
534 pub enum InlineAsmOperand
<'tcx
> {
536 reg
: InlineAsmRegOrRegClass
,
540 reg
: InlineAsmRegOrRegClass
,
542 expr
: Option
<ExprId
>,
545 reg
: InlineAsmRegOrRegClass
,
550 reg
: InlineAsmRegOrRegClass
,
553 out_expr
: Option
<ExprId
>,
556 value
: mir
::ConstantKind
<'tcx
>,
560 value
: mir
::ConstantKind
<'tcx
>,
568 #[derive(Copy, Clone, Debug, PartialEq, HashStable)]
569 pub enum BindingMode
{
574 #[derive(Clone, Debug, HashStable)]
575 pub struct FieldPat
<'tcx
> {
577 pub pattern
: Box
<Pat
<'tcx
>>,
580 #[derive(Clone, Debug, HashStable)]
581 pub struct Pat
<'tcx
> {
584 pub kind
: PatKind
<'tcx
>,
587 impl<'tcx
> Pat
<'tcx
> {
588 pub fn wildcard_from_ty(ty
: Ty
<'tcx
>) -> Self {
589 Pat { ty, span: DUMMY_SP, kind: PatKind::Wild }
592 pub fn simple_ident(&self) -> Option
<Symbol
> {
594 PatKind
::Binding { name, mode: BindingMode::ByValue, subpattern: None, .. }
=> {
601 /// Call `f` on every "binding" in a pattern, e.g., on `a` in
602 /// `match foo() { Some(a) => (), None => () }`
603 pub fn each_binding(&self, mut f
: impl FnMut(Symbol
, BindingMode
, Ty
<'tcx
>, Span
)) {
604 self.walk_always(|p
| {
605 if let PatKind
::Binding { name, mode, ty, .. }
= p
.kind
{
606 f(name
, mode
, ty
, p
.span
);
611 /// Walk the pattern in left-to-right order.
613 /// If `it(pat)` returns `false`, the children are not visited.
614 pub fn walk(&self, mut it
: impl FnMut(&Pat
<'tcx
>) -> bool
) {
618 fn walk_(&self, it
: &mut impl FnMut(&Pat
<'tcx
>) -> bool
) {
625 Wild
| Range(..) | Binding { subpattern: None, .. }
| Constant { .. }
=> {}
626 AscribeUserType { subpattern, .. }
627 | Binding { subpattern: Some(subpattern), .. }
628 | Deref { subpattern }
=> subpattern
.walk_(it
),
629 Leaf { subpatterns }
| Variant { subpatterns, .. }
=> {
630 subpatterns
.iter().for_each(|field
| field
.pattern
.walk_(it
))
632 Or { pats }
=> pats
.iter().for_each(|p
| p
.walk_(it
)),
633 Array { box ref prefix, ref slice, box ref suffix }
634 | Slice { box ref prefix, ref slice, box ref suffix }
=> {
635 prefix
.iter().chain(slice
.iter()).chain(suffix
.iter()).for_each(|p
| p
.walk_(it
))
640 /// Walk the pattern in left-to-right order.
642 /// If you always want to recurse, prefer this method over `walk`.
643 pub fn walk_always(&self, mut it
: impl FnMut(&Pat
<'tcx
>)) {
651 impl<'tcx
> IntoDiagnosticArg
for Pat
<'tcx
> {
652 fn into_diagnostic_arg(self) -> DiagnosticArgValue
<'
static> {
653 format
!("{}", self).into_diagnostic_arg()
657 #[derive(Clone, Debug, HashStable)]
658 pub struct Ascription
<'tcx
> {
659 pub annotation
: CanonicalUserTypeAnnotation
<'tcx
>,
660 /// Variance to use when relating the `user_ty` to the **type of the value being
661 /// matched**. Typically, this is `Variance::Covariant`, since the value being matched must
662 /// have a type that is some subtype of the ascribed type.
664 /// Note that this variance does not apply for any bindings within subpatterns. The type
665 /// assigned to those bindings must be exactly equal to the `user_ty` given here.
667 /// The only place where this field is not `Covariant` is when matching constants, where
668 /// we currently use `Contravariant` -- this is because the constant type just needs to
669 /// be "comparable" to the type of the input value. So, for example:
672 /// match x { "foo" => .. }
675 /// requires that `&'static str <: T_x`, where `T_x` is the type of `x`. Really, we should
676 /// probably be checking for a `PartialEq` impl instead, but this preserves the behavior
677 /// of the old type-check for now. See #57280 for details.
678 pub variance
: ty
::Variance
,
681 #[derive(Clone, Debug, HashStable)]
682 pub enum PatKind
<'tcx
> {
683 /// A wildcard pattern: `_`.
687 ascription
: Ascription
<'tcx
>,
688 subpattern
: Box
<Pat
<'tcx
>>,
691 /// `x`, `ref x`, `x @ P`, etc.
693 mutability
: Mutability
,
698 subpattern
: Option
<Box
<Pat
<'tcx
>>>,
699 /// Is this the leftmost occurrence of the binding, i.e., is `var` the
700 /// `HirId` of this pattern?
704 /// `Foo(...)` or `Foo{...}` or `Foo`, where `Foo` is a variant name from an ADT with
705 /// multiple variants.
707 adt_def
: AdtDef
<'tcx
>,
708 substs
: SubstsRef
<'tcx
>,
709 variant_index
: VariantIdx
,
710 subpatterns
: Vec
<FieldPat
<'tcx
>>,
713 /// `(...)`, `Foo(...)`, `Foo{...}`, or `Foo`, where `Foo` is a variant name from an ADT with
714 /// a single variant.
716 subpatterns
: Vec
<FieldPat
<'tcx
>>,
719 /// `box P`, `&P`, `&mut P`, etc.
721 subpattern
: Box
<Pat
<'tcx
>>,
724 /// One of the following:
725 /// * `&str`, which will be handled as a string pattern and thus exhaustiveness
726 /// checking will detect if you use the same string twice in different patterns.
727 /// * integer, bool, char or float, which will be handled by exhaustiveness to cover exactly
728 /// its own value, similar to `&str`, but these values are much simpler.
729 /// * Opaque constants, that must not be matched structurally. So anything that does not derive
730 /// `PartialEq` and `Eq`.
732 value
: mir
::ConstantKind
<'tcx
>,
735 Range(Box
<PatRange
<'tcx
>>),
737 /// Matches against a slice, checking the length and extracting elements.
738 /// irrefutable when there is a slice pattern and both `prefix` and `suffix` are empty.
739 /// e.g., `&[ref xs @ ..]`.
741 prefix
: Box
<[Box
<Pat
<'tcx
>>]>,
742 slice
: Option
<Box
<Pat
<'tcx
>>>,
743 suffix
: Box
<[Box
<Pat
<'tcx
>>]>,
746 /// Fixed match against an array; irrefutable.
748 prefix
: Box
<[Box
<Pat
<'tcx
>>]>,
749 slice
: Option
<Box
<Pat
<'tcx
>>>,
750 suffix
: Box
<[Box
<Pat
<'tcx
>>]>,
753 /// An or-pattern, e.g. `p | q`.
754 /// Invariant: `pats.len() >= 2`.
756 pats
: Box
<[Box
<Pat
<'tcx
>>]>,
760 #[derive(Clone, Debug, PartialEq, HashStable)]
761 pub struct PatRange
<'tcx
> {
762 pub lo
: mir
::ConstantKind
<'tcx
>,
763 pub hi
: mir
::ConstantKind
<'tcx
>,
767 impl<'tcx
> fmt
::Display
for Pat
<'tcx
> {
768 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
769 // Printing lists is a chore.
770 let mut first
= true;
771 let mut start_or_continue
= |s
| {
779 let mut start_or_comma
= || start_or_continue(", ");
782 PatKind
::Wild
=> write
!(f
, "_"),
783 PatKind
::AscribeUserType { ref subpattern, .. }
=> write
!(f
, "{}: _", subpattern
),
784 PatKind
::Binding { mutability, name, mode, ref subpattern, .. }
=> {
785 let is_mut
= match mode
{
786 BindingMode
::ByValue
=> mutability
== Mutability
::Mut
,
787 BindingMode
::ByRef(bk
) => {
789 matches
!(bk
, BorrowKind
::Mut { .. }
)
795 write
!(f
, "{}", name
)?
;
796 if let Some(ref subpattern
) = *subpattern
{
797 write
!(f
, " @ {}", subpattern
)?
;
801 PatKind
::Variant { ref subpatterns, .. }
| PatKind
::Leaf { ref subpatterns }
=> {
802 let variant_and_name
= match self.kind
{
803 PatKind
::Variant { adt_def, variant_index, .. }
=> ty
::tls
::with(|tcx
| {
804 let variant
= adt_def
.variant(variant_index
);
805 let adt_did
= adt_def
.did();
806 let name
= if tcx
.get_diagnostic_item(sym
::Option
) == Some(adt_did
)
807 || tcx
.get_diagnostic_item(sym
::Result
) == Some(adt_did
)
809 variant
.name
.to_string()
811 format
!("{}::{}", tcx
.def_path_str(adt_def
.did()), variant
.name
)
813 Some((variant
, name
))
815 _
=> self.ty
.ty_adt_def().and_then(|adt_def
| {
816 if !adt_def
.is_enum() {
817 ty
::tls
::with(|tcx
| {
818 Some((adt_def
.non_enum_variant(), tcx
.def_path_str(adt_def
.did())))
826 if let Some((variant
, name
)) = &variant_and_name
{
827 write
!(f
, "{}", name
)?
;
829 // Only for Adt we can have `S {...}`,
830 // which we handle separately here.
831 if variant
.ctor
.is_none() {
835 for p
in subpatterns
{
836 if let PatKind
::Wild
= p
.pattern
.kind
{
839 let name
= variant
.fields
[p
.field
].name
;
840 write
!(f
, "{}{}: {}", start_or_comma(), name
, p
.pattern
)?
;
844 if printed
< variant
.fields
.len() {
845 write
!(f
, "{}..", start_or_comma())?
;
848 return write
!(f
, " }}");
853 variant_and_name
.as_ref().map_or(subpatterns
.len(), |(v
, _
)| v
.fields
.len());
854 if num_fields
!= 0 || variant_and_name
.is_none() {
856 for i
in 0..num_fields
{
857 write
!(f
, "{}", start_or_comma())?
;
859 // Common case: the field is where we expect it.
860 if let Some(p
) = subpatterns
.get(i
) {
861 if p
.field
.index() == i
{
862 write
!(f
, "{}", p
.pattern
)?
;
867 // Otherwise, we have to go looking for it.
868 if let Some(p
) = subpatterns
.iter().find(|p
| p
.field
.index() == i
) {
869 write
!(f
, "{}", p
.pattern
)?
;
879 PatKind
::Deref { ref subpattern }
=> {
880 match self.ty
.kind() {
881 ty
::Adt(def
, _
) if def
.is_box() => write
!(f
, "box ")?
,
882 ty
::Ref(_
, _
, mutbl
) => {
883 write
!(f
, "&{}", mutbl
.prefix_str())?
;
885 _
=> bug
!("{} is a bad Deref pattern type", self.ty
),
887 write
!(f
, "{}", subpattern
)
889 PatKind
::Constant { value }
=> write
!(f
, "{}", value
),
890 PatKind
::Range(box PatRange { lo, hi, end }
) => {
891 write
!(f
, "{}", lo
)?
;
892 write
!(f
, "{}", end
)?
;
895 PatKind
::Slice { ref prefix, ref slice, ref suffix }
896 | PatKind
::Array { ref prefix, ref slice, ref suffix }
=> {
898 for p
in prefix
.iter() {
899 write
!(f
, "{}{}", start_or_comma(), p
)?
;
901 if let Some(ref slice
) = *slice
{
902 write
!(f
, "{}", start_or_comma())?
;
905 _
=> write
!(f
, "{}", slice
)?
,
909 for p
in suffix
.iter() {
910 write
!(f
, "{}{}", start_or_comma(), p
)?
;
914 PatKind
::Or { ref pats }
=> {
915 for pat
in pats
.iter() {
916 write
!(f
, "{}{}", start_or_continue(" | "), pat
)?
;
924 // Some nodes are used a lot. Make sure they don't unintentionally get bigger.
925 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
928 // tidy-alphabetical-start
929 static_assert_size
!(Block
, 56);
930 static_assert_size
!(Expr
<'_
>, 64);
931 static_assert_size
!(ExprKind
<'_
>, 40);
932 static_assert_size
!(Pat
<'_
>, 72);
933 static_assert_size
!(PatKind
<'_
>, 56);
934 static_assert_size
!(Stmt
<'_
>, 56);
935 static_assert_size
!(StmtKind
<'_
>, 48);
936 // tidy-alphabetical-end