summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_middle/src/thir.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_middle/src/thir.rs')
-rw-r--r--compiler/rustc_middle/src/thir.rs236
1 files changed, 139 insertions, 97 deletions
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index b856af1d8..86b415050 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -15,50 +15,33 @@ use rustc_hir::def_id::DefId;
use rustc_hir::RangeEnd;
use rustc_index::newtype_index;
use rustc_index::vec::IndexVec;
-use rustc_middle::infer::canonical::Canonical;
use rustc_middle::middle::region;
use rustc_middle::mir::interpret::AllocId;
use rustc_middle::mir::{self, BinOp, BorrowKind, FakeReadCause, Field, Mutability, UnOp};
use rustc_middle::ty::adjustment::PointerCast;
use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::CanonicalUserTypeAnnotation;
-use rustc_middle::ty::{self, AdtDef, Ty, UpvarSubsts, UserType};
-use rustc_span::{Span, Symbol, DUMMY_SP};
+use rustc_middle::ty::{self, AdtDef, Ty, UpvarSubsts};
+use rustc_middle::ty::{CanonicalUserType, CanonicalUserTypeAnnotation};
+use rustc_span::def_id::LocalDefId;
+use rustc_span::{sym, Span, Symbol, DUMMY_SP};
use rustc_target::abi::VariantIdx;
use rustc_target::asm::InlineAsmRegOrRegClass;
-
-use rustc_span::def_id::LocalDefId;
use std::fmt;
use std::ops::Index;
pub mod visit;
-newtype_index! {
- /// An index to an [`Arm`] stored in [`Thir::arms`]
- #[derive(HashStable)]
- pub struct ArmId {
- DEBUG_FORMAT = "a{}"
- }
-}
-
-newtype_index! {
- /// An index to an [`Expr`] stored in [`Thir::exprs`]
- #[derive(HashStable)]
- pub struct ExprId {
- DEBUG_FORMAT = "e{}"
- }
-}
-
-newtype_index! {
- #[derive(HashStable)]
- /// An index to a [`Stmt`] stored in [`Thir::stmts`]
- pub struct StmtId {
- DEBUG_FORMAT = "s{}"
- }
-}
-
macro_rules! thir_with_elements {
- ($($name:ident: $id:ty => $value:ty,)*) => {
+ ($($name:ident: $id:ty => $value:ty => $format:literal,)*) => {
+ $(
+ newtype_index! {
+ #[derive(HashStable)]
+ pub struct $id {
+ DEBUG_FORMAT = $format
+ }
+ }
+ )*
+
/// A container for a THIR body.
///
/// This can be indexed directly by any THIR index (e.g. [`ExprId`]).
@@ -90,10 +73,29 @@ macro_rules! thir_with_elements {
}
}
+pub const UPVAR_ENV_PARAM: ParamId = ParamId::from_u32(0);
+
thir_with_elements! {
- arms: ArmId => Arm<'tcx>,
- exprs: ExprId => Expr<'tcx>,
- stmts: StmtId => Stmt<'tcx>,
+ arms: ArmId => Arm<'tcx> => "a{}",
+ blocks: BlockId => Block => "b{}",
+ exprs: ExprId => Expr<'tcx> => "e{}",
+ stmts: StmtId => Stmt<'tcx> => "s{}",
+ params: ParamId => Param<'tcx> => "p{}",
+}
+
+/// Description of a type-checked function parameter.
+#[derive(Clone, Debug, HashStable)]
+pub struct Param<'tcx> {
+ /// The pattern that appears in the parameter list, or None for implicit parameters.
+ pub pat: Option<Box<Pat<'tcx>>>,
+ /// The possibly inferred type.
+ pub ty: Ty<'tcx>,
+ /// Span of the explicitly provided type, or None if inferred for closures.
+ pub ty_span: Option<Span>,
+ /// Whether this param is `self`, and how it is bound.
+ pub self_kind: Option<hir::ImplicitSelfKind>,
+ /// HirId for lints.
+ pub hir_id: Option<hir::HirId>,
}
#[derive(Copy, Clone, Debug, HashStable)]
@@ -121,8 +123,10 @@ pub struct Block {
pub safety_mode: BlockSafety,
}
+type UserTy<'tcx> = Option<Box<CanonicalUserType<'tcx>>>;
+
#[derive(Clone, Debug, HashStable)]
-pub struct Adt<'tcx> {
+pub struct AdtExpr<'tcx> {
/// The ADT we're constructing.
pub adt_def: AdtDef<'tcx>,
/// The variant of the ADT.
@@ -131,13 +135,30 @@ pub struct Adt<'tcx> {
/// Optional user-given substs: for something like `let x =
/// Bar::<T> { ... }`.
- pub user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
+ pub user_ty: UserTy<'tcx>,
pub fields: Box<[FieldExpr]>,
/// The base, e.g. `Foo {x: 1, .. base}`.
pub base: Option<FruInfo<'tcx>>,
}
+#[derive(Clone, Debug, HashStable)]
+pub struct ClosureExpr<'tcx> {
+ pub closure_id: LocalDefId,
+ pub substs: UpvarSubsts<'tcx>,
+ pub upvars: Box<[ExprId]>,
+ pub movability: Option<hir::Movability>,
+ pub fake_reads: Vec<(ExprId, FakeReadCause, hir::HirId)>,
+}
+
+#[derive(Clone, Debug, HashStable)]
+pub struct InlineAsmExpr<'tcx> {
+ pub template: &'tcx [InlineAsmTemplatePiece],
+ pub operands: Box<[InlineAsmOperand<'tcx>]>,
+ pub options: InlineAsmOptions,
+ pub line_spans: &'tcx [Span],
+}
+
#[derive(Copy, Clone, Debug, HashStable)]
pub enum BlockSafety {
Safe,
@@ -177,13 +198,13 @@ pub enum StmtKind<'tcx> {
/// `let <PAT> = ...`
///
/// If a type annotation is included, it is added as an ascription pattern.
- pattern: Pat<'tcx>,
+ pattern: Box<Pat<'tcx>>,
/// `let pat: ty = <INIT>`
initializer: Option<ExprId>,
/// `let pat: ty = <INIT> else { <ELSE> }
- else_block: Option<Block>,
+ else_block: Option<BlockId>,
/// The lint level for this `let` statement.
lint_level: LintLevel,
@@ -298,7 +319,7 @@ pub enum ExprKind<'tcx> {
},
Let {
expr: ExprId,
- pat: Pat<'tcx>,
+ pat: Box<Pat<'tcx>>,
},
/// A `match` expression.
Match {
@@ -307,7 +328,7 @@ pub enum ExprKind<'tcx> {
},
/// A block.
Block {
- body: Block,
+ block: BlockId,
},
/// An assignment: `lhs = rhs`.
Assign {
@@ -387,27 +408,21 @@ pub enum ExprKind<'tcx> {
fields: Box<[ExprId]>,
},
/// An ADT constructor, e.g. `Foo {x: 1, y: 2}`.
- Adt(Box<Adt<'tcx>>),
+ Adt(Box<AdtExpr<'tcx>>),
/// A type ascription on a place.
PlaceTypeAscription {
source: ExprId,
/// Type that the user gave to this expression
- user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
+ user_ty: UserTy<'tcx>,
},
/// A type ascription on a value, e.g. `42: i32`.
ValueTypeAscription {
source: ExprId,
/// Type that the user gave to this expression
- user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
+ user_ty: UserTy<'tcx>,
},
/// A closure definition.
- Closure {
- closure_id: LocalDefId,
- substs: UpvarSubsts<'tcx>,
- upvars: Box<[ExprId]>,
- movability: Option<hir::Movability>,
- fake_reads: Vec<(ExprId, FakeReadCause, hir::HirId)>,
- },
+ Closure(Box<ClosureExpr<'tcx>>),
/// A literal.
Literal {
lit: &'tcx hir::Lit,
@@ -416,17 +431,17 @@ pub enum ExprKind<'tcx> {
/// For literals that don't correspond to anything in the HIR
NonHirLiteral {
lit: ty::ScalarInt,
- user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
+ user_ty: UserTy<'tcx>,
},
/// A literal of a ZST type.
ZstLiteral {
- user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
+ user_ty: UserTy<'tcx>,
},
/// Associated constants and named constants
NamedConst {
def_id: DefId,
substs: SubstsRef<'tcx>,
- user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
+ user_ty: UserTy<'tcx>,
},
ConstParam {
param: ty::ParamConst,
@@ -443,12 +458,7 @@ pub enum ExprKind<'tcx> {
def_id: DefId,
},
/// Inline assembly, i.e. `asm!()`.
- InlineAsm {
- template: &'tcx [InlineAsmTemplatePiece],
- operands: Box<[InlineAsmOperand<'tcx>]>,
- options: InlineAsmOptions,
- line_spans: &'tcx [Span],
- },
+ InlineAsm(Box<InlineAsmExpr<'tcx>>),
/// An expression taking a reference to a thread local.
ThreadLocalRef(DefId),
/// A `yield` expression.
@@ -475,7 +485,7 @@ pub struct FruInfo<'tcx> {
/// A `match` arm.
#[derive(Clone, Debug, HashStable)]
pub struct Arm<'tcx> {
- pub pattern: Pat<'tcx>,
+ pub pattern: Box<Pat<'tcx>>,
pub guard: Option<Guard<'tcx>>,
pub body: ExprId,
pub lint_level: LintLevel,
@@ -487,7 +497,7 @@ pub struct Arm<'tcx> {
#[derive(Clone, Debug, HashStable)]
pub enum Guard<'tcx> {
If(ExprId),
- IfLet(Pat<'tcx>, ExprId),
+ IfLet(Box<Pat<'tcx>>, ExprId),
}
#[derive(Copy, Clone, Debug, HashStable)]
@@ -542,19 +552,28 @@ pub enum BindingMode {
#[derive(Clone, Debug, HashStable)]
pub struct FieldPat<'tcx> {
pub field: Field,
- pub pattern: Pat<'tcx>,
+ pub pattern: Box<Pat<'tcx>>,
}
#[derive(Clone, Debug, HashStable)]
pub struct Pat<'tcx> {
pub ty: Ty<'tcx>,
pub span: Span,
- pub kind: Box<PatKind<'tcx>>,
+ pub kind: PatKind<'tcx>,
}
impl<'tcx> Pat<'tcx> {
pub fn wildcard_from_ty(ty: Ty<'tcx>) -> Self {
- Pat { ty, span: DUMMY_SP, kind: Box::new(PatKind::Wild) }
+ Pat { ty, span: DUMMY_SP, kind: PatKind::Wild }
+ }
+
+ pub fn simple_ident(&self) -> Option<Symbol> {
+ match self.kind {
+ PatKind::Binding { name, mode: BindingMode::ByValue, subpattern: None, .. } => {
+ Some(name)
+ }
+ _ => None,
+ }
}
}
@@ -589,7 +608,7 @@ pub enum PatKind<'tcx> {
AscribeUserType {
ascription: Ascription<'tcx>,
- subpattern: Pat<'tcx>,
+ subpattern: Box<Pat<'tcx>>,
},
/// `x`, `ref x`, `x @ P`, etc.
@@ -599,7 +618,7 @@ pub enum PatKind<'tcx> {
mode: BindingMode,
var: LocalVarId,
ty: Ty<'tcx>,
- subpattern: Option<Pat<'tcx>>,
+ subpattern: Option<Box<Pat<'tcx>>>,
/// Is this the leftmost occurrence of the binding, i.e., is `var` the
/// `HirId` of this pattern?
is_primary: bool,
@@ -622,7 +641,7 @@ pub enum PatKind<'tcx> {
/// `box P`, `&P`, `&mut P`, etc.
Deref {
- subpattern: Pat<'tcx>,
+ subpattern: Box<Pat<'tcx>>,
},
/// One of the following:
@@ -636,32 +655,32 @@ pub enum PatKind<'tcx> {
value: mir::ConstantKind<'tcx>,
},
- Range(PatRange<'tcx>),
+ Range(Box<PatRange<'tcx>>),
/// Matches against a slice, checking the length and extracting elements.
/// irrefutable when there is a slice pattern and both `prefix` and `suffix` are empty.
/// e.g., `&[ref xs @ ..]`.
Slice {
- prefix: Vec<Pat<'tcx>>,
- slice: Option<Pat<'tcx>>,
- suffix: Vec<Pat<'tcx>>,
+ prefix: Box<[Box<Pat<'tcx>>]>,
+ slice: Option<Box<Pat<'tcx>>>,
+ suffix: Box<[Box<Pat<'tcx>>]>,
},
/// Fixed match against an array; irrefutable.
Array {
- prefix: Vec<Pat<'tcx>>,
- slice: Option<Pat<'tcx>>,
- suffix: Vec<Pat<'tcx>>,
+ prefix: Box<[Box<Pat<'tcx>>]>,
+ slice: Option<Box<Pat<'tcx>>>,
+ suffix: Box<[Box<Pat<'tcx>>]>,
},
/// An or-pattern, e.g. `p | q`.
/// Invariant: `pats.len() >= 2`.
Or {
- pats: Vec<Pat<'tcx>>,
+ pats: Box<[Box<Pat<'tcx>>]>,
},
}
-#[derive(Copy, Clone, Debug, PartialEq, HashStable)]
+#[derive(Clone, Debug, PartialEq, HashStable)]
pub struct PatRange<'tcx> {
pub lo: mir::ConstantKind<'tcx>,
pub hi: mir::ConstantKind<'tcx>,
@@ -682,7 +701,7 @@ impl<'tcx> fmt::Display for Pat<'tcx> {
};
let mut start_or_comma = || start_or_continue(", ");
- match *self.kind {
+ match self.kind {
PatKind::Wild => write!(f, "_"),
PatKind::AscribeUserType { ref subpattern, .. } => write!(f, "{}: _", subpattern),
PatKind::Binding { mutability, name, mode, ref subpattern, .. } => {
@@ -703,17 +722,32 @@ impl<'tcx> fmt::Display for Pat<'tcx> {
Ok(())
}
PatKind::Variant { ref subpatterns, .. } | PatKind::Leaf { ref subpatterns } => {
- let variant = match *self.kind {
- PatKind::Variant { adt_def, variant_index, .. } => {
- Some(adt_def.variant(variant_index))
- }
- _ => self.ty.ty_adt_def().and_then(|adt| {
- if !adt.is_enum() { Some(adt.non_enum_variant()) } else { None }
+ let variant_and_name = match self.kind {
+ PatKind::Variant { adt_def, variant_index, .. } => ty::tls::with(|tcx| {
+ let variant = adt_def.variant(variant_index);
+ let adt_did = adt_def.did();
+ let name = if tcx.get_diagnostic_item(sym::Option) == Some(adt_did)
+ || tcx.get_diagnostic_item(sym::Result) == Some(adt_did)
+ {
+ variant.name.to_string()
+ } else {
+ format!("{}::{}", tcx.def_path_str(adt_def.did()), variant.name)
+ };
+ Some((variant, name))
+ }),
+ _ => self.ty.ty_adt_def().and_then(|adt_def| {
+ if !adt_def.is_enum() {
+ ty::tls::with(|tcx| {
+ Some((adt_def.non_enum_variant(), tcx.def_path_str(adt_def.did())))
+ })
+ } else {
+ None
+ }
}),
};
- if let Some(variant) = variant {
- write!(f, "{}", variant.name)?;
+ if let Some((variant, name)) = &variant_and_name {
+ write!(f, "{}", name)?;
// Only for Adt we can have `S {...}`,
// which we handle separately here.
@@ -722,7 +756,7 @@ impl<'tcx> fmt::Display for Pat<'tcx> {
let mut printed = 0;
for p in subpatterns {
- if let PatKind::Wild = *p.pattern.kind {
+ if let PatKind::Wild = p.pattern.kind {
continue;
}
let name = variant.fields[p.field.index()].name;
@@ -738,8 +772,9 @@ impl<'tcx> fmt::Display for Pat<'tcx> {
}
}
- let num_fields = variant.map_or(subpatterns.len(), |v| v.fields.len());
- if num_fields != 0 || variant.is_none() {
+ let num_fields =
+ variant_and_name.as_ref().map_or(subpatterns.len(), |(v, _)| v.fields.len());
+ if num_fields != 0 || variant_and_name.is_none() {
write!(f, "(")?;
for i in 0..num_fields {
write!(f, "{}", start_or_comma())?;
@@ -775,7 +810,7 @@ impl<'tcx> fmt::Display for Pat<'tcx> {
write!(f, "{}", subpattern)
}
PatKind::Constant { value } => write!(f, "{}", value),
- PatKind::Range(PatRange { lo, hi, end }) => {
+ PatKind::Range(box PatRange { lo, hi, end }) => {
write!(f, "{}", lo)?;
write!(f, "{}", end)?;
write!(f, "{}", hi)
@@ -783,24 +818,24 @@ impl<'tcx> fmt::Display for Pat<'tcx> {
PatKind::Slice { ref prefix, ref slice, ref suffix }
| PatKind::Array { ref prefix, ref slice, ref suffix } => {
write!(f, "[")?;
- for p in prefix {
+ for p in prefix.iter() {
write!(f, "{}{}", start_or_comma(), p)?;
}
if let Some(ref slice) = *slice {
write!(f, "{}", start_or_comma())?;
- match *slice.kind {
+ match slice.kind {
PatKind::Wild => {}
_ => write!(f, "{}", slice)?,
}
write!(f, "..")?;
}
- for p in suffix {
+ for p in suffix.iter() {
write!(f, "{}{}", start_or_comma(), p)?;
}
write!(f, "]")
}
PatKind::Or { ref pats } => {
- for pat in pats {
+ for pat in pats.iter() {
write!(f, "{}{}", start_or_continue(" | "), pat)?;
}
Ok(())
@@ -814,8 +849,15 @@ impl<'tcx> fmt::Display for Pat<'tcx> {
mod size_asserts {
use super::*;
// These are in alphabetical order, which is easy to maintain.
- rustc_data_structures::static_assert_size!(Block, 56);
- rustc_data_structures::static_assert_size!(Expr<'_>, 104);
- rustc_data_structures::static_assert_size!(Pat<'_>, 24);
- rustc_data_structures::static_assert_size!(Stmt<'_>, 120);
+ static_assert_size!(Block, 56);
+ static_assert_size!(Expr<'_>, 64);
+ static_assert_size!(ExprKind<'_>, 40);
+ #[cfg(not(bootstrap))]
+ static_assert_size!(Pat<'_>, 72);
+ #[cfg(not(bootstrap))]
+ static_assert_size!(PatKind<'_>, 56);
+ #[cfg(not(bootstrap))]
+ static_assert_size!(Stmt<'_>, 48);
+ #[cfg(not(bootstrap))]
+ static_assert_size!(StmtKind<'_>, 40);
}