rustc_borrowck/
opaque_types.rs

1use rustc_data_structures::fx::FxIndexMap;
2use rustc_hir::def_id::LocalDefId;
3use rustc_middle::ty::{OpaqueHiddenType, Ty, TyCtxt};
4
5#[derive(Debug, Default)]
6pub(super) struct ConcreteOpaqueTypes<'tcx> {
7    concrete_opaque_types: FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>>,
8}
9
10impl<'tcx> ConcreteOpaqueTypes<'tcx> {
11    pub(super) fn is_empty(&self) -> bool {
12        self.concrete_opaque_types.is_empty()
13    }
14
15    pub(super) fn into_inner(self) -> FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>> {
16        self.concrete_opaque_types
17    }
18
19    /// Insert an opaque type into the list of opaque types defined by this function
20    /// after mapping the hidden type to the generic parameters of the opaque type
21    /// definition.
22    pub(super) fn insert(
23        &mut self,
24        tcx: TyCtxt<'tcx>,
25        def_id: LocalDefId,
26        hidden_ty: OpaqueHiddenType<'tcx>,
27    ) {
28        // Sometimes two opaque types are the same only after we remap the generic parameters
29        // back to the opaque type definition. E.g. we may have `OpaqueType<X, Y>` mapped to
30        // `(X, Y)` and `OpaqueType<Y, X>` mapped to `(Y, X)`, and those are the same, but we
31        // only know that once we convert the generic parameters to those of the opaque type.
32        if let Some(prev) = self.concrete_opaque_types.get_mut(&def_id) {
33            if prev.ty != hidden_ty.ty {
34                let (Ok(guar) | Err(guar)) =
35                    prev.build_mismatch_error(&hidden_ty, tcx).map(|d| d.emit());
36                prev.ty = Ty::new_error(tcx, guar);
37            }
38            // Pick a better span if there is one.
39            // FIXME(oli-obk): collect multiple spans for better diagnostics down the road.
40            prev.span = prev.span.substitute_dummy(hidden_ty.span);
41        } else {
42            self.concrete_opaque_types.insert(def_id, hidden_ty);
43        }
44    }
45
46    pub(super) fn extend_from_nested_body(
47        &mut self,
48        tcx: TyCtxt<'tcx>,
49        nested_body: &FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>>,
50    ) {
51        for (&def_id, &hidden_ty) in nested_body {
52            self.insert(tcx, def_id, hidden_ty);
53        }
54    }
55}