Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
9beff383
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,发现更多精彩内容 >>
提交
9beff383
编写于
7月 08, 2019
作者:
S
Shotaro Yamada
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Associated type bound for inlined impl Trait doc
上级
b78367d8
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
131 addition
and
68 deletion
+131
-68
src/librustdoc/clean/mod.rs
src/librustdoc/clean/mod.rs
+70
-23
src/librustdoc/clean/simplify.rs
src/librustdoc/clean/simplify.rs
+51
-45
src/test/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs
src/test/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs
+4
-0
src/test/rustdoc/inline_cross/impl_trait.rs
src/test/rustdoc/inline_cross/impl_trait.rs
+6
-0
未找到文件。
src/librustdoc/clean/mod.rs
浏览文件 @
9beff383
...
...
@@ -1698,7 +1698,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Generics {
// Don't populate `cx.impl_trait_bounds` before `clean`ning `where` clauses,
// since `Clean for ty::Predicate` would consume them.
let
mut
impl_trait
=
FxHashMap
::
<
ImplTraitParam
,
Vec
<
_
>>
::
default
();
let
mut
impl_trait
=
FxHashMap
::
<
ImplTraitParam
,
Vec
<
GenericBound
>>
::
default
();
// Bounds in the type_params and lifetimes fields are repeated in the
// predicates field (see rustc_typeck::collect::ty_generics), so remove
...
...
@@ -1720,41 +1720,73 @@ fn clean(&self, cx: &DocContext<'_>) -> Generics {
ty
::
GenericParamDefKind
::
Const
{
..
}
=>
None
,
})
.collect
::
<
Vec
<
GenericParamDef
>>
();
// (param index, def id of trait) -> (name, type)
let
mut
impl_trait_proj
=
FxHashMap
::
<
(
u32
,
DefId
),
Vec
<
(
String
,
Type
)
>>
::
default
();
let
mut
where_predicates
=
preds
.predicates
.iter
()
.flat_map
(|(
p
,
_
)|
{
let
param_idx
=
if
let
Some
(
trait_ref
)
=
p
.to_opt_poly_trait_ref
()
{
if
let
ty
::
Param
(
param
)
=
trait_ref
.self_ty
()
.sty
{
Some
(
param
.index
)
}
else
{
None
}
}
else
if
let
Some
(
outlives
)
=
p
.to_opt_type_outlives
()
{
if
let
ty
::
Param
(
param
)
=
outlives
.skip_binder
()
.0
.sty
{
Some
(
param
.index
)
}
else
{
None
let
param_idx
=
(||
{
if
let
Some
(
trait_ref
)
=
p
.to_opt_poly_trait_ref
()
{
if
let
ty
::
Param
(
param
)
=
trait_ref
.self_ty
()
.sty
{
return
Some
(
param
.index
);
}
}
else
if
let
Some
(
outlives
)
=
p
.to_opt_type_outlives
()
{
if
let
ty
::
Param
(
param
)
=
outlives
.skip_binder
()
.0
.sty
{
return
Some
(
param
.index
);
}
}
else
if
let
ty
::
Predicate
::
Projection
(
proj
)
=
p
{
if
let
ty
::
Param
(
param
)
=
proj
.skip_binder
()
.projection_ty
.self_ty
()
.sty
{
return
Some
(
param
.index
);
}
}
}
else
{
None
};
}
)()
;
let
p
=
p
.clean
(
cx
)
?
;
if
let
Some
(
b
)
=
param_idx
.and_then
(|
i
|
impl_trait
.get_mut
(
&
i
.into
()))
{
b
.extend
(
p
.get_bounds
()
.into_iter
()
.flatten
()
.cloned
()
.filter
(|
b
|
!
b
.is_sized_bound
(
cx
))
);
return
None
;
if
let
Some
(
param_idx
)
=
param_idx
{
if
let
Some
(
b
)
=
impl_trait
.get_mut
(
&
param_idx
.into
())
{
b
.extend
(
p
.get_bounds
()
.into_iter
()
.flatten
()
.cloned
()
.filter
(|
b
|
!
b
.is_sized_bound
(
cx
))
);
let
proj
=
match
&
p
{
WherePredicate
::
EqPredicate
{
lhs
,
rhs
}
=>
Some
((
lhs
,
rhs
))
.and_then
(|(
lhs
,
rhs
)|
Some
((
lhs
.projection
()
?
,
rhs
))),
_
=>
None
,
};
if
let
Some
(((
_
,
trait_did
,
name
),
rhs
))
=
proj
{
impl_trait_proj
.entry
((
param_idx
,
trait_did
))
.or_default
()
.push
((
name
.to_string
(),
rhs
.clone
()));
}
return
None
;
}
}
Some
(
p
)
})
.collect
::
<
Vec
<
_
>>
();
for
((
param_idx
,
trait_did
),
bounds
)
in
impl_trait_proj
{
for
(
name
,
rhs
)
in
bounds
{
simplify
::
merge_bounds
(
cx
,
impl_trait
.get_mut
(
&
param_idx
.into
())
.unwrap
(),
trait_did
,
&
name
,
&
rhs
,
);
}
}
// Move `TraitPredicate`s to the front.
for
(
_
,
bounds
)
in
impl_trait
.iter_mut
()
{
bounds
.sort_by_key
(|
b
|
if
let
GenericBound
::
TraitBound
(
..
)
=
b
{
...
...
@@ -2664,6 +2696,21 @@ pub fn is_full_generic(&self) -> bool {
_
=>
false
,
}
}
pub
fn
projection
(
&
self
)
->
Option
<
(
&
Type
,
DefId
,
&
str
)
>
{
let
(
self_
,
trait_
,
name
)
=
match
self
{
QPath
{
ref
self_type
,
ref
trait_
,
ref
name
}
=>
{
(
self_type
,
trait_
,
name
)
}
_
=>
return
None
,
};
let
trait_did
=
match
**
trait_
{
ResolvedPath
{
did
,
..
}
=>
did
,
_
=>
return
None
,
};
Some
((
&
self_
,
trait_did
,
name
))
}
}
impl
GetDefId
for
Type
{
...
...
src/librustdoc/clean/simplify.rs
浏览文件 @
9beff383
...
...
@@ -53,58 +53,21 @@ pub fn where_clauses(cx: &DocContext<'_>, clauses: Vec<WP>) -> Vec<WP> {
// Look for equality predicates on associated types that can be merged into
// general bound predicates
equalities
.retain
(|
&
(
ref
lhs
,
ref
rhs
)|
{
let
(
self_
,
trait_
,
name
)
=
match
*
lhs
{
clean
::
QPath
{
ref
self_type
,
ref
trait_
,
ref
name
}
=>
{
(
self_type
,
trait_
,
name
)
}
_
=>
return
true
,
};
let
generic
=
match
**
self_
{
clean
::
Generic
(
ref
s
)
=>
s
,
_
=>
return
true
,
let
(
self_
,
trait_did
,
name
)
=
if
let
Some
(
p
)
=
lhs
.projection
()
{
p
}
else
{
return
true
;
};
let
trait_did
=
match
**
trait
_
{
clean
::
ResolvedPath
{
did
,
..
}
=>
did
,
let
generic
=
match
self
_
{
clean
::
Generic
(
s
)
=>
s
,
_
=>
return
true
,
};
let
bounds
=
match
params
.get_mut
(
generic
)
{
Some
(
bound
)
=>
bound
,
None
=>
return
true
,
};
!
bounds
.iter_mut
()
.any
(|
b
|
{
let
trait_ref
=
match
*
b
{
clean
::
GenericBound
::
TraitBound
(
ref
mut
tr
,
_
)
=>
tr
,
clean
::
GenericBound
::
Outlives
(
..
)
=>
return
false
,
};
let
(
did
,
path
)
=
match
trait_ref
.trait_
{
clean
::
ResolvedPath
{
did
,
ref
mut
path
,
..
}
=>
(
did
,
path
),
_
=>
return
false
,
};
// If this QPath's trait `trait_did` is the same as, or a supertrait
// of, the bound's trait `did` then we can keep going, otherwise
// this is just a plain old equality bound.
if
!
trait_is_same_or_supertrait
(
cx
,
did
,
trait_did
)
{
return
false
}
let
last
=
path
.segments
.last_mut
()
.expect
(
"segments were empty"
);
match
last
.args
{
PP
::
AngleBracketed
{
ref
mut
bindings
,
..
}
=>
{
bindings
.push
(
clean
::
TypeBinding
{
name
:
name
.clone
(),
kind
:
clean
::
TypeBindingKind
::
Equality
{
ty
:
rhs
.clone
(),
},
});
}
PP
::
Parenthesized
{
ref
mut
output
,
..
}
=>
{
assert
!
(
output
.is_none
());
if
*
rhs
!=
clean
::
Type
::
Tuple
(
Vec
::
new
())
{
*
output
=
Some
(
rhs
.clone
());
}
}
};
true
})
merge_bounds
(
cx
,
bounds
,
trait_did
,
name
,
rhs
)
});
// And finally, let's reassemble everything
...
...
@@ -127,6 +90,49 @@ pub fn where_clauses(cx: &DocContext<'_>, clauses: Vec<WP>) -> Vec<WP> {
clauses
}
pub
fn
merge_bounds
(
cx
:
&
clean
::
DocContext
<
'_
>
,
bounds
:
&
mut
Vec
<
clean
::
GenericBound
>
,
trait_did
:
DefId
,
name
:
&
str
,
rhs
:
&
clean
::
Type
,
)
->
bool
{
!
bounds
.iter_mut
()
.any
(|
b
|
{
let
trait_ref
=
match
*
b
{
clean
::
GenericBound
::
TraitBound
(
ref
mut
tr
,
_
)
=>
tr
,
clean
::
GenericBound
::
Outlives
(
..
)
=>
return
false
,
};
let
(
did
,
path
)
=
match
trait_ref
.trait_
{
clean
::
ResolvedPath
{
did
,
ref
mut
path
,
..
}
=>
(
did
,
path
),
_
=>
return
false
,
};
// If this QPath's trait `trait_did` is the same as, or a supertrait
// of, the bound's trait `did` then we can keep going, otherwise
// this is just a plain old equality bound.
if
!
trait_is_same_or_supertrait
(
cx
,
did
,
trait_did
)
{
return
false
}
let
last
=
path
.segments
.last_mut
()
.expect
(
"segments were empty"
);
match
last
.args
{
PP
::
AngleBracketed
{
ref
mut
bindings
,
..
}
=>
{
bindings
.push
(
clean
::
TypeBinding
{
name
:
name
.to_string
(),
kind
:
clean
::
TypeBindingKind
::
Equality
{
ty
:
rhs
.clone
(),
},
});
}
PP
::
Parenthesized
{
ref
mut
output
,
..
}
=>
{
assert
!
(
output
.is_none
());
if
*
rhs
!=
clean
::
Type
::
Tuple
(
Vec
::
new
())
{
*
output
=
Some
(
rhs
.clone
());
}
}
};
true
})
}
pub
fn
ty_params
(
mut
params
:
Vec
<
clean
::
GenericParamDef
>
)
->
Vec
<
clean
::
GenericParamDef
>
{
for
param
in
&
mut
params
{
match
param
.kind
{
...
...
src/test/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs
浏览文件 @
9beff383
use
std
::
ops
::
Deref
;
pub
fn
func
<
'a
>
(
_
x
:
impl
Clone
+
Into
<
Vec
<
u8
>>
+
'a
)
{}
pub
fn
func2
<
T
>
(
_
x
:
impl
Deref
<
Target
=
Option
<
T
>>
+
Iterator
<
Item
=
T
>
,
_
y
:
impl
Iterator
<
Item
=
u8
>
)
{}
pub
struct
Foo
;
impl
Foo
{
...
...
src/test/rustdoc/inline_cross/impl_trait.rs
浏览文件 @
9beff383
...
...
@@ -7,6 +7,12 @@
// @!has - '//pre[@class="rust fn"]' 'where'
pub
use
impl_trait_aux
::
func
;
// @has impl_trait/fn.func2.html
// @has - '//pre[@class="rust fn"]' "_x: impl Deref<Target = Option<T>> + Iterator<Item = T>,"
// @has - '//pre[@class="rust fn"]' "_y: impl Iterator<Item = u8>)"
// @!has - '//pre[@class="rust fn"]' 'where'
pub
use
impl_trait_aux
::
func2
;
// @has impl_trait/struct.Foo.html
// @has - '//code[@id="method.v"]' "pub fn method<'a>(_x: impl Clone + Into<Vec<u8>> + 'a)"
// @!has - '//code[@id="method.v"]' 'where'
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录