diff options
| author | Michael Goulet <michael@errs.io> | 2025-01-25 04:26:32 +0000 |
|---|---|---|
| committer | Michael Goulet <michael@errs.io> | 2025-01-28 18:55:03 +0000 |
| commit | 48b7e38c0607e856dbbb932e60ecc85e45a1427d (patch) | |
| tree | 8940572ec00be905372772a0ce230cacab287750 | |
| parent | 2b8930c71c8040d338f99e1b1be6f1056edd6638 (diff) | |
| download | rust-48b7e38c0607e856dbbb932e60ecc85e45a1427d.tar.gz rust-48b7e38c0607e856dbbb932e60ecc85e45a1427d.zip | |
Move outlives env computation into methods
8 files changed, 71 insertions, 49 deletions
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 1e7451a16af..5440d451ec8 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -1,6 +1,8 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_errors::ErrorGuaranteed; +use rustc_hir::OpaqueTyOrigin; use rustc_hir::def_id::LocalDefId; +use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, TyCtxtInferExt as _}; use rustc_macros::extension; use rustc_middle::ty::fold::fold_regions; @@ -10,6 +12,7 @@ use rustc_middle::ty::{ TypingMode, }; use rustc_span::Span; +use rustc_trait_selection::regions::OutlivesEnvironmentBuildExt; use rustc_trait_selection::traits::ObligationCtxt; use tracing::{debug, instrument}; @@ -406,10 +409,6 @@ impl<'tcx> LazyOpaqueTyEnv<'tcx> { } fn get_canonical_args(&self) -> ty::GenericArgsRef<'tcx> { - use rustc_hir as hir; - use rustc_infer::infer::outlives::env::OutlivesEnvironment; - use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _; - if let Some(&canonical_args) = self.canonical_args.get() { return canonical_args; } @@ -417,9 +416,9 @@ impl<'tcx> LazyOpaqueTyEnv<'tcx> { let &Self { tcx, def_id, .. } = self; let origin = tcx.local_opaque_ty_origin(def_id); let parent = match origin { - hir::OpaqueTyOrigin::FnReturn { parent, .. } - | hir::OpaqueTyOrigin::AsyncFn { parent, .. } - | hir::OpaqueTyOrigin::TyAlias { parent, .. } => parent, + OpaqueTyOrigin::FnReturn { parent, .. } + | OpaqueTyOrigin::AsyncFn { parent, .. } + | OpaqueTyOrigin::TyAlias { parent, .. } => parent, }; let param_env = tcx.param_env(parent); let args = GenericArgs::identity_for_item(tcx, parent).extend_to( @@ -439,8 +438,7 @@ impl<'tcx> LazyOpaqueTyEnv<'tcx> { tcx.dcx().span_delayed_bug(tcx.def_span(def_id), "error getting implied bounds"); Default::default() }); - let implied_bounds = infcx.implied_bounds_tys(parent, param_env, wf_tys); - let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); + let outlives_env = OutlivesEnvironment::new(&infcx, parent, param_env, wf_tys); let mut seen = vec![tcx.lifetimes.re_static]; let canonical_args = fold_regions(tcx, args, |r1, _| { diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 5023a09e2f3..83bb8c0dfaf 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -25,11 +25,10 @@ use rustc_middle::{bug, span_bug}; use rustc_session::parse::feature_err; use rustc_span::{DUMMY_SP, Ident, Span, sym}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; -use rustc_trait_selection::regions::InferCtxtRegionExt; +use rustc_trait_selection::regions::{InferCtxtRegionExt, OutlivesEnvironmentBuildExt}; use rustc_trait_selection::traits::misc::{ ConstParamTyImplementationError, type_allowed_to_implement_const_param_ty, }; -use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; use rustc_trait_selection::traits::{ self, FulfillmentError, Obligation, ObligationCause, ObligationCauseCode, ObligationCtxt, @@ -128,13 +127,13 @@ where let infcx_compat = infcx.fork(); // We specifically want to call the non-compat version of `implied_bounds_tys`; we do this always. - let implied_bounds = infcx.implied_bounds_tys_compat( + let outlives_env = OutlivesEnvironment::new_with_implied_bounds_compat( + &infcx, body_def_id, param_env, assumed_wf_types.iter().copied(), false, ); - let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); lint_redundant_lifetimes(tcx, body_def_id, &outlives_env); @@ -176,9 +175,13 @@ where // but that does result in slightly more work when this option is set and // just obscures what we mean here anyways. Let's just be explicit. if is_bevy && !infcx.tcx.sess.opts.unstable_opts.no_implied_bounds_compat { - let implied_bounds = - infcx_compat.implied_bounds_tys_compat(body_def_id, param_env, assumed_wf_types, true); - let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); + let outlives_env = OutlivesEnvironment::new_with_implied_bounds_compat( + &infcx, + body_def_id, + param_env, + assumed_wf_types, + true, + ); let errors_compat = infcx_compat.resolve_regions_with_outlives_env(&outlives_env); if errors_compat.is_empty() { Ok(()) diff --git a/compiler/rustc_infer/src/infer/outlives/env.rs b/compiler/rustc_infer/src/infer/outlives/env.rs index 9300fc574dc..f8ab0b53a00 100644 --- a/compiler/rustc_infer/src/infer/outlives/env.rs +++ b/compiler/rustc_infer/src/infer/outlives/env.rs @@ -59,12 +59,6 @@ pub struct OutlivesEnvironment<'tcx> { pub type RegionBoundPairs<'tcx> = FxIndexSet<ty::OutlivesPredicate<'tcx, GenericKind<'tcx>>>; impl<'tcx> OutlivesEnvironment<'tcx> { - /// Create a new `OutlivesEnvironment` without extra outlives bounds. - #[inline] - pub fn new(param_env: ty::ParamEnv<'tcx>) -> Self { - Self::with_bounds(param_env, vec![]) - } - /// Create a new `OutlivesEnvironment` with extra outlives bounds. pub fn with_bounds( param_env: ty::ParamEnv<'tcx>, diff --git a/compiler/rustc_lint/src/impl_trait_overcaptures.rs b/compiler/rustc_lint/src/impl_trait_overcaptures.rs index d6546066d86..d251b4b7459 100644 --- a/compiler/rustc_lint/src/impl_trait_overcaptures.rs +++ b/compiler/rustc_lint/src/impl_trait_overcaptures.rs @@ -25,8 +25,8 @@ use rustc_span::{Span, Symbol}; use rustc_trait_selection::errors::{ AddPreciseCapturingForOvercapture, impl_trait_overcapture_suggestion, }; +use rustc_trait_selection::regions::OutlivesEnvironmentBuildExt; use rustc_trait_selection::traits::ObligationCtxt; -use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt; use crate::{LateContext, LateLintPass, fluent_generated as fluent}; @@ -190,9 +190,7 @@ fn check_fn(tcx: TyCtxt<'_>, parent_def_id: LocalDefId) { let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env); let ocx = ObligationCtxt::new(&infcx); let assumed_wf_tys = ocx.assumed_wf_types(param_env, parent_def_id).unwrap_or_default(); - let implied_bounds = - infcx.implied_bounds_tys_compat(parent_def_id, param_env, assumed_wf_tys, false); - OutlivesEnvironment::with_bounds(param_env, implied_bounds) + OutlivesEnvironment::new(&infcx, parent_def_id, param_env, assumed_wf_tys) }), }); } diff --git a/compiler/rustc_trait_selection/src/regions.rs b/compiler/rustc_trait_selection/src/regions.rs index 1bae6c80cfa..fc9fa44b4c6 100644 --- a/compiler/rustc_trait_selection/src/regions.rs +++ b/compiler/rustc_trait_selection/src/regions.rs @@ -9,6 +9,46 @@ use rustc_middle::ty::{self, Ty}; 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<Item = Ty<'tcx>>, + ) -> Self { + Self::new_with_implied_bounds_compat( + infcx, + body_id, + param_env, + assumed_wf_tys, + !infcx.tcx.sess.opts.unstable_opts.no_implied_bounds_compat, + ) + } + + 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>>, + implied_bounds_compat: bool, + ) -> Self { + // FIXME: This needs to be modified so that we normalize the known type + // outlives obligations then elaborate them into their region/type components. + // Otherwise, `<W<'a> as Mirror>::Assoc: 'b` will not imply `'a: 'b` even + // if we can normalize `'a`. + OutlivesEnvironment::with_bounds( + param_env, + infcx.implied_bounds_tys_with_compat( + body_id, + param_env, + assumed_wf_tys, + implied_bounds_compat, + ), + ) + } +} + #[extension(pub trait InferCtxtRegionExt<'tcx>)] impl<'tcx> InferCtxt<'tcx> { /// Resolve regions, using the deep normalizer to normalize any type-outlives @@ -23,9 +63,11 @@ impl<'tcx> InferCtxt<'tcx> { param_env: ty::ParamEnv<'tcx>, assumed_wf_tys: impl IntoIterator<Item = Ty<'tcx>>, ) -> Vec<RegionResolutionError<'tcx>> { - self.resolve_regions_with_outlives_env(&OutlivesEnvironment::with_bounds( + self.resolve_regions_with_outlives_env(&OutlivesEnvironment::new( + self, + body_id, param_env, - self.implied_bounds_tys(body_id, param_env, assumed_wf_tys), + assumed_wf_tys, )) } diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 9a53e8a5d51..1fca2f4da7e 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -6,6 +6,7 @@ use std::iter; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet, IndexEntry}; use rustc_data_structures::unord::UnordSet; +use rustc_hir::def_id::CRATE_DEF_ID; use rustc_infer::infer::DefineOpaqueTypes; use rustc_middle::ty::{Region, RegionVid}; use tracing::debug; @@ -13,6 +14,7 @@ use tracing::debug; use super::*; use crate::errors::UnableToConstructConstantValue; use crate::infer::region_constraints::{Constraint, RegionConstraintData}; +use crate::regions::OutlivesEnvironmentBuildExt; use crate::traits::project::ProjectAndUnifyResult; // FIXME(twk): this is obviously not nice to duplicate like that @@ -158,7 +160,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { panic!("Unable to fulfill trait {trait_did:?} for '{ty:?}': {errors:?}"); } - let outlives_env = OutlivesEnvironment::new(full_env); + let outlives_env = OutlivesEnvironment::new(&infcx, CRATE_DEF_ID, full_env, []); let _ = infcx.process_registered_region_obligations(&outlives_env, |ty, _| Ok(ty)); let region_data = infcx.inner.borrow_mut().unwrap_region_constraints().data().clone(); diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs index eecc499f384..18932695807 100644 --- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs @@ -108,8 +108,9 @@ fn implied_outlives_bounds<'a, 'tcx>( #[extension(pub trait InferCtxtExt<'tcx>)] impl<'tcx> InferCtxt<'tcx> { - /// Do *NOT* call this directly. - fn implied_bounds_tys_compat<Tys: IntoIterator<Item = Ty<'tcx>>>( + /// Do *NOT* call this directly. You probably want to construct a `OutlivesEnvironment` + /// instead if you're interested in the implied bounds for a given signature. + fn implied_bounds_tys_with_compat<Tys: IntoIterator<Item = Ty<'tcx>>>( &self, body_id: LocalDefId, param_env: ParamEnv<'tcx>, @@ -119,20 +120,4 @@ impl<'tcx> InferCtxt<'tcx> { tys.into_iter() .flat_map(move |ty| implied_outlives_bounds(self, param_env, body_id, ty, compat)) } - - /// If `-Z no-implied-bounds-compat` is set, calls `implied_bounds_tys_compat` - /// with `compat` set to `true`, otherwise `false`. - fn implied_bounds_tys( - &self, - body_id: LocalDefId, - param_env: ParamEnv<'tcx>, - tys: impl IntoIterator<Item = Ty<'tcx>>, - ) -> impl Iterator<Item = OutlivesBound<'tcx>> { - self.implied_bounds_tys_compat( - body_id, - param_env, - tys, - !self.tcx.sess.opts.unstable_opts.no_implied_bounds_compat, - ) - } } diff --git a/src/doc/rustc-dev-guide/src/traits/implied-bounds.md b/src/doc/rustc-dev-guide/src/traits/implied-bounds.md index 63b09a43f47..05693dcd5a1 100644 --- a/src/doc/rustc-dev-guide/src/traits/implied-bounds.md +++ b/src/doc/rustc-dev-guide/src/traits/implied-bounds.md @@ -40,7 +40,7 @@ requirements of impls and functions as explicit predicates. ### using implicit implied bounds as assumptions These bounds are not added to the `ParamEnv` of the affected item itself. For lexical -region resolution they are added using [`fn OutlivesEnvironment::with_bounds`]. +region resolution they are added using [`fn OutlivesEnvironment::new`]. Similarly, during MIR borrowck we add them using [`fn UniversalRegionRelationsBuilder::add_implied_bounds`]. @@ -55,7 +55,7 @@ The assumed outlives constraints for implicit bounds are computed using the MIR borrowck adds the outlives constraints for both the normalized and unnormalized types, lexical region resolution [only uses the unnormalized types][notnorm]. -[`fn OutlivesEnvironment::with_bounds`]: https://github.com/rust-lang/rust/blob/5b8bc568d28b2e922290c9a966b3231d0ce9398b/compiler/rustc_infer/src/infer/outlives/env.rs#L90-L97 +[`fn OutlivesEnvironment::new`]: TODO [`fn UniversalRegionRelationsBuilder::add_implied_bounds`]: https://github.com/rust-lang/rust/blob/5b8bc568d28b2e922290c9a966b3231d0ce9398b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs#L316 [mir]: https://github.com/rust-lang/rust/blob/91cae1dcdcf1a31bd8a92e4a63793d65cfe289bb/compiler/rustc_borrowck/src/type_check/free_region_relations.rs#L258-L332 [`fn assumed_wf_types`]: https://github.com/rust-lang/rust/blob/5b8bc568d28b2e922290c9a966b3231d0ce9398b/compiler/rustc_ty_utils/src/implied_bounds.rs#L21 |
