]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_const_eval/src/util/compare_types.rs
Auto merge of #104522 - RalfJung:try_normalize_after_erasing_regions, r=oli-obk
[rust.git] / compiler / rustc_const_eval / src / util / compare_types.rs
1 //! Routines to check for relations between fully inferred types.
2 //!
3 //! FIXME: Move this to a more general place. The utility of this extends to
4 //! other areas of the compiler as well.
5
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;
10
11 /// Returns whether the two types are equal up to subtyping.
12 ///
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>(
16     tcx: TyCtxt<'tcx>,
17     param_env: ParamEnv<'tcx>,
18     src: Ty<'tcx>,
19     dest: Ty<'tcx>,
20 ) -> bool {
21     // Fast path.
22     if src == dest {
23         return true;
24     }
25
26     // Check for subtyping in either direction.
27     is_subtype(tcx, param_env, src, dest) || is_subtype(tcx, param_env, dest, src)
28 }
29
30 /// Returns whether `src` is a subtype of `dest`, i.e. `src <: dest`.
31 ///
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>(
35     tcx: TyCtxt<'tcx>,
36     param_env: ParamEnv<'tcx>,
37     src: Ty<'tcx>,
38     dest: Ty<'tcx>,
39 ) -> bool {
40     if src == dest {
41         return true;
42     }
43
44     let mut builder =
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) {
52         Ok(()) => {}
53         Err(_) => return false,
54     };
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.
59     //
60     // It seems very unlikely that this hides any bugs.
61     let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
62     errors.is_empty()
63 }