提交 4ab0c588 编写于 作者: N Niko Matsakis

Switch the code to use De Bruijn indices rather than binder-ids.

上级 23652eff
...@@ -294,7 +294,7 @@ fn parse_region(st: &mut PState, conv: conv_did) -> ty::Region { ...@@ -294,7 +294,7 @@ fn parse_region(st: &mut PState, conv: conv_did) -> ty::Region {
match next(st) { match next(st) {
'b' => { 'b' => {
assert_eq!(next(st), '['); assert_eq!(next(st), '[');
let id = parse_uint(st) as ast::NodeId; let id = ty::DebruijnIndex::new(parse_uint(st));
assert_eq!(next(st), '|'); assert_eq!(next(st), '|');
let br = parse_bound_region(st, |x,y| conv(x,y)); let br = parse_bound_region(st, |x,y| conv(x,y));
assert_eq!(next(st), ']'); assert_eq!(next(st), ']');
...@@ -579,8 +579,6 @@ fn parse_bare_fn_ty(st: &mut PState, conv: conv_did) -> ty::BareFnTy { ...@@ -579,8 +579,6 @@ fn parse_bare_fn_ty(st: &mut PState, conv: conv_did) -> ty::BareFnTy {
fn parse_sig(st: &mut PState, conv: conv_did) -> ty::FnSig { fn parse_sig(st: &mut PState, conv: conv_did) -> ty::FnSig {
assert_eq!(next(st), '['); assert_eq!(next(st), '[');
let id = parse_uint(st) as ast::NodeId;
assert_eq!(next(st), '|');
let mut inputs = Vec::new(); let mut inputs = Vec::new();
while peek(st) != ']' { while peek(st) != ']' {
inputs.push(parse_ty(st, |x,y| conv(x,y))); 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 { ...@@ -598,8 +596,7 @@ fn parse_sig(st: &mut PState, conv: conv_did) -> ty::FnSig {
} }
_ => ty::FnConverging(parse_ty(st, |x,y| conv(x,y))) _ => ty::FnConverging(parse_ty(st, |x,y| conv(x,y)))
}; };
ty::FnSig {binder_id: id, ty::FnSig {inputs: inputs,
inputs: inputs,
output: output, output: output,
variadic: variadic} variadic: variadic}
} }
......
...@@ -130,7 +130,7 @@ fn enc_region_substs(w: &mut SeekableMemWriter, cx: &ctxt, substs: &subst::Regio ...@@ -130,7 +130,7 @@ fn enc_region_substs(w: &mut SeekableMemWriter, cx: &ctxt, substs: &subst::Regio
pub fn enc_region(w: &mut SeekableMemWriter, cx: &ctxt, r: ty::Region) { pub fn enc_region(w: &mut SeekableMemWriter, cx: &ctxt, r: ty::Region) {
match r { match r {
ty::ReLateBound(id, br) => { ty::ReLateBound(id, br) => {
mywrite!(w, "b[{}|", id); mywrite!(w, "b[{}|", id.depth);
enc_bound_region(w, cx, br); enc_bound_region(w, cx, br);
mywrite!(w, "]"); mywrite!(w, "]");
} }
...@@ -331,7 +331,7 @@ pub fn enc_closure_ty(w: &mut SeekableMemWriter, cx: &ctxt, ft: &ty::ClosureTy) ...@@ -331,7 +331,7 @@ pub fn enc_closure_ty(w: &mut SeekableMemWriter, cx: &ctxt, ft: &ty::ClosureTy)
} }
fn enc_fn_sig(w: &mut SeekableMemWriter, cx: &ctxt, fsig: &ty::FnSig) { fn enc_fn_sig(w: &mut SeekableMemWriter, cx: &ctxt, fsig: &ty::FnSig) {
mywrite!(w, "[{}|", fsig.binder_id); mywrite!(w, "[");
for ty in fsig.inputs.iter() { for ty in fsig.inputs.iter() {
enc_ty(w, cx, *ty); enc_ty(w, cx, *ty);
} }
......
...@@ -483,8 +483,8 @@ fn tr(&self, dcx: &DecodeContext) -> def::Def { ...@@ -483,8 +483,8 @@ fn tr(&self, dcx: &DecodeContext) -> def::Def {
impl tr for ty::Region { impl tr for ty::Region {
fn tr(&self, dcx: &DecodeContext) -> ty::Region { fn tr(&self, dcx: &DecodeContext) -> ty::Region {
match *self { match *self {
ty::ReLateBound(id, br) => { ty::ReLateBound(debruijn, br) => {
ty::ReLateBound(dcx.tr_id(id), br.tr(dcx)) ty::ReLateBound(debruijn, br.tr(dcx))
} }
ty::ReEarlyBound(id, space, index, ident) => { ty::ReEarlyBound(id, space, index, ident) => {
ty::ReEarlyBound(dcx.tr_id(id), space, index, ident) ty::ReEarlyBound(dcx.tr_id(id), space, index, ident)
......
...@@ -39,8 +39,7 @@ pub enum DefRegion { ...@@ -39,8 +39,7 @@ pub enum DefRegion {
DefEarlyBoundRegion(/* space */ subst::ParamSpace, DefEarlyBoundRegion(/* space */ subst::ParamSpace,
/* index */ uint, /* index */ uint,
/* lifetime decl */ ast::NodeId), /* lifetime decl */ ast::NodeId),
DefLateBoundRegion(/* binder_id */ ast::NodeId, DefLateBoundRegion(ty::DebruijnIndex,
/* depth */ uint,
/* lifetime decl */ ast::NodeId), /* lifetime decl */ ast::NodeId),
DefFreeRegion(/* block scope */ ast::NodeId, DefFreeRegion(/* block scope */ ast::NodeId,
/* lifetime decl */ ast::NodeId), /* lifetime decl */ ast::NodeId),
...@@ -60,9 +59,9 @@ enum ScopeChain<'a> { ...@@ -60,9 +59,9 @@ enum ScopeChain<'a> {
/// EarlyScope(i, ['a, 'b, ...], s) extends s with early-bound /// EarlyScope(i, ['a, 'b, ...], s) extends s with early-bound
/// lifetimes, assigning indexes 'a => i, 'b => i+1, ... etc. /// lifetimes, assigning indexes 'a => i, 'b => i+1, ... etc.
EarlyScope(subst::ParamSpace, &'a Vec<ast::LifetimeDef>, Scope<'a>), EarlyScope(subst::ParamSpace, &'a Vec<ast::LifetimeDef>, Scope<'a>),
/// LateScope(binder_id, ['a, 'b, ...], s) extends s with late-bound /// LateScope(['a, 'b, ...], s) extends s with late-bound
/// lifetimes introduced by the declaration binder_id. /// lifetimes introduced by the declaration binder_id.
LateScope(ast::NodeId, &'a Vec<ast::LifetimeDef>, Scope<'a>), LateScope(&'a Vec<ast::LifetimeDef>, Scope<'a>),
/// lifetimes introduced by items within a code block are scoped /// lifetimes introduced by items within a code block are scoped
/// to that block. /// to that block.
BlockScope(ast::NodeId, Scope<'a>), BlockScope(ast::NodeId, Scope<'a>),
...@@ -115,12 +114,12 @@ fn visit_item(&mut self, item: &ast::Item) { ...@@ -115,12 +114,12 @@ fn visit_item(&mut self, item: &ast::Item) {
} }
fn visit_fn(&mut self, fk: visit::FnKind<'v>, fd: &'v ast::FnDecl, fn visit_fn(&mut self, fk: visit::FnKind<'v>, fd: &'v ast::FnDecl,
b: &'v ast::Block, s: Span, n: ast::NodeId) { b: &'v ast::Block, s: Span, _: ast::NodeId) {
match fk { match fk {
visit::FkItemFn(_, generics, _, _) | visit::FkItemFn(_, generics, _, _) |
visit::FkMethod(_, generics, _) => { visit::FkMethod(_, generics, _) => {
self.visit_early_late( self.visit_early_late(
subst::FnSpace, n, generics, subst::FnSpace, generics,
|this| visit::walk_fn(this, fk, fd, b, s)) |this| visit::walk_fn(this, fk, fd, b, s))
} }
visit::FkFnBlock(..) => { visit::FkFnBlock(..) => {
...@@ -130,21 +129,37 @@ fn visit_fn(&mut self, fk: visit::FnKind<'v>, fd: &'v ast::FnDecl, ...@@ -130,21 +129,37 @@ fn visit_fn(&mut self, fk: visit::FnKind<'v>, fd: &'v ast::FnDecl,
} }
fn visit_ty(&mut self, ty: &ast::Ty) { fn visit_ty(&mut self, ty: &ast::Ty) {
let lifetimes = match ty.node { match ty.node {
ast::TyClosure(ref c) | ast::TyProc(ref c) => &c.lifetimes, ast::TyClosure(ref c) | ast::TyProc(ref c) => {
ast::TyBareFn(ref c) => &c.lifetimes, // Careful, the bounds on a closure/proc are *not* within its binder.
_ => return visit::walk_ty(self, ty) visit::walk_ty_param_bounds_helper(self, &c.bounds);
}; visit::walk_lifetime_decls_helper(self, &c.lifetimes);
self.with(LateScope(&c.lifetimes, self.scope), |this| {
self.with(LateScope(ty.id, lifetimes, self.scope), |this| { this.check_lifetime_defs(&c.lifetimes);
this.check_lifetime_defs(lifetimes); for argument in c.decl.inputs.iter() {
this.visit_ty(&*argument.ty)
}
visit::walk_fn_ret_ty(this, &c.decl.output);
});
}
ast::TyBareFn(ref c) => {
visit::walk_lifetime_decls_helper(self, &c.lifetimes);
self.with(LateScope(&c.lifetimes, self.scope), |this| {
// a bare fn has no bounds, so everything
// contained within is scoped within its binder.
this.check_lifetime_defs(&c.lifetimes);
visit::walk_ty(this, ty); visit::walk_ty(this, ty);
}); });
} }
_ => {
visit::walk_ty(self, ty)
}
}
}
fn visit_ty_method(&mut self, m: &ast::TypeMethod) { fn visit_ty_method(&mut self, m: &ast::TypeMethod) {
self.visit_early_late( self.visit_early_late(
subst::FnSpace, m.id, &m.generics, subst::FnSpace, &m.generics,
|this| visit::walk_ty_method(this, m)) |this| visit::walk_ty_method(this, m))
} }
...@@ -216,11 +231,25 @@ fn visit_poly_trait_ref(&mut self, trait_ref: &ast::PolyTraitRef) { ...@@ -216,11 +231,25 @@ fn visit_poly_trait_ref(&mut self, trait_ref: &ast::PolyTraitRef) {
fn visit_trait_ref(&mut self, trait_ref: &ast::TraitRef) { fn visit_trait_ref(&mut self, trait_ref: &ast::TraitRef) {
self.visit_path(&trait_ref.path, trait_ref.ref_id); self.visit_path(&trait_ref.path, trait_ref.ref_id);
} }
}
impl<'a> LifetimeContext<'a> {
fn with(&mut self, wrap_scope: ScopeChain, f: |&mut LifetimeContext|) {
let LifetimeContext {sess, ref mut named_region_map, ..} = *self;
let mut this = LifetimeContext {
sess: sess,
named_region_map: *named_region_map,
scope: &wrap_scope,
def_map: self.def_map,
};
debug!("entering scope {}", this.scope);
f(&mut this);
debug!("exiting scope {}", this.scope);
}
/// Visits self by adding a scope and handling recursive walk over the contents with `walk`. /// Visits self by adding a scope and handling recursive walk over the contents with `walk`.
fn visit_early_late(&mut self, fn visit_early_late(&mut self,
early_space: subst::ParamSpace, early_space: subst::ParamSpace,
binder_id: ast::NodeId,
generics: &ast::Generics, generics: &ast::Generics,
walk: |&mut LifetimeContext|) { walk: |&mut LifetimeContext|) {
/*! /*!
...@@ -249,15 +278,14 @@ fn visit_early_late(&mut self, ...@@ -249,15 +278,14 @@ fn visit_early_late(&mut self,
let referenced_idents = early_bound_lifetime_names(generics); let referenced_idents = early_bound_lifetime_names(generics);
debug!("visit_early_late: binder_id={} referenced_idents={}", debug!("visit_early_late: referenced_idents={}",
binder_id,
referenced_idents); referenced_idents);
let (early, late) = generics.lifetimes.clone().partition( let (early, late) = generics.lifetimes.clone().partition(
|l| referenced_idents.iter().any(|&i| i == l.lifetime.name)); |l| referenced_idents.iter().any(|&i| i == l.lifetime.name));
self.with(EarlyScope(early_space, &early, self.scope), |this| { self.with(EarlyScope(early_space, &early, self.scope), |this| {
this.with(LateScope(binder_id, &late, this.scope), |this| { this.with(LateScope(&late, this.scope), |this| {
this.check_lifetime_defs(&generics.lifetimes); this.check_lifetime_defs(&generics.lifetimes);
walk(this); walk(this);
}); });
...@@ -271,7 +299,7 @@ fn resolve_lifetime_ref(&mut self, lifetime_ref: &ast::Lifetime) { ...@@ -271,7 +299,7 @@ fn resolve_lifetime_ref(&mut self, lifetime_ref: &ast::Lifetime) {
// block, then the lifetime is not bound but free, so switch // block, then the lifetime is not bound but free, so switch
// over to `resolve_free_lifetime_ref()` to complete the // over to `resolve_free_lifetime_ref()` to complete the
// search. // search.
let mut depth = 0; let mut late_depth = 0;
let mut scope = self.scope; let mut scope = self.scope;
loop { loop {
match *scope { match *scope {
...@@ -291,22 +319,22 @@ fn resolve_lifetime_ref(&mut self, lifetime_ref: &ast::Lifetime) { ...@@ -291,22 +319,22 @@ fn resolve_lifetime_ref(&mut self, lifetime_ref: &ast::Lifetime) {
return; return;
} }
None => { None => {
depth += 1;
scope = s; scope = s;
} }
} }
} }
LateScope(binder_id, lifetimes, s) => { LateScope(lifetimes, s) => {
match search_lifetimes(lifetimes, lifetime_ref) { match search_lifetimes(lifetimes, lifetime_ref) {
Some((_index, decl_id)) => { Some((_index, decl_id)) => {
let def = DefLateBoundRegion(binder_id, depth, decl_id); let debruijn = ty::DebruijnIndex::new(late_depth + 1);
let def = DefLateBoundRegion(debruijn, decl_id);
self.insert_lifetime(lifetime_ref, def); self.insert_lifetime(lifetime_ref, def);
return; return;
} }
None => { None => {
depth += 1; late_depth += 1;
scope = s; scope = s;
} }
} }
...@@ -339,7 +367,7 @@ fn resolve_free_lifetime_ref(&mut self, ...@@ -339,7 +367,7 @@ fn resolve_free_lifetime_ref(&mut self,
} }
EarlyScope(_, lifetimes, s) | EarlyScope(_, lifetimes, s) |
LateScope(_, lifetimes, s) => { LateScope(lifetimes, s) => {
search_result = search_lifetimes(lifetimes, lifetime_ref); search_result = search_lifetimes(lifetimes, lifetime_ref);
if search_result.is_some() { if search_result.is_some() {
break; break;
...@@ -517,7 +545,7 @@ impl<'a> fmt::Show for ScopeChain<'a> { ...@@ -517,7 +545,7 @@ impl<'a> fmt::Show for ScopeChain<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match *self { match *self {
EarlyScope(space, defs, _) => write!(fmt, "EarlyScope({}, {})", space, defs), EarlyScope(space, defs, _) => write!(fmt, "EarlyScope({}, {})", space, defs),
LateScope(id, defs, _) => write!(fmt, "LateScope({}, {})", id, defs), LateScope(defs, _) => write!(fmt, "LateScope({})", defs),
BlockScope(id, _) => write!(fmt, "BlockScope({})", id), BlockScope(id, _) => write!(fmt, "BlockScope({})", id),
RootScope => write!(fmt, "RootScope"), RootScope => write!(fmt, "RootScope"),
} }
......
...@@ -14,8 +14,7 @@ ...@@ -14,8 +14,7 @@
pub use self::RegionSubsts::*; pub use self::RegionSubsts::*;
use middle::ty; use middle::ty;
use middle::ty_fold; use middle::ty_fold::{mod, TypeFoldable, TypeFolder};
use middle::ty_fold::{TypeFoldable, TypeFolder};
use util::ppaux::Repr; use util::ppaux::Repr;
use std::fmt; use std::fmt;
...@@ -506,11 +505,22 @@ struct SubstFolder<'a, 'tcx: 'a> { ...@@ -506,11 +505,22 @@ struct SubstFolder<'a, 'tcx: 'a> {
// Depth of type stack // Depth of type stack
ty_stack_depth: uint, ty_stack_depth: uint,
// Number of region binders we have passed through while doing the substitution
region_binders_passed: uint,
} }
impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> { impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> {
fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> { self.tcx } fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> { self.tcx }
fn enter_region_binder(&mut self) {
self.region_binders_passed += 1;
}
fn exit_region_binder(&mut self) {
self.region_binders_passed -= 1;
}
fn fold_region(&mut self, r: ty::Region) -> ty::Region { fn fold_region(&mut self, r: ty::Region) -> ty::Region {
// Note: This routine only handles regions that are bound on // Note: This routine only handles regions that are bound on
// type declarations and other outer declarations, not those // type declarations and other outer declarations, not those
...@@ -524,7 +534,9 @@ fn fold_region(&mut self, r: ty::Region) -> ty::Region { ...@@ -524,7 +534,9 @@ fn fold_region(&mut self, r: ty::Region) -> ty::Region {
ErasedRegions => ty::ReStatic, ErasedRegions => ty::ReStatic,
NonerasedRegions(ref regions) => NonerasedRegions(ref regions) =>
match regions.opt_get(space, i) { match regions.opt_get(space, i) {
Some(t) => *t, Some(&r) => {
self.shift_region_through_binders(r)
}
None => { None => {
let span = self.span.unwrap_or(DUMMY_SP); let span = self.span.unwrap_or(DUMMY_SP);
self.tcx().sess.span_bug( self.tcx().sess.span_bug(
...@@ -557,12 +569,7 @@ fn fold_ty(&mut self, t: ty::t) -> ty::t { ...@@ -557,12 +569,7 @@ fn fold_ty(&mut self, t: ty::t) -> ty::t {
let t1 = match ty::get(t).sty { let t1 = match ty::get(t).sty {
ty::ty_param(p) => { ty::ty_param(p) => {
check(self, self.ty_for_param(p, t)
p,
t,
self.substs.types.opt_get(p.space, p.idx),
p.space,
p.idx)
} }
_ => { _ => {
ty_fold::super_fold_ty(self, t) ty_fold::super_fold_ty(self, t)
...@@ -576,30 +583,100 @@ fn fold_ty(&mut self, t: ty::t) -> ty::t { ...@@ -576,30 +583,100 @@ fn fold_ty(&mut self, t: ty::t) -> ty::t {
} }
return t1; return t1;
}
}
fn check(this: &SubstFolder, impl<'a,'tcx> SubstFolder<'a,'tcx> {
p: ty::ParamTy, fn ty_for_param(&self, p: ty::ParamTy, source_ty: ty::t) -> ty::t {
source_ty: ty::t, // Look up the type in the substitutions. It really should be in there.
opt_ty: Option<&ty::t>, let opt_ty = self.substs.types.opt_get(p.space, p.idx);
space: ParamSpace, let ty = match opt_ty {
index: uint)
-> ty::t {
match opt_ty {
Some(t) => *t, Some(t) => *t,
None => { None => {
let span = this.span.unwrap_or(DUMMY_SP); let span = self.span.unwrap_or(DUMMY_SP);
this.tcx().sess.span_bug( self.tcx().sess.span_bug(
span, span,
format!("Type parameter `{}` ({}/{}/{}) out of range \ format!("Type parameter `{}` ({}/{}/{}) out of range \
when substituting (root type={}) substs={}", when substituting (root type={}) substs={}",
p.repr(this.tcx()), p.repr(self.tcx()),
source_ty.repr(this.tcx()), source_ty.repr(self.tcx()),
space, p.space,
index, p.idx,
this.root_ty.repr(this.tcx()), self.root_ty.repr(self.tcx()),
this.substs.repr(this.tcx())).as_slice()); self.substs.repr(self.tcx())).as_slice());
} }
};
self.shift_regions_through_binders(ty)
} }
fn shift_regions_through_binders(&self, ty: ty::t) -> ty::t {
/*!
* It is sometimes necessary to adjust the debruijn indices
* during substitution. This occurs when we are substituting a
* type with escaping regions into a context where we have
* passed through region binders. That's quite a
* mouthful. Let's see an example:
*
* ```
* type Func<A> = fn(A);
* type MetaFunc = for<'a> fn(Func<&'a int>)
* ```
*
* The type `MetaFunc`, when fully expanded, will be
*
* for<'a> fn(fn(&'a int))
* ^~ ^~ ^~~
* | | |
* | | DebruijnIndex of 2
* Binders
*
* Here the `'a` lifetime is bound in the outer function, but
* appears as an argument of the inner one. Therefore, that
* appearance will have a DebruijnIndex of 2, because we must
* skip over the inner binder (remember that we count Debruijn
* indices from 1). However, in the definition of `MetaFunc`,
* the binder is not visible, so the type `&'a int` will have
* a debruijn index of 1. It's only during the substitution
* that we can see we must increase the depth by 1 to account
* for the binder that we passed through.
*
* As a second example, consider this twist:
*
* ```
* type FuncTuple<A> = (A,fn(A));
* type MetaFuncTuple = for<'a> fn(FuncTuple<&'a int>)
* ```
*
* Here the final type will be:
*
* for<'a> fn((&'a int, fn(&'a int)))
* ^~~ ^~~
* | |
* DebruijnIndex of 1 |
* DebruijnIndex of 2
*
* As indicated in the diagram, here the same type `&'a int`
* is substituted once, but in the first case we do not
* increase the Debruijn index and in the second case we
* do. The reason is that only in the second case have we
* passed through a fn binder.
*/
debug!("shift_regions(ty={}, region_binders_passed={}, type_has_escaping_regions={})",
ty.repr(self.tcx()), self.region_binders_passed, ty::type_has_escaping_regions(ty));
if self.region_binders_passed == 0 || !ty::type_has_escaping_regions(ty) {
return ty;
}
let result = ty_fold::shift_regions(self.tcx(), self.region_binders_passed, &ty);
debug!("shift_regions: shifted result = {}", result.repr(self.tcx()));
result
} }
fn shift_region_through_binders(&self, region: ty::Region) -> ty::Region {
ty_fold::shift_region(region, self.region_binders_passed)
} }
} }
此差异已折叠。
...@@ -63,6 +63,17 @@ pub trait TypeFoldable { ...@@ -63,6 +63,17 @@ pub trait TypeFoldable {
pub trait TypeFolder<'tcx> { pub trait TypeFolder<'tcx> {
fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx>; fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx>;
/// Invoked by the `super_*` routines when we enter a region
/// binding level (for example, when entering a function
/// signature). This is used by clients that want to track the
/// Debruijn index nesting level.
fn enter_region_binder(&mut self) { }
/// Invoked by the `super_*` routines when we exit a region
/// binding level. This is used by clients that want to
/// track the Debruijn index nesting level.
fn exit_region_binder(&mut self) { }
fn fold_ty(&mut self, t: ty::t) -> ty::t { fn fold_ty(&mut self, t: ty::t) -> ty::t {
super_fold_ty(self, t) super_fold_ty(self, t)
} }
...@@ -85,10 +96,10 @@ fn fold_substs(&mut self, ...@@ -85,10 +96,10 @@ fn fold_substs(&mut self,
super_fold_substs(self, substs) super_fold_substs(self, substs)
} }
fn fold_sig(&mut self, fn fold_fn_sig(&mut self,
sig: &ty::FnSig) sig: &ty::FnSig)
-> ty::FnSig { -> ty::FnSig {
super_fold_sig(self, sig) super_fold_fn_sig(self, sig)
} }
fn fold_output(&mut self, fn fold_output(&mut self,
...@@ -153,6 +164,12 @@ fn fold_with<'tcx, F:TypeFolder<'tcx>>(&self, _: &mut F) -> () { ...@@ -153,6 +164,12 @@ fn fold_with<'tcx, F:TypeFolder<'tcx>>(&self, _: &mut F) -> () {
} }
} }
impl<T:TypeFoldable,U:TypeFoldable> TypeFoldable for (T, U) {
fn fold_with<'tcx, F:TypeFolder<'tcx>>(&self, folder: &mut F) -> (T, U) {
(self.0.fold_with(folder), self.1.fold_with(folder))
}
}
impl<T:TypeFoldable> TypeFoldable for Option<T> { impl<T:TypeFoldable> TypeFoldable for Option<T> {
fn fold_with<'tcx, F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Option<T> { fn fold_with<'tcx, F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Option<T> {
self.as_ref().map(|t| t.fold_with(folder)) self.as_ref().map(|t| t.fold_with(folder))
...@@ -171,6 +188,15 @@ fn fold_with<'tcx, F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Vec<T> { ...@@ -171,6 +188,15 @@ fn fold_with<'tcx, F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Vec<T> {
} }
} }
impl<T:TypeFoldable> TypeFoldable for ty::Binder<T> {
fn fold_with<'tcx, F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::Binder<T> {
folder.enter_region_binder();
let result = ty::bind(self.value.fold_with(folder));
folder.exit_region_binder();
result
}
}
impl<T:TypeFoldable> TypeFoldable for OwnedSlice<T> { impl<T:TypeFoldable> TypeFoldable for OwnedSlice<T> {
fn fold_with<'tcx, F: TypeFolder<'tcx>>(&self, folder: &mut F) -> OwnedSlice<T> { fn fold_with<'tcx, F: TypeFolder<'tcx>>(&self, folder: &mut F) -> OwnedSlice<T> {
self.iter().map(|t| t.fold_with(folder)).collect() self.iter().map(|t| t.fold_with(folder)).collect()
...@@ -179,7 +205,24 @@ fn fold_with<'tcx, F: TypeFolder<'tcx>>(&self, folder: &mut F) -> OwnedSlice<T> ...@@ -179,7 +205,24 @@ fn fold_with<'tcx, F: TypeFolder<'tcx>>(&self, folder: &mut F) -> OwnedSlice<T>
impl<T:TypeFoldable> TypeFoldable for VecPerParamSpace<T> { impl<T:TypeFoldable> TypeFoldable for VecPerParamSpace<T> {
fn fold_with<'tcx, F: TypeFolder<'tcx>>(&self, folder: &mut F) -> VecPerParamSpace<T> { fn fold_with<'tcx, F: TypeFolder<'tcx>>(&self, folder: &mut F) -> VecPerParamSpace<T> {
self.map(|t| t.fold_with(folder))
// Things in the Fn space take place under an additional level
// of region binding relative to the other spaces. This is
// because those entries are attached to a method, and methods
// always introduce a level of region binding.
let result = self.map_enumerated(|(space, index, elem)| {
if space == subst::FnSpace && index == 0 {
// enter new level when/if we reach the first thing in fn space
folder.enter_region_binder();
}
elem.fold_with(folder)
});
if result.len(subst::FnSpace) > 0 {
// if there was anything in fn space, exit the region binding level
folder.exit_region_binder();
}
result
} }
} }
...@@ -221,7 +264,7 @@ fn fold_with<'tcx, F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::FnOutput { ...@@ -221,7 +264,7 @@ fn fold_with<'tcx, F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::FnOutput {
impl TypeFoldable for ty::FnSig { impl TypeFoldable for ty::FnSig {
fn fold_with<'tcx, F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::FnSig { fn fold_with<'tcx, F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::FnSig {
folder.fold_sig(self) folder.fold_fn_sig(self)
} }
} }
...@@ -457,11 +500,21 @@ pub fn super_fold_substs<'tcx, T: TypeFolder<'tcx>>(this: &mut T, ...@@ -457,11 +500,21 @@ pub fn super_fold_substs<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
types: substs.types.fold_with(this) } types: substs.types.fold_with(this) }
} }
pub fn super_fold_sig<'tcx, T: TypeFolder<'tcx>>(this: &mut T, pub fn super_fold_fn_sig<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
sig: &ty::FnSig) sig: &ty::FnSig)
-> ty::FnSig { -> ty::FnSig
ty::FnSig { binder_id: sig.binder_id, {
inputs: sig.inputs.fold_with(this), this.enter_region_binder();
let result = super_fold_fn_sig_contents(this, sig);
this.exit_region_binder();
result
}
pub fn super_fold_fn_sig_contents<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
sig: &ty::FnSig)
-> ty::FnSig
{
ty::FnSig { inputs: sig.inputs.fold_with(this),
output: sig.output.fold_with(this), output: sig.output.fold_with(this),
variadic: sig.variadic } variadic: sig.variadic }
} }
...@@ -622,6 +675,27 @@ pub fn super_fold_obligation<'tcx, T:TypeFolder<'tcx>>(this: &mut T, ...@@ -622,6 +675,27 @@ pub fn super_fold_obligation<'tcx, T:TypeFolder<'tcx>>(this: &mut T,
} }
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// Higher-ranked things
/**
* Designates a "binder" for late-bound regions.
*/
pub trait HigherRankedFoldable : Repr {
/// Folds the contents of `self`, ignoring the region binder created
/// by `self`.
fn fold_contents<'tcx, F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self;
}
impl HigherRankedFoldable for ty::FnSig {
fn fold_contents<'tcx, F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::FnSig {
super_fold_fn_sig_contents(folder, self)
}
}
impl<T:TypeFoldable+Repr> HigherRankedFoldable for ty::Binder<T> {
fn fold_contents<'tcx, F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::Binder<T> {
ty::bind(self.value.fold_with(folder))
}
}
// Some sample folders // Some sample folders
pub struct BottomUpFolder<'a, 'tcx: 'a> { pub struct BottomUpFolder<'a, 'tcx: 'a> {
...@@ -655,77 +729,43 @@ fn fold_ty(&mut self, ty: ty::t) -> ty::t { ...@@ -655,77 +729,43 @@ fn fold_ty(&mut self, ty: ty::t) -> ty::t {
/// current position of the fold.) /// current position of the fold.)
pub struct RegionFolder<'a, 'tcx: 'a> { pub struct RegionFolder<'a, 'tcx: 'a> {
tcx: &'a ty::ctxt<'tcx>, tcx: &'a ty::ctxt<'tcx>,
fld_t: |ty::t|: 'a -> ty::t, current_depth: uint,
fld_r: |ty::Region|: 'a -> ty::Region, fld_r: |ty::Region, uint|: 'a -> ty::Region,
within_binder_ids: Vec<ast::NodeId>,
} }
impl<'a, 'tcx> RegionFolder<'a, 'tcx> { impl<'a, 'tcx> RegionFolder<'a, 'tcx> {
pub fn general(tcx: &'a ty::ctxt<'tcx>, pub fn new(tcx: &'a ty::ctxt<'tcx>, fld_r: |ty::Region, uint|: 'a -> ty::Region)
fld_r: |ty::Region|: 'a -> ty::Region,
fld_t: |ty::t|: 'a -> ty::t)
-> RegionFolder<'a, 'tcx> { -> RegionFolder<'a, 'tcx> {
RegionFolder { RegionFolder {
tcx: tcx, tcx: tcx,
fld_t: fld_t, current_depth: 1,
fld_r: fld_r, fld_r: fld_r,
within_binder_ids: vec![],
} }
} }
pub fn regions(tcx: &'a ty::ctxt<'tcx>, fld_r: |ty::Region|: 'a -> ty::Region)
-> RegionFolder<'a, 'tcx> {
fn noop(t: ty::t) -> ty::t { t }
RegionFolder {
tcx: tcx,
fld_t: noop,
fld_r: fld_r,
within_binder_ids: vec![],
}
}
}
/// If `ty` has `FnSig` (i.e. closure or fn), return its binder_id;
/// else None.
fn opt_binder_id_of_function(t: ty::t) -> Option<ast::NodeId> {
match ty::get(t).sty {
ty::ty_closure(ref f) => Some(f.sig.binder_id),
ty::ty_bare_fn(ref f) => Some(f.sig.binder_id),
_ => None,
}
} }
impl<'a, 'tcx> TypeFolder<'tcx> for RegionFolder<'a, 'tcx> { impl<'a, 'tcx> TypeFolder<'tcx> for RegionFolder<'a, 'tcx> {
fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> { self.tcx } fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> { self.tcx }
fn fold_ty(&mut self, ty: ty::t) -> ty::t { fn enter_region_binder(&mut self) {
debug!("RegionFolder.fold_ty({})", ty.repr(self.tcx())); self.current_depth += 1;
let opt_binder_id = opt_binder_id_of_function(ty);
match opt_binder_id {
Some(binder_id) => self.within_binder_ids.push(binder_id),
None => {}
}
let t1 = super_fold_ty(self, ty);
let ret = (self.fld_t)(t1);
if opt_binder_id.is_some() {
self.within_binder_ids.pop();
} }
ret fn exit_region_binder(&mut self) {
self.current_depth -= 1;
} }
fn fold_region(&mut self, r: ty::Region) -> ty::Region { fn fold_region(&mut self, r: ty::Region) -> ty::Region {
match r { match r {
ty::ReLateBound(binder_id, _) if self.within_binder_ids.contains(&binder_id) => { ty::ReLateBound(debruijn, _) if debruijn.depth < self.current_depth => {
debug!("RegionFolder.fold_region({}) skipped bound region", r.repr(self.tcx())); debug!("RegionFolder.fold_region({}) skipped bound region (current depth={})",
r.repr(self.tcx()), self.current_depth);
r r
} }
_ => { _ => {
debug!("RegionFolder.fold_region({}) folding free region", r.repr(self.tcx())); debug!("RegionFolder.fold_region({}) folding free region (current_depth={})",
(self.fld_r)(r) r.repr(self.tcx()), self.current_depth);
(self.fld_r)(r, self.current_depth)
} }
} }
} }
...@@ -755,3 +795,33 @@ fn fold_region(&mut self, r: ty::Region) -> ty::Region { ...@@ -755,3 +795,33 @@ fn fold_region(&mut self, r: ty::Region) -> ty::Region {
} }
} }
} }
///////////////////////////////////////////////////////////////////////////
// Region shifter
//
// Shifts the De Bruijn indices on all escaping bound regions by a
// fixed amount. Useful in substitution or when otherwise introducing
// a binding level that is not intended to capture the existing bound
// regions. See comment on `shift_regions_through_binders` method in
// `subst.rs` for more details.
pub fn shift_region(region: ty::Region, amount: uint) -> ty::Region {
match region {
ty::ReLateBound(debruijn, br) => {
ty::ReLateBound(debruijn.shifted(amount), br)
}
_ => {
region
}
}
}
pub fn shift_regions<T:TypeFoldable+Repr>(tcx: &ty::ctxt, amount: uint, value: &T) -> T {
debug!("shift_regions(value={}, amount={})",
value.repr(tcx), amount);
value.fold_with(&mut RegionFolder::new(tcx, |region, _current_depth| {
shift_region(region, amount)
}))
}
...@@ -106,9 +106,8 @@ pub fn ast_region_to_region(tcx: &ty::ctxt, lifetime: &ast::Lifetime) ...@@ -106,9 +106,8 @@ pub fn ast_region_to_region(tcx: &ty::ctxt, lifetime: &ast::Lifetime)
ty::ReStatic ty::ReStatic
} }
Some(&rl::DefLateBoundRegion(binder_id, _, id)) => { Some(&rl::DefLateBoundRegion(debruijn, id)) => {
ty::ReLateBound(binder_id, ty::BrNamed(ast_util::local_def(id), ty::ReLateBound(debruijn, ty::BrNamed(ast_util::local_def(id), lifetime.name))
lifetime.name))
} }
Some(&rl::DefEarlyBoundRegion(space, index, id)) => { Some(&rl::DefEarlyBoundRegion(space, index, id)) => {
...@@ -210,8 +209,7 @@ fn ast_path_substs<'tcx,AC,RS>( ...@@ -210,8 +209,7 @@ fn ast_path_substs<'tcx,AC,RS>(
decl_generics: &ty::Generics, decl_generics: &ty::Generics,
self_ty: Option<ty::t>, self_ty: Option<ty::t>,
associated_ty: Option<ty::t>, associated_ty: Option<ty::t>,
path: &ast::Path, path: &ast::Path)
binder_id: ast::NodeId)
-> Substs -> Substs
where AC: AstConv<'tcx>, RS: RegionScope where AC: AstConv<'tcx>, RS: RegionScope
{ {
...@@ -463,8 +461,7 @@ pub fn ast_path_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( ...@@ -463,8 +461,7 @@ pub fn ast_path_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
this: &AC, this: &AC,
rscope: &RS, rscope: &RS,
did: ast::DefId, did: ast::DefId,
path: &ast::Path, path: &ast::Path)
binder_id: ast::NodeId)
-> TypeAndSubsts -> TypeAndSubsts
{ {
let tcx = this.tcx(); let tcx = this.tcx();
...@@ -473,14 +470,13 @@ pub fn ast_path_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( ...@@ -473,14 +470,13 @@ pub fn ast_path_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
ty: decl_ty ty: decl_ty
} = this.get_item_ty(did); } = this.get_item_ty(did);
let substs = ast_path_substs(this, let substs = ast_path_substs_for_ty(this,
rscope, rscope,
did, did,
&generics, &generics,
None, None,
None, None,
path, path);
binder_id);
let ty = decl_ty.subst(tcx, &substs); let ty = decl_ty.subst(tcx, &substs);
TypeAndSubsts { substs: substs, ty: ty } TypeAndSubsts { substs: substs, ty: ty }
} }
...@@ -494,8 +490,7 @@ pub fn ast_path_to_ty_relaxed<'tcx,AC,RS>( ...@@ -494,8 +490,7 @@ pub fn ast_path_to_ty_relaxed<'tcx,AC,RS>(
this: &AC, this: &AC,
rscope: &RS, rscope: &RS,
did: ast::DefId, did: ast::DefId,
path: &ast::Path, path: &ast::Path)
binder_id: ast::NodeId)
-> TypeAndSubsts -> TypeAndSubsts
where AC : AstConv<'tcx>, RS : RegionScope where AC : AstConv<'tcx>, RS : RegionScope
{ {
...@@ -521,7 +516,7 @@ pub fn ast_path_to_ty_relaxed<'tcx,AC,RS>( ...@@ -521,7 +516,7 @@ pub fn ast_path_to_ty_relaxed<'tcx,AC,RS>(
Substs::new(VecPerParamSpace::params_from_type(type_params), Substs::new(VecPerParamSpace::params_from_type(type_params),
VecPerParamSpace::params_from_type(region_params)) VecPerParamSpace::params_from_type(region_params))
} else { } else {
ast_path_substs(this, rscope, did, &generics, None, None, path, binder_id) ast_path_substs_for_ty(this, rscope, did, &generics, None, None, path)
}; };
let ty = decl_ty.subst(tcx, &substs); let ty = decl_ty.subst(tcx, &substs);
...@@ -628,7 +623,7 @@ pub fn ast_ty_to_builtin_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( ...@@ -628,7 +623,7 @@ pub fn ast_ty_to_builtin_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
match a_def { match a_def {
def::DefTy(did, _) | def::DefTy(did, _) |
def::DefStruct(did) if Some(did) == this.tcx().lang_items.owned_box() => { def::DefStruct(did) if Some(did) == this.tcx().lang_items.owned_box() => {
let ty = ast_path_to_ty(this, rscope, did, path, id).ty; let ty = ast_path_to_ty(this, rscope, did, path).ty;
match ty::get(ty).sty { match ty::get(ty).sty {
ty::ty_struct(struct_def_id, ref substs) => { ty::ty_struct(struct_def_id, ref substs) => {
assert_eq!(struct_def_id, did); assert_eq!(struct_def_id, did);
...@@ -689,8 +684,7 @@ fn mk_pointer<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( ...@@ -689,8 +684,7 @@ fn mk_pointer<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
trait_def_id, trait_def_id,
None, None,
None, None,
path, path);
id);
let empty_vec = []; let empty_vec = [];
let bounds = match *opt_bounds { None => empty_vec.as_slice(), let bounds = match *opt_bounds { None => empty_vec.as_slice(),
Some(ref bounds) => bounds.as_slice() }; Some(ref bounds) => bounds.as_slice() };
...@@ -752,12 +746,7 @@ fn associated_ty_to_ty<'tcx,AC,RS>(this: &AC, ...@@ -752,12 +746,7 @@ fn associated_ty_to_ty<'tcx,AC,RS>(this: &AC,
trait_did, trait_did,
None, None,
Some(for_type), Some(for_type),
trait_path, trait_path);
ast::DUMMY_NODE_ID); // *see below
// * The trait in a qualified path cannot be "higher-ranked" and
// hence cannot use the parenthetical sugar, so the binder-id is
// irrelevant.
debug!("associated_ty_to_ty(trait_ref={})", debug!("associated_ty_to_ty(trait_ref={})",
trait_ref.repr(this.tcx())); trait_ref.repr(this.tcx()));
...@@ -830,8 +819,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( ...@@ -830,8 +819,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
tcx.sess.span_err(ast_ty.span, tcx.sess.span_err(ast_ty.span,
"variadic function must have C calling convention"); "variadic function must have C calling convention");
} }
ty::mk_bare_fn(tcx, ty_of_bare_fn(this, ast_ty.id, bf.fn_style, ty::mk_bare_fn(tcx, ty_of_bare_fn(this, bf.fn_style, bf.abi, &*bf.decl))
bf.abi, &*bf.decl))
} }
ast::TyClosure(ref f) => { ast::TyClosure(ref f) => {
// Use corresponding trait store to figure out default bounds // Use corresponding trait store to figure out default bounds
...@@ -842,7 +830,6 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( ...@@ -842,7 +830,6 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
[].as_slice(), [].as_slice(),
f.bounds.as_slice()); f.bounds.as_slice());
let fn_decl = ty_of_closure(this, let fn_decl = ty_of_closure(this,
ast_ty.id,
f.fn_style, f.fn_style,
f.onceness, f.onceness,
bounds, bounds,
...@@ -863,7 +850,6 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( ...@@ -863,7 +850,6 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
f.bounds.as_slice()); f.bounds.as_slice());
let fn_decl = ty_of_closure(this, let fn_decl = ty_of_closure(this,
ast_ty.id,
f.fn_style, f.fn_style,
f.onceness, f.onceness,
bounds, bounds,
...@@ -910,8 +896,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( ...@@ -910,8 +896,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
trait_def_id, trait_def_id,
None, None,
None, None,
path, path);
id);
let empty_bounds: &[ast::TyParamBound] = &[]; let empty_bounds: &[ast::TyParamBound] = &[];
let ast_bounds = match *bounds { let ast_bounds = match *bounds {
Some(ref b) => b.as_slice(), Some(ref b) => b.as_slice(),
...@@ -927,7 +912,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( ...@@ -927,7 +912,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
bounds) bounds)
} }
def::DefTy(did, _) | def::DefStruct(did) => { def::DefTy(did, _) | def::DefStruct(did) => {
ast_path_to_ty(this, rscope, did, path, id).ty ast_path_to_ty(this, rscope, did, path).ty
} }
def::DefTyParam(space, id, n) => { def::DefTyParam(space, id, n) => {
check_path_args(tcx, path, NO_TPS | NO_REGIONS); check_path_args(tcx, path, NO_TPS | NO_REGIONS);
...@@ -1056,7 +1041,6 @@ struct SelfInfo<'a> { ...@@ -1056,7 +1041,6 @@ struct SelfInfo<'a> {
pub fn ty_of_method<'tcx, AC: AstConv<'tcx>>( pub fn ty_of_method<'tcx, AC: AstConv<'tcx>>(
this: &AC, this: &AC,
id: ast::NodeId,
fn_style: ast::FnStyle, fn_style: ast::FnStyle,
untransformed_self_ty: ty::t, untransformed_self_ty: ty::t,
explicit_self: &ast::ExplicitSelf, explicit_self: &ast::ExplicitSelf,
...@@ -1069,7 +1053,6 @@ pub fn ty_of_method<'tcx, AC: AstConv<'tcx>>( ...@@ -1069,7 +1053,6 @@ pub fn ty_of_method<'tcx, AC: AstConv<'tcx>>(
}); });
let (bare_fn_ty, optional_explicit_self_category) = let (bare_fn_ty, optional_explicit_self_category) =
ty_of_method_or_bare_fn(this, ty_of_method_or_bare_fn(this,
id,
fn_style, fn_style,
abi, abi,
self_info, self_info,
...@@ -1077,17 +1060,14 @@ pub fn ty_of_method<'tcx, AC: AstConv<'tcx>>( ...@@ -1077,17 +1060,14 @@ pub fn ty_of_method<'tcx, AC: AstConv<'tcx>>(
(bare_fn_ty, optional_explicit_self_category.unwrap()) (bare_fn_ty, optional_explicit_self_category.unwrap())
} }
pub fn ty_of_bare_fn<'tcx, AC: AstConv<'tcx>>(this: &AC, id: ast::NodeId, pub fn ty_of_bare_fn<'tcx, AC: AstConv<'tcx>>(this: &AC, fn_style: ast::FnStyle, abi: abi::Abi,
fn_style: ast::FnStyle, abi: abi::Abi,
decl: &ast::FnDecl) -> ty::BareFnTy { decl: &ast::FnDecl) -> ty::BareFnTy {
let (bare_fn_ty, _) = let (bare_fn_ty, _) = ty_of_method_or_bare_fn(this, fn_style, abi, None, decl);
ty_of_method_or_bare_fn(this, id, fn_style, abi, None, decl);
bare_fn_ty bare_fn_ty
} }
fn ty_of_method_or_bare_fn<'tcx, AC: AstConv<'tcx>>( fn ty_of_method_or_bare_fn<'tcx, AC: AstConv<'tcx>>(
this: &AC, this: &AC,
id: ast::NodeId,
fn_style: ast::FnStyle, fn_style: ast::FnStyle,
abi: abi::Abi, abi: abi::Abi,
opt_self_info: Option<SelfInfo>, opt_self_info: Option<SelfInfo>,
...@@ -1098,7 +1078,7 @@ fn ty_of_method_or_bare_fn<'tcx, AC: AstConv<'tcx>>( ...@@ -1098,7 +1078,7 @@ fn ty_of_method_or_bare_fn<'tcx, AC: AstConv<'tcx>>(
// New region names that appear inside of the arguments of the function // New region names that appear inside of the arguments of the function
// declaration are bound to that function type. // declaration are bound to that function type.
let rb = rscope::BindingRscope::new(id); let rb = rscope::BindingRscope::new();
// `implied_output_region` is the region that will be assumed for any // `implied_output_region` is the region that will be assumed for any
// region parameters in the return type. In accordance with the rules for // region parameters in the return type. In accordance with the rules for
...@@ -1114,7 +1094,9 @@ fn ty_of_method_or_bare_fn<'tcx, AC: AstConv<'tcx>>( ...@@ -1114,7 +1094,9 @@ fn ty_of_method_or_bare_fn<'tcx, AC: AstConv<'tcx>>(
determine_explicit_self_category(this, &rb, &self_info); determine_explicit_self_category(this, &rb, &self_info);
explicit_self_category_result = Some(explicit_self_category); explicit_self_category_result = Some(explicit_self_category);
match explicit_self_category { match explicit_self_category {
ty::StaticExplicitSelfCategory => (None, None), ty::StaticExplicitSelfCategory => {
(None, None)
}
ty::ByValueExplicitSelfCategory => { ty::ByValueExplicitSelfCategory => {
(Some(self_info.untransformed_self_ty), None) (Some(self_info.untransformed_self_ty), None)
} }
...@@ -1205,7 +1187,6 @@ fn ty_of_method_or_bare_fn<'tcx, AC: AstConv<'tcx>>( ...@@ -1205,7 +1187,6 @@ fn ty_of_method_or_bare_fn<'tcx, AC: AstConv<'tcx>>(
fn_style: fn_style, fn_style: fn_style,
abi: abi, abi: abi,
sig: ty::FnSig { sig: ty::FnSig {
binder_id: id,
inputs: self_and_input_tys, inputs: self_and_input_tys,
output: output_ty, output: output_ty,
variadic: decl.variadic variadic: decl.variadic
...@@ -1290,7 +1271,6 @@ fn determine_explicit_self_category<'tcx, AC: AstConv<'tcx>, ...@@ -1290,7 +1271,6 @@ fn determine_explicit_self_category<'tcx, AC: AstConv<'tcx>,
pub fn ty_of_closure<'tcx, AC: AstConv<'tcx>>( pub fn ty_of_closure<'tcx, AC: AstConv<'tcx>>(
this: &AC, this: &AC,
id: ast::NodeId,
fn_style: ast::FnStyle, fn_style: ast::FnStyle,
onceness: ast::Onceness, onceness: ast::Onceness,
bounds: ty::ExistentialBounds, bounds: ty::ExistentialBounds,
...@@ -1300,13 +1280,14 @@ pub fn ty_of_closure<'tcx, AC: AstConv<'tcx>>( ...@@ -1300,13 +1280,14 @@ pub fn ty_of_closure<'tcx, AC: AstConv<'tcx>>(
expected_sig: Option<ty::FnSig>) expected_sig: Option<ty::FnSig>)
-> ty::ClosureTy -> ty::ClosureTy
{ {
debug!("ty_of_fn_decl"); debug!("ty_of_closure(expected_sig={})",
expected_sig.repr(this.tcx()));
// new region names that appear inside of the fn decl are bound to // new region names that appear inside of the fn decl are bound to
// that function type // that function type
let rb = rscope::BindingRscope::new(id); let rb = rscope::BindingRscope::new();
let input_tys = decl.inputs.iter().enumerate().map(|(i, a)| { let input_tys: Vec<_> = decl.inputs.iter().enumerate().map(|(i, a)| {
let expected_arg_ty = expected_sig.as_ref().and_then(|e| { let expected_arg_ty = expected_sig.as_ref().and_then(|e| {
// no guarantee that the correct number of expected args // no guarantee that the correct number of expected args
// were supplied // were supplied
...@@ -1331,14 +1312,16 @@ pub fn ty_of_closure<'tcx, AC: AstConv<'tcx>>( ...@@ -1331,14 +1312,16 @@ pub fn ty_of_closure<'tcx, AC: AstConv<'tcx>>(
ast::NoReturn(_) => ty::FnDiverging ast::NoReturn(_) => ty::FnDiverging
}; };
debug!("ty_of_closure: input_tys={}", input_tys.repr(this.tcx()));
debug!("ty_of_closure: output_ty={}", output_ty.repr(this.tcx()));
ty::ClosureTy { ty::ClosureTy {
fn_style: fn_style, fn_style: fn_style,
onceness: onceness, onceness: onceness,
store: store, store: store,
bounds: bounds, bounds: bounds,
abi: abi, abi: abi,
sig: ty::FnSig {binder_id: id, sig: ty::FnSig {inputs: input_tys,
inputs: input_tys,
output: output_ty, output: output_ty,
variadic: decl.variadic} variadic: decl.variadic}
} }
......
...@@ -528,9 +528,7 @@ fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>, ...@@ -528,9 +528,7 @@ fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
// First, we have to replace any bound regions in the fn type with free ones. // First, we have to replace any bound regions in the fn type with free ones.
// The free region references will be bound the node_id of the body block. // The free region references will be bound the node_id of the body block.
let (_, fn_sig) = replace_late_bound_regions(tcx, fn_sig.binder_id, fn_sig, |br| { let fn_sig = liberate_late_bound_regions(tcx, body.id, fn_sig);
ty::ReFree(ty::FreeRegion {scope_id: body.id, bound_region: br})
});
let arg_tys = fn_sig.inputs.as_slice(); let arg_tys = fn_sig.inputs.as_slice();
let ret_ty = fn_sig.output; let ret_ty = fn_sig.output;
...@@ -3031,7 +3029,6 @@ fn check_call<'a>(fcx: &FnCtxt, ...@@ -3031,7 +3029,6 @@ fn check_call<'a>(fcx: &FnCtxt,
// In that case, we check each argument against "error" in order to // In that case, we check each argument against "error" in order to
// set up all the node type bindings. // set up all the node type bindings.
let error_fn_sig = FnSig { let error_fn_sig = FnSig {
binder_id: ast::CRATE_NODE_ID,
inputs: err_args(args.len()), inputs: err_args(args.len()),
output: ty::FnConverging(ty::mk_err()), output: ty::FnConverging(ty::mk_err()),
variadic: false variadic: false
...@@ -3051,9 +3048,7 @@ fn check_call<'a>(fcx: &FnCtxt, ...@@ -3051,9 +3048,7 @@ fn check_call<'a>(fcx: &FnCtxt,
// Replace any bound regions that appear in the function // Replace any bound regions that appear in the function
// signature with region variables // signature with region variables
let fn_sig = let fn_sig =
fcx.infcx().replace_late_bound_regions_with_fresh_var( fcx.infcx().replace_late_bound_regions_with_fresh_var(call_expr.span,
fn_sig.binder_id,
call_expr.span,
infer::FnCall, infer::FnCall,
fn_sig).0; fn_sig).0;
...@@ -3437,7 +3432,6 @@ fn check_unboxed_closure(fcx: &FnCtxt, ...@@ -3437,7 +3432,6 @@ fn check_unboxed_closure(fcx: &FnCtxt,
body: &ast::Block) { body: &ast::Block) {
let mut fn_ty = astconv::ty_of_closure( let mut fn_ty = astconv::ty_of_closure(
fcx, fcx,
expr.id,
ast::NormalFn, ast::NormalFn,
ast::Many, ast::Many,
...@@ -3508,6 +3502,10 @@ fn check_expr_fn(fcx: &FnCtxt, ...@@ -3508,6 +3502,10 @@ fn check_expr_fn(fcx: &FnCtxt,
expected: Expectation) { expected: Expectation) {
let tcx = fcx.ccx.tcx; let tcx = fcx.ccx.tcx;
debug!("check_expr_fn(expr={}, expected={})",
expr.repr(tcx),
expected.repr(tcx));
// Find the expected input/output types (if any). Substitute // Find the expected input/output types (if any). Substitute
// fresh bound regions for any bound regions we find in the // fresh bound regions for any bound regions we find in the
// expected types so as to avoid capture. // expected types so as to avoid capture.
...@@ -3517,10 +3515,11 @@ fn check_expr_fn(fcx: &FnCtxt, ...@@ -3517,10 +3515,11 @@ fn check_expr_fn(fcx: &FnCtxt,
expected_bounds) = { expected_bounds) = {
match expected_sty { match expected_sty {
Some(ty::ty_closure(ref cenv)) => { Some(ty::ty_closure(ref cenv)) => {
let (_, sig) = let (sig, _) =
replace_late_bound_regions( replace_late_bound_regions(
tcx, cenv.sig.binder_id, &cenv.sig, tcx,
|_| fcx.inh.infcx.fresh_bound_region(expr.id)); &cenv.sig,
|_, debruijn| fcx.inh.infcx.fresh_bound_region(debruijn));
let onceness = match (&store, &cenv.store) { let onceness = match (&store, &cenv.store) {
// As the closure type and onceness go, only three // As the closure type and onceness go, only three
// combinations are legit: // combinations are legit:
...@@ -3561,7 +3560,6 @@ fn check_expr_fn(fcx: &FnCtxt, ...@@ -3561,7 +3560,6 @@ fn check_expr_fn(fcx: &FnCtxt,
// construct the function type // construct the function type
let fn_ty = astconv::ty_of_closure(fcx, let fn_ty = astconv::ty_of_closure(fcx,
expr.id,
ast::NormalFn, ast::NormalFn,
expected_onceness, expected_onceness,
expected_bounds, expected_bounds,
...@@ -5943,7 +5941,6 @@ fn param(ccx: &CrateCtxt, n: uint) -> ty::t { ...@@ -5943,7 +5941,6 @@ fn param(ccx: &CrateCtxt, n: uint) -> ty::t {
fn_style: ast::UnsafeFn, fn_style: ast::UnsafeFn,
abi: abi::RustIntrinsic, abi: abi::RustIntrinsic,
sig: FnSig { sig: FnSig {
binder_id: it.id,
inputs: inputs, inputs: inputs,
output: output, output: output,
variadic: false, variadic: false,
......
...@@ -14,47 +14,14 @@ ...@@ -14,47 +14,14 @@
use middle::subst::{ParamSpace, Subst, Substs}; use middle::subst::{ParamSpace, Subst, Substs};
use middle::ty; use middle::ty;
use middle::ty_fold; use middle::ty_fold::{TypeFolder};
use middle::ty_fold::{TypeFolder, TypeFoldable};
use syntax::ast; use syntax::ast;
use std::collections::hash_map::{Occupied, Vacant};
use util::nodemap::FnvHashMap;
use util::ppaux::Repr; use util::ppaux::Repr;
// Helper functions related to manipulating region types. // Helper functions related to manipulating region types.
pub fn replace_late_bound_regions<T>(
tcx: &ty::ctxt,
binder_id: ast::NodeId,
value: &T,
map_fn: |ty::BoundRegion| -> ty::Region)
-> (FnvHashMap<ty::BoundRegion,ty::Region>, T)
where T : TypeFoldable + Repr
{
debug!("replace_late_bound_regions(binder_id={}, value={})",
binder_id, value.repr(tcx));
let mut map = FnvHashMap::new();
let new_value = {
let mut folder = ty_fold::RegionFolder::regions(tcx, |r| {
match r {
ty::ReLateBound(s, br) if s == binder_id => {
match map.entry(br) {
Vacant(entry) => *entry.set(map_fn(br)),
Occupied(entry) => *entry.into_mut(),
}
}
_ => r
}
});
value.fold_with(&mut folder)
};
debug!("resulting map: {}", map);
(map, new_value)
}
pub enum WfConstraint { pub enum WfConstraint {
RegionSubRegionConstraint(Option<ty::t>, ty::Region, ty::Region), RegionSubRegionConstraint(Option<ty::t>, ty::Region, ty::Region),
RegionSubParamConstraint(Option<ty::t>, ty::Region, ty::ParamTy), RegionSubParamConstraint(Option<ty::t>, ty::Region, ty::ParamTy),
......
...@@ -372,16 +372,12 @@ fn fold_ty(&mut self, t: ty::t) -> ty::t { ...@@ -372,16 +372,12 @@ fn fold_ty(&mut self, t: ty::t) -> ty::t {
ty::ty_closure(box ty::ClosureTy{sig: ref fn_sig, ..}) => { ty::ty_closure(box ty::ClosureTy{sig: ref fn_sig, ..}) => {
self.binding_count += 1; self.binding_count += 1;
let (_, fn_sig) = let fn_sig = liberate_late_bound_regions(self.fcx.tcx(), self.scope_id, fn_sig);
replace_late_bound_regions(
self.fcx.tcx(), fn_sig.binder_id, fn_sig,
|br| ty::ReFree(ty::FreeRegion{scope_id: self.scope_id,
bound_region: br}));
debug!("late-bound regions replaced: {}", debug!("late-bound regions replaced: {}",
fn_sig.repr(self.tcx())); fn_sig.repr(self.tcx()));
self.fold_sig(&fn_sig); self.fold_fn_sig(&fn_sig);
self.binding_count -= 1; self.binding_count -= 1;
} }
......
...@@ -214,12 +214,11 @@ pub fn get_enum_variant_types(ccx: &CrateCtxt, ...@@ -214,12 +214,11 @@ pub fn get_enum_variant_types(ccx: &CrateCtxt,
for variant in variants.iter() { for variant in variants.iter() {
// Nullary enum constructors get turned into constants; n-ary enum // Nullary enum constructors get turned into constants; n-ary enum
// constructors get turned into functions. // constructors get turned into functions.
let scope = variant.node.id;
let result_ty = match variant.node.kind { let result_ty = match variant.node.kind {
ast::TupleVariantKind(ref args) if args.len() > 0 => { ast::TupleVariantKind(ref args) if args.len() > 0 => {
let rs = ExplicitRscope; let rs = ExplicitRscope;
let input_tys: Vec<_> = args.iter().map(|va| ccx.to_ty(&rs, &*va.ty)).collect(); let input_tys: Vec<_> = args.iter().map(|va| ccx.to_ty(&rs, &*va.ty)).collect();
ty::mk_ctor_fn(tcx, scope, input_tys.as_slice(), enum_ty) ty::mk_ctor_fn(tcx, input_tys.as_slice(), enum_ty)
} }
ast::TupleVariantKind(_) => { ast::TupleVariantKind(_) => {
...@@ -403,7 +402,6 @@ fn ty_method_of_trait_method(ccx: &CrateCtxt, ...@@ -403,7 +402,6 @@ fn ty_method_of_trait_method(ccx: &CrateCtxt,
let trait_self_ty = ty::mk_self_type(tmcx.tcx(), let trait_self_ty = ty::mk_self_type(tmcx.tcx(),
local_def(trait_id)); local_def(trait_id));
astconv::ty_of_method(&tmcx, astconv::ty_of_method(&tmcx,
*m_id,
*m_fn_style, *m_fn_style,
trait_self_ty, trait_self_ty,
m_explicit_self, m_explicit_self,
...@@ -588,7 +586,6 @@ fn ty_of_method(ccx: &CrateCtxt, ...@@ -588,7 +586,6 @@ fn ty_of_method(ccx: &CrateCtxt,
method_generics: &m_ty_generics, method_generics: &m_ty_generics,
}; };
astconv::ty_of_method(&imcx, astconv::ty_of_method(&imcx,
m.id,
m.pe_fn_style(), m.pe_fn_style(),
untransformed_rcvr_ty, untransformed_rcvr_ty,
m.pe_explicit_self(), m.pe_explicit_self(),
...@@ -603,7 +600,6 @@ fn ty_of_method(ccx: &CrateCtxt, ...@@ -603,7 +600,6 @@ fn ty_of_method(ccx: &CrateCtxt,
method_generics: &m_ty_generics, method_generics: &m_ty_generics,
}; };
astconv::ty_of_method(&tmcx, astconv::ty_of_method(&tmcx,
m.id,
m.pe_fn_style(), m.pe_fn_style(),
untransformed_rcvr_ty, untransformed_rcvr_ty,
m.pe_explicit_self(), m.pe_explicit_self(),
...@@ -1294,7 +1290,6 @@ pub fn convert_struct(ccx: &CrateCtxt, ...@@ -1294,7 +1290,6 @@ pub fn convert_struct(ccx: &CrateCtxt,
|field| (*tcx.tcache.borrow())[ |field| (*tcx.tcache.borrow())[
local_def(field.node.id)].ty).collect(); local_def(field.node.id)].ty).collect();
let ctor_fn_ty = ty::mk_ctor_fn(tcx, let ctor_fn_ty = ty::mk_ctor_fn(tcx,
ctor_id,
inputs.as_slice(), inputs.as_slice(),
selfty); selfty);
write_ty_to_tcx(tcx, ctor_id, ctor_fn_ty); write_ty_to_tcx(tcx, ctor_id, ctor_fn_ty);
...@@ -1465,11 +1460,7 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: &ast::Item) ...@@ -1465,11 +1460,7 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: &ast::Item)
ccx: ccx, ccx: ccx,
generics: &ty_generics, generics: &ty_generics,
}; };
astconv::ty_of_bare_fn(&fcx, astconv::ty_of_bare_fn(&fcx, fn_style, abi, &**decl)
it.id,
fn_style,
abi,
&**decl)
}; };
let pty = Polytype { let pty = Polytype {
generics: ty_generics, generics: ty_generics,
...@@ -2091,7 +2082,7 @@ pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt, ...@@ -2091,7 +2082,7 @@ pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt,
ast_generics, ast_generics,
ty::Generics::empty(), ty::Generics::empty(),
DontCreateTypeParametersForAssociatedTypes); DontCreateTypeParametersForAssociatedTypes);
let rb = BindingRscope::new(def_id.node); let rb = BindingRscope::new();
let input_tys = decl.inputs let input_tys = decl.inputs
.iter() .iter()
.map(|a| ty_of_arg(ccx, &rb, a, None)) .map(|a| ty_of_arg(ccx, &rb, a, None))
...@@ -2109,8 +2100,7 @@ pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt, ...@@ -2109,8 +2100,7 @@ pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt,
ty::BareFnTy { ty::BareFnTy {
abi: abi, abi: abi,
fn_style: ast::UnsafeFn, fn_style: ast::UnsafeFn,
sig: ty::FnSig {binder_id: def_id.node, sig: ty::FnSig {inputs: input_tys,
inputs: input_tys,
output: output, output: output,
variadic: decl.variadic} variadic: decl.variadic}
}); });
......
...@@ -334,48 +334,6 @@ pub fn expected_found<'tcx, C: Combine<'tcx>, T>( ...@@ -334,48 +334,6 @@ pub fn expected_found<'tcx, C: Combine<'tcx>, T>(
} }
} }
pub fn super_fn_sigs<'tcx, C: Combine<'tcx>>(this: &C,
a: &ty::FnSig,
b: &ty::FnSig)
-> cres<ty::FnSig> {
fn argvecs<'tcx, C: Combine<'tcx>>(this: &C,
a_args: &[ty::t],
b_args: &[ty::t])
-> cres<Vec<ty::t>> {
if a_args.len() == b_args.len() {
a_args.iter().zip(b_args.iter())
.map(|(a, b)| this.args(*a, *b)).collect()
} else {
Err(ty::terr_arg_count)
}
}
if a.variadic != b.variadic {
return Err(ty::terr_variadic_mismatch(expected_found(this, a.variadic, b.variadic)));
}
let inputs = try!(argvecs(this,
a.inputs.as_slice(),
b.inputs.as_slice()));
let output = try!(match (a.output, b.output) {
(ty::FnConverging(a_ty), ty::FnConverging(b_ty)) =>
Ok(ty::FnConverging(try!(this.tys(a_ty, b_ty)))),
(ty::FnDiverging, ty::FnDiverging) =>
Ok(ty::FnDiverging),
(a, b) =>
Err(ty::terr_convergence_mismatch(
expected_found(this, a != ty::FnDiverging, b != ty::FnDiverging)
)),
});
Ok(FnSig {binder_id: a.binder_id,
inputs: inputs,
output: output,
variadic: a.variadic})
}
pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C, a: ty::t, b: ty::t) -> cres<ty::t> { pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C, a: ty::t, b: ty::t) -> cres<ty::t> {
let tcx = this.infcx().tcx; let tcx = this.infcx().tcx;
......
...@@ -125,4 +125,8 @@ fn tys(&self, a: ty::t, b: ty::t) -> cres<ty::t> { ...@@ -125,4 +125,8 @@ fn tys(&self, a: ty::t, b: ty::t) -> cres<ty::t> {
fn fn_sigs(&self, a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig> { fn fn_sigs(&self, a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig> {
self.higher_ranked_glb(a, b) self.higher_ranked_glb(a, b)
} }
fn trait_refs(&self, a: &ty::TraitRef, b: &ty::TraitRef) -> cres<ty::TraitRef> {
self.higher_ranked_glb(a, b)
}
} }
...@@ -797,8 +797,8 @@ pub fn fresh_substs_for_trait(&self, ...@@ -797,8 +797,8 @@ pub fn fresh_substs_for_trait(&self,
subst::Substs::new_trait(type_parameters, regions, assoc_type_parameters, self_ty) subst::Substs::new_trait(type_parameters, regions, assoc_type_parameters, self_ty)
} }
pub fn fresh_bound_region(&self, binder_id: ast::NodeId) -> ty::Region { pub fn fresh_bound_region(&self, debruijn: ty::DebruijnIndex) -> ty::Region {
self.region_vars.new_bound(binder_id) self.region_vars.new_bound(debruijn)
} }
pub fn resolve_regions_and_report_errors(&self) { pub fn resolve_regions_and_report_errors(&self) {
...@@ -968,30 +968,19 @@ pub fn report_mismatched_types(&self, ...@@ -968,30 +968,19 @@ pub fn report_mismatched_types(&self,
pub fn replace_late_bound_regions_with_fresh_var<T>( pub fn replace_late_bound_regions_with_fresh_var<T>(
&self, &self,
binder_id: ast::NodeId,
span: Span, span: Span,
lbrct: LateBoundRegionConversionTime, lbrct: LateBoundRegionConversionTime,
value: &T) value: &T)
-> (T, FnvHashMap<ty::BoundRegion,ty::Region>) -> (T, FnvHashMap<ty::BoundRegion,ty::Region>)
where T : TypeFoldable + Repr where T : HigherRankedFoldable
{ {
let (map, value) = ty::replace_late_bound_regions(
replace_late_bound_regions(
self.tcx, self.tcx,
binder_id,
value, value,
|br| self.next_region_var(LateBoundRegion(span, br, lbrct))); |br, _| self.next_region_var(LateBoundRegion(span, br, lbrct)))
(value, map)
} }
} }
pub fn fold_regions_in_sig(tcx: &ty::ctxt,
fn_sig: &ty::FnSig,
fldr: |r: ty::Region| -> ty::Region)
-> ty::FnSig {
ty_fold::RegionFolder::regions(tcx, fldr).fold_sig(fn_sig)
}
impl TypeTrace { impl TypeTrace {
pub fn span(&self) -> Span { pub fn span(&self) -> Span {
self.origin.span() self.origin.span()
......
...@@ -332,7 +332,7 @@ pub fn new_skolemized(&self, br: ty::BoundRegion) -> Region { ...@@ -332,7 +332,7 @@ pub fn new_skolemized(&self, br: ty::BoundRegion) -> Region {
ReInfer(ReSkolemized(sc, br)) ReInfer(ReSkolemized(sc, br))
} }
pub fn new_bound(&self, binder_id: ast::NodeId) -> Region { pub fn new_bound(&self, debruijn: ty::DebruijnIndex) -> Region {
// Creates a fresh bound variable for use in GLB computations. // Creates a fresh bound variable for use in GLB computations.
// See discussion of GLB computation in the large comment at // See discussion of GLB computation in the large comment at
// the top of this file for more details. // the top of this file for more details.
...@@ -358,7 +358,7 @@ pub fn new_bound(&self, binder_id: ast::NodeId) -> Region { ...@@ -358,7 +358,7 @@ pub fn new_bound(&self, binder_id: ast::NodeId) -> Region {
self.tcx.sess.bug("rollover in RegionInference new_bound()"); self.tcx.sess.bug("rollover in RegionInference new_bound()");
} }
ReLateBound(binder_id, BrFresh(sc)) ReLateBound(debruijn, BrFresh(sc))
} }
fn values_are_none(&self) -> bool { fn values_are_none(&self) -> bool {
......
...@@ -383,7 +383,6 @@ fn check_main_fn_ty(ccx: &CrateCtxt, ...@@ -383,7 +383,6 @@ fn check_main_fn_ty(ccx: &CrateCtxt,
fn_style: ast::NormalFn, fn_style: ast::NormalFn,
abi: abi::Rust, abi: abi::Rust,
sig: ty::FnSig { sig: ty::FnSig {
binder_id: main_id,
inputs: Vec::new(), inputs: Vec::new(),
output: ty::FnConverging(ty::mk_nil(tcx)), output: ty::FnConverging(ty::mk_nil(tcx)),
variadic: false variadic: false
...@@ -432,7 +431,6 @@ fn check_start_fn_ty(ccx: &CrateCtxt, ...@@ -432,7 +431,6 @@ fn check_start_fn_ty(ccx: &CrateCtxt,
fn_style: ast::NormalFn, fn_style: ast::NormalFn,
abi: abi::Rust, abi: abi::Rust,
sig: ty::FnSig { sig: ty::FnSig {
binder_id: start_id,
inputs: vec!( inputs: vec!(
ty::mk_int(), ty::mk_int(),
ty::mk_imm_ptr(tcx, ty::mk_imm_ptr(tcx, ty::mk_u8())) ty::mk_imm_ptr(tcx, ty::mk_imm_ptr(tcx, ty::mk_u8()))
......
...@@ -104,14 +104,12 @@ fn anon_regions(&self, ...@@ -104,14 +104,12 @@ fn anon_regions(&self,
/// A scope in which we generate anonymous, late-bound regions for /// A scope in which we generate anonymous, late-bound regions for
/// omitted regions. This occurs in function signatures. /// omitted regions. This occurs in function signatures.
pub struct BindingRscope { pub struct BindingRscope {
binder_id: ast::NodeId,
anon_bindings: Cell<uint>, anon_bindings: Cell<uint>,
} }
impl BindingRscope { impl BindingRscope {
pub fn new(binder_id: ast::NodeId) -> BindingRscope { pub fn new() -> BindingRscope {
BindingRscope { BindingRscope {
binder_id: binder_id,
anon_bindings: Cell::new(0), anon_bindings: Cell::new(0),
} }
} }
...@@ -119,7 +117,7 @@ pub fn new(binder_id: ast::NodeId) -> BindingRscope { ...@@ -119,7 +117,7 @@ pub fn new(binder_id: ast::NodeId) -> BindingRscope {
fn next_region(&self) -> ty::Region { fn next_region(&self) -> ty::Region {
let idx = self.anon_bindings.get(); let idx = self.anon_bindings.get();
self.anon_bindings.set(idx + 1); self.anon_bindings.set(idx + 1);
ty::ReLateBound(self.binder_id, ty::BrAnon(idx)) ty::ReLateBound(ty::DebruijnIndex::new(1), ty::BrAnon(idx))
} }
} }
......
...@@ -252,8 +252,7 @@ pub fn vec_map_to_string<T>(ts: &[T], f: |t: &T| -> String) -> String { ...@@ -252,8 +252,7 @@ pub fn vec_map_to_string<T>(ts: &[T], f: |t: &T| -> String) -> String {
} }
pub fn fn_sig_to_string(cx: &ctxt, typ: &ty::FnSig) -> String { pub fn fn_sig_to_string(cx: &ctxt, typ: &ty::FnSig) -> String {
format!("fn{}{} -> {}", typ.binder_id, typ.inputs.repr(cx), format!("fn{} -> {}", typ.inputs.repr(cx), typ.output.repr(cx))
typ.output.repr(cx))
} }
pub fn trait_ref_to_string(cx: &ctxt, trait_ref: &ty::TraitRef) -> String { pub fn trait_ref_to_string(cx: &ctxt, trait_ref: &ty::TraitRef) -> String {
...@@ -1301,3 +1300,8 @@ fn repr(&self, tcx: &ctxt) -> String { ...@@ -1301,3 +1300,8 @@ fn repr(&self, tcx: &ctxt) -> String {
} }
} }
impl<T:Repr> Repr for ty::Binder<T> {
fn repr(&self, tcx: &ctxt) -> String {
format!("Binder({})", self.value.repr(tcx))
}
}
此差异已折叠。
...@@ -269,7 +269,6 @@ pub fn trans_unboxing_shim(bcx: Block, ...@@ -269,7 +269,6 @@ pub fn trans_unboxing_shim(bcx: Block,
let self_type = fty.sig.inputs[0]; let self_type = fty.sig.inputs[0];
let boxed_self_type = ty::mk_uniq(tcx, self_type); let boxed_self_type = ty::mk_uniq(tcx, self_type);
let boxed_function_type = ty::FnSig { let boxed_function_type = ty::FnSig {
binder_id: fty.sig.binder_id,
inputs: fty.sig.inputs.iter().enumerate().map(|(i, typ)| { inputs: fty.sig.inputs.iter().enumerate().map(|(i, typ)| {
if i == 0 { if i == 0 {
boxed_self_type boxed_self_type
...@@ -294,7 +293,6 @@ pub fn trans_unboxing_shim(bcx: Block, ...@@ -294,7 +293,6 @@ pub fn trans_unboxing_shim(bcx: Block,
// RustCall so the untupled arguments can be passed // RustCall so the untupled arguments can be passed
// through verbatim. This is kind of ugly. // through verbatim. This is kind of ugly.
let fake_ty = ty::FnSig { let fake_ty = ty::FnSig {
binder_id: fty.sig.binder_id,
inputs: type_of::untuple_arguments_if_necessary(ccx, inputs: type_of::untuple_arguments_if_necessary(ccx,
fty.sig.inputs.as_slice(), fty.sig.inputs.as_slice(),
fty.abi), fty.abi),
......
...@@ -609,9 +609,6 @@ pub fn get_vtable(bcx: Block, ...@@ -609,9 +609,6 @@ pub fn get_vtable(bcx: Block,
fn_style: closure_info.closure_type.fn_style, fn_style: closure_info.closure_type.fn_style,
abi: Rust, abi: Rust,
sig: ty::FnSig { sig: ty::FnSig {
binder_id: closure_info.closure_type
.sig
.binder_id,
inputs: new_inputs, inputs: new_inputs,
output: new_output, output: new_output,
variadic: false, variadic: false,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册