]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_middle/src/thir.rs
New upstream version 1.68.2+dfsg1
[rustc.git] / compiler / rustc_middle / src / thir.rs
CommitLineData
136023e0
XL
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
17df50a5 11use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
9c376795 12use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg};
17df50a5 13use rustc_hir as hir;
17df50a5
XL
14use rustc_hir::def_id::DefId;
15use rustc_hir::RangeEnd;
16use rustc_index::newtype_index;
94222f64 17use rustc_index::vec::IndexVec;
17df50a5 18use rustc_middle::middle::region;
5099ac24 19use rustc_middle::mir::interpret::AllocId;
923072b8 20use rustc_middle::mir::{self, BinOp, BorrowKind, FakeReadCause, Field, Mutability, UnOp};
17df50a5
XL
21use rustc_middle::ty::adjustment::PointerCast;
22use rustc_middle::ty::subst::SubstsRef;
f2b60f7d
FG
23use rustc_middle::ty::{self, AdtDef, Ty, UpvarSubsts};
24use rustc_middle::ty::{CanonicalUserType, CanonicalUserTypeAnnotation};
25use rustc_span::def_id::LocalDefId;
26use rustc_span::{sym, Span, Symbol, DUMMY_SP};
17df50a5
XL
27use rustc_target::abi::VariantIdx;
28use rustc_target::asm::InlineAsmRegOrRegClass;
17df50a5
XL
29use std::fmt;
30use std::ops::Index;
31
c295e0f8
XL
32pub mod visit;
33
17df50a5 34macro_rules! thir_with_elements {
f2b60f7d
FG
35 ($($name:ident: $id:ty => $value:ty => $format:literal,)*) => {
36 $(
37 newtype_index! {
38 #[derive(HashStable)]
9c376795
FG
39 #[debug_format = $format]
40 pub struct $id {}
f2b60f7d
FG
41 }
42 )*
43
136023e0
XL
44 /// A container for a THIR body.
45 ///
46 /// This can be indexed directly by any THIR index (e.g. [`ExprId`]).
04454e1e 47 #[derive(Debug, HashStable, Clone)]
17df50a5
XL
48 pub struct Thir<'tcx> {
49 $(
50 pub $name: IndexVec<$id, $value>,
51 )*
52 }
53
54 impl<'tcx> Thir<'tcx> {
55 pub fn new() -> Thir<'tcx> {
56 Thir {
57 $(
58 $name: IndexVec::new(),
59 )*
60 }
61 }
62 }
63
64 $(
65 impl<'tcx> Index<$id> for Thir<'tcx> {
66 type Output = $value;
67 fn index(&self, index: $id) -> &Self::Output {
68 &self.$name[index]
69 }
70 }
71 )*
72 }
73}
74
f2b60f7d
FG
75pub const UPVAR_ENV_PARAM: ParamId = ParamId::from_u32(0);
76
17df50a5 77thir_with_elements! {
f2b60f7d
FG
78 arms: ArmId => Arm<'tcx> => "a{}",
79 blocks: BlockId => Block => "b{}",
80 exprs: ExprId => Expr<'tcx> => "e{}",
81 stmts: StmtId => Stmt<'tcx> => "s{}",
82 params: ParamId => Param<'tcx> => "p{}",
83}
84
85/// Description of a type-checked function parameter.
86#[derive(Clone, Debug, HashStable)]
87pub struct Param<'tcx> {
88 /// The pattern that appears in the parameter list, or None for implicit parameters.
89 pub pat: Option<Box<Pat<'tcx>>>,
90 /// The possibly inferred type.
91 pub ty: Ty<'tcx>,
92 /// Span of the explicitly provided type, or None if inferred for closures.
93 pub ty_span: Option<Span>,
94 /// Whether this param is `self`, and how it is bound.
95 pub self_kind: Option<hir::ImplicitSelfKind>,
96 /// HirId for lints.
97 pub hir_id: Option<hir::HirId>,
17df50a5
XL
98}
99
100#[derive(Copy, Clone, Debug, HashStable)]
101pub enum LintLevel {
102 Inherited,
103 Explicit(hir::HirId),
104}
105
04454e1e 106#[derive(Clone, Debug, HashStable)]
17df50a5 107pub struct Block {
136023e0
XL
108 /// Whether the block itself has a label. Used by `label: {}`
109 /// and `try` blocks.
110 ///
111 /// This does *not* include labels on loops, e.g. `'label: loop {}`.
17df50a5
XL
112 pub targeted_by_break: bool,
113 pub region_scope: region::Scope,
114 pub opt_destruction_scope: Option<region::Scope>,
136023e0
XL
115 /// The span of the block, including the opening braces,
116 /// the label, and the `unsafe` keyword, if present.
17df50a5 117 pub span: Span,
136023e0 118 /// The statements in the blocK.
17df50a5 119 pub stmts: Box<[StmtId]>,
136023e0 120 /// The trailing expression of the block, if any.
17df50a5
XL
121 pub expr: Option<ExprId>,
122 pub safety_mode: BlockSafety,
123}
124
f2b60f7d
FG
125type UserTy<'tcx> = Option<Box<CanonicalUserType<'tcx>>>;
126
04454e1e 127#[derive(Clone, Debug, HashStable)]
f2b60f7d 128pub struct AdtExpr<'tcx> {
136023e0 129 /// The ADT we're constructing.
5e7ed085 130 pub adt_def: AdtDef<'tcx>,
136023e0
XL
131 /// The variant of the ADT.
132 pub variant_index: VariantIdx,
133 pub substs: SubstsRef<'tcx>,
134
135 /// Optional user-given substs: for something like `let x =
136 /// Bar::<T> { ... }`.
f2b60f7d 137 pub user_ty: UserTy<'tcx>,
136023e0
XL
138
139 pub fields: Box<[FieldExpr]>,
140 /// The base, e.g. `Foo {x: 1, .. base}`.
141 pub base: Option<FruInfo<'tcx>>,
142}
143
f2b60f7d
FG
144#[derive(Clone, Debug, HashStable)]
145pub struct ClosureExpr<'tcx> {
146 pub closure_id: LocalDefId,
147 pub substs: UpvarSubsts<'tcx>,
148 pub upvars: Box<[ExprId]>,
149 pub movability: Option<hir::Movability>,
150 pub fake_reads: Vec<(ExprId, FakeReadCause, hir::HirId)>,
151}
152
153#[derive(Clone, Debug, HashStable)]
154pub struct InlineAsmExpr<'tcx> {
155 pub template: &'tcx [InlineAsmTemplatePiece],
156 pub operands: Box<[InlineAsmOperand<'tcx>]>,
157 pub options: InlineAsmOptions,
158 pub line_spans: &'tcx [Span],
159}
160
17df50a5
XL
161#[derive(Copy, Clone, Debug, HashStable)]
162pub enum BlockSafety {
163 Safe,
136023e0
XL
164 /// A compiler-generated unsafe block
165 BuiltinUnsafe,
166 /// An `unsafe` block. The `HirId` is the ID of the block.
17df50a5 167 ExplicitUnsafe(hir::HirId),
17df50a5
XL
168}
169
04454e1e 170#[derive(Clone, Debug, HashStable)]
17df50a5
XL
171pub struct Stmt<'tcx> {
172 pub kind: StmtKind<'tcx>,
173 pub opt_destruction_scope: Option<region::Scope>,
174}
175
04454e1e 176#[derive(Clone, Debug, HashStable)]
17df50a5 177pub enum StmtKind<'tcx> {
136023e0 178 /// An expression with a trailing semicolon.
17df50a5 179 Expr {
136023e0 180 /// The scope for this statement; may be used as lifetime of temporaries.
17df50a5
XL
181 scope: region::Scope,
182
136023e0 183 /// The expression being evaluated in this statement.
17df50a5
XL
184 expr: ExprId,
185 },
186
136023e0 187 /// A `let` binding.
17df50a5 188 Let {
136023e0
XL
189 /// The scope for variables bound in this `let`; it covers this and
190 /// all the remaining statements in the block.
17df50a5
XL
191 remainder_scope: region::Scope,
192
136023e0
XL
193 /// The scope for the initialization itself; might be used as
194 /// lifetime of temporaries.
17df50a5
XL
195 init_scope: region::Scope,
196
197 /// `let <PAT> = ...`
198 ///
136023e0 199 /// If a type annotation is included, it is added as an ascription pattern.
f2b60f7d 200 pattern: Box<Pat<'tcx>>,
17df50a5 201
136023e0 202 /// `let pat: ty = <INIT>`
17df50a5
XL
203 initializer: Option<ExprId>,
204
2b03887a 205 /// `let pat: ty = <INIT> else { <ELSE> }`
f2b60f7d 206 else_block: Option<BlockId>,
064997fb 207
136023e0 208 /// The lint level for this `let` statement.
17df50a5
XL
209 lint_level: LintLevel,
210 },
211}
212
064997fb
FG
213#[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)]
214#[derive(TypeFoldable, TypeVisitable)]
923072b8
FG
215pub struct LocalVarId(pub hir::HirId);
216
136023e0 217/// A THIR expression.
04454e1e 218#[derive(Clone, Debug, HashStable)]
17df50a5 219pub struct Expr<'tcx> {
136023e0 220 /// The type of this expression
17df50a5
XL
221 pub ty: Ty<'tcx>,
222
136023e0
XL
223 /// The lifetime of this expression if it should be spilled into a
224 /// temporary; should be `None` only if in a constant context
17df50a5
XL
225 pub temp_lifetime: Option<region::Scope>,
226
227 /// span of the expression in the source
228 pub span: Span,
229
230 /// kind of expression
231 pub kind: ExprKind<'tcx>,
232}
233
04454e1e 234#[derive(Clone, Debug, HashStable)]
17df50a5 235pub enum ExprKind<'tcx> {
5099ac24 236 /// `Scope`s are used to explicitly mark destruction scopes,
136023e0 237 /// and to track the `HirId` of the expressions within the scope.
17df50a5
XL
238 Scope {
239 region_scope: region::Scope,
240 lint_level: LintLevel,
241 value: ExprId,
242 },
136023e0 243 /// A `box <value>` expression.
17df50a5
XL
244 Box {
245 value: ExprId,
246 },
136023e0 247 /// An `if` expression.
17df50a5 248 If {
94222f64 249 if_then_scope: region::Scope,
17df50a5
XL
250 cond: ExprId,
251 then: ExprId,
252 else_opt: Option<ExprId>,
253 },
136023e0 254 /// A function call. Method calls and overloaded operators are converted to plain function calls.
17df50a5 255 Call {
136023e0
XL
256 /// The type of the function. This is often a [`FnDef`] or a [`FnPtr`].
257 ///
258 /// [`FnDef`]: ty::TyKind::FnDef
259 /// [`FnPtr`]: ty::TyKind::FnPtr
17df50a5 260 ty: Ty<'tcx>,
136023e0 261 /// The function itself.
17df50a5 262 fun: ExprId,
136023e0
XL
263 /// The arguments passed to the function.
264 ///
265 /// Note: in some cases (like calling a closure), the function call `f(...args)` gets
266 /// rewritten as a call to a function trait method (e.g. `FnOnce::call_once(f, (...args))`).
17df50a5 267 args: Box<[ExprId]>,
136023e0
XL
268 /// Whether this is from an overloaded operator rather than a
269 /// function call from HIR. `true` for overloaded function call.
17df50a5 270 from_hir_call: bool,
136023e0
XL
271 /// The span of the function, without the dot and receiver
272 /// (e.g. `foo(a, b)` in `x.foo(a, b)`).
17df50a5
XL
273 fn_span: Span,
274 },
136023e0 275 /// A *non-overloaded* dereference.
17df50a5
XL
276 Deref {
277 arg: ExprId,
136023e0
XL
278 },
279 /// A *non-overloaded* binary operation.
17df50a5
XL
280 Binary {
281 op: BinOp,
282 lhs: ExprId,
283 rhs: ExprId,
136023e0
XL
284 },
285 /// A logical operation. This is distinct from `BinaryOp` because
286 /// the operands need to be lazily evaluated.
17df50a5
XL
287 LogicalOp {
288 op: LogicalOp,
289 lhs: ExprId,
290 rhs: ExprId,
136023e0
XL
291 },
292 /// A *non-overloaded* unary operation. Note that here the deref (`*`)
293 /// operator is represented by `ExprKind::Deref`.
17df50a5
XL
294 Unary {
295 op: UnOp,
296 arg: ExprId,
136023e0
XL
297 },
298 /// A cast: `<source> as <type>`. The type we cast to is the type of
299 /// the parent expression.
17df50a5
XL
300 Cast {
301 source: ExprId,
302 },
303 Use {
304 source: ExprId,
305 }, // Use a lexpr to get a vexpr.
136023e0 306 /// A coercion from `!` to any type.
17df50a5
XL
307 NeverToAny {
308 source: ExprId,
309 },
136023e0 310 /// A pointer cast. More information can be found in [`PointerCast`].
17df50a5
XL
311 Pointer {
312 cast: PointerCast,
313 source: ExprId,
314 },
136023e0 315 /// A `loop` expression.
17df50a5
XL
316 Loop {
317 body: ExprId,
318 },
94222f64
XL
319 Let {
320 expr: ExprId,
f2b60f7d 321 pat: Box<Pat<'tcx>>,
94222f64 322 },
136023e0 323 /// A `match` expression.
17df50a5
XL
324 Match {
325 scrutinee: ExprId,
326 arms: Box<[ArmId]>,
327 },
136023e0 328 /// A block.
17df50a5 329 Block {
f2b60f7d 330 block: BlockId,
17df50a5 331 },
136023e0 332 /// An assignment: `lhs = rhs`.
17df50a5
XL
333 Assign {
334 lhs: ExprId,
335 rhs: ExprId,
336 },
136023e0 337 /// A *non-overloaded* operation assignment, e.g. `lhs += rhs`.
17df50a5
XL
338 AssignOp {
339 op: BinOp,
340 lhs: ExprId,
341 rhs: ExprId,
342 },
923072b8 343 /// Access to a field of a struct, a tuple, an union, or an enum.
17df50a5
XL
344 Field {
345 lhs: ExprId,
923072b8
FG
346 /// Variant containing the field.
347 variant_index: VariantIdx,
136023e0 348 /// This can be a named (`.foo`) or unnamed (`.0`) field.
17df50a5
XL
349 name: Field,
350 },
136023e0 351 /// A *non-overloaded* indexing operation.
17df50a5
XL
352 Index {
353 lhs: ExprId,
354 index: ExprId,
355 },
136023e0 356 /// A local variable.
17df50a5 357 VarRef {
923072b8 358 id: LocalVarId,
17df50a5
XL
359 },
360 /// Used to represent upvars mentioned in a closure/generator
361 UpvarRef {
362 /// DefId of the closure/generator
363 closure_def_id: DefId,
364
365 /// HirId of the root variable
923072b8 366 var_hir_id: LocalVarId,
17df50a5 367 },
136023e0 368 /// A borrow, e.g. `&arg`.
17df50a5
XL
369 Borrow {
370 borrow_kind: BorrowKind,
371 arg: ExprId,
372 },
373 /// A `&raw [const|mut] $place_expr` raw borrow resulting in type `*[const|mut] T`.
374 AddressOf {
375 mutability: hir::Mutability,
376 arg: ExprId,
377 },
136023e0 378 /// A `break` expression.
17df50a5
XL
379 Break {
380 label: region::Scope,
381 value: Option<ExprId>,
382 },
136023e0 383 /// A `continue` expression.
17df50a5
XL
384 Continue {
385 label: region::Scope,
386 },
136023e0 387 /// A `return` expression.
17df50a5
XL
388 Return {
389 value: Option<ExprId>,
390 },
136023e0 391 /// An inline `const` block, e.g. `const {}`.
17df50a5 392 ConstBlock {
5e7ed085
FG
393 did: DefId,
394 substs: SubstsRef<'tcx>,
17df50a5 395 },
136023e0 396 /// An array literal constructed from one repeated element, e.g. `[1; 5]`.
17df50a5
XL
397 Repeat {
398 value: ExprId,
04454e1e 399 count: ty::Const<'tcx>,
17df50a5 400 },
136023e0 401 /// An array, e.g. `[a, b, c, d]`.
17df50a5
XL
402 Array {
403 fields: Box<[ExprId]>,
404 },
136023e0 405 /// A tuple, e.g. `(a, b, c, d)`.
17df50a5
XL
406 Tuple {
407 fields: Box<[ExprId]>,
408 },
136023e0 409 /// An ADT constructor, e.g. `Foo {x: 1, y: 2}`.
f2b60f7d 410 Adt(Box<AdtExpr<'tcx>>),
136023e0 411 /// A type ascription on a place.
17df50a5
XL
412 PlaceTypeAscription {
413 source: ExprId,
414 /// Type that the user gave to this expression
f2b60f7d 415 user_ty: UserTy<'tcx>,
17df50a5 416 },
136023e0 417 /// A type ascription on a value, e.g. `42: i32`.
17df50a5
XL
418 ValueTypeAscription {
419 source: ExprId,
420 /// Type that the user gave to this expression
f2b60f7d 421 user_ty: UserTy<'tcx>,
17df50a5 422 },
136023e0 423 /// A closure definition.
f2b60f7d 424 Closure(Box<ClosureExpr<'tcx>>),
136023e0 425 /// A literal.
17df50a5 426 Literal {
5e7ed085
FG
427 lit: &'tcx hir::Lit,
428 neg: bool,
429 },
430 /// For literals that don't correspond to anything in the HIR
431 NonHirLiteral {
432 lit: ty::ScalarInt,
f2b60f7d 433 user_ty: UserTy<'tcx>,
5e7ed085 434 },
064997fb
FG
435 /// A literal of a ZST type.
436 ZstLiteral {
f2b60f7d 437 user_ty: UserTy<'tcx>,
064997fb 438 },
5e7ed085
FG
439 /// Associated constants and named constants
440 NamedConst {
441 def_id: DefId,
442 substs: SubstsRef<'tcx>,
f2b60f7d 443 user_ty: UserTy<'tcx>,
17df50a5 444 },
5e7ed085
FG
445 ConstParam {
446 param: ty::ParamConst,
447 def_id: DefId,
448 },
449 // FIXME improve docs for `StaticRef` by distinguishing it from `NamedConst`
17df50a5
XL
450 /// A literal containing the address of a `static`.
451 ///
452 /// This is only distinguished from `Literal` so that we can register some
453 /// info for diagnostics.
454 StaticRef {
5099ac24
FG
455 alloc_id: AllocId,
456 ty: Ty<'tcx>,
17df50a5
XL
457 def_id: DefId,
458 },
136023e0 459 /// Inline assembly, i.e. `asm!()`.
f2b60f7d 460 InlineAsm(Box<InlineAsmExpr<'tcx>>),
17df50a5
XL
461 /// An expression taking a reference to a thread local.
462 ThreadLocalRef(DefId),
136023e0 463 /// A `yield` expression.
17df50a5
XL
464 Yield {
465 value: ExprId,
466 },
467}
468
136023e0
XL
469/// Represents the association of a field identifier and an expression.
470///
471/// This is used in struct constructors.
04454e1e 472#[derive(Clone, Debug, HashStable)]
17df50a5
XL
473pub struct FieldExpr {
474 pub name: Field,
475 pub expr: ExprId,
476}
477
04454e1e 478#[derive(Clone, Debug, HashStable)]
17df50a5
XL
479pub struct FruInfo<'tcx> {
480 pub base: ExprId,
481 pub field_types: Box<[Ty<'tcx>]>,
482}
483
136023e0 484/// A `match` arm.
04454e1e 485#[derive(Clone, Debug, HashStable)]
17df50a5 486pub struct Arm<'tcx> {
f2b60f7d 487 pub pattern: Box<Pat<'tcx>>,
17df50a5
XL
488 pub guard: Option<Guard<'tcx>>,
489 pub body: ExprId,
490 pub lint_level: LintLevel,
491 pub scope: region::Scope,
492 pub span: Span,
493}
494
136023e0 495/// A `match` guard.
04454e1e 496#[derive(Clone, Debug, HashStable)]
17df50a5
XL
497pub enum Guard<'tcx> {
498 If(ExprId),
f2b60f7d 499 IfLet(Box<Pat<'tcx>>, ExprId),
17df50a5
XL
500}
501
502#[derive(Copy, Clone, Debug, HashStable)]
503pub enum LogicalOp {
136023e0 504 /// The `&&` operator.
17df50a5 505 And,
136023e0 506 /// The `||` operator.
17df50a5
XL
507 Or,
508}
509
04454e1e 510#[derive(Clone, Debug, HashStable)]
17df50a5
XL
511pub enum InlineAsmOperand<'tcx> {
512 In {
513 reg: InlineAsmRegOrRegClass,
514 expr: ExprId,
515 },
516 Out {
517 reg: InlineAsmRegOrRegClass,
518 late: bool,
519 expr: Option<ExprId>,
520 },
521 InOut {
522 reg: InlineAsmRegOrRegClass,
523 late: bool,
524 expr: ExprId,
525 },
526 SplitInOut {
527 reg: InlineAsmRegOrRegClass,
528 late: bool,
529 in_expr: ExprId,
530 out_expr: Option<ExprId>,
531 },
532 Const {
04454e1e 533 value: mir::ConstantKind<'tcx>,
17df50a5
XL
534 span: Span,
535 },
536 SymFn {
04454e1e
FG
537 value: mir::ConstantKind<'tcx>,
538 span: Span,
17df50a5
XL
539 },
540 SymStatic {
541 def_id: DefId,
542 },
543}
544
545#[derive(Copy, Clone, Debug, PartialEq, HashStable)]
546pub enum BindingMode {
547 ByValue,
548 ByRef(BorrowKind),
549}
550
923072b8 551#[derive(Clone, Debug, HashStable)]
17df50a5
XL
552pub struct FieldPat<'tcx> {
553 pub field: Field,
f2b60f7d 554 pub pattern: Box<Pat<'tcx>>,
17df50a5
XL
555}
556
923072b8 557#[derive(Clone, Debug, HashStable)]
17df50a5
XL
558pub struct Pat<'tcx> {
559 pub ty: Ty<'tcx>,
560 pub span: Span,
f2b60f7d 561 pub kind: PatKind<'tcx>,
17df50a5
XL
562}
563
564impl<'tcx> Pat<'tcx> {
565 pub fn wildcard_from_ty(ty: Ty<'tcx>) -> Self {
f2b60f7d
FG
566 Pat { ty, span: DUMMY_SP, kind: PatKind::Wild }
567 }
568
569 pub fn simple_ident(&self) -> Option<Symbol> {
570 match self.kind {
571 PatKind::Binding { name, mode: BindingMode::ByValue, subpattern: None, .. } => {
572 Some(name)
573 }
574 _ => None,
575 }
17df50a5
XL
576 }
577}
578
9c376795
FG
579impl<'tcx> IntoDiagnosticArg for Pat<'tcx> {
580 fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
581 format!("{}", self).into_diagnostic_arg()
582 }
583}
584
923072b8 585#[derive(Clone, Debug, HashStable)]
17df50a5 586pub struct Ascription<'tcx> {
923072b8
FG
587 pub annotation: CanonicalUserTypeAnnotation<'tcx>,
588 /// Variance to use when relating the `user_ty` to the **type of the value being
17df50a5
XL
589 /// matched**. Typically, this is `Variance::Covariant`, since the value being matched must
590 /// have a type that is some subtype of the ascribed type.
591 ///
592 /// Note that this variance does not apply for any bindings within subpatterns. The type
593 /// assigned to those bindings must be exactly equal to the `user_ty` given here.
594 ///
595 /// The only place where this field is not `Covariant` is when matching constants, where
596 /// we currently use `Contravariant` -- this is because the constant type just needs to
597 /// be "comparable" to the type of the input value. So, for example:
598 ///
599 /// ```text
600 /// match x { "foo" => .. }
601 /// ```
602 ///
603 /// requires that `&'static str <: T_x`, where `T_x` is the type of `x`. Really, we should
604 /// probably be checking for a `PartialEq` impl instead, but this preserves the behavior
605 /// of the old type-check for now. See #57280 for details.
606 pub variance: ty::Variance,
17df50a5
XL
607}
608
923072b8 609#[derive(Clone, Debug, HashStable)]
17df50a5 610pub enum PatKind<'tcx> {
923072b8 611 /// A wildcard pattern: `_`.
17df50a5
XL
612 Wild,
613
614 AscribeUserType {
615 ascription: Ascription<'tcx>,
f2b60f7d 616 subpattern: Box<Pat<'tcx>>,
17df50a5
XL
617 },
618
619 /// `x`, `ref x`, `x @ P`, etc.
620 Binding {
621 mutability: Mutability,
622 name: Symbol,
623 mode: BindingMode,
923072b8 624 var: LocalVarId,
17df50a5 625 ty: Ty<'tcx>,
f2b60f7d 626 subpattern: Option<Box<Pat<'tcx>>>,
17df50a5
XL
627 /// Is this the leftmost occurrence of the binding, i.e., is `var` the
628 /// `HirId` of this pattern?
629 is_primary: bool,
630 },
631
632 /// `Foo(...)` or `Foo{...}` or `Foo`, where `Foo` is a variant name from an ADT with
633 /// multiple variants.
634 Variant {
5e7ed085 635 adt_def: AdtDef<'tcx>,
17df50a5
XL
636 substs: SubstsRef<'tcx>,
637 variant_index: VariantIdx,
638 subpatterns: Vec<FieldPat<'tcx>>,
639 },
640
641 /// `(...)`, `Foo(...)`, `Foo{...}`, or `Foo`, where `Foo` is a variant name from an ADT with
642 /// a single variant.
643 Leaf {
644 subpatterns: Vec<FieldPat<'tcx>>,
645 },
646
647 /// `box P`, `&P`, `&mut P`, etc.
648 Deref {
f2b60f7d 649 subpattern: Box<Pat<'tcx>>,
17df50a5
XL
650 },
651
652 /// One of the following:
653 /// * `&str`, which will be handled as a string pattern and thus exhaustiveness
654 /// checking will detect if you use the same string twice in different patterns.
5e7ed085 655 /// * integer, bool, char or float, which will be handled by exhaustiveness to cover exactly
17df50a5
XL
656 /// its own value, similar to `&str`, but these values are much simpler.
657 /// * Opaque constants, that must not be matched structurally. So anything that does not derive
658 /// `PartialEq` and `Eq`.
659 Constant {
923072b8 660 value: mir::ConstantKind<'tcx>,
17df50a5
XL
661 },
662
f2b60f7d 663 Range(Box<PatRange<'tcx>>),
17df50a5
XL
664
665 /// Matches against a slice, checking the length and extracting elements.
666 /// irrefutable when there is a slice pattern and both `prefix` and `suffix` are empty.
667 /// e.g., `&[ref xs @ ..]`.
668 Slice {
f2b60f7d
FG
669 prefix: Box<[Box<Pat<'tcx>>]>,
670 slice: Option<Box<Pat<'tcx>>>,
671 suffix: Box<[Box<Pat<'tcx>>]>,
17df50a5
XL
672 },
673
674 /// Fixed match against an array; irrefutable.
675 Array {
f2b60f7d
FG
676 prefix: Box<[Box<Pat<'tcx>>]>,
677 slice: Option<Box<Pat<'tcx>>>,
678 suffix: Box<[Box<Pat<'tcx>>]>,
17df50a5
XL
679 },
680
681 /// An or-pattern, e.g. `p | q`.
682 /// Invariant: `pats.len() >= 2`.
683 Or {
f2b60f7d 684 pats: Box<[Box<Pat<'tcx>>]>,
17df50a5
XL
685 },
686}
687
f2b60f7d 688#[derive(Clone, Debug, PartialEq, HashStable)]
17df50a5 689pub struct PatRange<'tcx> {
923072b8
FG
690 pub lo: mir::ConstantKind<'tcx>,
691 pub hi: mir::ConstantKind<'tcx>,
17df50a5
XL
692 pub end: RangeEnd,
693}
694
695impl<'tcx> fmt::Display for Pat<'tcx> {
696 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
697 // Printing lists is a chore.
698 let mut first = true;
699 let mut start_or_continue = |s| {
700 if first {
701 first = false;
702 ""
703 } else {
704 s
705 }
706 };
707 let mut start_or_comma = || start_or_continue(", ");
708
f2b60f7d 709 match self.kind {
17df50a5
XL
710 PatKind::Wild => write!(f, "_"),
711 PatKind::AscribeUserType { ref subpattern, .. } => write!(f, "{}: _", subpattern),
712 PatKind::Binding { mutability, name, mode, ref subpattern, .. } => {
713 let is_mut = match mode {
714 BindingMode::ByValue => mutability == Mutability::Mut,
715 BindingMode::ByRef(bk) => {
716 write!(f, "ref ")?;
717 matches!(bk, BorrowKind::Mut { .. })
718 }
719 };
720 if is_mut {
721 write!(f, "mut ")?;
722 }
723 write!(f, "{}", name)?;
724 if let Some(ref subpattern) = *subpattern {
725 write!(f, " @ {}", subpattern)?;
726 }
727 Ok(())
728 }
729 PatKind::Variant { ref subpatterns, .. } | PatKind::Leaf { ref subpatterns } => {
f2b60f7d
FG
730 let variant_and_name = match self.kind {
731 PatKind::Variant { adt_def, variant_index, .. } => ty::tls::with(|tcx| {
732 let variant = adt_def.variant(variant_index);
733 let adt_did = adt_def.did();
734 let name = if tcx.get_diagnostic_item(sym::Option) == Some(adt_did)
735 || tcx.get_diagnostic_item(sym::Result) == Some(adt_did)
736 {
737 variant.name.to_string()
738 } else {
739 format!("{}::{}", tcx.def_path_str(adt_def.did()), variant.name)
740 };
741 Some((variant, name))
742 }),
743 _ => self.ty.ty_adt_def().and_then(|adt_def| {
744 if !adt_def.is_enum() {
745 ty::tls::with(|tcx| {
746 Some((adt_def.non_enum_variant(), tcx.def_path_str(adt_def.did())))
747 })
748 } else {
749 None
750 }
94222f64 751 }),
17df50a5
XL
752 };
753
f2b60f7d
FG
754 if let Some((variant, name)) = &variant_and_name {
755 write!(f, "{}", name)?;
17df50a5
XL
756
757 // Only for Adt we can have `S {...}`,
758 // which we handle separately here.
487cf647 759 if variant.ctor.is_none() {
17df50a5
XL
760 write!(f, " {{ ")?;
761
762 let mut printed = 0;
763 for p in subpatterns {
f2b60f7d 764 if let PatKind::Wild = p.pattern.kind {
17df50a5
XL
765 continue;
766 }
5099ac24 767 let name = variant.fields[p.field.index()].name;
17df50a5
XL
768 write!(f, "{}{}: {}", start_or_comma(), name, p.pattern)?;
769 printed += 1;
770 }
771
772 if printed < variant.fields.len() {
773 write!(f, "{}..", start_or_comma())?;
774 }
775
776 return write!(f, " }}");
777 }
778 }
779
f2b60f7d
FG
780 let num_fields =
781 variant_and_name.as_ref().map_or(subpatterns.len(), |(v, _)| v.fields.len());
782 if num_fields != 0 || variant_and_name.is_none() {
17df50a5
XL
783 write!(f, "(")?;
784 for i in 0..num_fields {
785 write!(f, "{}", start_or_comma())?;
786
787 // Common case: the field is where we expect it.
788 if let Some(p) = subpatterns.get(i) {
789 if p.field.index() == i {
790 write!(f, "{}", p.pattern)?;
791 continue;
792 }
793 }
794
795 // Otherwise, we have to go looking for it.
796 if let Some(p) = subpatterns.iter().find(|p| p.field.index() == i) {
797 write!(f, "{}", p.pattern)?;
798 } else {
799 write!(f, "_")?;
800 }
801 }
802 write!(f, ")")?;
803 }
804
805 Ok(())
806 }
807 PatKind::Deref { ref subpattern } => {
808 match self.ty.kind() {
809 ty::Adt(def, _) if def.is_box() => write!(f, "box ")?,
810 ty::Ref(_, _, mutbl) => {
811 write!(f, "&{}", mutbl.prefix_str())?;
812 }
813 _ => bug!("{} is a bad Deref pattern type", self.ty),
814 }
815 write!(f, "{}", subpattern)
816 }
817 PatKind::Constant { value } => write!(f, "{}", value),
f2b60f7d 818 PatKind::Range(box PatRange { lo, hi, end }) => {
17df50a5
XL
819 write!(f, "{}", lo)?;
820 write!(f, "{}", end)?;
821 write!(f, "{}", hi)
822 }
823 PatKind::Slice { ref prefix, ref slice, ref suffix }
824 | PatKind::Array { ref prefix, ref slice, ref suffix } => {
825 write!(f, "[")?;
f2b60f7d 826 for p in prefix.iter() {
17df50a5
XL
827 write!(f, "{}{}", start_or_comma(), p)?;
828 }
829 if let Some(ref slice) = *slice {
830 write!(f, "{}", start_or_comma())?;
f2b60f7d 831 match slice.kind {
17df50a5
XL
832 PatKind::Wild => {}
833 _ => write!(f, "{}", slice)?,
834 }
835 write!(f, "..")?;
836 }
f2b60f7d 837 for p in suffix.iter() {
17df50a5
XL
838 write!(f, "{}{}", start_or_comma(), p)?;
839 }
840 write!(f, "]")
841 }
842 PatKind::Or { ref pats } => {
f2b60f7d 843 for pat in pats.iter() {
17df50a5
XL
844 write!(f, "{}{}", start_or_continue(" | "), pat)?;
845 }
846 Ok(())
847 }
848 }
849 }
850}
064997fb
FG
851
852// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
853#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
854mod size_asserts {
855 use super::*;
2b03887a 856 // tidy-alphabetical-start
f2b60f7d
FG
857 static_assert_size!(Block, 56);
858 static_assert_size!(Expr<'_>, 64);
859 static_assert_size!(ExprKind<'_>, 40);
f2b60f7d 860 static_assert_size!(Pat<'_>, 72);
f2b60f7d 861 static_assert_size!(PatKind<'_>, 56);
f2b60f7d 862 static_assert_size!(Stmt<'_>, 48);
f2b60f7d 863 static_assert_size!(StmtKind<'_>, 40);
2b03887a 864 // tidy-alphabetical-end
064997fb 865}