//! unit-tested and separated from the Rust source and compiler data
//! structures.
-use self::cx::Cx;
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_middle::infer::canonical::Canonical;
use rustc_middle::middle::region;
-use rustc_middle::mir::{BinOp, BorrowKind, Field, UnOp};
+use rustc_middle::mir::{BinOp, BorrowKind, FakeReadCause, Field, UnOp};
use rustc_middle::ty::adjustment::PointerCast;
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::{AdtDef, Const, Ty, UpvarSubsts, UserType};
use rustc_target::asm::InlineAsmRegOrRegClass;
crate mod constant;
+
crate mod cx;
+pub use cx::build_thir;
crate mod pattern;
-crate use self::pattern::PatTyProj;
-crate use self::pattern::{BindingMode, FieldPat, Pat, PatKind, PatRange};
+pub use self::pattern::{Ascription, BindingMode, FieldPat, Pat, PatKind, PatRange, PatTyProj};
+
+mod arena;
+pub use arena::Arena;
mod util;
#[derive(Copy, Clone, Debug)]
-crate enum LintLevel {
+pub enum LintLevel {
Inherited,
Explicit(hir::HirId),
}
-#[derive(Clone, Debug)]
-crate struct Block<'tcx> {
- crate targeted_by_break: bool,
- crate region_scope: region::Scope,
- crate opt_destruction_scope: Option<region::Scope>,
- crate span: Span,
- crate stmts: Vec<StmtRef<'tcx>>,
- crate expr: Option<ExprRef<'tcx>>,
- crate safety_mode: BlockSafety,
+#[derive(Debug)]
+pub struct Block<'thir, 'tcx> {
+ pub targeted_by_break: bool,
+ pub region_scope: region::Scope,
+ pub opt_destruction_scope: Option<region::Scope>,
+ pub span: Span,
+ pub stmts: &'thir [Stmt<'thir, 'tcx>],
+ pub expr: Option<&'thir Expr<'thir, 'tcx>>,
+ pub safety_mode: BlockSafety,
}
#[derive(Copy, Clone, Debug)]
-crate enum BlockSafety {
+pub enum BlockSafety {
Safe,
ExplicitUnsafe(hir::HirId),
PushUnsafe,
PopUnsafe,
}
-#[derive(Clone, Debug)]
-crate enum StmtRef<'tcx> {
- Mirror(Box<Stmt<'tcx>>),
-}
-
-#[derive(Clone, Debug)]
-crate struct Stmt<'tcx> {
- crate kind: StmtKind<'tcx>,
- crate opt_destruction_scope: Option<region::Scope>,
+#[derive(Debug)]
+pub struct Stmt<'thir, 'tcx> {
+ pub kind: StmtKind<'thir, 'tcx>,
+ pub opt_destruction_scope: Option<region::Scope>,
}
-#[derive(Clone, Debug)]
-crate enum StmtKind<'tcx> {
+#[derive(Debug)]
+pub enum StmtKind<'thir, 'tcx> {
Expr {
/// scope for this statement; may be used as lifetime of temporaries
scope: region::Scope,
/// expression being evaluated in this statement
- expr: ExprRef<'tcx>,
+ expr: &'thir Expr<'thir, 'tcx>,
},
Let {
pattern: Pat<'tcx>,
/// let pat: ty = <INIT> ...
- initializer: Option<ExprRef<'tcx>>,
+ initializer: Option<&'thir Expr<'thir, 'tcx>>,
/// the lint level for this let-statement
lint_level: LintLevel,
}
// `Expr` is used a lot. Make sure it doesn't unintentionally get bigger.
-#[cfg(target_arch = "x86_64")]
-rustc_data_structures::static_assert_size!(Expr<'_>, 168);
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
+rustc_data_structures::static_assert_size!(Expr<'_, '_>, 144);
/// The Thir trait implementor lowers their expressions (`&'tcx H::Expr`)
/// into instances of this `Expr` enum. This lowering can be done
/// basically as lazily or as eagerly as desired: every recursive
-/// reference to an expression in this enum is an `ExprRef<'tcx>`, which
+/// reference to an expression in this enum is an `&'thir Expr<'thir, 'tcx>`, which
/// may in turn be another instance of this enum (boxed), or else an
/// unlowered `&'tcx H::Expr`. Note that instances of `Expr` are very
/// short-lived. They are created by `Thir::to_expr`, analyzed and
/// MIR simplifications are already done in the impl of `Thir`. For
/// example, method calls and overloaded operators are absent: they are
/// expected to be converted into `Expr::Call` instances.
-#[derive(Clone, Debug)]
-crate struct Expr<'tcx> {
+#[derive(Debug)]
+pub struct Expr<'thir, 'tcx> {
/// type of this expression
- crate ty: Ty<'tcx>,
+ pub ty: Ty<'tcx>,
/// lifetime of this expression if it should be spilled into a
/// temporary; should be None only if in a constant context
- crate temp_lifetime: Option<region::Scope>,
+ pub temp_lifetime: Option<region::Scope>,
/// span of the expression in the source
- crate span: Span,
+ pub span: Span,
/// kind of expression
- crate kind: ExprKind<'tcx>,
+ pub kind: ExprKind<'thir, 'tcx>,
}
-#[derive(Clone, Debug)]
-crate enum ExprKind<'tcx> {
+#[derive(Debug)]
+pub enum ExprKind<'thir, 'tcx> {
Scope {
region_scope: region::Scope,
lint_level: LintLevel,
- value: ExprRef<'tcx>,
+ value: &'thir Expr<'thir, 'tcx>,
},
Box {
- value: ExprRef<'tcx>,
+ value: &'thir Expr<'thir, 'tcx>,
},
If {
- cond: ExprRef<'tcx>,
- then: ExprRef<'tcx>,
- else_opt: Option<ExprRef<'tcx>>,
+ cond: &'thir Expr<'thir, 'tcx>,
+ then: &'thir Expr<'thir, 'tcx>,
+ else_opt: Option<&'thir Expr<'thir, 'tcx>>,
},
Call {
ty: Ty<'tcx>,
- fun: ExprRef<'tcx>,
- args: Vec<ExprRef<'tcx>>,
- // Whether this is from a call in HIR, rather than from an overloaded
- // operator. True for overloaded function call.
+ fun: &'thir Expr<'thir, 'tcx>,
+ args: &'thir [Expr<'thir, 'tcx>],
+ /// Whether this is from a call in HIR, rather than from an overloaded
+ /// operator. `true` for overloaded function call.
from_hir_call: bool,
/// This `Span` is the span of the function, without the dot and receiver
/// (e.g. `foo(a, b)` in `x.foo(a, b)`
fn_span: Span,
},
Deref {
- arg: ExprRef<'tcx>,
+ arg: &'thir Expr<'thir, 'tcx>,
}, // NOT overloaded!
Binary {
op: BinOp,
- lhs: ExprRef<'tcx>,
- rhs: ExprRef<'tcx>,
+ lhs: &'thir Expr<'thir, 'tcx>,
+ rhs: &'thir Expr<'thir, 'tcx>,
}, // NOT overloaded!
LogicalOp {
op: LogicalOp,
- lhs: ExprRef<'tcx>,
- rhs: ExprRef<'tcx>,
+ lhs: &'thir Expr<'thir, 'tcx>,
+ rhs: &'thir Expr<'thir, 'tcx>,
}, // NOT overloaded!
// LogicalOp is distinct from BinaryOp because of lazy evaluation of the operands.
Unary {
op: UnOp,
- arg: ExprRef<'tcx>,
+ arg: &'thir Expr<'thir, 'tcx>,
}, // NOT overloaded!
Cast {
- source: ExprRef<'tcx>,
+ source: &'thir Expr<'thir, 'tcx>,
},
Use {
- source: ExprRef<'tcx>,
+ source: &'thir Expr<'thir, 'tcx>,
}, // Use a lexpr to get a vexpr.
NeverToAny {
- source: ExprRef<'tcx>,
+ source: &'thir Expr<'thir, 'tcx>,
},
Pointer {
cast: PointerCast,
- source: ExprRef<'tcx>,
+ source: &'thir Expr<'thir, 'tcx>,
},
Loop {
- body: ExprRef<'tcx>,
+ body: &'thir Expr<'thir, 'tcx>,
},
Match {
- scrutinee: ExprRef<'tcx>,
- arms: Vec<Arm<'tcx>>,
+ scrutinee: &'thir Expr<'thir, 'tcx>,
+ arms: &'thir [Arm<'thir, 'tcx>],
},
Block {
- body: &'tcx hir::Block<'tcx>,
+ body: Block<'thir, 'tcx>,
},
Assign {
- lhs: ExprRef<'tcx>,
- rhs: ExprRef<'tcx>,
+ lhs: &'thir Expr<'thir, 'tcx>,
+ rhs: &'thir Expr<'thir, 'tcx>,
},
AssignOp {
op: BinOp,
- lhs: ExprRef<'tcx>,
- rhs: ExprRef<'tcx>,
+ lhs: &'thir Expr<'thir, 'tcx>,
+ rhs: &'thir Expr<'thir, 'tcx>,
},
Field {
- lhs: ExprRef<'tcx>,
+ lhs: &'thir Expr<'thir, 'tcx>,
name: Field,
},
Index {
- lhs: ExprRef<'tcx>,
- index: ExprRef<'tcx>,
+ lhs: &'thir Expr<'thir, 'tcx>,
+ index: &'thir Expr<'thir, 'tcx>,
},
VarRef {
id: hir::HirId,
},
Borrow {
borrow_kind: BorrowKind,
- arg: ExprRef<'tcx>,
+ arg: &'thir Expr<'thir, 'tcx>,
},
/// A `&raw [const|mut] $place_expr` raw borrow resulting in type `*[const|mut] T`.
AddressOf {
mutability: hir::Mutability,
- arg: ExprRef<'tcx>,
+ arg: &'thir Expr<'thir, 'tcx>,
},
Break {
label: region::Scope,
- value: Option<ExprRef<'tcx>>,
+ value: Option<&'thir Expr<'thir, 'tcx>>,
},
Continue {
label: region::Scope,
},
Return {
- value: Option<ExprRef<'tcx>>,
+ value: Option<&'thir Expr<'thir, 'tcx>>,
},
ConstBlock {
value: &'tcx Const<'tcx>,
},
Repeat {
- value: ExprRef<'tcx>,
+ value: &'thir Expr<'thir, 'tcx>,
count: &'tcx Const<'tcx>,
},
Array {
- fields: Vec<ExprRef<'tcx>>,
+ fields: &'thir [Expr<'thir, 'tcx>],
},
Tuple {
- fields: Vec<ExprRef<'tcx>>,
+ fields: &'thir [Expr<'thir, 'tcx>],
},
Adt {
adt_def: &'tcx AdtDef,
/// Bar::<T> { ... }`.
user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
- fields: Vec<FieldExprRef<'tcx>>,
- base: Option<FruInfo<'tcx>>,
+ fields: &'thir [FieldExpr<'thir, 'tcx>],
+ base: Option<FruInfo<'thir, 'tcx>>,
},
PlaceTypeAscription {
- source: ExprRef<'tcx>,
+ source: &'thir Expr<'thir, 'tcx>,
/// Type that the user gave to this expression
user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
},
ValueTypeAscription {
- source: ExprRef<'tcx>,
+ source: &'thir Expr<'thir, 'tcx>,
/// Type that the user gave to this expression
user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
},
Closure {
closure_id: DefId,
substs: UpvarSubsts<'tcx>,
- upvars: Vec<ExprRef<'tcx>>,
+ upvars: &'thir [Expr<'thir, 'tcx>],
movability: Option<hir::Movability>,
+ fake_reads: Vec<(&'thir Expr<'thir, 'tcx>, FakeReadCause, hir::HirId)>,
},
Literal {
literal: &'tcx Const<'tcx>,
},
InlineAsm {
template: &'tcx [InlineAsmTemplatePiece],
- operands: Vec<InlineAsmOperand<'tcx>>,
+ operands: &'thir [InlineAsmOperand<'thir, 'tcx>],
options: InlineAsmOptions,
line_spans: &'tcx [Span],
},
ThreadLocalRef(DefId),
LlvmInlineAsm {
asm: &'tcx hir::LlvmInlineAsmInner,
- outputs: Vec<ExprRef<'tcx>>,
- inputs: Vec<ExprRef<'tcx>>,
+ outputs: &'thir [Expr<'thir, 'tcx>],
+ inputs: &'thir [Expr<'thir, 'tcx>],
},
Yield {
- value: ExprRef<'tcx>,
+ value: &'thir Expr<'thir, 'tcx>,
},
}
-#[derive(Clone, Debug)]
-crate enum ExprRef<'tcx> {
- Thir(&'tcx hir::Expr<'tcx>),
- Mirror(Box<Expr<'tcx>>),
+#[derive(Debug)]
+pub struct FieldExpr<'thir, 'tcx> {
+ pub name: Field,
+ pub expr: &'thir Expr<'thir, 'tcx>,
}
-#[derive(Clone, Debug)]
-crate struct FieldExprRef<'tcx> {
- crate name: Field,
- crate expr: ExprRef<'tcx>,
+#[derive(Debug)]
+pub struct FruInfo<'thir, 'tcx> {
+ pub base: &'thir Expr<'thir, 'tcx>,
+ pub field_types: &'thir [Ty<'tcx>],
}
-#[derive(Clone, Debug)]
-crate struct FruInfo<'tcx> {
- crate base: ExprRef<'tcx>,
- crate field_types: Vec<Ty<'tcx>>,
+#[derive(Debug)]
+pub struct Arm<'thir, 'tcx> {
+ pub pattern: Pat<'tcx>,
+ pub guard: Option<Guard<'thir, 'tcx>>,
+ pub body: &'thir Expr<'thir, 'tcx>,
+ pub lint_level: LintLevel,
+ pub scope: region::Scope,
+ pub span: Span,
}
-#[derive(Clone, Debug)]
-crate struct Arm<'tcx> {
- crate pattern: Pat<'tcx>,
- crate guard: Option<Guard<'tcx>>,
- crate body: ExprRef<'tcx>,
- crate lint_level: LintLevel,
- crate scope: region::Scope,
- crate span: Span,
-}
-
-#[derive(Clone, Debug)]
-crate enum Guard<'tcx> {
- If(ExprRef<'tcx>),
- IfLet(Pat<'tcx>, ExprRef<'tcx>),
+#[derive(Debug)]
+pub enum Guard<'thir, 'tcx> {
+ If(&'thir Expr<'thir, 'tcx>),
+ IfLet(Pat<'tcx>, &'thir Expr<'thir, 'tcx>),
}
#[derive(Copy, Clone, Debug)]
-crate enum LogicalOp {
+pub enum LogicalOp {
And,
Or,
}
-impl<'tcx> ExprRef<'tcx> {
- crate fn span(&self) -> Span {
- match self {
- ExprRef::Thir(expr) => expr.span,
- ExprRef::Mirror(expr) => expr.span,
- }
- }
-}
-
-#[derive(Clone, Debug)]
-crate enum InlineAsmOperand<'tcx> {
+#[derive(Debug)]
+pub enum InlineAsmOperand<'thir, 'tcx> {
In {
reg: InlineAsmRegOrRegClass,
- expr: ExprRef<'tcx>,
+ expr: &'thir Expr<'thir, 'tcx>,
},
Out {
reg: InlineAsmRegOrRegClass,
late: bool,
- expr: Option<ExprRef<'tcx>>,
+ expr: Option<&'thir Expr<'thir, 'tcx>>,
},
InOut {
reg: InlineAsmRegOrRegClass,
late: bool,
- expr: ExprRef<'tcx>,
+ expr: &'thir Expr<'thir, 'tcx>,
},
SplitInOut {
reg: InlineAsmRegOrRegClass,
late: bool,
- in_expr: ExprRef<'tcx>,
- out_expr: Option<ExprRef<'tcx>>,
+ in_expr: &'thir Expr<'thir, 'tcx>,
+ out_expr: Option<&'thir Expr<'thir, 'tcx>>,
},
Const {
- expr: ExprRef<'tcx>,
+ expr: &'thir Expr<'thir, 'tcx>,
},
SymFn {
- expr: ExprRef<'tcx>,
+ expr: &'thir Expr<'thir, 'tcx>,
},
SymStatic {
def_id: DefId,
},
}
-
-///////////////////////////////////////////////////////////////////////////
-// The Mirror trait
-
-/// "Mirroring" is the process of converting from a HIR type into one
-/// of the THIR types defined in this file. This is basically a "on
-/// the fly" desugaring step that hides a lot of the messiness in the
-/// tcx. For example, the mirror of a `&'tcx hir::Expr` is an
-/// `Expr<'tcx>`.
-///
-/// Mirroring is gradual: when you mirror an outer expression like `e1
-/// + e2`, the references to the inner expressions `e1` and `e2` are
-/// `ExprRef<'tcx>` instances, and they may or may not be eagerly
-/// mirrored. This allows a single AST node from the compiler to
-/// expand into one or more Thir nodes, which lets the Thir nodes be
-/// simpler.
-crate trait Mirror<'tcx> {
- type Output;
-
- fn make_mirror(self, cx: &mut Cx<'_, 'tcx>) -> Self::Output;
-}
-
-impl<'tcx> Mirror<'tcx> for Expr<'tcx> {
- type Output = Expr<'tcx>;
-
- fn make_mirror(self, _: &mut Cx<'_, 'tcx>) -> Expr<'tcx> {
- self
- }
-}
-
-impl<'tcx> Mirror<'tcx> for ExprRef<'tcx> {
- type Output = Expr<'tcx>;
-
- fn make_mirror(self, hir: &mut Cx<'_, 'tcx>) -> Expr<'tcx> {
- match self {
- ExprRef::Thir(h) => h.make_mirror(hir),
- ExprRef::Mirror(m) => *m,
- }
- }
-}
-
-impl<'tcx> Mirror<'tcx> for Stmt<'tcx> {
- type Output = Stmt<'tcx>;
-
- fn make_mirror(self, _: &mut Cx<'_, 'tcx>) -> Stmt<'tcx> {
- self
- }
-}
-
-impl<'tcx> Mirror<'tcx> for StmtRef<'tcx> {
- type Output = Stmt<'tcx>;
-
- fn make_mirror(self, _: &mut Cx<'_, 'tcx>) -> Stmt<'tcx> {
- match self {
- StmtRef::Mirror(m) => *m,
- }
- }
-}
-
-impl<'tcx> Mirror<'tcx> for Block<'tcx> {
- type Output = Block<'tcx>;
-
- fn make_mirror(self, _: &mut Cx<'_, 'tcx>) -> Block<'tcx> {
- self
- }
-}