Skip to content

Commit

Permalink
Skip NonUpvar closure generic in impl Trait regionck
Browse files Browse the repository at this point in the history
  • Loading branch information
cramertj committed Nov 10, 2017
1 parent bd582de commit 0d12267
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 12 deletions.
56 changes: 52 additions & 4 deletions src/librustc_typeck/check/regionck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,10 @@ use middle::region;
use rustc::hir::def_id::DefId;
use rustc::ty::subst::Substs;
use rustc::traits;
use rustc::ty::{self, Ty, TypeFoldable};
use rustc::ty::{self, Binder, Region, Ty, TyCtxt, TypeFoldable};
use rustc::infer::{self, GenericKind, SubregionOrigin, VerifyBound};
use rustc::ty::adjustment;
use rustc::ty::fold::TypeVisitor;
use rustc::ty::outlives::Component;
use rustc::ty::wf;

Expand Down Expand Up @@ -530,10 +531,57 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
let least_region = least_region.unwrap_or(self.tcx.types.re_static);
debug!("constrain_anon_types: least_region={:?}", least_region);

struct RegionExceptClosureNonUpvarVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a, F> {
tcx: TyCtxt<'a, 'gcx, 'tcx>,
current_depth: u32,
f: F,
}

impl<'a, 'gcx, 'tcx, F> TypeVisitor<'tcx> for
RegionExceptClosureNonUpvarVisitor<'a, 'gcx, 'tcx, F>
where F: FnMut(ty::Region<'tcx>)
{
fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &Binder<T>) -> bool {
self.current_depth += 1;
t.skip_binder().visit_with(self);
self.current_depth -= 1;

false // keep visiting
}

// Skip the non-upvar generics in closures-- we don't want to place bounds on those
// because the closure can outlive them.
fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
if let ty::TypeVariants::TyClosure(def_id, ref closure_substs) = t.sty {
// Only iterate over the upvar tys, skipping others
for subst in closure_substs.upvar_tys(def_id, self.tcx) {
subst.visit_with(self);
}
false // keep visiting
} else {
t.super_visit_with(self)
}
}

fn visit_region(&mut self, r: Region<'tcx>) -> bool {
match *r {
ty::ReLateBound(debruijn, _) if debruijn.depth < self.current_depth => {
// ignore bound regions
}
_ => (self.f)(r),
}

false // keep visiting
}
}

// Require that all regions outlive `least_region`
self.tcx.for_each_free_region(&concrete_ty, |region| {
self.sub_regions(infer::CallReturn(span), least_region, region);
});
let mut visitor = RegionExceptClosureNonUpvarVisitor {
tcx: self.tcx,
current_depth: 0,
f: |region| self.sub_regions(infer::CallReturn(span), least_region, region),
};
concrete_ty.visit_with(&mut visitor);
}
}

Expand Down
14 changes: 6 additions & 8 deletions src/librustc_typeck/check/writeback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use rustc::hir::def_id::{DefId, DefIndex};
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
use rustc::infer::{InferCtxt};
use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::fold::{TypeFolder,TypeFoldable};
use rustc::ty::fold::{TypeFolder, TypeFoldable};
use rustc::ty::subst::{Kind, Substs};
use rustc::util::nodemap::{DefIdSet, FxHashMap};
use syntax::ast;
Expand Down Expand Up @@ -297,7 +297,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
// and remapping only those used in the `impl Trait` return type,
// resulting in the parameters shifting.
let id_substs = Substs::identity_for_item(gcx, def_id);
let map: FxHashMap<Kind, Kind> =
let map: FxHashMap<Kind<'tcx>, Kind<'gcx>> =
anon_defn.substs
.iter()
.enumerate()
Expand All @@ -319,12 +319,10 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
_ => if let Some(r1) =
map.get(&Kind::from(r)).and_then(|k| k.as_region()) { r1 } else
{
let span = node_id.to_span(&self.fcx.tcx);
self.tcx().sess.delay_span_bug(
span,
&format!("only named lifetimes are allowed in `impl Trait`, \
but `{}` was found in the type `{}`",
r, inside_ty));
// No mapping was found. This means that it is either a
// disallowed lifetime, which will be caught by regionck,
// or it is a region in a non-upvar closure generic, which
// is explicitly allowed.
gcx.types.re_static
},
}
Expand Down

0 comments on commit 0d12267

Please sign in to comment.