Remove unnecessary param-env from lexical region resolution and fully structural relations

This commit is contained in:
Michael Goulet 2023-12-18 21:22:39 +00:00
parent e6d6b1d92c
commit 009cd9c815
9 changed files with 28 additions and 68 deletions

View file

@ -674,13 +674,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
// eagerly. // eagerly.
let mut outlives_requirements = infcx.tcx.is_typeck_child(mir_def_id).then(Vec::new); let mut outlives_requirements = infcx.tcx.is_typeck_child(mir_def_id).then(Vec::new);
self.check_type_tests( self.check_type_tests(infcx, body, outlives_requirements.as_mut(), &mut errors_buffer);
infcx,
param_env,
body,
outlives_requirements.as_mut(),
&mut errors_buffer,
);
debug!(?errors_buffer); debug!(?errors_buffer);
debug!(?outlives_requirements); debug!(?outlives_requirements);
@ -938,7 +932,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
fn check_type_tests( fn check_type_tests(
&self, &self,
infcx: &InferCtxt<'tcx>, infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
body: &Body<'tcx>, body: &Body<'tcx>,
mut propagated_outlives_requirements: Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>, mut propagated_outlives_requirements: Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>,
errors_buffer: &mut RegionErrors<'tcx>, errors_buffer: &mut RegionErrors<'tcx>,
@ -956,7 +949,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
let generic_ty = type_test.generic_kind.to_ty(tcx); let generic_ty = type_test.generic_kind.to_ty(tcx);
if self.eval_verify_bound( if self.eval_verify_bound(
infcx, infcx,
param_env,
generic_ty, generic_ty,
type_test.lower_bound, type_test.lower_bound,
&type_test.verify_bound, &type_test.verify_bound,
@ -967,7 +959,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
if let Some(propagated_outlives_requirements) = &mut propagated_outlives_requirements { if let Some(propagated_outlives_requirements) = &mut propagated_outlives_requirements {
if self.try_promote_type_test( if self.try_promote_type_test(
infcx, infcx,
param_env,
body, body,
type_test, type_test,
propagated_outlives_requirements, propagated_outlives_requirements,
@ -1025,7 +1016,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
fn try_promote_type_test( fn try_promote_type_test(
&self, &self,
infcx: &InferCtxt<'tcx>, infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
body: &Body<'tcx>, body: &Body<'tcx>,
type_test: &TypeTest<'tcx>, type_test: &TypeTest<'tcx>,
propagated_outlives_requirements: &mut Vec<ClosureOutlivesRequirement<'tcx>>, propagated_outlives_requirements: &mut Vec<ClosureOutlivesRequirement<'tcx>>,
@ -1087,7 +1077,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
// where `ur` is a local bound -- we are sometimes in a // where `ur` is a local bound -- we are sometimes in a
// position to prove things that our caller cannot. See // position to prove things that our caller cannot. See
// #53570 for an example. // #53570 for an example.
if self.eval_verify_bound(infcx, param_env, generic_ty, ur, &type_test.verify_bound) { if self.eval_verify_bound(infcx, generic_ty, ur, &type_test.verify_bound) {
continue; continue;
} }
@ -1270,7 +1260,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
fn eval_verify_bound( fn eval_verify_bound(
&self, &self,
infcx: &InferCtxt<'tcx>, infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
generic_ty: Ty<'tcx>, generic_ty: Ty<'tcx>,
lower_bound: RegionVid, lower_bound: RegionVid,
verify_bound: &VerifyBound<'tcx>, verify_bound: &VerifyBound<'tcx>,
@ -1279,7 +1268,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
match verify_bound { match verify_bound {
VerifyBound::IfEq(verify_if_eq_b) => { VerifyBound::IfEq(verify_if_eq_b) => {
self.eval_if_eq(infcx, param_env, generic_ty, lower_bound, *verify_if_eq_b) self.eval_if_eq(infcx, generic_ty, lower_bound, *verify_if_eq_b)
} }
VerifyBound::IsEmpty => { VerifyBound::IsEmpty => {
@ -1293,11 +1282,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
} }
VerifyBound::AnyBound(verify_bounds) => verify_bounds.iter().any(|verify_bound| { VerifyBound::AnyBound(verify_bounds) => verify_bounds.iter().any(|verify_bound| {
self.eval_verify_bound(infcx, param_env, generic_ty, lower_bound, verify_bound) self.eval_verify_bound(infcx, generic_ty, lower_bound, verify_bound)
}), }),
VerifyBound::AllBounds(verify_bounds) => verify_bounds.iter().all(|verify_bound| { VerifyBound::AllBounds(verify_bounds) => verify_bounds.iter().all(|verify_bound| {
self.eval_verify_bound(infcx, param_env, generic_ty, lower_bound, verify_bound) self.eval_verify_bound(infcx, generic_ty, lower_bound, verify_bound)
}), }),
} }
} }
@ -1305,19 +1294,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
fn eval_if_eq( fn eval_if_eq(
&self, &self,
infcx: &InferCtxt<'tcx>, infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
generic_ty: Ty<'tcx>, generic_ty: Ty<'tcx>,
lower_bound: RegionVid, lower_bound: RegionVid,
verify_if_eq_b: ty::Binder<'tcx, VerifyIfEq<'tcx>>, verify_if_eq_b: ty::Binder<'tcx, VerifyIfEq<'tcx>>,
) -> bool { ) -> bool {
let generic_ty = self.normalize_to_scc_representatives(infcx.tcx, generic_ty); let generic_ty = self.normalize_to_scc_representatives(infcx.tcx, generic_ty);
let verify_if_eq_b = self.normalize_to_scc_representatives(infcx.tcx, verify_if_eq_b); let verify_if_eq_b = self.normalize_to_scc_representatives(infcx.tcx, verify_if_eq_b);
match test_type_match::extract_verify_if_eq( match test_type_match::extract_verify_if_eq(infcx.tcx, &verify_if_eq_b, generic_ty) {
infcx.tcx,
param_env,
&verify_if_eq_b,
generic_ty,
) {
Some(r) => { Some(r) => {
let r_vid = self.to_region_vid(r); let r_vid = self.to_region_vid(r);
self.eval_outlives(r_vid, lower_bound) self.eval_outlives(r_vid, lower_bound)

View file

@ -2654,8 +2654,7 @@ impl<'tcx> TypeRelation<'tcx> for SameTypeModuloInfer<'_, 'tcx> {
} }
fn param_env(&self) -> ty::ParamEnv<'tcx> { fn param_env(&self) -> ty::ParamEnv<'tcx> {
// Unused, only for consts which we treat as always equal unreachable!("purely structural relation should not need a param-env")
ty::ParamEnv::empty()
} }
fn tag(&self) -> &'static str { fn tag(&self) -> &'static str {

View file

@ -31,13 +31,12 @@ use super::outlives::test_type_match;
/// all the variables as well as a set of errors that must be reported. /// all the variables as well as a set of errors that must be reported.
#[instrument(level = "debug", skip(region_rels, var_infos, data))] #[instrument(level = "debug", skip(region_rels, var_infos, data))]
pub(crate) fn resolve<'tcx>( pub(crate) fn resolve<'tcx>(
param_env: ty::ParamEnv<'tcx>,
region_rels: &RegionRelations<'_, 'tcx>, region_rels: &RegionRelations<'_, 'tcx>,
var_infos: VarInfos, var_infos: VarInfos,
data: RegionConstraintData<'tcx>, data: RegionConstraintData<'tcx>,
) -> (LexicalRegionResolutions<'tcx>, Vec<RegionResolutionError<'tcx>>) { ) -> (LexicalRegionResolutions<'tcx>, Vec<RegionResolutionError<'tcx>>) {
let mut errors = vec![]; let mut errors = vec![];
let mut resolver = LexicalResolver { param_env, region_rels, var_infos, data }; let mut resolver = LexicalResolver { region_rels, var_infos, data };
let values = resolver.infer_variable_values(&mut errors); let values = resolver.infer_variable_values(&mut errors);
(values, errors) (values, errors)
} }
@ -120,7 +119,6 @@ struct RegionAndOrigin<'tcx> {
type RegionGraph<'tcx> = Graph<(), Constraint<'tcx>>; type RegionGraph<'tcx> = Graph<(), Constraint<'tcx>>;
struct LexicalResolver<'cx, 'tcx> { struct LexicalResolver<'cx, 'tcx> {
param_env: ty::ParamEnv<'tcx>,
region_rels: &'cx RegionRelations<'cx, 'tcx>, region_rels: &'cx RegionRelations<'cx, 'tcx>,
var_infos: VarInfos, var_infos: VarInfos,
data: RegionConstraintData<'tcx>, data: RegionConstraintData<'tcx>,
@ -914,12 +912,8 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
match bound { match bound {
VerifyBound::IfEq(verify_if_eq_b) => { VerifyBound::IfEq(verify_if_eq_b) => {
let verify_if_eq_b = var_values.normalize(self.region_rels.tcx, *verify_if_eq_b); let verify_if_eq_b = var_values.normalize(self.region_rels.tcx, *verify_if_eq_b);
match test_type_match::extract_verify_if_eq( match test_type_match::extract_verify_if_eq(self.tcx(), &verify_if_eq_b, generic_ty)
self.tcx(), {
self.param_env,
&verify_if_eq_b,
generic_ty,
) {
Some(r) => { Some(r) => {
self.bound_is_met(&VerifyBound::OutlivedBy(r), var_values, generic_ty, min) self.bound_is_met(&VerifyBound::OutlivedBy(r), var_values, generic_ty, min)
} }

View file

@ -84,7 +84,6 @@ where
} else { } else {
test_type_match::extract_verify_if_eq( test_type_match::extract_verify_if_eq(
tcx, tcx,
param_env,
&outlives.map_bound(|ty::OutlivesPredicate(ty, bound)| { &outlives.map_bound(|ty::OutlivesPredicate(ty, bound)| {
VerifyIfEq { ty, bound } VerifyIfEq { ty, bound }
}), }),

View file

@ -67,7 +67,7 @@ impl<'tcx> InferCtxt<'tcx> {
let region_rels = &RegionRelations::new(self.tcx, outlives_env.free_region_map()); let region_rels = &RegionRelations::new(self.tcx, outlives_env.free_region_map());
let (lexical_region_resolutions, errors) = let (lexical_region_resolutions, errors) =
lexical_region_resolve::resolve(outlives_env.param_env, region_rels, var_infos, data); lexical_region_resolve::resolve(region_rels, var_infos, data);
let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions)); let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions));
assert!(old_value.is_none()); assert!(old_value.is_none());

View file

@ -36,15 +36,14 @@ use crate::infer::region_constraints::VerifyIfEq;
/// like are used. This is a particular challenge since this function is invoked /// 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 /// very late in inference and hence cannot make use of the normal inference
/// machinery. /// machinery.
#[instrument(level = "debug", skip(tcx, param_env))] #[instrument(level = "debug", skip(tcx))]
pub fn extract_verify_if_eq<'tcx>( pub fn extract_verify_if_eq<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
verify_if_eq_b: &ty::Binder<'tcx, VerifyIfEq<'tcx>>, verify_if_eq_b: &ty::Binder<'tcx, VerifyIfEq<'tcx>>,
test_ty: Ty<'tcx>, test_ty: Ty<'tcx>,
) -> Option<ty::Region<'tcx>> { ) -> Option<ty::Region<'tcx>> {
assert!(!verify_if_eq_b.has_escaping_bound_vars()); assert!(!verify_if_eq_b.has_escaping_bound_vars());
let mut m = MatchAgainstHigherRankedOutlives::new(tcx, param_env); let mut m = MatchAgainstHigherRankedOutlives::new(tcx);
let verify_if_eq = verify_if_eq_b.skip_binder(); let verify_if_eq = verify_if_eq_b.skip_binder();
m.relate(verify_if_eq.ty, test_ty).ok()?; m.relate(verify_if_eq.ty, test_ty).ok()?;
@ -73,10 +72,9 @@ pub fn extract_verify_if_eq<'tcx>(
} }
/// True if a (potentially higher-ranked) outlives /// True if a (potentially higher-ranked) outlives
#[instrument(level = "debug", skip(tcx, param_env))] #[instrument(level = "debug", skip(tcx))]
pub(super) fn can_match_erased_ty<'tcx>( pub(super) fn can_match_erased_ty<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
outlives_predicate: ty::Binder<'tcx, ty::TypeOutlivesPredicate<'tcx>>, outlives_predicate: ty::Binder<'tcx, ty::TypeOutlivesPredicate<'tcx>>,
erased_ty: Ty<'tcx>, erased_ty: Ty<'tcx>,
) -> bool { ) -> bool {
@ -87,25 +85,20 @@ pub(super) fn can_match_erased_ty<'tcx>(
// pointless micro-optimization // pointless micro-optimization
true true
} else { } else {
MatchAgainstHigherRankedOutlives::new(tcx, param_env).relate(outlives_ty, erased_ty).is_ok() MatchAgainstHigherRankedOutlives::new(tcx).relate(outlives_ty, erased_ty).is_ok()
} }
} }
struct MatchAgainstHigherRankedOutlives<'tcx> { struct MatchAgainstHigherRankedOutlives<'tcx> {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
pattern_depth: ty::DebruijnIndex, pattern_depth: ty::DebruijnIndex,
map: FxHashMap<ty::BoundRegion, ty::Region<'tcx>>, map: FxHashMap<ty::BoundRegion, ty::Region<'tcx>>,
} }
impl<'tcx> MatchAgainstHigherRankedOutlives<'tcx> { impl<'tcx> MatchAgainstHigherRankedOutlives<'tcx> {
fn new( fn new(tcx: TyCtxt<'tcx>) -> MatchAgainstHigherRankedOutlives<'tcx> {
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> MatchAgainstHigherRankedOutlives<'tcx> {
MatchAgainstHigherRankedOutlives { MatchAgainstHigherRankedOutlives {
tcx, tcx,
param_env,
pattern_depth: ty::INNERMOST, pattern_depth: ty::INNERMOST,
map: FxHashMap::default(), map: FxHashMap::default(),
} }
@ -144,15 +137,17 @@ impl<'tcx> MatchAgainstHigherRankedOutlives<'tcx> {
impl<'tcx> TypeRelation<'tcx> for MatchAgainstHigherRankedOutlives<'tcx> { impl<'tcx> TypeRelation<'tcx> for MatchAgainstHigherRankedOutlives<'tcx> {
fn tag(&self) -> &'static str { fn tag(&self) -> &'static str {
"Match" "MatchAgainstHigherRankedOutlives"
} }
fn tcx(&self) -> TyCtxt<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx self.tcx
} }
fn param_env(&self) -> ty::ParamEnv<'tcx> { fn param_env(&self) -> ty::ParamEnv<'tcx> {
self.param_env unreachable!("purely structural relation should not need a param-env")
} }
fn a_is_expected(&self) -> bool { fn a_is_expected(&self) -> bool {
true true
} // irrelevant } // irrelevant

View file

@ -312,14 +312,8 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
) -> impl Iterator<Item = ty::Binder<'tcx, ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>>> ) -> impl Iterator<Item = ty::Binder<'tcx, ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>>>
{ {
let tcx = self.tcx; let tcx = self.tcx;
let param_env = self.param_env;
clauses.filter_map(|p| p.as_type_outlives_clause()).filter(move |outlives_predicate| { clauses.filter_map(|p| p.as_type_outlives_clause()).filter(move |outlives_predicate| {
super::test_type_match::can_match_erased_ty( super::test_type_match::can_match_erased_ty(tcx, *outlives_predicate, erased_ty)
tcx,
param_env,
*outlives_predicate,
erased_ty,
)
}) })
} }
} }

View file

@ -20,12 +20,11 @@ use crate::ty::{self, InferConst, Ty, TyCtxt};
/// affects any type variables or unification state. /// affects any type variables or unification state.
pub struct MatchAgainstFreshVars<'tcx> { pub struct MatchAgainstFreshVars<'tcx> {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
} }
impl<'tcx> MatchAgainstFreshVars<'tcx> { impl<'tcx> MatchAgainstFreshVars<'tcx> {
pub fn new(tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> MatchAgainstFreshVars<'tcx> { pub fn new(tcx: TyCtxt<'tcx>) -> MatchAgainstFreshVars<'tcx> {
MatchAgainstFreshVars { tcx, param_env } MatchAgainstFreshVars { tcx }
} }
} }
@ -33,13 +32,15 @@ impl<'tcx> TypeRelation<'tcx> for MatchAgainstFreshVars<'tcx> {
fn tag(&self) -> &'static str { fn tag(&self) -> &'static str {
"MatchAgainstFreshVars" "MatchAgainstFreshVars"
} }
fn tcx(&self) -> TyCtxt<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx self.tcx
} }
fn param_env(&self) -> ty::ParamEnv<'tcx> { fn param_env(&self) -> ty::ParamEnv<'tcx> {
self.param_env panic!("relation should not need a param-env")
} }
fn a_is_expected(&self) -> bool { fn a_is_expected(&self) -> bool {
true true
} // irrelevant } // irrelevant

View file

@ -1226,11 +1226,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
if unbound_input_types if unbound_input_types
&& stack.iter().skip(1).any(|prev| { && stack.iter().skip(1).any(|prev| {
stack.obligation.param_env == prev.obligation.param_env stack.obligation.param_env == prev.obligation.param_env
&& self.match_fresh_trait_refs( && self.match_fresh_trait_refs(stack.fresh_trait_pred, prev.fresh_trait_pred)
stack.fresh_trait_pred,
prev.fresh_trait_pred,
prev.obligation.param_env,
)
}) })
{ {
debug!("evaluate_stack --> unbound argument, recursive --> giving up",); debug!("evaluate_stack --> unbound argument, recursive --> giving up",);
@ -2632,9 +2628,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
&self, &self,
previous: ty::PolyTraitPredicate<'tcx>, previous: ty::PolyTraitPredicate<'tcx>,
current: ty::PolyTraitPredicate<'tcx>, current: ty::PolyTraitPredicate<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> bool { ) -> bool {
let mut matcher = MatchAgainstFreshVars::new(self.tcx(), param_env); let mut matcher = MatchAgainstFreshVars::new(self.tcx());
matcher.relate(previous, current).is_ok() matcher.relate(previous, current).is_ok()
} }