use rustc_hir::def_id::LocalDefId; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{InferCtxt, RegionResolutionError}; use rustc_macros::extension; use rustc_middle::traits::ObligationCause; use rustc_middle::traits::query::NoSolution; use rustc_middle::ty::{self, Ty, elaborate}; use crate::traits::ScrubbedTraitError; use crate::traits::outlives_bounds::InferCtxtExt; #[extension(pub trait OutlivesEnvironmentBuildExt<'tcx>)] impl<'tcx> OutlivesEnvironment<'tcx> { fn new( infcx: &InferCtxt<'tcx>, body_id: LocalDefId, param_env: ty::ParamEnv<'tcx>, assumed_wf_tys: impl IntoIterator>, ) -> 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>, disable_implied_bounds_hack: bool, ) -> Self { let mut bounds = vec![]; 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), type_outlives, ) { Ok(new) => type_outlives = new, Err(_) => { infcx.dcx().delayed_bug(format!("could not normalize `{bound}`")); } } } bounds.push(type_outlives); } } // FIXME(-Znext-trait-solver): Normalize these. let higher_ranked_assumptions = infcx.take_registered_region_assumptions(); let higher_ranked_assumptions = elaborate::elaborate_outlives_assumptions(infcx.tcx, higher_ranked_assumptions); // FIXME: This needs to be modified so that we normalize the known type // outlives obligations then elaborate them into their region/type components. // Otherwise, ` as Mirror>::Assoc: 'b` will not imply `'a: 'b` even // if we can normalize `'a`. 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 InferCtxtRegionExt<'tcx>)] impl<'tcx> InferCtxt<'tcx> { /// Resolve regions, using the deep normalizer to normalize any type-outlives /// obligations in the process. This is in `rustc_trait_selection` because /// we need to normalize. /// /// Prefer this method over `resolve_regions_with_normalize`, unless you are /// doing something specific for normalization. /// /// 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>, ) -> Vec> { self.resolve_regions_with_outlives_env(&OutlivesEnvironment::new( self, body_id, param_env, assumed_wf_tys, )) } /// Don't call this directly unless you know what you're doing. fn resolve_regions_with_outlives_env( &self, outlives_env: &OutlivesEnvironment<'tcx>, ) -> Vec> { 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, ), ty, ) .map_err(|_: Vec>| NoSolution) } else { Ok(ty) } }) } }