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::{EarlyBinder, OpaqueHiddenType, Ty, TyCtxt, TypeVisitableExt};
6use rustc_span::ErrorGuaranteed;
7use smallvec::SmallVec;
8
9use crate::consumers::BorrowckConsumer;
10use crate::{ClosureRegionRequirements, ConcreteOpaqueTypes, PropagatedBorrowCheckResults};
11
12pub(super) struct BorrowCheckRootCtxt<'tcx> {
15 pub tcx: TyCtxt<'tcx>,
16 root_def_id: LocalDefId,
17 concrete_opaque_types: ConcreteOpaqueTypes<'tcx>,
18 nested_bodies: FxHashMap<LocalDefId, PropagatedBorrowCheckResults<'tcx>>,
19 tainted_by_errors: Option<ErrorGuaranteed>,
20 pub consumer: Option<BorrowckConsumer<'tcx>>,
23}
24
25impl<'tcx> BorrowCheckRootCtxt<'tcx> {
26 pub(super) fn new(
27 tcx: TyCtxt<'tcx>,
28 root_def_id: LocalDefId,
29 consumer: Option<BorrowckConsumer<'tcx>>,
30 ) -> BorrowCheckRootCtxt<'tcx> {
31 BorrowCheckRootCtxt {
32 tcx,
33 root_def_id,
34 concrete_opaque_types: Default::default(),
35 nested_bodies: Default::default(),
36 tainted_by_errors: None,
37 consumer,
38 }
39 }
40
41 pub(super) fn root_def_id(&self) -> LocalDefId {
42 self.root_def_id
43 }
44
45 pub(super) fn add_concrete_opaque_type(
49 &mut self,
50 def_id: LocalDefId,
51 hidden_ty: OpaqueHiddenType<'tcx>,
52 ) {
53 if let Some(prev) = self.concrete_opaque_types.0.get_mut(&def_id) {
58 if prev.ty != hidden_ty.ty {
59 let guar = hidden_ty.ty.error_reported().err().unwrap_or_else(|| {
60 let (Ok(e) | Err(e)) =
61 prev.build_mismatch_error(&hidden_ty, self.tcx).map(|d| d.emit());
62 e
63 });
64 prev.ty = Ty::new_error(self.tcx, guar);
65 }
66 prev.span = prev.span.substitute_dummy(hidden_ty.span);
69 } else {
70 self.concrete_opaque_types.0.insert(def_id, hidden_ty);
71 }
72 }
73
74 pub(super) fn get_concrete_opaque_type(
75 &mut self,
76 def_id: LocalDefId,
77 ) -> Option<EarlyBinder<'tcx, OpaqueHiddenType<'tcx>>> {
78 self.concrete_opaque_types.0.get(&def_id).map(|ty| EarlyBinder::bind(*ty))
79 }
80
81 pub(super) fn set_tainted_by_errors(&mut self, guar: ErrorGuaranteed) {
82 self.tainted_by_errors = Some(guar);
83 }
84
85 pub(super) fn get_or_insert_nested(
86 &mut self,
87 def_id: LocalDefId,
88 ) -> &PropagatedBorrowCheckResults<'tcx> {
89 debug_assert_eq!(
90 self.tcx.typeck_root_def_id(def_id.to_def_id()),
91 self.root_def_id.to_def_id()
92 );
93 if !self.nested_bodies.contains_key(&def_id) {
94 let result = super::do_mir_borrowck(self, def_id);
95 if let Some(prev) = self.nested_bodies.insert(def_id, result) {
96 bug!("unexpected previous nested body: {prev:?}");
97 }
98 }
99
100 self.nested_bodies.get(&def_id).unwrap()
101 }
102
103 pub(super) fn closure_requirements(
104 &mut self,
105 nested_body_def_id: LocalDefId,
106 ) -> &Option<ClosureRegionRequirements<'tcx>> {
107 &self.get_or_insert_nested(nested_body_def_id).closure_requirements
108 }
109
110 pub(super) fn used_mut_upvars(
111 &mut self,
112 nested_body_def_id: LocalDefId,
113 ) -> &SmallVec<[FieldIdx; 8]> {
114 &self.get_or_insert_nested(nested_body_def_id).used_mut_upvars
115 }
116
117 pub(super) fn finalize(self) -> Result<&'tcx ConcreteOpaqueTypes<'tcx>, ErrorGuaranteed> {
118 if let Some(guar) = self.tainted_by_errors {
119 Err(guar)
120 } else {
121 Ok(self.tcx.arena.alloc(self.concrete_opaque_types))
122 }
123 }
124}