mirror of
https://github.com/rust-lang/rust.git
synced 2025-10-06 20:27:48 +00:00
105 lines
4.0 KiB
Rust
105 lines
4.0 KiB
Rust
use rustc_abi::FieldIdx;
|
|
use rustc_data_structures::fx::FxHashMap;
|
|
use rustc_hir::def_id::LocalDefId;
|
|
use rustc_middle::bug;
|
|
use rustc_middle::ty::{OpaqueHiddenType, Ty, TyCtxt, TypeVisitableExt};
|
|
use rustc_span::ErrorGuaranteed;
|
|
use smallvec::SmallVec;
|
|
|
|
use crate::{ClosureRegionRequirements, ConcreteOpaqueTypes, PropagatedBorrowCheckResults};
|
|
|
|
/// The shared context used by both the root as well as all its nested
|
|
/// items.
|
|
pub(super) struct BorrowCheckRootCtxt<'tcx> {
|
|
pub tcx: TyCtxt<'tcx>,
|
|
root_def_id: LocalDefId,
|
|
concrete_opaque_types: ConcreteOpaqueTypes<'tcx>,
|
|
nested_bodies: FxHashMap<LocalDefId, PropagatedBorrowCheckResults<'tcx>>,
|
|
tainted_by_errors: Option<ErrorGuaranteed>,
|
|
}
|
|
|
|
impl<'tcx> BorrowCheckRootCtxt<'tcx> {
|
|
pub(super) fn new(tcx: TyCtxt<'tcx>, root_def_id: LocalDefId) -> BorrowCheckRootCtxt<'tcx> {
|
|
BorrowCheckRootCtxt {
|
|
tcx,
|
|
root_def_id,
|
|
concrete_opaque_types: Default::default(),
|
|
nested_bodies: Default::default(),
|
|
tainted_by_errors: None,
|
|
}
|
|
}
|
|
|
|
/// Collect all defining uses of opaque types inside of this typeck root. This
|
|
/// expects the hidden type to be mapped to the definition parameters of the opaque
|
|
/// and errors if we end up with distinct hidden types.
|
|
pub(super) fn add_concrete_opaque_type(
|
|
&mut self,
|
|
def_id: LocalDefId,
|
|
hidden_ty: OpaqueHiddenType<'tcx>,
|
|
) {
|
|
// Sometimes two opaque types are the same only after we remap the generic parameters
|
|
// back to the opaque type definition. E.g. we may have `OpaqueType<X, Y>` mapped to
|
|
// `(X, Y)` and `OpaqueType<Y, X>` mapped to `(Y, X)`, and those are the same, but we
|
|
// only know that once we convert the generic parameters to those of the opaque type.
|
|
if let Some(prev) = self.concrete_opaque_types.0.get_mut(&def_id) {
|
|
if prev.ty != hidden_ty.ty {
|
|
let guar = hidden_ty.ty.error_reported().err().unwrap_or_else(|| {
|
|
let (Ok(e) | Err(e)) =
|
|
prev.build_mismatch_error(&hidden_ty, self.tcx).map(|d| d.emit());
|
|
e
|
|
});
|
|
prev.ty = Ty::new_error(self.tcx, guar);
|
|
}
|
|
// Pick a better span if there is one.
|
|
// FIXME(oli-obk): collect multiple spans for better diagnostics down the road.
|
|
prev.span = prev.span.substitute_dummy(hidden_ty.span);
|
|
} else {
|
|
self.concrete_opaque_types.0.insert(def_id, hidden_ty);
|
|
}
|
|
}
|
|
|
|
pub(super) fn set_tainted_by_errors(&mut self, guar: ErrorGuaranteed) {
|
|
self.tainted_by_errors = Some(guar);
|
|
}
|
|
|
|
pub(super) fn get_or_insert_nested(
|
|
&mut self,
|
|
def_id: LocalDefId,
|
|
) -> &PropagatedBorrowCheckResults<'tcx> {
|
|
debug_assert_eq!(
|
|
self.tcx.typeck_root_def_id(def_id.to_def_id()),
|
|
self.root_def_id.to_def_id()
|
|
);
|
|
if !self.nested_bodies.contains_key(&def_id) {
|
|
let result = super::do_mir_borrowck(self, def_id, None).0;
|
|
if let Some(prev) = self.nested_bodies.insert(def_id, result) {
|
|
bug!("unexpected previous nested body: {prev:?}");
|
|
}
|
|
}
|
|
|
|
self.nested_bodies.get(&def_id).unwrap()
|
|
}
|
|
|
|
pub(super) fn closure_requirements(
|
|
&mut self,
|
|
nested_body_def_id: LocalDefId,
|
|
) -> &Option<ClosureRegionRequirements<'tcx>> {
|
|
&self.get_or_insert_nested(nested_body_def_id).closure_requirements
|
|
}
|
|
|
|
pub(super) fn used_mut_upvars(
|
|
&mut self,
|
|
nested_body_def_id: LocalDefId,
|
|
) -> &SmallVec<[FieldIdx; 8]> {
|
|
&self.get_or_insert_nested(nested_body_def_id).used_mut_upvars
|
|
}
|
|
|
|
pub(super) fn finalize(self) -> Result<&'tcx ConcreteOpaqueTypes<'tcx>, ErrorGuaranteed> {
|
|
if let Some(guar) = self.tainted_by_errors {
|
|
Err(guar)
|
|
} else {
|
|
Ok(self.tcx.arena.alloc(self.concrete_opaque_types))
|
|
}
|
|
}
|
|
}
|