Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
c886629d
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,发现更多精彩内容 >>
提交
c886629d
编写于
10月 08, 2012
作者:
P
Patrick Walton
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
rustc: Implement monomorphic default methods. r=nmatsakis
上级
2a1aa9fb
变更
22
隐藏空白更改
内联
并排
Showing
22 changed file
with
638 addition
and
300 deletion
+638
-300
src/rustc/metadata/common.rs
src/rustc/metadata/common.rs
+2
-0
src/rustc/metadata/csearch.rs
src/rustc/metadata/csearch.rs
+14
-0
src/rustc/metadata/decoder.rs
src/rustc/metadata/decoder.rs
+51
-3
src/rustc/metadata/encoder.rs
src/rustc/metadata/encoder.rs
+26
-4
src/rustc/middle/resolve.rs
src/rustc/middle/resolve.rs
+15
-6
src/rustc/middle/trans/base.rs
src/rustc/middle/trans/base.rs
+26
-68
src/rustc/middle/trans/callee.rs
src/rustc/middle/trans/callee.rs
+20
-8
src/rustc/middle/trans/closure.rs
src/rustc/middle/trans/closure.rs
+2
-2
src/rustc/middle/trans/common.rs
src/rustc/middle/trans/common.rs
+25
-5
src/rustc/middle/trans/expr.rs
src/rustc/middle/trans/expr.rs
+3
-1
src/rustc/middle/trans/foreign.rs
src/rustc/middle/trans/foreign.rs
+2
-2
src/rustc/middle/trans/inline.rs
src/rustc/middle/trans/inline.rs
+12
-7
src/rustc/middle/trans/meth.rs
src/rustc/middle/trans/meth.rs
+72
-19
src/rustc/middle/trans/monomorphize.rs
src/rustc/middle/trans/monomorphize.rs
+51
-12
src/rustc/middle/trans/type_use.rs
src/rustc/middle/trans/type_use.rs
+7
-2
src/rustc/middle/ty.rs
src/rustc/middle/ty.rs
+35
-16
src/rustc/middle/typeck.rs
src/rustc/middle/typeck.rs
+1
-8
src/rustc/middle/typeck/check/method.rs
src/rustc/middle/typeck/check/method.rs
+57
-15
src/rustc/middle/typeck/check/vtable.rs
src/rustc/middle/typeck/check/vtable.rs
+1
-1
src/rustc/middle/typeck/coherence.rs
src/rustc/middle/typeck/coherence.rs
+179
-116
src/rustc/middle/typeck/collect.rs
src/rustc/middle/typeck/collect.rs
+14
-5
src/test/run-pass/default-method-simple.rs
src/test/run-pass/default-method-simple.rs
+23
-0
未找到文件。
src/rustc/metadata/common.rs
浏览文件 @
c886629d
...
...
@@ -124,5 +124,7 @@ enum astencode_tag { // Reserves 0x50 -- 0x6f
tag_table_legacy_boxed_trait
=
0x63
}
const
tag_item_trait_method_sort
:
uint
=
0x70
;
type
link_meta
=
{
name
:
~
str
,
vers
:
~
str
,
extras_hash
:
~
str
};
src/rustc/metadata/csearch.rs
浏览文件 @
c886629d
...
...
@@ -23,6 +23,7 @@
export
get_enum_variants
;
export
get_impls_for_mod
;
export
get_trait_methods
;
export
get_provided_trait_methods
;
export
get_method_names_if_trait
;
export
get_item_attrs
;
export
each_path
;
...
...
@@ -31,6 +32,12 @@
export
get_impl_method
;
export
get_item_path
;
export
maybe_get_item_ast
,
found_ast
,
found
,
found_parent
,
not_found
;
export
ProvidedTraitMethodInfo
;
struct
ProvidedTraitMethodInfo
{
ty
:
ty
::
method
,
def_id
:
ast
::
def_id
}
fn
get_symbol
(
cstore
:
cstore
::
cstore
,
def
:
ast
::
def_id
)
->
~
str
{
let
cdata
=
cstore
::
get_crate_data
(
cstore
,
def
.crate
)
.data
;
...
...
@@ -99,6 +106,13 @@ fn get_trait_methods(tcx: ty::ctxt, def: ast::def_id) -> @~[ty::method] {
decoder
::
get_trait_methods
(
cstore
.intr
,
cdata
,
def
.node
,
tcx
)
}
fn
get_provided_trait_methods
(
tcx
:
ty
::
ctxt
,
def
:
ast
::
def_id
)
->
~
[
ProvidedTraitMethodInfo
]
{
let
cstore
=
tcx
.cstore
;
let
cdata
=
cstore
::
get_crate_data
(
cstore
,
def
.crate
);
decoder
::
get_provided_trait_methods
(
cstore
.intr
,
cdata
,
def
.node
,
tcx
)
}
fn
get_method_names_if_trait
(
cstore
:
cstore
::
cstore
,
def
:
ast
::
def_id
)
->
Option
<@
DVec
<
(
ast
::
ident
,
ast
::
self_ty_
)
>>
{
...
...
src/rustc/metadata/decoder.rs
浏览文件 @
c886629d
...
...
@@ -19,6 +19,7 @@
use
common
::
*
;
use
syntax
::
parse
::
token
::
ident_interner
;
use
hash
::{
Hash
,
HashUtil
};
use
csearch
::
ProvidedTraitMethodInfo
;
export
class_dtor
;
export
get_class_fields
;
...
...
@@ -40,6 +41,7 @@
export
get_crate_vers
;
export
get_impls_for_mod
;
export
get_trait_methods
;
export
get_provided_trait_methods
;
export
get_method_names_if_trait
;
export
get_item_attrs
;
export
get_crate_module_paths
;
...
...
@@ -164,6 +166,13 @@ fn item_family(item: ebml::Doc) -> Family {
}
}
fn
item_method_sort
(
item
:
ebml
::
Doc
)
->
char
{
for
ebml
::
tagged_docs
(
item
,
tag_item_trait_method_sort
)
|
doc
|
{
return
str
::
from_bytes
(
ebml
::
doc_data
(
doc
))[
0
]
as
char
;
}
return
'r'
;
}
fn
item_symbol
(
item
:
ebml
::
Doc
)
->
~
str
{
let
sym
=
ebml
::
get_doc
(
item
,
tag_items_data_item_symbol
);
return
str
::
from_bytes
(
ebml
::
doc_data
(
sym
));
...
...
@@ -701,6 +710,7 @@ fn get_trait_methods(intr: @ident_interner, cdata: cmd, id: ast::node_id,
let
bounds
=
item_ty_param_bounds
(
mth
,
tcx
,
cdata
);
let
name
=
item_name
(
intr
,
mth
);
let
ty
=
doc_type
(
mth
,
tcx
,
cdata
);
let
def_id
=
item_def_id
(
mth
,
cdata
);
let
fty
=
match
ty
::
get
(
ty
)
.sty
{
ty
::
ty_fn
(
f
)
=>
f
,
_
=>
{
...
...
@@ -708,14 +718,52 @@ fn get_trait_methods(intr: @ident_interner, cdata: cmd, id: ast::node_id,
~
"get_trait_methods: id has non-function type"
);
}
};
let
self_ty
=
get_self_ty
(
mth
);
result
.push
({
ident
:
name
,
tps
:
bounds
,
fty
:
fty
,
self_ty
:
self_ty
,
vis
:
ast
::
public
});
result
.push
({
ident
:
name
,
tps
:
bounds
,
fty
:
fty
,
self_ty
:
self_ty
,
vis
:
ast
::
public
,
def_id
:
def_id
});
}
debug!
(
"get_trait_methods: }"
);
@
result
}
fn
get_provided_trait_methods
(
intr
:
@
ident_interner
,
cdata
:
cmd
,
id
:
ast
::
node_id
,
tcx
:
ty
::
ctxt
)
->
~
[
ProvidedTraitMethodInfo
]
{
let
data
=
cdata
.data
;
let
item
=
lookup_item
(
id
,
data
);
let
mut
result
=
~
[];
for
ebml
::
tagged_docs
(
item
,
tag_item_trait_method
)
|
mth
|
{
if
item_method_sort
(
mth
)
!=
'p'
{
loop
;
}
let
did
=
item_def_id
(
mth
,
cdata
);
let
bounds
=
item_ty_param_bounds
(
mth
,
tcx
,
cdata
);
let
name
=
item_name
(
intr
,
mth
);
let
ty
=
doc_type
(
mth
,
tcx
,
cdata
);
let
fty
;
match
ty
::
get
(
ty
)
.sty
{
ty
::
ty_fn
(
f
)
=>
fty
=
f
,
_
=>
{
tcx
.diag
.handler
()
.bug
(
~
"get_provided_trait_methods(): id
\
has non-function type"
);
}
}
let
self_ty
=
get_self_ty
(
mth
);
let
ty_method
=
{
ident
:
name
,
tps
:
bounds
,
fty
:
fty
,
self_ty
:
self_ty
,
vis
:
ast
::
public
,
def_id
:
did
};
let
provided_trait_method_info
=
ProvidedTraitMethodInfo
{
ty
:
ty_method
,
def_id
:
did
};
vec
::
push
(
&
mut
result
,
move
provided_trait_method_info
);
}
return
move
result
;
}
// If the item in question is a trait, returns its set of methods and
// their self types. Otherwise, returns none. This overlaps in an
// annoying way with get_trait_methods.
...
...
src/rustc/metadata/encoder.rs
浏览文件 @
c886629d
...
...
@@ -388,6 +388,12 @@ fn encode_self_type(ebml_w: ebml::Serializer, self_type: ast::self_ty_) {
ebml_w
.end_tag
();
}
fn
encode_method_sort
(
ebml_w
:
ebml
::
Serializer
,
sort
:
char
)
{
ebml_w
.start_tag
(
tag_item_trait_method_sort
);
ebml_w
.writer
.write
(
&
[
sort
as
u8
]);
ebml_w
.end_tag
();
}
/* Returns an index of items in this class */
fn
encode_info_for_class
(
ecx
:
@
encode_ctxt
,
ebml_w
:
ebml
::
Serializer
,
id
:
node_id
,
path
:
ast_map
::
path
,
...
...
@@ -726,6 +732,8 @@ fn add_to_index_(item: @item, ebml_w: ebml::Serializer,
}
}
item_trait
(
tps
,
traits
,
ms
)
=>
{
let
provided_methods
=
dvec
::
DVec
();
add_to_index
();
ebml_w
.start_tag
(
tag_items_data_item
);
encode_def_id
(
ebml_w
,
local_def
(
item
.id
));
...
...
@@ -746,12 +754,21 @@ fn add_to_index_(item: @item, ebml_w: ebml::Serializer,
encode_type
(
ecx
,
ebml_w
,
ty
::
mk_fn
(
tcx
,
mty
.fty
));
encode_family
(
ebml_w
,
purity_fn_family
(
mty
.fty.meta.purity
));
encode_self_type
(
ebml_w
,
mty
.self_ty
);
encode_method_sort
(
ebml_w
,
'r'
);
ebml_w
.end_tag
();
}
provided
(
m
)
=>
{
encode_info_for_method
(
ecx
,
ebml_w
,
path
,
should_inline
(
m
.attrs
),
item
.id
,
m
,
m
.tps
);
provided_methods
.push
(
m
);
ebml_w
.start_tag
(
tag_item_trait_method
);
encode_def_id
(
ebml_w
,
local_def
(
m
.id
));
encode_name
(
ecx
,
ebml_w
,
mty
.ident
);
encode_type_param_bounds
(
ebml_w
,
ecx
,
m
.tps
);
encode_type
(
ecx
,
ebml_w
,
ty
::
mk_fn
(
tcx
,
mty
.fty
));
encode_family
(
ebml_w
,
purity_fn_family
(
mty
.fty.meta.purity
));
encode_self_type
(
ebml_w
,
mty
.self_ty
);
encode_method_sort
(
ebml_w
,
'p'
);
ebml_w
.end_tag
();
}
}
i
+=
1u
;
...
...
@@ -785,7 +802,12 @@ fn add_to_index_(item: @item, ebml_w: ebml::Serializer,
ebml_w
.end_tag
();
}
// Finally, output all the provided methods as items.
for
provided_methods
.each
|
m
|
{
index
.push
({
val
:
m
.id
,
pos
:
ebml_w
.writer
.tell
()});
encode_info_for_method
(
ecx
,
ebml_w
,
path
,
true
,
item
.id
,
*
m
,
m
.tps
);
}
}
item_mac
(
*
)
=>
fail
~
"item macros unimplemented"
}
...
...
src/rustc/middle/resolve.rs
浏览文件 @
c886629d
...
...
@@ -4680,6 +4680,9 @@ fn record_candidate_traits_for_expr_if_necessary(expr: @expr) {
}
fn
search_for_traits_containing_method
(
name
:
ident
)
->
@
DVec
<
def_id
>
{
debug!
(
"(searching for traits containing method) looking for '%s'"
,
self
.session
.str_of
(
name
));
let
found_traits
=
@
DVec
();
let
mut
search_module
=
self
.current_module
;
loop
{
...
...
@@ -4687,8 +4690,8 @@ fn search_for_traits_containing_method(name: ident) -> @DVec<def_id> {
match
copy
self
.current_trait_refs
{
Some
(
trait_def_ids
)
=>
{
for
trait_def_ids
.each
|
trait_def_id
|
{
self
.add_trait_info_if_containing_method
(
found_traits
,
*
trait_def_id
,
name
);
self
.add_trait_info_if_containing_method
(
found_traits
,
*
trait_def_id
,
name
);
}
}
None
=>
{
...
...
@@ -4702,8 +4705,8 @@ fn search_for_traits_containing_method(name: ident) -> @DVec<def_id> {
Some
(
def
)
=>
{
match
def
.def
{
def_ty
(
trait_def_id
)
=>
{
self
.add_trait_info_if_containing_method
(
found_traits
,
trait_def_id
,
name
);
self
.add_trait_info_if_containing_method
(
found_traits
,
trait_def_id
,
name
);
}
_
=>
{
// Continue.
...
...
@@ -4730,8 +4733,8 @@ fn search_for_traits_containing_method(name: ident) -> @DVec<def_id> {
match
def
.def
{
def_ty
(
trait_def_id
)
=>
{
self
.
add_trait_info_if_containing_method
(
found_traits
,
trait_def_id
,
name
);
add_trait_info_if_containing_method
(
found_traits
,
trait_def_id
,
name
);
}
_
=>
{
// Continue.
...
...
@@ -4766,6 +4769,12 @@ fn add_trait_info_if_containing_method(found_traits: @DVec<def_id>,
trait_def_id
:
def_id
,
name
:
ident
)
{
debug!
(
"(adding trait info if containing method) trying trait %d:%d
\
for method '%s'"
,
trait_def_id
.crate
,
trait_def_id
.node
,
self
.session
.str_of
(
name
));
match
self
.trait_info
.find
(
trait_def_id
)
{
Some
(
trait_info
)
if
trait_info
.contains_key
(
name
)
=>
{
debug!
(
"(adding trait info if containing method) found trait
\
...
...
src/rustc/middle/trans/base.rs
浏览文件 @
c886629d
...
...
@@ -206,7 +206,7 @@ fn GEP_enum(bcx: block, llblobptr: ValueRef, enum_id: ast::def_id,
assert
ix
<
variant
.args
.len
();
let
arg_lltys
=
vec
::
map
(
variant
.args
,
|
aty
|
{
type_of
(
ccx
,
ty
::
subst_tps
(
ccx
.tcx
,
ty_substs
,
*
aty
))
type_of
(
ccx
,
ty
::
subst_tps
(
ccx
.tcx
,
ty_substs
,
None
,
*
aty
))
});
let
typed_blobptr
=
PointerCast
(
bcx
,
llblobptr
,
T_ptr
(
T_struct
(
arg_lltys
)));
...
...
@@ -385,16 +385,16 @@ fn get_res_dtor(ccx: @crate_ctxt, did: ast::def_id,
let
_
icx
=
ccx
.insn_ctxt
(
"trans_res_dtor"
);
if
(
substs
.is_not_empty
())
{
let
did
=
if
did
.crate
!=
ast
::
local_crate
{
inline
::
maybe_instantiate_inline
(
ccx
,
did
)
inline
::
maybe_instantiate_inline
(
ccx
,
did
,
true
)
}
else
{
did
};
assert
did
.crate
==
ast
::
local_crate
;
monomorphize
::
monomorphic_fn
(
ccx
,
did
,
substs
,
None
,
None
)
.val
monomorphize
::
monomorphic_fn
(
ccx
,
did
,
substs
,
None
,
None
,
None
)
.val
}
else
if
did
.crate
==
ast
::
local_crate
{
get_item_val
(
ccx
,
did
.node
)
}
else
{
let
tcx
=
ccx
.tcx
;
let
name
=
csearch
::
get_symbol
(
ccx
.sess.cstore
,
did
);
let
class_ty
=
ty
::
subst_tps
(
tcx
,
substs
,
let
class_ty
=
ty
::
subst_tps
(
tcx
,
substs
,
None
,
ty
::
lookup_item_type
(
tcx
,
parent_id
)
.ty
);
let
llty
=
type_of_dtor
(
ccx
,
class_ty
);
get_extern_fn
(
ccx
.externs
,
ccx
.llmod
,
name
,
lib
::
llvm
::
CCallConv
,
...
...
@@ -529,7 +529,8 @@ fn iter_variant(cx: block, a_tup: ValueRef,
let
v_id
=
variant
.id
;
for
vec
::
each
(
fn_ty
.sig.inputs
)
|
a
|
{
let
llfldp_a
=
GEP_enum
(
cx
,
a_tup
,
tid
,
v_id
,
tps
,
j
);
let
ty_subst
=
ty
::
subst_tps
(
ccx
.tcx
,
tps
,
a
.ty
);
// XXX: Is "None" right here?
let
ty_subst
=
ty
::
subst_tps
(
ccx
.tcx
,
tps
,
None
,
a
.ty
);
cx
=
f
(
cx
,
llfldp_a
,
ty_subst
);
j
+=
1u
;
}
...
...
@@ -1392,8 +1393,11 @@ fn mk_standard_basic_blocks(llfn: ValueRef) ->
// - create_llargs_for_fn_args.
// - new_fn_ctxt
// - trans_args
fn
new_fn_ctxt_w_id
(
ccx
:
@
crate_ctxt
,
path
:
path
,
llfndecl
:
ValueRef
,
id
:
ast
::
node_id
,
fn
new_fn_ctxt_w_id
(
ccx
:
@
crate_ctxt
,
path
:
path
,
llfndecl
:
ValueRef
,
id
:
ast
::
node_id
,
impl_id
:
Option
<
ast
::
def_id
>
,
param_substs
:
Option
<
param_substs
>
,
sp
:
Option
<
span
>
)
->
fn_ctxt
{
let
llbbs
=
mk_standard_basic_blocks
(
llfndecl
);
...
...
@@ -1410,6 +1414,7 @@ fn new_fn_ctxt_w_id(ccx: @crate_ctxt, path: path,
lllocals
:
HashMap
(),
llupvars
:
HashMap
(),
id
:
id
,
impl_id
:
impl_id
,
param_substs
:
param_substs
,
span
:
sp
,
path
:
path
,
...
...
@@ -1418,7 +1423,7 @@ fn new_fn_ctxt_w_id(ccx: @crate_ctxt, path: path,
fn
new_fn_ctxt
(
ccx
:
@
crate_ctxt
,
path
:
path
,
llfndecl
:
ValueRef
,
sp
:
Option
<
span
>
)
->
fn_ctxt
{
return
new_fn_ctxt_w_id
(
ccx
,
path
,
llfndecl
,
-
1
,
None
,
sp
);
return
new_fn_ctxt_w_id
(
ccx
,
path
,
llfndecl
,
-
1
,
None
,
None
,
sp
);
}
// NB: must keep 4 fns in sync:
...
...
@@ -1561,6 +1566,7 @@ fn trans_closure(ccx: @crate_ctxt, path: path, decl: ast::fn_decl,
ty_self
:
self_arg
,
param_substs
:
Option
<
param_substs
>
,
id
:
ast
::
node_id
,
impl_id
:
Option
<
ast
::
def_id
>
,
maybe_load_env
:
fn
(
fn_ctxt
),
finish
:
fn
(
block
))
{
ccx
.stats.n_closures
+=
1
;
...
...
@@ -1568,7 +1574,7 @@ fn trans_closure(ccx: @crate_ctxt, path: path, decl: ast::fn_decl,
set_uwtable
(
llfndecl
);
// Set up arguments to the function.
let
fcx
=
new_fn_ctxt_w_id
(
ccx
,
path
,
llfndecl
,
id
,
param_substs
,
let
fcx
=
new_fn_ctxt_w_id
(
ccx
,
path
,
llfndecl
,
id
,
impl_id
,
param_substs
,
Some
(
body
.span
));
let
raw_llargs
=
create_llargs_for_fn_args
(
fcx
,
ty_self
,
decl
.inputs
);
...
...
@@ -1620,14 +1626,15 @@ fn trans_fn(ccx: @crate_ctxt,
llfndecl
:
ValueRef
,
ty_self
:
self_arg
,
param_substs
:
Option
<
param_substs
>
,
id
:
ast
::
node_id
)
{
id
:
ast
::
node_id
,
impl_id
:
Option
<
ast
::
def_id
>
)
{
let
do_time
=
ccx
.sess
.trans_stats
();
let
start
=
if
do_time
{
time
::
get_time
()
}
else
{
{
sec
:
0i64
,
nsec
:
0i32
}
};
let
_
icx
=
ccx
.insn_ctxt
(
"trans_fn"
);
ccx
.stats.n_fns
+=
1
;
trans_closure
(
ccx
,
path
,
decl
,
body
,
llfndecl
,
ty_self
,
param_substs
,
id
,
param_substs
,
id
,
impl_id
,
|
fcx
|
{
if
ccx
.sess.opts.extra_debuginfo
{
debuginfo
::
create_function
(
fcx
);
...
...
@@ -1654,7 +1661,7 @@ fn trans_enum_variant(ccx: @crate_ctxt,
ty
:
varg
.ty
,
ident
:
special_idents
::
arg
,
id
:
varg
.id
});
let
fcx
=
new_fn_ctxt_w_id
(
ccx
,
~
[],
llfndecl
,
variant
.node.id
,
let
fcx
=
new_fn_ctxt_w_id
(
ccx
,
~
[],
llfndecl
,
variant
.node.id
,
None
,
param_substs
,
None
);
let
raw_llargs
=
create_llargs_for_fn_args
(
fcx
,
no_self
,
fn_args
);
let
ty_param_substs
=
match
param_substs
{
...
...
@@ -1704,7 +1711,7 @@ fn trans_class_dtor(ccx: @crate_ctxt, path: path,
let
mut
class_ty
=
ty
::
lookup_item_type
(
tcx
,
parent_id
)
.ty
;
/* Substitute in the class type if necessary */
do
option
::
iter
(
&
psubsts
)
|
ss
|
{
class_ty
=
ty
::
subst_tps
(
tcx
,
ss
.tys
,
class_ty
);
class_ty
=
ty
::
subst_tps
(
tcx
,
ss
.tys
,
ss
.self_ty
,
class_ty
);
}
/* The dtor takes a (null) output pointer, and a self argument,
...
...
@@ -1724,7 +1731,7 @@ fn trans_class_dtor(ccx: @crate_ctxt, path: path,
}
/* Translate the dtor body */
trans_fn
(
ccx
,
path
,
ast_util
::
dtor_dec
(),
body
,
lldecl
,
impl_self
(
class_ty
),
psubsts
,
dtor_id
);
body
,
lldecl
,
impl_self
(
class_ty
),
psubsts
,
dtor_id
,
None
);
lldecl
}
...
...
@@ -1777,7 +1784,7 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) {
let
llfndecl
=
get_item_val
(
ccx
,
item
.id
);
trans_fn
(
ccx
,
vec
::
append
(
*
path
,
~
[
path_name
(
item
.ident
)]),
decl
,
body
,
llfndecl
,
no_self
,
None
,
item
.id
);
decl
,
body
,
llfndecl
,
no_self
,
None
,
item
.id
,
None
);
}
else
{
for
vec
::
each
(
body
.node.stmts
)
|
stmt
|
{
match
stmt
.node
{
...
...
@@ -1789,48 +1796,8 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) {
}
}
}
ast
::
item_impl
(
tps
,
trait_refs
,
self_ast_ty
,
ms
)
=>
{
meth
::
trans_impl
(
ccx
,
*
path
,
item
.ident
,
ms
,
tps
,
None
);
// Translate any methods that have provided implementations.
for
trait_refs
.each
|
trait_ref_ptr
|
{
let
trait_def
=
ccx
.tcx.def_map
.get
(
trait_ref_ptr
.ref_id
);
// XXX: Cross-crate default methods.
let
trait_id
=
def_id_of_def
(
trait_def
);
if
trait_id
.crate
!=
ast
::
local_crate
{
loop
;
}
// Get the self type.
let
self_ty
;
match
ccx
.tcx.ast_ty_to_ty_cache
.get
(
self_ast_ty
)
{
ty
::
atttce_resolved
(
self_type
)
=>
self_ty
=
self_type
,
ty
::
atttce_unresolved
=>
{
ccx
.tcx.sess
.impossible_case
(
item
.span
,
~
"didn't cache self ast ty"
);
}
}
match
ccx
.tcx.items
.get
(
trait_id
.node
)
{
ast_map
::
node_item
(
trait_item
,
_
)
=>
{
match
trait_item
.node
{
ast
::
item_trait
(
tps
,
_
,
trait_methods
)
=>
{
trans_trait
(
ccx
,
tps
,
trait_methods
,
path
,
item
.ident
,
self_ty
);
}
_
=>
{
ccx
.tcx.sess
.impossible_case
(
item
.span
,
~
"trait item not a
\
trait"
);
}
}
}
_
=>
{
ccx
.tcx.sess
.impossible_case
(
item
.span
,
~
"no trait item"
);
}
}
}
ast
::
item_impl
(
tps
,
_
,
_
,
ms
)
=>
{
meth
::
trans_impl
(
ccx
,
*
path
,
item
.ident
,
ms
,
tps
,
None
,
item
.id
);
}
ast
::
item_mod
(
m
)
=>
{
trans_mod
(
ccx
,
m
);
...
...
@@ -1871,16 +1838,7 @@ fn trans_struct_def(ccx: @crate_ctxt, struct_def: @ast::struct_def,
// If there are ty params, the ctor will get monomorphized
// Translate methods
meth
::
trans_impl
(
ccx
,
*
path
,
ident
,
struct_def
.methods
,
tps
,
None
);
}
fn
trans_trait
(
ccx
:
@
crate_ctxt
,
tps
:
~
[
ast
::
ty_param
],
trait_methods
:
~
[
ast
::
trait_method
],
path
:
@
ast_map
::
path
,
ident
:
ast
::
ident
,
self_ty
:
ty
::
t
)
{
// Translate any methods that have provided implementations
let
(
_
,
provided_methods
)
=
ast_util
::
split_trait_methods
(
trait_methods
);
meth
::
trans_impl
(
ccx
,
*
path
,
ident
,
provided_methods
,
tps
,
Some
(
self_ty
));
meth
::
trans_impl
(
ccx
,
*
path
,
ident
,
struct_def
.methods
,
tps
,
None
,
id
);
}
// Translate a module. Doing this amounts to translating the items in the
...
...
@@ -2035,7 +1993,7 @@ fn get_dtor_symbol(ccx: @crate_ctxt, path: path, id: ast::node_id,
// this to item_symbols
match
substs
{
Some
(
ss
)
=>
{
let
mono_ty
=
ty
::
subst_tps
(
ccx
.tcx
,
ss
.tys
,
t
);
let
mono_ty
=
ty
::
subst_tps
(
ccx
.tcx
,
ss
.tys
,
ss
.self_ty
,
t
);
mangle_exported_name
(
ccx
,
vec
::
append
(
path
,
...
...
src/rustc/middle/trans/callee.rs
浏览文件 @
c886629d
...
...
@@ -184,21 +184,31 @@ fn trans_fn_ref_with_vtables(
// Polytype of the function item (may have type params)
let
fn_tpt
=
ty
::
lookup_item_type
(
tcx
,
def_id
);
// Modify the def_id if this is a default method; we want to be
// monomorphizing the trait's code.
let
(
def_id
,
opt_impl_did
)
=
match
tcx
.provided_method_sources
.find
(
def_id
)
{
None
=>
(
def_id
,
None
),
Some
(
source
)
=>
(
source
.method_id
,
Some
(
source
.impl_id
))
};
// Check whether this fn has an inlined copy and, if so, redirect
// def_id to the local id of the inlined copy.
let
def_id
=
{
if
def_id
.crate
!=
ast
::
local_crate
{
inline
::
maybe_instantiate_inline
(
ccx
,
def_id
)
let
may_translate
=
opt_impl_did
.is_none
();
inline
::
maybe_instantiate_inline
(
ccx
,
def_id
,
may_translate
)
}
else
{
def_id
}
};
// We must monomorphise if the fn has type parameters or is a rust
// intrinsic. In particular, if we see an intrinsic that is
// inlined from a different crate, we want to reemit the intrinsic
// instead of trying to call it in the other crate.
let
must_monomorphise
=
type_params
.len
()
>
0
||
{
// We must monomorphise if the fn has type parameters, is a rust
// intrinsic, or is a default method. In particular, if we see an
// intrinsic that is inlined from a different crate, we want to reemit the
// intrinsic instead of trying to call it in the other crate.
let
must_monomorphise
=
type_params
.len
()
>
0
||
opt_impl_did
.is_some
()
||
{
if
def_id
.crate
==
ast
::
local_crate
{
let
map_node
=
session
::
expect
(
ccx
.sess
,
...
...
@@ -222,7 +232,7 @@ fn trans_fn_ref_with_vtables(
let
mut
{
val
,
must_cast
}
=
monomorphize
::
monomorphic_fn
(
ccx
,
def_id
,
type_params
,
vtables
,
Some
(
ref_id
));
vtables
,
opt_impl_did
,
Some
(
ref_id
));
if
must_cast
&&
ref_id
!=
0
{
// Monotype of the REFERENCE to the function (type params
// are subst'd)
...
...
@@ -317,7 +327,9 @@ fn trans_rtcall_or_lang_call_with_type_params(bcx: block,
match
callee
.data
{
Fn
(
fn_data
)
=>
{
let
substituted
=
ty
::
subst_tps
(
callee
.bcx
.tcx
(),
type_params
,
fty
);
type_params
,
None
,
fty
);
let
mut
llfnty
=
type_of
::
type_of
(
callee
.bcx
.ccx
(),
substituted
);
llfnty
=
T_ptr
(
struct_elt
(
llfnty
,
0
));
...
...
src/rustc/middle/trans/closure.rs
浏览文件 @
c886629d
...
...
@@ -372,7 +372,7 @@ fn trans_expr_fn(bcx: block,
let
{
llbox
,
cdata_ty
,
bcx
}
=
build_closure
(
bcx
,
cap_vars
,
ck
,
ret_handle
);
trans_closure
(
ccx
,
sub_path
,
decl
,
body
,
llfn
,
no_self
,
bcx
.fcx.param_substs
,
id
,
|
fcx
|
{
bcx
.fcx.param_substs
,
id
,
None
,
|
fcx
|
{
load_environment
(
fcx
,
cdata_ty
,
cap_vars
,
ret_handle
.is_some
(),
ck
);
},
|
bcx
|
{
...
...
@@ -395,7 +395,7 @@ fn trans_expr_fn(bcx: block,
}
ty
::
proto_bare
=>
{
trans_closure
(
ccx
,
sub_path
,
decl
,
body
,
llfn
,
no_self
,
None
,
id
,
|
_
fcx
|
{
},
|
_
bcx
|
{
});
id
,
None
,
|
_
fcx
|
{
},
|
_
bcx
|
{
});
rslt
(
bcx
,
C_null
(
T_opaque_box_ptr
(
ccx
)))
}
ty
::
proto_vstore
(
ty
::
vstore_fixed
(
_
))
=>
{
...
...
src/rustc/middle/trans/common.rs
浏览文件 @
c886629d
...
...
@@ -181,9 +181,12 @@ struct ValSelfData {
enum
local_val
{
local_mem
(
ValueRef
),
local_imm
(
ValueRef
),
}
// Here `self_ty` is the real type of the self parameter to this method. It
// will only be set in the case of default methods.
type
param_substs
=
{
tys
:
~
[
ty
::
t
],
vtables
:
Option
<
typeck
::
vtable_res
>
,
bounds
:
@~
[
ty
::
param_bounds
]};
bounds
:
@~
[
ty
::
param_bounds
],
self_ty
:
Option
<
ty
::
t
>
};
fn
param_substs_to_str
(
tcx
:
ty
::
ctxt
,
substs
:
&
param_substs
)
->
~
str
{
fmt!
(
"param_substs {tys:%?, vtables:%?, bounds:%?}"
,
...
...
@@ -220,6 +223,10 @@ fn param_substs_to_str(tcx: ty::ctxt, substs: ¶m_substs) -> ~str {
mut
llreturn
:
BasicBlockRef
,
// The 'self' value currently in use in this function, if there
// is one.
//
// NB: This is the type of the self *variable*, not the self *type*. The
// self type is set only for default methods, while the self variable is
// set for all methods.
mut
llself
:
Option
<
ValSelfData
>
,
// The a value alloca'd for calls to upcalls.rust_personality. Used when
// outputting the resume instruction.
...
...
@@ -240,6 +247,9 @@ fn param_substs_to_str(tcx: ty::ctxt, substs: ¶m_substs) -> ~str {
// a user-defined function.
id
:
ast
::
node_id
,
// The def_id of the impl we're inside, or None if we aren't inside one.
impl_id
:
Option
<
ast
::
def_id
>
,
// If this function is being monomorphized, this contains the type
// substitutions used.
param_substs
:
Option
<
param_substs
>
,
...
...
@@ -1110,7 +1120,11 @@ enum mono_param_id {
datum
::
DatumMode
),
}
type
mono_id_
=
{
def
:
ast
::
def_id
,
params
:
~
[
mono_param_id
]};
type
mono_id_
=
{
def
:
ast
::
def_id
,
params
:
~
[
mono_param_id
],
impl_did_opt
:
Option
<
ast
::
def_id
>
};
type
mono_id
=
@
mono_id_
;
...
...
@@ -1193,7 +1207,9 @@ fn path_str(sess: session::session, p: path) -> ~str {
fn
monomorphize_type
(
bcx
:
block
,
t
:
ty
::
t
)
->
ty
::
t
{
match
bcx
.fcx.param_substs
{
Some
(
substs
)
=>
ty
::
subst_tps
(
bcx
.tcx
(),
substs
.tys
,
t
),
Some
(
substs
)
=>
{
ty
::
subst_tps
(
bcx
.tcx
(),
substs
.tys
,
substs
.self_ty
,
t
)
}
_
=>
{
assert
!
ty
::
type_has_params
(
t
);
t
}
}
}
...
...
@@ -1213,7 +1229,9 @@ fn node_id_type_params(bcx: block, id: ast::node_id) -> ~[ty::t] {
let
params
=
ty
::
node_id_to_type_params
(
tcx
,
id
);
match
bcx
.fcx.param_substs
{
Some
(
substs
)
=>
{
vec
::
map
(
params
,
|
t
|
ty
::
subst_tps
(
tcx
,
substs
.tys
,
*
t
))
do
vec
::
map
(
params
)
|
t
|
{
ty
::
subst_tps
(
tcx
,
substs
.tys
,
substs
.self_ty
,
*
t
)
}
}
_
=>
params
}
...
...
@@ -1241,7 +1259,9 @@ fn resolve_vtable_in_fn_ctxt(fcx: fn_ctxt, vt: typeck::vtable_origin)
typeck
::
vtable_static
(
trait_id
,
tys
,
sub
)
=>
{
let
tys
=
match
fcx
.param_substs
{
Some
(
substs
)
=>
{
vec
::
map
(
tys
,
|
t
|
ty
::
subst_tps
(
tcx
,
substs
.tys
,
*
t
))
do
vec
::
map
(
tys
)
|
t
|
{
ty
::
subst_tps
(
tcx
,
substs
.tys
,
substs
.self_ty
,
*
t
)
}
}
_
=>
tys
};
...
...
src/rustc/middle/trans/expr.rs
浏览文件 @
c886629d
...
...
@@ -793,7 +793,9 @@ fn trans_local_var(bcx: block, def: ast::def) -> Datum {
// This cast should not be necessary. We should cast self *once*,
// but right now this conflicts with default methods.
let
llselfty
=
T_ptr
(
type_of
::
type_of
(
bcx
.ccx
(),
self_info
.t
));
let
real_self_ty
=
monomorphize_type
(
bcx
,
self_info
.t
);
let
llselfty
=
T_ptr
(
type_of
::
type_of
(
bcx
.ccx
(),
real_self_ty
));
let
casted_val
=
PointerCast
(
bcx
,
self_info
.v
,
llselfty
);
Datum
{
val
:
casted_val
,
...
...
src/rustc/middle/trans/foreign.rs
浏览文件 @
c886629d
...
...
@@ -794,7 +794,7 @@ fn trans_intrinsic(ccx: @crate_ctxt, decl: ValueRef, item: @ast::foreign_item,
{
debug!
(
"trans_intrinsic(item.ident=%s)"
,
ccx
.sess
.str_of
(
item
.ident
));
let
fcx
=
new_fn_ctxt_w_id
(
ccx
,
path
,
decl
,
item
.id
,
let
fcx
=
new_fn_ctxt_w_id
(
ccx
,
path
,
decl
,
item
.id
,
None
,
Some
(
substs
),
Some
(
item
.span
));
let
mut
bcx
=
top_scope_block
(
fcx
,
None
),
lltop
=
bcx
.llbb
;
match
ccx
.sess
.str_of
(
item
.ident
)
{
...
...
@@ -1025,7 +1025,7 @@ fn build_rust_fn(ccx: @crate_ctxt, path: ast_map::path,
)));
let
llty
=
type_of_fn_from_ty
(
ccx
,
t
);
let
llfndecl
=
decl_internal_cdecl_fn
(
ccx
.llmod
,
ps
,
llty
);
trans_fn
(
ccx
,
path
,
decl
,
body
,
llfndecl
,
no_self
,
None
,
id
);
trans_fn
(
ccx
,
path
,
decl
,
body
,
llfndecl
,
no_self
,
None
,
id
,
None
);
return
llfndecl
;
}
...
...
src/rustc/middle/trans/inline.rs
浏览文件 @
c886629d
...
...
@@ -5,9 +5,12 @@
use
base
::{
trans_item
,
get_item_val
,
self_arg
,
trans_fn
,
impl_self
,
get_insn_ctxt
};
fn
maybe_instantiate_inline
(
ccx
:
@
crate_ctxt
,
fn_id
:
ast
::
def_id
)
->
ast
::
def_id
{
// `translate` will be true if this function is allowed to translate the
// item and false otherwise. Currently, this parameter is set to false when
// translating default methods.
fn
maybe_instantiate_inline
(
ccx
:
@
crate_ctxt
,
fn_id
:
ast
::
def_id
,
translate
:
bool
)
->
ast
::
def_id
{
let
_
icx
=
ccx
.insn_ctxt
(
"maybe_instantiate_inline"
);
match
ccx
.external
.find
(
fn_id
)
{
Some
(
Some
(
node_id
))
=>
{
...
...
@@ -31,7 +34,7 @@ fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id)
csearch
::
found
(
ast
::
ii_item
(
item
))
=>
{
ccx
.external
.insert
(
fn_id
,
Some
(
item
.id
));
ccx
.stats.n_inlines
+=
1
;
trans_item
(
ccx
,
*
item
);
if
translate
{
trans_item
(
ccx
,
*
item
);
}
local_def
(
item
.id
)
}
csearch
::
found
(
ast
::
ii_foreign
(
item
))
=>
{
...
...
@@ -53,7 +56,7 @@ fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id)
_
=>
ccx
.sess
.bug
(
~
"maybe_instantiate_inline: item has a
\
non-enum parent"
)
}
trans_item
(
ccx
,
*
item
);
if
translate
{
trans_item
(
ccx
,
*
item
);
}
local_def
(
my_id
)
}
csearch
::
found_parent
(
_
,
_
)
=>
{
...
...
@@ -65,13 +68,14 @@ fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id)
ccx
.external
.insert
(
fn_id
,
Some
(
mth
.id
));
let
{
bounds
:
impl_bnds
,
region_param
:
_
,
ty
:
impl_ty
}
=
ty
::
lookup_item_type
(
ccx
.tcx
,
impl_did
);
if
(
*
impl_bnds
)
.len
()
+
mth
.tps
.len
()
==
0u
{
if
translate
&&
(
*
impl_bnds
)
.len
()
+
mth
.tps
.len
()
==
0u
{
let
llfn
=
get_item_val
(
ccx
,
mth
.id
);
let
path
=
vec
::
append
(
ty
::
item_path
(
ccx
.tcx
,
impl_did
),
~
[
path_name
(
mth
.ident
)]);
trans_fn
(
ccx
,
path
,
mth
.decl
,
mth
.body
,
llfn
,
impl_self
(
impl_ty
),
None
,
mth
.id
);
llfn
,
impl_self
(
impl_ty
),
None
,
mth
.id
,
Some
(
impl_did
));
}
local_def
(
mth
.id
)
}
...
...
@@ -83,3 +87,4 @@ fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id)
}
}
}
src/rustc/middle/trans/meth.rs
浏览文件 @
c886629d
...
...
@@ -28,7 +28,7 @@
*/
fn
trans_impl
(
ccx
:
@
crate_ctxt
,
path
:
path
,
name
:
ast
::
ident
,
methods
:
~
[
@
ast
::
method
],
tps
:
~
[
ast
::
ty_param
],
self_ty
:
Option
<
ty
::
t
>
)
{
self_ty
:
Option
<
ty
::
t
>
,
id
:
ast
::
node_id
)
{
let
_
icx
=
ccx
.insn_ctxt
(
"impl::trans_impl"
);
if
tps
.len
()
>
0u
{
return
;
}
let
sub_path
=
vec
::
append_one
(
path
,
path_name
(
name
));
...
...
@@ -36,7 +36,22 @@ fn trans_impl(ccx: @crate_ctxt, path: path, name: ast::ident,
if
method
.tps
.len
()
==
0u
{
let
llfn
=
get_item_val
(
ccx
,
method
.id
);
let
path
=
vec
::
append_one
(
sub_path
,
path_name
(
method
.ident
));
trans_method
(
ccx
,
path
,
*
method
,
None
,
self_ty
,
llfn
);
let
param_substs_opt
;
match
self_ty
{
None
=>
param_substs_opt
=
None
,
Some
(
self_ty
)
=>
{
param_substs_opt
=
Some
({
tys
:
~
[],
vtables
:
None
,
bounds
:
@~
[],
self_ty
:
Some
(
self_ty
)
});
}
}
trans_method
(
ccx
,
path
,
*
method
,
param_substs_opt
,
self_ty
,
llfn
,
ast_util
::
local_def
(
id
));
}
}
}
...
...
@@ -54,13 +69,15 @@ fn trans_impl(ccx: @crate_ctxt, path: path, name: ast::ident,
will be none if this is not a default method and must always be present
if this is a default method.
- `llfn`: the LLVM ValueRef for the method
- `impl_id`: the node ID of the impl this method is inside
*/
fn
trans_method
(
ccx
:
@
crate_ctxt
,
path
:
path
,
method
:
&
ast
::
method
,
param_substs
:
Option
<
param_substs
>
,
base_self_ty
:
Option
<
ty
::
t
>
,
llfn
:
ValueRef
)
{
llfn
:
ValueRef
,
impl_id
:
ast
::
def_id
)
{
// figure out how self is being passed
let
self_arg
=
match
method
.self_ty.node
{
...
...
@@ -76,8 +93,10 @@ fn trans_method(ccx: @crate_ctxt,
Some
(
provided_self_ty
)
=>
self_ty
=
provided_self_ty
}
let
self_ty
=
match
param_substs
{
None
=>
self_ty
,
Some
({
tys
:
ref
tys
,
_
})
=>
ty
::
subst_tps
(
ccx
.tcx
,
*
tys
,
self_ty
)
None
=>
self_ty
,
Some
({
tys
:
ref
tys
,
_
})
=>
{
ty
::
subst_tps
(
ccx
.tcx
,
*
tys
,
None
,
self_ty
)
}
};
match
method
.self_ty.node
{
ast
::
sty_value
=>
{
...
...
@@ -98,15 +117,20 @@ fn trans_method(ccx: @crate_ctxt,
llfn
,
self_arg
,
param_substs
,
method
.id
);
method
.id
,
Some
(
impl_id
));
}
fn
trans_self_arg
(
bcx
:
block
,
base
:
@
ast
::
expr
,
fn
trans_self_arg
(
bcx
:
block
,
base
:
@
ast
::
expr
,
mentry
:
typeck
::
method_map_entry
)
->
Result
{
let
_
icx
=
bcx
.insn_ctxt
(
"impl::trans_self_arg"
);
let
mut
temp_cleanups
=
~
[];
// Compute the mode and type of self.
let
self_arg
=
{
mode
:
mentry
.self_arg.mode
,
ty
:
monomorphize_type
(
bcx
,
mentry
.self_arg.ty
)};
let
result
=
trans_arg_expr
(
bcx
,
self_arg
,
base
,
&
mut
temp_cleanups
,
None
,
DontAutorefArg
);
...
...
@@ -120,11 +144,31 @@ fn trans_self_arg(bcx: block, base: @ast::expr,
}
fn
trans_method_callee
(
bcx
:
block
,
callee_id
:
ast
::
node_id
,
self
:
@
ast
::
expr
,
mentry
:
typeck
::
method_map_entry
)
->
Callee
{
self
:
@
ast
::
expr
,
mentry
:
typeck
::
method_map_entry
)
->
Callee
{
let
_
icx
=
bcx
.insn_ctxt
(
"impl::trans_method_callee"
);
match
mentry
.origin
{
// Replace method_self with method_static here.
let
mut
origin
=
mentry
.origin
;
match
origin
{
typeck
::
method_self
(
copy
trait_id
,
copy
method_index
)
=>
{
// Get the ID of the impl we're inside.
let
impl_def_id
=
bcx
.fcx.impl_id
.get
();
io
::
println
(
fmt!
(
"impl_def_id is %?"
,
impl_def_id
));
// Get the ID of the method we're calling.
let
method_name
=
ty
::
trait_methods
(
bcx
.tcx
(),
trait_id
)[
method_index
]
.ident
;
let
method_id
=
method_with_name
(
bcx
.ccx
(),
impl_def_id
,
method_name
);
origin
=
typeck
::
method_static
(
method_id
);
}
typeck
::
method_static
(
*
)
|
typeck
::
method_param
(
*
)
|
typeck
::
method_trait
(
*
)
=>
{}
}
match
origin
{
typeck
::
method_static
(
did
)
=>
{
let
callee_fn
=
callee
::
trans_fn_ref
(
bcx
,
did
,
callee_id
);
let
Result
{
bcx
,
val
}
=
trans_self_arg
(
bcx
,
self
,
mentry
);
...
...
@@ -155,7 +199,7 @@ fn trans_method_callee(bcx: block, callee_id: ast::node_id,
trans_trait_callee
(
bcx
,
callee_id
,
off
,
self
,
vstore
)
}
typeck
::
method_self
(
*
)
=>
{
bcx
.tcx
()
.sess
.span_bug
(
self
.span
,
~
"self method call"
);
fail
~
"method_self should have been handled above"
}
}
}
...
...
@@ -519,13 +563,21 @@ fn vtable_id(ccx: @crate_ctxt, origin: typeck::vtable_origin) -> mono_id {
match
origin
{
typeck
::
vtable_static
(
impl_id
,
substs
,
sub_vtables
)
=>
{
monomorphize
::
make_mono_id
(
ccx
,
impl_id
,
substs
,
if
(
*
sub_vtables
)
.len
()
==
0u
{
None
}
else
{
Some
(
sub_vtables
)
},
None
)
ccx
,
impl_id
,
substs
,
if
(
*
sub_vtables
)
.len
()
==
0u
{
None
}
else
{
Some
(
sub_vtables
)
},
None
,
None
)
}
typeck
::
vtable_trait
(
trait_id
,
substs
)
=>
{
@
{
def
:
trait_id
,
params
:
vec
::
map
(
substs
,
|
t
|
mono_precise
(
*
t
,
None
))}
params
:
vec
::
map
(
substs
,
|
t
|
mono_precise
(
*
t
,
None
)),
impl_did_opt
:
None
}
}
// can't this be checked at the callee?
_
=>
fail
~
"vtable_id"
...
...
@@ -571,7 +623,7 @@ fn make_impl_vtable(ccx: @crate_ctxt, impl_id: ast::def_id, substs: ~[ty::t],
let
has_tps
=
(
*
ty
::
lookup_item_type
(
ccx
.tcx
,
impl_id
)
.bounds
)
.len
()
>
0u
;
make_vtable
(
ccx
,
vec
::
map
(
*
ty
::
trait_methods
(
tcx
,
trt_id
),
|
im
|
{
let
fty
=
ty
::
subst_tps
(
tcx
,
substs
,
ty
::
mk_fn
(
tcx
,
im
.fty
));
let
fty
=
ty
::
subst_tps
(
tcx
,
substs
,
None
,
ty
::
mk_fn
(
tcx
,
im
.fty
));
if
(
*
im
.tps
)
.len
()
>
0u
||
ty
::
type_has_self
(
fty
)
{
C_null
(
T_ptr
(
T_nil
()))
}
else
{
...
...
@@ -580,10 +632,11 @@ fn make_impl_vtable(ccx: @crate_ctxt, impl_id: ast::def_id, substs: ~[ty::t],
// If the method is in another crate, need to make an inlined
// copy first
if
m_id
.crate
!=
ast
::
local_crate
{
m_id
=
inline
::
maybe_instantiate_inline
(
ccx
,
m_id
);
// XXX: Set impl ID here?
m_id
=
inline
::
maybe_instantiate_inline
(
ccx
,
m_id
,
true
);
}
monomorphize
::
monomorphic_fn
(
ccx
,
m_id
,
substs
,
Some
(
vtables
),
None
)
.val
Some
(
vtables
),
None
,
None
)
.val
}
else
if
m_id
.crate
==
ast
::
local_crate
{
get_item_val
(
ccx
,
m_id
.node
)
}
else
{
...
...
src/rustc/middle/trans/monomorphize.rs
浏览文件 @
c886629d
...
...
@@ -16,9 +16,9 @@ fn monomorphic_fn(ccx: @crate_ctxt,
fn_id
:
ast
::
def_id
,
real_substs
:
~
[
ty
::
t
],
vtables
:
Option
<
typeck
::
vtable_res
>
,
ref_id
:
Option
<
ast
::
node_id
>
)
->
{
val
:
ValueRef
,
must_cast
:
bool
}
{
impl_did_opt
:
Option
<
ast
::
def_id
>
,
ref_id
:
Option
<
ast
::
node_id
>
)
->
{
val
:
ValueRef
,
must_cast
:
bool
}
{
let
_
icx
=
ccx
.insn_ctxt
(
"monomorphic_fn"
);
let
mut
must_cast
=
false
;
let
substs
=
vec
::
map
(
real_substs
,
|
t
|
{
...
...
@@ -31,7 +31,8 @@ fn monomorphic_fn(ccx: @crate_ctxt,
for
real_substs
.each
()
|
s
|
{
assert
!
ty
::
type_has_params
(
*
s
);
}
for
substs
.each
()
|
s
|
{
assert
!
ty
::
type_has_params
(
*
s
);
}
let
param_uses
=
type_use
::
type_uses_for
(
ccx
,
fn_id
,
substs
.len
());
let
hash_id
=
make_mono_id
(
ccx
,
fn_id
,
substs
,
vtables
,
Some
(
param_uses
));
let
hash_id
=
make_mono_id
(
ccx
,
fn_id
,
substs
,
vtables
,
impl_did_opt
,
Some
(
param_uses
));
if
vec
::
any
(
hash_id
.params
,
|
p
|
match
*
p
{
mono_precise
(
_
,
_
)
=>
false
,
_
=>
true
})
{
must_cast
=
true
;
...
...
@@ -73,8 +74,11 @@ fn monomorphic_fn(ccx: @crate_ctxt,
}
ast_map
::
node_dtor
(
_
,
dtor
,
_
,
pt
)
=>
(
pt
,
special_idents
::
dtor
,
dtor
.span
),
ast_map
::
node_trait_method
(
*
)
=>
{
ccx
.tcx.sess
.bug
(
~
"Can't monomorphize a trait method"
)
ast_map
::
node_trait_method
(
@
ast
::
provided
(
m
),
_
,
pt
)
=>
{
(
pt
,
m
.ident
,
m
.span
)
}
ast_map
::
node_trait_method
(
@
ast
::
required
(
_
),
_
,
_
)
=>
{
ccx
.tcx.sess
.bug
(
~
"Can't monomorphize a required trait method"
)
}
ast_map
::
node_expr
(
*
)
=>
{
ccx
.tcx.sess
.bug
(
~
"Can't monomorphize an expr"
)
...
...
@@ -93,7 +97,18 @@ fn monomorphic_fn(ccx: @crate_ctxt,
ccx
.tcx.sess
.bug
(
~
"Can't monomorphize a local"
)
}
};
let
mono_ty
=
ty
::
subst_tps
(
ccx
.tcx
,
substs
,
llitem_ty
);
// Look up the impl type if we're translating a default method.
// XXX: Generics.
let
impl_ty_opt
;
match
impl_did_opt
{
None
=>
impl_ty_opt
=
None
,
Some
(
impl_did
)
=>
{
impl_ty_opt
=
Some
(
ty
::
lookup_item_type
(
ccx
.tcx
,
impl_did
)
.ty
);
}
}
let
mono_ty
=
ty
::
subst_tps
(
ccx
.tcx
,
substs
,
impl_ty_opt
,
llitem_ty
);
let
llfty
=
type_of_fn_from_ty
(
ccx
,
mono_ty
);
ccx
.stats.n_monos
+=
1
;
...
...
@@ -118,12 +133,18 @@ fn monomorphic_fn(ccx: @crate_ctxt,
lldecl
};
let
psubsts
=
Some
({
tys
:
substs
,
vtables
:
vtables
,
bounds
:
tpt
.bounds
});
let
psubsts
=
Some
({
tys
:
substs
,
vtables
:
vtables
,
bounds
:
tpt
.bounds
,
self_ty
:
impl_ty_opt
});
let
lldecl
=
match
map_node
{
ast_map
::
node_item
(
i
@@
{
node
:
ast
::
item_fn
(
decl
,
_
,
_
,
body
),
_
},
_
)
=>
{
let
d
=
mk_lldecl
();
set_inline_hint_if_appr
(
i
.attrs
,
d
);
trans_fn
(
ccx
,
pt
,
decl
,
body
,
d
,
no_self
,
psubsts
,
fn_id
.node
);
trans_fn
(
ccx
,
pt
,
decl
,
body
,
d
,
no_self
,
psubsts
,
fn_id
.node
,
None
);
d
}
ast_map
::
node_item
(
*
)
=>
{
...
...
@@ -154,11 +175,19 @@ fn monomorphic_fn(ccx: @crate_ctxt,
}
d
}
ast_map
::
node_method
(
mth
,
_
,
_
)
=>
{
ast_map
::
node_method
(
mth
,
supplied_impl_did
,
_
)
=>
{
// XXX: What should the self type be here?
let
d
=
mk_lldecl
();
set_inline_hint_if_appr
(
mth
.attrs
,
d
);
meth
::
trans_method
(
ccx
,
pt
,
mth
,
psubsts
,
None
,
d
);
// Override the impl def ID if necessary.
let
impl_did
;
match
impl_did_opt
{
None
=>
impl_did
=
supplied_impl_did
,
Some
(
override_impl_did
)
=>
impl_did
=
override_impl_did
}
meth
::
trans_method
(
ccx
,
pt
,
mth
,
psubsts
,
None
,
d
,
impl_did
);
d
}
ast_map
::
node_dtor
(
_
,
dtor
,
_
,
pt
)
=>
{
...
...
@@ -171,6 +200,15 @@ fn monomorphic_fn(ccx: @crate_ctxt,
trans_class_dtor
(
ccx
,
*
pt
,
dtor
.node.body
,
dtor
.node.id
,
psubsts
,
Some
(
hash_id
),
parent_id
)
}
ast_map
::
node_trait_method
(
@
ast
::
provided
(
mth
),
_
,
pt
)
=>
{
let
d
=
mk_lldecl
();
set_inline_hint_if_appr
(
mth
.attrs
,
d
);
io
::
println
(
fmt!
(
"monomorphic_fn impl_did_opt is %?"
,
impl_did_opt
));
meth
::
trans_method
(
ccx
,
*
pt
,
mth
,
psubsts
,
None
,
d
,
impl_did_opt
.get
());
d
}
// Ugh -- but this ensures any new variants won't be forgotten
ast_map
::
node_expr
(
*
)
|
ast_map
::
node_stmt
(
*
)
|
...
...
@@ -226,6 +264,7 @@ fn normalize_for_monomorphization(tcx: ty::ctxt, ty: ty::t) -> Option<ty::t> {
fn
make_mono_id
(
ccx
:
@
crate_ctxt
,
item
:
ast
::
def_id
,
substs
:
~
[
ty
::
t
],
vtables
:
Option
<
typeck
::
vtable_res
>
,
impl_did_opt
:
Option
<
ast
::
def_id
>
,
param_uses
:
Option
<~
[
type_use
::
type_uses
]
>
)
->
mono_id
{
let
precise_param_ids
=
match
vtables
{
Some
(
vts
)
=>
{
...
...
@@ -295,5 +334,5 @@ fn make_mono_id(ccx: @crate_ctxt, item: ast::def_id, substs: ~[ty::t],
})
}
};
@
{
def
:
item
,
params
:
param_ids
}
@
{
def
:
item
,
params
:
param_ids
,
impl_did_opt
:
impl_did_opt
}
}
src/rustc/middle/trans/type_use.rs
浏览文件 @
c886629d
...
...
@@ -40,8 +40,13 @@ fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint)
Some
(
uses
)
=>
return
uses
,
None
=>
()
}
let
fn_id_loc
=
if
fn_id
.crate
==
local_crate
{
fn_id
}
else
{
inline
::
maybe_instantiate_inline
(
ccx
,
fn_id
)
};
let
fn_id_loc
=
if
fn_id
.crate
==
local_crate
{
fn_id
}
else
{
inline
::
maybe_instantiate_inline
(
ccx
,
fn_id
,
true
)
};
// Conservatively assume full use for recursive loops
ccx
.type_use_cache
.insert
(
fn_id
,
vec
::
from_elem
(
n_tps
,
3u
));
...
...
src/rustc/middle/ty.rs
浏览文件 @
c886629d
...
...
@@ -19,6 +19,7 @@
use
syntax
::
print
::
pprust
::
*
;
use
util
::
ppaux
::{
ty_to_str
,
proto_ty_to_str
,
tys_to_str
};
export
ProvidedMethodSource
;
export
TyVid
,
IntVid
,
FnVid
,
RegionVid
,
vid
;
export
br_hashmap
;
export
is_instantiable
;
...
...
@@ -207,7 +208,8 @@
tps
:
@~
[
param_bounds
],
fty
:
FnTy
,
self_ty
:
ast
::
self_ty_
,
vis
:
ast
::
visibility
};
vis
:
ast
::
visibility
,
def_id
:
ast
::
def_id
};
type
mt
=
{
ty
:
t
,
mutbl
:
ast
::
mutability
};
...
...
@@ -314,6 +316,11 @@ enum AutoRefKind {
AutoPtr
}
struct
ProvidedMethodSource
{
method_id
:
ast
::
def_id
,
impl_id
:
ast
::
def_id
}
type
ctxt
=
@
{
diag
:
syntax
::
diagnostic
::
span_handler
,
interner
:
HashMap
<
intern_key
,
t_box
>
,
...
...
@@ -356,7 +363,8 @@ enum AutoRefKind {
adjustments
:
HashMap
<
ast
::
node_id
,
@
AutoAdjustment
>
,
normalized_cache
:
HashMap
<
t
,
t
>
,
lang_items
:
middle
::
lang_items
::
LanguageItems
,
legacy_boxed_traits
:
HashMap
<
node_id
,
()
>
};
legacy_boxed_traits
:
HashMap
<
node_id
,
()
>
,
provided_method_sources
:
HashMap
<
ast
::
def_id
,
ProvidedMethodSource
>
};
enum
tbox_flag
{
has_params
=
1
,
...
...
@@ -879,7 +887,8 @@ fn mk_ctxt(s: session::session,
adjustments
:
HashMap
(),
normalized_cache
:
new_ty_hash
(),
lang_items
:
move
lang_items
,
legacy_boxed_traits
:
HashMap
()}
legacy_boxed_traits
:
HashMap
(),
provided_method_sources
:
HashMap
()}
}
...
...
@@ -1392,13 +1401,23 @@ fn do_fold(cx: ctxt, t0: t, under_r: bool,
}
// Substitute *only* type parameters. Used in trans where regions are erased.
fn
subst_tps
(
cx
:
ctxt
,
tps
:
&
[
t
],
typ
:
t
)
->
t
{
if
tps
.len
()
==
0u
{
return
typ
;
}
fn
subst_tps
(
cx
:
ctxt
,
tps
:
&
[
t
],
self_ty_opt
:
Option
<
t
>
,
typ
:
t
)
->
t
{
if
tps
.len
()
==
0u
&&
self_ty_opt
.is_none
()
{
return
typ
;
}
let
tb
=
ty
::
get
(
typ
);
if
!
tbox_has_flag
(
tb
,
has_params
)
{
return
typ
;
}
if
self_ty_opt
.is_none
()
&&
!
tbox_has_flag
(
tb
,
has_params
)
{
return
typ
;
}
match
tb
.sty
{
ty_param
(
p
)
=>
tps
[
p
.idx
],
ref
sty
=>
fold_sty_to_ty
(
cx
,
sty
,
|
t
|
subst_tps
(
cx
,
tps
,
t
))
ty_param
(
p
)
=>
tps
[
p
.idx
],
ty_self
=>
{
match
self_ty_opt
{
None
=>
cx
.sess
.bug
(
~
"ty_self unexpected here"
),
Some
(
self_ty
)
=>
{
subst_tps
(
cx
,
tps
,
self_ty_opt
,
self_ty
)
}
}
}
ref
sty
=>
{
fold_sty_to_ty
(
cx
,
sty
,
|
t
|
subst_tps
(
cx
,
tps
,
self_ty_opt
,
t
))
}
}
}
...
...
@@ -3328,20 +3347,18 @@ fn store_trait_methods(cx: ctxt, id: ast::node_id, ms: @~[method]) {
cx
.trait_method_cache
.insert
(
ast_util
::
local_def
(
id
),
ms
);
}
fn
provided_trait_methods
(
cx
:
ctxt
,
id
:
ast
::
def_id
)
->
~
[
@
ast
::
method
]
{
fn
provided_trait_methods
(
cx
:
ctxt
,
id
:
ast
::
def_id
)
->
~
[
ast
::
ident
]
{
if
is_local
(
id
)
{
match
cx
.items
.find
(
id
.node
)
{
Some
(
ast_map
::
node_item
(
@
{
node
:
item_trait
(
_
,
_
,
ms
),
_
},
_
))
=>
match
ast_util
::
split_trait_methods
(
ms
)
{
(
_
,
p
)
=>
p
(
_
,
p
)
=>
p
.map
(|
method
|
method
.ident
)
},
_
=>
cx
.sess
.bug
(
fmt!
(
"provided_trait_methods: %? is not a trait"
,
id
))
}
}
else
{
// FIXME #2794: default methods for traits don't work cross-crate
~
[]
}
else
{
csearch
::
get_provided_trait_methods
(
cx
,
id
)
.map
(|
info
|
info
.ty.ident
)
}
}
...
...
@@ -3599,10 +3616,12 @@ fn enum_variant_with_id(cx: ctxt, enum_id: ast::def_id,
// the type cache. Returns the type parameters and type.
fn
lookup_item_type
(
cx
:
ctxt
,
did
:
ast
::
def_id
)
->
ty_param_bounds_and_ty
{
match
cx
.tcache
.find
(
did
)
{
Some
(
tpt
)
=>
return
tpt
,
None
=>
{
Some
(
tpt
)
=>
{
// The item is in this crate. The caller should have added it to the
// type cache already
return
tpt
;
}
None
=>
{
assert
did
.crate
!=
ast
::
local_crate
;
let
tyt
=
csearch
::
get_type
(
cx
,
did
);
cx
.tcache
.insert
(
did
,
tyt
);
...
...
src/rustc/middle/typeck.rs
浏览文件 @
c886629d
...
...
@@ -62,6 +62,7 @@
use
util
::
common
::{
indent
,
indenter
};
use
std
::
list
;
use
list
::{
List
,
Nil
,
Cons
};
use
dvec
::
DVec
;
export
check_crate
;
export
infer
;
...
...
@@ -174,12 +175,6 @@ fn to_str(tcx: ty::ctxt) -> ~str {
type
vtable_map
=
HashMap
<
ast
::
node_id
,
vtable_res
>
;
// Stores information about provided methods, aka "default methods" in traits.
// Maps from a trait's def_id to a MethodInfo about
// that method in that trait.
type
provided_methods_map
=
HashMap
<
ast
::
node_id
,
~
[
@
resolve
::
MethodInfo
]
>
;
type
ty_param_substs_and_ty
=
{
substs
:
ty
::
substs
,
ty
:
ty
::
t
};
type
crate_ctxt_
=
{
// A mapping from method call sites to traits that have
...
...
@@ -188,7 +183,6 @@ fn to_str(tcx: ty::ctxt) -> ~str {
method_map
:
method_map
,
vtable_map
:
vtable_map
,
coherence_info
:
@
coherence
::
CoherenceInfo
,
provided_methods_map
:
provided_methods_map
,
tcx
:
ty
::
ctxt
};
enum
crate_ctxt
{
...
...
@@ -340,7 +334,6 @@ fn check_crate(tcx: ty::ctxt,
method_map
:
std
::
map
::
HashMap
(),
vtable_map
:
std
::
map
::
HashMap
(),
coherence_info
:
@
coherence
::
CoherenceInfo
(),
provided_methods_map
:
std
::
map
::
HashMap
(),
tcx
:
tcx
});
collect
::
collect_item_types
(
ccx
,
crate
);
coherence
::
check_coherence
(
ccx
,
crate
);
...
...
src/rustc/middle/typeck/check/method.rs
浏览文件 @
c886629d
...
...
@@ -69,7 +69,7 @@ trait `ToStr` imported, and I call `to_str()` on a value of type `T`,
*/
use
coherence
::
get_base_type_def_id
;
use
coherence
::
{
ProvidedMethodInfo
,
get_base_type_def_id
}
;
use
middle
::
resolve
::{
Impl
,
MethodInfo
};
use
middle
::
ty
::
*
;
use
syntax
::
ast
::{
def_id
,
sty_by_ref
,
sty_value
,
sty_region
,
sty_box
,
...
...
@@ -146,7 +146,7 @@ fn do_lookup(&self, self_ty: ty::t) -> Option<method_map_entry> {
// Prepare the list of candidates
self
.push_inherent_candidates
(
self_ty
);
self
.push_extension_candidates
();
self
.push_extension_candidates
(
self_ty
);
let
enum_dids
=
DVec
();
let
mut
self_ty
=
self_ty
;
...
...
@@ -251,7 +251,7 @@ fn push_inherent_candidates(&self, self_ty: ty::t) {
}
}
fn
push_extension_candidates
(
&
self
)
{
fn
push_extension_candidates
(
&
self
,
self_ty
:
ty
::
t
)
{
// If the method being called is associated with a trait, then
// find all the impls of that trait. Each of those are
// candidates.
...
...
@@ -259,6 +259,8 @@ fn push_extension_candidates(&self) {
for
opt_applicable_traits
.each
|
applicable_traits
|
{
for
applicable_traits
.each
|
trait_did
|
{
let
coherence_info
=
self
.fcx.ccx.coherence_info
;
// Look for explicit implementations.
let
opt_impl_infos
=
coherence_info
.extension_methods
.find
(
*
trait_did
);
for
opt_impl_infos
.each
|
impl_infos
|
{
...
...
@@ -267,12 +269,21 @@ fn push_extension_candidates(&self) {
&
self
.extension_candidates
,
*
impl_info
);
}
}
// Look for default methods.
match
coherence_info
.provided_methods
.find
(
*
trait_did
)
{
Some
(
methods
)
=>
{
self
.push_candidates_from_provided_methods
(
&
self
.extension_candidates
,
self_ty
,
*
trait_did
,
methods
);
}
None
=>
{}
}
}
}
}
fn
push_inherent_candidates_from_param
(
&
self
,
param_ty
:
param_ty
)
{
fn
push_inherent_candidates_from_param
(
&
self
,
param_ty
:
param_ty
)
{
debug!
(
"push_inherent_candidates_from_param(param_ty=%?)"
,
param_ty
);
let
_
indenter
=
indenter
();
...
...
@@ -348,8 +359,7 @@ fn push_inherent_candidates_from_trait(&self,
self_ty
:
ty
::
t
,
did
:
def_id
,
substs
:
&
ty
::
substs
,
vstore
:
ty
::
vstore
)
{
vstore
:
ty
::
vstore
)
{
debug!
(
"push_inherent_candidates_from_trait(did=%s, substs=%s)"
,
self
.did_to_str
(
did
),
substs_to_str
(
self
.tcx
(),
substs
));
...
...
@@ -423,8 +433,7 @@ fn push_inherent_candidates_from_self(&self,
});
}
fn
push_inherent_impl_candidates_for_type
(
did
:
def_id
)
{
fn
push_inherent_impl_candidates_for_type
(
did
:
def_id
)
{
let
opt_impl_infos
=
self
.fcx.ccx.coherence_info.inherent_methods
.find
(
did
);
for
opt_impl_infos
.each
|
impl_infos
|
{
...
...
@@ -436,8 +445,7 @@ fn push_inherent_impl_candidates_for_type(did: def_id)
}
fn
push_candidates_from_impl
(
&
self
,
candidates
:
&
DVec
<
Candidate
>
,
impl_info
:
&
resolve
::
Impl
)
{
impl_info
:
&
resolve
::
Impl
)
{
if
!
self
.impl_dups
.insert
(
impl_info
.did
,
())
{
return
;
// already visited
}
...
...
@@ -471,12 +479,47 @@ fn push_candidates_from_impl(&self, candidates: &DVec<Candidate>,
});
}
fn
push_candidates_from_provided_methods
(
&
self
,
candidates
:
&
DVec
<
Candidate
>
,
self_ty
:
ty
::
t
,
trait_def_id
:
def_id
,
methods
:
@
DVec
<@
ProvidedMethodInfo
>
)
{
debug!
(
"(pushing candidates from provided methods) considering trait
\
id %d:%d"
,
trait_def_id
.crate
,
trait_def_id
.node
);
for
methods
.each
|
provided_method_info
|
{
if
provided_method_info
.method_info.ident
!=
self
.m_name
{
loop
;
}
debug!
(
"(pushing candidates from provided methods) adding
\
candidate"
);
// XXX: Needs to support generics.
let
dummy_substs
=
{
self_r
:
None
,
self_ty
:
None
,
tps
:
~
[]
};
let
(
impl_ty
,
impl_substs
)
=
self
.create_rcvr_ty_and_substs_for_method
(
provided_method_info
.method_info.self_type
,
self_ty
,
dummy_substs
);
candidates
.push
(
Candidate
{
rcvr_ty
:
impl_ty
,
rcvr_substs
:
move
impl_substs
,
num_method_tps
:
provided_method_info
.method_info.n_tps
,
self_mode
:
get_mode_from_self_type
(
provided_method_info
.method_info.self_type
),
origin
:
method_static
(
provided_method_info
.method_info.did
)
});
}
}
fn
create_rcvr_ty_and_substs_for_method
(
&
self
,
self_decl
:
ast
::
self_ty_
,
self_ty
:
ty
::
t
,
+
self_substs
:
ty
::
substs
)
->
(
ty
::
t
,
ty
::
substs
)
{
->
(
ty
::
t
,
ty
::
substs
)
{
// If the self type includes a region (like &self), we need to
// ensure that the receiver substitutions have a self region.
// If the receiver type does not itself contain borrowed
...
...
@@ -693,8 +736,7 @@ fn consider_candidates(&self,
fn
confirm_candidate
(
&
self
,
self_ty
:
ty
::
t
,
candidate
:
&
Candidate
)
->
method_map_entry
{
->
method_map_entry
{
let
tcx
=
self
.tcx
();
let
fty
=
self
.fn_ty_from_origin
(
&
candidate
.origin
);
...
...
src/rustc/middle/typeck/check/vtable.rs
浏览文件 @
c886629d
...
...
@@ -444,7 +444,7 @@ fn connect_trait_tps(fcx: @fn_ctxt, expr: @ast::expr, impl_tys: ~[ty::t],
// XXX: This should work for multiple traits.
let
ity
=
ty
::
impl_traits
(
tcx
,
impl_did
,
vstore
)[
0
];
let
trait_ty
=
ty
::
subst_tps
(
tcx
,
impl_tys
,
ity
);
let
trait_ty
=
ty
::
subst_tps
(
tcx
,
impl_tys
,
None
,
ity
);
debug!
(
"(connect trait tps) trait type is %?, impl did is %?"
,
ty
::
get
(
trait_ty
)
.sty
,
impl_did
);
match
ty
::
get
(
trait_ty
)
.sty
{
...
...
src/rustc/middle/typeck/coherence.rs
浏览文件 @
c886629d
...
...
@@ -4,12 +4,13 @@
// has at most one implementation for each type. Then we build a mapping from
// each trait in the system to its implementations.
use
metadata
::
csearch
::{
each_path
,
get_impl_traits
,
get_impls_for_mod
};
use
metadata
::
csearch
::{
ProvidedTraitMethodInfo
,
each_path
,
get_impl_traits
};
use
metadata
::
csearch
::{
get_impls_for_mod
};
use
metadata
::
cstore
::{
cstore
,
iter_crate_data
};
use
metadata
::
decoder
::{
dl_def
,
dl_field
,
dl_impl
};
use
middle
::
resolve
::{
Impl
,
MethodInfo
};
use
middle
::
ty
::{
get
,
lookup_item_type
,
subst
,
t
,
ty_box
};
use
middle
::
ty
::{
ty_uniq
,
ty_ptr
,
ty_rptr
,
ty_enum
};
use
middle
::
ty
::{
ProvidedMethodSource
,
get
,
lookup_item_type
,
subst
,
t
};
use
middle
::
ty
::{
ty_
box
,
ty_
uniq
,
ty_ptr
,
ty_rptr
,
ty_enum
};
use
middle
::
ty
::{
ty_class
,
ty_nil
,
ty_bot
,
ty_bool
,
ty_int
,
ty_uint
};
use
middle
::
ty
::{
ty_float
,
ty_estr
,
ty_evec
,
ty_rec
};
use
middle
::
ty
::{
ty_fn
,
ty_trait
,
ty_tup
,
ty_infer
};
...
...
@@ -17,7 +18,7 @@
use
middle
::
ty
::{
ty_opaque_closure_ptr
,
ty_unboxed_vec
,
type_is_ty_var
};
use
middle
::
typeck
::
infer
::{
infer_ctxt
,
can_mk_subty
};
use
middle
::
typeck
::
infer
::{
new_infer_ctxt
,
resolve_ivar
,
resolve_type
};
use
syntax
::
ast
::{
crate
,
def_id
,
def_mod
};
use
syntax
::
ast
::{
crate
,
def_id
,
def_mod
,
def_ty
};
use
syntax
::
ast
::{
item
,
item_class
,
item_const
,
item_enum
,
item_fn
};
use
syntax
::
ast
::{
item_foreign_mod
,
item_impl
,
item_mac
,
item_mod
};
use
syntax
::
ast
::{
item_trait
,
item_ty
,
local_crate
,
method
,
node_id
};
...
...
@@ -118,6 +119,21 @@ fn method_to_MethodInfo(ast_method: @method) -> @MethodInfo {
}
}
// Stores the method info and definition ID of the associated trait method for
// each instantiation of each provided method.
struct
ProvidedMethodInfo
{
method_info
:
@
MethodInfo
,
trait_method_def_id
:
def_id
}
// Stores information about provided methods (a.k.a. default methods) in
// implementations.
//
// This is a map from ID of each implementation to the method info and trait
// method ID of each of the default methods belonging to the trait that that
// implementation implements.
type
ProvidedMethodsMap
=
HashMap
<
def_id
,
@
DVec
<@
ProvidedMethodInfo
>>
;
struct
CoherenceInfo
{
// Contains implementations of methods that are inherent to a type.
// Methods in these implementations don't need to be exported.
...
...
@@ -128,14 +144,20 @@ struct CoherenceInfo {
extension_methods
:
HashMap
<
def_id
,
@
DVec
<@
Impl
>>
,
// A mapping from a supertrait to its subtraits.
supertrait_to_subtraits
:
HashMap
<
def_id
,
@
DVec
<
def_id
>>
supertrait_to_subtraits
:
HashMap
<
def_id
,
@
DVec
<
def_id
>>
,
// A mapping from an implementation ID to the method info and trait method
// ID of the provided (a.k.a. default) methods in the traits that that
// implementation implements.
provided_methods
:
ProvidedMethodsMap
,
}
fn
CoherenceInfo
()
->
CoherenceInfo
{
CoherenceInfo
{
inherent_methods
:
HashMap
(),
extension_methods
:
HashMap
(),
supertrait_to_subtraits
:
HashMap
()
supertrait_to_subtraits
:
HashMap
(),
provided_methods
:
HashMap
(),
}
}
...
...
@@ -165,68 +187,6 @@ struct CoherenceChecker {
}
impl
CoherenceChecker
{
// Create a mapping containing a MethodInfo for every provided
// method in every trait.
fn
build_provided_methods_map
(
crate
:
@
crate
)
{
let
sess
=
self
.crate_context.tcx.sess
;
let
pmm
=
self
.crate_context.provided_methods_map
;
visit_crate
(
*
crate
,
(),
mk_simple_visitor
(
@
{
visit_item
:
|
item
|
{
match
item
.node
{
item_trait
(
_
,
_
,
trait_methods
)
=>
{
for
trait_methods
.each
|
trait_method
|
{
debug!
(
"(building provided methods map) checking
\
trait `%s` with id %d"
,
sess
.str_of
(
item
.ident
),
item
.id
);
match
*
trait_method
{
required
(
_
)
=>
{
/* fall through */
}
provided
(
m
)
=>
{
// For every provided method in the
// trait, store a MethodInfo.
let
mi
=
method_to_MethodInfo
(
m
);
match
pmm
.find
(
item
.id
)
{
Some
(
mis
)
=>
{
// If the trait already has an
// entry in the
// provided_methods_map, we just
// need to add this method to
// that entry.
debug!
(
"(building provided
\
methods map) adding
\
method `%s` to entry for
\
existing trait"
,
sess
.str_of
(
mi
.ident
));
let
mut
method_infos
=
mis
;
method_infos
.push
(
mi
);
pmm
.insert
(
item
.id
,
method_infos
);
}
None
=>
{
// If the trait doesn't have an
// entry yet, create one.
debug!
(
"(building provided
\
methods map) creating new
\
entry for method `%s`"
,
sess
.str_of
(
mi
.ident
));
pmm
.insert
(
item
.id
,
~
[
mi
]);
}
}
}
}
}
}
_
=>
{
// Nothing to do.
}
};
},
..
*
default_simple_visitor
()
}));
}
fn
check_coherence
(
crate
:
@
crate
)
{
// Check implementations and traits. This populates the tables
// containing the inherent methods and extension methods. It also
...
...
@@ -307,6 +267,7 @@ fn check_implementation(item: @item, associated_traits: ~[@trait_ref]) {
self
.crate_context.tcx.sess.parse_sess.interner
),
self
.crate_context.tcx.sess
.str_of
(
item
.ident
));
self
.instantiate_default_methods
(
item
.id
,
trait_did
);
let
implementation
=
self
.create_impl_from_item
(
item
);
self
.add_trait_method
(
trait_did
,
implementation
);
}
...
...
@@ -321,6 +282,7 @@ fn check_implementation(item: @item, associated_traits: ~[@trait_ref]) {
// Nothing to do.
}
Some
(
base_type_def_id
)
=>
{
// XXX: Gather up default methods?
let
implementation
=
self
.create_impl_from_item
(
item
);
self
.add_inherent_method
(
base_type_def_id
,
implementation
);
...
...
@@ -330,6 +292,68 @@ fn check_implementation(item: @item, associated_traits: ~[@trait_ref]) {
}
}
// Creates default method IDs and performs type substitutions for an impl
// and trait pair. Then, for each provided method in the trait, inserts a
// `ProvidedMethodInfo` instance into the `provided_method_sources` map.
fn
instantiate_default_methods
(
impl_id
:
ast
::
node_id
,
trait_did
:
ast
::
def_id
)
{
for
self
.each_provided_trait_method
(
trait_did
)
|
trait_method
|
{
// Synthesize an ID.
let
tcx
=
self
.crate_context.tcx
;
let
new_id
=
syntax
::
parse
::
next_node_id
(
tcx
.sess.parse_sess
);
let
new_did
=
local_def
(
new_id
);
// XXX: Perform substitutions.
let
new_polytype
=
ty
::
lookup_item_type
(
tcx
,
trait_method
.def_id
);
tcx
.tcache
.insert
(
new_did
,
new_polytype
);
// Pair the new synthesized ID up with the
// ID of the method.
let
source
=
ProvidedMethodSource
{
method_id
:
trait_method
.def_id
,
impl_id
:
local_def
(
impl_id
)
};
self
.crate_context.tcx.provided_method_sources
.insert
(
new_did
,
source
);
let
provided_method_info
=
@
ProvidedMethodInfo
{
method_info
:
@
{
did
:
new_did
,
n_tps
:
trait_method
.tps
.len
(),
ident
:
trait_method
.ident
,
self_type
:
trait_method
.self_ty
},
trait_method_def_id
:
trait_method
.def_id
};
let
pmm
=
self
.crate_context.coherence_info.provided_methods
;
match
pmm
.find
(
local_def
(
impl_id
))
{
Some
(
mis
)
=>
{
// If the trait already has an entry in the
// provided_methods_map, we just need to add this
// method to that entry.
debug!
(
"(checking implementation) adding method `%s`
\
to entry for existing trait"
,
self
.crate_context.tcx.sess
.str_of
(
provided_method_info
.method_info.ident
));
mis
.push
(
provided_method_info
);
}
None
=>
{
// If the trait doesn't have an entry yet, create one.
debug!
(
"(checking implementation) creating new entry
\
for method `%s`"
,
self
.crate_context.tcx.sess
.str_of
(
provided_method_info
.method_info.ident
));
let
method_infos
=
@
DVec
();
method_infos
.push
(
provided_method_info
);
pmm
.insert
(
local_def
(
impl_id
),
method_infos
);
}
}
}
}
fn
register_inherited_trait
(
item
:
@
item
,
supertraits
:
~
[
@
trait_ref
])
{
// XXX: This is wrong. We need to support substitutions; e.g.
// trait Foo : Bar<int>.
...
...
@@ -354,8 +378,7 @@ fn register_inherited_trait(item: @item, supertraits: ~[@trait_ref]) {
fn
add_inherent_method
(
base_def_id
:
def_id
,
implementation
:
@
Impl
)
{
let
implementation_list
;
match
self
.crate_context.coherence_info.inherent_methods
.find
(
base_def_id
)
{
.find
(
base_def_id
)
{
None
=>
{
implementation_list
=
@
DVec
();
self
.crate_context.coherence_info.inherent_methods
...
...
@@ -372,8 +395,7 @@ fn add_inherent_method(base_def_id: def_id, implementation: @Impl) {
fn
add_trait_method
(
trait_id
:
def_id
,
implementation
:
@
Impl
)
{
let
implementation_list
;
match
self
.crate_context.coherence_info.extension_methods
.find
(
trait_id
)
{
.find
(
trait_id
)
{
None
=>
{
implementation_list
=
@
DVec
();
self
.crate_context.coherence_info.extension_methods
...
...
@@ -413,6 +435,26 @@ fn check_implementation_coherence(_trait_def_id: def_id,
}
}
fn
each_provided_trait_method
(
trait_did
:
ast
::
def_id
,
f
:
&
fn
(
x
:
&
ty
::
method
)
->
bool
)
{
// Make a list of all the names of the provided methods.
// XXX: This is horrible.
let
provided_method_idents
=
HashMap
();
let
tcx
=
self
.crate_context.tcx
;
for
ty
::
provided_trait_methods
(
tcx
,
trait_did
)
.each
|
ident
|
{
provided_method_idents
.insert
(
*
ident
,
());
}
for
ty
::
trait_methods
(
tcx
,
trait_did
)
.each
|
method
|
{
if
provided_method_idents
.contains_key
(
method
.ident
)
{
if
!
f
(
method
)
{
break
;
}
}
}
}
fn
polytypes_unify
(
polytype_a
:
ty_param_bounds_and_ty
,
polytype_b
:
ty_param_bounds_and_ty
)
->
bool
{
...
...
@@ -449,7 +491,6 @@ fn universally_quantify_polytype(polytype: ty_param_bounds_and_ty) -> t {
fn
get_self_type_for_implementation
(
implementation
:
@
Impl
)
->
ty_param_bounds_and_ty
{
return
self
.crate_context.tcx.tcache
.get
(
implementation
.did
);
}
...
...
@@ -552,33 +593,15 @@ fn trait_ref_to_trait_def_id(trait_ref: @trait_ref) -> def_id {
// Converts an implementation in the AST to an Impl structure.
fn
create_impl_from_item
(
item
:
@
item
)
->
@
Impl
{
fn
add_provided_methods
(
inherent_methods
:
~
[
@
MethodInfo
],
all_provided_methods
:
~
[
@
MethodInfo
],
sess
:
driver
::
session
::
session
)
->
~
[
@
MethodInfo
]
{
let
mut
methods
=
inherent_methods
;
// If there's no inherent method with the same name as a
// provided method, add that provided method to `methods`.
fn
add_provided_methods
(
all_methods
:
&
mut
~
[
@
MethodInfo
],
all_provided_methods
:
~
[
@
ProvidedMethodInfo
],
sess
:
driver
::
session
::
session
)
{
for
all_provided_methods
.each
|
provided_method
|
{
let
mut
method_inherent_to_impl
=
false
;
for
inherent_methods
.each
|
inherent_method
|
{
if
provided_method
.ident
==
inherent_method
.ident
{
method_inherent_to_impl
=
true
;
}
}
if
!
method_inherent_to_impl
{
debug!
(
"(creating impl) adding provided method `%s` to impl"
,
sess
.str_of
(
provided_method
.ident
));
methods
.push
(
*
provided_method
);
}
debug!
(
"(creating impl) adding provided method `%s` to impl"
,
sess
.str_of
(
provided_method
.method_info.ident
));
vec
::
push
(
all_methods
,
provided_method
.method_info
);
}
return
methods
;
}
match
item
.node
{
...
...
@@ -598,24 +621,22 @@ fn add_provided_methods(inherent_methods: ~[@MethodInfo],
let
trait_did
=
self
.trait_ref_to_trait_def_id
(
*
trait_ref
);
match
self
.crate_context.provided_methods_map
.find
(
trait_did
.node
)
{
match
self
.crate_context
.coherence_info
.provided_methods
.find
(
local_def
(
item
.id
))
{
None
=>
{
debug!
(
"(creating impl) trait with node_id `%d`
\
has no provided methods"
,
trait_did
.node
);
/* fall through */
}
Some
(
all_provided
)
=>
{
Some
(
all_provided
)
=>
{
debug!
(
"(creating impl) trait with node_id `%d`
\
has provided methods"
,
trait_did
.node
);
// Selectively add only those provided
// methods that aren't inherent to the
// trait.
// XXX: could probably be doing this with filter.
methods
=
add_provided_methods
(
methods
,
all_provided
,
// Add all provided methods.
add_provided_methods
(
&
mut
methods
,
all_provided
.get
(),
self
.crate_context.tcx.sess
);
}
}
...
...
@@ -758,6 +779,41 @@ fn add_impls_for_module(impls_seen: HashMap<def_id,()>,
}
}
fn
add_default_methods_for_external_trait
(
trait_def_id
:
ast
::
def_id
)
{
let
tcx
=
self
.crate_context.tcx
;
let
pmm
=
self
.crate_context.coherence_info.provided_methods
;
if
pmm
.contains_key
(
trait_def_id
)
{
return
;
}
debug!
(
"(adding default methods for trait) processing trait"
);
for
csearch
::
get_provided_trait_methods
(
tcx
,
trait_def_id
)
.each
|
info
|
{
debug!
(
"(adding default methods for trait) found default method"
);
// Create a new def ID for this provided method.
let
parse_sess
=
&
self
.crate_context.tcx.sess.parse_sess
;
let
new_did
=
local_def
(
syntax
::
parse
::
next_node_id
(
*
parse_sess
));
let
provided_method_info
=
@
ProvidedMethodInfo
{
method_info
:
@
{
did
:
new_did
,
n_tps
:
info
.ty.tps
.len
(),
ident
:
info
.ty.ident
,
self_type
:
info
.ty.self_ty
},
trait_method_def_id
:
info
.def_id
};
let
method_infos
=
@
DVec
();
method_infos
.push
(
provided_method_info
);
pmm
.insert
(
trait_def_id
,
method_infos
);
}
}
// Adds implementations and traits from external crates to the coherence
// info.
fn
add_external_crates
()
{
let
impls_seen
=
HashMap
();
...
...
@@ -768,20 +824,28 @@ fn add_external_crates() {
{
crate
:
crate_number
,
node
:
0
});
for
each_path
(
crate_store
,
crate_number
)
|
path_entry
|
{
let
module_def_id
;
match
path_entry
.def_like
{
dl_def
(
def_mod
(
def_id
))
=>
{
module_def_id
=
def_id
;
self
.add_impls_for_module
(
impls_seen
,
crate_store
,
def_id
);
}
dl_def
(
def_ty
(
def_id
))
=>
{
let
tcx
=
self
.crate_context.tcx
;
let
polytype
=
csearch
::
get_type
(
tcx
,
def_id
);
match
ty
::
get
(
polytype
.ty
)
.sty
{
ty
::
ty_trait
(
*
)
=>
{
self
.add_default_methods_for_external_trait
(
def_id
);
}
_
=>
{}
}
}
dl_def
(
_
)
|
dl_impl
(
_
)
|
dl_field
=>
{
// Skip this.
loop
;
}
}
self
.add_impls_for_module
(
impls_seen
,
crate_store
,
module_def_id
);
}
}
}
...
...
@@ -789,7 +853,6 @@ fn add_external_crates() {
fn
check_coherence
(
crate_context
:
@
crate_ctxt
,
crate
:
@
crate
)
{
let
coherence_checker
=
@
CoherenceChecker
(
crate_context
);
(
*
coherence_checker
)
.build_provided_methods_map
(
crate
);
(
*
coherence_checker
)
.check_coherence
(
crate
);
}
src/rustc/middle/typeck/collect.rs
浏览文件 @
c886629d
...
...
@@ -212,9 +212,15 @@ fn make_static_method_ty(ccx: @crate_ctxt,
match
tcx
.items
.get
(
id
)
{
ast_map
::
node_item
(
@
{
node
:
ast
::
item_trait
(
params
,
_
,
ms
),
_
},
_
)
=>
{
store_methods
::
<
ast
::
trait_method
>
(
ccx
,
id
,
ms
,
|
m
|
{
let
def_id
;
match
*
m
{
ast
::
required
(
ty_method
)
=>
def_id
=
local_def
(
ty_method
.id
),
ast
::
provided
(
method
)
=>
def_id
=
local_def
(
method
.id
)
}
let
trait_bounds
=
ty_param_bounds
(
ccx
,
params
);
let
ty_m
=
trait_method_to_ty_method
(
*
m
);
let
method_ty
=
ty_of_ty_method
(
ccx
,
ty_m
,
region_paramd
);
let
method_ty
=
ty_of_ty_method
(
ccx
,
ty_m
,
region_paramd
,
def_id
);
if
ty_m
.self_ty.node
==
ast
::
sty_static
{
make_static_method_ty
(
ccx
,
ty_m
,
region_paramd
,
method_ty
,
trait_ty
,
trait_bounds
);
...
...
@@ -373,7 +379,7 @@ fn check_methods_against_trait(ccx: @crate_ctxt,
let
provided_methods
=
ty
::
provided_trait_methods
(
tcx
,
did
);
match
vec
::
find
(
provided_methods
,
|
provided_method
|
provided_method
.ident
==
trait_m
.ident
)
{
*
provided_method
==
trait_m
.ident
)
{
Some
(
_
)
=>
{
// If there's a provided method with the name we
// want, then we're fine; nothing else to do.
...
...
@@ -546,19 +552,22 @@ fn ty_of_method(ccx: @crate_ctxt,
m
.purity
,
@~
[],
m
.decl
,
None
,
m
.span
),
self_ty
:
m
.self_ty.node
,
vis
:
m
.vis
}
vis
:
m
.vis
,
def_id
:
local_def
(
m
.id
)}
}
fn
ty_of_ty_method
(
self
:
@
crate_ctxt
,
m
:
ast
::
ty_method
,
rp
:
Option
<
ty
::
region_variance
>
)
->
ty
::
method
{
rp
:
Option
<
ty
::
region_variance
>
,
id
:
ast
::
def_id
)
->
ty
::
method
{
{
ident
:
m
.ident
,
tps
:
ty_param_bounds
(
self
,
m
.tps
),
fty
:
ty_of_fn_decl
(
self
,
type_rscope
(
rp
),
ast
::
proto_bare
,
m
.purity
,
@~
[],
m
.decl
,
None
,
m
.span
),
// assume public, because this is only invoked on trait methods
self_ty
:
m
.self_ty.node
,
vis
:
ast
::
public
}
vis
:
ast
::
public
,
def_id
:
id
}
}
/*
...
...
src/test/run-pass/default-method-simple.rs
0 → 100644
浏览文件 @
c886629d
trait
Foo
{
fn
f
()
{
io
::
println
(
"Hello!"
);
self
.g
();
}
fn
g
();
}
struct
A
{
x
:
int
}
impl
A
:
Foo
{
fn
g
()
{
io
::
println
(
"Goodbye!"
);
}
}
fn
main
()
{
let
a
=
A
{
x
:
1
};
a
.f
();
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录