Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
fb9d0ccc
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,发现更多精彩内容 >>
提交
fb9d0ccc
编写于
10月 31, 2014
作者:
N
Niko Matsakis
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Move associated types into the Assoc space and add in the builtin bounds
from the definition (including Sized).
上级
d2f8074e
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
243 addition
and
209 deletion
+243
-209
src/librustc/middle/subst.rs
src/librustc/middle/subst.rs
+2
-1
src/librustc/middle/traits/select.rs
src/librustc/middle/traits/select.rs
+1
-0
src/librustc/middle/ty.rs
src/librustc/middle/ty.rs
+10
-17
src/librustc/middle/typeck/astconv.rs
src/librustc/middle/typeck/astconv.rs
+38
-13
src/librustc/middle/typeck/collect.rs
src/librustc/middle/typeck/collect.rs
+119
-159
src/librustc/middle/typeck/infer/mod.rs
src/librustc/middle/typeck/infer/mod.rs
+8
-3
src/librustc/util/ppaux.rs
src/librustc/util/ppaux.rs
+41
-16
src/test/compile-fail/associated-types-unsized.rs
src/test/compile-fail/associated-types-unsized.rs
+24
-0
未找到文件。
src/librustc/middle/subst.rs
浏览文件 @
fb9d0ccc
...
...
@@ -118,10 +118,11 @@ pub fn new_type(t: Vec<ty::t>,
pub
fn
new_trait
(
t
:
Vec
<
ty
::
t
>
,
r
:
Vec
<
ty
::
Region
>
,
a
:
Vec
<
ty
::
t
>
,
s
:
ty
::
t
)
->
Substs
{
Substs
::
new
(
VecPerParamSpace
::
new
(
t
,
vec!
(
s
),
Vec
::
new
()
,
Vec
::
new
()),
Substs
::
new
(
VecPerParamSpace
::
new
(
t
,
vec!
(
s
),
a
,
Vec
::
new
()),
VecPerParamSpace
::
new
(
r
,
Vec
::
new
(),
Vec
::
new
(),
Vec
::
new
()))
}
...
...
src/librustc/middle/traits/select.rs
浏览文件 @
fb9d0ccc
...
...
@@ -1683,6 +1683,7 @@ fn confirm_unboxed_closure_candidate(&mut self,
vec!
[
arguments_tuple
.subst
(
self
.tcx
(),
substs
),
new_signature
.output
.unwrap
()
.subst
(
self
.tcx
(),
substs
)],
vec!
[],
vec!
[],
obligation
.self_ty
())
});
...
...
src/librustc/middle/ty.rs
浏览文件 @
fb9d0ccc
...
...
@@ -573,10 +573,6 @@ pub struct ctxt<'tcx> {
/// Maps def IDs to true if and only if they're associated types.
pub
associated_types
:
RefCell
<
DefIdMap
<
bool
>>
,
/// Maps def IDs of traits to information about their associated types.
pub
trait_associated_types
:
RefCell
<
DefIdMap
<
Rc
<
Vec
<
AssociatedTypeInfo
>>>>
,
/// Caches the results of trait selection. This cache is used
/// for things that do not have to do with the parameters in scope.
pub
selection_cache
:
traits
::
SelectionCache
,
...
...
@@ -1564,7 +1560,6 @@ pub fn mk_ctxt<'tcx>(s: Session,
stability
:
RefCell
::
new
(
stability
),
capture_modes
:
capture_modes
,
associated_types
:
RefCell
::
new
(
DefIdMap
::
new
()),
trait_associated_types
:
RefCell
::
new
(
DefIdMap
::
new
()),
selection_cache
:
traits
::
SelectionCache
::
new
(),
repr_hint_cache
:
RefCell
::
new
(
DefIdMap
::
new
()),
}
...
...
@@ -1994,6 +1989,16 @@ pub fn is_noop(&self) -> bool {
}
}
impl
ParamBounds
{
pub
fn
empty
()
->
ParamBounds
{
ParamBounds
{
builtin_bounds
:
empty_builtin_bounds
(),
trait_bounds
:
Vec
::
new
(),
region_bounds
:
Vec
::
new
(),
}
}
}
// Type utilities
pub
fn
type_is_nil
(
ty
:
t
)
->
bool
{
...
...
@@ -4155,18 +4160,6 @@ fn cmp(&self, other: &AssociatedTypeInfo) -> Ordering {
}
}
/// Returns the associated types belonging to the given trait, in parameter
/// order.
pub
fn
associated_types_for_trait
(
cx
:
&
ctxt
,
trait_id
:
ast
::
DefId
)
->
Rc
<
Vec
<
AssociatedTypeInfo
>>
{
cx
.trait_associated_types
.borrow
()
.find
(
&
trait_id
)
.expect
(
"associated_types_for_trait(): trait not found, try calling
\
ensure_associated_types()"
)
.clone
()
}
pub
fn
trait_item_def_ids
(
cx
:
&
ctxt
,
id
:
ast
::
DefId
)
->
Rc
<
Vec
<
ImplOrTraitItemId
>>
{
lookup_locally_or_in_crate_store
(
"trait_item_def_ids"
,
...
...
src/librustc/middle/typeck/astconv.rs
浏览文件 @
fb9d0ccc
...
...
@@ -54,7 +54,7 @@
use
middle
::
lang_items
::{
FnTraitLangItem
,
FnMutTraitLangItem
};
use
middle
::
lang_items
::{
FnOnceTraitLangItem
};
use
middle
::
resolve_lifetime
as
rl
;
use
middle
::
subst
::{
FnSpace
,
TypeSpace
,
SelfSpace
,
Subst
,
Substs
};
use
middle
::
subst
::{
FnSpace
,
TypeSpace
,
AssocSpace
,
SelfSpace
,
Subst
,
Substs
};
use
middle
::
subst
::{
VecPerParamSpace
};
use
middle
::
ty
;
use
middle
::
typeck
::
lookup_def_tcx
;
...
...
@@ -215,7 +215,8 @@ fn ast_path_substs<'tcx,AC,RS>(
associated_ty
:
Option
<
ty
::
t
>
,
path
:
&
ast
::
Path
)
->
Substs
where
AC
:
AstConv
<
'tcx
>
,
RS
:
RegionScope
{
where
AC
:
AstConv
<
'tcx
>
,
RS
:
RegionScope
{
/*!
* Given a path `path` that refers to an item `I` with the
* declared generics `decl_generics`, returns an appropriate
...
...
@@ -338,17 +339,21 @@ fn ast_path_substs<'tcx,AC,RS>(
substs
.types
.push
(
TypeSpace
,
default
);
}
None
=>
{
// This is an associated type.
substs
.types
.push
(
TypeSpace
,
this
.associated_type_binding
(
path
.span
,
associated_ty
,
decl_def_id
,
param
.def_id
))
tcx
.sess
.span_bug
(
path
.span
,
"extra parameter without default"
);
}
}
}
for
param
in
decl_generics
.types
.get_slice
(
AssocSpace
)
.iter
()
{
substs
.types
.push
(
AssocSpace
,
this
.associated_type_binding
(
path
.span
,
associated_ty
,
decl_def_id
,
param
.def_id
))
}
substs
}
...
...
@@ -628,9 +633,13 @@ fn mk_pointer<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
a_seq_ty
:
&
ast
::
Ty
,
ptr_ty
:
PointerTy
,
constr
:
|
ty
::
t
|
->
ty
::
t
)
->
ty
::
t
{
->
ty
::
t
{
let
tcx
=
this
.tcx
();
debug!
(
"mk_pointer(ptr_ty={})"
,
ptr_ty
);
debug!
(
"mk_pointer(ptr_ty={}, a_seq_ty={})"
,
ptr_ty
,
a_seq_ty
.repr
(
tcx
));
match
a_seq_ty
.node
{
ast
::
TyVec
(
ref
ty
)
=>
{
...
...
@@ -730,7 +739,13 @@ fn associated_ty_to_ty<'tcx,AC,RS>(this: &AC,
trait_type_id
:
ast
::
DefId
,
span
:
Span
)
->
ty
::
t
where
AC
:
AstConv
<
'tcx
>
,
RS
:
RegionScope
{
where
AC
:
AstConv
<
'tcx
>
,
RS
:
RegionScope
{
debug!
(
"associated_ty_to_ty(trait_path={}, for_ast_type={}, trait_type_id={})"
,
trait_path
.repr
(
this
.tcx
()),
for_ast_type
.repr
(
this
.tcx
()),
trait_type_id
.repr
(
this
.tcx
()));
// Find the trait that this associated type belongs to.
let
trait_did
=
match
ty
::
impl_or_trait_item
(
this
.tcx
(),
trait_type_id
)
.container
()
{
...
...
@@ -757,9 +772,16 @@ fn associated_ty_to_ty<'tcx,AC,RS>(this: &AC,
None
,
Some
(
for_type
),
trait_path
);
debug!
(
"associated_ty_to_ty(trait_ref={})"
,
trait_ref
.repr
(
this
.tcx
()));
let
trait_def
=
this
.get_trait_def
(
trait_did
);
for
type_parameter
in
trait_def
.generics.types
.iter
()
{
if
type_parameter
.def_id
==
trait_type_id
{
debug!
(
"associated_ty_to_ty(type_parameter={} substs={})"
,
type_parameter
.repr
(
this
.tcx
()),
trait_ref
.substs
.repr
(
this
.tcx
()));
return
*
trait_ref
.substs.types
.get
(
type_parameter
.space
,
type_parameter
.index
)
}
...
...
@@ -772,7 +794,10 @@ fn associated_ty_to_ty<'tcx,AC,RS>(this: &AC,
// Parses the programmer's textual representation of a type into our
// internal notion of a type.
pub
fn
ast_ty_to_ty
<
'tcx
,
AC
:
AstConv
<
'tcx
>
,
RS
:
RegionScope
>
(
this
:
&
AC
,
rscope
:
&
RS
,
ast_ty
:
&
ast
::
Ty
)
->
ty
::
t
{
this
:
&
AC
,
rscope
:
&
RS
,
ast_ty
:
&
ast
::
Ty
)
->
ty
::
t
{
debug!
(
"ast_ty_to_ty(ast_ty={})"
,
ast_ty
.repr
(
this
.tcx
()));
let
tcx
=
this
.tcx
();
...
...
src/librustc/middle/typeck/collect.rs
浏览文件 @
fb9d0ccc
...
...
@@ -305,6 +305,12 @@ fn collect_trait_methods(ccx: &CrateCtxt,
}
});
debug!
(
"ty_method_of_trait_method yielded {}
\
for method {} of trait {}"
,
ty_method
.repr
(
ccx
.tcx
),
trait_item
.repr
(
ccx
.tcx
),
local_def
(
trait_id
)
.repr
(
ccx
.tcx
));
make_method_ty
(
ccx
,
&*
ty_method
);
tcx
.impl_or_trait_items
...
...
@@ -460,7 +466,7 @@ fn convert_associated_type(ccx: &CrateCtxt,
// associated type.
let
type_parameter_def
=
trait_def
.generics
.types
.get_slice
(
subst
::
Type
Space
)
.get_slice
(
subst
::
Assoc
Space
)
.iter
()
.find
(|
def
|
{
def
.def_id
==
local_def
(
associated_type
.ty_param.id
)
...
...
@@ -475,7 +481,7 @@ fn convert_associated_type(ccx: &CrateCtxt,
}
};
let
param_type
=
ty
::
mk_param
(
ccx
.tcx
,
subst
::
TypeS
pace
,
type_parameter_def
.s
pace
,
type_parameter_def
.index
,
local_def
(
associated_type
.ty_param.id
));
ccx
.tcx.tcache
.borrow_mut
()
.insert
(
local_def
(
associated_type
.ty_param.id
),
...
...
@@ -780,25 +786,18 @@ fn associated_type_binding(&self,
ty
:
Option
<
ty
::
t
>
,
trait_id
:
ast
::
DefId
,
associated_type_id
:
ast
::
DefId
)
->
ty
::
t
{
ensure_associated_types
(
self
,
trait_id
);
let
associated_type_ids
=
ty
::
associated_types_for_trait
(
self
.ccx.tcx
,
trait_id
);
->
ty
::
t
{
let
trait_def
=
ty
::
lookup_trait_def
(
self
.tcx
(),
trait_id
);
match
self
.opt_trait_ref_id
{
Some
(
trait_ref_id
)
if
trait_ref_id
==
trait_id
=>
{
// It's an associated type on the trait that we're
// implementing.
let
associated_type_id
=
associated_type_ids
.iter
()
.find
(|
id
|
{
id
.def_id
==
associated_type_id
})
.expect
(
"associated_type_binding():
\
expected associated type ID
\
in trait"
);
let
associated_type
=
ty
::
impl_or_trait_item
(
self
.ccx.tcx
,
associated_type_id
.def_id
);
assert
!
(
trait_def
.generics.types
.get_slice
(
subst
::
AssocSpace
)
.iter
()
.any
(|
type_param_def
|
type_param_def
.def_id
==
associated_type_id
));
let
associated_type
=
ty
::
impl_or_trait_item
(
self
.ccx.tcx
,
associated_type_id
);
for
impl_item
in
self
.impl_items
.iter
()
{
match
*
impl_item
{
ast
::
MethodImplItem
(
_
)
=>
{}
...
...
@@ -980,7 +979,7 @@ fn associated_type_binding(&self,
ast
::
TypeTraitItem
(
ref
item
)
=>
{
if
local_def
(
item
.ty_param.id
)
==
associated_type_id
{
return
ty
::
mk_param
(
self
.tcx
(),
subst
::
Type
Space
,
subst
::
Assoc
Space
,
index
,
associated_type_id
)
}
...
...
@@ -1451,7 +1450,8 @@ fn mk_trait_substs(ccx: &CrateCtxt,
trait_id
:
ast
::
NodeId
,
generics
:
&
ast
::
Generics
,
items
:
&
[
ast
::
TraitItem
])
->
subst
::
Substs
{
->
subst
::
Substs
{
// Creates a no-op substitution for the trait's type parameters.
let
regions
=
generics
.lifetimes
...
...
@@ -1464,7 +1464,7 @@ fn mk_trait_substs(ccx: &CrateCtxt,
.collect
();
// Start with the generics in the type parameters...
let
mut
types
:
Vec
<
_
>
=
let
types
:
Vec
<
_
>
=
generics
.ty_params
.iter
()
.enumerate
()
...
...
@@ -1472,24 +1472,27 @@ fn mk_trait_substs(ccx: &CrateCtxt,
i
,
local_def
(
def
.id
)))
.collect
();
// ...and add generics synthesized from the associated types.
for
item
in
items
.iter
()
{
match
*
item
{
// ...and also create generics synthesized from the associated types.
let
assoc_types
:
Vec
<
_
>
=
items
.iter
()
.flat_map
(|
item
|
match
*
item
{
ast
::
TypeTraitItem
(
ref
trait_item
)
=>
{
let
index
=
types
.len
();
types
.push
(
ty
::
mk_param
(
ccx
.tcx
,
subst
::
Type
Space
,
index
,
local_def
(
trait_item
.ty_param.id
))
)
Some
(
ty
::
mk_param
(
ccx
.tcx
,
subst
::
Assoc
Space
,
index
,
local_def
(
trait_item
.ty_param.id
)))
.into_iter
(
)
}
ast
::
RequiredMethod
(
_
)
|
ast
::
ProvidedMethod
(
_
)
=>
{}
}
}
ast
::
RequiredMethod
(
_
)
|
ast
::
ProvidedMethod
(
_
)
=>
{
None
.into_iter
()
}
})
.collect
();
let
self_ty
=
ty
::
mk_param
(
ccx
.tcx
,
subst
::
SelfSpace
,
0
,
local_def
(
trait_id
));
subst
::
Substs
::
new_trait
(
types
,
regions
,
self_ty
)
subst
::
Substs
::
new_trait
(
types
,
regions
,
assoc_types
,
self_ty
)
}
}
...
...
@@ -1680,14 +1683,14 @@ fn ty_generics_for_trait(ccx: &CrateCtxt,
let
def
=
get_or_create_type_parameter_def
(
ccx
,
subst
::
Type
Space
,
subst
::
Assoc
Space
,
&
associated_type
.ty_param
,
generics
.types
.len
(
subst
::
TypeSpace
),
&
ast_generics
.where_clause
,
Some
(
local_def
(
trait_id
)));
ccx
.tcx.ty_param_defs
.borrow_mut
()
.insert
(
associated_type
.ty_param.id
,
def
.clone
());
generics
.types
.push
(
subst
::
Type
Space
,
def
);
generics
.types
.push
(
subst
::
Assoc
Space
,
def
);
}
ast
::
ProvidedMethod
(
_
)
|
ast
::
RequiredMethod
(
_
)
=>
{}
}
...
...
@@ -1786,86 +1789,17 @@ enum CreateTypeParametersForAssociatedTypesFlag {
CreateTypeParametersForAssociatedTypes
,
}
fn
ensure_associated_types
<
'tcx
,
AC
>
(
this
:
&
AC
,
trait_id
:
ast
::
DefId
)
where
AC
:
AstConv
<
'tcx
>
{
if
this
.tcx
()
.trait_associated_types
.borrow
()
.contains_key
(
&
trait_id
)
{
return
}
if
trait_id
.krate
==
ast
::
LOCAL_CRATE
{
match
this
.tcx
()
.map
.find
(
trait_id
.node
)
{
Some
(
ast_map
::
NodeItem
(
item
))
=>
{
match
item
.node
{
ast
::
ItemTrait
(
_
,
_
,
_
,
ref
trait_items
)
=>
{
let
mut
result
=
Vec
::
new
();
let
mut
index
=
0
;
for
trait_item
in
trait_items
.iter
()
{
match
*
trait_item
{
ast
::
RequiredMethod
(
_
)
|
ast
::
ProvidedMethod
(
_
)
=>
{}
ast
::
TypeTraitItem
(
ref
associated_type
)
=>
{
let
info
=
ty
::
AssociatedTypeInfo
{
def_id
:
local_def
(
associated_type
.ty_param.id
),
index
:
index
,
name
:
associated_type
.ty_param.ident.name
,
};
result
.push
(
info
);
index
+=
1
;
}
}
}
this
.tcx
()
.trait_associated_types
.borrow_mut
()
.insert
(
trait_id
,
Rc
::
new
(
result
));
return
}
_
=>
{
this
.tcx
()
.sess
.bug
(
"ensure_associated_types()
\
called on non-trait"
)
}
}
}
_
=>
{
this
.tcx
()
.sess
.bug
(
"ensure_associated_types() called on
\
non-trait"
)
}
}
}
// Cross-crate case.
let
mut
result
=
Vec
::
new
();
let
mut
index
=
0
;
let
trait_items
=
ty
::
trait_items
(
this
.tcx
(),
trait_id
);
for
trait_item
in
trait_items
.iter
()
{
match
*
trait_item
{
ty
::
MethodTraitItem
(
_
)
=>
{}
ty
::
TypeTraitItem
(
ref
associated_type
)
=>
{
let
info
=
ty
::
AssociatedTypeInfo
{
def_id
:
associated_type
.def_id
,
index
:
index
,
name
:
associated_type
.name
};
result
.push
(
info
);
index
+=
1
;
}
}
}
this
.tcx
()
.trait_associated_types
.borrow_mut
()
.insert
(
trait_id
,
Rc
::
new
(
result
));
}
fn
ty_generics
<
'tcx
,
AC
>
(
this
:
&
AC
,
space
:
subst
::
ParamSpace
,
lifetime_defs
:
&
[
ast
::
LifetimeDef
],
types
:
&
[
ast
::
TyParam
],
base_generics
:
ty
::
Generics
,
where_clause
:
&
ast
::
WhereClause
,
create_type_parameters_for_associated_types
:
create_type_parameters_for_associated_types
_flag
:
CreateTypeParametersForAssociatedTypesFlag
)
->
ty
::
Generics
where
AC
:
AstConv
<
'tcx
>
{
where
AC
:
AstConv
<
'tcx
>
{
let
mut
result
=
base_generics
;
for
(
i
,
l
)
in
lifetime_defs
.iter
()
.enumerate
()
{
...
...
@@ -1886,62 +1820,11 @@ fn ty_generics<'tcx,AC>(this: &AC,
// First, create the virtual type parameters for associated types if
// necessary.
let
mut
associated_types_generics
=
ty
::
Generics
::
empty
();
match
create_type_parameters_for_associated_types
{
match
create_type_parameters_for_associated_types
_flag
{
DontCreateTypeParametersForAssociatedTypes
=>
{}
CreateTypeParametersForAssociatedTypes
=>
{
let
mut
index
=
0
;
for
param
in
types
.iter
()
{
for
bound
in
param
.bounds
.iter
()
{
match
*
bound
{
ast
::
TraitTyParamBound
(
ref
trait_bound
)
=>
{
match
lookup_def_tcx
(
this
.tcx
(),
trait_bound
.path.span
,
trait_bound
.ref_id
)
{
def
::
DefTrait
(
trait_did
)
=>
{
ensure_associated_types
(
this
,
trait_did
);
let
associated_types
=
ty
::
associated_types_for_trait
(
this
.tcx
(),
trait_did
);
for
associated_type_info
in
associated_types
.iter
()
{
let
associated_type_trait_item
=
ty
::
impl_or_trait_item
(
this
.tcx
(),
associated_type_info
.def_id
);
let
def
=
ty
::
TypeParameterDef
{
name
:
associated_type_trait_item
.name
(),
def_id
:
associated_type_info
.def_id
,
space
:
space
,
index
:
types
.len
()
+
index
,
bounds
:
ty
::
ParamBounds
{
builtin_bounds
:
ty
::
empty_builtin_bounds
(),
trait_bounds
:
Vec
::
new
(),
region_bounds
:
Vec
::
new
(),
},
associated_with
:
{
Some
(
local_def
(
param
.id
))
},
default
:
None
,
};
associated_types_generics
.types
.push
(
space
,
def
);
index
+=
1
;
}
}
_
=>
{
this
.tcx
()
.sess
.span_bug
(
trait_bound
.path
.span
,
"not a trait?!"
)
}
}
}
_
=>
{}
}
}
}
create_type_parameters_for_associated_types
(
this
,
space
,
types
,
&
mut
associated_types_generics
);
}
}
...
...
@@ -1976,6 +1859,83 @@ fn ty_generics<'tcx,AC>(this: &AC,
}
return
result
;
fn
create_type_parameters_for_associated_types
<
'tcx
,
AC
>
(
this
:
&
AC
,
space
:
subst
::
ParamSpace
,
types
:
&
[
ast
::
TyParam
],
associated_types_generics
:
&
mut
ty
::
Generics
)
where
AC
:
AstConv
<
'tcx
>
{
// The idea here is roughly as follows. We start with
// an item that is paramerized by various type parameters
// with bounds:
//
// fn foo<T:Iterator>(t: T) { ... }
//
// The traits in those bounds declare associated types:
//
// trait Iterator { type Elem; ... }
//
// And we rewrite the original function so that every associated
// type is bound to some fresh type parameter:
//
// fn foo<A,T:Iterator<Elem=A>>(t: T) { ... }
// Number of synthetic type parameters created thus far
let
mut
index
=
0
;
// Iterate over the each type parameter `T` (from the example)
for
param
in
types
.iter
()
{
// Iterate over the bound `Iterator`
for
bound
in
param
.bounds
.iter
()
{
// In the above example, `ast_trait_ref` is `Iterator`.
let
ast_trait_ref
=
match
*
bound
{
ast
::
TraitTyParamBound
(
ref
r
)
=>
r
,
ast
::
UnboxedFnTyParamBound
(
..
)
=>
{
continue
;
}
ast
::
RegionTyParamBound
(
..
)
=>
{
continue
;
}
};
let
trait_def_id
=
match
lookup_def_tcx
(
this
.tcx
(),
ast_trait_ref
.path.span
,
ast_trait_ref
.ref_id
)
{
def
::
DefTrait
(
trait_def_id
)
=>
trait_def_id
,
_
=>
{
this
.tcx
()
.sess
.span_bug
(
ast_trait_ref
.path.span
,
"not a trait?!"
)
}
};
// trait_def_id is def-id of `Iterator`
let
trait_def
=
ty
::
lookup_trait_def
(
this
.tcx
(),
trait_def_id
);
let
associated_type_defs
=
trait_def
.generics.types
.get_slice
(
subst
::
AssocSpace
);
// Iterate over each associated type `Elem`
for
associated_type_def
in
associated_type_defs
.iter
()
{
// Create the fresh type parameter `A`
let
def
=
ty
::
TypeParameterDef
{
name
:
associated_type_def
.name
,
def_id
:
associated_type_def
.def_id
,
space
:
space
,
index
:
types
.len
()
+
index
,
bounds
:
ty
::
ParamBounds
{
builtin_bounds
:
associated_type_def
.bounds.builtin_bounds
,
// FIXME(#18178) -- we should add the other bounds, but
// that requires subst and more logic
trait_bounds
:
Vec
::
new
(),
region_bounds
:
Vec
::
new
(),
},
associated_with
:
Some
(
local_def
(
param
.id
)),
default
:
None
,
};
associated_types_generics
.types
.push
(
space
,
def
);
index
+=
1
;
}
}
}
}
}
fn
get_or_create_type_parameter_def
<
'tcx
,
AC
>
(
this
:
&
AC
,
...
...
src/librustc/middle/typeck/infer/mod.rs
浏览文件 @
fb9d0ccc
...
...
@@ -774,10 +774,15 @@ pub fn fresh_substs_for_trait(&self,
assert
!
(
generics
.regions
.len
(
subst
::
FnSpace
)
==
0
);
let
type_parameter_count
=
generics
.types
.len
(
subst
::
TypeSpace
);
let
type_parameters
=
self
.next_ty_vars
(
type_parameter_count
);
let
region_param_defs
=
generics
.regions
.get_slice
(
subst
::
TypeSpace
);
let
regions
=
self
.region_vars_for_defs
(
span
,
region_param_defs
);
let
type_parameters
=
self
.next_ty_vars
(
type_parameter_count
);
subst
::
Substs
::
new_trait
(
type_parameters
,
regions
,
self_ty
)
let
assoc_type_parameter_count
=
generics
.types
.len
(
subst
::
AssocSpace
);
let
assoc_type_parameters
=
self
.next_ty_vars
(
assoc_type_parameter_count
);
subst
::
Substs
::
new_trait
(
type_parameters
,
regions
,
assoc_type_parameters
,
self_ty
)
}
pub
fn
fresh_bound_region
(
&
self
,
binder_id
:
ast
::
NodeId
)
->
ty
::
Region
{
...
...
@@ -791,7 +796,7 @@ pub fn resolve_regions_and_report_errors(&self) {
pub
fn
ty_to_string
(
&
self
,
t
:
ty
::
t
)
->
String
{
ty_to_string
(
self
.tcx
,
self
.resolve_type_vars_if_possible
(
t
))
self
.resolve_type_vars_if_possible
(
t
))
}
pub
fn
tys_to_string
(
&
self
,
ts
:
&
[
ty
::
t
])
->
String
{
...
...
src/librustc/util/ppaux.rs
浏览文件 @
fb9d0ccc
...
...
@@ -423,7 +423,13 @@ fn infer_ty_to_string(cx: &ctxt, ty: ty::InferTy) -> String {
}
ty_infer
(
infer_ty
)
=>
infer_ty_to_string
(
cx
,
infer_ty
),
ty_err
=>
"[type error]"
.to_string
(),
ty_param
(
ref
param_ty
)
=>
param_ty
.repr
(
cx
),
ty_param
(
ref
param_ty
)
=>
{
if
cx
.sess
.verbose
()
{
param_ty
.repr
(
cx
)
}
else
{
param_ty
.user_string
(
cx
)
}
}
ty_enum
(
did
,
ref
substs
)
|
ty_struct
(
did
,
ref
substs
)
=>
{
let
base
=
ty
::
item_path_str
(
cx
,
did
);
let
generics
=
ty
::
lookup_item_type
(
cx
,
did
)
.generics
;
...
...
@@ -479,6 +485,17 @@ pub fn parameterized(cx: &ctxt,
generics
:
&
ty
::
Generics
)
->
String
{
if
cx
.sess
.verbose
()
{
if
substs
.is_noop
()
{
return
format!
(
"{}"
,
base
);
}
else
{
return
format!
(
"{}<{},{}>"
,
base
,
substs
.regions
.repr
(
cx
),
substs
.types
.repr
(
cx
));
}
}
let
mut
strs
=
Vec
::
new
();
match
substs
.regions
{
...
...
@@ -503,7 +520,7 @@ pub fn parameterized(cx: &ctxt,
let
tps
=
substs
.types
.get_slice
(
subst
::
TypeSpace
);
let
ty_params
=
generics
.types
.get_slice
(
subst
::
TypeSpace
);
let
has_defaults
=
ty_params
.last
()
.map_or
(
false
,
|
def
|
def
.default
.is_some
());
let
num_defaults
=
if
has_defaults
&&
!
cx
.sess
.verbose
()
{
let
num_defaults
=
if
has_defaults
{
ty_params
.iter
()
.zip
(
tps
.iter
())
.rev
()
.take_while
(|
&
(
def
,
&
actual
)|
{
match
def
.default
{
Some
(
default
)
=>
default
.subst
(
cx
,
substs
)
==
actual
,
...
...
@@ -518,18 +535,6 @@ pub fn parameterized(cx: &ctxt,
strs
.push
(
ty_to_string
(
cx
,
*
t
))
}
if
cx
.sess
.verbose
()
{
for
t
in
substs
.types
.get_slice
(
subst
::
SelfSpace
)
.iter
()
{
strs
.push
(
format!
(
"self {}"
,
t
.repr
(
cx
)));
}
// generally there shouldn't be any substs in the fn param
// space, but in verbose mode, print them out.
for
t
in
substs
.types
.get_slice
(
subst
::
FnSpace
)
.iter
()
{
strs
.push
(
format!
(
"fn {}"
,
t
.repr
(
cx
)));
}
}
if
strs
.len
()
>
0u
{
format!
(
"{}<{}>"
,
base
,
strs
.connect
(
", "
))
}
else
{
...
...
@@ -725,7 +730,7 @@ impl Repr for ty::TraitRef {
fn
repr
(
&
self
,
tcx
:
&
ctxt
)
->
String
{
let
base
=
ty
::
item_path_str
(
tcx
,
self
.def_id
);
let
trait_def
=
ty
::
lookup_trait_def
(
tcx
,
self
.def_id
);
format!
(
"<{}
as
{}>"
,
format!
(
"<{}
:
{}>"
,
self
.substs
.self_ty
()
.repr
(
tcx
),
parameterized
(
tcx
,
base
.as_slice
(),
&
self
.substs
,
&
trait_def
.generics
))
}
...
...
@@ -740,6 +745,19 @@ fn repr(&self, tcx: &ctxt) -> String {
}
}
impl
Repr
for
ast
::
TraitItem
{
fn
repr
(
&
self
,
_
tcx
:
&
ctxt
)
->
String
{
match
*
self
{
ast
::
RequiredMethod
(
ref
data
)
=>
format!
(
"RequiredMethod({}, id={})"
,
data
.ident
,
data
.id
),
ast
::
ProvidedMethod
(
ref
data
)
=>
format!
(
"ProvidedMethod(id={})"
,
data
.id
),
ast
::
TypeTraitItem
(
ref
data
)
=>
format!
(
"TypeTraitItem({}, id={})"
,
data
.ty_param.ident
,
data
.ty_param.id
),
}
}
}
impl
Repr
for
ast
::
Expr
{
fn
repr
(
&
self
,
_
tcx
:
&
ctxt
)
->
String
{
format!
(
"expr({}: {})"
,
self
.id
,
pprust
::
expr_to_string
(
self
))
...
...
@@ -758,6 +776,12 @@ fn user_string(&self, _tcx: &ctxt) -> String {
}
}
impl
Repr
for
ast
::
Ty
{
fn
repr
(
&
self
,
_
tcx
:
&
ctxt
)
->
String
{
format!
(
"type({})"
,
pprust
::
ty_to_string
(
self
))
}
}
impl
Repr
for
ast
::
Item
{
fn
repr
(
&
self
,
tcx
:
&
ctxt
)
->
String
{
format!
(
"item({})"
,
tcx
.map
.node_to_string
(
self
.id
))
...
...
@@ -1261,7 +1285,8 @@ fn user_string(&self, tcx: &ctxt) -> String {
impl
Repr
for
ParamTy
{
fn
repr
(
&
self
,
tcx
:
&
ctxt
)
->
String
{
self
.user_string
(
tcx
)
let
ident
=
self
.user_string
(
tcx
);
format!
(
"{}/{}.{}"
,
ident
,
self
.space
,
self
.idx
)
}
}
...
...
src/test/compile-fail/associated-types-unsized.rs
0 → 100644
浏览文件 @
fb9d0ccc
// 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.
#![feature(associated_types)]
trait
Get
{
type
Sized
?
Value
;
fn
get
(
&
self
)
->
<
Self
as
Get
>
::
Value
;
}
fn
foo
<
T
:
Get
>
(
t
:
T
)
{
let
x
=
t
.get
();
//~ ERROR the trait `core::kinds::Sized` is not implemented
}
fn
main
()
{
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录