use super::universal_regions::UniversalRegions;
use crate::borrow_check::nll::constraints::graph::NormalConstraintGraph;
-use crate::borrow_check::nll::constraints::{ConstraintSccIndex, ConstraintSet, OutlivesConstraint};
+use crate::borrow_check::nll::constraints::{
+ ConstraintSccIndex, OutlivesConstraint, OutlivesConstraintSet,
+};
+use crate::borrow_check::nll::member_constraints::{MemberConstraintSet, NllMemberConstraintIndex};
use crate::borrow_check::nll::region_infer::values::{
- PlaceholderIndices, RegionElement, ToElementIndex
+ PlaceholderIndices, RegionElement, ToElementIndex,
};
-use crate::borrow_check::Upvar;
use crate::borrow_check::nll::type_check::free_region_relations::UniversalRegionRelations;
use crate::borrow_check::nll::type_check::Locations;
+use crate::borrow_check::Upvar;
use rustc::hir::def_id::DefId;
-use rustc::infer::canonical::QueryRegionConstraint;
+use rustc::infer::canonical::QueryOutlivesConstraint;
+use rustc::infer::opaque_types;
use rustc::infer::region_constraints::{GenericKind, VarInfos, VerifyBound};
use rustc::infer::{InferCtxt, NLLRegionVariableOrigin, RegionVariableOrigin};
use rustc::mir::{
- ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureRegionRequirements,
- ConstraintCategory, Local, Location, Body,
+ Body, ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureRegionRequirements,
+ ConstraintCategory, Local, Location,
};
use rustc::ty::{self, subst::SubstsRef, RegionVid, Ty, TyCtxt, TypeFoldable};
use rustc::util::common::{self, ErrorReported};
+use rustc_data_structures::binary_search_util;
use rustc_data_structures::bit_set::BitSet;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::graph::WithSuccessors;
use rustc_data_structures::graph::scc::Sccs;
+use rustc_data_structures::graph::vec_graph::VecGraph;
use rustc_data_structures::indexed_vec::IndexVec;
use rustc_errors::{Diagnostic, DiagnosticBuilder};
use syntax_pos::Span;
liveness_constraints: LivenessValues<RegionVid>,
/// The outlives constraints computed by the type-check.
- constraints: Rc<ConstraintSet>,
+ constraints: Rc<OutlivesConstraintSet>,
/// The constraint-set, but in graph form, making it easy to traverse
/// the constraints adjacent to a particular region. Used to construct
/// the SCC (see `constraint_sccs`) and for error reporting.
constraint_graph: Rc<NormalConstraintGraph>,
- /// The SCC computed from `constraints` and the constraint graph. Used to
+ /// The SCC computed from `constraints` and the constraint
+ /// graph. We have an edge from SCC A to SCC B if `A: B`. Used to
/// compute the values of each region.
constraint_sccs: Rc<Sccs<RegionVid, ConstraintSccIndex>>,
+ /// Reverse of the SCC constraint graph -- i.e., an edge `A -> B`
+ /// exists if `B: A`. Computed lazilly.
+ rev_constraint_graph: Option<Rc<VecGraph<ConstraintSccIndex>>>,
+
+ /// The "R0 member of [R1..Rn]" constraints, indexed by SCC.
+ member_constraints: Rc<MemberConstraintSet<'tcx, ConstraintSccIndex>>,
+
+ /// Records the member constraints that we applied to each scc.
+ /// This is useful for error reporting. Once constraint
+ /// propagation is done, this vector is sorted according to
+ /// `member_region_scc`.
+ member_constraints_applied: Vec<AppliedMemberConstraint>,
+
/// Map closure bounds to a `Span` that should be used for error reporting.
closure_bounds_mapping:
FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>>,
universal_region_relations: Rc<UniversalRegionRelations<'tcx>>,
}
+/// Each time that `apply_member_constraint` is successful, it appends
+/// one of these structs to the `member_constraints_applied` field.
+/// This is used in error reporting to trace out what happened.
+///
+/// The way that `apply_member_constraint` works is that it effectively
+/// adds a new lower bound to the SCC it is analyzing: so you wind up
+/// with `'R: 'O` where `'R` is the pick-region and `'O` is the
+/// minimal viable option.
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
+struct AppliedMemberConstraint {
+ /// The SCC that was affected. (The "member region".)
+ ///
+ /// The vector if `AppliedMemberConstraint` elements is kept sorted
+ /// by this field.
+ member_region_scc: ConstraintSccIndex,
+
+ /// The "best option" that `apply_member_constraint` found -- this was
+ /// added as an "ad-hoc" lower-bound to `member_region_scc`.
+ min_choice: ty::RegionVid,
+
+ /// The "member constraint index" -- we can find out details about
+ /// the constraint from
+ /// `set.member_constraints[member_constraint_index]`.
+ member_constraint_index: NllMemberConstraintIndex,
+}
+
struct RegionDefinition<'tcx> {
/// What kind of variable is this -- a free region? existential
/// variable? etc. (See the `NLLRegionVariableOrigin` for more
placeholder_indices: Rc<PlaceholderIndices>,
universal_region_relations: Rc<UniversalRegionRelations<'tcx>>,
_body: &Body<'tcx>,
- outlives_constraints: ConstraintSet,
+ outlives_constraints: OutlivesConstraintSet,
+ member_constraints_in: MemberConstraintSet<'tcx, RegionVid>,
closure_bounds_mapping: FxHashMap<
Location,
FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>,
let scc_representatives = Self::compute_scc_representatives(&constraint_sccs, &definitions);
+ let member_constraints =
+ Rc::new(member_constraints_in.into_mapped(|r| constraint_sccs.scc(r)));
+
let mut result = Self {
definitions,
liveness_constraints,
constraints,
constraint_graph,
constraint_sccs,
+ rev_constraint_graph: None,
+ member_constraints,
+ member_constraints_applied: Vec::new(),
closure_bounds_mapping,
scc_universes,
scc_representatives,
debug!(
"init_free_and_bound_regions: placeholder {:?} is \
not compatible with universe {:?} of its SCC {:?}",
- placeholder,
- scc_universe,
- scc,
+ placeholder, scc_universe, scc,
);
self.add_incompatible_universe(scc);
}
self.scc_universes[scc]
}
+ /// Once region solving has completed, this function will return
+ /// the member constraints that were applied to the value of a given
+ /// region `r`. See `AppliedMemberConstraint`.
+ fn applied_member_constraints(&self, r: impl ToRegionVid) -> &[AppliedMemberConstraint] {
+ let scc = self.constraint_sccs.scc(r.to_region_vid());
+ binary_search_util::binary_search_slice(
+ &self.member_constraints_applied,
+ |applied| applied.member_region_scc,
+ &scc,
+ )
+ }
+
/// Performs region inference and report errors if we see any
/// unsatisfiable constraints. If this is a closure, returns the
/// region requirements to propagate to our creator, if any.
// to store those. Otherwise, we'll pass in `None` to the
// functions below, which will trigger them to report errors
// eagerly.
- let mut outlives_requirements = if infcx.tcx.is_closure(mir_def_id) {
- Some(vec![])
- } else {
- None
- };
+ let mut outlives_requirements =
+ if infcx.tcx.is_closure(mir_def_id) { Some(vec![]) } else { None };
self.check_type_tests(
infcx,
errors_buffer,
);
+ self.check_member_constraints(infcx, mir_def_id, errors_buffer);
+
let outlives_requirements = outlives_requirements.unwrap_or(vec![]);
if outlives_requirements.is_empty() {
None
} else {
let num_external_vids = self.universal_regions.num_global_and_external_regions();
- Some(ClosureRegionRequirements {
- num_external_vids,
- outlives_requirements,
- })
+ Some(ClosureRegionRequirements { num_external_vids, outlives_requirements })
}
}
debug!("propagate_constraints()");
debug!("propagate_constraints: constraints={:#?}", {
- let mut constraints: Vec<_> = self.constraints.iter().collect();
+ let mut constraints: Vec<_> = self.constraints.outlives().iter().collect();
constraints.sort();
constraints
.into_iter()
for scc_index in self.constraint_sccs.all_sccs() {
self.propagate_constraint_sccs_if_new(scc_index, visited);
}
+
+ // Sort the applied member constraints so we can binary search
+ // through them later.
+ 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
+ /// been computed. The `visited` parameter is a bitset
#[inline]
fn propagate_constraint_sccs_if_new(
&mut self,
}
}
+ /// Computes the value of the SCC `scc_a`, which has not yet been
+ /// computed. This works by first computing all successors of the
+ /// SCC (if they haven't been computed already) and then unioning
+ /// together their elements.
fn propagate_constraint_sccs_new(
&mut self,
scc_a: ConstraintSccIndex,
// Walk each SCC `B` such that `A: B`...
for &scc_b in constraint_sccs.successors(scc_a) {
- debug!(
- "propagate_constraint_sccs: scc_a = {:?} scc_b = {:?}",
- scc_a, scc_b
- );
+ debug!("propagate_constraint_sccs: scc_a = {:?} scc_b = {:?}", scc_a, scc_b);
// ...compute the value of `B`...
self.propagate_constraint_sccs_if_new(scc_b, visited);
}
}
+ // Now take member constraints into account.
+ let member_constraints = self.member_constraints.clone();
+ for m_c_i in member_constraints.indices(scc_a) {
+ self.apply_member_constraint(
+ scc_a,
+ m_c_i,
+ member_constraints.choice_regions(m_c_i),
+ );
+ }
+
debug!(
"propagate_constraint_sccs: scc_a = {:?} has value {:?}",
scc_a,
);
}
+ /// Invoked for each `R0 member of [R1..Rn]` constraint.
+ ///
+ /// `scc` is the SCC containing R0, and `choice_regions` are the
+ /// `R1..Rn` regions -- they are always known to be universal
+ /// regions (and if that's not true, we just don't attempt to
+ /// enforce the constraint).
+ ///
+ /// The current value of `scc` at the time the method is invoked
+ /// is considered a *lower bound*. If possible, we will modify
+ /// the constraint to set it equal to one of the option regions.
+ /// If we make any changes, returns true, else false.
+ fn apply_member_constraint(
+ &mut self,
+ scc: ConstraintSccIndex,
+ member_constraint_index: NllMemberConstraintIndex,
+ choice_regions: &[ty::RegionVid],
+ ) -> bool {
+ debug!("apply_member_constraint(scc={:?}, choice_regions={:#?})", scc, choice_regions,);
+
+ if let Some(uh_oh) =
+ choice_regions.iter().find(|&&r| !self.universal_regions.is_universal_region(r))
+ {
+ // FIXME(#61773): This case can only occur with
+ // `impl_trait_in_bindings`, I believe, and we are just
+ // opting not to handle it for now. See #61773 for
+ // details.
+ bug!(
+ "member constraint for `{:?}` has an option region `{:?}` \
+ that is not a universal region",
+ self.member_constraints[member_constraint_index].opaque_type_def_id,
+ uh_oh,
+ );
+ }
+
+ // Create a mutable vector of the options. We'll try to winnow
+ // them down.
+ let mut choice_regions: Vec<ty::RegionVid> = choice_regions.to_vec();
+
+ // The 'member region' in a member constraint is part of the
+ // hidden type, which must be in the root universe. Therefore,
+ // it cannot have any placeholders in its value.
+ assert!(self.scc_universes[scc] == ty::UniverseIndex::ROOT);
+ debug_assert!(
+ self.scc_values.placeholders_contained_in(scc).next().is_none(),
+ "scc {:?} in a member constraint has placeholder value: {:?}",
+ scc,
+ self.scc_values.region_value_str(scc),
+ );
+
+ // The existing value for `scc` is a lower-bound. This will
+ // consist of some set `{P} + {LB}` of points `{P}` and
+ // lower-bound free regions `{LB}`. As each choice region `O`
+ // is a free region, it will outlive the points. But we can
+ // only consider the option `O` if `O: LB`.
+ choice_regions.retain(|&o_r| {
+ self.scc_values
+ .universal_regions_outlived_by(scc)
+ .all(|lb| self.universal_region_relations.outlives(o_r, lb))
+ });
+ debug!("apply_member_constraint: after lb, choice_regions={:?}", choice_regions);
+
+ // Now find all the *upper bounds* -- that is, each UB is a
+ // free region that must outlive the member region `R0` (`UB:
+ // R0`). Therefore, we need only keep an option `O` if `UB: O`
+ // for all UB.
+ if choice_regions.len() > 1 {
+ let universal_region_relations = self.universal_region_relations.clone();
+ let rev_constraint_graph = self.rev_constraint_graph();
+ for ub in self.upper_bounds(scc, &rev_constraint_graph) {
+ debug!("apply_member_constraint: ub={:?}", ub);
+ choice_regions.retain(|&o_r| universal_region_relations.outlives(ub, o_r));
+ }
+ debug!("apply_member_constraint: after ub, choice_regions={:?}", choice_regions);
+ }
+
+ // If we ruled everything out, we're done.
+ if choice_regions.is_empty() {
+ return false;
+ }
+
+ // Otherwise, we need to find the minimum remaining choice, if
+ // any, and take that.
+ debug!("apply_member_constraint: choice_regions remaining are {:#?}", choice_regions);
+ let min = |r1: ty::RegionVid, r2: ty::RegionVid| -> Option<ty::RegionVid> {
+ let r1_outlives_r2 = self.universal_region_relations.outlives(r1, r2);
+ let r2_outlives_r1 = self.universal_region_relations.outlives(r2, r1);
+ if r1_outlives_r2 && r2_outlives_r1 {
+ Some(r1.min(r2))
+ } else if r1_outlives_r2 {
+ Some(r2)
+ } else if r2_outlives_r1 {
+ Some(r1)
+ } else {
+ None
+ }
+ };
+ let mut min_choice = choice_regions[0];
+ for &other_option in &choice_regions[1..] {
+ debug!(
+ "apply_member_constraint: min_choice={:?} other_option={:?}",
+ min_choice, other_option,
+ );
+ match min(min_choice, other_option) {
+ Some(m) => min_choice = m,
+ None => {
+ debug!(
+ "apply_member_constraint: {:?} and {:?} are incomparable; no min choice",
+ min_choice, other_option,
+ );
+ return false;
+ }
+ }
+ }
+
+ let min_choice_scc = self.constraint_sccs.scc(min_choice);
+ debug!(
+ "apply_member_constraint: min_choice={:?} best_choice_scc={:?}",
+ min_choice,
+ min_choice_scc,
+ );
+ if self.scc_values.add_region(scc, min_choice_scc) {
+ self.member_constraints_applied.push(AppliedMemberConstraint {
+ member_region_scc: scc,
+ min_choice,
+ member_constraint_index,
+ });
+
+ true
+ } else {
+ false
+ }
+ }
+
+ /// Compute and return the reverse SCC-based constraint graph (lazilly).
+ fn upper_bounds(
+ &'a mut self,
+ scc0: ConstraintSccIndex,
+ rev_constraint_graph: &'a VecGraph<ConstraintSccIndex>,
+ ) -> impl Iterator<Item = RegionVid> + 'a {
+ let scc_values = &self.scc_values;
+ let mut duplicates = FxHashSet::default();
+ rev_constraint_graph
+ .depth_first_search(scc0)
+ .skip(1)
+ .flat_map(move |scc1| scc_values.universal_regions_outlived_by(scc1))
+ .filter(move |&r| duplicates.insert(r))
+ }
+
+ /// Compute and return the reverse SCC-based constraint graph (lazilly).
+ fn rev_constraint_graph(
+ &mut self,
+ ) -> Rc<VecGraph<ConstraintSccIndex>> {
+ if let Some(g) = &self.rev_constraint_graph {
+ return g.clone();
+ }
+
+ let rev_graph = Rc::new(self.constraint_sccs.reverse());
+ self.rev_constraint_graph = Some(rev_graph.clone());
+ rev_graph
+ }
+
/// Returns `true` if all the elements in the value of `scc_b` are nameable
/// in `scc_a`. Used during constraint propagation, and only once
/// the value of `scc_b` has been computed.
// Otherwise, we have to iterate over the universe elements in
// B's value, and check whether all of them are nameable
// from universe_a
- self.scc_values
- .placeholders_contained_in(scc_b)
- .all(|p| universe_a.can_name(p.universe))
+ self.scc_values.placeholders_contained_in(scc_b).all(|p| universe_a.can_name(p.universe))
}
/// Extend `scc` so that it can outlive some placeholder region
) -> bool {
let tcx = infcx.tcx;
- let TypeTest {
- generic_kind,
- lower_bound,
- locations,
- verify_bound: _,
- } = type_test;
+ let TypeTest { generic_kind, lower_bound, locations, verify_bound: _ } = type_test;
let generic_ty = generic_kind.to_ty(tcx);
let subject = match self.try_promote_type_test_subject(infcx, generic_ty) {
ty: Ty<'tcx>,
) -> Option<ClosureOutlivesSubject<'tcx>> {
let tcx = infcx.tcx;
- let gcx = tcx.global_tcx();
debug!("try_promote_type_test_subject(ty = {:?})", ty);
});
debug!("try_promote_type_test_subject: folded ty = {:?}", ty);
- // `lift` will only fail if we failed to promote some region.
- let ty = gcx.lift(&ty)?;
+ // `has_local_value` will only be true if we failed to promote some region.
+ if ty.has_local_value() {
+ return None;
+ }
Some(ClosureOutlivesSubject::Ty(ty))
}
/// except that it converts further takes the non-local upper
/// bound of `'y`, so that the final result is non-local.
fn non_local_universal_upper_bound(&self, r: RegionVid) -> RegionVid {
- debug!(
- "non_local_universal_upper_bound(r={:?}={})",
- r,
- self.region_value_str(r)
- );
+ debug!("non_local_universal_upper_bound(r={:?}={})", r, self.region_value_str(r));
let lub = self.universal_upper_bound(r);
// creator.
let non_local_lub = self.universal_region_relations.non_local_upper_bound(lub);
- debug!(
- "non_local_universal_upper_bound: non_local_lub={:?}",
- non_local_lub
- );
+ debug!("non_local_universal_upper_bound: non_local_lub={:?}", non_local_lub);
non_local_lub
}
/// - For each `end('x)` element in `'r`, compute the mutual LUB, yielding
/// a result `'y`.
fn universal_upper_bound(&self, r: RegionVid) -> RegionVid {
- debug!(
- "universal_upper_bound(r={:?}={})",
- r,
- self.region_value_str(r)
- );
+ debug!("universal_upper_bound(r={:?}={})", r, self.region_value_str(r));
// Find the smallest universal region that contains all other
// universal regions within `region`.
lower_bound: RegionVid,
verify_bound: &VerifyBound<'tcx>,
) -> bool {
- debug!(
- "eval_verify_bound(lower_bound={:?}, verify_bound={:?})",
- lower_bound, verify_bound
- );
+ debug!("eval_verify_bound(lower_bound={:?}, verify_bound={:?})", lower_bound, verify_bound);
match verify_bound {
VerifyBound::IfEq(test_ty, verify_bound1) => {
VerifyBound::OutlivedBy(r) => {
let r_vid = self.to_region_vid(r);
- self.eval_outlives(body, r_vid, lower_bound)
+ self.eval_outlives(r_vid, lower_bound)
}
VerifyBound::AnyBound(verify_bounds) => verify_bounds.iter().any(|verify_bound| {
})
}
- // Evaluate whether `sup_region: sub_region @ point`.
- fn eval_outlives(
- &self,
- _body: &Body<'tcx>,
- sup_region: RegionVid,
- sub_region: RegionVid,
- ) -> bool {
+ // Evaluate whether `sup_region == sub_region`.
+ fn eval_equal(&self, r1: RegionVid, r2: RegionVid) -> bool {
+ self.eval_outlives(r1, r2) && self.eval_outlives(r2, r1)
+ }
+
+ // Evaluate whether `sup_region: sub_region`.
+ fn eval_outlives(&self, sup_region: RegionVid, sub_region: RegionVid) -> bool {
debug!("eval_outlives({:?}: {:?})", sup_region, sub_region);
debug!(
- "eval_outlives: sup_region's value = {:?}",
+ "eval_outlives: sup_region's value = {:?} universal={:?}",
self.region_value_str(sup_region),
+ self.universal_regions.is_universal_region(sup_region),
);
debug!(
- "eval_outlives: sub_region's value = {:?}",
+ "eval_outlives: sub_region's value = {:?} universal={:?}",
self.region_value_str(sub_region),
+ self.universal_regions.is_universal_region(sub_region),
);
let sub_region_scc = self.constraint_sccs.scc(sub_region);
// now). Therefore, the sup-region outlives the sub-region if,
// for each universal region R1 in the sub-region, there
// exists some region R2 in the sup-region that outlives R1.
- let universal_outlives = self.scc_values
- .universal_regions_outlived_by(sub_region_scc)
- .all(|r1| {
+ let universal_outlives =
+ self.scc_values.universal_regions_outlived_by(sub_region_scc).all(|r1| {
self.scc_values
.universal_regions_outlived_by(sup_region_scc)
.any(|r2| self.universal_region_relations.outlives(r2, r1))
return true;
}
- self.scc_values
- .contains_points(sup_region_scc, sub_region_scc)
+ self.scc_values.contains_points(sup_region_scc, sub_region_scc)
}
/// Once regions have been propagated, this method is used to see
// Because this free region must be in the ROOT universe, we
// know it cannot contain any bound universes.
assert!(self.scc_universes[longer_fr_scc] == ty::UniverseIndex::ROOT);
- debug_assert!(
- self.scc_values
- .placeholders_contained_in(longer_fr_scc)
- .next()
- .is_none()
- );
+ debug_assert!(self.scc_values.placeholders_contained_in(longer_fr_scc).next().is_none());
// Only check all of the relations for the main representative of each
// SCC, otherwise just check that we outlive said representative. This
errors_buffer: &mut Vec<Diagnostic>,
) -> Option<ErrorReported> {
// If it is known that `fr: o`, carry on.
- if self.universal_region_relations
- .outlives(longer_fr, shorter_fr)
- {
+ if self.universal_region_relations.outlives(longer_fr, shorter_fr) {
return None;
}
// We'll call it `fr-` -- it's ever so slightly smaller than
// `longer_fr`.
- if let Some(fr_minus) = self
- .universal_region_relations
- .non_local_lower_bound(longer_fr)
+ if let Some(fr_minus) = self.universal_region_relations.non_local_lower_bound(longer_fr)
{
debug!("check_universal_region: fr_minus={:?}", fr_minus);
// Grow `shorter_fr` until we find some non-local regions. (We
// always will.) We'll call them `shorter_fr+` -- they're ever
// so slightly larger than `shorter_fr`.
- let shorter_fr_plus = self.universal_region_relations
- .non_local_upper_bounds(&shorter_fr);
- debug!(
- "check_universal_region: shorter_fr_plus={:?}",
- shorter_fr_plus
- );
+ let shorter_fr_plus =
+ self.universal_region_relations.non_local_upper_bounds(&shorter_fr);
+ debug!("check_universal_region: shorter_fr_plus={:?}", shorter_fr_plus);
for &&fr in &shorter_fr_plus {
// Push the constraint `fr-: shorter_fr+`
propagated_outlives_requirements.push(ClosureOutlivesRequirement {
longer_fr: RegionVid,
placeholder: ty::PlaceholderRegion,
) {
- debug!(
- "check_bound_universal_region(fr={:?}, placeholder={:?})",
- longer_fr, placeholder,
- );
+ debug!("check_bound_universal_region(fr={:?}, placeholder={:?})", longer_fr, placeholder,);
let longer_fr_scc = self.constraint_sccs.scc(longer_fr);
- debug!(
- "check_bound_universal_region: longer_fr_scc={:?}",
- longer_fr_scc,
- );
+ debug!("check_bound_universal_region: longer_fr_scc={:?}", longer_fr_scc,);
// If we have some bound universal region `'a`, then the only
// elements it can contain is itself -- we don't know anything
// else about it!
let error_element = match {
- self.scc_values
- .elements_contained_in(longer_fr_scc)
- .find(|element| match element {
- RegionElement::Location(_) => true,
- RegionElement::RootUniversalRegion(_) => true,
- RegionElement::PlaceholderRegion(placeholder1) => placeholder != *placeholder1,
- })
+ self.scc_values.elements_contained_in(longer_fr_scc).find(|element| match element {
+ RegionElement::Location(_) => true,
+ RegionElement::RootUniversalRegion(_) => true,
+ RegionElement::PlaceholderRegion(placeholder1) => placeholder != *placeholder1,
+ })
} {
Some(v) => v,
None => return,
let error_region = match error_element {
RegionElement::Location(l) => self.find_sub_region_live_at(longer_fr, l),
RegionElement::RootUniversalRegion(r) => r,
- RegionElement::PlaceholderRegion(error_placeholder) => self.definitions
+ RegionElement::PlaceholderRegion(error_placeholder) => self
+ .definitions
.iter_enumerated()
.filter_map(|(r, definition)| match definition.origin {
NLLRegionVariableOrigin::Placeholder(p) if p == error_placeholder => Some(r),
// the AST-based checker uses a more conservative check,
// so to even see this error, one must pass in a special
// flag.
- let mut diag = infcx
- .tcx
- .sess
- .struct_span_err(span, "higher-ranked subtype error");
+ let mut diag = infcx.tcx.sess.struct_span_err(span, "higher-ranked subtype error");
diag.emit();
}
+
+ fn check_member_constraints(
+ &self,
+ infcx: &InferCtxt<'_, 'tcx>,
+ mir_def_id: DefId,
+ errors_buffer: &mut Vec<Diagnostic>,
+ ) {
+ let member_constraints = self.member_constraints.clone();
+ for m_c_i in member_constraints.all_indices() {
+ debug!("check_member_constraint(m_c_i={:?})", m_c_i);
+ let m_c = &member_constraints[m_c_i];
+ let member_region_vid = m_c.member_region_vid;
+ debug!(
+ "check_member_constraint: member_region_vid={:?} with value {}",
+ member_region_vid,
+ self.region_value_str(member_region_vid),
+ );
+ let choice_regions = member_constraints.choice_regions(m_c_i);
+ debug!("check_member_constraint: choice_regions={:?}", choice_regions);
+
+ // Did the member region wind up equal to any of the option regions?
+ if let Some(o) = choice_regions.iter().find(|&&o_r| {
+ self.eval_equal(o_r, m_c.member_region_vid)
+ }) {
+ debug!("check_member_constraint: evaluated as equal to {:?}", o);
+ continue;
+ }
+
+ // If not, report an error.
+ let region_scope_tree = &infcx.tcx.region_scope_tree(mir_def_id);
+ let member_region = infcx.tcx.mk_region(ty::ReVar(member_region_vid));
+ opaque_types::unexpected_hidden_region_diagnostic(
+ infcx.tcx,
+ Some(region_scope_tree),
+ m_c.opaque_type_def_id,
+ m_c.hidden_ty,
+ member_region,
+ )
+ .buffer(errors_buffer);
+ }
+ }
}
impl<'tcx> RegionDefinition<'tcx> {
_ => NLLRegionVariableOrigin::Existential,
};
- Self {
- origin,
- universe,
- external_name: None,
- }
+ Self { origin, universe, external_name: None }
}
}
tcx: TyCtxt<'tcx>,
closure_def_id: DefId,
closure_substs: SubstsRef<'tcx>,
- ) -> Vec<QueryRegionConstraint<'tcx>>;
+ ) -> Vec<QueryOutlivesConstraint<'tcx>>;
fn subst_closure_mapping<T>(
&self,
tcx: TyCtxt<'tcx>,
closure_def_id: DefId,
closure_substs: SubstsRef<'tcx>,
- ) -> Vec<QueryRegionConstraint<'tcx>> {
+ ) -> Vec<QueryOutlivesConstraint<'tcx>> {
debug!(
"apply_requirements(closure_def_id={:?}, closure_substs={:?})",
closure_def_id, closure_substs
if let ty::ReClosureBound(vid) = r {
closure_mapping[*vid]
} else {
- bug!(
- "subst_closure_mapping: encountered non-closure bound free region {:?}",
- r
- )
+ bug!("subst_closure_mapping: encountered non-closure bound free region {:?}", r)
}
})
}