1
Fork 0

rename to "member constraints"

This commit is contained in:
Niko Matsakis 2019-06-18 08:52:23 -04:00
parent e39f66a859
commit eca55b58d6
14 changed files with 275 additions and 261 deletions

View file

@ -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
} }
} }

View file

@ -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() }
} }

View file

@ -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
} }

View file

@ -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(),
}); });
} }
} }

View file

@ -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(

View file

@ -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,
), ),
}); });
} }

View file

@ -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()
} }

View file

@ -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,

View file

@ -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 {

View file

@ -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,
} }

View file

@ -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);
} }

View file

@ -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);

View file

@ -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