Auto merge of #100944 - nnethercote:shrink-thir-Expr, r=cjgillot

Shrink `thir::Expr`

r? `@cjgillot`
This commit is contained in:
bors 2022-08-26 10:00:27 +00:00
commit 8a13871b69
15 changed files with 191 additions and 150 deletions

View file

@ -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_middle::ty::{self, AdtDef, Ty, UpvarSubsts};
use rustc_middle::ty::{CanonicalUserType, CanonicalUserTypeAnnotation};
use rustc_span::def_id::LocalDefId;
use rustc_span::{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`]).
@ -91,9 +74,10 @@ macro_rules! thir_with_elements {
}
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{}",
}
#[derive(Copy, Clone, Debug, HashStable)]
@ -121,8 +105,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 +117,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,
@ -183,7 +186,7 @@ pub enum StmtKind<'tcx> {
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,
@ -307,7 +310,7 @@ pub enum ExprKind<'tcx> {
},
/// A block.
Block {
body: Block,
block: BlockId,
},
/// An assignment: `lhs = rhs`.
Assign {
@ -387,27 +390,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 +413,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 +440,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.
@ -815,7 +807,10 @@ mod size_asserts {
use super::*;
// These are in alphabetical order, which is easy to maintain.
static_assert_size!(Block, 56);
static_assert_size!(Expr<'_>, 104);
static_assert_size!(Expr<'_>, 64);
static_assert_size!(ExprKind<'_>, 40);
static_assert_size!(Pat<'_>, 24);
static_assert_size!(Stmt<'_>, 120);
static_assert_size!(PatKind<'_>, 112);
static_assert_size!(Stmt<'_>, 72);
static_assert_size!(StmtKind<'_>, 64);
}

View file

@ -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])
}
}
}

View file

@ -11,7 +11,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
&mut self,
destination: Place<'tcx>,
block: BasicBlock,
ast_block: &Block,
ast_block: BlockId,
source_info: SourceInfo,
) -> BlockAnd<()> {
let Block {
@ -22,7 +22,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
expr,
targeted_by_break,
safety_mode,
} = *ast_block;
} = self.thir[ast_block];
let expr = expr.map(|expr| &self.thir[expr]);
self.in_opt_scope(opt_destruction_scope.map(|de| (de, source_info)), move |this| {
this.in_scope((region_scope, source_info), LintLevel::Inherited, move |this| {
@ -146,7 +146,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
block,
init,
initializer_span,
else_block,
*else_block,
visibility_scope,
last_remainder_scope,
remainder_span,

View file

@ -41,11 +41,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
Constant { span, user_ty: None, literal }
}
ExprKind::NonHirLiteral { lit, user_ty } => {
let user_ty = user_ty.map(|user_ty| {
ExprKind::NonHirLiteral { lit, ref user_ty } => {
let user_ty = user_ty.as_ref().map(|box user_ty| {
this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
span,
user_ty,
user_ty: *user_ty,
inferred_ty: ty,
})
});
@ -53,11 +53,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
Constant { span, user_ty: user_ty, literal }
}
ExprKind::ZstLiteral { user_ty } => {
let user_ty = user_ty.map(|user_ty| {
ExprKind::ZstLiteral { ref user_ty } => {
let user_ty = user_ty.as_ref().map(|box user_ty| {
this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
span,
user_ty,
user_ty: *user_ty,
inferred_ty: ty,
})
});
@ -65,11 +65,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
Constant { span, user_ty: user_ty, literal }
}
ExprKind::NamedConst { def_id, substs, user_ty } => {
let user_ty = user_ty.map(|user_ty| {
ExprKind::NamedConst { def_id, substs, ref user_ty } => {
let user_ty = user_ty.as_ref().map(|box user_ty| {
this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
span,
user_ty,
user_ty: *user_ty,
inferred_ty: ty,
})
});

View file

@ -513,7 +513,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
block.and(place_builder)
}
ExprKind::PlaceTypeAscription { source, user_ty } => {
ExprKind::PlaceTypeAscription { source, ref user_ty } => {
let place_builder = unpack!(
block = this.expr_as_place(
block,
@ -522,11 +522,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
fake_borrow_temps,
)
);
if let Some(user_ty) = user_ty {
if let Some(box user_ty) = user_ty {
let annotation_index =
this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
span: source_info.span,
user_ty,
user_ty: *user_ty,
inferred_ty: expr.ty,
});
@ -547,15 +547,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
block.and(place_builder)
}
ExprKind::ValueTypeAscription { source, user_ty } => {
ExprKind::ValueTypeAscription { source, ref user_ty } => {
let source = &this.thir[source];
let temp =
unpack!(block = this.as_temp(block, source.temp_lifetime, source, mutability));
if let Some(user_ty) = user_ty {
if let Some(box user_ty) = user_ty {
let annotation_index =
this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
span: source_info.span,
user_ty,
user_ty: *user_ty,
inferred_ty: expr.ty,
});
this.cfg.push(

View file

@ -302,7 +302,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
block.and(Rvalue::Aggregate(Box::new(AggregateKind::Tuple), fields))
}
ExprKind::Closure { closure_id, substs, ref upvars, movability, ref fake_reads } => {
ExprKind::Closure(box ClosureExpr {
closure_id,
substs,
ref upvars,
movability,
ref fake_reads,
}) => {
// Convert the closure fake reads, if any, from `ExprRef` to mir `Place`
// and push the fake reads.
// This must come before creating the operands. This is required in case

View file

@ -83,8 +83,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// Don't bother with StorageLive and Dead for these temporaries,
// they are never assigned.
ExprKind::Break { .. } | ExprKind::Continue { .. } | ExprKind::Return { .. } => (),
ExprKind::Block { body: Block { expr: None, targeted_by_break: false, .. } }
if expr_ty.is_never() => {}
ExprKind::Block { block }
if let Block { expr: None, targeted_by_break: false, .. } = this.thir[block]
&& expr_ty.is_never() => {}
_ => {
this.cfg
.push(block, Statement { source_info, kind: StatementKind::StorageLive(temp) });

View file

@ -46,7 +46,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
})
})
}
ExprKind::Block { body: ref ast_block } => {
ExprKind::Block { block: ast_block } => {
this.ast_block(destination, block, ast_block, source_info)
}
ExprKind::Match { scrutinee, ref arms } => {
@ -314,11 +314,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
this.cfg.push_assign(block, source_info, destination, address_of);
block.unit()
}
ExprKind::Adt(box Adt {
ExprKind::Adt(box AdtExpr {
adt_def,
variant_index,
substs,
user_ty,
ref user_ty,
ref fields,
ref base,
}) => {
@ -378,10 +378,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
};
let inferred_ty = expr.ty;
let user_ty = user_ty.map(|ty| {
let user_ty = user_ty.as_ref().map(|box user_ty| {
this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
span: source_info.span,
user_ty: ty,
user_ty: *user_ty,
inferred_ty,
})
});
@ -400,7 +400,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
);
block.unit()
}
ExprKind::InlineAsm { template, ref operands, options, line_spans } => {
ExprKind::InlineAsm(box InlineAsmExpr {
template,
ref operands,
options,
line_spans,
}) => {
use rustc_middle::{mir, thir};
let operands = operands
.into_iter()

View file

@ -116,14 +116,22 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// it is usually better to focus on `the_value` rather
// than the entirety of block(s) surrounding it.
let adjusted_span = (|| {
if let ExprKind::Block { body } = &expr.kind && let Some(tail_ex) = body.expr {
if let ExprKind::Block { block } = expr.kind
&& let Some(tail_ex) = this.thir[block].expr
{
let mut expr = &this.thir[tail_ex];
while let ExprKind::Block {
body: Block { expr: Some(nested_expr), .. },
}
| ExprKind::Scope { value: nested_expr, .. } = expr.kind
{
expr = &this.thir[nested_expr];
loop {
match expr.kind {
ExprKind::Block { block }
if let Some(nested_expr) = this.thir[block].expr =>
{
expr = &this.thir[nested_expr];
}
ExprKind::Scope { value: nested_expr, .. } => {
expr = &this.thir[nested_expr];
}
_ => break,
}
}
this.block_context.push(BlockFrame::TailExpr {
tail_result_is_ignored: true,

View file

@ -2280,15 +2280,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
mut block: BasicBlock,
init: &Expr<'tcx>,
initializer_span: Span,
else_block: &Block,
else_block: BlockId,
visibility_scope: Option<SourceScope>,
remainder_scope: region::Scope,
remainder_span: Span,
pattern: &Pat<'tcx>,
) -> BlockAnd<()> {
let else_block_span = self.thir[else_block].span;
let (matching, failure) = self.in_if_then_scope(remainder_scope, |this| {
let scrutinee = unpack!(block = this.lower_scrutinee(block, init, initializer_span));
let pat = Pat { ty: init.ty, span: else_block.span, kind: Box::new(PatKind::Wild) };
let pat = Pat { ty: init.ty, span: else_block_span, kind: Box::new(PatKind::Wild) };
let mut wildcard = Candidate::new(scrutinee.clone(), &pat, false);
this.declare_bindings(
visibility_scope,
@ -2318,7 +2319,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
);
// This block is for the failure case
let failure = this.bind_pattern(
this.source_info(else_block.span),
this.source_info(else_block_span),
wildcard,
None,
&fake_borrow_temps,
@ -2334,19 +2335,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// This place is not really used because this destination place
// should never be used to take values at the end of the failure
// block.
let dummy_place = self.temp(self.tcx.types.never, else_block.span);
let dummy_place = self.temp(self.tcx.types.never, else_block_span);
let failure_block;
unpack!(
failure_block = self.ast_block(
dummy_place,
failure,
else_block,
self.source_info(else_block.span),
self.source_info(else_block_span),
)
);
self.cfg.terminate(
failure_block,
self.source_info(else_block.span),
self.source_info(else_block_span),
TerminatorKind::Unreachable,
);
matching.unit()

View file

@ -391,7 +391,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
ExprKind::InlineAsm { .. } => {
self.requires_unsafe(expr.span, UseOfInlineAssembly);
}
ExprKind::Adt(box Adt {
ExprKind::Adt(box AdtExpr {
adt_def,
variant_index: _,
substs: _,
@ -402,13 +402,13 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
(Bound::Unbounded, Bound::Unbounded) => {}
_ => self.requires_unsafe(expr.span, InitializingTypeWith),
},
ExprKind::Closure {
ExprKind::Closure(box ClosureExpr {
closure_id,
substs: _,
upvars: _,
movability: _,
fake_reads: _,
} => {
}) => {
let closure_def = if let Some((did, const_param_id)) =
ty::WithOptConstParam::try_lookup(closure_id, self.tcx)
{

View file

@ -9,13 +9,13 @@ use rustc_index::vec::Idx;
use rustc_middle::ty::CanonicalUserTypeAnnotation;
impl<'tcx> Cx<'tcx> {
pub(crate) fn mirror_block(&mut self, block: &'tcx hir::Block<'tcx>) -> Block {
pub(crate) fn mirror_block(&mut self, block: &'tcx hir::Block<'tcx>) -> BlockId {
// We have to eagerly lower the "spine" of the statements
// in order to get the lexical scoping correctly.
let stmts = self.mirror_stmts(block.hir_id.local_id, block.stmts);
let opt_destruction_scope =
self.region_scope_tree.opt_destruction_scope(block.hir_id.local_id);
Block {
let block = Block {
targeted_by_break: block.targeted_by_break,
region_scope: region::Scope {
id: block.hir_id.local_id,
@ -34,7 +34,9 @@ impl<'tcx> Cx<'tcx> {
BlockSafety::ExplicitUnsafe(block.hir_id)
}
},
}
};
self.thir.blocks.push(block)
}
fn mirror_stmts(

View file

@ -108,8 +108,8 @@ impl<'tcx> Cx<'tcx> {
// // ^ error message points at this expression.
// }
let mut adjust_span = |expr: &mut Expr<'tcx>| {
if let ExprKind::Block { body } = &expr.kind {
if let Some(last_expr) = body.expr {
if let ExprKind::Block { block } = expr.kind {
if let Some(last_expr) = self.thir[block].expr {
span = self.thir[last_expr].span;
expr.span = span;
}
@ -329,7 +329,7 @@ impl<'tcx> Cx<'tcx> {
if let UserType::TypeOf(ref mut did, _) = &mut u_ty.value {
*did = adt_def.did();
}
u_ty
Box::new(u_ty)
});
debug!("make_mirror_unadjusted: (call) user_ty={:?}", user_ty);
@ -341,7 +341,7 @@ impl<'tcx> Cx<'tcx> {
expr: self.mirror_expr(e),
})
.collect();
ExprKind::Adt(Box::new(Adt {
ExprKind::Adt(Box::new(AdtExpr {
adt_def,
substs,
variant_index: index,
@ -369,7 +369,7 @@ impl<'tcx> Cx<'tcx> {
ExprKind::AddressOf { mutability, arg: self.mirror_expr(arg) }
}
hir::ExprKind::Block(ref blk, _) => ExprKind::Block { body: self.mirror_block(blk) },
hir::ExprKind::Block(ref blk, _) => ExprKind::Block { block: self.mirror_block(blk) },
hir::ExprKind::Assign(ref lhs, ref rhs, _) => {
ExprKind::Assign { lhs: self.mirror_expr(lhs), rhs: self.mirror_expr(rhs) }
@ -464,9 +464,9 @@ impl<'tcx> Cx<'tcx> {
ty::Adt(adt, substs) => match adt.adt_kind() {
AdtKind::Struct | AdtKind::Union => {
let user_provided_types = self.typeck_results().user_provided_types();
let user_ty = user_provided_types.get(expr.hir_id).copied();
let user_ty = user_provided_types.get(expr.hir_id).copied().map(Box::new);
debug!("make_mirror_unadjusted: (struct/union) user_ty={:?}", user_ty);
ExprKind::Adt(Box::new(Adt {
ExprKind::Adt(Box::new(AdtExpr {
adt_def: *adt,
variant_index: VariantIdx::new(0),
substs,
@ -490,9 +490,10 @@ impl<'tcx> Cx<'tcx> {
let index = adt.variant_index_with_id(variant_id);
let user_provided_types =
self.typeck_results().user_provided_types();
let user_ty = user_provided_types.get(expr.hir_id).copied();
let user_ty =
user_provided_types.get(expr.hir_id).copied().map(Box::new);
debug!("make_mirror_unadjusted: (variant) user_ty={:?}", user_ty);
ExprKind::Adt(Box::new(Adt {
ExprKind::Adt(Box::new(AdtExpr {
adt_def: *adt,
variant_index: index,
substs,
@ -547,7 +548,13 @@ impl<'tcx> Cx<'tcx> {
None => Vec::new(),
};
ExprKind::Closure { closure_id: def_id, substs, upvars, movability, fake_reads }
ExprKind::Closure(Box::new(ClosureExpr {
closure_id: def_id,
substs,
upvars,
movability,
fake_reads,
}))
}
hir::ExprKind::Path(ref qpath) => {
@ -555,7 +562,7 @@ impl<'tcx> Cx<'tcx> {
self.convert_path_expr(expr, res)
}
hir::ExprKind::InlineAsm(ref asm) => ExprKind::InlineAsm {
hir::ExprKind::InlineAsm(ref asm) => ExprKind::InlineAsm(Box::new(InlineAsmExpr {
template: asm.template,
operands: asm
.operands
@ -614,7 +621,7 @@ impl<'tcx> Cx<'tcx> {
.collect(),
options: asm.options,
line_spans: asm.line_spans,
},
})),
hir::ExprKind::ConstBlock(ref anon_const) => {
let ty = self.typeck_results().node_type(anon_const.hir_id);
@ -679,8 +686,8 @@ impl<'tcx> Cx<'tcx> {
let body = self.thir.exprs.push(Expr {
ty: block_ty,
temp_lifetime,
span: block.span,
kind: ExprKind::Block { body: block },
span: self.thir[block].span,
kind: ExprKind::Block { block },
});
ExprKind::Loop { body }
}
@ -712,14 +719,17 @@ impl<'tcx> Cx<'tcx> {
});
debug!("make_mirror_unadjusted: (cast) user_ty={:?}", user_ty);
ExprKind::ValueTypeAscription { source: cast_expr, user_ty: Some(*user_ty) }
ExprKind::ValueTypeAscription {
source: cast_expr,
user_ty: Some(Box::new(*user_ty)),
}
} else {
cast
}
}
hir::ExprKind::Type(ref source, ref ty) => {
let user_provided_types = self.typeck_results.user_provided_types();
let user_ty = user_provided_types.get(ty.hir_id).copied();
let user_ty = user_provided_types.get(ty.hir_id).copied().map(Box::new);
debug!("make_mirror_unadjusted: (type) user_ty={:?}", user_ty);
let mirrored = self.mirror_expr(source);
if source.is_syntactic_place_expr() {
@ -748,7 +758,7 @@ impl<'tcx> Cx<'tcx> {
&mut self,
hir_id: hir::HirId,
res: Res,
) -> Option<ty::CanonicalUserType<'tcx>> {
) -> Option<Box<ty::CanonicalUserType<'tcx>>> {
debug!("user_substs_applied_to_res: res={:?}", res);
let user_provided_type = match res {
// A reference to something callable -- e.g., a fn, method, or
@ -759,7 +769,7 @@ impl<'tcx> Cx<'tcx> {
| Res::Def(DefKind::Ctor(_, CtorKind::Fn), _)
| Res::Def(DefKind::Const, _)
| Res::Def(DefKind::AssocConst, _) => {
self.typeck_results().user_provided_types().get(hir_id).copied()
self.typeck_results().user_provided_types().get(hir_id).copied().map(Box::new)
}
// A unit struct/variant which is used as a value (e.g.,
@ -767,11 +777,11 @@ impl<'tcx> Cx<'tcx> {
// this variant -- but with the substitutions given by the
// user.
Res::Def(DefKind::Ctor(_, CtorKind::Const), _) => {
self.user_substs_applied_to_ty_of_hir_id(hir_id)
self.user_substs_applied_to_ty_of_hir_id(hir_id).map(Box::new)
}
// `Self` is used in expression as a tuple struct constructor or a unit struct constructor
Res::SelfCtor(_) => self.user_substs_applied_to_ty_of_hir_id(hir_id),
Res::SelfCtor(_) => self.user_substs_applied_to_ty_of_hir_id(hir_id).map(Box::new),
_ => bug!("user_substs_applied_to_res: unexpected res {:?} at {:?}", res, hir_id),
};
@ -846,22 +856,22 @@ impl<'tcx> Cx<'tcx> {
Res::Def(DefKind::Const, def_id) | Res::Def(DefKind::AssocConst, def_id) => {
let user_ty = self.user_substs_applied_to_res(expr.hir_id, res);
ExprKind::NamedConst { def_id, substs, user_ty: user_ty }
ExprKind::NamedConst { def_id, substs, user_ty }
}
Res::Def(DefKind::Ctor(_, CtorKind::Const), def_id) => {
let user_provided_types = self.typeck_results.user_provided_types();
let user_provided_type = user_provided_types.get(expr.hir_id).copied();
debug!("convert_path_expr: user_provided_type={:?}", user_provided_type);
let user_ty = user_provided_types.get(expr.hir_id).copied().map(Box::new);
debug!("convert_path_expr: user_ty={:?}", user_ty);
let ty = self.typeck_results().node_type(expr.hir_id);
match ty.kind() {
// A unit struct/variant which is used as a value.
// We return a completely different ExprKind here to account for this special case.
ty::Adt(adt_def, substs) => ExprKind::Adt(Box::new(Adt {
ty::Adt(adt_def, substs) => ExprKind::Adt(Box::new(AdtExpr {
adt_def: *adt_def,
variant_index: adt_def.variant_index_with_ctor_id(def_id),
substs,
user_ty: user_provided_type,
user_ty,
fields: Box::new([]),
base: None,
})),

View file

@ -311,8 +311,15 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
// bar::<{ N + 1 }>();
// }
// ```
ExprKind::Block { body: thir::Block { stmts: box [], expr: Some(e), .. } } => {
self.recurse_build(*e)?
ExprKind::Block { block } => {
if let thir::Block { stmts: box [], expr: Some(e), .. } = &self.body.blocks[*block] {
self.recurse_build(*e)?
} else {
self.maybe_supported_error(
node.span,
"blocks are not supported in generic constant",
)?
}
}
// `ExprKind::Use` happens when a `hir::ExprKind::Cast` is a
// "coercion cast" i.e. using a coercion or is a no-op.
@ -349,10 +356,6 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
node.span,
"array construction is not supported in generic constants",
)?,
ExprKind::Block { .. } => self.maybe_supported_error(
node.span,
"blocks are not supported in generic constant",
)?,
ExprKind::NeverToAny { .. } => self.maybe_supported_error(
node.span,
"converting nevers to any is not supported in generic constant",

View file

@ -1,6 +1,17 @@
DefId(0:3 ~ thir_tree[8f1d]::main):
Thir {
arms: [],
blocks: [
Block {
targeted_by_break: false,
region_scope: Node(1),
opt_destruction_scope: None,
span: $DIR/thir-tree.rs:4:15: 4:17 (#0),
stmts: [],
expr: None,
safety_mode: Safe,
},
],
exprs: [
Expr {
ty: (),
@ -9,15 +20,7 @@ Thir {
),
span: $DIR/thir-tree.rs:4:15: 4:17 (#0),
kind: Block {
body: Block {
targeted_by_break: false,
region_scope: Node(1),
opt_destruction_scope: None,
span: $DIR/thir-tree.rs:4:15: 4:17 (#0),
stmts: [],
expr: None,
safety_mode: Safe,
},
block: b0,
},
},
Expr {