]> git.proxmox.com Git - rustc.git/blob - compiler/rustc_middle/src/thir.rs
New upstream version 1.70.0+dfsg1
[rustc.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_errors::{DiagnosticArgValue, IntoDiagnosticArg};
13 use rustc_hir as hir;
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;
29 use std::fmt;
30 use std::ops::Index;
31
32 pub mod visit;
33
34 macro_rules! thir_with_elements {
35 (
36 $($field_name:ident: $field_ty:ty,)*
37
38 @elements:
39 $($name:ident: $id:ty => $value:ty => $format:literal,)*
40 ) => {
41 $(
42 newtype_index! {
43 #[derive(HashStable)]
44 #[debug_format = $format]
45 pub struct $id {}
46 }
47 )*
48
49 /// A container for a THIR body.
50 ///
51 /// This can be indexed directly by any THIR index (e.g. [`ExprId`]).
52 #[derive(Debug, HashStable, Clone)]
53 pub struct Thir<'tcx> {
54 $(
55 pub $field_name: $field_ty,
56 )*
57 $(
58 pub $name: IndexVec<$id, $value>,
59 )*
60 }
61
62 impl<'tcx> Thir<'tcx> {
63 pub fn new($($field_name: $field_ty,)*) -> Thir<'tcx> {
64 Thir {
65 $(
66 $field_name,
67 )*
68 $(
69 $name: IndexVec::new(),
70 )*
71 }
72 }
73 }
74
75 $(
76 impl<'tcx> Index<$id> for Thir<'tcx> {
77 type Output = $value;
78 fn index(&self, index: $id) -> &Self::Output {
79 &self.$name[index]
80 }
81 }
82 )*
83 }
84 }
85
86 pub const UPVAR_ENV_PARAM: ParamId = ParamId::from_u32(0);
87
88 thir_with_elements! {
89 body_type: BodyTy<'tcx>,
90
91 @elements:
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{}",
97 }
98
99 #[derive(Debug, HashStable, Clone)]
100 pub enum BodyTy<'tcx> {
101 Const(Ty<'tcx>),
102 Fn(FnSig<'tcx>),
103 }
104
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.
111 pub ty: Ty<'tcx>,
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>,
116 /// HirId for lints.
117 pub hir_id: Option<hir::HirId>,
118 }
119
120 #[derive(Copy, Clone, Debug, HashStable)]
121 pub enum LintLevel {
122 Inherited,
123 Explicit(hir::HirId),
124 }
125
126 #[derive(Clone, Debug, HashStable)]
127 pub struct Block {
128 /// Whether the block itself has a label. Used by `label: {}`
129 /// and `try` blocks.
130 ///
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.
137 pub span: Span,
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,
143 }
144
145 type UserTy<'tcx> = Option<Box<CanonicalUserType<'tcx>>>;
146
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>,
154
155 /// Optional user-given substs: for something like `let x =
156 /// Bar::<T> { ... }`.
157 pub user_ty: UserTy<'tcx>,
158
159 pub fields: Box<[FieldExpr]>,
160 /// The base, e.g. `Foo {x: 1, .. base}`.
161 pub base: Option<FruInfo<'tcx>>,
162 }
163
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)>,
171 }
172
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],
179 }
180
181 #[derive(Copy, Clone, Debug, HashStable)]
182 pub enum BlockSafety {
183 Safe,
184 /// A compiler-generated unsafe block
185 BuiltinUnsafe,
186 /// An `unsafe` block. The `HirId` is the ID of the block.
187 ExplicitUnsafe(hir::HirId),
188 }
189
190 #[derive(Clone, Debug, HashStable)]
191 pub struct Stmt<'tcx> {
192 pub kind: StmtKind<'tcx>,
193 pub opt_destruction_scope: Option<region::Scope>,
194 }
195
196 #[derive(Clone, Debug, HashStable)]
197 pub enum StmtKind<'tcx> {
198 /// An expression with a trailing semicolon.
199 Expr {
200 /// The scope for this statement; may be used as lifetime of temporaries.
201 scope: region::Scope,
202
203 /// The expression being evaluated in this statement.
204 expr: ExprId,
205 },
206
207 /// A `let` binding.
208 Let {
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,
212
213 /// The scope for the initialization itself; might be used as
214 /// lifetime of temporaries.
215 init_scope: region::Scope,
216
217 /// `let <PAT> = ...`
218 ///
219 /// If a type annotation is included, it is added as an ascription pattern.
220 pattern: Box<Pat<'tcx>>,
221
222 /// `let pat: ty = <INIT>`
223 initializer: Option<ExprId>,
224
225 /// `let pat: ty = <INIT> else { <ELSE> }`
226 else_block: Option<BlockId>,
227
228 /// The lint level for this `let` statement.
229 lint_level: LintLevel,
230
231 /// Span of the `let <PAT> = <INIT>` part.
232 span: Span,
233 },
234 }
235
236 #[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)]
237 #[derive(TypeFoldable, TypeVisitable)]
238 pub struct LocalVarId(pub hir::HirId);
239
240 /// A THIR expression.
241 #[derive(Clone, Debug, HashStable)]
242 pub struct Expr<'tcx> {
243 /// kind of expression
244 pub kind: ExprKind<'tcx>,
245
246 /// The type of this expression
247 pub ty: Ty<'tcx>,
248
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>,
252
253 /// span of the expression in the source
254 pub span: Span,
255 }
256
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.
261 Scope {
262 region_scope: region::Scope,
263 lint_level: LintLevel,
264 value: ExprId,
265 },
266 /// A `box <value>` expression.
267 Box {
268 value: ExprId,
269 },
270 /// An `if` expression.
271 If {
272 if_then_scope: region::Scope,
273 cond: ExprId,
274 then: ExprId,
275 else_opt: Option<ExprId>,
276 },
277 /// A function call. Method calls and overloaded operators are converted to plain function calls.
278 Call {
279 /// The type of the function. This is often a [`FnDef`] or a [`FnPtr`].
280 ///
281 /// [`FnDef`]: ty::TyKind::FnDef
282 /// [`FnPtr`]: ty::TyKind::FnPtr
283 ty: Ty<'tcx>,
284 /// The function itself.
285 fun: ExprId,
286 /// The arguments passed to the function.
287 ///
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))`).
290 args: Box<[ExprId]>,
291 /// Whether this is from an overloaded operator rather than a
292 /// function call from HIR. `true` for overloaded function call.
293 from_hir_call: bool,
294 /// The span of the function, without the dot and receiver
295 /// (e.g. `foo(a, b)` in `x.foo(a, b)`).
296 fn_span: Span,
297 },
298 /// A *non-overloaded* dereference.
299 Deref {
300 arg: ExprId,
301 },
302 /// A *non-overloaded* binary operation.
303 Binary {
304 op: BinOp,
305 lhs: ExprId,
306 rhs: ExprId,
307 },
308 /// A logical operation. This is distinct from `BinaryOp` because
309 /// the operands need to be lazily evaluated.
310 LogicalOp {
311 op: LogicalOp,
312 lhs: ExprId,
313 rhs: ExprId,
314 },
315 /// A *non-overloaded* unary operation. Note that here the deref (`*`)
316 /// operator is represented by `ExprKind::Deref`.
317 Unary {
318 op: UnOp,
319 arg: ExprId,
320 },
321 /// A cast: `<source> as <type>`. The type we cast to is the type of
322 /// the parent expression.
323 Cast {
324 source: ExprId,
325 },
326 Use {
327 source: ExprId,
328 }, // Use a lexpr to get a vexpr.
329 /// A coercion from `!` to any type.
330 NeverToAny {
331 source: ExprId,
332 },
333 /// A pointer cast. More information can be found in [`PointerCast`].
334 Pointer {
335 cast: PointerCast,
336 source: ExprId,
337 },
338 /// A `loop` expression.
339 Loop {
340 body: ExprId,
341 },
342 Let {
343 expr: ExprId,
344 pat: Box<Pat<'tcx>>,
345 },
346 /// A `match` expression.
347 Match {
348 scrutinee: ExprId,
349 arms: Box<[ArmId]>,
350 },
351 /// A block.
352 Block {
353 block: BlockId,
354 },
355 /// An assignment: `lhs = rhs`.
356 Assign {
357 lhs: ExprId,
358 rhs: ExprId,
359 },
360 /// A *non-overloaded* operation assignment, e.g. `lhs += rhs`.
361 AssignOp {
362 op: BinOp,
363 lhs: ExprId,
364 rhs: ExprId,
365 },
366 /// Access to a field of a struct, a tuple, an union, or an enum.
367 Field {
368 lhs: ExprId,
369 /// Variant containing the field.
370 variant_index: VariantIdx,
371 /// This can be a named (`.foo`) or unnamed (`.0`) field.
372 name: FieldIdx,
373 },
374 /// A *non-overloaded* indexing operation.
375 Index {
376 lhs: ExprId,
377 index: ExprId,
378 },
379 /// A local variable.
380 VarRef {
381 id: LocalVarId,
382 },
383 /// Used to represent upvars mentioned in a closure/generator
384 UpvarRef {
385 /// DefId of the closure/generator
386 closure_def_id: DefId,
387
388 /// HirId of the root variable
389 var_hir_id: LocalVarId,
390 },
391 /// A borrow, e.g. `&arg`.
392 Borrow {
393 borrow_kind: BorrowKind,
394 arg: ExprId,
395 },
396 /// A `&raw [const|mut] $place_expr` raw borrow resulting in type `*[const|mut] T`.
397 AddressOf {
398 mutability: hir::Mutability,
399 arg: ExprId,
400 },
401 /// A `break` expression.
402 Break {
403 label: region::Scope,
404 value: Option<ExprId>,
405 },
406 /// A `continue` expression.
407 Continue {
408 label: region::Scope,
409 },
410 /// A `return` expression.
411 Return {
412 value: Option<ExprId>,
413 },
414 /// An inline `const` block, e.g. `const {}`.
415 ConstBlock {
416 did: DefId,
417 substs: SubstsRef<'tcx>,
418 },
419 /// An array literal constructed from one repeated element, e.g. `[1; 5]`.
420 Repeat {
421 value: ExprId,
422 count: ty::Const<'tcx>,
423 },
424 /// An array, e.g. `[a, b, c, d]`.
425 Array {
426 fields: Box<[ExprId]>,
427 },
428 /// A tuple, e.g. `(a, b, c, d)`.
429 Tuple {
430 fields: Box<[ExprId]>,
431 },
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 {
436 source: ExprId,
437 /// Type that the user gave to this expression
438 user_ty: UserTy<'tcx>,
439 },
440 /// A type ascription on a value, e.g. `42: i32`.
441 ValueTypeAscription {
442 source: ExprId,
443 /// Type that the user gave to this expression
444 user_ty: UserTy<'tcx>,
445 },
446 /// A closure definition.
447 Closure(Box<ClosureExpr<'tcx>>),
448 /// A literal.
449 Literal {
450 lit: &'tcx hir::Lit,
451 neg: bool,
452 },
453 /// For literals that don't correspond to anything in the HIR
454 NonHirLiteral {
455 lit: ty::ScalarInt,
456 user_ty: UserTy<'tcx>,
457 },
458 /// A literal of a ZST type.
459 ZstLiteral {
460 user_ty: UserTy<'tcx>,
461 },
462 /// Associated constants and named constants
463 NamedConst {
464 def_id: DefId,
465 substs: SubstsRef<'tcx>,
466 user_ty: UserTy<'tcx>,
467 },
468 ConstParam {
469 param: ty::ParamConst,
470 def_id: DefId,
471 },
472 // FIXME improve docs for `StaticRef` by distinguishing it from `NamedConst`
473 /// A literal containing the address of a `static`.
474 ///
475 /// This is only distinguished from `Literal` so that we can register some
476 /// info for diagnostics.
477 StaticRef {
478 alloc_id: AllocId,
479 ty: Ty<'tcx>,
480 def_id: DefId,
481 },
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.
487 Yield {
488 value: ExprId,
489 },
490 }
491
492 /// Represents the association of a field identifier and an expression.
493 ///
494 /// This is used in struct constructors.
495 #[derive(Clone, Debug, HashStable)]
496 pub struct FieldExpr {
497 pub name: FieldIdx,
498 pub expr: ExprId,
499 }
500
501 #[derive(Clone, Debug, HashStable)]
502 pub struct FruInfo<'tcx> {
503 pub base: ExprId,
504 pub field_types: Box<[Ty<'tcx>]>,
505 }
506
507 /// A `match` arm.
508 #[derive(Clone, Debug, HashStable)]
509 pub struct Arm<'tcx> {
510 pub pattern: Box<Pat<'tcx>>,
511 pub guard: Option<Guard<'tcx>>,
512 pub body: ExprId,
513 pub lint_level: LintLevel,
514 pub scope: region::Scope,
515 pub span: Span,
516 }
517
518 /// A `match` guard.
519 #[derive(Clone, Debug, HashStable)]
520 pub enum Guard<'tcx> {
521 If(ExprId),
522 IfLet(Box<Pat<'tcx>>, ExprId),
523 }
524
525 #[derive(Copy, Clone, Debug, HashStable)]
526 pub enum LogicalOp {
527 /// The `&&` operator.
528 And,
529 /// The `||` operator.
530 Or,
531 }
532
533 #[derive(Clone, Debug, HashStable)]
534 pub enum InlineAsmOperand<'tcx> {
535 In {
536 reg: InlineAsmRegOrRegClass,
537 expr: ExprId,
538 },
539 Out {
540 reg: InlineAsmRegOrRegClass,
541 late: bool,
542 expr: Option<ExprId>,
543 },
544 InOut {
545 reg: InlineAsmRegOrRegClass,
546 late: bool,
547 expr: ExprId,
548 },
549 SplitInOut {
550 reg: InlineAsmRegOrRegClass,
551 late: bool,
552 in_expr: ExprId,
553 out_expr: Option<ExprId>,
554 },
555 Const {
556 value: mir::ConstantKind<'tcx>,
557 span: Span,
558 },
559 SymFn {
560 value: mir::ConstantKind<'tcx>,
561 span: Span,
562 },
563 SymStatic {
564 def_id: DefId,
565 },
566 }
567
568 #[derive(Copy, Clone, Debug, PartialEq, HashStable)]
569 pub enum BindingMode {
570 ByValue,
571 ByRef(BorrowKind),
572 }
573
574 #[derive(Clone, Debug, HashStable)]
575 pub struct FieldPat<'tcx> {
576 pub field: FieldIdx,
577 pub pattern: Box<Pat<'tcx>>,
578 }
579
580 #[derive(Clone, Debug, HashStable)]
581 pub struct Pat<'tcx> {
582 pub ty: Ty<'tcx>,
583 pub span: Span,
584 pub kind: PatKind<'tcx>,
585 }
586
587 impl<'tcx> Pat<'tcx> {
588 pub fn wildcard_from_ty(ty: Ty<'tcx>) -> Self {
589 Pat { ty, span: DUMMY_SP, kind: PatKind::Wild }
590 }
591
592 pub fn simple_ident(&self) -> Option<Symbol> {
593 match self.kind {
594 PatKind::Binding { name, mode: BindingMode::ByValue, subpattern: None, .. } => {
595 Some(name)
596 }
597 _ => None,
598 }
599 }
600
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);
607 }
608 });
609 }
610
611 /// Walk the pattern in left-to-right order.
612 ///
613 /// If `it(pat)` returns `false`, the children are not visited.
614 pub fn walk(&self, mut it: impl FnMut(&Pat<'tcx>) -> bool) {
615 self.walk_(&mut it)
616 }
617
618 fn walk_(&self, it: &mut impl FnMut(&Pat<'tcx>) -> bool) {
619 if !it(self) {
620 return;
621 }
622
623 use PatKind::*;
624 match &self.kind {
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))
631 }
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))
636 }
637 }
638 }
639
640 /// Walk the pattern in left-to-right order.
641 ///
642 /// If you always want to recurse, prefer this method over `walk`.
643 pub fn walk_always(&self, mut it: impl FnMut(&Pat<'tcx>)) {
644 self.walk(|p| {
645 it(p);
646 true
647 })
648 }
649 }
650
651 impl<'tcx> IntoDiagnosticArg for Pat<'tcx> {
652 fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
653 format!("{}", self).into_diagnostic_arg()
654 }
655 }
656
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.
663 ///
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.
666 ///
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:
670 ///
671 /// ```text
672 /// match x { "foo" => .. }
673 /// ```
674 ///
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,
679 }
680
681 #[derive(Clone, Debug, HashStable)]
682 pub enum PatKind<'tcx> {
683 /// A wildcard pattern: `_`.
684 Wild,
685
686 AscribeUserType {
687 ascription: Ascription<'tcx>,
688 subpattern: Box<Pat<'tcx>>,
689 },
690
691 /// `x`, `ref x`, `x @ P`, etc.
692 Binding {
693 mutability: Mutability,
694 name: Symbol,
695 mode: BindingMode,
696 var: LocalVarId,
697 ty: Ty<'tcx>,
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?
701 is_primary: bool,
702 },
703
704 /// `Foo(...)` or `Foo{...}` or `Foo`, where `Foo` is a variant name from an ADT with
705 /// multiple variants.
706 Variant {
707 adt_def: AdtDef<'tcx>,
708 substs: SubstsRef<'tcx>,
709 variant_index: VariantIdx,
710 subpatterns: Vec<FieldPat<'tcx>>,
711 },
712
713 /// `(...)`, `Foo(...)`, `Foo{...}`, or `Foo`, where `Foo` is a variant name from an ADT with
714 /// a single variant.
715 Leaf {
716 subpatterns: Vec<FieldPat<'tcx>>,
717 },
718
719 /// `box P`, `&P`, `&mut P`, etc.
720 Deref {
721 subpattern: Box<Pat<'tcx>>,
722 },
723
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`.
731 Constant {
732 value: mir::ConstantKind<'tcx>,
733 },
734
735 Range(Box<PatRange<'tcx>>),
736
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 @ ..]`.
740 Slice {
741 prefix: Box<[Box<Pat<'tcx>>]>,
742 slice: Option<Box<Pat<'tcx>>>,
743 suffix: Box<[Box<Pat<'tcx>>]>,
744 },
745
746 /// Fixed match against an array; irrefutable.
747 Array {
748 prefix: Box<[Box<Pat<'tcx>>]>,
749 slice: Option<Box<Pat<'tcx>>>,
750 suffix: Box<[Box<Pat<'tcx>>]>,
751 },
752
753 /// An or-pattern, e.g. `p | q`.
754 /// Invariant: `pats.len() >= 2`.
755 Or {
756 pats: Box<[Box<Pat<'tcx>>]>,
757 },
758 }
759
760 #[derive(Clone, Debug, PartialEq, HashStable)]
761 pub struct PatRange<'tcx> {
762 pub lo: mir::ConstantKind<'tcx>,
763 pub hi: mir::ConstantKind<'tcx>,
764 pub end: RangeEnd,
765 }
766
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| {
772 if first {
773 first = false;
774 ""
775 } else {
776 s
777 }
778 };
779 let mut start_or_comma = || start_or_continue(", ");
780
781 match self.kind {
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) => {
788 write!(f, "ref ")?;
789 matches!(bk, BorrowKind::Mut { .. })
790 }
791 };
792 if is_mut {
793 write!(f, "mut ")?;
794 }
795 write!(f, "{}", name)?;
796 if let Some(ref subpattern) = *subpattern {
797 write!(f, " @ {}", subpattern)?;
798 }
799 Ok(())
800 }
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)
808 {
809 variant.name.to_string()
810 } else {
811 format!("{}::{}", tcx.def_path_str(adt_def.did()), variant.name)
812 };
813 Some((variant, name))
814 }),
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())))
819 })
820 } else {
821 None
822 }
823 }),
824 };
825
826 if let Some((variant, name)) = &variant_and_name {
827 write!(f, "{}", name)?;
828
829 // Only for Adt we can have `S {...}`,
830 // which we handle separately here.
831 if variant.ctor.is_none() {
832 write!(f, " {{ ")?;
833
834 let mut printed = 0;
835 for p in subpatterns {
836 if let PatKind::Wild = p.pattern.kind {
837 continue;
838 }
839 let name = variant.fields[p.field].name;
840 write!(f, "{}{}: {}", start_or_comma(), name, p.pattern)?;
841 printed += 1;
842 }
843
844 if printed < variant.fields.len() {
845 write!(f, "{}..", start_or_comma())?;
846 }
847
848 return write!(f, " }}");
849 }
850 }
851
852 let num_fields =
853 variant_and_name.as_ref().map_or(subpatterns.len(), |(v, _)| v.fields.len());
854 if num_fields != 0 || variant_and_name.is_none() {
855 write!(f, "(")?;
856 for i in 0..num_fields {
857 write!(f, "{}", start_or_comma())?;
858
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)?;
863 continue;
864 }
865 }
866
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)?;
870 } else {
871 write!(f, "_")?;
872 }
873 }
874 write!(f, ")")?;
875 }
876
877 Ok(())
878 }
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())?;
884 }
885 _ => bug!("{} is a bad Deref pattern type", self.ty),
886 }
887 write!(f, "{}", subpattern)
888 }
889 PatKind::Constant { value } => write!(f, "{}", value),
890 PatKind::Range(box PatRange { lo, hi, end }) => {
891 write!(f, "{}", lo)?;
892 write!(f, "{}", end)?;
893 write!(f, "{}", hi)
894 }
895 PatKind::Slice { ref prefix, ref slice, ref suffix }
896 | PatKind::Array { ref prefix, ref slice, ref suffix } => {
897 write!(f, "[")?;
898 for p in prefix.iter() {
899 write!(f, "{}{}", start_or_comma(), p)?;
900 }
901 if let Some(ref slice) = *slice {
902 write!(f, "{}", start_or_comma())?;
903 match slice.kind {
904 PatKind::Wild => {}
905 _ => write!(f, "{}", slice)?,
906 }
907 write!(f, "..")?;
908 }
909 for p in suffix.iter() {
910 write!(f, "{}{}", start_or_comma(), p)?;
911 }
912 write!(f, "]")
913 }
914 PatKind::Or { ref pats } => {
915 for pat in pats.iter() {
916 write!(f, "{}{}", start_or_continue(" | "), pat)?;
917 }
918 Ok(())
919 }
920 }
921 }
922 }
923
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"))]
926 mod size_asserts {
927 use super::*;
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
937 }