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