Skip to main content

rustc_trait_selection/traits/
const_evaluatable.rs

1//! Checking that constant values used in types can be successfully evaluated.
2//!
3//! For concrete constants, this is fairly simple as we can just try and evaluate it.
4//!
5//! When dealing with polymorphic constants, for example `size_of::<T>() - 1`,
6//! this is not as easy.
7//!
8//! In this case we try to build an abstract representation of this constant using
9//! `thir_abstract_const` which can then be checked for structural equality with other
10//! generic constants mentioned in the `caller_bounds` of the current environment.
11
12use rustc_infer::infer::InferCtxt;
13use rustc_middle::traits::ObligationCause;
14use rustc_middle::ty::abstract_const::NotConstEvaluatable;
15use rustc_middle::ty::{
16    self, CallerBoundsIterator, TyCtxt, TypeVisitable, TypeVisitableExt, TypeVisitor,
17};
18use rustc_span::{DUMMY_SP, Span, bug};
19use tracing::{debug, instrument};
20
21use super::EvaluateConstErr;
22use crate::traits::ObligationCtxt;
23
24/// Check if a given constant can be evaluated.
25{}
#[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::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("is_const_evaluatable",
                                    "rustc_trait_selection::traits::const_evaluatable",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/bbcdfd90a3f81ca2a5f6d69b943a6ff0d8582102/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs"),
                                    ::tracing_core::__macro_support::Option::Some(25u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::const_evaluatable"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("unexpanded_ct")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("unexpanded_ct");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("param_env")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("param_env");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("span")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("span");
                                                        NAME.as_str()
                                                    }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::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};
                                meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&unexpanded_ct)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&param_env)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&span)
                                                            as &dyn ::tracing::field::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: Result<(), NotConstEvaluatable> =
                loop {};
            return __tracing_attr_fake_return;
        }
        {
            let tcx = infcx.tcx;
            match tcx.expand_abstract_consts(unexpanded_ct).kind() {
                ty::ConstKind::Alias(_, _) | ty::ConstKind::Expr(_) => (),
                ty::ConstKind::Param(_) | ty::ConstKind::Bound(_, _) |
                    ty::ConstKind::Placeholder(_) | ty::ConstKind::Value(_) |
                    ty::ConstKind::Error(_) => return Ok(()),
                ty::ConstKind::Infer(_) =>
                    return Err(NotConstEvaluatable::MentionsInfer),
            };
            if tcx.features().generic_const_exprs() {
                let ct = tcx.expand_abstract_consts(unexpanded_ct);
                let is_anon_ct =
                    #[allow(non_exhaustive_omitted_patterns)] match ct.kind() {
                        ty::ConstKind::Alias(_, ty::AliasConst {
                            kind: ty::AliasConstKind::Anon { .. }, .. }) => true,
                        _ => false,
                    };
                if !is_anon_ct {
                    if satisfied_from_param_env(tcx, infcx, ct, param_env) {
                        return Ok(());
                    }
                    if ct.has_non_region_infer() {
                        return Err(NotConstEvaluatable::MentionsInfer);
                    } else if ct.has_non_region_param() {
                        return Err(NotConstEvaluatable::MentionsParam);
                    }
                }
                match unexpanded_ct.kind() {
                    ty::ConstKind::Expr(_) => {
                        tcx.dcx().span_bug(span,
                            "evaluating `ConstKind::Expr` is not currently supported");
                    }
                    ty::ConstKind::Alias(_, _) => {
                        match crate::traits::try_evaluate_const(infcx,
                                unexpanded_ct, param_env,
                                |ty| { Ok::<_, !>(ty.skip_norm_wip()) }) {
                            Err(EvaluateConstErr::HasGenericsOrInfers) => {
                                Err(NotConstEvaluatable::Error(infcx.dcx().span_delayed_bug(span,
                                            "Missing value for constant, but no error reported?")))
                            }
                            Err(EvaluateConstErr::EvaluationFailure(e) |
                                EvaluateConstErr::InvalidConstParamTy(e)) =>
                                Err(NotConstEvaluatable::Error(e)),
                            Ok(_) => Ok(()),
                        }
                    }
                    _ =>
                        ::rustc_span::macros::bug_impl(None,
                            format_args!("unexpected constkind in `is_const_evalautable: {0:?}`",
                                unexpanded_ct), Location::caller()),
                }
            } else if tcx.features().gca() {
                crate::traits::evaluate_const(infcx, unexpanded_ct,
                    param_env);
                Ok(())
            } else {
                let alias_const =
                    match unexpanded_ct.kind() {
                        ty::ConstKind::Alias(_, alias_const) => alias_const,
                        ty::ConstKind::Expr(_) => {
                            ::rustc_span::macros::bug_impl(None,
                                format_args!("`ConstKind::Expr` without `feature(generic_const_exprs)` enabled"),
                                Location::caller())
                        }
                        _ =>
                            ::rustc_span::macros::bug_impl(None,
                                format_args!("unexpected constkind in `is_const_evalautable: {0:?}`",
                                    unexpanded_ct), Location::caller()),
                    };
                match crate::traits::try_evaluate_const(infcx, unexpanded_ct,
                        param_env, |ty| { Ok::<_, !>(ty.skip_norm_wip()) }) {
                    Err(_) if
                        tcx.sess.is_nightly_build() &&
                            satisfied_from_param_env(tcx, infcx,
                                tcx.expand_abstract_consts(unexpanded_ct), param_env) => {
                        tcx.dcx().struct_span_fatal(if span == DUMMY_SP {
                                            alias_const.kind.def_span(tcx)
                                        } else { span },
                                        "failed to evaluate generic const expression").with_note("the crate this constant originates from uses `#![feature(generic_const_exprs)]`").with_span_suggestion_verbose(DUMMY_SP,
                                "consider enabling this feature",
                                "#![feature(generic_const_exprs)]\n",
                                rustc_errors::Applicability::MaybeIncorrect).emit_fatal()
                    }
                    Err(EvaluateConstErr::HasGenericsOrInfers) => {
                        let err =
                            if alias_const.has_non_region_infer() {
                                NotConstEvaluatable::MentionsInfer
                            } else if alias_const.has_non_region_param() {
                                NotConstEvaluatable::MentionsParam
                            } else {
                                let guar =
                                    infcx.dcx().span_delayed_bug(span,
                                        "Missing value for constant, but no error reported?");
                                NotConstEvaluatable::Error(guar)
                            };
                        Err(err)
                    }
                    Err(EvaluateConstErr::EvaluationFailure(e) |
                        EvaluateConstErr::InvalidConstParamTy(e)) =>
                        Err(NotConstEvaluatable::Error(e)),
                    Ok(_) => Ok(()),
                }
            }
        }
    }
}#[instrument(skip(infcx), level = "debug")]
26pub fn is_const_evaluatable<'tcx>(
27    infcx: &InferCtxt<'tcx>,
28    unexpanded_ct: ty::Const<'tcx>,
29    param_env: ty::ParamEnv<'tcx>,
30    span: Span,
31) -> Result<(), NotConstEvaluatable> {
32    let tcx = infcx.tcx;
33    match tcx.expand_abstract_consts(unexpanded_ct).kind() {
34        ty::ConstKind::Alias(_, _) | ty::ConstKind::Expr(_) => (),
35        ty::ConstKind::Param(_)
36        | ty::ConstKind::Bound(_, _)
37        | ty::ConstKind::Placeholder(_)
38        | ty::ConstKind::Value(_)
39        | ty::ConstKind::Error(_) => return Ok(()),
40        ty::ConstKind::Infer(_) => return Err(NotConstEvaluatable::MentionsInfer),
41    };
42
43    if tcx.features().generic_const_exprs() {
44        let ct = tcx.expand_abstract_consts(unexpanded_ct);
45
46        let is_anon_ct = matches!(
47            ct.kind(),
48            ty::ConstKind::Alias(_, ty::AliasConst { kind: ty::AliasConstKind::Anon { .. }, .. })
49        );
50
51        if !is_anon_ct {
52            if satisfied_from_param_env(tcx, infcx, ct, param_env) {
53                return Ok(());
54            }
55            if ct.has_non_region_infer() {
56                return Err(NotConstEvaluatable::MentionsInfer);
57            } else if ct.has_non_region_param() {
58                return Err(NotConstEvaluatable::MentionsParam);
59            }
60        }
61
62        match unexpanded_ct.kind() {
63            ty::ConstKind::Expr(_) => {
64                // FIXME(generic_const_exprs): we have a fully concrete `ConstKind::Expr`, but
65                // haven't implemented evaluating `ConstKind::Expr` yet, so we are unable to tell
66                // if it is evaluatable or not. As this is unreachable for now, we can simple ICE
67                // here.
68                tcx.dcx().span_bug(span, "evaluating `ConstKind::Expr` is not currently supported");
69            }
70            ty::ConstKind::Alias(_, _) => {
71                match crate::traits::try_evaluate_const(infcx, unexpanded_ct, param_env, |ty| {
72                    Ok::<_, !>(ty.skip_norm_wip())
73                }) {
74                    Err(EvaluateConstErr::HasGenericsOrInfers) => {
75                        Err(NotConstEvaluatable::Error(infcx.dcx().span_delayed_bug(
76                            span,
77                            "Missing value for constant, but no error reported?",
78                        )))
79                    }
80                    Err(
81                        EvaluateConstErr::EvaluationFailure(e)
82                        | EvaluateConstErr::InvalidConstParamTy(e),
83                    ) => Err(NotConstEvaluatable::Error(e)),
84                    Ok(_) => Ok(()),
85                }
86            }
87            _ => bug!("unexpected constkind in `is_const_evalautable: {unexpanded_ct:?}`"),
88        }
89    } else if tcx.features().gca() {
90        // This is a sanity check to make sure that non-generics consts are checked to
91        // be evaluatable in case they aren't cchecked elsewhere. This will NOT error
92        // if the const uses generics, as desired.
93        crate::traits::evaluate_const(infcx, unexpanded_ct, param_env);
94        Ok(())
95    } else {
96        let alias_const = match unexpanded_ct.kind() {
97            ty::ConstKind::Alias(_, alias_const) => alias_const,
98            ty::ConstKind::Expr(_) => {
99                bug!("`ConstKind::Expr` without `feature(generic_const_exprs)` enabled")
100            }
101            _ => bug!("unexpected constkind in `is_const_evalautable: {unexpanded_ct:?}`"),
102        };
103
104        match crate::traits::try_evaluate_const(infcx, unexpanded_ct, param_env, |ty| {
105            Ok::<_, !>(ty.skip_norm_wip())
106        }) {
107            // If we're evaluating a generic foreign constant, under a nightly compiler while
108            // the current crate does not enable `feature(generic_const_exprs)`, abort
109            // compilation with a useful error.
110            Err(_)
111                if tcx.sess.is_nightly_build()
112                    && satisfied_from_param_env(
113                        tcx,
114                        infcx,
115                        tcx.expand_abstract_consts(unexpanded_ct),
116                        param_env,
117                    ) =>
118            {
119                tcx.dcx()
120                    .struct_span_fatal(
121                        // Slightly better span than just using `span` alone
122                        if span == DUMMY_SP { alias_const.kind.def_span(tcx) } else { span },
123                        "failed to evaluate generic const expression",
124                    )
125                    .with_note("the crate this constant originates from uses `#![feature(generic_const_exprs)]`")
126                    .with_span_suggestion_verbose(
127                        DUMMY_SP,
128                        "consider enabling this feature",
129                        "#![feature(generic_const_exprs)]\n",
130                        rustc_errors::Applicability::MaybeIncorrect,
131                    )
132                    .emit_fatal()
133            }
134
135            Err(EvaluateConstErr::HasGenericsOrInfers) => {
136                let err = if alias_const.has_non_region_infer() {
137                    NotConstEvaluatable::MentionsInfer
138                } else if alias_const.has_non_region_param() {
139                    NotConstEvaluatable::MentionsParam
140                } else {
141                    let guar = infcx.dcx().span_delayed_bug(
142                        span,
143                        "Missing value for constant, but no error reported?",
144                    );
145                    NotConstEvaluatable::Error(guar)
146                };
147
148                Err(err)
149            }
150            Err(
151                EvaluateConstErr::EvaluationFailure(e) | EvaluateConstErr::InvalidConstParamTy(e),
152            ) => Err(NotConstEvaluatable::Error(e)),
153            Ok(_) => Ok(()),
154        }
155    }
156}
157
158{}
#[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::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("satisfied_from_param_env",
                                    "rustc_trait_selection::traits::const_evaluatable",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/bbcdfd90a3f81ca2a5f6d69b943a6ff0d8582102/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs"),
                                    ::tracing_core::__macro_support::Option::Some(158u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::const_evaluatable"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("ct")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("ct");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("param_env")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("param_env");
                                                        NAME.as_str()
                                                    }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::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};
                                meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&ct)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&param_env)
                                                            as &dyn ::tracing::field::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: bool = loop {};
            return __tracing_attr_fake_return;
        }
        {
            struct Visitor<'a, 'tcx> {
                ct: ty::Const<'tcx>,
                param_env: ty::ParamEnv<'tcx>,
                infcx: &'a InferCtxt<'tcx>,
                single_match: Option<Result<ty::Const<'tcx>, ()>>,
            }
            impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for Visitor<'a, 'tcx> {
                fn visit_const(&mut self, c: ty::Const<'tcx>) {
                    {
                        use ::tracing::__macro_support::Callsite as _;
                        static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                            {
                                static META: ::tracing::Metadata<'static> =
                                    {
                                        ::tracing_core::metadata::Metadata::new("event /rustc-dev/bbcdfd90a3f81ca2a5f6d69b943a6ff0d8582102/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs:178",
                                            "rustc_trait_selection::traits::const_evaluatable",
                                            ::tracing::Level::DEBUG,
                                            ::tracing_core::__macro_support::Option::Some("/rustc-dev/bbcdfd90a3f81ca2a5f6d69b943a6ff0d8582102/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs"),
                                            ::tracing_core::__macro_support::Option::Some(178u32),
                                            ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::const_evaluatable"),
                                            ::tracing_core::field::FieldSet::new(&["message"],
                                                ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                            ::tracing::metadata::Kind::EVENT)
                                    };
                                ::tracing::callsite::DefaultCallsite::new(&META)
                            };
                        let enabled =
                            ::tracing::Level::DEBUG <=
                                        ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                    ::tracing::Level::DEBUG <=
                                        ::tracing::level_filters::LevelFilter::current() &&
                                {
                                    let interest = __CALLSITE.interest();
                                    !interest.is_never() &&
                                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                            interest)
                                };
                        if enabled {
                            (|value_set: ::tracing::field::ValueSet|
                                        {
                                            let meta = __CALLSITE.metadata();
                                            ::tracing::Event::dispatch(meta, &value_set);
                                            ;
                                        })({
                                    #[allow(unused_imports)]
                                    use ::tracing::field::{debug, display, Value};
                                    __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("is_const_evaluatable: candidate={0:?}",
                                                                        c) as &dyn ::tracing::field::Value))])
                                });
                        } else { ; }
                    };
                    if self.infcx.probe(|_|
                                {
                                    let ocx = ObligationCtxt::new(self.infcx);
                                    ocx.eq(&ObligationCause::dummy(), self.param_env, c,
                                                self.ct).is_ok() &&
                                        ocx.evaluate_obligations_error_on_ambiguity().no_errors()
                                }) {
                        self.single_match =
                            match self.single_match {
                                None => Some(Ok(c)),
                                Some(Ok(o)) if o == c => Some(Ok(c)),
                                Some(_) => Some(Err(())),
                            };
                    }
                    if let ty::ConstKind::Expr(e) = c.kind() {
                        e.visit_with(self);
                    } else {}
                }
            }
            let mut single_match: Option<Result<ty::Const<'tcx>, ()>> = None;
            for clause in param_env.caller_bounds().non_trait_clauses().iter()
                {
                match clause.kind().skip_binder() {
                    ty::ClauseKind::ConstEvaluatable(ce) => {
                        let b_ct = tcx.expand_abstract_consts(ce);
                        let mut v = Visitor { ct, infcx, param_env, single_match };
                        let _ = b_ct.visit_with(&mut v);
                        single_match = v.single_match;
                    }
                    _ => {}
                }
            }
            if let Some(Ok(c)) = single_match {
                let ocx = ObligationCtxt::new(infcx);
                if !ocx.eq(&ObligationCause::dummy(), param_env, c,
                                ct).is_ok() {
                    ::core::panicking::panic("assertion failed: ocx.eq(&ObligationCause::dummy(), param_env, c, ct).is_ok()")
                };
                if !ocx.evaluate_obligations_error_on_ambiguity().no_errors()
                    {
                    ::core::panicking::panic("assertion failed: ocx.evaluate_obligations_error_on_ambiguity().no_errors()")
                };
                return true;
            }
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("event /rustc-dev/bbcdfd90a3f81ca2a5f6d69b943a6ff0d8582102/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs:227",
                                    "rustc_trait_selection::traits::const_evaluatable",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/bbcdfd90a3f81ca2a5f6d69b943a6ff0d8582102/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs"),
                                    ::tracing_core::__macro_support::Option::Some(227u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::const_evaluatable"),
                                    ::tracing_core::field::FieldSet::new(&["message"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::EVENT)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let enabled =
                    ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::STATIC_MAX_LEVEL &&
                            ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::LevelFilter::current() &&
                        {
                            let interest = __CALLSITE.interest();
                            !interest.is_never() &&
                                ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                    interest)
                        };
                if enabled {
                    (|value_set: ::tracing::field::ValueSet|
                                {
                                    let meta = __CALLSITE.metadata();
                                    ::tracing::Event::dispatch(meta, &value_set);
                                    ;
                                })({
                            #[allow(unused_imports)]
                            use ::tracing::field::{debug, display, Value};
                            __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("is_const_evaluatable: no")
                                                        as &dyn ::tracing::field::Value))])
                        });
                } else { ; }
            };
            false
        }
    }
}#[instrument(skip(infcx, tcx), level = "debug")]
159fn satisfied_from_param_env<'tcx>(
160    tcx: TyCtxt<'tcx>,
161    infcx: &InferCtxt<'tcx>,
162    ct: ty::Const<'tcx>,
163    param_env: ty::ParamEnv<'tcx>,
164) -> bool {
165    // Try to unify with each subtree in the AbstractConst to allow for
166    // `N + 1` being const evaluatable even if theres only a `ConstEvaluatable`
167    // predicate for `(N + 1) * 2`
168    struct Visitor<'a, 'tcx> {
169        ct: ty::Const<'tcx>,
170        param_env: ty::ParamEnv<'tcx>,
171
172        infcx: &'a InferCtxt<'tcx>,
173        single_match: Option<Result<ty::Const<'tcx>, ()>>,
174    }
175
176    impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for Visitor<'a, 'tcx> {
177        fn visit_const(&mut self, c: ty::Const<'tcx>) {
178            debug!("is_const_evaluatable: candidate={:?}", c);
179            if self.infcx.probe(|_| {
180                let ocx = ObligationCtxt::new(self.infcx);
181                ocx.eq(&ObligationCause::dummy(), self.param_env, c, self.ct).is_ok()
182                    && ocx.evaluate_obligations_error_on_ambiguity().no_errors()
183            }) {
184                self.single_match = match self.single_match {
185                    None => Some(Ok(c)),
186                    Some(Ok(o)) if o == c => Some(Ok(c)),
187                    Some(_) => Some(Err(())),
188                };
189            }
190
191            if let ty::ConstKind::Expr(e) = c.kind() {
192                e.visit_with(self);
193            } else {
194                // FIXME(generic_const_exprs): This doesn't recurse into `<T as Trait<U>>::ASSOC`'s args.
195                // This is currently unobservable as `<T as Trait<{ U + 1 }>>::ASSOC` creates an anon const
196                // with its own `ConstEvaluatable` bound in the param env which we will visit separately.
197                //
198                // If we start allowing directly writing `ConstKind::Expr` without an intermediate anon const
199                // this will be incorrect. It might be worth investigating making `clauses_of` elaborate
200                // all of the `ConstEvaluatable` bounds rather than having a visitor here.
201            }
202        }
203    }
204
205    let mut single_match: Option<Result<ty::Const<'tcx>, ()>> = None;
206
207    for clause in param_env.caller_bounds().non_trait_clauses().iter() {
208        match clause.kind().skip_binder() {
209            ty::ClauseKind::ConstEvaluatable(ce) => {
210                let b_ct = tcx.expand_abstract_consts(ce);
211                let mut v = Visitor { ct, infcx, param_env, single_match };
212                let _ = b_ct.visit_with(&mut v);
213
214                single_match = v.single_match;
215            }
216            _ => {} // don't care
217        }
218    }
219
220    if let Some(Ok(c)) = single_match {
221        let ocx = ObligationCtxt::new(infcx);
222        assert!(ocx.eq(&ObligationCause::dummy(), param_env, c, ct).is_ok());
223        assert!(ocx.evaluate_obligations_error_on_ambiguity().no_errors());
224        return true;
225    }
226
227    debug!("is_const_evaluatable: no");
228    false
229}