Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
3657ae13
R
Rust
项目概览
int
/
Rust
接近 1 年 前同步成功
通知
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,发现更多精彩内容 >>
提交
3657ae13
编写于
12月 28, 2014
作者:
N
Niko Matsakis
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Don't normalize associated types when in region binders, wait until we instantiate
them. Also fix some assertions and handling of builtin bounds.
上级
2bbd2f9c
变更
11
隐藏空白更改
内联
并排
Showing
11 changed file
with
214 addition
and
85 deletion
+214
-85
src/librustc/middle/traits/fulfill.rs
src/librustc/middle/traits/fulfill.rs
+7
-0
src/librustc/middle/traits/select.rs
src/librustc/middle/traits/select.rs
+30
-8
src/librustc/middle/ty.rs
src/librustc/middle/ty.rs
+16
-5
src/librustc_typeck/check/assoc.rs
src/librustc_typeck/check/assoc.rs
+24
-2
src/librustc_typeck/check/closure.rs
src/librustc_typeck/check/closure.rs
+10
-3
src/librustc_typeck/check/method/confirm.rs
src/librustc_typeck/check/method/confirm.rs
+10
-9
src/librustc_typeck/check/method/mod.rs
src/librustc_typeck/check/method/mod.rs
+10
-8
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/mod.rs
+87
-42
src/librustc_typeck/check/regionmanip.rs
src/librustc_typeck/check/regionmanip.rs
+7
-6
src/librustc_typeck/check/wf.rs
src/librustc_typeck/check/wf.rs
+1
-2
src/libsyntax/visit.rs
src/libsyntax/visit.rs
+12
-0
未找到文件。
src/librustc/middle/traits/fulfill.rs
浏览文件 @
3657ae13
...
@@ -109,6 +109,10 @@ pub fn normalize_associated_type<'a>(&mut self,
...
@@ -109,6 +109,10 @@ pub fn normalize_associated_type<'a>(&mut self,
cause
:
ObligationCause
<
'tcx
>
)
cause
:
ObligationCause
<
'tcx
>
)
->
Ty
<
'tcx
>
->
Ty
<
'tcx
>
{
{
debug!
(
"normalize_associated_type(trait_ref={}, item_name={})"
,
trait_ref
.repr
(
infcx
.tcx
),
item_name
.repr
(
infcx
.tcx
));
assert
!
(
!
trait_ref
.has_escaping_regions
());
assert
!
(
!
trait_ref
.has_escaping_regions
());
let
ty_var
=
infcx
.next_ty_var
();
let
ty_var
=
infcx
.next_ty_var
();
...
@@ -120,6 +124,9 @@ pub fn normalize_associated_type<'a>(&mut self,
...
@@ -120,6 +124,9 @@ pub fn normalize_associated_type<'a>(&mut self,
});
});
let
obligation
=
Obligation
::
new
(
cause
,
projection
.as_predicate
());
let
obligation
=
Obligation
::
new
(
cause
,
projection
.as_predicate
());
self
.register_predicate
(
infcx
,
obligation
);
self
.register_predicate
(
infcx
,
obligation
);
debug!
(
"normalize_associated_type: result={}"
,
ty_var
.repr
(
infcx
.tcx
));
ty_var
ty_var
}
}
...
...
src/librustc/middle/traits/select.rs
浏览文件 @
3657ae13
...
@@ -1141,7 +1141,11 @@ fn builtin_bound(&mut self,
...
@@ -1141,7 +1141,11 @@ fn builtin_bound(&mut self,
obligation
:
&
TraitObligation
<
'tcx
>
)
obligation
:
&
TraitObligation
<
'tcx
>
)
->
Result
<
BuiltinBoundConditions
<
'tcx
>
,
SelectionError
<
'tcx
>>
->
Result
<
BuiltinBoundConditions
<
'tcx
>
,
SelectionError
<
'tcx
>>
{
{
// TODO seems like we ought to skolemize here, oder?
// Note: these tests operate on types that may contain bound
// regions. To be proper, we ought to skolemize here, but we
// forego the skolemization and defer it until the
// confirmation step.
let
self_ty
=
self
.infcx
.shallow_resolve
(
obligation
.predicate
.0
.self_ty
());
let
self_ty
=
self
.infcx
.shallow_resolve
(
obligation
.predicate
.0
.self_ty
());
return
match
self_ty
.sty
{
return
match
self_ty
.sty
{
ty
::
ty_infer
(
ty
::
IntVar
(
_
))
|
ty
::
ty_infer
(
ty
::
IntVar
(
_
))
|
...
@@ -1627,13 +1631,31 @@ fn vtable_builtin_data(&mut self,
...
@@ -1627,13 +1631,31 @@ fn vtable_builtin_data(&mut self,
->
VtableBuiltinData
<
PredicateObligation
<
'tcx
>>
->
VtableBuiltinData
<
PredicateObligation
<
'tcx
>>
{
{
let
derived_cause
=
self
.derived_cause
(
obligation
,
BuiltinDerivedObligation
);
let
derived_cause
=
self
.derived_cause
(
obligation
,
BuiltinDerivedObligation
);
let
obligations
=
nested
.iter
()
.map
(|
&
t
|
{
let
obligations
=
nested
.iter
()
.map
(|
&
bound_ty
|
{
util
::
predicate_for_builtin_bound
(
// the obligation might be higher-ranked, e.g. for<'a> &'a
self
.tcx
(),
// int : Copy. In that case, we will wind up with
derived_cause
.clone
(),
// late-bound regions in the `nested` vector. So for each
bound
,
// one we instantiate to a skolemized region, do our work
obligation
.recursion_depth
+
1
,
// to produce something like `&'0 int : Copy`, and then
t
)
// re-bind it. This is a bit of busy-work but preserves
// the invariant that we only manipulate free regions, not
// bound ones.
self
.infcx
.try
(|
snapshot
|
{
let
(
skol_ty
,
skol_map
)
=
self
.infcx
()
.skolemize_late_bound_regions
(
&
ty
::
Binder
(
bound_ty
),
snapshot
);
let
skol_predicate
=
util
::
predicate_for_builtin_bound
(
self
.tcx
(),
derived_cause
.clone
(),
bound
,
obligation
.recursion_depth
+
1
,
skol_ty
);
match
skol_predicate
{
Ok
(
skol_predicate
)
=>
Ok
(
self
.infcx
()
.plug_leaks
(
skol_map
,
snapshot
,
&
skol_predicate
)),
Err
(
ErrorReported
)
=>
Err
(
ErrorReported
)
}
})
})
.collect
::
<
Result
<
_
,
_
>>
();
})
.collect
::
<
Result
<
_
,
_
>>
();
let
mut
obligations
=
match
obligations
{
let
mut
obligations
=
match
obligations
{
Ok
(
o
)
=>
o
,
Ok
(
o
)
=>
o
,
...
...
src/librustc/middle/ty.rs
浏览文件 @
3657ae13
...
@@ -6903,8 +6903,19 @@ fn has_regions_escaping_depth(&self, depth: u32) -> bool {
...
@@ -6903,8 +6903,19 @@ fn has_regions_escaping_depth(&self, depth: u32) -> bool {
impl
<
'tcx
>
RegionEscape
for
TraitRef
<
'tcx
>
{
impl
<
'tcx
>
RegionEscape
for
TraitRef
<
'tcx
>
{
fn
has_regions_escaping_depth
(
&
self
,
depth
:
u32
)
->
bool
{
fn
has_regions_escaping_depth
(
&
self
,
depth
:
u32
)
->
bool
{
self
.substs.types
.iter
()
.any
(|
t
|
t
.has_regions_escaping_depth
(
depth
))
&&
self
.substs.types
.iter
()
.any
(|
t
|
t
.has_regions_escaping_depth
(
depth
))
||
self
.substs
.regions
()
.iter
()
.any
(|
t
|
t
.has_regions_escaping_depth
(
depth
))
self
.substs.regions
.has_regions_escaping_depth
(
depth
)
}
}
impl
<
'tcx
>
RegionEscape
for
subst
::
RegionSubsts
{
fn
has_regions_escaping_depth
(
&
self
,
depth
:
u32
)
->
bool
{
match
*
self
{
subst
::
ErasedRegions
=>
false
,
subst
::
NonerasedRegions
(
ref
r
)
=>
{
r
.iter
()
.any
(|
t
|
t
.has_regions_escaping_depth
(
depth
))
}
}
}
}
}
}
...
@@ -6921,7 +6932,7 @@ fn has_regions_escaping_depth(&self, depth: u32) -> bool {
...
@@ -6921,7 +6932,7 @@ fn has_regions_escaping_depth(&self, depth: u32) -> bool {
}
}
impl
<
'tcx
>
RegionEscape
for
TraitPredicate
<
'tcx
>
{
impl
<
'tcx
>
RegionEscape
for
TraitPredicate
<
'tcx
>
{
fn
has_regions_escaping_depth
(
&
self
,
depth
:
u
int
)
->
bool
{
fn
has_regions_escaping_depth
(
&
self
,
depth
:
u
32
)
->
bool
{
self
.trait_ref
.has_regions_escaping_depth
(
depth
)
self
.trait_ref
.has_regions_escaping_depth
(
depth
)
}
}
}
}
...
@@ -6933,14 +6944,14 @@ fn has_regions_escaping_depth(&self, depth: u32) -> bool {
...
@@ -6933,14 +6944,14 @@ fn has_regions_escaping_depth(&self, depth: u32) -> bool {
}
}
impl
<
'tcx
>
RegionEscape
for
ProjectionPredicate
<
'tcx
>
{
impl
<
'tcx
>
RegionEscape
for
ProjectionPredicate
<
'tcx
>
{
fn
has_regions_escaping_depth
(
&
self
,
depth
:
u
int
)
->
bool
{
fn
has_regions_escaping_depth
(
&
self
,
depth
:
u
32
)
->
bool
{
self
.projection_ty
.has_regions_escaping_depth
(
depth
)
||
self
.projection_ty
.has_regions_escaping_depth
(
depth
)
||
self
.ty
.has_regions_escaping_depth
(
depth
)
self
.ty
.has_regions_escaping_depth
(
depth
)
}
}
}
}
impl
<
'tcx
>
RegionEscape
for
ProjectionTy
<
'tcx
>
{
impl
<
'tcx
>
RegionEscape
for
ProjectionTy
<
'tcx
>
{
fn
has_regions_escaping_depth
(
&
self
,
depth
:
u
int
)
->
bool
{
fn
has_regions_escaping_depth
(
&
self
,
depth
:
u
32
)
->
bool
{
self
.trait_ref
.has_regions_escaping_depth
(
depth
)
self
.trait_ref
.has_regions_escaping_depth
(
depth
)
}
}
}
}
...
...
src/librustc_typeck/check/assoc.rs
浏览文件 @
3657ae13
...
@@ -33,7 +33,8 @@ pub fn normalize_associated_types_in<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
...
@@ -33,7 +33,8 @@ pub fn normalize_associated_types_in<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
let
mut
normalizer
=
AssociatedTypeNormalizer
{
span
:
span
,
let
mut
normalizer
=
AssociatedTypeNormalizer
{
span
:
span
,
body_id
:
body_id
,
body_id
:
body_id
,
infcx
:
infcx
,
infcx
:
infcx
,
fulfillment_cx
:
fulfillment_cx
};
fulfillment_cx
:
fulfillment_cx
,
region_binders
:
0
};
value
.fold_with
(
&
mut
normalizer
)
value
.fold_with
(
&
mut
normalizer
)
}
}
...
@@ -42,6 +43,7 @@ struct AssociatedTypeNormalizer<'a,'tcx:'a> {
...
@@ -42,6 +43,7 @@ struct AssociatedTypeNormalizer<'a,'tcx:'a> {
fulfillment_cx
:
&
'a
mut
FulfillmentContext
<
'tcx
>
,
fulfillment_cx
:
&
'a
mut
FulfillmentContext
<
'tcx
>
,
span
:
Span
,
span
:
Span
,
body_id
:
ast
::
NodeId
,
body_id
:
ast
::
NodeId
,
region_binders
:
uint
,
}
}
impl
<
'a
,
'tcx
>
TypeFolder
<
'tcx
>
for
AssociatedTypeNormalizer
<
'a
,
'tcx
>
{
impl
<
'a
,
'tcx
>
TypeFolder
<
'tcx
>
for
AssociatedTypeNormalizer
<
'a
,
'tcx
>
{
...
@@ -49,9 +51,29 @@ fn tcx(&self) -> &ty::ctxt<'tcx> {
...
@@ -49,9 +51,29 @@ fn tcx(&self) -> &ty::ctxt<'tcx> {
self
.infcx.tcx
self
.infcx.tcx
}
}
fn
enter_region_binder
(
&
mut
self
)
{
self
.region_binders
+=
1
;
}
fn
exit_region_binder
(
&
mut
self
)
{
self
.region_binders
-=
1
;
}
fn
fold_ty
(
&
mut
self
,
ty
:
Ty
<
'tcx
>
)
->
Ty
<
'tcx
>
{
fn
fold_ty
(
&
mut
self
,
ty
:
Ty
<
'tcx
>
)
->
Ty
<
'tcx
>
{
// We don't want to normalize associated types that occur inside of region
// binders, because they may contain bound regions, and we can't cope with that.
//
// Example:
//
// for<'a> fn(<T as Foo<&'a>>::A)
//
// Instead of normalizing `<T as Foo<&'a>>::A` here, we'll
// normalize it when we instantiate those bound regions (which
// should occur eventually).
let
no_region_binders
=
self
.region_binders
==
0
;
match
ty
.sty
{
match
ty
.sty
{
ty
::
ty_projection
(
ref
data
)
=>
{
ty
::
ty_projection
(
ref
data
)
if
no_region_binders
=>
{
let
cause
=
let
cause
=
ObligationCause
::
new
(
ObligationCause
::
new
(
self
.span
,
self
.span
,
...
...
src/librustc_typeck/check/closure.rs
浏览文件 @
3657ae13
...
@@ -14,6 +14,7 @@
...
@@ -14,6 +14,7 @@
use
astconv
;
use
astconv
;
use
middle
::
infer
;
use
middle
::
infer
;
use
middle
::
region
::
CodeExtent
;
use
middle
::
subst
;
use
middle
::
subst
;
use
middle
::
ty
::{
mod
,
ToPolyTraitRef
,
Ty
};
use
middle
::
ty
::{
mod
,
ToPolyTraitRef
,
Ty
};
use
rscope
::
RegionScope
;
use
rscope
::
RegionScope
;
...
@@ -132,10 +133,13 @@ fn check_unboxed_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
...
@@ -132,10 +133,13 @@ fn check_unboxed_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
fcx
.write_ty
(
expr
.id
,
closure_type
);
fcx
.write_ty
(
expr
.id
,
closure_type
);
let
fn_sig
=
ty
::
liberate_late_bound_regions
(
fcx
.tcx
(),
CodeExtent
::
from_node_id
(
body
.id
),
&
fn_ty
.sig
);
check_fn
(
fcx
.ccx
,
check_fn
(
fcx
.ccx
,
ast
::
Unsafety
::
Normal
,
ast
::
Unsafety
::
Normal
,
expr
.id
,
expr
.id
,
&
fn_
ty
.
sig
,
&
fn_sig
,
decl
,
decl
,
expr
.id
,
expr
.id
,
&*
body
,
&*
body
,
...
@@ -310,7 +314,7 @@ fn check_boxed_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
...
@@ -310,7 +314,7 @@ fn check_boxed_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
decl
,
decl
,
abi
::
Rust
,
abi
::
Rust
,
expected_sig
);
expected_sig
);
let
f
ty
_sig
=
fn_ty
.sig
.clone
();
let
f
n
_sig
=
fn_ty
.sig
.clone
();
let
fty
=
ty
::
mk_closure
(
tcx
,
fn_ty
);
let
fty
=
ty
::
mk_closure
(
tcx
,
fn_ty
);
debug!
(
"check_expr_fn fty={}"
,
fcx
.infcx
()
.ty_to_string
(
fty
));
debug!
(
"check_expr_fn fty={}"
,
fcx
.infcx
()
.ty_to_string
(
fty
));
...
@@ -325,10 +329,13 @@ fn check_boxed_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
...
@@ -325,10 +329,13 @@ fn check_boxed_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
ty
::
UniqTraitStore
=>
(
ast
::
Unsafety
::
Normal
,
expr
.id
)
ty
::
UniqTraitStore
=>
(
ast
::
Unsafety
::
Normal
,
expr
.id
)
};
};
let
fn_sig
=
ty
::
liberate_late_bound_regions
(
tcx
,
CodeExtent
::
from_node_id
(
body
.id
),
&
fn_sig
);
check_fn
(
fcx
.ccx
,
check_fn
(
fcx
.ccx
,
inherited_style
,
inherited_style
,
inherited_style_id
,
inherited_style_id
,
&
f
ty
_sig
,
&
f
n
_sig
,
&*
decl
,
&*
decl
,
expr
.id
,
expr
.id
,
&*
body
,
&*
body
,
...
...
src/librustc_typeck/check/method/confirm.rs
浏览文件 @
3657ae13
...
@@ -424,17 +424,18 @@ fn instantiate_method_sig(&mut self,
...
@@ -424,17 +424,18 @@ fn instantiate_method_sig(&mut self,
debug!
(
"method_bounds after subst = {}"
,
debug!
(
"method_bounds after subst = {}"
,
method_bounds
.repr
(
self
.tcx
()));
method_bounds
.repr
(
self
.tcx
()));
// Substitute the type/early-bound-regions into the method
// Instantiate late-bound regions and substitute the trait
// signature. In addition, the method signature may bind
// parameters into the method type to get the actual method type.
// late-bound regions, so instantiate those.
//
let
method_sig
=
self
.fcx
.instantiate_type_scheme
(
self
.span
,
// NB: Instantiate late-bound regions first so that
&
all_substs
,
// `instantiate_type_scheme` can normalize associated types that
&
pick
.method_ty.fty.sig
);
// may reference those regions.
debug!
(
"late-bound lifetimes from method substituted, method_sig={}"
,
let
method_sig
=
self
.replace_late_bound_regions_with_fresh_var
(
&
pick
.method_ty.fty.sig
);
debug!
(
"late-bound lifetimes from method instantiated, method_sig={}"
,
method_sig
.repr
(
self
.tcx
()));
method_sig
.repr
(
self
.tcx
()));
let
method_sig
=
self
.
replace_late_bound_regions_with_fresh_var
(
&
method_sig
);
let
method_sig
=
self
.
fcx
.instantiate_type_scheme
(
self
.span
,
&
all_substs
,
&
method_sig
);
debug!
(
"
late-bound lifetimes from method instantia
ted, method_sig={}"
,
debug!
(
"
type scheme substitu
ted, method_sig={}"
,
method_sig
.repr
(
self
.tcx
()));
method_sig
.repr
(
self
.tcx
()));
InstantiatedMethodSig
{
InstantiatedMethodSig
{
...
...
src/librustc_typeck/check/method/mod.rs
浏览文件 @
3657ae13
...
@@ -190,19 +190,21 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>,
...
@@ -190,19 +190,21 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>,
debug!
(
"lookup_in_trait_adjusted: method_num={} method_ty={}"
,
debug!
(
"lookup_in_trait_adjusted: method_num={} method_ty={}"
,
method_num
,
method_ty
.repr
(
fcx
.tcx
()));
method_num
,
method_ty
.repr
(
fcx
.tcx
()));
// Substitute the trait parameters into the method type and
// Instantiate late-bound regions and substitute the trait
// instantiate late-bound regions to get the actual method type.
// parameters into the method type to get the actual method type.
let
bare_fn_ty
=
fcx
.instantiate_type_scheme
(
span
,
//
&
trait_ref
.substs
,
// NB: Instantiate late-bound regions first so that
&
method_ty
.fty
);
// `instantiate_type_scheme` can normalize associated types that
// may reference those regions.
let
fn_sig
=
fcx
.infcx
()
.replace_late_bound_regions_with_fresh_var
(
span
,
let
fn_sig
=
fcx
.infcx
()
.replace_late_bound_regions_with_fresh_var
(
span
,
infer
::
FnCall
,
infer
::
FnCall
,
&
bare_fn_ty
.sig
)
.0
;
&
method_ty
.fty.sig
)
.0
;
let
fn_sig
=
fcx
.instantiate_type_scheme
(
span
,
&
trait_ref
.substs
,
&
fn_sig
);
let
transformed_self_ty
=
fn_sig
.inputs
[
0
];
let
transformed_self_ty
=
fn_sig
.inputs
[
0
];
let
fty
=
ty
::
mk_bare_fn
(
tcx
,
None
,
tcx
.mk_bare_fn
(
ty
::
BareFnTy
{
let
fty
=
ty
::
mk_bare_fn
(
tcx
,
None
,
tcx
.mk_bare_fn
(
ty
::
BareFnTy
{
sig
:
ty
::
Binder
(
fn_sig
),
sig
:
ty
::
Binder
(
fn_sig
),
unsafety
:
bare_fn_
ty
.unsafety
,
unsafety
:
method_ty
.f
ty.unsafety
,
abi
:
bare_fn_
ty
.abi
.clone
(),
abi
:
method_ty
.f
ty.abi
.clone
(),
}));
}));
debug!
(
"lookup_in_trait_adjusted: matched method fty={} obligation={}"
,
debug!
(
"lookup_in_trait_adjusted: matched method fty={} obligation={}"
,
...
...
src/librustc_typeck/check/mod.rs
浏览文件 @
3657ae13
...
@@ -432,13 +432,15 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
...
@@ -432,13 +432,15 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
ty
::
ty_bare_fn
(
_
,
ref
fn_ty
)
=>
{
ty
::
ty_bare_fn
(
_
,
ref
fn_ty
)
=>
{
let
inh
=
Inherited
::
new
(
ccx
.tcx
,
param_env
);
let
inh
=
Inherited
::
new
(
ccx
.tcx
,
param_env
);
// Compute the fty from point of view of inside fn
// Compute the fty from point of view of inside fn.
// (replace any type-scheme with a type, and normalize
let
fn_sig
=
// associated types appearing in the fn signature).
fn_ty
.sig
.subst
(
ccx
.tcx
,
&
inh
.param_env.free_substs
);
let
fn_ty
=
fn_ty
.subst
(
ccx
.tcx
,
&
inh
.param_env.free_substs
);
let
fn_sig
=
let
fn_ty
=
inh
.normalize_associated_types_in
(
body
.span
,
body
.id
,
&
fn_ty
);
liberate_late_bound_regions
(
ccx
.tcx
,
CodeExtent
::
from_node_id
(
body
.id
),
&
fn_sig
);
let
fn_sig
=
let
fcx
=
check_fn
(
ccx
,
fn_ty
.unsafety
,
id
,
&
fn_ty
.sig
,
inh
.normalize_associated_types_in
(
body
.span
,
body
.id
,
&
fn_sig
);
let
fcx
=
check_fn
(
ccx
,
fn_ty
.unsafety
,
id
,
&
fn_sig
,
decl
,
id
,
body
,
&
inh
);
decl
,
id
,
body
,
&
inh
);
vtable
::
select_all_fcx_obligations_or_error
(
&
fcx
);
vtable
::
select_all_fcx_obligations_or_error
(
&
fcx
);
...
@@ -542,7 +544,7 @@ fn visit_item(&mut self, _: &ast::Item) { }
...
@@ -542,7 +544,7 @@ fn visit_item(&mut self, _: &ast::Item) { }
fn
check_fn
<
'a
,
'tcx
>
(
ccx
:
&
'a
CrateCtxt
<
'a
,
'tcx
>
,
fn
check_fn
<
'a
,
'tcx
>
(
ccx
:
&
'a
CrateCtxt
<
'a
,
'tcx
>
,
unsafety
:
ast
::
Unsafety
,
unsafety
:
ast
::
Unsafety
,
unsafety_id
:
ast
::
NodeId
,
unsafety_id
:
ast
::
NodeId
,
fn_sig
:
&
ty
::
Poly
FnSig
<
'tcx
>
,
fn_sig
:
&
ty
::
FnSig
<
'tcx
>
,
decl
:
&
ast
::
FnDecl
,
decl
:
&
ast
::
FnDecl
,
fn_id
:
ast
::
NodeId
,
fn_id
:
ast
::
NodeId
,
body
:
&
ast
::
Block
,
body
:
&
ast
::
Block
,
...
@@ -552,10 +554,6 @@ fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
...
@@ -552,10 +554,6 @@ fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
let
tcx
=
ccx
.tcx
;
let
tcx
=
ccx
.tcx
;
let
err_count_on_creation
=
tcx
.sess
.err_count
();
let
err_count_on_creation
=
tcx
.sess
.err_count
();
// 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
=
liberate_late_bound_regions
(
tcx
,
CodeExtent
::
from_node_id
(
body
.id
),
fn_sig
);
let
arg_tys
=
fn_sig
.inputs
[];
let
arg_tys
=
fn_sig
.inputs
[];
let
ret_ty
=
fn_sig
.output
;
let
ret_ty
=
fn_sig
.output
;
...
@@ -1161,39 +1159,80 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
...
@@ -1161,39 +1159,80 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
}
}
}
}
// We now need to check that the signature of the impl method is
// compatible with that of the trait method. We do this by
// checking that `impl_fty <: trait_fty`.
//
// FIXME. Unfortunately, this doesn't quite work right now because
// associated type normalization is not integrated into subtype
// checks. For the comparison to be valid, we need to
// normalize the associated types in the impl/trait methods
// first. However, because function types bind regions, just
// calling `normalize_associated_types_in` would have no effect on
// any associated types appearing in the fn arguments or return
// type.
// Compute skolemized form of impl and trait method tys.
// Compute skolemized form of impl and trait method tys.
let
impl_fty
=
ty
::
mk_bare_fn
(
tcx
,
None
,
tcx
.mk_bare_fn
(
impl_m
.fty
.clone
()));
let
impl_fty
=
ty
::
mk_bare_fn
(
tcx
,
None
,
tcx
.mk_bare_fn
(
impl_m
.fty
.clone
()));
let
impl_fty
=
impl_fty
.subst
(
tcx
,
impl_to_skol_substs
);
let
impl_fty
=
impl_fty
.subst
(
tcx
,
impl_to_skol_substs
);
let
trait_fty
=
ty
::
mk_bare_fn
(
tcx
,
None
,
tcx
.mk_bare_fn
(
trait_m
.fty
.clone
()));
let
trait_fty
=
ty
::
mk_bare_fn
(
tcx
,
None
,
tcx
.mk_bare_fn
(
trait_m
.fty
.clone
()));
let
trait_fty
=
trait_fty
.subst
(
tcx
,
&
trait_to_skol_substs
);
let
trait_fty
=
trait_fty
.subst
(
tcx
,
&
trait_to_skol_substs
);
let
trait_fty
=
assoc
::
normalize_associated_types_in
(
&
infcx
,
let
err
=
infcx
.try
(|
snapshot
|
{
&
mut
fulfillment_cx
,
let
origin
=
infer
::
MethodCompatCheck
(
impl_m_span
);
impl_m_span
,
impl_m_body_id
,
let
(
impl_sig
,
_
)
=
&
trait_fty
);
infcx
.replace_late_bound_regions_with_fresh_var
(
impl_m_span
,
infer
::
HigherRankedType
,
// Check the impl method type IM is a subtype of the trait method
&
impl_m
.fty.sig
);
// type TM. To see why this makes sense, think of a vtable. The
let
impl_sig
=
// expected type of the function pointers in the vtable is the
impl_sig
.subst
(
tcx
,
impl_to_skol_substs
);
// type TM of the trait method. The actual type will be the type
let
impl_sig
=
// IM of the impl method. Because we know that IM <: TM, that
assoc
::
normalize_associated_types_in
(
&
infcx
,
// means that anywhere a TM is expected, a IM will do instead. In
&
mut
fulfillment_cx
,
// other words, anyone expecting to call a method with the type
impl_m_span
,
// from the trait, can safely call a method with the type from the
impl_m_body_id
,
// impl instead.
&
impl_sig
);
debug!
(
"checking trait method for compatibility: impl ty {}, trait ty {}"
,
let
impl_fty
=
ty
::
mk_bare_fn
(
tcx
,
None
,
ty
::
BareFnTy
{
unsafety
:
impl_m
.fty.unsafety
,
impl_fty
.repr
(
tcx
),
abi
:
impl_m
.fty.abi
,
trait_fty
.repr
(
tcx
));
sig
:
ty
::
Binder
(
impl_sig
)
});
match
infer
::
mk_subty
(
&
infcx
,
false
,
infer
::
MethodCompatCheck
(
impl_m_span
),
debug!
(
"compare_impl_method: impl_fty={}"
,
impl_fty
,
trait_fty
)
{
impl_fty
.repr
(
tcx
));
Ok
(())
=>
{}
Err
(
ref
terr
)
=>
{
let
(
trait_sig
,
skol_map
)
=
infcx
.skolemize_late_bound_regions
(
&
trait_m
.fty.sig
,
snapshot
);
let
trait_sig
=
trait_sig
.subst
(
tcx
,
&
trait_to_skol_substs
);
let
trait_sig
=
assoc
::
normalize_associated_types_in
(
&
infcx
,
&
mut
fulfillment_cx
,
impl_m_span
,
impl_m_body_id
,
&
trait_sig
);
let
trait_fty
=
ty
::
mk_bare_fn
(
tcx
,
None
,
ty
::
BareFnTy
{
unsafety
:
trait_m
.fty.unsafety
,
abi
:
trait_m
.fty.abi
,
sig
:
ty
::
Binder
(
trait_sig
)
});
debug!
(
"compare_impl_method: trait_fty={}"
,
trait_fty
.repr
(
tcx
));
try!
(
infer
::
mk_subty
(
&
infcx
,
false
,
origin
,
impl_fty
,
trait_fty
));
infcx
.leak_check
(
&
skol_map
,
snapshot
)
});
match
err
{
Ok
(())
=>
{
}
Err
(
terr
)
=>
{
debug!
(
"checking trait method for compatibility: impl ty {}, trait ty {}"
,
impl_fty
.repr
(
tcx
),
trait_fty
.repr
(
tcx
));
span_err!
(
tcx
.sess
,
impl_m_span
,
E0053
,
span_err!
(
tcx
.sess
,
impl_m_span
,
E0053
,
"method `{}` has an incompatible type for trait: {}"
,
"method `{}` has an incompatible type for trait: {}"
,
token
::
get_name
(
trait_m
.name
),
token
::
get_name
(
trait_m
.name
),
ty
::
type_err_to_str
(
tcx
,
terr
));
ty
::
type_err_to_str
(
tcx
,
&
terr
));
ty
::
note_and_explain_type_err
(
tcx
,
terr
)
;
return
;
}
}
}
}
...
@@ -1791,7 +1830,7 @@ fn register_unsize_obligations(&self,
...
@@ -1791,7 +1830,7 @@ fn register_unsize_obligations(&self,
/// Also returns the substitution from the type parameters on `def_id` to the fresh variables.
/// Also returns the substitution from the type parameters on `def_id` to the fresh variables.
/// Registers any trait obligations specified on `def_id` at the same time.
/// Registers any trait obligations specified on `def_id` at the same time.
///
///
/// Note that function is only intended to be used with types (notably, not
impl
s). This is
/// Note that function is only intended to be used with types (notably, not
fn
s). This is
/// because it doesn't do any instantiation of late-bound regions.
/// because it doesn't do any instantiation of late-bound regions.
pub
fn
instantiate_type
(
&
self
,
pub
fn
instantiate_type
(
&
self
,
span
:
Span
,
span
:
Span
,
...
@@ -3061,12 +3100,18 @@ fn check_call(fcx: &FnCtxt,
...
@@ -3061,12 +3100,18 @@ fn check_call(fcx: &FnCtxt,
}
}
};
};
// Replace any bound regions that appear in the function
// Replace any late-bound regions that appear in the function
// signature with region variables
// signature with region variables. We also have to
// renormalize the associated types at this point, since they
// previously appeared within a `Binder<>` and hence would not
// have been normalized before.
let
fn_sig
=
let
fn_sig
=
fcx
.infcx
()
.replace_late_bound_regions_with_fresh_var
(
call_expr
.span
,
fcx
.infcx
()
.replace_late_bound_regions_with_fresh_var
(
call_expr
.span
,
infer
::
FnCall
,
infer
::
FnCall
,
fn_sig
)
.0
;
fn_sig
)
.0
;
let
fn_sig
=
fcx
.normalize_associated_types_in
(
call_expr
.span
,
&
fn_sig
);
// Call the generic checker.
// Call the generic checker.
check_argument_types
(
fcx
,
check_argument_types
(
fcx
,
...
...
src/librustc_typeck/check/regionmanip.rs
浏览文件 @
3657ae13
...
@@ -104,7 +104,8 @@ fn accumulate_from_ty(&mut self, ty: Ty<'tcx>) {
...
@@ -104,7 +104,8 @@ fn accumulate_from_ty(&mut self, ty: Ty<'tcx>) {
ty
::
ty_enum
(
def_id
,
substs
)
|
ty
::
ty_enum
(
def_id
,
substs
)
|
ty
::
ty_struct
(
def_id
,
substs
)
=>
{
ty
::
ty_struct
(
def_id
,
substs
)
=>
{
self
.accumulate_from_adt
(
ty
,
def_id
,
substs
)
let
item_scheme
=
ty
::
lookup_item_type
(
self
.tcx
,
def_id
);
self
.accumulate_from_adt
(
ty
,
def_id
,
&
item_scheme
.generics
,
substs
)
}
}
ty
::
ty_vec
(
t
,
_
)
|
ty
::
ty_vec
(
t
,
_
)
|
...
@@ -127,7 +128,9 @@ fn accumulate_from_ty(&mut self, ty: Ty<'tcx>) {
...
@@ -127,7 +128,9 @@ fn accumulate_from_ty(&mut self, ty: Ty<'tcx>) {
// TODO What region constraints are necessary here, if any??
// TODO What region constraints are necessary here, if any??
// this seems like a minimal requirement:
// this seems like a minimal requirement:
self
.accumulate_from_ty
(
data
.trait_ref
.self_ty
());
let
trait_def
=
ty
::
lookup_trait_def
(
self
.tcx
,
data
.trait_ref.def_id
);
self
.accumulate_from_adt
(
ty
,
data
.trait_ref.def_id
,
&
trait_def
.generics
,
&
data
.trait_ref.substs
)
}
}
ty
::
ty_tup
(
ref
tuptys
)
=>
{
ty
::
ty_tup
(
ref
tuptys
)
=>
{
...
@@ -222,14 +225,12 @@ fn push_param_constraint(&mut self,
...
@@ -222,14 +225,12 @@ fn push_param_constraint(&mut self,
fn
accumulate_from_adt
(
&
mut
self
,
fn
accumulate_from_adt
(
&
mut
self
,
ty
:
Ty
<
'tcx
>
,
ty
:
Ty
<
'tcx
>
,
def_id
:
ast
::
DefId
,
def_id
:
ast
::
DefId
,
generics
:
&
ty
::
Generics
<
'tcx
>
,
substs
:
&
Substs
<
'tcx
>
)
substs
:
&
Substs
<
'tcx
>
)
{
{
// The generic declarations from the type, appropriately
// The generic declarations from the type, appropriately
// substituted for the actual substitutions.
// substituted for the actual substitutions.
let
generics
=
let
generics
=
generics
.subst
(
self
.tcx
,
substs
);
ty
::
lookup_item_type
(
self
.tcx
,
def_id
)
.generics
.subst
(
self
.tcx
,
substs
);
// Variance of each type/region parameter.
// Variance of each type/region parameter.
let
variances
=
ty
::
item_variances
(
self
.tcx
,
def_id
);
let
variances
=
ty
::
item_variances
(
self
.tcx
,
def_id
);
...
...
src/librustc_typeck/check/wf.rs
浏览文件 @
3657ae13
...
@@ -349,8 +349,7 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
...
@@ -349,8 +349,7 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
//
//
// (I believe we should do the same for traits, but
// (I believe we should do the same for traits, but
// that will require an RFC. -nmatsakis)
// that will require an RFC. -nmatsakis)
let
bounds
=
type_scheme
let
bounds
=
type_scheme
.generics
.to_bounds
(
self
.tcx
(),
substs
);
.generics
.to_bounds
(
self
.tcx
(),
substs
);
let
bounds
=
filter_to_trait_obligations
(
bounds
);
let
bounds
=
filter_to_trait_obligations
(
bounds
);
self
.fcx
.add_obligations_for_parameters
(
self
.fcx
.add_obligations_for_parameters
(
traits
::
ObligationCause
::
new
(
self
.span
,
traits
::
ObligationCause
::
new
(
self
.span
,
...
...
src/libsyntax/visit.rs
浏览文件 @
3657ae13
...
@@ -133,6 +133,9 @@ fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v PathSegment)
...
@@ -133,6 +133,9 @@ fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v PathSegment)
fn
visit_path_parameters
(
&
mut
self
,
path_span
:
Span
,
path_parameters
:
&
'v
PathParameters
)
{
fn
visit_path_parameters
(
&
mut
self
,
path_span
:
Span
,
path_parameters
:
&
'v
PathParameters
)
{
walk_path_parameters
(
self
,
path_span
,
path_parameters
)
walk_path_parameters
(
self
,
path_span
,
path_parameters
)
}
}
fn
visit_assoc_type_binding
(
&
mut
self
,
type_binding
:
&
'v
TypeBinding
)
{
walk_assoc_type_binding
(
self
,
type_binding
)
}
fn
visit_attribute
(
&
mut
self
,
_
attr
:
&
'v
Attribute
)
{}
fn
visit_attribute
(
&
mut
self
,
_
attr
:
&
'v
Attribute
)
{}
}
}
...
@@ -467,6 +470,9 @@ pub fn walk_path_parameters<'v, V: Visitor<'v>>(visitor: &mut V,
...
@@ -467,6 +470,9 @@ pub fn walk_path_parameters<'v, V: Visitor<'v>>(visitor: &mut V,
for
lifetime
in
data
.lifetimes
.iter
()
{
for
lifetime
in
data
.lifetimes
.iter
()
{
visitor
.visit_lifetime_ref
(
lifetime
);
visitor
.visit_lifetime_ref
(
lifetime
);
}
}
for
binding
in
data
.bindings
.iter
()
{
visitor
.visit_assoc_type_binding
(
&**
binding
);
}
}
}
ast
::
ParenthesizedParameters
(
ref
data
)
=>
{
ast
::
ParenthesizedParameters
(
ref
data
)
=>
{
for
typ
in
data
.inputs
.iter
()
{
for
typ
in
data
.inputs
.iter
()
{
...
@@ -479,6 +485,12 @@ pub fn walk_path_parameters<'v, V: Visitor<'v>>(visitor: &mut V,
...
@@ -479,6 +485,12 @@ pub fn walk_path_parameters<'v, V: Visitor<'v>>(visitor: &mut V,
}
}
}
}
pub
fn
walk_assoc_type_binding
<
'v
,
V
:
Visitor
<
'v
>>
(
visitor
:
&
mut
V
,
type_binding
:
&
'v
TypeBinding
)
{
visitor
.visit_ident
(
type_binding
.span
,
type_binding
.ident
);
visitor
.visit_ty
(
&*
type_binding
.ty
);
}
pub
fn
walk_pat
<
'v
,
V
:
Visitor
<
'v
>>
(
visitor
:
&
mut
V
,
pattern
:
&
'v
Pat
)
{
pub
fn
walk_pat
<
'v
,
V
:
Visitor
<
'v
>>
(
visitor
:
&
mut
V
,
pattern
:
&
'v
Pat
)
{
match
pattern
.node
{
match
pattern
.node
{
PatEnum
(
ref
path
,
ref
children
)
=>
{
PatEnum
(
ref
path
,
ref
children
)
=>
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录