rename to "member constraints"
This commit is contained in:
parent
e39f66a859
commit
eca55b58d6
@ -23,7 +23,7 @@
|
||||
|
||||
use crate::infer::{InferCtxt, RegionVariableOrigin, TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use crate::infer::{ConstVariableOrigin, ConstVariableOriginKind};
|
||||
use crate::infer::region_constraints::PickConstraint;
|
||||
use crate::infer::region_constraints::MemberConstraint;
|
||||
use crate::mir::interpret::ConstValue;
|
||||
use rustc_data_structures::indexed_vec::IndexVec;
|
||||
use rustc_macros::HashStable;
|
||||
@ -198,14 +198,14 @@ pub struct QueryResponse<'tcx, R> {
|
||||
#[derive(Clone, Debug, Default, HashStable)]
|
||||
pub struct QueryRegionConstraints<'tcx> {
|
||||
pub outlives: Vec<QueryOutlivesConstraint<'tcx>>,
|
||||
pub pick_constraints: Vec<PickConstraint<'tcx>>,
|
||||
pub member_constraints: Vec<MemberConstraint<'tcx>>,
|
||||
}
|
||||
|
||||
impl QueryRegionConstraints<'_> {
|
||||
/// Represents an empty (trivially true) set of region
|
||||
/// constraints.
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.outlives.is_empty() && self.pick_constraints.is_empty()
|
||||
self.outlives.is_empty() && self.member_constraints.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
@ -558,14 +558,14 @@ BraceStructLiftImpl! {
|
||||
|
||||
BraceStructTypeFoldableImpl! {
|
||||
impl<'tcx> TypeFoldable<'tcx> for QueryRegionConstraints<'tcx> {
|
||||
outlives, pick_constraints
|
||||
outlives, member_constraints
|
||||
}
|
||||
}
|
||||
|
||||
BraceStructLiftImpl! {
|
||||
impl<'a, 'tcx> Lift<'tcx> for QueryRegionConstraints<'a> {
|
||||
type Lifted = QueryRegionConstraints<'tcx>;
|
||||
outlives, pick_constraints
|
||||
outlives, member_constraints
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -351,9 +351,9 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
|
||||
})
|
||||
);
|
||||
|
||||
// ...also include the query pick constraints.
|
||||
output_query_region_constraints.pick_constraints.extend(
|
||||
query_response.value.region_constraints.pick_constraints.iter().map(|p_c| {
|
||||
// ...also include the query member constraints.
|
||||
output_query_region_constraints.member_constraints.extend(
|
||||
query_response.value.region_constraints.member_constraints.iter().map(|p_c| {
|
||||
substitute_value(self.tcx, &result_subst, p_c)
|
||||
})
|
||||
);
|
||||
@ -663,7 +663,7 @@ pub fn make_query_region_constraints<'tcx>(
|
||||
constraints,
|
||||
verifys,
|
||||
givens,
|
||||
pick_constraints,
|
||||
member_constraints,
|
||||
} = region_constraints;
|
||||
|
||||
assert!(verifys.is_empty());
|
||||
@ -694,5 +694,5 @@ pub fn make_query_region_constraints<'tcx>(
|
||||
)
|
||||
.collect();
|
||||
|
||||
QueryRegionConstraints { outlives, pick_constraints: pick_constraints.clone() }
|
||||
QueryRegionConstraints { outlives, member_constraints: member_constraints.clone() }
|
||||
}
|
||||
|
@ -377,12 +377,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
RegionResolutionError::PickConstraintFailure {
|
||||
RegionResolutionError::MemberConstraintFailure {
|
||||
opaque_type_def_id,
|
||||
hidden_ty,
|
||||
pick_region,
|
||||
member_region,
|
||||
span: _,
|
||||
option_regions: _,
|
||||
choice_regions: _,
|
||||
} => {
|
||||
let hidden_ty = self.resolve_vars_if_possible(&hidden_ty);
|
||||
opaque_types::unexpected_hidden_region_diagnostic(
|
||||
@ -390,7 +390,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
Some(region_scope_tree),
|
||||
opaque_type_def_id,
|
||||
hidden_ty,
|
||||
pick_region,
|
||||
member_region,
|
||||
).emit();
|
||||
}
|
||||
}
|
||||
@ -430,7 +430,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
RegionResolutionError::GenericBoundFailure(..) => true,
|
||||
RegionResolutionError::ConcreteFailure(..)
|
||||
| RegionResolutionError::SubSupConflict(..)
|
||||
| RegionResolutionError::PickConstraintFailure { .. } => false,
|
||||
| RegionResolutionError::MemberConstraintFailure { .. } => false,
|
||||
};
|
||||
|
||||
let mut errors = if errors.iter().all(|e| is_bound_failure(e)) {
|
||||
@ -448,7 +448,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
RegionResolutionError::ConcreteFailure(ref sro, _, _) => sro.span(),
|
||||
RegionResolutionError::GenericBoundFailure(ref sro, _, _) => sro.span(),
|
||||
RegionResolutionError::SubSupConflict(_, ref rvo, _, _, _, _) => rvo.span(),
|
||||
RegionResolutionError::PickConstraintFailure { span, .. } => span,
|
||||
RegionResolutionError::MemberConstraintFailure { span, .. } => span,
|
||||
});
|
||||
errors
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
use crate::hir::def_id::DefId;
|
||||
use crate::infer::region_constraints::Constraint;
|
||||
use crate::infer::region_constraints::GenericKind;
|
||||
use crate::infer::region_constraints::PickConstraint;
|
||||
use crate::infer::region_constraints::MemberConstraint;
|
||||
use crate::infer::region_constraints::RegionConstraintData;
|
||||
use crate::infer::region_constraints::VarInfos;
|
||||
use crate::infer::region_constraints::VerifyBound;
|
||||
@ -84,15 +84,15 @@ pub enum RegionResolutionError<'tcx> {
|
||||
Region<'tcx>,
|
||||
),
|
||||
|
||||
/// Indicates a failure of a `PickConstraint`. These arise during
|
||||
/// Indicates a failure of a `MemberConstraint`. These arise during
|
||||
/// impl trait processing explicitly -- basically, the impl trait's hidden type
|
||||
/// included some region that it was not supposed to.
|
||||
PickConstraintFailure {
|
||||
MemberConstraintFailure {
|
||||
span: Span,
|
||||
opaque_type_def_id: DefId,
|
||||
hidden_ty: Ty<'tcx>,
|
||||
pick_region: Region<'tcx>,
|
||||
option_regions: Vec<Region<'tcx>>,
|
||||
member_region: Region<'tcx>,
|
||||
choice_regions: Vec<Region<'tcx>>,
|
||||
},
|
||||
}
|
||||
|
||||
@ -133,7 +133,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
|
||||
self.expand_givens(&graph);
|
||||
loop {
|
||||
self.expansion(&mut var_data);
|
||||
if !self.enforce_pick_constraints(&graph, &mut var_data) {
|
||||
if !self.enforce_member_constraints(&graph, &mut var_data) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -197,16 +197,16 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Enforce all pick constraints and return true if anything
|
||||
/// changed. See `enforce_pick_constraint` for more details.
|
||||
fn enforce_pick_constraints(
|
||||
/// Enforce all member constraints and return true if anything
|
||||
/// changed. See `enforce_member_constraint` for more details.
|
||||
fn enforce_member_constraints(
|
||||
&self,
|
||||
graph: &RegionGraph<'tcx>,
|
||||
var_values: &mut LexicalRegionResolutions<'tcx>,
|
||||
) -> bool {
|
||||
let mut any_changed = false;
|
||||
for pick_constraint in &self.data.pick_constraints {
|
||||
if self.enforce_pick_constraint(graph, pick_constraint, var_values) {
|
||||
for member_constraint in &self.data.member_constraints {
|
||||
if self.enforce_member_constraint(graph, member_constraint, var_values) {
|
||||
any_changed = true;
|
||||
}
|
||||
}
|
||||
@ -230,39 +230,44 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
|
||||
///
|
||||
/// From that list, we look for a *minimal* option `'o_min`. If we
|
||||
/// find one, then we can enforce that `'r: 'o_min`.
|
||||
fn enforce_pick_constraint(
|
||||
fn enforce_member_constraint(
|
||||
&self,
|
||||
graph: &RegionGraph<'tcx>,
|
||||
pick_constraint: &PickConstraint<'tcx>,
|
||||
member_constraint: &MemberConstraint<'tcx>,
|
||||
var_values: &mut LexicalRegionResolutions<'tcx>,
|
||||
) -> bool {
|
||||
debug!("enforce_pick_constraint(pick_constraint={:#?})", pick_constraint);
|
||||
debug!("enforce_member_constraint(member_constraint={:#?})", member_constraint);
|
||||
|
||||
// the constraint is some inference variable (`vid`) which
|
||||
// must be equal to one of the options
|
||||
let pick_vid = match pick_constraint.pick_region {
|
||||
let member_vid = match member_constraint.member_region {
|
||||
ty::ReVar(vid) => *vid,
|
||||
_ => return false,
|
||||
};
|
||||
|
||||
// The current value of `vid` is a lower bound LB -- i.e., we
|
||||
// know that `LB <= vid` must be true.
|
||||
let pick_lower_bound: ty::Region<'tcx> = match var_values.value(pick_vid) {
|
||||
let member_lower_bound: ty::Region<'tcx> = match var_values.value(member_vid) {
|
||||
VarValue::ErrorValue => return false,
|
||||
VarValue::Value(r) => r,
|
||||
};
|
||||
|
||||
// find all the "upper bounds" -- that is, each region `b` such that
|
||||
// `r0 <= b` must hold.
|
||||
let (pick_upper_bounds, _) = self.collect_concrete_regions(graph, pick_vid, OUTGOING, None);
|
||||
let (member_upper_bounds, _) = self.collect_concrete_regions(
|
||||
graph,
|
||||
member_vid,
|
||||
OUTGOING,
|
||||
None,
|
||||
);
|
||||
|
||||
// get an iterator over the *available options* -- that is,
|
||||
// each constraint regions `o` where `lb <= o` and `o <= ub` for all the
|
||||
// get an iterator over the *available choice* -- that is,
|
||||
// each choice region `c` where `lb <= c` and `c <= ub` for all the
|
||||
// upper bounds `ub`.
|
||||
debug!("enforce_pick_constraint: upper_bounds={:#?}", pick_upper_bounds);
|
||||
let mut options = pick_constraint.option_regions.iter().filter(|option| {
|
||||
self.sub_concrete_regions(pick_lower_bound, option)
|
||||
&& pick_upper_bounds
|
||||
debug!("enforce_member_constraint: upper_bounds={:#?}", member_upper_bounds);
|
||||
let mut options = member_constraint.choice_regions.iter().filter(|option| {
|
||||
self.sub_concrete_regions(member_lower_bound, option)
|
||||
&& member_upper_bounds
|
||||
.iter()
|
||||
.all(|upper_bound| self.sub_concrete_regions(option, upper_bound.region))
|
||||
});
|
||||
@ -274,23 +279,23 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
|
||||
Some(&r) => r,
|
||||
None => return false,
|
||||
};
|
||||
debug!("enforce_pick_constraint: least_choice={:?}", least_choice);
|
||||
debug!("enforce_member_constraint: least_choice={:?}", least_choice);
|
||||
for &option in options {
|
||||
debug!("enforce_pick_constraint: option={:?}", option);
|
||||
debug!("enforce_member_constraint: option={:?}", option);
|
||||
if !self.sub_concrete_regions(least_choice, option) {
|
||||
if self.sub_concrete_regions(option, least_choice) {
|
||||
debug!("enforce_pick_constraint: new least choice");
|
||||
debug!("enforce_member_constraint: new least choice");
|
||||
least_choice = option;
|
||||
} else {
|
||||
debug!("enforce_pick_constraint: no least choice");
|
||||
debug!("enforce_member_constraint: no least choice");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
debug!("enforce_pick_constraint: final least choice = {:?}", least_choice);
|
||||
if least_choice != pick_lower_bound {
|
||||
*var_values.value_mut(pick_vid) = VarValue::Value(least_choice);
|
||||
debug!("enforce_member_constraint: final least choice = {:?}", least_choice);
|
||||
if least_choice != member_lower_bound {
|
||||
*var_values.value_mut(member_vid) = VarValue::Value(least_choice);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
@ -547,20 +552,20 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
for pick_constraint in &self.data.pick_constraints {
|
||||
let pick_region = var_data.normalize(self.tcx(), pick_constraint.pick_region);
|
||||
let option_regions = pick_constraint
|
||||
.option_regions
|
||||
for member_constraint in &self.data.member_constraints {
|
||||
let member_region = var_data.normalize(self.tcx(), member_constraint.member_region);
|
||||
let choice_regions = member_constraint
|
||||
.choice_regions
|
||||
.iter()
|
||||
.map(|&option_region| var_data.normalize(self.tcx(), option_region));
|
||||
if !option_regions.clone().any(|option_region| pick_region == option_region) {
|
||||
let span = self.tcx().def_span(pick_constraint.opaque_type_def_id);
|
||||
errors.push(RegionResolutionError::PickConstraintFailure {
|
||||
.map(|&choice_region| var_data.normalize(self.tcx(), choice_region));
|
||||
if !choice_regions.clone().any(|choice_region| member_region == choice_region) {
|
||||
let span = self.tcx().def_span(member_constraint.opaque_type_def_id);
|
||||
errors.push(RegionResolutionError::MemberConstraintFailure {
|
||||
span,
|
||||
opaque_type_def_id: pick_constraint.opaque_type_def_id,
|
||||
hidden_ty: pick_constraint.hidden_ty,
|
||||
pick_region,
|
||||
option_regions: option_regions.collect(),
|
||||
opaque_type_def_id: member_constraint.opaque_type_def_id,
|
||||
hidden_ty: member_constraint.hidden_ty,
|
||||
member_region,
|
||||
choice_regions: choice_regions.collect(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -907,7 +907,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
|
||||
/// Require that the region `r` be equal to one of the regions in
|
||||
/// the set `regions`.
|
||||
pub fn pick_constraint(
|
||||
pub fn member_constraint(
|
||||
&self,
|
||||
opaque_type_def_id: DefId,
|
||||
definition_span: Span,
|
||||
@ -915,9 +915,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
region: ty::Region<'tcx>,
|
||||
in_regions: &Lrc<Vec<ty::Region<'tcx>>>,
|
||||
) {
|
||||
debug!("pick_constraint({:?} <: {:?})", region, in_regions);
|
||||
debug!("member_constraint({:?} <: {:?})", region, in_regions);
|
||||
self.borrow_region_constraints()
|
||||
.pick_constraint(opaque_type_def_id, definition_span, hidden_ty, region, in_regions);
|
||||
.member_constraint(opaque_type_def_id, definition_span, hidden_ty, region, in_regions);
|
||||
}
|
||||
|
||||
pub fn subtype_predicate(
|
||||
|
@ -393,7 +393,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
// we will create a "in bound" like `'r in
|
||||
// ['a, 'b, 'c]`, where `'a..'c` are the
|
||||
// regions that appear in the impl trait.
|
||||
return self.generate_pick_constraint(
|
||||
return self.generate_member_constraint(
|
||||
concrete_ty,
|
||||
abstract_type_generics,
|
||||
opaque_defn,
|
||||
@ -418,17 +418,17 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
/// related, we would generate a constraint `'r in ['a, 'b,
|
||||
/// 'static]` for each region `'r` that appears in the hidden type
|
||||
/// (i.e., it must be equal to `'a`, `'b`, or `'static`).
|
||||
fn generate_pick_constraint(
|
||||
fn generate_member_constraint(
|
||||
&self,
|
||||
concrete_ty: Ty<'tcx>,
|
||||
abstract_type_generics: &ty::Generics,
|
||||
opaque_defn: &OpaqueTypeDecl<'tcx>,
|
||||
opaque_type_def_id: DefId,
|
||||
) {
|
||||
// Create the set of option regions: each region in the hidden
|
||||
// Create the set of choice regions: each region in the hidden
|
||||
// type can be equal to any of the region parameters of the
|
||||
// opaque type definition.
|
||||
let option_regions: Lrc<Vec<ty::Region<'tcx>>> = Lrc::new(
|
||||
let choice_regions: Lrc<Vec<ty::Region<'tcx>>> = Lrc::new(
|
||||
abstract_type_generics
|
||||
.params
|
||||
.iter()
|
||||
@ -443,12 +443,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
|
||||
concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
|
||||
tcx: self.tcx,
|
||||
op: |r| self.pick_constraint(
|
||||
op: |r| self.member_constraint(
|
||||
opaque_type_def_id,
|
||||
opaque_defn.definition_span,
|
||||
concrete_ty,
|
||||
r,
|
||||
&option_regions,
|
||||
&choice_regions,
|
||||
),
|
||||
});
|
||||
}
|
||||
|
@ -81,10 +81,10 @@ pub struct RegionConstraintData<'tcx> {
|
||||
/// be a region variable (or neither, as it happens).
|
||||
pub constraints: BTreeMap<Constraint<'tcx>, SubregionOrigin<'tcx>>,
|
||||
|
||||
/// Constraints of the form `pick R0 from [R1, ..., Rn]`, meaning that
|
||||
/// Constraints of the form `R0 member of [R1, ..., Rn]`, meaning that
|
||||
/// `R0` must be equal to one of the regions `R1..Rn`. These occur
|
||||
/// with `impl Trait` quite frequently.
|
||||
pub pick_constraints: Vec<PickConstraint<'tcx>>,
|
||||
pub member_constraints: Vec<MemberConstraint<'tcx>>,
|
||||
|
||||
/// A "verify" is something that we need to verify after inference
|
||||
/// is done, but which does not directly affect inference in any
|
||||
@ -145,40 +145,40 @@ impl Constraint<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Requires that `region` must be equal to one of the regions in `option_regions`.
|
||||
/// Requires that `region` must be equal to one of the regions in `choice_regions`.
|
||||
/// We often denote this using the syntax:
|
||||
///
|
||||
/// ```
|
||||
/// pick R0 from [O1..On]
|
||||
/// R0 member of [O1..On]
|
||||
/// ```
|
||||
#[derive(Debug, Clone, HashStable)]
|
||||
pub struct PickConstraint<'tcx> {
|
||||
pub struct MemberConstraint<'tcx> {
|
||||
/// the def-id of the opaque type causing this constraint: used for error reporting
|
||||
pub opaque_type_def_id: DefId,
|
||||
|
||||
/// the span where the hidden type was instantiated
|
||||
pub definition_span: Span,
|
||||
|
||||
/// the hidden type in which `pick_region` appears: used for error reporting
|
||||
/// the hidden type in which `member_region` appears: used for error reporting
|
||||
pub hidden_ty: Ty<'tcx>,
|
||||
|
||||
/// the region R0
|
||||
pub pick_region: Region<'tcx>,
|
||||
pub member_region: Region<'tcx>,
|
||||
|
||||
/// the options O1..On
|
||||
pub option_regions: Lrc<Vec<Region<'tcx>>>,
|
||||
pub choice_regions: Lrc<Vec<Region<'tcx>>>,
|
||||
}
|
||||
|
||||
BraceStructTypeFoldableImpl! {
|
||||
impl<'tcx> TypeFoldable<'tcx> for PickConstraint<'tcx> {
|
||||
opaque_type_def_id, definition_span, hidden_ty, pick_region, option_regions
|
||||
impl<'tcx> TypeFoldable<'tcx> for MemberConstraint<'tcx> {
|
||||
opaque_type_def_id, definition_span, hidden_ty, member_region, choice_regions
|
||||
}
|
||||
}
|
||||
|
||||
BraceStructLiftImpl! {
|
||||
impl<'a, 'tcx> Lift<'tcx> for PickConstraint<'a> {
|
||||
type Lifted = PickConstraint<'tcx>;
|
||||
opaque_type_def_id, definition_span, hidden_ty, pick_region, option_regions
|
||||
impl<'a, 'tcx> Lift<'tcx> for MemberConstraint<'a> {
|
||||
type Lifted = MemberConstraint<'tcx>;
|
||||
opaque_type_def_id, definition_span, hidden_ty, member_region, choice_regions
|
||||
}
|
||||
}
|
||||
|
||||
@ -688,26 +688,26 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pick_constraint(
|
||||
pub fn member_constraint(
|
||||
&mut self,
|
||||
opaque_type_def_id: DefId,
|
||||
definition_span: Span,
|
||||
hidden_ty: Ty<'tcx>,
|
||||
pick_region: ty::Region<'tcx>,
|
||||
option_regions: &Lrc<Vec<ty::Region<'tcx>>>,
|
||||
member_region: ty::Region<'tcx>,
|
||||
choice_regions: &Lrc<Vec<ty::Region<'tcx>>>,
|
||||
) {
|
||||
debug!("pick_constraint({:?} in {:#?})", pick_region, option_regions);
|
||||
debug!("member_constraint({:?} in {:#?})", member_region, choice_regions);
|
||||
|
||||
if option_regions.iter().any(|&r| r == pick_region) {
|
||||
if choice_regions.iter().any(|&r| r == member_region) {
|
||||
return;
|
||||
}
|
||||
|
||||
self.data.pick_constraints.push(PickConstraint {
|
||||
self.data.member_constraints.push(MemberConstraint {
|
||||
opaque_type_def_id,
|
||||
definition_span,
|
||||
hidden_ty,
|
||||
pick_region,
|
||||
option_regions: option_regions.clone()
|
||||
member_region,
|
||||
choice_regions: choice_regions.clone()
|
||||
});
|
||||
|
||||
}
|
||||
@ -975,12 +975,12 @@ impl<'tcx> RegionConstraintData<'tcx> {
|
||||
pub fn is_empty(&self) -> bool {
|
||||
let RegionConstraintData {
|
||||
constraints,
|
||||
pick_constraints,
|
||||
member_constraints,
|
||||
verifys,
|
||||
givens,
|
||||
} = self;
|
||||
constraints.is_empty() &&
|
||||
pick_constraints.is_empty() &&
|
||||
member_constraints.is_empty() &&
|
||||
verifys.is_empty() &&
|
||||
givens.is_empty()
|
||||
}
|
||||
|
@ -349,7 +349,7 @@ impl<'tcx, A: Lift<'tcx>, B: Lift<'tcx>, C: Lift<'tcx>> Lift<'tcx> for (A, B, C)
|
||||
tcx.lift(&self.0).and_then(|a| {
|
||||
tcx.lift(&self.1).and_then(|b| tcx.lift(&self.2).map(|c| (a, b, c)))
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for Option<T> {
|
||||
|
@ -37,7 +37,7 @@ crate mod type_check;
|
||||
mod universal_regions;
|
||||
|
||||
mod constraints;
|
||||
mod pick_constraints;
|
||||
mod member_constraints;
|
||||
|
||||
use self::facts::AllFacts;
|
||||
use self::region_infer::RegionInferenceContext;
|
||||
@ -130,7 +130,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>(
|
||||
placeholder_index_to_region: _,
|
||||
mut liveness_constraints,
|
||||
outlives_constraints,
|
||||
pick_constraints,
|
||||
member_constraints,
|
||||
closure_bounds_mapping,
|
||||
type_tests,
|
||||
} = constraints;
|
||||
@ -152,7 +152,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>(
|
||||
universal_region_relations,
|
||||
body,
|
||||
outlives_constraints,
|
||||
pick_constraints,
|
||||
member_constraints,
|
||||
closure_bounds_mapping,
|
||||
type_tests,
|
||||
liveness_constraints,
|
||||
|
@ -1,36 +1,36 @@
|
||||
use crate::rustc::ty::{self, Ty};
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::infer::region_constraints::PickConstraint;
|
||||
use rustc::infer::region_constraints::MemberConstraint;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
|
||||
use std::hash::Hash;
|
||||
use std::ops::Index;
|
||||
use syntax_pos::Span;
|
||||
|
||||
/// Compactly stores a set of `pick R0 in [R1...Rn]` constraints,
|
||||
/// Compactly stores a set of `R0 member of [R1...Rn]` constraints,
|
||||
/// indexed by the region R0.
|
||||
crate struct PickConstraintSet<'tcx, R>
|
||||
crate struct MemberConstraintSet<'tcx, R>
|
||||
where
|
||||
R: Copy + Hash + Eq,
|
||||
{
|
||||
/// Stores the first "pick" constraint for a given R0. This is an
|
||||
/// Stores the first "member" constraint for a given R0. This is an
|
||||
/// index into the `constraints` vector below.
|
||||
first_constraints: FxHashMap<R, NllPickConstraintIndex>,
|
||||
first_constraints: FxHashMap<R, NllMemberConstraintIndex>,
|
||||
|
||||
/// Stores the data about each `pick R0 from [R1..Rn]` constraint.
|
||||
/// Stores the data about each `R0 member of [R1..Rn]` constraint.
|
||||
/// These are organized into a linked list, so each constraint
|
||||
/// contains the index of the next constraint with the same R0.
|
||||
constraints: IndexVec<NllPickConstraintIndex, NllPickConstraint<'tcx>>,
|
||||
constraints: IndexVec<NllMemberConstraintIndex, NllMemberConstraint<'tcx>>,
|
||||
|
||||
/// Stores the `R1..Rn` regions for *all* sets. For any given
|
||||
/// constraint, we keep two indices so that we can pull out a
|
||||
/// slice.
|
||||
option_regions: Vec<ty::RegionVid>,
|
||||
choice_regions: Vec<ty::RegionVid>,
|
||||
}
|
||||
|
||||
/// Represents a `pick R0 in [R1..Rn]` constraint
|
||||
crate struct NllPickConstraint<'tcx> {
|
||||
next_constraint: Option<NllPickConstraintIndex>,
|
||||
/// Represents a `R0 member of [R1..Rn]` constraint
|
||||
crate struct NllMemberConstraint<'tcx> {
|
||||
next_constraint: Option<NllMemberConstraintIndex>,
|
||||
|
||||
/// The opaque type whose hidden type is being inferred. (Used in error reporting.)
|
||||
crate opaque_type_def_id: DefId,
|
||||
@ -42,67 +42,70 @@ crate struct NllPickConstraint<'tcx> {
|
||||
crate hidden_ty: Ty<'tcx>,
|
||||
|
||||
/// The region R0.
|
||||
crate pick_region_vid: ty::RegionVid,
|
||||
crate member_region_vid: ty::RegionVid,
|
||||
|
||||
/// Index of `R1` in `option_regions` vector from `PickConstraintSet`.
|
||||
/// Index of `R1` in `choice_regions` vector from `MemberConstraintSet`.
|
||||
start_index: usize,
|
||||
|
||||
/// Index of `Rn` in `option_regions` vector from `PickConstraintSet`.
|
||||
/// Index of `Rn` in `choice_regions` vector from `MemberConstraintSet`.
|
||||
end_index: usize,
|
||||
}
|
||||
|
||||
newtype_index! {
|
||||
crate struct NllPickConstraintIndex {
|
||||
DEBUG_FORMAT = "PickConstraintIndex({})"
|
||||
crate struct NllMemberConstraintIndex {
|
||||
DEBUG_FORMAT = "MemberConstraintIndex({})"
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for PickConstraintSet<'tcx, ty::RegionVid> {
|
||||
impl Default for MemberConstraintSet<'tcx, ty::RegionVid> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
first_constraints: Default::default(),
|
||||
constraints: Default::default(),
|
||||
option_regions: Default::default(),
|
||||
choice_regions: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> PickConstraintSet<'tcx, ty::RegionVid> {
|
||||
impl<'tcx> MemberConstraintSet<'tcx, ty::RegionVid> {
|
||||
crate fn push_constraint(
|
||||
&mut self,
|
||||
p_c: &PickConstraint<'tcx>,
|
||||
m_c: &MemberConstraint<'tcx>,
|
||||
mut to_region_vid: impl FnMut(ty::Region<'tcx>) -> ty::RegionVid,
|
||||
) {
|
||||
debug!("push_constraint(p_c={:?})", p_c);
|
||||
let pick_region_vid: ty::RegionVid = to_region_vid(p_c.pick_region);
|
||||
let next_constraint = self.first_constraints.get(&pick_region_vid).cloned();
|
||||
let start_index = self.option_regions.len();
|
||||
let end_index = start_index + p_c.option_regions.len();
|
||||
debug!("push_constraint: pick_region_vid={:?}", pick_region_vid);
|
||||
let constraint_index = self.constraints.push(NllPickConstraint {
|
||||
debug!("push_constraint(m_c={:?})", m_c);
|
||||
let member_region_vid: ty::RegionVid = to_region_vid(m_c.member_region);
|
||||
let next_constraint = self.first_constraints.get(&member_region_vid).cloned();
|
||||
let start_index = self.choice_regions.len();
|
||||
let end_index = start_index + m_c.choice_regions.len();
|
||||
debug!("push_constraint: member_region_vid={:?}", member_region_vid);
|
||||
let constraint_index = self.constraints.push(NllMemberConstraint {
|
||||
next_constraint,
|
||||
pick_region_vid,
|
||||
opaque_type_def_id: p_c.opaque_type_def_id,
|
||||
definition_span: p_c.definition_span,
|
||||
hidden_ty: p_c.hidden_ty,
|
||||
member_region_vid,
|
||||
opaque_type_def_id: m_c.opaque_type_def_id,
|
||||
definition_span: m_c.definition_span,
|
||||
hidden_ty: m_c.hidden_ty,
|
||||
start_index,
|
||||
end_index,
|
||||
});
|
||||
self.first_constraints.insert(pick_region_vid, constraint_index);
|
||||
self.option_regions.extend(p_c.option_regions.iter().map(|&r| to_region_vid(r)));
|
||||
self.first_constraints.insert(member_region_vid, constraint_index);
|
||||
self.choice_regions.extend(m_c.choice_regions.iter().map(|&r| to_region_vid(r)));
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, R1> PickConstraintSet<'tcx, R1>
|
||||
impl<'tcx, R1> MemberConstraintSet<'tcx, R1>
|
||||
where
|
||||
R1: Copy + Hash + Eq,
|
||||
{
|
||||
/// Remap the "pick region" key using `map_fn`, producing a new
|
||||
/// Remap the "member region" key using `map_fn`, producing a new
|
||||
/// pick-constraint set. This is used in the NLL code to map from
|
||||
/// the original `RegionVid` to an scc index. In some cases, we
|
||||
/// may have multiple R1 values mapping to the same R2 key -- that
|
||||
/// is ok, the two sets will be merged.
|
||||
crate fn into_mapped<R2>(self, mut map_fn: impl FnMut(R1) -> R2) -> PickConstraintSet<'tcx, R2>
|
||||
crate fn into_mapped<R2>(
|
||||
self,
|
||||
mut map_fn: impl FnMut(R1) -> R2,
|
||||
) -> MemberConstraintSet<'tcx, R2>
|
||||
where
|
||||
R2: Copy + Hash + Eq,
|
||||
{
|
||||
@ -116,7 +119,7 @@ where
|
||||
// link from one list to point at the othe other (see
|
||||
// `append_list`).
|
||||
|
||||
let PickConstraintSet { first_constraints, mut constraints, option_regions } = self;
|
||||
let MemberConstraintSet { first_constraints, mut constraints, choice_regions } = self;
|
||||
|
||||
let mut first_constraints2 = FxHashMap::default();
|
||||
first_constraints2.reserve(first_constraints.len());
|
||||
@ -129,33 +132,33 @@ where
|
||||
first_constraints2.insert(r2, start1);
|
||||
}
|
||||
|
||||
PickConstraintSet {
|
||||
MemberConstraintSet {
|
||||
first_constraints: first_constraints2,
|
||||
constraints,
|
||||
option_regions,
|
||||
choice_regions,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, R> PickConstraintSet<'tcx, R>
|
||||
impl<'tcx, R> MemberConstraintSet<'tcx, R>
|
||||
where
|
||||
R: Copy + Hash + Eq,
|
||||
{
|
||||
crate fn all_indices(
|
||||
&self,
|
||||
) -> impl Iterator<Item = NllPickConstraintIndex> {
|
||||
) -> impl Iterator<Item = NllMemberConstraintIndex> {
|
||||
self.constraints.indices()
|
||||
}
|
||||
|
||||
/// Iterate down the constraint indices associated with a given
|
||||
/// peek-region. You can then use `option_regions` and other
|
||||
/// peek-region. You can then use `choice_regions` and other
|
||||
/// methods to access data.
|
||||
crate fn indices(
|
||||
&self,
|
||||
pick_region_vid: R,
|
||||
) -> impl Iterator<Item = NllPickConstraintIndex> + '_ {
|
||||
let mut next = self.first_constraints.get(&pick_region_vid).cloned();
|
||||
std::iter::from_fn(move || -> Option<NllPickConstraintIndex> {
|
||||
member_region_vid: R,
|
||||
) -> impl Iterator<Item = NllMemberConstraintIndex> + '_ {
|
||||
let mut next = self.first_constraints.get(&member_region_vid).cloned();
|
||||
std::iter::from_fn(move || -> Option<NllMemberConstraintIndex> {
|
||||
if let Some(current) = next {
|
||||
next = self.constraints[current].next_constraint;
|
||||
Some(current)
|
||||
@ -165,25 +168,25 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the "option regions" for a given pick constraint. This is the R1..Rn from
|
||||
/// a constraint like:
|
||||
/// Returns the "choice regions" for a given member
|
||||
/// constraint. This is the R1..Rn from a constraint like:
|
||||
///
|
||||
/// ```
|
||||
/// pick R0 in [R1..Rn]
|
||||
/// R0 member of [R1..Rn]
|
||||
/// ```
|
||||
crate fn option_regions(&self, pci: NllPickConstraintIndex) -> &[ty::RegionVid] {
|
||||
let NllPickConstraint { start_index, end_index, .. } = &self.constraints[pci];
|
||||
&self.option_regions[*start_index..*end_index]
|
||||
crate fn choice_regions(&self, pci: NllMemberConstraintIndex) -> &[ty::RegionVid] {
|
||||
let NllMemberConstraint { start_index, end_index, .. } = &self.constraints[pci];
|
||||
&self.choice_regions[*start_index..*end_index]
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, R> Index<NllPickConstraintIndex> for PickConstraintSet<'tcx, R>
|
||||
impl<'tcx, R> Index<NllMemberConstraintIndex> for MemberConstraintSet<'tcx, R>
|
||||
where
|
||||
R: Copy + Hash + Eq,
|
||||
{
|
||||
type Output = NllPickConstraint<'tcx>;
|
||||
type Output = NllMemberConstraint<'tcx>;
|
||||
|
||||
fn index(&self, i: NllPickConstraintIndex) -> &NllPickConstraint<'tcx> {
|
||||
fn index(&self, i: NllMemberConstraintIndex) -> &NllMemberConstraint<'tcx> {
|
||||
&self.constraints[i]
|
||||
}
|
||||
}
|
||||
@ -205,9 +208,9 @@ where
|
||||
/// target_list: A -> B -> C -> D -> E -> F -> (None)
|
||||
/// ```
|
||||
fn append_list(
|
||||
constraints: &mut IndexVec<NllPickConstraintIndex, NllPickConstraint<'_>>,
|
||||
target_list: NllPickConstraintIndex,
|
||||
source_list: NllPickConstraintIndex,
|
||||
constraints: &mut IndexVec<NllMemberConstraintIndex, NllMemberConstraint<'_>>,
|
||||
target_list: NllMemberConstraintIndex,
|
||||
source_list: NllMemberConstraintIndex,
|
||||
) {
|
||||
let mut p = target_list;
|
||||
loop {
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::borrow_check::nll::constraints::OutlivesConstraint;
|
||||
use crate::borrow_check::nll::region_infer::AppliedPickConstraint;
|
||||
use crate::borrow_check::nll::region_infer::AppliedMemberConstraint;
|
||||
use crate::borrow_check::nll::region_infer::RegionInferenceContext;
|
||||
use crate::borrow_check::nll::type_check::Locations;
|
||||
use crate::borrow_check::nll::universal_regions::DefiningTy;
|
||||
@ -224,13 +224,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
// But pick-constraints can also give rise to `'r: 'x`
|
||||
// edges that were not part of the graph initially, so
|
||||
// watch out for those.
|
||||
let outgoing_edges_from_picks = self.applied_pick_constraints(r)
|
||||
let outgoing_edges_from_picks = self.applied_member_constraints(r)
|
||||
.iter()
|
||||
.map(|&AppliedPickConstraint { best_option, pick_constraint_index, .. }| {
|
||||
let p_c = &self.pick_constraints[pick_constraint_index];
|
||||
.map(|&AppliedMemberConstraint { min_choice, member_constraint_index, .. }| {
|
||||
let p_c = &self.member_constraints[member_constraint_index];
|
||||
OutlivesConstraint {
|
||||
sup: r,
|
||||
sub: best_option,
|
||||
sub: min_choice,
|
||||
locations: Locations::All(p_c.definition_span),
|
||||
category: ConstraintCategory::OpaqueType,
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ use crate::borrow_check::nll::constraints::graph::NormalConstraintGraph;
|
||||
use crate::borrow_check::nll::constraints::{
|
||||
ConstraintSccIndex, OutlivesConstraint, OutlivesConstraintSet,
|
||||
};
|
||||
use crate::borrow_check::nll::pick_constraints::{PickConstraintSet, NllPickConstraintIndex};
|
||||
use crate::borrow_check::nll::member_constraints::{MemberConstraintSet, NllMemberConstraintIndex};
|
||||
use crate::borrow_check::nll::region_infer::values::{
|
||||
PlaceholderIndices, RegionElement, ToElementIndex,
|
||||
};
|
||||
@ -72,14 +72,14 @@ pub struct RegionInferenceContext<'tcx> {
|
||||
/// exists if `B: A`. Computed lazilly.
|
||||
rev_constraint_graph: Option<Rc<VecGraph<ConstraintSccIndex>>>,
|
||||
|
||||
/// The "pick R0 from [R1..Rn]" constraints, indexed by SCC.
|
||||
pick_constraints: Rc<PickConstraintSet<'tcx, ConstraintSccIndex>>,
|
||||
/// The "R0 member of [R1..Rn]" constraints, indexed by SCC.
|
||||
member_constraints: Rc<MemberConstraintSet<'tcx, ConstraintSccIndex>>,
|
||||
|
||||
/// Records the pick-constraints that we applied to each scc.
|
||||
/// This is useful for error reporting. Once constraint
|
||||
/// propagation is done, this vector is sorted according to
|
||||
/// `pick_region_scc`.
|
||||
pick_constraints_applied: Vec<AppliedPickConstraint>,
|
||||
/// `member_region_scc`.
|
||||
member_constraints_applied: Vec<AppliedMemberConstraint>,
|
||||
|
||||
/// Map closure bounds to a `Span` that should be used for error reporting.
|
||||
closure_bounds_mapping:
|
||||
@ -116,30 +116,30 @@ pub struct RegionInferenceContext<'tcx> {
|
||||
universal_region_relations: Rc<UniversalRegionRelations<'tcx>>,
|
||||
}
|
||||
|
||||
/// Each time that `apply_pick_constraint` is successful, it appends
|
||||
/// one of these structs to the `pick_constraints_applied` field.
|
||||
/// Each time that `apply_member_constraint` is successful, it appends
|
||||
/// one of these structs to the `member_constraints_applied` field.
|
||||
/// This is used in error reporting to trace out what happened.
|
||||
///
|
||||
/// The way that `apply_pick_constraint` works is that it effectively
|
||||
/// The way that `apply_member_constraint` works is that it effectively
|
||||
/// adds a new lower bound to the SCC it is analyzing: so you wind up
|
||||
/// with `'R: 'O` where `'R` is the pick-region and `'O` is the
|
||||
/// minimal viable option.
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
||||
struct AppliedPickConstraint {
|
||||
/// The SCC that was affected. (The "pick region".)
|
||||
struct AppliedMemberConstraint {
|
||||
/// The SCC that was affected. (The "member region".)
|
||||
///
|
||||
/// The vector if `AppliedPickConstraint` elements is kept sorted
|
||||
/// The vector if `AppliedMemberConstraint` elements is kept sorted
|
||||
/// by this field.
|
||||
pick_region_scc: ConstraintSccIndex,
|
||||
member_region_scc: ConstraintSccIndex,
|
||||
|
||||
/// The "best option" that `apply_pick_constraint` found -- this was
|
||||
/// added as an "ad-hoc" lower-bound to `pick_region_scc`.
|
||||
best_option: ty::RegionVid,
|
||||
/// The "best option" that `apply_member_constraint` found -- this was
|
||||
/// added as an "ad-hoc" lower-bound to `member_region_scc`.
|
||||
min_choice: ty::RegionVid,
|
||||
|
||||
/// The "pick constraint index" -- we can find out details about
|
||||
/// The "member constraint index" -- we can find out details about
|
||||
/// the constraint from
|
||||
/// `set.pick_constraints[pick_constraint_index]`.
|
||||
pick_constraint_index: NllPickConstraintIndex,
|
||||
/// `set.member_constraints[member_constraint_index]`.
|
||||
member_constraint_index: NllMemberConstraintIndex,
|
||||
}
|
||||
|
||||
struct RegionDefinition<'tcx> {
|
||||
@ -234,7 +234,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
universal_region_relations: Rc<UniversalRegionRelations<'tcx>>,
|
||||
_body: &Body<'tcx>,
|
||||
outlives_constraints: OutlivesConstraintSet,
|
||||
pick_constraints_in: PickConstraintSet<'tcx, RegionVid>,
|
||||
member_constraints_in: MemberConstraintSet<'tcx, RegionVid>,
|
||||
closure_bounds_mapping: FxHashMap<
|
||||
Location,
|
||||
FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>,
|
||||
@ -266,7 +266,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
|
||||
let scc_representatives = Self::compute_scc_representatives(&constraint_sccs, &definitions);
|
||||
|
||||
let pick_constraints = Rc::new(pick_constraints_in.into_mapped(|r| constraint_sccs.scc(r)));
|
||||
let member_constraints =
|
||||
Rc::new(member_constraints_in.into_mapped(|r| constraint_sccs.scc(r)));
|
||||
|
||||
let mut result = Self {
|
||||
definitions,
|
||||
@ -275,8 +276,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
constraint_graph,
|
||||
constraint_sccs,
|
||||
rev_constraint_graph: None,
|
||||
pick_constraints,
|
||||
pick_constraints_applied: Vec::new(),
|
||||
member_constraints,
|
||||
member_constraints_applied: Vec::new(),
|
||||
closure_bounds_mapping,
|
||||
scc_universes,
|
||||
scc_representatives,
|
||||
@ -447,12 +448,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
|
||||
/// Once region solving has completed, this function will return
|
||||
/// the pick-constraints that were applied to the value of a given
|
||||
/// region `r`. See `AppliedPickConstraint`.
|
||||
fn applied_pick_constraints(&self, r: impl ToRegionVid) -> &[AppliedPickConstraint] {
|
||||
/// region `r`. See `AppliedMemberConstraint`.
|
||||
fn applied_member_constraints(&self, r: impl ToRegionVid) -> &[AppliedMemberConstraint] {
|
||||
let scc = self.constraint_sccs.scc(r.to_region_vid());
|
||||
binary_search_util::binary_search_slice(
|
||||
&self.pick_constraints_applied,
|
||||
|applied| applied.pick_region_scc,
|
||||
&self.member_constraints_applied,
|
||||
|applied| applied.member_region_scc,
|
||||
&scc,
|
||||
)
|
||||
}
|
||||
@ -511,7 +512,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
errors_buffer,
|
||||
);
|
||||
|
||||
self.check_pick_constraints(infcx, mir_def_id, errors_buffer);
|
||||
self.check_member_constraints(infcx, mir_def_id, errors_buffer);
|
||||
|
||||
let outlives_requirements = outlives_requirements.unwrap_or(vec![]);
|
||||
|
||||
@ -548,9 +549,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
self.propagate_constraint_sccs_if_new(scc_index, visited);
|
||||
}
|
||||
|
||||
// Sort the applied pick constraints so we can binary search
|
||||
// Sort the applied member constraints so we can binary search
|
||||
// through them later.
|
||||
self.pick_constraints_applied.sort_by_key(|applied| applied.pick_region_scc);
|
||||
self.member_constraints_applied.sort_by_key(|applied| applied.member_region_scc);
|
||||
}
|
||||
|
||||
/// Computes the value of the SCC `scc_a` if it has not already
|
||||
@ -597,13 +598,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
// Now take pick constraints into account
|
||||
let pick_constraints = self.pick_constraints.clone();
|
||||
for p_c_i in pick_constraints.indices(scc_a) {
|
||||
self.apply_pick_constraint(
|
||||
// Now take member constraints into account
|
||||
let member_constraints = self.member_constraints.clone();
|
||||
for m_c_i in member_constraints.indices(scc_a) {
|
||||
self.apply_member_constraint(
|
||||
scc_a,
|
||||
p_c_i,
|
||||
pick_constraints.option_regions(p_c_i),
|
||||
m_c_i,
|
||||
member_constraints.choice_regions(m_c_i),
|
||||
);
|
||||
}
|
||||
|
||||
@ -614,9 +615,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
);
|
||||
}
|
||||
|
||||
/// Invoked for each `pick R0 from [R1..Rn]` constraint.
|
||||
/// Invoked for each `member R0 of [R1..Rn]` constraint.
|
||||
///
|
||||
/// `scc` is the SCC containing R0, and `option_regions` are the
|
||||
/// `scc` is the SCC containing R0, and `choice_regions` are the
|
||||
/// `R1..Rn` regions -- they are always known to be universal
|
||||
/// regions (and if that's not true, we just don't attempt to
|
||||
/// enforce the constraint).
|
||||
@ -625,34 +626,34 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
/// is considered a *lower bound*. If possible, we will modify
|
||||
/// the constraint to set it equal to one of the option regions.
|
||||
/// If we make any changes, returns true, else false.
|
||||
fn apply_pick_constraint(
|
||||
fn apply_member_constraint(
|
||||
&mut self,
|
||||
scc: ConstraintSccIndex,
|
||||
pick_constraint_index: NllPickConstraintIndex,
|
||||
option_regions: &[ty::RegionVid],
|
||||
member_constraint_index: NllMemberConstraintIndex,
|
||||
choice_regions: &[ty::RegionVid],
|
||||
) -> bool {
|
||||
debug!("apply_pick_constraint(scc={:?}, option_regions={:#?})", scc, option_regions,);
|
||||
debug!("apply_member_constraint(scc={:?}, choice_regions={:#?})", scc, choice_regions,);
|
||||
|
||||
if let Some(uh_oh) =
|
||||
option_regions.iter().find(|&&r| !self.universal_regions.is_universal_region(r))
|
||||
choice_regions.iter().find(|&&r| !self.universal_regions.is_universal_region(r))
|
||||
{
|
||||
// FIXME(#61773): This case can only occur with
|
||||
// `impl_trait_in_bindings`, I believe, and we are just
|
||||
// opting not to handle it for now. See #61773 for
|
||||
// details.
|
||||
bug!(
|
||||
"pick constraint for `{:?}` has an option region `{:?}` \
|
||||
"member constraint for `{:?}` has an option region `{:?}` \
|
||||
that is not a universal region",
|
||||
self.pick_constraints[pick_constraint_index].opaque_type_def_id,
|
||||
self.member_constraints[member_constraint_index].opaque_type_def_id,
|
||||
uh_oh,
|
||||
);
|
||||
}
|
||||
|
||||
// Create a mutable vector of the options. We'll try to winnow
|
||||
// them down.
|
||||
let mut option_regions: Vec<ty::RegionVid> = option_regions.to_vec();
|
||||
let mut choice_regions: Vec<ty::RegionVid> = choice_regions.to_vec();
|
||||
|
||||
// The 'pick-region' in a pick-constraint is part of the
|
||||
// The 'member region' in a member constraint is part of the
|
||||
// hidden type, which must be in the root universe. Therefore,
|
||||
// it cannot have any placeholders in its value.
|
||||
assert!(self.scc_universes[scc] == ty::UniverseIndex::ROOT);
|
||||
@ -665,35 +666,37 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
|
||||
// The existing value for `scc` is a lower-bound. This will
|
||||
// consist of some set {P} + {LB} of points {P} and
|
||||
// lower-bound free regions {LB}. As each option region O is a
|
||||
// lower-bound free regions {LB}. As each choice region O is a
|
||||
// free region, it will outlive the points. But we can only
|
||||
// consider the option O if O: LB.
|
||||
option_regions.retain(|&o_r| {
|
||||
choice_regions.retain(|&o_r| {
|
||||
self.scc_values
|
||||
.universal_regions_outlived_by(scc)
|
||||
.all(|lb| self.universal_region_relations.outlives(o_r, lb))
|
||||
});
|
||||
debug!("apply_pick_constraint: after lb, option_regions={:?}", option_regions);
|
||||
debug!("apply_member_constraint: after lb, choice_regions={:?}", choice_regions);
|
||||
|
||||
// Now find all the *upper bounds* -- that is, each UB is a free
|
||||
// region that must outlive pick region R0 (`UB: R0`). Therefore,
|
||||
// we need only keep an option O if `UB: O` for all UB.
|
||||
if option_regions.len() > 1 {
|
||||
// Now find all the *upper bounds* -- that is, each UB is a
|
||||
// free region that must outlive the member region R0 (`UB:
|
||||
// R0`). Therefore, we need only keep an option O if `UB: O`
|
||||
// for all UB.
|
||||
if choice_regions.len() > 1 {
|
||||
let universal_region_relations = self.universal_region_relations.clone();
|
||||
for ub in self.upper_bounds(scc) {
|
||||
debug!("apply_pick_constraint: ub={:?}", ub);
|
||||
option_regions.retain(|&o_r| universal_region_relations.outlives(ub, o_r));
|
||||
debug!("apply_member_constraint: ub={:?}", ub);
|
||||
choice_regions.retain(|&o_r| universal_region_relations.outlives(ub, o_r));
|
||||
}
|
||||
debug!("apply_pick_constraint: after ub, option_regions={:?}", option_regions);
|
||||
debug!("apply_member_constraint: after ub, choice_regions={:?}", choice_regions);
|
||||
}
|
||||
|
||||
// If we ruled everything out, we're done.
|
||||
if option_regions.is_empty() {
|
||||
if choice_regions.is_empty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Otherwise, we need to find the minimum option, if any, and take that.
|
||||
debug!("apply_pick_constraint: option_regions remaining are {:#?}", option_regions);
|
||||
// Otherwise, we need to find the minimum remaining choice, if
|
||||
// any, and take that.
|
||||
debug!("apply_member_constraint: choice_regions remaining are {:#?}", choice_regions);
|
||||
let min = |r1: ty::RegionVid, r2: ty::RegionVid| -> Option<ty::RegionVid> {
|
||||
let r1_outlives_r2 = self.universal_region_relations.outlives(r1, r2);
|
||||
let r2_outlives_r1 = self.universal_region_relations.outlives(r2, r1);
|
||||
@ -707,35 +710,35 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
None
|
||||
}
|
||||
};
|
||||
let mut best_option = option_regions[0];
|
||||
for &other_option in &option_regions[1..] {
|
||||
let mut min_choice = choice_regions[0];
|
||||
for &other_option in &choice_regions[1..] {
|
||||
debug!(
|
||||
"apply_pick_constraint: best_option={:?} other_option={:?}",
|
||||
best_option, other_option,
|
||||
"apply_member_constraint: min_choice={:?} other_option={:?}",
|
||||
min_choice, other_option,
|
||||
);
|
||||
match min(best_option, other_option) {
|
||||
Some(m) => best_option = m,
|
||||
match min(min_choice, other_option) {
|
||||
Some(m) => min_choice = m,
|
||||
None => {
|
||||
debug!(
|
||||
"apply_pick_constraint: {:?} and {:?} are incomparable --> no best choice",
|
||||
best_option, other_option,
|
||||
"apply_member_constraint: {:?} and {:?} are incomparable; no min choice",
|
||||
min_choice, other_option,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let best_option_scc = self.constraint_sccs.scc(best_option);
|
||||
let min_choice_scc = self.constraint_sccs.scc(min_choice);
|
||||
debug!(
|
||||
"apply_pick_constraint: best_choice={:?} best_option_scc={:?}",
|
||||
best_option,
|
||||
best_option_scc,
|
||||
"apply_member_constraint: min_choice={:?} best_choice_scc={:?}",
|
||||
min_choice,
|
||||
min_choice_scc,
|
||||
);
|
||||
if self.scc_values.add_region(scc, best_option_scc) {
|
||||
self.pick_constraints_applied.push(AppliedPickConstraint {
|
||||
pick_region_scc: scc,
|
||||
best_option,
|
||||
pick_constraint_index,
|
||||
if self.scc_values.add_region(scc, min_choice_scc) {
|
||||
self.member_constraints_applied.push(AppliedMemberConstraint {
|
||||
member_region_scc: scc,
|
||||
min_choice,
|
||||
member_constraint_index,
|
||||
});
|
||||
|
||||
true
|
||||
@ -1542,42 +1545,42 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
diag.emit();
|
||||
}
|
||||
|
||||
fn check_pick_constraints(
|
||||
fn check_member_constraints(
|
||||
&self,
|
||||
infcx: &InferCtxt<'_, 'tcx>,
|
||||
mir_def_id: DefId,
|
||||
errors_buffer: &mut Vec<Diagnostic>,
|
||||
) {
|
||||
let pick_constraints = self.pick_constraints.clone();
|
||||
for p_c_i in pick_constraints.all_indices() {
|
||||
debug!("check_pick_constraint(p_c_i={:?})", p_c_i);
|
||||
let p_c = &pick_constraints[p_c_i];
|
||||
let pick_region_vid = p_c.pick_region_vid;
|
||||
let member_constraints = self.member_constraints.clone();
|
||||
for m_c_i in member_constraints.all_indices() {
|
||||
debug!("check_member_constraint(m_c_i={:?})", m_c_i);
|
||||
let m_c = &member_constraints[m_c_i];
|
||||
let member_region_vid = m_c.member_region_vid;
|
||||
debug!(
|
||||
"check_pick_constraint: pick_region_vid={:?} with value {}",
|
||||
pick_region_vid,
|
||||
self.region_value_str(pick_region_vid),
|
||||
"check_member_constraint: member_region_vid={:?} with value {}",
|
||||
member_region_vid,
|
||||
self.region_value_str(member_region_vid),
|
||||
);
|
||||
let option_regions = pick_constraints.option_regions(p_c_i);
|
||||
debug!("check_pick_constraint: option_regions={:?}", option_regions);
|
||||
let choice_regions = member_constraints.choice_regions(m_c_i);
|
||||
debug!("check_member_constraint: choice_regions={:?}", choice_regions);
|
||||
|
||||
// did the pick-region wind up equal to any of the option regions?
|
||||
if let Some(o) = option_regions.iter().find(|&&o_r| {
|
||||
self.eval_equal(o_r, p_c.pick_region_vid)
|
||||
if let Some(o) = choice_regions.iter().find(|&&o_r| {
|
||||
self.eval_equal(o_r, m_c.member_region_vid)
|
||||
}) {
|
||||
debug!("check_pick_constraint: evaluated as equal to {:?}", o);
|
||||
debug!("check_member_constraint: evaluated as equal to {:?}", o);
|
||||
continue;
|
||||
}
|
||||
|
||||
// if not, report an error
|
||||
let region_scope_tree = &infcx.tcx.region_scope_tree(mir_def_id);
|
||||
let pick_region = infcx.tcx.mk_region(ty::ReVar(pick_region_vid));
|
||||
let member_region = infcx.tcx.mk_region(ty::ReVar(member_region_vid));
|
||||
opaque_types::unexpected_hidden_region_diagnostic(
|
||||
infcx.tcx,
|
||||
Some(region_scope_tree),
|
||||
p_c.opaque_type_def_id,
|
||||
p_c.hidden_ty,
|
||||
pick_region,
|
||||
m_c.opaque_type_def_id,
|
||||
m_c.hidden_ty,
|
||||
member_region,
|
||||
)
|
||||
.buffer(errors_buffer);
|
||||
}
|
||||
|
@ -53,20 +53,23 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
||||
pub(super) fn convert_all(&mut self, query_constraints: &QueryRegionConstraints<'tcx>) {
|
||||
debug!("convert_all(query_constraints={:#?})", query_constraints);
|
||||
|
||||
let QueryRegionConstraints { outlives, pick_constraints } = query_constraints;
|
||||
let QueryRegionConstraints { outlives, member_constraints } = query_constraints;
|
||||
|
||||
// Annoying: to invoke `self.to_region_vid`, we need access to
|
||||
// `self.constraints`, but we also want to be mutating
|
||||
// `self.pick_constraints`. For now, just swap out the value
|
||||
// `self.member_constraints`. For now, just swap out the value
|
||||
// we want and replace at the end.
|
||||
let mut tmp = std::mem::replace(&mut self.constraints.pick_constraints, Default::default());
|
||||
for pick_constraint in pick_constraints {
|
||||
let mut tmp = std::mem::replace(
|
||||
&mut self.constraints.member_constraints,
|
||||
Default::default(),
|
||||
);
|
||||
for member_constraint in member_constraints {
|
||||
tmp.push_constraint(
|
||||
pick_constraint,
|
||||
member_constraint,
|
||||
|r| self.to_region_vid(r),
|
||||
);
|
||||
}
|
||||
self.constraints.pick_constraints = tmp;
|
||||
self.constraints.member_constraints = tmp;
|
||||
|
||||
for query_constraint in outlives {
|
||||
self.convert(query_constraint);
|
||||
|
@ -5,7 +5,7 @@
|
||||
use crate::borrow_check::borrow_set::BorrowSet;
|
||||
use crate::borrow_check::location::LocationTable;
|
||||
use crate::borrow_check::nll::constraints::{OutlivesConstraintSet, OutlivesConstraint};
|
||||
use crate::borrow_check::nll::pick_constraints::PickConstraintSet;
|
||||
use crate::borrow_check::nll::member_constraints::MemberConstraintSet;
|
||||
use crate::borrow_check::nll::facts::AllFacts;
|
||||
use crate::borrow_check::nll::region_infer::values::LivenessValues;
|
||||
use crate::borrow_check::nll::region_infer::values::PlaceholderIndex;
|
||||
@ -129,7 +129,7 @@ pub(crate) fn type_check<'tcx>(
|
||||
placeholder_index_to_region: IndexVec::default(),
|
||||
liveness_constraints: LivenessValues::new(elements.clone()),
|
||||
outlives_constraints: OutlivesConstraintSet::default(),
|
||||
pick_constraints: PickConstraintSet::default(),
|
||||
member_constraints: MemberConstraintSet::default(),
|
||||
closure_bounds_mapping: Default::default(),
|
||||
type_tests: Vec::default(),
|
||||
};
|
||||
@ -889,7 +889,7 @@ crate struct MirTypeckRegionConstraints<'tcx> {
|
||||
|
||||
crate outlives_constraints: OutlivesConstraintSet,
|
||||
|
||||
crate pick_constraints: PickConstraintSet<'tcx, RegionVid>,
|
||||
crate member_constraints: MemberConstraintSet<'tcx, RegionVid>,
|
||||
|
||||
crate closure_bounds_mapping:
|
||||
FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>>,
|
||||
@ -2525,7 +2525,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
// constraints only come from `-> impl Trait` and
|
||||
// friends which don't appear (thus far...) in
|
||||
// closures.
|
||||
pick_constraints: vec![],
|
||||
member_constraints: vec![],
|
||||
};
|
||||
|
||||
let bounds_mapping = closure_constraints
|
||||
|
Loading…
x
Reference in New Issue
Block a user