Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
77b06d24
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,发现更多精彩内容 >>
提交
77b06d24
编写于
2月 02, 2012
作者:
N
Niko Matsakis
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
infer modes rather than overwriting with expected ty
上级
5163606d
变更
20
隐藏空白更改
内联
并排
Showing
20 changed file
with
309 addition
and
166 deletion
+309
-166
src/comp/front/test.rs
src/comp/front/test.rs
+1
-1
src/comp/metadata/tydecode.rs
src/comp/metadata/tydecode.rs
+1
-1
src/comp/metadata/tyencode.rs
src/comp/metadata/tyencode.rs
+1
-5
src/comp/middle/alias.rs
src/comp/middle/alias.rs
+16
-9
src/comp/middle/block_use.rs
src/comp/middle/block_use.rs
+1
-1
src/comp/middle/kind.rs
src/comp/middle/kind.rs
+4
-1
src/comp/middle/last_use.rs
src/comp/middle/last_use.rs
+13
-3
src/comp/middle/mut.rs
src/comp/middle/mut.rs
+8
-4
src/comp/middle/trans/base.rs
src/comp/middle/trans/base.rs
+18
-15
src/comp/middle/trans/closure.rs
src/comp/middle/trans/closure.rs
+9
-2
src/comp/middle/trans/common.rs
src/comp/middle/trans/common.rs
+2
-1
src/comp/middle/trans/impl.rs
src/comp/middle/trans/impl.rs
+2
-1
src/comp/middle/tstate/auxiliary.rs
src/comp/middle/tstate/auxiliary.rs
+5
-3
src/comp/middle/tstate/pre_post_conditions.rs
src/comp/middle/tstate/pre_post_conditions.rs
+4
-5
src/comp/middle/ty.rs
src/comp/middle/ty.rs
+99
-17
src/comp/middle/typeck.rs
src/comp/middle/typeck.rs
+80
-58
src/comp/syntax/ast.rs
src/comp/syntax/ast.rs
+11
-1
src/comp/syntax/parse/parser.rs
src/comp/syntax/parse/parser.rs
+15
-10
src/comp/syntax/print/pprust.rs
src/comp/syntax/print/pprust.rs
+13
-8
src/comp/util/ppaux.rs
src/comp/util/ppaux.rs
+6
-20
未找到文件。
src/comp/front/test.rs
浏览文件 @
77b06d24
...
@@ -382,7 +382,7 @@ fn mk_main(cx: test_ctxt) -> @ast::item {
...
@@ -382,7 +382,7 @@ fn mk_main(cx: test_ctxt) -> @ast::item {
let
args_ty
:
ast
::
ty
=
nospan
(
ast
::
ty_vec
(
args_mt
));
let
args_ty
:
ast
::
ty
=
nospan
(
ast
::
ty_vec
(
args_mt
));
let
args_arg
:
ast
::
arg
=
let
args_arg
:
ast
::
arg
=
{
mode
:
ast
::
by_val
,
{
mode
:
ast
::
expl
(
ast
::
by_val
)
,
ty
:
@
args_ty
,
ty
:
@
args_ty
,
ident
:
"args"
,
ident
:
"args"
,
id
:
cx
.sess
.next_node_id
()};
id
:
cx
.sess
.next_node_id
()};
...
...
src/comp/metadata/tydecode.rs
浏览文件 @
77b06d24
...
@@ -353,7 +353,7 @@ fn parse_ty_fn(st: @pstate, conv: conv_did) -> ty::fn_ty {
...
@@ -353,7 +353,7 @@ fn parse_ty_fn(st: @pstate, conv: conv_did) -> ty::fn_ty {
'#'
{
ast
::
by_val
}
'#'
{
ast
::
by_val
}
};
};
st
.pos
+=
1u
;
st
.pos
+=
1u
;
inputs
+=
[{
mode
:
mode
,
ty
:
parse_ty
(
st
,
conv
)}];
inputs
+=
[{
mode
:
ast
::
expl
(
mode
)
,
ty
:
parse_ty
(
st
,
conv
)}];
}
}
st
.pos
+=
1u
;
// eat the ']'
st
.pos
+=
1u
;
// eat the ']'
let
cs
=
parse_constrs
(
st
,
conv
);
let
cs
=
parse_constrs
(
st
,
conv
);
...
...
src/comp/metadata/tyencode.rs
浏览文件 @
77b06d24
...
@@ -203,16 +203,12 @@ fn enc_proto(w: io::writer, proto: proto) {
...
@@ -203,16 +203,12 @@ fn enc_proto(w: io::writer, proto: proto) {
fn
enc_ty_fn
(
w
:
io
::
writer
,
cx
:
@
ctxt
,
ft
:
ty
::
fn_ty
)
{
fn
enc_ty_fn
(
w
:
io
::
writer
,
cx
:
@
ctxt
,
ft
:
ty
::
fn_ty
)
{
w
.write_char
(
'['
);
w
.write_char
(
'['
);
for
arg
:
ty
::
arg
in
ft
.inputs
{
for
arg
:
ty
::
arg
in
ft
.inputs
{
alt
arg
.mode
{
alt
ty
::
resolved_mode
(
cx
.tcx
,
arg
.mode
)
{
by_mut_ref
{
w
.write_char
(
'&'
);
}
by_mut_ref
{
w
.write_char
(
'&'
);
}
by_move
{
w
.write_char
(
'-'
);
}
by_move
{
w
.write_char
(
'-'
);
}
by_copy
{
w
.write_char
(
'+'
);
}
by_copy
{
w
.write_char
(
'+'
);
}
by_ref
{
w
.write_char
(
'='
);
}
by_ref
{
w
.write_char
(
'='
);
}
by_val
{
w
.write_char
(
'#'
);
}
by_val
{
w
.write_char
(
'#'
);
}
// tediously, this has to be there until there's a way
// to constraint post-typeck types not to contain a mode_infer
mode_infer
{
cx
.tcx.sess
.bug
(
"enc_ty_fn: shouldn't see
\
mode_infer"
);
}
}
}
enc_ty
(
w
,
cx
,
arg
.ty
);
enc_ty
(
w
,
cx
,
arg
.ty
);
}
}
...
...
src/comp/middle/alias.rs
浏览文件 @
77b06d24
...
@@ -82,9 +82,11 @@ fn visit_fn(cx: @ctx, _fk: visit::fn_kind, decl: ast::fn_decl,
...
@@ -82,9 +82,11 @@ fn visit_fn(cx: @ctx, _fk: visit::fn_kind, decl: ast::fn_decl,
let
fty
=
ty
::
node_id_to_type
(
cx
.tcx
,
id
);
let
fty
=
ty
::
node_id_to_type
(
cx
.tcx
,
id
);
let
args
=
ty
::
ty_fn_args
(
cx
.tcx
,
fty
);
let
args
=
ty
::
ty_fn_args
(
cx
.tcx
,
fty
);
for
arg
in
args
{
for
arg
in
args
{
if
arg
.mode
==
ast
::
by_val
&&
alt
ty
::
resolved_mode
(
cx
.tcx
,
arg
.mode
)
{
ty
::
type_has_dynamic_size
(
cx
.tcx
,
arg
.ty
)
{
ast
::
by_val
if
ty
::
type_has_dynamic_size
(
cx
.tcx
,
arg
.ty
)
{
err
(
*
cx
,
sp
,
"can not pass a dynamically-sized type by value"
);
err
(
*
cx
,
sp
,
"can not pass a dynamically-sized type by value"
);
}
_
{
/* fallthrough */
}
}
}
}
}
...
@@ -226,7 +228,8 @@ fn check_call(cx: ctx, sc: scope, f: @ast::expr, args: [@ast::expr])
...
@@ -226,7 +228,8 @@ fn check_call(cx: ctx, sc: scope, f: @ast::expr, args: [@ast::expr])
for
arg_t
:
ty
::
arg
in
arg_ts
{
for
arg_t
:
ty
::
arg
in
arg_ts
{
let
arg
=
args
[
i
];
let
arg
=
args
[
i
];
let
root
=
expr_root
(
cx
,
arg
,
false
);
let
root
=
expr_root
(
cx
,
arg
,
false
);
if
arg_t
.mode
==
ast
::
by_mut_ref
{
alt
ty
::
resolved_mode
(
cx
.tcx
,
arg_t
.mode
)
{
ast
::
by_mut_ref
{
alt
path_def
(
cx
,
arg
)
{
alt
path_def
(
cx
,
arg
)
{
some
(
def
)
{
some
(
def
)
{
let
dnum
=
ast_util
::
def_id_of_def
(
def
)
.node
;
let
dnum
=
ast_util
::
def_id_of_def
(
def
)
.node
;
...
@@ -234,18 +237,21 @@ fn check_call(cx: ctx, sc: scope, f: @ast::expr, args: [@ast::expr])
...
@@ -234,18 +237,21 @@ fn check_call(cx: ctx, sc: scope, f: @ast::expr, args: [@ast::expr])
}
}
_
{
}
_
{
}
}
}
}
ast
::
by_ref
|
ast
::
by_val
|
ast
::
by_move
|
ast
::
by_copy
{
}
}
}
let
root_var
=
path_def_id
(
cx
,
root
.ex
);
let
root_var
=
path_def_id
(
cx
,
root
.ex
);
let
arg_copied
=
alt
ty
::
resolved_mode
(
cx
.tcx
,
arg_t
.mode
)
{
ast
::
by_move
|
ast
::
by_copy
{
copied
}
ast
::
by_mut_ref
{
not_allowed
}
ast
::
by_ref
|
ast
::
by_val
{
not_copied
}
};
bindings
+=
[
@
{
node_id
:
arg
.id
,
bindings
+=
[
@
{
node_id
:
arg
.id
,
span
:
arg
.span
,
span
:
arg
.span
,
root_var
:
root_var
,
root_var
:
root_var
,
local_id
:
0u
,
local_id
:
0u
,
unsafe_tys
:
unsafe_set
(
root
.mut
),
unsafe_tys
:
unsafe_set
(
root
.mut
),
mutable
copied
:
alt
arg_t
.mode
{
mutable
copied
:
arg_copied
}];
ast
::
by_move
|
ast
::
by_copy
{
copied
}
ast
::
by_mut_ref
{
not_allowed
}
_
{
not_copied
}
}}];
i
+=
1u
;
i
+=
1u
;
}
}
let
f_may_close
=
let
f_may_close
=
...
@@ -279,7 +285,8 @@ fn check_call(cx: ctx, sc: scope, f: @ast::expr, args: [@ast::expr])
...
@@ -279,7 +285,8 @@ fn check_call(cx: ctx, sc: scope, f: @ast::expr, args: [@ast::expr])
for
unsafe_ty
in
b
.unsafe_tys
{
for
unsafe_ty
in
b
.unsafe_tys
{
let
i
=
0u
;
let
i
=
0u
;
for
arg_t
:
ty
::
arg
in
arg_ts
{
for
arg_t
:
ty
::
arg
in
arg_ts
{
let
mut_alias
=
arg_t
.mode
==
ast
::
by_mut_ref
;
let
mut_alias
=
(
ast
::
by_mut_ref
==
ty
::
arg_mode
(
cx
.tcx
,
arg_t
));
if
i
!=
j
&&
if
i
!=
j
&&
ty_can_unsafely_include
(
cx
,
unsafe_ty
,
arg_t
.ty
,
ty_can_unsafely_include
(
cx
,
unsafe_ty
,
arg_t
.ty
,
mut_alias
)
&&
mut_alias
)
&&
...
...
src/comp/middle/block_use.rs
浏览文件 @
77b06d24
...
@@ -28,7 +28,7 @@ fn visit_expr(ex: @expr, cx: ctx, v: visit::vt<ctx>) {
...
@@ -28,7 +28,7 @@ fn visit_expr(ex: @expr, cx: ctx, v: visit::vt<ctx>) {
v
.visit_expr
(
f
,
cx
,
v
);
v
.visit_expr
(
f
,
cx
,
v
);
let
i
=
0u
;
let
i
=
0u
;
for
arg_t
in
ty
::
ty_fn_args
(
cx
.tcx
,
ty
::
expr_ty
(
cx
.tcx
,
f
))
{
for
arg_t
in
ty
::
ty_fn_args
(
cx
.tcx
,
ty
::
expr_ty
(
cx
.tcx
,
f
))
{
cx
.allow_block
=
arg_t
.mode
==
by_ref
;
cx
.allow_block
=
(
ty
::
arg_mode
(
cx
.tcx
,
arg_t
)
==
by_ref
)
;
v
.visit_expr
(
args
[
i
],
cx
,
v
);
v
.visit_expr
(
args
[
i
],
cx
,
v
);
i
+=
1u
;
i
+=
1u
;
}
}
...
...
src/comp/middle/kind.rs
浏览文件 @
77b06d24
...
@@ -165,7 +165,10 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
...
@@ -165,7 +165,10 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
expr_call
(
f
,
args
,
_
)
{
expr_call
(
f
,
args
,
_
)
{
let
i
=
0u
;
let
i
=
0u
;
for
arg_t
in
ty
::
ty_fn_args
(
cx
.tcx
,
ty
::
expr_ty
(
cx
.tcx
,
f
))
{
for
arg_t
in
ty
::
ty_fn_args
(
cx
.tcx
,
ty
::
expr_ty
(
cx
.tcx
,
f
))
{
alt
arg_t
.mode
{
by_copy
{
maybe_copy
(
cx
,
args
[
i
]);
}
_
{}
}
alt
ty
::
arg_mode
(
cx
.tcx
,
arg_t
)
{
by_copy
{
maybe_copy
(
cx
,
args
[
i
]);
}
by_ref
|
by_val
|
by_mut_ref
|
by_move
{
}
}
i
+=
1u
;
i
+=
1u
;
}
}
}
}
...
...
src/comp/middle/last_use.rs
浏览文件 @
77b06d24
...
@@ -157,7 +157,7 @@ fn visit_expr(ex: @expr, cx: ctx, v: visit::vt<ctx>) {
...
@@ -157,7 +157,7 @@ fn visit_expr(ex: @expr, cx: ctx, v: visit::vt<ctx>) {
fns
+=
[
arg
];
fns
+=
[
arg
];
}
}
_
{
_
{
alt
arg_ts
[
i
]
.mode
{
alt
ty
::
arg_mode
(
cx
.tcx
,
arg_ts
[
i
])
{
by_mut_ref
{
clear_if_path
(
cx
,
arg
,
v
,
false
);
}
by_mut_ref
{
clear_if_path
(
cx
,
arg
,
v
,
false
);
}
_
{
v
.visit_expr
(
arg
,
cx
,
v
);
}
_
{
v
.visit_expr
(
arg
,
cx
,
v
);
}
}
}
...
@@ -286,11 +286,21 @@ fn clear_in_current(cx: ctx, my_def: node_id, to: bool) {
...
@@ -286,11 +286,21 @@ fn clear_in_current(cx: ctx, my_def: node_id, to: bool) {
fn
clear_def_if_path
(
cx
:
ctx
,
d
:
def
,
to
:
bool
)
fn
clear_def_if_path
(
cx
:
ctx
,
d
:
def
,
to
:
bool
)
->
option
<
node_id
>
{
->
option
<
node_id
>
{
alt
d
{
alt
d
{
def_local
(
def_id
,
let_copy
)
|
def_arg
(
def_id
,
by_copy
)
|
def_local
(
def_id
,
let_copy
)
{
def_arg
(
def_id
,
by_move
)
{
clear_in_current
(
cx
,
def_id
.node
,
to
);
clear_in_current
(
cx
,
def_id
.node
,
to
);
some
(
def_id
.node
)
some
(
def_id
.node
)
}
}
def_arg
(
def_id
,
m
)
{
alt
ty
::
resolved_mode
(
cx
.tcx
,
m
)
{
by_copy
|
by_move
{
clear_in_current
(
cx
,
def_id
.node
,
to
);
some
(
def_id
.node
)
}
by_ref
|
by_val
|
by_mut_ref
{
none
}
}
}
_
{
_
{
none
none
}
}
...
...
src/comp/middle/mut.rs
浏览文件 @
77b06d24
...
@@ -228,10 +228,10 @@ fn check_call(cx: @ctx, f: @expr, args: [@expr]) {
...
@@ -228,10 +228,10 @@ fn check_call(cx: @ctx, f: @expr, args: [@expr]) {
let
arg_ts
=
ty
::
ty_fn_args
(
cx
.tcx
,
ty
::
expr_ty
(
cx
.tcx
,
f
));
let
arg_ts
=
ty
::
ty_fn_args
(
cx
.tcx
,
ty
::
expr_ty
(
cx
.tcx
,
f
));
let
i
=
0u
;
let
i
=
0u
;
for
arg_t
:
ty
::
arg
in
arg_ts
{
for
arg_t
:
ty
::
arg
in
arg_ts
{
alt
arg_t
.mode
{
alt
ty
::
resolved_mode
(
cx
.tcx
,
arg_t
.mode
)
{
by_mut_ref
{
check_lval
(
cx
,
args
[
i
],
msg_mut_ref
);
}
by_mut_ref
{
check_lval
(
cx
,
args
[
i
],
msg_mut_ref
);
}
by_move
{
check_lval
(
cx
,
args
[
i
],
msg_move_out
);
}
by_move
{
check_lval
(
cx
,
args
[
i
],
msg_move_out
);
}
_
{
}
by_ref
|
by_val
|
by_copy
{
}
}
}
i
+=
1u
;
i
+=
1u
;
}
}
...
@@ -267,8 +267,12 @@ fn is_immutable_def(cx: @ctx, def: def) -> option<str> {
...
@@ -267,8 +267,12 @@ fn is_immutable_def(cx: @ctx, def: def) -> option<str> {
def_use
(
_
)
{
def_use
(
_
)
{
some
(
"static item"
)
some
(
"static item"
)
}
}
def_arg
(
_
,
by_ref
)
|
def_arg
(
_
,
by_val
)
|
def_arg
(
_
,
m
)
{
def_arg
(
_
,
mode_infer
)
{
some
(
"argument"
)
}
alt
ty
::
resolved_mode
(
cx
.tcx
,
m
)
{
by_ref
|
by_val
{
some
(
"argument"
)
}
by_mut_ref
|
by_move
|
by_copy
{
none
}
}
}
def_self
(
_
)
{
some
(
"self argument"
)
}
def_self
(
_
)
{
some
(
"self argument"
)
}
def_upvar
(
_
,
inner
,
node_id
)
{
def_upvar
(
_
,
inner
,
node_id
)
{
let
ty
=
ty
::
node_id_to_type
(
cx
.tcx
,
node_id
);
let
ty
=
ty
::
node_id_to_type
(
cx
.tcx
,
node_id
);
...
...
src/comp/middle/trans/base.rs
浏览文件 @
77b06d24
...
@@ -63,16 +63,18 @@ fn type_of(cx: @crate_ctxt, t: ty::t) : type_has_static_size(cx, t)
...
@@ -63,16 +63,18 @@ fn type_of(cx: @crate_ctxt, t: ty::t) : type_has_static_size(cx, t)
fn
type_of_explicit_args
(
cx
:
@
crate_ctxt
,
inputs
:
[
ty
::
arg
])
->
fn
type_of_explicit_args
(
cx
:
@
crate_ctxt
,
inputs
:
[
ty
::
arg
])
->
[
TypeRef
]
{
[
TypeRef
]
{
let
atys
=
[]
;
let
tcx
=
ccx_tcx
(
cx
)
;
for
arg
in
inputs
{
vec
::
map
(
inputs
)
{|
arg
|
let
arg_ty
=
arg
.ty
;
let
arg_ty
=
arg
.ty
;
// FIXME: would be nice to have a constraint on arg
// FIXME: would be nice to have a constraint on arg
// that would obviate the need for this check
// that would obviate the need for this check
check
non_ty_var
(
cx
,
arg_ty
);
check
non_ty_var
(
cx
,
arg_ty
);
let
llty
=
type_of_inner
(
cx
,
arg_ty
);
let
llty
=
type_of_inner
(
cx
,
arg_ty
);
atys
+=
[
if
arg
.mode
==
ast
::
by_val
{
llty
}
else
{
T_ptr
(
llty
)
}];
alt
ty
::
resolved_mode
(
tcx
,
arg
.mode
)
{
ast
::
by_val
{
llty
}
_
{
T_ptr
(
llty
)
}
}
}
}
ret
atys
;
}
}
...
@@ -2981,15 +2983,16 @@ fn trans_arg_expr(cx: @block_ctxt, arg: ty::arg, lldestty: TypeRef,
...
@@ -2981,15 +2983,16 @@ fn trans_arg_expr(cx: @block_ctxt, arg: ty::arg, lldestty: TypeRef,
let
lv
=
trans_temp_lval
(
cx
,
e
);
let
lv
=
trans_temp_lval
(
cx
,
e
);
let
bcx
=
lv
.bcx
;
let
bcx
=
lv
.bcx
;
let
val
=
lv
.val
;
let
val
=
lv
.val
;
let
arg_mode
=
ty
::
resolved_mode
(
ccx
.tcx
,
arg
.mode
);
if
is_bot
{
if
is_bot
{
// For values of type _|_, we generate an
// For values of type _|_, we generate an
// "undef" value, as such a value should never
// "undef" value, as such a value should never
// be inspected. It's important for the value
// be inspected. It's important for the value
// to have type lldestty (the callee's expected type).
// to have type lldestty (the callee's expected type).
val
=
llvm
::
LLVMGetUndef
(
lldestty
);
val
=
llvm
::
LLVMGetUndef
(
lldestty
);
}
else
if
arg
.mode
==
ast
::
by_ref
||
arg
.
mode
==
ast
::
by_val
{
}
else
if
arg
_mode
==
ast
::
by_ref
||
arg_
mode
==
ast
::
by_val
{
let
copied
=
false
,
imm
=
ty
::
type_is_immediate
(
ccx
.tcx
,
e_ty
);
let
copied
=
false
,
imm
=
ty
::
type_is_immediate
(
ccx
.tcx
,
e_ty
);
if
arg
.
mode
==
ast
::
by_ref
&&
lv
.kind
!=
owned
&&
imm
{
if
arg
_
mode
==
ast
::
by_ref
&&
lv
.kind
!=
owned
&&
imm
{
val
=
do_spill_noroot
(
bcx
,
val
);
val
=
do_spill_noroot
(
bcx
,
val
);
copied
=
true
;
copied
=
true
;
}
}
...
@@ -3002,10 +3005,10 @@ fn trans_arg_expr(cx: @block_ctxt, arg: ty::arg, lldestty: TypeRef,
...
@@ -3002,10 +3005,10 @@ fn trans_arg_expr(cx: @block_ctxt, arg: ty::arg, lldestty: TypeRef,
}
else
{
bcx
=
take_ty
(
bcx
,
val
,
e_ty
);
}
}
else
{
bcx
=
take_ty
(
bcx
,
val
,
e_ty
);
}
add_clean
(
bcx
,
val
,
e_ty
);
add_clean
(
bcx
,
val
,
e_ty
);
}
}
if
arg
.
mode
==
ast
::
by_val
&&
(
lv
.kind
==
owned
||
!
imm
)
{
if
arg
_
mode
==
ast
::
by_val
&&
(
lv
.kind
==
owned
||
!
imm
)
{
val
=
Load
(
bcx
,
val
);
val
=
Load
(
bcx
,
val
);
}
}
}
else
if
arg
.
mode
==
ast
::
by_copy
{
}
else
if
arg
_
mode
==
ast
::
by_copy
{
let
{
bcx
:
cx
,
val
:
alloc
}
=
alloc_ty
(
bcx
,
e_ty
);
let
{
bcx
:
cx
,
val
:
alloc
}
=
alloc_ty
(
bcx
,
e_ty
);
let
last_use
=
ccx
.last_uses
.contains_key
(
e
.id
);
let
last_use
=
ccx
.last_uses
.contains_key
(
e
.id
);
bcx
=
cx
;
bcx
=
cx
;
...
@@ -3031,7 +3034,7 @@ fn trans_arg_expr(cx: @block_ctxt, arg: ty::arg, lldestty: TypeRef,
...
@@ -3031,7 +3034,7 @@ fn trans_arg_expr(cx: @block_ctxt, arg: ty::arg, lldestty: TypeRef,
}
}
// Collect arg for later if it happens to be one we've moving out.
// Collect arg for later if it happens to be one we've moving out.
if
arg
.
mode
==
ast
::
by_move
{
if
arg
_
mode
==
ast
::
by_move
{
if
lv
.kind
==
owned
{
if
lv
.kind
==
owned
{
// Use actual ty, not declared ty -- anything else doesn't make
// Use actual ty, not declared ty -- anything else doesn't make
// sense if declared ty is a ty param
// sense if declared ty is a ty param
...
@@ -4414,9 +4417,10 @@ fn create_llargs_for_fn_args(cx: @fn_ctxt, ty_self: self_arg,
...
@@ -4414,9 +4417,10 @@ fn create_llargs_for_fn_args(cx: @fn_ctxt, ty_self: self_arg,
fn
copy_args_to_allocas
(
fcx
:
@
fn_ctxt
,
bcx
:
@
block_ctxt
,
args
:
[
ast
::
arg
],
fn
copy_args_to_allocas
(
fcx
:
@
fn_ctxt
,
bcx
:
@
block_ctxt
,
args
:
[
ast
::
arg
],
arg_tys
:
[
ty
::
arg
])
->
@
block_ctxt
{
arg_tys
:
[
ty
::
arg
])
->
@
block_ctxt
{
let
tcx
=
bcx_tcx
(
bcx
);
let
arg_n
:
uint
=
0u
,
bcx
=
bcx
;
let
arg_n
:
uint
=
0u
,
bcx
=
bcx
;
fn
epic_fail_
(
bcx
:
@
block_ctxt
)
->
!
{
let
epic_fail
=
fn
@
(
)
->
!
{
bcx_tcx
(
bcx
)
.sess
.bug
(
"Someone forgot
\
tcx
.sess
.bug
(
"Someone forgot
\
to document an invariant in copy_args_to_allocas!"
);
to document an invariant in copy_args_to_allocas!"
);
}
}
let
epic_fail
=
bind
epic_fail_
(
bcx
);
let
epic_fail
=
bind
epic_fail_
(
bcx
);
...
@@ -4424,7 +4428,7 @@ fn epic_fail_(bcx: @block_ctxt) -> ! {
...
@@ -4424,7 +4428,7 @@ fn epic_fail_(bcx: @block_ctxt) -> ! {
let
id
=
args
[
arg_n
]
.id
;
let
id
=
args
[
arg_n
]
.id
;
let
argval
=
alt
fcx
.llargs
.get
(
id
)
{
local_mem
(
v
)
{
v
}
let
argval
=
alt
fcx
.llargs
.get
(
id
)
{
local_mem
(
v
)
{
v
}
_
{
epic_fail
()
}
};
_
{
epic_fail
()
}
};
alt
arg
.mode
{
alt
ty
::
resolved_mode
(
tcx
,
arg
.mode
)
{
ast
::
by_mut_ref
{
}
ast
::
by_mut_ref
{
}
ast
::
by_move
|
ast
::
by_copy
{
add_clean
(
bcx
,
argval
,
arg
.ty
);
}
ast
::
by_move
|
ast
::
by_copy
{
add_clean
(
bcx
,
argval
,
arg
.ty
);
}
ast
::
by_val
{
ast
::
by_val
{
...
@@ -4438,7 +4442,6 @@ fn epic_fail_(bcx: @block_ctxt) -> ! {
...
@@ -4438,7 +4442,6 @@ fn epic_fail_(bcx: @block_ctxt) -> ! {
}
}
}
}
ast
::
by_ref
{}
ast
::
by_ref
{}
_
{
epic_fail
();
}
}
}
if
fcx_ccx
(
fcx
)
.sess.opts.extra_debuginfo
{
if
fcx_ccx
(
fcx
)
.sess.opts.extra_debuginfo
{
debuginfo
::
create_arg
(
bcx
,
args
[
arg_n
],
args
[
arg_n
]
.ty.span
);
debuginfo
::
create_arg
(
bcx
,
args
[
arg_n
],
args
[
arg_n
]
.ty.span
);
...
@@ -4585,7 +4588,7 @@ fn trans_enum_variant(ccx: @crate_ctxt,
...
@@ -4585,7 +4588,7 @@ fn trans_enum_variant(ccx: @crate_ctxt,
// Translate variant arguments to function arguments.
// Translate variant arguments to function arguments.
let
fn_args
=
[],
i
=
0u
;
let
fn_args
=
[],
i
=
0u
;
for
varg
in
variant
.node.args
{
for
varg
in
variant
.node.args
{
fn_args
+=
[{
mode
:
ast
::
by_copy
,
fn_args
+=
[{
mode
:
ast
::
expl
(
ast
::
by_copy
)
,
ty
:
varg
.ty
,
ty
:
varg
.ty
,
ident
:
"arg"
+
uint
::
to_str
(
i
,
10u
),
ident
:
"arg"
+
uint
::
to_str
(
i
,
10u
),
id
:
varg
.id
}];
id
:
varg
.id
}];
...
@@ -5039,7 +5042,7 @@ fn create_main(ccx: @crate_ctxt, main_llfn: ValueRef,
...
@@ -5039,7 +5042,7 @@ fn create_main(ccx: @crate_ctxt, main_llfn: ValueRef,
takes_argv
:
bool
)
->
ValueRef
{
takes_argv
:
bool
)
->
ValueRef
{
let
unit_ty
=
ty
::
mk_str
(
ccx
.tcx
);
let
unit_ty
=
ty
::
mk_str
(
ccx
.tcx
);
let
vecarg_ty
:
ty
::
arg
=
let
vecarg_ty
:
ty
::
arg
=
{
mode
:
ast
::
by_val
,
{
mode
:
ast
::
expl
(
ast
::
by_val
)
,
ty
:
ty
::
mk_vec
(
ccx
.tcx
,
{
ty
:
unit_ty
,
mut
:
ast
::
imm
})};
ty
:
ty
::
mk_vec
(
ccx
.tcx
,
{
ty
:
unit_ty
,
mut
:
ast
::
imm
})};
// FIXME: mk_nil should have a postcondition
// FIXME: mk_nil should have a postcondition
let
nt
=
ty
::
mk_nil
(
ccx
.tcx
);
let
nt
=
ty
::
mk_nil
(
ccx
.tcx
);
...
...
src/comp/middle/trans/closure.rs
浏览文件 @
77b06d24
...
@@ -895,13 +895,20 @@ fn trans_bind_thunk(ccx: @crate_ctxt,
...
@@ -895,13 +895,20 @@ fn trans_bind_thunk(ccx: @crate_ctxt,
[
0
,
abi
::
closure_body_bindings
,
b
]);
[
0
,
abi
::
closure_body_bindings
,
b
]);
bcx
=
bound_arg
.bcx
;
bcx
=
bound_arg
.bcx
;
let
val
=
bound_arg
.val
;
let
val
=
bound_arg
.val
;
if
out_arg
.mode
==
ast
::
by_val
{
val
=
Load
(
bcx
,
val
);
}
if
out_arg
.mode
==
ast
::
by_copy
{
alt
ty
::
resolved_mode
(
tcx
,
out_arg
.mode
)
{
ast
::
by_val
{
val
=
Load
(
bcx
,
val
);
}
ast
::
by_copy
{
let
{
bcx
:
cx
,
val
:
alloc
}
=
alloc_ty
(
bcx
,
out_arg
.ty
);
let
{
bcx
:
cx
,
val
:
alloc
}
=
alloc_ty
(
bcx
,
out_arg
.ty
);
bcx
=
memmove_ty
(
cx
,
alloc
,
val
,
out_arg
.ty
);
bcx
=
memmove_ty
(
cx
,
alloc
,
val
,
out_arg
.ty
);
bcx
=
take_ty
(
bcx
,
alloc
,
out_arg
.ty
);
bcx
=
take_ty
(
bcx
,
alloc
,
out_arg
.ty
);
val
=
alloc
;
val
=
alloc
;
}
ast
::
by_ref
|
ast
::
by_mut_ref
|
ast
::
by_move
{
}
}
}
// If the type is parameterized, then we need to cast the
// If the type is parameterized, then we need to cast the
// type we actually have to the parameterized out type.
// type we actually have to the parameterized out type.
if
ty
::
type_contains_params
(
ccx
.tcx
,
out_arg
.ty
)
{
if
ty
::
type_contains_params
(
ccx
.tcx
,
out_arg
.ty
)
{
...
...
src/comp/middle/trans/common.rs
浏览文件 @
77b06d24
...
@@ -300,7 +300,8 @@ fn get_res_dtor(ccx: @crate_ctxt, did: ast::def_id, inner_t: ty::t)
...
@@ -300,7 +300,8 @@ fn get_res_dtor(ccx: @crate_ctxt, did: ast::def_id, inner_t: ty::t)
let
nil_res
=
ty
::
mk_nil
(
ccx
.tcx
);
let
nil_res
=
ty
::
mk_nil
(
ccx
.tcx
);
// FIXME: Silly check -- mk_nil should have a postcondition
// FIXME: Silly check -- mk_nil should have a postcondition
check
non_ty_var
(
ccx
,
nil_res
);
check
non_ty_var
(
ccx
,
nil_res
);
let
f_t
=
type_of_fn
(
ccx
,
[{
mode
:
ast
::
by_ref
,
ty
:
inner_t
}],
let
fn_mode
=
ast
::
expl
(
ast
::
by_ref
);
let
f_t
=
type_of_fn
(
ccx
,
[{
mode
:
fn_mode
,
ty
:
inner_t
}],
nil_res
,
*
param_bounds
);
nil_res
,
*
param_bounds
);
ret
base
::
get_extern_const
(
ccx
.externs
,
ccx
.llmod
,
ret
base
::
get_extern_const
(
ccx
.externs
,
ccx
.llmod
,
csearch
::
get_symbol
(
ccx
.sess.cstore
,
csearch
::
get_symbol
(
ccx
.sess.cstore
,
...
...
src/comp/middle/trans/impl.rs
浏览文件 @
77b06d24
...
@@ -63,7 +63,8 @@ fn trans_impl(ccx: @crate_ctxt, path: path, name: ast::ident,
...
@@ -63,7 +63,8 @@ fn trans_impl(ccx: @crate_ctxt, path: path, name: ast::ident,
fn
trans_self_arg
(
bcx
:
@
block_ctxt
,
base
:
@
ast
::
expr
)
->
result
{
fn
trans_self_arg
(
bcx
:
@
block_ctxt
,
base
:
@
ast
::
expr
)
->
result
{
let
tz
=
[],
tr
=
[];
let
tz
=
[],
tr
=
[];
let
basety
=
expr_ty
(
bcx
,
base
);
let
basety
=
expr_ty
(
bcx
,
base
);
let
{
bcx
,
val
}
=
trans_arg_expr
(
bcx
,
{
mode
:
ast
::
by_ref
,
ty
:
basety
},
let
m_by_ref
=
ast
::
expl
(
ast
::
by_ref
);
let
{
bcx
,
val
}
=
trans_arg_expr
(
bcx
,
{
mode
:
m_by_ref
,
ty
:
basety
},
T_ptr
(
type_of_or_i8
(
bcx
,
basety
)),
tz
,
T_ptr
(
type_of_or_i8
(
bcx
,
basety
)),
tz
,
tr
,
base
);
tr
,
base
);
rslt
(
bcx
,
PointerCast
(
bcx
,
val
,
T_opaque_cbox_ptr
(
bcx_ccx
(
bcx
))))
rslt
(
bcx
,
PointerCast
(
bcx
,
val
,
T_opaque_cbox_ptr
(
bcx_ccx
(
bcx
))))
...
...
src/comp/middle/tstate/auxiliary.rs
浏览文件 @
77b06d24
...
@@ -1089,10 +1089,12 @@ fn callee_modes(fcx: fn_ctxt, callee: node_id) -> [mode] {
...
@@ -1089,10 +1089,12 @@ fn callee_modes(fcx: fn_ctxt, callee: node_id) -> [mode] {
}
}
fn
callee_arg_init_ops
(
fcx
:
fn_ctxt
,
callee
:
node_id
)
->
[
init_op
]
{
fn
callee_arg_init_ops
(
fcx
:
fn_ctxt
,
callee
:
node_id
)
->
[
init_op
]
{
fn
mode_to_op
(
m
:
mode
)
->
init_op
{
vec
::
map
(
callee_modes
(
fcx
,
callee
))
{|
m
|
alt
m
{
by_move
{
init_move
}
_
{
init_assign
}
}
alt
ty
::
resolved_mode
(
fcx
.ccx.tcx
,
m
)
{
by_move
{
init_move
}
by_copy
|
by_ref
|
by_val
|
by_mut_ref
{
init_assign
}
}
}
}
vec
::
map
(
callee_modes
(
fcx
,
callee
),
mode_to_op
)
}
}
fn
anon_bindings
(
ops
:
[
init_op
],
es
:
[
@
expr
])
->
[
binding
]
{
fn
anon_bindings
(
ops
:
[
init_op
],
es
:
[
@
expr
])
->
[
binding
]
{
...
...
src/comp/middle/tstate/pre_post_conditions.rs
浏览文件 @
77b06d24
...
@@ -276,12 +276,11 @@ fn handle_var_def(fcx: fn_ctxt, rslt: pre_and_post, def: def, name: ident) {
...
@@ -276,12 +276,11 @@ fn handle_var_def(fcx: fn_ctxt, rslt: pre_and_post, def: def, name: ident) {
fn
forget_args_moved_in
(
fcx
:
fn_ctxt
,
parent
:
@
expr
,
modes
:
[
mode
],
fn
forget_args_moved_in
(
fcx
:
fn_ctxt
,
parent
:
@
expr
,
modes
:
[
mode
],
operands
:
[
@
expr
])
{
operands
:
[
@
expr
])
{
let
i
=
0u
;
vec
::
iteri
(
modes
)
{|
i
,
mode
|
for
mode
:
mode
in
modes
{
alt
ty
::
resolved_mode
(
fcx
.ccx.tcx
,
mode
)
{
if
mode
==
by_move
{
by_move
{
forget_in_postcond
(
fcx
,
parent
.id
,
operands
[
i
]
.id
);
}
forget_in_postcond
(
fcx
,
parent
.id
,
operands
[
i
]
.id
);
by_ref
|
by_val
|
by_mut_ref
|
by_copy
{
}
}
}
i
+=
1u
;
}
}
}
}
...
...
src/comp/middle/ty.rs
浏览文件 @
77b06d24
...
@@ -19,7 +19,6 @@
...
@@ -19,7 +19,6 @@
import
syntax
::
util
::
interner
;
import
syntax
::
util
::
interner
;
import
util
::
ppaux
::
ty_to_str
;
import
util
::
ppaux
::
ty_to_str
;
import
util
::
ppaux
::
ty_constr_to_str
;
import
util
::
ppaux
::
ty_constr_to_str
;
import
util
::
ppaux
::
mode_str
;
import
syntax
::
print
::
pprust
::
*
;
import
syntax
::
print
::
pprust
::
*
;
export
node_id_to_type
;
export
node_id_to_type
;
...
@@ -168,6 +167,10 @@
...
@@ -168,6 +167,10 @@
export
type_structurally_contains_uniques
;
export
type_structurally_contains_uniques
;
export
type_autoderef
;
export
type_autoderef
;
export
type_param
;
export
type_param
;
export
resolved_mode
;
export
arg_mode
;
export
unify_mode
;
export
set_default_mode
;
export
unify
;
export
unify
;
export
variant_info
;
export
variant_info
;
export
walk_ty
;
export
walk_ty
;
...
@@ -178,12 +181,12 @@
...
@@ -178,12 +181,12 @@
export
ck_uniq
;
export
ck_uniq
;
export
param_bound
,
param_bounds
,
bound_copy
,
bound_send
,
bound_iface
;
export
param_bound
,
param_bounds
,
bound_copy
,
bound_send
,
bound_iface
;
export
param_bounds_to_kind
;
export
param_bounds_to_kind
;
export
default_arg_mode_for_ty
;
// Data types
// Data types
// TODO: really should be a separate type, or a refinement,
// Note: after typeck, you should use resolved_mode() to convert this mode
// so that we don't have to handle the mode_infer case after
// into an rmode, which will take into account the results of mode inference.
// typeck. but that's too hard right now.
type
arg
=
{
mode
:
ast
::
mode
,
ty
:
t
};
type
arg
=
{
mode
:
ast
::
mode
,
ty
:
t
};
type
field
=
{
ident
:
ast
::
ident
,
mt
:
mt
};
type
field
=
{
ident
:
ast
::
ident
,
mt
:
mt
};
...
@@ -217,7 +220,8 @@
...
@@ -217,7 +220,8 @@
ast_ty_to_ty_cache
:
hashmap
<@
ast
::
ty
,
option
<
t
>>
,
ast_ty_to_ty_cache
:
hashmap
<@
ast
::
ty
,
option
<
t
>>
,
enum_var_cache
:
hashmap
<
def_id
,
@
[
variant_info
]
>
,
enum_var_cache
:
hashmap
<
def_id
,
@
[
variant_info
]
>
,
iface_method_cache
:
hashmap
<
def_id
,
@
[
method
]
>
,
iface_method_cache
:
hashmap
<
def_id
,
@
[
method
]
>
,
ty_param_bounds
:
hashmap
<
ast
::
node_id
,
param_bounds
>
};
ty_param_bounds
:
hashmap
<
ast
::
node_id
,
param_bounds
>
,
inferred_modes
:
hashmap
<
ast
::
node_id
,
ast
::
mode
>
};
type
ty_ctxt
=
ctxt
;
type
ty_ctxt
=
ctxt
;
...
@@ -424,7 +428,8 @@ fn eq_raw_ty(&&a: @raw_t, &&b: @raw_t) -> bool {
...
@@ -424,7 +428,8 @@ fn eq_raw_ty(&&a: @raw_t, &&b: @raw_t) -> bool {
map
::
mk_hashmap
(
ast_util
::
hash_ty
,
ast_util
::
eq_ty
),
map
::
mk_hashmap
(
ast_util
::
hash_ty
,
ast_util
::
eq_ty
),
enum_var_cache
:
new_def_hash
(),
enum_var_cache
:
new_def_hash
(),
iface_method_cache
:
new_def_hash
(),
iface_method_cache
:
new_def_hash
(),
ty_param_bounds
:
map
::
new_int_hash
()};
ty_param_bounds
:
map
::
new_int_hash
(),
inferred_modes
:
map
::
new_int_hash
()};
populate_type_store
(
cx
);
populate_type_store
(
cx
);
ret
cx
;
ret
cx
;
}
}
...
@@ -646,6 +651,12 @@ fn mk_named(cx: ctxt, base: t, name: @str) -> t {
...
@@ -646,6 +651,12 @@ fn mk_named(cx: ctxt, base: t, name: @str) -> t {
}
}
}
}
fn
default_arg_mode_for_ty
(
tcx
:
ty
::
ctxt
,
ty
:
ty
::
t
)
->
ast
::
rmode
{
assert
!
ty
::
type_contains_vars
(
tcx
,
ty
);
if
ty
::
type_is_immediate
(
tcx
,
ty
)
{
ast
::
by_val
}
else
{
ast
::
by_ref
}
}
fn
walk_ty
(
cx
:
ctxt
,
ty
:
t
,
f
:
fn
(
t
))
{
fn
walk_ty
(
cx
:
ctxt
,
ty
:
t
,
f
:
fn
(
t
))
{
alt
struct
(
cx
,
ty
)
{
alt
struct
(
cx
,
ty
)
{
ty_nil
|
ty_bot
|
ty_bool
|
ty_int
(
_
)
|
ty_uint
(
_
)
|
ty_float
(
_
)
|
ty_nil
|
ty_bot
|
ty_bool
|
ty_int
(
_
)
|
ty_uint
(
_
)
|
ty_float
(
_
)
|
...
@@ -684,13 +695,14 @@ enum fold_mode {
...
@@ -684,13 +695,14 @@ enum fold_mode {
fn
fold_ty
(
cx
:
ctxt
,
fld
:
fold_mode
,
ty_0
:
t
)
->
t
{
fn
fold_ty
(
cx
:
ctxt
,
fld
:
fold_mode
,
ty_0
:
t
)
->
t
{
let
ty
=
ty_0
;
let
ty
=
ty_0
;
// Fast paths.
// Fast paths.
alt
fld
{
alt
fld
{
fm_var
(
_
)
{
if
!
type_contains_vars
(
cx
,
ty
)
{
ret
ty
;
}
}
fm_var
(
_
)
{
if
!
type_contains_vars
(
cx
,
ty
)
{
ret
ty
;
}
}
fm_param
(
_
)
{
if
!
type_contains_params
(
cx
,
ty
)
{
ret
ty
;
}
}
fm_param
(
_
)
{
if
!
type_contains_params
(
cx
,
ty
)
{
ret
ty
;
}
}
fm_general
(
_
)
{
/* no fast path */
}
fm_general
(
_
)
{
/* no fast path */
}
}
}
alt
interner
::
get
(
*
cx
.ts
,
ty
)
.struct
{
alt
interner
::
get
(
*
cx
.ts
,
ty
)
.struct
{
ty_nil
|
ty_bot
|
ty_bool
|
ty_int
(
_
)
|
ty_uint
(
_
)
|
ty_float
(
_
)
|
ty_nil
|
ty_bot
|
ty_bool
|
ty_int
(
_
)
|
ty_uint
(
_
)
|
ty_float
(
_
)
|
ty_str
|
ty_type
|
ty_send_type
|
ty_opaque_closure_ptr
(
_
)
{}
ty_str
|
ty_type
|
ty_send_type
|
ty_opaque_closure_ptr
(
_
)
{}
...
@@ -1619,6 +1631,77 @@ fn occurs_check_fails(tcx: ctxt, sp: option<span>, vid: int, rt: t) ->
...
@@ -1619,6 +1631,77 @@ fn occurs_check_fails(tcx: ctxt, sp: option<span>, vid: int, rt: t) ->
}
else
{
ret
false
;
}
}
else
{
ret
false
;
}
}
}
// Maintains a little union-set tree for inferred modes. `canon()` returns
// the current head value for `m0`.
fn
canon
<
T
:
copy
>
(
tbl
:
hashmap
<
ast
::
node_id
,
ast
::
inferable
<
T
>>
,
m0
:
ast
::
inferable
<
T
>
)
->
ast
::
inferable
<
T
>
{
alt
m0
{
ast
::
infer
(
id
)
{
alt
tbl
.find
(
id
)
{
none
{
m0
}
some
(
m1
)
{
let
cm1
=
canon
(
tbl
,
m1
);
// path compression:
if
cm1
!=
m1
{
tbl
.insert
(
id
,
cm1
);
}
cm1
}
}
}
_
{
m0
}
}
}
// Maintains a little union-set tree for inferred modes. `resolve_mode()`
// returns the current head value for `m0`.
fn
canon_mode
(
cx
:
ctxt
,
m0
:
ast
::
mode
)
->
ast
::
mode
{
canon
(
cx
.inferred_modes
,
m0
)
}
// Returns the head value for mode, failing if `m` was a infer(_) that
// was never inferred. This should be safe for use after typeck.
fn
resolved_mode
(
cx
:
ctxt
,
m
:
ast
::
mode
)
->
ast
::
rmode
{
alt
canon_mode
(
cx
,
m
)
{
ast
::
infer
(
_
)
{
cx
.sess
.bug
(
#
fmt
[
"mode %? was never resolved"
,
m
]);
}
ast
::
expl
(
m0
)
{
m0
}
}
}
fn
arg_mode
(
cx
:
ctxt
,
a
:
arg
)
->
ast
::
rmode
{
ty
::
resolved_mode
(
cx
,
a
.mode
)
}
// Unifies `m1` and `m2`. Returns unified value or failure code.
fn
unify_mode
(
cx
:
ctxt
,
m1
:
ast
::
mode
,
m2
:
ast
::
mode
)
->
result
::
t
<
ast
::
mode
,
type_err
>
{
alt
(
canon_mode
(
cx
,
m1
),
canon_mode
(
cx
,
m2
))
{
(
m1
,
m2
)
if
(
m1
==
m2
)
{
result
::
ok
(
m1
)
}
(
ast
::
infer
(
id1
),
ast
::
infer
(
id2
))
{
cx
.inferred_modes
.insert
(
id2
,
m1
);
result
::
ok
(
m1
)
}
(
ast
::
infer
(
id
),
m
)
|
(
m
,
ast
::
infer
(
id
))
{
cx
.inferred_modes
.insert
(
id
,
m
);
result
::
ok
(
m1
)
}
(
m1
,
m2
)
{
result
::
err
(
terr_mode_mismatch
(
m1
,
m2
))
}
}
}
// If `m` was never unified, unifies it with `m_def`. Returns the final value
// for `m`.
fn
set_default_mode
(
cx
:
ctxt
,
m
:
ast
::
mode
,
m_def
:
ast
::
rmode
)
{
alt
canon_mode
(
cx
,
m
)
{
ast
::
infer
(
id
)
{
cx
.inferred_modes
.insert
(
id
,
ast
::
expl
(
m_def
));
}
ast
::
expl
(
_
)
{
}
}
}
// Type unification via Robinson's algorithm (Robinson 1965). Implemented as
// Type unification via Robinson's algorithm (Robinson 1965). Implemented as
// described in Hoder and Voronkov:
// described in Hoder and Voronkov:
//
//
...
@@ -1869,15 +1952,14 @@ fn unify_args(cx: @ctxt, e_args: [arg], a_args: [arg], variance: variance)
...
@@ -1869,15 +1952,14 @@ fn unify_args(cx: @ctxt, e_args: [arg], a_args: [arg], variance: variance)
for
expected_input
in
e_args
{
for
expected_input
in
e_args
{
let
actual_input
=
a_args
[
i
];
let
actual_input
=
a_args
[
i
];
i
+=
1u
;
i
+=
1u
;
// Unify the result modes.
// Unify the result modes.
let
result_mode
=
if
expected_input
.mode
==
ast
::
mode_infer
{
let
result_mode
=
actual_input
.mode
alt
unify_mode
(
cx
.tcx
,
expected_input
.mode
,
}
else
if
actual_input
.mode
==
ast
::
mode_infer
{
actual_input
.mode
)
{
expected_input
.mode
result
::
err
(
err
)
{
ret
either
::
left
(
ures_err
(
err
));
}
}
else
if
expected_input
.mode
!=
actual_input
.mode
{
result
::
ok
(
m
)
{
m
}
ret
either
::
left
(
ures_err
(
terr_mode_mismatch
(
};
expected_input
.mode
,
actual_input
.mode
)));
}
else
{
expected_input
.mode
};
alt
unify_step
(
cx
,
expected_input
.ty
,
actual_input
.ty
,
alt
unify_step
(
cx
,
expected_input
.ty
,
actual_input
.ty
,
variance
)
{
variance
)
{
...
@@ -2446,8 +2528,8 @@ fn to_str(s: ast::ret_style) -> str {
...
@@ -2446,8 +2528,8 @@ fn to_str(s: ast::ret_style) -> str {
}
}
terr_arg_count
{
ret
"incorrect number of function parameters"
;
}
terr_arg_count
{
ret
"incorrect number of function parameters"
;
}
terr_mode_mismatch
(
e_mode
,
a_mode
)
{
terr_mode_mismatch
(
e_mode
,
a_mode
)
{
ret
"expected argument mode "
+
mode_str
(
e_mode
)
+
" but found "
+
ret
"expected argument mode "
+
mode_
to_
str
(
e_mode
)
+
" but found "
+
mode_str
(
a_mode
);
mode_
to_
str
(
a_mode
);
}
}
terr_constr_len
(
e_len
,
a_len
)
{
terr_constr_len
(
e_len
,
a_len
)
{
ret
"Expected a type with "
+
uint
::
str
(
e_len
)
+
ret
"Expected a type with "
+
uint
::
str
(
e_len
)
+
...
...
src/comp/middle/typeck.rs
浏览文件 @
77b06d24
...
@@ -64,7 +64,6 @@ enum self_info {
...
@@ -64,7 +64,6 @@ enum self_info {
var_bindings
:
@
ty
::
unify
::
var_bindings
,
var_bindings
:
@
ty
::
unify
::
var_bindings
,
locals
:
hashmap
<
ast
::
node_id
,
int
>
,
locals
:
hashmap
<
ast
::
node_id
,
int
>
,
next_var_id
:
@
mutable
int
,
next_var_id
:
@
mutable
int
,
mutable
fixups
:
[
ast
::
node_id
],
ccx
:
@
crate_ctxt
};
ccx
:
@
crate_ctxt
};
...
@@ -215,27 +214,11 @@ fn type_is_c_like_enum(fcx: @fn_ctxt, sp: span, typ: ty::t) -> bool {
...
@@ -215,27 +214,11 @@ fn type_is_c_like_enum(fcx: @fn_ctxt, sp: span, typ: ty::t) -> bool {
ret
ty
::
type_is_c_like_enum
(
fcx
.ccx.tcx
,
typ_s
);
ret
ty
::
type_is_c_like_enum
(
fcx
.ccx.tcx
,
typ_s
);
}
}
// Parses the programmer's textual representation of a type into our internal
// notion of a type. `getter` is a function that returns the type
// corresponding to a definition ID:
fn
default_arg_mode_for_ty
(
tcx
:
ty
::
ctxt
,
m
:
ast
::
mode
,
ty
:
ty
::
t
)
->
ast
::
mode
{
alt
m
{
ast
::
mode_infer
{
alt
ty
::
struct
(
tcx
,
ty
)
{
ty
::
ty_var
(
_
)
{
ast
::
mode_infer
}
_
{
if
ty
::
type_is_immediate
(
tcx
,
ty
)
{
ast
::
by_val
}
else
{
ast
::
by_ref
}
}
}
}
_
{
m
}
}
}
enum
mode
{
m_collect
,
m_check
,
m_check_tyvar
(
@
fn_ctxt
),
}
enum
mode
{
m_collect
,
m_check
,
m_check_tyvar
(
@
fn_ctxt
),
}
// Parses the programmer's textual representation of a type into our
// internal notion of a type. `getter` is a function that returns the type
// corresponding to a definition ID:
fn
ast_ty_to_ty
(
tcx
:
ty
::
ctxt
,
mode
:
mode
,
&&
ast_ty
:
@
ast
::
ty
)
->
ty
::
t
{
fn
ast_ty_to_ty
(
tcx
:
ty
::
ctxt
,
mode
:
mode
,
&&
ast_ty
:
@
ast
::
ty
)
->
ty
::
t
{
fn
getter
(
tcx
:
ty
::
ctxt
,
mode
:
mode
,
id
:
ast
::
def_id
)
fn
getter
(
tcx
:
ty
::
ctxt
,
mode
:
mode
,
id
:
ast
::
def_id
)
->
ty
::
ty_param_bounds_and_ty
{
->
ty
::
ty_param_bounds_and_ty
{
...
@@ -443,13 +426,38 @@ fn ty_of_native_item(tcx: ty::ctxt, mode: mode, it: @ast::native_item)
...
@@ -443,13 +426,38 @@ fn ty_of_native_item(tcx: ty::ctxt, mode: mode, it: @ast::native_item)
}
}
}
}
fn
ty_of_arg
(
tcx
:
ty
::
ctxt
,
mode
:
mode
,
a
:
ast
::
arg
)
->
ty
::
arg
{
fn
ty_of_arg
(
tcx
:
ty
::
ctxt
,
mode
:
mode
,
a
:
ast
::
arg
)
->
ty
::
arg
{
fn
arg_mode
(
tcx
:
ty
::
ctxt
,
m
:
ast
::
mode
,
ty
:
ty
::
t
)
->
ast
::
mode
{
alt
m
{
ast
::
infer
(
_
)
{
alt
ty
::
struct
(
tcx
,
ty
)
{
// If the type is not specified, then this must be a fn expr.
// Leave the mode as infer(_), it will get inferred based
// on constraints elsewhere.
ty
::
ty_var
(
_
)
{
m
}
// If the type is known, then use the default for that type.
// Here we unify m and the default. This should update the
// tables in tcx but should never fail, because nothing else
// will have been unified with m yet:
_
{
let
m1
=
ast
::
expl
(
ty
::
default_arg_mode_for_ty
(
tcx
,
ty
));
result
::
get
(
ty
::
unify_mode
(
tcx
,
m
,
m1
))
}
}
}
ast
::
expl
(
_
)
{
m
}
}
}
let
ty
=
ast_ty_to_ty
(
tcx
,
mode
,
a
.ty
);
let
ty
=
ast_ty_to_ty
(
tcx
,
mode
,
a
.ty
);
{
mode
:
default_arg_mode_for_ty
(
tcx
,
a
.mode
,
ty
),
ty
:
ty
}
let
mode
=
arg_mode
(
tcx
,
a
.mode
,
ty
);
}
{
mode
:
mode
,
ty
:
ty
}
fn
ty_of_fn_decl
(
tcx
:
ty
::
ctxt
,
mode
:
mode
,
}
proto
:
ast
::
proto
,
decl
:
ast
::
fn_decl
)
->
ty
::
fn_ty
{
fn
ty_of_fn_decl
(
tcx
:
ty
::
ctxt
,
let
input_tys
=
[];
mode
:
mode
,
for
a
:
ast
::
arg
in
decl
.inputs
{
input_tys
+=
[
ty_of_arg
(
tcx
,
mode
,
a
)];
}
proto
:
ast
::
proto
,
decl
:
ast
::
fn_decl
)
->
ty
::
fn_ty
{
let
input_tys
=
vec
::
map
(
decl
.inputs
)
{|
a
|
ty_of_arg
(
tcx
,
mode
,
a
)
};
let
output_ty
=
ast_ty_to_ty
(
tcx
,
mode
,
decl
.output
);
let
output_ty
=
ast_ty_to_ty
(
tcx
,
mode
,
decl
.output
);
let
out_constrs
=
[];
let
out_constrs
=
[];
...
@@ -472,7 +480,9 @@ fn ty_of_native_fn_decl(tcx: ty::ctxt, mode: mode, decl: ast::fn_decl,
...
@@ -472,7 +480,9 @@ fn ty_of_native_fn_decl(tcx: ty::ctxt, mode: mode, decl: ast::fn_decl,
ty_params
:
[
ast
::
ty_param
],
def_id
:
ast
::
def_id
)
ty_params
:
[
ast
::
ty_param
],
def_id
:
ast
::
def_id
)
->
ty
::
ty_param_bounds_and_ty
{
->
ty
::
ty_param_bounds_and_ty
{
let
input_tys
=
[],
bounds
=
ty_param_bounds
(
tcx
,
mode
,
ty_params
);
let
input_tys
=
[],
bounds
=
ty_param_bounds
(
tcx
,
mode
,
ty_params
);
for
a
:
ast
::
arg
in
decl
.inputs
{
input_tys
+=
[
ty_of_arg
(
tcx
,
mode
,
a
)];
}
for
a
:
ast
::
arg
in
decl
.inputs
{
input_tys
+=
[
ty_of_arg
(
tcx
,
mode
,
a
)];
}
let
output_ty
=
ast_ty_to_ty
(
tcx
,
mode
,
decl
.output
);
let
output_ty
=
ast_ty_to_ty
(
tcx
,
mode
,
decl
.output
);
let
t_fn
=
ty
::
mk_fn
(
tcx
,
{
proto
:
ast
::
proto_bare
,
let
t_fn
=
ty
::
mk_fn
(
tcx
,
{
proto
:
ast
::
proto_bare
,
...
@@ -585,7 +595,9 @@ fn compare_impl_method(tcx: ty::ctxt, sp: span, impl_m: ty::method,
...
@@ -585,7 +595,9 @@ fn compare_impl_method(tcx: ty::ctxt, sp: span, impl_m: ty::method,
}
else
{
}
else
{
let
auto_modes
=
vec
::
map2
(
impl_m
.fty.inputs
,
if_m
.fty.inputs
,
{|
i
,
f
|
let
auto_modes
=
vec
::
map2
(
impl_m
.fty.inputs
,
if_m
.fty.inputs
,
{|
i
,
f
|
alt
ty
::
struct
(
tcx
,
f
.ty
)
{
alt
ty
::
struct
(
tcx
,
f
.ty
)
{
ty
::
ty_param
(
0u
,
_
)
{
{
mode
:
ast
::
by_ref
with
i
}
}
ty
::
ty_param
(
0u
,
_
)
{
{
mode
:
ast
::
expl
(
ast
::
by_ref
)
with
i
}
}
_
{
i
}
_
{
i
}
}
}
});
});
...
@@ -641,7 +653,7 @@ fn get_enum_variant_types(cx: @ctxt, enum_ty: ty::t,
...
@@ -641,7 +653,7 @@ fn get_enum_variant_types(cx: @ctxt, enum_ty: ty::t,
let
args
:
[
arg
]
=
[];
let
args
:
[
arg
]
=
[];
for
va
:
ast
::
variant_arg
in
variant
.node.args
{
for
va
:
ast
::
variant_arg
in
variant
.node.args
{
let
arg_ty
=
ast_ty_to_ty
(
cx
.tcx
,
m_collect
,
va
.ty
);
let
arg_ty
=
ast_ty_to_ty
(
cx
.tcx
,
m_collect
,
va
.ty
);
args
+=
[{
mode
:
ast
::
by_copy
,
ty
:
arg_ty
}];
args
+=
[{
mode
:
ast
::
expl
(
ast
::
by_copy
)
,
ty
:
arg_ty
}];
}
}
// FIXME: this will be different for constrained types
// FIXME: this will be different for constrained types
ty
::
mk_fn
(
cx
.tcx
,
ty
::
mk_fn
(
cx
.tcx
,
...
@@ -716,7 +728,7 @@ fn convert(cx: @ctxt, it: @ast::item) {
...
@@ -716,7 +728,7 @@ fn convert(cx: @ctxt, it: @ast::item) {
params
);
params
);
let
t_ctor
=
ty
::
mk_fn
(
cx
.tcx
,
{
let
t_ctor
=
ty
::
mk_fn
(
cx
.tcx
,
{
proto
:
ast
::
proto_box
,
proto
:
ast
::
proto_box
,
inputs
:
[{
mode
:
ast
::
by_copy
with
t_arg
}],
inputs
:
[{
mode
:
ast
::
expl
(
ast
::
by_copy
)
with
t_arg
}],
output
:
t_res
,
output
:
t_res
,
ret_style
:
ast
::
return_val
,
constraints
:
[]
ret_style
:
ast
::
return_val
,
constraints
:
[]
});
});
...
@@ -925,9 +937,6 @@ fn variant_arg_types(ccx: @crate_ctxt, _sp: span, vid: ast::def_id,
...
@@ -925,9 +937,6 @@ fn variant_arg_types(ccx: @crate_ctxt, _sp: span, vid: ast::def_id,
// Type resolution: the phase that finds all the types in the AST with
// Type resolution: the phase that finds all the types in the AST with
// unresolved type variables and replaces "ty_var" types with their
// unresolved type variables and replaces "ty_var" types with their
// substitutions.
// substitutions.
//
// TODO: inefficient since not all types have vars in them. It would be better
// to maintain a list of fixups.
mod
writeback
{
mod
writeback
{
export
resolve_type_vars_in_block
;
export
resolve_type_vars_in_block
;
...
@@ -946,24 +955,32 @@ fn resolve_type_vars_in_type(fcx: @fn_ctxt, sp: span, typ: ty::t) ->
...
@@ -946,24 +955,32 @@ fn resolve_type_vars_in_type(fcx: @fn_ctxt, sp: span, typ: ty::t) ->
}
}
}
}
}
}
fn
resolve_type_vars_for_node
(
wbcx
:
wb_ctxt
,
sp
:
span
,
id
:
ast
::
node_id
)
{
fn
resolve_type_vars_for_node
(
wbcx
:
wb_ctxt
,
sp
:
span
,
id
:
ast
::
node_id
)
->
option
<
ty
::
t
>
{
let
fcx
=
wbcx
.fcx
,
tcx
=
fcx
.ccx.tcx
;
let
fcx
=
wbcx
.fcx
,
tcx
=
fcx
.ccx.tcx
;
alt
resolve_type_vars_in_type
(
fcx
,
sp
,
ty
::
node_id_to_type
(
tcx
,
id
))
{
alt
resolve_type_vars_in_type
(
fcx
,
sp
,
ty
::
node_id_to_type
(
tcx
,
id
))
{
some
(
t
)
{
write_ty
(
tcx
,
id
,
t
);
}
none
{
none
{
wbcx
.success
=
false
;
ret
}
wbcx
.success
=
false
;
}
ret
none
;
alt
tcx
.node_type_substs
.find
(
id
)
{
}
some
(
substs
)
{
let
new_substs
=
[];
some
(
t
)
{
for
subst
:
ty
::
t
in
substs
{
write_ty
(
tcx
,
id
,
t
);
alt
resolve_type_vars_in_type
(
fcx
,
sp
,
subst
)
{
alt
tcx
.node_type_substs
.find
(
id
)
{
some
(
t
)
{
new_substs
+=
[
t
];
}
some
(
substs
)
{
none
{
wbcx
.success
=
false
;
ret
;
}
let
new_substs
=
[];
for
subst
:
ty
::
t
in
substs
{
alt
resolve_type_vars_in_type
(
fcx
,
sp
,
subst
)
{
some
(
t
)
{
new_substs
+=
[
t
];
}
none
{
wbcx
.success
=
false
;
ret
none
;
}
}
}
}
write_substs
(
tcx
,
id
,
new_substs
);
}
none
{}
}
}
write_substs
(
tcx
,
id
,
new_substs
);
ret
some
(
t
);
}
}
none
{}
}
}
}
}
...
@@ -984,8 +1001,19 @@ fn visit_expr(e: @ast::expr, wbcx: wb_ctxt, v: wb_vt) {
...
@@ -984,8 +1001,19 @@ fn visit_expr(e: @ast::expr, wbcx: wb_ctxt, v: wb_vt) {
alt
e
.node
{
alt
e
.node
{
ast
::
expr_fn
(
_
,
decl
,
_
,
_
)
|
ast
::
expr_fn
(
_
,
decl
,
_
,
_
)
|
ast
::
expr_fn_block
(
decl
,
_
)
{
ast
::
expr_fn_block
(
decl
,
_
)
{
for
input
in
decl
.inputs
{
vec
::
iter
(
decl
.inputs
)
{|
input
|
resolve_type_vars_for_node
(
wbcx
,
e
.span
,
input
.id
);
let
r_ty
=
resolve_type_vars_for_node
(
wbcx
,
e
.span
,
input
.id
);
// Just in case we never constrained the mode to anything,
// constrain it to the default for the type in question.
alt
(
r_ty
,
input
.mode
)
{
(
some
(
t
),
ast
::
infer
(
_
))
{
let
tcx
=
wbcx
.fcx.ccx.tcx
;
let
m_def
=
ty
::
default_arg_mode_for_ty
(
tcx
,
t
);
ty
::
set_default_mode
(
tcx
,
input
.mode
,
m_def
);
}
_
{}
}
}
}
}
}
_
{
}
_
{
}
...
@@ -1541,8 +1569,8 @@ fn check_expr_fn_with_unifier(fcx: @fn_ctxt,
...
@@ -1541,8 +1569,8 @@ fn check_expr_fn_with_unifier(fcx: @fn_ctxt,
unify
:
unifier
,
unify
:
unifier
,
expected
:
ty
::
t
)
{
expected
:
ty
::
t
)
{
let
tcx
=
fcx
.ccx.tcx
;
let
tcx
=
fcx
.ccx.tcx
;
let
fty
=
ty
::
mk_fn
(
tcx
,
ty_of_fn_decl
(
tcx
,
m_check_tyvar
(
fcx
),
let
fty
=
ty
::
mk_fn
(
tcx
,
proto
,
decl
));
ty_of_fn_decl
(
tcx
,
m_check_tyvar
(
fcx
),
proto
,
decl
));
#
debug
(
"check_expr_fn_with_unifier %s fty=%s"
,
#
debug
(
"check_expr_fn_with_unifier %s fty=%s"
,
expr_to_str
(
expr
),
expr_to_str
(
expr
),
...
@@ -1600,7 +1628,8 @@ fn check_call_or_bind(fcx: @fn_ctxt, sp: span, fty: ty::t,
...
@@ -1600,7 +1628,8 @@ fn check_call_or_bind(fcx: @fn_ctxt, sp: span, fty: ty::t,
}]);
}]);
// HACK: build an arguments list with dummy arguments to
// HACK: build an arguments list with dummy arguments to
// check against
// check against
let
dummy
=
{
mode
:
ast
::
by_ref
,
ty
:
ty
::
mk_bot
(
fcx
.ccx.tcx
)};
let
dummy
=
{
mode
:
ast
::
expl
(
ast
::
by_ref
),
ty
:
ty
::
mk_bot
(
fcx
.ccx.tcx
)};
arg_tys
=
vec
::
init_elt
(
supplied_arg_count
,
dummy
);
arg_tys
=
vec
::
init_elt
(
supplied_arg_count
,
dummy
);
}
}
...
@@ -2027,7 +2056,6 @@ fn check_user_unop(fcx: @fn_ctxt, op_str: str, mname: str,
...
@@ -2027,7 +2056,6 @@ fn check_user_unop(fcx: @fn_ctxt, op_str: str, mname: str,
ty_to_str
(
tcx
,
expected
));
ty_to_str
(
tcx
,
expected
));
check_expr_fn_with_unifier
(
fcx
,
expr
,
proto
,
decl
,
body
,
check_expr_fn_with_unifier
(
fcx
,
expr
,
proto
,
decl
,
body
,
unify
,
expected
);
unify
,
expected
);
write_ty
(
tcx
,
id
,
expected
);
}
}
ast
::
expr_block
(
b
)
{
ast
::
expr_block
(
b
)
{
// If this is an unchecked block, turn off purity-checking
// If this is an unchecked block, turn off purity-checking
...
@@ -2428,7 +2456,6 @@ fn check_const(ccx: @crate_ctxt, _sp: span, e: @ast::expr, id: ast::node_id) {
...
@@ -2428,7 +2456,6 @@ fn check_const(ccx: @crate_ctxt, _sp: span, e: @ast::expr, id: ast::node_id) {
// FIXME: this is kinda a kludge; we manufacture a fake function context
// FIXME: this is kinda a kludge; we manufacture a fake function context
// and statement context for checking the initializer expression.
// and statement context for checking the initializer expression.
let
rty
=
node_id_to_type
(
ccx
.tcx
,
id
);
let
rty
=
node_id_to_type
(
ccx
.tcx
,
id
);
let
fixups
:
[
ast
::
node_id
]
=
[];
let
fcx
:
@
fn_ctxt
=
let
fcx
:
@
fn_ctxt
=
@
{
ret_ty
:
rty
,
@
{
ret_ty
:
rty
,
purity
:
ast
::
pure_fn
,
purity
:
ast
::
pure_fn
,
...
@@ -2436,7 +2463,6 @@ fn check_const(ccx: @crate_ctxt, _sp: span, e: @ast::expr, id: ast::node_id) {
...
@@ -2436,7 +2463,6 @@ fn check_const(ccx: @crate_ctxt, _sp: span, e: @ast::expr, id: ast::node_id) {
var_bindings
:
ty
::
unify
::
mk_var_bindings
(),
var_bindings
:
ty
::
unify
::
mk_var_bindings
(),
locals
:
new_int_hash
::
<
int
>
(),
locals
:
new_int_hash
::
<
int
>
(),
next_var_id
:
@
mutable
0
,
next_var_id
:
@
mutable
0
,
mutable
fixups
:
fixups
,
ccx
:
ccx
};
ccx
:
ccx
};
check_expr
(
fcx
,
e
);
check_expr
(
fcx
,
e
);
let
cty
=
expr_ty
(
fcx
.ccx.tcx
,
e
);
let
cty
=
expr_ty
(
fcx
.ccx.tcx
,
e
);
...
@@ -2449,7 +2475,6 @@ fn check_enum_variants(ccx: @crate_ctxt, sp: span, vs: [ast::variant],
...
@@ -2449,7 +2475,6 @@ fn check_enum_variants(ccx: @crate_ctxt, sp: span, vs: [ast::variant],
// FIXME: this is kinda a kludge; we manufacture a fake function context
// FIXME: this is kinda a kludge; we manufacture a fake function context
// and statement context for checking the initializer expression.
// and statement context for checking the initializer expression.
let
rty
=
node_id_to_type
(
ccx
.tcx
,
id
);
let
rty
=
node_id_to_type
(
ccx
.tcx
,
id
);
let
fixups
:
[
ast
::
node_id
]
=
[];
let
fcx
:
@
fn_ctxt
=
let
fcx
:
@
fn_ctxt
=
@
{
ret_ty
:
rty
,
@
{
ret_ty
:
rty
,
purity
:
ast
::
pure_fn
,
purity
:
ast
::
pure_fn
,
...
@@ -2457,7 +2482,6 @@ fn check_enum_variants(ccx: @crate_ctxt, sp: span, vs: [ast::variant],
...
@@ -2457,7 +2482,6 @@ fn check_enum_variants(ccx: @crate_ctxt, sp: span, vs: [ast::variant],
var_bindings
:
ty
::
unify
::
mk_var_bindings
(),
var_bindings
:
ty
::
unify
::
mk_var_bindings
(),
locals
:
new_int_hash
::
<
int
>
(),
locals
:
new_int_hash
::
<
int
>
(),
next_var_id
:
@
mutable
0
,
next_var_id
:
@
mutable
0
,
mutable
fixups
:
fixups
,
ccx
:
ccx
};
ccx
:
ccx
};
let
disr_vals
:
[
int
]
=
[];
let
disr_vals
:
[
int
]
=
[];
let
disr_val
=
0
;
let
disr_val
=
0
;
...
@@ -2630,7 +2654,6 @@ fn check_fn(ccx: @crate_ctxt,
...
@@ -2630,7 +2654,6 @@ fn check_fn(ccx: @crate_ctxt,
};
};
let
gather_result
=
gather_locals
(
ccx
,
decl
,
body
,
id
,
old_fcx
);
let
gather_result
=
gather_locals
(
ccx
,
decl
,
body
,
id
,
old_fcx
);
let
fixups
:
[
ast
::
node_id
]
=
[];
let
fcx
:
@
fn_ctxt
=
let
fcx
:
@
fn_ctxt
=
@
{
ret_ty
:
ty
::
ty_fn_ret
(
ccx
.tcx
,
ty
::
node_id_to_type
(
ccx
.tcx
,
id
)),
@
{
ret_ty
:
ty
::
ty_fn_ret
(
ccx
.tcx
,
ty
::
node_id_to_type
(
ccx
.tcx
,
id
)),
purity
:
purity
,
purity
:
purity
,
...
@@ -2638,7 +2661,6 @@ fn check_fn(ccx: @crate_ctxt,
...
@@ -2638,7 +2661,6 @@ fn check_fn(ccx: @crate_ctxt,
var_bindings
:
gather_result
.var_bindings
,
var_bindings
:
gather_result
.var_bindings
,
locals
:
gather_result
.locals
,
locals
:
gather_result
.locals
,
next_var_id
:
gather_result
.next_var_id
,
next_var_id
:
gather_result
.next_var_id
,
mutable
fixups
:
fixups
,
ccx
:
ccx
};
ccx
:
ccx
};
check_constraints
(
fcx
,
decl
.constraints
,
decl
.inputs
);
check_constraints
(
fcx
,
decl
.constraints
,
decl
.inputs
);
...
...
src/comp/syntax/ast.rs
浏览文件 @
77b06d24
...
@@ -160,7 +160,17 @@ enum unop {
...
@@ -160,7 +160,17 @@ enum unop {
deref
,
not
,
neg
,
deref
,
not
,
neg
,
}
}
enum
mode
{
by_ref
,
by_val
,
by_mut_ref
,
by_move
,
by_copy
,
mode_infer
,
}
// Generally, after typeck you can get the inferred value
// using ty::resolved_T(...).
enum
inferable
<
T
>
{
expl
(
T
),
infer
(
node_id
)
}
// "resolved" mode: the real modes.
enum
rmode
{
by_ref
,
by_val
,
by_mut_ref
,
by_move
,
by_copy
}
// inferable mode.
type
mode
=
inferable
<
rmode
>
;
type
stmt
=
spanned
<
stmt_
>
;
type
stmt
=
spanned
<
stmt_
>
;
...
...
src/comp/syntax/parse/parser.rs
浏览文件 @
77b06d24
...
@@ -521,14 +521,19 @@ fn parse_ty(p: parser, colons_before_params: bool) -> @ast::ty {
...
@@ -521,14 +521,19 @@ fn parse_ty(p: parser, colons_before_params: bool) -> @ast::ty {
}
}
fn
parse_arg_mode
(
p
:
parser
)
->
ast
::
mode
{
fn
parse_arg_mode
(
p
:
parser
)
->
ast
::
mode
{
if
eat
(
p
,
token
::
BINOP
(
token
::
AND
))
{
ast
::
by_mut_ref
}
if
eat
(
p
,
token
::
BINOP
(
token
::
AND
))
{
else
if
eat
(
p
,
token
::
BINOP
(
token
::
MINUS
))
{
ast
::
by_move
}
ast
::
expl
(
ast
::
by_mut_ref
)
else
if
eat
(
p
,
token
::
ANDAND
)
{
ast
::
by_ref
}
}
else
if
eat
(
p
,
token
::
BINOP
(
token
::
MINUS
))
{
else
if
eat
(
p
,
token
::
BINOP
(
token
::
PLUS
))
{
ast
::
expl
(
ast
::
by_move
)
if
eat
(
p
,
token
::
BINOP
(
token
::
PLUS
))
{
ast
::
by_val
}
}
else
if
eat
(
p
,
token
::
ANDAND
)
{
else
{
ast
::
by_copy
}
ast
::
expl
(
ast
::
by_ref
)
}
}
else
if
eat
(
p
,
token
::
BINOP
(
token
::
PLUS
))
{
else
{
ast
::
mode_infer
}
if
eat
(
p
,
token
::
BINOP
(
token
::
PLUS
))
{
ast
::
expl
(
ast
::
by_val
)
}
else
{
ast
::
expl
(
ast
::
by_copy
)
}
}
else
{
ast
::
infer
(
p
.get_id
())
}
}
}
fn
parse_arg
(
p
:
parser
)
->
ast
::
arg
{
fn
parse_arg
(
p
:
parser
)
->
ast
::
arg
{
...
@@ -1984,8 +1989,8 @@ fn parse_item_res(p: parser, attrs: [ast::attribute]) -> @ast::item {
...
@@ -1984,8 +1989,8 @@ fn parse_item_res(p: parser, attrs: [ast::attribute]) -> @ast::item {
let
dtor
=
parse_block_no_value
(
p
);
let
dtor
=
parse_block_no_value
(
p
);
let
decl
=
let
decl
=
{
inputs
:
{
inputs
:
[{
mode
:
ast
::
by_ref
,
ty
:
t
,
ident
:
arg_iden
t
,
[{
mode
:
ast
::
expl
(
ast
::
by_ref
),
ty
:
t
,
id
:
p
.get_id
()}],
id
ent
:
arg_ident
,
id
:
p
.get_id
()}],
output
:
@
spanned
(
lo
,
lo
,
ast
::
ty_nil
),
output
:
@
spanned
(
lo
,
lo
,
ast
::
ty_nil
),
purity
:
ast
::
impure_fn
,
purity
:
ast
::
impure_fn
,
cf
:
ast
::
return_val
,
cf
:
ast
::
return_val
,
...
...
src/comp/syntax/print/pprust.rs
浏览文件 @
77b06d24
...
@@ -136,7 +136,7 @@ fn res_to_str(decl: ast::fn_decl, name: ast::ident,
...
@@ -136,7 +136,7 @@ fn res_to_str(decl: ast::fn_decl, name: ast::ident,
fn
test_res_to_str
()
{
fn
test_res_to_str
()
{
let
decl
:
ast
::
fn_decl
=
{
let
decl
:
ast
::
fn_decl
=
{
inputs
:
[{
inputs
:
[{
mode
:
ast
::
by_val
,
mode
:
ast
::
expl
(
ast
::
by_val
)
,
ty
:
@
ast_util
::
respan
(
ast_util
::
dummy_sp
(),
ast
::
ty_bool
),
ty
:
@
ast_util
::
respan
(
ast_util
::
dummy_sp
(),
ast
::
ty_bool
),
ident
:
"b"
,
ident
:
"b"
,
id
:
0
id
:
0
...
@@ -1280,17 +1280,22 @@ fn print_arg(s: ps, x: ast::arg) {
...
@@ -1280,17 +1280,22 @@ fn print_arg(s: ps, x: ast::arg) {
maybe_print_comment
(
s
,
decl
.output.span.lo
);
maybe_print_comment
(
s
,
decl
.output.span.lo
);
}
}
fn
print_arg_mode
(
s
:
ps
,
m
:
ast
::
mode
)
{
fn
mode_to_str
(
m
:
ast
::
mode
)
->
str
{
alt
m
{
alt
m
{
ast
::
by_mut_ref
{
word
(
s
.s
,
"&"
);
}
ast
::
expl
(
ast
::
by_mut_ref
)
{
"&"
}
ast
::
by_move
{
word
(
s
.s
,
"-"
);
}
ast
::
expl
(
ast
::
by_move
)
{
"-"
}
ast
::
by_ref
{
word
(
s
.s
,
"&&"
);
}
ast
::
expl
(
ast
::
by_ref
)
{
"&&"
}
ast
::
by_val
{
word
(
s
.s
,
"++"
);
}
ast
::
expl
(
ast
::
by_val
)
{
"++"
}
ast
::
by_copy
{
word
(
s
.s
,
"+"
);
}
ast
::
expl
(
ast
::
by_copy
)
{
"+"
}
ast
::
mode_infer
{
}
ast
::
infer
(
_
)
{
""
}
}
}
}
}
fn
print_arg_mode
(
s
:
ps
,
m
:
ast
::
mode
)
{
let
ms
=
mode_to_str
(
m
);
if
ms
!=
""
{
word
(
s
.s
,
ms
);
}
}
fn
print_bounds
(
s
:
ps
,
bounds
:
@
[
ast
::
ty_param_bound
])
{
fn
print_bounds
(
s
:
ps
,
bounds
:
@
[
ast
::
ty_param_bound
])
{
if
vec
::
len
(
*
bounds
)
>
0u
{
if
vec
::
len
(
*
bounds
)
>
0u
{
word
(
s
.s
,
":"
);
word
(
s
.s
,
":"
);
...
...
src/comp/util/ppaux.rs
浏览文件 @
77b06d24
...
@@ -4,32 +4,18 @@
...
@@ -4,32 +4,18 @@
import
middle
::
ty
::
*
;
import
middle
::
ty
::
*
;
import
metadata
::
encoder
;
import
metadata
::
encoder
;
import
syntax
::
print
::
pprust
;
import
syntax
::
print
::
pprust
;
import
syntax
::
print
::
pprust
::{
path_to_str
,
constr_args_to_str
,
proto_to_str
};
import
syntax
::
print
::
pprust
::{
path_to_str
,
constr_args_to_str
,
proto_to_str
,
mode_to_str
};
import
syntax
::{
ast
,
ast_util
};
import
syntax
::{
ast
,
ast_util
};
import
middle
::
ast_map
;
import
middle
::
ast_map
;
fn
mode_str
(
m
:
ast
::
mode
)
->
str
{
alt
m
{
ast
::
by_ref
{
"&&"
}
ast
::
by_val
{
"++"
}
ast
::
by_mut_ref
{
"&"
}
ast
::
by_move
{
"-"
}
ast
::
by_copy
{
"+"
}
_
{
""
}
}
}
fn
ty_to_str
(
cx
:
ctxt
,
typ
:
t
)
->
str
{
fn
ty_to_str
(
cx
:
ctxt
,
typ
:
t
)
->
str
{
fn
fn_input_to_str
(
cx
:
ctxt
,
input
:
{
mode
:
ast
::
mode
,
ty
:
t
})
->
fn
fn_input_to_str
(
cx
:
ctxt
,
input
:
{
mode
:
ast
::
mode
,
ty
:
t
})
->
str
{
str
{
let
modestr
=
alt
input
.mode
{
let
arg_mode
=
ty
::
arg_mode
(
cx
,
input
);
ast
::
by_ref
{
let
modestr
=
{
if
ty
::
type_is_immediate
(
cx
,
input
.ty
)
{
"&&"
}
else
{
""
}
if
arg_mode
==
ty
::
default_arg_mode_for_ty
(
cx
,
input
.ty
)
{
""
}
}
else
{
mode_to_str
(
input
.mode
)
}
ast
::
by_val
{
if
ty
::
type_is_immediate
(
cx
,
input
.ty
)
{
""
}
else
{
"++"
}
}
_
{
mode_str
(
input
.mode
)
}
};
};
modestr
+
ty_to_str
(
cx
,
input
.ty
)
modestr
+
ty_to_str
(
cx
,
input
.ty
)
}
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录