use self::ScopeChain::*;
use session::Session;
+use middle::def;
+use middle::resolve::DefMap;
use middle::subst;
+use middle::ty;
use std::fmt;
use syntax::ast;
use syntax::codemap::Span;
-use syntax::owned_slice::OwnedSlice;
use syntax::parse::token::special_idents;
use syntax::parse::token;
use syntax::print::pprust::{lifetime_to_string};
struct LifetimeContext<'a> {
sess: &'a Session,
named_region_map: &'a mut NamedRegionMap,
- scope: Scope<'a>
+ scope: Scope<'a>,
+ def_map: &'a DefMap,
}
enum ScopeChain<'a> {
static ROOT_SCOPE: ScopeChain<'static> = RootScope;
-pub fn krate(sess: &Session, krate: &ast::Crate) -> NamedRegionMap {
+pub fn krate(sess: &Session, krate: &ast::Crate, def_map: &DefMap) -> NamedRegionMap {
let mut named_region_map = NodeMap::new();
visit::walk_crate(&mut LifetimeContext {
sess: sess,
named_region_map: &mut named_region_map,
- scope: &ROOT_SCOPE
+ scope: &ROOT_SCOPE,
+ def_map: def_map,
}, krate);
sess.abort_if_errors();
named_region_map
visit::walk_ty(this, ty);
});
}
+ ast::TyPath(ref path, ref opt_bounds, id) => {
+ // if this path references a trait, then this will resolve to
+ // a trait ref, which introduces a binding scope.
+ match self.def_map.borrow().get(&id) {
+ Some(&def::DefTrait(..)) => {
+ self.with(LateScope(&Vec::new(), self.scope), |this| {
+ this.visit_path(path, id);
+ });
+
+ match *opt_bounds {
+ Some(ref bounds) => {
+ visit::walk_ty_param_bounds_helper(self, bounds);
+ }
+ None => { }
+ }
+ }
+ _ => {
+ visit::walk_ty(self, ty);
+ }
+ }
+ }
_ => {
visit::walk_ty(self, ty)
}
fn visit_generics(&mut self, generics: &ast::Generics) {
for ty_param in generics.ty_params.iter() {
- self.visit_ty_param_bounds(&ty_param.bounds);
+ visit::walk_ty_param_bounds_helper(self, &ty_param.bounds);
match ty_param.default {
Some(ref ty) => self.visit_ty(&**ty),
None => {}
}
for predicate in generics.where_clause.predicates.iter() {
self.visit_ident(predicate.span, predicate.ident);
- self.visit_ty_param_bounds(&predicate.bounds);
- }
- }
-}
-
-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
- };
- debug!("entering scope {}", this.scope);
- f(&mut this);
- debug!("exiting scope {}", this.scope);
- }
-
- fn visit_ty_param_bounds(&mut self,
- bounds: &OwnedSlice<ast::TyParamBound>) {
- for bound in bounds.iter() {
- match *bound {
- ast::TraitTyParamBound(ref trait_ref) => {
- self.visit_poly_trait_ref(trait_ref);
- }
- ast::RegionTyParamBound(ref lifetime) => {
- self.visit_lifetime_ref(lifetime);
- }
- }
+ visit::walk_ty_param_bounds_helper(self, &predicate.bounds);
}
}
fn visit_poly_trait_ref(&mut self, trait_ref: &ast::PolyTraitRef) {
- let ref_id = trait_ref.trait_ref.ref_id;
- self.with(LateScope(ref_id, &trait_ref.bound_lifetimes, self.scope), |this| {
+ debug!("visit_poly_trait_ref trait_ref={}", trait_ref);
+
+ self.with(LateScope(&trait_ref.bound_lifetimes, self.scope), |this| {
this.check_lifetime_defs(&trait_ref.bound_lifetimes);
for lifetime in trait_ref.bound_lifetimes.iter() {
this.visit_lifetime_decl(lifetime);
obligation: Obligation)
{
debug!("register_obligation({})", obligation.repr(tcx));
+ assert!(!obligation.trait_ref.has_escaping_regions());
self.trait_obligations.push(obligation);
}
use middle::mem_categorization::Typer;
use middle::subst::{Subst, Substs, VecPerParamSpace};
use middle::ty;
-use middle::typeck::check::regionmanip;
use middle::typeck::infer;
-use middle::typeck::infer::LateBoundRegionConversionTime::*;
use middle::typeck::infer::{InferCtxt, TypeSkolemizer};
use middle::ty_fold::TypeFoldable;
use std::cell::RefCell;
*/
debug!("select({})", obligation.repr(self.tcx()));
+ assert!(!obligation.trait_ref.has_escaping_regions());
let stack = self.push_stack(None, obligation);
match try!(self.candidate_from_obligation(&stack)) {
debug!("evaluate_obligation({})",
obligation.repr(self.tcx()));
+ assert!(!obligation.trait_ref.has_escaping_regions());
let stack = self.push_stack(None, obligation);
self.evaluate_stack(&stack).may_apply()
debug!("candidate_from_obligation(cache_skol_trait_ref={}, obligation={})",
cache_skol_trait_ref.repr(self.tcx()),
stack.repr(self.tcx()));
+ assert!(!stack.obligation.trait_ref.has_escaping_regions());
match self.check_candidate_cache(cache_skol_trait_ref.clone()) {
Some(c) => {
}
};
- // FIXME(pcwalton): This is a bogus thing to do, but
- // it'll do for now until we get the new trait-bound
- // region skolemization working.
- let (_, new_signature) =
- regionmanip::replace_late_bound_regions(
- self.tcx(),
- closure_type.sig.binder_id,
- &closure_type.sig,
- |br| self.infcx.next_region_var(
- infer::LateBoundRegion(obligation.cause.span, br,
- infer::FnCall)));
-
- let arguments_tuple = new_signature.inputs[0];
- let trait_ref = Rc::new(ty::TraitRef {
- def_id: obligation.trait_ref.def_id,
- substs: Substs::new_trait(
+ let closure_sig = &closure_type.sig;
+ let arguments_tuple = closure_sig.inputs[0];
+ let substs =
+ Substs::new_trait(
vec![arguments_tuple.subst(self.tcx(), substs),
- new_signature.output.unwrap().subst(self.tcx(), substs)],
+ closure_sig.output.unwrap().subst(self.tcx(), substs)],
vec![],
vec![],
- obligation.self_ty())
+ obligation.self_ty());
+ let trait_ref = Rc::new(ty::TraitRef {
+ def_id: obligation.trait_ref.def_id,
+ substs: substs,
});
self.confirm(obligation.cause,
pub bounds: ExistentialBounds
}
+/**
+ * A complete reference to a trait. These take numerous guises in syntax,
+ * but perhaps the most recognizable form is in a where clause:
+ *
+ * T : Foo<U>
+ *
+ * This would be represented by a trait-reference where the def-id is the
+ * def-id for the trait `Foo` and the substs defines `T` as parameter 0 in the
+ * `SelfSpace` and `U` as parameter 0 in the `TypeSpace`.
+ *
+ * Trait references also appear in object types like `Foo<U>`, but in
+ * that case the `Self` parameter is absent from the substitutions.
+ *
+ * Note that a `TraitRef` introduces a level of region binding, to
+ * account for higher-ranked trait bounds like `T : for<'a> Foo<&'a
+ * U>` or higher-ranked object types.
+ */
#[deriving(Clone, PartialEq, Eq, Hash, Show)]
pub struct TraitRef {
pub def_id: DefId,
// associated types.
self.substs.types.as_slice()
}
+
+ pub fn has_escaping_regions(&self) -> bool {
+ self.substs.has_regions_escaping_depth(1)
+ }
+
+ pub fn has_bound_regions(&self) -> bool {
+ self.substs.has_regions_escaping_depth(0)
+ }
}
/// When type checking, we use the `ParameterEnvironment` to track
}
&ty_trait(box TyTrait { ref principal, ref bounds }) => {
- self.add_substs(&principal.substs);
+ let mut computation = FlagComputation::new();
+ computation.add_substs(&principal.substs);
+ self.add_bound_computation(&computation);
+
self.add_bounds(bounds);
}
-> ty::ParamBounds
{
let trait_def = lookup_trait_def(tcx, trait_ref.def_id);
+
debug!("bounds_for_trait_ref(trait_def={}, trait_ref={})",
trait_def.repr(tcx), trait_ref.repr(tcx));
- trait_def.bounds.subst(tcx, &trait_ref.substs)
+
+ // The interaction between HRTB and supertraits is not entirely
+ // obvious. Let me walk you (and myself) through an example.
+ //
+ // Let's start with an easy case. Consider two traits:
+ //
+ // trait Foo<'a> : Bar<'a,'a> { }
+ // trait Bar<'b,'c> { }
+ //
+ // Now, if we have a trait reference `for<'x> T : Foo<'x>`, then
+ // we can deduce that `for<'x> T : Bar<'x,'x>`. Basically, if we
+ // knew that `Foo<'x>` (for any 'x) then we also know that
+ // `Bar<'x,'x>` (for any 'x). This more-or-less falls out from
+ // normal substitution.
+ //
+ // In terms of why this is sound, the idea is that whenever there
+ // is an impl of `T:Foo<'a>`, it must show that `T:Bar<'a,'a>`
+ // holds. So if there is an impl of `T:Foo<'a>` that applies to
+ // all `'a`, then we must know that `T:Bar<'a,'a>` holds for all
+ // `'a`.
+ //
+ // Another example to be careful of is this:
+ //
+ // trait Foo1<'a> : for<'b> Bar1<'a,'b> { }
+ // trait Bar1<'b,'c> { }
+ //
+ // Here, if we have `for<'x> T : Foo1<'x>`, then what do we know?
+ // The answer is that we know `for<'x,'b> T : Bar1<'x,'b>`. The
+ // reason is similar to the previous example: any impl of
+ // `T:Foo1<'x>` must show that `for<'b> T : Bar1<'x, 'b>`. So
+ // basically we would want to collapse the bound lifetimes from
+ // the input (`trait_ref`) and the supertraits.
+ //
+ // To achieve this in practice is fairly straightforward. Let's
+ // consider the more complicated scenario:
+ //
+ // - We start out with `for<'x> T : Foo1<'x>`. In this case, `'x`
+ // has a De Bruijn index of 1. We want to produce `for<'x,'b> T : Bar1<'x,'b>`,
+ // where both `'x` and `'b` would have a DB index of 1.
+ // The substitution from the input trait-ref is therefore going to be
+ // `'a => 'x` (where `'x` has a DB index of 1).
+ // - The super-trait-ref is `for<'b> Bar1<'a,'b>`, where `'a` is an
+ // early-bound parameter and `'b' is a late-bound parameter with a
+ // DB index of 1.
+ // - If we replace `'a` with `'x` from the input, it too will have
+ // a DB index of 1, and thus we'll have `for<'x,'b> Bar1<'x,'b>`
+ // just as we wanted.
+ //
+ // There is only one catch. If we just apply the substitution `'a
+ // => 'x` to `for<'b> Bar1<'a,'b>`, the substitution code will
+ // adjust the DB index because we substituting into a binder (it
+ // tries to be so smart...) resulting in `for<'x> for<'b>
+ // Bar1<'x,'b>` (we have no syntax for this, so use your
+ // imagination). Basically the 'x will have DB index of 2 and 'b
+ // will have DB index of 1. Not quite what we want. So we apply
+ // the substitution to the *contents* of the trait reference,
+ // rather than the trait reference itself (put another way, the
+ // substitution code expects equal binding levels in the values
+ // from the substitution and the value being substituted into, and
+ // this trick achieves that).
+
+ // Carefully avoid the binder introduced by each trait-ref by
+ // substituting over the substs, not the trait-refs themselves,
+ // thus achieving the "collapse" described in the big comment
+ // above.
+ let trait_bounds: Vec<_> =
+ trait_def.bounds.trait_bounds
+ .iter()
+ .map(|bound_trait_ref| {
+ ty::TraitRef::new(bound_trait_ref.def_id,
+ bound_trait_ref.substs.subst(tcx, &trait_ref.substs))
+ })
+ .map(|bound_trait_ref| Rc::new(bound_trait_ref))
+ .collect();
+
+ debug!("bounds_for_trait_ref: trait_bounds={}",
+ trait_bounds.repr(tcx));
+
+ // The region bounds and builtin bounds do not currently introduce
+ // binders so we can just substitute in a straightforward way here.
+ let region_bounds =
+ trait_def.bounds.region_bounds.subst(tcx, &trait_ref.substs);
+ let builtin_bounds =
+ trait_def.bounds.builtin_bounds.subst(tcx, &trait_ref.substs);
+
+ ty::ParamBounds {
+ trait_bounds: trait_bounds,
+ region_bounds: region_bounds,
+ builtin_bounds: builtin_bounds,
+ }
}
/// Iterate over attributes of a definition.
use middle::traits;
use middle::typeck;
use std::rc::Rc;
-use syntax::ast;
use syntax::owned_slice::OwnedSlice;
use util::ppaux::Repr;
// "super" routines: these are the default implementations for TypeFolder.
//
// They should invoke `foo.fold_with()` to do recursive folding.
+
pub fn super_fold_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
t: ty::t)
-> ty::t {
abi: fty.abi,
}
}
+
pub fn super_fold_trait_ref<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
t: &ty::TraitRef)
- -> ty::TraitRef {
+ -> ty::TraitRef
+{
+ this.enter_region_binder();
+ let result = super_fold_trait_ref_contents(this, t);
+ this.exit_region_binder();
+ result
+}
+
+pub fn super_fold_trait_ref_contents<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
+ t: &ty::TraitRef)
+ -> ty::TraitRef
+{
ty::TraitRef {
def_id: t.def_id,
substs: t.substs.fold_with(this),
super_fold_fn_sig_contents(folder, self)
}
}
+
+impl HigherRankedFoldable for ty::TraitRef {
+ fn fold_contents<'tcx, F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::TraitRef {
+ super_fold_trait_ref_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))
}
}
+
+impl<T:HigherRankedFoldable> HigherRankedFoldable for Rc<T> {
+ fn fold_contents<'tcx, F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Rc<T> {
+ Rc::new((**self).fold_contents(folder))
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////
// Some sample folders
pub struct BottomUpFolder<'a, 'tcx: 'a> {
use middle::subst::{VecPerParamSpace};
use middle::ty;
use middle::typeck::lookup_def_tcx;
-use middle::typeck::infer;
-use middle::typeck::rscope::{UnelidableRscope, RegionScope, SpecificRscope, BindingRscope};
+use middle::typeck::rscope::{UnelidableRscope, RegionScope, SpecificRscope,
+ ShiftedRscope, BindingRscope};
use middle::typeck::rscope;
use middle::typeck::TypeAndSubsts;
-use middle::typeck;
use util::nodemap::DefIdMap;
use util::ppaux::{Repr, UserString};
vec![input_ty, output]
}
+pub fn instantiate_poly_trait_ref<'tcx,AC,RS>(
+ this: &AC,
+ rscope: &RS,
+ ast_trait_ref: &ast::PolyTraitRef,
+ self_ty: Option<ty::t>,
+ associated_type: Option<ty::t>)
+ -> Rc<ty::TraitRef>
+ where AC: AstConv<'tcx>, RS: RegionScope
+{
+ instantiate_trait_ref(this, rscope, &ast_trait_ref.trait_ref, self_ty, associated_type)
}
pub fn instantiate_trait_ref<'tcx,AC,RS>(this: &AC,
match lookup_def_tcx(this.tcx(),
ast_trait_ref.path.span,
ast_trait_ref.ref_id) {
- def::DefTrait(trait_did) => {
- let trait_ref =
- Rc::new(ast_path_to_trait_ref(this,
- rscope,
- trait_did,
- self_ty,
- associated_type,
- &ast_trait_ref.path,
- ast_trait_ref.ref_id));
-
+ def::DefTrait(trait_def_id) => {
+ let trait_ref = Rc::new(ast_path_to_trait_ref(this, rscope, trait_def_id, self_ty,
+ associated_type, &ast_trait_ref.path));
this.tcx().trait_refs.borrow_mut().insert(ast_trait_ref.ref_id,
trait_ref.clone());
trait_ref
}
}
-pub fn ast_path_to_trait_ref<'tcx,AC,RS>(this: &AC,
- rscope: &RS,
- trait_def_id: ast::DefId,
- self_ty: Option<ty::t>,
- associated_type: Option<ty::t>,
- path: &ast::Path,
- binder_id: ast::NodeId)
- -> ty::TraitRef
- where AC: AstConv<'tcx>,
- RS: RegionScope {
+fn ast_path_to_trait_ref<'tcx,AC,RS>(
+ this: &AC,
+ rscope: &RS,
+ trait_def_id: ast::DefId,
+ self_ty: Option<ty::t>,
+ associated_type: Option<ty::t>,
+ path: &ast::Path)
+ -> ty::TraitRef
+ where AC: AstConv<'tcx>, RS: RegionScope
+{
let trait_def = this.get_trait_def(trait_def_id);
- ty::TraitRef {
- def_id: trait_def_id,
- substs: ast_path_substs(this,
- rscope,
- trait_def_id,
- &trait_def.generics,
- self_ty,
- associated_type,
- path,
- binder_id)
- }
+
+ // the trait reference introduces a binding level here, so
+ // we need to shift the `rscope`. It'd be nice if we could
+ // do away with this rscope stuff and work this knowledge
+ // into resolve_lifetimes, as we do with non-omitted
+ // lifetimes. Oh well, not there yet.
+ let shifted_rscope = ShiftedRscope::new(rscope);
+
+ let (regions, types) = match path.segments.last().unwrap().parameters {
+ ast::AngleBracketedParameters(ref data) => {
+ convert_angle_bracketed_parameters(this, &shifted_rscope, data)
+ }
+ ast::ParenthesizedParameters(ref data) => {
+ (Vec::new(), convert_parenthesized_parameters(this, data))
+ }
+ };
+
+ let substs = create_substs_for_ast_path(this,
+ &shifted_rscope,
+ path.span,
+ trait_def_id,
+ &trait_def.generics,
+ self_ty,
+ types,
+ regions,
+ associated_type);
+
+ ty::TraitRef::new(trait_def_id, substs)
}
pub fn ast_path_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
ast_ty.span,
&[Rc::new(result.clone())],
ast_bounds);
- ty::mk_trait(tcx,
- result,
- bounds)
+ let result_ty = ty::mk_trait(tcx, result, bounds);
+ debug!("ast_ty_to_ty: result_ty={}", result_ty.repr(this.tcx()));
+ result_ty
}
def::DefTy(did, _) | def::DefStruct(did) => {
ast_path_to_ty(this, rscope, did, path).ty
pub struct PartitionedBounds<'a> {
pub builtin_bounds: ty::BuiltinBounds,
- pub trait_bounds: Vec<&'a ast::TraitRef>,
+ pub trait_bounds: Vec<&'a ast::PolyTraitRef>,
pub region_bounds: Vec<&'a ast::Lifetime>,
}
for &ast_bound in ast_bounds.iter() {
match *ast_bound {
ast::TraitTyParamBound(ref b) => {
- let b = &b.trait_ref; // FIXME
- match lookup_def_tcx(tcx, b.path.span, b.ref_id) {
+ match lookup_def_tcx(tcx, b.trait_ref.path.span, b.trait_ref.ref_id) {
def::DefTrait(trait_did) => {
match trait_def_ids.get(&trait_did) {
// Already seen this trait. We forbid
// reason).
Some(span) => {
span_err!(
- tcx.sess, b.path.span, E0127,
+ tcx.sess, b.trait_ref.path.span, E0127,
"trait `{}` already appears in the \
list of bounds",
- b.path.user_string(tcx));
+ b.trait_ref.path.user_string(tcx));
tcx.sess.span_note(
*span,
"previous appearance is here");
None => { }
}
- trait_def_ids.insert(trait_did, b.path.span);
+ trait_def_ids.insert(trait_did, b.trait_ref.path.span);
if ty::try_add_builtin_trait(tcx,
trait_did,
astconv::partition_bounds(this.tcx(), span, all_bounds.as_slice());
let trait_bounds: Vec<Rc<ty::TraitRef>> =
trait_bounds.into_iter()
- .map(|b| {
- astconv::instantiate_trait_ref(this,
- &ExplicitRscope,
- b,
- Some(param_ty.to_ty(this.tcx())),
- Some(param_ty.to_ty(this.tcx())))
+ .map(|bound| {
+ astconv::instantiate_poly_trait_ref(this,
+ &ExplicitRscope,
+ bound,
+ Some(param_ty.to_ty(this.tcx())),
+ Some(param_ty.to_ty(this.tcx())))
})
.collect();
let region_bounds: Vec<ty::Region> =
pub trait Combine<'tcx> {
fn infcx<'a>(&'a self) -> &'a InferCtxt<'a, 'tcx>;
+ fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> { self.infcx().tcx }
fn tag(&self) -> String;
fn a_is_expected(&self) -> bool;
fn trace(&self) -> TypeTrace;
Err(ty::terr_trait_stores_differ(vk, expected_found(self, a, b)))
}
}
-
}
fn trait_refs(&self,
a: &ty::TraitRef,
b: &ty::TraitRef)
- -> cres<ty::TraitRef> {
- // Different traits cannot be related
-
- // - NOTE in the future, expand out subtraits!
-
- if a.def_id != b.def_id {
- Err(ty::terr_traits(
- expected_found(self, a.def_id, b.def_id)))
- } else {
- let substs = try!(self.substs(a.def_id, &a.substs, &b.substs));
- Ok(ty::TraitRef { def_id: a.def_id,
- substs: substs })
- }
- }
+ -> cres<ty::TraitRef>;
+ // this must be overridden to do correctly, so as to account for higher-ranked
+ // behavior
}
#[deriving(Clone)]
try!(self.sub().fn_sigs(a, b));
self.sub().fn_sigs(b, a)
}
+
+ fn trait_refs(&self, a: &ty::TraitRef, b: &ty::TraitRef) -> cres<ty::TraitRef> {
+ try!(self.sub().trait_refs(a, b));
+ self.sub().trait_refs(b, a)
+ }
}
* a lattice.
*/
-use middle::ty::{RegionVid, TyVar};
+use middle::ty::{TyVar};
use middle::ty;
use middle::typeck::infer::*;
use middle::typeck::infer::combine::*;
use middle::typeck::infer::glb::Glb;
use middle::typeck::infer::lub::Lub;
-use util::nodemap::FnvHashMap;
use util::ppaux::Repr;
pub trait LatticeDir {
}
}
}
-
-///////////////////////////////////////////////////////////////////////////
-// Random utility functions used by LUB/GLB when computing LUB/GLB of
-// fn types
-
-pub fn var_ids<'tcx, T: Combine<'tcx>>(this: &T,
- map: &FnvHashMap<ty::BoundRegion, ty::Region>)
- -> Vec<RegionVid> {
- map.iter().map(|(_, r)| match *r {
- ty::ReInfer(ty::ReVar(r)) => { r }
- r => {
- this.infcx().tcx.sess.span_bug(
- this.trace().origin.span(),
- format!("found non-region-vid: {}", r).as_slice());
- }
- }).collect()
-}
-
-pub fn is_var_in_set(new_vars: &[RegionVid], r: ty::Region) -> bool {
- match r {
- ty::ReInfer(ty::ReVar(ref v)) => new_vars.iter().any(|x| x == v),
- _ => false
- }
-}
fn glb<'a>(&'a self) -> Glb<'a, 'tcx> { Glb(self.fields.clone()) }
fn mts(&self, a: &ty::mt, b: &ty::mt) -> cres<ty::mt> {
- let tcx = self.fields.infcx.tcx;
+ let tcx = self.tcx();
debug!("{}.mts({}, {})",
self.tag(),
fn regions(&self, a: ty::Region, b: ty::Region) -> cres<ty::Region> {
debug!("{}.regions({}, {})",
self.tag(),
- a.repr(self.fields.infcx.tcx),
- b.repr(self.fields.infcx.tcx));
+ a.repr(self.tcx()),
+ b.repr(self.tcx()));
- Ok(self.fields.infcx.region_vars.lub_regions(Subtype(self.trace()), a, b))
+ Ok(self.infcx().region_vars.lub_regions(Subtype(self.trace()), a, b))
}
fn fn_sigs(&self, a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig> {
fn tys(&self, a: ty::t, b: ty::t) -> cres<ty::t> {
super_lattice_tys(self, a, b)
}
+
+ fn trait_refs(&self, a: &ty::TraitRef, b: &ty::TraitRef) -> cres<ty::TraitRef> {
+ self.higher_ranked_lub(a, b)
+ }
}
use middle::subst;
use middle::subst::Substs;
use middle::ty::{TyVid, IntVid, FloatVid, RegionVid};
+use middle::ty::replace_late_bound_regions;
use middle::ty;
-use middle::ty_fold;
-use middle::ty_fold::{TypeFolder, TypeFoldable};
-use middle::typeck::check::regionmanip::replace_late_bound_regions;
+use middle::ty_fold::{HigherRankedFoldable, TypeFolder, TypeFoldable};
use std::cell::{RefCell};
use std::rc::Rc;
use syntax::ast;
format!("({})", tstrs.connect(", "))
}
- pub fn trait_ref_to_string(&self, t: &ty::TraitRef) -> String {
- let t = self.resolve_type_vars_in_trait_ref_if_possible(t);
+ pub fn trait_ref_to_string(&self, t: &Rc<ty::TraitRef>) -> String {
+ let t = self.resolve_type_vars_in_trait_ref_if_possible(&**t);
trait_ref_to_string(self.tcx, &t)
}
fn regions(&self, a: ty::Region, b: ty::Region) -> cres<ty::Region> {
debug!("{}.regions({}, {})",
self.tag(),
- a.repr(self.fields.infcx.tcx),
- b.repr(self.fields.infcx.tcx));
- self.fields.infcx.region_vars.make_subregion(Subtype(self.trace()), a, b);
+ a.repr(self.tcx()),
+ b.repr(self.tcx()));
+ self.infcx().region_vars.make_subregion(Subtype(self.trace()), a, b);
Ok(a)
}
fn mts(&self, a: &ty::mt, b: &ty::mt) -> cres<ty::mt> {
debug!("mts({} <: {})",
- a.repr(self.fields.infcx.tcx),
- b.repr(self.fields.infcx.tcx));
+ a.repr(self.tcx()),
+ b.repr(self.tcx()));
if a.mutbl != b.mutbl {
return Err(ty::terr_mutability);
fn tys(&self, a: ty::t, b: ty::t) -> cres<ty::t> {
debug!("{}.tys({}, {})", self.tag(),
- a.repr(self.fields.infcx.tcx), b.repr(self.fields.infcx.tcx));
+ a.repr(self.tcx()), b.repr(self.tcx()));
if a == b { return Ok(a); }
let infcx = self.fields.infcx;
fn fn_sigs(&self, a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig> {
self.higher_ranked_sub(a, b)
}
+
+ fn trait_refs(&self, a: &ty::TraitRef, b: &ty::TraitRef) -> cres<ty::TraitRef> {
+ self.higher_ranked_sub(a, b)
+ }
}
use middle::ty;
+use middle::ty_fold;
use std::cell::Cell;
-use syntax::ast;
use syntax::codemap::Span;
/// Defines strategies for handling regions that are omitted. For
}
}
+/// A scope which simply shifts the Debruijn index of other scopes
+/// to account for binding levels.
+pub struct ShiftedRscope<'r> {
+ base_scope: &'r RegionScope+'r
+}
+
+impl<'r> ShiftedRscope<'r> {
+ pub fn new(base_scope: &'r RegionScope+'r) -> ShiftedRscope<'r> {
+ ShiftedRscope { base_scope: base_scope }
+ }
+}
+
+impl<'r> RegionScope for ShiftedRscope<'r> {
+ fn default_region_bound(&self, span: Span) -> Option<ty::Region>
+ {
+ self.base_scope.default_region_bound(span)
+ .map(|r| ty_fold::shift_region(r, 1))
+ }
+
+ fn anon_regions(&self,
+ span: Span,
+ count: uint)
+ -> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>>
+ {
+ match self.base_scope.anon_regions(span, count) {
+ Ok(mut v) => {
+ for r in v.iter_mut() {
+ *r = ty_fold::shift_region(*r, 1);
+ }
+ Ok(v)
+ }
+ Err(errs) => {
+ Err(errs)
+ }
+ }
+ }
+}
syntax::ext::mtwt::clear_tables();
let named_region_map = time(time_passes, "lifetime resolution", (),
- |_| middle::resolve_lifetime::krate(&sess, krate));
+ |_| middle::resolve_lifetime::krate(&sess, krate, &def_map));
time(time_passes, "looking for entry point", (),
|_| middle::entry::find_entry_point(&sess, &ast_map));