Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
3e67085d
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,发现更多精彩内容 >>
提交
3e67085d
编写于
4月 09, 2013
作者:
A
Alex Crichton
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Allow lint modes to be used on unused variables and dead assignments
上级
56417773
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
82 addition
and
60 deletion
+82
-60
src/librustc/middle/lint.rs
src/librustc/middle/lint.rs
+8
-11
src/librustc/middle/liveness.rs
src/librustc/middle/liveness.rs
+48
-31
src/test/compile-fail/liveness-unused.rs
src/test/compile-fail/liveness-unused.rs
+26
-18
未找到文件。
src/librustc/middle/lint.rs
浏览文件 @
3e67085d
...
...
@@ -83,9 +83,8 @@ pub enum lint {
legacy_modes
,
// FIXME(#3266)--make liveness warnings lintable
// unused_variable,
// dead_assignment
unused_variable
,
dead_assignment
,
}
pub
fn
level_to_str
(
lv
:
level
)
->
&
'static
str
{
...
...
@@ -257,21 +256,19 @@ pub fn get_lint_dict() -> LintDict {
default
:
deny
}),
/* FIXME(#3266)--make liveness warnings lintable
(@~"unused_variable",
@LintSpec {
(
~
"unused_variable"
,
LintSpec
{
lint
:
unused_variable
,
desc
:
"detect variables which are not used in any way"
,
default
:
warn
}),
}),
(
@
~"dead_assignment",
@
LintSpec {
(
~
"dead_assignment"
,
LintSpec
{
lint
:
dead_assignment
,
desc
:
"detect assignments that will never be read"
,
default
:
warn
}),
*/
}),
];
let
mut
map
=
HashMap
::
new
();
do
vec
::
consume
(
v
)
|
_
,
(
k
,
v
)|
{
...
...
src/librustc/middle/liveness.rs
浏览文件 @
3e67085d
...
...
@@ -105,6 +105,7 @@
use
core
::
prelude
::
*
;
use
middle
::
lint
::{
unused_variable
,
dead_assignment
};
use
middle
::
pat_util
;
use
middle
::
ty
;
use
middle
::
typeck
;
...
...
@@ -118,6 +119,7 @@
use
core
::
to_str
;
use
core
::
uint
;
use
core
::
vec
;
use
core
::
util
::
with
;
use
syntax
::
ast
::
*
;
use
syntax
::
codemap
::
span
;
use
syntax
::
parse
::
token
::
special_idents
;
...
...
@@ -169,6 +171,7 @@ pub fn check_crate(tcx: ty::ctxt,
visit_local
:
visit_local
,
visit_expr
:
visit_expr
,
visit_arm
:
visit_arm
,
visit_item
:
visit_item
,
..
*
visit
::
default_visitor
()
});
...
...
@@ -177,7 +180,8 @@ pub fn check_crate(tcx: ty::ctxt,
method_map
,
variable_moves_map
,
capture_map
,
last_use_map
);
last_use_map
,
0
);
visit
::
visit_crate
(
*
crate
,
initial_maps
,
visitor
);
tcx
.sess
.abort_if_errors
();
return
last_use_map
;
...
...
@@ -269,13 +273,16 @@ struct IrMaps {
capture_info_map
:
HashMap
<
node_id
,
@~
[
CaptureInfo
]
>
,
var_kinds
:
~
[
VarKind
],
lnks
:
~
[
LiveNodeKind
],
cur_item
:
node_id
,
}
fn
IrMaps
(
tcx
:
ty
::
ctxt
,
method_map
:
typeck
::
method_map
,
variable_moves_map
:
moves
::
VariableMovesMap
,
capture_map
:
moves
::
CaptureMap
,
last_use_map
:
last_use_map
)
last_use_map
:
last_use_map
,
cur_item
:
node_id
)
->
IrMaps
{
IrMaps
{
tcx
:
tcx
,
...
...
@@ -289,7 +296,8 @@ fn IrMaps(tcx: ty::ctxt,
variable_map
:
HashMap
::
new
(),
capture_info_map
:
HashMap
::
new
(),
var_kinds
:
~
[],
lnks
:
~
[]
lnks
:
~
[],
cur_item
:
cur_item
,
}
}
...
...
@@ -394,6 +402,12 @@ fn add_last_use(&mut self, expr_id: node_id, var: Variable) {
}
}
fn
visit_item
(
item
:
@
item
,
&&
self
:
@
mut
IrMaps
,
v
:
vt
<@
mut
IrMaps
>
)
{
do
with
(
&
mut
self
.cur_item
,
item
.id
)
{
visit
::
visit_item
(
item
,
self
,
v
)
}
}
fn
visit_fn
(
fk
:
&
visit
::
fn_kind
,
decl
:
&
fn_decl
,
body
:
&
blk
,
...
...
@@ -409,7 +423,8 @@ fn visit_fn(fk: &visit::fn_kind,
self
.method_map
,
self
.variable_moves_map
,
self
.capture_map
,
self
.last_use_map
);
self
.last_use_map
,
self
.cur_item
);
debug!
(
"creating fn_maps: %x"
,
ptr
::
addr_of
(
&
(
*
fn_maps
))
as
uint
);
...
...
@@ -692,17 +707,19 @@ fn variable_from_def_map(&self, node_id: node_id,
}
}
fn
pat_bindings
(
&
self
,
pat
:
@
pat
,
f
:
&
fn
(
LiveNode
,
Variable
,
span
))
{
fn
pat_bindings
(
&
self
,
pat
:
@
pat
,
f
:
&
fn
(
LiveNode
,
Variable
,
span
,
node_id
))
{
let
def_map
=
self
.tcx.def_map
;
do
pat_util
::
pat_bindings
(
def_map
,
pat
)
|
_
bm
,
p_id
,
sp
,
_
n
|
{
let
ln
=
self
.live_node
(
p_id
,
sp
);
let
var
=
self
.variable
(
p_id
,
sp
);
f
(
ln
,
var
,
sp
);
f
(
ln
,
var
,
sp
,
p_id
);
}
}
fn
arm_pats_bindings
(
&
self
,
pats
:
&
[
@
pat
],
f
:
&
fn
(
LiveNode
,
Variable
,
span
))
{
pats
:
&
[
@
pat
],
f
:
&
fn
(
LiveNode
,
Variable
,
span
,
node_id
))
{
// only consider the first pattern; any later patterns must have
// the same bindings, and we also consider the first pattern to be
// the "authoratative" set of ids
...
...
@@ -718,7 +735,7 @@ fn define_bindings_in_pat(&self, pat: @pat, succ: LiveNode) -> LiveNode {
fn
define_bindings_in_arm_pats
(
&
self
,
pats
:
&
[
@
pat
],
succ
:
LiveNode
)
->
LiveNode
{
let
mut
succ
=
succ
;
do
self
.arm_pats_bindings
(
pats
)
|
ln
,
var
,
_
sp
|
{
do
self
.arm_pats_bindings
(
pats
)
|
ln
,
var
,
_
sp
,
_
id
|
{
self
.init_from_succ
(
ln
,
succ
);
self
.define
(
ln
,
var
);
succ
=
ln
;
...
...
@@ -1509,8 +1526,8 @@ fn check_local(local: @local, &&self: @Liveness, vt: vt<@Liveness>) {
// should not be live at this point.
debug!
(
"check_local() with no initializer"
);
do
self
.pat_bindings
(
local
.node.pat
)
|
ln
,
var
,
sp
|
{
if
!
self
.warn_about_unused
(
sp
,
ln
,
var
)
{
do
self
.pat_bindings
(
local
.node.pat
)
|
ln
,
var
,
sp
,
id
|
{
if
!
self
.warn_about_unused
(
sp
,
id
,
ln
,
var
)
{
match
self
.live_on_exit
(
ln
,
var
)
{
None
=>
{
/* not live: good */
}
Some
(
lnk
)
=>
{
...
...
@@ -1528,8 +1545,8 @@ fn check_local(local: @local, &&self: @Liveness, vt: vt<@Liveness>) {
}
fn
check_arm
(
arm
:
&
arm
,
&&
self
:
@
Liveness
,
vt
:
vt
<@
Liveness
>
)
{
do
self
.arm_pats_bindings
(
arm
.pats
)
|
ln
,
var
,
sp
|
{
self
.warn_about_unused
(
sp
,
ln
,
var
);
do
self
.arm_pats_bindings
(
arm
.pats
)
|
ln
,
var
,
sp
,
id
|
{
self
.warn_about_unused
(
sp
,
id
,
ln
,
var
);
}
visit
::
visit_arm
(
arm
,
self
,
vt
);
}
...
...
@@ -1691,14 +1708,14 @@ fn check_lvalue(@self, expr: @expr, vt: vt<@Liveness>) {
let
ln
=
self
.live_node
(
expr
.id
,
expr
.span
);
let
var
=
self
.variable
(
nid
,
expr
.span
);
self
.check_for_reassignment
(
ln
,
var
,
expr
.span
);
self
.warn_about_dead_assign
(
expr
.span
,
ln
,
var
);
self
.warn_about_dead_assign
(
expr
.span
,
expr
.id
,
ln
,
var
);
}
def
=>
{
match
relevant_def
(
def
)
{
Some
(
nid
)
=>
{
let
ln
=
self
.live_node
(
expr
.id
,
expr
.span
);
let
var
=
self
.variable
(
nid
,
expr
.span
);
self
.warn_about_dead_assign
(
expr
.span
,
ln
,
var
);
self
.warn_about_dead_assign
(
expr
.span
,
expr
.id
,
ln
,
var
);
}
None
=>
{}
}
...
...
@@ -1715,7 +1732,7 @@ fn check_lvalue(@self, expr: @expr, vt: vt<@Liveness>) {
}
fn
check_for_reassignments_in_pat
(
@
self
,
pat
:
@
pat
)
{
do
self
.pat_bindings
(
pat
)
|
ln
,
var
,
sp
|
{
do
self
.pat_bindings
(
pat
)
|
ln
,
var
,
sp
,
_
id
|
{
self
.check_for_reassignment
(
ln
,
var
,
sp
);
}
}
...
...
@@ -1861,21 +1878,21 @@ fn warn_about_unused_args(@self, decl: &fn_decl, entry_ln: LiveNode) {
do
pat_util
::
pat_bindings
(
self
.tcx.def_map
,
arg
.pat
)
|
_
bm
,
p_id
,
sp
,
_
n
|
{
let
var
=
self
.variable
(
p_id
,
sp
);
self
.warn_about_unused
(
sp
,
entry_ln
,
var
);
self
.warn_about_unused
(
sp
,
p_id
,
entry_ln
,
var
);
}
}
}
fn
warn_about_unused_or_dead_vars_in_pat
(
@
self
,
pat
:
@
pat
)
{
do
self
.pat_bindings
(
pat
)
|
ln
,
var
,
sp
|
{
if
!
self
.warn_about_unused
(
sp
,
ln
,
var
)
{
self
.warn_about_dead_assign
(
sp
,
ln
,
var
);
do
self
.pat_bindings
(
pat
)
|
ln
,
var
,
sp
,
id
|
{
if
!
self
.warn_about_unused
(
sp
,
id
,
ln
,
var
)
{
self
.warn_about_dead_assign
(
sp
,
id
,
ln
,
var
);
}
}
}
fn
warn_about_unused
(
@
self
,
sp
:
span
,
ln
:
LiveNode
,
var
:
Variable
)
->
bool
{
fn
warn_about_unused
(
@
self
,
sp
:
span
,
id
:
node_id
,
ln
:
LiveNode
,
var
:
Variable
)
->
bool
{
if
!
self
.used_on_entry
(
ln
,
var
)
{
for
self
.should_warn
(
var
)
.each
|
name
|
{
...
...
@@ -1889,14 +1906,14 @@ fn warn_about_unused(@self, sp: span, ln: LiveNode, var: Variable)
};
if
is_assigned
{
// FIXME(#3266)--make liveness warnings lintable
self
.tcx.sess
.span_warn
(
sp
,
fmt!
(
"variable `%s` is assigned to,
\
self
.tcx.sess
.span_lint
(
unused_variable
,
id
,
self
.ir.cur_item
,
sp
,
fmt!
(
"variable `%s` is assigned to,
\
but never used"
,
**
name
));
}
else
{
// FIXME(#3266)--make liveness warnings lintable
self
.tcx.sess
.span_warn
(
sp
,
fmt!
(
"unused variable: `%s`"
,
**
name
));
self
.tcx.sess
.span_lint
(
unused_variable
,
id
,
self
.ir.cur_item
,
sp
,
fmt!
(
"unused variable: `%s`"
,
**
name
));
}
}
return
true
;
...
...
@@ -1904,12 +1921,12 @@ fn warn_about_unused(@self, sp: span, ln: LiveNode, var: Variable)
return
false
;
}
fn
warn_about_dead_assign
(
@
self
,
sp
:
span
,
ln
:
LiveNode
,
var
:
Variable
)
{
fn
warn_about_dead_assign
(
@
self
,
sp
:
span
,
id
:
node_id
,
ln
:
LiveNode
,
var
:
Variable
)
{
if
self
.live_on_exit
(
ln
,
var
)
.is_none
()
{
for
self
.should_warn
(
var
)
.each
|
name
|
{
// FIXME(#3266)--make liveness warnings lintable
self
.tcx.sess
.span_warn
(
sp
,
self
.tcx.sess
.span_lint
(
dead_assignment
,
id
,
self
.ir.cur_item
,
sp
,
fmt!
(
"value assigned to `%s` is never read"
,
**
name
));
}
}
...
...
src/test/compile-fail/liveness-unused.rs
浏览文件 @
3e67085d
...
...
@@ -8,38 +8,57 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[deny(unused_variable)]
;
#[deny(dead_assignment)]
;
fn
f1
(
x
:
int
)
{
//~^
WARNING
unused variable: `x`
//~^
ERROR
unused variable: `x`
}
fn
f1b
(
x
:
&
mut
int
)
{
//~^
WARNING
unused variable: `x`
//~^
ERROR
unused variable: `x`
}
#[allow(unused_variable)]
fn
f1c
(
x
:
int
)
{}
fn
f2
()
{
let
x
=
3
;
//~^
WARNING
unused variable: `x`
//~^
ERROR
unused variable: `x`
}
fn
f3
()
{
let
mut
x
=
3
;
//~^
WARNING
variable `x` is assigned to, but never used
//~^
ERROR
variable `x` is assigned to, but never used
x
+=
4
;
//~^
WARNING
value assigned to `x` is never read
//~^
ERROR
value assigned to `x` is never read
}
fn
f3b
()
{
let
mut
z
=
3
;
//~^
WARNING
variable `z` is assigned to, but never used
//~^
ERROR
variable `z` is assigned to, but never used
loop
{
z
+=
4
;
}
}
#[allow(unused_variable)]
fn
f3c
()
{
let
mut
z
=
3
;
loop
{
z
+=
4
;
}
}
#[allow(unused_variable)]
#[allow(dead_assignment)]
fn
f3d
()
{
let
mut
x
=
3
;
x
+=
4
;
}
fn
f4
()
{
match
Some
(
3
)
{
Some
(
i
)
=>
{
//~^
WARNING
unused variable: `i`
//~^
ERROR
unused variable: `i`
}
None
=>
{}
}
...
...
@@ -57,16 +76,5 @@ fn f4b() -> int {
}
}
// leave this in here just to trigger compile-fail:
struct
r
{
x
:
(),
}
impl
Drop
for
r
{
fn
finalize
(
&
self
)
{}
}
fn
main
()
{
let
x
=
r
{
x
:
()
};
||
{
copy
x
;
};
//~ ERROR copying a value of non-copyable type
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录