rustc_const_eval/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
6use rustc_infer::infer::TyCtxtInferExt;
7use rustc_middle::traits::ObligationCause;
8use rustc_middle::ty::{Ty, TyCtxt, TypingEnv, Variance};
9use rustc_trait_selection::traits::ObligationCtxt;
10
11/// Returns whether `src` is a subtype of `dest`, i.e. `src <: dest`.
12pub fn sub_types<'tcx>(
13    tcx: TyCtxt<'tcx>,
14    typing_env: TypingEnv<'tcx>,
15    src: Ty<'tcx>,
16    dest: Ty<'tcx>,
17) -> bool {
18    relate_types(tcx, typing_env, Variance::Covariant, src, dest)
19}
20
21/// Returns whether `src` is a subtype of `dest`, i.e. `src <: dest`.
22///
23/// When validating assignments, the variance should be `Covariant`. When checking
24/// during `MirPhase` >= `MirPhase::Runtime(RuntimePhase::Initial)` variance should be `Invariant`
25/// because we want to check for type equality.
26pub fn relate_types<'tcx>(
27    tcx: TyCtxt<'tcx>,
28    typing_env: TypingEnv<'tcx>,
29    variance: Variance,
30    src: Ty<'tcx>,
31    dest: Ty<'tcx>,
32) -> bool {
33    if src == dest {
34        return true;
35    }
36
37    let (infcx, param_env) = tcx.infer_ctxt().ignoring_regions().build_with_typing_env(typing_env);
38    let ocx = ObligationCtxt::new(&infcx);
39    let cause = ObligationCause::dummy();
40    let src = ocx.normalize(&cause, param_env, src);
41    let dest = ocx.normalize(&cause, param_env, dest);
42    match ocx.relate(&cause, param_env, variance, src, dest) {
43        Ok(()) => {}
44        Err(_) => return false,
45    };
46    ocx.select_all_or_error().is_empty()
47}