1 //! Routines to check for relations between fully inferred types.
3 //! FIXME: Move this to a more general place. The utility of this extends to
4 //! other areas of the compiler as well.
6 use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt};
7 use rustc_infer::traits::ObligationCause;
8 use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
9 use rustc_trait_selection::traits::ObligationCtxt;
11 /// Returns whether the two types are equal up to subtyping.
13 /// This is used in case we don't know the expected subtyping direction
14 /// and still want to check whether anything is broken.
15 pub fn is_equal_up_to_subtyping<'tcx>(
17 param_env: ParamEnv<'tcx>,
26 // Check for subtyping in either direction.
27 is_subtype(tcx, param_env, src, dest) || is_subtype(tcx, param_env, dest, src)
30 /// Returns whether `src` is a subtype of `dest`, i.e. `src <: dest`.
32 /// This mostly ignores opaque types as it can be used in constraining contexts
33 /// while still computing the final underlying type.
34 pub fn is_subtype<'tcx>(
36 param_env: ParamEnv<'tcx>,
45 tcx.infer_ctxt().ignoring_regions().with_opaque_type_inference(DefiningAnchor::Bubble);
46 let infcx = builder.build();
47 let ocx = ObligationCtxt::new(&infcx);
48 let cause = ObligationCause::dummy();
49 let src = ocx.normalize(cause.clone(), param_env, src);
50 let dest = ocx.normalize(cause.clone(), param_env, dest);
51 match ocx.sub(&cause, param_env, src, dest) {
53 Err(_) => return false,
55 let errors = ocx.select_all_or_error();
56 // With `Reveal::All`, opaque types get normalized away, with `Reveal::UserFacing`
57 // we would get unification errors because we're unable to look into opaque types,
58 // even if they're constrained in our current function.
60 // It seems very unlikely that this hides any bugs.
61 let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();