Skip to content

Commit 30187c8

Browse files
committed
Track bound vars
1 parent 62a49c3 commit 30187c8

File tree

33 files changed

+479
-363
lines changed

33 files changed

+479
-363
lines changed

compiler/rustc_hir/src/hir.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -314,12 +314,12 @@ pub struct GenericArgs<'hir> {
314314
pub parenthesized: bool,
315315
}
316316

317-
impl GenericArgs<'_> {
317+
impl<'tcx> GenericArgs<'tcx> {
318318
pub const fn none() -> Self {
319319
Self { args: &[], bindings: &[], parenthesized: false }
320320
}
321321

322-
pub fn inputs(&self) -> &[Ty<'_>] {
322+
pub fn inputs(&self) -> &[Ty<'tcx>] {
323323
if self.parenthesized {
324324
for arg in self.args {
325325
match arg {

compiler/rustc_middle/src/ich/impls_ty.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ where
124124
{
125125
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
126126
self.as_ref().skip_binder().hash_stable(hcx, hasher);
127+
self.bound_vars().hash_stable(hcx, hasher);
127128
}
128129
}
129130

compiler/rustc_middle/src/ty/codec.rs

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for Ty<'tcx> {
122122

123123
impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::Binder<'tcx, ty::PredicateKind<'tcx>> {
124124
fn encode(&self, e: &mut E) -> Result<(), E::Error> {
125+
self.bound_vars().encode(e)?;
125126
encode_with_shorthand(e, &self.skip_binder(), TyEncoder::predicate_shorthands)
126127
}
127128
}
@@ -228,16 +229,20 @@ impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for Ty<'tcx> {
228229

229230
impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Binder<'tcx, ty::PredicateKind<'tcx>> {
230231
fn decode(decoder: &mut D) -> Result<ty::Binder<'tcx, ty::PredicateKind<'tcx>>, D::Error> {
232+
let bound_vars = Decodable::decode(decoder)?;
231233
// Handle shorthands first, if we have an usize > 0x80.
232-
Ok(ty::Binder::bind(if decoder.positioned_at_shorthand() {
233-
let pos = decoder.read_usize()?;
234-
assert!(pos >= SHORTHAND_OFFSET);
235-
let shorthand = pos - SHORTHAND_OFFSET;
236-
237-
decoder.with_position(shorthand, ty::PredicateKind::decode)?
238-
} else {
239-
ty::PredicateKind::decode(decoder)?
240-
}))
234+
Ok(ty::Binder::bind_with_vars(
235+
if decoder.positioned_at_shorthand() {
236+
let pos = decoder.read_usize()?;
237+
assert!(pos >= SHORTHAND_OFFSET);
238+
let shorthand = pos - SHORTHAND_OFFSET;
239+
240+
decoder.with_position(shorthand, ty::PredicateKind::decode)?
241+
} else {
242+
ty::PredicateKind::decode(decoder)?
243+
},
244+
bound_vars,
245+
))
241246
}
242247
}
243248

@@ -379,6 +384,13 @@ impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [mir::abstract_const::N
379384
}
380385
}
381386

387+
impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List<ty::BoundVariableKind> {
388+
fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> {
389+
let len = decoder.read_usize()?;
390+
Ok(decoder.tcx().mk_bound_variable_kinds((0..len).map(|_| Decodable::decode(decoder)))?)
391+
}
392+
}
393+
382394
impl_decodable_via_ref! {
383395
&'tcx ty::TypeckResults<'tcx>,
384396
&'tcx ty::List<Ty<'tcx>>,
@@ -387,7 +399,8 @@ impl_decodable_via_ref! {
387399
&'tcx mir::Body<'tcx>,
388400
&'tcx mir::UnsafetyCheckResult,
389401
&'tcx mir::BorrowCheckResult<'tcx>,
390-
&'tcx mir::coverage::CodeRegion
402+
&'tcx mir::coverage::CodeRegion,
403+
&'tcx ty::List<ty::BoundVariableKind>
391404
}
392405

393406
#[macro_export]
@@ -490,12 +503,14 @@ macro_rules! impl_binder_encode_decode {
490503
$(
491504
impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::Binder<'tcx, $t> {
492505
fn encode(&self, e: &mut E) -> Result<(), E::Error> {
506+
self.bound_vars().encode(e)?;
493507
self.as_ref().skip_binder().encode(e)
494508
}
495509
}
496510
impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Binder<'tcx, $t> {
497511
fn decode(decoder: &mut D) -> Result<Self, D::Error> {
498-
Ok(ty::Binder::bind(Decodable::decode(decoder)?))
512+
let bound_vars = Decodable::decode(decoder)?;
513+
Ok(ty::Binder::bind_with_vars(Decodable::decode(decoder)?, bound_vars))
499514
}
500515
}
501516
)*

compiler/rustc_middle/src/ty/context.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ pub struct CtxtInterners<'tcx> {
9696
const_: InternedSet<'tcx, Const<'tcx>>,
9797
/// Const allocations.
9898
allocation: InternedSet<'tcx, Allocation>,
99+
bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>,
99100
}
100101

101102
impl<'tcx> CtxtInterners<'tcx> {
@@ -114,6 +115,7 @@ impl<'tcx> CtxtInterners<'tcx> {
114115
place_elems: Default::default(),
115116
const_: Default::default(),
116117
allocation: Default::default(),
118+
bound_variable_kinds: Default::default(),
117119
}
118120
}
119121

@@ -1624,6 +1626,7 @@ nop_list_lift! {poly_existential_predicates; ty::Binder<'a, ExistentialPredicate
16241626
nop_list_lift! {predicates; Predicate<'a> => Predicate<'tcx>}
16251627
nop_list_lift! {canonical_var_infos; CanonicalVarInfo<'a> => CanonicalVarInfo<'tcx>}
16261628
nop_list_lift! {projs; ProjectionKind => ProjectionKind}
1629+
nop_list_lift! {bound_variable_kinds; ty::BoundVariableKind => ty::BoundVariableKind}
16271630

16281631
// This is the impl for `&'a InternalSubsts<'a>`.
16291632
nop_list_lift! {substs; GenericArg<'a> => GenericArg<'tcx>}
@@ -2080,6 +2083,7 @@ slice_interners!(
20802083
predicates: _intern_predicates(Predicate<'tcx>),
20812084
projs: _intern_projs(ProjectionKind),
20822085
place_elems: _intern_place_elems(PlaceElem<'tcx>),
2086+
bound_variable_kinds: _intern_bound_variable_kinds(ty::BoundVariableKind),
20832087
);
20842088

20852089
impl<'tcx> TyCtxt<'tcx> {
@@ -2516,6 +2520,13 @@ impl<'tcx> TyCtxt<'tcx> {
25162520
if ts.is_empty() { List::empty() } else { self._intern_canonical_var_infos(ts) }
25172521
}
25182522

2523+
pub fn intern_bound_variable_kinds(
2524+
self,
2525+
ts: &[ty::BoundVariableKind],
2526+
) -> &'tcx List<ty::BoundVariableKind> {
2527+
if ts.is_empty() { List::empty() } else { self._intern_bound_variable_kinds(ts) }
2528+
}
2529+
25192530
pub fn mk_fn_sig<I>(
25202531
self,
25212532
inputs: I,
@@ -2576,6 +2587,15 @@ impl<'tcx> TyCtxt<'tcx> {
25762587
self.mk_substs(iter::once(self_ty.into()).chain(rest.iter().cloned()))
25772588
}
25782589

2590+
pub fn mk_bound_variable_kinds<
2591+
I: InternAs<[ty::BoundVariableKind], &'tcx List<ty::BoundVariableKind>>,
2592+
>(
2593+
self,
2594+
iter: I,
2595+
) -> I::Output {
2596+
iter.intern_with(|xs| self.intern_bound_variable_kinds(xs))
2597+
}
2598+
25792599
/// Walks upwards from `id` to find a node which might change lint levels with attributes.
25802600
/// It stops at `bound` and just returns it if reached.
25812601
pub fn maybe_lint_level_root_bounded(self, mut id: HirId, bound: HirId) -> HirId {

compiler/rustc_middle/src/ty/fold.rs

Lines changed: 100 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ use rustc_hir as hir;
3535
use rustc_hir::def_id::DefId;
3636

3737
use rustc_data_structures::fx::FxHashSet;
38+
use rustc_data_structures::sso::SsoHashSet;
3839
use std::collections::BTreeMap;
3940
use std::fmt;
4041
use std::ops::ControlFlow;
@@ -702,10 +703,109 @@ impl<'tcx> TyCtxt<'tcx> {
702703
r
703704
})
704705
.0,
706+
self,
705707
)
706708
}
707709
}
708710

711+
pub struct BoundVarsCollector<'tcx> {
712+
binder_index: ty::DebruijnIndex,
713+
vars: BTreeMap<u32, ty::BoundVariableKind>,
714+
// We may encounter the same variable at different levels of binding, so
715+
// this can't just be `Ty`
716+
visited: SsoHashSet<(ty::DebruijnIndex, Ty<'tcx>)>,
717+
}
718+
719+
impl<'tcx> BoundVarsCollector<'tcx> {
720+
pub fn new() -> Self {
721+
BoundVarsCollector {
722+
binder_index: ty::INNERMOST,
723+
vars: BTreeMap::new(),
724+
visited: SsoHashSet::default(),
725+
}
726+
}
727+
728+
pub fn into_vars(self, tcx: TyCtxt<'tcx>) -> &'tcx ty::List<ty::BoundVariableKind> {
729+
let max = self.vars.iter().map(|(k, _)| *k).max().unwrap_or_else(|| 0);
730+
for i in 0..max {
731+
if let None = self.vars.get(&i) {
732+
panic!("Unknown variable: {:?}", i);
733+
}
734+
}
735+
736+
tcx.mk_bound_variable_kinds(self.vars.into_iter().map(|(_, v)| v))
737+
}
738+
}
739+
740+
impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> {
741+
type BreakTy = ();
742+
743+
fn visit_binder<T: TypeFoldable<'tcx>>(
744+
&mut self,
745+
t: &Binder<'tcx, T>,
746+
) -> ControlFlow<Self::BreakTy> {
747+
self.binder_index.shift_in(1);
748+
let result = t.super_visit_with(self);
749+
self.binder_index.shift_out(1);
750+
result
751+
}
752+
753+
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
754+
if t.outer_exclusive_binder < self.binder_index
755+
|| !self.visited.insert((self.binder_index, t))
756+
{
757+
return ControlFlow::CONTINUE;
758+
}
759+
use std::collections::btree_map::Entry;
760+
match *t.kind() {
761+
ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => {
762+
match self.vars.entry(bound_ty.var.as_u32()) {
763+
Entry::Vacant(entry) => {
764+
entry.insert(ty::BoundVariableKind::Ty(bound_ty.kind));
765+
}
766+
Entry::Occupied(entry) => match entry.get() {
767+
ty::BoundVariableKind::Ty(_) => {}
768+
_ => bug!("Conflicting bound vars"),
769+
},
770+
}
771+
}
772+
773+
_ => (),
774+
};
775+
776+
t.super_visit_with(self)
777+
}
778+
779+
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
780+
use std::collections::btree_map::Entry;
781+
match r {
782+
ty::ReLateBound(index, br) if *index == self.binder_index => match br.kind {
783+
ty::BrNamed(_def_id, _name) => {
784+
// FIXME
785+
}
786+
787+
ty::BrAnon(var) => match self.vars.entry(var) {
788+
Entry::Vacant(entry) => {
789+
entry.insert(ty::BoundVariableKind::Region(br.kind));
790+
}
791+
Entry::Occupied(entry) => match entry.get() {
792+
ty::BoundVariableKind::Region(_) => {}
793+
_ => bug!("Conflicting bound vars"),
794+
},
795+
},
796+
797+
ty::BrEnv => {
798+
// FIXME
799+
}
800+
},
801+
802+
_ => (),
803+
};
804+
805+
r.super_visit_with(self)
806+
}
807+
}
808+
709809
///////////////////////////////////////////////////////////////////////////
710810
// Shifter
711811
//
@@ -907,57 +1007,6 @@ impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor {
9071007
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
9081008
struct FoundFlags;
9091009

910-
crate struct CountBoundVars {
911-
crate outer_index: ty::DebruijnIndex,
912-
crate bound_tys: FxHashSet<ty::BoundTy>,
913-
crate bound_regions: FxHashSet<ty::BoundRegion>,
914-
crate bound_consts: FxHashSet<ty::BoundVar>,
915-
}
916-
917-
impl<'tcx> TypeVisitor<'tcx> for CountBoundVars {
918-
type BreakTy = ();
919-
920-
fn visit_binder<T: TypeFoldable<'tcx>>(
921-
&mut self,
922-
t: &Binder<'tcx, T>,
923-
) -> ControlFlow<Self::BreakTy> {
924-
self.outer_index.shift_in(1);
925-
let result = t.super_visit_with(self);
926-
self.outer_index.shift_out(1);
927-
result
928-
}
929-
930-
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
931-
match t.kind {
932-
ty::Bound(debruijn, ty) if debruijn == self.outer_index => {
933-
self.bound_tys.insert(ty);
934-
ControlFlow::CONTINUE
935-
}
936-
_ => t.super_visit_with(self),
937-
}
938-
}
939-
940-
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
941-
match r {
942-
ty::ReLateBound(debruijn, re) if *debruijn == self.outer_index => {
943-
self.bound_regions.insert(*re);
944-
ControlFlow::CONTINUE
945-
}
946-
_ => r.super_visit_with(self),
947-
}
948-
}
949-
950-
fn visit_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
951-
match ct.val {
952-
ty::ConstKind::Bound(debruijn, c) if debruijn == self.outer_index => {
953-
self.bound_consts.insert(c);
954-
ControlFlow::CONTINUE
955-
}
956-
_ => ct.super_visit_with(self),
957-
}
958-
}
959-
}
960-
9611010
// FIXME: Optimize for checking for infer flags
9621011
struct HasTypeFlagsVisitor {
9631012
flags: ty::TypeFlags,

compiler/rustc_middle/src/ty/mod.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,12 @@ pub use self::sty::BoundRegionKind::*;
6767
pub use self::sty::RegionKind::*;
6868
pub use self::sty::TyKind::*;
6969
pub use self::sty::{
70-
Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar, CanonicalPolyFnSig,
71-
ClosureSubsts, ClosureSubstsParts, ConstVid, EarlyBoundRegion, ExistentialPredicate,
72-
ExistentialProjection, ExistentialTraitRef, FnSig, FreeRegion, GenSig, GeneratorSubsts,
73-
GeneratorSubstsParts, ParamConst, ParamTy, PolyExistentialProjection, PolyExistentialTraitRef,
74-
PolyFnSig, PolyGenSig, PolyTraitRef, ProjectionTy, Region, RegionKind, RegionVid, TraitRef,
75-
TyKind, TypeAndMut, UpvarSubsts,
70+
Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar, BoundVariableKind,
71+
CanonicalPolyFnSig, ClosureSubsts, ClosureSubstsParts, ConstVid, EarlyBoundRegion,
72+
ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig, FreeRegion, GenSig,
73+
GeneratorSubsts, GeneratorSubstsParts, ParamConst, ParamTy, PolyExistentialProjection,
74+
PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef, ProjectionTy, Region, RegionKind,
75+
RegionVid, TraitRef, TyKind, TypeAndMut, UpvarSubsts,
7676
};
7777
pub use self::trait_def::TraitDef;
7878

@@ -546,7 +546,7 @@ impl<'tcx> Predicate<'tcx> {
546546
let substs = trait_ref.skip_binder().substs;
547547
let pred = self.kind().skip_binder();
548548
let new = pred.subst(tcx, substs);
549-
tcx.reuse_or_mk_predicate(self, ty::Binder::bind(new))
549+
tcx.reuse_or_mk_predicate(self, ty::Binder::bind(new, tcx))
550550
}
551551
}
552552

compiler/rustc_middle/src/ty/structural_impls.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -460,8 +460,10 @@ where
460460
{
461461
type Lifted = ty::Binder<'tcx, T::Lifted>;
462462
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
463-
// FIXME: need to lift inner values
464-
tcx.lift(self.skip_binder()).map(|v| ty::Binder::bind(v))
463+
let bound_vars = tcx.lift(self.bound_vars());
464+
tcx.lift(self.skip_binder())
465+
.zip(bound_vars)
466+
.map(|(value, vars)| ty::Binder::bind_with_vars(value, vars))
465467
}
466468
}
467469

0 commit comments

Comments
 (0)