diff --git a/src/librustc/infer/lexical_region_resolve/mod.rs b/src/librustc/infer/lexical_region_resolve/mod.rs index 4b1f8a5be14..b0a9e0afa70 100644 --- a/src/librustc/infer/lexical_region_resolve/mod.rs +++ b/src/librustc/infer/lexical_region_resolve/mod.rs @@ -592,12 +592,6 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { debug!("collect_errors: verify={:?}", verify); let sub = var_data.normalize(self.tcx(), verify.region); - // This was an inference variable which didn't get - // constrained, therefore it can be assume to hold. - if let ty::ReEmpty = *sub { - continue; - } - let verify_kind_ty = verify.kind.to_ty(self.tcx()); if self.bound_is_met(&verify.bound, var_data, verify_kind_ty, sub) { continue; @@ -893,6 +887,14 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { self.region_rels.is_subregion_of(min, var_values.normalize(self.tcx(), r)) } + VerifyBound::IsEmpty => { + if let ty::ReEmpty = min { + true + } else { + false + } + } + VerifyBound::AnyBound(bs) => { bs.iter().any(|b| self.bound_is_met(b, var_values, generic_ty, min)) } diff --git a/src/librustc/infer/outlives/verify.rs b/src/librustc/infer/outlives/verify.rs index 8ee8482e79d..9d6c3f30aa7 100644 --- a/src/librustc/infer/outlives/verify.rs +++ b/src/librustc/infer/outlives/verify.rs @@ -60,7 +60,18 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { // scope type parameters: let param_bounds = param_bounds.chain(self.implicit_region_bound); - VerifyBound::AnyBound(param_bounds.map(|r| VerifyBound::OutlivedBy(r)).collect()) + let any_bounds: Vec<_> = param_bounds.map(|r| VerifyBound::OutlivedBy(r)).collect(); + + if any_bounds.is_empty() { + // We know that all types `T` outlive `'empty`, so if we + // can find no other bound, then check that the region + // being tested is `'empty`. + VerifyBound::IsEmpty + } else { + // If we can find any other bound R such that `T: R`, then + // we don't need to check for `'empty`, because `R: 'empty`. + VerifyBound::AnyBound(any_bounds) + } } /// Given a projection like `T::Item`, searches the environment diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs index 410058b70b5..667a4c3a7e2 100644 --- a/src/librustc/infer/region_constraints/mod.rs +++ b/src/librustc/infer/region_constraints/mod.rs @@ -233,6 +233,9 @@ pub enum VerifyBound<'tcx> { /// if `R: min`, then by transitivity `G: min`. OutlivedBy(Region<'tcx>), + /// Given a region `R`, true if it is `'empty`. + IsEmpty, + /// Given a set of bounds `B`, expands to the function: /// /// ```rust @@ -867,6 +870,7 @@ impl<'tcx> VerifyBound<'tcx> { VerifyBound::IfEq(..) => false, VerifyBound::OutlivedBy(ty::ReStatic) => true, VerifyBound::OutlivedBy(_) => false, + VerifyBound::IsEmpty => false, VerifyBound::AnyBound(bs) => bs.iter().any(|b| b.must_hold()), VerifyBound::AllBounds(bs) => bs.iter().all(|b| b.must_hold()), } @@ -875,7 +879,7 @@ impl<'tcx> VerifyBound<'tcx> { pub fn cannot_hold(&self) -> bool { match self { VerifyBound::IfEq(_, b) => b.cannot_hold(), - VerifyBound::OutlivedBy(ty::ReEmpty) => true, + VerifyBound::IsEmpty => false, VerifyBound::OutlivedBy(_) => false, VerifyBound::AnyBound(bs) => bs.iter().all(|b| b.cannot_hold()), VerifyBound::AllBounds(bs) => bs.iter().any(|b| b.cannot_hold()), diff --git a/src/librustc_mir/borrow_check/region_infer/mod.rs b/src/librustc_mir/borrow_check/region_infer/mod.rs index 26d9cf2e045..6abca481eac 100644 --- a/src/librustc_mir/borrow_check/region_infer/mod.rs +++ b/src/librustc_mir/borrow_check/region_infer/mod.rs @@ -1108,6 +1108,11 @@ impl<'tcx> RegionInferenceContext<'tcx> { self.eval_if_eq(tcx, body, generic_ty, lower_bound, test_ty, verify_bound1) } + VerifyBound::IsEmpty => { + let lower_bound_scc = self.constraint_sccs.scc(lower_bound); + self.scc_values.elements_contained_in(lower_bound_scc).next().is_none() + } + VerifyBound::OutlivedBy(r) => { let r_vid = self.to_region_vid(r); self.eval_outlives(r_vid, lower_bound)