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