Skip to content

Commit 6d5efa9

Browse files
committed
Add var to BoundRegion. Add query to get bound vars for applicable items.
1 parent 666859a commit 6d5efa9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+1261
-372
lines changed

compiler/rustc_hir/src/hir.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,7 @@ pub enum TraitBoundModifier {
402402
/// `typeck::collect::compute_bounds` matches these against
403403
/// the "special" built-in traits (see `middle::lang_items`) and
404404
/// detects `Copy`, `Send` and `Sync`.
405-
#[derive(Debug, HashStable_Generic)]
405+
#[derive(Clone, Debug, HashStable_Generic)]
406406
pub enum GenericBound<'hir> {
407407
Trait(PolyTraitRef<'hir>, TraitBoundModifier),
408408
// FIXME(davidtwco): Introduce `PolyTraitRef::LangItem`
@@ -2556,7 +2556,7 @@ pub enum UseKind {
25562556
/// that the `ref_id` is for. Note that `ref_id`'s value is not the `HirId` of the
25572557
/// trait being referred to but just a unique `HirId` that serves as a key
25582558
/// within the resolution map.
2559-
#[derive(Debug, HashStable_Generic)]
2559+
#[derive(Clone, Debug, HashStable_Generic)]
25602560
pub struct TraitRef<'hir> {
25612561
pub path: &'hir Path<'hir>,
25622562
// Don't hash the `ref_id`. It is tracked via the thing it is used to access.
@@ -2575,7 +2575,7 @@ impl TraitRef<'_> {
25752575
}
25762576
}
25772577

2578-
#[derive(Debug, HashStable_Generic)]
2578+
#[derive(Clone, Debug, HashStable_Generic)]
25792579
pub struct PolyTraitRef<'hir> {
25802580
/// The `'a` in `for<'a> Foo<&'a T>`.
25812581
pub bound_generic_params: &'hir [GenericParam<'hir>],

compiler/rustc_infer/src/infer/canonical/canonicalizer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -621,7 +621,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
621621
r: ty::Region<'tcx>,
622622
) -> ty::Region<'tcx> {
623623
let var = self.canonical_var(info, r.into());
624-
let br = ty::BoundRegion { kind: ty::BrAnon(var.as_u32()) };
624+
let br = ty::BoundRegion { var, kind: ty::BrAnon(var.as_u32()) };
625625
let region = ty::ReLateBound(self.binder_index, br);
626626
self.tcx().mk_region(region)
627627
}

compiler/rustc_infer/src/infer/canonical/query_response.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
439439

440440
// We only allow a `ty::INNERMOST` index in substitutions.
441441
assert_eq!(debruijn, ty::INNERMOST);
442-
opt_values[br.assert_bound_var()] = Some(*original_value);
442+
opt_values[br.var] = Some(*original_value);
443443
}
444444
}
445445
GenericArgKind::Const(result_value) => {

compiler/rustc_infer/src/infer/canonical/substitute.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,10 @@ where
7171
if var_values.var_values.is_empty() {
7272
value
7373
} else {
74-
let fld_r =
75-
|br: ty::BoundRegion| match var_values.var_values[br.assert_bound_var()].unpack() {
76-
GenericArgKind::Lifetime(l) => l,
77-
r => bug!("{:?} is a region but value is {:?}", br, r),
78-
};
74+
let fld_r = |br: ty::BoundRegion| match var_values.var_values[br.var].unpack() {
75+
GenericArgKind::Lifetime(l) => l,
76+
r => bug!("{:?} is a region but value is {:?}", br, r),
77+
};
7978

8079
let fld_t = |bound_ty: ty::BoundTy| match var_values.var_values[bound_ty.var].unpack() {
8180
GenericArgKind::Type(ty) => ty,

compiler/rustc_middle/src/ich/impls_ty.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,16 +70,16 @@ impl<'a> HashStable<StableHashingContext<'a>> for ty::RegionKind {
7070
ty::ReEmpty(universe) => {
7171
universe.hash_stable(hcx, hasher);
7272
}
73-
ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrAnon(i) }) => {
73+
ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrAnon(i), .. }) => {
7474
db.hash_stable(hcx, hasher);
7575
i.hash_stable(hcx, hasher);
7676
}
77-
ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrNamed(def_id, name) }) => {
77+
ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrNamed(def_id, name), .. }) => {
7878
db.hash_stable(hcx, hasher);
7979
def_id.hash_stable(hcx, hasher);
8080
name.hash_stable(hcx, hasher);
8181
}
82-
ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrEnv }) => {
82+
ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrEnv, .. }) => {
8383
db.hash_stable(hcx, hasher);
8484
}
8585
ty::ReEarlyBound(ty::EarlyBoundRegion { def_id, index, name }) => {

compiler/rustc_middle/src/infer/canonical.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,8 @@ impl<'tcx> CanonicalVarValues<'tcx> {
314314
tcx.mk_ty(ty::Bound(ty::INNERMOST, ty::BoundVar::from_u32(i).into())).into()
315315
}
316316
GenericArgKind::Lifetime(..) => {
317-
let br = ty::BoundRegion { kind: ty::BrAnon(i) };
317+
let br =
318+
ty::BoundRegion { var: ty::BoundVar::from_u32(i), kind: ty::BrAnon(i) };
318319
tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)).into()
319320
}
320321
GenericArgKind::Const(ct) => tcx

compiler/rustc_middle/src/middle/resolve_lifetime.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,4 +83,6 @@ pub struct ResolveLifetimes {
8383
/// be late-bound if (a) it does NOT appear in a where-clause and
8484
/// (b) it DOES appear in the arguments.
8585
pub late_bound: FxHashMap<LocalDefId, FxHashSet<ItemLocalId>>,
86+
87+
pub late_bound_vars: FxHashMap<LocalDefId, FxHashMap<ItemLocalId, Vec<ty::BoundVariableKind>>>,
8688
}

compiler/rustc_middle/src/query/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1290,6 +1290,10 @@ rustc_queries! {
12901290
-> Option<Vec<ObjectLifetimeDefault>> {
12911291
desc { "looking up lifetime defaults for a region on an item" }
12921292
}
1293+
query late_bound_vars_map(_: LocalDefId)
1294+
-> Option<&'tcx FxHashMap<ItemLocalId, Vec<ty::BoundVariableKind>>> {
1295+
desc { "looking up late bound vars" }
1296+
}
12931297

12941298
query visibility(def_id: DefId) -> ty::Visibility {
12951299
eval_always

compiler/rustc_middle/src/ty/context.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -810,7 +810,7 @@ impl CanonicalUserType<'tcx> {
810810
ty::ReLateBound(debruijn, br) => {
811811
// We only allow a `ty::INNERMOST` index in substitutions.
812812
assert_eq!(*debruijn, ty::INNERMOST);
813-
cvar == br.assert_bound_var()
813+
cvar == br.var
814814
}
815815
_ => false,
816816
},
@@ -2672,6 +2672,17 @@ impl<'tcx> TyCtxt<'tcx> {
26722672
pub fn object_lifetime_defaults(self, id: HirId) -> Option<Vec<ObjectLifetimeDefault>> {
26732673
self.object_lifetime_defaults_map(id.owner)
26742674
}
2675+
2676+
pub fn late_bound_vars(self, id: HirId) -> &'tcx List<ty::BoundVariableKind> {
2677+
self.mk_bound_variable_kinds(
2678+
self.late_bound_vars_map(id.owner)
2679+
.and_then(|map| map.get(&id.local_id).cloned())
2680+
.unwrap_or_else(|| {
2681+
bug!("No bound vars found for {:?} ({:?})", self.hir().node_to_string(id), id)
2682+
})
2683+
.iter(),
2684+
)
2685+
}
26752686
}
26762687

26772688
impl TyCtxtAt<'tcx> {

compiler/rustc_middle/src/ty/fold.rs

Lines changed: 141 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,42 @@ impl<'tcx> TyCtxt<'tcx> {
634634
.0
635635
}
636636

637+
pub fn shift_bound_var_indices<T>(self, bound_vars: usize, value: T) -> T
638+
where
639+
T: TypeFoldable<'tcx>,
640+
{
641+
self.replace_escaping_bound_vars(
642+
value,
643+
|r| {
644+
self.mk_region(ty::ReLateBound(
645+
ty::INNERMOST,
646+
ty::BoundRegion {
647+
var: ty::BoundVar::from_usize(r.var.as_usize() + bound_vars),
648+
kind: r.kind,
649+
},
650+
))
651+
},
652+
|t| {
653+
self.mk_ty(ty::Bound(
654+
ty::INNERMOST,
655+
ty::BoundTy {
656+
var: ty::BoundVar::from_usize(t.var.as_usize() + bound_vars),
657+
kind: t.kind,
658+
},
659+
))
660+
},
661+
|c, ty| {
662+
self.mk_const(ty::Const {
663+
val: ty::ConstKind::Bound(
664+
ty::INNERMOST,
665+
ty::BoundVar::from_usize(c.as_usize() + bound_vars),
666+
),
667+
ty,
668+
})
669+
},
670+
)
671+
}
672+
637673
/// Returns a set of all late-bound regions that are constrained
638674
/// by `value`, meaning that if we instantiate those LBR with
639675
/// variables and equate `value` with something else, those
@@ -695,16 +731,21 @@ impl<'tcx> TyCtxt<'tcx> {
695731
T: TypeFoldable<'tcx>,
696732
{
697733
let mut counter = 0;
698-
Binder::bind(
699-
self.replace_late_bound_regions(sig, |_| {
700-
let br = ty::BoundRegion { kind: ty::BrAnon(counter) };
734+
let inner = self
735+
.replace_late_bound_regions(sig, |_| {
736+
let br = ty::BoundRegion {
737+
var: ty::BoundVar::from_u32(counter),
738+
kind: ty::BrAnon(counter),
739+
};
701740
let r = self.mk_region(ty::ReLateBound(ty::INNERMOST, br));
702741
counter += 1;
703742
r
704743
})
705-
.0,
706-
self,
707-
)
744+
.0;
745+
let bound_vars = self.mk_bound_variable_kinds(
746+
(0..counter).map(|i| ty::BoundVariableKind::Region(ty::BrAnon(i))),
747+
);
748+
Binder::bind_with_vars(inner, bound_vars)
708749
}
709750
}
710751

@@ -777,27 +818,105 @@ impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> {
777818
}
778819

779820
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
780-
use std::collections::btree_map::Entry;
781821
match r {
782-
ty::ReLateBound(index, br) if *index == self.binder_index => match br.kind {
783-
ty::BrNamed(_def_id, _name) => {
784-
// FIXME
785-
}
822+
ty::ReLateBound(index, _br) if *index == self.binder_index => {
823+
bug!("{:?} {:?}", index, _br)
824+
}
786825

787-
ty::BrAnon(var) => match self.vars.entry(var) {
788-
Entry::Vacant(entry) => {
789-
entry.insert(ty::BoundVariableKind::Region(br.kind));
826+
_ => (),
827+
};
828+
829+
r.super_visit_with(self)
830+
}
831+
}
832+
833+
pub struct ValidateBoundVars<'tcx> {
834+
bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
835+
binder_index: ty::DebruijnIndex,
836+
// We may encounter the same variable at different levels of binding, so
837+
// this can't just be `Ty`
838+
visited: SsoHashSet<(ty::DebruijnIndex, Ty<'tcx>)>,
839+
}
840+
841+
impl<'tcx> ValidateBoundVars<'tcx> {
842+
pub fn new(bound_vars: &'tcx ty::List<ty::BoundVariableKind>) -> Self {
843+
ValidateBoundVars {
844+
bound_vars,
845+
binder_index: ty::INNERMOST,
846+
visited: SsoHashSet::default(),
847+
}
848+
}
849+
}
850+
851+
impl<'tcx> TypeVisitor<'tcx> for ValidateBoundVars<'tcx> {
852+
type BreakTy = ();
853+
854+
fn visit_binder<T: TypeFoldable<'tcx>>(
855+
&mut self,
856+
t: &Binder<'tcx, T>,
857+
) -> ControlFlow<Self::BreakTy> {
858+
self.binder_index.shift_in(1);
859+
let result = t.super_visit_with(self);
860+
self.binder_index.shift_out(1);
861+
result
862+
}
863+
864+
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
865+
if t.outer_exclusive_binder < self.binder_index
866+
|| !self.visited.insert((self.binder_index, t))
867+
{
868+
return ControlFlow::BREAK;
869+
}
870+
match *t.kind() {
871+
ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => {
872+
if self.bound_vars.len() <= bound_ty.var.as_usize() {
873+
panic!("Not enough bound vars: {:?} not found in {:?}", t, self.bound_vars);
874+
}
875+
let list_var = self.bound_vars[bound_ty.var.as_usize()];
876+
match list_var {
877+
ty::BoundVariableKind::Ty(kind) => {
878+
if kind != bound_ty.kind {
879+
panic!(
880+
"Mismatched type kinds: {:?} doesn't var in list {:?}",
881+
bound_ty.kind, list_var
882+
);
883+
}
790884
}
791-
Entry::Occupied(entry) => match entry.get() {
792-
ty::BoundVariableKind::Region(_) => {}
793-
_ => bug!("Conflicting bound vars"),
794-
},
795-
},
885+
_ => panic!(
886+
"Mismatched bound variable kinds! Expected type, found {:?}",
887+
list_var
888+
),
889+
}
890+
}
891+
892+
_ => (),
893+
};
894+
895+
t.super_visit_with(self)
896+
}
796897

797-
ty::BrEnv => {
798-
// FIXME
898+
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
899+
match r {
900+
ty::ReLateBound(index, br) if *index == self.binder_index => {
901+
if self.bound_vars.len() <= br.var.as_usize() {
902+
panic!("Not enough bound vars: {:?} not found in {:?}", *br, self.bound_vars);
799903
}
800-
},
904+
let list_var = self.bound_vars[br.var.as_usize()];
905+
match list_var {
906+
ty::BoundVariableKind::Region(kind) => {
907+
if kind != br.kind {
908+
panic!(
909+
"Mismatched region kinds: {:?} doesn't match var ({:?}) in list ({:?})",
910+
br.kind, list_var, self.bound_vars
911+
);
912+
}
913+
}
914+
_ => panic!(
915+
"Mismatched bound variable kinds! Expected region, found {:?}",
916+
list_var
917+
),
918+
}
919+
}
801920

802921
_ => (),
803922
};

0 commit comments

Comments
 (0)