summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_mir_build/src/thir/cx
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_mir_build/src/thir/cx')
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/block.rs18
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/expr.rs72
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/mod.rs116
3 files changed, 162 insertions, 44 deletions
diff --git a/compiler/rustc_mir_build/src/thir/cx/block.rs b/compiler/rustc_mir_build/src/thir/cx/block.rs
index dccaa61ed..321353ca2 100644
--- a/compiler/rustc_mir_build/src/thir/cx/block.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/block.rs
@@ -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(
@@ -85,21 +87,21 @@ impl<'tcx> Cx<'tcx> {
{
debug!("mirror_stmts: user_ty={:?}", user_ty);
let annotation = CanonicalUserTypeAnnotation {
- user_ty,
+ user_ty: Box::new(user_ty),
span: ty.span,
inferred_ty: self.typeck_results.node_type(ty.hir_id),
};
- pattern = Pat {
+ pattern = Box::new(Pat {
ty: pattern.ty,
span: pattern.span,
- kind: Box::new(PatKind::AscribeUserType {
+ kind: PatKind::AscribeUserType {
ascription: Ascription {
annotation,
variance: ty::Variance::Covariant,
},
subpattern: pattern,
- }),
- };
+ },
+ });
}
}
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index 985601712..d059877f8 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -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;
}
@@ -261,15 +261,19 @@ impl<'tcx> Cx<'tcx> {
let kind = match expr.kind {
// Here comes the interesting stuff:
- hir::ExprKind::MethodCall(segment, ref args, fn_span) => {
+ hir::ExprKind::MethodCall(segment, receiver, ref args, fn_span) => {
// Rewrite a.b(c) into UFCS form like Trait::b(a, c)
let expr = self.method_callee(expr, segment.ident.span, None);
// When we apply adjustments to the receiver, use the span of
// the overall method call for better diagnostics. args[0]
// is guaranteed to exist, since a method call always has a receiver.
- let old_adjustment_span = self.adjustment_span.replace((args[0].hir_id, expr_span));
- tracing::info!("Using method span: {:?}", expr.span);
- let args = self.mirror_exprs(args);
+ let old_adjustment_span =
+ self.adjustment_span.replace((receiver.hir_id, expr_span));
+ info!("Using method span: {:?}", expr.span);
+ let args = std::iter::once(receiver)
+ .chain(args.iter())
+ .map(|expr| self.mirror_expr(expr))
+ .collect();
self.adjustment_span = old_adjustment_span;
ExprKind::Call {
ty: expr.ty,
@@ -329,7 +333,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 +345,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 +373,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 +468,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 +494,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 +552,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 +566,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 +625,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 +690,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 +723,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 +762,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 +773,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 +781,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 +860,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,
})),
diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs
index f7351a4ca..3ef1b263f 100644
--- a/compiler/rustc_mir_build/src/thir/cx/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs
@@ -8,12 +8,14 @@ use crate::thir::util::UserAnnotatedTyHelpers;
use rustc_data_structures::steal::Steal;
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
+use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::lang_items::LangItem;
use rustc_hir::HirId;
use rustc_hir::Node;
use rustc_middle::middle::region;
use rustc_middle::thir::*;
-use rustc_middle::ty::{self, RvalueScopes, TyCtxt};
+use rustc_middle::ty::{self, RvalueScopes, Subst, TyCtxt};
use rustc_span::Span;
pub(crate) fn thir_body<'tcx>(
@@ -27,6 +29,26 @@ pub(crate) fn thir_body<'tcx>(
return Err(reported);
}
let expr = cx.mirror_expr(&body.value);
+
+ let owner_id = hir.local_def_id_to_hir_id(owner_def.did);
+ if let Some(ref fn_decl) = hir.fn_decl_by_hir_id(owner_id) {
+ let closure_env_param = cx.closure_env_param(owner_def.did, owner_id);
+ let explicit_params = cx.explicit_params(owner_id, fn_decl, body);
+ cx.thir.params = closure_env_param.into_iter().chain(explicit_params).collect();
+
+ // The resume argument may be missing, in that case we need to provide it here.
+ // It will always be `()` in this case.
+ if tcx.def_kind(owner_def.did) == DefKind::Generator && body.params.is_empty() {
+ cx.thir.params.push(Param {
+ ty: tcx.mk_unit(),
+ pat: None,
+ ty_span: None,
+ self_kind: None,
+ hir_id: None,
+ });
+ }
+ }
+
Ok((tcx.alloc_steal_thir(cx.thir), expr))
}
@@ -44,11 +66,11 @@ struct Cx<'tcx> {
tcx: TyCtxt<'tcx>,
thir: Thir<'tcx>,
- pub(crate) param_env: ty::ParamEnv<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
- pub(crate) region_scope_tree: &'tcx region::ScopeTree,
- pub(crate) typeck_results: &'tcx ty::TypeckResults<'tcx>,
- pub(crate) rvalue_scopes: &'tcx RvalueScopes,
+ region_scope_tree: &'tcx region::ScopeTree,
+ typeck_results: &'tcx ty::TypeckResults<'tcx>,
+ rvalue_scopes: &'tcx RvalueScopes,
/// When applying adjustments to the expression
/// with the given `HirId`, use the given `Span`,
@@ -77,14 +99,94 @@ impl<'tcx> Cx<'tcx> {
}
}
- #[tracing::instrument(level = "debug", skip(self))]
- pub(crate) fn pattern_from_hir(&mut self, p: &hir::Pat<'_>) -> Pat<'tcx> {
+ #[instrument(level = "debug", skip(self))]
+ fn pattern_from_hir(&mut self, p: &hir::Pat<'_>) -> Box<Pat<'tcx>> {
let p = match self.tcx.hir().get(p.hir_id) {
Node::Pat(p) => p,
node => bug!("pattern became {:?}", node),
};
pat_from_hir(self.tcx, self.param_env, self.typeck_results(), p)
}
+
+ fn closure_env_param(&self, owner_def: LocalDefId, owner_id: HirId) -> Option<Param<'tcx>> {
+ match self.tcx.def_kind(owner_def) {
+ DefKind::Closure => {
+ let closure_ty = self.typeck_results.node_type(owner_id);
+
+ let ty::Closure(closure_def_id, closure_substs) = *closure_ty.kind() else {
+ bug!("closure expr does not have closure type: {:?}", closure_ty);
+ };
+
+ let bound_vars = self.tcx.mk_bound_variable_kinds(std::iter::once(
+ ty::BoundVariableKind::Region(ty::BrEnv),
+ ));
+ let br = ty::BoundRegion {
+ var: ty::BoundVar::from_usize(bound_vars.len() - 1),
+ kind: ty::BrEnv,
+ };
+ let env_region = ty::ReLateBound(ty::INNERMOST, br);
+ let closure_env_ty =
+ self.tcx.closure_env_ty(closure_def_id, closure_substs, env_region).unwrap();
+ let liberated_closure_env_ty = self.tcx.erase_late_bound_regions(
+ ty::Binder::bind_with_vars(closure_env_ty, bound_vars),
+ );
+ let env_param = Param {
+ ty: liberated_closure_env_ty,
+ pat: None,
+ ty_span: None,
+ self_kind: None,
+ hir_id: None,
+ };
+
+ Some(env_param)
+ }
+ DefKind::Generator => {
+ let gen_ty = self.typeck_results.node_type(owner_id);
+ let gen_param =
+ Param { ty: gen_ty, pat: None, ty_span: None, self_kind: None, hir_id: None };
+ Some(gen_param)
+ }
+ _ => None,
+ }
+ }
+
+ fn explicit_params<'a>(
+ &'a mut self,
+ owner_id: HirId,
+ fn_decl: &'tcx hir::FnDecl<'tcx>,
+ body: &'tcx hir::Body<'tcx>,
+ ) -> impl Iterator<Item = Param<'tcx>> + 'a {
+ let fn_sig = self.typeck_results.liberated_fn_sigs()[owner_id];
+
+ body.params.iter().enumerate().map(move |(index, param)| {
+ let ty_span = fn_decl
+ .inputs
+ .get(index)
+ // Make sure that inferred closure args have no type span
+ .and_then(|ty| if param.pat.span != ty.span { Some(ty.span) } else { None });
+
+ let self_kind = if index == 0 && fn_decl.implicit_self.has_implicit_self() {
+ Some(fn_decl.implicit_self)
+ } else {
+ None
+ };
+
+ // C-variadic fns also have a `VaList` input that's not listed in `fn_sig`
+ // (as it's created inside the body itself, not passed in from outside).
+ let ty = if fn_decl.c_variadic && index == fn_decl.inputs.len() {
+ let va_list_did = self.tcx.require_lang_item(LangItem::VaList, Some(param.span));
+
+ self.tcx
+ .bound_type_of(va_list_did)
+ .subst(self.tcx, &[self.tcx.lifetimes.re_erased.into()])
+ } else {
+ fn_sig.inputs()[index]
+ };
+
+ let pat = self.pattern_from_hir(param.pat);
+ Param { pat: Some(pat), ty, ty_span, self_kind, hir_id: Some(param.hir_id) }
+ })
+ }
}
impl<'tcx> UserAnnotatedTyHelpers<'tcx> for Cx<'tcx> {