Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
d3a0e178
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,发现更多精彩内容 >>
提交
d3a0e178
编写于
5月 16, 2016
作者:
J
Jeffrey Seyfried
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Move cfg_attr processing and stmt/expr attribute gated feature checking into `StripUnconfigured`
上级
a306f85d
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
86 addition
and
248 deletion
+86
-248
src/libsyntax/config.rs
src/libsyntax/config.rs
+86
-248
未找到文件。
src/libsyntax/config.rs
浏览文件 @
d3a0e178
...
...
@@ -13,7 +13,6 @@
use
feature_gate
::
GatedCfgAttr
;
use
fold
::
Folder
;
use
{
ast
,
fold
,
attr
};
use
visit
;
use
codemap
::{
Spanned
,
respan
};
use
ptr
::
P
;
...
...
@@ -21,6 +20,7 @@
pub
trait
CfgFolder
:
fold
::
Folder
{
fn
configure
<
T
:
HasAttrs
>
(
&
mut
self
,
node
:
T
)
->
Option
<
T
>
;
fn
visit_stmt_or_expr_attrs
(
&
mut
self
,
_
attrs
:
&
[
ast
::
Attribute
])
{}
fn
visit_unconfigurable_expr
(
&
mut
self
,
_
expr
:
&
ast
::
Expr
)
{}
}
...
...
@@ -31,14 +31,78 @@ pub struct StripUnconfigured<'a> {
config
:
&
'a
ast
::
CrateConfig
,
}
impl
<
'a
>
CfgFolder
for
StripUnconfigured
<
'a
>
{
fn
configure
<
T
:
HasAttrs
>
(
&
mut
self
,
node
:
T
)
->
Option
<
T
>
{
if
in_cfg
(
self
.config
,
node
.attrs
(),
&
mut
self
.diag
)
{
Some
(
node
)
impl
<
'a
>
StripUnconfigured
<
'a
>
{
// Determine if an item should be translated in the current crate
// configuration based on the item's attributes
fn
in_cfg
(
&
mut
self
,
attrs
:
&
[
ast
::
Attribute
])
->
bool
{
attrs
.iter
()
.all
(|
attr
|
{
let
mis
=
match
attr
.node.value.node
{
ast
::
MetaItemKind
::
List
(
_
,
ref
mis
)
if
is_cfg
(
&
attr
)
=>
mis
,
_
=>
return
true
};
if
mis
.len
()
!=
1
{
self
.diag
.emit_error
(|
diagnostic
|
{
diagnostic
.span_err
(
attr
.span
,
"expected 1 cfg-pattern"
);
});
return
true
;
}
attr
::
cfg_matches
(
self
.config
,
&
mis
[
0
],
&
mut
self
.diag
)
})
}
fn
process_cfg_attrs
(
&
mut
self
,
attrs
:
Vec
<
ast
::
Attribute
>
)
->
Vec
<
ast
::
Attribute
>
{
attrs
.into_iter
()
.filter_map
(|
attr
|
self
.process_cfg_attr
(
attr
))
.collect
()
}
fn
process_cfg_attr
(
&
mut
self
,
attr
:
ast
::
Attribute
)
->
Option
<
ast
::
Attribute
>
{
if
!
attr
.check_name
(
"cfg_attr"
)
{
return
Some
(
attr
);
}
let
attr_list
=
match
attr
.meta_item_list
()
{
Some
(
attr_list
)
=>
attr_list
,
None
=>
{
let
msg
=
"expected `#[cfg_attr(<cfg pattern>, <attr>)]`"
;
self
.diag.diag
.span_err
(
attr
.span
,
msg
);
return
None
;
}
};
let
(
cfg
,
mi
)
=
match
(
attr_list
.len
(),
attr_list
.get
(
0
),
attr_list
.get
(
1
))
{
(
2
,
Some
(
cfg
),
Some
(
mi
))
=>
(
cfg
,
mi
),
_
=>
{
let
msg
=
"expected `#[cfg_attr(<cfg pattern>, <attr>)]`"
;
self
.diag.diag
.span_err
(
attr
.span
,
msg
);
return
None
;
}
};
if
attr
::
cfg_matches
(
self
.config
,
&
cfg
,
&
mut
self
.diag
)
{
Some
(
respan
(
mi
.span
,
ast
::
Attribute_
{
id
:
attr
::
mk_attr_id
(),
style
:
attr
.node.style
,
value
:
mi
.clone
(),
is_sugared_doc
:
false
,
}))
}
else
{
None
}
}
}
impl
<
'a
>
CfgFolder
for
StripUnconfigured
<
'a
>
{
fn
configure
<
T
:
HasAttrs
>
(
&
mut
self
,
node
:
T
)
->
Option
<
T
>
{
let
node
=
node
.map_attrs
(|
attrs
|
self
.process_cfg_attrs
(
attrs
));
if
self
.in_cfg
(
node
.attrs
())
{
Some
(
node
)
}
else
{
None
}
}
fn
visit_stmt_or_expr_attrs
(
&
mut
self
,
attrs
:
&
[
ast
::
Attribute
])
{
// flag the offending attributes
for
attr
in
attrs
.iter
()
{
self
.diag.feature_gated_cfgs
.push
(
GatedCfgAttr
::
GatedAttr
(
attr
.span
));
}
}
fn
visit_unconfigurable_expr
(
&
mut
self
,
expr
:
&
ast
::
Expr
)
{
if
let
Some
(
attr
)
=
expr
.attrs
()
.iter
()
.find
(|
a
|
is_cfg
(
a
))
{
...
...
@@ -54,11 +118,6 @@ pub fn strip_unconfigured_items(diagnostic: &Handler, krate: ast::Crate,
feature_gated_cfgs
:
&
mut
Vec
<
GatedCfgAttr
>
)
->
ast
::
Crate
{
// Need to do this check here because cfg runs before feature_gates
check_for_gated_stmt_expr_attributes
(
&
krate
,
feature_gated_cfgs
);
let
krate
=
process_cfg_attr
(
diagnostic
,
krate
,
feature_gated_cfgs
);
StripUnconfigured
{
config
:
&
krate
.config
.clone
(),
diag
:
CfgDiagReal
{
...
...
@@ -72,7 +131,9 @@ impl<T: CfgFolder> fold::Folder for T {
fn
fold_foreign_mod
(
&
mut
self
,
foreign_mod
:
ast
::
ForeignMod
)
->
ast
::
ForeignMod
{
ast
::
ForeignMod
{
abi
:
foreign_mod
.abi
,
items
:
foreign_mod
.items
.into_iter
()
.filter_map
(|
item
|
self
.configure
(
item
))
.collect
(),
items
:
foreign_mod
.items
.into_iter
()
.filter_map
(|
item
|
{
self
.configure
(
item
)
.map
(|
item
|
fold
::
noop_fold_foreign_item
(
item
,
self
))
})
.collect
(),
}
}
...
...
@@ -126,6 +187,7 @@ fn fold_item_kind(&mut self, item: ast::ItemKind) -> ast::ItemKind {
}
fn
fold_expr
(
&
mut
self
,
expr
:
P
<
ast
::
Expr
>
)
->
P
<
ast
::
Expr
>
{
self
.visit_stmt_or_expr_attrs
(
expr
.attrs
());
// If an expr is valid to cfg away it will have been removed by the
// outer stmt or expression folder before descending in here.
// Anything else is always required, and thus has to error out
...
...
@@ -142,6 +204,19 @@ fn fold_opt_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
}
fn
fold_stmt
(
&
mut
self
,
stmt
:
ast
::
Stmt
)
->
SmallVector
<
ast
::
Stmt
>
{
let
is_item
=
match
stmt
.node
{
ast
::
StmtKind
::
Decl
(
ref
decl
,
_
)
=>
match
decl
.node
{
ast
::
DeclKind
::
Item
(
_
)
=>
true
,
_
=>
false
,
},
_
=>
false
,
};
// avoid calling `visit_stmt_or_expr_attrs` on items
if
!
is_item
{
self
.visit_stmt_or_expr_attrs
(
stmt
.attrs
());
}
self
.configure
(
stmt
)
.map
(|
stmt
|
fold
::
noop_fold_stmt
(
stmt
,
self
))
.unwrap_or
(
SmallVector
::
zero
())
}
...
...
@@ -178,205 +253,6 @@ fn is_cfg(attr: &ast::Attribute) -> bool {
attr
.check_name
(
"cfg"
)
}
// Determine if an item should be translated in the current crate
// configuration based on the item's attributes
fn
in_cfg
<
T
:
CfgDiag
>
(
cfg
:
&
[
P
<
ast
::
MetaItem
>
],
attrs
:
&
[
ast
::
Attribute
],
diag
:
&
mut
T
)
->
bool
{
attrs
.iter
()
.all
(|
attr
|
{
let
mis
=
match
attr
.node.value.node
{
ast
::
MetaItemKind
::
List
(
_
,
ref
mis
)
if
is_cfg
(
&
attr
)
=>
mis
,
_
=>
return
true
};
if
mis
.len
()
!=
1
{
diag
.emit_error
(|
diagnostic
|
{
diagnostic
.span_err
(
attr
.span
,
"expected 1 cfg-pattern"
);
});
return
true
;
}
attr
::
cfg_matches
(
cfg
,
&
mis
[
0
],
diag
)
})
}
struct
CfgAttrFolder
<
'a
,
T
>
{
diag
:
T
,
config
:
&
'a
ast
::
CrateConfig
,
}
// Process `#[cfg_attr]`.
fn
process_cfg_attr
(
diagnostic
:
&
Handler
,
krate
:
ast
::
Crate
,
feature_gated_cfgs
:
&
mut
Vec
<
GatedCfgAttr
>
)
->
ast
::
Crate
{
let
mut
fld
=
CfgAttrFolder
{
diag
:
CfgDiagReal
{
diag
:
diagnostic
,
feature_gated_cfgs
:
feature_gated_cfgs
,
},
config
:
&
krate
.config
.clone
(),
};
fld
.fold_crate
(
krate
)
}
impl
<
'a
,
T
:
CfgDiag
>
fold
::
Folder
for
CfgAttrFolder
<
'a
,
T
>
{
fn
fold_attribute
(
&
mut
self
,
attr
:
ast
::
Attribute
)
->
Option
<
ast
::
Attribute
>
{
if
!
attr
.check_name
(
"cfg_attr"
)
{
return
fold
::
noop_fold_attribute
(
attr
,
self
);
}
let
attr_list
=
match
attr
.meta_item_list
()
{
Some
(
attr_list
)
=>
attr_list
,
None
=>
{
self
.diag
.emit_error
(|
diag
|
{
diag
.span_err
(
attr
.span
,
"expected `#[cfg_attr(<cfg pattern>, <attr>)]`"
);
});
return
None
;
}
};
let
(
cfg
,
mi
)
=
match
(
attr_list
.len
(),
attr_list
.get
(
0
),
attr_list
.get
(
1
))
{
(
2
,
Some
(
cfg
),
Some
(
mi
))
=>
(
cfg
,
mi
),
_
=>
{
self
.diag
.emit_error
(|
diag
|
{
diag
.span_err
(
attr
.span
,
"expected `#[cfg_attr(<cfg pattern>, <attr>)]`"
);
});
return
None
;
}
};
if
attr
::
cfg_matches
(
&
self
.config
[
..
],
&
cfg
,
&
mut
self
.diag
)
{
Some
(
respan
(
mi
.span
,
ast
::
Attribute_
{
id
:
attr
::
mk_attr_id
(),
style
:
attr
.node.style
,
value
:
mi
.clone
(),
is_sugared_doc
:
false
,
}))
}
else
{
None
}
}
// Need the ability to run pre-expansion.
fn
fold_mac
(
&
mut
self
,
mac
:
ast
::
Mac
)
->
ast
::
Mac
{
fold
::
noop_fold_mac
(
mac
,
self
)
}
}
fn
check_for_gated_stmt_expr_attributes
(
krate
:
&
ast
::
Crate
,
discovered
:
&
mut
Vec
<
GatedCfgAttr
>
)
{
let
mut
v
=
StmtExprAttrFeatureVisitor
{
config
:
&
krate
.config
,
discovered
:
discovered
,
};
visit
::
walk_crate
(
&
mut
v
,
krate
);
}
/// To cover this feature, we need to discover all attributes
/// so we need to run before cfg.
struct
StmtExprAttrFeatureVisitor
<
'a
,
'b
>
{
config
:
&
'a
ast
::
CrateConfig
,
discovered
:
&
'b
mut
Vec
<
GatedCfgAttr
>
,
}
// Runs the cfg_attr and cfg folders locally in "silent" mode
// to discover attribute use on stmts or expressions ahead of time
impl
<
'v
,
'a
,
'b
>
visit
::
Visitor
<
'v
>
for
StmtExprAttrFeatureVisitor
<
'a
,
'b
>
{
fn
visit_stmt
(
&
mut
self
,
s
:
&
'v
ast
::
Stmt
)
{
// check if there even are any attributes on this node
let
stmt_attrs
=
s
.node
.attrs
();
if
stmt_attrs
.len
()
>
0
{
// attributes on items are fine
if
let
ast
::
StmtKind
::
Decl
(
ref
decl
,
_
)
=
s
.node
{
if
let
ast
::
DeclKind
::
Item
(
_
)
=
decl
.node
{
visit
::
walk_stmt
(
self
,
s
);
return
;
}
}
// flag the offending attributes
for
attr
in
stmt_attrs
{
self
.discovered
.push
(
GatedCfgAttr
::
GatedAttr
(
attr
.span
));
}
// if the node does not end up being cfg-d away, walk down
if
node_survives_cfg
(
stmt_attrs
,
self
.config
)
{
visit
::
walk_stmt
(
self
,
s
);
}
}
else
{
visit
::
walk_stmt
(
self
,
s
);
}
}
fn
visit_expr
(
&
mut
self
,
ex
:
&
'v
ast
::
Expr
)
{
// check if there even are any attributes on this node
let
expr_attrs
=
ex
.attrs
();
if
expr_attrs
.len
()
>
0
{
// flag the offending attributes
for
attr
in
expr_attrs
{
self
.discovered
.push
(
GatedCfgAttr
::
GatedAttr
(
attr
.span
));
}
// if the node does not end up being cfg-d away, walk down
if
node_survives_cfg
(
expr_attrs
,
self
.config
)
{
visit
::
walk_expr
(
self
,
ex
);
}
}
else
{
visit
::
walk_expr
(
self
,
ex
);
}
}
fn
visit_foreign_item
(
&
mut
self
,
i
:
&
'v
ast
::
ForeignItem
)
{
if
node_survives_cfg
(
&
i
.attrs
,
self
.config
)
{
visit
::
walk_foreign_item
(
self
,
i
);
}
}
fn
visit_item
(
&
mut
self
,
i
:
&
'v
ast
::
Item
)
{
if
node_survives_cfg
(
&
i
.attrs
,
self
.config
)
{
visit
::
walk_item
(
self
,
i
);
}
}
fn
visit_impl_item
(
&
mut
self
,
ii
:
&
'v
ast
::
ImplItem
)
{
if
node_survives_cfg
(
&
ii
.attrs
,
self
.config
)
{
visit
::
walk_impl_item
(
self
,
ii
);
}
}
fn
visit_trait_item
(
&
mut
self
,
ti
:
&
'v
ast
::
TraitItem
)
{
if
node_survives_cfg
(
&
ti
.attrs
,
self
.config
)
{
visit
::
walk_trait_item
(
self
,
ti
);
}
}
fn
visit_struct_field
(
&
mut
self
,
s
:
&
'v
ast
::
StructField
)
{
if
node_survives_cfg
(
&
s
.attrs
,
self
.config
)
{
visit
::
walk_struct_field
(
self
,
s
);
}
}
fn
visit_variant
(
&
mut
self
,
v
:
&
'v
ast
::
Variant
,
g
:
&
'v
ast
::
Generics
,
item_id
:
ast
::
NodeId
)
{
if
node_survives_cfg
(
&
v
.node.attrs
,
self
.config
)
{
visit
::
walk_variant
(
self
,
v
,
g
,
item_id
);
}
}
fn
visit_arm
(
&
mut
self
,
a
:
&
'v
ast
::
Arm
)
{
if
node_survives_cfg
(
&
a
.attrs
,
self
.config
)
{
visit
::
walk_arm
(
self
,
a
);
}
}
// This visitor runs pre expansion, so we need to prevent
// the default panic here
fn
visit_mac
(
&
mut
self
,
mac
:
&
'v
ast
::
Mac
)
{
visit
::
walk_mac
(
self
,
mac
)
}
}
pub
trait
CfgDiag
{
fn
emit_error
<
F
>
(
&
mut
self
,
f
:
F
)
where
F
:
FnMut
(
&
Handler
);
fn
flag_gated
<
F
>
(
&
mut
self
,
f
:
F
)
where
F
:
FnMut
(
&
mut
Vec
<
GatedCfgAttr
>
);
...
...
@@ -395,41 +271,3 @@ fn flag_gated<F>(&mut self, mut f: F) where F: FnMut(&mut Vec<GatedCfgAttr>) {
f
(
self
.feature_gated_cfgs
)
}
}
struct
CfgDiagSilent
{
error
:
bool
,
}
impl
CfgDiag
for
CfgDiagSilent
{
fn
emit_error
<
F
>
(
&
mut
self
,
_
:
F
)
where
F
:
FnMut
(
&
Handler
)
{
self
.error
=
true
;
}
fn
flag_gated
<
F
>
(
&
mut
self
,
_
:
F
)
where
F
:
FnMut
(
&
mut
Vec
<
GatedCfgAttr
>
)
{}
}
fn
node_survives_cfg
(
attrs
:
&
[
ast
::
Attribute
],
config
:
&
ast
::
CrateConfig
)
->
bool
{
let
mut
survives_cfg
=
true
;
for
attr
in
attrs
{
let
mut
fld
=
CfgAttrFolder
{
diag
:
CfgDiagSilent
{
error
:
false
},
config
:
config
,
};
let
attr
=
fld
.fold_attribute
(
attr
.clone
());
// In case of error we can just return true,
// since the actual cfg folders will end compilation anyway.
if
fld
.diag.error
{
return
true
;
}
survives_cfg
&=
attr
.map
(|
attr
|
{
let
mut
diag
=
CfgDiagSilent
{
error
:
false
};
let
r
=
in_cfg
(
config
,
&
[
attr
],
&
mut
diag
);
if
diag
.error
{
return
true
;
}
r
})
.unwrap_or
(
true
)
}
survives_cfg
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录