diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:06:31 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:06:31 +0000 |
commit | 2ff14448863ac1a1dd9533461708e29aae170c2d (patch) | |
tree | 85b9fea2bbfe3f06473cfa381eed11f273b57c5c /compiler/rustc_infer/src/infer/outlives | |
parent | Adding debian version 1.64.0+dfsg1-1. (diff) | |
download | rustc-2ff14448863ac1a1dd9533461708e29aae170c2d.tar.xz rustc-2ff14448863ac1a1dd9533461708e29aae170c2d.zip |
Adding debian version 1.65.0+dfsg1-2.debian/1.65.0+dfsg1-2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_infer/src/infer/outlives')
5 files changed, 91 insertions, 30 deletions
diff --git a/compiler/rustc_infer/src/infer/outlives/env.rs b/compiler/rustc_infer/src/infer/outlives/env.rs index b2decd64f..9922b156e 100644 --- a/compiler/rustc_infer/src/infer/outlives/env.rs +++ b/compiler/rustc_infer/src/infer/outlives/env.rs @@ -2,6 +2,7 @@ use crate::infer::free_regions::FreeRegionMap; use crate::infer::{GenericKind, InferCtxt}; use crate::traits::query::OutlivesBound; use rustc_data_structures::fx::FxIndexSet; +use rustc_data_structures::transitive_relation::TransitiveRelationBuilder; use rustc_middle::ty::{self, ReEarlyBound, ReFree, ReVar, Region}; use super::explicit_outlives_bounds; @@ -51,23 +52,49 @@ pub struct OutlivesEnvironment<'tcx> { region_bound_pairs: RegionBoundPairs<'tcx>, } +/// Builder of OutlivesEnvironment. +#[derive(Debug)] +struct OutlivesEnvironmentBuilder<'tcx> { + param_env: ty::ParamEnv<'tcx>, + region_relation: TransitiveRelationBuilder<Region<'tcx>>, + region_bound_pairs: RegionBoundPairs<'tcx>, +} + /// "Region-bound pairs" tracks outlives relations that are known to /// be true, either because of explicit where-clauses like `T: 'a` or /// because of implied bounds. pub type RegionBoundPairs<'tcx> = FxIndexSet<ty::OutlivesPredicate<GenericKind<'tcx>, Region<'tcx>>>; -impl<'a, 'tcx> OutlivesEnvironment<'tcx> { - pub fn new(param_env: ty::ParamEnv<'tcx>) -> Self { - let mut env = OutlivesEnvironment { +impl<'tcx> OutlivesEnvironment<'tcx> { + /// Create a builder using `ParamEnv` and add explicit outlives bounds into it. + fn builder(param_env: ty::ParamEnv<'tcx>) -> OutlivesEnvironmentBuilder<'tcx> { + let mut builder = OutlivesEnvironmentBuilder { param_env, - free_region_map: Default::default(), + region_relation: Default::default(), region_bound_pairs: Default::default(), }; - env.add_outlives_bounds(None, explicit_outlives_bounds(param_env)); + builder.add_outlives_bounds(None, explicit_outlives_bounds(param_env)); - env + builder + } + + #[inline] + /// Create a new `OutlivesEnvironment` without extra outlives bounds. + pub fn new(param_env: ty::ParamEnv<'tcx>) -> Self { + Self::builder(param_env).build() + } + + /// Create a new `OutlivesEnvironment` with extra outlives bounds. + pub fn with_bounds<'a>( + param_env: ty::ParamEnv<'tcx>, + infcx: Option<&InferCtxt<'a, 'tcx>>, + extra_bounds: impl IntoIterator<Item = OutlivesBound<'tcx>>, + ) -> Self { + let mut builder = Self::builder(param_env); + builder.add_outlives_bounds(infcx, extra_bounds); + builder.build() } /// Borrows current value of the `free_region_map`. @@ -79,6 +106,18 @@ impl<'a, 'tcx> OutlivesEnvironment<'tcx> { pub fn region_bound_pairs(&self) -> &RegionBoundPairs<'tcx> { &self.region_bound_pairs } +} + +impl<'a, 'tcx> OutlivesEnvironmentBuilder<'tcx> { + #[inline] + #[instrument(level = "debug")] + fn build(self) -> OutlivesEnvironment<'tcx> { + OutlivesEnvironment { + param_env: self.param_env, + free_region_map: FreeRegionMap { relation: self.region_relation.freeze() }, + region_bound_pairs: self.region_bound_pairs, + } + } /// Processes outlives bounds that are known to hold, whether from implied or other sources. /// @@ -86,11 +125,8 @@ impl<'a, 'tcx> OutlivesEnvironment<'tcx> { /// contain inference variables, it must be supplied, in which /// case we will register "givens" on the inference context. (See /// `RegionConstraintData`.) - pub fn add_outlives_bounds<I>( - &mut self, - infcx: Option<&InferCtxt<'a, 'tcx>>, - outlives_bounds: I, - ) where + fn add_outlives_bounds<I>(&mut self, infcx: Option<&InferCtxt<'a, 'tcx>>, outlives_bounds: I) + where I: IntoIterator<Item = OutlivesBound<'tcx>>, { // Record relationships such as `T:'x` that don't go into the @@ -122,7 +158,9 @@ impl<'a, 'tcx> OutlivesEnvironment<'tcx> { // system to be more general and to make use // of *every* relationship that arises here, // but presently we do not.) - self.free_region_map.relate_regions(r_a, r_b); + if r_a.is_free_or_static() && r_b.is_free() { + self.region_relation.add(r_a, r_b) + } } } } diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs index 2a085288f..2d19d1823 100644 --- a/compiler/rustc_infer/src/infer/outlives/mod.rs +++ b/compiler/rustc_infer/src/infer/outlives/mod.rs @@ -9,7 +9,7 @@ pub mod verify; use rustc_middle::traits::query::OutlivesBound; use rustc_middle::ty; -#[instrument(level = "debug", skip(param_env))] +#[instrument(level = "debug", skip(param_env), ret)] pub fn explicit_outlives_bounds<'tcx>( param_env: ty::ParamEnv<'tcx>, ) -> impl Iterator<Item = OutlivesBound<'tcx>> + 'tcx { diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index ad052f58c..5bd1774f6 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -69,6 +69,7 @@ use crate::infer::{ use crate::traits::{ObligationCause, ObligationCauseCode}; use rustc_data_structures::undo_log::UndoLogs; use rustc_hir::def_id::LocalDefId; +use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::{self, Region, Ty, TyCtxt, TypeVisitable}; use smallvec::smallvec; @@ -92,12 +93,14 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { sub_region: Region<'tcx>, cause: &ObligationCause<'tcx>, ) { + debug!(?sup_type, ?sub_region, ?cause); let origin = SubregionOrigin::from_obligation_cause(cause, || { infer::RelateParamBound( cause.span, sup_type, match cause.code().peel_derives() { - ObligationCauseCode::BindingObligation(_, span) => Some(*span), + ObligationCauseCode::BindingObligation(_, span) + | ObligationCauseCode::ExprBindingObligation(_, span, ..) => Some(*span), _ => None, }, ) @@ -161,7 +164,8 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { let outlives = &mut TypeOutlives::new(self, self.tcx, ®ion_bound_pairs, None, param_env); - outlives.type_must_outlive(origin, sup_type, sub_region); + let category = origin.to_constraint_category(); + outlives.type_must_outlive(origin, sup_type, sub_region, category); } } @@ -205,6 +209,7 @@ pub trait TypeOutlivesDelegate<'tcx> { origin: SubregionOrigin<'tcx>, a: ty::Region<'tcx>, b: ty::Region<'tcx>, + constraint_category: ConstraintCategory<'tcx>, ); fn push_verify( @@ -247,19 +252,19 @@ where /// - `origin`, the reason we need this constraint /// - `ty`, the type `T` /// - `region`, the region `'a` + #[instrument(level = "debug", skip(self))] pub fn type_must_outlive( &mut self, origin: infer::SubregionOrigin<'tcx>, ty: Ty<'tcx>, region: ty::Region<'tcx>, + category: ConstraintCategory<'tcx>, ) { - debug!("type_must_outlive(ty={:?}, region={:?}, origin={:?})", ty, region, origin); - assert!(!ty.has_escaping_bound_vars()); let mut components = smallvec![]; push_outlives_components(self.tcx, ty, &mut components); - self.components_must_outlive(origin, &components, region); + self.components_must_outlive(origin, &components, region, category); } fn components_must_outlive( @@ -267,12 +272,13 @@ where origin: infer::SubregionOrigin<'tcx>, components: &[Component<'tcx>], region: ty::Region<'tcx>, + category: ConstraintCategory<'tcx>, ) { for component in components.iter() { let origin = origin.clone(); match component { Component::Region(region1) => { - self.delegate.push_sub_region_constraint(origin, region, *region1); + self.delegate.push_sub_region_constraint(origin, region, *region1, category); } Component::Param(param_ty) => { self.param_ty_must_outlive(origin, region, *param_ty); @@ -281,7 +287,7 @@ where self.projection_must_outlive(origin, region, *projection_ty); } Component::EscapingProjection(subcomponents) => { - self.components_must_outlive(origin, &subcomponents, region); + self.components_must_outlive(origin, &subcomponents, region, category); } Component::UnresolvedInferenceVariable(v) => { // ignore this, we presume it will yield an error @@ -312,7 +318,7 @@ where self.delegate.push_verify(origin, generic, region, verify_bound); } - #[tracing::instrument(level = "debug", skip(self))] + #[instrument(level = "debug", skip(self))] fn projection_must_outlive( &mut self, origin: infer::SubregionOrigin<'tcx>, @@ -388,13 +394,19 @@ where if approx_env_bounds.is_empty() && trait_bounds.is_empty() && needs_infer { debug!("projection_must_outlive: no declared bounds"); + let constraint = origin.to_constraint_category(); for k in projection_ty.substs { match k.unpack() { GenericArgKind::Lifetime(lt) => { - self.delegate.push_sub_region_constraint(origin.clone(), region, lt); + self.delegate.push_sub_region_constraint( + origin.clone(), + region, + lt, + constraint, + ); } GenericArgKind::Type(ty) => { - self.type_must_outlive(origin.clone(), ty, region); + self.type_must_outlive(origin.clone(), ty, region, constraint); } GenericArgKind::Const(_) => { // Const parameters don't impose constraints. @@ -432,7 +444,8 @@ where let unique_bound = trait_bounds[0]; debug!("projection_must_outlive: unique trait bound = {:?}", unique_bound); debug!("projection_must_outlive: unique declared bound appears in trait ref"); - self.delegate.push_sub_region_constraint(origin, region, unique_bound); + let category = origin.to_constraint_category(); + self.delegate.push_sub_region_constraint(origin, region, unique_bound, category); return; } @@ -454,6 +467,7 @@ impl<'cx, 'tcx> TypeOutlivesDelegate<'tcx> for &'cx InferCtxt<'cx, 'tcx> { origin: SubregionOrigin<'tcx>, a: ty::Region<'tcx>, b: ty::Region<'tcx>, + _constraint_category: ConstraintCategory<'tcx>, ) { self.sub_regions(origin, a, b) } diff --git a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs index 772e297b7..a5c21f0fb 100644 --- a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs +++ b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs @@ -34,7 +34,7 @@ use crate::infer::region_constraints::VerifyIfEq; /// like are used. This is a particular challenge since this function is invoked /// very late in inference and hence cannot make use of the normal inference /// machinery. -#[tracing::instrument(level = "debug", skip(tcx, param_env))] +#[instrument(level = "debug", skip(tcx, param_env))] pub fn extract_verify_if_eq<'tcx>( tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -71,7 +71,7 @@ pub fn extract_verify_if_eq<'tcx>( } /// True if a (potentially higher-ranked) outlives -#[tracing::instrument(level = "debug", skip(tcx, param_env))] +#[instrument(level = "debug", skip(tcx, param_env))] pub(super) fn can_match_erased_ty<'tcx>( tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -110,7 +110,7 @@ impl<'tcx> Match<'tcx> { /// Binds the pattern variable `br` to `value`; returns an `Err` if the pattern /// is already bound to a different value. - #[tracing::instrument(level = "debug", skip(self))] + #[instrument(level = "debug", skip(self))] fn bind( &mut self, br: ty::BoundRegion, @@ -174,7 +174,14 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> { #[instrument(skip(self), level = "debug")] fn tys(&mut self, pattern: Ty<'tcx>, value: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { - if pattern == value { Ok(pattern) } else { relate::super_relate_tys(self, pattern, value) } + if let ty::Error(_) = pattern.kind() { + // Unlike normal `TypeRelation` rules, `ty::Error` does not equal any type. + self.no_match() + } else if pattern == value { + Ok(pattern) + } else { + relate::super_relate_tys(self, pattern, value) + } } #[instrument(skip(self), level = "debug")] diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs index c7d7ef40d..752334950 100644 --- a/compiler/rustc_infer/src/infer/outlives/verify.rs +++ b/compiler/rustc_infer/src/infer/outlives/verify.rs @@ -50,13 +50,13 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { } } + #[instrument(level = "debug", skip(self))] fn param_bound(&self, param_ty: ty::ParamTy) -> VerifyBound<'tcx> { - debug!("param_bound(param_ty={:?})", param_ty); - // Start with anything like `T: 'a` we can scrape from the // environment. If the environment contains something like // `for<'a> T: 'a`, then we know that `T` outlives everything. let declared_bounds_from_env = self.declared_generic_bounds_from_env(param_ty); + debug!(?declared_bounds_from_env); let mut param_bounds = vec![]; for declared_bound in declared_bounds_from_env { let bound_region = declared_bound.map_bound(|outlives| outlives.1); @@ -65,6 +65,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { param_bounds.push(VerifyBound::OutlivedBy(region)); } else { // This is `for<'a> T: 'a`. This means that `T` outlives everything! All done here. + debug!("found that {param_ty:?} outlives any lifetime, returning empty vector"); return VerifyBound::AllBounds(vec![]); } } @@ -72,6 +73,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { // Add in the default bound of fn body that applies to all in // scope type parameters: if let Some(r) = self.implicit_region_bound { + debug!("adding implicit region bound of {r:?}"); param_bounds.push(VerifyBound::OutlivedBy(r)); } |