1use relate::lattice::{LatticeOp, LatticeOpKind};
29use rustc_middle::bug;
30use rustc_middle::ty::relate::solver_relating::RelateExt as NextSolverRelate;
31use rustc_middle::ty::{Const, 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 Ty<'tcx> {
308 fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
309 TypeTrace {
310 cause: cause.clone(),
311 values: ValuePairs::Terms(ExpectedFound::new(a.into(), b.into())),
312 }
313 }
314}
315
316impl<'tcx> ToTrace<'tcx> for ty::Region<'tcx> {
317 fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
318 TypeTrace { cause: cause.clone(), values: ValuePairs::Regions(ExpectedFound::new(a, b)) }
319 }
320}
321
322impl<'tcx> ToTrace<'tcx> for Const<'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::GenericArg<'tcx> {
332 fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
333 TypeTrace {
334 cause: cause.clone(),
335 values: match (a.kind(), b.kind()) {
336 (GenericArgKind::Lifetime(a), GenericArgKind::Lifetime(b)) => {
337 ValuePairs::Regions(ExpectedFound::new(a, b))
338 }
339 (GenericArgKind::Type(a), GenericArgKind::Type(b)) => {
340 ValuePairs::Terms(ExpectedFound::new(a.into(), b.into()))
341 }
342 (GenericArgKind::Const(a), GenericArgKind::Const(b)) => {
343 ValuePairs::Terms(ExpectedFound::new(a.into(), b.into()))
344 }
345 _ => bug!("relating different kinds: {a:?} {b:?}"),
346 },
347 }
348 }
349}
350
351impl<'tcx> ToTrace<'tcx> for ty::Term<'tcx> {
352 fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
353 TypeTrace { cause: cause.clone(), values: ValuePairs::Terms(ExpectedFound::new(a, b)) }
354 }
355}
356
357impl<'tcx> ToTrace<'tcx> for ty::TraitRef<'tcx> {
358 fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
359 TypeTrace { cause: cause.clone(), values: ValuePairs::TraitRefs(ExpectedFound::new(a, b)) }
360 }
361}
362
363impl<'tcx> ToTrace<'tcx> for ty::AliasTy<'tcx> {
364 fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
365 TypeTrace {
366 cause: cause.clone(),
367 values: ValuePairs::Aliases(ExpectedFound::new(a.into(), b.into())),
368 }
369 }
370}
371
372impl<'tcx> ToTrace<'tcx> for ty::AliasTerm<'tcx> {
373 fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
374 TypeTrace { cause: cause.clone(), values: ValuePairs::Aliases(ExpectedFound::new(a, b)) }
375 }
376}
377
378impl<'tcx> ToTrace<'tcx> for ty::FnSig<'tcx> {
379 fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
380 TypeTrace {
381 cause: cause.clone(),
382 values: ValuePairs::PolySigs(ExpectedFound::new(
383 ty::Binder::dummy(a),
384 ty::Binder::dummy(b),
385 )),
386 }
387 }
388}
389
390impl<'tcx> ToTrace<'tcx> for ty::PolyFnSig<'tcx> {
391 fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
392 TypeTrace { cause: cause.clone(), values: ValuePairs::PolySigs(ExpectedFound::new(a, b)) }
393 }
394}
395
396impl<'tcx> ToTrace<'tcx> for ty::PolyExistentialTraitRef<'tcx> {
397 fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
398 TypeTrace {
399 cause: cause.clone(),
400 values: ValuePairs::ExistentialTraitRef(ExpectedFound::new(a, b)),
401 }
402 }
403}
404
405impl<'tcx> ToTrace<'tcx> for ty::ExistentialTraitRef<'tcx> {
406 fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
407 TypeTrace {
408 cause: cause.clone(),
409 values: ValuePairs::ExistentialTraitRef(ExpectedFound::new(
410 ty::Binder::dummy(a),
411 ty::Binder::dummy(b),
412 )),
413 }
414 }
415}
416
417impl<'tcx> ToTrace<'tcx> for ty::PolyExistentialProjection<'tcx> {
418 fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
419 TypeTrace {
420 cause: cause.clone(),
421 values: ValuePairs::ExistentialProjection(ExpectedFound::new(a, b)),
422 }
423 }
424}
425
426impl<'tcx> ToTrace<'tcx> for ty::ExistentialProjection<'tcx> {
427 fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
428 TypeTrace {
429 cause: cause.clone(),
430 values: ValuePairs::ExistentialProjection(ExpectedFound::new(
431 ty::Binder::dummy(a),
432 ty::Binder::dummy(b),
433 )),
434 }
435 }
436}