Skip to content

Commit 0d12267

Browse files
committed
Skip NonUpvar closure generic in impl Trait regionck
1 parent bd582de commit 0d12267

File tree

2 files changed

+58
-12
lines changed

2 files changed

+58
-12
lines changed

src/librustc_typeck/check/regionck.rs

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,10 @@ use middle::region;
9191
use rustc::hir::def_id::DefId;
9292
use rustc::ty::subst::Substs;
9393
use rustc::traits;
94-
use rustc::ty::{self, Ty, TypeFoldable};
94+
use rustc::ty::{self, Binder, Region, Ty, TyCtxt, TypeFoldable};
9595
use rustc::infer::{self, GenericKind, SubregionOrigin, VerifyBound};
9696
use rustc::ty::adjustment;
97+
use rustc::ty::fold::TypeVisitor;
9798
use rustc::ty::outlives::Component;
9899
use rustc::ty::wf;
99100

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

534+
struct RegionExceptClosureNonUpvarVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a, F> {
535+
tcx: TyCtxt<'a, 'gcx, 'tcx>,
536+
current_depth: u32,
537+
f: F,
538+
}
539+
540+
impl<'a, 'gcx, 'tcx, F> TypeVisitor<'tcx> for
541+
RegionExceptClosureNonUpvarVisitor<'a, 'gcx, 'tcx, F>
542+
where F: FnMut(ty::Region<'tcx>)
543+
{
544+
fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &Binder<T>) -> bool {
545+
self.current_depth += 1;
546+
t.skip_binder().visit_with(self);
547+
self.current_depth -= 1;
548+
549+
false // keep visiting
550+
}
551+
552+
// Skip the non-upvar generics in closures-- we don't want to place bounds on those
553+
// because the closure can outlive them.
554+
fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
555+
if let ty::TypeVariants::TyClosure(def_id, ref closure_substs) = t.sty {
556+
// Only iterate over the upvar tys, skipping others
557+
for subst in closure_substs.upvar_tys(def_id, self.tcx) {
558+
subst.visit_with(self);
559+
}
560+
false // keep visiting
561+
} else {
562+
t.super_visit_with(self)
563+
}
564+
}
565+
566+
fn visit_region(&mut self, r: Region<'tcx>) -> bool {
567+
match *r {
568+
ty::ReLateBound(debruijn, _) if debruijn.depth < self.current_depth => {
569+
// ignore bound regions
570+
}
571+
_ => (self.f)(r),
572+
}
573+
574+
false // keep visiting
575+
}
576+
}
577+
533578
// Require that all regions outlive `least_region`
534-
self.tcx.for_each_free_region(&concrete_ty, |region| {
535-
self.sub_regions(infer::CallReturn(span), least_region, region);
536-
});
579+
let mut visitor = RegionExceptClosureNonUpvarVisitor {
580+
tcx: self.tcx,
581+
current_depth: 0,
582+
f: |region| self.sub_regions(infer::CallReturn(span), least_region, region),
583+
};
584+
concrete_ty.visit_with(&mut visitor);
537585
}
538586
}
539587

src/librustc_typeck/check/writeback.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use rustc::hir::def_id::{DefId, DefIndex};
1818
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
1919
use rustc::infer::{InferCtxt};
2020
use rustc::ty::{self, Ty, TyCtxt};
21-
use rustc::ty::fold::{TypeFolder,TypeFoldable};
21+
use rustc::ty::fold::{TypeFolder, TypeFoldable};
2222
use rustc::ty::subst::{Kind, Substs};
2323
use rustc::util::nodemap::{DefIdSet, FxHashMap};
2424
use syntax::ast;
@@ -297,7 +297,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
297297
// and remapping only those used in the `impl Trait` return type,
298298
// resulting in the parameters shifting.
299299
let id_substs = Substs::identity_for_item(gcx, def_id);
300-
let map: FxHashMap<Kind, Kind> =
300+
let map: FxHashMap<Kind<'tcx>, Kind<'gcx>> =
301301
anon_defn.substs
302302
.iter()
303303
.enumerate()
@@ -319,12 +319,10 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
319319
_ => if let Some(r1) =
320320
map.get(&Kind::from(r)).and_then(|k| k.as_region()) { r1 } else
321321
{
322-
let span = node_id.to_span(&self.fcx.tcx);
323-
self.tcx().sess.delay_span_bug(
324-
span,
325-
&format!("only named lifetimes are allowed in `impl Trait`, \
326-
but `{}` was found in the type `{}`",
327-
r, inside_ty));
322+
// No mapping was found. This means that it is either a
323+
// disallowed lifetime, which will be caught by regionck,
324+
// or it is a region in a non-upvar closure generic, which
325+
// is explicitly allowed.
328326
gcx.types.re_static
329327
},
330328
}

0 commit comments

Comments
 (0)