Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
2ca4964d
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,发现更多精彩内容 >>
未验证
提交
2ca4964d
编写于
11月 13, 2020
作者:
S
Santiago Pastorino
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Allow to self reference associated types in where clauses
上级
24dcf6f7
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
204 addition
and
63 deletion
+204
-63
compiler/rustc_infer/src/traits/util.rs
compiler/rustc_infer/src/traits/util.rs
+35
-0
compiler/rustc_middle/src/query/mod.rs
compiler/rustc_middle/src/query/mod.rs
+10
-0
compiler/rustc_middle/src/ty/query/keys.rs
compiler/rustc_middle/src/ty/query/keys.rs
+11
-0
compiler/rustc_trait_selection/src/traits/mod.rs
compiler/rustc_trait_selection/src/traits/mod.rs
+2
-1
compiler/rustc_typeck/src/astconv/mod.rs
compiler/rustc_typeck/src/astconv/mod.rs
+43
-6
compiler/rustc_typeck/src/collect.rs
compiler/rustc_typeck/src/collect.rs
+87
-54
compiler/rustc_typeck/src/collect/item_bounds.rs
compiler/rustc_typeck/src/collect/item_bounds.rs
+4
-2
src/test/ui/associated-type-bounds/super-trait-referencing-self.rs
...ui/associated-type-bounds/super-trait-referencing-self.rs
+12
-0
未找到文件。
compiler/rustc_infer/src/traits/util.rs
浏览文件 @
2ca4964d
...
...
@@ -4,6 +4,7 @@
use
rustc_data_structures
::
fx
::
FxHashSet
;
use
rustc_middle
::
ty
::
outlives
::
Component
;
use
rustc_middle
::
ty
::{
self
,
ToPredicate
,
TyCtxt
,
WithConstness
};
use
rustc_span
::
symbol
::
Ident
;
pub
fn
anonymize_predicate
<
'tcx
>
(
tcx
:
TyCtxt
<
'tcx
>
,
...
...
@@ -89,6 +90,32 @@ pub fn elaborate_trait_refs<'tcx>(
elaborate_predicates
(
tcx
,
predicates
)
}
pub
fn
elaborate_trait_refs_that_define_assoc_type
<
'tcx
>
(
tcx
:
TyCtxt
<
'tcx
>
,
trait_refs
:
impl
Iterator
<
Item
=
ty
::
PolyTraitRef
<
'tcx
>>
,
assoc_name
:
Ident
,
)
->
FxHashSet
<
ty
::
PolyTraitRef
<
'tcx
>>
{
let
mut
stack
:
Vec
<
_
>
=
trait_refs
.collect
();
let
mut
trait_refs
=
FxHashSet
::
default
();
while
let
Some
(
trait_ref
)
=
stack
.pop
()
{
if
trait_refs
.insert
(
trait_ref
)
{
let
super_predicates
=
tcx
.super_predicates_that_define_assoc_type
((
trait_ref
.def_id
(),
Some
(
assoc_name
)));
for
(
super_predicate
,
_
)
in
super_predicates
.predicates
{
let
bound_predicate
=
super_predicate
.bound_atom
();
let
subst_predicate
=
super_predicate
.subst_supertrait
(
tcx
,
&
bound_predicate
.rebind
(
trait_ref
.skip_binder
()));
if
let
Some
(
binder
)
=
subst_predicate
.to_opt_poly_trait_ref
()
{
stack
.push
(
binder
.value
);
}
}
}
}
trait_refs
}
pub
fn
elaborate_predicates
<
'tcx
>
(
tcx
:
TyCtxt
<
'tcx
>
,
predicates
:
impl
Iterator
<
Item
=
ty
::
Predicate
<
'tcx
>>
,
...
...
@@ -287,6 +314,14 @@ pub fn transitive_bounds<'tcx>(
elaborate_trait_refs
(
tcx
,
bounds
)
.filter_to_traits
()
}
pub
fn
transitive_bounds_that_define_assoc_type
<
'tcx
>
(
tcx
:
TyCtxt
<
'tcx
>
,
bounds
:
impl
Iterator
<
Item
=
ty
::
PolyTraitRef
<
'tcx
>>
,
assoc_name
:
Ident
,
)
->
FxHashSet
<
ty
::
PolyTraitRef
<
'tcx
>>
{
elaborate_trait_refs_that_define_assoc_type
(
tcx
,
bounds
,
assoc_name
)
}
///////////////////////////////////////////////////////////////////////////
// Other
///////////////////////////////////////////////////////////////////////////
...
...
compiler/rustc_middle/src/query/mod.rs
浏览文件 @
2ca4964d
...
...
@@ -436,6 +436,16 @@ fn describe_as_module(def_id: LocalDefId, tcx: TyCtxt<'_>) -> String {
desc
{
|
tcx
|
"computing the supertraits of `{}`"
,
tcx
.def_path_str
(
key
)
}
}
/// Maps from the `DefId` of a trait to the list of
/// super-predicates. This is a subset of the full list of
/// predicates. We store these in a separate map because we must
/// evaluate them even during type conversion, often before the
/// full predicates are available (note that supertraits have
/// additional acyclicity requirements).
query
super_predicates_that_define_assoc_type
(
key
:
(
DefId
,
Option
<
rustc_span
::
symbol
::
Ident
>
))
->
ty
::
GenericPredicates
<
'tcx
>
{
desc
{
|
tcx
|
"computing the supertraits of `{}`"
,
tcx
.def_path_str
(
key
.0
)
}
}
/// 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
,
rustc_span
::
symbol
::
Ident
))
->
ty
::
GenericPredicates
<
'tcx
>
{
...
...
compiler/rustc_middle/src/ty/query/keys.rs
浏览文件 @
2ca4964d
...
...
@@ -149,6 +149,17 @@ fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
}
}
impl
Key
for
(
DefId
,
Option
<
Ident
>
)
{
type
CacheSelector
=
DefaultCacheSelector
;
fn
query_crate
(
&
self
)
->
CrateNum
{
self
.0
.krate
}
fn
default_span
(
&
self
,
tcx
:
TyCtxt
<
'_
>
)
->
Span
{
tcx
.def_span
(
self
.0
)
}
}
impl
Key
for
(
DefId
,
LocalDefId
,
Ident
)
{
type
CacheSelector
=
DefaultCacheSelector
;
...
...
compiler/rustc_trait_selection/src/traits/mod.rs
浏览文件 @
2ca4964d
...
...
@@ -65,7 +65,8 @@
get_vtable_index_of_object_method
,
impl_item_is_final
,
predicate_for_trait_def
,
upcast_choices
,
};
pub
use
self
::
util
::{
supertrait_def_ids
,
supertraits
,
transitive_bounds
,
SupertraitDefIds
,
Supertraits
,
supertrait_def_ids
,
supertraits
,
transitive_bounds
,
transitive_bounds_that_define_assoc_type
,
SupertraitDefIds
,
Supertraits
,
};
pub
use
self
::
chalk_fulfill
::
FulfillmentContext
as
ChalkFulfillmentContext
;
...
...
compiler/rustc_typeck/src/astconv/mod.rs
浏览文件 @
2ca4964d
...
...
@@ -6,6 +6,7 @@
mod
generics
;
use
crate
::
bounds
::
Bounds
;
use
crate
::
collect
::
super_traits_of
;
use
crate
::
collect
::
PlaceholderHirTyCollector
;
use
crate
::
errors
::{
AmbiguousLifetimeBound
,
MultipleRelaxedDefaultBounds
,
TraitObjectDeclaredWithNoTraits
,
...
...
@@ -768,7 +769,7 @@ fn trait_defines_associated_type_named(&self, trait_def_id: DefId, assoc_name: I
}
// Returns `true` if a bounds list includes `?Sized`.
pub
fn
is_unsized
(
&
self
,
ast_bounds
:
&
[
hir
::
GenericBound
<
'_
>
],
span
:
Span
)
->
bool
{
pub
fn
is_unsized
(
&
self
,
ast_bounds
:
&
[
&
hir
::
GenericBound
<
'_
>
],
span
:
Span
)
->
bool
{
let
tcx
=
self
.tcx
();
// Try to find an unbound in bounds.
...
...
@@ -826,7 +827,7 @@ pub fn is_unsized(&self, ast_bounds: &[hir::GenericBound<'_>], span: Span) -> bo
fn
add_bounds
(
&
self
,
param_ty
:
Ty
<
'tcx
>
,
ast_bounds
:
&
[
hir
::
GenericBound
<
'_
>
],
ast_bounds
:
&
[
&
hir
::
GenericBound
<
'_
>
],
bounds
:
&
mut
Bounds
<
'tcx
>
,
)
{
let
mut
trait_bounds
=
Vec
::
new
();
...
...
@@ -844,7 +845,7 @@ fn add_bounds(
hir
::
GenericBound
::
Trait
(
_
,
hir
::
TraitBoundModifier
::
Maybe
)
=>
{}
hir
::
GenericBound
::
LangItemTrait
(
lang_item
,
span
,
hir_id
,
args
)
=>
self
.instantiate_lang_item_trait_ref
(
lang_item
,
span
,
hir_id
,
args
,
param_ty
,
bounds
,
*
lang_item
,
*
span
,
*
hir_id
,
args
,
param_ty
,
bounds
,
),
hir
::
GenericBound
::
Outlives
(
ref
l
)
=>
region_bounds
.push
(
l
),
}
...
...
@@ -878,7 +879,7 @@ fn add_bounds(
pub
fn
compute_bounds
(
&
self
,
param_ty
:
Ty
<
'tcx
>
,
ast_bounds
:
&
[
hir
::
GenericBound
<
'_
>
],
ast_bounds
:
&
[
&
hir
::
GenericBound
<
'_
>
],
sized_by_default
:
SizedByDefault
,
span
:
Span
,
)
->
Bounds
<
'tcx
>
{
...
...
@@ -896,6 +897,39 @@ pub fn compute_bounds(
bounds
}
pub
fn
compute_bounds_that_match_assoc_type
(
&
self
,
param_ty
:
Ty
<
'tcx
>
,
ast_bounds
:
&
[
hir
::
GenericBound
<
'_
>
],
sized_by_default
:
SizedByDefault
,
span
:
Span
,
assoc_name
:
Ident
,
)
->
Bounds
<
'tcx
>
{
let
mut
result
=
Vec
::
new
();
for
ast_bound
in
ast_bounds
{
if
let
Some
(
trait_ref
)
=
ast_bound
.trait_ref
()
{
if
let
Some
(
trait_did
)
=
trait_ref
.trait_def_id
()
{
if
super_traits_of
(
self
.tcx
(),
trait_did
)
.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
()
})
{
result
.push
(
ast_bound
);
}
}
}
}
self
.compute_bounds
(
param_ty
,
&
result
,
sized_by_default
,
span
)
}
/// Given an HIR binding like `Item = Foo` or `Item: Foo`, pushes the corresponding predicates
/// onto `bounds`.
///
...
...
@@ -1050,7 +1084,8 @@ fn add_predicates_for_ast_type_binding(
// Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty`
// parameter to have a skipped binder.
let
param_ty
=
tcx
.mk_projection
(
assoc_ty
.def_id
,
candidate
.skip_binder
()
.substs
);
self
.add_bounds
(
param_ty
,
ast_bounds
,
bounds
);
let
ast_bounds
:
Vec
<
_
>
=
ast_bounds
.iter
()
.collect
();
self
.add_bounds
(
param_ty
,
&
ast_bounds
,
bounds
);
}
}
Ok
(())
...
...
@@ -1377,12 +1412,14 @@ fn find_bound_for_assoc_item(
let
param_name
=
tcx
.hir
()
.ty_param_name
(
param_hir_id
);
self
.one_bound_for_assoc_type
(
||
{
traits
::
transitive_bounds
(
traits
::
transitive_bounds
_that_define_assoc_type
(
tcx
,
predicates
.iter
()
.filter_map
(|(
p
,
_
)|
{
p
.to_opt_poly_trait_ref
()
.map
(|
trait_ref
|
trait_ref
.value
)
}),
assoc_name
,
)
.into_iter
()
},
||
param_name
.to_string
(),
assoc_name
,
...
...
compiler/rustc_typeck/src/collect.rs
浏览文件 @
2ca4964d
// ignore-tidy-filelength
//! "Collection" is the process of determining the type and other external
//! details of each item in Rust. Collection is specifically concerned
//! with *inter-procedural* things -- for example, for a function
...
...
@@ -79,6 +80,7 @@ pub fn provide(providers: &mut Providers) {
projection_ty_from_predicates
,
explicit_predicates_of
,
super_predicates_of
,
super_predicates_that_define_assoc_type
,
trait_explicit_predicates_and_bounds
,
type_param_predicates
,
trait_def
,
...
...
@@ -651,17 +653,10 @@ fn bound_defines_assoc_item(&self, b: &hir::GenericBound<'_>, assoc_name: Ident)
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
|
{
super_traits_of
(
self
.tcx
,
trait_did
)
.any
(|
trait_did
|
{
self
.tcx
.associated_items
(
*
trait_did
)
.find_by_name_and_kind
(
self
.tcx
,
assoc_name
,
ty
::
AssocKind
::
Type
,
*
trait_did
,
)
.associated_items
(
trait_did
)
.find_by_name_and_kind
(
self
.tcx
,
assoc_name
,
ty
::
AssocKind
::
Type
,
trait_did
)
.is_some
()
})
}
...
...
@@ -1035,55 +1030,91 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::AdtDef {
/// the transitive super-predicates are converted.
fn
super_predicates_of
(
tcx
:
TyCtxt
<
'_
>
,
trait_def_id
:
DefId
)
->
ty
::
GenericPredicates
<
'_
>
{
debug!
(
"super_predicates(trait_def_id={:?})"
,
trait_def_id
);
let
trait_hir_id
=
tcx
.hir
()
.local_def_id_to_hir_id
(
trait_def_id
.expect_local
());
tcx
.super_predicates_that_define_assoc_type
((
trait_def_id
,
None
))
}
let
item
=
match
tcx
.hir
()
.get
(
trait_hir_id
)
{
Node
::
Item
(
item
)
=>
item
,
_
=>
bug!
(
"trait_node_id {} is not an item"
,
trait_hir_id
),
};
/// Ensures that the super-predicates of the trait with a `DefId`
/// of `trait_def_id` are converted and stored. This also ensures that
/// the transitive super-predicates are converted.
fn
super_predicates_that_define_assoc_type
(
tcx
:
TyCtxt
<
'_
>
,
(
trait_def_id
,
assoc_name
):
(
DefId
,
Option
<
Ident
>
),
)
->
ty
::
GenericPredicates
<
'_
>
{
debug!
(
"super_predicates_that_define_assoc_type(trait_def_id={:?}, assoc_name={:?})"
,
trait_def_id
,
assoc_name
);
if
trait_def_id
.is_local
()
{
debug!
(
"super_predicates_that_define_assoc_type: local trait_def_id={:?}"
,
trait_def_id
);
let
trait_hir_id
=
tcx
.hir
()
.local_def_id_to_hir_id
(
trait_def_id
.expect_local
());
let
(
generics
,
bounds
)
=
match
item
.kind
{
hir
::
ItemKind
::
Trait
(
..
,
ref
generics
,
ref
supertraits
,
_
)
=>
(
generics
,
supertraits
),
hir
::
ItemKind
::
TraitAlias
(
ref
generics
,
ref
supertraits
)
=>
(
generics
,
supertraits
),
_
=>
span_bug!
(
item
.span
,
"super_predicates invoked on non-trait"
),
};
let
item
=
match
tcx
.hir
()
.get
(
trait_hir_id
)
{
Node
::
Item
(
item
)
=>
item
,
_
=>
bug!
(
"trait_node_id {} is not an item"
,
trait_hir_id
),
};
let
icx
=
ItemCtxt
::
new
(
tcx
,
trait_def_id
);
// Convert the bounds that follow the colon, e.g., `Bar + Zed` in `trait Foo: Bar + Zed`.
let
self_param_ty
=
tcx
.types.self_param
;
let
superbounds1
=
AstConv
::
compute_bounds
(
&
icx
,
self_param_ty
,
bounds
,
SizedByDefault
::
No
,
item
.span
);
let
superbounds1
=
superbounds1
.predicates
(
tcx
,
self_param_ty
);
// Convert any explicit superbounds in the where-clause,
// e.g., `trait Foo where Self: Bar`.
// In the case of trait aliases, however, we include all bounds in the where-clause,
// so e.g., `trait Foo = where u32: PartialEq<Self>` would include `u32: PartialEq<Self>`
// as one of its "superpredicates".
let
is_trait_alias
=
tcx
.is_trait_alias
(
trait_def_id
);
let
superbounds2
=
icx
.type_parameter_bounds_in_generics
(
generics
,
item
.hir_id
,
self_param_ty
,
OnlySelfBounds
(
!
is_trait_alias
),
None
,
);
let
(
generics
,
bounds
)
=
match
item
.kind
{
hir
::
ItemKind
::
Trait
(
..
,
ref
generics
,
ref
supertraits
,
_
)
=>
(
generics
,
supertraits
),
hir
::
ItemKind
::
TraitAlias
(
ref
generics
,
ref
supertraits
)
=>
(
generics
,
supertraits
),
_
=>
span_bug!
(
item
.span
,
"super_predicates invoked on non-trait"
),
};
// Combine the two lists to form the complete set of superbounds:
let
superbounds
=
&*
tcx
.arena
.alloc_from_iter
(
superbounds1
.into_iter
()
.chain
(
superbounds2
));
let
icx
=
ItemCtxt
::
new
(
tcx
,
trait_def_id
);
// Now require that immediate supertraits are converted,
// which will, in turn, reach indirect supertraits.
for
&
(
pred
,
span
)
in
superbounds
{
debug!
(
"superbound: {:?}"
,
pred
);
if
let
ty
::
PredicateAtom
::
Trait
(
bound
,
_
)
=
pred
.skip_binders
()
{
tcx
.at
(
span
)
.super_predicates_of
(
bound
.def_id
());
// Convert the bounds that follow the colon, e.g., `Bar + Zed` in `trait Foo: Bar + Zed`.
let
self_param_ty
=
tcx
.types.self_param
;
let
superbounds1
=
if
let
Some
(
assoc_name
)
=
assoc_name
{
AstConv
::
compute_bounds_that_match_assoc_type
(
&
icx
,
self_param_ty
,
&
bounds
,
SizedByDefault
::
No
,
item
.span
,
assoc_name
,
)
}
else
{
let
bounds
:
Vec
<
_
>
=
bounds
.iter
()
.collect
();
AstConv
::
compute_bounds
(
&
icx
,
self_param_ty
,
&
bounds
,
SizedByDefault
::
No
,
item
.span
)
};
let
superbounds1
=
superbounds1
.predicates
(
tcx
,
self_param_ty
);
// Convert any explicit superbounds in the where-clause,
// e.g., `trait Foo where Self: Bar`.
// In the case of trait aliases, however, we include all bounds in the where-clause,
// so e.g., `trait Foo = where u32: PartialEq<Self>` would include `u32: PartialEq<Self>`
// as one of its "superpredicates".
let
is_trait_alias
=
tcx
.is_trait_alias
(
trait_def_id
);
let
superbounds2
=
icx
.type_parameter_bounds_in_generics
(
generics
,
item
.hir_id
,
self_param_ty
,
OnlySelfBounds
(
!
is_trait_alias
),
assoc_name
,
);
// Combine the two lists to form the complete set of superbounds:
let
superbounds
=
&*
tcx
.arena
.alloc_from_iter
(
superbounds1
.into_iter
()
.chain
(
superbounds2
));
// Now require that immediate supertraits are converted,
// which will, in turn, reach indirect supertraits.
if
assoc_name
.is_none
()
{
// FIXME: move this into the `super_predicates_of` query
for
&
(
pred
,
span
)
in
superbounds
{
debug!
(
"superbound: {:?}"
,
pred
);
if
let
ty
::
PredicateAtom
::
Trait
(
bound
,
_
)
=
pred
.skip_binders
()
{
tcx
.at
(
span
)
.super_predicates_of
(
bound
.def_id
());
}
}
}
}
ty
::
GenericPredicates
{
parent
:
None
,
predicates
:
superbounds
}
ty
::
GenericPredicates
{
parent
:
None
,
predicates
:
superbounds
}
}
else
{
// if `assoc_name` is None, then the query should've been redirected to an
// external provider
assert
!
(
assoc_name
.is_some
());
tcx
.super_predicates_of
(
trait_def_id
)
}
}
pub
fn
super_traits_of
(
tcx
:
TyCtxt
<
'_
>
,
trait_def_id
:
DefId
)
->
impl
Iterator
<
Item
=
DefId
>
{
...
...
@@ -1123,6 +1154,8 @@ pub fn super_traits_of(tcx: TyCtxt<'_>, trait_def_id: DefId) -> impl Iterator<It
}
}
}
set
.into_iter
()
}
fn
trait_def
(
tcx
:
TyCtxt
<
'_
>
,
def_id
:
DefId
)
->
ty
::
TraitDef
{
...
...
@@ -1976,8 +2009,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
index
+=
1
;
let
sized
=
SizedByDefault
::
Yes
;
let
bounds
=
AstConv
::
compute_bounds
(
&
icx
,
param_ty
,
&
param
.
bounds
,
sized
,
param
.span
);
let
bounds
:
Vec
<
_
>
=
param
.bounds
.iter
()
.collect
();
let
bounds
=
AstConv
::
compute_bounds
(
&
icx
,
param_ty
,
&
bounds
,
sized
,
param
.span
);
predicates
.extend
(
bounds
.predicates
(
tcx
,
param_ty
));
}
GenericParamKind
::
Const
{
..
}
=>
{
...
...
compiler/rustc_typeck/src/collect/item_bounds.rs
浏览文件 @
2ca4964d
...
...
@@ -25,10 +25,11 @@ fn associated_type_bounds<'tcx>(
InternalSubsts
::
identity_for_item
(
tcx
,
assoc_item_def_id
),
);
let
bounds
:
Vec
<
_
>
=
bounds
.iter
()
.collect
();
let
bounds
=
AstConv
::
compute_bounds
(
&
ItemCtxt
::
new
(
tcx
,
assoc_item_def_id
),
item_ty
,
bounds
,
&
bounds
,
SizedByDefault
::
Yes
,
span
,
);
...
...
@@ -65,10 +66,11 @@ fn opaque_type_bounds<'tcx>(
let
item_ty
=
tcx
.mk_opaque
(
opaque_def_id
,
InternalSubsts
::
identity_for_item
(
tcx
,
opaque_def_id
));
let
bounds
:
Vec
<
_
>
=
bounds
.iter
()
.collect
();
let
bounds
=
AstConv
::
compute_bounds
(
&
ItemCtxt
::
new
(
tcx
,
opaque_def_id
),
item_ty
,
bounds
,
&
bounds
,
SizedByDefault
::
Yes
,
span
,
)
...
...
src/test/ui/associated-type-bounds/super-trait-referencing-self.rs
0 → 100644
浏览文件 @
2ca4964d
// check-pass
trait
Foo
{
type
Bar
;
}
trait
Qux
:
Foo
+
AsRef
<
Self
::
Bar
>
{}
trait
Foo2
{}
trait
Qux2
:
Foo2
+
AsRef
<
Self
::
Bar
>
{
type
Bar
;
}
fn
main
()
{}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录