rustc_middle/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
11use std::cmp::Ordering;
12use std::fmt;
13use std::ops::Index;
14use std::sync::Arc;
15
16use rustc_abi::{FieldIdx, Integer, Size, VariantIdx};
17use rustc_ast::{AsmMacro, InlineAsmOptions, InlineAsmTemplatePiece};
18use rustc_hir as hir;
19use rustc_hir::def_id::DefId;
20use rustc_hir::{BindingMode, ByRef, HirId, MatchSource, RangeEnd};
21use rustc_index::{IndexVec, newtype_index};
22use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeVisitable};
23use rustc_span::def_id::LocalDefId;
24use rustc_span::{ErrorGuaranteed, Span, Symbol};
25use rustc_target::asm::InlineAsmRegOrRegClass;
26use tracing::instrument;
27
28use crate::middle::region;
29use crate::mir::interpret::AllocId;
30use crate::mir::{self, AssignOp, BinOp, BorrowKind, FakeReadCause, UnOp};
31use crate::thir::visit::for_each_immediate_subpat;
32use crate::ty::adjustment::PointerCoercion;
33use crate::ty::layout::IntegerExt;
34use crate::ty::{
35 self, AdtDef, CanonicalUserType, CanonicalUserTypeAnnotation, FnSig, GenericArgsRef, Ty,
36 TyCtxt, UpvarArgs,
37};
38
39pub mod visit;
40
41macro_rules! thir_with_elements {
42 (
43 $($name:ident: $id:ty => $value:ty => $format:literal,)*
44 ) => {
45 $(
46 newtype_index! {
47 #[derive(HashStable)]
48 #[debug_format = $format]
49 pub struct $id {}
50 }
51 )*
52
53 // Note: Making `Thir` implement `Clone` is useful for external tools that need access to
54 // THIR bodies even after the `Steal` query result has been stolen.
55 // One such tool is https://github.com/rust-corpus/qrates/.
56 /// A container for a THIR body.
57 ///
58 /// This can be indexed directly by any THIR index (e.g. [`ExprId`]).
59 #[derive(Debug, HashStable, Clone)]
60 pub struct Thir<'tcx> {
61 pub body_type: BodyTy<'tcx>,
62 $(
63 pub $name: IndexVec<$id, $value>,
64 )*
65 }
66
67 impl<'tcx> Thir<'tcx> {
68 pub fn new(body_type: BodyTy<'tcx>) -> Thir<'tcx> {
69 Thir {
70 body_type,
71 $(
72 $name: IndexVec::new(),
73 )*
74 }
75 }
76 }
77
78 $(
79 impl<'tcx> Index<$id> for Thir<'tcx> {
80 type Output = $value;
81 fn index(&self, index: $id) -> &Self::Output {
82 &self.$name[index]
83 }
84 }
85 )*
86 }
87}
88
89thir_with_elements! {
90 arms: ArmId => Arm<'tcx> => "a{}",
91 blocks: BlockId => Block => "b{}",
92 exprs: ExprId => Expr<'tcx> => "e{}",
93 stmts: StmtId => Stmt<'tcx> => "s{}",
94 params: ParamId => Param<'tcx> => "p{}",
95}
96
97#[derive(Debug, HashStable, Clone)]
98pub enum BodyTy<'tcx> {
99 Const(Ty<'tcx>),
100 Fn(FnSig<'tcx>),
101 GlobalAsm(Ty<'tcx>),
102}
103
104/// Description of a type-checked function parameter.
105#[derive(Clone, Debug, HashStable)]
106pub struct Param<'tcx> {
107 /// The pattern that appears in the parameter list, or None for implicit parameters.
108 pub pat: Option<Box<Pat<'tcx>>>,
109 /// The possibly inferred type.
110 pub ty: Ty<'tcx>,
111 /// Span of the explicitly provided type, or None if inferred for closures.
112 pub ty_span: Option<Span>,
113 /// Whether this param is `self`, and how it is bound.
114 pub self_kind: Option<hir::ImplicitSelfKind>,
115 /// HirId for lints.
116 pub hir_id: Option<HirId>,
117}
118
119#[derive(Copy, Clone, Debug, HashStable)]
120pub enum LintLevel {
121 Inherited,
122 Explicit(HirId),
123}
124
125#[derive(Clone, Debug, HashStable)]
126pub struct Block {
127 /// Whether the block itself has a label. Used by `label: {}`
128 /// and `try` blocks.
129 ///
130 /// This does *not* include labels on loops, e.g. `'label: loop {}`.
131 pub targeted_by_break: bool,
132 pub region_scope: region::Scope,
133 /// The span of the block, including the opening braces,
134 /// the label, and the `unsafe` keyword, if present.
135 pub span: Span,
136 /// The statements in the blocK.
137 pub stmts: Box<[StmtId]>,
138 /// The trailing expression of the block, if any.
139 pub expr: Option<ExprId>,
140 pub safety_mode: BlockSafety,
141}
142
143type UserTy<'tcx> = Option<Box<CanonicalUserType<'tcx>>>;
144
145#[derive(Clone, Debug, HashStable)]
146pub struct AdtExpr<'tcx> {
147 /// The ADT we're constructing.
148 pub adt_def: AdtDef<'tcx>,
149 /// The variant of the ADT.
150 pub variant_index: VariantIdx,
151 pub args: GenericArgsRef<'tcx>,
152
153 /// Optional user-given args: for something like `let x =
154 /// Bar::<T> { ... }`.
155 pub user_ty: UserTy<'tcx>,
156
157 pub fields: Box<[FieldExpr]>,
158 /// The base, e.g. `Foo {x: 1, ..base}`.
159 pub base: AdtExprBase<'tcx>,
160}
161
162#[derive(Clone, Debug, HashStable)]
163pub enum AdtExprBase<'tcx> {
164 /// A struct expression where all the fields are explicitly enumerated: `Foo { a, b }`.
165 None,
166 /// A struct expression with a "base", an expression of the same type as the outer struct that
167 /// will be used to populate any fields not explicitly mentioned: `Foo { ..base }`
168 Base(FruInfo<'tcx>),
169 /// A struct expression with a `..` tail but no "base" expression. The values from the struct
170 /// fields' default values will be used to populate any fields not explicitly mentioned:
171 /// `Foo { .. }`.
172 DefaultFields(Box<[Ty<'tcx>]>),
173}
174
175#[derive(Clone, Debug, HashStable)]
176pub struct ClosureExpr<'tcx> {
177 pub closure_id: LocalDefId,
178 pub args: UpvarArgs<'tcx>,
179 pub upvars: Box<[ExprId]>,
180 pub movability: Option<hir::Movability>,
181 pub fake_reads: Vec<(ExprId, FakeReadCause, HirId)>,
182}
183
184#[derive(Clone, Debug, HashStable)]
185pub struct InlineAsmExpr<'tcx> {
186 pub asm_macro: AsmMacro,
187 pub template: &'tcx [InlineAsmTemplatePiece],
188 pub operands: Box<[InlineAsmOperand<'tcx>]>,
189 pub options: InlineAsmOptions,
190 pub line_spans: &'tcx [Span],
191}
192
193#[derive(Copy, Clone, Debug, HashStable)]
194pub enum BlockSafety {
195 Safe,
196 /// A compiler-generated unsafe block
197 BuiltinUnsafe,
198 /// An `unsafe` block. The `HirId` is the ID of the block.
199 ExplicitUnsafe(HirId),
200}
201
202#[derive(Clone, Debug, HashStable)]
203pub struct Stmt<'tcx> {
204 pub kind: StmtKind<'tcx>,
205}
206
207#[derive(Clone, Debug, HashStable)]
208pub enum StmtKind<'tcx> {
209 /// An expression with a trailing semicolon.
210 Expr {
211 /// The scope for this statement; may be used as lifetime of temporaries.
212 scope: region::Scope,
213
214 /// The expression being evaluated in this statement.
215 expr: ExprId,
216 },
217
218 /// A `let` binding.
219 Let {
220 /// The scope for variables bound in this `let`; it covers this and
221 /// all the remaining statements in the block.
222 remainder_scope: region::Scope,
223
224 /// The scope for the initialization itself; might be used as
225 /// lifetime of temporaries.
226 init_scope: region::Scope,
227
228 /// `let <PAT> = ...`
229 ///
230 /// If a type annotation is included, it is added as an ascription pattern.
231 pattern: Box<Pat<'tcx>>,
232
233 /// `let pat: ty = <INIT>`
234 initializer: Option<ExprId>,
235
236 /// `let pat: ty = <INIT> else { <ELSE> }`
237 else_block: Option<BlockId>,
238
239 /// The lint level for this `let` statement.
240 lint_level: LintLevel,
241
242 /// Span of the `let <PAT> = <INIT>` part.
243 span: Span,
244 },
245}
246
247#[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)]
248pub struct LocalVarId(pub HirId);
249
250/// A THIR expression.
251#[derive(Clone, Debug, HashStable)]
252pub struct Expr<'tcx> {
253 /// kind of expression
254 pub kind: ExprKind<'tcx>,
255
256 /// The type of this expression
257 pub ty: Ty<'tcx>,
258
259 /// The id of the HIR expression whose [temporary scope] should be used for this expression.
260 ///
261 /// [temporary scope]: https://doc.rust-lang.org/reference/destructors.html#temporary-scopes
262 pub temp_scope_id: hir::ItemLocalId,
263
264 /// span of the expression in the source
265 pub span: Span,
266}
267
268#[derive(Clone, Debug, HashStable)]
269pub enum ExprKind<'tcx> {
270 /// `Scope`s are used to explicitly mark destruction scopes,
271 /// and to track the `HirId` of the expressions within the scope.
272 Scope {
273 region_scope: region::Scope,
274 lint_level: LintLevel,
275 value: ExprId,
276 },
277 /// A `box <value>` expression.
278 Box {
279 value: ExprId,
280 },
281 /// An `if` expression.
282 If {
283 if_then_scope: region::Scope,
284 cond: ExprId,
285 /// `then` is always `ExprKind::Block`.
286 then: ExprId,
287 /// If present, the `else_opt` expr is always `ExprKind::Block` (for
288 /// `else`) or `ExprKind::If` (for `else if`).
289 else_opt: Option<ExprId>,
290 },
291 /// A function call. Method calls and overloaded operators are converted to plain function calls.
292 Call {
293 /// The type of the function. This is often a [`FnDef`] or a [`FnPtr`].
294 ///
295 /// [`FnDef`]: ty::TyKind::FnDef
296 /// [`FnPtr`]: ty::TyKind::FnPtr
297 ty: Ty<'tcx>,
298 /// The function itself.
299 fun: ExprId,
300 /// The arguments passed to the function.
301 ///
302 /// Note: in some cases (like calling a closure), the function call `f(...args)` gets
303 /// rewritten as a call to a function trait method (e.g. `FnOnce::call_once(f, (...args))`).
304 args: Box<[ExprId]>,
305 /// Whether this is from an overloaded operator rather than a
306 /// function call from HIR. `true` for overloaded function call.
307 from_hir_call: bool,
308 /// The span of the function, without the dot and receiver
309 /// (e.g. `foo(a, b)` in `x.foo(a, b)`).
310 fn_span: Span,
311 },
312 /// A use expression `x.use`.
313 ByUse {
314 /// The expression on which use is applied.
315 expr: ExprId,
316 /// The span of use, without the dot and receiver
317 /// (e.g. `use` in `x.use`).
318 span: Span,
319 },
320 /// A *non-overloaded* dereference.
321 Deref {
322 arg: ExprId,
323 },
324 /// A *non-overloaded* binary operation.
325 Binary {
326 op: BinOp,
327 lhs: ExprId,
328 rhs: ExprId,
329 },
330 /// A logical operation. This is distinct from `BinaryOp` because
331 /// the operands need to be lazily evaluated.
332 LogicalOp {
333 op: LogicalOp,
334 lhs: ExprId,
335 rhs: ExprId,
336 },
337 /// A *non-overloaded* unary operation. Note that here the deref (`*`)
338 /// operator is represented by `ExprKind::Deref`.
339 Unary {
340 op: UnOp,
341 arg: ExprId,
342 },
343 /// A cast: `<source> as <type>`. The type we cast to is the type of
344 /// the parent expression.
345 Cast {
346 source: ExprId,
347 },
348 /// Forces its contents to be treated as a value expression, not a place
349 /// expression. This is inserted in some places where an operation would
350 /// otherwise be erased completely (e.g. some no-op casts), but we still
351 /// need to ensure that its operand is treated as a value and not a place.
352 Use {
353 source: ExprId,
354 },
355 /// A coercion from `!` to any type.
356 NeverToAny {
357 source: ExprId,
358 },
359 /// A pointer coercion. More information can be found in [`PointerCoercion`].
360 /// Pointer casts that cannot be done by coercions are represented by [`ExprKind::Cast`].
361 PointerCoercion {
362 cast: PointerCoercion,
363 source: ExprId,
364 /// Whether this coercion is written with an `as` cast in the source code.
365 is_from_as_cast: bool,
366 },
367 /// A `loop` expression.
368 Loop {
369 body: ExprId,
370 },
371 /// A `#[loop_match] loop { state = 'blk: { match state { ... } } }` expression.
372 LoopMatch {
373 /// The state variable that is updated.
374 /// The `match_data.scrutinee` is the same variable, but with a different span.
375 state: ExprId,
376 region_scope: region::Scope,
377 match_data: Box<LoopMatchMatchData>,
378 },
379 /// Special expression representing the `let` part of an `if let` or similar construct
380 /// (including `if let` guards in match arms, and let-chains formed by `&&`).
381 ///
382 /// This isn't considered a real expression in surface Rust syntax, so it can
383 /// only appear in specific situations, such as within the condition of an `if`.
384 ///
385 /// (Not to be confused with [`StmtKind::Let`], which is a normal `let` statement.)
386 Let {
387 expr: ExprId,
388 pat: Box<Pat<'tcx>>,
389 },
390 /// A `match` expression.
391 Match {
392 scrutinee: ExprId,
393 arms: Box<[ArmId]>,
394 match_source: MatchSource,
395 },
396 /// A block.
397 Block {
398 block: BlockId,
399 },
400 /// An assignment: `lhs = rhs`.
401 Assign {
402 lhs: ExprId,
403 rhs: ExprId,
404 },
405 /// A *non-overloaded* operation assignment, e.g. `lhs += rhs`.
406 AssignOp {
407 op: AssignOp,
408 lhs: ExprId,
409 rhs: ExprId,
410 },
411 /// Access to a field of a struct, a tuple, an union, or an enum.
412 Field {
413 lhs: ExprId,
414 /// Variant containing the field.
415 variant_index: VariantIdx,
416 /// This can be a named (`.foo`) or unnamed (`.0`) field.
417 name: FieldIdx,
418 },
419 /// A *non-overloaded* indexing operation.
420 Index {
421 lhs: ExprId,
422 index: ExprId,
423 },
424 /// A local variable.
425 VarRef {
426 id: LocalVarId,
427 },
428 /// Used to represent upvars mentioned in a closure/coroutine
429 UpvarRef {
430 /// DefId of the closure/coroutine
431 closure_def_id: DefId,
432
433 /// HirId of the root variable
434 var_hir_id: LocalVarId,
435 },
436 /// A borrow, e.g. `&arg`.
437 Borrow {
438 borrow_kind: BorrowKind,
439 arg: ExprId,
440 },
441 /// A `&raw [const|mut] $place_expr` raw borrow resulting in type `*[const|mut] T`.
442 RawBorrow {
443 mutability: hir::Mutability,
444 arg: ExprId,
445 },
446 /// A `break` expression.
447 Break {
448 label: region::Scope,
449 value: Option<ExprId>,
450 },
451 /// A `continue` expression.
452 Continue {
453 label: region::Scope,
454 },
455 /// A `#[const_continue] break` expression.
456 ConstContinue {
457 label: region::Scope,
458 value: ExprId,
459 },
460 /// A `return` expression.
461 Return {
462 value: Option<ExprId>,
463 },
464 /// A `become` expression.
465 Become {
466 value: ExprId,
467 },
468 /// An inline `const` block, e.g. `const {}`.
469 ConstBlock {
470 did: DefId,
471 args: GenericArgsRef<'tcx>,
472 },
473 /// An array literal constructed from one repeated element, e.g. `[1; 5]`.
474 Repeat {
475 value: ExprId,
476 count: ty::Const<'tcx>,
477 },
478 /// An array, e.g. `[a, b, c, d]`.
479 Array {
480 fields: Box<[ExprId]>,
481 },
482 /// A tuple, e.g. `(a, b, c, d)`.
483 Tuple {
484 fields: Box<[ExprId]>,
485 },
486 /// An ADT constructor, e.g. `Foo {x: 1, y: 2}`.
487 Adt(Box<AdtExpr<'tcx>>),
488 /// A type ascription on a place.
489 PlaceTypeAscription {
490 source: ExprId,
491 /// Type that the user gave to this expression
492 user_ty: UserTy<'tcx>,
493 user_ty_span: Span,
494 },
495 /// A type ascription on a value, e.g. `type_ascribe!(42, i32)` or `42 as i32`.
496 ValueTypeAscription {
497 source: ExprId,
498 /// Type that the user gave to this expression
499 user_ty: UserTy<'tcx>,
500 user_ty_span: Span,
501 },
502 /// An unsafe binder cast on a place, e.g. `unwrap_binder!(*ptr)`.
503 PlaceUnwrapUnsafeBinder {
504 source: ExprId,
505 },
506 /// An unsafe binder cast on a value, e.g. `unwrap_binder!(rvalue())`,
507 /// which makes a temporary.
508 ValueUnwrapUnsafeBinder {
509 source: ExprId,
510 },
511 /// Construct an unsafe binder, e.g. `wrap_binder(&ref)`.
512 WrapUnsafeBinder {
513 source: ExprId,
514 },
515 /// A closure definition.
516 Closure(Box<ClosureExpr<'tcx>>),
517 /// A literal.
518 Literal {
519 lit: hir::Lit,
520 neg: bool,
521 },
522 /// For literals that don't correspond to anything in the HIR
523 NonHirLiteral {
524 lit: ty::ScalarInt,
525 user_ty: UserTy<'tcx>,
526 },
527 /// A literal of a ZST type.
528 ZstLiteral {
529 user_ty: UserTy<'tcx>,
530 },
531 /// Associated constants and named constants
532 NamedConst {
533 def_id: DefId,
534 args: GenericArgsRef<'tcx>,
535 user_ty: UserTy<'tcx>,
536 },
537 ConstParam {
538 param: ty::ParamConst,
539 def_id: DefId,
540 },
541 // FIXME improve docs for `StaticRef` by distinguishing it from `NamedConst`
542 /// A literal containing the address of a `static`.
543 ///
544 /// This is only distinguished from `Literal` so that we can register some
545 /// info for diagnostics.
546 StaticRef {
547 alloc_id: AllocId,
548 ty: Ty<'tcx>,
549 def_id: DefId,
550 },
551 /// Inline assembly, i.e. `asm!()`.
552 InlineAsm(Box<InlineAsmExpr<'tcx>>),
553 /// An expression taking a reference to a thread local.
554 ThreadLocalRef(DefId),
555 /// A `yield` expression.
556 Yield {
557 value: ExprId,
558 },
559}
560
561/// Represents the association of a field identifier and an expression.
562///
563/// This is used in struct constructors.
564#[derive(Clone, Debug, HashStable)]
565pub struct FieldExpr {
566 pub name: FieldIdx,
567 pub expr: ExprId,
568}
569
570#[derive(Clone, Debug, HashStable)]
571pub struct FruInfo<'tcx> {
572 pub base: ExprId,
573 pub field_types: Box<[Ty<'tcx>]>,
574}
575
576/// A `match` arm.
577#[derive(Clone, Debug, HashStable)]
578pub struct Arm<'tcx> {
579 pub pattern: Box<Pat<'tcx>>,
580 pub guard: Option<ExprId>,
581 pub body: ExprId,
582 pub lint_level: LintLevel,
583 pub scope: region::Scope,
584 pub span: Span,
585}
586
587/// The `match` part of a `#[loop_match]`
588#[derive(Clone, Debug, HashStable)]
589pub struct LoopMatchMatchData {
590 pub scrutinee: ExprId,
591 pub arms: Box<[ArmId]>,
592 pub span: Span,
593}
594
595#[derive(Copy, Clone, Debug, HashStable)]
596pub enum LogicalOp {
597 /// The `&&` operator.
598 And,
599 /// The `||` operator.
600 Or,
601}
602
603#[derive(Clone, Debug, HashStable)]
604pub enum InlineAsmOperand<'tcx> {
605 In {
606 reg: InlineAsmRegOrRegClass,
607 expr: ExprId,
608 },
609 Out {
610 reg: InlineAsmRegOrRegClass,
611 late: bool,
612 expr: Option<ExprId>,
613 },
614 InOut {
615 reg: InlineAsmRegOrRegClass,
616 late: bool,
617 expr: ExprId,
618 },
619 SplitInOut {
620 reg: InlineAsmRegOrRegClass,
621 late: bool,
622 in_expr: ExprId,
623 out_expr: Option<ExprId>,
624 },
625 Const {
626 value: mir::Const<'tcx>,
627 span: Span,
628 },
629 SymFn {
630 value: ExprId,
631 },
632 SymStatic {
633 def_id: DefId,
634 },
635 Label {
636 block: BlockId,
637 },
638}
639
640#[derive(Clone, Debug, HashStable, TypeVisitable)]
641pub struct FieldPat<'tcx> {
642 pub field: FieldIdx,
643 pub pattern: Pat<'tcx>,
644}
645
646#[derive(Clone, Debug, HashStable, TypeVisitable)]
647pub struct Pat<'tcx> {
648 pub ty: Ty<'tcx>,
649 pub span: Span,
650 pub kind: PatKind<'tcx>,
651}
652
653impl<'tcx> Pat<'tcx> {
654 pub fn simple_ident(&self) -> Option<Symbol> {
655 match self.kind {
656 PatKind::Binding {
657 name, mode: BindingMode(ByRef::No, _), subpattern: None, ..
658 } => Some(name),
659 _ => None,
660 }
661 }
662
663 /// Call `f` on every "binding" in a pattern, e.g., on `a` in
664 /// `match foo() { Some(a) => (), None => () }`
665 pub fn each_binding(&self, mut f: impl FnMut(Symbol, ByRef, Ty<'tcx>, Span)) {
666 self.walk_always(|p| {
667 if let PatKind::Binding { name, mode, ty, .. } = p.kind {
668 f(name, mode.0, ty, p.span);
669 }
670 });
671 }
672
673 /// Walk the pattern in left-to-right order.
674 ///
675 /// If `it(pat)` returns `false`, the children are not visited.
676 pub fn walk(&self, mut it: impl FnMut(&Pat<'tcx>) -> bool) {
677 self.walk_(&mut it)
678 }
679
680 fn walk_(&self, it: &mut impl FnMut(&Pat<'tcx>) -> bool) {
681 if !it(self) {
682 return;
683 }
684
685 for_each_immediate_subpat(self, |p| p.walk_(it));
686 }
687
688 /// Whether the pattern has a `PatKind::Error` nested within.
689 pub fn pat_error_reported(&self) -> Result<(), ErrorGuaranteed> {
690 let mut error = None;
691 self.walk(|pat| {
692 if let PatKind::Error(e) = pat.kind
693 && error.is_none()
694 {
695 error = Some(e);
696 }
697 error.is_none()
698 });
699 match error {
700 None => Ok(()),
701 Some(e) => Err(e),
702 }
703 }
704
705 /// Walk the pattern in left-to-right order.
706 ///
707 /// If you always want to recurse, prefer this method over `walk`.
708 pub fn walk_always(&self, mut it: impl FnMut(&Pat<'tcx>)) {
709 self.walk(|p| {
710 it(p);
711 true
712 })
713 }
714
715 /// Whether this a never pattern.
716 pub fn is_never_pattern(&self) -> bool {
717 let mut is_never_pattern = false;
718 self.walk(|pat| match &pat.kind {
719 PatKind::Never => {
720 is_never_pattern = true;
721 false
722 }
723 PatKind::Or { pats } => {
724 is_never_pattern = pats.iter().all(|p| p.is_never_pattern());
725 false
726 }
727 _ => true,
728 });
729 is_never_pattern
730 }
731}
732
733#[derive(Clone, Debug, HashStable, TypeVisitable)]
734pub struct Ascription<'tcx> {
735 pub annotation: CanonicalUserTypeAnnotation<'tcx>,
736 /// Variance to use when relating the `user_ty` to the **type of the value being
737 /// matched**. Typically, this is `Variance::Covariant`, since the value being matched must
738 /// have a type that is some subtype of the ascribed type.
739 ///
740 /// Note that this variance does not apply for any bindings within subpatterns. The type
741 /// assigned to those bindings must be exactly equal to the `user_ty` given here.
742 ///
743 /// The only place where this field is not `Covariant` is when matching constants, where
744 /// we currently use `Contravariant` -- this is because the constant type just needs to
745 /// be "comparable" to the type of the input value. So, for example:
746 ///
747 /// ```text
748 /// match x { "foo" => .. }
749 /// ```
750 ///
751 /// requires that `&'static str <: T_x`, where `T_x` is the type of `x`. Really, we should
752 /// probably be checking for a `PartialEq` impl instead, but this preserves the behavior
753 /// of the old type-check for now. See #57280 for details.
754 pub variance: ty::Variance,
755}
756
757#[derive(Clone, Debug, HashStable, TypeVisitable)]
758pub enum PatKind<'tcx> {
759 /// A missing pattern, e.g. for an anonymous param in a bare fn like `fn f(u32)`.
760 Missing,
761
762 /// A wildcard pattern: `_`.
763 Wild,
764
765 AscribeUserType {
766 ascription: Ascription<'tcx>,
767 subpattern: Box<Pat<'tcx>>,
768 },
769
770 /// `x`, `ref x`, `x @ P`, etc.
771 Binding {
772 name: Symbol,
773 #[type_visitable(ignore)]
774 mode: BindingMode,
775 #[type_visitable(ignore)]
776 var: LocalVarId,
777 ty: Ty<'tcx>,
778 subpattern: Option<Box<Pat<'tcx>>>,
779
780 /// Is this the leftmost occurrence of the binding, i.e., is `var` the
781 /// `HirId` of this pattern?
782 ///
783 /// (The same binding can occur multiple times in different branches of
784 /// an or-pattern, but only one of them will be primary.)
785 is_primary: bool,
786 /// Is this binding a shorthand struct pattern, i.e. `Foo { a }`?
787 is_shorthand: bool,
788 },
789
790 /// `Foo(...)` or `Foo{...}` or `Foo`, where `Foo` is a variant name from an ADT with
791 /// multiple variants.
792 Variant {
793 adt_def: AdtDef<'tcx>,
794 args: GenericArgsRef<'tcx>,
795 variant_index: VariantIdx,
796 subpatterns: Vec<FieldPat<'tcx>>,
797 },
798
799 /// `(...)`, `Foo(...)`, `Foo{...}`, or `Foo`, where `Foo` is a variant name from an ADT with
800 /// a single variant.
801 Leaf {
802 subpatterns: Vec<FieldPat<'tcx>>,
803 },
804
805 /// `box P`, `&P`, `&mut P`, etc.
806 Deref {
807 subpattern: Box<Pat<'tcx>>,
808 },
809
810 /// Deref pattern, written `box P` for now.
811 DerefPattern {
812 subpattern: Box<Pat<'tcx>>,
813 /// Whether the pattern scrutinee needs to be borrowed in order to call `Deref::deref` or
814 /// `DerefMut::deref_mut`, and if so, which. This is `ByRef::No` for deref patterns on
815 /// boxes; they are lowered using a built-in deref rather than a method call, thus they
816 /// don't borrow the scrutinee.
817 #[type_visitable(ignore)]
818 borrow: ByRef,
819 },
820
821 /// One of the following:
822 /// * `&str`, which will be handled as a string pattern and thus
823 /// exhaustiveness checking will detect if you use the same string twice in different
824 /// patterns.
825 /// * integer, bool, char or float, which will be handled by
826 /// exhaustiveness to cover exactly its own value, similar to `&str`, but these values are
827 /// much simpler.
828 /// * raw pointers derived from integers, other raw pointers will have already resulted in an
829 /// error.
830 /// * `String`, if `string_deref_patterns` is enabled.
831 Constant {
832 value: ty::Value<'tcx>,
833 },
834
835 /// Pattern obtained by converting a constant (inline or named) to its pattern
836 /// representation using `const_to_pat`. This is used for unsafety checking.
837 ExpandedConstant {
838 /// [DefId] of the constant item.
839 def_id: DefId,
840 /// The pattern that the constant lowered to.
841 ///
842 /// HACK: we need to keep the `DefId` of inline constants around for unsafety checking;
843 /// therefore when a range pattern contains inline constants, we re-wrap the range pattern
844 /// with the `ExpandedConstant` nodes that correspond to the range endpoints. Hence
845 /// `subpattern` may actually be a range pattern, and `def_id` be the constant for one of
846 /// its endpoints.
847 subpattern: Box<Pat<'tcx>>,
848 },
849
850 Range(Arc<PatRange<'tcx>>),
851
852 /// Matches against a slice, checking the length and extracting elements.
853 /// irrefutable when there is a slice pattern and both `prefix` and `suffix` are empty.
854 /// e.g., `&[ref xs @ ..]`.
855 Slice {
856 prefix: Box<[Pat<'tcx>]>,
857 slice: Option<Box<Pat<'tcx>>>,
858 suffix: Box<[Pat<'tcx>]>,
859 },
860
861 /// Fixed match against an array; irrefutable.
862 Array {
863 prefix: Box<[Pat<'tcx>]>,
864 slice: Option<Box<Pat<'tcx>>>,
865 suffix: Box<[Pat<'tcx>]>,
866 },
867
868 /// An or-pattern, e.g. `p | q`.
869 /// Invariant: `pats.len() >= 2`.
870 Or {
871 pats: Box<[Pat<'tcx>]>,
872 },
873
874 /// A never pattern `!`.
875 Never,
876
877 /// An error has been encountered during lowering. We probably shouldn't report more lints
878 /// related to this pattern.
879 Error(ErrorGuaranteed),
880}
881
882/// A range pattern.
883/// The boundaries must be of the same type and that type must be numeric.
884#[derive(Clone, Debug, PartialEq, HashStable, TypeVisitable)]
885pub struct PatRange<'tcx> {
886 /// Must not be `PosInfinity`.
887 pub lo: PatRangeBoundary<'tcx>,
888 /// Must not be `NegInfinity`.
889 pub hi: PatRangeBoundary<'tcx>,
890 #[type_visitable(ignore)]
891 pub end: RangeEnd,
892 pub ty: Ty<'tcx>,
893}
894
895impl<'tcx> PatRange<'tcx> {
896 /// Whether this range covers the full extent of possible values (best-effort, we ignore floats).
897 #[inline]
898 pub fn is_full_range(&self, tcx: TyCtxt<'tcx>) -> Option<bool> {
899 let (min, max, size, bias) = match *self.ty.kind() {
900 ty::Char => (0, std::char::MAX as u128, Size::from_bits(32), 0),
901 ty::Int(ity) => {
902 let size = Integer::from_int_ty(&tcx, ity).size();
903 let max = size.truncate(u128::MAX);
904 let bias = 1u128 << (size.bits() - 1);
905 (0, max, size, bias)
906 }
907 ty::Uint(uty) => {
908 let size = Integer::from_uint_ty(&tcx, uty).size();
909 let max = size.unsigned_int_max();
910 (0, max, size, 0)
911 }
912 _ => return None,
913 };
914
915 // We want to compare ranges numerically, but the order of the bitwise representation of
916 // signed integers does not match their numeric order. Thus, to correct the ordering, we
917 // need to shift the range of signed integers to correct the comparison. This is achieved by
918 // XORing with a bias (see pattern/deconstruct_pat.rs for another pertinent example of this
919 // pattern).
920 //
921 // Also, for performance, it's important to only do the second `try_to_bits` if necessary.
922 let lo_is_min = match self.lo {
923 PatRangeBoundary::NegInfinity => true,
924 PatRangeBoundary::Finite(value) => {
925 let lo = value.try_to_scalar_int().unwrap().to_bits(size) ^ bias;
926 lo <= min
927 }
928 PatRangeBoundary::PosInfinity => false,
929 };
930 if lo_is_min {
931 let hi_is_max = match self.hi {
932 PatRangeBoundary::NegInfinity => false,
933 PatRangeBoundary::Finite(value) => {
934 let hi = value.try_to_scalar_int().unwrap().to_bits(size) ^ bias;
935 hi > max || hi == max && self.end == RangeEnd::Included
936 }
937 PatRangeBoundary::PosInfinity => true,
938 };
939 if hi_is_max {
940 return Some(true);
941 }
942 }
943 Some(false)
944 }
945
946 #[inline]
947 pub fn contains(&self, value: ty::Value<'tcx>, tcx: TyCtxt<'tcx>) -> Option<bool> {
948 use Ordering::*;
949 debug_assert_eq!(value.ty, self.ty);
950 let ty = self.ty;
951 let value = PatRangeBoundary::Finite(value.valtree);
952 // For performance, it's important to only do the second comparison if necessary.
953 Some(
954 match self.lo.compare_with(value, ty, tcx)? {
955 Less | Equal => true,
956 Greater => false,
957 } && match value.compare_with(self.hi, ty, tcx)? {
958 Less => true,
959 Equal => self.end == RangeEnd::Included,
960 Greater => false,
961 },
962 )
963 }
964
965 #[inline]
966 pub fn overlaps(&self, other: &Self, tcx: TyCtxt<'tcx>) -> Option<bool> {
967 use Ordering::*;
968 debug_assert_eq!(self.ty, other.ty);
969 // For performance, it's important to only do the second comparison if necessary.
970 Some(
971 match other.lo.compare_with(self.hi, self.ty, tcx)? {
972 Less => true,
973 Equal => self.end == RangeEnd::Included,
974 Greater => false,
975 } && match self.lo.compare_with(other.hi, self.ty, tcx)? {
976 Less => true,
977 Equal => other.end == RangeEnd::Included,
978 Greater => false,
979 },
980 )
981 }
982}
983
984impl<'tcx> fmt::Display for PatRange<'tcx> {
985 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
986 if let &PatRangeBoundary::Finite(valtree) = &self.lo {
987 let value = ty::Value { ty: self.ty, valtree };
988 write!(f, "{value}")?;
989 }
990 if let &PatRangeBoundary::Finite(valtree) = &self.hi {
991 write!(f, "{}", self.end)?;
992 let value = ty::Value { ty: self.ty, valtree };
993 write!(f, "{value}")?;
994 } else {
995 // `0..` is parsed as an inclusive range, we must display it correctly.
996 write!(f, "..")?;
997 }
998 Ok(())
999 }
1000}
1001
1002/// A (possibly open) boundary of a range pattern.
1003/// If present, the const must be of a numeric type.
1004#[derive(Copy, Clone, Debug, PartialEq, HashStable, TypeVisitable)]
1005pub enum PatRangeBoundary<'tcx> {
1006 /// The type of this valtree is stored in the surrounding `PatRange`.
1007 Finite(ty::ValTree<'tcx>),
1008 NegInfinity,
1009 PosInfinity,
1010}
1011
1012impl<'tcx> PatRangeBoundary<'tcx> {
1013 #[inline]
1014 pub fn is_finite(self) -> bool {
1015 matches!(self, Self::Finite(..))
1016 }
1017 #[inline]
1018 pub fn as_finite(self) -> Option<ty::ValTree<'tcx>> {
1019 match self {
1020 Self::Finite(value) => Some(value),
1021 Self::NegInfinity | Self::PosInfinity => None,
1022 }
1023 }
1024 pub fn to_bits(self, ty: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> u128 {
1025 match self {
1026 Self::Finite(value) => value.try_to_scalar_int().unwrap().to_bits_unchecked(),
1027 Self::NegInfinity => {
1028 // Unwrap is ok because the type is known to be numeric.
1029 ty.numeric_min_and_max_as_bits(tcx).unwrap().0
1030 }
1031 Self::PosInfinity => {
1032 // Unwrap is ok because the type is known to be numeric.
1033 ty.numeric_min_and_max_as_bits(tcx).unwrap().1
1034 }
1035 }
1036 }
1037
1038 #[instrument(skip(tcx), level = "debug", ret)]
1039 pub fn compare_with(self, other: Self, ty: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> Option<Ordering> {
1040 use PatRangeBoundary::*;
1041 match (self, other) {
1042 // When comparing with infinities, we must remember that `0u8..` and `0u8..=255`
1043 // describe the same range. These two shortcuts are ok, but for the rest we must check
1044 // bit values.
1045 (PosInfinity, PosInfinity) => return Some(Ordering::Equal),
1046 (NegInfinity, NegInfinity) => return Some(Ordering::Equal),
1047
1048 // This code is hot when compiling matches with many ranges. So we
1049 // special-case extraction of evaluated scalars for speed, for types where
1050 // we can do scalar comparisons. E.g. `unicode-normalization` has
1051 // many ranges such as '\u{037A}'..='\u{037F}', and chars can be compared
1052 // in this way.
1053 (Finite(a), Finite(b)) if matches!(ty.kind(), ty::Int(_) | ty::Uint(_) | ty::Char) => {
1054 if let (Some(a), Some(b)) = (a.try_to_scalar_int(), b.try_to_scalar_int()) {
1055 let sz = ty.primitive_size(tcx);
1056 let cmp = match ty.kind() {
1057 ty::Uint(_) | ty::Char => a.to_uint(sz).cmp(&b.to_uint(sz)),
1058 ty::Int(_) => a.to_int(sz).cmp(&b.to_int(sz)),
1059 _ => unreachable!(),
1060 };
1061 return Some(cmp);
1062 }
1063 }
1064 _ => {}
1065 }
1066
1067 let a = self.to_bits(ty, tcx);
1068 let b = other.to_bits(ty, tcx);
1069
1070 match ty.kind() {
1071 ty::Float(ty::FloatTy::F16) => {
1072 use rustc_apfloat::Float;
1073 let a = rustc_apfloat::ieee::Half::from_bits(a);
1074 let b = rustc_apfloat::ieee::Half::from_bits(b);
1075 a.partial_cmp(&b)
1076 }
1077 ty::Float(ty::FloatTy::F32) => {
1078 use rustc_apfloat::Float;
1079 let a = rustc_apfloat::ieee::Single::from_bits(a);
1080 let b = rustc_apfloat::ieee::Single::from_bits(b);
1081 a.partial_cmp(&b)
1082 }
1083 ty::Float(ty::FloatTy::F64) => {
1084 use rustc_apfloat::Float;
1085 let a = rustc_apfloat::ieee::Double::from_bits(a);
1086 let b = rustc_apfloat::ieee::Double::from_bits(b);
1087 a.partial_cmp(&b)
1088 }
1089 ty::Float(ty::FloatTy::F128) => {
1090 use rustc_apfloat::Float;
1091 let a = rustc_apfloat::ieee::Quad::from_bits(a);
1092 let b = rustc_apfloat::ieee::Quad::from_bits(b);
1093 a.partial_cmp(&b)
1094 }
1095 ty::Int(ity) => {
1096 let size = rustc_abi::Integer::from_int_ty(&tcx, *ity).size();
1097 let a = size.sign_extend(a) as i128;
1098 let b = size.sign_extend(b) as i128;
1099 Some(a.cmp(&b))
1100 }
1101 ty::Uint(_) | ty::Char => Some(a.cmp(&b)),
1102 _ => bug!(),
1103 }
1104 }
1105}
1106
1107// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
1108#[cfg(target_pointer_width = "64")]
1109mod size_asserts {
1110 use rustc_data_structures::static_assert_size;
1111
1112 use super::*;
1113 // tidy-alphabetical-start
1114 static_assert_size!(Block, 48);
1115 static_assert_size!(Expr<'_>, 64);
1116 static_assert_size!(ExprKind<'_>, 40);
1117 static_assert_size!(Pat<'_>, 64);
1118 static_assert_size!(PatKind<'_>, 48);
1119 static_assert_size!(Stmt<'_>, 48);
1120 static_assert_size!(StmtKind<'_>, 48);
1121 // tidy-alphabetical-end
1122}