]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_infer/src/infer/at.rs
New upstream version 1.70.0+dfsg1
[rustc.git] / compiler / rustc_infer / src / infer / at.rs
CommitLineData
9fa01778 1//! A nice interface for working with the infcx. The basic idea is to
7cac9316 2//! do `infcx.at(cause, param_env)`, which sets the "cause" of the
9fa01778 3//! operation as well as the surrounding parameter environment. Then
7cac9316
XL
4//! you can do something like `.sub(a, b)` or `.eq(a, b)` to create a
5//! subtype or equality relationship respectively. The first argument
6//! is always the "expected" output from the POV of diagnostics.
7//!
8//! Examples:
04454e1e 9//! ```ignore (fragment)
7cac9316
XL
10//! infcx.at(cause, param_env).sub(a, b)
11//! // requires that `a <: b`, with `a` considered the "expected" type
12//!
13//! infcx.at(cause, param_env).sup(a, b)
14//! // requires that `b <: a`, with `a` considered the "expected" type
15//!
16//! infcx.at(cause, param_env).eq(a, b)
17//! // requires that `a == b`, with `a` considered the "expected" type
04454e1e 18//! ```
7cac9316 19//! For finer-grained control, you can also do use `trace`:
04454e1e 20//! ```ignore (fragment)
7cac9316 21//! infcx.at(...).trace(a, b).sub(&c, &d)
04454e1e 22//! ```
7cac9316
XL
23//! This will set `a` and `b` as the "root" values for
24//! error-reporting, but actually operate on `c` and `d`. This is
25//! sometimes useful when the types of `c` and `d` are not traceable
26//! things. (That system should probably be refactored.)
27
28use super::*;
29
ba9703b0 30use rustc_middle::ty::relate::{Relate, TypeRelation};
5e7ed085 31use rustc_middle::ty::{Const, ImplSubject};
7cac9316 32
353b0b11
FG
33use std::cell::Cell;
34
35/// Whether we should define opaque types or just treat them opaquely.
36///
37/// Currently only used to prevent predicate matching from matching anything
38/// against opaque types.
39#[derive(Debug, PartialEq, Eq, Clone, Copy)]
40pub enum DefineOpaqueTypes {
41 Yes,
42 No,
43}
44
dc9dc135 45pub struct At<'a, 'tcx> {
2b03887a 46 pub infcx: &'a InferCtxt<'tcx>,
0531ce1d
XL
47 pub cause: &'a ObligationCause<'tcx>,
48 pub param_env: ty::ParamEnv<'tcx>,
7cac9316
XL
49}
50
dc9dc135
XL
51pub struct Trace<'a, 'tcx> {
52 at: At<'a, 'tcx>,
7cac9316
XL
53 a_is_expected: bool,
54 trace: TypeTrace<'tcx>,
55}
56
2b03887a 57impl<'tcx> InferCtxt<'tcx> {
a1dfa0c6 58 #[inline]
2b03887a 59 pub fn at<'a>(
dc9dc135
XL
60 &'a self,
61 cause: &'a ObligationCause<'tcx>,
62 param_env: ty::ParamEnv<'tcx>,
63 ) -> At<'a, 'tcx> {
353b0b11 64 At { infcx: self, cause, param_env }
7cac9316 65 }
5099ac24
FG
66
67 /// Forks the inference context, creating a new inference context with the same inference
68 /// variables in the same state. This can be used to "branch off" many tests from the same
69 /// common state. Used in coherence.
70 pub fn fork(&self) -> Self {
71 Self {
04454e1e
FG
72 tcx: self.tcx,
73 defining_use_anchor: self.defining_use_anchor,
064997fb 74 considering_regions: self.considering_regions,
5099ac24
FG
75 inner: self.inner.clone(),
76 skip_leak_check: self.skip_leak_check.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_closure_mismatch: self.reported_closure_mismatch.clone(),
f2b60f7d 82 tainted_by_errors: self.tainted_by_errors.clone(),
5099ac24
FG
83 err_count_on_creation: self.err_count_on_creation,
84 in_snapshot: self.in_snapshot.clone(),
85 universe: self.universe.clone(),
487cf647 86 intercrate: self.intercrate,
353b0b11 87 inside_canonicalization_ctxt: Cell::new(self.inside_canonicalization_ctxt()),
5099ac24
FG
88 }
89 }
7cac9316
XL
90}
91
92pub trait ToTrace<'tcx>: Relate<'tcx> + Copy {
dfeec247
XL
93 fn to_trace(
94 cause: &ObligationCause<'tcx>,
95 a_is_expected: bool,
96 a: Self,
97 b: Self,
98 ) -> TypeTrace<'tcx>;
7cac9316
XL
99}
100
dc9dc135 101impl<'a, 'tcx> At<'a, 'tcx> {
9fa01778 102 /// Makes `a <: b`, where `a` may or may not be expected.
923072b8
FG
103 ///
104 /// See [`At::trace_exp`] and [`Trace::sub`] for a version of
105 /// this method that only requires `T: Relate<'tcx>`
353b0b11
FG
106 pub fn sub_exp<T>(
107 self,
108 define_opaque_types: DefineOpaqueTypes,
109 a_is_expected: bool,
110 a: T,
111 b: T,
112 ) -> InferResult<'tcx, ()>
dfeec247
XL
113 where
114 T: ToTrace<'tcx>,
7cac9316 115 {
353b0b11 116 self.trace_exp(a_is_expected, a, b).sub(define_opaque_types, a, b)
7cac9316
XL
117 }
118
9fa01778 119 /// Makes `actual <: expected`. For example, if type-checking a
7cac9316
XL
120 /// call like `foo(x)`, where `foo: fn(i32)`, you might have
121 /// `sup(i32, x)`, since the "expected" type is the type that
122 /// appears in the signature.
923072b8
FG
123 ///
124 /// See [`At::trace`] and [`Trace::sub`] for a version of
125 /// this method that only requires `T: Relate<'tcx>`
353b0b11
FG
126 pub fn sup<T>(
127 self,
128 define_opaque_types: DefineOpaqueTypes,
129 expected: T,
130 actual: T,
131 ) -> InferResult<'tcx, ()>
dfeec247
XL
132 where
133 T: ToTrace<'tcx>,
7cac9316 134 {
353b0b11 135 self.sub_exp(define_opaque_types, false, actual, expected)
7cac9316
XL
136 }
137
9fa01778 138 /// Makes `expected <: actual`.
923072b8
FG
139 ///
140 /// See [`At::trace`] and [`Trace::sub`] for a version of
141 /// this method that only requires `T: Relate<'tcx>`
353b0b11
FG
142 pub fn sub<T>(
143 self,
144 define_opaque_types: DefineOpaqueTypes,
145 expected: T,
146 actual: T,
147 ) -> InferResult<'tcx, ()>
dfeec247
XL
148 where
149 T: ToTrace<'tcx>,
7cac9316 150 {
353b0b11 151 self.sub_exp(define_opaque_types, true, expected, actual)
7cac9316
XL
152 }
153
9fa01778 154 /// Makes `expected <: actual`.
923072b8
FG
155 ///
156 /// See [`At::trace_exp`] and [`Trace::eq`] for a version of
157 /// this method that only requires `T: Relate<'tcx>`
353b0b11
FG
158 pub fn eq_exp<T>(
159 self,
160 define_opaque_types: DefineOpaqueTypes,
161 a_is_expected: bool,
162 a: T,
163 b: T,
164 ) -> InferResult<'tcx, ()>
dfeec247
XL
165 where
166 T: ToTrace<'tcx>,
7cac9316 167 {
353b0b11 168 self.trace_exp(a_is_expected, a, b).eq(define_opaque_types, a, b)
7cac9316
XL
169 }
170
9fa01778 171 /// Makes `expected <: actual`.
923072b8
FG
172 ///
173 /// See [`At::trace`] and [`Trace::eq`] for a version of
174 /// this method that only requires `T: Relate<'tcx>`
353b0b11
FG
175 pub fn eq<T>(
176 self,
177 define_opaque_types: DefineOpaqueTypes,
178 expected: T,
179 actual: T,
180 ) -> InferResult<'tcx, ()>
dfeec247
XL
181 where
182 T: ToTrace<'tcx>,
7cac9316 183 {
353b0b11 184 self.trace(expected, actual).eq(define_opaque_types, expected, actual)
7cac9316
XL
185 }
186
353b0b11
FG
187 pub fn relate<T>(
188 self,
189 define_opaque_types: DefineOpaqueTypes,
190 expected: T,
191 variance: ty::Variance,
192 actual: T,
193 ) -> InferResult<'tcx, ()>
dfeec247
XL
194 where
195 T: ToTrace<'tcx>,
0bf4aa26
XL
196 {
197 match variance {
353b0b11
FG
198 ty::Variance::Covariant => self.sub(define_opaque_types, expected, actual),
199 ty::Variance::Invariant => self.eq(define_opaque_types, expected, actual),
200 ty::Variance::Contravariant => self.sup(define_opaque_types, expected, actual),
0bf4aa26
XL
201
202 // We could make this make sense but it's not readily
203 // exposed and I don't feel like dealing with it. Note
204 // that bivariance in general does a bit more than just
205 // *nothing*, it checks that the types are the same
206 // "modulo variance" basically.
207 ty::Variance::Bivariant => panic!("Bivariant given to `relate()`"),
208 }
209 }
210
9fa01778 211 /// Computes the least-upper-bound, or mutual supertype, of two
7cac9316
XL
212 /// values. The order of the arguments doesn't matter, but since
213 /// this can result in an error (e.g., if asked to compute LUB of
214 /// u32 and i32), it is meaningful to call one of them the
215 /// "expected type".
923072b8
FG
216 ///
217 /// See [`At::trace`] and [`Trace::lub`] for a version of
218 /// this method that only requires `T: Relate<'tcx>`
353b0b11
FG
219 pub fn lub<T>(
220 self,
221 define_opaque_types: DefineOpaqueTypes,
222 expected: T,
223 actual: T,
224 ) -> InferResult<'tcx, T>
dfeec247
XL
225 where
226 T: ToTrace<'tcx>,
7cac9316 227 {
353b0b11 228 self.trace(expected, actual).lub(define_opaque_types, expected, actual)
7cac9316
XL
229 }
230
9fa01778 231 /// Computes the greatest-lower-bound, or mutual subtype, of two
7cac9316
XL
232 /// values. As with `lub` order doesn't matter, except for error
233 /// cases.
923072b8
FG
234 ///
235 /// See [`At::trace`] and [`Trace::glb`] for a version of
236 /// this method that only requires `T: Relate<'tcx>`
353b0b11
FG
237 pub fn glb<T>(
238 self,
239 define_opaque_types: DefineOpaqueTypes,
240 expected: T,
241 actual: T,
242 ) -> InferResult<'tcx, T>
dfeec247
XL
243 where
244 T: ToTrace<'tcx>,
7cac9316 245 {
353b0b11 246 self.trace(expected, actual).glb(define_opaque_types, expected, actual)
7cac9316
XL
247 }
248
249 /// Sets the "trace" values that will be used for
3b2f2976 250 /// error-reporting, but doesn't actually perform any operation
7cac9316
XL
251 /// yet (this is useful when you want to set the trace using
252 /// distinct values from those you wish to operate upon).
dc9dc135
XL
253 pub fn trace<T>(self, expected: T, actual: T) -> Trace<'a, 'tcx>
254 where
255 T: ToTrace<'tcx>,
7cac9316
XL
256 {
257 self.trace_exp(true, expected, actual)
258 }
259
260 /// Like `trace`, but the expected value is determined by the
261 /// boolean argument (if true, then the first argument `a` is the
262 /// "expected" value).
dc9dc135
XL
263 pub fn trace_exp<T>(self, a_is_expected: bool, a: T, b: T) -> Trace<'a, 'tcx>
264 where
265 T: ToTrace<'tcx>,
7cac9316 266 {
353b0b11 267 let trace = ToTrace::to_trace(self.cause, a_is_expected, a, b);
74b04a01 268 Trace { at: self, trace, a_is_expected }
7cac9316
XL
269 }
270}
271
dc9dc135 272impl<'a, 'tcx> Trace<'a, 'tcx> {
9fa01778 273 /// Makes `a <: b` where `a` may or may not be expected (if
7cac9316 274 /// `a_is_expected` is true, then `a` is expected).
c295e0f8 275 #[instrument(skip(self), level = "debug")]
353b0b11 276 pub fn sub<T>(self, define_opaque_types: DefineOpaqueTypes, a: T, b: T) -> InferResult<'tcx, ()>
dfeec247
XL
277 where
278 T: Relate<'tcx>,
7cac9316 279 {
7cac9316
XL
280 let Trace { at, trace, a_is_expected } = self;
281 at.infcx.commit_if_ok(|_| {
353b0b11 282 let mut fields = at.infcx.combine_fields(trace, at.param_env, define_opaque_types);
dfeec247
XL
283 fields
284 .sub(a_is_expected)
285 .relate(a, b)
286 .map(move |_| InferOk { value: (), obligations: fields.obligations })
7cac9316
XL
287 })
288 }
289
9fa01778 290 /// Makes `a == b`; the expectation is set by the call to
7cac9316 291 /// `trace()`.
c295e0f8 292 #[instrument(skip(self), level = "debug")]
353b0b11 293 pub fn eq<T>(self, define_opaque_types: DefineOpaqueTypes, a: T, b: T) -> InferResult<'tcx, ()>
dfeec247
XL
294 where
295 T: Relate<'tcx>,
7cac9316 296 {
7cac9316
XL
297 let Trace { at, trace, a_is_expected } = self;
298 at.infcx.commit_if_ok(|_| {
353b0b11 299 let mut fields = at.infcx.combine_fields(trace, at.param_env, define_opaque_types);
dfeec247
XL
300 fields
301 .equate(a_is_expected)
302 .relate(a, b)
303 .map(move |_| InferOk { value: (), obligations: fields.obligations })
7cac9316
XL
304 })
305 }
306
c295e0f8 307 #[instrument(skip(self), level = "debug")]
353b0b11 308 pub fn lub<T>(self, define_opaque_types: DefineOpaqueTypes, a: T, b: T) -> InferResult<'tcx, T>
dfeec247
XL
309 where
310 T: Relate<'tcx>,
7cac9316 311 {
7cac9316
XL
312 let Trace { at, trace, a_is_expected } = self;
313 at.infcx.commit_if_ok(|_| {
353b0b11 314 let mut fields = at.infcx.combine_fields(trace, at.param_env, define_opaque_types);
dfeec247
XL
315 fields
316 .lub(a_is_expected)
317 .relate(a, b)
318 .map(move |t| InferOk { value: t, obligations: fields.obligations })
7cac9316
XL
319 })
320 }
321
c295e0f8 322 #[instrument(skip(self), level = "debug")]
353b0b11 323 pub fn glb<T>(self, define_opaque_types: DefineOpaqueTypes, a: T, b: T) -> InferResult<'tcx, T>
dfeec247
XL
324 where
325 T: Relate<'tcx>,
7cac9316 326 {
7cac9316
XL
327 let Trace { at, trace, a_is_expected } = self;
328 at.infcx.commit_if_ok(|_| {
353b0b11 329 let mut fields = at.infcx.combine_fields(trace, at.param_env, define_opaque_types);
dfeec247
XL
330 fields
331 .glb(a_is_expected)
332 .relate(a, b)
333 .map(move |t| InferOk { value: t, obligations: fields.obligations })
7cac9316
XL
334 })
335 }
336}
337
5e7ed085
FG
338impl<'tcx> ToTrace<'tcx> for ImplSubject<'tcx> {
339 fn to_trace(
5e7ed085
FG
340 cause: &ObligationCause<'tcx>,
341 a_is_expected: bool,
342 a: Self,
343 b: Self,
344 ) -> TypeTrace<'tcx> {
345 match (a, b) {
346 (ImplSubject::Trait(trait_ref_a), ImplSubject::Trait(trait_ref_b)) => {
353b0b11 347 ToTrace::to_trace(cause, a_is_expected, trait_ref_a, trait_ref_b)
5e7ed085
FG
348 }
349 (ImplSubject::Inherent(ty_a), ImplSubject::Inherent(ty_b)) => {
353b0b11 350 ToTrace::to_trace(cause, a_is_expected, ty_a, ty_b)
5e7ed085
FG
351 }
352 (ImplSubject::Trait(_), ImplSubject::Inherent(_))
353 | (ImplSubject::Inherent(_), ImplSubject::Trait(_)) => {
354 bug!("can not trace TraitRef and Ty");
355 }
356 }
357 }
358}
359
7cac9316 360impl<'tcx> ToTrace<'tcx> for Ty<'tcx> {
dfeec247
XL
361 fn to_trace(
362 cause: &ObligationCause<'tcx>,
363 a_is_expected: bool,
364 a: Self,
365 b: Self,
366 ) -> TypeTrace<'tcx> {
5099ac24
FG
367 TypeTrace {
368 cause: cause.clone(),
369 values: Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
370 }
7cac9316
XL
371 }
372}
373
0531ce1d 374impl<'tcx> ToTrace<'tcx> for ty::Region<'tcx> {
dfeec247
XL
375 fn to_trace(
376 cause: &ObligationCause<'tcx>,
377 a_is_expected: bool,
378 a: Self,
379 b: Self,
380 ) -> TypeTrace<'tcx> {
381 TypeTrace { cause: cause.clone(), values: Regions(ExpectedFound::new(a_is_expected, a, b)) }
0531ce1d
XL
382 }
383}
384
5099ac24
FG
385impl<'tcx> ToTrace<'tcx> for Const<'tcx> {
386 fn to_trace(
5099ac24
FG
387 cause: &ObligationCause<'tcx>,
388 a_is_expected: bool,
389 a: Self,
390 b: Self,
391 ) -> TypeTrace<'tcx> {
392 TypeTrace {
393 cause: cause.clone(),
394 values: Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
395 }
396 }
397}
398
9ffffee4
FG
399impl<'tcx> ToTrace<'tcx> for ty::GenericArg<'tcx> {
400 fn to_trace(
9ffffee4
FG
401 cause: &ObligationCause<'tcx>,
402 a_is_expected: bool,
403 a: Self,
404 b: Self,
405 ) -> TypeTrace<'tcx> {
406 use GenericArgKind::*;
407 TypeTrace {
408 cause: cause.clone(),
409 values: match (a.unpack(), b.unpack()) {
410 (Lifetime(a), Lifetime(b)) => Regions(ExpectedFound::new(a_is_expected, a, b)),
411 (Type(a), Type(b)) => Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
412 (Const(a), Const(b)) => {
413 Terms(ExpectedFound::new(a_is_expected, a.into(), b.into()))
414 }
415
416 (Lifetime(_), Type(_) | Const(_))
417 | (Type(_), Lifetime(_) | Const(_))
418 | (Const(_), Lifetime(_) | Type(_)) => {
419 bug!("relating different kinds: {a:?} {b:?}")
420 }
421 },
422 }
423 }
424}
425
5099ac24 426impl<'tcx> ToTrace<'tcx> for ty::Term<'tcx> {
dfeec247
XL
427 fn to_trace(
428 cause: &ObligationCause<'tcx>,
429 a_is_expected: bool,
430 a: Self,
431 b: Self,
432 ) -> TypeTrace<'tcx> {
5099ac24 433 TypeTrace { cause: cause.clone(), values: Terms(ExpectedFound::new(a_is_expected, a, b)) }
48663c56
XL
434 }
435}
436
7cac9316 437impl<'tcx> ToTrace<'tcx> for ty::TraitRef<'tcx> {
dfeec247
XL
438 fn to_trace(
439 cause: &ObligationCause<'tcx>,
440 a_is_expected: bool,
441 a: Self,
442 b: Self,
443 ) -> TypeTrace<'tcx> {
7cac9316
XL
444 TypeTrace {
445 cause: cause.clone(),
dfeec247 446 values: TraitRefs(ExpectedFound::new(a_is_expected, a, b)),
7cac9316
XL
447 }
448 }
449}
450
451impl<'tcx> ToTrace<'tcx> for ty::PolyTraitRef<'tcx> {
dfeec247
XL
452 fn to_trace(
453 cause: &ObligationCause<'tcx>,
454 a_is_expected: bool,
455 a: Self,
456 b: Self,
457 ) -> TypeTrace<'tcx> {
7cac9316
XL
458 TypeTrace {
459 cause: cause.clone(),
dfeec247 460 values: PolyTraitRefs(ExpectedFound::new(a_is_expected, a, b)),
7cac9316
XL
461 }
462 }
463}
6a06907d 464
9c376795 465impl<'tcx> ToTrace<'tcx> for ty::AliasTy<'tcx> {
6a06907d 466 fn to_trace(
6a06907d
XL
467 cause: &ObligationCause<'tcx>,
468 a_is_expected: bool,
469 a: Self,
470 b: Self,
471 ) -> TypeTrace<'tcx> {
353b0b11 472 TypeTrace { cause: cause.clone(), values: Aliases(ExpectedFound::new(a_is_expected, a, b)) }
6a06907d
XL
473 }
474}
9c376795
FG
475
476impl<'tcx> ToTrace<'tcx> for ty::FnSig<'tcx> {
477 fn to_trace(
9c376795
FG
478 cause: &ObligationCause<'tcx>,
479 a_is_expected: bool,
480 a: Self,
481 b: Self,
482 ) -> TypeTrace<'tcx> {
483 TypeTrace { cause: cause.clone(), values: Sigs(ExpectedFound::new(a_is_expected, a, b)) }
484 }
485}