1use relate::lattice::{LatticeOp, LatticeOpKind};
29use rustc_middle::bug;
30use rustc_middle::ty::relate::solver_relating::RelateExt as NextSolverRelate;
31use rustc_middle::ty::{Const, ImplSubject, TypingMode};
32
33use super::*;
34use crate::infer::relate::type_relating::TypeRelating;
35use crate::infer::relate::{Relate, TypeRelation};
36use crate::traits::Obligation;
37use crate::traits::solve::Goal;
38
39#[derive(Debug, PartialEq, Eq, Clone, Copy)]
44pub enum DefineOpaqueTypes {
45 Yes,
46 No,
47}
48
49#[derive(Clone, Copy)]
50pub struct At<'a, 'tcx> {
51 pub infcx: &'a InferCtxt<'tcx>,
52 pub cause: &'a ObligationCause<'tcx>,
53 pub param_env: ty::ParamEnv<'tcx>,
54}
55
56impl<'tcx> InferCtxt<'tcx> {
57 #[inline]
58 pub fn at<'a>(
59 &'a self,
60 cause: &'a ObligationCause<'tcx>,
61 param_env: ty::ParamEnv<'tcx>,
62 ) -> At<'a, 'tcx> {
63 At { infcx: self, cause, param_env }
64 }
65
66 pub fn fork(&self) -> Self {
70 Self {
71 tcx: self.tcx,
72 typing_mode: self.typing_mode,
73 considering_regions: self.considering_regions,
74 skip_leak_check: self.skip_leak_check,
75 inner: self.inner.clone(),
76 lexical_region_resolutions: self.lexical_region_resolutions.clone(),
77 selection_cache: self.selection_cache.clone(),
78 evaluation_cache: self.evaluation_cache.clone(),
79 reported_trait_errors: self.reported_trait_errors.clone(),
80 reported_signature_mismatch: self.reported_signature_mismatch.clone(),
81 tainted_by_errors: self.tainted_by_errors.clone(),
82 universe: self.universe.clone(),
83 next_trait_solver: self.next_trait_solver,
84 obligation_inspector: self.obligation_inspector.clone(),
85 }
86 }
87
88 pub fn fork_with_typing_mode(&self, typing_mode: TypingMode<'tcx>) -> Self {
92 let forked = Self {
95 tcx: self.tcx,
96 typing_mode,
97 considering_regions: self.considering_regions,
98 skip_leak_check: self.skip_leak_check,
99 inner: self.inner.clone(),
100 lexical_region_resolutions: self.lexical_region_resolutions.clone(),
101 selection_cache: Default::default(),
102 evaluation_cache: Default::default(),
103 reported_trait_errors: self.reported_trait_errors.clone(),
104 reported_signature_mismatch: self.reported_signature_mismatch.clone(),
105 tainted_by_errors: self.tainted_by_errors.clone(),
106 universe: self.universe.clone(),
107 next_trait_solver: self.next_trait_solver,
108 obligation_inspector: self.obligation_inspector.clone(),
109 };
110 forked.inner.borrow_mut().projection_cache().clear();
111 forked
112 }
113}
114
115pub trait ToTrace<'tcx>: Relate<TyCtxt<'tcx>> + Copy {
116 fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx>;
117}
118
119impl<'a, 'tcx> At<'a, 'tcx> {
120 pub fn sup<T>(
125 self,
126 define_opaque_types: DefineOpaqueTypes,
127 expected: T,
128 actual: T,
129 ) -> InferResult<'tcx, ()>
130 where
131 T: ToTrace<'tcx>,
132 {
133 if self.infcx.next_trait_solver {
134 NextSolverRelate::relate(
135 self.infcx,
136 self.param_env,
137 expected,
138 ty::Contravariant,
139 actual,
140 self.cause.span,
141 )
142 .map(|goals| self.goals_to_obligations(goals))
143 } else {
144 let mut op = TypeRelating::new(
145 self.infcx,
146 ToTrace::to_trace(self.cause, expected, actual),
147 self.param_env,
148 define_opaque_types,
149 ty::Contravariant,
150 );
151 op.relate(expected, actual)?;
152 Ok(InferOk { value: (), obligations: op.into_obligations() })
153 }
154 }
155
156 pub fn sub<T>(
158 self,
159 define_opaque_types: DefineOpaqueTypes,
160 expected: T,
161 actual: T,
162 ) -> InferResult<'tcx, ()>
163 where
164 T: ToTrace<'tcx>,
165 {
166 if self.infcx.next_trait_solver {
167 NextSolverRelate::relate(
168 self.infcx,
169 self.param_env,
170 expected,
171 ty::Covariant,
172 actual,
173 self.cause.span,
174 )
175 .map(|goals| self.goals_to_obligations(goals))
176 } else {
177 let mut op = TypeRelating::new(
178 self.infcx,
179 ToTrace::to_trace(self.cause, expected, actual),
180 self.param_env,
181 define_opaque_types,
182 ty::Covariant,
183 );
184 op.relate(expected, actual)?;
185 Ok(InferOk { value: (), obligations: op.into_obligations() })
186 }
187 }
188
189 pub fn eq<T>(
191 self,
192 define_opaque_types: DefineOpaqueTypes,
193 expected: T,
194 actual: T,
195 ) -> InferResult<'tcx, ()>
196 where
197 T: ToTrace<'tcx>,
198 {
199 self.eq_trace(
200 define_opaque_types,
201 ToTrace::to_trace(self.cause, expected, actual),
202 expected,
203 actual,
204 )
205 }
206
207 pub fn eq_trace<T>(
209 self,
210 define_opaque_types: DefineOpaqueTypes,
211 trace: TypeTrace<'tcx>,
212 expected: T,
213 actual: T,
214 ) -> InferResult<'tcx, ()>
215 where
216 T: Relate<TyCtxt<'tcx>>,
217 {
218 if self.infcx.next_trait_solver {
219 NextSolverRelate::relate(
220 self.infcx,
221 self.param_env,
222 expected,
223 ty::Invariant,
224 actual,
225 self.cause.span,
226 )
227 .map(|goals| self.goals_to_obligations(goals))
228 } else {
229 let mut op = TypeRelating::new(
230 self.infcx,
231 trace,
232 self.param_env,
233 define_opaque_types,
234 ty::Invariant,
235 );
236 op.relate(expected, actual)?;
237 Ok(InferOk { value: (), obligations: op.into_obligations() })
238 }
239 }
240
241 pub fn relate<T>(
242 self,
243 define_opaque_types: DefineOpaqueTypes,
244 expected: T,
245 variance: ty::Variance,
246 actual: T,
247 ) -> InferResult<'tcx, ()>
248 where
249 T: ToTrace<'tcx>,
250 {
251 match variance {
252 ty::Covariant => self.sub(define_opaque_types, expected, actual),
253 ty::Invariant => self.eq(define_opaque_types, expected, actual),
254 ty::Contravariant => self.sup(define_opaque_types, expected, actual),
255
256 ty::Bivariant => panic!("Bivariant given to `relate()`"),
262 }
263 }
264
265 pub fn lub<T>(self, expected: T, actual: T) -> InferResult<'tcx, T>
271 where
272 T: ToTrace<'tcx>,
273 {
274 let mut op = LatticeOp::new(
275 self.infcx,
276 ToTrace::to_trace(self.cause, expected, actual),
277 self.param_env,
278 LatticeOpKind::Lub,
279 );
280 let value = op.relate(expected, actual)?;
281 Ok(InferOk { value, obligations: op.into_obligations() })
282 }
283
284 fn goals_to_obligations(
285 &self,
286 goals: Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
287 ) -> InferOk<'tcx, ()> {
288 InferOk {
289 value: (),
290 obligations: goals
291 .into_iter()
292 .map(|goal| {
293 Obligation::new(
294 self.infcx.tcx,
295 self.cause.clone(),
296 goal.param_env,
297 goal.predicate,
298 )
299 })
300 .collect(),
301 }
302 }
303}
304
305impl<'tcx> ToTrace<'tcx> for ImplSubject<'tcx> {
306 fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
307 match (a, b) {
308 (ImplSubject::Trait(trait_ref_a), ImplSubject::Trait(trait_ref_b)) => {
309 ToTrace::to_trace(cause, trait_ref_a, trait_ref_b)
310 }
311 (ImplSubject::Inherent(ty_a), ImplSubject::Inherent(ty_b)) => {
312 ToTrace::to_trace(cause, ty_a, ty_b)
313 }
314 (ImplSubject::Trait(_), ImplSubject::Inherent(_))
315 | (ImplSubject::Inherent(_), ImplSubject::Trait(_)) => {
316 bug!("can not trace TraitRef and Ty");
317 }
318 }
319 }
320}
321
322impl<'tcx> ToTrace<'tcx> for Ty<'tcx> {
323 fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
324 TypeTrace {
325 cause: cause.clone(),
326 values: ValuePairs::Terms(ExpectedFound::new(a.into(), b.into())),
327 }
328 }
329}
330
331impl<'tcx> ToTrace<'tcx> for ty::Region<'tcx> {
332 fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
333 TypeTrace { cause: cause.clone(), values: ValuePairs::Regions(ExpectedFound::new(a, b)) }
334 }
335}
336
337impl<'tcx> ToTrace<'tcx> for Const<'tcx> {
338 fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
339 TypeTrace {
340 cause: cause.clone(),
341 values: ValuePairs::Terms(ExpectedFound::new(a.into(), b.into())),
342 }
343 }
344}
345
346impl<'tcx> ToTrace<'tcx> for ty::GenericArg<'tcx> {
347 fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
348 TypeTrace {
349 cause: cause.clone(),
350 values: match (a.unpack(), b.unpack()) {
351 (GenericArgKind::Lifetime(a), GenericArgKind::Lifetime(b)) => {
352 ValuePairs::Regions(ExpectedFound::new(a, b))
353 }
354 (GenericArgKind::Type(a), GenericArgKind::Type(b)) => {
355 ValuePairs::Terms(ExpectedFound::new(a.into(), b.into()))
356 }
357 (GenericArgKind::Const(a), GenericArgKind::Const(b)) => {
358 ValuePairs::Terms(ExpectedFound::new(a.into(), b.into()))
359 }
360 _ => bug!("relating different kinds: {a:?} {b:?}"),
361 },
362 }
363 }
364}
365
366impl<'tcx> ToTrace<'tcx> for ty::Term<'tcx> {
367 fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
368 TypeTrace { cause: cause.clone(), values: ValuePairs::Terms(ExpectedFound::new(a, b)) }
369 }
370}
371
372impl<'tcx> ToTrace<'tcx> for ty::TraitRef<'tcx> {
373 fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
374 TypeTrace { cause: cause.clone(), values: ValuePairs::TraitRefs(ExpectedFound::new(a, b)) }
375 }
376}
377
378impl<'tcx> ToTrace<'tcx> for ty::AliasTy<'tcx> {
379 fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
380 TypeTrace {
381 cause: cause.clone(),
382 values: ValuePairs::Aliases(ExpectedFound::new(a.into(), b.into())),
383 }
384 }
385}
386
387impl<'tcx> ToTrace<'tcx> for ty::AliasTerm<'tcx> {
388 fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
389 TypeTrace { cause: cause.clone(), values: ValuePairs::Aliases(ExpectedFound::new(a, b)) }
390 }
391}
392
393impl<'tcx> ToTrace<'tcx> for ty::FnSig<'tcx> {
394 fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
395 TypeTrace {
396 cause: cause.clone(),
397 values: ValuePairs::PolySigs(ExpectedFound::new(
398 ty::Binder::dummy(a),
399 ty::Binder::dummy(b),
400 )),
401 }
402 }
403}
404
405impl<'tcx> ToTrace<'tcx> for ty::PolyFnSig<'tcx> {
406 fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
407 TypeTrace { cause: cause.clone(), values: ValuePairs::PolySigs(ExpectedFound::new(a, b)) }
408 }
409}
410
411impl<'tcx> ToTrace<'tcx> for ty::PolyExistentialTraitRef<'tcx> {
412 fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
413 TypeTrace {
414 cause: cause.clone(),
415 values: ValuePairs::ExistentialTraitRef(ExpectedFound::new(a, b)),
416 }
417 }
418}
419
420impl<'tcx> ToTrace<'tcx> for ty::ExistentialTraitRef<'tcx> {
421 fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
422 TypeTrace {
423 cause: cause.clone(),
424 values: ValuePairs::ExistentialTraitRef(ExpectedFound::new(
425 ty::Binder::dummy(a),
426 ty::Binder::dummy(b),
427 )),
428 }
429 }
430}
431
432impl<'tcx> ToTrace<'tcx> for ty::PolyExistentialProjection<'tcx> {
433 fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
434 TypeTrace {
435 cause: cause.clone(),
436 values: ValuePairs::ExistentialProjection(ExpectedFound::new(a, b)),
437 }
438 }
439}
440
441impl<'tcx> ToTrace<'tcx> for ty::ExistentialProjection<'tcx> {
442 fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
443 TypeTrace {
444 cause: cause.clone(),
445 values: ValuePairs::ExistentialProjection(ExpectedFound::new(
446 ty::Binder::dummy(a),
447 ty::Binder::dummy(b),
448 )),
449 }
450 }
451}