]> git.proxmox.com Git - rustc.git/blob - compiler/rustc_const_eval/src/util/compare_types.rs
New upstream version 1.67.1+dfsg1
[rustc.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, param_env, src);
50 let dest = ocx.normalize(&cause, 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 }