]>
Commit | Line | Data |
---|---|---|
f9f354fc | 1 | use super::combine::{CombineFields, ConstEquateRelation, RelationDir}; |
48663c56 | 2 | use super::Subtype; |
cc61c64b | 3 | |
ba9703b0 XL |
4 | use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation}; |
5 | use rustc_middle::ty::subst::SubstsRef; | |
6 | use rustc_middle::ty::TyVar; | |
7 | use rustc_middle::ty::{self, Ty, TyCtxt}; | |
dfeec247 XL |
8 | |
9 | use rustc_hir::def_id::DefId; | |
1a4d82fc | 10 | |
b039eaaf | 11 | /// Ensures `a` is made equal to `b`. Returns `a` on success. |
dc9dc135 XL |
12 | pub struct Equate<'combine, 'infcx, 'tcx> { |
13 | fields: &'combine mut CombineFields<'infcx, 'tcx>, | |
5bcae85e | 14 | a_is_expected: bool, |
1a4d82fc JJ |
15 | } |
16 | ||
dc9dc135 XL |
17 | impl<'combine, 'infcx, 'tcx> Equate<'combine, 'infcx, 'tcx> { |
18 | pub fn new( | |
19 | fields: &'combine mut CombineFields<'infcx, 'tcx>, | |
20 | a_is_expected: bool, | |
21 | ) -> Equate<'combine, 'infcx, 'tcx> { | |
74b04a01 | 22 | Equate { fields, a_is_expected } |
54a0048b | 23 | } |
c34b1796 | 24 | } |
1a4d82fc | 25 | |
a2a8927a | 26 | impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> { |
dfeec247 XL |
27 | fn tag(&self) -> &'static str { |
28 | "Equate" | |
29 | } | |
1a4d82fc | 30 | |
dfeec247 XL |
31 | fn tcx(&self) -> TyCtxt<'tcx> { |
32 | self.fields.tcx() | |
33 | } | |
1a4d82fc | 34 | |
dfeec247 XL |
35 | fn param_env(&self) -> ty::ParamEnv<'tcx> { |
36 | self.fields.param_env | |
37 | } | |
416331ca | 38 | |
dfeec247 XL |
39 | fn a_is_expected(&self) -> bool { |
40 | self.a_is_expected | |
41 | } | |
1a4d82fc | 42 | |
dfeec247 XL |
43 | fn relate_item_substs( |
44 | &mut self, | |
45 | _item_def_id: DefId, | |
46 | a_subst: SubstsRef<'tcx>, | |
47 | b_subst: SubstsRef<'tcx>, | |
48 | ) -> RelateResult<'tcx, SubstsRef<'tcx>> { | |
0731742a | 49 | // N.B., once we are equating types, we don't care about |
cc61c64b | 50 | // variance, so don't try to lookup the variance here. This |
0731742a | 51 | // also avoids some cycles (e.g., #41849) since looking up |
cc61c64b XL |
52 | // variance requires computing types which can require |
53 | // performing trait matching (which then performs equality | |
54 | // unification). | |
55 | ||
56 | relate::relate_substs(self, None, a_subst, b_subst) | |
57 | } | |
58 | ||
dfeec247 XL |
59 | fn relate_with_variance<T: Relate<'tcx>>( |
60 | &mut self, | |
61 | _: ty::Variance, | |
17df50a5 | 62 | _info: ty::VarianceDiagInfo<'tcx>, |
f035d41b XL |
63 | a: T, |
64 | b: T, | |
dfeec247 | 65 | ) -> RelateResult<'tcx, T> { |
c34b1796 | 66 | self.relate(a, b) |
1a4d82fc JJ |
67 | } |
68 | ||
c34b1796 | 69 | fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { |
dfeec247 XL |
70 | debug!("{}.tys({:?}, {:?})", self.tag(), a, b); |
71 | if a == b { | |
72 | return Ok(a); | |
73 | } | |
1a4d82fc JJ |
74 | |
75 | let infcx = self.fields.infcx; | |
f9f354fc XL |
76 | let a = infcx.inner.borrow_mut().type_variables().replace_if_possible(a); |
77 | let b = infcx.inner.borrow_mut().type_variables().replace_if_possible(b); | |
13cf67c4 XL |
78 | |
79 | debug!("{}.tys: replacements ({:?}, {:?})", self.tag(), a, b); | |
80 | ||
1b1a35ee | 81 | match (a.kind(), b.kind()) { |
b7449926 | 82 | (&ty::Infer(TyVar(a_id)), &ty::Infer(TyVar(b_id))) => { |
f9f354fc | 83 | infcx.inner.borrow_mut().type_variables().equate(a_id, b_id); |
1a4d82fc JJ |
84 | } |
85 | ||
b7449926 | 86 | (&ty::Infer(TyVar(a_id)), _) => { |
cc61c64b | 87 | self.fields.instantiate(b, RelationDir::EqTo, a_id, self.a_is_expected)?; |
1a4d82fc JJ |
88 | } |
89 | ||
b7449926 | 90 | (_, &ty::Infer(TyVar(b_id))) => { |
cc61c64b | 91 | self.fields.instantiate(a, RelationDir::EqTo, b_id, self.a_is_expected)?; |
1a4d82fc JJ |
92 | } |
93 | ||
94 | _ => { | |
a7813a04 | 95 | self.fields.infcx.super_combine_tys(self, a, b)?; |
1a4d82fc JJ |
96 | } |
97 | } | |
0bf4aa26 XL |
98 | |
99 | Ok(a) | |
1a4d82fc JJ |
100 | } |
101 | ||
dfeec247 XL |
102 | fn regions( |
103 | &mut self, | |
104 | a: ty::Region<'tcx>, | |
105 | b: ty::Region<'tcx>, | |
106 | ) -> RelateResult<'tcx, ty::Region<'tcx>> { | |
107 | debug!("{}.regions({:?}, {:?})", self.tag(), a, b); | |
94222f64 | 108 | let origin = Subtype(Box::new(self.fields.trace.clone())); |
74b04a01 XL |
109 | self.fields |
110 | .infcx | |
111 | .inner | |
112 | .borrow_mut() | |
113 | .unwrap_region_constraints() | |
114 | .make_eqregion(origin, a, b); | |
c34b1796 AL |
115 | Ok(a) |
116 | } | |
117 | ||
48663c56 XL |
118 | fn consts( |
119 | &mut self, | |
5099ac24 FG |
120 | a: ty::Const<'tcx>, |
121 | b: ty::Const<'tcx>, | |
122 | ) -> RelateResult<'tcx, ty::Const<'tcx>> { | |
e1599b0c | 123 | self.fields.infcx.super_combine_consts(self, a, b) |
48663c56 XL |
124 | } |
125 | ||
dfeec247 XL |
126 | fn binders<T>( |
127 | &mut self, | |
cdc7bbd5 XL |
128 | a: ty::Binder<'tcx, T>, |
129 | b: ty::Binder<'tcx, T>, | |
130 | ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> | |
dfeec247 XL |
131 | where |
132 | T: Relate<'tcx>, | |
1a4d82fc | 133 | { |
74b04a01 XL |
134 | if a.skip_binder().has_escaping_bound_vars() || b.skip_binder().has_escaping_bound_vars() { |
135 | self.fields.higher_ranked_sub(a, b, self.a_is_expected)?; | |
136 | self.fields.higher_ranked_sub(b, a, self.a_is_expected) | |
137 | } else { | |
138 | // Fast path for the common case. | |
139 | self.relate(a.skip_binder(), b.skip_binder())?; | |
f035d41b | 140 | Ok(a) |
74b04a01 | 141 | } |
1a4d82fc JJ |
142 | } |
143 | } | |
f9f354fc XL |
144 | |
145 | impl<'tcx> ConstEquateRelation<'tcx> for Equate<'_, '_, 'tcx> { | |
5099ac24 | 146 | fn const_equate_obligation(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>) { |
f9f354fc XL |
147 | self.fields.add_const_equate_obligation(self.a_is_expected, a, b); |
148 | } | |
149 | } |