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::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::PointerCoercion; 22 use rustc_middle::ty::subst::SubstsRef; 23 use rustc_middle::ty::{self, AdtDef, FnSig, List, 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 pub struct LocalVarId(pub hir::HirId); 238 239 /// A THIR expression. 240 #[derive(Clone, Debug, HashStable)] 241 pub struct Expr<'tcx> { 242 /// kind of expression 243 pub kind: ExprKind<'tcx>, 244 245 /// The type of this expression 246 pub ty: Ty<'tcx>, 247 248 /// The lifetime of this expression if it should be spilled into a 249 /// temporary; should be `None` only if in a constant context 250 pub temp_lifetime: Option<region::Scope>, 251 252 /// span of the expression in the source 253 pub span: Span, 254 } 255 256 #[derive(Clone, Debug, HashStable)] 257 pub enum ExprKind<'tcx> { 258 /// `Scope`s are used to explicitly mark destruction scopes, 259 /// and to track the `HirId` of the expressions within the scope. 260 Scope { 261 region_scope: region::Scope, 262 lint_level: LintLevel, 263 value: ExprId, 264 }, 265 /// A `box <value>` expression. 266 Box { 267 value: ExprId, 268 }, 269 /// An `if` expression. 270 If { 271 if_then_scope: region::Scope, 272 cond: ExprId, 273 then: ExprId, 274 else_opt: Option<ExprId>, 275 }, 276 /// A function call. Method calls and overloaded operators are converted to plain function calls. 277 Call { 278 /// The type of the function. This is often a [`FnDef`] or a [`FnPtr`]. 279 /// 280 /// [`FnDef`]: ty::TyKind::FnDef 281 /// [`FnPtr`]: ty::TyKind::FnPtr 282 ty: Ty<'tcx>, 283 /// The function itself. 284 fun: ExprId, 285 /// The arguments passed to the function. 286 /// 287 /// Note: in some cases (like calling a closure), the function call `f(...args)` gets 288 /// rewritten as a call to a function trait method (e.g. `FnOnce::call_once(f, (...args))`). 289 args: Box<[ExprId]>, 290 /// Whether this is from an overloaded operator rather than a 291 /// function call from HIR. `true` for overloaded function call. 292 from_hir_call: bool, 293 /// The span of the function, without the dot and receiver 294 /// (e.g. `foo(a, b)` in `x.foo(a, b)`). 295 fn_span: Span, 296 }, 297 /// A *non-overloaded* dereference. 298 Deref { 299 arg: ExprId, 300 }, 301 /// A *non-overloaded* binary operation. 302 Binary { 303 op: BinOp, 304 lhs: ExprId, 305 rhs: ExprId, 306 }, 307 /// A logical operation. This is distinct from `BinaryOp` because 308 /// the operands need to be lazily evaluated. 309 LogicalOp { 310 op: LogicalOp, 311 lhs: ExprId, 312 rhs: ExprId, 313 }, 314 /// A *non-overloaded* unary operation. Note that here the deref (`*`) 315 /// operator is represented by `ExprKind::Deref`. 316 Unary { 317 op: UnOp, 318 arg: ExprId, 319 }, 320 /// A cast: `<source> as <type>`. The type we cast to is the type of 321 /// the parent expression. 322 Cast { 323 source: ExprId, 324 }, 325 Use { 326 source: ExprId, 327 }, // Use a lexpr to get a vexpr. 328 /// A coercion from `!` to any type. 329 NeverToAny { 330 source: ExprId, 331 }, 332 /// A pointer coercion. More information can be found in [`PointerCoercion`]. 333 /// Pointer casts that cannot be done by coercions are represented by [`ExprKind::Cast`]. 334 PointerCoercion { 335 cast: PointerCoercion, 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 /// A `become` expression. 415 Become { 416 value: ExprId, 417 }, 418 /// An inline `const` block, e.g. `const {}`. 419 ConstBlock { 420 did: DefId, 421 substs: SubstsRef<'tcx>, 422 }, 423 /// An array literal constructed from one repeated element, e.g. `[1; 5]`. 424 Repeat { 425 value: ExprId, 426 count: ty::Const<'tcx>, 427 }, 428 /// An array, e.g. `[a, b, c, d]`. 429 Array { 430 fields: Box<[ExprId]>, 431 }, 432 /// A tuple, e.g. `(a, b, c, d)`. 433 Tuple { 434 fields: Box<[ExprId]>, 435 }, 436 /// An ADT constructor, e.g. `Foo {x: 1, y: 2}`. 437 Adt(Box<AdtExpr<'tcx>>), 438 /// A type ascription on a place. 439 PlaceTypeAscription { 440 source: ExprId, 441 /// Type that the user gave to this expression 442 user_ty: UserTy<'tcx>, 443 }, 444 /// A type ascription on a value, e.g. `42: i32`. 445 ValueTypeAscription { 446 source: ExprId, 447 /// Type that the user gave to this expression 448 user_ty: UserTy<'tcx>, 449 }, 450 /// A closure definition. 451 Closure(Box<ClosureExpr<'tcx>>), 452 /// A literal. 453 Literal { 454 lit: &'tcx hir::Lit, 455 neg: bool, 456 }, 457 /// For literals that don't correspond to anything in the HIR 458 NonHirLiteral { 459 lit: ty::ScalarInt, 460 user_ty: UserTy<'tcx>, 461 }, 462 /// A literal of a ZST type. 463 ZstLiteral { 464 user_ty: UserTy<'tcx>, 465 }, 466 /// Associated constants and named constants 467 NamedConst { 468 def_id: DefId, 469 substs: SubstsRef<'tcx>, 470 user_ty: UserTy<'tcx>, 471 }, 472 ConstParam { 473 param: ty::ParamConst, 474 def_id: DefId, 475 }, 476 // FIXME improve docs for `StaticRef` by distinguishing it from `NamedConst` 477 /// A literal containing the address of a `static`. 478 /// 479 /// This is only distinguished from `Literal` so that we can register some 480 /// info for diagnostics. 481 StaticRef { 482 alloc_id: AllocId, 483 ty: Ty<'tcx>, 484 def_id: DefId, 485 }, 486 /// Inline assembly, i.e. `asm!()`. 487 InlineAsm(Box<InlineAsmExpr<'tcx>>), 488 /// Field offset (`offset_of!`) 489 OffsetOf { 490 container: Ty<'tcx>, 491 fields: &'tcx List<FieldIdx>, 492 }, 493 /// An expression taking a reference to a thread local. 494 ThreadLocalRef(DefId), 495 /// A `yield` expression. 496 Yield { 497 value: ExprId, 498 }, 499 } 500 501 /// Represents the association of a field identifier and an expression. 502 /// 503 /// This is used in struct constructors. 504 #[derive(Clone, Debug, HashStable)] 505 pub struct FieldExpr { 506 pub name: FieldIdx, 507 pub expr: ExprId, 508 } 509 510 #[derive(Clone, Debug, HashStable)] 511 pub struct FruInfo<'tcx> { 512 pub base: ExprId, 513 pub field_types: Box<[Ty<'tcx>]>, 514 } 515 516 /// A `match` arm. 517 #[derive(Clone, Debug, HashStable)] 518 pub struct Arm<'tcx> { 519 pub pattern: Box<Pat<'tcx>>, 520 pub guard: Option<Guard<'tcx>>, 521 pub body: ExprId, 522 pub lint_level: LintLevel, 523 pub scope: region::Scope, 524 pub span: Span, 525 } 526 527 /// A `match` guard. 528 #[derive(Clone, Debug, HashStable)] 529 pub enum Guard<'tcx> { 530 If(ExprId), 531 IfLet(Box<Pat<'tcx>>, ExprId), 532 } 533 534 #[derive(Copy, Clone, Debug, HashStable)] 535 pub enum LogicalOp { 536 /// The `&&` operator. 537 And, 538 /// The `||` operator. 539 Or, 540 } 541 542 #[derive(Clone, Debug, HashStable)] 543 pub enum InlineAsmOperand<'tcx> { 544 In { 545 reg: InlineAsmRegOrRegClass, 546 expr: ExprId, 547 }, 548 Out { 549 reg: InlineAsmRegOrRegClass, 550 late: bool, 551 expr: Option<ExprId>, 552 }, 553 InOut { 554 reg: InlineAsmRegOrRegClass, 555 late: bool, 556 expr: ExprId, 557 }, 558 SplitInOut { 559 reg: InlineAsmRegOrRegClass, 560 late: bool, 561 in_expr: ExprId, 562 out_expr: Option<ExprId>, 563 }, 564 Const { 565 value: mir::ConstantKind<'tcx>, 566 span: Span, 567 }, 568 SymFn { 569 value: mir::ConstantKind<'tcx>, 570 span: Span, 571 }, 572 SymStatic { 573 def_id: DefId, 574 }, 575 } 576 577 #[derive(Copy, Clone, Debug, PartialEq, HashStable)] 578 pub enum BindingMode { 579 ByValue, 580 ByRef(BorrowKind), 581 } 582 583 #[derive(Clone, Debug, HashStable)] 584 pub struct FieldPat<'tcx> { 585 pub field: FieldIdx, 586 pub pattern: Box<Pat<'tcx>>, 587 } 588 589 #[derive(Clone, Debug, HashStable)] 590 pub struct Pat<'tcx> { 591 pub ty: Ty<'tcx>, 592 pub span: Span, 593 pub kind: PatKind<'tcx>, 594 } 595 596 impl<'tcx> Pat<'tcx> { wildcard_from_ty(ty: Ty<'tcx>) -> Self597 pub fn wildcard_from_ty(ty: Ty<'tcx>) -> Self { 598 Pat { ty, span: DUMMY_SP, kind: PatKind::Wild } 599 } 600 simple_ident(&self) -> Option<Symbol>601 pub fn simple_ident(&self) -> Option<Symbol> { 602 match self.kind { 603 PatKind::Binding { name, mode: BindingMode::ByValue, subpattern: None, .. } => { 604 Some(name) 605 } 606 _ => None, 607 } 608 } 609 610 /// Call `f` on every "binding" in a pattern, e.g., on `a` in 611 /// `match foo() { Some(a) => (), None => () }` each_binding(&self, mut f: impl FnMut(Symbol, BindingMode, Ty<'tcx>, Span))612 pub fn each_binding(&self, mut f: impl FnMut(Symbol, BindingMode, Ty<'tcx>, Span)) { 613 self.walk_always(|p| { 614 if let PatKind::Binding { name, mode, ty, .. } = p.kind { 615 f(name, mode, ty, p.span); 616 } 617 }); 618 } 619 620 /// Walk the pattern in left-to-right order. 621 /// 622 /// If `it(pat)` returns `false`, the children are not visited. walk(&self, mut it: impl FnMut(&Pat<'tcx>) -> bool)623 pub fn walk(&self, mut it: impl FnMut(&Pat<'tcx>) -> bool) { 624 self.walk_(&mut it) 625 } 626 walk_(&self, it: &mut impl FnMut(&Pat<'tcx>) -> bool)627 fn walk_(&self, it: &mut impl FnMut(&Pat<'tcx>) -> bool) { 628 if !it(self) { 629 return; 630 } 631 632 use PatKind::*; 633 match &self.kind { 634 Wild | Range(..) | Binding { subpattern: None, .. } | Constant { .. } => {} 635 AscribeUserType { subpattern, .. } 636 | Binding { subpattern: Some(subpattern), .. } 637 | Deref { subpattern } => subpattern.walk_(it), 638 Leaf { subpatterns } | Variant { subpatterns, .. } => { 639 subpatterns.iter().for_each(|field| field.pattern.walk_(it)) 640 } 641 Or { pats } => pats.iter().for_each(|p| p.walk_(it)), 642 Array { box ref prefix, ref slice, box ref suffix } 643 | Slice { box ref prefix, ref slice, box ref suffix } => { 644 prefix.iter().chain(slice.iter()).chain(suffix.iter()).for_each(|p| p.walk_(it)) 645 } 646 } 647 } 648 649 /// Walk the pattern in left-to-right order. 650 /// 651 /// If you always want to recurse, prefer this method over `walk`. walk_always(&self, mut it: impl FnMut(&Pat<'tcx>))652 pub fn walk_always(&self, mut it: impl FnMut(&Pat<'tcx>)) { 653 self.walk(|p| { 654 it(p); 655 true 656 }) 657 } 658 } 659 660 impl<'tcx> IntoDiagnosticArg for Pat<'tcx> { into_diagnostic_arg(self) -> DiagnosticArgValue<'static>661 fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { 662 format!("{}", self).into_diagnostic_arg() 663 } 664 } 665 666 #[derive(Clone, Debug, HashStable)] 667 pub struct Ascription<'tcx> { 668 pub annotation: CanonicalUserTypeAnnotation<'tcx>, 669 /// Variance to use when relating the `user_ty` to the **type of the value being 670 /// matched**. Typically, this is `Variance::Covariant`, since the value being matched must 671 /// have a type that is some subtype of the ascribed type. 672 /// 673 /// Note that this variance does not apply for any bindings within subpatterns. The type 674 /// assigned to those bindings must be exactly equal to the `user_ty` given here. 675 /// 676 /// The only place where this field is not `Covariant` is when matching constants, where 677 /// we currently use `Contravariant` -- this is because the constant type just needs to 678 /// be "comparable" to the type of the input value. So, for example: 679 /// 680 /// ```text 681 /// match x { "foo" => .. } 682 /// ``` 683 /// 684 /// requires that `&'static str <: T_x`, where `T_x` is the type of `x`. Really, we should 685 /// probably be checking for a `PartialEq` impl instead, but this preserves the behavior 686 /// of the old type-check for now. See #57280 for details. 687 pub variance: ty::Variance, 688 } 689 690 #[derive(Clone, Debug, HashStable)] 691 pub enum PatKind<'tcx> { 692 /// A wildcard pattern: `_`. 693 Wild, 694 695 AscribeUserType { 696 ascription: Ascription<'tcx>, 697 subpattern: Box<Pat<'tcx>>, 698 }, 699 700 /// `x`, `ref x`, `x @ P`, etc. 701 Binding { 702 mutability: Mutability, 703 name: Symbol, 704 mode: BindingMode, 705 var: LocalVarId, 706 ty: Ty<'tcx>, 707 subpattern: Option<Box<Pat<'tcx>>>, 708 /// Is this the leftmost occurrence of the binding, i.e., is `var` the 709 /// `HirId` of this pattern? 710 is_primary: bool, 711 }, 712 713 /// `Foo(...)` or `Foo{...}` or `Foo`, where `Foo` is a variant name from an ADT with 714 /// multiple variants. 715 Variant { 716 adt_def: AdtDef<'tcx>, 717 substs: SubstsRef<'tcx>, 718 variant_index: VariantIdx, 719 subpatterns: Vec<FieldPat<'tcx>>, 720 }, 721 722 /// `(...)`, `Foo(...)`, `Foo{...}`, or `Foo`, where `Foo` is a variant name from an ADT with 723 /// a single variant. 724 Leaf { 725 subpatterns: Vec<FieldPat<'tcx>>, 726 }, 727 728 /// `box P`, `&P`, `&mut P`, etc. 729 Deref { 730 subpattern: Box<Pat<'tcx>>, 731 }, 732 733 /// One of the following: 734 /// * `&str`, which will be handled as a string pattern and thus exhaustiveness 735 /// checking will detect if you use the same string twice in different patterns. 736 /// * integer, bool, char or float, which will be handled by exhaustiveness to cover exactly 737 /// its own value, similar to `&str`, but these values are much simpler. 738 /// * Opaque constants, that must not be matched structurally. So anything that does not derive 739 /// `PartialEq` and `Eq`. 740 Constant { 741 value: mir::ConstantKind<'tcx>, 742 }, 743 744 Range(Box<PatRange<'tcx>>), 745 746 /// Matches against a slice, checking the length and extracting elements. 747 /// irrefutable when there is a slice pattern and both `prefix` and `suffix` are empty. 748 /// e.g., `&[ref xs @ ..]`. 749 Slice { 750 prefix: Box<[Box<Pat<'tcx>>]>, 751 slice: Option<Box<Pat<'tcx>>>, 752 suffix: Box<[Box<Pat<'tcx>>]>, 753 }, 754 755 /// Fixed match against an array; irrefutable. 756 Array { 757 prefix: Box<[Box<Pat<'tcx>>]>, 758 slice: Option<Box<Pat<'tcx>>>, 759 suffix: Box<[Box<Pat<'tcx>>]>, 760 }, 761 762 /// An or-pattern, e.g. `p | q`. 763 /// Invariant: `pats.len() >= 2`. 764 Or { 765 pats: Box<[Box<Pat<'tcx>>]>, 766 }, 767 } 768 769 #[derive(Clone, Debug, PartialEq, HashStable)] 770 pub struct PatRange<'tcx> { 771 pub lo: mir::ConstantKind<'tcx>, 772 pub hi: mir::ConstantKind<'tcx>, 773 pub end: RangeEnd, 774 } 775 776 impl<'tcx> fmt::Display for Pat<'tcx> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result777 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 778 // Printing lists is a chore. 779 let mut first = true; 780 let mut start_or_continue = |s| { 781 if first { 782 first = false; 783 "" 784 } else { 785 s 786 } 787 }; 788 let mut start_or_comma = || start_or_continue(", "); 789 790 match self.kind { 791 PatKind::Wild => write!(f, "_"), 792 PatKind::AscribeUserType { ref subpattern, .. } => write!(f, "{}: _", subpattern), 793 PatKind::Binding { mutability, name, mode, ref subpattern, .. } => { 794 let is_mut = match mode { 795 BindingMode::ByValue => mutability == Mutability::Mut, 796 BindingMode::ByRef(bk) => { 797 write!(f, "ref ")?; 798 matches!(bk, BorrowKind::Mut { .. }) 799 } 800 }; 801 if is_mut { 802 write!(f, "mut ")?; 803 } 804 write!(f, "{}", name)?; 805 if let Some(ref subpattern) = *subpattern { 806 write!(f, " @ {}", subpattern)?; 807 } 808 Ok(()) 809 } 810 PatKind::Variant { ref subpatterns, .. } | PatKind::Leaf { ref subpatterns } => { 811 let variant_and_name = match self.kind { 812 PatKind::Variant { adt_def, variant_index, .. } => ty::tls::with(|tcx| { 813 let variant = adt_def.variant(variant_index); 814 let adt_did = adt_def.did(); 815 let name = if tcx.get_diagnostic_item(sym::Option) == Some(adt_did) 816 || tcx.get_diagnostic_item(sym::Result) == Some(adt_did) 817 { 818 variant.name.to_string() 819 } else { 820 format!("{}::{}", tcx.def_path_str(adt_def.did()), variant.name) 821 }; 822 Some((variant, name)) 823 }), 824 _ => self.ty.ty_adt_def().and_then(|adt_def| { 825 if !adt_def.is_enum() { 826 ty::tls::with(|tcx| { 827 Some((adt_def.non_enum_variant(), tcx.def_path_str(adt_def.did()))) 828 }) 829 } else { 830 None 831 } 832 }), 833 }; 834 835 if let Some((variant, name)) = &variant_and_name { 836 write!(f, "{}", name)?; 837 838 // Only for Adt we can have `S {...}`, 839 // which we handle separately here. 840 if variant.ctor.is_none() { 841 write!(f, " {{ ")?; 842 843 let mut printed = 0; 844 for p in subpatterns { 845 if let PatKind::Wild = p.pattern.kind { 846 continue; 847 } 848 let name = variant.fields[p.field].name; 849 write!(f, "{}{}: {}", start_or_comma(), name, p.pattern)?; 850 printed += 1; 851 } 852 853 if printed < variant.fields.len() { 854 write!(f, "{}..", start_or_comma())?; 855 } 856 857 return write!(f, " }}"); 858 } 859 } 860 861 let num_fields = 862 variant_and_name.as_ref().map_or(subpatterns.len(), |(v, _)| v.fields.len()); 863 if num_fields != 0 || variant_and_name.is_none() { 864 write!(f, "(")?; 865 for i in 0..num_fields { 866 write!(f, "{}", start_or_comma())?; 867 868 // Common case: the field is where we expect it. 869 if let Some(p) = subpatterns.get(i) { 870 if p.field.index() == i { 871 write!(f, "{}", p.pattern)?; 872 continue; 873 } 874 } 875 876 // Otherwise, we have to go looking for it. 877 if let Some(p) = subpatterns.iter().find(|p| p.field.index() == i) { 878 write!(f, "{}", p.pattern)?; 879 } else { 880 write!(f, "_")?; 881 } 882 } 883 write!(f, ")")?; 884 } 885 886 Ok(()) 887 } 888 PatKind::Deref { ref subpattern } => { 889 match self.ty.kind() { 890 ty::Adt(def, _) if def.is_box() => write!(f, "box ")?, 891 ty::Ref(_, _, mutbl) => { 892 write!(f, "&{}", mutbl.prefix_str())?; 893 } 894 _ => bug!("{} is a bad Deref pattern type", self.ty), 895 } 896 write!(f, "{}", subpattern) 897 } 898 PatKind::Constant { value } => write!(f, "{}", value), 899 PatKind::Range(box PatRange { lo, hi, end }) => { 900 write!(f, "{}", lo)?; 901 write!(f, "{}", end)?; 902 write!(f, "{}", hi) 903 } 904 PatKind::Slice { ref prefix, ref slice, ref suffix } 905 | PatKind::Array { ref prefix, ref slice, ref suffix } => { 906 write!(f, "[")?; 907 for p in prefix.iter() { 908 write!(f, "{}{}", start_or_comma(), p)?; 909 } 910 if let Some(ref slice) = *slice { 911 write!(f, "{}", start_or_comma())?; 912 match slice.kind { 913 PatKind::Wild => {} 914 _ => write!(f, "{}", slice)?, 915 } 916 write!(f, "..")?; 917 } 918 for p in suffix.iter() { 919 write!(f, "{}{}", start_or_comma(), p)?; 920 } 921 write!(f, "]") 922 } 923 PatKind::Or { ref pats } => { 924 for pat in pats.iter() { 925 write!(f, "{}{}", start_or_continue(" | "), pat)?; 926 } 927 Ok(()) 928 } 929 } 930 } 931 } 932 933 // Some nodes are used a lot. Make sure they don't unintentionally get bigger. 934 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] 935 mod size_asserts { 936 use super::*; 937 // tidy-alphabetical-start 938 static_assert_size!(Block, 56); 939 static_assert_size!(Expr<'_>, 64); 940 static_assert_size!(ExprKind<'_>, 40); 941 static_assert_size!(Pat<'_>, 64); 942 static_assert_size!(PatKind<'_>, 48); 943 static_assert_size!(Stmt<'_>, 56); 944 static_assert_size!(StmtKind<'_>, 48); 945 // tidy-alphabetical-end 946 } 947