Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
6fb68f1c
R
Rust
项目概览
int
/
Rust
11 个月 前同步成功
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
Rust
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
6fb68f1c
编写于
11月 15, 2014
作者:
N
Niko Matsakis
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Introduce machinery for higher-ranked TraitRefs
上级
ecdb741d
变更
15
隐藏空白更改
内联
并排
Showing
15 changed file
with
334 addition
and
167 deletion
+334
-167
src/librustc/middle/resolve_lifetime.rs
src/librustc/middle/resolve_lifetime.rs
+34
-36
src/librustc/middle/traits/fulfill.rs
src/librustc/middle/traits/fulfill.rs
+1
-0
src/librustc/middle/traits/select.rs
src/librustc/middle/traits/select.rs
+12
-20
src/librustc/middle/ty.rs
src/librustc/middle/ty.rs
+120
-2
src/librustc/middle/ty_fold.rs
src/librustc/middle/ty_fold.rs
+29
-2
src/librustc/middle/typeck/astconv.rs
src/librustc/middle/typeck/astconv.rs
+61
-43
src/librustc/middle/typeck/collect.rs
src/librustc/middle/typeck/collect.rs
+6
-6
src/librustc/middle/typeck/infer/combine.rs
src/librustc/middle/typeck/infer/combine.rs
+4
-15
src/librustc/middle/typeck/infer/equate.rs
src/librustc/middle/typeck/infer/equate.rs
+5
-0
src/librustc/middle/typeck/infer/lattice.rs
src/librustc/middle/typeck/infer/lattice.rs
+1
-26
src/librustc/middle/typeck/infer/lub.rs
src/librustc/middle/typeck/infer/lub.rs
+8
-4
src/librustc/middle/typeck/infer/mod.rs
src/librustc/middle/typeck/infer/mod.rs
+4
-5
src/librustc/middle/typeck/infer/sub.rs
src/librustc/middle/typeck/infer/sub.rs
+10
-6
src/librustc/middle/typeck/rscope.rs
src/librustc/middle/typeck/rscope.rs
+38
-1
src/librustc_trans/driver/driver.rs
src/librustc_trans/driver/driver.rs
+1
-1
未找到文件。
src/librustc/middle/resolve_lifetime.rs
浏览文件 @
6fb68f1c
...
...
@@ -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
);
...
...
src/librustc/middle/traits/fulfill.rs
浏览文件 @
6fb68f1c
...
...
@@ -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
);
}
...
...
src/librustc/middle/traits/select.rs
浏览文件 @
6fb68f1c
...
...
@@ -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
,
...
...
src/librustc/middle/ty.rs
浏览文件 @
6fb68f1c
...
...
@@ -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.
...
...
src/librustc/middle/ty_fold.rs
浏览文件 @
6fb68f1c
...
...
@@ -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
>
{
...
...
src/librustc/middle/typeck/astconv.rs
浏览文件 @
6fb68f1c
...
...
@@ -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
,
Specific
Rscope
,
BindingRscope
};
use
middle
::
typeck
::
rscope
::{
UnelidableRscope
,
RegionScope
,
SpecificRscope
,
Shifted
Rscope
,
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
::
Poly
TraitRef
>
,
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
,
...
...
src/librustc/middle/typeck/collect.rs
浏览文件 @
6fb68f1c
...
...
@@ -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
(|
b
ound
|
{
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
>
=
...
...
src/librustc/middle/typeck/infer/combine.rs
浏览文件 @
6fb68f1c
...
...
@@ -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)]
...
...
src/librustc/middle/typeck/infer/equate.rs
浏览文件 @
6fb68f1c
...
...
@@ -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
)
}
}
src/librustc/middle/typeck/infer/lattice.rs
浏览文件 @
6fb68f1c
...
...
@@ -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
}
}
src/librustc/middle/typeck/infer/lub.rs
浏览文件 @
6fb68f1c
...
...
@@ -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
)
}
}
src/librustc/middle/typeck/infer/mod.rs
浏览文件 @
6fb68f1c
...
...
@@ -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
)
}
...
...
src/librustc/middle/typeck/infer/sub.rs
浏览文件 @
6fb68f1c
...
...
@@ -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
)
}
}
src/librustc/middle/typeck/rscope.rs
浏览文件 @
6fb68f1c
...
...
@@ -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
)
}
}
}
}
src/librustc_trans/driver/driver.rs
浏览文件 @
6fb68f1c
...
...
@@ -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.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录