Apply suggestions from review

This commit is contained in:
Michael Goulet 2024-01-26 19:18:14 +00:00
parent dc050f6d5b
commit 720d7a7a03
11 changed files with 77 additions and 50 deletions

View File

@ -33,7 +33,7 @@ pub(crate) struct ConstraintConversion<'a, 'tcx> {
/// our special inference variable there, we would mess that up.
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
implicit_region_bound: ty::Region<'tcx>,
param_env: ty::ParamEnv<'tcx>,
known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>],
locations: Locations,
span: Span,
category: ConstraintCategory<'tcx>,
@ -47,7 +47,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
universal_regions: &'a UniversalRegions<'tcx>,
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
implicit_region_bound: ty::Region<'tcx>,
param_env: ty::ParamEnv<'tcx>,
known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>],
locations: Locations,
span: Span,
category: ConstraintCategory<'tcx>,
@ -59,7 +59,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
universal_regions,
region_bound_pairs,
implicit_region_bound,
param_env,
known_type_outlives_obligations,
locations,
span,
category,
@ -136,7 +136,11 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
// Extract out various useful fields we'll need below.
let ConstraintConversion {
tcx, region_bound_pairs, implicit_region_bound, param_env, ..
tcx,
region_bound_pairs,
implicit_region_bound,
known_type_outlives_obligations,
..
} = *self;
let ty::OutlivesPredicate(k1, r2) = predicate;
@ -157,8 +161,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
tcx,
region_bound_pairs,
Some(implicit_region_bound),
// FIXME(-Znext-solver): These bounds are not normalized!
param_env.caller_bounds(),
known_type_outlives_obligations,
)
.type_must_outlive(origin, t1, r2, constraint_category);
}

View File

@ -45,12 +45,14 @@ type NormalizedInputsAndOutput<'tcx> = Vec<Ty<'tcx>>;
pub(crate) struct CreateResult<'tcx> {
pub(crate) universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
pub(crate) region_bound_pairs: RegionBoundPairs<'tcx>,
pub(crate) known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>],
pub(crate) normalized_inputs_and_output: NormalizedInputsAndOutput<'tcx>,
}
pub(crate) fn create<'tcx>(
infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>],
implicit_region_bound: ty::Region<'tcx>,
universal_regions: &Rc<UniversalRegions<'tcx>>,
constraints: &mut MirTypeckRegionConstraints<'tcx>,
@ -58,6 +60,7 @@ pub(crate) fn create<'tcx>(
UniversalRegionRelationsBuilder {
infcx,
param_env,
known_type_outlives_obligations,
implicit_region_bound,
constraints,
universal_regions: universal_regions.clone(),
@ -175,6 +178,7 @@ impl UniversalRegionRelations<'_> {
struct UniversalRegionRelationsBuilder<'this, 'tcx> {
infcx: &'this InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>],
universal_regions: Rc<UniversalRegions<'tcx>>,
implicit_region_bound: ty::Region<'tcx>,
constraints: &'this mut MirTypeckRegionConstraints<'tcx>,
@ -200,7 +204,8 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
let defining_ty_def_id = self.universal_regions.defining_ty.def_id().expect_local();
let span = tcx.def_span(defining_ty_def_id);
// Insert the facts we know from the predicates. Why? Why not.
// Insert the `'a: 'b` we know from the predicates.
// This does not consider the type-outlives.
let param_env = self.param_env;
self.add_outlives_bounds(outlives::explicit_outlives_bounds(param_env));
@ -308,6 +313,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
outlives: self.outlives.freeze(),
inverse_outlives: self.inverse_outlives.freeze(),
}),
known_type_outlives_obligations: self.known_type_outlives_obligations,
region_bound_pairs: self.region_bound_pairs,
normalized_inputs_and_output,
}
@ -322,7 +328,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
&self.universal_regions,
&self.region_bound_pairs,
self.implicit_region_bound,
self.param_env,
self.known_type_outlives_obligations,
Locations::All(span),
span,
ConstraintCategory::Internal,

View File

@ -152,9 +152,14 @@ pub(crate) fn type_check<'mir, 'tcx>(
universal_region_relations,
region_bound_pairs,
normalized_inputs_and_output,
known_type_outlives_obligations,
} = free_region_relations::create(
infcx,
param_env,
// FIXME(-Znext-solver): These are unnormalized. Normalize them.
infcx.tcx.arena.alloc_from_iter(
param_env.caller_bounds().iter().filter_map(|clause| clause.as_type_outlives_clause()),
),
implicit_region_bound,
universal_regions,
&mut constraints,
@ -176,6 +181,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
body,
param_env,
&region_bound_pairs,
known_type_outlives_obligations,
implicit_region_bound,
&mut borrowck_context,
);
@ -850,6 +856,7 @@ struct TypeChecker<'a, 'tcx> {
/// all of the promoted items.
user_type_annotations: &'a CanonicalUserTypeAnnotations<'tcx>,
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>],
implicit_region_bound: ty::Region<'tcx>,
reported_errors: FxIndexSet<(Ty<'tcx>, Span)>,
borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>,
@ -1000,6 +1007,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
body: &'a Body<'tcx>,
param_env: ty::ParamEnv<'tcx>,
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>],
implicit_region_bound: ty::Region<'tcx>,
borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>,
) -> Self {
@ -1010,6 +1018,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
user_type_annotations: &body.user_type_annotations,
param_env,
region_bound_pairs,
known_type_outlives_obligations,
implicit_region_bound,
borrowck_context,
reported_errors: Default::default(),
@ -1127,7 +1136,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
self.borrowck_context.universal_regions,
self.region_bound_pairs,
self.implicit_region_bound,
self.param_env,
self.known_type_outlives_obligations,
locations,
locations.span(self.body),
category,
@ -2731,7 +2740,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
self.borrowck_context.universal_regions,
self.region_bound_pairs,
self.implicit_region_bound,
self.param_env,
self.known_type_outlives_obligations,
locations,
DUMMY_SP, // irrelevant; will be overridden.
ConstraintCategory::Boring, // same as above.

View File

@ -189,7 +189,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
RegionResolutionError::UpperBoundUniverseConflict(a, _, _, _, b) => {
format!("{b}: {a}", a = ty::Region::new_var(tcx, a))
}
RegionResolutionError::CannotNormalize(..) => todo!(),
RegionResolutionError::CannotNormalize(..) => unreachable!(),
};
guar = Some(
struct_span_code_err!(

View File

@ -1,7 +1,7 @@
//! Various code related to computing outlives relations.
use self::env::OutlivesEnvironment;
use super::region_constraints::RegionConstraintData;
use super::{InferCtxt, RegionResolutionError};
use super::{InferCtxt, RegionResolutionError, SubregionOrigin};
use crate::infer::free_regions::RegionRelations;
use crate::infer::lexical_region_resolve;
use rustc_middle::traits::query::OutlivesBound;
@ -42,14 +42,14 @@ impl<'tcx> InferCtxt<'tcx> {
/// done -- or the compiler will panic -- but it is legal to use
/// `resolve_vars_if_possible` as well as `fully_resolve`.
///
/// If you are in a crate that has access to `rustc_trai_selection`,
/// then it's probably better to use `resolve_regions_normalizing_outlives_obligations`,
/// If you are in a crate that has access to `rustc_trait_selection`,
/// then it's probably better to use `resolve_regions`,
/// which knows how to normalize registered region obligations.
#[must_use]
pub fn resolve_regions_with_normalize(
&self,
outlives_env: &OutlivesEnvironment<'tcx>,
deeply_normalize_ty: impl Fn(Ty<'tcx>) -> Result<Ty<'tcx>, Ty<'tcx>>,
deeply_normalize_ty: impl Fn(Ty<'tcx>, SubregionOrigin<'tcx>) -> Result<Ty<'tcx>, Ty<'tcx>>,
) -> Vec<RegionResolutionError<'tcx>> {
match self.process_registered_region_obligations(outlives_env, deeply_normalize_ty) {
Ok(()) => {}

View File

@ -68,8 +68,8 @@ use crate::infer::{
use crate::traits::{ObligationCause, ObligationCauseCode};
use rustc_data_structures::undo_log::UndoLogs;
use rustc_middle::mir::ConstraintCategory;
use rustc_middle::ty::GenericArgKind;
use rustc_middle::ty::{self, GenericArgsRef, Region, Ty, TyCtxt, TypeVisitableExt};
use rustc_middle::ty::{GenericArgKind, ToPredicate};
use rustc_span::DUMMY_SP;
use smallvec::smallvec;
@ -128,7 +128,7 @@ impl<'tcx> InferCtxt<'tcx> {
pub fn process_registered_region_obligations<E>(
&self,
outlives_env: &OutlivesEnvironment<'tcx>,
mut deeply_normalize_ty: impl FnMut(Ty<'tcx>) -> Result<Ty<'tcx>, E>,
mut deeply_normalize_ty: impl FnMut(Ty<'tcx>, SubregionOrigin<'tcx>) -> Result<Ty<'tcx>, E>,
) -> Result<(), (E, SubregionOrigin<'tcx>)> {
assert!(!self.in_snapshot(), "cannot process registered region obligations in a snapshot");
@ -141,20 +141,23 @@ impl<'tcx> InferCtxt<'tcx> {
let ty::ClauseKind::TypeOutlives(outlives) = bound_clause.skip_binder() else {
return None;
};
Some(deeply_normalize_ty(outlives.0).map(|ty| {
bound_clause
.rebind(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, outlives.1)))
.to_predicate(self.tcx)
}))
Some(
deeply_normalize_ty(
outlives.0,
SubregionOrigin::AscribeUserTypeProvePredicate(DUMMY_SP),
)
.map(|ty| bound_clause.rebind(ty::OutlivesPredicate(ty, outlives.1))),
)
})
// FIXME: How do we accurately report an error here :(
// FIXME(-Znext-solver): How do we accurately report an error here :(
.try_collect()
.map_err(|e| (e, SubregionOrigin::AscribeUserTypeProvePredicate(DUMMY_SP)))?;
let my_region_obligations = self.take_registered_region_obligations();
for RegionObligation { sup_type, sub_region, origin } in my_region_obligations {
let sup_type = deeply_normalize_ty(sup_type).map_err(|e| (e, origin.clone()))?;
let sup_type =
deeply_normalize_ty(sup_type, origin.clone()).map_err(|e| (e, origin.clone()))?;
debug!(?sup_type, ?sub_region, ?origin);
let outlives = &mut TypeOutlives::new(
@ -216,7 +219,7 @@ where
tcx: TyCtxt<'tcx>,
region_bound_pairs: &'cx RegionBoundPairs<'tcx>,
implicit_region_bound: Option<ty::Region<'tcx>>,
caller_bounds: &'cx [ty::Clause<'tcx>],
caller_bounds: &'cx [ty::PolyTypeOutlivesPredicate<'tcx>],
) -> Self {
Self {
delegate,

View File

@ -23,7 +23,7 @@ pub struct VerifyBoundCx<'cx, 'tcx> {
/// Outside of borrowck the only way to prove `T: '?0` is by
/// setting `'?0` to `'empty`.
implicit_region_bound: Option<ty::Region<'tcx>>,
caller_bounds: &'cx [ty::Clause<'tcx>],
caller_bounds: &'cx [ty::PolyTypeOutlivesPredicate<'tcx>],
}
impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
@ -31,7 +31,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
tcx: TyCtxt<'tcx>,
region_bound_pairs: &'cx RegionBoundPairs<'tcx>,
implicit_region_bound: Option<ty::Region<'tcx>>,
caller_bounds: &'cx [ty::Clause<'tcx>],
caller_bounds: &'cx [ty::PolyTypeOutlivesPredicate<'tcx>],
) -> Self {
Self { tcx, region_bound_pairs, implicit_region_bound, caller_bounds }
}
@ -219,8 +219,9 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
// To start, collect bounds from user environment. Note that
// parameter environments are already elaborated, so we don't
// have to worry about that.
let param_bounds =
self.collect_outlives_from_clause_list(erased_ty, self.caller_bounds.iter().copied());
let param_bounds = self.caller_bounds.iter().copied().filter(move |outlives_predicate| {
super::test_type_match::can_match_erased_ty(tcx, *outlives_predicate, erased_ty)
});
// Next, collect regions we scraped from the well-formedness
// constraints in the fn signature. To do that, we walk the list
@ -307,22 +308,4 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
.filter_map(|p| p.no_bound_vars())
.map(|OutlivesPredicate(_, r)| r)
}
/// Searches through a predicate list for a predicate `T: 'a`.
///
/// Careful: does not elaborate predicates, and just uses `==`
/// when comparing `ty` for equality, so `ty` must be something
/// that does not involve inference variables and where you
/// otherwise want a precise match.
fn collect_outlives_from_clause_list(
&self,
erased_ty: Ty<'tcx>,
clauses: impl Iterator<Item = ty::Clause<'tcx>>,
) -> impl Iterator<Item = ty::Binder<'tcx, ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>>>
{
let tcx = self.tcx;
clauses.filter_map(|p| p.as_type_outlives_clause()).filter(move |outlives_predicate| {
super::test_type_match::can_match_erased_ty(tcx, *outlives_predicate, erased_ty)
})
}
}

View File

@ -20,12 +20,15 @@ impl<'tcx> InferCtxtRegionExt<'tcx> for InferCtxt<'tcx> {
&self,
outlives_env: &OutlivesEnvironment<'tcx>,
) -> Vec<RegionResolutionError<'tcx>> {
self.resolve_regions(outlives_env, |ty| {
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(), outlives_env.param_env),
self.at(
&ObligationCause::dummy_with_span(origin.span()),
outlives_env.param_env,
),
ty,
)
.map_err(|_| ty)

View File

@ -179,7 +179,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
}
let outlives_env = OutlivesEnvironment::new(full_env);
let _ = infcx.process_registered_region_obligations::<!>(&outlives_env, |ty| Ok(ty));
let _ = infcx.process_registered_region_obligations::<!>(&outlives_env, |ty, _| Ok(ty));
let region_data =
infcx.inner.borrow_mut().unwrap_region_constraints().region_constraint_data().clone();

View File

@ -0,0 +1,13 @@
//~ ERROR the type `<() as StaticTy>::Item<'a>` does not fulfill the required lifetime
// compile-flags: -Znext-solver
// Regression test for rust-lang/trait-system-refactor-initiative#59
trait StaticTy {
type Item<'a>: 'static;
}
impl StaticTy for () {
type Item<'a> = &'a ();
}
fn main() {}

View File

@ -0,0 +1,7 @@
error[E0477]: the type `<() as StaticTy>::Item<'a>` does not fulfill the required lifetime
|
= note: type must satisfy the static lifetime
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0477`.