Skip to main content

rustc_trait_selection/traits/select/
_match.rs

1use rustc_hir::def_id::DefId;
2use rustc_infer::infer::relate::{
3    self, Relate, RelateResult, TypeRelation, structurally_relate_tys,
4};
5use rustc_middle::ty::error::{ExpectedFound, TypeError};
6use rustc_middle::ty::{self, InferConst, Ty, TyCtxt};
7use tracing::instrument;
8
9/// A type "A" *matches* "B" if the fresh types in B could be
10/// instantiated with values so as to make it equal to A. Matching is
11/// intended to be used only on freshened types, and it basically
12/// indicates if the non-freshened versions of A and B could have been
13/// unified.
14///
15/// It is only an approximation. If it yields false, unification would
16/// definitely fail, but a true result doesn't mean unification would
17/// succeed. This is because we don't track the "side-constraints" on
18/// type variables, nor do we track if the same freshened type appears
19/// more than once. To some extent these approximations could be
20/// fixed, given effort.
21///
22/// Like subtyping, matching is really a binary relation, so the only
23/// important thing about the result is Ok/Err. Also, matching never
24/// affects any type variables or unification state.
25pub(crate) struct MatchAgainstFreshVars<'tcx> {
26    tcx: TyCtxt<'tcx>,
27}
28
29impl<'tcx> MatchAgainstFreshVars<'tcx> {
30    pub(crate) fn new(tcx: TyCtxt<'tcx>) -> MatchAgainstFreshVars<'tcx> {
31        MatchAgainstFreshVars { tcx }
32    }
33}
34
35impl<'tcx> TypeRelation<TyCtxt<'tcx>> for MatchAgainstFreshVars<'tcx> {
36    fn cx(&self) -> TyCtxt<'tcx> {
37        self.tcx
38    }
39
40    fn relate_ty_args(
41        &mut self,
42        a_ty: Ty<'tcx>,
43        _: Ty<'tcx>,
44        _: DefId,
45        a_args: ty::GenericArgsRef<'tcx>,
46        b_args: ty::GenericArgsRef<'tcx>,
47        _: impl FnOnce(ty::GenericArgsRef<'tcx>) -> Ty<'tcx>,
48    ) -> RelateResult<'tcx, Ty<'tcx>> {
49        relate::relate_args_invariantly(self, a_args, b_args)?;
50        Ok(a_ty)
51    }
52
53    fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
54        &mut self,
55        _: ty::Variance,
56        _: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
57        a: T,
58        b: T,
59    ) -> RelateResult<'tcx, T> {
60        self.relate(a, b)
61    }
62
63    #[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::TRACE <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("regions",
                                    "rustc_trait_selection::traits::select::_match",
                                    ::tracing::Level::TRACE,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/traits/select/_match.rs"),
                                    ::tracing_core::__macro_support::Option::Some(63u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::select::_match"),
                                    ::tracing_core::field::FieldSet::new(&["a", "_b"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::TRACE <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::TRACE <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                let mut iter = meta.fields().iter();
                                meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&a)
                                                            as &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&_b)
                                                            as &dyn Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return:
                    RelateResult<'tcx, ty::Region<'tcx>> = loop {};
            return __tracing_attr_fake_return;
        }
        { Ok(a) }
    }
}#[instrument(skip(self), level = "trace")]
64    fn regions(
65        &mut self,
66        a: ty::Region<'tcx>,
67        _b: ty::Region<'tcx>,
68    ) -> RelateResult<'tcx, ty::Region<'tcx>> {
69        Ok(a)
70    }
71
72    #[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::TRACE <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("tys",
                                    "rustc_trait_selection::traits::select::_match",
                                    ::tracing::Level::TRACE,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/traits/select/_match.rs"),
                                    ::tracing_core::__macro_support::Option::Some(72u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::select::_match"),
                                    ::tracing_core::field::FieldSet::new(&["a", "b"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::TRACE <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::TRACE <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                let mut iter = meta.fields().iter();
                                meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&a)
                                                            as &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&b)
                                                            as &dyn Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return: RelateResult<'tcx, Ty<'tcx>> =
                loop {};
            return __tracing_attr_fake_return;
        }
        {
            if a == b { return Ok(a); }
            match (a.kind(), b.kind()) {
                (_,
                    &ty::Infer(ty::FreshTy(_)) | &ty::Infer(ty::FreshIntTy(_)) |
                    &ty::Infer(ty::FreshFloatTy(_))) => Ok(a),
                (&ty::Infer(_), _) | (_, &ty::Infer(_)) => {
                    Err(TypeError::Sorts(ExpectedFound::new(a, b)))
                }
                (&ty::Error(guar), _) | (_, &ty::Error(guar)) =>
                    Ok(Ty::new_error(self.cx(), guar)),
                _ => structurally_relate_tys(self, a, b),
            }
        }
    }
}#[instrument(skip(self), level = "trace")]
73    fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
74        if a == b {
75            return Ok(a);
76        }
77
78        match (a.kind(), b.kind()) {
79            (
80                _,
81                &ty::Infer(ty::FreshTy(_))
82                | &ty::Infer(ty::FreshIntTy(_))
83                | &ty::Infer(ty::FreshFloatTy(_)),
84            ) => Ok(a),
85
86            (&ty::Infer(_), _) | (_, &ty::Infer(_)) => {
87                Err(TypeError::Sorts(ExpectedFound::new(a, b)))
88            }
89
90            (&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(Ty::new_error(self.cx(), guar)),
91
92            _ => structurally_relate_tys(self, a, b),
93        }
94    }
95
96    #[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::TRACE <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("consts",
                                    "rustc_trait_selection::traits::select::_match",
                                    ::tracing::Level::TRACE,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/traits/select/_match.rs"),
                                    ::tracing_core::__macro_support::Option::Some(96u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::select::_match"),
                                    ::tracing_core::field::FieldSet::new(&["a", "b"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::TRACE <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::TRACE <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                let mut iter = meta.fields().iter();
                                meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&a)
                                                            as &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&b)
                                                            as &dyn Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return:
                    RelateResult<'tcx, ty::Const<'tcx>> = loop {};
            return __tracing_attr_fake_return;
        }
        {
            if a == b { return Ok(a); }
            match (a.kind(), b.kind()) {
                (_, ty::ConstKind::Infer(InferConst::Fresh(_))) => {
                    return Ok(a);
                }
                (ty::ConstKind::Infer(_), _) | (_, ty::ConstKind::Infer(_)) =>
                    {
                    return Err(TypeError::ConstMismatch(ExpectedFound::new(a,
                                    b)));
                }
                _ => {}
            }
            relate::structurally_relate_consts(self, a, b)
        }
    }
}#[instrument(skip(self), level = "trace")]
97    fn consts(
98        &mut self,
99        a: ty::Const<'tcx>,
100        b: ty::Const<'tcx>,
101    ) -> RelateResult<'tcx, ty::Const<'tcx>> {
102        if a == b {
103            return Ok(a);
104        }
105
106        match (a.kind(), b.kind()) {
107            (_, ty::ConstKind::Infer(InferConst::Fresh(_))) => {
108                return Ok(a);
109            }
110
111            (ty::ConstKind::Infer(_), _) | (_, ty::ConstKind::Infer(_)) => {
112                return Err(TypeError::ConstMismatch(ExpectedFound::new(a, b)));
113            }
114
115            _ => {}
116        }
117
118        relate::structurally_relate_consts(self, a, b)
119    }
120
121    fn binders<T>(
122        &mut self,
123        a: ty::Binder<'tcx, T>,
124        b: ty::Binder<'tcx, T>,
125    ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
126    where
127        T: Relate<TyCtxt<'tcx>>,
128    {
129        Ok(a.rebind(self.relate(a.skip_binder(), b.skip_binder())?))
130    }
131}