Skip to main content

rustc_traits/
normalize_projection_ty.rs

1use rustc_infer::infer::TyCtxtInferExt;
2use rustc_infer::infer::canonical::{Canonical, QueryResponse};
3use rustc_infer::traits::PredicateObligations;
4use rustc_middle::query::Providers;
5use rustc_middle::ty::{self, ParamEnvAnd, TyCtxt};
6use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
7use rustc_trait_selection::infer::InferCtxtBuilderExt;
8use rustc_trait_selection::traits::query::normalize::NormalizationResult;
9use rustc_trait_selection::traits::query::{CanonicalAliasGoal, NoSolution};
10use rustc_trait_selection::traits::{self, ObligationCause, ScrubbedTraitError, SelectionContext};
11use tracing::debug;
12
13pub(crate) fn provide(p: &mut Providers) {
14    *p = Providers {
15        normalize_canonicalized_projection,
16        normalize_canonicalized_free_alias,
17        normalize_canonicalized_inherent_projection,
18        ..*p
19    };
20}
21
22/// If `normalized_term` is a const, returns a `ConstArgHasType` obligation
23/// to verify that the const value's type matches the alias's declared type.
24/// Returns `None` if the term is a type rather than a const.
25fn const_arg_has_type_obligation<'tcx>(
26    tcx: TyCtxt<'tcx>,
27    param_env: ty::ParamEnv<'tcx>,
28    normalized_term: ty::Term<'tcx>,
29    goal: ty::AliasTerm<'tcx>,
30) -> Option<traits::PredicateObligation<'tcx>> {
31    let ct = normalized_term.as_const()?;
32    let expected_ty = goal.expect_ct().type_of(tcx).skip_norm_wip();
33    Some(traits::Obligation::new(
34        tcx,
35        ObligationCause::dummy(),
36        param_env,
37        ty::ClauseKind::ConstArgHasType(ct, expected_ty),
38    ))
39}
40
41fn normalize_canonicalized_projection<'tcx>(
42    tcx: TyCtxt<'tcx>,
43    goal: CanonicalAliasGoal<'tcx>,
44) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, NormalizationResult<'tcx>>>, NoSolution> {
45    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_traits/src/normalize_projection_ty.rs:45",
                        "rustc_traits::normalize_projection_ty",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_traits/src/normalize_projection_ty.rs"),
                        ::tracing_core::__macro_support::Option::Some(45u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_traits::normalize_projection_ty"),
                        ::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};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("normalize_canonicalized_projection(goal={0:#?})",
                                                    goal) as &dyn Value))])
            });
    } else { ; }
};debug!("normalize_canonicalized_projection(goal={:#?})", goal);
46
47    tcx.infer_ctxt().enter_canonical_trait_query(
48        &goal,
49        |ocx, ParamEnvAnd { param_env, value: goal }| {
50            if true {
    if !!ocx.infcx.next_trait_solver() {
        ::core::panicking::panic("assertion failed: !ocx.infcx.next_trait_solver()")
    };
};debug_assert!(!ocx.infcx.next_trait_solver());
51            let selcx = &mut SelectionContext::new(ocx.infcx);
52            let cause = ObligationCause::dummy();
53            let mut obligations = PredicateObligations::new();
54            let normalized_term = traits::normalize_projection_term(
55                selcx,
56                param_env,
57                goal,
58                cause,
59                0,
60                &mut obligations,
61            );
62            obligations.extend(const_arg_has_type_obligation(
63                tcx,
64                param_env,
65                normalized_term,
66                goal,
67            ));
68            ocx.register_obligations(obligations);
69            // #112047: With projections and opaques, we are able to create opaques that
70            // are recursive (given some generic parameters of the opaque's type variables).
71            // In that case, we may only realize a cycle error when calling
72            // `normalize_erasing_regions` in mono.
73            let errors = ocx.try_evaluate_obligations();
74            if !errors.is_empty() {
75                // Rustdoc may attempt to normalize type alias types which are not
76                // well-formed. Rustdoc also normalizes types that are just not
77                // well-formed, since we don't do as much HIR analysis (checking
78                // that impl vars are constrained by the signature, for example).
79                if !tcx.sess.opts.actually_rustdoc {
80                    for error in &errors {
81                        if let ScrubbedTraitError::Cycle(cycle) = &error {
82                            ocx.infcx.err_ctxt().report_overflow_obligation_cycle(cycle);
83                        }
84                    }
85                }
86                return Err(NoSolution);
87            }
88
89            Ok(NormalizationResult { normalized_term })
90        },
91    )
92}
93
94fn normalize_canonicalized_free_alias<'tcx>(
95    tcx: TyCtxt<'tcx>,
96    goal: CanonicalAliasGoal<'tcx>,
97) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, NormalizationResult<'tcx>>>, NoSolution> {
98    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_traits/src/normalize_projection_ty.rs:98",
                        "rustc_traits::normalize_projection_ty",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_traits/src/normalize_projection_ty.rs"),
                        ::tracing_core::__macro_support::Option::Some(98u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_traits::normalize_projection_ty"),
                        ::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};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("normalize_canonicalized_free_alias(goal={0:#?})",
                                                    goal) as &dyn Value))])
            });
    } else { ; }
};debug!("normalize_canonicalized_free_alias(goal={:#?})", goal);
99
100    tcx.infer_ctxt().enter_canonical_trait_query(
101        &goal,
102        |ocx, ParamEnvAnd { param_env, value: goal }| {
103            let def_id = goal.expect_free_def_id();
104            let obligations = tcx.predicates_of(def_id).instantiate_own(tcx, goal.args).map(
105                |(predicate, span)| {
106                    traits::Obligation::new(
107                        tcx,
108                        ObligationCause::dummy_with_span(span),
109                        param_env,
110                        predicate.skip_norm_wip(),
111                    )
112                },
113            );
114            ocx.register_obligations(obligations);
115            let normalized_term: ty::Term<'tcx> = if goal.kind.is_type() {
116                tcx.type_of(def_id).instantiate(tcx, goal.args).skip_norm_wip().into()
117            } else {
118                tcx.const_of_item(def_id).instantiate(tcx, goal.args).skip_norm_wip().into()
119            };
120            ocx.register_obligations(const_arg_has_type_obligation(
121                tcx,
122                param_env,
123                normalized_term,
124                goal,
125            ));
126            Ok(NormalizationResult { normalized_term })
127        },
128    )
129}
130
131fn normalize_canonicalized_inherent_projection<'tcx>(
132    tcx: TyCtxt<'tcx>,
133    goal: CanonicalAliasGoal<'tcx>,
134) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, NormalizationResult<'tcx>>>, NoSolution> {
135    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_traits/src/normalize_projection_ty.rs:135",
                        "rustc_traits::normalize_projection_ty",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_traits/src/normalize_projection_ty.rs"),
                        ::tracing_core::__macro_support::Option::Some(135u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_traits::normalize_projection_ty"),
                        ::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};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("normalize_canonicalized_inherent_projection(goal={0:#?})",
                                                    goal) as &dyn Value))])
            });
    } else { ; }
};debug!("normalize_canonicalized_inherent_projection(goal={:#?})", goal);
136
137    tcx.infer_ctxt().enter_canonical_trait_query(
138        &goal,
139        |ocx, ParamEnvAnd { param_env, value: goal }| {
140            let selcx = &mut SelectionContext::new(ocx.infcx);
141            let cause = ObligationCause::dummy();
142            let mut obligations = PredicateObligations::new();
143            let normalized_term = traits::normalize_inherent_projection(
144                selcx,
145                param_env,
146                goal.into(),
147                cause,
148                0,
149                &mut obligations,
150            );
151            obligations.extend(const_arg_has_type_obligation(
152                tcx,
153                param_env,
154                normalized_term,
155                goal,
156            ));
157            ocx.register_obligations(obligations);
158
159            Ok(NormalizationResult { normalized_term })
160        },
161    )
162}