Skip to content

Commit c5ed318

Browse files
committed
implement (unused) matching solver
1 parent d203c13 commit c5ed318

File tree

7 files changed

+329
-24
lines changed

7 files changed

+329
-24
lines changed

compiler/rustc_borrowck/src/nll.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
299299

300300
// Solve the region constraints.
301301
let (closure_region_requirements, nll_errors) =
302-
regioncx.solve(infcx, &body, polonius_output.clone());
302+
regioncx.solve(infcx, param_env, &body, polonius_output.clone());
303303

304304
if !nll_errors.is_empty() {
305305
// Suppress unhelpful extra errors in `infer_opaque_types`.

compiler/rustc_borrowck/src/region_infer/mod.rs

Lines changed: 80 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,16 @@ use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
1010
use rustc_hir::CRATE_HIR_ID;
1111
use rustc_index::vec::IndexVec;
1212
use rustc_infer::infer::canonical::QueryOutlivesConstraint;
13-
use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound};
13+
use rustc_infer::infer::outlives::test_type_match;
14+
use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound, VerifyIfEq};
1415
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin};
1516
use rustc_middle::mir::{
1617
Body, ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureRegionRequirements,
1718
ConstraintCategory, Local, Location, ReturnConstraint,
1819
};
1920
use rustc_middle::traits::ObligationCause;
2021
use rustc_middle::traits::ObligationCauseCode;
22+
use rustc_middle::ty::Region;
2123
use rustc_middle::ty::{self, subst::SubstsRef, RegionVid, Ty, TyCtxt, TypeFoldable};
2224
use rustc_span::Span;
2325

@@ -46,6 +48,7 @@ pub mod values;
4648

4749
pub struct RegionInferenceContext<'tcx> {
4850
pub var_infos: VarInfos,
51+
4952
/// Contains the definition for every region variable. Region
5053
/// variables are identified by their index (`RegionVid`). The
5154
/// definition contains information about where the region came
@@ -559,6 +562,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
559562
pub(super) fn solve(
560563
&mut self,
561564
infcx: &InferCtxt<'_, 'tcx>,
565+
param_env: ty::ParamEnv<'tcx>,
562566
body: &Body<'tcx>,
563567
polonius_output: Option<Rc<PoloniusOutput>>,
564568
) -> (Option<ClosureRegionRequirements<'tcx>>, RegionErrors<'tcx>) {
@@ -574,7 +578,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
574578
// eagerly.
575579
let mut outlives_requirements = infcx.tcx.is_typeck_child(mir_def_id).then(Vec::new);
576580

577-
self.check_type_tests(infcx, body, outlives_requirements.as_mut(), &mut errors_buffer);
581+
self.check_type_tests(
582+
infcx,
583+
param_env,
584+
body,
585+
outlives_requirements.as_mut(),
586+
&mut errors_buffer,
587+
);
578588

579589
// In Polonius mode, the errors about missing universal region relations are in the output
580590
// and need to be emitted or propagated. Otherwise, we need to check whether the
@@ -823,6 +833,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
823833
fn check_type_tests(
824834
&self,
825835
infcx: &InferCtxt<'_, 'tcx>,
836+
param_env: ty::ParamEnv<'tcx>,
826837
body: &Body<'tcx>,
827838
mut propagated_outlives_requirements: Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>,
828839
errors_buffer: &mut RegionErrors<'tcx>,
@@ -839,7 +850,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
839850

840851
let generic_ty = type_test.generic_kind.to_ty(tcx);
841852
if self.eval_verify_bound(
842-
tcx,
853+
infcx,
854+
param_env,
843855
body,
844856
generic_ty,
845857
type_test.lower_bound,
@@ -851,6 +863,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
851863
if let Some(propagated_outlives_requirements) = &mut propagated_outlives_requirements {
852864
if self.try_promote_type_test(
853865
infcx,
866+
param_env,
854867
body,
855868
type_test,
856869
propagated_outlives_requirements,
@@ -907,6 +920,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
907920
fn try_promote_type_test(
908921
&self,
909922
infcx: &InferCtxt<'_, 'tcx>,
923+
param_env: ty::ParamEnv<'tcx>,
910924
body: &Body<'tcx>,
911925
type_test: &TypeTest<'tcx>,
912926
propagated_outlives_requirements: &mut Vec<ClosureOutlivesRequirement<'tcx>>,
@@ -938,7 +952,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
938952
// where `ur` is a local bound -- we are sometimes in a
939953
// position to prove things that our caller cannot. See
940954
// #53570 for an example.
941-
if self.eval_verify_bound(tcx, body, generic_ty, ur, &type_test.verify_bound) {
955+
if self.eval_verify_bound(
956+
infcx,
957+
param_env,
958+
body,
959+
generic_ty,
960+
ur,
961+
&type_test.verify_bound,
962+
) {
942963
continue;
943964
}
944965

@@ -1161,7 +1182,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
11611182
/// `point`.
11621183
fn eval_verify_bound(
11631184
&self,
1164-
tcx: TyCtxt<'tcx>,
1185+
infcx: &InferCtxt<'_, 'tcx>,
1186+
param_env: ty::ParamEnv<'tcx>,
11651187
body: &Body<'tcx>,
11661188
generic_ty: Ty<'tcx>,
11671189
lower_bound: RegionVid,
@@ -1170,14 +1192,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
11701192
debug!("eval_verify_bound(lower_bound={:?}, verify_bound={:?})", lower_bound, verify_bound);
11711193

11721194
match verify_bound {
1173-
VerifyBound::IfEq(test_ty, verify_bound1) => self.eval_if_eq(
1174-
tcx,
1175-
body,
1176-
generic_ty,
1177-
lower_bound,
1178-
*test_ty,
1179-
&VerifyBound::OutlivedBy(*verify_bound1),
1180-
),
1195+
VerifyBound::IfEq(test_ty, verify_bound1) => {
1196+
self.eval_if_eq(infcx, generic_ty, lower_bound, *test_ty, *verify_bound1)
1197+
}
1198+
1199+
VerifyBound::IfEqBound(verify_if_eq_b) => {
1200+
self.eval_if_eq_bound(infcx, param_env, generic_ty, lower_bound, *verify_if_eq_b)
1201+
}
11811202

11821203
VerifyBound::IsEmpty => {
11831204
let lower_bound_scc = self.constraint_sccs.scc(lower_bound);
@@ -1190,33 +1211,71 @@ impl<'tcx> RegionInferenceContext<'tcx> {
11901211
}
11911212

11921213
VerifyBound::AnyBound(verify_bounds) => verify_bounds.iter().any(|verify_bound| {
1193-
self.eval_verify_bound(tcx, body, generic_ty, lower_bound, verify_bound)
1214+
self.eval_verify_bound(
1215+
infcx,
1216+
param_env,
1217+
body,
1218+
generic_ty,
1219+
lower_bound,
1220+
verify_bound,
1221+
)
11941222
}),
11951223

11961224
VerifyBound::AllBounds(verify_bounds) => verify_bounds.iter().all(|verify_bound| {
1197-
self.eval_verify_bound(tcx, body, generic_ty, lower_bound, verify_bound)
1225+
self.eval_verify_bound(
1226+
infcx,
1227+
param_env,
1228+
body,
1229+
generic_ty,
1230+
lower_bound,
1231+
verify_bound,
1232+
)
11981233
}),
11991234
}
12001235
}
12011236

12021237
fn eval_if_eq(
12031238
&self,
1204-
tcx: TyCtxt<'tcx>,
1205-
body: &Body<'tcx>,
1239+
infcx: &InferCtxt<'_, 'tcx>,
12061240
generic_ty: Ty<'tcx>,
12071241
lower_bound: RegionVid,
12081242
test_ty: Ty<'tcx>,
1209-
verify_bound: &VerifyBound<'tcx>,
1243+
verify_bound: Region<'tcx>,
12101244
) -> bool {
1211-
let generic_ty_normalized = self.normalize_to_scc_representatives(tcx, generic_ty);
1212-
let test_ty_normalized = self.normalize_to_scc_representatives(tcx, test_ty);
1245+
let generic_ty_normalized = self.normalize_to_scc_representatives(infcx.tcx, generic_ty);
1246+
let test_ty_normalized = self.normalize_to_scc_representatives(infcx.tcx, test_ty);
12131247
if generic_ty_normalized == test_ty_normalized {
1214-
self.eval_verify_bound(tcx, body, generic_ty, lower_bound, verify_bound)
1248+
let verify_bound_vid = self.to_region_vid(verify_bound);
1249+
self.eval_outlives(verify_bound_vid, lower_bound)
12151250
} else {
12161251
false
12171252
}
12181253
}
12191254

1255+
fn eval_if_eq_bound(
1256+
&self,
1257+
infcx: &InferCtxt<'_, 'tcx>,
1258+
param_env: ty::ParamEnv<'tcx>,
1259+
generic_ty: Ty<'tcx>,
1260+
lower_bound: RegionVid,
1261+
verify_if_eq_b: ty::Binder<'tcx, VerifyIfEq<'tcx>>,
1262+
) -> bool {
1263+
let generic_ty = self.normalize_to_scc_representatives(infcx.tcx, generic_ty);
1264+
let verify_if_eq_b = self.normalize_to_scc_representatives(infcx.tcx, verify_if_eq_b);
1265+
match test_type_match::extract_verify_if_eq_bound(
1266+
infcx.tcx,
1267+
param_env,
1268+
&verify_if_eq_b,
1269+
generic_ty,
1270+
) {
1271+
Some(r) => {
1272+
let r_vid = self.to_region_vid(r);
1273+
self.eval_outlives(r_vid, lower_bound)
1274+
}
1275+
None => false,
1276+
}
1277+
}
1278+
12201279
/// This is a conservative normalization procedure. It takes every
12211280
/// free region in `value` and replaces it with the
12221281
/// "representative" of its SCC (see `scc_representatives` field).

compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,22 @@ use rustc_middle::ty::{Region, RegionVid};
2222
use rustc_span::Span;
2323
use std::fmt;
2424

25+
use super::outlives::test_type_match;
26+
2527
/// This function performs lexical region resolution given a complete
2628
/// set of constraints and variable origins. It performs a fixed-point
2729
/// iteration to find region values which satisfy all constraints,
2830
/// assuming such values can be found. It returns the final values of
2931
/// all the variables as well as a set of errors that must be reported.
3032
#[instrument(level = "debug", skip(region_rels, var_infos, data))]
3133
pub(crate) fn resolve<'tcx>(
34+
param_env: ty::ParamEnv<'tcx>,
3235
region_rels: &RegionRelations<'_, 'tcx>,
3336
var_infos: VarInfos,
3437
data: RegionConstraintData<'tcx>,
3538
) -> (LexicalRegionResolutions<'tcx>, Vec<RegionResolutionError<'tcx>>) {
3639
let mut errors = vec![];
37-
let mut resolver = LexicalResolver { region_rels, var_infos, data };
40+
let mut resolver = LexicalResolver { param_env, region_rels, var_infos, data };
3841
let values = resolver.infer_variable_values(&mut errors);
3942
(values, errors)
4043
}
@@ -100,6 +103,7 @@ struct RegionAndOrigin<'tcx> {
100103
type RegionGraph<'tcx> = Graph<(), Constraint<'tcx>>;
101104

102105
struct LexicalResolver<'cx, 'tcx> {
106+
param_env: ty::ParamEnv<'tcx>,
103107
region_rels: &'cx RegionRelations<'cx, 'tcx>,
104108
var_infos: VarInfos,
105109
data: RegionConstraintData<'tcx>,
@@ -823,6 +827,21 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
823827
&& self.bound_is_met(&VerifyBound::OutlivedBy(*r), var_values, generic_ty, min)
824828
}
825829

830+
VerifyBound::IfEqBound(verify_if_eq_b) => {
831+
match test_type_match::extract_verify_if_eq_bound(
832+
self.tcx(),
833+
self.param_env,
834+
verify_if_eq_b,
835+
generic_ty,
836+
) {
837+
Some(r) => {
838+
self.bound_is_met(&VerifyBound::OutlivedBy(r), var_values, generic_ty, min)
839+
}
840+
841+
None => false,
842+
}
843+
}
844+
826845
VerifyBound::OutlivedBy(r) => {
827846
self.sub_concrete_regions(min, var_values.normalize(self.tcx(), *r))
828847
}

compiler/rustc_infer/src/infer/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1290,7 +1290,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
12901290
&RegionRelations::new(self.tcx, region_context, outlives_env.free_region_map());
12911291

12921292
let (lexical_region_resolutions, errors) =
1293-
lexical_region_resolve::resolve(region_rels, var_infos, data);
1293+
lexical_region_resolve::resolve(outlives_env.param_env, region_rels, var_infos, data);
12941294

12951295
let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions));
12961296
assert!(old_value.is_none());

compiler/rustc_infer/src/infer/outlives/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
pub mod components;
44
pub mod env;
55
pub mod obligations;
6+
pub mod test_type_match;
67
pub mod verify;
78

89
use rustc_middle::traits::query::OutlivesBound;

0 commit comments

Comments
 (0)