提交 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 {
match next(st) {
'b' => {
assert_eq!(next(st), '[');
let id = parse_uint(st) as ast::NodeId;
let id = ty::DebruijnIndex::new(parse_uint(st));
assert_eq!(next(st), '|');
let br = parse_bound_region(st, |x,y| conv(x,y));
assert_eq!(next(st), ']');
......@@ -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 {
assert_eq!(next(st), '[');
let id = parse_uint(st) as ast::NodeId;
assert_eq!(next(st), '|');
let mut inputs = Vec::new();
while peek(st) != ']' {
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 {
}
_ => ty::FnConverging(parse_ty(st, |x,y| conv(x,y)))
};
ty::FnSig {binder_id: id,
inputs: inputs,
ty::FnSig {inputs: inputs,
output: output,
variadic: variadic}
}
......
......@@ -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) {
match r {
ty::ReLateBound(id, br) => {
mywrite!(w, "b[{}|", id);
mywrite!(w, "b[{}|", id.depth);
enc_bound_region(w, cx, br);
mywrite!(w, "]");
}
......@@ -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) {
mywrite!(w, "[{}|", fsig.binder_id);
mywrite!(w, "[");
for ty in fsig.inputs.iter() {
enc_ty(w, cx, *ty);
}
......
......@@ -483,8 +483,8 @@ fn tr(&self, dcx: &DecodeContext) -> def::Def {
impl tr for ty::Region {
fn tr(&self, dcx: &DecodeContext) -> ty::Region {
match *self {
ty::ReLateBound(id, br) => {
ty::ReLateBound(dcx.tr_id(id), br.tr(dcx))
ty::ReLateBound(debruijn, br) => {
ty::ReLateBound(debruijn, br.tr(dcx))
}
ty::ReEarlyBound(id, space, index, ident) => {
ty::ReEarlyBound(dcx.tr_id(id), space, index, ident)
......
......@@ -39,8 +39,7 @@ pub enum DefRegion {
DefEarlyBoundRegion(/* space */ subst::ParamSpace,
/* index */ uint,
/* lifetime decl */ ast::NodeId),
DefLateBoundRegion(/* binder_id */ ast::NodeId,
/* depth */ uint,
DefLateBoundRegion(ty::DebruijnIndex,
/* lifetime decl */ ast::NodeId),
DefFreeRegion(/* block scope */ ast::NodeId,
/* lifetime decl */ ast::NodeId),
......@@ -60,9 +59,9 @@ enum ScopeChain<'a> {
/// EarlyScope(i, ['a, 'b, ...], s) extends s with early-bound
/// lifetimes, assigning indexes 'a => i, 'b => i+1, ... etc.
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.
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
/// to that block.
BlockScope(ast::NodeId, Scope<'a>),
......@@ -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,
b: &'v ast::Block, s: Span, n: ast::NodeId) {
b: &'v ast::Block, s: Span, _: ast::NodeId) {
match fk {
visit::FkItemFn(_, generics, _, _) |
visit::FkMethod(_, generics, _) => {
self.visit_early_late(
subst::FnSpace, n, generics,
subst::FnSpace, generics,
|this| visit::walk_fn(this, fk, fd, b, s))
}
visit::FkFnBlock(..) => {
......@@ -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) {
let lifetimes = match ty.node {
ast::TyClosure(ref c) | ast::TyProc(ref c) => &c.lifetimes,
ast::TyBareFn(ref c) => &c.lifetimes,
_ => return visit::walk_ty(self, ty)
};
self.with(LateScope(ty.id, lifetimes, self.scope), |this| {
this.check_lifetime_defs(lifetimes);
visit::walk_ty(this, ty);
});
match ty.node {
ast::TyClosure(ref c) | ast::TyProc(ref c) => {
// Careful, the bounds on a closure/proc are *not* within its binder.
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| {
this.check_lifetime_defs(&c.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(self, ty)
}
}
}
fn visit_ty_method(&mut self, m: &ast::TypeMethod) {
self.visit_early_late(
subst::FnSpace, m.id, &m.generics,
subst::FnSpace, &m.generics,
|this| visit::walk_ty_method(this, m))
}
......@@ -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) {
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`.
fn visit_early_late(&mut self,
early_space: subst::ParamSpace,
binder_id: ast::NodeId,
generics: &ast::Generics,
walk: |&mut LifetimeContext|) {
/*!
......@@ -249,15 +278,14 @@ fn visit_early_late(&mut self,
let referenced_idents = early_bound_lifetime_names(generics);
debug!("visit_early_late: binder_id={} referenced_idents={}",
binder_id,
debug!("visit_early_late: referenced_idents={}",
referenced_idents);
let (early, late) = generics.lifetimes.clone().partition(
|l| referenced_idents.iter().any(|&i| i == l.lifetime.name));
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);
walk(this);
});
......@@ -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
// over to `resolve_free_lifetime_ref()` to complete the
// search.
let mut depth = 0;
let mut late_depth = 0;
let mut scope = self.scope;
loop {
match *scope {
......@@ -291,22 +319,22 @@ fn resolve_lifetime_ref(&mut self, lifetime_ref: &ast::Lifetime) {
return;
}
None => {
depth += 1;
scope = s;
}
}
}
LateScope(binder_id, lifetimes, s) => {
LateScope(lifetimes, s) => {
match search_lifetimes(lifetimes, lifetime_ref) {
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);
return;
}
None => {
depth += 1;
late_depth += 1;
scope = s;
}
}
......@@ -339,7 +367,7 @@ fn resolve_free_lifetime_ref(&mut self,
}
EarlyScope(_, lifetimes, s) |
LateScope(_, lifetimes, s) => {
LateScope(lifetimes, s) => {
search_result = search_lifetimes(lifetimes, lifetime_ref);
if search_result.is_some() {
break;
......@@ -517,7 +545,7 @@ impl<'a> fmt::Show for ScopeChain<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match *self {
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),
RootScope => write!(fmt, "RootScope"),
}
......
......@@ -14,8 +14,7 @@
pub use self::RegionSubsts::*;
use middle::ty;
use middle::ty_fold;
use middle::ty_fold::{TypeFoldable, TypeFolder};
use middle::ty_fold::{mod, TypeFoldable, TypeFolder};
use util::ppaux::Repr;
use std::fmt;
......@@ -506,11 +505,22 @@ struct SubstFolder<'a, 'tcx: 'a> {
// Depth of type stack
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> {
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 {
// Note: This routine only handles regions that are bound on
// type declarations and other outer declarations, not those
......@@ -524,7 +534,9 @@ fn fold_region(&mut self, r: ty::Region) -> ty::Region {
ErasedRegions => ty::ReStatic,
NonerasedRegions(ref regions) =>
match regions.opt_get(space, i) {
Some(t) => *t,
Some(&r) => {
self.shift_region_through_binders(r)
}
None => {
let span = self.span.unwrap_or(DUMMY_SP);
self.tcx().sess.span_bug(
......@@ -557,12 +569,7 @@ fn fold_ty(&mut self, t: ty::t) -> ty::t {
let t1 = match ty::get(t).sty {
ty::ty_param(p) => {
check(self,
p,
t,
self.substs.types.opt_get(p.space, p.idx),
p.space,
p.idx)
self.ty_for_param(p, t)
}
_ => {
ty_fold::super_fold_ty(self, t)
......@@ -576,30 +583,100 @@ fn fold_ty(&mut self, t: ty::t) -> ty::t {
}
return t1;
}
}
fn check(this: &SubstFolder,
p: ty::ParamTy,
source_ty: ty::t,
opt_ty: Option<&ty::t>,
space: ParamSpace,
index: uint)
-> ty::t {
match opt_ty {
Some(t) => *t,
None => {
let span = this.span.unwrap_or(DUMMY_SP);
this.tcx().sess.span_bug(
span,
format!("Type parameter `{}` ({}/{}/{}) out of range \
impl<'a,'tcx> SubstFolder<'a,'tcx> {
fn ty_for_param(&self, p: ty::ParamTy, source_ty: ty::t) -> ty::t {
// Look up the type in the substitutions. It really should be in there.
let opt_ty = self.substs.types.opt_get(p.space, p.idx);
let ty = match opt_ty {
Some(t) => *t,
None => {
let span = self.span.unwrap_or(DUMMY_SP);
self.tcx().sess.span_bug(
span,
format!("Type parameter `{}` ({}/{}/{}) out of range \
when substituting (root type={}) substs={}",
p.repr(this.tcx()),
source_ty.repr(this.tcx()),
space,
index,
this.root_ty.repr(this.tcx()),
this.substs.repr(this.tcx())).as_slice());
}
p.repr(self.tcx()),
source_ty.repr(self.tcx()),
p.space,
p.idx,
self.root_ty.repr(self.tcx()),
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 {
pub trait TypeFolder<'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 {
super_fold_ty(self, t)
}
......@@ -85,10 +96,10 @@ fn fold_substs(&mut self,
super_fold_substs(self, substs)
}
fn fold_sig(&mut self,
fn fold_fn_sig(&mut self,
sig: &ty::FnSig)
-> ty::FnSig {
super_fold_sig(self, sig)
super_fold_fn_sig(self, sig)
}
fn fold_output(&mut self,
......@@ -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> {
fn fold_with<'tcx, F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Option<T> {
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> {
}
}
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> {
fn fold_with<'tcx, F: TypeFolder<'tcx>>(&self, folder: &mut F) -> OwnedSlice<T> {
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>
impl<T:TypeFoldable> TypeFoldable for 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 {
impl TypeFoldable for 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,
types: substs.types.fold_with(this) }
}
pub fn super_fold_sig<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
sig: &ty::FnSig)
-> ty::FnSig {
ty::FnSig { binder_id: sig.binder_id,
inputs: sig.inputs.fold_with(this),
pub fn super_fold_fn_sig<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
sig: &ty::FnSig)
-> ty::FnSig
{
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),
variadic: sig.variadic }
}
......@@ -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
pub struct BottomUpFolder<'a, 'tcx: 'a> {
......@@ -655,77 +729,43 @@ fn fold_ty(&mut self, ty: ty::t) -> ty::t {
/// current position of the fold.)
pub struct RegionFolder<'a, 'tcx: 'a> {
tcx: &'a ty::ctxt<'tcx>,
fld_t: |ty::t|: 'a -> ty::t,
fld_r: |ty::Region|: 'a -> ty::Region,
within_binder_ids: Vec<ast::NodeId>,
current_depth: uint,
fld_r: |ty::Region, uint|: 'a -> ty::Region,
}
impl<'a, 'tcx> RegionFolder<'a, 'tcx> {
pub fn general(tcx: &'a ty::ctxt<'tcx>,
fld_r: |ty::Region|: 'a -> ty::Region,
fld_t: |ty::t|: 'a -> ty::t)
-> RegionFolder<'a, 'tcx> {
pub fn new(tcx: &'a ty::ctxt<'tcx>, fld_r: |ty::Region, uint|: 'a -> ty::Region)
-> RegionFolder<'a, 'tcx> {
RegionFolder {
tcx: tcx,
fld_t: fld_t,
current_depth: 1,
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> {
fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> { self.tcx }
fn fold_ty(&mut self, ty: ty::t) -> ty::t {
debug!("RegionFolder.fold_ty({})", ty.repr(self.tcx()));
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();
}
fn enter_region_binder(&mut self) {
self.current_depth += 1;
}
ret
fn exit_region_binder(&mut self) {
self.current_depth -= 1;
}
fn fold_region(&mut self, r: ty::Region) -> ty::Region {
match r {
ty::ReLateBound(binder_id, _) if self.within_binder_ids.contains(&binder_id) => {
debug!("RegionFolder.fold_region({}) skipped bound region", r.repr(self.tcx()));
ty::ReLateBound(debruijn, _) if debruijn.depth < self.current_depth => {
debug!("RegionFolder.fold_region({}) skipped bound region (current depth={})",
r.repr(self.tcx()), self.current_depth);
r
}
_ => {
debug!("RegionFolder.fold_region({}) folding free region", r.repr(self.tcx()));
(self.fld_r)(r)
debug!("RegionFolder.fold_region({}) folding free region (current_depth={})",
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 {
}
}
}
///////////////////////////////////////////////////////////////////////////
// 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)
ty::ReStatic
}
Some(&rl::DefLateBoundRegion(binder_id, _, id)) => {
ty::ReLateBound(binder_id, ty::BrNamed(ast_util::local_def(id),
lifetime.name))
Some(&rl::DefLateBoundRegion(debruijn, id)) => {
ty::ReLateBound(debruijn, ty::BrNamed(ast_util::local_def(id), lifetime.name))
}
Some(&rl::DefEarlyBoundRegion(space, index, id)) => {
......@@ -210,8 +209,7 @@ fn ast_path_substs<'tcx,AC,RS>(
decl_generics: &ty::Generics,
self_ty: Option<ty::t>,
associated_ty: Option<ty::t>,
path: &ast::Path,
binder_id: ast::NodeId)
path: &ast::Path)
-> Substs
where AC: AstConv<'tcx>, RS: RegionScope
{
......@@ -463,8 +461,7 @@ pub fn ast_path_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
this: &AC,
rscope: &RS,
did: ast::DefId,
path: &ast::Path,
binder_id: ast::NodeId)
path: &ast::Path)
-> TypeAndSubsts
{
let tcx = this.tcx();
......@@ -473,14 +470,13 @@ pub fn ast_path_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
ty: decl_ty
} = this.get_item_ty(did);
let substs = ast_path_substs(this,
rscope,
did,
&generics,
None,
None,
path,
binder_id);
let substs = ast_path_substs_for_ty(this,
rscope,
did,
&generics,
None,
None,
path);
let ty = decl_ty.subst(tcx, &substs);
TypeAndSubsts { substs: substs, ty: ty }
}
......@@ -494,8 +490,7 @@ pub fn ast_path_to_ty_relaxed<'tcx,AC,RS>(
this: &AC,
rscope: &RS,
did: ast::DefId,
path: &ast::Path,
binder_id: ast::NodeId)
path: &ast::Path)
-> TypeAndSubsts
where AC : AstConv<'tcx>, RS : RegionScope
{
......@@ -521,7 +516,7 @@ pub fn ast_path_to_ty_relaxed<'tcx,AC,RS>(
Substs::new(VecPerParamSpace::params_from_type(type_params),
VecPerParamSpace::params_from_type(region_params))
} 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);
......@@ -628,7 +623,7 @@ pub fn ast_ty_to_builtin_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
match a_def {
def::DefTy(did, _) |
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 {
ty::ty_struct(struct_def_id, ref substs) => {
assert_eq!(struct_def_id, did);
......@@ -689,8 +684,7 @@ fn mk_pointer<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
trait_def_id,
None,
None,
path,
id);
path);
let empty_vec = [];
let bounds = match *opt_bounds { None => empty_vec.as_slice(),
Some(ref bounds) => bounds.as_slice() };
......@@ -752,12 +746,7 @@ fn associated_ty_to_ty<'tcx,AC,RS>(this: &AC,
trait_did,
None,
Some(for_type),
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.
trait_path);
debug!("associated_ty_to_ty(trait_ref={})",
trait_ref.repr(this.tcx()));
......@@ -830,8 +819,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
tcx.sess.span_err(ast_ty.span,
"variadic function must have C calling convention");
}
ty::mk_bare_fn(tcx, ty_of_bare_fn(this, ast_ty.id, bf.fn_style,
bf.abi, &*bf.decl))
ty::mk_bare_fn(tcx, ty_of_bare_fn(this, bf.fn_style, bf.abi, &*bf.decl))
}
ast::TyClosure(ref f) => {
// 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>(
[].as_slice(),
f.bounds.as_slice());
let fn_decl = ty_of_closure(this,
ast_ty.id,
f.fn_style,
f.onceness,
bounds,
......@@ -863,7 +850,6 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
f.bounds.as_slice());
let fn_decl = ty_of_closure(this,
ast_ty.id,
f.fn_style,
f.onceness,
bounds,
......@@ -910,8 +896,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
trait_def_id,
None,
None,
path,
id);
path);
let empty_bounds: &[ast::TyParamBound] = &[];
let ast_bounds = match *bounds {
Some(ref b) => b.as_slice(),
......@@ -927,7 +912,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
bounds)
}
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) => {
check_path_args(tcx, path, NO_TPS | NO_REGIONS);
......@@ -1056,7 +1041,6 @@ struct SelfInfo<'a> {
pub fn ty_of_method<'tcx, AC: AstConv<'tcx>>(
this: &AC,
id: ast::NodeId,
fn_style: ast::FnStyle,
untransformed_self_ty: ty::t,
explicit_self: &ast::ExplicitSelf,
......@@ -1069,7 +1053,6 @@ pub fn ty_of_method<'tcx, AC: AstConv<'tcx>>(
});
let (bare_fn_ty, optional_explicit_self_category) =
ty_of_method_or_bare_fn(this,
id,
fn_style,
abi,
self_info,
......@@ -1077,17 +1060,14 @@ pub fn ty_of_method<'tcx, AC: AstConv<'tcx>>(
(bare_fn_ty, optional_explicit_self_category.unwrap())
}
pub fn ty_of_bare_fn<'tcx, AC: AstConv<'tcx>>(this: &AC, id: ast::NodeId,
fn_style: ast::FnStyle, abi: abi::Abi,
pub fn ty_of_bare_fn<'tcx, AC: AstConv<'tcx>>(this: &AC, fn_style: ast::FnStyle, abi: abi::Abi,
decl: &ast::FnDecl) -> ty::BareFnTy {
let (bare_fn_ty, _) =
ty_of_method_or_bare_fn(this, id, fn_style, abi, None, decl);
let (bare_fn_ty, _) = ty_of_method_or_bare_fn(this, fn_style, abi, None, decl);
bare_fn_ty
}
fn ty_of_method_or_bare_fn<'tcx, AC: AstConv<'tcx>>(
this: &AC,
id: ast::NodeId,
fn_style: ast::FnStyle,
abi: abi::Abi,
opt_self_info: Option<SelfInfo>,
......@@ -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
// 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
// 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>>(
determine_explicit_self_category(this, &rb, &self_info);
explicit_self_category_result = Some(explicit_self_category);
match explicit_self_category {
ty::StaticExplicitSelfCategory => (None, None),
ty::StaticExplicitSelfCategory => {
(None, None)
}
ty::ByValueExplicitSelfCategory => {
(Some(self_info.untransformed_self_ty), None)
}
......@@ -1205,7 +1187,6 @@ fn ty_of_method_or_bare_fn<'tcx, AC: AstConv<'tcx>>(
fn_style: fn_style,
abi: abi,
sig: ty::FnSig {
binder_id: id,
inputs: self_and_input_tys,
output: output_ty,
variadic: decl.variadic
......@@ -1290,7 +1271,6 @@ fn determine_explicit_self_category<'tcx, AC: AstConv<'tcx>,
pub fn ty_of_closure<'tcx, AC: AstConv<'tcx>>(
this: &AC,
id: ast::NodeId,
fn_style: ast::FnStyle,
onceness: ast::Onceness,
bounds: ty::ExistentialBounds,
......@@ -1300,13 +1280,14 @@ pub fn ty_of_closure<'tcx, AC: AstConv<'tcx>>(
expected_sig: Option<ty::FnSig>)
-> 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
// 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| {
// no guarantee that the correct number of expected args
// were supplied
......@@ -1331,14 +1312,16 @@ pub fn ty_of_closure<'tcx, AC: AstConv<'tcx>>(
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 {
fn_style: fn_style,
onceness: onceness,
store: store,
bounds: bounds,
abi: abi,
sig: ty::FnSig {binder_id: id,
inputs: input_tys,
sig: ty::FnSig {inputs: input_tys,
output: output_ty,
variadic: decl.variadic}
}
......
......@@ -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.
// 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| {
ty::ReFree(ty::FreeRegion {scope_id: body.id, bound_region: br})
});
let fn_sig = liberate_late_bound_regions(tcx, body.id, fn_sig);
let arg_tys = fn_sig.inputs.as_slice();
let ret_ty = fn_sig.output;
......@@ -3031,7 +3029,6 @@ fn check_call<'a>(fcx: &FnCtxt,
// In that case, we check each argument against "error" in order to
// set up all the node type bindings.
let error_fn_sig = FnSig {
binder_id: ast::CRATE_NODE_ID,
inputs: err_args(args.len()),
output: ty::FnConverging(ty::mk_err()),
variadic: false
......@@ -3051,11 +3048,9 @@ fn check_call<'a>(fcx: &FnCtxt,
// Replace any bound regions that appear in the function
// signature with region variables
let fn_sig =
fcx.infcx().replace_late_bound_regions_with_fresh_var(
fn_sig.binder_id,
call_expr.span,
infer::FnCall,
fn_sig).0;
fcx.infcx().replace_late_bound_regions_with_fresh_var(call_expr.span,
infer::FnCall,
fn_sig).0;
// Call the generic checker.
check_argument_types(fcx,
......@@ -3437,7 +3432,6 @@ fn check_unboxed_closure(fcx: &FnCtxt,
body: &ast::Block) {
let mut fn_ty = astconv::ty_of_closure(
fcx,
expr.id,
ast::NormalFn,
ast::Many,
......@@ -3508,6 +3502,10 @@ fn check_expr_fn(fcx: &FnCtxt,
expected: Expectation) {
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
// fresh bound regions for any bound regions we find in the
// expected types so as to avoid capture.
......@@ -3517,10 +3515,11 @@ fn check_expr_fn(fcx: &FnCtxt,
expected_bounds) = {
match expected_sty {
Some(ty::ty_closure(ref cenv)) => {
let (_, sig) =
let (sig, _) =
replace_late_bound_regions(
tcx, cenv.sig.binder_id, &cenv.sig,
|_| fcx.inh.infcx.fresh_bound_region(expr.id));
tcx,
&cenv.sig,
|_, debruijn| fcx.inh.infcx.fresh_bound_region(debruijn));
let onceness = match (&store, &cenv.store) {
// As the closure type and onceness go, only three
// combinations are legit:
......@@ -3561,7 +3560,6 @@ fn check_expr_fn(fcx: &FnCtxt,
// construct the function type
let fn_ty = astconv::ty_of_closure(fcx,
expr.id,
ast::NormalFn,
expected_onceness,
expected_bounds,
......@@ -5943,7 +5941,6 @@ fn param(ccx: &CrateCtxt, n: uint) -> ty::t {
fn_style: ast::UnsafeFn,
abi: abi::RustIntrinsic,
sig: FnSig {
binder_id: it.id,
inputs: inputs,
output: output,
variadic: false,
......
......@@ -14,47 +14,14 @@
use middle::subst::{ParamSpace, Subst, Substs};
use middle::ty;
use middle::ty_fold;
use middle::ty_fold::{TypeFolder, TypeFoldable};
use middle::ty_fold::{TypeFolder};
use syntax::ast;
use std::collections::hash_map::{Occupied, Vacant};
use util::nodemap::FnvHashMap;
use util::ppaux::Repr;
// 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 {
RegionSubRegionConstraint(Option<ty::t>, ty::Region, ty::Region),
RegionSubParamConstraint(Option<ty::t>, ty::Region, ty::ParamTy),
......
......@@ -372,16 +372,12 @@ fn fold_ty(&mut self, t: ty::t) -> ty::t {
ty::ty_closure(box ty::ClosureTy{sig: ref fn_sig, ..}) => {
self.binding_count += 1;
let (_, 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}));
let fn_sig = liberate_late_bound_regions(self.fcx.tcx(), self.scope_id, fn_sig);
debug!("late-bound regions replaced: {}",
fn_sig.repr(self.tcx()));
self.fold_sig(&fn_sig);
self.fold_fn_sig(&fn_sig);
self.binding_count -= 1;
}
......
......@@ -214,12 +214,11 @@ pub fn get_enum_variant_types(ccx: &CrateCtxt,
for variant in variants.iter() {
// Nullary enum constructors get turned into constants; n-ary enum
// constructors get turned into functions.
let scope = variant.node.id;
let result_ty = match variant.node.kind {
ast::TupleVariantKind(ref args) if args.len() > 0 => {
let rs = ExplicitRscope;
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(_) => {
......@@ -403,7 +402,6 @@ fn ty_method_of_trait_method(ccx: &CrateCtxt,
let trait_self_ty = ty::mk_self_type(tmcx.tcx(),
local_def(trait_id));
astconv::ty_of_method(&tmcx,
*m_id,
*m_fn_style,
trait_self_ty,
m_explicit_self,
......@@ -588,7 +586,6 @@ fn ty_of_method(ccx: &CrateCtxt,
method_generics: &m_ty_generics,
};
astconv::ty_of_method(&imcx,
m.id,
m.pe_fn_style(),
untransformed_rcvr_ty,
m.pe_explicit_self(),
......@@ -603,7 +600,6 @@ fn ty_of_method(ccx: &CrateCtxt,
method_generics: &m_ty_generics,
};
astconv::ty_of_method(&tmcx,
m.id,
m.pe_fn_style(),
untransformed_rcvr_ty,
m.pe_explicit_self(),
......@@ -1294,7 +1290,6 @@ pub fn convert_struct(ccx: &CrateCtxt,
|field| (*tcx.tcache.borrow())[
local_def(field.node.id)].ty).collect();
let ctor_fn_ty = ty::mk_ctor_fn(tcx,
ctor_id,
inputs.as_slice(),
selfty);
write_ty_to_tcx(tcx, ctor_id, ctor_fn_ty);
......@@ -1465,11 +1460,7 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: &ast::Item)
ccx: ccx,
generics: &ty_generics,
};
astconv::ty_of_bare_fn(&fcx,
it.id,
fn_style,
abi,
&**decl)
astconv::ty_of_bare_fn(&fcx, fn_style, abi, &**decl)
};
let pty = Polytype {
generics: ty_generics,
......@@ -2091,7 +2082,7 @@ pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt,
ast_generics,
ty::Generics::empty(),
DontCreateTypeParametersForAssociatedTypes);
let rb = BindingRscope::new(def_id.node);
let rb = BindingRscope::new();
let input_tys = decl.inputs
.iter()
.map(|a| ty_of_arg(ccx, &rb, a, None))
......@@ -2109,8 +2100,7 @@ pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt,
ty::BareFnTy {
abi: abi,
fn_style: ast::UnsafeFn,
sig: ty::FnSig {binder_id: def_id.node,
inputs: input_tys,
sig: ty::FnSig {inputs: input_tys,
output: output,
variadic: decl.variadic}
});
......
......@@ -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> {
let tcx = this.infcx().tcx;
......
......@@ -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> {
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,
subst::Substs::new_trait(type_parameters, regions, assoc_type_parameters, self_ty)
}
pub fn fresh_bound_region(&self, binder_id: ast::NodeId) -> ty::Region {
self.region_vars.new_bound(binder_id)
pub fn fresh_bound_region(&self, debruijn: ty::DebruijnIndex) -> ty::Region {
self.region_vars.new_bound(debruijn)
}
pub fn resolve_regions_and_report_errors(&self) {
......@@ -968,30 +968,19 @@ pub fn report_mismatched_types(&self,
pub fn replace_late_bound_regions_with_fresh_var<T>(
&self,
binder_id: ast::NodeId,
span: Span,
lbrct: LateBoundRegionConversionTime,
value: &T)
-> (T, FnvHashMap<ty::BoundRegion,ty::Region>)
where T : TypeFoldable + Repr
where T : HigherRankedFoldable
{
let (map, value) =
replace_late_bound_regions(
self.tcx,
binder_id,
value,
|br| self.next_region_var(LateBoundRegion(span, br, lbrct)));
(value, map)
ty::replace_late_bound_regions(
self.tcx,
value,
|br, _| self.next_region_var(LateBoundRegion(span, br, lbrct)))
}
}
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 {
pub fn span(&self) -> Span {
self.origin.span()
......
......@@ -332,7 +332,7 @@ pub fn new_skolemized(&self, br: ty::BoundRegion) -> Region {
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.
// See discussion of GLB computation in the large comment at
// the top of this file for more details.
......@@ -358,7 +358,7 @@ pub fn new_bound(&self, binder_id: ast::NodeId) -> Region {
self.tcx.sess.bug("rollover in RegionInference new_bound()");
}
ReLateBound(binder_id, BrFresh(sc))
ReLateBound(debruijn, BrFresh(sc))
}
fn values_are_none(&self) -> bool {
......
......@@ -383,7 +383,6 @@ fn check_main_fn_ty(ccx: &CrateCtxt,
fn_style: ast::NormalFn,
abi: abi::Rust,
sig: ty::FnSig {
binder_id: main_id,
inputs: Vec::new(),
output: ty::FnConverging(ty::mk_nil(tcx)),
variadic: false
......@@ -432,7 +431,6 @@ fn check_start_fn_ty(ccx: &CrateCtxt,
fn_style: ast::NormalFn,
abi: abi::Rust,
sig: ty::FnSig {
binder_id: start_id,
inputs: vec!(
ty::mk_int(),
ty::mk_imm_ptr(tcx, ty::mk_imm_ptr(tcx, ty::mk_u8()))
......
......@@ -104,14 +104,12 @@ fn anon_regions(&self,
/// A scope in which we generate anonymous, late-bound regions for
/// omitted regions. This occurs in function signatures.
pub struct BindingRscope {
binder_id: ast::NodeId,
anon_bindings: Cell<uint>,
}
impl BindingRscope {
pub fn new(binder_id: ast::NodeId) -> BindingRscope {
pub fn new() -> BindingRscope {
BindingRscope {
binder_id: binder_id,
anon_bindings: Cell::new(0),
}
}
......@@ -119,7 +117,7 @@ pub fn new(binder_id: ast::NodeId) -> BindingRscope {
fn next_region(&self) -> ty::Region {
let idx = self.anon_bindings.get();
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 {
}
pub fn fn_sig_to_string(cx: &ctxt, typ: &ty::FnSig) -> String {
format!("fn{}{} -> {}", typ.binder_id, typ.inputs.repr(cx),
typ.output.repr(cx))
format!("fn{} -> {}", typ.inputs.repr(cx), typ.output.repr(cx))
}
pub fn trait_ref_to_string(cx: &ctxt, trait_ref: &ty::TraitRef) -> String {
......@@ -262,11 +261,11 @@ pub fn trait_ref_to_string(cx: &ctxt, trait_ref: &ty::TraitRef) -> String {
pub fn ty_to_string(cx: &ctxt, typ: t) -> String {
fn bare_fn_to_string(cx: &ctxt,
fn_style: ast::FnStyle,
abi: abi::Abi,
ident: Option<ast::Ident>,
sig: &ty::FnSig)
-> String {
fn_style: ast::FnStyle,
abi: abi::Abi,
ident: Option<ast::Ident>,
sig: &ty::FnSig)
-> String {
let mut s = String::new();
match fn_style {
ast::NormalFn => {}
......@@ -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,
let self_type = fty.sig.inputs[0];
let boxed_self_type = ty::mk_uniq(tcx, self_type);
let boxed_function_type = ty::FnSig {
binder_id: fty.sig.binder_id,
inputs: fty.sig.inputs.iter().enumerate().map(|(i, typ)| {
if i == 0 {
boxed_self_type
......@@ -294,7 +293,6 @@ pub fn trans_unboxing_shim(bcx: Block,
// RustCall so the untupled arguments can be passed
// through verbatim. This is kind of ugly.
let fake_ty = ty::FnSig {
binder_id: fty.sig.binder_id,
inputs: type_of::untuple_arguments_if_necessary(ccx,
fty.sig.inputs.as_slice(),
fty.abi),
......
......@@ -609,9 +609,6 @@ pub fn get_vtable(bcx: Block,
fn_style: closure_info.closure_type.fn_style,
abi: Rust,
sig: ty::FnSig {
binder_id: closure_info.closure_type
.sig
.binder_id,
inputs: new_inputs,
output: new_output,
variadic: false,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册