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 {
let
args_ty
:
ast
::
ty
=
nospan
(
ast
::
ty_vec
(
args_mt
));
let
args_arg
:
ast
::
arg
=
{
mode
:
ast
::
by_val
,
{
mode
:
ast
::
expl
(
ast
::
by_val
)
,
ty
:
@
args_ty
,
ident
:
"args"
,
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 {
'#'
{
ast
::
by_val
}
};
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 ']'
let
cs
=
parse_constrs
(
st
,
conv
);
...
...
src/comp/metadata/tyencode.rs
浏览文件 @
77b06d24
...
...
@@ -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
)
{
w
.write_char
(
'['
);
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_move
{
w
.write_char
(
'-'
);
}
by_copy
{
w
.write_char
(
'+'
);
}
by_ref
{
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
);
}
...
...
src/comp/middle/alias.rs
浏览文件 @
77b06d24
...
...
@@ -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
args
=
ty
::
ty_fn_args
(
cx
.tcx
,
fty
);
for
arg
in
args
{
if
arg
.mode
==
ast
::
by_val
&&
ty
::
type_has_dynamic_size
(
cx
.tcx
,
arg
.ty
)
{
alt
ty
::
resolved_mode
(
cx
.tcx
,
arg
.mode
)
{
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"
);
}
_
{
/* fallthrough */
}
}
}
...
...
@@ -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
{
let
arg
=
args
[
i
];
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
)
{
some
(
def
)
{
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])
}
_
{
}
}
}
ast
::
by_ref
|
ast
::
by_val
|
ast
::
by_move
|
ast
::
by_copy
{
}
}
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
,
span
:
arg
.span
,
root_var
:
root_var
,
local_id
:
0u
,
unsafe_tys
:
unsafe_set
(
root
.mut
),
mutable
copied
:
alt
arg_t
.mode
{
ast
::
by_move
|
ast
::
by_copy
{
copied
}
ast
::
by_mut_ref
{
not_allowed
}
_
{
not_copied
}
}}];
mutable
copied
:
arg_copied
}];
i
+=
1u
;
}
let
f_may_close
=
...
...
@@ -279,7 +285,8 @@ fn check_call(cx: ctx, sc: scope, f: @ast::expr, args: [@ast::expr])
for
unsafe_ty
in
b
.unsafe_tys
{
let
i
=
0u
;
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
&&
ty_can_unsafely_include
(
cx
,
unsafe_ty
,
arg_t
.ty
,
mut_alias
)
&&
...
...
src/comp/middle/block_use.rs
浏览文件 @
77b06d24
...
...
@@ -28,7 +28,7 @@ fn visit_expr(ex: @expr, cx: ctx, v: visit::vt<ctx>) {
v
.visit_expr
(
f
,
cx
,
v
);
let
i
=
0u
;
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
);
i
+=
1u
;
}
...
...
src/comp/middle/kind.rs
浏览文件 @
77b06d24
...
...
@@ -165,7 +165,10 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
expr_call
(
f
,
args
,
_
)
{
let
i
=
0u
;
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
;
}
}
...
...
src/comp/middle/last_use.rs
浏览文件 @
77b06d24
...
...
@@ -157,7 +157,7 @@ fn visit_expr(ex: @expr, cx: ctx, v: visit::vt<ctx>) {
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
);
}
_
{
v
.visit_expr
(
arg
,
cx
,
v
);
}
}
...
...
@@ -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
)
->
option
<
node_id
>
{
alt
d
{
def_local
(
def_id
,
let_copy
)
|
def_arg
(
def_id
,
by_copy
)
|
def_arg
(
def_id
,
by_move
)
{
def_local
(
def_id
,
let_copy
)
{
clear_in_current
(
cx
,
def_id
.node
,
to
);
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
}
...
...
src/comp/middle/mut.rs
浏览文件 @
77b06d24
...
...
@@ -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
i
=
0u
;
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_move
{
check_lval
(
cx
,
args
[
i
],
msg_move_out
);
}
_
{
}
by_ref
|
by_val
|
by_copy
{
}
}
i
+=
1u
;
}
...
...
@@ -267,8 +267,12 @@ fn is_immutable_def(cx: @ctx, def: def) -> option<str> {
def_use
(
_
)
{
some
(
"static item"
)
}
def_arg
(
_
,
by_ref
)
|
def_arg
(
_
,
by_val
)
|
def_arg
(
_
,
mode_infer
)
{
some
(
"argument"
)
}
def_arg
(
_
,
m
)
{
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_upvar
(
_
,
inner
,
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)
fn
type_of_explicit_args
(
cx
:
@
crate_ctxt
,
inputs
:
[
ty
::
arg
])
->
[
TypeRef
]
{
let
atys
=
[]
;
for
arg
in
inputs
{
let
tcx
=
ccx_tcx
(
cx
)
;
vec
::
map
(
inputs
)
{|
arg
|
let
arg_ty
=
arg
.ty
;
// FIXME: would be nice to have a constraint on arg
// that would obviate the need for this check
check
non_ty_var
(
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,
let
lv
=
trans_temp_lval
(
cx
,
e
);
let
bcx
=
lv
.bcx
;
let
val
=
lv
.val
;
let
arg_mode
=
ty
::
resolved_mode
(
ccx
.tcx
,
arg
.mode
);
if
is_bot
{
// For values of type _|_, we generate an
// "undef" value, as such a value should never
// be inspected. It's important for the value
// to have type lldestty (the callee's expected type).
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
);
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
);
copied
=
true
;
}
...
...
@@ -3002,10 +3005,10 @@ fn trans_arg_expr(cx: @block_ctxt, arg: ty::arg, lldestty: TypeRef,
}
else
{
bcx
=
take_ty
(
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
);
}
}
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
last_use
=
ccx
.last_uses
.contains_key
(
e
.id
);
bcx
=
cx
;
...
...
@@ -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.
if
arg
.
mode
==
ast
::
by_move
{
if
arg
_
mode
==
ast
::
by_move
{
if
lv
.kind
==
owned
{
// Use actual ty, not declared ty -- anything else doesn't make
// 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,
fn
copy_args_to_allocas
(
fcx
:
@
fn_ctxt
,
bcx
:
@
block_ctxt
,
args
:
[
ast
::
arg
],
arg_tys
:
[
ty
::
arg
])
->
@
block_ctxt
{
let
tcx
=
bcx_tcx
(
bcx
);
let
arg_n
:
uint
=
0u
,
bcx
=
bcx
;
fn
epic_fail_
(
bcx
:
@
block_ctxt
)
->
!
{
bcx_tcx
(
bcx
)
.sess
.bug
(
"Someone forgot
\
let
epic_fail
=
fn
@
(
)
->
!
{
tcx
.sess
.bug
(
"Someone forgot
\
to document an invariant in copy_args_to_allocas!"
);
}
let
epic_fail
=
bind
epic_fail_
(
bcx
);
...
...
@@ -4424,7 +4428,7 @@ fn epic_fail_(bcx: @block_ctxt) -> ! {
let
id
=
args
[
arg_n
]
.id
;
let
argval
=
alt
fcx
.llargs
.get
(
id
)
{
local_mem
(
v
)
{
v
}
_
{
epic_fail
()
}
};
alt
arg
.mode
{
alt
ty
::
resolved_mode
(
tcx
,
arg
.mode
)
{
ast
::
by_mut_ref
{
}
ast
::
by_move
|
ast
::
by_copy
{
add_clean
(
bcx
,
argval
,
arg
.ty
);
}
ast
::
by_val
{
...
...
@@ -4438,7 +4442,6 @@ fn epic_fail_(bcx: @block_ctxt) -> ! {
}
}
ast
::
by_ref
{}
_
{
epic_fail
();
}
}
if
fcx_ccx
(
fcx
)
.sess.opts.extra_debuginfo
{
debuginfo
::
create_arg
(
bcx
,
args
[
arg_n
],
args
[
arg_n
]
.ty.span
);
...
...
@@ -4585,7 +4588,7 @@ fn trans_enum_variant(ccx: @crate_ctxt,
// Translate variant arguments to function arguments.
let
fn_args
=
[],
i
=
0u
;
for
varg
in
variant
.node.args
{
fn_args
+=
[{
mode
:
ast
::
by_copy
,
fn_args
+=
[{
mode
:
ast
::
expl
(
ast
::
by_copy
)
,
ty
:
varg
.ty
,
ident
:
"arg"
+
uint
::
to_str
(
i
,
10u
),
id
:
varg
.id
}];
...
...
@@ -5039,7 +5042,7 @@ fn create_main(ccx: @crate_ctxt, main_llfn: ValueRef,
takes_argv
:
bool
)
->
ValueRef
{
let
unit_ty
=
ty
::
mk_str
(
ccx
.tcx
);
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
})};
// FIXME: mk_nil should have a postcondition
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,
[
0
,
abi
::
closure_body_bindings
,
b
]);
bcx
=
bound_arg
.bcx
;
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
);
bcx
=
memmove_ty
(
cx
,
alloc
,
val
,
out_arg
.ty
);
bcx
=
take_ty
(
bcx
,
alloc
,
out_arg
.ty
);
val
=
alloc
;
}
ast
::
by_ref
|
ast
::
by_mut_ref
|
ast
::
by_move
{
}
}
// If the type is parameterized, then we need to cast the
// type we actually have to the parameterized out type.
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)
let
nil_res
=
ty
::
mk_nil
(
ccx
.tcx
);
// FIXME: Silly check -- mk_nil should have a postcondition
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
);
ret
base
::
get_extern_const
(
ccx
.externs
,
ccx
.llmod
,
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,
fn
trans_self_arg
(
bcx
:
@
block_ctxt
,
base
:
@
ast
::
expr
)
->
result
{
let
tz
=
[],
tr
=
[];
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
,
tr
,
base
);
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] {
}
fn
callee_arg_init_ops
(
fcx
:
fn_ctxt
,
callee
:
node_id
)
->
[
init_op
]
{
fn
mode_to_op
(
m
:
mode
)
->
init_op
{
alt
m
{
by_move
{
init_move
}
_
{
init_assign
}
}
vec
::
map
(
callee_modes
(
fcx
,
callee
))
{|
m
|
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
]
{
...
...
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) {
fn
forget_args_moved_in
(
fcx
:
fn_ctxt
,
parent
:
@
expr
,
modes
:
[
mode
],
operands
:
[
@
expr
])
{
let
i
=
0u
;
for
mode
:
mode
in
modes
{
if
mode
==
by_move
{
forget_in_postcond
(
fcx
,
parent
.id
,
operands
[
i
]
.id
);
vec
::
iteri
(
modes
)
{|
i
,
mode
|
alt
ty
::
resolved_mode
(
fcx
.ccx.tcx
,
mode
)
{
by_move
{
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 @@
import
syntax
::
util
::
interner
;
import
util
::
ppaux
::
ty_to_str
;
import
util
::
ppaux
::
ty_constr_to_str
;
import
util
::
ppaux
::
mode_str
;
import
syntax
::
print
::
pprust
::
*
;
export
node_id_to_type
;
...
...
@@ -168,6 +167,10 @@
export
type_structurally_contains_uniques
;
export
type_autoderef
;
export
type_param
;
export
resolved_mode
;
export
arg_mode
;
export
unify_mode
;
export
set_default_mode
;
export
unify
;
export
variant_info
;
export
walk_ty
;
...
...
@@ -178,12 +181,12 @@
export
ck_uniq
;
export
param_bound
,
param_bounds
,
bound_copy
,
bound_send
,
bound_iface
;
export
param_bounds_to_kind
;
export
default_arg_mode_for_ty
;
// Data types
// TODO: really should be a separate type, or a refinement,
// so that we don't have to handle the mode_infer case after
// typeck. but that's too hard right now.
// Note: after typeck, you should use resolved_mode() to convert this mode
// into an rmode, which will take into account the results of mode inference.
type
arg
=
{
mode
:
ast
::
mode
,
ty
:
t
};
type
field
=
{
ident
:
ast
::
ident
,
mt
:
mt
};
...
...
@@ -217,7 +220,8 @@
ast_ty_to_ty_cache
:
hashmap
<@
ast
::
ty
,
option
<
t
>>
,
enum_var_cache
:
hashmap
<
def_id
,
@
[
variant_info
]
>
,
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
;
...
...
@@ -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
),
enum_var_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
);
ret
cx
;
}
...
...
@@ -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
))
{
alt
struct
(
cx
,
ty
)
{
ty_nil
|
ty_bot
|
ty_bool
|
ty_int
(
_
)
|
ty_uint
(
_
)
|
ty_float
(
_
)
|
...
...
@@ -684,13 +695,14 @@ enum fold_mode {
fn
fold_ty
(
cx
:
ctxt
,
fld
:
fold_mode
,
ty_0
:
t
)
->
t
{
let
ty
=
ty_0
;
// Fast paths.
// Fast paths.
alt
fld
{
fm_var
(
_
)
{
if
!
type_contains_vars
(
cx
,
ty
)
{
ret
ty
;
}
}
fm_param
(
_
)
{
if
!
type_contains_params
(
cx
,
ty
)
{
ret
ty
;
}
}
fm_general
(
_
)
{
/* no fast path */
}
}
alt
interner
::
get
(
*
cx
.ts
,
ty
)
.struct
{
ty_nil
|
ty_bot
|
ty_bool
|
ty_int
(
_
)
|
ty_uint
(
_
)
|
ty_float
(
_
)
|
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) ->
}
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
// described in Hoder and Voronkov:
//
...
...
@@ -1869,15 +1952,14 @@ fn unify_args(cx: @ctxt, e_args: [arg], a_args: [arg], variance: variance)
for
expected_input
in
e_args
{
let
actual_input
=
a_args
[
i
];
i
+=
1u
;
// Unify the result modes.
let
result_mode
=
if
expected_input
.mode
==
ast
::
mode_infer
{
actual_input
.mode
}
else
if
actual_input
.mode
==
ast
::
mode_infer
{
expected_input
.mode
}
else
if
expected_input
.mode
!=
actual_input
.mode
{
ret
either
::
left
(
ures_err
(
terr_mode_mismatch
(
expected_input
.mode
,
actual_input
.mode
)));
}
else
{
expected_input
.mode
};
let
result_mode
=
alt
unify_mode
(
cx
.tcx
,
expected_input
.mode
,
actual_input
.mode
)
{
result
::
err
(
err
)
{
ret
either
::
left
(
ures_err
(
err
));
}
result
::
ok
(
m
)
{
m
}
};
alt
unify_step
(
cx
,
expected_input
.ty
,
actual_input
.ty
,
variance
)
{
...
...
@@ -2446,8 +2528,8 @@ fn to_str(s: ast::ret_style) -> str {
}
terr_arg_count
{
ret
"incorrect number of function parameters"
;
}
terr_mode_mismatch
(
e_mode
,
a_mode
)
{
ret
"expected argument mode "
+
mode_str
(
e_mode
)
+
" but found "
+
mode_str
(
a_mode
);
ret
"expected argument mode "
+
mode_
to_
str
(
e_mode
)
+
" but found "
+
mode_
to_
str
(
a_mode
);
}
terr_constr_len
(
e_len
,
a_len
)
{
ret
"Expected a type with "
+
uint
::
str
(
e_len
)
+
...
...
src/comp/middle/typeck.rs
浏览文件 @
77b06d24
...
...
@@ -64,7 +64,6 @@ enum self_info {
var_bindings
:
@
ty
::
unify
::
var_bindings
,
locals
:
hashmap
<
ast
::
node_id
,
int
>
,
next_var_id
:
@
mutable
int
,
mutable
fixups
:
[
ast
::
node_id
],
ccx
:
@
crate_ctxt
};
...
...
@@ -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
);
}
// 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
),
}
// 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
getter
(
tcx
:
ty
::
ctxt
,
mode
:
mode
,
id
:
ast
::
def_id
)
->
ty
::
ty_param_bounds_and_ty
{
...
...
@@ -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
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
);
{
mode
:
default_arg_mode_for_ty
(
tcx
,
a
.mode
,
ty
),
ty
:
ty
}
}
fn
ty_of_fn_decl
(
tcx
:
ty
::
ctxt
,
mode
:
mode
,
proto
:
ast
::
proto
,
decl
:
ast
::
fn_decl
)
->
ty
::
fn_ty
{
let
input_tys
=
[];
for
a
:
ast
::
arg
in
decl
.inputs
{
input_tys
+=
[
ty_of_arg
(
tcx
,
mode
,
a
)];
}
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
{
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
out_constrs
=
[];
...
...
@@ -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
::
ty_param_bounds_and_ty
{
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
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,
}
else
{
let
auto_modes
=
vec
::
map2
(
impl_m
.fty.inputs
,
if_m
.fty.inputs
,
{|
i
,
f
|
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
}
}
});
...
...
@@ -641,7 +653,7 @@ fn get_enum_variant_types(cx: @ctxt, enum_ty: ty::t,
let
args
:
[
arg
]
=
[];
for
va
:
ast
::
variant_arg
in
variant
.node.args
{
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
ty
::
mk_fn
(
cx
.tcx
,
...
...
@@ -716,7 +728,7 @@ fn convert(cx: @ctxt, it: @ast::item) {
params
);
let
t_ctor
=
ty
::
mk_fn
(
cx
.tcx
,
{
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
,
ret_style
:
ast
::
return_val
,
constraints
:
[]
});
...
...
@@ -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
// unresolved type variables and replaces "ty_var" types with their
// substitutions.
//
// TODO: inefficient since not all types have vars in them. It would be better
// to maintain a list of fixups.
mod
writeback
{
export
resolve_type_vars_in_block
;
...
...
@@ -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
;
alt
resolve_type_vars_in_type
(
fcx
,
sp
,
ty
::
node_id_to_type
(
tcx
,
id
))
{
some
(
t
)
{
write_ty
(
tcx
,
id
,
t
);
}
none
{
wbcx
.success
=
false
;
ret
}
}
alt
tcx
.node_type_substs
.find
(
id
)
{
some
(
substs
)
{
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
{
wbcx
.success
=
false
;
ret
none
;
}
some
(
t
)
{
write_ty
(
tcx
,
id
,
t
);
alt
tcx
.node_type_substs
.find
(
id
)
{
some
(
substs
)
{
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) {
alt
e
.node
{
ast
::
expr_fn
(
_
,
decl
,
_
,
_
)
|
ast
::
expr_fn_block
(
decl
,
_
)
{
for
input
in
decl
.inputs
{
resolve_type_vars_for_node
(
wbcx
,
e
.span
,
input
.id
);
vec
::
iter
(
decl
.inputs
)
{|
input
|
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,
unify
:
unifier
,
expected
:
ty
::
t
)
{
let
tcx
=
fcx
.ccx.tcx
;
let
fty
=
ty
::
mk_fn
(
tcx
,
ty_of_fn_decl
(
tcx
,
m_check_tyvar
(
fcx
),
proto
,
decl
));
let
fty
=
ty
::
mk_fn
(
tcx
,
ty_of_fn_decl
(
tcx
,
m_check_tyvar
(
fcx
),
proto
,
decl
));
#
debug
(
"check_expr_fn_with_unifier %s fty=%s"
,
expr_to_str
(
expr
),
...
...
@@ -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
// 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
);
}
...
...
@@ -2027,7 +2056,6 @@ fn check_user_unop(fcx: @fn_ctxt, op_str: str, mname: str,
ty_to_str
(
tcx
,
expected
));
check_expr_fn_with_unifier
(
fcx
,
expr
,
proto
,
decl
,
body
,
unify
,
expected
);
write_ty
(
tcx
,
id
,
expected
);
}
ast
::
expr_block
(
b
)
{
// 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) {
// FIXME: this is kinda a kludge; we manufacture a fake function context
// and statement context for checking the initializer expression.
let
rty
=
node_id_to_type
(
ccx
.tcx
,
id
);
let
fixups
:
[
ast
::
node_id
]
=
[];
let
fcx
:
@
fn_ctxt
=
@
{
ret_ty
:
rty
,
purity
:
ast
::
pure_fn
,
...
...
@@ -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
(),
locals
:
new_int_hash
::
<
int
>
(),
next_var_id
:
@
mutable
0
,
mutable
fixups
:
fixups
,
ccx
:
ccx
};
check_expr
(
fcx
,
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],
// FIXME: this is kinda a kludge; we manufacture a fake function context
// and statement context for checking the initializer expression.
let
rty
=
node_id_to_type
(
ccx
.tcx
,
id
);
let
fixups
:
[
ast
::
node_id
]
=
[];
let
fcx
:
@
fn_ctxt
=
@
{
ret_ty
:
rty
,
purity
:
ast
::
pure_fn
,
...
...
@@ -2457,7 +2482,6 @@ fn check_enum_variants(ccx: @crate_ctxt, sp: span, vs: [ast::variant],
var_bindings
:
ty
::
unify
::
mk_var_bindings
(),
locals
:
new_int_hash
::
<
int
>
(),
next_var_id
:
@
mutable
0
,
mutable
fixups
:
fixups
,
ccx
:
ccx
};
let
disr_vals
:
[
int
]
=
[];
let
disr_val
=
0
;
...
...
@@ -2630,7 +2654,6 @@ fn check_fn(ccx: @crate_ctxt,
};
let
gather_result
=
gather_locals
(
ccx
,
decl
,
body
,
id
,
old_fcx
);
let
fixups
:
[
ast
::
node_id
]
=
[];
let
fcx
:
@
fn_ctxt
=
@
{
ret_ty
:
ty
::
ty_fn_ret
(
ccx
.tcx
,
ty
::
node_id_to_type
(
ccx
.tcx
,
id
)),
purity
:
purity
,
...
...
@@ -2638,7 +2661,6 @@ fn check_fn(ccx: @crate_ctxt,
var_bindings
:
gather_result
.var_bindings
,
locals
:
gather_result
.locals
,
next_var_id
:
gather_result
.next_var_id
,
mutable
fixups
:
fixups
,
ccx
:
ccx
};
check_constraints
(
fcx
,
decl
.constraints
,
decl
.inputs
);
...
...
src/comp/syntax/ast.rs
浏览文件 @
77b06d24
...
...
@@ -160,7 +160,17 @@ enum unop {
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_
>
;
...
...
src/comp/syntax/parse/parser.rs
浏览文件 @
77b06d24
...
...
@@ -521,14 +521,19 @@ fn parse_ty(p: parser, colons_before_params: bool) -> @ast::ty {
}
fn
parse_arg_mode
(
p
:
parser
)
->
ast
::
mode
{
if
eat
(
p
,
token
::
BINOP
(
token
::
AND
))
{
ast
::
by_mut_ref
}
else
if
eat
(
p
,
token
::
BINOP
(
token
::
MINUS
))
{
ast
::
by_move
}
else
if
eat
(
p
,
token
::
ANDAND
)
{
ast
::
by_ref
}
else
if
eat
(
p
,
token
::
BINOP
(
token
::
PLUS
))
{
if
eat
(
p
,
token
::
BINOP
(
token
::
PLUS
))
{
ast
::
by_val
}
else
{
ast
::
by_copy
}
}
else
{
ast
::
mode_infer
}
if
eat
(
p
,
token
::
BINOP
(
token
::
AND
))
{
ast
::
expl
(
ast
::
by_mut_ref
)
}
else
if
eat
(
p
,
token
::
BINOP
(
token
::
MINUS
))
{
ast
::
expl
(
ast
::
by_move
)
}
else
if
eat
(
p
,
token
::
ANDAND
)
{
ast
::
expl
(
ast
::
by_ref
)
}
else
if
eat
(
p
,
token
::
BINOP
(
token
::
PLUS
))
{
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
{
...
...
@@ -1984,8 +1989,8 @@ fn parse_item_res(p: parser, attrs: [ast::attribute]) -> @ast::item {
let
dtor
=
parse_block_no_value
(
p
);
let
decl
=
{
inputs
:
[{
mode
:
ast
::
by_ref
,
ty
:
t
,
ident
:
arg_iden
t
,
id
:
p
.get_id
()}],
[{
mode
:
ast
::
expl
(
ast
::
by_ref
),
ty
:
t
,
id
ent
:
arg_ident
,
id
:
p
.get_id
()}],
output
:
@
spanned
(
lo
,
lo
,
ast
::
ty_nil
),
purity
:
ast
::
impure_fn
,
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,
fn
test_res_to_str
()
{
let
decl
:
ast
::
fn_decl
=
{
inputs
:
[{
mode
:
ast
::
by_val
,
mode
:
ast
::
expl
(
ast
::
by_val
)
,
ty
:
@
ast_util
::
respan
(
ast_util
::
dummy_sp
(),
ast
::
ty_bool
),
ident
:
"b"
,
id
:
0
...
...
@@ -1280,17 +1280,22 @@ fn print_arg(s: ps, x: ast::arg) {
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
{
ast
::
by_mut_ref
{
word
(
s
.s
,
"&"
);
}
ast
::
by_move
{
word
(
s
.s
,
"-"
);
}
ast
::
by_ref
{
word
(
s
.s
,
"&&"
);
}
ast
::
by_val
{
word
(
s
.s
,
"++"
);
}
ast
::
by_copy
{
word
(
s
.s
,
"+"
);
}
ast
::
mode_infer
{
}
ast
::
expl
(
ast
::
by_mut_ref
)
{
"&"
}
ast
::
expl
(
ast
::
by_move
)
{
"-"
}
ast
::
expl
(
ast
::
by_ref
)
{
"&&"
}
ast
::
expl
(
ast
::
by_val
)
{
"++"
}
ast
::
expl
(
ast
::
by_copy
)
{
"+"
}
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
])
{
if
vec
::
len
(
*
bounds
)
>
0u
{
word
(
s
.s
,
":"
);
...
...
src/comp/util/ppaux.rs
浏览文件 @
77b06d24
...
...
@@ -4,32 +4,18 @@
import
middle
::
ty
::
*
;
import
metadata
::
encoder
;
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
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
fn_input_to_str
(
cx
:
ctxt
,
input
:
{
mode
:
ast
::
mode
,
ty
:
t
})
->
str
{
let
modestr
=
alt
input
.mode
{
ast
::
by_ref
{
if
ty
::
type_is_immediate
(
cx
,
input
.ty
)
{
"&&"
}
else
{
""
}
}
ast
::
by_val
{
if
ty
::
type_is_immediate
(
cx
,
input
.ty
)
{
""
}
else
{
"++"
}
}
_
{
mode_str
(
input
.mode
)
}
let
arg_mode
=
ty
::
arg_mode
(
cx
,
input
);
let
modestr
=
{
if
arg_mode
==
ty
::
default_arg_mode_for_ty
(
cx
,
input
.ty
)
{
""
}
else
{
mode_to_str
(
input
.mode
)
}
};
modestr
+
ty_to_str
(
cx
,
input
.ty
)
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录