From fef38a6337c6acf14eb70bf013717f484aa57eec Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 25 Dec 2023 21:37:29 +0000 Subject: [PATCH] Normalize caller bounds --- .../src/type_check/constraint_conversion.rs | 3 +- .../src/infer/outlives/obligations.rs | 28 ++++++++++++++++--- .../rustc_infer/src/infer/outlives/verify.rs | 10 +++---- compiler/rustc_infer/src/lib.rs | 1 + 4 files changed, 32 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index 21d8026e1708..02ef7357d664 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -157,7 +157,8 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { tcx, region_bound_pairs, Some(implicit_region_bound), - param_env, + // FIXME(-Znext-solver): These bounds are not normalized! + param_env.caller_bounds(), ) .type_must_outlive(origin, t1, r2, constraint_category); } diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 1621e323d2ca..bc66522a8b6c 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -68,8 +68,9 @@ 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; use super::env::OutlivesEnvironment; @@ -131,6 +132,25 @@ impl<'tcx> InferCtxt<'tcx> { ) -> Result<(), (E, SubregionOrigin<'tcx>)> { assert!(!self.in_snapshot(), "cannot process registered region obligations in a snapshot"); + let normalized_caller_bounds: Vec<_> = outlives_env + .param_env + .caller_bounds() + .iter() + .filter_map(|clause| { + let bound_clause = clause.kind(); + 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) + })) + }) + // FIXME: 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 { @@ -142,7 +162,7 @@ impl<'tcx> InferCtxt<'tcx> { self.tcx, outlives_env.region_bound_pairs(), None, - outlives_env.param_env, + &normalized_caller_bounds, ); let category = origin.to_constraint_category(); outlives.type_must_outlive(origin, sup_type, sub_region, category); @@ -196,7 +216,7 @@ where tcx: TyCtxt<'tcx>, region_bound_pairs: &'cx RegionBoundPairs<'tcx>, implicit_region_bound: Option>, - param_env: ty::ParamEnv<'tcx>, + caller_bounds: &'cx [ty::Clause<'tcx>], ) -> Self { Self { delegate, @@ -205,7 +225,7 @@ where tcx, region_bound_pairs, implicit_region_bound, - param_env, + caller_bounds, ), } } diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs index 7a85268492b4..2ad8b6b98e3e 100644 --- a/compiler/rustc_infer/src/infer/outlives/verify.rs +++ b/compiler/rustc_infer/src/infer/outlives/verify.rs @@ -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>, - param_env: ty::ParamEnv<'tcx>, + caller_bounds: &'cx [ty::Clause<'tcx>], } impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { @@ -31,9 +31,9 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { tcx: TyCtxt<'tcx>, region_bound_pairs: &'cx RegionBoundPairs<'tcx>, implicit_region_bound: Option>, - param_env: ty::ParamEnv<'tcx>, + caller_bounds: &'cx [ty::Clause<'tcx>], ) -> Self { - Self { tcx, region_bound_pairs, implicit_region_bound, param_env } + Self { tcx, region_bound_pairs, implicit_region_bound, caller_bounds } } #[instrument(level = "debug", skip(self))] @@ -219,8 +219,8 @@ 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 c_b = self.param_env.caller_bounds(); - let param_bounds = self.collect_outlives_from_clause_list(erased_ty, c_b.into_iter()); + let param_bounds = + self.collect_outlives_from_clause_list(erased_ty, self.caller_bounds.iter().copied()); // Next, collect regions we scraped from the well-formedness // constraints in the fn signature. To do that, we walk the list diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index 9e3de1825ed3..e2dd4b49e1a4 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -21,6 +21,7 @@ #![feature(extend_one)] #![feature(let_chains)] #![feature(if_let_guard)] +#![feature(iterator_try_collect)] #![feature(min_specialization)] #![feature(try_blocks)] #![recursion_limit = "512"] // For rustdoc