diff options
Diffstat (limited to 'compiler/rustc_mir_build/src/thir/cx')
-rw-r--r-- | compiler/rustc_mir_build/src/thir/cx/block.rs | 18 | ||||
-rw-r--r-- | compiler/rustc_mir_build/src/thir/cx/expr.rs | 72 | ||||
-rw-r--r-- | compiler/rustc_mir_build/src/thir/cx/mod.rs | 116 |
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> { |