Skip to content

Commit

Permalink
Apply suggestions from review
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Jan 30, 2024
1 parent dc050f6 commit 720d7a7
Show file tree
Hide file tree
Showing 11 changed files with 77 additions and 50 deletions.
15 changes: 9 additions & 6 deletions compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>,
Expand All @@ -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>,
Expand All @@ -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,
Expand Down Expand Up @@ -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;
Expand All @@ -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);
}
Expand Down
10 changes: 8 additions & 2 deletions compiler/rustc_borrowck/src/type_check/free_region_relations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,19 +45,22 @@ 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>,
) -> CreateResult<'tcx> {
UniversalRegionRelationsBuilder {
infcx,
param_env,
known_type_outlives_obligations,
implicit_region_bound,
constraints,
universal_regions: universal_regions.clone(),
Expand Down Expand Up @@ -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>,
Expand All @@ -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));

Expand Down Expand Up @@ -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,
}
Expand All @@ -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,
Expand Down
13 changes: 11 additions & 2 deletions compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
);
Expand Down Expand Up @@ -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>,
Expand Down Expand Up @@ -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 {
Expand All @@ -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(),
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/check/dropck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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!(
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_infer/src/infer/outlives/mod.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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(()) => {}
Expand Down
23 changes: 13 additions & 10 deletions compiler/rustc_infer/src/infer/outlives/obligations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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");

Expand All @@ -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(
Expand Down Expand Up @@ -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,
Expand Down
27 changes: 5 additions & 22 deletions compiler/rustc_infer/src/infer/outlives/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@ 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> {
pub fn new(
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 }
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
})
}
}
7 changes: 5 additions & 2 deletions compiler/rustc_trait_selection/src/regions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_trait_selection/src/traits/auto_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
13 changes: 13 additions & 0 deletions tests/ui/traits/next-solver/unsound-region-obligation.rs
Original file line number Diff line number Diff line change
@@ -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() {}
7 changes: 7 additions & 0 deletions tests/ui/traits/next-solver/unsound-region-obligation.stderr
Original file line number Diff line number Diff line change
@@ -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`.

0 comments on commit 720d7a7

Please sign in to comment.