• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! There are four type combiners: [Equate], [Sub], [Lub], and [Glb].
2 //! Each implements the trait [TypeRelation] and contains methods for
3 //! combining two instances of various things and yielding a new instance.
4 //! These combiner methods always yield a `Result<T>`. To relate two
5 //! types, you can use `infcx.at(cause, param_env)` which then allows
6 //! you to use the relevant methods of [At](super::at::At).
7 //!
8 //! Combiners mostly do their specific behavior and then hand off the
9 //! bulk of the work to [InferCtxt::super_combine_tys] and
10 //! [InferCtxt::super_combine_consts].
11 //!
12 //! Combining two types may have side-effects on the inference contexts
13 //! which can be undone by using snapshots. You probably want to use
14 //! either [InferCtxt::commit_if_ok] or [InferCtxt::probe].
15 //!
16 //! On success, the  LUB/GLB operations return the appropriate bound. The
17 //! return value of `Equate` or `Sub` shouldn't really be used.
18 //!
19 //! ## Contravariance
20 //!
21 //! We explicitly track which argument is expected using
22 //! [TypeRelation::a_is_expected], so when dealing with contravariance
23 //! this should be correctly updated.
24 
25 use super::equate::Equate;
26 use super::glb::Glb;
27 use super::lub::Lub;
28 use super::sub::Sub;
29 use super::{DefineOpaqueTypes, InferCtxt, TypeTrace};
30 use crate::infer::generalize::{self, CombineDelegate, Generalization};
31 use crate::traits::{Obligation, PredicateObligations};
32 use rustc_middle::infer::canonical::OriginalQueryValues;
33 use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue};
34 use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
35 use rustc_middle::ty::error::{ExpectedFound, TypeError};
36 use rustc_middle::ty::relate::{RelateResult, TypeRelation};
37 use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeVisitableExt};
38 use rustc_middle::ty::{IntType, UintType};
39 use rustc_span::DUMMY_SP;
40 
41 #[derive(Clone)]
42 pub struct CombineFields<'infcx, 'tcx> {
43     pub infcx: &'infcx InferCtxt<'tcx>,
44     pub trace: TypeTrace<'tcx>,
45     pub cause: Option<ty::relate::Cause>,
46     pub param_env: ty::ParamEnv<'tcx>,
47     pub obligations: PredicateObligations<'tcx>,
48     pub define_opaque_types: DefineOpaqueTypes,
49 }
50 
51 impl<'tcx> InferCtxt<'tcx> {
super_combine_tys<R>( &self, relation: &mut R, a: Ty<'tcx>, b: Ty<'tcx>, ) -> RelateResult<'tcx, Ty<'tcx>> where R: ObligationEmittingRelation<'tcx>,52     pub fn super_combine_tys<R>(
53         &self,
54         relation: &mut R,
55         a: Ty<'tcx>,
56         b: Ty<'tcx>,
57     ) -> RelateResult<'tcx, Ty<'tcx>>
58     where
59         R: ObligationEmittingRelation<'tcx>,
60     {
61         let a_is_expected = relation.a_is_expected();
62         debug_assert!(!a.has_escaping_bound_vars());
63         debug_assert!(!b.has_escaping_bound_vars());
64 
65         match (a.kind(), b.kind()) {
66             // Relate integral variables to other types
67             (&ty::Infer(ty::IntVar(a_id)), &ty::Infer(ty::IntVar(b_id))) => {
68                 self.inner
69                     .borrow_mut()
70                     .int_unification_table()
71                     .unify_var_var(a_id, b_id)
72                     .map_err(|e| int_unification_error(a_is_expected, e))?;
73                 Ok(a)
74             }
75             (&ty::Infer(ty::IntVar(v_id)), &ty::Int(v)) => {
76                 self.unify_integral_variable(a_is_expected, v_id, IntType(v))
77             }
78             (&ty::Int(v), &ty::Infer(ty::IntVar(v_id))) => {
79                 self.unify_integral_variable(!a_is_expected, v_id, IntType(v))
80             }
81             (&ty::Infer(ty::IntVar(v_id)), &ty::Uint(v)) => {
82                 self.unify_integral_variable(a_is_expected, v_id, UintType(v))
83             }
84             (&ty::Uint(v), &ty::Infer(ty::IntVar(v_id))) => {
85                 self.unify_integral_variable(!a_is_expected, v_id, UintType(v))
86             }
87 
88             // Relate floating-point variables to other types
89             (&ty::Infer(ty::FloatVar(a_id)), &ty::Infer(ty::FloatVar(b_id))) => {
90                 self.inner
91                     .borrow_mut()
92                     .float_unification_table()
93                     .unify_var_var(a_id, b_id)
94                     .map_err(|e| float_unification_error(relation.a_is_expected(), e))?;
95                 Ok(a)
96             }
97             (&ty::Infer(ty::FloatVar(v_id)), &ty::Float(v)) => {
98                 self.unify_float_variable(a_is_expected, v_id, v)
99             }
100             (&ty::Float(v), &ty::Infer(ty::FloatVar(v_id))) => {
101                 self.unify_float_variable(!a_is_expected, v_id, v)
102             }
103 
104             // We don't expect `TyVar` or `Fresh*` vars at this point with lazy norm.
105             (
106                 ty::Alias(..),
107                 ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)),
108             )
109             | (
110                 ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)),
111                 ty::Alias(..),
112             ) if self.next_trait_solver() => {
113                 bug!()
114             }
115 
116             (_, ty::Alias(..)) | (ty::Alias(..), _) if self.next_trait_solver() => {
117                 relation.register_type_relate_obligation(a, b);
118                 Ok(a)
119             }
120 
121             // All other cases of inference are errors
122             (&ty::Infer(_), _) | (_, &ty::Infer(_)) => {
123                 Err(TypeError::Sorts(ty::relate::expected_found(relation, a, b)))
124             }
125 
126             // During coherence, opaque types should be treated as *possibly*
127             // equal to any other type (except for possibly itself). This is an
128             // extremely heavy hammer, but can be relaxed in a fowards-compatible
129             // way later.
130             (&ty::Alias(ty::Opaque, _), _) | (_, &ty::Alias(ty::Opaque, _)) if self.intercrate => {
131                 relation.register_predicates([ty::Binder::dummy(ty::PredicateKind::Ambiguous)]);
132                 Ok(a)
133             }
134 
135             _ => ty::relate::structurally_relate_tys(relation, a, b),
136         }
137     }
138 
super_combine_consts<R>( &self, relation: &mut R, a: ty::Const<'tcx>, b: ty::Const<'tcx>, ) -> RelateResult<'tcx, ty::Const<'tcx>> where R: ObligationEmittingRelation<'tcx>,139     pub fn super_combine_consts<R>(
140         &self,
141         relation: &mut R,
142         a: ty::Const<'tcx>,
143         b: ty::Const<'tcx>,
144     ) -> RelateResult<'tcx, ty::Const<'tcx>>
145     where
146         R: ObligationEmittingRelation<'tcx>,
147     {
148         debug!("{}.consts({:?}, {:?})", relation.tag(), a, b);
149         debug_assert!(!a.has_escaping_bound_vars());
150         debug_assert!(!b.has_escaping_bound_vars());
151         if a == b {
152             return Ok(a);
153         }
154 
155         let a = self.shallow_resolve(a);
156         let b = self.shallow_resolve(b);
157 
158         // We should never have to relate the `ty` field on `Const` as it is checked elsewhere that consts have the
159         // correct type for the generic param they are an argument for. However there have been a number of cases
160         // historically where asserting that the types are equal has found bugs in the compiler so this is valuable
161         // to check even if it is a bit nasty impl wise :(
162         //
163         // This probe is probably not strictly necessary but it seems better to be safe and not accidentally find
164         // ourselves with a check to find bugs being required for code to compile because it made inference progress.
165         let compatible_types = self.probe(|_| {
166             if a.ty() == b.ty() {
167                 return Ok(());
168             }
169 
170             // We don't have access to trait solving machinery in `rustc_infer` so the logic for determining if the
171             // two const param's types are able to be equal has to go through a canonical query with the actual logic
172             // in `rustc_trait_selection`.
173             let canonical = self.canonicalize_query(
174                 (relation.param_env(), a.ty(), b.ty()),
175                 &mut OriginalQueryValues::default(),
176             );
177             self.tcx.check_tys_might_be_eq(canonical).map_err(|_| {
178                 self.tcx.sess.delay_span_bug(
179                     DUMMY_SP,
180                     format!("cannot relate consts of different types (a={:?}, b={:?})", a, b,),
181                 )
182             })
183         });
184 
185         // If the consts have differing types, just bail with a const error with
186         // the expected const's type. Specifically, we don't want const infer vars
187         // to do any type shapeshifting before and after resolution.
188         if let Err(guar) = compatible_types {
189             // HACK: equating both sides with `[const error]` eagerly prevents us
190             // from leaving unconstrained inference vars during things like impl
191             // matching in the solver.
192             let a_error = ty::Const::new_error(self.tcx, guar, a.ty());
193             if let ty::ConstKind::Infer(InferConst::Var(vid)) = a.kind() {
194                 return self.unify_const_variable(vid, a_error, relation.param_env());
195             }
196             let b_error = ty::Const::new_error(self.tcx, guar, b.ty());
197             if let ty::ConstKind::Infer(InferConst::Var(vid)) = b.kind() {
198                 return self.unify_const_variable(vid, b_error, relation.param_env());
199             }
200 
201             return Ok(if relation.a_is_expected() { a_error } else { b_error });
202         }
203 
204         match (a.kind(), b.kind()) {
205             (
206                 ty::ConstKind::Infer(InferConst::Var(a_vid)),
207                 ty::ConstKind::Infer(InferConst::Var(b_vid)),
208             ) => {
209                 self.inner.borrow_mut().const_unification_table().union(a_vid, b_vid);
210                 return Ok(a);
211             }
212 
213             // All other cases of inference with other variables are errors.
214             (ty::ConstKind::Infer(InferConst::Var(_)), ty::ConstKind::Infer(_))
215             | (ty::ConstKind::Infer(_), ty::ConstKind::Infer(InferConst::Var(_))) => {
216                 bug!("tried to combine ConstKind::Infer/ConstKind::Infer(InferConst::Var)")
217             }
218 
219             (ty::ConstKind::Infer(InferConst::Var(vid)), _) => {
220                 return self.unify_const_variable(vid, b, relation.param_env());
221             }
222 
223             (_, ty::ConstKind::Infer(InferConst::Var(vid))) => {
224                 return self.unify_const_variable(vid, a, relation.param_env());
225             }
226             (ty::ConstKind::Unevaluated(..), _) | (_, ty::ConstKind::Unevaluated(..))
227                 if self.tcx.features().generic_const_exprs || self.next_trait_solver() =>
228             {
229                 let (a, b) = if relation.a_is_expected() { (a, b) } else { (b, a) };
230 
231                 relation.register_predicates([ty::Binder::dummy(if self.next_trait_solver() {
232                     ty::PredicateKind::AliasRelate(
233                         a.into(),
234                         b.into(),
235                         ty::AliasRelationDirection::Equate,
236                     )
237                 } else {
238                     ty::PredicateKind::ConstEquate(a, b)
239                 })]);
240 
241                 return Ok(b);
242             }
243             _ => {}
244         }
245 
246         ty::relate::structurally_relate_consts(relation, a, b)
247     }
248 
249     /// Unifies the const variable `target_vid` with the given constant.
250     ///
251     /// This also tests if the given const `ct` contains an inference variable which was previously
252     /// unioned with `target_vid`. If this is the case, inferring `target_vid` to `ct`
253     /// would result in an infinite type as we continuously replace an inference variable
254     /// in `ct` with `ct` itself.
255     ///
256     /// This is especially important as unevaluated consts use their parents generics.
257     /// They therefore often contain unused substs, making these errors far more likely.
258     ///
259     /// A good example of this is the following:
260     ///
261     /// ```compile_fail,E0308
262     /// #![feature(generic_const_exprs)]
263     ///
264     /// fn bind<const N: usize>(value: [u8; N]) -> [u8; 3 + 4] {
265     ///     todo!()
266     /// }
267     ///
268     /// fn main() {
269     ///     let mut arr = Default::default();
270     ///     arr = bind(arr);
271     /// }
272     /// ```
273     ///
274     /// Here `3 + 4` ends up as `ConstKind::Unevaluated` which uses the generics
275     /// of `fn bind` (meaning that its substs contain `N`).
276     ///
277     /// `bind(arr)` now infers that the type of `arr` must be `[u8; N]`.
278     /// The assignment `arr = bind(arr)` now tries to equate `N` with `3 + 4`.
279     ///
280     /// As `3 + 4` contains `N` in its substs, this must not succeed.
281     ///
282     /// See `tests/ui/const-generics/occurs-check/` for more examples where this is relevant.
283     #[instrument(level = "debug", skip(self))]
unify_const_variable( &self, target_vid: ty::ConstVid<'tcx>, ct: ty::Const<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> RelateResult<'tcx, ty::Const<'tcx>>284     fn unify_const_variable(
285         &self,
286         target_vid: ty::ConstVid<'tcx>,
287         ct: ty::Const<'tcx>,
288         param_env: ty::ParamEnv<'tcx>,
289     ) -> RelateResult<'tcx, ty::Const<'tcx>> {
290         let span =
291             self.inner.borrow_mut().const_unification_table().probe_value(target_vid).origin.span;
292         let Generalization { value, needs_wf: _ } = generalize::generalize(
293             self,
294             &mut CombineDelegate { infcx: self, span, param_env },
295             ct,
296             target_vid,
297             ty::Variance::Invariant,
298         )?;
299 
300         self.inner.borrow_mut().const_unification_table().union_value(
301             target_vid,
302             ConstVarValue {
303                 origin: ConstVariableOrigin {
304                     kind: ConstVariableOriginKind::ConstInference,
305                     span: DUMMY_SP,
306                 },
307                 val: ConstVariableValue::Known { value },
308             },
309         );
310         Ok(value)
311     }
312 
unify_integral_variable( &self, vid_is_expected: bool, vid: ty::IntVid, val: ty::IntVarValue, ) -> RelateResult<'tcx, Ty<'tcx>>313     fn unify_integral_variable(
314         &self,
315         vid_is_expected: bool,
316         vid: ty::IntVid,
317         val: ty::IntVarValue,
318     ) -> RelateResult<'tcx, Ty<'tcx>> {
319         self.inner
320             .borrow_mut()
321             .int_unification_table()
322             .unify_var_value(vid, Some(val))
323             .map_err(|e| int_unification_error(vid_is_expected, e))?;
324         match val {
325             IntType(v) => Ok(Ty::new_int(self.tcx, v)),
326             UintType(v) => Ok(Ty::new_uint(self.tcx, v)),
327         }
328     }
329 
unify_float_variable( &self, vid_is_expected: bool, vid: ty::FloatVid, val: ty::FloatTy, ) -> RelateResult<'tcx, Ty<'tcx>>330     fn unify_float_variable(
331         &self,
332         vid_is_expected: bool,
333         vid: ty::FloatVid,
334         val: ty::FloatTy,
335     ) -> RelateResult<'tcx, Ty<'tcx>> {
336         self.inner
337             .borrow_mut()
338             .float_unification_table()
339             .unify_var_value(vid, Some(ty::FloatVarValue(val)))
340             .map_err(|e| float_unification_error(vid_is_expected, e))?;
341         Ok(Ty::new_float(self.tcx, val))
342     }
343 }
344 
345 impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
tcx(&self) -> TyCtxt<'tcx>346     pub fn tcx(&self) -> TyCtxt<'tcx> {
347         self.infcx.tcx
348     }
349 
equate<'a>(&'a mut self, a_is_expected: bool) -> Equate<'a, 'infcx, 'tcx>350     pub fn equate<'a>(&'a mut self, a_is_expected: bool) -> Equate<'a, 'infcx, 'tcx> {
351         Equate::new(self, a_is_expected)
352     }
353 
sub<'a>(&'a mut self, a_is_expected: bool) -> Sub<'a, 'infcx, 'tcx>354     pub fn sub<'a>(&'a mut self, a_is_expected: bool) -> Sub<'a, 'infcx, 'tcx> {
355         Sub::new(self, a_is_expected)
356     }
357 
lub<'a>(&'a mut self, a_is_expected: bool) -> Lub<'a, 'infcx, 'tcx>358     pub fn lub<'a>(&'a mut self, a_is_expected: bool) -> Lub<'a, 'infcx, 'tcx> {
359         Lub::new(self, a_is_expected)
360     }
361 
glb<'a>(&'a mut self, a_is_expected: bool) -> Glb<'a, 'infcx, 'tcx>362     pub fn glb<'a>(&'a mut self, a_is_expected: bool) -> Glb<'a, 'infcx, 'tcx> {
363         Glb::new(self, a_is_expected)
364     }
365 
366     /// Here, `dir` is either `EqTo`, `SubtypeOf`, or `SupertypeOf`.
367     /// The idea is that we should ensure that the type `a_ty` is equal
368     /// to, a subtype of, or a supertype of (respectively) the type
369     /// to which `b_vid` is bound.
370     ///
371     /// Since `b_vid` has not yet been instantiated with a type, we
372     /// will first instantiate `b_vid` with a *generalized* version
373     /// of `a_ty`. Generalization introduces other inference
374     /// variables wherever subtyping could occur.
375     #[instrument(skip(self), level = "debug")]
instantiate( &mut self, a_ty: Ty<'tcx>, ambient_variance: ty::Variance, b_vid: ty::TyVid, a_is_expected: bool, ) -> RelateResult<'tcx, ()>376     pub fn instantiate(
377         &mut self,
378         a_ty: Ty<'tcx>,
379         ambient_variance: ty::Variance,
380         b_vid: ty::TyVid,
381         a_is_expected: bool,
382     ) -> RelateResult<'tcx, ()> {
383         // Get the actual variable that b_vid has been inferred to
384         debug_assert!(self.infcx.inner.borrow_mut().type_variables().probe(b_vid).is_unknown());
385 
386         // Generalize type of `a_ty` appropriately depending on the
387         // direction. As an example, assume:
388         //
389         // - `a_ty == &'x ?1`, where `'x` is some free region and `?1` is an
390         //   inference variable,
391         // - and `dir` == `SubtypeOf`.
392         //
393         // Then the generalized form `b_ty` would be `&'?2 ?3`, where
394         // `'?2` and `?3` are fresh region/type inference
395         // variables. (Down below, we will relate `a_ty <: b_ty`,
396         // adding constraints like `'x: '?2` and `?1 <: ?3`.)
397         let Generalization { value: b_ty, needs_wf } = generalize::generalize(
398             self.infcx,
399             &mut CombineDelegate {
400                 infcx: self.infcx,
401                 param_env: self.param_env,
402                 span: self.trace.span(),
403             },
404             a_ty,
405             b_vid,
406             ambient_variance,
407         )?;
408 
409         debug!(?b_ty);
410         self.infcx.inner.borrow_mut().type_variables().instantiate(b_vid, b_ty);
411 
412         if needs_wf {
413             self.obligations.push(Obligation::new(
414                 self.tcx(),
415                 self.trace.cause.clone(),
416                 self.param_env,
417                 ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(
418                     b_ty.into(),
419                 ))),
420             ));
421         }
422 
423         // Finally, relate `b_ty` to `a_ty`, as described in previous comment.
424         //
425         // FIXME(#16847): This code is non-ideal because all these subtype
426         // relations wind up attributed to the same spans. We need
427         // to associate causes/spans with each of the relations in
428         // the stack to get this right.
429         match ambient_variance {
430             ty::Variance::Invariant => self.equate(a_is_expected).relate(a_ty, b_ty),
431             ty::Variance::Covariant => self.sub(a_is_expected).relate(a_ty, b_ty),
432             ty::Variance::Contravariant => self.sub(a_is_expected).relate_with_variance(
433                 ty::Contravariant,
434                 ty::VarianceDiagInfo::default(),
435                 a_ty,
436                 b_ty,
437             ),
438             ty::Variance::Bivariant => {
439                 unreachable!("no code should be generalizing bivariantly (currently)")
440             }
441         }?;
442 
443         Ok(())
444     }
445 
register_obligations(&mut self, obligations: PredicateObligations<'tcx>)446     pub fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
447         self.obligations.extend(obligations.into_iter());
448     }
449 
register_predicates(&mut self, obligations: impl IntoIterator<Item: ToPredicate<'tcx>>)450     pub fn register_predicates(&mut self, obligations: impl IntoIterator<Item: ToPredicate<'tcx>>) {
451         self.obligations.extend(obligations.into_iter().map(|to_pred| {
452             Obligation::new(self.infcx.tcx, self.trace.cause.clone(), self.param_env, to_pred)
453         }))
454     }
455 }
456 
457 pub trait ObligationEmittingRelation<'tcx>: TypeRelation<'tcx> {
458     /// Register obligations that must hold in order for this relation to hold
register_obligations(&mut self, obligations: PredicateObligations<'tcx>)459     fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>);
460 
461     /// Register predicates that must hold in order for this relation to hold. Uses
462     /// a default obligation cause, [`ObligationEmittingRelation::register_obligations`] should
463     /// be used if control over the obligation causes is required.
register_predicates(&mut self, obligations: impl IntoIterator<Item: ToPredicate<'tcx>>)464     fn register_predicates(&mut self, obligations: impl IntoIterator<Item: ToPredicate<'tcx>>);
465 
466     /// Register an obligation that both types must be related to each other according to
467     /// the [`ty::AliasRelationDirection`] given by [`ObligationEmittingRelation::alias_relate_direction`]
register_type_relate_obligation(&mut self, a: Ty<'tcx>, b: Ty<'tcx>)468     fn register_type_relate_obligation(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) {
469         self.register_predicates([ty::Binder::dummy(ty::PredicateKind::AliasRelate(
470             a.into(),
471             b.into(),
472             self.alias_relate_direction(),
473         ))]);
474     }
475 
476     /// Relation direction emitted for `AliasRelate` predicates, corresponding to the direction
477     /// of the relation.
alias_relate_direction(&self) -> ty::AliasRelationDirection478     fn alias_relate_direction(&self) -> ty::AliasRelationDirection;
479 }
480 
int_unification_error<'tcx>( a_is_expected: bool, v: (ty::IntVarValue, ty::IntVarValue), ) -> TypeError<'tcx>481 fn int_unification_error<'tcx>(
482     a_is_expected: bool,
483     v: (ty::IntVarValue, ty::IntVarValue),
484 ) -> TypeError<'tcx> {
485     let (a, b) = v;
486     TypeError::IntMismatch(ExpectedFound::new(a_is_expected, a, b))
487 }
488 
float_unification_error<'tcx>( a_is_expected: bool, v: (ty::FloatVarValue, ty::FloatVarValue), ) -> TypeError<'tcx>489 fn float_unification_error<'tcx>(
490     a_is_expected: bool,
491     v: (ty::FloatVarValue, ty::FloatVarValue),
492 ) -> TypeError<'tcx> {
493     let (ty::FloatVarValue(a), ty::FloatVarValue(b)) = v;
494     TypeError::FloatMismatch(ExpectedFound::new(a_is_expected, a, b))
495 }
496