rustc_borrowck/
root_cx.rs

1use 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::consumers::BorrowckConsumer;
10use crate::{ClosureRegionRequirements, ConcreteOpaqueTypes, PropagatedBorrowCheckResults};
11
12/// The shared context used by both the root as well as all its nested
13/// items.
14pub(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    /// This should be `None` during normal compilation. See [`crate::consumers`] for more
21    /// information on how this is used.
22    pub(crate) 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    /// Collect all defining uses of opaque types inside of this typeck root. This
42    /// expects the hidden type to be mapped to the definition parameters of the opaque
43    /// and errors if we end up with distinct hidden types.
44    pub(super) fn add_concrete_opaque_type(
45        &mut self,
46        def_id: LocalDefId,
47        hidden_ty: OpaqueHiddenType<'tcx>,
48    ) {
49        // Sometimes two opaque types are the same only after we remap the generic parameters
50        // back to the opaque type definition. E.g. we may have `OpaqueType<X, Y>` mapped to
51        // `(X, Y)` and `OpaqueType<Y, X>` mapped to `(Y, X)`, and those are the same, but we
52        // only know that once we convert the generic parameters to those of the opaque type.
53        if let Some(prev) = self.concrete_opaque_types.0.get_mut(&def_id) {
54            if prev.ty != hidden_ty.ty {
55                let guar = hidden_ty.ty.error_reported().err().unwrap_or_else(|| {
56                    let (Ok(e) | Err(e)) =
57                        prev.build_mismatch_error(&hidden_ty, self.tcx).map(|d| d.emit());
58                    e
59                });
60                prev.ty = Ty::new_error(self.tcx, guar);
61            }
62            // Pick a better span if there is one.
63            // FIXME(oli-obk): collect multiple spans for better diagnostics down the road.
64            prev.span = prev.span.substitute_dummy(hidden_ty.span);
65        } else {
66            self.concrete_opaque_types.0.insert(def_id, hidden_ty);
67        }
68    }
69
70    pub(super) fn set_tainted_by_errors(&mut self, guar: ErrorGuaranteed) {
71        self.tainted_by_errors = Some(guar);
72    }
73
74    pub(super) fn get_or_insert_nested(
75        &mut self,
76        def_id: LocalDefId,
77    ) -> &PropagatedBorrowCheckResults<'tcx> {
78        debug_assert_eq!(
79            self.tcx.typeck_root_def_id(def_id.to_def_id()),
80            self.root_def_id.to_def_id()
81        );
82        if !self.nested_bodies.contains_key(&def_id) {
83            let result = super::do_mir_borrowck(self, def_id);
84            if let Some(prev) = self.nested_bodies.insert(def_id, result) {
85                bug!("unexpected previous nested body: {prev:?}");
86            }
87        }
88
89        self.nested_bodies.get(&def_id).unwrap()
90    }
91
92    pub(super) fn closure_requirements(
93        &mut self,
94        nested_body_def_id: LocalDefId,
95    ) -> &Option<ClosureRegionRequirements<'tcx>> {
96        &self.get_or_insert_nested(nested_body_def_id).closure_requirements
97    }
98
99    pub(super) fn used_mut_upvars(
100        &mut self,
101        nested_body_def_id: LocalDefId,
102    ) -> &SmallVec<[FieldIdx; 8]> {
103        &self.get_or_insert_nested(nested_body_def_id).used_mut_upvars
104    }
105
106    pub(super) fn finalize(self) -> Result<&'tcx ConcreteOpaqueTypes<'tcx>, ErrorGuaranteed> {
107        if let Some(guar) = self.tainted_by_errors {
108            Err(guar)
109        } else {
110            Ok(self.tcx.arena.alloc(self.concrete_opaque_types))
111        }
112    }
113}