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.rs140
1 files changed, 83 insertions, 57 deletions
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index bba470564..886d80545 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -9,7 +9,7 @@ use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::{GeneratorKind, Node};
+use rustc_hir::{CoroutineKind, Node};
use rustc_index::bit_set::GrowableBitSet;
use rustc_index::{Idx, IndexSlice, IndexVec};
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
@@ -53,10 +53,7 @@ pub(crate) fn closure_saved_names_of_captured_variables<'tcx>(
}
/// Construct the MIR for a given `DefId`.
-fn mir_build(tcx: TyCtxt<'_>, def: LocalDefId) -> Body<'_> {
- // Ensure unsafeck and abstract const building is ran before we steal the THIR.
- tcx.ensure_with_value()
- .thir_check_unsafety(tcx.typeck_root_def_id(def.to_def_id()).expect_local());
+fn mir_build<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Body<'tcx> {
tcx.ensure_with_value().thir_abstract_const(def);
if let Err(e) = tcx.check_match(def) {
return construct_error(tcx, def, e);
@@ -65,20 +62,27 @@ fn mir_build(tcx: TyCtxt<'_>, def: LocalDefId) -> Body<'_> {
let body = match tcx.thir_body(def) {
Err(error_reported) => construct_error(tcx, def, 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();
+ let build_mir = |thir: &Thir<'tcx>| 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),
+ };
- tcx.ensure().check_match(def);
// this must run before MIR dump, because
// "not all control paths return a value" is reported here.
//
// maybe move the check to a MIR pass?
tcx.ensure().check_liveness(def);
- 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),
+ if tcx.sess.opts.unstable_opts.thir_unsafeck {
+ // Don't steal here if THIR unsafeck is being used. Instead
+ // steal in unsafeck. This is so that pattern inline constants
+ // can be evaluated as part of building the THIR of the parent
+ // function without a cycle.
+ build_mir(&thir.borrow())
+ } else {
+ // We ran all queries that depended on THIR at the beginning
+ // of `mir_build`, so now we can steal it
+ build_mir(&thir.steal())
}
}
};
@@ -173,7 +177,7 @@ struct Builder<'a, 'tcx> {
check_overflow: bool,
fn_span: Span,
arg_count: usize,
- generator_kind: Option<GeneratorKind>,
+ coroutine_kind: Option<CoroutineKind>,
/// The current set of scopes, updated as we traverse;
/// see the `scope` module for more details.
@@ -448,7 +452,7 @@ fn construct_fn<'tcx>(
) -> Body<'tcx> {
let span = tcx.def_span(fn_def);
let fn_id = tcx.hir().local_def_id_to_hir_id(fn_def);
- let generator_kind = tcx.generator_kind(fn_def);
+ let coroutine_kind = tcx.coroutine_kind(fn_def);
// The representation of thir for `-Zunpretty=thir-tree` relies on
// the entry expression being the last element of `thir.exprs`.
@@ -478,15 +482,15 @@ fn construct_fn<'tcx>(
let arguments = &thir.params;
- let (yield_ty, return_ty) = if generator_kind.is_some() {
- let gen_ty = arguments[thir::UPVAR_ENV_PARAM].ty;
- let gen_sig = match gen_ty.kind() {
- ty::Generator(_, gen_args, ..) => gen_args.as_generator().sig(),
+ let (yield_ty, return_ty) = if coroutine_kind.is_some() {
+ let coroutine_ty = arguments[thir::UPVAR_ENV_PARAM].ty;
+ let coroutine_sig = match coroutine_ty.kind() {
+ ty::Coroutine(_, gen_args, ..) => gen_args.as_coroutine().sig(),
_ => {
- span_bug!(span, "generator w/o generator type: {:?}", gen_ty)
+ span_bug!(span, "coroutine w/o coroutine type: {:?}", coroutine_ty)
}
};
- (Some(gen_sig.yield_ty), gen_sig.return_ty)
+ (Some(coroutine_sig.yield_ty), coroutine_sig.return_ty)
} else {
(None, fn_sig.output())
};
@@ -519,7 +523,7 @@ fn construct_fn<'tcx>(
safety,
return_ty,
return_ty_span,
- generator_kind,
+ coroutine_kind,
);
let call_site_scope =
@@ -553,7 +557,7 @@ fn construct_fn<'tcx>(
None
};
if yield_ty.is_some() {
- body.generator.as_mut().unwrap().yield_ty = yield_ty;
+ body.coroutine.as_mut().unwrap().yield_ty = yield_ty;
}
body
}
@@ -616,29 +620,53 @@ 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, 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 = Ty::new_error(tcx, err);
- let num_params = match body_owner_kind {
- hir::BodyOwnerKind::Fn => tcx.fn_sig(def).skip_binder().inputs().skip_binder().len(),
- hir::BodyOwnerKind::Closure => {
- let ty = tcx.type_of(def).instantiate_identity();
- match ty.kind() {
- ty::Closure(_, args) => 1 + args.as_closure().sig().inputs().skip_binder().len(),
- ty::Generator(..) => 2,
- _ => bug!("expected closure or generator, found {ty:?}"),
- }
+fn construct_error(tcx: TyCtxt<'_>, def_id: LocalDefId, guar: ErrorGuaranteed) -> Body<'_> {
+ let span = tcx.def_span(def_id);
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
+ let coroutine_kind = tcx.coroutine_kind(def_id);
+
+ let (inputs, output, yield_ty) = match tcx.def_kind(def_id) {
+ DefKind::Const
+ | DefKind::AssocConst
+ | DefKind::AnonConst
+ | DefKind::InlineConst
+ | DefKind::Static(_) => (vec![], tcx.type_of(def_id).instantiate_identity(), None),
+ DefKind::Ctor(..) | DefKind::Fn | DefKind::AssocFn => {
+ let sig = tcx.liberate_late_bound_regions(
+ def_id.to_def_id(),
+ tcx.fn_sig(def_id).instantiate_identity(),
+ );
+ (sig.inputs().to_vec(), sig.output(), None)
+ }
+ DefKind::Closure => {
+ let closure_ty = tcx.type_of(def_id).instantiate_identity();
+ let ty::Closure(_, args) = closure_ty.kind() else { bug!() };
+ let args = args.as_closure();
+ let sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), args.sig());
+ let self_ty = match args.kind() {
+ ty::ClosureKind::Fn => Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, closure_ty),
+ ty::ClosureKind::FnMut => Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, closure_ty),
+ ty::ClosureKind::FnOnce => closure_ty,
+ };
+ ([self_ty].into_iter().chain(sig.inputs().to_vec()).collect(), sig.output(), None)
+ }
+ DefKind::Coroutine => {
+ let coroutine_ty = tcx.type_of(def_id).instantiate_identity();
+ let ty::Coroutine(_, args, _) = coroutine_ty.kind() else { bug!() };
+ let args = args.as_coroutine();
+ let yield_ty = args.yield_ty();
+ let return_ty = args.return_ty();
+ (vec![coroutine_ty, args.resume_ty()], return_ty, Some(yield_ty))
}
- hir::BodyOwnerKind::Const { .. } => 0,
- hir::BodyOwnerKind::Static(_) => 0,
+ dk => bug!("{:?} is not a body: {:?}", def_id, dk),
};
+
+ let source_info = SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE };
+ let local_decls = IndexVec::from_iter(
+ [output].iter().chain(&inputs).map(|ty| LocalDecl::with_source_info(*ty, source_info)),
+ );
let mut cfg = CFG { basic_blocks: IndexVec::new() };
let mut source_scopes = IndexVec::new();
- let mut local_decls = IndexVec::from_elem_n(LocalDecl::new(ty, span), 1);
cfg.start_new_block();
source_scopes.push(SourceScopeData {
@@ -651,28 +679,24 @@ fn construct_error(tcx: TyCtxt<'_>, def: LocalDefId, err: ErrorGuaranteed) -> Bo
safety: Safety::Safe,
}),
});
- let source_info = SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE };
- // Some MIR passes will expect the number of parameters to match the
- // function declaration.
- for _ in 0..num_params {
- local_decls.push(LocalDecl::with_source_info(ty, source_info));
- }
cfg.terminate(START_BLOCK, source_info, TerminatorKind::Unreachable);
let mut body = Body::new(
- MirSource::item(def.to_def_id()),
+ MirSource::item(def_id.to_def_id()),
cfg.basic_blocks,
source_scopes,
local_decls,
IndexVec::new(),
- num_params,
+ inputs.len(),
vec![],
span,
- generator_kind,
- Some(err),
+ coroutine_kind,
+ Some(guar),
);
- body.generator.as_mut().map(|gen| gen.yield_ty = Some(ty));
+
+ body.coroutine.as_mut().map(|gen| gen.yield_ty = yield_ty);
+
body
}
@@ -687,7 +711,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
safety: Safety,
return_ty: Ty<'tcx>,
return_span: Span,
- generator_kind: Option<GeneratorKind>,
+ coroutine_kind: Option<CoroutineKind>,
) -> Builder<'a, 'tcx> {
let tcx = infcx.tcx;
let attrs = tcx.hir().attrs(hir_id);
@@ -718,7 +742,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
cfg: CFG { basic_blocks: IndexVec::new() },
fn_span: span,
arg_count,
- generator_kind,
+ coroutine_kind,
scopes: scope::Scopes::new(),
block_context: BlockContext::new(),
source_scopes: IndexVec::new(),
@@ -760,7 +784,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
self.arg_count,
self.var_debug_info,
self.fn_span,
- self.generator_kind,
+ self.coroutine_kind,
None,
)
}
@@ -777,7 +801,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let upvar_args = match closure_ty.kind() {
ty::Closure(_, args) => ty::UpvarArgs::Closure(args),
- ty::Generator(_, args, _) => ty::UpvarArgs::Generator(args),
+ ty::Coroutine(_, args, _) => ty::UpvarArgs::Coroutine(args),
_ => return,
};
@@ -847,7 +871,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
self.local_decls.push(LocalDecl::with_source_info(param.ty, source_info));
// If this is a simple binding pattern, give debuginfo a nice name.
- if let Some(ref pat) = param.pat && let Some(name) = pat.simple_ident() {
+ if let Some(ref pat) = param.pat
+ && let Some(name) = pat.simple_ident()
+ {
self.var_debug_info.push(VarDebugInfo {
name,
source_info,