rustc_borrowck/
root_cx.rs1use rustc_abi::FieldIdx;
2use rustc_data_structures::fx::FxHashMap;
3use rustc_hir::def_id::LocalDefId;
4use rustc_middle::bug;
5use rustc_middle::ty::{OpaqueHiddenType, Ty, TyCtxt, TypeVisitableExt};
6use rustc_span::ErrorGuaranteed;
7use smallvec::SmallVec;
8
9use crate::{ClosureRegionRequirements, ConcreteOpaqueTypes, PropagatedBorrowCheckResults};
10
11pub(super) struct BorrowCheckRootCtxt<'tcx> {
14 pub tcx: TyCtxt<'tcx>,
15 root_def_id: LocalDefId,
16 concrete_opaque_types: ConcreteOpaqueTypes<'tcx>,
17 nested_bodies: FxHashMap<LocalDefId, PropagatedBorrowCheckResults<'tcx>>,
18 tainted_by_errors: Option<ErrorGuaranteed>,
19}
20
21impl<'tcx> BorrowCheckRootCtxt<'tcx> {
22 pub(super) fn new(tcx: TyCtxt<'tcx>, root_def_id: LocalDefId) -> BorrowCheckRootCtxt<'tcx> {
23 BorrowCheckRootCtxt {
24 tcx,
25 root_def_id,
26 concrete_opaque_types: Default::default(),
27 nested_bodies: Default::default(),
28 tainted_by_errors: None,
29 }
30 }
31
32 pub(super) fn add_concrete_opaque_type(
36 &mut self,
37 def_id: LocalDefId,
38 hidden_ty: OpaqueHiddenType<'tcx>,
39 ) {
40 if let Some(prev) = self.concrete_opaque_types.0.get_mut(&def_id) {
45 if prev.ty != hidden_ty.ty {
46 let guar = hidden_ty.ty.error_reported().err().unwrap_or_else(|| {
47 let (Ok(e) | Err(e)) =
48 prev.build_mismatch_error(&hidden_ty, self.tcx).map(|d| d.emit());
49 e
50 });
51 prev.ty = Ty::new_error(self.tcx, guar);
52 }
53 prev.span = prev.span.substitute_dummy(hidden_ty.span);
56 } else {
57 self.concrete_opaque_types.0.insert(def_id, hidden_ty);
58 }
59 }
60
61 pub(super) fn set_tainted_by_errors(&mut self, guar: ErrorGuaranteed) {
62 self.tainted_by_errors = Some(guar);
63 }
64
65 pub(super) fn get_or_insert_nested(
66 &mut self,
67 def_id: LocalDefId,
68 ) -> &PropagatedBorrowCheckResults<'tcx> {
69 debug_assert_eq!(
70 self.tcx.typeck_root_def_id(def_id.to_def_id()),
71 self.root_def_id.to_def_id()
72 );
73 if !self.nested_bodies.contains_key(&def_id) {
74 let result = super::do_mir_borrowck(self, def_id, None).0;
75 if let Some(prev) = self.nested_bodies.insert(def_id, result) {
76 bug!("unexpected previous nested body: {prev:?}");
77 }
78 }
79
80 self.nested_bodies.get(&def_id).unwrap()
81 }
82
83 pub(super) fn closure_requirements(
84 &mut self,
85 nested_body_def_id: LocalDefId,
86 ) -> &Option<ClosureRegionRequirements<'tcx>> {
87 &self.get_or_insert_nested(nested_body_def_id).closure_requirements
88 }
89
90 pub(super) fn used_mut_upvars(
91 &mut self,
92 nested_body_def_id: LocalDefId,
93 ) -> &SmallVec<[FieldIdx; 8]> {
94 &self.get_or_insert_nested(nested_body_def_id).used_mut_upvars
95 }
96
97 pub(super) fn finalize(self) -> Result<&'tcx ConcreteOpaqueTypes<'tcx>, ErrorGuaranteed> {
98 if let Some(guar) = self.tainted_by_errors {
99 Err(guar)
100 } else {
101 Ok(self.tcx.arena.alloc(self.concrete_opaque_types))
102 }
103 }
104}