Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
0bd2232f
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,发现更多精彩内容 >>
提交
0bd2232f
编写于
4月 17, 2022
作者:
E
est31
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Implement the unused_macro_rules lint
上级
3d43be3a
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
139 addition
and
27 deletion
+139
-27
compiler/rustc_expand/src/base.rs
compiler/rustc_expand/src/base.rs
+2
-0
compiler/rustc_expand/src/mbe/macro_rules.rs
compiler/rustc_expand/src/mbe/macro_rules.rs
+28
-12
compiler/rustc_resolve/Cargo.toml
compiler/rustc_resolve/Cargo.toml
+0
-1
compiler/rustc_resolve/src/build_reduced_graph.rs
compiler/rustc_resolve/src/build_reduced_graph.rs
+18
-8
compiler/rustc_resolve/src/diagnostics.rs
compiler/rustc_resolve/src/diagnostics.rs
+14
-0
compiler/rustc_resolve/src/diagnostics/tests.rs
compiler/rustc_resolve/src/diagnostics/tests.rs
+40
-0
compiler/rustc_resolve/src/lib.rs
compiler/rustc_resolve/src/lib.rs
+2
-0
compiler/rustc_resolve/src/macros.rs
compiler/rustc_resolve/src/macros.rs
+35
-6
未找到文件。
compiler/rustc_expand/src/base.rs
浏览文件 @
0bd2232f
...
...
@@ -887,6 +887,8 @@ fn resolve_macro_invocation(
force
:
bool
,
)
->
Result
<
Lrc
<
SyntaxExtension
>
,
Indeterminate
>
;
fn
record_macro_rule_usage
(
&
mut
self
,
mac_id
:
NodeId
,
rule_index
:
usize
);
fn
check_unused_macros
(
&
mut
self
);
// Resolver interfaces for specific built-in macros.
...
...
compiler/rustc_expand/src/mbe/macro_rules.rs
浏览文件 @
0bd2232f
...
...
@@ -156,13 +156,13 @@ impl<'a> ParserAnyMacro<'a> {
}
struct
MacroRulesMacroExpander
{
node_id
:
NodeId
,
name
:
Ident
,
span
:
Span
,
transparency
:
Transparency
,
lhses
:
Vec
<
Vec
<
MatcherLoc
>>
,
rhses
:
Vec
<
mbe
::
TokenTree
>
,
valid
:
bool
,
is_local
:
bool
,
}
impl
TTMacroExpander
for
MacroRulesMacroExpander
{
...
...
@@ -179,12 +179,12 @@ fn expand<'cx>(
cx
,
sp
,
self
.span
,
self
.node_id
,
self
.name
,
self
.transparency
,
input
,
&
self
.lhses
,
&
self
.rhses
,
self
.is_local
,
)
}
}
...
...
@@ -207,14 +207,17 @@ fn generic_extension<'cx, 'tt>(
cx
:
&
'cx
mut
ExtCtxt
<
'_
>
,
sp
:
Span
,
def_span
:
Span
,
node_id
:
NodeId
,
name
:
Ident
,
transparency
:
Transparency
,
arg
:
TokenStream
,
lhses
:
&
'tt
[
Vec
<
MatcherLoc
>
],
rhses
:
&
'tt
[
mbe
::
TokenTree
],
is_local
:
bool
,
)
->
Box
<
dyn
MacResult
+
'cx
>
{
let
sess
=
&
cx
.sess.parse_sess
;
// Macros defined in the current crate have a real node id,
// whereas macros from an external crate have a dummy id.
let
is_local
=
node_id
!=
DUMMY_NODE_ID
;
if
cx
.trace_macros
()
{
let
msg
=
format!
(
"expanding `{}! {{ {} }}`"
,
name
,
pprust
::
tts_to_string
(
&
arg
));
...
...
@@ -296,6 +299,10 @@ fn generic_extension<'cx, 'tt>(
let
mut
p
=
Parser
::
new
(
sess
,
tts
,
false
,
None
);
p
.last_type_ascription
=
cx
.current_expansion.prior_type_ascription
;
if
is_local
{
cx
.resolver
.record_macro_rule_usage
(
node_id
,
i
);
}
// Let the context choose how to interpret the result.
// Weird, but useful for X-macros.
return
Box
::
new
(
ParserAnyMacro
{
...
...
@@ -372,7 +379,7 @@ pub fn compile_declarative_macro(
features
:
&
Features
,
def
:
&
ast
::
Item
,
edition
:
Edition
,
)
->
SyntaxExtension
{
)
->
(
SyntaxExtension
,
Vec
<
Span
>
)
{
debug!
(
"compile_declarative_macro: {:?}"
,
def
);
let
mk_syn_ext
=
|
expander
|
{
SyntaxExtension
::
new
(
...
...
@@ -385,6 +392,7 @@ pub fn compile_declarative_macro(
&
def
.attrs
,
)
};
let
dummy_syn_ext
=
||
(
mk_syn_ext
(
Box
::
new
(
macro_rules_dummy_expander
)),
Vec
::
new
());
let
diag
=
&
sess
.parse_sess.span_diagnostic
;
let
lhs_nm
=
Ident
::
new
(
sym
::
lhs
,
def
.span
);
...
...
@@ -445,17 +453,17 @@ pub fn compile_declarative_macro(
let
s
=
parse_failure_msg
(
&
token
);
let
sp
=
token
.span
.substitute_dummy
(
def
.span
);
sess
.parse_sess.span_diagnostic
.struct_span_err
(
sp
,
&
s
)
.span_label
(
sp
,
msg
)
.emit
();
return
mk_syn_ext
(
Box
::
new
(
macro_rules_dummy_expander
)
);
return
dummy_syn_ext
(
);
}
Error
(
sp
,
msg
)
=>
{
sess
.parse_sess
.span_diagnostic
.struct_span_err
(
sp
.substitute_dummy
(
def
.span
),
&
msg
)
.emit
();
return
mk_syn_ext
(
Box
::
new
(
macro_rules_dummy_expander
)
);
return
dummy_syn_ext
(
);
}
ErrorReported
=>
{
return
mk_syn_ext
(
Box
::
new
(
macro_rules_dummy_expander
)
);
return
dummy_syn_ext
(
);
}
};
...
...
@@ -530,6 +538,15 @@ pub fn compile_declarative_macro(
None
=>
{}
}
// Compute the spans of the macro rules
// We only take the span of the lhs here,
// so that the spans of created warnings are smaller.
let
rule_spans
=
if
def
.id
!=
DUMMY_NODE_ID
{
lhses
.iter
()
.map
(|
lhs
|
lhs
.span
())
.collect
::
<
Vec
<
_
>>
()
}
else
{
Vec
::
new
()
};
// Convert the lhses into `MatcherLoc` form, which is better for doing the
// actual matching. Unless the matcher is invalid.
let
lhses
=
if
valid
{
...
...
@@ -549,17 +566,16 @@ pub fn compile_declarative_macro(
vec!
[]
};
mk_syn_ext
(
Box
::
new
(
MacroRulesMacroExpander
{
let
expander
=
Box
::
new
(
MacroRulesMacroExpander
{
name
:
def
.ident
,
span
:
def
.span
,
node_id
:
def
.id
,
transparency
,
lhses
,
rhses
,
valid
,
// Macros defined in the current crate have a real node id,
// whereas macros from an external crate have a dummy id.
is_local
:
def
.id
!=
DUMMY_NODE_ID
,
}))
});
(
mk_syn_ext
(
expander
),
rule_spans
)
}
fn
check_lhs_nt_follows
(
sess
:
&
ParseSess
,
def
:
&
ast
::
Item
,
lhs
:
&
mbe
::
TokenTree
)
->
bool
{
...
...
compiler/rustc_resolve/Cargo.toml
浏览文件 @
0bd2232f
...
...
@@ -4,7 +4,6 @@ version = "0.0.0"
edition
=
"2021"
[lib]
test
=
false
doctest
=
false
[dependencies]
...
...
compiler/rustc_resolve/src/build_reduced_graph.rs
浏览文件 @
0bd2232f
...
...
@@ -194,7 +194,7 @@ pub fn expect_module(&mut self, def_id: DefId) -> Module<'a> {
}
let
ext
=
Lrc
::
new
(
match
self
.cstore
()
.load_macro_untracked
(
def_id
,
&
self
.session
)
{
LoadedMacro
::
MacroDef
(
item
,
edition
)
=>
self
.compile_macro
(
&
item
,
edition
),
LoadedMacro
::
MacroDef
(
item
,
edition
)
=>
self
.compile_macro
(
&
item
,
edition
)
.0
,
LoadedMacro
::
ProcMacro
(
ext
)
=>
ext
,
});
...
...
@@ -1218,9 +1218,18 @@ fn proc_macro_stub(&self, item: &ast::Item) -> Option<(MacroKind, Ident, Span)>
// Mark the given macro as unused unless its name starts with `_`.
// Macro uses will remove items from this set, and the remaining
// items will be reported as `unused_macros`.
fn
insert_unused_macro
(
&
mut
self
,
ident
:
Ident
,
def_id
:
LocalDefId
,
node_id
:
NodeId
)
{
fn
insert_unused_macro
(
&
mut
self
,
ident
:
Ident
,
def_id
:
LocalDefId
,
node_id
:
NodeId
,
rule_spans
:
&
[
Span
],
)
{
if
!
ident
.as_str
()
.starts_with
(
'_'
)
{
self
.r.unused_macros
.insert
(
def_id
,
(
node_id
,
ident
));
for
(
rule_i
,
rule_span
)
in
rule_spans
.iter
()
.enumerate
()
{
self
.r.unused_macro_rules
.insert
((
def_id
,
rule_i
),
(
ident
,
*
rule_span
));
}
}
}
...
...
@@ -1228,15 +1237,16 @@ fn define_macro(&mut self, item: &ast::Item) -> MacroRulesScopeRef<'a> {
let
parent_scope
=
self
.parent_scope
;
let
expansion
=
parent_scope
.expansion
;
let
def_id
=
self
.r
.local_def_id
(
item
.id
);
let
(
ext
,
ident
,
span
,
macro_rules
)
=
match
&
item
.kind
{
let
(
ext
,
ident
,
span
,
macro_rules
,
rule_spans
)
=
match
&
item
.kind
{
ItemKind
::
MacroDef
(
def
)
=>
{
let
ext
=
Lrc
::
new
(
self
.r
.compile_macro
(
item
,
self
.r.session
.edition
()));
(
ext
,
item
.ident
,
item
.span
,
def
.macro_rules
)
let
(
ext
,
rule_spans
)
=
self
.r
.compile_macro
(
item
,
self
.r.session
.edition
());
let
ext
=
Lrc
::
new
(
ext
);
(
ext
,
item
.ident
,
item
.span
,
def
.macro_rules
,
rule_spans
)
}
ItemKind
::
Fn
(
..
)
=>
match
self
.proc_macro_stub
(
item
)
{
Some
((
macro_kind
,
ident
,
span
))
=>
{
self
.r.proc_macro_stubs
.insert
(
def_id
);
(
self
.r
.dummy_ext
(
macro_kind
),
ident
,
span
,
false
)
(
self
.r
.dummy_ext
(
macro_kind
),
ident
,
span
,
false
,
Vec
::
new
()
)
}
None
=>
return
parent_scope
.macro_rules
,
},
...
...
@@ -1264,7 +1274,7 @@ fn define_macro(&mut self, item: &ast::Item) -> MacroRulesScopeRef<'a> {
self
.r
.define
(
module
,
ident
,
MacroNS
,
(
res
,
vis
,
span
,
expansion
,
IsMacroExport
));
}
else
{
self
.r
.check_reserved_macro_name
(
ident
,
res
);
self
.insert_unused_macro
(
ident
,
def_id
,
item
.id
);
self
.insert_unused_macro
(
ident
,
def_id
,
item
.id
,
&
rule_spans
);
}
self
.r.visibilities
.insert
(
def_id
,
vis
);
let
scope
=
self
.r.arenas
.alloc_macro_rules_scope
(
MacroRulesScope
::
Binding
(
...
...
@@ -1287,7 +1297,7 @@ fn define_macro(&mut self, item: &ast::Item) -> MacroRulesScopeRef<'a> {
_
=>
self
.resolve_visibility
(
&
item
.vis
),
};
if
vis
!=
ty
::
Visibility
::
Public
{
self
.insert_unused_macro
(
ident
,
def_id
,
item
.id
);
self
.insert_unused_macro
(
ident
,
def_id
,
item
.id
,
&
rule_spans
);
}
self
.r
.define
(
module
,
ident
,
MacroNS
,
(
res
,
vis
,
span
,
expansion
));
self
.r.visibilities
.insert
(
def_id
,
vis
);
...
...
compiler/rustc_resolve/src/diagnostics.rs
浏览文件 @
0bd2232f
...
...
@@ -35,6 +35,9 @@
use
crate
::{
ParentScope
,
PathResult
,
ResolutionError
,
Resolver
,
Scope
,
ScopeSet
};
use
crate
::{
Segment
,
UseError
};
#[cfg(test)]
mod
tests
;
type
Res
=
def
::
Res
<
ast
::
NodeId
>
;
/// A vector of spans and replacements, a message and applicability.
...
...
@@ -2663,3 +2666,14 @@ fn is_span_suitable_for_use_injection(s: Span) -> bool {
// import or other generated ones
!
s
.from_expansion
()
}
/// Convert the given number into the corresponding ordinal
crate
fn
ordinalize
(
v
:
usize
)
->
String
{
let
suffix
=
match
((
11
..=
13
)
.contains
(
&
(
v
%
100
)),
v
%
10
)
{
(
false
,
1
)
=>
"st"
,
(
false
,
2
)
=>
"nd"
,
(
false
,
3
)
=>
"rd"
,
_
=>
"th"
,
};
format!
(
"{v}{suffix}"
)
}
compiler/rustc_resolve/src/diagnostics/tests.rs
0 → 100644
浏览文件 @
0bd2232f
use
super
::
ordinalize
;
#[test]
fn
test_ordinalize
()
{
assert_eq!
(
ordinalize
(
1
),
"1st"
);
assert_eq!
(
ordinalize
(
2
),
"2nd"
);
assert_eq!
(
ordinalize
(
3
),
"3rd"
);
assert_eq!
(
ordinalize
(
4
),
"4th"
);
assert_eq!
(
ordinalize
(
5
),
"5th"
);
// ...
assert_eq!
(
ordinalize
(
10
),
"10th"
);
assert_eq!
(
ordinalize
(
11
),
"11th"
);
assert_eq!
(
ordinalize
(
12
),
"12th"
);
assert_eq!
(
ordinalize
(
13
),
"13th"
);
assert_eq!
(
ordinalize
(
14
),
"14th"
);
// ...
assert_eq!
(
ordinalize
(
20
),
"20th"
);
assert_eq!
(
ordinalize
(
21
),
"21st"
);
assert_eq!
(
ordinalize
(
22
),
"22nd"
);
assert_eq!
(
ordinalize
(
23
),
"23rd"
);
assert_eq!
(
ordinalize
(
24
),
"24th"
);
// ...
assert_eq!
(
ordinalize
(
30
),
"30th"
);
assert_eq!
(
ordinalize
(
31
),
"31st"
);
assert_eq!
(
ordinalize
(
32
),
"32nd"
);
assert_eq!
(
ordinalize
(
33
),
"33rd"
);
assert_eq!
(
ordinalize
(
34
),
"34th"
);
// ...
assert_eq!
(
ordinalize
(
7010
),
"7010th"
);
assert_eq!
(
ordinalize
(
7011
),
"7011th"
);
assert_eq!
(
ordinalize
(
7012
),
"7012th"
);
assert_eq!
(
ordinalize
(
7013
),
"7013th"
);
assert_eq!
(
ordinalize
(
7014
),
"7014th"
);
// ...
assert_eq!
(
ordinalize
(
7020
),
"7020th"
);
assert_eq!
(
ordinalize
(
7021
),
"7021st"
);
assert_eq!
(
ordinalize
(
7022
),
"7022nd"
);
assert_eq!
(
ordinalize
(
7023
),
"7023rd"
);
assert_eq!
(
ordinalize
(
7024
),
"7024th"
);
}
compiler/rustc_resolve/src/lib.rs
浏览文件 @
0bd2232f
...
...
@@ -973,6 +973,7 @@ pub struct Resolver<'a> {
local_macro_def_scopes
:
FxHashMap
<
LocalDefId
,
Module
<
'a
>>
,
ast_transform_scopes
:
FxHashMap
<
LocalExpnId
,
Module
<
'a
>>
,
unused_macros
:
FxHashMap
<
LocalDefId
,
(
NodeId
,
Ident
)
>
,
unused_macro_rules
:
FxHashMap
<
(
LocalDefId
,
usize
),
(
Ident
,
Span
)
>
,
proc_macro_stubs
:
FxHashSet
<
LocalDefId
>
,
/// Traces collected during macro resolution and validated when it's complete.
single_segment_macro_resolutions
:
...
...
@@ -1372,6 +1373,7 @@ pub fn new(
potentially_unused_imports
:
Vec
::
new
(),
struct_constructors
:
Default
::
default
(),
unused_macros
:
Default
::
default
(),
unused_macro_rules
:
Default
::
default
(),
proc_macro_stubs
:
Default
::
default
(),
single_segment_macro_resolutions
:
Default
::
default
(),
multi_segment_macro_resolutions
:
Default
::
default
(),
...
...
compiler/rustc_resolve/src/macros.rs
浏览文件 @
0bd2232f
...
...
@@ -22,7 +22,8 @@
use
rustc_hir
::
def_id
::{
CrateNum
,
LocalDefId
};
use
rustc_middle
::
middle
::
stability
;
use
rustc_middle
::
ty
::
RegisteredTools
;
use
rustc_session
::
lint
::
builtin
::{
LEGACY_DERIVE_HELPERS
,
SOFT_UNSTABLE
,
UNUSED_MACROS
};
use
rustc_session
::
lint
::
builtin
::{
LEGACY_DERIVE_HELPERS
,
SOFT_UNSTABLE
};
use
rustc_session
::
lint
::
builtin
::{
UNUSED_MACROS
,
UNUSED_MACRO_RULES
};
use
rustc_session
::
lint
::
BuiltinLintDiagnostics
;
use
rustc_session
::
parse
::
feature_err
;
use
rustc_session
::
Session
;
...
...
@@ -311,6 +312,11 @@ fn resolve_macro_invocation(
Ok
(
ext
)
}
fn
record_macro_rule_usage
(
&
mut
self
,
id
:
NodeId
,
rule_i
:
usize
)
{
let
did
=
self
.local_def_id
(
id
);
self
.unused_macro_rules
.remove
(
&
(
did
,
rule_i
));
}
fn
check_unused_macros
(
&
mut
self
)
{
for
(
_
,
&
(
node_id
,
ident
))
in
self
.unused_macros
.iter
()
{
self
.lint_buffer
.buffer_lint
(
...
...
@@ -320,6 +326,23 @@ fn check_unused_macros(&mut self) {
&
format!
(
"unused macro definition: `{}`"
,
ident
.as_str
()),
);
}
for
(
&
(
def_id
,
arm_i
),
&
(
ident
,
rule_span
))
in
self
.unused_macro_rules
.iter
()
{
if
self
.unused_macros
.contains_key
(
&
def_id
)
{
// We already lint the entire macro as unused
continue
;
}
let
node_id
=
self
.def_id_to_node_id
[
def_id
];
self
.lint_buffer
.buffer_lint
(
UNUSED_MACRO_RULES
,
node_id
,
rule_span
,
&
format!
(
"{} rule of macro `{}` is never used"
,
crate
::
diagnostics
::
ordinalize
(
arm_i
+
1
),
ident
.as_str
()
),
);
}
}
fn
has_derive_copy
(
&
self
,
expn_id
:
LocalExpnId
)
->
bool
{
...
...
@@ -830,10 +853,15 @@ fn prohibit_imported_non_macro_attrs(
}
}
/// Compile the macro into a `SyntaxExtension` and possibly replace
/// its expander to a pre-defined one for built-in macros.
crate
fn
compile_macro
(
&
mut
self
,
item
:
&
ast
::
Item
,
edition
:
Edition
)
->
SyntaxExtension
{
let
mut
result
=
compile_declarative_macro
(
/// Compile the macro into a `SyntaxExtension` and its rule spans.
///
/// Possibly replace its expander to a pre-defined one for built-in macros.
crate
fn
compile_macro
(
&
mut
self
,
item
:
&
ast
::
Item
,
edition
:
Edition
,
)
->
(
SyntaxExtension
,
Vec
<
Span
>
)
{
let
(
mut
result
,
mut
rule_spans
)
=
compile_declarative_macro
(
&
self
.session
,
self
.session
.features_untracked
(),
item
,
...
...
@@ -849,6 +877,7 @@ fn prohibit_imported_non_macro_attrs(
match
mem
::
replace
(
builtin_macro
,
BuiltinMacroState
::
AlreadySeen
(
item
.span
))
{
BuiltinMacroState
::
NotYetSeen
(
ext
)
=>
{
result
.kind
=
ext
;
rule_spans
=
Vec
::
new
();
if
item
.id
!=
ast
::
DUMMY_NODE_ID
{
self
.builtin_macro_kinds
.insert
(
self
.local_def_id
(
item
.id
),
result
.macro_kind
());
...
...
@@ -871,6 +900,6 @@ fn prohibit_imported_non_macro_attrs(
}
}
result
(
result
,
rule_spans
)
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录