]>
Commit | Line | Data |
---|---|---|
e1599b0c | 1 | use super::combine::{CombineFields, RelationDir}; |
dfeec247 | 2 | use super::SubregionOrigin; |
1a4d82fc | 3 | |
f9f354fc | 4 | use crate::infer::combine::ConstEquateRelation; |
9fa01778 | 5 | use crate::traits::Obligation; |
ba9703b0 | 6 | use rustc_middle::ty::relate::{Cause, Relate, RelateResult, TypeRelation}; |
064997fb | 7 | use rustc_middle::ty::visit::TypeVisitable; |
ba9703b0 | 8 | use rustc_middle::ty::TyVar; |
487cf647 | 9 | use rustc_middle::ty::{self, Ty, TyCtxt}; |
62682a34 | 10 | use std::mem; |
1a4d82fc | 11 | |
b039eaaf | 12 | /// Ensures `a` is made a subtype of `b`. Returns `a` on success. |
2b03887a FG |
13 | pub struct Sub<'combine, 'a, 'tcx> { |
14 | fields: &'combine mut CombineFields<'a, 'tcx>, | |
5bcae85e | 15 | a_is_expected: bool, |
1a4d82fc JJ |
16 | } |
17 | ||
dc9dc135 XL |
18 | impl<'combine, 'infcx, 'tcx> Sub<'combine, 'infcx, 'tcx> { |
19 | pub fn new( | |
20 | f: &'combine mut CombineFields<'infcx, 'tcx>, | |
21 | a_is_expected: bool, | |
22 | ) -> Sub<'combine, 'infcx, 'tcx> { | |
74b04a01 | 23 | Sub { fields: f, a_is_expected } |
c34b1796 | 24 | } |
54a0048b | 25 | |
5bcae85e SL |
26 | fn with_expected_switched<R, F: FnOnce(&mut Self) -> R>(&mut self, f: F) -> R { |
27 | self.a_is_expected = !self.a_is_expected; | |
28 | let result = f(self); | |
29 | self.a_is_expected = !self.a_is_expected; | |
30 | result | |
54a0048b | 31 | } |
1a4d82fc JJ |
32 | } |
33 | ||
a2a8927a | 34 | impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> { |
dfeec247 XL |
35 | fn tag(&self) -> &'static str { |
36 | "Sub" | |
37 | } | |
487cf647 FG |
38 | |
39 | fn intercrate(&self) -> bool { | |
40 | self.fields.infcx.intercrate | |
41 | } | |
42 | ||
dfeec247 XL |
43 | fn tcx(&self) -> TyCtxt<'tcx> { |
44 | self.fields.infcx.tcx | |
45 | } | |
416331ca | 46 | |
dfeec247 XL |
47 | fn param_env(&self) -> ty::ParamEnv<'tcx> { |
48 | self.fields.param_env | |
49 | } | |
416331ca | 50 | |
dfeec247 XL |
51 | fn a_is_expected(&self) -> bool { |
52 | self.a_is_expected | |
53 | } | |
85aaf69f | 54 | |
487cf647 FG |
55 | fn mark_ambiguous(&mut self) { |
56 | self.fields.mark_ambiguous() | |
57 | } | |
58 | ||
dfeec247 XL |
59 | fn with_cause<F, R>(&mut self, cause: Cause, f: F) -> R |
60 | where | |
61 | F: FnOnce(&mut Self) -> R, | |
62682a34 SL |
62 | { |
63 | debug!("sub with_cause={:?}", cause); | |
64 | let old_cause = mem::replace(&mut self.fields.cause, Some(cause)); | |
65 | let r = f(self); | |
66 | debug!("sub old_cause={:?}", old_cause); | |
67 | self.fields.cause = old_cause; | |
68 | r | |
69 | } | |
70 | ||
dfeec247 XL |
71 | fn relate_with_variance<T: Relate<'tcx>>( |
72 | &mut self, | |
73 | variance: ty::Variance, | |
17df50a5 | 74 | _info: ty::VarianceDiagInfo<'tcx>, |
f035d41b XL |
75 | a: T, |
76 | b: T, | |
dfeec247 | 77 | ) -> RelateResult<'tcx, T> { |
c34b1796 | 78 | match variance { |
5bcae85e | 79 | ty::Invariant => self.fields.equate(self.a_is_expected).relate(a, b), |
c34b1796 | 80 | ty::Covariant => self.relate(a, b), |
3dfed10e | 81 | ty::Bivariant => Ok(a), |
dfeec247 | 82 | ty::Contravariant => self.with_expected_switched(|this| this.relate(b, a)), |
85aaf69f | 83 | } |
1a4d82fc JJ |
84 | } |
85 | ||
5e7ed085 | 86 | #[instrument(skip(self), level = "debug")] |
c34b1796 | 87 | fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { |
dfeec247 XL |
88 | if a == b { |
89 | return Ok(a); | |
90 | } | |
1a4d82fc JJ |
91 | |
92 | let infcx = self.fields.infcx; | |
f9f354fc XL |
93 | let a = infcx.inner.borrow_mut().type_variables().replace_if_possible(a); |
94 | let b = infcx.inner.borrow_mut().type_variables().replace_if_possible(b); | |
5e7ed085 | 95 | |
1b1a35ee | 96 | match (a.kind(), b.kind()) { |
94222f64 | 97 | (&ty::Infer(TyVar(_)), &ty::Infer(TyVar(_))) => { |
cc61c64b XL |
98 | // Shouldn't have any LBR here, so we can safely put |
99 | // this under a binder below without fear of accidental | |
100 | // capture. | |
a1dfa0c6 XL |
101 | assert!(!a.has_escaping_bound_vars()); |
102 | assert!(!b.has_escaping_bound_vars()); | |
cc61c64b XL |
103 | |
104 | // can't make progress on `A <: B` if both A and B are | |
94222f64 | 105 | // type variables, so record an obligation. |
dfeec247 | 106 | self.fields.obligations.push(Obligation::new( |
487cf647 | 107 | self.tcx(), |
dfeec247 XL |
108 | self.fields.trace.cause.clone(), |
109 | self.fields.param_env, | |
c295e0f8 | 110 | ty::Binder::dummy(ty::PredicateKind::Subtype(ty::SubtypePredicate { |
dfeec247 XL |
111 | a_is_expected: self.a_is_expected, |
112 | a, | |
113 | b, | |
487cf647 | 114 | })), |
dfeec247 | 115 | )); |
cc61c64b | 116 | |
1a4d82fc JJ |
117 | Ok(a) |
118 | } | |
b7449926 | 119 | (&ty::Infer(TyVar(a_id)), _) => { |
dfeec247 | 120 | self.fields.instantiate(b, RelationDir::SupertypeOf, a_id, !self.a_is_expected)?; |
1a4d82fc JJ |
121 | Ok(a) |
122 | } | |
b7449926 | 123 | (_, &ty::Infer(TyVar(b_id))) => { |
cc61c64b | 124 | self.fields.instantiate(a, RelationDir::SubtypeOf, b_id, self.a_is_expected)?; |
1a4d82fc JJ |
125 | Ok(a) |
126 | } | |
127 | ||
487cf647 FG |
128 | (&ty::Error(e), _) | (_, &ty::Error(e)) => { |
129 | infcx.set_tainted_by_errors(e); | |
130 | Ok(self.tcx().ty_error_with_guaranteed(e)) | |
1a4d82fc JJ |
131 | } |
132 | ||
5e7ed085 FG |
133 | (&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => { |
134 | self.fields.infcx.super_combine_tys(self, a, b)?; | |
135 | Ok(a) | |
136 | } | |
137 | (&ty::Opaque(did, ..), _) | (_, &ty::Opaque(did, ..)) | |
138 | if self.fields.define_opaque_types && did.is_local() => | |
139 | { | |
5e7ed085 FG |
140 | self.fields.obligations.extend( |
141 | infcx | |
2b03887a FG |
142 | .handle_opaque_type( |
143 | a, | |
144 | b, | |
145 | self.a_is_expected, | |
146 | &self.fields.trace.cause, | |
147 | self.param_env(), | |
148 | )? | |
5e7ed085 FG |
149 | .obligations, |
150 | ); | |
2b03887a FG |
151 | Ok(a) |
152 | } | |
153 | // Optimization of GeneratorWitness relation since we know that all | |
154 | // free regions are replaced with bound regions during construction. | |
155 | // This greatly speeds up subtyping of GeneratorWitness. | |
156 | (&ty::GeneratorWitness(a_types), &ty::GeneratorWitness(b_types)) => { | |
157 | let a_types = infcx.tcx.anonymize_bound_vars(a_types); | |
158 | let b_types = infcx.tcx.anonymize_bound_vars(b_types); | |
159 | if a_types.bound_vars() == b_types.bound_vars() { | |
160 | let (a_types, b_types) = infcx.replace_bound_vars_with_placeholders( | |
161 | a_types.map_bound(|a_types| (a_types, b_types.skip_binder())), | |
162 | ); | |
163 | for (a, b) in std::iter::zip(a_types, b_types) { | |
164 | self.relate(a, b)?; | |
165 | } | |
166 | Ok(a) | |
167 | } else { | |
168 | Err(ty::error::TypeError::Sorts(ty::relate::expected_found(self, a, b))) | |
169 | } | |
5e7ed085 FG |
170 | } |
171 | ||
1a4d82fc | 172 | _ => { |
a7813a04 | 173 | self.fields.infcx.super_combine_tys(self, a, b)?; |
b039eaaf | 174 | Ok(a) |
1a4d82fc JJ |
175 | } |
176 | } | |
177 | } | |
178 | ||
dfeec247 XL |
179 | fn regions( |
180 | &mut self, | |
181 | a: ty::Region<'tcx>, | |
182 | b: ty::Region<'tcx>, | |
183 | ) -> RelateResult<'tcx, ty::Region<'tcx>> { | |
184 | debug!("{}.regions({:?}, {:?}) self.cause={:?}", self.tag(), a, b, self.fields.cause); | |
476ff2be | 185 | |
c1a9b12d SL |
186 | // FIXME -- we have more fine-grained information available |
187 | // from the "cause" field, we could perhaps give more tailored | |
188 | // error messages. | |
94222f64 | 189 | let origin = SubregionOrigin::Subtype(Box::new(self.fields.trace.clone())); |
74b04a01 XL |
190 | self.fields |
191 | .infcx | |
192 | .inner | |
193 | .borrow_mut() | |
194 | .unwrap_region_constraints() | |
195 | .make_subregion(origin, a, b); | |
476ff2be | 196 | |
c34b1796 AL |
197 | Ok(a) |
198 | } | |
199 | ||
48663c56 XL |
200 | fn consts( |
201 | &mut self, | |
5099ac24 FG |
202 | a: ty::Const<'tcx>, |
203 | b: ty::Const<'tcx>, | |
204 | ) -> RelateResult<'tcx, ty::Const<'tcx>> { | |
e1599b0c | 205 | self.fields.infcx.super_combine_consts(self, a, b) |
48663c56 XL |
206 | } |
207 | ||
dfeec247 XL |
208 | fn binders<T>( |
209 | &mut self, | |
cdc7bbd5 XL |
210 | a: ty::Binder<'tcx, T>, |
211 | b: ty::Binder<'tcx, T>, | |
212 | ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> | |
dfeec247 XL |
213 | where |
214 | T: Relate<'tcx>, | |
1a4d82fc | 215 | { |
923072b8 FG |
216 | self.fields.higher_ranked_sub(a, b, self.a_is_expected)?; |
217 | Ok(a) | |
1a4d82fc JJ |
218 | } |
219 | } | |
f9f354fc XL |
220 | |
221 | impl<'tcx> ConstEquateRelation<'tcx> for Sub<'_, '_, 'tcx> { | |
5099ac24 | 222 | fn const_equate_obligation(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>) { |
f9f354fc XL |
223 | self.fields.add_const_equate_obligation(self.a_is_expected, a, b); |
224 | } | |
225 | } |