Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
f45c0ef5
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,发现更多精彩内容 >>
提交
f45c0ef5
编写于
12月 14, 2014
作者:
N
Niko Matsakis
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Implement "perfect forwarding" for HR impls (#19730).
上级
c2ca1a4b
变更
38
显示空白变更内容
内联
并排
Showing
38 changed file
with
759 addition
and
416 deletion
+759
-416
src/librustc/lint/builtin.rs
src/librustc/lint/builtin.rs
+1
-3
src/librustc/metadata/csearch.rs
src/librustc/metadata/csearch.rs
+1
-1
src/librustc/metadata/decoder.rs
src/librustc/metadata/decoder.rs
+2
-2
src/librustc/middle/astencode.rs
src/librustc/middle/astencode.rs
+4
-4
src/librustc/middle/dead.rs
src/librustc/middle/dead.rs
+1
-1
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/expr_use_visitor.rs
+2
-2
src/librustc/middle/infer/error_reporting.rs
src/librustc/middle/infer/error_reporting.rs
+12
-1
src/librustc/middle/infer/higher_ranked/mod.rs
src/librustc/middle/infer/higher_ranked/mod.rs
+96
-6
src/librustc/middle/infer/mod.rs
src/librustc/middle/infer/mod.rs
+39
-8
src/librustc/middle/privacy.rs
src/librustc/middle/privacy.rs
+5
-5
src/librustc/middle/resolve_lifetime.rs
src/librustc/middle/resolve_lifetime.rs
+2
-7
src/librustc/middle/traits/coherence.rs
src/librustc/middle/traits/coherence.rs
+5
-10
src/librustc/middle/traits/fulfill.rs
src/librustc/middle/traits/fulfill.rs
+1
-4
src/librustc/middle/traits/select.rs
src/librustc/middle/traits/select.rs
+168
-124
src/librustc/middle/ty.rs
src/librustc/middle/ty.rs
+29
-28
src/librustc/middle/ty_fold.rs
src/librustc/middle/ty_fold.rs
+21
-12
src/librustc_trans/save/mod.rs
src/librustc_trans/save/mod.rs
+2
-2
src/librustc_trans/trans/callee.rs
src/librustc_trans/trans/callee.rs
+2
-3
src/librustc_trans/trans/meth.rs
src/librustc_trans/trans/meth.rs
+3
-3
src/librustc_typeck/astconv.rs
src/librustc_typeck/astconv.rs
+9
-10
src/librustc_typeck/check/method/confirm.rs
src/librustc_typeck/check/method/confirm.rs
+22
-33
src/librustc_typeck/check/method/mod.rs
src/librustc_typeck/check/method/mod.rs
+7
-9
src/librustc_typeck/check/method/probe.rs
src/librustc_typeck/check/method/probe.rs
+14
-18
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/mod.rs
+8
-54
src/librustc_typeck/check/wf.rs
src/librustc_typeck/check/wf.rs
+1
-4
src/librustc_typeck/coherence/mod.rs
src/librustc_typeck/coherence/mod.rs
+11
-13
src/librustc_typeck/coherence/unsafety.rs
src/librustc_typeck/coherence/unsafety.rs
+1
-1
src/librustc_typeck/collect.rs
src/librustc_typeck/collect.rs
+56
-42
src/librustdoc/clean/inline.rs
src/librustdoc/clean/inline.rs
+1
-1
src/test/compile-fail/hrtb-conflate-regions.rs
src/test/compile-fail/hrtb-conflate-regions.rs
+40
-0
src/test/compile-fail/hrtb-just-for-static.rs
src/test/compile-fail/hrtb-just-for-static.rs
+37
-0
src/test/compile-fail/hrtb-perfect-forwarding.rs
src/test/compile-fail/hrtb-perfect-forwarding.rs
+66
-0
src/test/compile-fail/hrtb-type-outlives.rs
src/test/compile-fail/hrtb-type-outlives.rs
+59
-0
src/test/compile-fail/issue-14366.rs
src/test/compile-fail/issue-14366.rs
+0
-1
src/test/compile-fail/kindck-inherited-copy-bound.rs
src/test/compile-fail/kindck-inherited-copy-bound.rs
+6
-1
src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs
src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs
+8
-1
src/test/compile-fail/unboxed-closures-wrong-abi.rs
src/test/compile-fail/unboxed-closures-wrong-abi.rs
+9
-1
src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs
...compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs
+8
-1
未找到文件。
src/librustc/lint/builtin.rs
浏览文件 @
f45c0ef5
...
...
@@ -1784,9 +1784,7 @@ fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
method_num
:
index
,
..
})
=>
{
ty
::
trait_item
(
cx
.tcx
,
trait_ref
.def_id
(),
index
)
.def_id
()
ty
::
trait_item
(
cx
.tcx
,
trait_ref
.def_id
,
index
)
.def_id
()
}
}
}
...
...
src/librustc/metadata/csearch.rs
浏览文件 @
f45c0ef5
...
...
@@ -262,7 +262,7 @@ pub fn get_field_type<'tcx>(tcx: &ty::ctxt<'tcx>, class_id: ast::DefId,
// if there is one.
pub
fn
get_impl_trait
<
'tcx
>
(
tcx
:
&
ty
::
ctxt
<
'tcx
>
,
def
:
ast
::
DefId
)
->
Option
<
Rc
<
ty
::
Poly
TraitRef
<
'tcx
>>>
{
->
Option
<
Rc
<
ty
::
TraitRef
<
'tcx
>>>
{
let
cstore
=
&
tcx
.sess.cstore
;
let
cdata
=
cstore
.get_crate_data
(
def
.krate
);
decoder
::
get_impl_trait
(
&*
cdata
,
def
.node
,
tcx
)
...
...
src/librustc/metadata/decoder.rs
浏览文件 @
f45c0ef5
...
...
@@ -425,11 +425,11 @@ pub fn get_repr_attrs(cdata: Cmd, id: ast::NodeId) -> Vec<attr::ReprAttr> {
pub
fn
get_impl_trait
<
'tcx
>
(
cdata
:
Cmd
,
id
:
ast
::
NodeId
,
tcx
:
&
ty
::
ctxt
<
'tcx
>
)
->
Option
<
Rc
<
ty
::
Poly
TraitRef
<
'tcx
>>>
->
Option
<
Rc
<
ty
::
TraitRef
<
'tcx
>>>
{
let
item_doc
=
lookup_item
(
id
,
cdata
.data
());
reader
::
maybe_get_doc
(
item_doc
,
tag_item_trait_ref
)
.map
(|
tp
|
{
Rc
::
new
(
ty
::
Binder
(
doc_trait_ref
(
tp
,
tcx
,
cdata
)
))
Rc
::
new
(
doc_trait_ref
(
tp
,
tcx
,
cdata
))
})
}
...
...
src/librustc/middle/astencode.rs
浏览文件 @
f45c0ef5
...
...
@@ -887,7 +887,7 @@ fn emit_method_origin<'b>(&mut self,
this
.emit_enum_variant
(
"MethodTypeParam"
,
2
,
1
,
|
this
|
{
this
.emit_struct
(
"MethodParam"
,
2
,
|
this
|
{
try!
(
this
.emit_struct_field
(
"trait_ref"
,
0
,
|
this
|
{
Ok
(
this
.emit_trait_ref
(
ecx
,
&
p
.trait_ref
.0
))
Ok
(
this
.emit_trait_ref
(
ecx
,
&
*
p
.trait_ref
))
}));
try!
(
this
.emit_struct_field
(
"method_num"
,
0
,
|
this
|
{
this
.emit_uint
(
p
.method_num
)
...
...
@@ -901,7 +901,7 @@ fn emit_method_origin<'b>(&mut self,
this
.emit_enum_variant
(
"MethodTraitObject"
,
3
,
1
,
|
this
|
{
this
.emit_struct
(
"MethodObject"
,
2
,
|
this
|
{
try!
(
this
.emit_struct_field
(
"trait_ref"
,
0
,
|
this
|
{
Ok
(
this
.emit_trait_ref
(
ecx
,
&
o
.trait_ref
.0
))
Ok
(
this
.emit_trait_ref
(
ecx
,
&
*
o
.trait_ref
))
}));
try!
(
this
.emit_struct_field
(
"object_trait_id"
,
0
,
|
this
|
{
Ok
(
this
.emit_def_id
(
o
.object_trait_id
))
...
...
@@ -1457,7 +1457,7 @@ fn read_method_origin<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
ty
::
MethodParam
{
trait_ref
:
{
this
.read_struct_field
(
"trait_ref"
,
0
,
|
this
|
{
Ok
(
this
.read_
poly_
trait_ref
(
dcx
))
Ok
(
this
.read_trait_ref
(
dcx
))
})
.unwrap
()
},
method_num
:
{
...
...
@@ -1475,7 +1475,7 @@ fn read_method_origin<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
ty
::
MethodObject
{
trait_ref
:
{
this
.read_struct_field
(
"trait_ref"
,
0
,
|
this
|
{
Ok
(
this
.read_
poly_
trait_ref
(
dcx
))
Ok
(
this
.read_trait_ref
(
dcx
))
})
.unwrap
()
},
object_trait_id
:
{
...
...
src/librustc/middle/dead.rs
浏览文件 @
f45c0ef5
...
...
@@ -112,7 +112,7 @@ fn lookup_and_handle_method(&mut self, id: ast::NodeId,
..
})
=>
{
let
trait_item
=
ty
::
trait_item
(
self
.tcx
,
trait_ref
.def_id
()
,
trait_ref
.def_id
,
index
);
match
trait_item
{
ty
::
MethodTraitItem
(
method
)
=>
{
...
...
src/librustc/middle/expr_use_visitor.rs
浏览文件 @
f45c0ef5
...
...
@@ -265,7 +265,7 @@ fn from_method_id(tcx: &ty::ctxt, method_id: ast::DefId)
}
Some
(
ref
trait_ref
)
=>
(
*
trait_ref
)
.clone
(),
};
OverloadedCallType
::
from_trait_id
(
tcx
,
trait_ref
.def_id
()
)
OverloadedCallType
::
from_trait_id
(
tcx
,
trait_ref
.def_id
)
}
fn
from_unboxed_closure
(
tcx
:
&
ty
::
ctxt
,
closure_did
:
ast
::
DefId
)
...
...
@@ -292,7 +292,7 @@ fn from_method_origin(tcx: &ty::ctxt, origin: &MethodOrigin)
}
MethodTypeParam
(
MethodParam
{
ref
trait_ref
,
..
})
|
MethodTraitObject
(
MethodObject
{
ref
trait_ref
,
..
})
=>
{
OverloadedCallType
::
from_trait_id
(
tcx
,
trait_ref
.def_id
()
)
OverloadedCallType
::
from_trait_id
(
tcx
,
trait_ref
.def_id
)
}
}
}
...
...
src/librustc/middle/infer/error_reporting.rs
浏览文件 @
f45c0ef5
...
...
@@ -395,7 +395,8 @@ fn report_and_explain_type_error(&self,
fn
values_str
(
&
self
,
values
:
&
ValuePairs
<
'tcx
>
)
->
Option
<
String
>
{
match
*
values
{
infer
::
Types
(
ref
exp_found
)
=>
self
.expected_found_str
(
exp_found
),
infer
::
TraitRefs
(
ref
exp_found
)
=>
self
.expected_found_str
(
exp_found
)
infer
::
TraitRefs
(
ref
exp_found
)
=>
self
.expected_found_str
(
exp_found
),
infer
::
PolyTraitRefs
(
ref
exp_found
)
=>
self
.expected_found_str
(
exp_found
)
}
}
...
...
@@ -1647,6 +1648,16 @@ fn contains_error(&self) -> bool {
}
}
impl
<
'tcx
>
Resolvable
<
'tcx
>
for
Rc
<
ty
::
TraitRef
<
'tcx
>>
{
fn
resolve
<
'a
>
(
&
self
,
infcx
:
&
InferCtxt
<
'a
,
'tcx
>
)
->
Rc
<
ty
::
TraitRef
<
'tcx
>>
{
Rc
::
new
(
infcx
.resolve_type_vars_if_possible
(
&**
self
))
}
fn
contains_error
(
&
self
)
->
bool
{
ty
::
trait_ref_contains_error
(
&**
self
)
}
}
impl
<
'tcx
>
Resolvable
<
'tcx
>
for
Rc
<
ty
::
PolyTraitRef
<
'tcx
>>
{
fn
resolve
<
'a
>
(
&
self
,
infcx
:
&
InferCtxt
<
'a
,
'tcx
>
)
->
Rc
<
ty
::
PolyTraitRef
<
'tcx
>>
{
...
...
src/librustc/middle/infer/higher_ranked/mod.rs
浏览文件 @
f45c0ef5
...
...
@@ -219,7 +219,7 @@ fn higher_ranked_glb<T>(&self, a: &Binder<T>, b: &Binder<T>) -> cres<'tcx, Binde
self
.infcx
()
.resolve_type_vars_if_possible
(
&
result0
);
debug!
(
"glb result0 = {}"
,
result0
.repr
(
self
.tcx
()));
// Generalize the regions appearing in
fn_ty
0 if possible
// Generalize the regions appearing in
result
0 if possible
let
new_vars
=
self
.infcx
()
.region_vars_confined_to_snapshot
(
snapshot
);
let
span
=
self
.trace
()
.origin
.span
();
let
result1
=
...
...
@@ -358,7 +358,7 @@ fn fold_regions_in<'tcx, T, F>(tcx: &ty::ctxt<'tcx>,
where
T
:
Combineable
<
'tcx
>
,
F
:
FnMut
(
ty
::
Region
,
ty
::
DebruijnIndex
)
->
ty
::
Region
,
{
unbound_value
.fold_with
(
&
mut
ty_fold
::
RegionFolder
::
new
(
tcx
,
|
region
,
current_depth
|
{
unbound_value
.fold_with
(
&
mut
ty_fold
::
RegionFolder
::
new
(
tcx
,
&
mut
|
region
,
current_depth
|
{
// we should only be encountering "escaping" late-bound regions here,
// because the ones at the current level should have been replaced
// with fresh variables
...
...
@@ -414,11 +414,11 @@ fn region_vars_confined_to_snapshot(&self,
*
* The reason is that when we walk through the subtyping
* algorith, we begin by replacing `'a` with a skolemized
* variable `'
0`. We then have `fn(_#0t) <: fn(&'0
int)`. This
* can be made true by unifying `_#0t` with `&'
0
int`. In the
* variable `'
1`. We then have `fn(_#0t) <: fn(&'1
int)`. This
* can be made true by unifying `_#0t` with `&'
1
int`. In the
* process, we create a fresh variable for the skolemized
* region, `'$
0`, and hence we have that `_#0t == &'$0
* int`. However, because `'$
0
` was created during the sub
* region, `'$
2`, and hence we have that `_#0t == &'$2
* int`. However, because `'$
2
` was created during the sub
* computation, if we're not careful we will erroneously
* assume it is one of the transient region variables
* representing a lub/glb internally. Not good.
...
...
@@ -522,3 +522,93 @@ pub fn leak_check<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
}
Ok
(())
}
/// This code converts from skolemized regions back to late-bound
/// regions. It works by replacing each region in the taint set of a
/// skolemized region with a bound-region. The bound region will be bound
/// by the outer-most binder in `value`; the caller must ensure that there is
/// such a binder and it is the right place.
///
/// This routine is only intended to be used when the leak-check has
/// passed; currently, it's used in the trait matching code to create
/// a set of nested obligations frmo an impl that matches against
/// something higher-ranked. More details can be found in
/// `middle::traits::doc.rs`.
///
/// As a brief example, consider the obligation `for<'a> Fn(&'a int)
/// -> &'a int`, and the impl:
///
/// impl<A,R> Fn<A,R> for SomethingOrOther
/// where A : Clone
/// { ... }
///
/// Here we will have replaced `'a` with a skolemized region
/// `'0`. This means that our substitution will be `{A=>&'0
/// int, R=>&'0 int}`.
///
/// When we apply the substitution to the bounds, we will wind up with
/// `&'0 int : Clone` as a predicate. As a last step, we then go and
/// replace `'0` with a late-bound region `'a`. The depth is matched
/// to the depth of the predicate, in this case 1, so that the final
/// predicate is `for<'a> &'a int : Clone`.
pub
fn
plug_leaks
<
'a
,
'tcx
,
T
>
(
infcx
:
&
InferCtxt
<
'a
,
'tcx
>
,
skol_map
:
SkolemizationMap
,
snapshot
:
&
CombinedSnapshot
,
value
:
&
T
)
->
T
where
T
:
TypeFoldable
<
'tcx
>
+
Repr
<
'tcx
>
{
debug_assert!
(
leak_check
(
infcx
,
&
skol_map
,
snapshot
)
.is_ok
());
debug!
(
"plug_leaks(skol_map={}, value={})"
,
skol_map
.repr
(
infcx
.tcx
),
value
.repr
(
infcx
.tcx
));
// Compute a mapping from the "taint set" of each skolemized
// region back to the `ty::BoundRegion` that it originally
// represented. Because `leak_check` passed, we know that that
// these taint sets are mutually disjoint.
let
inv_skol_map
:
FnvHashMap
<
ty
::
Region
,
ty
::
BoundRegion
>
=
skol_map
.into_iter
()
.flat_map
(|(
skol_br
,
skol
)|
{
infcx
.tainted_regions
(
snapshot
,
skol
)
.into_iter
()
.map
(
move
|
tainted_region
|
(
tainted_region
,
skol_br
))
})
.collect
();
debug!
(
"plug_leaks: inv_skol_map={}"
,
inv_skol_map
.repr
(
infcx
.tcx
));
// Remove any instantiated type variables from `value`; those can hide
// references to regions from the `fold_regions` code below.
let
value
=
infcx
.resolve_type_vars_if_possible
(
value
);
// Map any skolemization byproducts back to a late-bound
// region. Put that late-bound region at whatever the outermost
// binder is that we encountered in `value`. The caller is
// responsible for ensuring that (a) `value` contains at least one
// binder and (b) that binder is the one we want to use.
let
result
=
ty_fold
::
fold_regions
(
infcx
.tcx
,
&
value
,
|
r
,
current_depth
|
{
match
inv_skol_map
.get
(
&
r
)
{
None
=>
r
,
Some
(
br
)
=>
{
// It is the responsibility of the caller to ensure
// that each skolemized region appears within a
// binder. In practice, this routine is only used by
// trait checking, and all of the skolemized regions
// appear inside predicates, which always have
// binders, so this assert is satisfied.
assert
!
(
current_depth
>
1
);
ty
::
ReLateBound
(
ty
::
DebruijnIndex
::
new
(
current_depth
-
1
),
br
.clone
())
}
}
});
debug!
(
"plug_leaks: result={}"
,
result
.repr
(
infcx
.tcx
));
result
}
src/librustc/middle/infer/mod.rs
浏览文件 @
f45c0ef5
...
...
@@ -137,7 +137,8 @@ impl Copy for TypeOrigin {}
#[deriving(Clone,
Show)]
pub
enum
ValuePairs
<
'tcx
>
{
Types
(
ty
::
expected_found
<
Ty
<
'tcx
>>
),
TraitRefs
(
ty
::
expected_found
<
Rc
<
ty
::
PolyTraitRef
<
'tcx
>>>
),
TraitRefs
(
ty
::
expected_found
<
Rc
<
ty
::
TraitRef
<
'tcx
>>>
),
PolyTraitRefs
(
ty
::
expected_found
<
Rc
<
ty
::
PolyTraitRef
<
'tcx
>>>
),
}
/// The trace designates the path through inference that we took to
...
...
@@ -349,7 +350,7 @@ pub fn can_mk_subty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
b
:
Ty
<
'tcx
>
)
->
ures
<
'tcx
>
{
debug!
(
"can_mk_subty({} <: {})"
,
a
.repr
(
cx
.tcx
),
b
.repr
(
cx
.tcx
));
cx
.probe
(||
{
cx
.probe
(|
_
|
{
let
trace
=
TypeTrace
{
origin
:
Misc
(
codemap
::
DUMMY_SP
),
values
:
Types
(
expected_found
(
true
,
a
,
b
))
...
...
@@ -362,7 +363,7 @@ pub fn can_mk_eqty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
a
:
Ty
<
'tcx
>
,
b
:
Ty
<
'tcx
>
)
->
ures
<
'tcx
>
{
debug!
(
"can_mk_subty({} <: {})"
,
a
.repr
(
cx
.tcx
),
b
.repr
(
cx
.tcx
));
cx
.probe
(||
{
cx
.probe
(|
_
|
{
let
trace
=
TypeTrace
{
origin
:
Misc
(
codemap
::
DUMMY_SP
),
values
:
Types
(
expected_found
(
true
,
a
,
b
))
...
...
@@ -634,11 +635,11 @@ pub fn try<T, E, F>(&self, f: F) -> Result<T, E> where
/// Execute `f` then unroll any bindings it creates
pub
fn
probe
<
R
,
F
>
(
&
self
,
f
:
F
)
->
R
where
F
:
FnOnce
()
->
R
,
F
:
FnOnce
(
&
CombinedSnapshot
)
->
R
,
{
debug!
(
"probe()"
);
let
snapshot
=
self
.start_snapshot
();
let
r
=
f
();
let
r
=
f
(
&
snapshot
);
self
.rollback_to
(
snapshot
);
r
}
...
...
@@ -683,6 +684,25 @@ pub fn eq_types(&self,
})
}
pub
fn
sub_trait_refs
(
&
self
,
a_is_expected
:
bool
,
origin
:
TypeOrigin
,
a
:
Rc
<
ty
::
TraitRef
<
'tcx
>>
,
b
:
Rc
<
ty
::
TraitRef
<
'tcx
>>
)
->
ures
<
'tcx
>
{
debug!
(
"sub_trait_refs({} <: {})"
,
a
.repr
(
self
.tcx
),
b
.repr
(
self
.tcx
));
self
.commit_if_ok
(||
{
let
trace
=
TypeTrace
{
origin
:
origin
,
values
:
TraitRefs
(
expected_found
(
a_is_expected
,
a
.clone
(),
b
.clone
()))
};
self
.sub
(
a_is_expected
,
trace
)
.trait_refs
(
&*
a
,
&*
b
)
.to_ures
()
})
}
pub
fn
sub_poly_trait_refs
(
&
self
,
a_is_expected
:
bool
,
origin
:
TypeOrigin
,
...
...
@@ -690,14 +710,13 @@ pub fn sub_poly_trait_refs(&self,
b
:
Rc
<
ty
::
PolyTraitRef
<
'tcx
>>
)
->
ures
<
'tcx
>
{
debug!
(
"sub_trait_refs({} <: {})"
,
debug!
(
"sub_
poly_
trait_refs({} <: {})"
,
a
.repr
(
self
.tcx
),
b
.repr
(
self
.tcx
));
self
.commit_if_ok
(||
{
let
trace
=
TypeTrace
{
origin
:
origin
,
values
:
TraitRefs
(
expected_found
(
a_is_expected
,
a
.clone
(),
b
.clone
()))
values
:
PolyTraitRefs
(
expected_found
(
a_is_expected
,
a
.clone
(),
b
.clone
()))
};
self
.sub
(
a_is_expected
,
trace
)
.binders
(
&*
a
,
&*
b
)
.to_ures
()
})
...
...
@@ -727,6 +746,18 @@ pub fn leak_check(&self,
}
}
pub
fn
plug_leaks
<
T
>
(
&
self
,
skol_map
:
SkolemizationMap
,
snapshot
:
&
CombinedSnapshot
,
value
:
&
T
)
->
T
where
T
:
TypeFoldable
<
'tcx
>
+
Repr
<
'tcx
>
{
/*! See `higher_ranked::leak_check` */
higher_ranked
::
plug_leaks
(
self
,
skol_map
,
snapshot
,
value
)
}
pub
fn
equality_predicate
(
&
self
,
span
:
Span
,
predicate
:
&
ty
::
PolyEquatePredicate
<
'tcx
>
)
...
...
src/librustc/middle/privacy.rs
浏览文件 @
f45c0ef5
...
...
@@ -257,8 +257,8 @@ fn visit_item(&mut self, item: &ast::Item) {
};
let
tr
=
ty
::
impl_trait_ref
(
self
.tcx
,
local_def
(
item
.id
));
let
public_trait
=
tr
.clone
()
.map_or
(
false
,
|
tr
|
{
!
is_local
(
tr
.def_id
()
)
||
self
.exported_items
.contains
(
&
tr
.def_id
()
.node
)
!
is_local
(
tr
.def_id
)
||
self
.exported_items
.contains
(
&
tr
.def_id.node
)
});
if
public_ty
||
public_trait
{
...
...
@@ -407,7 +407,7 @@ fn def_privacy(&self, did: ast::DefId) -> PrivacyResult {
match
ty
::
impl_trait_ref
(
self
.tcx
,
id
)
{
Some
(
t
)
=>
{
debug!
(
"privacy - impl of trait {}"
,
id
);
self
.def_privacy
(
t
.def_id
()
)
self
.def_privacy
(
t
.def_id
)
}
None
=>
{
debug!
(
"privacy - found a method {}"
,
...
...
@@ -432,7 +432,7 @@ fn def_privacy(&self, did: ast::DefId) -> PrivacyResult {
match
ty
::
impl_trait_ref
(
self
.tcx
,
id
)
{
Some
(
t
)
=>
{
debug!
(
"privacy - impl of trait {}"
,
id
);
self
.def_privacy
(
t
.def_id
()
)
self
.def_privacy
(
t
.def_id
)
}
None
=>
{
debug!
(
"privacy - found a typedef {}"
,
...
...
@@ -811,7 +811,7 @@ fn check_method(&mut self, span: Span, origin: &MethodOrigin,
// is whether the trait itself is accessible or not.
MethodTypeParam
(
MethodParam
{
ref
trait_ref
,
..
})
|
MethodTraitObject
(
MethodObject
{
ref
trait_ref
,
..
})
=>
{
self
.report_error
(
self
.ensure_public
(
span
,
trait_ref
.def_id
()
,
self
.report_error
(
self
.ensure_public
(
span
,
trait_ref
.def_id
,
None
,
"source trait"
));
}
}
...
...
src/librustc/middle/resolve_lifetime.rs
浏览文件 @
f45c0ef5
...
...
@@ -108,7 +108,8 @@ fn visit_item(&mut self, item: &ast::Item) {
ast
::
ItemTy
(
_
,
ref
generics
)
|
ast
::
ItemEnum
(
_
,
ref
generics
)
|
ast
::
ItemStruct
(
_
,
ref
generics
)
|
ast
::
ItemTrait
(
_
,
ref
generics
,
_
,
_
,
_
)
=>
{
ast
::
ItemTrait
(
_
,
ref
generics
,
_
,
_
,
_
)
|
ast
::
ItemImpl
(
_
,
ref
generics
,
_
,
_
,
_
)
=>
{
// These kinds of items have only early bound lifetime parameters.
let
lifetimes
=
&
generics
.lifetimes
;
let
early_scope
=
EarlyScope
(
subst
::
TypeSpace
,
lifetimes
,
&
ROOT_SCOPE
);
...
...
@@ -117,12 +118,6 @@ fn visit_item(&mut self, item: &ast::Item) {
visit
::
walk_item
(
this
,
item
);
});
}
ast
::
ItemImpl
(
_
,
ref
generics
,
_
,
_
,
_
)
=>
{
// Impls have both early- and late-bound lifetimes.
this
.visit_early_late
(
subst
::
TypeSpace
,
generics
,
|
this
|
{
visit
::
walk_item
(
this
,
item
);
})
}
}
});
}
...
...
src/librustc/middle/traits/coherence.rs
浏览文件 @
f45c0ef5
...
...
@@ -17,7 +17,7 @@
use
middle
::
subst
;
use
middle
::
subst
::
Subst
;
use
middle
::
ty
::{
mod
,
Ty
};
use
middle
::
infer
::
{
mod
,
InferCtxt
}
;
use
middle
::
infer
::
InferCtxt
;
use
std
::
rc
::
Rc
;
use
syntax
::
ast
;
use
syntax
::
codemap
::
DUMMY_SP
;
...
...
@@ -38,12 +38,7 @@ pub fn impl_can_satisfy(infcx: &InferCtxt,
let
impl1_substs
=
util
::
fresh_substs_for_impl
(
infcx
,
DUMMY_SP
,
impl1_def_id
);
let
impl1_trait_ref
=
ty
::
impl_trait_ref
(
infcx
.tcx
,
impl1_def_id
)
.unwrap
()
.subst
(
infcx
.tcx
,
&
impl1_substs
);
let
impl1_trait_ref
=
infcx
.replace_late_bound_regions_with_fresh_var
(
DUMMY_SP
,
infer
::
FnCall
,
&*
impl1_trait_ref
)
.0
;
(
*
ty
::
impl_trait_ref
(
infcx
.tcx
,
impl1_def_id
)
.unwrap
())
.subst
(
infcx
.tcx
,
&
impl1_substs
);
// Determine whether `impl2` can provide an implementation for those
// same types.
...
...
@@ -67,15 +62,15 @@ pub fn impl_is_local(tcx: &ty::ctxt,
debug!
(
"trait_ref={}"
,
trait_ref
.repr
(
tcx
));
// If the trait is local to the crate, ok.
if
trait_ref
.def_id
()
.krate
==
ast
::
LOCAL_CRATE
{
if
trait_ref
.def_id.krate
==
ast
::
LOCAL_CRATE
{
debug!
(
"trait {} is local to current crate"
,
trait_ref
.def_id
()
.repr
(
tcx
));
trait_ref
.def_id
.repr
(
tcx
));
return
true
;
}
// Otherwise, at least one of the input types must be local to the
// crate.
trait_ref
.
0
.
input_types
()
.iter
()
.any
(|
&
t
|
ty_is_local
(
tcx
,
t
))
trait_ref
.input_types
()
.iter
()
.any
(|
&
t
|
ty_is_local
(
tcx
,
t
))
}
pub
fn
ty_is_local
<
'tcx
>
(
tcx
:
&
ty
::
ctxt
<
'tcx
>
,
ty
:
Ty
<
'tcx
>
)
->
bool
{
...
...
src/librustc/middle/traits/fulfill.rs
浏览文件 @
f45c0ef5
...
...
@@ -360,10 +360,7 @@ fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
// For now, we just check that there are no higher-ranked
// regions. If there are, we will call this obligation an
// error. Eventually we should be able to support some
// cases here, I imagine (e.g., `for<'a> &'a int : 'a`).
//
// TODO This is overly conservative, but good enough for
// now.
// cases here, I imagine (e.g., `for<'a> int : 'a`).
if
ty
::
count_late_bound_regions
(
selcx
.tcx
(),
binder
)
!=
0
{
errors
.push
(
FulfillmentError
::
new
(
...
...
src/librustc/middle/traits/select.rs
浏览文件 @
f45c0ef5
...
...
@@ -289,7 +289,7 @@ fn evaluate_predicate_recursively<'o>(&mut self,
}
ty
::
Predicate
::
Equate
(
ref
p
)
=>
{
let
result
=
self
.infcx
.probe
(||
{
let
result
=
self
.infcx
.probe
(|
_
|
{
self
.infcx
.equality_predicate
(
obligation
.cause.span
,
p
)
});
match
result
{
...
...
@@ -410,13 +410,18 @@ pub fn evaluate_impl(&mut self,
impl_def_id
.repr
(
self
.tcx
()),
obligation
.repr
(
self
.tcx
()));
self
.infcx
.probe
(||
{
match
self
.match_impl
(
impl_def_id
,
obligation
)
{
self
.infcx
.probe
(|
snapshot
|
{
let
(
skol_obligation_trait_ref
,
skol_map
)
=
self
.infcx
()
.skolemize_late_bound_regions
(
&*
obligation
.trait_ref
,
snapshot
);
match
self
.match_impl
(
impl_def_id
,
obligation
,
snapshot
,
&
skol_map
,
Rc
::
new
(
skol_obligation_trait_ref
))
{
Ok
(
substs
)
=>
{
let
vtable_impl
=
self
.vtable_impl
(
impl_def_id
,
substs
,
obligation
.cause
,
obligation
.recursion_depth
+
1
);
obligation
.recursion_depth
+
1
,
skol_map
,
snapshot
);
self
.winnow_selection
(
None
,
VtableImpl
(
vtable_impl
))
.may_apply
()
}
Err
(())
=>
{
...
...
@@ -711,8 +716,7 @@ fn assemble_candidates_from_caller_bounds(&mut self,
let
matching_bounds
=
all_bounds
.filter
(
|
bound
|
self
.infcx
.probe
(
||
self
.match_trait_refs
(
obligation
,
(
*
bound
)
.clone
()))
.is_ok
());
|
_
|
self
.match_where_clause
(
obligation
,
bound
.clone
()))
.is_ok
());
let
param_candidates
=
matching_bounds
.map
(
...
...
@@ -819,8 +823,11 @@ fn assemble_candidates_from_impls(&mut self,
{
let
all_impls
=
self
.all_impls
(
obligation
.trait_ref
.def_id
());
for
&
impl_def_id
in
all_impls
.iter
()
{
self
.infcx
.probe
(||
{
match
self
.match_impl
(
impl_def_id
,
obligation
)
{
self
.infcx
.probe
(|
snapshot
|
{
let
(
skol_obligation_trait_ref
,
skol_map
)
=
self
.infcx
()
.skolemize_late_bound_regions
(
&*
obligation
.trait_ref
,
snapshot
);
match
self
.match_impl
(
impl_def_id
,
obligation
,
snapshot
,
&
skol_map
,
Rc
::
new
(
skol_obligation_trait_ref
))
{
Ok
(
_
)
=>
{
candidates
.vec
.push
(
ImplCandidate
(
impl_def_id
));
}
...
...
@@ -848,15 +855,8 @@ fn winnow_candidate<'o>(&mut self,
candidate
:
&
Candidate
<
'tcx
>
)
->
EvaluationResult
<
'tcx
>
{
/*!
* Further evaluate `candidate` to decide whether all type parameters match
* and whether nested obligations are met. Returns true if `candidate` remains
* viable after this further scrutiny.
*/
debug!
(
"winnow_candidate: depth={} candidate={}"
,
stack
.obligation.recursion_depth
,
candidate
.repr
(
self
.tcx
()));
let
result
=
self
.infcx
.probe
(||
{
debug!
(
"winnow_candidate: candidate={}"
,
candidate
.repr
(
self
.tcx
()));
let
result
=
self
.infcx
.probe
(|
_
|
{
let
candidate
=
(
*
candidate
)
.clone
();
match
self
.confirm_candidate
(
stack
.obligation
,
candidate
)
{
Ok
(
selection
)
=>
self
.winnow_selection
(
Some
(
stack
),
selection
),
...
...
@@ -919,17 +919,23 @@ fn candidate_should_be_dropped_in_favor_of<'o>(&mut self,
candidate_i
.repr
(
self
.tcx
()),
candidate_j
.repr
(
self
.tcx
()));
self
.infcx
.probe
(||
{
self
.infcx
.probe
(|
snapshot
|
{
let
(
skol_obligation_trait_ref
,
skol_map
)
=
self
.infcx
()
.skolemize_late_bound_regions
(
&*
stack
.obligation.trait_ref
,
snapshot
);
let
impl_substs
=
self
.rematch_impl
(
impl_def_id
,
stack
.obligation
);
self
.rematch_impl
(
impl_def_id
,
stack
.obligation
,
snapshot
,
&
skol_map
,
Rc
::
new
(
skol_obligation_trait_ref
));
let
impl_trait_ref
=
ty
::
impl_trait_ref
(
self
.tcx
(),
impl_def_id
)
.unwrap
();
let
impl_trait_ref
=
impl_trait_ref
.subst
(
self
.tcx
(),
&
impl_substs
);
let
poly_impl_trait_ref
=
Rc
::
new
(
ty
::
Binder
((
*
impl_trait_ref
)
.clone
()));
let
origin
=
infer
::
RelateOutputImplTypes
(
stack
.obligation.cause.span
);
self
.infcx
.sub_poly_trait_refs
(
false
,
origin
,
impl_trait_ref
,
vt
.bound
.clone
())
.sub_poly_trait_refs
(
false
,
origin
,
poly_
impl_trait_ref
,
vt
.bound
.clone
())
.is_ok
()
})
}
...
...
@@ -1400,10 +1406,21 @@ fn confirm_param_candidate(&mut self,
obligation
.repr
(
self
.tcx
()),
param
.repr
(
self
.tcx
()));
let
()
=
try!
(
self
.confirm
(
obligation
.cause
,
// During evaluation, we already checked that this
// where-clause trait-ref could be unified with the obligation
// trait-ref. Repeat that unification now without any
// transactional boundary; it should not fail.
match
self
.confirm_poly_trait_refs
(
obligation
.cause
,
obligation
.trait_ref
.clone
(),
param
.bound
.clone
()));
Ok
(
param
)
param
.bound
.clone
())
{
Ok
(())
=>
Ok
(
param
),
Err
(
_
)
=>
{
self
.tcx
()
.sess
.bug
(
format!
(
"Where clause `{}` was applicable to `{}` but now is not"
,
param
.bound
.repr
(
self
.tcx
()),
obligation
.repr
(
self
.tcx
()))
.as_slice
());
}
}
}
fn
confirm_builtin_candidate
(
&
mut
self
,
...
...
@@ -1476,23 +1493,44 @@ fn confirm_impl_candidate(&mut self,
// First, create the substitutions by matching the impl again,
// this time not in a probe.
let
substs
=
self
.rematch_impl
(
impl_def_id
,
obligation
);
self
.infcx
.try
(|
snapshot
|
{
let
(
skol_obligation_trait_ref
,
skol_map
)
=
self
.infcx
()
.skolemize_late_bound_regions
(
&*
obligation
.trait_ref
,
snapshot
);
let
substs
=
self
.rematch_impl
(
impl_def_id
,
obligation
,
snapshot
,
&
skol_map
,
Rc
::
new
(
skol_obligation_trait_ref
));
debug!
(
"confirm_impl_candidate substs={}"
,
substs
);
Ok
(
self
.vtable_impl
(
impl_def_id
,
substs
,
obligation
.cause
,
obligation
.recursion_depth
+
1
))
Ok
(
self
.vtable_impl
(
impl_def_id
,
substs
,
obligation
.cause
,
obligation
.recursion_depth
+
1
,
skol_map
,
snapshot
))
})
}
fn
vtable_impl
(
&
mut
self
,
impl_def_id
:
ast
::
DefId
,
substs
:
Substs
<
'tcx
>
,
cause
:
ObligationCause
<
'tcx
>
,
recursion_depth
:
uint
)
recursion_depth
:
uint
,
skol_map
:
infer
::
SkolemizationMap
,
snapshot
:
&
infer
::
CombinedSnapshot
)
->
VtableImplData
<
'tcx
,
PredicateObligation
<
'tcx
>>
{
debug!
(
"vtable_impl(impl_def_id={}, substs={}, recursion_depth={}, skol_map={})"
,
impl_def_id
.repr
(
self
.tcx
()),
substs
.repr
(
self
.tcx
()),
recursion_depth
,
skol_map
.repr
(
self
.tcx
()));
let
impl_predicates
=
self
.impl_predicates
(
cause
,
recursion_depth
,
impl_def_id
,
&
substs
);
&
substs
,
skol_map
,
snapshot
);
debug!
(
"vtable_impl: impl_def_id={} impl_predicates={}"
,
impl_def_id
.repr
(
self
.tcx
()),
impl_predicates
.repr
(
self
.tcx
()));
VtableImplData
{
impl_def_id
:
impl_def_id
,
substs
:
substs
,
nested
:
impl_predicates
}
...
...
@@ -1535,8 +1573,7 @@ fn confirm_fn_pointer_candidate(&mut self,
substs
:
substs
,
}));
let
()
=
try!
(
self
.confirm
(
obligation
.cause
,
try!
(
self
.confirm_poly_trait_refs
(
obligation
.cause
,
obligation
.trait_ref
.clone
(),
trait_ref
));
...
...
@@ -1582,11 +1619,54 @@ fn confirm_unboxed_closure_candidate(&mut self,
closure_def_id
.repr
(
self
.tcx
()),
trait_ref
.repr
(
self
.tcx
()));
self
.confirm
(
obligation
.cause
,
self
.confirm
_poly_trait_refs
(
obligation
.cause
,
obligation
.trait_ref
.clone
(),
trait_ref
)
}
/// In the case of unboxed closure types and fn pointers,
/// we currently treat the input type parameters on the trait as
/// outputs. This means that when we have a match we have only
/// considered the self type, so we have to go back and make sure
/// to relate the argument types too. This is kind of wrong, but
/// since we control the full set of impls, also not that wrong,
/// and it DOES yield better error messages (since we don't report
/// errors as if there is no applicable impl, but rather report
/// errors are about mismatched argument types.
///
/// Here is an example. Imagine we have an unboxed closure expression
/// and we desugared it so that the type of the expression is
/// `Closure`, and `Closure` expects an int as argument. Then it
/// is "as if" the compiler generated this impl:
///
/// impl Fn(int) for Closure { ... }
///
/// Now imagine our obligation is `Fn(uint) for Closure`. So far
/// we have matched the self-type `Closure`. At this point we'll
/// compare the `int` to `uint` and generate an error.
///
/// Note that this checking occurs *after* the impl has selected,
/// because these output type parameters should not affect the
/// selection of the impl. Therefore, if there is a mismatch, we
/// report an error to the user.
fn
confirm_poly_trait_refs
(
&
mut
self
,
obligation_cause
:
ObligationCause
,
obligation_trait_ref
:
Rc
<
ty
::
PolyTraitRef
<
'tcx
>>
,
expected_trait_ref
:
Rc
<
ty
::
PolyTraitRef
<
'tcx
>>
)
->
Result
<
(),
SelectionError
<
'tcx
>>
{
let
origin
=
infer
::
RelateOutputImplTypes
(
obligation_cause
.span
);
let
obligation_trait_ref
=
obligation_trait_ref
.clone
();
match
self
.infcx
.sub_poly_trait_refs
(
false
,
origin
,
expected_trait_ref
.clone
(),
obligation_trait_ref
.clone
())
{
Ok
(())
=>
Ok
(()),
Err
(
e
)
=>
Err
(
OutputTypeParameterMismatch
(
expected_trait_ref
,
obligation_trait_ref
,
e
))
}
}
///////////////////////////////////////////////////////////////////////////
// Matching
//
...
...
@@ -1599,10 +1679,14 @@ fn confirm_unboxed_closure_candidate(&mut self,
fn
rematch_impl
(
&
mut
self
,
impl_def_id
:
ast
::
DefId
,
obligation
:
&
TraitObligation
<
'tcx
>
)
obligation
:
&
TraitObligation
<
'tcx
>
,
snapshot
:
&
infer
::
CombinedSnapshot
,
skol_map
:
&
infer
::
SkolemizationMap
,
skol_obligation_trait_ref
:
Rc
<
ty
::
TraitRef
<
'tcx
>>
)
->
Substs
<
'tcx
>
{
match
self
.match_impl
(
impl_def_id
,
obligation
)
{
match
self
.match_impl
(
impl_def_id
,
obligation
,
snapshot
,
skol_map
,
skol_obligation_trait_ref
)
{
Ok
(
substs
)
=>
{
substs
}
...
...
@@ -1618,11 +1702,13 @@ fn rematch_impl(&mut self,
fn
match_impl
(
&
mut
self
,
impl_def_id
:
ast
::
DefId
,
obligation
:
&
TraitObligation
<
'tcx
>
)
obligation
:
&
TraitObligation
<
'tcx
>
,
snapshot
:
&
infer
::
CombinedSnapshot
,
skol_map
:
&
infer
::
SkolemizationMap
,
skol_obligation_trait_ref
:
Rc
<
ty
::
TraitRef
<
'tcx
>>
)
->
Result
<
Substs
<
'tcx
>
,
()
>
{
let
impl_trait_ref
=
ty
::
impl_trait_ref
(
self
.tcx
(),
impl_def_id
)
.unwrap
();
let
impl_trait_ref
=
ty
::
impl_trait_ref
(
self
.tcx
(),
impl_def_id
)
.unwrap
();
// Before we create the substitutions and everything, first
// consider a "quick reject". This avoids creating more types
...
...
@@ -1638,15 +1724,42 @@ fn match_impl(&mut self,
let
impl_trait_ref
=
impl_trait_ref
.subst
(
self
.tcx
(),
&
impl_substs
);
match
self
.match_trait_refs
(
obligation
,
impl_trait_ref
)
{
Ok
(())
=>
Ok
(
impl_substs
),
Err
(())
=>
Err
(())
debug!
(
"match_impl(impl_def_id={}, obligation={},
\
impl_trait_ref={}, skol_obligation_trait_ref={})"
,
impl_def_id
.repr
(
self
.tcx
()),
obligation
.repr
(
self
.tcx
()),
impl_trait_ref
.repr
(
self
.tcx
()),
skol_obligation_trait_ref
.repr
(
self
.tcx
()));
let
origin
=
infer
::
RelateOutputImplTypes
(
obligation
.cause.span
);
match
self
.infcx
.sub_trait_refs
(
false
,
origin
,
impl_trait_ref
,
skol_obligation_trait_ref
)
{
Ok
(())
=>
{
}
Err
(
e
)
=>
{
debug!
(
"match_impl: failed sub_trait_refs due to `{}`"
,
ty
::
type_err_to_str
(
self
.tcx
(),
&
e
));
return
Err
(());
}
}
match
self
.infcx
.leak_check
(
skol_map
,
snapshot
)
{
Ok
(())
=>
{
}
Err
(
e
)
=>
{
debug!
(
"match_impl: failed leak check due to `{}`"
,
ty
::
type_err_to_str
(
self
.tcx
(),
&
e
));
return
Err
(());
}
}
debug!
(
"match_impl: success impl_substs={}"
,
impl_substs
.repr
(
self
.tcx
()));
Ok
(
impl_substs
)
}
fn
fast_reject_trait_refs
(
&
mut
self
,
obligation
:
&
TraitObligation
,
impl_trait_ref
:
&
ty
::
Poly
TraitRef
)
impl_trait_ref
:
&
ty
::
TraitRef
)
->
bool
{
// We can avoid creating type variables and doing the full
...
...
@@ -1667,19 +1780,19 @@ fn fast_reject_trait_refs(&mut self,
})
}
fn
match_
trait_refs
(
&
mut
self
,
fn
match_
where_clause
(
&
mut
self
,
obligation
:
&
TraitObligation
<
'tcx
>
,
trait_ref
:
Rc
<
ty
::
PolyTraitRef
<
'tcx
>>
)
where_clause_
trait_ref
:
Rc
<
ty
::
PolyTraitRef
<
'tcx
>>
)
->
Result
<
(),()
>
{
debug!
(
"match_
trait_refs: obligation={}
trait_ref={}"
,
debug!
(
"match_
where_clause: obligation={} where_clause_
trait_ref={}"
,
obligation
.repr
(
self
.tcx
()),
trait_ref
.repr
(
self
.tcx
()));
where_clause_
trait_ref
.repr
(
self
.tcx
()));
let
origin
=
infer
::
RelateOutputImplTypes
(
obligation
.cause.span
);
match
self
.infcx
.sub_poly_trait_refs
(
false
,
origin
,
trait_ref
,
where_clause_
trait_ref
,
obligation
.trait_ref
.clone
())
{
Ok
(())
=>
Ok
(()),
Err
(
_
)
=>
Err
(()),
...
...
@@ -1754,78 +1867,6 @@ fn match_self_types(&mut self,
}
}
///////////////////////////////////////////////////////////////////////////
// Confirmation
//
// The final step of selection: once we know how an obligation is
// is resolved, we confirm that selection in order to have
// side-effects on the typing environment. This step also unifies
// the output type parameters from the obligation with those found
// on the impl/bound, which may yield type errors.
/// Relates the output type parameters from an impl to the
/// trait. This may lead to type errors. The confirmation step
/// is separated from the main match procedure because these
/// type errors do not cause us to select another impl.
///
/// As an example, consider matching the obligation
/// `Iterator<char> for Elems<int>` using the following impl:
///
/// impl<T> Iterator<T> for Elems<T> { ... }
///
/// The match phase will succeed with substitution `T=int`.
/// The confirm step will then try to unify `int` and `char`
/// and yield an error.
fn
confirm_impl_vtable
(
&
mut
self
,
impl_def_id
:
ast
::
DefId
,
obligation_cause
:
ObligationCause
<
'tcx
>
,
obligation_trait_ref
:
Rc
<
ty
::
PolyTraitRef
<
'tcx
>>
,
substs
:
&
Substs
<
'tcx
>
)
->
Result
<
(),
SelectionError
<
'tcx
>>
{
let
impl_trait_ref
=
ty
::
impl_trait_ref
(
self
.tcx
(),
impl_def_id
)
.unwrap
();
let
impl_trait_ref
=
impl_trait_ref
.subst
(
self
.tcx
(),
substs
);
self
.confirm
(
obligation_cause
,
obligation_trait_ref
,
impl_trait_ref
)
}
/// After we have determined which impl applies, and with what substitutions, there is one last
/// step. We have to go back and relate the "output" type parameters from the obligation to the
/// types that are specified in the impl.
///
/// For example, imagine we have:
///
/// impl<T> Iterator<T> for Vec<T> { ... }
///
/// and our obligation is `Iterator<Foo> for Vec<int>` (note the mismatch in the obligation
/// types). Up until this step, no error would be reported: the self type is `Vec<int>`, and
/// that matches `Vec<T>` with the substitution `T=int`. At this stage, we could then go and
/// check that the type parameters to the `Iterator` trait match. (In terms of the parameters,
/// the `expected_trait_ref` here would be `Iterator<int> for Vec<int>`, and the
/// `obligation_trait_ref` would be `Iterator<Foo> for Vec<int>`.
///
/// Note that this checking occurs *after* the impl has selected, because these output type
/// parameters should not affect the selection of the impl. Therefore, if there is a mismatch,
/// we report an error to the user.
fn
confirm
(
&
mut
self
,
obligation_cause
:
ObligationCause
,
obligation_trait_ref
:
Rc
<
ty
::
PolyTraitRef
<
'tcx
>>
,
expected_trait_ref
:
Rc
<
ty
::
PolyTraitRef
<
'tcx
>>
)
->
Result
<
(),
SelectionError
<
'tcx
>>
{
let
origin
=
infer
::
RelateOutputImplTypes
(
obligation_cause
.span
);
let
obligation_trait_ref
=
obligation_trait_ref
.clone
();
match
self
.infcx
.sub_poly_trait_refs
(
false
,
origin
,
expected_trait_ref
.clone
(),
obligation_trait_ref
.clone
())
{
Ok
(())
=>
Ok
(()),
Err
(
e
)
=>
Err
(
OutputTypeParameterMismatch
(
expected_trait_ref
,
obligation_trait_ref
,
e
))
}
}
///////////////////////////////////////////////////////////////////////////
// Miscellany
...
...
@@ -1857,11 +1898,14 @@ fn impl_predicates(&self,
cause
:
ObligationCause
<
'tcx
>
,
recursion_depth
:
uint
,
impl_def_id
:
ast
::
DefId
,
impl_substs
:
&
Substs
<
'tcx
>
)
impl_substs
:
&
Substs
<
'tcx
>
,
skol_map
:
infer
::
SkolemizationMap
,
snapshot
:
&
infer
::
CombinedSnapshot
)
->
VecPerParamSpace
<
PredicateObligation
<
'tcx
>>
{
let
impl_generics
=
ty
::
lookup_item_type
(
self
.tcx
(),
impl_def_id
)
.generics
;
let
bounds
=
impl_generics
.to_bounds
(
self
.tcx
(),
impl_substs
);
let
bounds
=
self
.infcx
()
.plug_leaks
(
skol_map
,
snapshot
,
&
bounds
);
util
::
predicates_for_generics
(
self
.tcx
(),
cause
,
recursion_depth
,
&
bounds
)
}
...
...
src/librustc/middle/ty.rs
浏览文件 @
f45c0ef5
...
...
@@ -478,8 +478,10 @@ pub enum MethodOrigin<'tcx> {
#[deriving(Clone,
Show)]
pub
struct
MethodParam
<
'tcx
>
{
// the precise trait reference that occurs as a bound -- this may
// be a supertrait of what the user actually typed.
pub
trait_ref
:
Rc
<
ty
::
PolyTraitRef
<
'tcx
>>
,
// be a supertrait of what the user actually typed. Note that it
// never contains bound regions; those regions should have been
// instantiated with fresh variables at this point.
pub
trait_ref
:
Rc
<
ty
::
TraitRef
<
'tcx
>>
,
// index of uint in the list of methods for the trait
pub
method_num
:
uint
,
...
...
@@ -489,7 +491,7 @@ pub struct MethodParam<'tcx> {
#[deriving(Clone,
Show)]
pub
struct
MethodObject
<
'tcx
>
{
// the (super)trait containing the method to be invoked
pub
trait_ref
:
Rc
<
ty
::
Poly
TraitRef
<
'tcx
>>
,
pub
trait_ref
:
Rc
<
ty
::
TraitRef
<
'tcx
>>
,
// the actual base trait id of the object
pub
object_trait_id
:
ast
::
DefId
,
...
...
@@ -665,7 +667,7 @@ pub struct ctxt<'tcx> {
/// A cache for the trait_items() routine
pub
trait_items_cache
:
RefCell
<
DefIdMap
<
Rc
<
Vec
<
ImplOrTraitItem
<
'tcx
>>>>>
,
pub
impl_trait_cache
:
RefCell
<
DefIdMap
<
Option
<
Rc
<
ty
::
Poly
TraitRef
<
'tcx
>>>>>
,
pub
impl_trait_cache
:
RefCell
<
DefIdMap
<
Option
<
Rc
<
ty
::
TraitRef
<
'tcx
>>>>>
,
pub
trait_refs
:
RefCell
<
NodeMap
<
Rc
<
TraitRef
<
'tcx
>>>>
,
pub
trait_defs
:
RefCell
<
DefIdMap
<
Rc
<
TraitDef
<
'tcx
>>>>
,
...
...
@@ -1306,7 +1308,7 @@ pub enum sty<'tcx> {
#[deriving(Clone,
PartialEq,
Eq,
Hash,
Show)]
pub
struct
TyTrait
<
'tcx
>
{
// Principal trait reference.
pub
principal
:
PolyTraitRef
<
'tcx
>
,
// would use Rc<TraitRef>, but it runs afoul of some static rules
pub
principal
:
PolyTraitRef
<
'tcx
>
,
pub
bounds
:
ExistentialBounds
}
...
...
@@ -1315,7 +1317,9 @@ impl<'tcx> TyTrait<'tcx> {
/// we convert the principal trait-ref into a normal trait-ref,
/// you must give *some* self-type. A common choice is `mk_err()`
/// or some skolemized type.
pub
fn
principal_trait_ref_with_self_ty
(
&
self
,
self_ty
:
Ty
<
'tcx
>
)
->
Rc
<
ty
::
PolyTraitRef
<
'tcx
>>
{
pub
fn
principal_trait_ref_with_self_ty
(
&
self
,
self_ty
:
Ty
<
'tcx
>
)
->
Rc
<
ty
::
PolyTraitRef
<
'tcx
>>
{
Rc
::
new
(
ty
::
Binder
(
ty
::
TraitRef
{
def_id
:
self
.principal
.def_id
(),
substs
:
self
.principal
.substs
()
.with_self_ty
(
self_ty
),
...
...
@@ -4818,7 +4822,7 @@ pub fn trait_item_def_ids(cx: &ctxt, id: ast::DefId)
}
pub
fn
impl_trait_ref
<
'tcx
>
(
cx
:
&
ctxt
<
'tcx
>
,
id
:
ast
::
DefId
)
->
Option
<
Rc
<
Poly
TraitRef
<
'tcx
>>>
{
->
Option
<
Rc
<
TraitRef
<
'tcx
>>>
{
memoized
(
&
cx
.impl_trait_cache
,
id
,
|
id
:
ast
::
DefId
|
{
if
id
.krate
==
ast
::
LOCAL_CRATE
{
debug!
(
"(impl_trait_ref) searching for trait impl {}"
,
id
);
...
...
@@ -4828,9 +4832,8 @@ pub fn impl_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
ast
::
ItemImpl
(
_
,
_
,
ref
opt_trait
,
_
,
_
)
=>
{
match
opt_trait
{
&
Some
(
ref
t
)
=>
{
let
trait_ref
=
(
*
ty
::
node_id_to_trait_ref
(
cx
,
t
.ref_id
))
.clone
();
Some
(
Rc
::
new
(
ty
::
Binder
(
trait_ref
)))
let
trait_ref
=
ty
::
node_id_to_trait_ref
(
cx
,
t
.ref_id
);
Some
(
trait_ref
)
}
&
None
=>
None
}
...
...
@@ -5736,7 +5739,7 @@ pub fn populate_implementations_for_type_if_necessary(tcx: &ctxt,
// Record the trait->implementation mappings, if applicable.
let
associated_traits
=
csearch
::
get_impl_trait
(
tcx
,
impl_def_id
);
for
trait_ref
in
associated_traits
.iter
()
{
record_trait_implementation
(
tcx
,
trait_ref
.def_id
()
,
impl_def_id
);
record_trait_implementation
(
tcx
,
trait_ref
.def_id
,
impl_def_id
);
}
// For any methods that use a default implementation, add them to
...
...
@@ -6432,8 +6435,10 @@ pub fn replace_late_bound_regions<'tcx, T, F>(
debug!
(
"replace_late_bound_regions({})"
,
binder
.repr
(
tcx
));
let
mut
map
=
FnvHashMap
::
new
();
let
value
=
{
let
mut
f
=
ty_fold
::
RegionFolder
::
new
(
tcx
,
|
region
,
current_depth
|
{
// Note: fold the field `0`, not the binder, so that late-bound
// regions bound by `binder` are considered free.
let
value
=
ty_fold
::
fold_regions
(
tcx
,
&
binder
.0
,
|
region
,
current_depth
|
{
debug!
(
"region={}"
,
region
.repr
(
tcx
));
match
region
{
ty
::
ReLateBound
(
debruijn
,
br
)
if
debruijn
.depth
==
current_depth
=>
{
...
...
@@ -6448,10 +6453,6 @@ pub fn replace_late_bound_regions<'tcx, T, F>(
}
});
// Note: fold the field `0`, not the binder, so that late-bound
// regions bound by `binder` are considered free.
binder
.0
.fold_with
(
&
mut
f
)
};
debug!
(
"resulting map: {} value: {}"
,
map
,
value
.repr
(
tcx
));
(
value
,
map
)
}
...
...
src/librustc/middle/ty_fold.rs
浏览文件 @
f45c0ef5
...
...
@@ -730,14 +730,17 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
/// regions (aka "lifetimes") that are bound within a type are not
/// visited by this folder; only regions that occur free will be
/// visited by `fld_r`.
pub
struct
RegionFolder
<
'a
,
'tcx
:
'a
,
F
>
where
F
:
FnMut
(
ty
::
Region
,
uint
)
->
ty
::
Region
{
pub
struct
RegionFolder
<
'a
,
'tcx
:
'a
>
{
tcx
:
&
'a
ty
::
ctxt
<
'tcx
>
,
current_depth
:
uint
,
fld_r
:
F
,
fld_r
:
&
'a
mut
(
FnMut
(
ty
::
Region
,
uint
)
->
ty
::
Region
+
'a
)
,
}
impl
<
'a
,
'tcx
,
F
>
RegionFolder
<
'a
,
'tcx
,
F
>
where
F
:
FnMut
(
ty
::
Region
,
uint
)
->
ty
::
Region
{
pub
fn
new
(
tcx
:
&
'a
ty
::
ctxt
<
'tcx
>
,
fld_r
:
F
)
->
RegionFolder
<
'a
,
'tcx
,
F
>
{
impl
<
'a
,
'tcx
>
RegionFolder
<
'a
,
'tcx
>
{
pub
fn
new
<
F
>
(
tcx
:
&
'a
ty
::
ctxt
<
'tcx
>
,
fld_r
:
&
'a
mut
F
)
->
RegionFolder
<
'a
,
'tcx
>
where
F
:
FnMut
(
ty
::
Region
,
uint
)
->
ty
::
Region
{
RegionFolder
{
tcx
:
tcx
,
current_depth
:
1
,
...
...
@@ -750,15 +753,21 @@ pub fn collect_regions<'tcx,T>(tcx: &ty::ctxt<'tcx>, value: &T) -> Vec<ty::Regio
where
T
:
TypeFoldable
<
'tcx
>
{
let
mut
vec
=
Vec
::
new
();
{
let
mut
folder
=
RegionFolder
::
new
(
tcx
,
|
r
,
_
|
{
vec
.push
(
r
);
r
});
value
.fold_with
(
&
mut
folder
);
}
fold_regions
(
tcx
,
value
,
|
r
,
_
|
{
vec
.push
(
r
);
r
});
vec
}
impl
<
'a
,
'tcx
,
F
>
TypeFolder
<
'tcx
>
for
RegionFolder
<
'a
,
'tcx
,
F
>
where
F
:
FnMut
(
ty
::
Region
,
uint
)
->
ty
::
Region
,
pub
fn
fold_regions
<
'tcx
,
T
,
F
>
(
tcx
:
&
ty
::
ctxt
<
'tcx
>
,
value
:
&
T
,
mut
f
:
F
)
->
T
where
F
:
FnMut
(
ty
::
Region
,
uint
)
->
ty
::
Region
,
T
:
TypeFoldable
<
'tcx
>
,
{
value
.fold_with
(
&
mut
RegionFolder
::
new
(
tcx
,
&
mut
f
))
}
impl
<
'a
,
'tcx
>
TypeFolder
<
'tcx
>
for
RegionFolder
<
'a
,
'tcx
>
{
fn
tcx
<
'a
>
(
&
'a
self
)
->
&
'a
ty
::
ctxt
<
'tcx
>
{
self
.tcx
}
...
...
@@ -780,7 +789,7 @@ fn fold_region(&mut self, r: ty::Region) -> ty::Region {
_
=>
{
debug!
(
"RegionFolder.fold_region({}) folding free region (current_depth={})"
,
r
.repr
(
self
.tcx
()),
self
.current_depth
);
(
self
.fld_r
)(
r
,
self
.current_depth
)
self
.fld_r
.call_mut
((
r
,
self
.current_depth
)
)
}
}
}
...
...
@@ -836,7 +845,7 @@ pub fn shift_regions<'tcx, T:TypeFoldable<'tcx>+Repr<'tcx>>(tcx: &ty::ctxt<'tcx>
debug!
(
"shift_regions(value={}, amount={})"
,
value
.repr
(
tcx
),
amount
);
value
.fold_with
(
&
mut
RegionFolder
::
new
(
tcx
,
|
region
,
_
current_depth
|
{
value
.fold_with
(
&
mut
RegionFolder
::
new
(
tcx
,
&
mut
|
region
,
_
current_depth
|
{
shift_region
(
region
,
amount
)
}))
}
...
...
src/librustc_trans/save/mod.rs
浏览文件 @
f45c0ef5
...
...
@@ -941,14 +941,14 @@ fn process_method_call(&mut self,
ty
::
MethodTypeParam
(
ref
mp
)
=>
{
// method invoked on a type parameter
let
trait_item
=
ty
::
trait_item
(
&
self
.analysis.ty_cx
,
mp
.trait_ref
.def_id
()
,
mp
.trait_ref.def_id
,
mp
.method_num
);
(
None
,
Some
(
trait_item
.def_id
()))
}
ty
::
MethodTraitObject
(
ref
mo
)
=>
{
// method invoked on a trait instance
let
trait_item
=
ty
::
trait_item
(
&
self
.analysis.ty_cx
,
mo
.trait_ref
.def_id
()
,
mo
.trait_ref.def_id
,
mo
.method_num
);
(
None
,
Some
(
trait_item
.def_id
()))
}
...
...
src/librustc_trans/trans/callee.rs
浏览文件 @
f45c0ef5
...
...
@@ -421,12 +421,11 @@ pub fn trans_fn_ref_with_substs<'blk, 'tcx>(
let
impl_or_trait_item
=
ty
::
impl_or_trait_item
(
tcx
,
source_id
);
match
impl_or_trait_item
{
ty
::
MethodTraitItem
(
method
)
=>
{
let
poly_trait_ref
=
ty
::
impl_trait_ref
(
tcx
,
impl_id
)
.unwrap
();
let
trait_ref
=
ty
::
erase_late_bound_regions
(
tcx
,
&*
poly_trait_ref
);
let
trait_ref
=
ty
::
impl_trait_ref
(
tcx
,
impl_id
)
.unwrap
();
// Compute the first substitution
let
first_subst
=
ty
::
make_substs_for_receiver_types
(
tcx
,
&
trait_ref
,
&*
method
)
ty
::
make_substs_for_receiver_types
(
tcx
,
&
*
trait_ref
,
&*
method
)
.erase_regions
();
// And compose them
...
...
src/librustc_trans/trans/meth.rs
浏览文件 @
f45c0ef5
...
...
@@ -133,14 +133,14 @@ pub fn trans_method_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
method_num
})
=>
{
let
trait_ref
=
Rc
::
new
(
t
rait_ref
.subst
(
bcx
.tcx
(),
bcx
.fcx.param_substs
));
Rc
::
new
(
t
y
::
Binder
((
**
trait_ref
)
.subst
(
bcx
.tcx
(),
bcx
.fcx.param_substs
)
));
let
span
=
bcx
.tcx
()
.map
.span
(
method_call
.expr_id
);
debug!
(
"method_call={} trait_ref={}"
,
method_call
,
trait_ref
.repr
(
bcx
.tcx
()));
let
origin
=
fulfill_obligation
(
bcx
.ccx
(),
span
,
(
*
trait_ref
)
.clone
());
trait_ref
.clone
());
debug!
(
"origin = {}"
,
origin
.repr
(
bcx
.tcx
()));
trans_monomorphized_callee
(
bcx
,
method_call
,
trait_ref
.def_id
(),
method_num
,
origin
)
...
...
@@ -618,7 +618,7 @@ fn emit_vtable_methods<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let
tcx
=
ccx
.tcx
();
let
trt_id
=
match
ty
::
impl_trait_ref
(
tcx
,
impl_id
)
{
Some
(
t_id
)
=>
t_id
.def_id
()
,
Some
(
t_id
)
=>
t_id
.def_id
,
None
=>
ccx
.sess
()
.bug
(
"make_impl_vtable: don't know how to
\
make a vtable for a type impl!"
)
};
...
...
src/librustc_typeck/astconv.rs
浏览文件 @
f45c0ef5
...
...
@@ -53,8 +53,7 @@
use
middle
::
resolve_lifetime
as
rl
;
use
middle
::
subst
::{
FnSpace
,
TypeSpace
,
AssocSpace
,
SelfSpace
,
Subst
,
Substs
};
use
middle
::
subst
::{
VecPerParamSpace
};
use
middle
::
ty
::{
mod
,
Ty
};
use
middle
::
ty_fold
;
use
middle
::
ty
::{
mod
,
RegionEscape
,
Ty
};
use
rscope
::{
mod
,
UnelidableRscope
,
RegionScope
,
SpecificRscope
,
ShiftedRscope
,
BindingRscope
};
use
TypeAndSubsts
;
...
...
@@ -533,7 +532,8 @@ pub fn instantiate_poly_trait_ref<'tcx,AC,RS>(
->
Rc
<
ty
::
PolyTraitRef
<
'tcx
>>
where
AC
:
AstConv
<
'tcx
>
,
RS
:
RegionScope
{
let
trait_ref
=
instantiate_trait_ref
(
this
,
rscope
,
&
ast_trait_ref
.trait_ref
,
self_ty
,
allow_eq
);
let
trait_ref
=
instantiate_trait_ref
(
this
,
rscope
,
&
ast_trait_ref
.trait_ref
,
self_ty
,
allow_eq
);
let
trait_ref
=
(
*
trait_ref
)
.clone
();
Rc
::
new
(
ty
::
Binder
(
trait_ref
))
// Ugh.
}
...
...
@@ -1200,10 +1200,9 @@ fn ty_of_method_or_bare_fn<'a, 'tcx, AC: AstConv<'tcx>>(
let
(
self_ty
,
mut
implied_output_region
)
=
match
opt_self_info
{
None
=>
(
None
,
None
),
Some
(
self_info
)
=>
{
// Shift regions in the self type by 1 to account for the binding
// level introduced by the function itself.
let
untransformed_self_ty
=
ty_fold
::
shift_regions
(
this
.tcx
(),
1
,
&
self_info
.untransformed_self_ty
);
// This type comes from an impl or trait; no late-bound
// regions should be present.
assert
!
(
!
self_info
.untransformed_self_ty
.has_escaping_regions
());
// Figure out and record the explicit self category.
let
explicit_self_category
=
...
...
@@ -1214,19 +1213,19 @@ fn ty_of_method_or_bare_fn<'a, 'tcx, AC: AstConv<'tcx>>(
(
None
,
None
)
}
ty
::
ByValueExplicitSelfCategory
=>
{
(
Some
(
untransformed_self_ty
),
None
)
(
Some
(
self_info
.
untransformed_self_ty
),
None
)
}
ty
::
ByReferenceExplicitSelfCategory
(
region
,
mutability
)
=>
{
(
Some
(
ty
::
mk_rptr
(
this
.tcx
(),
region
,
ty
::
mt
{
ty
:
untransformed_self_ty
,
ty
:
self_info
.
untransformed_self_ty
,
mutbl
:
mutability
})),
Some
(
region
))
}
ty
::
ByBoxExplicitSelfCategory
=>
{
(
Some
(
ty
::
mk_uniq
(
this
.tcx
(),
untransformed_self_ty
)),
None
)
(
Some
(
ty
::
mk_uniq
(
this
.tcx
(),
self_info
.
untransformed_self_ty
)),
None
)
}
}
}
...
...
src/librustc_typeck/check/method/confirm.rs
浏览文件 @
f45c0ef5
...
...
@@ -222,17 +222,19 @@ fn fresh_receiver_substs(&mut self,
// argument type), but those cases have already
// been ruled out when we deemed the trait to be
// "object safe".
let
original_trait_ref
=
let
original_
poly_
trait_ref
=
data
.principal_trait_ref_with_self_ty
(
object_ty
);
let
upcast_poly_trait_ref
=
this
.upcast
(
original_poly_trait_ref
.clone
(),
trait_def_id
);
let
upcast_trait_ref
=
this
.
upcast
(
original_trait_ref
.clone
(),
trait_def_id
);
debug!
(
"original_trait_ref={} upcast_trait_ref={} target_trait={}"
,
original_trait_ref
.repr
(
this
.tcx
()),
this
.
replace_late_bound_regions_with_fresh_var
(
&*
upcast_poly_trait_ref
);
debug!
(
"original_
poly_
trait_ref={} upcast_trait_ref={} target_trait={}"
,
original_
poly_
trait_ref
.repr
(
this
.tcx
()),
upcast_trait_ref
.repr
(
this
.tcx
()),
trait_def_id
.repr
(
this
.tcx
()));
let
substs
=
upcast_trait_ref
.substs
()
.clone
();
let
substs
=
upcast_trait_ref
.substs
.clone
();
let
origin
=
MethodTraitObject
(
MethodObject
{
trait_ref
:
upcast_trait_ref
,
trait_ref
:
Rc
::
new
(
upcast_trait_ref
)
,
object_trait_id
:
trait_def_id
,
method_num
:
method_num
,
real_index
:
real_index
,
...
...
@@ -257,7 +259,7 @@ fn fresh_receiver_substs(&mut self,
.subst
(
self
.tcx
(),
&
impl_polytype
.substs
);
let
origin
=
MethodTypeParam
(
MethodParam
{
trait_ref
:
impl_trait_ref
.clone
(),
method_num
:
method_num
});
(
impl_trait_ref
.substs
()
.clone
(),
origin
)
(
impl_trait_ref
.substs
.clone
(),
origin
)
}
probe
::
TraitPick
(
trait_def_id
,
method_num
)
=>
{
...
...
@@ -273,16 +275,20 @@ fn fresh_receiver_substs(&mut self,
self
.infcx
()
.next_ty_var
());
let
trait_ref
=
Rc
::
new
(
ty
::
Binder
(
ty
::
TraitRef
::
new
(
trait_def_id
,
substs
.clone
()
)));
Rc
::
new
(
ty
::
TraitRef
::
new
(
trait_def_id
,
substs
.clone
(
)));
let
origin
=
MethodTypeParam
(
MethodParam
{
trait_ref
:
trait_ref
,
method_num
:
method_num
});
(
substs
,
origin
)
}
probe
::
WhereClausePick
(
ref
trait_ref
,
method_num
)
=>
{
let
origin
=
MethodTypeParam
(
MethodParam
{
trait_ref
:
trait_ref
.clone
(),
probe
::
WhereClausePick
(
ref
poly_trait_ref
,
method_num
)
=>
{
// Where clauses can have bound regions in them. We need to instantiate
// those to convert from a poly-trait-ref to a trait-ref.
let
trait_ref
=
self
.replace_late_bound_regions_with_fresh_var
(
&**
poly_trait_ref
);
let
substs
=
trait_ref
.substs
.clone
();
let
origin
=
MethodTypeParam
(
MethodParam
{
trait_ref
:
Rc
::
new
(
trait_ref
),
method_num
:
method_num
});
(
trait_ref
.substs
()
.clone
()
,
origin
)
(
substs
,
origin
)
}
}
}
...
...
@@ -379,25 +385,9 @@ fn instantiate_method_sig(&mut self,
all_substs
:
subst
::
Substs
<
'tcx
>
)
->
InstantiatedMethodSig
<
'tcx
>
{
// If this method comes from an impl (as opposed to a trait),
// it may have late-bound regions from the impl that appear in
// the substitutions, method signature, and
// bounds. Instantiate those at this point. (If it comes from
// a trait, this step has no effect, as there are no
// late-bound regions to instantiate.)
//
// The binder level here corresponds to the impl.
let
(
all_substs
,
(
method_sig
,
method_generics
))
=
self
.replace_late_bound_regions_with_fresh_var
(
&
ty
::
Binder
((
all_substs
,
(
pick
.method_ty.fty.sig
.clone
(),
pick
.method_ty.generics
.clone
()))));
debug!
(
"late-bound lifetimes from impl instantiated,
\
all_substs={} method_sig={} method_generics={}"
,
all_substs
.repr
(
self
.tcx
()),
method_sig
.repr
(
self
.tcx
()),
method_generics
.repr
(
self
.tcx
()));
debug!
(
"instantiate_method_sig(pick={}, all_substs={})"
,
pick
.repr
(
self
.tcx
()),
all_substs
.repr
(
self
.tcx
()));
// Instantiate the bounds on the method with the
// type/early-bound-regions substitutions performed. The only
...
...
@@ -427,8 +417,7 @@ fn instantiate_method_sig(&mut self,
all_substs
.clone
()
}
};
let
method_bounds
=
method_generics
.to_bounds
(
self
.tcx
(),
&
method_bounds_substs
);
let
method_bounds
=
pick
.method_ty.generics
.to_bounds
(
self
.tcx
(),
&
method_bounds_substs
);
debug!
(
"method_bounds after subst = {}"
,
method_bounds
.repr
(
self
.tcx
()));
...
...
@@ -436,7 +425,7 @@ fn instantiate_method_sig(&mut self,
// Substitute the type/early-bound-regions into the method
// signature. In addition, the method signature may bind
// late-bound regions, so instantiate those.
let
method_sig
=
method_
sig
.subst
(
self
.tcx
(),
&
all_substs
);
let
method_sig
=
pick
.method_ty.fty.
sig
.subst
(
self
.tcx
(),
&
all_substs
);
let
method_sig
=
self
.replace_late_bound_regions_with_fresh_var
(
&
method_sig
);
debug!
(
"late-bound lifetimes from method instantiated, method_sig={}"
,
...
...
src/librustc_typeck/check/method/mod.rs
浏览文件 @
f45c0ef5
...
...
@@ -166,12 +166,13 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>,
// Construct a trait-reference `self_ty : Trait<input_tys>`
let
substs
=
subst
::
Substs
::
new_trait
(
input_types
,
Vec
::
new
(),
assoc_types
,
self_ty
);
let
trait_ref
=
Rc
::
new
(
ty
::
Binder
(
ty
::
TraitRef
::
new
(
trait_def_id
,
substs
)
));
let
trait_ref
=
Rc
::
new
(
ty
::
TraitRef
::
new
(
trait_def_id
,
substs
));
// Construct an obligation
let
poly_trait_ref
=
Rc
::
new
(
ty
::
Binder
((
*
trait_ref
)
.clone
()));
let
obligation
=
traits
::
Obligation
::
misc
(
span
,
fcx
.body_id
,
ty
::
Predicate
::
Trait
(
trait_ref
.clone
()
));
poly_trait_ref
.as_predicate
(
));
// Now we want to know if this can be matched
let
mut
selcx
=
traits
::
SelectionContext
::
new
(
fcx
.infcx
(),
...
...
@@ -194,11 +195,8 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>,
// Substitute the trait parameters into the method type and
// instantiate late-bound regions to get the actual method type.
//
// Note that as the method comes from a trait, it can only have
// late-bound regions from the fn itself, not the impl.
let
ref
bare_fn_ty
=
method_ty
.fty
;
let
fn_sig
=
bare_fn_ty
.sig
.subst
(
tcx
,
trait_ref
.substs
()
);
let
fn_sig
=
bare_fn_ty
.sig
.subst
(
tcx
,
&
trait_ref
.substs
);
let
fn_sig
=
fcx
.infcx
()
.replace_late_bound_regions_with_fresh_var
(
span
,
infer
::
FnCall
,
&
fn_sig
)
.0
;
...
...
@@ -221,7 +219,7 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>,
//
// Note that as the method comes from a trait, it should not have
// any late-bound regions appearing in its bounds.
let
method_bounds
=
method_ty
.generics
.to_bounds
(
fcx
.tcx
(),
trait_ref
.substs
()
);
let
method_bounds
=
method_ty
.generics
.to_bounds
(
fcx
.tcx
(),
&
trait_ref
.substs
);
assert
!
(
!
method_bounds
.has_escaping_regions
());
fcx
.add_obligations_for_parameters
(
traits
::
ObligationCause
::
misc
(
span
,
fcx
.body_id
),
...
...
@@ -293,7 +291,7 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>,
origin
:
MethodTypeParam
(
MethodParam
{
trait_ref
:
trait_ref
.clone
(),
method_num
:
method_num
}),
ty
:
fty
,
substs
:
trait_ref
.substs
()
.clone
()
substs
:
trait_ref
.substs
.clone
()
};
debug!
(
"callee = {}"
,
callee
.repr
(
fcx
.tcx
()));
...
...
@@ -379,7 +377,7 @@ fn report_candidates(fcx: &FnCtxt,
None
=>
format!
(
""
),
Some
(
trait_ref
)
=>
format!
(
" of the trait `{}`"
,
ty
::
item_path_str
(
fcx
.tcx
(),
trait_ref
.def_id
()
)),
trait_ref
.def_id
)),
};
span_note!
(
fcx
.sess
(),
method_span
,
...
...
src/librustc_typeck/check/method/probe.rs
浏览文件 @
f45c0ef5
...
...
@@ -19,7 +19,6 @@
use
middle
::
subst
::
Subst
;
use
middle
::
traits
;
use
middle
::
ty
::{
mod
,
Ty
};
use
middle
::
ty
::{
MethodObject
};
use
middle
::
ty_fold
::
TypeFoldable
;
use
middle
::
infer
;
use
middle
::
infer
::
InferCtxt
;
...
...
@@ -58,8 +57,8 @@ struct Candidate<'tcx> {
enum
CandidateKind
<
'tcx
>
{
InherentImplCandidate
(
/* Impl */
ast
::
DefId
,
subst
::
Substs
<
'tcx
>
),
ObjectCandidate
(
MethodObject
<
'tcx
>
),
ExtensionImplCandidate
(
/* Impl */
ast
::
DefId
,
Rc
<
ty
::
Poly
TraitRef
<
'tcx
>>
,
ObjectCandidate
(
/* Trait */
ast
::
DefId
,
/* method_num */
uint
,
/* real_index */
uint
),
ExtensionImplCandidate
(
/* Impl */
ast
::
DefId
,
Rc
<
ty
::
TraitRef
<
'tcx
>>
,
subst
::
Substs
<
'tcx
>
,
MethodIndex
),
UnboxedClosureCandidate
(
/* Trait */
ast
::
DefId
,
MethodIndex
),
WhereClauseCandidate
(
Rc
<
ty
::
PolyTraitRef
<
'tcx
>>
,
MethodIndex
),
...
...
@@ -149,7 +148,7 @@ pub fn probe<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
// this creates one big transaction so that all type variables etc
// that we create during the probe process are removed later
let
mut
dummy
=
Some
((
steps
,
opt_simplified_steps
));
// FIXME(#18101) need once closures
fcx
.infcx
()
.probe
(||
{
fcx
.infcx
()
.probe
(|
_
|
{
let
(
steps
,
opt_simplified_steps
)
=
dummy
.take
()
.unwrap
();
let
mut
probe_cx
=
ProbeContext
::
new
(
fcx
,
span
,
method_name
,
steps
,
opt_simplified_steps
);
probe_cx
.assemble_inherent_candidates
();
...
...
@@ -313,12 +312,7 @@ fn assemble_inherent_candidates_from_object(&mut self,
this
.inherent_candidates
.push
(
Candidate
{
xform_self_ty
:
xform_self_ty
,
method_ty
:
m
,
kind
:
ObjectCandidate
(
MethodObject
{
trait_ref
:
new_trait_ref
,
object_trait_id
:
trait_ref
.def_id
(),
method_num
:
method_num
,
real_index
:
vtable_index
})
kind
:
ObjectCandidate
(
new_trait_ref
.def_id
(),
method_num
,
vtable_index
)
});
});
}
...
...
@@ -502,7 +496,7 @@ fn assemble_extension_candidates_for_trait_impls(&mut self,
// Determine the receiver type that the method itself expects.
let
xform_self_ty
=
self
.xform_self_ty
(
&
method
,
impl_trait_ref
.substs
()
);
self
.xform_self_ty
(
&
method
,
&
impl_trait_ref
.substs
);
debug!
(
"xform_self_ty={}"
,
xform_self_ty
.repr
(
self
.tcx
()));
...
...
@@ -748,7 +742,7 @@ fn consider_probe(&self, self_ty: Ty<'tcx>, probe: &Candidate<'tcx>) -> bool {
self_ty
.repr
(
self
.tcx
()),
probe
.repr
(
self
.tcx
()));
self
.infcx
()
.probe
(||
{
self
.infcx
()
.probe
(|
_
|
{
// First check that the self type can be related.
match
self
.make_sub_ty
(
self_ty
,
probe
.xform_self_ty
)
{
Ok
(())
=>
{
}
...
...
@@ -1033,8 +1027,8 @@ fn to_unadjusted_pick(&self) -> Pick<'tcx> {
InherentImplCandidate
(
def_id
,
_
)
=>
{
InherentImplPick
(
def_id
)
}
ObjectCandidate
(
ref
data
)
=>
{
ObjectPick
(
d
ata
.trait_ref
.def_id
(),
data
.method_num
,
data
.
real_index
)
ObjectCandidate
(
def_id
,
method_num
,
real_index
)
=>
{
ObjectPick
(
d
ef_id
,
method_num
,
real_index
)
}
ExtensionImplCandidate
(
def_id
,
_
,
_
,
index
)
=>
{
ExtensionImplPick
(
def_id
,
index
)
...
...
@@ -1059,7 +1053,7 @@ fn to_unadjusted_pick(&self) -> Pick<'tcx> {
fn
to_source
(
&
self
)
->
CandidateSource
{
match
self
.kind
{
InherentImplCandidate
(
def_id
,
_
)
=>
ImplSource
(
def_id
),
ObjectCandidate
(
ref
obj
)
=>
TraitSource
(
obj
.trait_ref
.def_id
()
),
ObjectCandidate
(
def_id
,
_
,
_
)
=>
TraitSource
(
def_id
),
ExtensionImplCandidate
(
def_id
,
_
,
_
,
_
)
=>
ImplSource
(
def_id
),
UnboxedClosureCandidate
(
trait_def_id
,
_
)
=>
TraitSource
(
trait_def_id
),
WhereClauseCandidate
(
ref
trait_ref
,
_
)
=>
TraitSource
(
trait_ref
.def_id
()),
...
...
@@ -1075,7 +1069,9 @@ fn to_trait_data(&self) -> Option<(ast::DefId,MethodIndex)> {
UnboxedClosureCandidate
(
trait_def_id
,
method_num
)
=>
{
Some
((
trait_def_id
,
method_num
))
}
ExtensionImplCandidate
(
_
,
ref
trait_ref
,
_
,
method_num
)
|
ExtensionImplCandidate
(
_
,
ref
trait_ref
,
_
,
method_num
)
=>
{
Some
((
trait_ref
.def_id
,
method_num
))
}
WhereClauseCandidate
(
ref
trait_ref
,
method_num
)
=>
{
Some
((
trait_ref
.def_id
(),
method_num
))
}
...
...
@@ -1096,8 +1092,8 @@ fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
match
*
self
{
InherentImplCandidate
(
ref
a
,
ref
b
)
=>
format!
(
"InherentImplCandidate({},{})"
,
a
.repr
(
tcx
),
b
.repr
(
tcx
)),
ObjectCandidate
(
ref
a
)
=>
format!
(
"ObjectCandidate({}
)"
,
a
.repr
(
tcx
)
),
ObjectCandidate
(
a
,
b
,
c
)
=>
format!
(
"ObjectCandidate({}
,{},{})"
,
a
.repr
(
tcx
),
b
,
c
),
ExtensionImplCandidate
(
ref
a
,
ref
b
,
ref
c
,
ref
d
)
=>
format!
(
"ExtensionImplCandidate({},{},{},{})"
,
a
.repr
(
tcx
),
b
.repr
(
tcx
),
c
.repr
(
tcx
),
d
),
...
...
src/librustc_typeck/check/mod.rs
浏览文件 @
f45c0ef5
...
...
@@ -719,12 +719,7 @@ fn check_method_body<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
let
param_env
=
ParameterEnvironment
::
for_item
(
ccx
.tcx
,
method
.id
);
let
fty
=
ty
::
node_id_to_type
(
ccx
.tcx
,
method
.id
);
debug!
(
"fty (raw): {}"
,
fty
.repr
(
ccx
.tcx
));
let
body_id
=
method
.pe_body
()
.id
;
let
fty
=
liberate_late_bound_regions
(
ccx
.tcx
,
CodeExtent
::
from_node_id
(
body_id
),
&
ty
::
Binder
(
fty
));
debug!
(
"fty (liberated): {}"
,
fty
.repr
(
ccx
.tcx
));
debug!
(
"check_method_body: fty={}"
,
fty
.repr
(
ccx
.tcx
));
check_bare_fn
(
ccx
,
&*
method
.pe_fn_decl
(),
...
...
@@ -736,11 +731,11 @@ fn check_method_body<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
fn
check_impl_items_against_trait
<
'a
,
'tcx
>
(
ccx
:
&
CrateCtxt
<
'a
,
'tcx
>
,
impl_span
:
Span
,
impl_trait_ref
:
&
ty
::
Poly
TraitRef
<
'tcx
>
,
impl_trait_ref
:
&
ty
::
TraitRef
<
'tcx
>
,
impl_items
:
&
[
ast
::
ImplItem
])
{
// Locate trait methods
let
tcx
=
ccx
.tcx
;
let
trait_items
=
ty
::
trait_items
(
tcx
,
impl_trait_ref
.def_id
()
);
let
trait_items
=
ty
::
trait_items
(
tcx
,
impl_trait_ref
.def_id
);
// Check existing impl methods to see if they are both present in trait
// and compatible with trait signature
...
...
@@ -834,8 +829,7 @@ trait `{}`",
}
// Check for missing items from trait
let
provided_methods
=
ty
::
provided_trait_methods
(
tcx
,
impl_trait_ref
.def_id
());
let
provided_methods
=
ty
::
provided_trait_methods
(
tcx
,
impl_trait_ref
.def_id
);
let
mut
missing_methods
=
Vec
::
new
();
for
trait_item
in
trait_items
.iter
()
{
match
*
trait_item
{
...
...
@@ -894,37 +888,16 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
impl_m_span
:
Span
,
impl_m_body_id
:
ast
::
NodeId
,
trait_m
:
&
ty
::
Method
<
'tcx
>
,
impl_trait_ref
:
&
ty
::
Poly
TraitRef
<
'tcx
>
)
{
impl_trait_ref
:
&
ty
::
TraitRef
<
'tcx
>
)
{
debug!
(
"compare_impl_method(impl_trait_ref={})"
,
impl_trait_ref
.repr
(
tcx
));
let
impl_m_body_scope
=
CodeExtent
::
from_node_id
(
impl_m_body_id
);
// The impl's trait ref may bind late-bound regions from the impl.
// Liberate them and assign them the scope of the method body.
//
// An example would be:
//
// impl<'a> Foo<&'a T> for &'a U { ... }
//
// Here, the region parameter `'a` is late-bound, so the
// trait reference associated with the impl will be
//
// for<'a> Foo<&'a T>
//
// liberating will convert this into:
//
// Foo<&'A T>
//
// where `'A` is the `ReFree` version of `'a`.
let
impl_trait_ref
=
liberate_late_bound_regions
(
tcx
,
impl_m_body_scope
,
impl_trait_ref
);
debug!
(
"impl_trait_ref (liberated) = {}"
,
impl_trait_ref
.repr
(
tcx
));
let
infcx
=
infer
::
new_infer_ctxt
(
tcx
);
let
trait_to_impl_substs
=
impl_trait_ref
.substs
;
let
trait_to_impl_substs
=
&
impl_trait_ref
.substs
;
// Try to give more informative error messages about self typing
// mismatches. Note that any mismatch will also be detected
...
...
@@ -1060,7 +1033,6 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
if
!
check_region_bounds_on_impl_method
(
tcx
,
impl_m_span
,
impl_m
,
impl_m_body_scope
,
&
trait_m
.generics
,
&
impl_m
.generics
,
&
trait_to_skol_substs
,
...
...
@@ -1099,11 +1071,7 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
.map
(|
trait_param_def
|
&
trait_param_def
.bounds
);
let
impl_bounds
=
impl_m
.generics.types
.get_slice
(
subst
::
FnSpace
)
.iter
()
.map
(|
impl_param_def
|
liberate_late_bound_regions
(
tcx
,
impl_m_body_scope
,
&
ty
::
Binder
(
ty
::
Binder
(
impl_param_def
.bounds
.clone
())))
.0
);
.map
(|
impl_param_def
|
&
impl_param_def
.bounds
);
for
(
i
,
(
trait_param_bounds
,
impl_param_bounds
))
in
trait_bounds
.zip
(
impl_bounds
)
.enumerate
()
{
...
...
@@ -1164,12 +1132,9 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
}
}
// Compute skolemized form of impl and trait method tys. Note
// that we must liberate the late-bound regions from the impl.
// Compute skolemized form of impl and trait method tys.
let
impl_fty
=
ty
::
mk_bare_fn
(
tcx
,
impl_m
.fty
.clone
());
let
impl_fty
=
impl_fty
.subst
(
tcx
,
&
impl_to_skol_substs
);
let
impl_fty
=
liberate_late_bound_regions
(
tcx
,
impl_m_body_scope
,
&
ty
::
Binder
(
impl_fty
));
let
trait_fty
=
ty
::
mk_bare_fn
(
tcx
,
trait_m
.fty
.clone
());
let
trait_fty
=
trait_fty
.subst
(
tcx
,
&
trait_to_skol_substs
);
...
...
@@ -1231,7 +1196,6 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
fn
check_region_bounds_on_impl_method
<
'tcx
>
(
tcx
:
&
ty
::
ctxt
<
'tcx
>
,
span
:
Span
,
impl_m
:
&
ty
::
Method
<
'tcx
>
,
impl_m_body_scope
:
CodeExtent
,
trait_generics
:
&
ty
::
Generics
<
'tcx
>
,
impl_generics
:
&
ty
::
Generics
<
'tcx
>
,
trait_to_skol_substs
:
&
Substs
<
'tcx
>
,
...
...
@@ -1281,16 +1245,6 @@ fn check_region_bounds_on_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
let
impl_bounds
=
impl_param
.bounds
.subst
(
tcx
,
impl_to_skol_substs
);
// The bounds may reference late-bound regions from the
// impl declaration. In that case, we want to replace
// those with the liberated variety so as to match the
// versions appearing in the `trait_to_skol_substs`.
// There are two-levels of binder to be aware of: the
// impl, and the method.
let
impl_bounds
=
ty
::
liberate_late_bound_regions
(
tcx
,
impl_m_body_scope
,
&
ty
::
Binder
(
ty
::
Binder
(
impl_bounds
)))
.0
;
debug!
(
"check_region_bounds_on_impl_method:
\
trait_param={}
\
impl_param={}
\
...
...
src/librustc_typeck/check/wf.rs
浏览文件 @
f45c0ef5
...
...
@@ -166,11 +166,9 @@ fn check_impl(&mut self,
// Find the impl self type as seen from the "inside" --
// that is, with all type parameters converted from bound
// to free, and any late-bound regions on the impl
// liberated.
// to free.
let
self_ty
=
ty
::
node_id_to_type
(
fcx
.tcx
(),
item
.id
);
let
self_ty
=
self_ty
.subst
(
fcx
.tcx
(),
&
fcx
.inh.param_env.free_substs
);
let
self_ty
=
liberate_late_bound_regions
(
fcx
.tcx
(),
item_scope
,
&
ty
::
Binder
(
self_ty
));
bounds_checker
.check_traits_in_ty
(
self_ty
);
...
...
@@ -181,7 +179,6 @@ fn check_impl(&mut self,
Some
(
t
)
=>
{
t
}
};
let
trait_ref
=
(
*
trait_ref
)
.subst
(
fcx
.tcx
(),
&
fcx
.inh.param_env.free_substs
);
let
trait_ref
=
liberate_late_bound_regions
(
fcx
.tcx
(),
item_scope
,
&
trait_ref
);
// There are special rules that apply to drop.
if
...
...
src/librustc_typeck/coherence/mod.rs
浏览文件 @
f45c0ef5
...
...
@@ -18,8 +18,8 @@
use
metadata
::
csearch
::{
each_impl
,
get_impl_trait
};
use
metadata
::
csearch
;
use
middle
::
region
;
use
middle
::
subst
::{
mod
,
Subst
};
use
middle
::
ty
::
RegionEscape
;
use
middle
::
ty
::{
ImplContainer
,
ImplOrTraitItemId
,
MethodTraitItemId
};
use
middle
::
ty
::{
ParameterEnvironment
,
TypeTraitItemId
,
lookup_item_type
};
use
middle
::
ty
::{
Ty
,
ty_bool
,
ty_char
,
ty_closure
,
ty_enum
,
ty_err
};
...
...
@@ -339,7 +339,7 @@ fn add_external_impl(&self,
// Record all the trait items.
for
trait_ref
in
associated_traits
.iter
()
{
self
.add_trait_impl
(
trait_ref
.def_id
()
,
impl_def_id
);
self
.add_trait_impl
(
trait_ref
.def_id
,
impl_def_id
);
}
// For any methods that use a default implementation, add them to
...
...
@@ -459,6 +459,9 @@ fn check_implementations_of_copy(&self) {
let
trait_impls
=
trait_impls
.borrow
()
.clone
();
for
&
impl_did
in
trait_impls
.iter
()
{
debug!
(
"check_implementations_of_copy: impl_did={}"
,
impl_did
.repr
(
tcx
));
if
impl_did
.krate
!=
ast
::
LOCAL_CRATE
{
debug!
(
"check_implementations_of_copy(): impl not in this
\
crate"
);
...
...
@@ -466,20 +469,15 @@ fn check_implementations_of_copy(&self) {
}
let
self_type
=
self
.get_self_type_for_implementation
(
impl_did
);
debug!
(
"check_implementations_of_copy: self_type={} (bound)"
,
self_type
.repr
(
tcx
));
let
span
=
tcx
.map
.span
(
impl_did
.node
);
let
param_env
=
ParameterEnvironment
::
for_item
(
tcx
,
impl_did
.node
);
let
param_env
=
ParameterEnvironment
::
for_item
(
tcx
,
impl_did
.node
);
let
self_type
=
self_type
.ty
.subst
(
tcx
,
&
param_env
.free_substs
);
assert
!
(
!
self_type
.has_escaping_regions
());
// the self-type may have late-bound regions bound in the
// impl; liberate them.
let
item_scope
=
region
::
CodeExtent
::
from_node_id
(
impl_did
.node
);
let
self_type
=
ty
::
liberate_late_bound_regions
(
tcx
,
item_scope
,
&
ty
::
Binder
(
self_type
));
debug!
(
"can_type_implement_copy(self_type={})"
,
debug!
(
"check_implementations_of_copy: self_type={} (free)"
,
self_type
.repr
(
tcx
));
match
ty
::
can_type_implement_copy
(
tcx
,
self_type
,
&
param_env
)
{
...
...
src/librustc_typeck/coherence/unsafety.rs
浏览文件 @
f45c0ef5
...
...
@@ -45,7 +45,7 @@ fn visit_item(&mut self, item: &'v ast::Item) {
}
Some
(
trait_ref
)
=>
{
let
trait_def
=
ty
::
lookup_trait_def
(
self
.tcx
,
trait_ref
.def_id
()
);
let
trait_def
=
ty
::
lookup_trait_def
(
self
.tcx
,
trait_ref
.def_id
);
match
(
trait_def
.unsafety
,
unsafety
)
{
(
ast
::
Unsafety
::
Normal
,
ast
::
Unsafety
::
Unsafe
)
=>
{
self
.tcx.sess
.span_err
(
...
...
src/librustc_typeck/collect.rs
浏览文件 @
f45c0ef5
...
...
@@ -43,8 +43,8 @@
use
middle
::
subst
;
use
middle
::
subst
::{
Substs
};
use
middle
::
ty
::{
AsPredicate
,
ImplContainer
,
ImplOrTraitItemContainer
,
TraitContainer
};
use
middle
::
ty
::{
mod
,
Ty
,
Polytype
};
use
middle
::
ty_fold
::{
mod
,
TypeFolder
};
use
middle
::
ty
::{
mod
,
RegionEscape
,
Ty
,
Polytype
};
use
middle
::
ty_fold
::{
mod
,
TypeFolder
,
TypeFoldable
};
use
middle
::
infer
;
use
rscope
::
*
;
use
{
CrateCtxt
,
lookup_def_tcx
,
no_params
,
write_ty_to_tcx
};
...
...
@@ -226,7 +226,7 @@ pub fn get_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
ast
::
StructVariantKind
(
ref
struct_def
)
=>
{
let
pty
=
Polytype
{
generics
:
ty_generics_for_type
(
generics
:
ty_generics_for_type
_or_impl
(
ccx
,
generics
,
DontCreateTypeParametersForAssociatedTypes
),
...
...
@@ -239,7 +239,7 @@ pub fn get_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
};
let
pty
=
Polytype
{
generics
:
ty_generics_for_type
(
generics
:
ty_generics_for_type
_or_impl
(
ccx
,
generics
,
DontCreateTypeParametersForAssociatedTypes
),
...
...
@@ -1050,7 +1050,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
ref
selfty
,
ref
impl_items
)
=>
{
// Create generics from the generics specified in the impl head.
let
ty_generics
=
ty_generics_for_impl
(
let
ty_generics
=
ty_generics_for_
type_or_
impl
(
ccx
,
generics
,
CreateTypeParametersForAssociatedTypes
);
...
...
@@ -1482,7 +1482,7 @@ pub fn ty_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item)
let
pty
=
{
let
ty
=
ccx
.to_ty
(
&
ExplicitRscope
,
&**
t
);
Polytype
{
generics
:
ty_generics_for_type
(
generics
:
ty_generics_for_type
_or_impl
(
ccx
,
generics
,
DontCreateTypeParametersForAssociatedTypes
),
...
...
@@ -1495,7 +1495,7 @@ pub fn ty_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item)
}
ast
::
ItemEnum
(
_
,
ref
generics
)
=>
{
// Create a new generic polytype.
let
ty_generics
=
ty_generics_for_type
(
let
ty_generics
=
ty_generics_for_type
_or_impl
(
ccx
,
generics
,
DontCreateTypeParametersForAssociatedTypes
);
...
...
@@ -1513,7 +1513,7 @@ pub fn ty_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item)
tcx
.sess
.span_bug
(
it
.span
,
"invoked ty_of_item on trait"
);
}
ast
::
ItemStruct
(
_
,
ref
generics
)
=>
{
let
ty_generics
=
ty_generics_for_type
(
let
ty_generics
=
ty_generics_for_type
_or_impl
(
ccx
,
generics
,
DontCreateTypeParametersForAssociatedTypes
);
...
...
@@ -1580,7 +1580,7 @@ fn ty_of_trait_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
}
}
fn
ty_generics_for_type
<
'a
,
'tcx
>
(
ccx
:
&
CrateCtxt
<
'a
,
'tcx
>
,
fn
ty_generics_for_type
_or_impl
<
'a
,
'tcx
>
(
ccx
:
&
CrateCtxt
<
'a
,
'tcx
>
,
generics
:
&
ast
::
Generics
,
create_type_parameters_for_associated_types
:
CreateTypeParametersForAssociatedTypesFlag
)
...
...
@@ -1664,24 +1664,6 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
generics
}
fn
ty_generics_for_impl
<
'a
,
'tcx
>
(
ccx
:
&
CrateCtxt
<
'a
,
'tcx
>
,
generics
:
&
ast
::
Generics
,
create_type_parameters_for_associated_types
:
CreateTypeParametersForAssociatedTypesFlag
)
->
ty
::
Generics
<
'tcx
>
{
let
early_lifetimes
=
resolve_lifetime
::
early_bound_lifetimes
(
generics
);
debug!
(
"ty_generics_for_impl: early_lifetimes={}"
,
early_lifetimes
);
ty_generics
(
ccx
,
subst
::
TypeSpace
,
early_lifetimes
.as_slice
(),
generics
.ty_params
.as_slice
(),
ty
::
Generics
::
empty
(),
&
generics
.where_clause
,
create_type_parameters_for_associated_types
)
}
fn
ty_generics_for_fn_or_method
<
'tcx
,
AC
>
(
this
:
&
AC
,
generics
:
&
ast
::
Generics
,
...
...
@@ -2186,8 +2168,12 @@ pub fn mk_item_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
subst
::
Substs
::
new
(
types
,
regions
)
}
/// Verifies that the explicit self type of a method matches the impl or
/// trait.
/// Verifies that the explicit self type of a method matches the impl
/// or trait. This is a bit weird but basically because right now we
/// don't handle the general case, but instead map it to one of
/// several pre-defined options using various heuristics, this method
/// comes back to check after the fact that explicit type the user
/// wrote actually matches what the pre-defined option said.
fn
check_method_self_type
<
'a
,
'tcx
,
RS
:
RegionScope
>
(
crate_context
:
&
CrateCtxt
<
'a
,
'tcx
>
,
rs
:
&
RS
,
...
...
@@ -2209,19 +2195,21 @@ fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
// contain late-bound regions from the method, but not the
// trait (since traits only have early-bound region
// parameters).
assert
!
(
!
ty
::
type_escapes_depth
(
required_type
,
1
));
assert
!
(
!
base_type
.has_regions_escaping_depth
(
1
));
let
required_type_free
=
ty
::
liberate_late_bound_regions
(
crate_context
.tcx
,
body_scope
,
&
ty
::
Binder
(
required_type
));
liberate_early_bound_regions
(
crate_context
.tcx
,
body_scope
,
&
ty
::
liberate_late_bound_regions
(
crate_context
.tcx
,
body_scope
,
&
ty
::
Binder
(
required_type
)));
// The "base type" comes from the impl. It may have late-bound
// regions from the impl or the method.
// The "base type" comes from the impl. It too may have late-bound
// regions from the method.
assert
!
(
!
base_type
.has_regions_escaping_depth
(
1
));
let
base_type_free
=
ty
::
liberate_late_bound_regions
(
// liberate impl regions:
crate_context
.tcx
,
body_scope
,
&
ty
::
liberate_late_bound_regions
(
// liberate method regions:
liberate_early_bound_regions
(
crate_context
.tcx
,
body_scope
,
&
ty
::
Binder
(
ty
::
Binder
(
base_type
))));
&
ty
::
liberate_late_bound_regions
(
crate_context
.tcx
,
body_scope
,
&
ty
::
Binder
(
base_type
)));
debug!
(
"required_type={} required_type_free={}
\
base_type={} base_type_free={}"
,
...
...
@@ -2242,4 +2230,30 @@ fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
}));
infcx
.resolve_regions_and_report_errors
(
body_id
);
}
fn
liberate_early_bound_regions
<
'tcx
,
T
>
(
tcx
:
&
ty
::
ctxt
<
'tcx
>
,
scope
:
region
::
CodeExtent
,
value
:
&
T
)
->
T
where
T
:
TypeFoldable
<
'tcx
>
+
Repr
<
'tcx
>
{
/*!
* Convert early-bound regions into free regions; normally this is done by
* applying the `free_substs` from the `ParameterEnvironment`, but this particular
* method-self-type check is kind of hacky and done very early in the process,
* before we really have a `ParameterEnvironment` to check.
*/
ty_fold
::
fold_regions
(
tcx
,
value
,
|
region
,
_
|
{
match
region
{
ty
::
ReEarlyBound
(
id
,
_
,
_
,
name
)
=>
{
let
def_id
=
local_def
(
id
);
ty
::
ReFree
(
ty
::
FreeRegion
{
scope
:
scope
,
bound_region
:
ty
::
BrNamed
(
def_id
,
name
)
})
}
_
=>
region
}
})
}
}
src/librustdoc/clean/inline.rs
浏览文件 @
f45c0ef5
...
...
@@ -281,7 +281,7 @@ fn build_impl(cx: &DocContext, tcx: &ty::ctxt,
// If this is an impl for a #[doc(hidden)] trait, be sure to not inline it.
match
associated_trait
{
Some
(
ref
t
)
=>
{
let
trait_attrs
=
load_attrs
(
cx
,
tcx
,
t
.def_id
()
);
let
trait_attrs
=
load_attrs
(
cx
,
tcx
,
t
.def_id
);
if
trait_attrs
.iter
()
.any
(|
a
|
is_doc_hidden
(
a
))
{
return
None
}
...
...
src/test/compile-fail/hrtb-conflate-regions.rs
0 → 100644
浏览文件 @
f45c0ef5
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Test what an impl with only one bound region `'a` cannot be used to
// satisfy a constraint whre there are two bound regions.
trait
Foo
<
X
>
{
fn
foo
(
&
self
,
x
:
X
)
{
}
}
fn
want_foo2
<
T
>
()
where
T
:
for
<
'a
,
'b
>
Foo
<
(
&
'a
int
,
&
'b
int
)
>
{
}
fn
want_foo1
<
T
>
()
where
T
:
for
<
'z
>
Foo
<
(
&
'z
int
,
&
'z
int
)
>
{
}
///////////////////////////////////////////////////////////////////////////
// Expressed as a where clause
struct
SomeStruct
;
impl
<
'a
>
Foo
<
(
&
'a
int
,
&
'a
int
)
>
for
SomeStruct
{
}
fn
a
()
{
want_foo1
::
<
SomeStruct
>
();
}
// OK -- foo wants just one region
fn
b
()
{
want_foo2
::
<
SomeStruct
>
();
}
//~ ERROR not implemented
fn
main
()
{
}
src/test/compile-fail/hrtb-just-for-static.rs
0 → 100644
浏览文件 @
f45c0ef5
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Test a case where you have an impl of `Foo<X>` for all `X` that
// is being applied to `for<'a> Foo<&'a mut X>`. Issue #19730.
trait
Foo
<
X
>
{
fn
foo
(
&
self
,
x
:
X
)
{
}
}
fn
want_hrtb
<
T
>
()
where
T
:
for
<
'a
>
Foo
<&
'a
int
>
{
}
// AnyInt implements Foo<&'a int> for any 'a, so it is a match.
struct
AnyInt
;
impl
<
'a
>
Foo
<&
'a
int
>
for
AnyInt
{
}
fn
give_any
()
{
want_hrtb
::
<
AnyInt
>
()
}
// StaticInt only implements Foo<&'a int> for 'a, so it is an error.
struct
StaticInt
;
impl
Foo
<&
'static
int
>
for
StaticInt
{
}
fn
give_static
()
{
want_hrtb
::
<
StaticInt
>
()
//~ ERROR `for<'a> Foo<&'a int>` is not implemented
}
fn
main
()
{
}
src/test/compile-fail/hrtb-perfect-forwarding.rs
0 → 100644
浏览文件 @
f45c0ef5
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Test a case where you have an impl of `Foo<X>` for all `X` that
// is being applied to `for<'a> Foo<&'a mut X>`. Issue #19730.
trait
Foo
<
X
>
{
fn
foo
(
&
mut
self
,
x
:
X
)
{
}
}
trait
Bar
<
X
>
{
fn
bar
(
&
mut
self
,
x
:
X
)
{
}
}
impl
<
'a
,
X
,
F
>
Foo
<
X
>
for
&
'a
mut
F
where
F
:
Foo
<
X
>
+
Bar
<
X
>
{
}
impl
<
'a
,
X
,
F
>
Bar
<
X
>
for
&
'a
mut
F
where
F
:
Bar
<
X
>
{
}
fn
no_hrtb
<
'b
,
T
>
(
mut
t
:
T
)
where
T
:
Bar
<&
'b
int
>
{
// OK -- `T : Bar<&'b int>`, and thus the impl above ensures that
// `&mut T : Bar<&'b int>`.
no_hrtb
(
&
mut
t
);
}
fn
bar_hrtb
<
T
>
(
mut
t
:
T
)
where
T
:
for
<
'b
>
Bar
<&
'b
int
>
{
// OK -- `T : for<'b> Bar<&'b int>`, and thus the impl above
// ensures that `&mut T : for<'b> Bar<&'b int>`. This is an
// example of a "perfect forwarding" impl.
bar_hrtb
(
&
mut
t
);
}
fn
foo_hrtb_bar_not
<
'b
,
T
>
(
mut
t
:
T
)
where
T
:
for
<
'a
>
Foo
<&
'a
int
>
+
Bar
<&
'b
int
>
{
// Not OK -- The forwarding impl for `Foo` requires that `Bar` also
// be implemented. Thus to satisfy `&mut T : for<'a> Foo<&'a
// int>`, we require `T : for<'a> Bar<&'a int>`, but the where
// clause only specifies `T : Bar<&'b int>`.
foo_hrtb_bar_not
(
&
mut
t
);
//~ ERROR `for<'a> Bar<&'a int>` is not implemented for the type `T`
}
fn
foo_hrtb_bar_hrtb
<
T
>
(
mut
t
:
T
)
where
T
:
for
<
'a
>
Foo
<&
'a
int
>
+
for
<
'b
>
Bar
<&
'b
int
>
{
// OK -- now we have `T : for<'b> Bar&'b int>`.
foo_hrtb_bar_hrtb
(
&
mut
t
);
}
fn
main
()
{
}
src/test/compile-fail/hrtb-type-outlives.rs
0 → 100644
浏览文件 @
f45c0ef5
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Test what happens when a HR obligation is applie to an impl with
// "outlives" bounds. Currently we're pretty conservative here; this
// will probably improve in time.
trait
Foo
<
X
>
{
fn
foo
(
&
self
,
x
:
X
)
{
}
}
fn
want_foo
<
T
>
()
where
T
:
for
<
'a
>
Foo
<&
'a
int
>
{
}
///////////////////////////////////////////////////////////////////////////
// Expressed as a where clause
struct
SomeStruct
<
X
>
{
x
:
X
}
impl
<
'a
,
X
>
Foo
<&
'a
int
>
for
SomeStruct
<
X
>
where
X
:
'a
{
}
fn
one
()
{
// In fact there is no good reason for this to be an error, but
// whatever, I'm mostly concerned it doesn't ICE right now:
want_foo
::
<
SomeStruct
<
uint
>>
();
//~^ ERROR requirement `for<'a> uint : 'a` is not satisfied
}
///////////////////////////////////////////////////////////////////////////
// Expressed as shorthand
struct
AnotherStruct
<
X
>
{
x
:
X
}
impl
<
'a
,
X
:
'a
>
Foo
<&
'a
int
>
for
AnotherStruct
<
X
>
{
}
fn
two
()
{
want_foo
::
<
AnotherStruct
<
uint
>>
();
//~^ ERROR requirement `for<'a> uint : 'a` is not satisfied
}
fn
main
()
{
}
src/test/compile-fail/issue-14366.rs
浏览文件 @
f45c0ef5
...
...
@@ -11,5 +11,4 @@
fn
main
()
{
let
_
x
=
"test"
as
&
::
std
::
any
::
Any
;
//~^ ERROR the trait `core::kinds::Sized` is not implemented for the type `str`
//~^^ ERROR the trait `core::kinds::Sized` is not implemented for the type `str`
}
src/test/compile-fail/kindck-inherited-copy-bound.rs
浏览文件 @
f45c0ef5
...
...
@@ -21,10 +21,15 @@ impl<T:Copy> Foo for T {
fn
take_param
<
T
:
Foo
>
(
foo
:
&
T
)
{
}
fn
main
()
{
fn
a
()
{
let
x
=
box
3
i
;
take_param
(
&
x
);
//~ ERROR `core::kinds::Copy` is not implemented
}
fn
b
()
{
let
x
=
box
3
i
;
let
y
=
&
x
;
let
z
=
&
x
as
&
Foo
;
//~ ERROR `core::kinds::Copy` is not implemented
}
fn
main
()
{
}
src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs
浏览文件 @
f45c0ef5
...
...
@@ -20,9 +20,16 @@ fn call_it<F:Fn(&int)->int>(_: &F, _: int) -> int { 0 }
fn
call_it_mut
<
F
:
FnMut
(
&
int
)
->
int
>
(
_
:
&
mut
F
,
_
:
int
)
->
int
{
0
}
fn
call_it_once
<
F
:
FnOnce
(
&
int
)
->
int
>
(
_
:
F
,
_
:
int
)
->
int
{
0
}
fn
main
()
{
fn
a
()
{
let
x
=
call_it
(
&
square
,
22
);
//~ ERROR not implemented
}
fn
b
()
{
let
y
=
call_it_mut
(
&
mut
square
,
22
);
//~ ERROR not implemented
}
fn
c
()
{
let
z
=
call_it_once
(
square
,
22
);
//~ ERROR not implemented
}
fn
main
()
{
}
src/test/compile-fail/unboxed-closures-wrong-abi.rs
浏览文件 @
f45c0ef5
...
...
@@ -20,9 +20,17 @@ fn call_it<F:Fn(&int)->int>(_: &F, _: int) -> int { 0 }
fn
call_it_mut
<
F
:
FnMut
(
&
int
)
->
int
>
(
_
:
&
mut
F
,
_
:
int
)
->
int
{
0
}
fn
call_it_once
<
F
:
FnOnce
(
&
int
)
->
int
>
(
_
:
F
,
_
:
int
)
->
int
{
0
}
fn
main
()
{
fn
a
()
{
let
x
=
call_it
(
&
square
,
22
);
//~ ERROR not implemented
}
fn
b
()
{
let
y
=
call_it_mut
(
&
mut
square
,
22
);
//~ ERROR not implemented
}
fn
c
()
{
let
z
=
call_it_once
(
square
,
22
);
//~ ERROR not implemented
}
fn
main
()
{
}
src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs
浏览文件 @
f45c0ef5
...
...
@@ -21,9 +21,16 @@ fn call_it<F:Fn(&int)->int>(_: &F, _: int) -> int { 0 }
fn
call_it_mut
<
F
:
FnMut
(
&
int
)
->
int
>
(
_
:
&
mut
F
,
_
:
int
)
->
int
{
0
}
fn
call_it_once
<
F
:
FnOnce
(
&
int
)
->
int
>
(
_
:
F
,
_
:
int
)
->
int
{
0
}
fn
main
()
{
fn
a
()
{
let
x
=
call_it
(
&
square
,
22
);
//~ ERROR not implemented
}
fn
b
()
{
let
y
=
call_it_mut
(
&
mut
square
,
22
);
//~ ERROR not implemented
}
fn
c
()
{
let
z
=
call_it_once
(
square
,
22
);
//~ ERROR not implemented
}
fn
main
()
{
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录