Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
c5befdc6
R
Rust
项目概览
int
/
Rust
11 个月 前同步成功
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
Rust
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
c5befdc6
编写于
1月 24, 2017
作者:
E
Eduard-Mihai Burtescu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
rustc: always keep an explicit lifetime in trait objects.
上级
41553d6f
变更
13
隐藏空白更改
内联
并排
Showing
13 changed file
with
137 addition
and
166 deletion
+137
-166
src/librustc/hir/intravisit.rs
src/librustc/hir/intravisit.rs
+8
-5
src/librustc/hir/lowering.rs
src/librustc/hir/lowering.rs
+20
-4
src/librustc/hir/mod.rs
src/librustc/hir/mod.rs
+1
-1
src/librustc/hir/print.rs
src/librustc/hir/print.rs
+15
-2
src/librustc/middle/resolve_lifetime.rs
src/librustc/middle/resolve_lifetime.rs
+10
-2
src/librustc_incremental/calculate_svh/svh_visitor.rs
src/librustc_incremental/calculate_svh/svh_visitor.rs
+1
-1
src/librustc_passes/ast_validation.rs
src/librustc_passes/ast_validation.rs
+11
-0
src/librustc_passes/diagnostics.rs
src/librustc_passes/diagnostics.rs
+1
-0
src/librustc_typeck/astconv.rs
src/librustc_typeck/astconv.rs
+38
-129
src/librustc_typeck/collect.rs
src/librustc_typeck/collect.rs
+14
-5
src/librustc_typeck/diagnostics.rs
src/librustc_typeck/diagnostics.rs
+0
-1
src/librustdoc/clean/mod.rs
src/librustdoc/clean/mod.rs
+14
-14
src/test/compile-fail/region-bounds-on-objects-and-type-parameters.rs
...pile-fail/region-bounds-on-objects-and-type-parameters.rs
+4
-2
未找到文件。
src/librustc/hir/intravisit.rs
浏览文件 @
c5befdc6
...
...
@@ -301,7 +301,7 @@ fn visit_trait_ref(&mut self, t: &'v TraitRef) {
fn
visit_ty_param_bound
(
&
mut
self
,
bounds
:
&
'v
TyParamBound
)
{
walk_ty_param_bound
(
self
,
bounds
)
}
fn
visit_poly_trait_ref
(
&
mut
self
,
t
:
&
'v
PolyTraitRef
,
m
:
&
'v
TraitBoundModifier
)
{
fn
visit_poly_trait_ref
(
&
mut
self
,
t
:
&
'v
PolyTraitRef
,
m
:
TraitBoundModifier
)
{
walk_poly_trait_ref
(
self
,
t
,
m
)
}
fn
visit_variant_data
(
&
mut
self
,
...
...
@@ -421,7 +421,7 @@ pub fn walk_lifetime_def<'v, V: Visitor<'v>>(visitor: &mut V, lifetime_def: &'v
pub
fn
walk_poly_trait_ref
<
'v
,
V
>
(
visitor
:
&
mut
V
,
trait_ref
:
&
'v
PolyTraitRef
,
_
modifier
:
&
'v
TraitBoundModifier
)
_
modifier
:
TraitBoundModifier
)
where
V
:
Visitor
<
'v
>
{
walk_list!
(
visitor
,
visit_lifetime_def
,
&
trait_ref
.bound_lifetimes
);
...
...
@@ -566,8 +566,11 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
visitor
.visit_ty
(
ty
);
visitor
.visit_nested_body
(
length
)
}
TyTraitObject
(
ref
bounds
)
=>
{
walk_list!
(
visitor
,
visit_ty_param_bound
,
bounds
);
TyTraitObject
(
ref
bounds
,
ref
lifetime
)
=>
{
for
bound
in
bounds
{
visitor
.visit_poly_trait_ref
(
bound
,
TraitBoundModifier
::
None
);
}
visitor
.visit_lifetime
(
lifetime
);
}
TyImplTrait
(
ref
bounds
)
=>
{
walk_list!
(
visitor
,
visit_ty_param_bound
,
bounds
);
...
...
@@ -695,7 +698,7 @@ pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v
pub
fn
walk_ty_param_bound
<
'v
,
V
:
Visitor
<
'v
>>
(
visitor
:
&
mut
V
,
bound
:
&
'v
TyParamBound
)
{
match
*
bound
{
TraitTyParamBound
(
ref
typ
,
ref
modifier
)
=>
{
TraitTyParamBound
(
ref
typ
,
modifier
)
=>
{
visitor
.visit_poly_trait_ref
(
typ
,
modifier
);
}
RegionTyParamBound
(
ref
lifetime
)
=>
{
...
...
src/librustc/hir/lowering.rs
浏览文件 @
c5befdc6
...
...
@@ -360,7 +360,23 @@ fn lower_ty(&mut self, t: &Ty) -> P<hir::Ty> {
hir
::
TyTypeof
(
self
.record_body
(
expr
,
None
))
}
TyKind
::
TraitObject
(
ref
bounds
)
=>
{
hir
::
TyTraitObject
(
self
.lower_bounds
(
bounds
))
let
mut
lifetime_bound
=
None
;
let
bounds
=
bounds
.iter
()
.filter_map
(|
bound
|
{
match
*
bound
{
TraitTyParamBound
(
ref
ty
,
TraitBoundModifier
::
None
)
=>
{
Some
(
self
.lower_poly_trait_ref
(
ty
))
}
TraitTyParamBound
(
_
,
TraitBoundModifier
::
Maybe
)
=>
None
,
RegionTyParamBound
(
ref
lifetime
)
=>
{
lifetime_bound
=
Some
(
self
.lower_lifetime
(
lifetime
));
None
}
}
})
.collect
();
let
lifetime_bound
=
lifetime_bound
.unwrap_or_else
(||
{
self
.elided_lifetime
(
t
.span
)
});
hir
::
TyTraitObject
(
bounds
,
lifetime_bound
)
}
TyKind
::
ImplTrait
(
ref
bounds
)
=>
{
hir
::
TyImplTrait
(
self
.lower_bounds
(
bounds
))
...
...
@@ -2361,20 +2377,20 @@ fn ty_path(&mut self, id: NodeId, span: Span, qpath: hir::QPath) -> P<hir::Ty> {
hir
::
QPath
::
Resolved
(
None
,
path
)
=>
{
// Turn trait object paths into `TyTraitObject` instead.
if
let
Def
::
Trait
(
_
)
=
path
.def
{
let
principal
=
hir
::
TraitTyParamBound
(
hir
::
PolyTraitRef
{
let
principal
=
hir
::
PolyTraitRef
{
bound_lifetimes
:
hir_vec!
[],
trait_ref
:
hir
::
TraitRef
{
path
:
path
.and_then
(|
path
|
path
),
ref_id
:
id
,
},
span
,
}
,
hir
::
TraitBoundModifier
::
None
)
;
};
// The original ID is taken by the `PolyTraitRef`,
// so the `Ty` itself needs a different one.
id
=
self
.next_id
();
hir
::
TyTraitObject
(
hir_vec!
[
principal
])
hir
::
TyTraitObject
(
hir_vec!
[
principal
]
,
self
.elided_lifetime
(
span
)
)
}
else
{
hir
::
TyPath
(
hir
::
QPath
::
Resolved
(
None
,
path
))
}
...
...
src/librustc/hir/mod.rs
浏览文件 @
c5befdc6
...
...
@@ -1205,7 +1205,7 @@ pub enum Ty_ {
TyPath
(
QPath
),
/// A trait object type `Bound1 + Bound2 + Bound3`
/// where `Bound` is a trait or a lifetime.
TyTraitObject
(
TyParamBounds
),
TyTraitObject
(
HirVec
<
PolyTraitRef
>
,
Lifetime
),
/// An `impl Bound1 + Bound2 + Bound3` type
/// where `Bound` is a trait or a lifetime.
TyImplTrait
(
TyParamBounds
),
...
...
src/librustc/hir/print.rs
浏览文件 @
c5befdc6
...
...
@@ -416,8 +416,21 @@ pub fn print_type(&mut self, ty: &hir::Ty) -> io::Result<()> {
hir
::
TyPath
(
ref
qpath
)
=>
{
self
.print_qpath
(
qpath
,
false
)
?
}
hir
::
TyTraitObject
(
ref
bounds
)
=>
{
self
.print_bounds
(
""
,
&
bounds
[
..
])
?
;
hir
::
TyTraitObject
(
ref
bounds
,
ref
lifetime
)
=>
{
let
mut
first
=
true
;
for
bound
in
bounds
{
self
.nbsp
()
?
;
if
first
{
first
=
false
;
}
else
{
self
.word_space
(
"+"
)
?
;
}
self
.print_poly_trait_ref
(
bound
)
?
;
}
if
!
lifetime
.is_elided
()
{
self
.word_space
(
"+"
)
?
;
self
.print_lifetime
(
lifetime
)
?
;
}
}
hir
::
TyImplTrait
(
ref
bounds
)
=>
{
self
.print_bounds
(
"impl "
,
&
bounds
[
..
])
?
;
...
...
src/librustc/middle/resolve_lifetime.rs
浏览文件 @
c5befdc6
...
...
@@ -322,6 +322,14 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
intravisit
::
walk_ty
(
this
,
ty
);
});
}
hir
::
TyTraitObject
(
ref
bounds
,
ref
lifetime
)
=>
{
for
bound
in
bounds
{
self
.visit_poly_trait_ref
(
bound
,
hir
::
TraitBoundModifier
::
None
);
}
if
!
lifetime
.is_elided
()
{
self
.visit_lifetime
(
lifetime
);
}
}
_
=>
{
intravisit
::
walk_ty
(
self
,
ty
)
}
...
...
@@ -441,7 +449,7 @@ fn visit_generics(&mut self, generics: &'tcx hir::Generics) {
fn
visit_poly_trait_ref
(
&
mut
self
,
trait_ref
:
&
'tcx
hir
::
PolyTraitRef
,
_
modifier
:
&
'tcx
hir
::
TraitBoundModifier
)
{
_
modifier
:
hir
::
TraitBoundModifier
)
{
debug!
(
"visit_poly_trait_ref trait_ref={:?}"
,
trait_ref
);
if
!
self
.trait_ref_hack
||
!
trait_ref
.bound_lifetimes
.is_empty
()
{
...
...
@@ -962,7 +970,7 @@ fn visit_ty(&mut self, ty: &hir::Ty) {
fn
visit_poly_trait_ref
(
&
mut
self
,
trait_ref
:
&
hir
::
PolyTraitRef
,
modifier
:
&
hir
::
TraitBoundModifier
)
{
modifier
:
hir
::
TraitBoundModifier
)
{
self
.binder_depth
+=
1
;
intravisit
::
walk_poly_trait_ref
(
self
,
trait_ref
,
modifier
);
self
.binder_depth
-=
1
;
...
...
src/librustc_incremental/calculate_svh/svh_visitor.rs
浏览文件 @
c5befdc6
...
...
@@ -828,7 +828,7 @@ fn visit_ty_param_bound(&mut self, bounds: &'tcx TyParamBound) {
visit
::
walk_ty_param_bound
(
self
,
bounds
)
}
fn
visit_poly_trait_ref
(
&
mut
self
,
t
:
&
'tcx
PolyTraitRef
,
m
:
&
'tcx
TraitBoundModifier
)
{
fn
visit_poly_trait_ref
(
&
mut
self
,
t
:
&
'tcx
PolyTraitRef
,
m
:
TraitBoundModifier
)
{
debug!
(
"visit_poly_trait_ref: st={:?}"
,
self
.st
);
SawPolyTraitRef
.hash
(
self
.st
);
m
.hash
(
self
.st
);
...
...
src/librustc_passes/ast_validation.rs
浏览文件 @
c5befdc6
...
...
@@ -144,6 +144,17 @@ fn visit_ty(&mut self, ty: &'a Ty) {
});
}
TyKind
::
TraitObject
(
ref
bounds
)
=>
{
let
mut
any_lifetime_bounds
=
false
;
for
bound
in
bounds
{
if
let
RegionTyParamBound
(
ref
lifetime
)
=
*
bound
{
if
any_lifetime_bounds
{
span_err!
(
self
.session
,
lifetime
.span
,
E0226
,
"only a single explicit lifetime bound is permitted"
);
break
;
}
any_lifetime_bounds
=
true
;
}
}
self
.no_questions_in_bounds
(
bounds
,
"trait object types"
,
false
);
}
TyKind
::
ImplTrait
(
ref
bounds
)
=>
{
...
...
src/librustc_passes/diagnostics.rs
浏览文件 @
c5befdc6
...
...
@@ -244,6 +244,7 @@ pub fn foo() {}
}
register_diagnostics!
{
E0226
,
// only a single explicit lifetime bound is permitted
E0472
,
// asm! is unsupported on this target
E0561
,
// patterns aren't allowed in function pointer types
E0571
,
// `break` with a value in a non-`loop`-loop
...
...
src/librustc_typeck/astconv.rs
浏览文件 @
c5befdc6
...
...
@@ -453,24 +453,6 @@ fn convert_parenthesized_parameters(&self,
(
self
.tcx
()
.mk_ty
(
ty
::
TyTuple
(
inputs
)),
output_binding
)
}
pub
fn
instantiate_poly_trait_ref
(
&
self
,
rscope
:
&
RegionScope
,
ast_trait_ref
:
&
hir
::
PolyTraitRef
,
self_ty
:
Ty
<
'tcx
>
,
poly_projections
:
&
mut
Vec
<
ty
::
PolyProjectionPredicate
<
'tcx
>>
)
->
ty
::
PolyTraitRef
<
'tcx
>
{
let
trait_ref
=
&
ast_trait_ref
.trait_ref
;
let
trait_def_id
=
self
.trait_def_id
(
trait_ref
);
self
.ast_path_to_poly_trait_ref
(
rscope
,
trait_ref
.path.span
,
trait_def_id
,
self_ty
,
trait_ref
.ref_id
,
trait_ref
.path.segments
.last
()
.unwrap
(),
poly_projections
)
}
/// Instantiates the path for the given trait reference, assuming that it's
/// bound to a valid trait type. Returns the def_id for the defining trait.
/// Fails if the type is a type other than a trait type.
...
...
@@ -505,17 +487,17 @@ fn trait_def_id(&self, trait_ref: &hir::TraitRef) -> DefId {
}
}
fn
ast_path_to
_poly_trait_ref
(
&
self
,
pub
fn
instantiate
_poly_trait_ref
(
&
self
,
rscope
:
&
RegionScope
,
span
:
Span
,
trait_def_id
:
DefId
,
ast_trait_ref
:
&
hir
::
PolyTraitRef
,
self_ty
:
Ty
<
'tcx
>
,
path_id
:
ast
::
NodeId
,
trait_segment
:
&
hir
::
PathSegment
,
poly_projections
:
&
mut
Vec
<
ty
::
PolyProjectionPredicate
<
'tcx
>>
)
->
ty
::
PolyTraitRef
<
'tcx
>
{
debug!
(
"ast_path_to_poly_trait_ref(trait_segment={:?})"
,
trait_segment
);
let
trait_ref
=
&
ast_trait_ref
.trait_ref
;
let
trait_def_id
=
self
.trait_def_id
(
trait_ref
);
debug!
(
"ast_path_to_poly_trait_ref({:?}, def_id={:?})"
,
trait_ref
,
trait_def_id
);
// The trait reference introduces a binding level here, so
// we need to shift the `rscope`. It'd be nice if we could
// do away with this rscope stuff and work this knowledge
...
...
@@ -525,23 +507,23 @@ fn ast_path_to_poly_trait_ref(&self,
let
(
substs
,
assoc_bindings
)
=
self
.create_substs_for_ast_trait_ref
(
shifted_rscope
,
span
,
trait_ref
.path.
span
,
trait_def_id
,
self_ty
,
trait_
segment
);
trait_
ref
.path.segments
.last
()
.unwrap
()
);
let
poly_trait_ref
=
ty
::
Binder
(
ty
::
TraitRef
::
new
(
trait_def_id
,
substs
));
poly_projections
.extend
(
assoc_bindings
.iter
()
.filter_map
(|
binding
|
{
// specify type to assert that error was already reported in Err case:
let
predicate
:
Result
<
_
,
ErrorReported
>
=
self
.ast_type_binding_to_poly_projection_predicate
(
path
_id
,
self
.ast_type_binding_to_poly_projection_predicate
(
trait_ref
.ref
_id
,
poly_trait_ref
,
binding
);
predicate
.ok
()
// ok to ignore Err() because ErrorReported (see above)
}));
debug!
(
"ast_path_to_poly_trait_ref(
trait_segment=
{:?}, projections={:?}) -> {:?}"
,
trait_
segment
,
poly_projections
,
poly_trait_ref
);
debug!
(
"ast_path_to_poly_trait_ref({:?}, projections={:?}) -> {:?}"
,
trait_
ref
,
poly_projections
,
poly_trait_ref
);
poly_trait_ref
}
...
...
@@ -754,32 +736,29 @@ fn trait_ref_to_existential(&self, trait_ref: ty::TraitRef<'tcx>)
ty
::
ExistentialTraitRef
::
erase_self_ty
(
self
.tcx
(),
trait_ref
)
}
fn
trait_path_to_object_type
(
&
self
,
rscope
:
&
RegionScope
,
path_span
:
Span
,
trait_def_id
:
DefId
,
trait_path_ref_id
:
ast
::
NodeId
,
trait_segment
:
&
hir
::
PathSegment
,
span
:
Span
,
partitioned_bounds
:
PartitionedBounds
)
->
Ty
<
'tcx
>
{
fn
conv_object_ty_poly_trait_ref
(
&
self
,
rscope
:
&
RegionScope
,
span
:
Span
,
trait_bounds
:
&
[
hir
::
PolyTraitRef
],
lifetime
:
&
hir
::
Lifetime
)
->
Ty
<
'tcx
>
{
let
tcx
=
self
.tcx
();
if
trait_bounds
.is_empty
()
{
span_err!
(
tcx
.sess
,
span
,
E0224
,
"at least one non-builtin trait is required for an object type"
);
return
tcx
.types.err
;
}
let
mut
projection_bounds
=
vec!
[];
let
dummy_self
=
tcx
.mk_ty
(
TRAIT_OBJECT_DUMMY_SELF
);
let
principal
=
self
.ast_path_to_poly_trait_ref
(
rscope
,
path_span
,
trait_def_id
,
let
principal
=
self
.instantiate_poly_trait_ref
(
rscope
,
&
trait_bounds
[
0
],
dummy_self
,
trait_path_ref_id
,
trait_segment
,
&
mut
projection_bounds
);
let
PartitionedBounds
{
trait_bounds
,
region_bounds
}
=
partitioned_bounds
;
let
(
auto_traits
,
trait_bounds
)
=
split_auto_traits
(
tcx
,
trait_bounds
);
let
(
auto_traits
,
trait_bounds
)
=
split_auto_traits
(
tcx
,
&
trait_bounds
[
1
..
]);
if
!
trait_bounds
.is_empty
()
{
let
b
=
&
trait_bounds
[
0
];
...
...
@@ -854,13 +833,12 @@ fn trait_path_to_object_type(&self,
v
.sort_by
(|
a
,
b
|
a
.cmp
(
tcx
,
b
));
let
existential_predicates
=
ty
::
Binder
(
tcx
.mk_existential_predicates
(
v
.into_iter
()));
let
region_bound
=
self
.compute_object_lifetime_bound
(
span
,
&
region_bounds
,
existential_predicates
);
let
region_bound
=
match
region_bound
{
Some
(
r
)
=>
r
,
None
=>
{
// Explicitly specified region bound. Use that.
let
region_bound
=
if
!
lifetime
.is_elided
()
{
self
.ast_region_to_region
(
lifetime
,
None
)
}
else
{
self
.compute_object_lifetime_bound
(
span
,
existential_predicates
)
.unwrap_or_else
(||
{
tcx
.mk_region
(
match
rscope
.object_lifetime_default
(
span
)
{
Some
(
r
)
=>
r
,
None
=>
{
...
...
@@ -870,7 +848,7 @@ fn trait_path_to_object_type(&self,
ty
::
ReStatic
}
})
}
}
)
};
debug!
(
"region_bound: {:?}"
,
region_bound
);
...
...
@@ -1330,8 +1308,8 @@ pub fn ast_ty_to_ty(&self, rscope: &RegionScope, ast_ty: &hir::Ty) -> Ty<'tcx> {
}
tcx
.mk_fn_ptr
(
bare_fn_ty
)
}
hir
::
TyTraitObject
(
ref
bounds
)
=>
{
self
.conv_object_ty_poly_trait_ref
(
rscope
,
ast_ty
.span
,
bounds
)
hir
::
TyTraitObject
(
ref
bounds
,
ref
lifetime
)
=>
{
self
.conv_object_ty_poly_trait_ref
(
rscope
,
ast_ty
.span
,
bounds
,
lifetime
)
}
hir
::
TyImplTrait
(
ref
bounds
)
=>
{
use
collect
::{
compute_bounds
,
SizedByDefault
};
...
...
@@ -1537,33 +1515,6 @@ pub fn ty_of_closure(&self,
}
}
fn
conv_object_ty_poly_trait_ref
(
&
self
,
rscope
:
&
RegionScope
,
span
:
Span
,
ast_bounds
:
&
[
hir
::
TyParamBound
])
->
Ty
<
'tcx
>
{
let
mut
partitioned_bounds
=
partition_bounds
(
ast_bounds
);
let
trait_bound
=
if
!
partitioned_bounds
.trait_bounds
.is_empty
()
{
partitioned_bounds
.trait_bounds
.remove
(
0
)
}
else
{
span_err!
(
self
.tcx
()
.sess
,
span
,
E0224
,
"at least one non-builtin trait is required for an object type"
);
return
self
.tcx
()
.types.err
;
};
let
trait_ref
=
&
trait_bound
.trait_ref
;
let
trait_def_id
=
self
.trait_def_id
(
trait_ref
);
self
.trait_path_to_object_type
(
rscope
,
trait_ref
.path.span
,
trait_def_id
,
trait_ref
.ref_id
,
trait_ref
.path.segments
.last
()
.unwrap
(),
span
,
partitioned_bounds
)
}
/// Given the bounds on an object, determines what single region bound (if any) we can
/// use to summarize this type. The basic idea is that we will use the bound the user
/// provided, if they provided one, and otherwise search the supertypes of trait bounds
...
...
@@ -1571,27 +1522,14 @@ fn conv_object_ty_poly_trait_ref(&self,
/// we return `None`.
fn
compute_object_lifetime_bound
(
&
self
,
span
:
Span
,
explicit_region_bounds
:
&
[
&
hir
::
Lifetime
],
existential_predicates
:
ty
::
Binder
<&
'tcx
ty
::
Slice
<
ty
::
ExistentialPredicate
<
'tcx
>>>
)
->
Option
<&
'tcx
ty
::
Region
>
// if None, use the default
{
let
tcx
=
self
.tcx
();
debug!
(
"compute_opt_region_bound(explicit_region_bounds={:?},
\
existential_predicates={:?})"
,
explicit_region_bounds
,
debug!
(
"compute_opt_region_bound(existential_predicates={:?})"
,
existential_predicates
);
if
explicit_region_bounds
.len
()
>
1
{
span_err!
(
tcx
.sess
,
explicit_region_bounds
[
1
]
.span
,
E0226
,
"only a single explicit lifetime bound is permitted"
);
}
if
let
Some
(
&
r
)
=
explicit_region_bounds
.get
(
0
)
{
// Explicitly specified region bound. Use that.
return
Some
(
self
.ast_region_to_region
(
r
,
None
));
}
if
let
Some
(
principal
)
=
existential_predicates
.principal
()
{
if
let
Err
(
ErrorReported
)
=
self
.ensure_super_predicates
(
span
,
principal
.def_id
())
{
return
Some
(
tcx
.mk_region
(
ty
::
ReStatic
));
...
...
@@ -1627,18 +1565,13 @@ fn compute_object_lifetime_bound(&self,
}
}
pub
struct
PartitionedBounds
<
'a
>
{
pub
trait_bounds
:
Vec
<&
'a
hir
::
PolyTraitRef
>
,
pub
region_bounds
:
Vec
<&
'a
hir
::
Lifetime
>
,
}
/// Divides a list of general trait bounds into two groups: builtin bounds (Sync/Send) and the
/// remaining general trait bounds.
fn
split_auto_traits
<
'a
,
'b
,
'gcx
,
'tcx
>
(
tcx
:
TyCtxt
<
'a
,
'gcx
,
'tcx
>
,
trait_bounds
:
Vec
<&
'b
hir
::
PolyTraitRef
>
)
trait_bounds
:
&
'b
[
hir
::
PolyTraitRef
]
)
->
(
Vec
<
DefId
>
,
Vec
<&
'b
hir
::
PolyTraitRef
>
)
{
let
(
auto_traits
,
trait_bounds
):
(
Vec
<
_
>
,
_
)
=
trait_bounds
.i
nto_i
ter
()
.partition
(|
bound
|
{
let
(
auto_traits
,
trait_bounds
):
(
Vec
<
_
>
,
_
)
=
trait_bounds
.iter
()
.partition
(|
bound
|
{
match
bound
.trait_ref.path.def
{
Def
::
Trait
(
trait_did
)
=>
{
// Checks whether `trait_did` refers to one of the builtin
...
...
@@ -1675,30 +1608,6 @@ fn split_auto_traits<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
(
auto_traits
,
trait_bounds
)
}
/// Divides a list of bounds from the AST into two groups: general trait bounds and region bounds
pub
fn
partition_bounds
<
'a
,
'b
,
'gcx
,
'tcx
>
(
ast_bounds
:
&
'b
[
hir
::
TyParamBound
])
->
PartitionedBounds
<
'b
>
{
let
mut
region_bounds
=
Vec
::
new
();
let
mut
trait_bounds
=
Vec
::
new
();
for
ast_bound
in
ast_bounds
{
match
*
ast_bound
{
hir
::
TraitTyParamBound
(
ref
b
,
hir
::
TraitBoundModifier
::
None
)
=>
{
trait_bounds
.push
(
b
);
}
hir
::
TraitTyParamBound
(
_
,
hir
::
TraitBoundModifier
::
Maybe
)
=>
{}
hir
::
RegionTyParamBound
(
ref
l
)
=>
{
region_bounds
.push
(
l
);
}
}
}
PartitionedBounds
{
trait_bounds
:
trait_bounds
,
region_bounds
:
region_bounds
,
}
}
fn
check_type_argument_count
(
tcx
:
TyCtxt
,
span
:
Span
,
supplied
:
usize
,
ty_param_defs
:
&
[
ty
::
TypeParameterDef
])
{
let
accepted
=
ty_param_defs
.len
();
...
...
src/librustc_typeck/collect.rs
浏览文件 @
c5befdc6
...
...
@@ -57,7 +57,7 @@
*/
use
astconv
::{
AstConv
,
Bounds
,
PartitionedBounds
,
partition_bounds
};
use
astconv
::{
AstConv
,
Bounds
};
use
lint
;
use
constrained_type_params
as
ctp
;
use
middle
::
lang_items
::
SizedTraitLangItem
;
...
...
@@ -1961,10 +1961,19 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
span
:
Span
)
->
Bounds
<
'tcx
>
{
let
PartitionedBounds
{
trait_bounds
,
region_bounds
}
=
partition_bounds
(
&
ast_bounds
);
let
mut
region_bounds
=
vec!
[];
let
mut
trait_bounds
=
vec!
[];
for
ast_bound
in
ast_bounds
{
match
*
ast_bound
{
hir
::
TraitTyParamBound
(
ref
b
,
hir
::
TraitBoundModifier
::
None
)
=>
{
trait_bounds
.push
(
b
);
}
hir
::
TraitTyParamBound
(
_
,
hir
::
TraitBoundModifier
::
Maybe
)
=>
{}
hir
::
RegionTyParamBound
(
ref
l
)
=>
{
region_bounds
.push
(
l
);
}
}
}
let
mut
projection_bounds
=
vec!
[];
...
...
src/librustc_typeck/diagnostics.rs
浏览文件 @
c5befdc6
...
...
@@ -4096,7 +4096,6 @@ fn main() {
// E0222, // Error code E0045 (variadic function must have C calling
// convention) duplicate
E0224
,
// at least one non-builtin train is required for an object type
E0226
,
// only a single explicit lifetime bound is permitted
E0227
,
// ambiguous lifetime bound, explicit lifetime bound required
E0228
,
// explicit lifetime bound required
E0231
,
// only named substitution parameters are allowed
...
...
src/librustdoc/clean/mod.rs
浏览文件 @
c5befdc6
...
...
@@ -1776,20 +1776,20 @@ fn clean(&self, cx: &DocContext) -> Type {
trait_
:
box
resolve_type
(
cx
,
trait_path
.clean
(
cx
),
self
.id
)
}
}
TyTraitObject
(
ref
bounds
)
=>
{
let
lhs_ty
=
bounds
[
0
]
.clean
(
cx
);
match
lhs_ty
{
TraitBound
(
poly_trait
,
..
)
=>
{
match
poly_trait
.trait_
{
ResolvedPath
{
path
,
typarams
:
None
,
did
,
is_generic
}
=>
{
ResolvedPath
{
path
:
path
,
typarams
:
Some
(
bounds
[
1
..
]
.clean
(
cx
)),
did
:
did
,
is_generic
:
is_generic
,
}
}
_
=>
Infer
// shouldn't happen
TyTraitObject
(
ref
bounds
,
ref
lifetime
)
=>
{
match
bounds
[
0
]
.clean
(
cx
)
.trait_
{
ResolvedPath
{
path
,
typarams
:
None
,
did
,
is_generic
}
=>
{
let
mut
bounds
:
Vec
<
_
>
=
bounds
[
1
..
]
.iter
()
.map
(|
bound
|
{
TraitBound
(
bound
.clean
(
cx
),
hir
::
TraitBoundModifier
::
None
)
})
.collect
();
if
!
lifetime
.is_elided
()
{
bounds
.push
(
RegionBound
(
lifetime
.clean
(
cx
)));
}
ResolvedPath
{
path
:
path
,
typarams
:
Some
(
bounds
),
did
:
did
,
is_generic
:
is_generic
,
}
}
_
=>
Infer
// shouldn't happen
...
...
src/test/compile-fail/region-bounds-on-objects-and-type-parameters.rs
浏览文件 @
c5befdc6
...
...
@@ -18,7 +18,7 @@ trait SomeTrait { }
// Bounds on object types:
struct
Foo
<
'a
,
'b
,
'c
>
{
struct
Foo
<
'a
,
'b
,
'c
>
{
//~ ERROR parameter `'b` is never used
// All of these are ok, because we can derive exactly one bound:
a
:
Box
<
IsStatic
>
,
b
:
Box
<
Is
<
'static
>>
,
...
...
@@ -28,7 +28,9 @@ struct Foo<'a,'b,'c> {
f
:
Box
<
SomeTrait
>
,
// OK, defaults to 'static due to RFC 599.
g
:
Box
<
SomeTrait
+
'a
>
,
z
:
Box
<
Is
<
'a
>+
'b
+
'c
>
,
//~ ERROR only a single explicit lifetime bound is permitted
z
:
Box
<
Is
<
'a
>+
'b
+
'c
>
,
//~^ ERROR only a single explicit lifetime bound is permitted
//~| ERROR lifetime bound not satisfied
}
fn
test
<
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录