More refactoring on a quest to understand region types.

This commit is contained in:
Lindsey Kuper 2012-05-25 17:00:45 -07:00
parent 269bc6fb5c
commit e11742de32
2 changed files with 62 additions and 22 deletions

View File

@ -5,7 +5,7 @@ import syntax::print::pprust::{expr_to_str};
// Extracts the bound regions from bound_tys and then replaces those same
// regions in `sty` with fresh region variables, returning the resulting type.
// Does not descend into fn types. This is used when deciding whether an impl
// applies at a given call site. See also universally_quantify_before_call().
// applies at a given call site.
fn universally_quantify_from_sty(fcx: @fn_ctxt,
span: span,
bound_tys: [ty::t],
@ -31,6 +31,11 @@ fn universally_quantify_from_sty(fcx: @fn_ctxt,
}
}
// Takes `isr`, a mapping from in-scope region names ("isr"s) to their
// corresponding regions (possibly produced by a call to
// collect_bound_regions_in_tys; and `ty`, a type. Returns an updated
// version of `ty`, in which bound regions in `ty` have been replaced
// with the corresponding bindings in `isr`.
fn replace_bound_regions(
tcx: ty::ctxt,
span: span,
@ -140,23 +145,29 @@ fn region_of(fcx: @fn_ctxt, expr: @ast::expr) -> ty::region {
}
}
// Takes `isr`, a (possibly empty) mapping from in-scope region names ("isr"s)
// to their corresponding regions; `tys`, a list of types, and `to_r`, a
// closure that takes a bound_region and returns a region. Returns an updated
// version of `isr`, extended with the in-scope region names from all of the
// bound regions appearing in the types in the `tys` list (if they're not in
// `isr` already), with each of those in-scope region names mapped to a region
// that's the result of applying `to_r` to itself.
// "collect" is something of a misnomer -- we're not merely collecting
// a list of the bound regions, but also doing the work of applying
// `to_r` to them!
fn collect_bound_regions_in_tys(
tcx: ty::ctxt,
isr: isr_alist,
tys: [ty::t],
to_r: fn(ty::bound_region) -> ty::region) -> isr_alist {
tys.foldl(isr) { |isr, t|
collect_bound_regions_in_ty(tcx, isr, t, to_r)
}
}
fn collect_bound_regions_in_ty(
tcx: ty::ctxt,
isr: isr_alist,
ty: ty::t,
to_r: fn(ty::bound_region) -> ty::region) -> isr_alist {
// Takes `isr` (described above), `to_r` (described above), and `r`, a
// region. If `r` is anything other than a bound region, or if it's a
// bound region that already appears in `isr`, then we return `isr`
// unchanged. If `r` is a bound region that doesn't already appear in
// `isr`, we return an updated isr_alist that now contains a mapping from
// `r` to the result of calling `to_r` on it.
fn append_isr(isr: isr_alist,
to_r: fn(ty::bound_region) -> ty::region,
r: ty::region) -> isr_alist {
@ -174,16 +185,30 @@ fn collect_bound_regions_in_ty(
}
}
let mut isr = isr;
// For each region in `t`, apply the `append_isr` function to that
// region, accumulating and returning the results in an isr_alist.
fn fold_over_regions_in_type(
tcx: ty::ctxt,
isr: isr_alist,
ty: ty::t,
to_r: fn(ty::bound_region) -> ty::region) -> isr_alist {
// Using fold_regions is inefficient, because it constructs new types, but
// it avoids code duplication in terms of locating all the regions within
// the various kinds of types. This had already caused me several bugs
// so I decided to switch over.
ty::fold_regions(tcx, ty) { |r, in_fn|
if !in_fn { isr = append_isr(isr, to_r, r); }
r
};
let mut isr = isr;
ret isr;
// Using fold_regions is inefficient, because it constructs new types,
// but it avoids code duplication in terms of locating all the regions
// within the various kinds of types. This had already caused me
// several bugs so I decided to switch over.
ty::fold_regions(tcx, ty) { |r, in_fn|
if !in_fn { isr = append_isr(isr, to_r, r); }
r
};
ret isr;
}
// For each type `t` in `tys`...
tys.foldl(isr) { |isr, t|
fold_over_regions_in_type(tcx, isr, t, to_r)
}
}

View File

@ -1618,11 +1618,23 @@ impl of combine for sub {
// First, we instantiate each bound region in the subtype with a fresh
// region variable.
// FIXME: This code is kinda redundant with
// regionmanip::universally_quantify_from_sty, except for the
// `sty` part. Fix somehow?
// a_isr is a mapping from all the bound regions in `a` to
// freshly created region variables for them.
let a_isr =
collect_bound_regions_in_tys(self.tcx,
@nil,
tys_in_fn_ty(a)) {
|br|
// N.B.: The name of the bound region doesn't have
// anything to do with the region variable that's created
// for it. The only thing we're doing with `br` here is
// using it in the debug message.
let rvar = self.infcx().next_region_var();
#debug["Bound region %s maps to %s",
bound_region_to_str(self.tcx, br),
@ -1638,6 +1650,9 @@ impl of combine for sub {
// Second, we instantiate each bound region in the supertype with a
// fresh concrete region.
// a_isr is a mapping from all the bound regions in `b` to
// the result of calling re_bound on them.
let b_isr =
collect_bound_regions_in_tys(self.tcx,
@nil,