Skip to main content

rustc_trait_selection/
regions.rs

1use rustc_hir::def_id::LocalDefId;
2use rustc_infer::infer::outlives::env::OutlivesEnvironment;
3use rustc_infer::infer::{InferCtxt, RegionResolutionError};
4use rustc_macros::extension;
5use rustc_middle::traits::ObligationCause;
6use rustc_middle::traits::query::NoSolution;
7use rustc_middle::ty::{self, Ty, Unnormalized, elaborate};
8use rustc_span::Span;
9
10use crate::traits::ScrubbedTraitError;
11use crate::traits::outlives_bounds::InferCtxtExt;
12
13impl<'tcx> OutlivesEnvironmentBuildExt<'tcx> for OutlivesEnvironment<'tcx> {
    fn new(infcx: &InferCtxt<'tcx>, body_id: LocalDefId,
        param_env: ty::ParamEnv<'tcx>,
        assumed_wf_tys: impl IntoIterator<Item = Ty<'tcx>>) -> Self {
        Self::new_with_implied_bounds_compat(infcx, body_id, param_env,
            assumed_wf_tys, false)
    }
    fn new_with_implied_bounds_compat(infcx: &InferCtxt<'tcx>,
        body_id: LocalDefId, param_env: ty::ParamEnv<'tcx>,
        assumed_wf_tys: impl IntoIterator<Item = Ty<'tcx>>,
        disable_implied_bounds_hack: bool) -> Self {
        let mut bounds = ::alloc::vec::Vec::new();
        for bound in param_env.caller_bounds() {
            if let Some(mut type_outlives) = bound.as_type_outlives_clause() {
                if infcx.next_trait_solver() {
                    match crate::solve::deeply_normalize::<_,
                                ScrubbedTraitError<'tcx>>(infcx.at(&ObligationCause::dummy(),
                                param_env), Unnormalized::new_wip(type_outlives)) {
                        Ok(new) => type_outlives = new,
                        Err(_) => {
                            infcx.dcx().delayed_bug(::alloc::__export::must_use({
                                        ::alloc::fmt::format(format_args!("could not normalize `{0}`",
                                                bound))
                                    }));
                        }
                    }
                }
                bounds.push(type_outlives);
            }
        }
        let higher_ranked_assumptions =
            infcx.take_registered_region_assumptions();
        let higher_ranked_assumptions =
            elaborate::elaborate_outlives_assumptions(infcx.tcx,
                higher_ranked_assumptions);
        OutlivesEnvironment::from_normalized_bounds(param_env, bounds,
            infcx.implied_bounds_tys(body_id, param_env, assumed_wf_tys,
                disable_implied_bounds_hack), higher_ranked_assumptions)
    }
}#[extension(pub trait OutlivesEnvironmentBuildExt<'tcx>)]
14impl<'tcx> OutlivesEnvironment<'tcx> {
15    fn new(
16        infcx: &InferCtxt<'tcx>,
17        body_id: LocalDefId,
18        param_env: ty::ParamEnv<'tcx>,
19        assumed_wf_tys: impl IntoIterator<Item = Ty<'tcx>>,
20    ) -> Self {
21        Self::new_with_implied_bounds_compat(infcx, body_id, param_env, assumed_wf_tys, false)
22    }
23
24    fn new_with_implied_bounds_compat(
25        infcx: &InferCtxt<'tcx>,
26        body_id: LocalDefId,
27        param_env: ty::ParamEnv<'tcx>,
28        assumed_wf_tys: impl IntoIterator<Item = Ty<'tcx>>,
29        disable_implied_bounds_hack: bool,
30    ) -> Self {
31        let mut bounds = vec![];
32
33        for bound in param_env.caller_bounds() {
34            if let Some(mut type_outlives) = bound.as_type_outlives_clause() {
35                if infcx.next_trait_solver() {
36                    match crate::solve::deeply_normalize::<_, ScrubbedTraitError<'tcx>>(
37                        infcx.at(&ObligationCause::dummy(), param_env),
38                        Unnormalized::new_wip(type_outlives),
39                    ) {
40                        Ok(new) => type_outlives = new,
41                        Err(_) => {
42                            infcx.dcx().delayed_bug(format!("could not normalize `{bound}`"));
43                        }
44                    }
45                }
46                bounds.push(type_outlives);
47            }
48        }
49
50        // FIXME(-Znext-trait-solver): Normalize these.
51        let higher_ranked_assumptions = infcx.take_registered_region_assumptions();
52        let higher_ranked_assumptions =
53            elaborate::elaborate_outlives_assumptions(infcx.tcx, higher_ranked_assumptions);
54
55        // FIXME: This needs to be modified so that we normalize the known type
56        // outlives obligations then elaborate them into their region/type components.
57        // Otherwise, `<W<'a> as Mirror>::Assoc: 'b` will not imply `'a: 'b` even
58        // if we can normalize `'a`.
59        OutlivesEnvironment::from_normalized_bounds(
60            param_env,
61            bounds,
62            infcx.implied_bounds_tys(
63                body_id,
64                param_env,
65                assumed_wf_tys,
66                disable_implied_bounds_hack,
67            ),
68            higher_ranked_assumptions,
69        )
70    }
71}
72
73impl<'tcx> InferCtxtRegionExt<'tcx> for InferCtxt<'tcx> {
    #[doc =
    " Resolve regions, using the deep normalizer to normalize any type-outlives"]
    #[doc =
    " obligations in the process. This is in `rustc_trait_selection` because"]
    #[doc = " we need to normalize."]
    #[doc = ""]
    #[doc =
    " Prefer this method over `resolve_regions_with_normalize`, unless you are"]
    #[doc = " doing something specific for normalization."]
    #[doc = ""]
    #[doc =
    " This function assumes that all infer variables are already constrained."]
    fn resolve_regions(&self, body_id: LocalDefId,
        param_env: ty::ParamEnv<'tcx>,
        assumed_wf_tys: impl IntoIterator<Item = Ty<'tcx>>)
        -> Vec<RegionResolutionError<'tcx>> {
        self.resolve_regions_with_outlives_env(&OutlivesEnvironment::new(self,
                    body_id, param_env, assumed_wf_tys),
            self.tcx.def_span(body_id))
    }
    #[doc = " Don\'t call this directly unless you know what you\'re doing."]
    fn resolve_regions_with_outlives_env(&self,
        outlives_env: &OutlivesEnvironment<'tcx>, span: Span)
        -> Vec<RegionResolutionError<'tcx>> {
        self.resolve_regions_with_normalize(&outlives_env,
            |ty, origin|
                {
                    let ty = self.resolve_vars_if_possible(ty);
                    if self.next_trait_solver() {
                        crate::solve::deeply_normalize(self.at(&ObligationCause::dummy_with_span(origin.span()),
                                    outlives_env.param_env),
                                Unnormalized::new_wip(ty)).map_err(|_:
                                    Vec<ScrubbedTraitError<'tcx>>| NoSolution)
                    } else { Ok(ty) }
                }, span)
    }
}#[extension(pub trait InferCtxtRegionExt<'tcx>)]
74impl<'tcx> InferCtxt<'tcx> {
75    /// Resolve regions, using the deep normalizer to normalize any type-outlives
76    /// obligations in the process. This is in `rustc_trait_selection` because
77    /// we need to normalize.
78    ///
79    /// Prefer this method over `resolve_regions_with_normalize`, unless you are
80    /// doing something specific for normalization.
81    ///
82    /// This function assumes that all infer variables are already constrained.
83    fn resolve_regions(
84        &self,
85        body_id: LocalDefId,
86        param_env: ty::ParamEnv<'tcx>,
87        assumed_wf_tys: impl IntoIterator<Item = Ty<'tcx>>,
88    ) -> Vec<RegionResolutionError<'tcx>> {
89        self.resolve_regions_with_outlives_env(
90            &OutlivesEnvironment::new(self, body_id, param_env, assumed_wf_tys),
91            self.tcx.def_span(body_id),
92        )
93    }
94
95    /// Don't call this directly unless you know what you're doing.
96    fn resolve_regions_with_outlives_env(
97        &self,
98        outlives_env: &OutlivesEnvironment<'tcx>,
99        span: Span,
100    ) -> Vec<RegionResolutionError<'tcx>> {
101        self.resolve_regions_with_normalize(
102            &outlives_env,
103            |ty, origin| {
104                let ty = self.resolve_vars_if_possible(ty);
105
106                if self.next_trait_solver() {
107                    crate::solve::deeply_normalize(
108                        self.at(
109                            &ObligationCause::dummy_with_span(origin.span()),
110                            outlives_env.param_env,
111                        ),
112                        Unnormalized::new_wip(ty),
113                    )
114                    .map_err(|_: Vec<ScrubbedTraitError<'tcx>>| NoSolution)
115                } else {
116                    Ok(ty)
117                }
118            },
119            span,
120        )
121    }
122}