diff options
Diffstat (limited to '')
-rw-r--r-- | compiler/rustc_middle/src/thir.rs | 236 | ||||
-rw-r--r-- | compiler/rustc_middle/src/thir/visit.rs | 29 |
2 files changed, 157 insertions, 108 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); } diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index 97249fdd1..79a0e75aa 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -1,5 +1,6 @@ use super::{ - Arm, Block, Expr, ExprKind, Guard, InlineAsmOperand, Pat, PatKind, Stmt, StmtKind, Thir, + AdtExpr, Arm, Block, ClosureExpr, Expr, ExprKind, Guard, InlineAsmExpr, InlineAsmOperand, Pat, + PatKind, Stmt, StmtKind, Thir, }; pub trait Visitor<'a, 'tcx: 'a>: Sized { @@ -75,7 +76,7 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp visitor.visit_arm(&visitor.thir()[arm]); } } - Block { ref body } => visitor.visit_block(body), + Block { block } => visitor.visit_block(&visitor.thir()[block]), Assign { lhs, rhs } | AssignOp { lhs, rhs, op: _ } => { visitor.visit_expr(&visitor.thir()[lhs]); visitor.visit_expr(&visitor.thir()[rhs]); @@ -108,7 +109,7 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp visitor.visit_expr(&visitor.thir()[field]); } } - Adt(box crate::thir::Adt { + Adt(box AdtExpr { ref fields, ref base, adt_def: _, @@ -126,14 +127,20 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp PlaceTypeAscription { source, user_ty: _ } | ValueTypeAscription { source, user_ty: _ } => { visitor.visit_expr(&visitor.thir()[source]) } - Closure { closure_id: _, substs: _, upvars: _, movability: _, fake_reads: _ } => {} + Closure(box ClosureExpr { + closure_id: _, + substs: _, + upvars: _, + movability: _, + fake_reads: _, + }) => {} Literal { lit: _, neg: _ } => {} NonHirLiteral { lit: _, user_ty: _ } => {} ZstLiteral { user_ty: _ } => {} NamedConst { def_id: _, substs: _, user_ty: _ } => {} ConstParam { param: _, def_id: _ } => {} StaticRef { alloc_id: _, ty: _, def_id: _ } => {} - InlineAsm { ref operands, template: _, options: _, line_spans: _ } => { + InlineAsm(box InlineAsmExpr { ref operands, template: _, options: _, line_spans: _ }) => { for op in &**operands { use InlineAsmOperand::*; match op { @@ -174,7 +181,7 @@ pub fn walk_stmt<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, stmt: &Stm } visitor.visit_pat(pattern); if let Some(block) = else_block { - visitor.visit_block(block) + visitor.visit_block(&visitor.thir()[*block]) } } } @@ -204,7 +211,7 @@ pub fn walk_arm<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, arm: &Arm<' pub fn walk_pat<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, pat: &Pat<'tcx>) { use PatKind::*; - match pat.kind.as_ref() { + match &pat.kind { AscribeUserType { subpattern, ascription: _ } | Deref { subpattern } | Binding { @@ -225,18 +232,18 @@ pub fn walk_pat<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, pat: &Pat<' Constant { value: _ } => {} Range(_) => {} Slice { prefix, slice, suffix } | Array { prefix, slice, suffix } => { - for subpattern in prefix { + for subpattern in prefix.iter() { visitor.visit_pat(&subpattern); } if let Some(pat) = slice { - visitor.visit_pat(pat); + visitor.visit_pat(&pat); } - for subpattern in suffix { + for subpattern in suffix.iter() { visitor.visit_pat(&subpattern); } } Or { pats } => { - for pat in pats { + for pat in pats.iter() { visitor.visit_pat(&pat); } } |