Skip to content

Commit cdf5547

Browse files
committed
Shift both late bound regions and bound types
1 parent 1c8fb66 commit cdf5547

File tree

25 files changed

+163
-117
lines changed

25 files changed

+163
-117
lines changed

src/librustc/infer/outlives/obligations.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ where
305305
ty, region, origin
306306
);
307307

308-
assert!(!ty.has_escaping_regions());
308+
assert!(!ty.has_escaping_bound_vars());
309309

310310
let components = self.tcx.outlives_components(ty);
311311
self.components_must_outlive(origin, components, region);

src/librustc/infer/sub.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,8 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
8484
// Shouldn't have any LBR here, so we can safely put
8585
// this under a binder below without fear of accidental
8686
// capture.
87-
assert!(!a.has_escaping_regions());
88-
assert!(!b.has_escaping_regions());
87+
assert!(!a.has_escaping_bound_vars());
88+
assert!(!b.has_escaping_bound_vars());
8989

9090
// can't make progress on `A <: B` if both A and B are
9191
// type variables, so record an obligation. We also

src/librustc/traits/fulfill.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
145145
debug!("normalize_projection_type(projection_ty={:?})",
146146
projection_ty);
147147

148-
debug_assert!(!projection_ty.has_escaping_regions());
148+
debug_assert!(!projection_ty.has_escaping_bound_vars());
149149

150150
// FIXME(#20304) -- cache
151151

src/librustc/traits/project.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a,
366366

367367
let ty = ty.super_fold_with(self);
368368
match ty.sty {
369-
ty::Opaque(def_id, substs) if !substs.has_escaping_regions() => { // (*)
369+
ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => { // (*)
370370
// Only normalize `impl Trait` after type-checking, usually in codegen.
371371
match self.param_env.reveal {
372372
Reveal::UserFacing => ty,
@@ -393,7 +393,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a,
393393
}
394394
}
395395

396-
ty::Projection(ref data) if !data.has_escaping_regions() => { // (*)
396+
ty::Projection(ref data) if !data.has_escaping_bound_vars() => { // (*)
397397

398398
// (*) This is kind of hacky -- we need to be able to
399399
// handle normalization within binders because

src/librustc/traits/query/normalize.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx
100100
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
101101
let ty = ty.super_fold_with(self);
102102
match ty.sty {
103-
ty::Opaque(def_id, substs) if !substs.has_escaping_regions() => {
103+
ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => {
104104
// (*)
105105
// Only normalize `impl Trait` after type-checking, usually in codegen.
106106
match self.param_env.reveal {
@@ -138,7 +138,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx
138138
}
139139
}
140140

141-
ty::Projection(ref data) if !data.has_escaping_regions() => {
141+
ty::Projection(ref data) if !data.has_escaping_bound_vars() => {
142142
// (*)
143143
// (*) This is kind of hacky -- we need to be able to
144144
// handle normalization within binders because

src/librustc/traits/select.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -587,7 +587,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
587587
obligation: &TraitObligation<'tcx>,
588588
) -> SelectionResult<'tcx, Selection<'tcx>> {
589589
debug!("select({:?})", obligation);
590-
debug_assert!(!obligation.predicate.has_escaping_regions());
590+
debug_assert!(!obligation.predicate.has_escaping_bound_vars());
591591

592592
let stack = self.push_stack(TraitObligationStackList::empty(), obligation);
593593

@@ -690,7 +690,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
690690

691691
match obligation.predicate {
692692
ty::Predicate::Trait(ref t) => {
693-
debug_assert!(!t.has_escaping_regions());
693+
debug_assert!(!t.has_escaping_bound_vars());
694694
let obligation = obligation.with(t.clone());
695695
self.evaluate_trait_predicate_recursively(previous_stack, obligation)
696696
}
@@ -722,9 +722,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
722722
},
723723

724724
ty::Predicate::TypeOutlives(ref binder) => {
725-
assert!(!binder.has_escaping_regions());
726-
// Check if the type has higher-ranked regions.
727-
if binder.skip_binder().0.has_escaping_regions() {
725+
assert!(!binder.has_escaping_bound_vars());
726+
// Check if the type has higher-ranked vars.
727+
if binder.skip_binder().0.has_escaping_bound_vars() {
728728
// If so, this obligation is an error (for now). Eventually we should be
729729
// able to support additional cases here, like `for<'a> &'a str: 'a`.
730730

@@ -740,7 +740,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
740740
Ok(EvaluatedToErr)
741741
}
742742
} else {
743-
// If the type has no late bound regions, then if we assign all
743+
// If the type has no late bound vars, then if we assign all
744744
// the inference variables in it to be 'static, then the type
745745
// will be 'static itself.
746746
//
@@ -1199,7 +1199,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
11991199
"candidate_from_obligation(cache_fresh_trait_pred={:?}, obligation={:?})",
12001200
cache_fresh_trait_pred, stack
12011201
);
1202-
debug_assert!(!stack.obligation.predicate.has_escaping_regions());
1202+
debug_assert!(!stack.obligation.predicate.has_escaping_bound_vars());
12031203

12041204
if let Some(c) =
12051205
self.check_candidate_cache(stack.obligation.param_env, &cache_fresh_trait_pred)
@@ -1765,7 +1765,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
17651765
placeholder_map: &infer::PlaceholderMap<'tcx>,
17661766
snapshot: &infer::CombinedSnapshot<'cx, 'tcx>,
17671767
) -> bool {
1768-
debug_assert!(!skol_trait_ref.has_escaping_regions());
1768+
debug_assert!(!skol_trait_ref.has_escaping_bound_vars());
17691769
if self.infcx
17701770
.at(&obligation.cause, obligation.param_env)
17711771
.sup(ty::Binder::dummy(skol_trait_ref), trait_bound)

src/librustc/ty/flags.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,10 @@ impl FlagComputation {
115115
self.add_substs(&substs.substs);
116116
}
117117

118-
&ty::Bound(_) => self.add_flags(TypeFlags::HAS_CANONICAL_VARS),
118+
&ty::Bound(bound_ty) => {
119+
self.add_flags(TypeFlags::HAS_CANONICAL_VARS);
120+
self.add_binder(bound_ty.level);
121+
}
119122

120123
&ty::Infer(infer) => {
121124
self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES); // it might, right?
@@ -142,7 +145,7 @@ impl FlagComputation {
142145
&ty::Projection(ref data) => {
143146
// currently we can't normalize projections that
144147
// include bound regions, so track those separately.
145-
if !data.has_escaping_regions() {
148+
if !data.has_escaping_bound_vars() {
146149
self.add_flags(TypeFlags::HAS_NORMALIZABLE_PROJECTION);
147150
}
148151
self.add_flags(TypeFlags::HAS_PROJECTION);

src/librustc/ty/fold.rs

Lines changed: 89 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -67,18 +67,18 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
6767
/// bound by `binder` or bound by some binder outside of `binder`.
6868
/// If `binder` is `ty::INNERMOST`, this indicates whether
6969
/// there are any late-bound regions that appear free.
70-
fn has_regions_bound_at_or_above(&self, binder: ty::DebruijnIndex) -> bool {
71-
self.visit_with(&mut HasEscapingRegionsVisitor { outer_index: binder })
70+
fn has_vars_bound_at_or_above(&self, binder: ty::DebruijnIndex) -> bool {
71+
self.visit_with(&mut HasEscapingVarsVisitor { outer_index: binder })
7272
}
7373

7474
/// True if this `self` has any regions that escape `binder` (and
7575
/// hence are not bound by it).
76-
fn has_regions_bound_above(&self, binder: ty::DebruijnIndex) -> bool {
77-
self.has_regions_bound_at_or_above(binder.shifted_in(1))
76+
fn has_vars_bound_above(&self, binder: ty::DebruijnIndex) -> bool {
77+
self.has_vars_bound_at_or_above(binder.shifted_in(1))
7878
}
7979

80-
fn has_escaping_regions(&self) -> bool {
81-
self.has_regions_bound_at_or_above(ty::INNERMOST)
80+
fn has_escaping_bound_vars(&self) -> bool {
81+
self.has_vars_bound_at_or_above(ty::INNERMOST)
8282
}
8383

8484
fn has_type_flags(&self, flags: TypeFlags) -> bool {
@@ -574,7 +574,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionReplacer<'a, 'gcx, 'tcx> {
574574
}
575575

576576
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
577-
if !t.has_regions_bound_at_or_above(self.current_index) {
577+
if !t.has_vars_bound_at_or_above(self.current_index) {
578578
return t;
579579
}
580580

@@ -603,55 +603,99 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionReplacer<'a, 'gcx, 'tcx> {
603603
}
604604

605605
///////////////////////////////////////////////////////////////////////////
606-
// Region shifter
606+
// Shifter
607607
//
608-
// Shifts the De Bruijn indices on all escaping bound regions by a
608+
// Shifts the De Bruijn indices on all escaping bound vars by a
609609
// fixed amount. Useful in substitution or when otherwise introducing
610610
// a binding level that is not intended to capture the existing bound
611-
// regions. See comment on `shift_regions_through_binders` method in
611+
// vars. See comment on `shift_vars_through_binders` method in
612612
// `subst.rs` for more details.
613613

614-
pub fn shift_region(region: ty::RegionKind, amount: u32) -> ty::RegionKind {
615-
match region {
616-
ty::ReLateBound(debruijn, br) => {
617-
ty::ReLateBound(debruijn.shifted_in(amount), br)
614+
struct Shifter<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
615+
tcx: TyCtxt<'a, 'gcx, 'tcx>,
616+
617+
current_index: ty::DebruijnIndex,
618+
amount: u32,
619+
}
620+
621+
impl Shifter<'a, 'gcx, 'tcx> {
622+
pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, amount: u32) -> Self {
623+
Shifter {
624+
tcx,
625+
current_index: ty::INNERMOST,
626+
amount,
618627
}
619-
_ => {
620-
region
628+
}
629+
}
630+
631+
impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Shifter<'a, 'gcx, 'tcx> {
632+
fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx }
633+
634+
fn fold_binder<T: TypeFoldable<'tcx>>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T> {
635+
self.current_index.shift_in(1);
636+
let t = t.super_fold_with(self);
637+
self.current_index.shift_out(1);
638+
t
639+
}
640+
641+
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
642+
match *r {
643+
ty::ReLateBound(debruijn, br) => {
644+
if self.amount == 0 || debruijn < self.current_index {
645+
r
646+
} else {
647+
let shifted = ty::ReLateBound(debruijn.shifted_in(self.amount), br);
648+
self.tcx.mk_region(shifted)
649+
}
650+
}
651+
_ => r
652+
}
653+
}
654+
655+
fn fold_ty(&mut self, ty: ty::Ty<'tcx>) -> ty::Ty<'tcx> {
656+
match ty.sty {
657+
ty::Bound(bound_ty) => {
658+
if self.amount == 0 || bound_ty.level < self.current_index {
659+
ty
660+
} else {
661+
let shifted = ty::BoundTy {
662+
level: bound_ty.level.shifted_in(self.amount),
663+
var: bound_ty.var,
664+
kind: bound_ty.kind,
665+
};
666+
self.tcx.mk_ty(ty::Bound(shifted))
667+
}
668+
}
669+
670+
_ => ty.super_fold_with(self),
621671
}
622672
}
623673
}
624674

625-
pub fn shift_region_ref<'a, 'gcx, 'tcx>(
626-
tcx: TyCtxt<'a, 'gcx, 'tcx>,
627-
region: ty::Region<'tcx>,
628-
amount: u32)
629-
-> ty::Region<'tcx>
630-
{
675+
pub fn shift_region(region: ty::RegionKind, amount: u32) -> ty::RegionKind {
631676
match region {
632-
&ty::ReLateBound(debruijn, br) if amount > 0 => {
633-
tcx.mk_region(ty::ReLateBound(debruijn.shifted_in(amount), br))
677+
ty::ReLateBound(debruijn, br) => {
678+
ty::ReLateBound(debruijn.shifted_in(amount), br)
634679
}
635680
_ => {
636681
region
637682
}
638683
}
639684
}
640685

641-
pub fn shift_regions<'a, 'gcx, 'tcx, T>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
642-
amount: u32,
643-
value: &T) -> T
644-
where T: TypeFoldable<'tcx>
645-
{
646-
debug!("shift_regions(value={:?}, amount={})",
686+
pub fn shift_vars<'a, 'gcx, 'tcx, T>(
687+
tcx: TyCtxt<'a, 'gcx, 'tcx>,
688+
amount: u32,
689+
value: &T
690+
) -> T where T: TypeFoldable<'tcx> {
691+
debug!("shift_vars(value={:?}, amount={})",
647692
value, amount);
648693

649-
value.fold_with(&mut RegionFolder::new(tcx, &mut false, &mut |region, _current_depth| {
650-
shift_region_ref(tcx, region, amount)
651-
}))
694+
value.fold_with(&mut Shifter::new(tcx, amount))
652695
}
653696

654-
/// An "escaping region" is a bound region whose binder is not part of `t`.
697+
/// An "escaping var" is a bound var whose binder is not part of `t`. A bound var can be a
698+
/// bound region or a bound type.
655699
///
656700
/// So, for example, consider a type like the following, which has two binders:
657701
///
@@ -663,24 +707,24 @@ pub fn shift_regions<'a, 'gcx, 'tcx, T>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
663707
/// binders of both `'a` and `'b` are part of the type itself. However, if we consider the *inner
664708
/// fn type*, that type has an escaping region: `'a`.
665709
///
666-
/// Note that what I'm calling an "escaping region" is often just called a "free region". However,
667-
/// we already use the term "free region". It refers to the regions that we use to represent bound
668-
/// regions on a fn definition while we are typechecking its body.
710+
/// Note that what I'm calling an "escaping var" is often just called a "free var". However,
711+
/// we already use the term "free var". It refers to the regions or types that we use to represent
712+
/// bound regions or type params on a fn definition while we are typechecking its body.
669713
///
670714
/// To clarify, conceptually there is no particular difference between
671-
/// an "escaping" region and a "free" region. However, there is a big
715+
/// an "escaping" var and a "free" var. However, there is a big
672716
/// difference in practice. Basically, when "entering" a binding
673717
/// level, one is generally required to do some sort of processing to
674-
/// a bound region, such as replacing it with a fresh/placeholder
675-
/// region, or making an entry in the environment to represent the
676-
/// scope to which it is attached, etc. An escaping region represents
677-
/// a bound region for which this processing has not yet been done.
678-
struct HasEscapingRegionsVisitor {
718+
/// a bound var, such as replacing it with a fresh/placeholder
719+
/// var, or making an entry in the environment to represent the
720+
/// scope to which it is attached, etc. An escaping var represents
721+
/// a bound var for which this processing has not yet been done.
722+
struct HasEscapingVarsVisitor {
679723
/// Anything bound by `outer_index` or "above" is escaping
680724
outer_index: ty::DebruijnIndex,
681725
}
682726

683-
impl<'tcx> TypeVisitor<'tcx> for HasEscapingRegionsVisitor {
727+
impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor {
684728
fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &Binder<T>) -> bool {
685729
self.outer_index.shift_in(1);
686730
let result = t.super_visit_with(self);
@@ -693,7 +737,7 @@ impl<'tcx> TypeVisitor<'tcx> for HasEscapingRegionsVisitor {
693737
// `outer_index`, that means that `t` contains some content
694738
// bound at `outer_index` or above (because
695739
// `outer_exclusive_binder` is always 1 higher than the
696-
// content in `t`). Therefore, `t` has some escaping regions.
740+
// content in `t`). Therefore, `t` has some escaping vars.
697741
t.outer_exclusive_binder > self.outer_index
698742
}
699743

src/librustc/ty/instance.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ impl<'tcx> fmt::Display for Instance<'tcx> {
145145
impl<'a, 'b, 'tcx> Instance<'tcx> {
146146
pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>)
147147
-> Instance<'tcx> {
148-
assert!(!substs.has_escaping_regions(),
148+
assert!(!substs.has_escaping_bound_vars(),
149149
"substs of instance {:?} not normalized for codegen: {:?}",
150150
def_id, substs);
151151
Instance { def: InstanceDef::Item(def_id), substs: substs }

src/librustc/ty/outlives.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
106106
// we simply fallback to the most restrictive rule, which
107107
// requires that `Pi: 'a` for all `i`.
108108
ty::Projection(ref data) => {
109-
if !data.has_escaping_regions() {
109+
if !data.has_escaping_bound_vars() {
110110
// best case: no escaping regions, so push the
111111
// projection and skip the subtree (thus generating no
112112
// constraints for Pi). This defers the choice between

0 commit comments

Comments
 (0)