Skip to content

Commit

Permalink
universe transition
Browse files Browse the repository at this point in the history
Remove the leak-check and its associated machinery. Replace with
making the solver aware of universes.
  • Loading branch information
nikomatsakis committed Jan 2, 2019
1 parent eba2ae5 commit b68fad6
Show file tree
Hide file tree
Showing 10 changed files with 144 additions and 799 deletions.
507 changes: 30 additions & 477 deletions src/librustc/infer/higher_ranked/mod.rs

Large diffs are not rendered by default.

41 changes: 36 additions & 5 deletions src/librustc/infer/lexical_region_resolve/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,23 +215,41 @@ impl<'cx, 'gcx, 'tcx> LexicalResolver<'cx, 'gcx, 'tcx> {
) -> bool {
debug!("expand_node({:?}, {:?} == {:?})", a_region, b_vid, b_data);

// Check if this relationship is implied by a given.
match *a_region {
// Check if this relationship is implied by a given.
ty::ReEarlyBound(_) | ty::ReFree(_) => if self.data.givens.contains(&(a_region, b_vid))
{
debug!("given");
return false;
},

_ => {}
}


match *b_data {
VarValue::Value(cur_region) => {
let lub = self.lub_concrete_regions(a_region, cur_region);
let mut lub = self.lub_concrete_regions(a_region, cur_region);
if lub == cur_region {
return false;
}

// Watch out for `'b: !1` relationships, where the
// universe of `'b` can't name the placeholder `!1`. In
// that case, we have to grow `'b` to be `'static` for the
// relationship to hold. This is obviously a kind of sub-optimal
// choice -- in the future, when we incorporate a knowledge
// of the parameter environment, we might be able to find a
// tighter bound than `'static`.
//
// (This might e.g. arise from being asked to prove `for<'a> { 'b: 'a }`.)
let b_universe = self.var_infos[b_vid].universe;
if let ty::RePlaceholder(p) = lub {
if b_universe.cannot_name(p.universe) {
lub = self.tcx().types.re_static;
}
}

debug!(
"Expanding value of {:?} from {:?} to {:?}",
b_vid, cur_region, lub
Expand Down Expand Up @@ -554,10 +572,22 @@ impl<'cx, 'gcx, 'tcx> LexicalResolver<'cx, 'gcx, 'tcx> {
lower_bounds.sort_by_key(region_order_key);
upper_bounds.sort_by_key(region_order_key);

let node_universe = self.var_infos[node_idx].universe;

for lower_bound in &lower_bounds {
let effective_lower_bound = if let ty::RePlaceholder(p) = lower_bound.region {
if node_universe.cannot_name(p.universe) {
self.tcx().types.re_static
} else {
lower_bound.region
}
} else {
lower_bound.region
};

for upper_bound in &upper_bounds {
if !self.region_rels
.is_subregion_of(lower_bound.region, upper_bound.region)
.is_subregion_of(effective_lower_bound, upper_bound.region)
{
let origin = self.var_infos[node_idx].origin.clone();
debug!(
Expand All @@ -580,9 +610,10 @@ impl<'cx, 'gcx, 'tcx> LexicalResolver<'cx, 'gcx, 'tcx> {
span_bug!(
self.var_infos[node_idx].origin.span(),
"collect_error_for_expanding_node() could not find \
error for var {:?}, lower_bounds={:?}, \
upper_bounds={:?}",
error for var {:?} in universe {:?}, lower_bounds={:#?}, \
upper_bounds={:#?}",
node_idx,
node_universe,
lower_bounds,
upper_bounds
);
Expand Down
86 changes: 19 additions & 67 deletions src/librustc/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ use ty::{FloatVid, IntVid, TyVid};
use util::nodemap::FxHashMap;

use self::combine::CombineFields;
use self::higher_ranked::HrMatchResult;
use self::lexical_region_resolve::LexicalRegionResolutions;
use self::outlives::env::OutlivesEnvironment;
use self::region_constraints::{GenericKind, RegionConstraintData, VarInfos, VerifyBound};
Expand Down Expand Up @@ -948,39 +947,32 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
return None;
}

Some(self.commit_if_ok(|snapshot| {
let (
ty::SubtypePredicate {
a_is_expected,
a,
b,
},
placeholder_map,
) = self.replace_bound_vars_with_placeholders(predicate);
let (
ty::SubtypePredicate {
a_is_expected,
a,
b,
},
_,
) = self.replace_bound_vars_with_placeholders(predicate);

let cause_span = cause.span;
let ok = self.at(cause, param_env).sub_exp(a_is_expected, a, b)?;
self.leak_check(false, cause_span, &placeholder_map, snapshot)?;
self.pop_placeholders(placeholder_map, snapshot);
Ok(ok.unit())
}))
Some(
self.at(cause, param_env)
.sub_exp(a_is_expected, a, b)
.map(|ok| ok.unit()),
)
}

pub fn region_outlives_predicate(
&self,
cause: &traits::ObligationCause<'tcx>,
predicate: &ty::PolyRegionOutlivesPredicate<'tcx>,
) -> UnitResult<'tcx> {
self.commit_if_ok(|snapshot| {
let (ty::OutlivesPredicate(r_a, r_b), placeholder_map) =
self.replace_bound_vars_with_placeholders(predicate);
let origin = SubregionOrigin::from_obligation_cause(cause, || {
RelateRegionParamBound(cause.span)
});
self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b`
self.leak_check(false, cause.span, &placeholder_map, snapshot)?;
Ok(self.pop_placeholders(placeholder_map, snapshot))
})
) {
let (ty::OutlivesPredicate(r_a, r_b), _) =
self.replace_bound_vars_with_placeholders(predicate);
let origin =
SubregionOrigin::from_obligation_cause(cause, || RelateRegionParamBound(cause.span));
self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b`
}

pub fn next_ty_var_id(&self, diverging: bool, origin: TypeVariableOrigin) -> TyVid {
Expand Down Expand Up @@ -1389,46 +1381,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
self.tcx.replace_bound_vars(value, fld_r, fld_t)
}

/// Given a higher-ranked projection predicate like:
///
/// for<'a> <T as Fn<&'a u32>>::Output = &'a u32
///
/// and a target trait-ref like:
///
/// <T as Fn<&'x u32>>
///
/// find a substitution `S` for the higher-ranked regions (here,
/// `['a => 'x]`) such that the predicate matches the trait-ref,
/// and then return the value (here, `&'a u32`) but with the
/// substitution applied (hence, `&'x u32`).
///
/// See `higher_ranked_match` in `higher_ranked/mod.rs` for more
/// details.
pub fn match_poly_projection_predicate(
&self,
cause: ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
match_a: ty::PolyProjectionPredicate<'tcx>,
match_b: ty::TraitRef<'tcx>,
) -> InferResult<'tcx, HrMatchResult<Ty<'tcx>>> {
let match_pair = match_a.map_bound(|p| (p.projection_ty.trait_ref(self.tcx), p.ty));
let trace = TypeTrace {
cause,
values: TraitRefs(ExpectedFound::new(
true,
match_pair.skip_binder().0,
match_b,
)),
};

let mut combine = self.combine_fields(trace, param_env);
let result = combine.higher_ranked_match(&match_pair, &match_b, true)?;
Ok(InferOk {
value: result,
obligations: combine.obligations,
})
}

/// See `verify_generic_bound` method in `region_constraints`
pub fn verify_generic_bound(
&self,
Expand Down
31 changes: 0 additions & 31 deletions src/librustc/infer/region_constraints/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ use ty::{Region, RegionVid};
use std::collections::BTreeMap;
use std::{cmp, fmt, mem, u32};

mod taint;

#[derive(Default)]
pub struct RegionConstraintCollector<'tcx> {
/// For each `RegionVid`, the corresponding `RegionVariableOrigin`.
Expand Down Expand Up @@ -826,35 +824,6 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
.collect()
}

/// Computes all regions that have been related to `r0` since the
/// mark `mark` was made---`r0` itself will be the first
/// entry. The `directions` parameter controls what kind of
/// relations are considered. For example, one can say that only
/// "incoming" edges to `r0` are desired, in which case one will
/// get the set of regions `{r|r <= r0}`. This is used when
/// checking whether placeholder regions are being improperly
/// related to other regions.
pub fn tainted(
&self,
tcx: TyCtxt<'_, '_, 'tcx>,
mark: &RegionSnapshot,
r0: Region<'tcx>,
directions: TaintDirections,
) -> FxHashSet<ty::Region<'tcx>> {
debug!(
"tainted(mark={:?}, r0={:?}, directions={:?})",
mark, r0, directions
);

// `result_set` acts as a worklist: we explore all outgoing
// edges and add any new regions we find to result_set. This
// is not a terribly efficient implementation.
let mut taint_set = taint::TaintSet::new(directions, r0);
taint_set.fixed_point(tcx, &self.undo_log[mark.length..], &self.data.verifys);
debug!("tainted: result={:?}", taint_set);
return taint_set.into_set();
}

pub fn region_constraints_added_in_snapshot(&self, mark: &RegionSnapshot) -> bool {
self.undo_log[mark.length..]
.iter()
Expand Down
85 changes: 0 additions & 85 deletions src/librustc/infer/region_constraints/taint.rs

This file was deleted.

8 changes: 1 addition & 7 deletions src/librustc/traits/auto_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -771,13 +771,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
}
}
&ty::Predicate::RegionOutlives(ref binder) => {
if select
.infcx()
.region_outlives_predicate(&dummy_cause, binder)
.is_err()
{
return false;
}
let () = select.infcx().region_outlives_predicate(&dummy_cause, binder);
}
&ty::Predicate::TypeOutlives(ref binder) => {
match (
Expand Down
9 changes: 3 additions & 6 deletions src/librustc/traits/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -728,12 +728,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
}

ty::Predicate::RegionOutlives(ref predicate) => {
let predicate = self.resolve_type_vars_if_possible(predicate);
let err = self.region_outlives_predicate(&obligation.cause,
&predicate).err().unwrap();
struct_span_err!(self.tcx.sess, span, E0279,
"the requirement `{}` is not satisfied (`{}`)",
predicate, err)
// These errors should show up as region
// inference failures.
panic!("region outlives {:?} failed", predicate);
}

ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => {
Expand Down
6 changes: 2 additions & 4 deletions src/librustc/traits/fulfill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,10 +331,8 @@ impl<'a, 'b, 'gcx, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'gcx,
}

ty::Predicate::RegionOutlives(ref binder) => {
match self.selcx.infcx().region_outlives_predicate(&obligation.cause, binder) {
Ok(()) => ProcessResult::Changed(vec![]),
Err(_) => ProcessResult::Error(CodeSelectionError(Unimplemented)),
}
let () = self.selcx.infcx().region_outlives_predicate(&obligation.cause, binder);
ProcessResult::Changed(vec![])
}

ty::Predicate::TypeOutlives(ref binder) => {
Expand Down
Loading

0 comments on commit b68fad6

Please sign in to comment.