Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
d5a27a0e
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,发现更多精彩内容 >>
提交
d5a27a0e
编写于
10月 26, 2012
作者:
P
Patrick Walton
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
rustc: Translate monomorphic intra-crate automatically-derived methods that follow the "eq" format
上级
c7ec183b
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
266 addition
and
33 deletion
+266
-33
src/libsyntax/ast_map.rs
src/libsyntax/ast_map.rs
+1
-1
src/rustc/middle/trans/base.rs
src/rustc/middle/trans/base.rs
+42
-1
src/rustc/middle/trans/callee.rs
src/rustc/middle/trans/callee.rs
+31
-15
src/rustc/middle/trans/deriving.rs
src/rustc/middle/trans/deriving.rs
+111
-6
src/rustc/middle/ty.rs
src/rustc/middle/ty.rs
+20
-2
src/rustc/middle/typeck/coherence.rs
src/rustc/middle/typeck/coherence.rs
+29
-8
src/test/run-pass/deriving-simple.rs
src/test/run-pass/deriving-simple.rs
+32
-0
未找到文件。
src/libsyntax/ast_map.rs
浏览文件 @
d5a27a0e
...
...
@@ -74,7 +74,7 @@ enum ast_node {
// Destructor for a class
node_dtor
(
~
[
ty_param
],
@
class_dtor
,
def_id
,
@
path
),
node_block
(
blk
),
node_struct_ctor
(
@
struct_def
,
@
item
,
@
path
)
node_struct_ctor
(
@
struct_def
,
@
item
,
@
path
)
,
}
type
map
=
std
::
map
::
HashMap
<
node_id
,
ast_node
>
;
...
...
src/rustc/middle/trans/base.rs
浏览文件 @
d5a27a0e
...
...
@@ -42,6 +42,7 @@
use
util
::
ppaux
::{
ty_to_str
,
ty_to_short_str
};
use
syntax
::
diagnostic
::
expect
;
use
util
::
common
::
indenter
;
use
ty
::
DerivedMethodInfo
;
use
build
::
*
;
use
shape
::
*
;
...
...
@@ -1843,7 +1844,7 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) {
match
ms_opt
{
None
=>
{
deriving
::
trans_deriving_impl
(
ccx
,
*
path
,
item
.ident
,
tps
,
None
,
item
.id
);
item
.id
);
}
Some
(
ms
)
=>
{
meth
::
trans_impl
(
ccx
,
*
path
,
item
.ident
,
ms
,
tps
,
None
,
...
...
@@ -2079,6 +2080,20 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef {
match
ccx
.item_vals
.find
(
id
)
{
Some
(
v
)
=>
v
,
None
=>
{
// First, check whether we need to automatically generate a method
// via the deriving mechanism.
match
ccx
.tcx.automatically_derived_methods
.find
(
local_def
(
id
))
{
None
=>
{}
// Continue.
Some
(
ref
derived_method_info
)
=>
{
// XXX: Mark as internal if necessary.
let
llfn
=
register_deriving_method
(
ccx
,
id
,
derived_method_info
);
ccx
.item_vals
.insert
(
id
,
llfn
);
return
llfn
;
}
}
// Failing that, look for an item.
let
mut
exprt
=
false
;
let
val
=
match
ccx
.tcx.items
.get
(
id
)
{
ast_map
::
node_item
(
i
,
pth
)
=>
{
...
...
@@ -2226,6 +2241,32 @@ fn register_method(ccx: @crate_ctxt, id: ast::node_id, pth: @ast_map::path,
llfn
}
fn
register_deriving_method
(
ccx
:
@
crate_ctxt
,
id
:
ast
::
node_id
,
derived_method_info
:
&
DerivedMethodInfo
)
->
ValueRef
{
// Find the path of the item.
let
path
,
span
;
match
ccx
.tcx.items
.get
(
derived_method_info
.containing_impl.node
)
{
ast_map
::
node_item
(
item
,
found_path
)
=>
{
path
=
found_path
;
span
=
item
.span
;
}
_
=>
{
ccx
.tcx.sess
.bug
(
~
"derived method info containing impl didn't
\
refer to an item"
);
}
}
let
path
=
vec
::
append
(
*
path
,
~
[
ast_map
::
path_name
(
derived_method_info
.method_info.ident
)
]);
let
mty
=
ty
::
lookup_item_type
(
ccx
.tcx
,
local_def
(
id
))
.ty
;
let
llfn
=
register_fn_full
(
ccx
,
span
,
path
,
id
,
mty
);
// XXX: Inline hint.
llfn
}
// The constant translation pass.
fn
trans_constant
(
ccx
:
@
crate_ctxt
,
it
:
@
ast
::
item
)
{
let
_
icx
=
ccx
.insn_ctxt
(
"trans_constant"
);
...
...
src/rustc/middle/trans/callee.rs
浏览文件 @
d5a27a0e
...
...
@@ -210,23 +210,30 @@ fn trans_fn_ref_with_vtables(
// 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
,
ccx
.tcx.items
.find
(
def_id
.node
),
||
fmt!
(
"local item should be in ast map"
));
match
map_node
{
ast_map
::
node_foreign_item
(
_
,
ast
::
foreign_abi_rust_intrinsic
,
_
)
=>
true
,
_
=>
false
let
must_monomorphise
;
if
type_params
.len
()
>
0
||
opt_impl_did
.is_some
()
{
must_monomorphise
=
true
;
}
else
if
ccx
.tcx.automatically_derived_methods
.contains_key
(
def_id
)
{
must_monomorphise
=
false
;
}
else
if
def_id
.crate
==
ast
::
local_crate
{
let
map_node
=
session
::
expect
(
ccx
.sess
,
ccx
.tcx.items
.find
(
def_id
.node
),
||
fmt!
(
"local item should be in ast map"
));
match
map_node
{
ast_map
::
node_foreign_item
(
_
,
ast
::
foreign_abi_rust_intrinsic
,
_
)
=>
{
must_monomorphise
=
true
;
}
_
=>
{
must_monomorphise
=
false
;
}
}
else
{
false
}
};
}
else
{
must_monomorphise
=
false
;
}
// Create a monomorphic verison of generic functions
if
must_monomorphise
{
...
...
@@ -434,6 +441,15 @@ fn trans_call_inner(
_
=>
{}
}
// Uncomment this to debug calls.
/*
io::println(fmt!("calling: %s", bcx.val_str(llfn)));
for llargs.each |llarg| {
io::println(fmt!("arg: %s", bcx.val_str(*llarg)));
}
io::println("---");
*/
// If the block is terminated, then one or more of the args
// has type _|_. Since that means it diverges, the code for
// the call itself is unreachable.
...
...
src/rustc/middle/trans/deriving.rs
浏览文件 @
d5a27a0e
// Translation of automatically-derived trait implementations. This handles
// enums and structs only; other types cannot be automatically derived.
use
middle
::
trans
::
base
::
get_insn_ctxt
;
use
middle
::
trans
::
common
::
crate_ctxt
;
use
syntax
::
ast
::{
ident
,
node_id
,
ty_param
};
use
lib
::
llvm
::
llvm
;
use
middle
::
trans
::
base
::{
finish_fn
,
get_insn_ctxt
,
get_item_val
};
use
middle
::
trans
::
base
::{
new_fn_ctxt
,
sub_block
,
top_scope_block
};
use
middle
::
trans
::
build
::{
Br
,
CondBr
,
GEPi
,
Load
,
PointerCast
,
Store
};
use
middle
::
trans
::
build
::{
ValueRef
};
use
middle
::
trans
::
callee
;
use
middle
::
trans
::
callee
::{
ArgVals
,
Callee
,
DontAutorefArg
,
Method
};
use
middle
::
trans
::
callee
::{
MethodData
};
use
middle
::
trans
::
common
;
use
middle
::
trans
::
common
::{
C_bool
,
T_ptr
,
block
,
crate_ctxt
};
use
middle
::
trans
::
expr
::
SaveIn
;
use
middle
::
trans
::
type_of
::
type_of
;
use
middle
::
typeck
::
method_static
;
use
syntax
::
ast
;
use
syntax
::
ast
::{
def_id
,
ident
,
node_id
,
ty_param
};
use
syntax
::
ast_map
::
path
;
use
syntax
::
ast_util
;
use
syntax
::
ast_util
::
local_def
;
/// The main "translation" pass for automatically-derived impls. Generates
/// code for monomorphic methods only. Other methods will be generated when
/// they are invoked with specific type parameters; see
/// `trans::base::lval_static_fn()` or `trans::base::monomorphic_fn()`.
pub
fn
trans_deriving_impl
(
ccx
:
@
crate_ctxt
,
_
path
:
path
,
_
name
:
ident
,
tps
:
~
[
ty_param
],
_
self_ty
:
Option
<
ty
::
t
>
,
_
id
:
node_id
)
{
tps
:
~
[
ty_param
],
id
:
node_id
)
{
let
_
icx
=
ccx
.insn_ctxt
(
"deriving::trans_deriving_impl"
);
if
tps
.len
()
>
0
{
return
;
}
// XXX: Unimplemented.
let
impl_def_id
=
local_def
(
id
);
let
self_ty
=
ty
::
lookup_item_type
(
ccx
.tcx
,
impl_def_id
);
let
method_dids
=
ccx
.tcx.automatically_derived_methods_for_impl
.get
(
impl_def_id
);
for
method_dids
.each
|
method_did
|
{
let
llfn
=
get_item_val
(
ccx
,
method_did
.node
);
match
ty
::
get
(
self_ty
.ty
)
.sty
{
ty
::
ty_class
(
*
)
=>
{
trans_deriving_struct_method
(
ccx
,
llfn
,
impl_def_id
,
self_ty
.ty
);
}
_
=>
{
ccx
.tcx.sess
.unimpl
(
~
"translation of non-struct deriving
\
method"
);
}
}
}
}
fn
trans_deriving_struct_method
(
ccx
:
@
crate_ctxt
,
llfn
:
ValueRef
,
impl_did
:
def_id
,
self_ty
:
ty
::
t
)
{
let
_
icx
=
ccx
.insn_ctxt
(
"trans_deriving_struct_method"
);
let
fcx
=
new_fn_ctxt
(
ccx
,
~
[],
llfn
,
None
);
let
top_bcx
=
top_scope_block
(
fcx
,
None
);
let
lltop
=
top_bcx
.llbb
;
let
mut
bcx
=
top_bcx
;
let
llselfty
=
type_of
(
ccx
,
self_ty
);
let
llselfval
=
PointerCast
(
bcx
,
fcx
.llenv
,
T_ptr
(
llselfty
));
let
llotherval
=
llvm
::
LLVMGetParam
(
llfn
,
2
);
let
struct_field_tys
;
match
ty
::
get
(
self_ty
)
.sty
{
ty
::
ty_class
(
struct_id
,
ref
struct_substs
)
=>
{
struct_field_tys
=
ty
::
class_items_as_fields
(
ccx
.tcx
,
struct_id
,
struct_substs
);
}
_
=>
{
ccx
.tcx.sess
.bug
(
~
"passed non-struct to
\
trans_deriving_struct_method"
);
}
}
// Iterate over every element of the struct.
for
ccx
.tcx.deriving_struct_methods
.get
(
impl_did
)
.eachi
|
i
,
derived_method_info
|
{
let
target_method_def_id
;
match
*
derived_method_info
{
method_static
(
did
)
=>
target_method_def_id
=
did
,
_
=>
fail
~
"derived method didn't resolve to a static method"
}
let
fn_expr_ty
=
ty
::
lookup_item_type
(
ccx
.tcx
,
target_method_def_id
)
.ty
;
let
llselfval
=
GEPi
(
bcx
,
llselfval
,
[
0
,
0
,
i
]);
let
llotherval
=
GEPi
(
bcx
,
llotherval
,
[
0
,
0
,
i
]);
// XXX: Cross-crate won't work!
let
llfn
=
get_item_val
(
ccx
,
target_method_def_id
.node
);
let
cb
:
&
fn
(
block
)
->
Callee
=
|
block
|
{
Callee
{
bcx
:
block
,
data
:
Method
(
MethodData
{
llfn
:
llfn
,
llself
:
llselfval
,
self_ty
:
struct_field_tys
[
i
]
.mt.ty
,
self_mode
:
ast
::
by_copy
})
}
};
bcx
=
callee
::
trans_call_inner
(
bcx
,
None
,
fn_expr_ty
,
ty
::
mk_bool
(
ccx
.tcx
),
cb
,
ArgVals
(
~
[
llotherval
]),
SaveIn
(
fcx
.llretptr
),
DontAutorefArg
);
// Return immediately if the call returned false.
let
next_block
=
sub_block
(
top_bcx
,
~
"next"
);
let
llcond
=
Load
(
bcx
,
fcx
.llretptr
);
CondBr
(
bcx
,
llcond
,
next_block
.llbb
,
fcx
.llreturn
);
bcx
=
next_block
;
}
Store
(
bcx
,
C_bool
(
true
),
fcx
.llretptr
);
Br
(
bcx
,
fcx
.llreturn
);
finish_fn
(
fcx
,
lltop
);
}
src/rustc/middle/ty.rs
浏览文件 @
d5a27a0e
...
...
@@ -200,6 +200,7 @@
export
trait_supertraits
;
export
AutoAdjustment
;
export
AutoRef
,
AutoRefKind
,
AutoSlice
,
AutoPtr
;
export
DerivedMethodInfo
;
// Data types
...
...
@@ -333,6 +334,11 @@ struct InstantiatedTraitRef {
tpt
:
ty_param_substs_and_ty
}
struct
DerivedMethodInfo
{
method_info
:
@
middle
::
resolve
::
MethodInfo
,
containing_impl
:
ast
::
def_id
}
type
ctxt
=
@
{
diag
:
syntax
::
diagnostic
::
span_handler
,
interner
:
HashMap
<
intern_key
,
t_box
>
,
...
...
@@ -379,7 +385,17 @@ struct InstantiatedTraitRef {
provided_method_sources
:
HashMap
<
ast
::
def_id
,
ProvidedMethodSource
>
,
supertraits
:
HashMap
<
ast
::
def_id
,
@~
[
InstantiatedTraitRef
]
>
,
deriving_struct_methods
:
HashMap
<
ast
::
def_id
,
@~
[
typeck
::
method_origin
]
>
};
@~
[
typeck
::
method_origin
]
>
,
// A mapping from the def ID of a method that was automatically derived
// to information about it.
automatically_derived_methods
:
HashMap
<
ast
::
def_id
,
DerivedMethodInfo
>
,
// A mapping from the def ID of an impl to the IDs of the derived
// methods within it.
automatically_derived_methods_for_impl
:
HashMap
<
ast
::
def_id
,
@~
[
ast
::
def_id
]
>
};
enum
tbox_flag
{
has_params
=
1
,
...
...
@@ -942,7 +958,9 @@ fn mk_ctxt(s: session::Session,
legacy_boxed_traits
:
HashMap
(),
provided_method_sources
:
HashMap
(),
supertraits
:
HashMap
(),
deriving_struct_methods
:
HashMap
()}
deriving_struct_methods
:
HashMap
(),
automatically_derived_methods
:
HashMap
(),
automatically_derived_methods_for_impl
:
HashMap
()}
}
...
...
src/rustc/middle/typeck/coherence.rs
浏览文件 @
d5a27a0e
...
...
@@ -9,10 +9,10 @@
use
metadata
::
cstore
::{
CStore
,
iter_crate_data
};
use
metadata
::
decoder
::{
dl_def
,
dl_field
,
dl_impl
};
use
middle
::
resolve
::{
Impl
,
MethodInfo
};
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
::{
DerivedMethodInfo
,
ProvidedMethodSource
,
ge
t
};
use
middle
::
ty
::{
lookup_item_type
,
subst
,
t
,
ty_bot
,
ty_box
,
ty_class
};
use
middle
::
ty
::{
ty_
bool
,
ty_enum
,
ty_int
,
ty_nil
,
ty_ptr
,
ty_rptr
,
ty_uint
};
use
middle
::
ty
::{
ty_float
,
ty_estr
,
ty_evec
,
ty_rec
,
ty_uniq
};
use
middle
::
ty
::{
ty_fn
,
ty_trait
,
ty_tup
,
ty_infer
};
use
middle
::
ty
::{
ty_param
,
ty_self
,
ty_type
,
ty_opaque_box
};
use
middle
::
ty
::{
ty_opaque_closure_ptr
,
ty_unboxed_vec
,
type_is_ty_var
};
...
...
@@ -592,17 +592,33 @@ fn trait_ref_to_trait_def_id(trait_ref: @trait_ref) -> def_id {
}
fn
add_automatically_derived_methods_from_trait
(
all_methods
:
&
mut
~
[
@
MethodInfo
],
trait_did
:
def_id
,
self_ty
:
ty
::
t
)
{
all_methods
:
&
mut
~
[
@
MethodInfo
],
trait_did
:
def_id
,
self_ty
:
ty
::
t
,
impl_did
:
def_id
)
{
let
tcx
=
self
.crate_context.tcx
;
let
new_method_dids
=
dvec
::
DVec
();
for
(
*
ty
::
trait_methods
(
tcx
,
trait_did
))
.each
|
method
|
{
// Generate a def ID for each node.
let
new_def_id
=
local_def
(
tcx
.sess
.next_node_id
());
all_methods
.push
(
@
{
let
method_info
=
@
{
did
:
new_def_id
,
n_tps
:
method
.tps
.len
(),
ident
:
method
.ident
,
self_type
:
method
.self_ty
});
};
all_methods
.push
(
method_info
);
// Note that this method was automatically derived so that trans
// can handle it differently.
let
derived_method_info
=
DerivedMethodInfo
{
method_info
:
method_info
,
containing_impl
:
impl_did
};
tcx
.automatically_derived_methods
.insert
(
new_def_id
,
derived_method_info
);
new_method_dids
.push
(
new_def_id
);
// Additionally, generate the type for the derived method and add
// it to the type cache.
...
...
@@ -615,6 +631,10 @@ fn add_automatically_derived_methods_from_trait(
ty
:
ty
::
subst
(
tcx
,
&
substs
,
ty
::
mk_fn
(
tcx
,
method
.fty
))
});
}
let
new_method_dids
=
@
dvec
::
unwrap
(
move
new_method_dids
);
tcx
.automatically_derived_methods_for_impl
.insert
(
impl_did
,
new_method_dids
);
}
// Converts an implementation in the AST to an Impl structure.
...
...
@@ -651,7 +671,8 @@ fn add_provided_methods(all_methods: &mut ~[@MethodInfo],
let
trait_did
=
self
.trait_ref_to_trait_def_id
(
*
trait_ref
);
self
.add_automatically_derived_methods_from_trait
(
&
mut
methods
,
trait_did
,
self_ty
.ty
);
&
mut
methods
,
trait_did
,
self_ty
.ty
,
local_def
(
item
.id
));
}
}
}
...
...
src/test/run-pass/deriving-simple.rs
0 → 100644
浏览文件 @
d5a27a0e
trait
MyEq
{
pure
fn
eq
(
other
:
&
self
)
->
bool
;
}
struct
A
{
x
:
int
}
struct
B
{
x
:
A
,
y
:
A
,
z
:
A
}
impl
A
:
MyEq
{
pure
fn
eq
(
other
:
&
A
)
->
bool
{
unsafe
{
io
::
println
(
fmt!
(
"eq %d %d"
,
self
.x
,
other
.x
));
}
self
.x
==
other
.x
}
}
impl
B
:
MyEq
;
fn
main
()
{
let
b
=
B
{
x
:
A
{
x
:
1
},
y
:
A
{
x
:
2
},
z
:
A
{
x
:
3
}
};
let
c
=
B
{
x
:
A
{
x
:
1
},
y
:
A
{
x
:
3
},
z
:
A
{
x
:
4
}
};
assert
b
.eq
(
&
b
);
assert
c
.eq
(
&
c
);
assert
!
b
.eq
(
&
c
);
assert
!
c
.eq
(
&
b
);
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录