提交 6fb68f1c 编写于 作者: N Niko Matsakis

Introduce machinery for higher-ranked TraitRefs

上级 ecdb741d
......@@ -21,11 +21,13 @@
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};
......@@ -52,7 +54,8 @@ pub enum DefRegion {
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> {
......@@ -72,12 +75,13 @@ 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
......@@ -151,6 +155,27 @@ fn visit_ty(&mut self, ty: &ast::Ty) {
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)
}
......@@ -177,7 +202,7 @@ fn visit_lifetime_ref(&mut self, lifetime_ref: &ast::Lifetime) {
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 => {}
......@@ -185,41 +210,14 @@ fn visit_generics(&mut self, generics: &ast::Generics) {
}
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);
......
......@@ -55,6 +55,7 @@ pub fn register_obligation(&mut self,
obligation: Obligation)
{
debug!("register_obligation({})", obligation.repr(tcx));
assert!(!obligation.trait_ref.has_escaping_regions());
self.trait_obligations.push(obligation);
}
......
......@@ -31,9 +31,7 @@
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;
......@@ -211,6 +209,7 @@ pub fn select(&mut self, obligation: &Obligation) -> SelectionResult<Selection>
*/
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)) {
......@@ -263,6 +262,7 @@ pub fn evaluate_obligation(&mut self,
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()
......@@ -747,6 +747,7 @@ fn candidate_from_obligation(&mut self,
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) => {
......@@ -1707,27 +1708,18 @@ fn confirm_unboxed_closure_candidate(&mut self,
}
};
// 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,
......
......@@ -1105,6 +1105,23 @@ pub struct TyTrait {
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,
......@@ -1410,6 +1427,14 @@ pub fn input_types(&self) -> &[ty::t] {
// 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
......@@ -1826,7 +1851,10 @@ fn add_sty(&mut self, st: &sty) {
}
&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);
}
......@@ -4708,9 +4736,99 @@ pub fn bounds_for_trait_ref(tcx: &ctxt,
-> 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.
......
......@@ -42,7 +42,6 @@
use middle::traits;
use middle::typeck;
use std::rc::Rc;
use syntax::ast;
use syntax::owned_slice::OwnedSlice;
use util::ppaux::Repr;
......@@ -477,6 +476,7 @@ fn fold_with<'tcx, F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::VtableP
// "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 {
......@@ -550,9 +550,21 @@ pub fn super_fold_closure_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut 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),
......@@ -691,11 +703,26 @@ fn fold_contents<'tcx, F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::FnSig
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> {
......
......@@ -55,11 +55,10 @@
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};
......@@ -414,6 +413,16 @@ fn convert_parenthesized_parameters<'tcx,AC>(this: &AC,
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,
......@@ -434,16 +443,9 @@ 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
......@@ -456,28 +458,45 @@ pub fn instantiate_trait_ref<'tcx,AC,RS>(this: &AC,
}
}
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>(
......@@ -923,9 +942,9 @@ pub fn ast_ty_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
......@@ -1562,7 +1581,7 @@ fn compute_region_bound<'tcx, AC: AstConv<'tcx>, RS:RegionScope>(
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>,
}
......@@ -1584,8 +1603,7 @@ pub fn partition_bounds<'a>(tcx: &ty::ctxt,
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
......@@ -1593,10 +1611,10 @@ pub fn partition_bounds<'a>(tcx: &ty::ctxt,
// 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");
......@@ -1607,7 +1625,7 @@ pub fn partition_bounds<'a>(tcx: &ty::ctxt,
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,
......
......@@ -2006,12 +2006,12 @@ fn conv_param_bounds<'tcx,AC>(this: &AC,
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> =
......
......@@ -59,6 +59,7 @@
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;
......@@ -296,26 +297,14 @@ fn trait_stores(&self,
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)]
......
......@@ -137,4 +137,9 @@ fn fn_sigs(&self, a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig> {
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)
}
}
......@@ -31,13 +31,12 @@
* 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 {
......@@ -101,27 +100,3 @@ pub fn super_lattice_tys<'tcx, L:LatticeDir+Combine<'tcx>>(this: &L,
}
}
}
///////////////////////////////////////////////////////////////////////////
// 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
}
}
......@@ -47,7 +47,7 @@ fn lub<'a>(&'a self) -> Lub<'a, 'tcx> { Lub(self.fields.clone()) }
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(),
......@@ -107,10 +107,10 @@ fn contraregions(&self, a: ty::Region, b: ty::Region)
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> {
......@@ -120,4 +120,8 @@ 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)
}
}
......@@ -31,10 +31,9 @@
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;
......@@ -816,8 +815,8 @@ pub fn tys_to_string(&self, ts: &[ty::t]) -> String {
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)
}
......
......@@ -63,16 +63,16 @@ fn contraregions(&self, a: ty::Region, b: ty::Region)
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);
......@@ -121,7 +121,7 @@ fn builtin_bounds(&self, a: BuiltinBounds, b: BuiltinBounds)
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;
......@@ -158,5 +158,9 @@ 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_sub(a, b)
}
fn trait_refs(&self, a: &ty::TraitRef, b: &ty::TraitRef) -> cres<ty::TraitRef> {
self.higher_ranked_sub(a, b)
}
}
......@@ -10,9 +10,9 @@
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
......@@ -136,3 +136,40 @@ fn anon_regions(&self,
}
}
/// 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)
}
}
}
}
......@@ -385,7 +385,7 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
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));
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册