Skip to content

Commit a9cbfaa

Browse files
committed
rewrite to use a custom folder
1 parent 75af15e commit a9cbfaa

File tree

1 file changed

+50
-42
lines changed
  • src/librustc/infer/anon_types

1 file changed

+50
-42
lines changed

src/librustc/infer/anon_types/mod.rs

Lines changed: 50 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ use infer::outlives::free_region_map::FreeRegionRelations;
1414
use rustc_data_structures::fx::FxHashMap;
1515
use syntax::ast;
1616
use traits::{self, PredicateObligation};
17-
use ty::{self, Ty};
18-
use ty::fold::{BottomUpFolder, TypeFoldable};
17+
use ty::{self, Ty, TyCtxt};
18+
use ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder};
1919
use ty::outlives::Component;
2020
use ty::subst::{Kind, UnpackedKind, Substs};
2121
use util::nodemap::DefIdMap;
@@ -458,55 +458,63 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
458458
// Convert the type from the function into a type valid outside
459459
// the function, by replacing invalid regions with 'static,
460460
// after producing an error for each of them.
461-
let definition_ty = gcx.fold_regions(&instantiated_ty, &mut false, |r, _| {
462-
match *r {
463-
// 'static and early-bound regions are valid.
464-
ty::ReStatic | ty::ReEmpty => r,
465-
466-
// All other regions, we map them appropriately to their adjusted
467-
// indices, erroring if we find any lifetimes that were not mapped
468-
// into the new set.
469-
_ => if let Some(UnpackedKind::Lifetime(r1)) = map.get(&r.into())
470-
.map(|k| k.unpack()) {
471-
r1
472-
} else {
473-
// No mapping was found. This means that
474-
// it is either a disallowed lifetime,
475-
// which will be caught by regionck, or it
476-
// is a region in a non-upvar closure
477-
// generic, which is explicitly
478-
// allowed. If that surprises you, read
479-
// on.
480-
//
481-
// The case of closure is a somewhat
482-
// subtle (read: hacky) consideration. The
483-
// problem is that our closure types
484-
// currently include all the lifetime
485-
// parameters declared on the enclosing
486-
// function, even if they are unused by
487-
// the closure itself. We can't readily
488-
// filter them out, so here we replace
489-
// those values with `'empty`. This can't
490-
// really make a difference to the rest of
491-
// the compiler; those regions are ignored
492-
// for the outlives relation, and hence
493-
// don't affect trait selection or auto
494-
// traits, and they are erased during
495-
// trans.
496-
gcx.types.re_empty
497-
},
498-
}
499-
});
500-
461+
let definition_ty = instantiated_ty.fold_with(&mut ReverseMapper { tcx: self.tcx, map });
501462
debug!(
502463
"infer_anon_definition_from_instantiation: definition_ty={:?}",
503464
definition_ty
504465
);
505466

467+
// We can unwrap here because our reverse mapper always
468+
// produces things with 'gcx lifetime, though the type folder
469+
// obscures that.
470+
let definition_ty = gcx.lift(&definition_ty).unwrap();
471+
506472
definition_ty
507473
}
508474
}
509475

476+
struct ReverseMapper<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
477+
tcx: TyCtxt<'cx, 'gcx, 'tcx>,
478+
map: FxHashMap<Kind<'tcx>, Kind<'gcx>>
479+
}
480+
481+
impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for ReverseMapper<'cx, 'gcx, 'tcx> {
482+
fn tcx(&self) -> TyCtxt<'_, 'gcx, 'tcx> {
483+
self.tcx
484+
}
485+
486+
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
487+
// ignore bound regions that appear in the type (e.g., this
488+
// would ignore `'r` in a type like `for<'r> fn(&'r u32)`.
489+
if let ty::ReLateBound(..) = *r {
490+
return r;
491+
}
492+
493+
match self.map.get(&r.into()).map(|k| k.unpack()) {
494+
Some(UnpackedKind::Lifetime(r1)) => r1,
495+
Some(u) => panic!("region mapped to unexpected kind: {:?}", u),
496+
None => {
497+
// No mapping was found. This means that it is either a
498+
// disallowed lifetime, which will be caught by regionck,
499+
// or it is a region in a non-upvar closure generic, which
500+
// is explicitly allowed. If that surprises you, read on.
501+
//
502+
// The case of closure is a somewhat subtle (read: hacky)
503+
// consideration. The problem is that our closure types
504+
// currently include all the lifetime parameters declared
505+
// on the enclosing function, even if they are unused by
506+
// the closure itself. We can't readily filter them out,
507+
// so here we replace those values with `'empty`. This
508+
// can't really make a difference to the rest of the
509+
// compiler; those regions are ignored for the outlives
510+
// relation, and hence don't affect trait selection or
511+
// auto traits, and they are erased during trans.
512+
self.tcx.types.re_empty
513+
}
514+
}
515+
}
516+
}
517+
510518
struct Instantiator<'a, 'gcx: 'tcx, 'tcx: 'a> {
511519
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
512520
parent_def_id: DefId,

0 commit comments

Comments
 (0)