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