Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
b2cac5af
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,发现更多精彩内容 >>
提交
b2cac5af
编写于
8月 08, 2011
作者:
G
Graydon Hoare
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Implement typestate checking for move-mode args. Un-XFAIL compile-fail/move-arg.rs.
上级
f7749b16
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
110 addition
and
32 deletion
+110
-32
src/comp/middle/tstate/auxiliary.rs
src/comp/middle/tstate/auxiliary.rs
+38
-7
src/comp/middle/tstate/pre_post_conditions.rs
src/comp/middle/tstate/pre_post_conditions.rs
+26
-3
src/comp/middle/tstate/states.rs
src/comp/middle/tstate/states.rs
+46
-18
src/test/compile-fail/move-arg.rs
src/test/compile-fail/move-arg.rs
+0
-4
未找到文件。
src/comp/middle/tstate/auxiliary.rs
浏览文件 @
b2cac5af
...
@@ -1093,14 +1093,45 @@ fn locals_to_bindings(locals : &(@local)[]) -> binding[] {
...
@@ -1093,14 +1093,45 @@ fn locals_to_bindings(locals : &(@local)[]) -> binding[] {
ivec
::
map
(
local_to_bindings
,
locals
)
ivec
::
map
(
local_to_bindings
,
locals
)
}
}
fn
anon_bindings
(
es
:
&
(
@
expr
)[])
->
binding
[]
{
fn
callee_modes
(
fcx
:
&
fn_ctxt
,
callee
:
node_id
)
->
ty
::
mode
[]
{
fn
expr_to_initializer
(
e
:
&@
expr
)
->
initializer
{
let
ty
=
ty
::
type_autoderef
(
fcx
.ccx.tcx
,
{
op
:
init_assign
,
expr
:
e
}
ty
::
node_id_to_type
(
fcx
.ccx.tcx
,
callee
));
alt
ty
::
struct
(
fcx
.ccx.tcx
,
ty
)
{
ty
::
ty_fn
(
_
,
args
,
_
,
_
,
_
)
|
ty
::
ty_native_fn
(
_
,
args
,
_
)
{
let
modes
=
~
[];
for
arg
:
ty
::
arg
in
args
{
modes
+=
~
[
arg
.mode
];
}
ret
modes
;
}
_
{
// Shouldn't happen; callee should be ty_fn.
fcx
.ccx.tcx.sess
.bug
(
"non-fn callee type in callee_modes: "
+
util
::
ppaux
::
ty_to_str
(
fcx
.ccx.tcx
,
ty
));
}
}
}
fn
callee_arg_init_ops
(
fcx
:
&
fn_ctxt
,
callee
:
node_id
)
->
init_op
[]
{
fn
mode_to_op
(
m
:
&
ty
::
mode
)
->
init_op
{
alt
m
{
ty
::
mo_move
.
{
init_move
}
_
{
init_assign
}
}
}
ivec
::
map
(
mode_to_op
,
callee_modes
(
fcx
,
callee
))
}
fn
anon_bindings
(
ops
:
&
init_op
[],
es
:
&
(
@
expr
)[])
->
binding
[]
{
let
bindings
:
binding
[]
=
~
[];
let
i
=
0
;
for
op
:
init_op
in
ops
{
bindings
+=
~
[{
lhs
:
~
[],
rhs
:
some
({
op
:
op
,
expr
:
es
.
(
i
)})}];
i
+=
1
;
}
}
ret
ivec
::
map
(
fn
(
e
:
&@
expr
)
->
binding
{
ret
bindings
;
{
lhs
:
~
[],
rhs
:
some
(
expr_to_initializer
(
e
))
}
},
es
);
}
}
//
//
...
...
src/comp/middle/tstate/pre_post_conditions.rs
浏览文件 @
b2cac5af
...
@@ -316,6 +316,18 @@ fn handle_var(fcx: &fn_ctxt, rslt: &pre_and_post, id: node_id, name: ident) {
...
@@ -316,6 +316,18 @@ fn handle_var(fcx: &fn_ctxt, rslt: &pre_and_post, id: node_id, name: ident) {
}
}
}
}
fn
forget_args_moved_in
(
fcx
:
&
fn_ctxt
,
parent
:
&@
expr
,
modes
:
&
ty
::
mode
[],
operands
:
&
(
@
expr
)[])
{
let
i
=
0
;
for
mode
:
ty
::
mode
in
modes
{
if
mode
==
ty
::
mo_move
{
forget_in_postcond
(
fcx
,
parent
.id
,
operands
.
(
i
)
.id
);
}
i
+=
1
;
}
}
/* Fills in annotations as a side effect. Does not rebuild the expr */
/* Fills in annotations as a side effect. Does not rebuild the expr */
fn
find_pre_post_expr
(
fcx
:
&
fn_ctxt
,
e
:
@
expr
)
{
fn
find_pre_post_expr
(
fcx
:
&
fn_ctxt
,
e
:
@
expr
)
{
let
enclosing
=
fcx
.enclosing
;
let
enclosing
=
fcx
.enclosing
;
...
@@ -336,6 +348,8 @@ fn find_pre_post_expr(fcx: &fn_ctxt, e: @expr) {
...
@@ -336,6 +348,8 @@ fn find_pre_post_expr(fcx: &fn_ctxt, e: @expr) {
require
(
i
,
expr_pp
(
fcx
.ccx
,
e
));
require
(
i
,
expr_pp
(
fcx
.ccx
,
e
));
}
}
forget_args_moved_in
(
fcx
,
e
,
callee_modes
(
fcx
,
operator
.id
),
operands
);
/* if this is a failing call, its postcondition sets everything */
/* if this is a failing call, its postcondition sets everything */
alt
controlflow_expr
(
fcx
.ccx
,
operator
)
{
alt
controlflow_expr
(
fcx
.ccx
,
operator
)
{
...
@@ -347,6 +361,8 @@ fn find_pre_post_expr(fcx: &fn_ctxt, e: @expr) {
...
@@ -347,6 +361,8 @@ fn find_pre_post_expr(fcx: &fn_ctxt, e: @expr) {
let
/* copy */
args
=
operands
;
let
/* copy */
args
=
operands
;
args
+=
~
[
operator
];
args
+=
~
[
operator
];
find_pre_post_exprs
(
fcx
,
args
,
e
.id
);
find_pre_post_exprs
(
fcx
,
args
,
e
.id
);
forget_args_moved_in
(
fcx
,
e
,
callee_modes
(
fcx
,
operator
.id
),
operands
);
}
}
expr_vec
(
args
,
_
,
_
)
{
find_pre_post_exprs
(
fcx
,
args
,
e
.id
);
}
expr_vec
(
args
,
_
,
_
)
{
find_pre_post_exprs
(
fcx
,
args
,
e
.id
);
}
expr_path
(
p
)
{
expr_path
(
p
)
{
...
@@ -544,14 +560,21 @@ fn combine_pp(antec: pre_and_post, fcx: fn_ctxt, pp: &pre_and_post,
...
@@ -544,14 +560,21 @@ fn combine_pp(antec: pre_and_post, fcx: fn_ctxt, pp: &pre_and_post,
expr_bind
(
operator
,
maybe_args
)
{
expr_bind
(
operator
,
maybe_args
)
{
let
args
=
~
[];
let
args
=
~
[];
for
expr_opt
:
option
::
t
[
@
expr
]
in
maybe_args
{
let
cmodes
=
callee_modes
(
fcx
,
operator
.id
);
let
modes
=
~
[];
let
i
=
0
;
for
expr_opt
:
option
::
t
[
@
expr
]
in
maybe_args
{
alt
expr_opt
{
alt
expr_opt
{
none
.
{
/* no-op */
}
none
.
{
/* no-op */
}
some
(
expr
)
{
args
+=
~
[
expr
];
}
some
(
expr
)
{
modes
+=
~
[
cmodes
.
(
i
)];
args
+=
~
[
expr
];
}
}
}
i
+=
1
;
}
}
args
+=
~
[
operator
];
/* ??? order of eval? */
args
+=
~
[
operator
];
/* ??? order of eval? */
forget_args_moved_in
(
fcx
,
e
,
modes
,
args
);
find_pre_post_exprs
(
fcx
,
args
,
e
.id
);
find_pre_post_exprs
(
fcx
,
args
,
e
.id
);
}
}
expr_break
.
{
clear_pp
(
expr_pp
(
fcx
.ccx
,
e
));
}
expr_break
.
{
clear_pp
(
expr_pp
(
fcx
.ccx
,
e
));
}
...
...
src/comp/middle/tstate/states.rs
浏览文件 @
b2cac5af
...
@@ -45,9 +45,6 @@ fn handle_move_or_copy(fcx: &fn_ctxt, post: &poststate, rhs_path: &path,
...
@@ -45,9 +45,6 @@ fn handle_move_or_copy(fcx: &fn_ctxt, post: &poststate, rhs_path: &path,
// not a local -- do nothing
// not a local -- do nothing
}
}
}
}
if
(
init_op
==
init_move
)
{
forget_in_poststate
(
fcx
,
post
,
rhs_id
);
}
}
}
fn
seq_states
(
fcx
:
&
fn_ctxt
,
pres
:
&
prestate
,
bindings
:
&
binding
[])
fn
seq_states
(
fcx
:
&
fn_ctxt
,
pres
:
&
prestate
,
bindings
:
&
binding
[])
...
@@ -67,10 +64,14 @@ fn seq_states(fcx: &fn_ctxt, pres: &prestate, bindings: &binding[])
...
@@ -67,10 +64,14 @@ fn seq_states(fcx: &fn_ctxt, pres: &prestate, bindings: &binding[])
handle_move_or_copy
(
fcx
,
post
,
p
,
an_init
.expr.id
,
i
,
handle_move_or_copy
(
fcx
,
post
,
p
,
an_init
.expr.id
,
i
,
an_init
.op
);
an_init
.op
);
}
}
_
{}
_
{
}
}
}
set_in_poststate_ident
(
fcx
,
i
.node
,
i
.ident
,
post
);
set_in_poststate_ident
(
fcx
,
i
.node
,
i
.ident
,
post
);
}
}
// Forget the RHS if we just moved it.
if
an_init
.op
==
init_move
{
forget_in_poststate
(
fcx
,
post
,
an_init
.expr.id
);
}
}
}
none
{
none
{
for
i
:
inst
in
b
.lhs
{
for
i
:
inst
in
b
.lhs
{
...
@@ -162,16 +163,24 @@ fn find_pre_post_state_two(fcx: &fn_ctxt, pres: &prestate, lhs: &@expr,
...
@@ -162,16 +163,24 @@ fn find_pre_post_state_two(fcx: &fn_ctxt, pres: &prestate, lhs: &@expr,
}
}
fn
find_pre_post_state_call
(
fcx
:
&
fn_ctxt
,
pres
:
&
prestate
,
a
:
&@
expr
,
fn
find_pre_post_state_call
(
fcx
:
&
fn_ctxt
,
pres
:
&
prestate
,
a
:
&@
expr
,
id
:
node_id
,
bs
:
&
(
@
expr
)[],
cf
:
controlflow
)
->
id
:
node_id
,
ops
:
&
init_op
[],
bs
:
&
(
@
expr
)[],
bool
{
cf
:
controlflow
)
->
bool
{
let
changed
=
find_pre_post_state_expr
(
fcx
,
pres
,
a
);
let
changed
=
find_pre_post_state_expr
(
fcx
,
pres
,
a
);
ret
find_pre_post_state_exprs
(
fcx
,
expr_poststate
(
fcx
.ccx
,
a
),
id
,
bs
,
cf
)
if
ivec
::
len
(
bs
)
!=
ivec
::
len
(
ops
)
{
fcx
.ccx.tcx.sess
.span_bug
(
a
.span
,
#
fmt
(
"mismatched arg lengths:
\
%u exprs vs. %u ops"
,
ivec
::
len
(
bs
),
ivec
::
len
(
ops
)));
}
ret
find_pre_post_state_exprs
(
fcx
,
expr_poststate
(
fcx
.ccx
,
a
),
id
,
ops
,
bs
,
cf
)
||
changed
;
||
changed
;
}
}
fn
find_pre_post_state_exprs
(
fcx
:
&
fn_ctxt
,
pres
:
&
prestate
,
id
:
node_id
,
fn
find_pre_post_state_exprs
(
fcx
:
&
fn_ctxt
,
pres
:
&
prestate
,
id
:
node_id
,
es
:
&
(
@
expr
)[],
cf
:
controlflow
)
->
bool
{
ops
:
&
init_op
[],
es
:
&
(
@
expr
)[],
let
rs
=
seq_states
(
fcx
,
pres
,
anon_bindings
(
es
));
cf
:
controlflow
)
->
bool
{
let
rs
=
seq_states
(
fcx
,
pres
,
anon_bindings
(
ops
,
es
));
let
changed
=
rs
.changed
|
set_prestate_ann
(
fcx
.ccx
,
id
,
pres
);
let
changed
=
rs
.changed
|
set_prestate_ann
(
fcx
.ccx
,
id
,
pres
);
/* if this is a failing call, it sets everything as initialized */
/* if this is a failing call, it sets everything as initialized */
alt
cf
{
alt
cf
{
...
@@ -304,23 +313,39 @@ fn find_pre_post_state_expr(fcx: &fn_ctxt, pres: &prestate, e: @expr) ->
...
@@ -304,23 +313,39 @@ fn find_pre_post_state_expr(fcx: &fn_ctxt, pres: &prestate, e: @expr) ->
alt
e
.node
{
alt
e
.node
{
expr_vec
(
elts
,
_
,
_
)
{
expr_vec
(
elts
,
_
,
_
)
{
ret
find_pre_post_state_exprs
(
fcx
,
pres
,
e
.id
,
elts
,
return
);
ret
find_pre_post_state_exprs
(
fcx
,
pres
,
e
.id
,
ivec
::
init_elt
(
init_assign
,
ivec
::
len
(
elts
)),
elts
,
return
);
}
}
expr_call
(
operator
,
operands
)
{
expr_call
(
operator
,
operands
)
{
ret
find_pre_post_state_call
(
fcx
,
pres
,
operator
,
e
.id
,
operands
,
ret
find_pre_post_state_call
(
fcx
,
pres
,
operator
,
e
.id
,
callee_arg_init_ops
(
fcx
,
operator
.id
),
operands
,
controlflow_expr
(
fcx
.ccx
,
operator
));
controlflow_expr
(
fcx
.ccx
,
operator
));
}
}
expr_spawn
(
_
,
_
,
operator
,
operands
)
{
expr_spawn
(
_
,
_
,
operator
,
operands
)
{
ret
find_pre_post_state_call
(
fcx
,
pres
,
operator
,
e
.id
,
operands
,
ret
find_pre_post_state_call
(
fcx
,
pres
,
operator
,
e
.id
,
return
);
callee_arg_init_ops
(
fcx
,
operator
.id
),
operands
,
return
);
}
}
expr_bind
(
operator
,
maybe_args
)
{
expr_bind
(
operator
,
maybe_args
)
{
let
args
=
~
[];
let
args
=
~
[];
for
a_opt
:
option
::
t
[
@
expr
]
in
maybe_args
{
let
callee_ops
=
callee_arg_init_ops
(
fcx
,
operator
.id
);
alt
a_opt
{
none
.
{
/* no-op */
}
some
(
a
)
{
args
+=
~
[
a
];
}
}
let
ops
=
~
[];
let
i
=
0
;
for
a_opt
:
option
::
t
[
@
expr
]
in
maybe_args
{
alt
a_opt
{
none
.
{
/* no-op */
}
some
(
a
)
{
ops
+=
~
[
callee_ops
.
(
i
)];
args
+=
~
[
a
];
}
}
i
+=
1
;
}
}
ret
find_pre_post_state_call
(
fcx
,
pres
,
operator
,
e
.id
,
ops
,
args
,
ret
find_pre_post_state_call
(
fcx
,
pres
,
operator
,
e
.id
,
args
,
return
);
return
);
}
}
expr_path
(
_
)
{
ret
pure_exp
(
fcx
.ccx
,
e
.id
,
pres
);
}
expr_path
(
_
)
{
ret
pure_exp
(
fcx
.ccx
,
e
.id
,
pres
);
}
expr_log
(
_
,
ex
)
{
expr_log
(
_
,
ex
)
{
...
@@ -347,7 +372,10 @@ fn find_pre_post_state_expr(fcx: &fn_ctxt, pres: &prestate, e: @expr) ->
...
@@ -347,7 +372,10 @@ fn find_pre_post_state_expr(fcx: &fn_ctxt, pres: &prestate, e: @expr) ->
}
}
expr_rec
(
fields
,
maybe_base
)
{
expr_rec
(
fields
,
maybe_base
)
{
let
changed
=
let
changed
=
find_pre_post_state_exprs
(
fcx
,
pres
,
e
.id
,
field_exprs
(
fields
),
find_pre_post_state_exprs
(
fcx
,
pres
,
e
.id
,
ivec
::
init_elt
(
init_assign
,
ivec
::
len
(
fields
)),
field_exprs
(
fields
),
return
);
return
);
alt
maybe_base
{
alt
maybe_base
{
none
.
{
/* do nothing */
}
none
.
{
/* do nothing */
}
...
...
src/test/compile-fail/move-arg.rs
浏览文件 @
b2cac5af
// xfail-stage0
// xfail-stage1
// xfail-stage2
// xfail-stage3
// error-pattern: Unsatisfied precondition constraint
// error-pattern: Unsatisfied precondition constraint
fn
test
(
foo
:
-
int
)
{
fn
test
(
foo
:
-
int
)
{
assert
(
foo
==
10
);
assert
(
foo
==
10
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录