Skip to content

Commit 5a9f07c

Browse files
Build a better MIR body when errors are encountered
1 parent 189d6c7 commit 5a9f07c

File tree

1 file changed

+59
-29
lines changed
  • compiler/rustc_mir_build/src/build

1 file changed

+59
-29
lines changed

compiler/rustc_mir_build/src/build/mod.rs

+59-29
Original file line numberDiff line numberDiff line change
@@ -620,29 +620,63 @@ fn construct_const<'a, 'tcx>(
620620
///
621621
/// This is required because we may still want to run MIR passes on an item
622622
/// with type errors, but normal MIR construction can't handle that in general.
623-
fn construct_error(tcx: TyCtxt<'_>, def: LocalDefId, err: ErrorGuaranteed) -> Body<'_> {
624-
let span = tcx.def_span(def);
625-
let hir_id = tcx.hir().local_def_id_to_hir_id(def);
626-
let coroutine_kind = tcx.coroutine_kind(def);
627-
let body_owner_kind = tcx.hir().body_owner_kind(def);
628-
629-
let ty = Ty::new_error(tcx, err);
630-
let num_params = match body_owner_kind {
631-
hir::BodyOwnerKind::Fn => tcx.fn_sig(def).skip_binder().inputs().skip_binder().len(),
632-
hir::BodyOwnerKind::Closure => {
633-
let ty = tcx.type_of(def).instantiate_identity();
634-
match ty.kind() {
635-
ty::Closure(_, args) => 1 + args.as_closure().sig().inputs().skip_binder().len(),
636-
ty::Coroutine(..) => 2,
637-
_ => bug!("expected closure or coroutine, found {ty:?}"),
638-
}
623+
fn construct_error(tcx: TyCtxt<'_>, def_id: LocalDefId, guar: ErrorGuaranteed) -> Body<'_> {
624+
let span = tcx.def_span(def_id);
625+
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
626+
let coroutine_kind = tcx.coroutine_kind(def_id);
627+
628+
let (inputs, output, yield_ty) = match tcx.def_kind(def_id) {
629+
DefKind::Const
630+
| DefKind::AssocConst
631+
| DefKind::AnonConst
632+
| DefKind::InlineConst
633+
| DefKind::Static(_) => (vec![], tcx.type_of(def_id).instantiate_identity(), None),
634+
DefKind::Ctor(..) | DefKind::Fn | DefKind::AssocFn => {
635+
let sig = tcx.liberate_late_bound_regions(
636+
def_id.to_def_id(),
637+
tcx.fn_sig(def_id).instantiate_identity(),
638+
);
639+
(sig.inputs().to_vec(), sig.output(), None)
640+
}
641+
DefKind::Closure => {
642+
let closure_ty = tcx.type_of(def_id).instantiate_identity();
643+
let ty::Closure(_, args) = closure_ty.kind() else { bug!() };
644+
let args = args.as_closure();
645+
let sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), args.sig());
646+
let self_ty = match args.kind() {
647+
ty::ClosureKind::Fn => Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, closure_ty),
648+
ty::ClosureKind::FnMut => Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, closure_ty),
649+
ty::ClosureKind::FnOnce => closure_ty,
650+
};
651+
([self_ty].into_iter().chain(sig.inputs().to_vec()).collect(), sig.output(), None)
652+
}
653+
DefKind::Coroutine => {
654+
let coroutine_ty = tcx.type_of(def_id).instantiate_identity();
655+
let ty::Coroutine(_, args, _) = coroutine_ty.kind() else { bug!() };
656+
let args = args.as_coroutine();
657+
let yield_ty = args.yield_ty();
658+
let return_ty = args.return_ty();
659+
let self_ty = Ty::new_adt(
660+
tcx,
661+
tcx.adt_def(tcx.lang_items().pin_type().unwrap()),
662+
tcx.mk_args(&[Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, coroutine_ty).into()]),
663+
);
664+
let coroutine_state = Ty::new_adt(
665+
tcx,
666+
tcx.adt_def(tcx.lang_items().coroutine_state().unwrap()),
667+
tcx.mk_args(&[yield_ty.into(), return_ty.into()]),
668+
);
669+
(vec![self_ty, args.resume_ty()], coroutine_state, Some(yield_ty))
639670
}
640-
hir::BodyOwnerKind::Const { .. } => 0,
641-
hir::BodyOwnerKind::Static(_) => 0,
671+
dk => bug!("{:?} is not a body: {:?}", def_id, dk),
642672
};
673+
674+
let source_info = SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE };
675+
let local_decls = IndexVec::from_iter(
676+
[output].iter().chain(&inputs).map(|ty| LocalDecl::with_source_info(*ty, source_info)),
677+
);
643678
let mut cfg = CFG { basic_blocks: IndexVec::new() };
644679
let mut source_scopes = IndexVec::new();
645-
let mut local_decls = IndexVec::from_elem_n(LocalDecl::new(ty, span), 1);
646680

647681
cfg.start_new_block();
648682
source_scopes.push(SourceScopeData {
@@ -655,28 +689,24 @@ fn construct_error(tcx: TyCtxt<'_>, def: LocalDefId, err: ErrorGuaranteed) -> Bo
655689
safety: Safety::Safe,
656690
}),
657691
});
658-
let source_info = SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE };
659692

660-
// Some MIR passes will expect the number of parameters to match the
661-
// function declaration.
662-
for _ in 0..num_params {
663-
local_decls.push(LocalDecl::with_source_info(ty, source_info));
664-
}
665693
cfg.terminate(START_BLOCK, source_info, TerminatorKind::Unreachable);
666694

667695
let mut body = Body::new(
668-
MirSource::item(def.to_def_id()),
696+
MirSource::item(def_id.to_def_id()),
669697
cfg.basic_blocks,
670698
source_scopes,
671699
local_decls,
672700
IndexVec::new(),
673-
num_params,
701+
inputs.len(),
674702
vec![],
675703
span,
676704
coroutine_kind,
677-
Some(err),
705+
Some(guar),
678706
);
679-
body.coroutine.as_mut().map(|gen| gen.yield_ty = Some(ty));
707+
708+
body.coroutine.as_mut().map(|gen| gen.yield_ty = yield_ty);
709+
680710
body
681711
}
682712

0 commit comments

Comments
 (0)