summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_mir_build/src/build/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_mir_build/src/build/mod.rs')
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs196
1 files changed, 86 insertions, 110 deletions
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index 9daf68a15..b3f9d8282 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -20,7 +20,7 @@ use rustc_middle::mir::*;
use rustc_middle::thir::{
self, BindingMode, Expr, ExprId, LintLevel, LocalVarId, Param, ParamId, PatKind, Thir,
};
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable, TypeckResults};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
use rustc_span::symbol::sym;
use rustc_span::Span;
use rustc_span::Symbol;
@@ -47,8 +47,6 @@ pub(crate) fn mir_built(
/// Construct the MIR for a given `DefId`.
fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_> {
- let body_owner_kind = tcx.hir().body_owner_kind(def.did);
-
// Ensure unsafeck and abstract const building is ran before we steal the THIR.
// We can't use `ensure()` for `thir_abstract_const` as it doesn't compute the query
// if inputs are green. This can cause ICEs when calling `thir_abstract_const` after
@@ -65,16 +63,15 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_
}
let body = match tcx.thir_body(def) {
- Err(error_reported) => construct_error(tcx, def.did, body_owner_kind, error_reported),
+ Err(error_reported) => construct_error(tcx, def.did, error_reported),
Ok((thir, expr)) => {
// We ran all queries that depended on THIR at the beginning
// of `mir_build`, so now we can steal it
let thir = thir.steal();
- if body_owner_kind.is_fn_or_closure() {
- construct_fn(tcx, def, &thir, expr)
- } else {
- construct_const(tcx, def, &thir, expr)
+ match thir.body_type {
+ thir::BodyTy::Fn(fn_sig) => construct_fn(tcx, def, &thir, expr, fn_sig),
+ thir::BodyTy::Const(ty) => construct_const(tcx, def, &thir, expr, ty),
}
}
};
@@ -158,13 +155,13 @@ struct BlockContext(Vec<BlockFrame>);
struct Builder<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
infcx: InferCtxt<'tcx>,
- typeck_results: &'tcx TypeckResults<'tcx>,
region_scope_tree: &'tcx region::ScopeTree,
param_env: ty::ParamEnv<'tcx>,
thir: &'a Thir<'tcx>,
cfg: CFG<'tcx>,
+ def: ty::WithOptConstParam<LocalDefId>,
def_id: DefId,
hir_id: hir::HirId,
parent_module: DefId,
@@ -434,11 +431,16 @@ fn construct_fn<'tcx>(
fn_def: ty::WithOptConstParam<LocalDefId>,
thir: &Thir<'tcx>,
expr: ExprId,
+ fn_sig: ty::FnSig<'tcx>,
) -> Body<'tcx> {
let span = tcx.def_span(fn_def.did);
let fn_id = tcx.hir().local_def_id_to_hir_id(fn_def.did);
let generator_kind = tcx.generator_kind(fn_def.did);
+ // The representation of thir for `-Zunpretty=thir-tree` relies on
+ // the entry expression being the last element of `thir.exprs`.
+ assert_eq!(expr.as_usize(), thir.exprs.len() - 1);
+
// Figure out what primary body this item has.
let body_id = tcx.hir().body_owned_by(fn_def.did);
let span_with_body = tcx.hir().span_with_body(fn_id);
@@ -449,11 +451,6 @@ fn construct_fn<'tcx>(
.output
.span();
- // fetch the fully liberated fn signature (that is, all bound
- // types/lifetimes replaced)
- let typeck_results = tcx.typeck_opt_const_arg(fn_def);
- let fn_sig = typeck_results.liberated_fn_sigs()[fn_id];
-
let safety = match fn_sig.unsafety {
hir::Unsafety::Normal => Safety::Safe,
hir::Unsafety::Unsafe => Safety::FnUnsafe,
@@ -525,13 +522,7 @@ fn construct_fn<'tcx>(
let return_block =
unpack!(builder.in_breakable_scope(None, Place::return_place(), fn_end, |builder| {
Some(builder.in_scope(arg_scope_s, LintLevel::Inherited, |builder| {
- builder.args_and_body(
- START_BLOCK,
- fn_def.did,
- arguments,
- arg_scope,
- &thir[expr],
- )
+ builder.args_and_body(START_BLOCK, arguments, arg_scope, &thir[expr])
}))
}));
let source_info = builder.source_info(fn_end);
@@ -559,6 +550,7 @@ fn construct_const<'a, 'tcx>(
def: ty::WithOptConstParam<LocalDefId>,
thir: &'a Thir<'tcx>,
expr: ExprId,
+ const_ty: Ty<'tcx>,
) -> Body<'tcx> {
let hir_id = tcx.hir().local_def_id_to_hir_id(def.did);
@@ -582,20 +574,6 @@ fn construct_const<'a, 'tcx>(
_ => span_bug!(tcx.def_span(def.did), "can't build MIR for {:?}", def.did),
};
- // Get the revealed type of this const. This is *not* the adjusted
- // type of its body, which may be a subtype of this type. For
- // example:
- //
- // fn foo(_: &()) {}
- // static X: fn(&'static ()) = foo;
- //
- // The adjusted type of the body of X is `for<'a> fn(&'a ())` which
- // is not the same as the type of X. We need the type of the return
- // place to be the type of the constant because NLL typeck will
- // equate them.
- let typeck_results = tcx.typeck_opt_const_arg(def);
- let const_ty = typeck_results.node_type(hir_id);
-
let infcx = tcx.infer_ctxt().build();
let mut builder = Builder::new(
thir,
@@ -625,21 +603,17 @@ fn construct_const<'a, 'tcx>(
///
/// This is required because we may still want to run MIR passes on an item
/// with type errors, but normal MIR construction can't handle that in general.
-fn construct_error(
- tcx: TyCtxt<'_>,
- def: LocalDefId,
- body_owner_kind: hir::BodyOwnerKind,
- err: ErrorGuaranteed,
-) -> Body<'_> {
+fn construct_error(tcx: TyCtxt<'_>, def: LocalDefId, err: ErrorGuaranteed) -> Body<'_> {
let span = tcx.def_span(def);
let hir_id = tcx.hir().local_def_id_to_hir_id(def);
let generator_kind = tcx.generator_kind(def);
+ let body_owner_kind = tcx.hir().body_owner_kind(def);
- let ty = tcx.ty_error();
+ let ty = tcx.ty_error(err);
let num_params = match body_owner_kind {
- hir::BodyOwnerKind::Fn => tcx.fn_sig(def).inputs().skip_binder().len(),
+ hir::BodyOwnerKind::Fn => tcx.fn_sig(def).skip_binder().inputs().skip_binder().len(),
hir::BodyOwnerKind::Closure => {
- let ty = tcx.type_of(def);
+ let ty = tcx.type_of(def).subst_identity();
match ty.kind() {
ty::Closure(_, substs) => {
1 + substs.as_closure().sig().inputs().skip_binder().len()
@@ -724,9 +698,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
thir,
tcx,
infcx,
- typeck_results: tcx.typeck_opt_const_arg(def),
region_scope_tree: tcx.region_scope_tree(def.did),
param_env,
+ def,
def_id: def.did.to_def_id(),
hir_id,
parent_module: tcx.parent_module(hir_id).to_def_id(),
@@ -776,14 +750,78 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
self.var_debug_info,
self.fn_span,
self.generator_kind,
- self.typeck_results.tainted_by_errors,
+ None,
)
}
+ fn insert_upvar_arg(&mut self) {
+ let Some(closure_arg) = self.local_decls.get(ty::CAPTURE_STRUCT_LOCAL) else { return };
+
+ let mut closure_ty = closure_arg.ty;
+ let mut closure_env_projs = vec![];
+ if let ty::Ref(_, ty, _) = closure_ty.kind() {
+ closure_env_projs.push(ProjectionElem::Deref);
+ closure_ty = *ty;
+ }
+
+ let upvar_substs = match closure_ty.kind() {
+ ty::Closure(_, substs) => ty::UpvarSubsts::Closure(substs),
+ ty::Generator(_, substs, _) => ty::UpvarSubsts::Generator(substs),
+ _ => return,
+ };
+
+ // In analyze_closure() in upvar.rs we gathered a list of upvars used by an
+ // indexed closure and we stored in a map called closure_min_captures in TypeckResults
+ // with the closure's DefId. Here, we run through that vec of UpvarIds for
+ // the given closure and use the necessary information to create upvar
+ // debuginfo and to fill `self.upvars`.
+ let capture_tys = upvar_substs.upvar_tys();
+
+ let tcx = self.tcx;
+ self.upvars = tcx
+ .closure_captures(self.def.did)
+ .iter()
+ .zip(capture_tys)
+ .enumerate()
+ .map(|(i, (captured_place, ty))| {
+ let name = captured_place.to_symbol();
+
+ let capture = captured_place.info.capture_kind;
+ let var_id = match captured_place.place.base {
+ HirPlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id,
+ _ => bug!("Expected an upvar"),
+ };
+
+ let mutability = captured_place.mutability;
+
+ let mut projs = closure_env_projs.clone();
+ projs.push(ProjectionElem::Field(Field::new(i), ty));
+ match capture {
+ ty::UpvarCapture::ByValue => {}
+ ty::UpvarCapture::ByRef(..) => {
+ projs.push(ProjectionElem::Deref);
+ }
+ };
+
+ let use_place = Place {
+ local: ty::CAPTURE_STRUCT_LOCAL,
+ projection: tcx.mk_place_elems(&projs),
+ };
+ self.var_debug_info.push(VarDebugInfo {
+ name,
+ source_info: SourceInfo::outermost(captured_place.var_ident.span),
+ value: VarDebugInfoContents::Place(use_place),
+ });
+
+ let capture = Capture { captured_place, use_place, mutability };
+ (var_id, capture)
+ })
+ .collect();
+ }
+
fn args_and_body(
&mut self,
mut block: BasicBlock,
- fn_def_id: LocalDefId,
arguments: &IndexVec<ParamId, Param<'tcx>>,
argument_scope: region::Scope,
expr: &Expr<'tcx>,
@@ -805,69 +843,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
}
- let tcx = self.tcx;
- let tcx_hir = tcx.hir();
- let hir_typeck_results = self.typeck_results;
-
- // In analyze_closure() in upvar.rs we gathered a list of upvars used by an
- // indexed closure and we stored in a map called closure_min_captures in TypeckResults
- // with the closure's DefId. Here, we run through that vec of UpvarIds for
- // the given closure and use the necessary information to create upvar
- // debuginfo and to fill `self.upvars`.
- if hir_typeck_results.closure_min_captures.get(&fn_def_id).is_some() {
- let mut closure_env_projs = vec![];
- let mut closure_ty = self.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty;
- if let ty::Ref(_, ty, _) = closure_ty.kind() {
- closure_env_projs.push(ProjectionElem::Deref);
- closure_ty = *ty;
- }
- let upvar_substs = match closure_ty.kind() {
- ty::Closure(_, substs) => ty::UpvarSubsts::Closure(substs),
- ty::Generator(_, substs, _) => ty::UpvarSubsts::Generator(substs),
- _ => span_bug!(self.fn_span, "upvars with non-closure env ty {:?}", closure_ty),
- };
- let def_id = self.def_id.as_local().unwrap();
- let capture_syms = tcx.symbols_for_closure_captures((def_id, fn_def_id));
- let capture_tys = upvar_substs.upvar_tys();
- let captures_with_tys = hir_typeck_results
- .closure_min_captures_flattened(fn_def_id)
- .zip(capture_tys.zip(capture_syms));
-
- self.upvars = captures_with_tys
- .enumerate()
- .map(|(i, (captured_place, (ty, sym)))| {
- let capture = captured_place.info.capture_kind;
- let var_id = match captured_place.place.base {
- HirPlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id,
- _ => bug!("Expected an upvar"),
- };
-
- let mutability = captured_place.mutability;
-
- let mut projs = closure_env_projs.clone();
- projs.push(ProjectionElem::Field(Field::new(i), ty));
- match capture {
- ty::UpvarCapture::ByValue => {}
- ty::UpvarCapture::ByRef(..) => {
- projs.push(ProjectionElem::Deref);
- }
- };
-
- let use_place = Place {
- local: ty::CAPTURE_STRUCT_LOCAL,
- projection: tcx.intern_place_elems(&projs),
- };
- self.var_debug_info.push(VarDebugInfo {
- name: *sym,
- source_info: SourceInfo::outermost(tcx_hir.span(var_id)),
- value: VarDebugInfoContents::Place(use_place),
- });
-
- let capture = Capture { captured_place, use_place, mutability };
- (var_id, capture)
- })
- .collect();
- }
+ self.insert_upvar_arg();
let mut scope = None;
// Bind the argument patterns