]>
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 | ||
5e7ed085 | 69 | #[instrument(skip(self), level = "debug")] |
c34b1796 | 70 | fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { |
dfeec247 XL |
71 | if a == b { |
72 | return Ok(a); | |
73 | } | |
1a4d82fc | 74 | |
5e7ed085 FG |
75 | trace!(a = ?a.kind(), b = ?b.kind()); |
76 | ||
1a4d82fc | 77 | let infcx = self.fields.infcx; |
5e7ed085 | 78 | |
f9f354fc XL |
79 | let a = infcx.inner.borrow_mut().type_variables().replace_if_possible(a); |
80 | let b = infcx.inner.borrow_mut().type_variables().replace_if_possible(b); | |
13cf67c4 | 81 | |
1b1a35ee | 82 | match (a.kind(), b.kind()) { |
b7449926 | 83 | (&ty::Infer(TyVar(a_id)), &ty::Infer(TyVar(b_id))) => { |
f9f354fc | 84 | infcx.inner.borrow_mut().type_variables().equate(a_id, b_id); |
1a4d82fc JJ |
85 | } |
86 | ||
b7449926 | 87 | (&ty::Infer(TyVar(a_id)), _) => { |
cc61c64b | 88 | self.fields.instantiate(b, RelationDir::EqTo, a_id, self.a_is_expected)?; |
1a4d82fc JJ |
89 | } |
90 | ||
b7449926 | 91 | (_, &ty::Infer(TyVar(b_id))) => { |
cc61c64b | 92 | self.fields.instantiate(a, RelationDir::EqTo, b_id, self.a_is_expected)?; |
1a4d82fc JJ |
93 | } |
94 | ||
5e7ed085 FG |
95 | (&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => { |
96 | self.fields.infcx.super_combine_tys(self, a, b)?; | |
97 | } | |
98 | (&ty::Opaque(did, ..), _) | (_, &ty::Opaque(did, ..)) | |
99 | if self.fields.define_opaque_types && did.is_local() => | |
100 | { | |
101 | self.fields.obligations.extend( | |
102 | infcx | |
103 | .handle_opaque_type( | |
104 | a, | |
105 | b, | |
106 | self.a_is_expected(), | |
107 | &self.fields.trace.cause, | |
108 | self.param_env(), | |
109 | )? | |
110 | .obligations, | |
111 | ); | |
112 | } | |
113 | ||
1a4d82fc | 114 | _ => { |
a7813a04 | 115 | self.fields.infcx.super_combine_tys(self, a, b)?; |
1a4d82fc JJ |
116 | } |
117 | } | |
0bf4aa26 XL |
118 | |
119 | Ok(a) | |
1a4d82fc JJ |
120 | } |
121 | ||
dfeec247 XL |
122 | fn regions( |
123 | &mut self, | |
124 | a: ty::Region<'tcx>, | |
125 | b: ty::Region<'tcx>, | |
126 | ) -> RelateResult<'tcx, ty::Region<'tcx>> { | |
127 | debug!("{}.regions({:?}, {:?})", self.tag(), a, b); | |
94222f64 | 128 | let origin = Subtype(Box::new(self.fields.trace.clone())); |
74b04a01 XL |
129 | self.fields |
130 | .infcx | |
131 | .inner | |
132 | .borrow_mut() | |
133 | .unwrap_region_constraints() | |
134 | .make_eqregion(origin, a, b); | |
c34b1796 AL |
135 | Ok(a) |
136 | } | |
137 | ||
48663c56 XL |
138 | fn consts( |
139 | &mut self, | |
5099ac24 FG |
140 | a: ty::Const<'tcx>, |
141 | b: ty::Const<'tcx>, | |
142 | ) -> RelateResult<'tcx, ty::Const<'tcx>> { | |
e1599b0c | 143 | self.fields.infcx.super_combine_consts(self, a, b) |
48663c56 XL |
144 | } |
145 | ||
dfeec247 XL |
146 | fn binders<T>( |
147 | &mut self, | |
cdc7bbd5 XL |
148 | a: ty::Binder<'tcx, T>, |
149 | b: ty::Binder<'tcx, T>, | |
150 | ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> | |
dfeec247 XL |
151 | where |
152 | T: Relate<'tcx>, | |
1a4d82fc | 153 | { |
74b04a01 XL |
154 | if a.skip_binder().has_escaping_bound_vars() || b.skip_binder().has_escaping_bound_vars() { |
155 | self.fields.higher_ranked_sub(a, b, self.a_is_expected)?; | |
156 | self.fields.higher_ranked_sub(b, a, self.a_is_expected) | |
157 | } else { | |
158 | // Fast path for the common case. | |
159 | self.relate(a.skip_binder(), b.skip_binder())?; | |
f035d41b | 160 | Ok(a) |
74b04a01 | 161 | } |
1a4d82fc JJ |
162 | } |
163 | } | |
f9f354fc XL |
164 | |
165 | impl<'tcx> ConstEquateRelation<'tcx> for Equate<'_, '_, 'tcx> { | |
5099ac24 | 166 | fn const_equate_obligation(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>) { |
f9f354fc XL |
167 | self.fields.add_const_equate_obligation(self.a_is_expected, a, b); |
168 | } | |
169 | } |