Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
24dcf6f7
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,发现更多精彩内容 >>
未验证
提交
24dcf6f7
编写于
11月 03, 2020
作者:
S
Santiago Pastorino
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Allow to use super trait bounds in where clauses
上级
361543d7
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
167 addition
and
23 deletion
+167
-23
compiler/rustc_middle/src/query/mod.rs
compiler/rustc_middle/src/query/mod.rs
+1
-1
compiler/rustc_middle/src/ty/query/keys.rs
compiler/rustc_middle/src/ty/query/keys.rs
+12
-1
compiler/rustc_typeck/src/astconv/mod.rs
compiler/rustc_typeck/src/astconv/mod.rs
+13
-6
compiler/rustc_typeck/src/check/fn_ctxt/mod.rs
compiler/rustc_typeck/src/check/fn_ctxt/mod.rs
+24
-4
compiler/rustc_typeck/src/collect.rs
compiler/rustc_typeck/src/collect.rs
+102
-11
src/test/ui/associated-type-bounds/super-trait-referencing.rs
...test/ui/associated-type-bounds/super-trait-referencing.rs
+15
-0
未找到文件。
compiler/rustc_middle/src/query/mod.rs
浏览文件 @
24dcf6f7
...
...
@@ -438,7 +438,7 @@ fn describe_as_module(def_id: LocalDefId, tcx: TyCtxt<'_>) -> String {
/// To avoid cycles within the predicates of a single item we compute
/// per-type-parameter predicates for resolving `T::AssocTy`.
query
type_param_predicates
(
key
:
(
DefId
,
LocalDefId
))
->
ty
::
GenericPredicates
<
'tcx
>
{
query
type_param_predicates
(
key
:
(
DefId
,
LocalDefId
,
rustc_span
::
symbol
::
Ident
))
->
ty
::
GenericPredicates
<
'tcx
>
{
desc
{
|
tcx
|
"computing the bounds for type parameter `{}`"
,
{
let
id
=
tcx
.hir
()
.local_def_id_to_hir_id
(
key
.1
);
tcx
.hir
()
.ty_param_name
(
id
)
...
...
compiler/rustc_middle/src/ty/query/keys.rs
浏览文件 @
24dcf6f7
...
...
@@ -7,7 +7,7 @@
use
crate
::
ty
::{
self
,
Ty
,
TyCtxt
};
use
rustc_hir
::
def_id
::{
CrateNum
,
DefId
,
LocalDefId
,
LOCAL_CRATE
};
use
rustc_query_system
::
query
::
DefaultCacheSelector
;
use
rustc_span
::
symbol
::
Symbol
;
use
rustc_span
::
symbol
::
{
Ident
,
Symbol
}
;
use
rustc_span
::{
Span
,
DUMMY_SP
};
/// The `Key` trait controls what types can legally be used as the key
...
...
@@ -149,6 +149,17 @@ fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
}
}
impl
Key
for
(
DefId
,
LocalDefId
,
Ident
)
{
type
CacheSelector
=
DefaultCacheSelector
;
fn
query_crate
(
&
self
)
->
CrateNum
{
self
.0
.krate
}
fn
default_span
(
&
self
,
tcx
:
TyCtxt
<
'_
>
)
->
Span
{
self
.1
.default_span
(
tcx
)
}
}
impl
Key
for
(
CrateNum
,
DefId
)
{
type
CacheSelector
=
DefaultCacheSelector
;
...
...
compiler/rustc_typeck/src/astconv/mod.rs
浏览文件 @
24dcf6f7
...
...
@@ -49,9 +49,10 @@ pub trait AstConv<'tcx> {
fn
default_constness_for_trait_bounds
(
&
self
)
->
Constness
;
/// Returns predicates in scope of the form `X: Foo`, where `X` is
/// a type parameter `X` with the given id `def_id`. This is a
/// subset of the full set of predicates.
/// Returns predicates in scope of the form `X: Foo<T>`, where `X`
/// is a type parameter `X` with the given id `def_id` and T
/// matches assoc_name. This is a subset of the full set of
/// predicates.
///
/// This is used for one specific purpose: resolving "short-hand"
/// associated type references like `T::Item`. In principle, we
...
...
@@ -60,7 +61,12 @@ pub trait AstConv<'tcx> {
/// but this can lead to cycle errors. The problem is that we have
/// to do this resolution *in order to create the predicates in
/// the first place*. Hence, we have this "special pass".
fn
get_type_parameter_bounds
(
&
self
,
span
:
Span
,
def_id
:
DefId
)
->
ty
::
GenericPredicates
<
'tcx
>
;
fn
get_type_parameter_bounds
(
&
self
,
span
:
Span
,
def_id
:
DefId
,
assoc_name
:
Ident
,
)
->
ty
::
GenericPredicates
<
'tcx
>
;
/// Returns the lifetime to use when a lifetime is omitted (and not elided).
fn
re_infer
(
&
self
,
param
:
Option
<&
ty
::
GenericParamDef
>
,
span
:
Span
)
...
...
@@ -1361,8 +1367,9 @@ fn find_bound_for_assoc_item(
ty_param_def_id
,
assoc_name
,
span
,
);
let
predicates
=
&
self
.get_type_parameter_bounds
(
span
,
ty_param_def_id
.to_def_id
())
.predicates
;
let
predicates
=
&
self
.get_type_parameter_bounds
(
span
,
ty_param_def_id
.to_def_id
(),
assoc_name
)
.predicates
;
debug!
(
"find_bound_for_assoc_item: predicates={:#?}"
,
predicates
);
...
...
compiler/rustc_typeck/src/check/fn_ctxt/mod.rs
浏览文件 @
24dcf6f7
...
...
@@ -20,6 +20,7 @@
use
rustc_middle
::
ty
::
subst
::
GenericArgKind
;
use
rustc_middle
::
ty
::{
self
,
Const
,
Ty
,
TyCtxt
};
use
rustc_session
::
Session
;
use
rustc_span
::
symbol
::
Ident
;
use
rustc_span
::{
self
,
Span
};
use
rustc_trait_selection
::
traits
::{
ObligationCause
,
ObligationCauseCode
};
...
...
@@ -183,7 +184,12 @@ fn default_constness_for_trait_bounds(&self) -> hir::Constness {
}
}
fn
get_type_parameter_bounds
(
&
self
,
_
:
Span
,
def_id
:
DefId
)
->
ty
::
GenericPredicates
<
'tcx
>
{
fn
get_type_parameter_bounds
(
&
self
,
_
:
Span
,
def_id
:
DefId
,
assoc_name
:
Ident
,
)
->
ty
::
GenericPredicates
<
'tcx
>
{
let
tcx
=
self
.tcx
;
let
hir_id
=
tcx
.hir
()
.local_def_id_to_hir_id
(
def_id
.expect_local
());
let
item_id
=
tcx
.hir
()
.ty_param_owner
(
hir_id
);
...
...
@@ -196,9 +202,23 @@ fn get_type_parameter_bounds(&self, _: Span, def_id: DefId) -> ty::GenericPredic
self
.param_env
.caller_bounds
()
.iter
()
.filter_map
(|
predicate
|
{
match
predicate
.skip_binders
()
{
ty
::
PredicateAtom
::
Trait
(
data
,
_
)
if
data
.self_ty
()
.is_param
(
index
)
=>
{
// HACK(eddyb) should get the original `Span`.
let
span
=
tcx
.def_span
(
def_id
);
Some
((
predicate
,
span
))
let
trait_did
=
data
.def_id
();
if
tcx
.associated_items
(
trait_did
)
.find_by_name_and_kind
(
tcx
,
assoc_name
,
ty
::
AssocKind
::
Type
,
trait_did
,
)
.is_some
()
{
// HACK(eddyb) should get the original `Span`.
let
span
=
tcx
.def_span
(
def_id
);
Some
((
predicate
,
span
))
}
else
{
None
}
}
_
=>
None
,
}
...
...
compiler/rustc_typeck/src/collect.rs
浏览文件 @
24dcf6f7
...
...
@@ -310,8 +310,17 @@ fn default_constness_for_trait_bounds(&self) -> hir::Constness {
}
}
fn
get_type_parameter_bounds
(
&
self
,
span
:
Span
,
def_id
:
DefId
)
->
ty
::
GenericPredicates
<
'tcx
>
{
self
.tcx
.at
(
span
)
.type_param_predicates
((
self
.item_def_id
,
def_id
.expect_local
()))
fn
get_type_parameter_bounds
(
&
self
,
span
:
Span
,
def_id
:
DefId
,
assoc_name
:
Ident
,
)
->
ty
::
GenericPredicates
<
'tcx
>
{
self
.tcx
.at
(
span
)
.type_param_predicates
((
self
.item_def_id
,
def_id
.expect_local
(),
assoc_name
,
))
}
fn
re_infer
(
&
self
,
_
:
Option
<&
ty
::
GenericParamDef
>
,
_
:
Span
)
->
Option
<
ty
::
Region
<
'tcx
>>
{
...
...
@@ -492,7 +501,7 @@ fn get_new_lifetime_name<'tcx>(
/// `X: Foo` where `X` is the type parameter `def_id`.
fn
type_param_predicates
(
tcx
:
TyCtxt
<
'_
>
,
(
item_def_id
,
def_id
):
(
DefId
,
LocalDefId
),
(
item_def_id
,
def_id
,
assoc_name
):
(
DefId
,
LocalDefId
,
Ident
),
)
->
ty
::
GenericPredicates
<
'_
>
{
use
rustc_hir
::
*
;
...
...
@@ -517,7 +526,7 @@ fn type_param_predicates(
let
mut
result
=
parent
.map
(|
parent
|
{
let
icx
=
ItemCtxt
::
new
(
tcx
,
parent
);
icx
.get_type_parameter_bounds
(
DUMMY_SP
,
def_id
.to_def_id
())
icx
.get_type_parameter_bounds
(
DUMMY_SP
,
def_id
.to_def_id
()
,
assoc_name
)
})
.unwrap_or_default
();
let
mut
extend
=
None
;
...
...
@@ -560,12 +569,18 @@ fn type_param_predicates(
let
icx
=
ItemCtxt
::
new
(
tcx
,
item_def_id
);
let
extra_predicates
=
extend
.into_iter
()
.chain
(
icx
.type_parameter_bounds_in_generics
(
ast_generics
,
param_id
,
ty
,
OnlySelfBounds
(
true
))
.into_iter
()
.filter
(|(
predicate
,
_
)|
match
predicate
.skip_binders
()
{
ty
::
PredicateAtom
::
Trait
(
data
,
_
)
=>
data
.self_ty
()
.is_param
(
index
),
_
=>
false
,
}),
icx
.type_parameter_bounds_in_generics
(
ast_generics
,
param_id
,
ty
,
OnlySelfBounds
(
true
),
Some
(
assoc_name
),
)
.into_iter
()
.filter
(|(
predicate
,
_
)|
match
predicate
.skip_binders
()
{
ty
::
PredicateAtom
::
Trait
(
data
,
_
)
=>
data
.self_ty
()
.is_param
(
index
),
_
=>
false
,
}),
);
result
.predicates
=
tcx
.arena
.alloc_from_iter
(
result
.predicates
.iter
()
.copied
()
.chain
(
extra_predicates
));
...
...
@@ -583,6 +598,7 @@ fn type_parameter_bounds_in_generics(
param_id
:
hir
::
HirId
,
ty
:
Ty
<
'tcx
>
,
only_self_bounds
:
OnlySelfBounds
,
assoc_name
:
Option
<
Ident
>
,
)
->
Vec
<
(
ty
::
Predicate
<
'tcx
>
,
Span
)
>
{
let
constness
=
self
.default_constness_for_trait_bounds
();
let
from_ty_params
=
ast_generics
...
...
@@ -593,6 +609,10 @@ fn type_parameter_bounds_in_generics(
_
=>
None
,
})
.flat_map
(|
bounds
|
bounds
.iter
())
.filter
(|
b
|
match
assoc_name
{
Some
(
assoc_name
)
=>
self
.bound_defines_assoc_item
(
b
,
assoc_name
),
None
=>
true
,
})
.flat_map
(|
b
|
predicates_from_bound
(
self
,
ty
,
b
,
constness
));
let
from_where_clauses
=
ast_generics
...
...
@@ -611,12 +631,43 @@ fn type_parameter_bounds_in_generics(
}
else
{
None
};
bp
.bounds
.iter
()
.filter_map
(
move
|
b
|
bt
.map
(|
bt
|
(
bt
,
b
)))
bp
.bounds
.iter
()
.filter
(|
b
|
match
assoc_name
{
Some
(
assoc_name
)
=>
self
.bound_defines_assoc_item
(
b
,
assoc_name
),
None
=>
true
,
})
.filter_map
(
move
|
b
|
bt
.map
(|
bt
|
(
bt
,
b
)))
})
.flat_map
(|(
bt
,
b
)|
predicates_from_bound
(
self
,
bt
,
b
,
constness
));
from_ty_params
.chain
(
from_where_clauses
)
.collect
()
}
fn
bound_defines_assoc_item
(
&
self
,
b
:
&
hir
::
GenericBound
<
'_
>
,
assoc_name
:
Ident
)
->
bool
{
debug!
(
"bound_defines_assoc_item(b={:?}, assoc_name={:?})"
,
b
,
assoc_name
);
match
b
{
hir
::
GenericBound
::
Trait
(
poly_trait_ref
,
_
)
=>
{
let
trait_ref
=
&
poly_trait_ref
.trait_ref
;
let
trait_did
=
trait_ref
.trait_def_id
()
.unwrap
();
let
traits_did
=
super_traits_of
(
self
.tcx
,
trait_did
);
traits_did
.iter
()
.any
(|
trait_did
|
{
self
.tcx
.associated_items
(
*
trait_did
)
.find_by_name_and_kind
(
self
.tcx
,
assoc_name
,
ty
::
AssocKind
::
Type
,
*
trait_did
,
)
.is_some
()
})
}
_
=>
false
,
}
}
}
/// Tests whether this is the AST for a reference to the type
...
...
@@ -1017,6 +1068,7 @@ fn super_predicates_of(tcx: TyCtxt<'_>, trait_def_id: DefId) -> ty::GenericPredi
item
.hir_id
,
self_param_ty
,
OnlySelfBounds
(
!
is_trait_alias
),
None
,
);
// Combine the two lists to form the complete set of superbounds:
...
...
@@ -1034,6 +1086,45 @@ fn super_predicates_of(tcx: TyCtxt<'_>, trait_def_id: DefId) -> ty::GenericPredi
ty
::
GenericPredicates
{
parent
:
None
,
predicates
:
superbounds
}
}
pub
fn
super_traits_of
(
tcx
:
TyCtxt
<
'_
>
,
trait_def_id
:
DefId
)
->
impl
Iterator
<
Item
=
DefId
>
{
let
mut
set
=
FxHashSet
::
default
();
let
mut
stack
=
vec!
[
trait_def_id
];
while
let
Some
(
trait_did
)
=
stack
.pop
()
{
if
!
set
.insert
(
trait_did
)
{
continue
;
}
if
trait_did
.is_local
()
{
let
trait_hir_id
=
tcx
.hir
()
.local_def_id_to_hir_id
(
trait_did
.expect_local
());
let
item
=
match
tcx
.hir
()
.get
(
trait_hir_id
)
{
Node
::
Item
(
item
)
=>
item
,
_
=>
bug!
(
"super_trait_of {} is not an item"
,
trait_hir_id
),
};
let
supertraits
=
match
item
.kind
{
hir
::
ItemKind
::
Trait
(
..
,
ref
supertraits
,
_
)
=>
supertraits
,
hir
::
ItemKind
::
TraitAlias
(
_
,
ref
supertraits
)
=>
supertraits
,
_
=>
span_bug!
(
item
.span
,
"super_trait_of invoked on non-trait"
),
};
for
supertrait
in
supertraits
.iter
()
{
let
trait_ref
=
supertrait
.trait_ref
();
if
let
Some
(
trait_did
)
=
trait_ref
.and_then
(|
trait_ref
|
trait_ref
.trait_def_id
())
{
stack
.push
(
trait_did
);
}
}
}
else
{
let
generic_predicates
=
tcx
.super_predicates_of
(
trait_did
);
for
(
predicate
,
_
)
in
generic_predicates
.predicates
{
if
let
ty
::
PredicateAtom
::
Trait
(
data
,
_
)
=
predicate
.skip_binders
()
{
stack
.push
(
data
.def_id
());
}
}
}
}
}
fn
trait_def
(
tcx
:
TyCtxt
<
'_
>
,
def_id
:
DefId
)
->
ty
::
TraitDef
{
let
hir_id
=
tcx
.hir
()
.local_def_id_to_hir_id
(
def_id
.expect_local
());
let
item
=
tcx
.hir
()
.expect_item
(
hir_id
);
...
...
src/test/ui/associated-type-bounds/super-trait-referencing.rs
0 → 100644
浏览文件 @
24dcf6f7
// check-pass
trait
Foo
{
type
Item
;
}
trait
Bar
<
T
>
{}
fn
baz
<
T
>
()
where
T
:
Foo
,
T
:
Bar
<
T
::
Item
>
,
{
}
fn
main
()
{}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录