rustc_trait_selection/error_reporting/infer/
sub_relations.rs
1use rustc_data_structures::fx::FxHashMap;
2use rustc_data_structures::undo_log::NoUndo;
3use rustc_data_structures::unify as ut;
4use rustc_middle::ty;
5
6use crate::infer::InferCtxt;
7
8#[derive(Debug, Copy, Clone, PartialEq)]
9struct SubId(u32);
10impl ut::UnifyKey for SubId {
11 type Value = ();
12 #[inline]
13 fn index(&self) -> u32 {
14 self.0
15 }
16 #[inline]
17 fn from_index(i: u32) -> SubId {
18 SubId(i)
19 }
20 fn tag() -> &'static str {
21 "SubId"
22 }
23}
24
25#[derive(Default)]
40pub struct SubRelations {
41 map: FxHashMap<ty::TyVid, SubId>,
42 table: ut::UnificationTableStorage<SubId>,
43}
44
45impl SubRelations {
46 fn get_id<'tcx>(&mut self, infcx: &InferCtxt<'tcx>, vid: ty::TyVid) -> SubId {
47 let root_vid = infcx.root_var(vid);
48 *self.map.entry(root_vid).or_insert_with(|| self.table.with_log(&mut NoUndo).new_key(()))
49 }
50
51 pub fn add_constraints<'tcx>(
52 &mut self,
53 infcx: &InferCtxt<'tcx>,
54 obls: impl IntoIterator<Item = ty::Predicate<'tcx>>,
55 ) {
56 for p in obls {
57 let (a, b) = match p.kind().skip_binder() {
58 ty::PredicateKind::Subtype(ty::SubtypePredicate { a_is_expected: _, a, b }) => {
59 (a, b)
60 }
61 ty::PredicateKind::Coerce(ty::CoercePredicate { a, b }) => (a, b),
62 _ => continue,
63 };
64
65 match (a.kind(), b.kind()) {
66 (&ty::Infer(ty::TyVar(a_vid)), &ty::Infer(ty::TyVar(b_vid))) => {
67 let a = self.get_id(infcx, a_vid);
68 let b = self.get_id(infcx, b_vid);
69 self.table.with_log(&mut NoUndo).unify_var_var(a, b).unwrap();
70 }
71 _ => continue,
72 }
73 }
74 }
75
76 pub fn unified<'tcx>(&mut self, infcx: &InferCtxt<'tcx>, a: ty::TyVid, b: ty::TyVid) -> bool {
77 let a = self.get_id(infcx, a);
78 let b = self.get_id(infcx, b);
79 self.table.with_log(&mut NoUndo).unioned(a, b)
80 }
81}