Skip to content

Commit 4ab0c58

Browse files
committed
Switch the code to use De Bruijn indices rather than binder-ids.
1 parent 23652ef commit 4ab0c58

File tree

22 files changed

+1071
-547
lines changed

22 files changed

+1071
-547
lines changed

src/librustc/metadata/tydecode.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ fn parse_region(st: &mut PState, conv: conv_did) -> ty::Region {
294294
match next(st) {
295295
'b' => {
296296
assert_eq!(next(st), '[');
297-
let id = parse_uint(st) as ast::NodeId;
297+
let id = ty::DebruijnIndex::new(parse_uint(st));
298298
assert_eq!(next(st), '|');
299299
let br = parse_bound_region(st, |x,y| conv(x,y));
300300
assert_eq!(next(st), ']');
@@ -579,8 +579,6 @@ fn parse_bare_fn_ty(st: &mut PState, conv: conv_did) -> ty::BareFnTy {
579579

580580
fn parse_sig(st: &mut PState, conv: conv_did) -> ty::FnSig {
581581
assert_eq!(next(st), '[');
582-
let id = parse_uint(st) as ast::NodeId;
583-
assert_eq!(next(st), '|');
584582
let mut inputs = Vec::new();
585583
while peek(st) != ']' {
586584
inputs.push(parse_ty(st, |x,y| conv(x,y)));
@@ -598,8 +596,7 @@ fn parse_sig(st: &mut PState, conv: conv_did) -> ty::FnSig {
598596
}
599597
_ => ty::FnConverging(parse_ty(st, |x,y| conv(x,y)))
600598
};
601-
ty::FnSig {binder_id: id,
602-
inputs: inputs,
599+
ty::FnSig {inputs: inputs,
603600
output: output,
604601
variadic: variadic}
605602
}

src/librustc/metadata/tyencode.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ fn enc_region_substs(w: &mut SeekableMemWriter, cx: &ctxt, substs: &subst::Regio
130130
pub fn enc_region(w: &mut SeekableMemWriter, cx: &ctxt, r: ty::Region) {
131131
match r {
132132
ty::ReLateBound(id, br) => {
133-
mywrite!(w, "b[{}|", id);
133+
mywrite!(w, "b[{}|", id.depth);
134134
enc_bound_region(w, cx, br);
135135
mywrite!(w, "]");
136136
}
@@ -331,7 +331,7 @@ pub fn enc_closure_ty(w: &mut SeekableMemWriter, cx: &ctxt, ft: &ty::ClosureTy)
331331
}
332332

333333
fn enc_fn_sig(w: &mut SeekableMemWriter, cx: &ctxt, fsig: &ty::FnSig) {
334-
mywrite!(w, "[{}|", fsig.binder_id);
334+
mywrite!(w, "[");
335335
for ty in fsig.inputs.iter() {
336336
enc_ty(w, cx, *ty);
337337
}

src/librustc/middle/astencode.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -483,8 +483,8 @@ impl tr for def::Def {
483483
impl tr for ty::Region {
484484
fn tr(&self, dcx: &DecodeContext) -> ty::Region {
485485
match *self {
486-
ty::ReLateBound(id, br) => {
487-
ty::ReLateBound(dcx.tr_id(id), br.tr(dcx))
486+
ty::ReLateBound(debruijn, br) => {
487+
ty::ReLateBound(debruijn, br.tr(dcx))
488488
}
489489
ty::ReEarlyBound(id, space, index, ident) => {
490490
ty::ReEarlyBound(dcx.tr_id(id), space, index, ident)

src/librustc/middle/resolve_lifetime.rs

Lines changed: 56 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,7 @@ pub enum DefRegion {
3939
DefEarlyBoundRegion(/* space */ subst::ParamSpace,
4040
/* index */ uint,
4141
/* lifetime decl */ ast::NodeId),
42-
DefLateBoundRegion(/* binder_id */ ast::NodeId,
43-
/* depth */ uint,
42+
DefLateBoundRegion(ty::DebruijnIndex,
4443
/* lifetime decl */ ast::NodeId),
4544
DefFreeRegion(/* block scope */ ast::NodeId,
4645
/* lifetime decl */ ast::NodeId),
@@ -60,9 +59,9 @@ enum ScopeChain<'a> {
6059
/// EarlyScope(i, ['a, 'b, ...], s) extends s with early-bound
6160
/// lifetimes, assigning indexes 'a => i, 'b => i+1, ... etc.
6261
EarlyScope(subst::ParamSpace, &'a Vec<ast::LifetimeDef>, Scope<'a>),
63-
/// LateScope(binder_id, ['a, 'b, ...], s) extends s with late-bound
62+
/// LateScope(['a, 'b, ...], s) extends s with late-bound
6463
/// lifetimes introduced by the declaration binder_id.
65-
LateScope(ast::NodeId, &'a Vec<ast::LifetimeDef>, Scope<'a>),
64+
LateScope(&'a Vec<ast::LifetimeDef>, Scope<'a>),
6665
/// lifetimes introduced by items within a code block are scoped
6766
/// to that block.
6867
BlockScope(ast::NodeId, Scope<'a>),
@@ -115,12 +114,12 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
115114
}
116115

117116
fn visit_fn(&mut self, fk: visit::FnKind<'v>, fd: &'v ast::FnDecl,
118-
b: &'v ast::Block, s: Span, n: ast::NodeId) {
117+
b: &'v ast::Block, s: Span, _: ast::NodeId) {
119118
match fk {
120119
visit::FkItemFn(_, generics, _, _) |
121120
visit::FkMethod(_, generics, _) => {
122121
self.visit_early_late(
123-
subst::FnSpace, n, generics,
122+
subst::FnSpace, generics,
124123
|this| visit::walk_fn(this, fk, fd, b, s))
125124
}
126125
visit::FkFnBlock(..) => {
@@ -130,21 +129,37 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
130129
}
131130

132131
fn visit_ty(&mut self, ty: &ast::Ty) {
133-
let lifetimes = match ty.node {
134-
ast::TyClosure(ref c) | ast::TyProc(ref c) => &c.lifetimes,
135-
ast::TyBareFn(ref c) => &c.lifetimes,
136-
_ => return visit::walk_ty(self, ty)
137-
};
138-
139-
self.with(LateScope(ty.id, lifetimes, self.scope), |this| {
140-
this.check_lifetime_defs(lifetimes);
141-
visit::walk_ty(this, ty);
142-
});
132+
match ty.node {
133+
ast::TyClosure(ref c) | ast::TyProc(ref c) => {
134+
// Careful, the bounds on a closure/proc are *not* within its binder.
135+
visit::walk_ty_param_bounds_helper(self, &c.bounds);
136+
visit::walk_lifetime_decls_helper(self, &c.lifetimes);
137+
self.with(LateScope(&c.lifetimes, self.scope), |this| {
138+
this.check_lifetime_defs(&c.lifetimes);
139+
for argument in c.decl.inputs.iter() {
140+
this.visit_ty(&*argument.ty)
141+
}
142+
visit::walk_fn_ret_ty(this, &c.decl.output);
143+
});
144+
}
145+
ast::TyBareFn(ref c) => {
146+
visit::walk_lifetime_decls_helper(self, &c.lifetimes);
147+
self.with(LateScope(&c.lifetimes, self.scope), |this| {
148+
// a bare fn has no bounds, so everything
149+
// contained within is scoped within its binder.
150+
this.check_lifetime_defs(&c.lifetimes);
151+
visit::walk_ty(this, ty);
152+
});
153+
}
154+
_ => {
155+
visit::walk_ty(self, ty)
156+
}
157+
}
143158
}
144159

145160
fn visit_ty_method(&mut self, m: &ast::TypeMethod) {
146161
self.visit_early_late(
147-
subst::FnSpace, m.id, &m.generics,
162+
subst::FnSpace, &m.generics,
148163
|this| visit::walk_ty_method(this, m))
149164
}
150165

@@ -216,11 +231,25 @@ impl<'a> LifetimeContext<'a> {
216231
fn visit_trait_ref(&mut self, trait_ref: &ast::TraitRef) {
217232
self.visit_path(&trait_ref.path, trait_ref.ref_id);
218233
}
234+
}
235+
236+
impl<'a> LifetimeContext<'a> {
237+
fn with(&mut self, wrap_scope: ScopeChain, f: |&mut LifetimeContext|) {
238+
let LifetimeContext {sess, ref mut named_region_map, ..} = *self;
239+
let mut this = LifetimeContext {
240+
sess: sess,
241+
named_region_map: *named_region_map,
242+
scope: &wrap_scope,
243+
def_map: self.def_map,
244+
};
245+
debug!("entering scope {}", this.scope);
246+
f(&mut this);
247+
debug!("exiting scope {}", this.scope);
248+
}
219249

220250
/// Visits self by adding a scope and handling recursive walk over the contents with `walk`.
221251
fn visit_early_late(&mut self,
222252
early_space: subst::ParamSpace,
223-
binder_id: ast::NodeId,
224253
generics: &ast::Generics,
225254
walk: |&mut LifetimeContext|) {
226255
/*!
@@ -249,15 +278,14 @@ impl<'a> LifetimeContext<'a> {
249278

250279
let referenced_idents = early_bound_lifetime_names(generics);
251280

252-
debug!("visit_early_late: binder_id={} referenced_idents={}",
253-
binder_id,
281+
debug!("visit_early_late: referenced_idents={}",
254282
referenced_idents);
255283

256284
let (early, late) = generics.lifetimes.clone().partition(
257285
|l| referenced_idents.iter().any(|&i| i == l.lifetime.name));
258286

259287
self.with(EarlyScope(early_space, &early, self.scope), |this| {
260-
this.with(LateScope(binder_id, &late, this.scope), |this| {
288+
this.with(LateScope(&late, this.scope), |this| {
261289
this.check_lifetime_defs(&generics.lifetimes);
262290
walk(this);
263291
});
@@ -271,7 +299,7 @@ impl<'a> LifetimeContext<'a> {
271299
// block, then the lifetime is not bound but free, so switch
272300
// over to `resolve_free_lifetime_ref()` to complete the
273301
// search.
274-
let mut depth = 0;
302+
let mut late_depth = 0;
275303
let mut scope = self.scope;
276304
loop {
277305
match *scope {
@@ -291,22 +319,22 @@ impl<'a> LifetimeContext<'a> {
291319
return;
292320
}
293321
None => {
294-
depth += 1;
295322
scope = s;
296323
}
297324
}
298325
}
299326

300-
LateScope(binder_id, lifetimes, s) => {
327+
LateScope(lifetimes, s) => {
301328
match search_lifetimes(lifetimes, lifetime_ref) {
302329
Some((_index, decl_id)) => {
303-
let def = DefLateBoundRegion(binder_id, depth, decl_id);
330+
let debruijn = ty::DebruijnIndex::new(late_depth + 1);
331+
let def = DefLateBoundRegion(debruijn, decl_id);
304332
self.insert_lifetime(lifetime_ref, def);
305333
return;
306334
}
307335

308336
None => {
309-
depth += 1;
337+
late_depth += 1;
310338
scope = s;
311339
}
312340
}
@@ -339,7 +367,7 @@ impl<'a> LifetimeContext<'a> {
339367
}
340368

341369
EarlyScope(_, lifetimes, s) |
342-
LateScope(_, lifetimes, s) => {
370+
LateScope(lifetimes, s) => {
343371
search_result = search_lifetimes(lifetimes, lifetime_ref);
344372
if search_result.is_some() {
345373
break;
@@ -517,7 +545,7 @@ impl<'a> fmt::Show for ScopeChain<'a> {
517545
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
518546
match *self {
519547
EarlyScope(space, defs, _) => write!(fmt, "EarlyScope({}, {})", space, defs),
520-
LateScope(id, defs, _) => write!(fmt, "LateScope({}, {})", id, defs),
548+
LateScope(defs, _) => write!(fmt, "LateScope({})", defs),
521549
BlockScope(id, _) => write!(fmt, "BlockScope({})", id),
522550
RootScope => write!(fmt, "RootScope"),
523551
}

0 commit comments

Comments
 (0)