Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
8250a26b
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,发现更多精彩内容 >>
提交
8250a26b
编写于
8月 19, 2016
作者:
S
Sergio Benitez
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Implement RFC#1559: allow all literals in attributes.
上级
528c6f3e
变更
45
展开全部
隐藏空白更改
内联
并排
Showing
45 changed file
with
942 addition
and
373 deletion
+942
-373
src/librustc/hir/check_attr.rs
src/librustc/hir/check_attr.rs
+12
-7
src/librustc/hir/fold.rs
src/librustc/hir/fold.rs
+20
-3
src/librustc/lint/context.rs
src/librustc/lint/context.rs
+5
-7
src/librustc_borrowck/borrowck/mir/mod.rs
src/librustc_borrowck/borrowck/mir/mod.rs
+4
-3
src/librustc_driver/lib.rs
src/librustc_driver/lib.rs
+7
-5
src/librustc_incremental/assert_dep_graph.rs
src/librustc_incremental/assert_dep_graph.rs
+24
-15
src/librustc_incremental/persist/dirty_clean.rs
src/librustc_incremental/persist/dirty_clean.rs
+10
-6
src/librustc_lint/builtin.rs
src/librustc_lint/builtin.rs
+3
-3
src/librustc_lint/unused.rs
src/librustc_lint/unused.rs
+7
-0
src/librustc_metadata/common.rs
src/librustc_metadata/common.rs
+1
-14
src/librustc_metadata/creader.rs
src/librustc_metadata/creader.rs
+1
-2
src/librustc_metadata/decoder.rs
src/librustc_metadata/decoder.rs
+13
-38
src/librustc_metadata/encoder.rs
src/librustc_metadata/encoder.rs
+4
-33
src/librustc_metadata/macro_import.rs
src/librustc_metadata/macro_import.rs
+5
-6
src/librustc_plugin/load.rs
src/librustc_plugin/load.rs
+10
-10
src/librustc_plugin/registry.rs
src/librustc_plugin/registry.rs
+2
-3
src/librustc_trans/assert_module_sources.rs
src/librustc_trans/assert_module_sources.rs
+1
-1
src/librustdoc/clean/mod.rs
src/librustdoc/clean/mod.rs
+41
-15
src/librustdoc/test.rs
src/librustdoc/test.rs
+2
-1
src/librustdoc/visit_ast.rs
src/librustdoc/visit_ast.rs
+3
-3
src/libsyntax/ast.rs
src/libsyntax/ast.rs
+50
-8
src/libsyntax/attr.rs
src/libsyntax/attr.rs
+229
-101
src/libsyntax/config.rs
src/libsyntax/config.rs
+26
-11
src/libsyntax/diagnostic_list.rs
src/libsyntax/diagnostic_list.rs
+18
-0
src/libsyntax/ext/build.rs
src/libsyntax/ext/build.rs
+11
-2
src/libsyntax/feature_gate.rs
src/libsyntax/feature_gate.rs
+38
-13
src/libsyntax/fold.rs
src/libsyntax/fold.rs
+18
-1
src/libsyntax/parse/attr.rs
src/libsyntax/parse/attr.rs
+48
-16
src/libsyntax/print/pprust.rs
src/libsyntax/print/pprust.rs
+17
-2
src/libsyntax/test.rs
src/libsyntax/test.rs
+4
-5
src/libsyntax_ext/deriving/cmp/eq.rs
src/libsyntax_ext/deriving/cmp/eq.rs
+1
-1
src/libsyntax_ext/deriving/generic/mod.rs
src/libsyntax_ext/deriving/generic/mod.rs
+1
-1
src/libsyntax_ext/deriving/mod.rs
src/libsyntax_ext/deriving/mod.rs
+3
-3
src/test/compile-fail-fulldeps/auxiliary/macro_crate_test.rs
src/test/compile-fail-fulldeps/auxiliary/macro_crate_test.rs
+9
-8
src/test/compile-fail/E0565-1.rs
src/test/compile-fail/E0565-1.rs
+17
-0
src/test/compile-fail/E0565.rs
src/test/compile-fail/E0565.rs
+17
-0
src/test/compile-fail/attr-literals.rs
src/test/compile-fail/attr-literals.rs
+33
-0
src/test/compile-fail/gated-attr-literals.rs
src/test/compile-fail/gated-attr-literals.rs
+44
-0
src/test/parse-fail/suffixed-literal-meta.rs
src/test/parse-fail/suffixed-literal-meta.rs
+25
-0
src/test/pretty/attr-literals.rs
src/test/pretty/attr-literals.rs
+11
-5
src/test/run-pass-fulldeps/auxiliary/custom_derive_plugin.rs
src/test/run-pass-fulldeps/auxiliary/custom_derive_plugin.rs
+0
-1
src/test/run-pass-fulldeps/auxiliary/custom_derive_plugin_attr.rs
.../run-pass-fulldeps/auxiliary/custom_derive_plugin_attr.rs
+1
-1
src/test/run-pass-fulldeps/auxiliary/macro_crate_test.rs
src/test/run-pass-fulldeps/auxiliary/macro_crate_test.rs
+86
-17
src/test/run-pass-fulldeps/auxiliary/plugin_args.rs
src/test/run-pass-fulldeps/auxiliary/plugin_args.rs
+2
-2
src/test/run-pass-fulldeps/macro-crate-multi-decorator-literals.rs
...run-pass-fulldeps/macro-crate-multi-decorator-literals.rs
+58
-0
未找到文件。
src/librustc/hir/check_attr.rs
浏览文件 @
8250a26b
...
...
@@ -11,7 +11,7 @@
use
session
::
Session
;
use
syntax
::
ast
;
use
syntax
::
attr
::
AttrMetaMethods
;
use
syntax
::
attr
::
{
AttrNestedMetaItemMethods
,
AttrMetaMethods
}
;
use
syntax
::
visit
;
use
syntax
::
visit
::
Visitor
;
...
...
@@ -52,18 +52,22 @@ fn check_repr(&self, attr: &ast::Attribute, target: Target) {
return
;
}
};
for
word
in
words
{
let
word
:
&
str
=
&
word
.name
();
let
message
=
match
word
{
let
name
=
match
word
.name
()
{
Some
(
word
)
=>
word
,
None
=>
continue
,
};
let
message
=
match
&*
name
{
"C"
=>
{
if
target
!=
Target
::
Struct
&&
target
!=
Target
::
Enum
{
"attribute should be applied to struct or enum"
"attribute should be applied to struct or enum"
}
else
{
continue
}
}
"packed"
|
"simd"
=>
{
"packed"
|
"simd"
=>
{
if
target
!=
Target
::
Struct
{
"attribute should be applied to struct"
}
else
{
...
...
@@ -74,13 +78,14 @@ fn check_repr(&self, attr: &ast::Attribute, target: Target) {
"i32"
|
"u32"
|
"i64"
|
"u64"
|
"isize"
|
"usize"
=>
{
if
target
!=
Target
::
Enum
{
"attribute should be applied to enum"
"attribute should be applied to enum"
}
else
{
continue
}
}
_
=>
continue
,
};
span_err!
(
self
.sess
,
attr
.span
,
E0517
,
"{}"
,
message
);
}
}
...
...
src/librustc/hir/fold.rs
浏览文件 @
8250a26b
...
...
@@ -12,8 +12,8 @@
//! and returns a piece of the same type.
use
hir
::
*
;
use
syntax
::
ast
::{
Name
,
NodeId
,
DUMMY_NODE_ID
,
Attribute
,
Attribute_
,
MetaItem
};
use
syntax
::
ast
::
MetaItemKind
;
use
syntax
::
ast
::{
Name
,
NodeId
,
DUMMY_NODE_ID
,
Attribute
,
Attribute_
};
use
syntax
::
ast
::
{
NestedMetaItem
,
NestedMetaItemKind
,
MetaItem
,
MetaItemKind
}
;
use
hir
;
use
syntax_pos
::
Span
;
use
syntax
::
codemap
::{
respan
,
Spanned
};
...
...
@@ -38,6 +38,10 @@ fn fold_meta_items(&mut self, meta_items: HirVec<P<MetaItem>>) -> HirVec<P<MetaI
noop_fold_meta_items
(
meta_items
,
self
)
}
fn
fold_meta_list_item
(
&
mut
self
,
list_item
:
NestedMetaItem
)
->
NestedMetaItem
{
noop_fold_meta_list_item
(
list_item
,
self
)
}
fn
fold_meta_item
(
&
mut
self
,
meta_item
:
P
<
MetaItem
>
)
->
P
<
MetaItem
>
{
noop_fold_meta_item
(
meta_item
,
self
)
}
...
...
@@ -486,13 +490,26 @@ pub fn noop_fold_attribute<T: Folder>(at: Attribute, fld: &mut T) -> Option<Attr
})
}
pub
fn
noop_fold_meta_list_item
<
T
:
Folder
>
(
li
:
NestedMetaItem
,
fld
:
&
mut
T
)
->
NestedMetaItem
{
Spanned
{
node
:
match
li
.node
{
NestedMetaItemKind
::
MetaItem
(
mi
)
=>
{
NestedMetaItemKind
::
MetaItem
(
fld
.fold_meta_item
(
mi
))
},
NestedMetaItemKind
::
Literal
(
lit
)
=>
NestedMetaItemKind
::
Literal
(
lit
)
},
span
:
fld
.new_span
(
li
.span
)
}
}
pub
fn
noop_fold_meta_item
<
T
:
Folder
>
(
mi
:
P
<
MetaItem
>
,
fld
:
&
mut
T
)
->
P
<
MetaItem
>
{
mi
.map
(|
Spanned
{
node
,
span
}|
{
Spanned
{
node
:
match
node
{
MetaItemKind
::
Word
(
id
)
=>
MetaItemKind
::
Word
(
id
),
MetaItemKind
::
List
(
id
,
mis
)
=>
{
MetaItemKind
::
List
(
id
,
mis
.move_map
(|
e
|
fld
.fold_meta_item
(
e
)))
MetaItemKind
::
List
(
id
,
mis
.move_map
(|
e
|
fld
.fold_meta_
list_
item
(
e
)))
}
MetaItemKind
::
NameValue
(
id
,
s
)
=>
MetaItemKind
::
NameValue
(
id
,
s
),
},
...
...
src/librustc/lint/context.rs
浏览文件 @
8250a26b
...
...
@@ -38,7 +38,7 @@
use
std
::
cmp
;
use
std
::
default
::
Default
as
StdDefault
;
use
std
::
mem
;
use
syntax
::
attr
::{
self
,
AttrMetaMethods
};
use
syntax
::
attr
::{
self
,
AttrMetaMethods
,
AttrNestedMetaItemMethods
};
use
syntax
::
parse
::
token
::
InternedString
;
use
syntax
::
ast
;
use
syntax_pos
::
Span
;
...
...
@@ -372,12 +372,10 @@ pub fn gather_attr(attr: &ast::Attribute)
return
out
;
};
for
meta
in
metas
{
out
.push
(
if
meta
.is_word
()
{
Ok
((
meta
.name
()
.clone
(),
level
,
meta
.span
))
}
else
{
Err
(
meta
.span
)
});
for
li
in
metas
{
out
.push
(
li
.word
()
.map_or
(
Err
(
li
.span
),
|
word
|
{
Ok
((
word
.name
()
.clone
(),
level
,
word
.span
))
}));
}
out
...
...
src/librustc_borrowck/borrowck/mir/mod.rs
浏览文件 @
8250a26b
...
...
@@ -11,7 +11,7 @@
use
borrowck
::
BorrowckCtxt
;
use
syntax
::
ast
::{
self
,
MetaItem
};
use
syntax
::
attr
::
AttrMetaMethods
;
use
syntax
::
attr
::
{
AttrMetaMethods
,
AttrNestedMetaItemMethods
}
;
use
syntax
::
ptr
::
P
;
use
syntax_pos
::{
Span
,
DUMMY_SP
};
...
...
@@ -43,8 +43,9 @@ fn has_rustc_mir_with(attrs: &[ast::Attribute], name: &str) -> Option<P<MetaItem
if
attr
.check_name
(
"rustc_mir"
)
{
let
items
=
attr
.meta_item_list
();
for
item
in
items
.iter
()
.flat_map
(|
l
|
l
.iter
())
{
if
item
.check_name
(
name
)
{
return
Some
(
item
.clone
())
match
item
.meta_item
()
{
Some
(
mi
)
if
mi
.check_name
(
name
)
=>
return
Some
(
mi
.clone
()),
_
=>
continue
}
}
}
...
...
src/librustc_driver/lib.rs
浏览文件 @
8250a26b
...
...
@@ -655,17 +655,19 @@ fn print_crate_info(sess: &Session,
if
!
allow_unstable_cfg
&&
GatedCfg
::
gate
(
&*
cfg
)
.is_some
()
{
continue
;
}
if
cfg
.is_word
()
{
println!
(
"{}"
,
cfg
.name
());
}
else
if
cfg
.is_value_str
()
{
if
let
Some
(
s
)
=
cfg
.value_str
()
{
println!
(
"{}=
\"
{}
\"
"
,
cfg
.name
(),
s
);
}
}
else
if
let
Some
(
s
)
=
cfg
.value_str
()
{
println!
(
"{}=
\"
{}
\"
"
,
cfg
.name
(),
s
);
}
else
if
cfg
.is_meta_item_list
()
{
// Right now there are not and should not be any
// MetaItemKind::List items in the configuration returned by
// `build_configuration`.
panic!
(
"MetaItemKind::List encountered in default cfg"
)
panic!
(
"Found an unexpected list in cfg attribute '{}'!"
,
cfg
.name
())
}
else
{
// There also shouldn't be literals.
panic!
(
"Found an unexpected literal in cfg attribute '{}'!"
,
cfg
.name
())
}
}
}
...
...
src/librustc_incremental/assert_dep_graph.rs
浏览文件 @
8250a26b
...
...
@@ -56,7 +56,7 @@
use
std
::
fs
::
File
;
use
std
::
io
::
Write
;
use
syntax
::
ast
;
use
syntax
::
attr
::
AttrMetaMethods
;
use
syntax
::
attr
::
{
AttrNestedMetaItemMethods
,
AttrMetaMethods
}
;
use
syntax
::
parse
::
token
::
InternedString
;
use
syntax_pos
::
Span
;
...
...
@@ -116,14 +116,18 @@ fn process_attrs(&mut self, node_id: ast::NodeId, def_id: DefId) {
for
attr
in
self
.tcx
.get_attrs
(
def_id
)
.iter
()
{
if
attr
.check_name
(
IF_THIS_CHANGED
)
{
let
mut
id
=
None
;
for
meta_item
in
attr
.meta_item_list
()
.unwrap_or_default
()
{
if
meta_item
.is_word
()
&&
id
.is_none
()
{
id
=
Some
(
meta_item
.name
()
.clone
());
}
else
{
// FIXME better-encapsulate meta_item (don't directly access `node`)
span_bug!
(
meta_item
.span
(),
"unexpected meta-item {:?}"
,
meta_item
.node
)
for
list_item
in
attr
.meta_item_list
()
.unwrap_or_default
()
{
match
list_item
.word
()
{
Some
(
word
)
if
id
.is_none
()
=>
{
id
=
Some
(
word
.name
()
.clone
())
},
_
=>
{
// FIXME better-encapsulate meta_item (don't directly access `node`)
span_bug!
(
list_item
.span
(),
"unexpected list-item {:?}"
,
list_item
.node
)
}
}
}
let
id
=
id
.unwrap_or
(
InternedString
::
new
(
ID
));
self
.if_this_changed
.entry
(
id
)
.or_insert
(
FnvHashSet
())
...
...
@@ -131,16 +135,21 @@ fn process_attrs(&mut self, node_id: ast::NodeId, def_id: DefId) {
}
else
if
attr
.check_name
(
THEN_THIS_WOULD_NEED
)
{
let
mut
dep_node_interned
=
None
;
let
mut
id
=
None
;
for
meta_item
in
attr
.meta_item_list
()
.unwrap_or_default
()
{
if
meta_item
.is_word
()
&&
dep_node_interned
.is_none
()
{
dep_node_interned
=
Some
(
meta_item
.name
()
.clone
());
}
else
if
meta_item
.is_word
()
&&
id
.is_none
()
{
id
=
Some
(
meta_item
.name
()
.clone
());
}
else
{
// FIXME better-encapsulate meta_item (don't directly access `node`)
span_bug!
(
meta_item
.span
(),
"unexpected meta-item {:?}"
,
meta_item
.node
)
for
list_item
in
attr
.meta_item_list
()
.unwrap_or_default
()
{
match
list_item
.word
()
{
Some
(
word
)
if
dep_node_interned
.is_none
()
=>
{
dep_node_interned
=
Some
(
word
.name
()
.clone
());
},
Some
(
word
)
if
id
.is_none
()
=>
{
id
=
Some
(
word
.name
()
.clone
())
},
_
=>
{
// FIXME better-encapsulate meta_item (don't directly access `node`)
span_bug!
(
list_item
.span
(),
"unexpected meta-item {:?}"
,
list_item
.node
)
}
}
}
let
dep_node
=
match
dep_node_interned
{
Some
(
ref
n
)
=>
{
match
DepNode
::
from_label_string
(
&
n
[
..
],
def_id
)
{
...
...
src/librustc_incremental/persist/dirty_clean.rs
浏览文件 @
8250a26b
...
...
@@ -31,8 +31,8 @@
use
rustc
::
hir
::
def_id
::
DefId
;
use
rustc
::
hir
::
intravisit
::
Visitor
;
use
rustc_data_structures
::
fnv
::
FnvHashSet
;
use
syntax
::
ast
::{
self
,
Attribute
,
MetaItem
};
use
syntax
::
attr
::
AttrMetaMethods
;
use
syntax
::
ast
::{
self
,
Attribute
,
Nested
MetaItem
};
use
syntax
::
attr
::
{
AttrNestedMetaItemMethods
,
AttrMetaMethods
}
;
use
syntax
::
parse
::
token
::
InternedString
;
use
rustc
::
ty
::
TyCtxt
;
...
...
@@ -71,13 +71,17 @@ pub struct DirtyCleanVisitor<'a, 'tcx:'a> {
}
impl
<
'a
,
'tcx
>
DirtyCleanVisitor
<
'a
,
'tcx
>
{
fn
expect_associated_value
(
&
self
,
item
:
&
MetaItem
)
->
InternedString
{
fn
expect_associated_value
(
&
self
,
item
:
&
Nested
MetaItem
)
->
InternedString
{
if
let
Some
(
value
)
=
item
.value_str
()
{
value
}
else
{
self
.tcx.sess
.span_fatal
(
item
.span
,
&
format!
(
"associated value expected for `{}`"
,
item
.name
()));
let
msg
=
if
let
Some
(
name
)
=
item
.name
()
{
format!
(
"associated value expected for `{}`"
,
name
)
}
else
{
"expected an associated value"
.to_string
()
};
self
.tcx.sess
.span_fatal
(
item
.span
,
&
msg
);
}
}
...
...
src/librustc_lint/builtin.rs
浏览文件 @
8250a26b
...
...
@@ -44,8 +44,8 @@
use
std
::
collections
::
HashSet
;
use
syntax
::{
ast
};
use
syntax
::
attr
::{
self
,
AttrMetaMethods
,
AttributeMethods
};
use
syntax_pos
::
Span
;
use
syntax
::
attr
::{
self
,
AttrMetaMethods
,
Attr
NestedMetaItemMethods
,
Attr
ibuteMethods
};
use
syntax_pos
::
{
Span
}
;
use
rustc
::
hir
::{
self
,
PatKind
};
use
rustc
::
hir
::
intravisit
::
FnKind
;
...
...
@@ -317,7 +317,7 @@ fn enter_lint_attrs(&mut self, _: &LateContext, attrs: &[ast::Attribute]) {
let
doc_hidden
=
self
.doc_hidden
()
||
attrs
.iter
()
.any
(|
attr
|
{
attr
.check_name
(
"doc"
)
&&
match
attr
.meta_item_list
()
{
None
=>
false
,
Some
(
l
)
=>
attr
::
contains_name
(
&
l
[
..
],
"hidden"
),
Some
(
l
)
=>
attr
::
list_
contains_name
(
&
l
[
..
],
"hidden"
),
}
});
self
.doc_hidden_stack
.push
(
doc_hidden
);
...
...
src/librustc_lint/unused.rs
浏览文件 @
8250a26b
...
...
@@ -234,10 +234,13 @@ fn get_lints(&self) -> LintArray {
impl
LateLintPass
for
UnusedAttributes
{
fn
check_attribute
(
&
mut
self
,
cx
:
&
LateContext
,
attr
:
&
ast
::
Attribute
)
{
debug!
(
"checking attribute: {:?}"
,
attr
);
// Note that check_name() marks the attribute as used if it matches.
for
&
(
ref
name
,
ty
,
_
)
in
KNOWN_ATTRIBUTES
{
match
ty
{
AttributeType
::
Whitelisted
if
attr
.check_name
(
name
)
=>
{
debug!
(
"{:?} is Whitelisted"
,
name
);
break
;
},
_
=>
()
...
...
@@ -247,11 +250,13 @@ fn check_attribute(&mut self, cx: &LateContext, attr: &ast::Attribute) {
let
plugin_attributes
=
cx
.sess
()
.plugin_attributes
.borrow_mut
();
for
&
(
ref
name
,
ty
)
in
plugin_attributes
.iter
()
{
if
ty
==
AttributeType
::
Whitelisted
&&
attr
.check_name
(
&
name
)
{
debug!
(
"{:?} (plugin attr) is whitelisted with ty {:?}"
,
name
,
ty
);
break
;
}
}
if
!
attr
::
is_used
(
attr
)
{
debug!
(
"Emitting warning for: {:?}"
,
attr
);
cx
.span_lint
(
UNUSED_ATTRIBUTES
,
attr
.span
,
"unused attribute"
);
// Is it a builtin attribute that must be used at the crate level?
let
known_crate
=
KNOWN_ATTRIBUTES
.iter
()
.find
(|
&&
(
name
,
ty
,
_
)|
{
...
...
@@ -275,6 +280,8 @@ fn check_attribute(&mut self, cx: &LateContext, attr: &ast::Attribute) {
};
cx
.span_lint
(
UNUSED_ATTRIBUTES
,
attr
.span
,
msg
);
}
}
else
{
debug!
(
"Attr was used: {:?}"
,
attr
);
}
}
}
...
...
src/librustc_metadata/common.rs
浏览文件 @
8250a26b
...
...
@@ -45,26 +45,13 @@
pub
const
tag_items_closure_ty
:
usize
=
0x2b
;
pub
const
tag_def_key
:
usize
=
0x2c
;
// GAP 0x2d 0x
2e
// GAP 0x2d 0x
34
pub
const
tag_index
:
usize
=
0x110
;
// top-level only
pub
const
tag_xref_index
:
usize
=
0x111
;
// top-level only
pub
const
tag_xref_data
:
usize
=
0x112
;
// top-level only
pub
const
tag_meta_item_name_value
:
usize
=
0x2f
;
pub
const
tag_meta_item_name
:
usize
=
0x30
;
pub
const
tag_meta_item_value
:
usize
=
0x31
;
pub
const
tag_attributes
:
usize
=
0x101
;
// top-level only
pub
const
tag_attribute
:
usize
=
0x32
;
pub
const
tag_meta_item_word
:
usize
=
0x33
;
pub
const
tag_meta_item_list
:
usize
=
0x34
;
// The list of crates that this crate depends on
pub
const
tag_crate_deps
:
usize
=
0x102
;
// top-level only
...
...
src/librustc_metadata/creader.rs
浏览文件 @
8250a26b
...
...
@@ -35,8 +35,7 @@
use
syntax
::
abi
::
Abi
;
use
syntax
::
codemap
;
use
syntax
::
parse
;
use
syntax
::
attr
;
use
syntax
::
attr
::
AttrMetaMethods
;
use
syntax
::
attr
::{
self
,
AttrMetaMethods
,
AttrNestedMetaItemMethods
};
use
syntax
::
parse
::
token
::
InternedString
;
use
syntax
::
visit
;
use
syntax_pos
::{
self
,
Span
,
mk_sp
,
Pos
};
...
...
src/librustc_metadata/decoder.rs
浏览文件 @
8250a26b
...
...
@@ -56,7 +56,6 @@
use
syntax
::
ast
;
use
syntax
::
codemap
;
use
syntax
::
print
::
pprust
;
use
syntax
::
ptr
::
P
;
use
syntax_pos
::{
self
,
Span
,
BytePos
,
NO_EXPANSION
};
pub
type
Cmd
<
'a
>
=
&
'a
CrateMetadata
;
...
...
@@ -1121,44 +1120,20 @@ pub fn get_struct_field_names(cdata: Cmd, id: DefIndex) -> Vec<ast::Name> {
}))
.collect
()
}
fn
get_meta_items
(
md
:
rbml
::
Doc
)
->
Vec
<
P
<
ast
::
MetaItem
>>
{
reader
::
tagged_docs
(
md
,
tag_meta_item_word
)
.map
(|
meta_item_doc
|
{
let
nd
=
reader
::
get_doc
(
meta_item_doc
,
tag_meta_item_name
);
let
n
=
token
::
intern_and_get_ident
(
nd
.as_str
());
attr
::
mk_word_item
(
n
)
})
.chain
(
reader
::
tagged_docs
(
md
,
tag_meta_item_name_value
)
.map
(|
meta_item_doc
|
{
let
nd
=
reader
::
get_doc
(
meta_item_doc
,
tag_meta_item_name
);
let
vd
=
reader
::
get_doc
(
meta_item_doc
,
tag_meta_item_value
);
let
n
=
token
::
intern_and_get_ident
(
nd
.as_str
());
let
v
=
token
::
intern_and_get_ident
(
vd
.as_str
());
// FIXME (#623): Should be able to decode MetaItemKind::NameValue variants,
// but currently the encoder just drops them
attr
::
mk_name_value_item_str
(
n
,
v
)
}))
.chain
(
reader
::
tagged_docs
(
md
,
tag_meta_item_list
)
.map
(|
meta_item_doc
|
{
let
nd
=
reader
::
get_doc
(
meta_item_doc
,
tag_meta_item_name
);
let
n
=
token
::
intern_and_get_ident
(
nd
.as_str
());
let
subitems
=
get_meta_items
(
meta_item_doc
);
attr
::
mk_list_item
(
n
,
subitems
)
}))
.collect
()
}
fn
get_attributes
(
md
:
rbml
::
Doc
)
->
Vec
<
ast
::
Attribute
>
{
match
reader
::
maybe_get_doc
(
md
,
tag_attributes
)
{
Some
(
attrs_d
)
=>
{
reader
::
tagged_docs
(
attrs_d
,
tag_attribute
)
.map
(|
attr_doc
|
{
let
is_sugared_doc
=
reader
::
doc_as_u8
(
reader
::
get_doc
(
attr_doc
,
tag_attribute_is_sugared_doc
)
)
==
1
;
let
meta_items
=
get_meta_items
(
attr_doc
);
// Currently it's only possible to have a single meta item on
// an attribute
assert_eq!
(
meta_items
.len
(),
1
);
let
meta_item
=
meta_items
.into_iter
()
.nth
(
0
)
.unwrap
();
attr
::
mk_doc_attr_outer
(
attr
::
mk_attr_id
(),
meta_item
,
is_sugared_doc
)
})
.collect
()
},
None
=>
vec!
[],
}
reader
::
maybe_get_doc
(
md
,
tag_attributes
)
.map_or
(
vec!
[],
|
attrs_doc
|
{
let
mut
decoder
=
reader
::
Decoder
::
new
(
attrs_doc
);
let
mut
attrs
:
Vec
<
ast
::
Attribute
>
=
decoder
.read_opaque
(|
opaque_decoder
,
_
|
{
Decodable
::
decode
(
opaque_decoder
)
})
.unwrap
();
// Need new unique IDs: old thread-local IDs won't map to new threads.
for
attr
in
attrs
.iter_mut
()
{
attr
.node.id
=
attr
::
mk_attr_id
();
}
attrs
})
}
fn
list_crate_attributes
(
md
:
rbml
::
Doc
,
hash
:
&
Svh
,
...
...
src/librustc_metadata/encoder.rs
浏览文件 @
8250a26b
...
...
@@ -41,7 +41,7 @@
use
std
::
rc
::
Rc
;
use
std
::
u32
;
use
syntax
::
ast
::{
self
,
NodeId
,
Name
,
CRATE_NODE_ID
,
CrateNum
};
use
syntax
::
attr
::{
self
,
AttrMetaMethods
,
AttributeMethods
}
;
use
syntax
::
attr
;
use
errors
::
Handler
;
use
syntax
;
use
syntax_pos
::
BytePos
;
...
...
@@ -1412,40 +1412,11 @@ fn encode_item_index(rbml_w: &mut Encoder, index: IndexData) {
rbml_w
.end_tag
();
}
fn
encode_meta_item
(
rbml_w
:
&
mut
Encoder
,
mi
:
&
ast
::
MetaItem
)
{
if
mi
.is_word
()
{
let
name
=
mi
.name
();
rbml_w
.start_tag
(
tag_meta_item_word
);
rbml_w
.wr_tagged_str
(
tag_meta_item_name
,
&
name
);
rbml_w
.end_tag
();
}
else
if
mi
.is_value_str
()
{
let
name
=
mi
.name
();
/* FIXME (#623): support other literal kinds */
let
value
=
mi
.value_str
()
.unwrap
();
rbml_w
.start_tag
(
tag_meta_item_name_value
);
rbml_w
.wr_tagged_str
(
tag_meta_item_name
,
&
name
);
rbml_w
.wr_tagged_str
(
tag_meta_item_value
,
&
value
);
rbml_w
.end_tag
();
}
else
{
// it must be a list
let
name
=
mi
.name
();
let
items
=
mi
.meta_item_list
()
.unwrap
();
rbml_w
.start_tag
(
tag_meta_item_list
);
rbml_w
.wr_tagged_str
(
tag_meta_item_name
,
&
name
);
for
inner_item
in
items
{
encode_meta_item
(
rbml_w
,
&
inner_item
);
}
rbml_w
.end_tag
();
}
}
fn
encode_attributes
(
rbml_w
:
&
mut
Encoder
,
attrs
:
&
[
ast
::
Attribute
])
{
rbml_w
.start_tag
(
tag_attributes
);
for
attr
in
attrs
{
rbml_w
.start_tag
(
tag_attribute
);
rbml_w
.wr_tagged_u8
(
tag_attribute_is_sugared_doc
,
attr
.node.is_sugared_doc
as
u8
);
encode_meta_item
(
rbml_w
,
attr
.meta
());
rbml_w
.end_tag
();
}
rbml_w
.emit_opaque
(|
opaque_encoder
|
{
attrs
.encode
(
opaque_encoder
)
})
.unwrap
();
rbml_w
.end_tag
();
}
...
...
src/librustc_metadata/macro_import.rs
浏览文件 @
8250a26b
...
...
@@ -18,8 +18,7 @@
use
std
::
collections
::{
HashSet
,
HashMap
};
use
syntax
::
parse
::
token
;
use
syntax
::
ast
;
use
syntax
::
attr
;
use
syntax
::
attr
::
AttrMetaMethods
;
use
syntax
::
attr
::{
self
,
AttrNestedMetaItemMethods
,
AttrMetaMethods
};
use
syntax
::
ext
;
use
syntax_pos
::
Span
;
...
...
@@ -64,8 +63,8 @@ fn load_crate(&mut self, extern_crate: &ast::Item, allows_macros: bool) -> Vec<a
}
if
let
(
Some
(
sel
),
Some
(
names
))
=
(
import
.as_mut
(),
names
)
{
for
attr
in
names
{
if
attr
.is_
word
()
{
sel
.insert
(
attr
.name
()
.clone
(),
attr
.span
());
if
let
Some
(
word
)
=
attr
.
word
()
{
sel
.insert
(
word
.name
()
.clone
(),
attr
.span
());
}
else
{
span_err!
(
self
.sess
,
attr
.span
(),
E0466
,
"bad macro import"
);
}
...
...
@@ -82,8 +81,8 @@ fn load_crate(&mut self, extern_crate: &ast::Item, allows_macros: bool) -> Vec<a
};
for
attr
in
names
{
if
attr
.is_
word
()
{
reexport
.insert
(
attr
.name
()
.clone
(),
attr
.span
());
if
let
Some
(
word
)
=
attr
.
word
()
{
reexport
.insert
(
word
.name
()
.clone
(),
attr
.span
());
}
else
{
call_bad_macro_reexport
(
self
.sess
,
attr
.span
());
}
...
...
src/librustc_plugin/load.rs
浏览文件 @
8250a26b
...
...
@@ -20,8 +20,7 @@
use
std
::
mem
;
use
std
::
path
::
PathBuf
;
use
syntax
::
ast
;
use
syntax
::
ptr
::
P
;
use
syntax
::
attr
::
AttrMetaMethods
;
use
syntax
::
attr
::{
AttrMetaMethods
,
AttrNestedMetaItemMethods
};
use
syntax_pos
::{
Span
,
COMMAND_LINE_SP
};
/// Pointer to a registrar function.
...
...
@@ -30,7 +29,7 @@
pub
struct
PluginRegistrar
{
pub
fun
:
PluginRegistrarFun
,
pub
args
:
Vec
<
P
<
ast
::
MetaItem
>
>
,
pub
args
:
Vec
<
ast
::
NestedMetaItem
>
,
}
struct
PluginLoader
<
'a
>
{
...
...
@@ -69,13 +68,14 @@ pub fn load_plugins(sess: &Session,
};
for
plugin
in
plugins
{
if
plugin
.value_str
()
.is_some
()
{
call_malformed_plugin_attribute
(
sess
,
attr
.span
);
continue
;
// plugins must have a name and can't be key = value
match
plugin
.name
()
{
Some
(
ref
name
)
if
!
plugin
.is_value_str
()
=>
{
let
args
=
plugin
.meta_item_list
()
.map
(
ToOwned
::
to_owned
);
loader
.load_plugin
(
plugin
.span
,
name
,
args
.unwrap_or_default
());
},
_
=>
call_malformed_plugin_attribute
(
sess
,
attr
.span
),
}
let
args
=
plugin
.meta_item_list
()
.map
(
ToOwned
::
to_owned
)
.unwrap_or_default
();
loader
.load_plugin
(
plugin
.span
,
&
plugin
.name
(),
args
);
}
}
}
...
...
@@ -102,7 +102,7 @@ fn new(sess: &'a Session,
}
}
fn
load_plugin
(
&
mut
self
,
span
:
Span
,
name
:
&
str
,
args
:
Vec
<
P
<
ast
::
MetaItem
>
>
)
{
fn
load_plugin
(
&
mut
self
,
span
:
Span
,
name
:
&
str
,
args
:
Vec
<
ast
::
NestedMetaItem
>
)
{
let
registrar
=
self
.reader
.find_plugin_registrar
(
span
,
name
);
if
let
Some
((
lib
,
svh
,
index
))
=
registrar
{
...
...
src/librustc_plugin/registry.rs
浏览文件 @
8250a26b
...
...
@@ -19,7 +19,6 @@
use
syntax
::
ext
::
base
::{
IdentTT
,
MultiModifier
,
MultiDecorator
};
use
syntax
::
ext
::
base
::{
MacroExpanderFn
,
MacroRulesTT
};
use
syntax
::
parse
::
token
;
use
syntax
::
ptr
::
P
;
use
syntax
::
ast
;
use
syntax
::
feature_gate
::
AttributeType
;
use
syntax_pos
::
Span
;
...
...
@@ -41,7 +40,7 @@ pub struct Registry<'a> {
pub
sess
:
&
'a
Session
,
#[doc(hidden)]
pub
args_hidden
:
Option
<
Vec
<
P
<
ast
::
MetaItem
>
>>
,
pub
args_hidden
:
Option
<
Vec
<
ast
::
NestedMetaItem
>>
,
#[doc(hidden)]
pub
krate_span
:
Span
,
...
...
@@ -95,7 +94,7 @@ pub fn new(sess: &'a Session, krate: &ast::Crate) -> Registry<'a> {
///
/// Returns empty slice in case the plugin was loaded
/// with `--extra-plugins`
pub
fn
args
<
'b
>
(
&
'b
self
)
->
&
'b
[
P
<
ast
::
MetaItem
>
]
{
pub
fn
args
<
'b
>
(
&
'b
self
)
->
&
'b
[
ast
::
NestedMetaItem
]
{
self
.args_hidden
.as_ref
()
.map
(|
v
|
&
v
[
..
])
.unwrap_or
(
&
[])
}
...
...
src/librustc_trans/assert_module_sources.rs
浏览文件 @
8250a26b
...
...
@@ -29,7 +29,7 @@
use
rustc
::
ty
::
TyCtxt
;
use
syntax
::
ast
;
use
syntax
::
attr
::
AttrMetaMethods
;
use
syntax
::
attr
::
{
AttrMetaMethods
,
AttrNestedMetaItemMethods
}
;
use
syntax
::
parse
::
token
::
InternedString
;
use
{
ModuleSource
,
ModuleTranslation
};
...
...
src/librustdoc/clean/mod.rs
浏览文件 @
8250a26b
...
...
@@ -26,10 +26,11 @@
use
syntax
::
abi
::
Abi
;
use
syntax
::
ast
;
use
syntax
::
attr
;
use
syntax
::
attr
::{
AttributeMethods
,
AttrMetaMethods
};
use
syntax
::
attr
::{
AttributeMethods
,
AttrMetaMethods
,
AttrNestedMetaItemMethods
};
use
syntax
::
codemap
::
Spanned
;
use
syntax
::
parse
::
token
::{
self
,
InternedString
,
keywords
};
use
syntax
::
ptr
::
P
;
use
syntax
::
print
::
pprust
as
syntax_pprust
;
use
syntax_pos
::{
self
,
DUMMY_SP
,
Pos
};
use
rustc_trans
::
back
::
link
;
...
...
@@ -501,11 +502,24 @@ fn list<'a>(&'a self, name: &str) -> &'a [Attribute] {
}
}
/// This is a flattened version of the AST's Attribute + MetaItem.
#[derive(Clone,
RustcEncodable,
RustcDecodable,
PartialEq,
Debug)]
pub
enum
Attribute
{
Word
(
String
),
List
(
String
,
Vec
<
Attribute
>
),
NameValue
(
String
,
String
)
NameValue
(
String
,
String
),
Literal
(
String
),
}
impl
Clean
<
Attribute
>
for
ast
::
NestedMetaItem
{
fn
clean
(
&
self
,
cx
:
&
DocContext
)
->
Attribute
{
if
let
Some
(
mi
)
=
self
.meta_item
()
{
mi
.clean
(
cx
)
}
else
{
// must be a literal
let
lit
=
self
.literal
()
.unwrap
();
Literal
(
syntax_pprust
::
lit_to_string
(
lit
))
}
}
}
impl
Clean
<
Attribute
>
for
ast
::
MetaItem
{
...
...
@@ -528,12 +542,28 @@ fn clean(&self, cx: &DocContext) -> Attribute {
}
// This is a rough approximation that gets us what we want.
impl
attr
::
AttrMetaMethods
for
Attribute
{
fn
name
(
&
self
)
->
InternedString
{
impl
attr
::
AttrNestedMetaItemMethods
for
Attribute
{
fn
check_name
(
&
self
,
name
:
&
str
)
->
bool
{
self
.name
()
.map_or
(
false
,
|
mi_name
|
&*
mi_name
==
name
)
}
fn
literal
(
&
self
)
->
Option
<&
ast
::
Lit
>
{
None
}
fn
is_literal
(
&
self
)
->
bool
{
match
*
self
{
Literal
(
..
)
=>
true
,
_
=>
false
,
}
}
fn
meta_item
(
&
self
)
->
Option
<&
P
<
ast
::
MetaItem
>>
{
None
}
fn
name
(
&
self
)
->
Option
<
InternedString
>
{
match
*
self
{
Word
(
ref
n
)
|
List
(
ref
n
,
_
)
|
NameValue
(
ref
n
,
_
)
=>
{
token
::
intern_and_get_ident
(
n
)
}
Some
(
token
::
intern_and_get_ident
(
n
))
},
_
=>
None
}
}
...
...
@@ -545,7 +575,8 @@ fn value_str(&self) -> Option<InternedString> {
_
=>
None
,
}
}
fn
meta_item_list
<
'a
>
(
&
'a
self
)
->
Option
<&
'a
[
P
<
ast
::
MetaItem
>
]
>
{
None
}
fn
word
(
&
self
)
->
Option
<&
P
<
ast
::
MetaItem
>>
{
None
}
fn
is_word
(
&
self
)
->
bool
{
match
*
self
{
...
...
@@ -554,12 +585,7 @@ fn is_word(&self) -> bool {
}
}
fn
is_value_str
(
&
self
)
->
bool
{
match
*
self
{
NameValue
(
..
)
=>
true
,
_
=>
false
,
}
}
fn
meta_item_list
<
'a
>
(
&
'a
self
)
->
Option
<&
'a
[
ast
::
NestedMetaItem
]
>
{
None
}
fn
is_meta_item_list
(
&
self
)
->
bool
{
match
*
self
{
...
...
@@ -2535,8 +2561,8 @@ fn clean(&self, cx: &DocContext) -> Vec<Item> {
// Don't inline doc(hidden) imports so they can be stripped at a later stage.
let
denied
=
self
.vis
!=
hir
::
Public
||
self
.attrs
.iter
()
.any
(|
a
|
{
&
a
.name
()[
..
]
==
"doc"
&&
match
a
.meta_item_list
()
{
Some
(
l
)
=>
attr
::
contains_name
(
l
,
"no_inline"
)
||
attr
::
contains_name
(
l
,
"hidden"
),
Some
(
l
)
=>
attr
::
list_
contains_name
(
l
,
"no_inline"
)
||
attr
::
list_
contains_name
(
l
,
"hidden"
),
None
=>
false
,
}
});
...
...
src/librustdoc/test.rs
浏览文件 @
8250a26b
...
...
@@ -141,6 +141,7 @@ pub fn run(input: &str,
// Look for #![doc(test(no_crate_inject))], used by crates in the std facade
fn
scrape_test_config
(
krate
:
&
::
rustc
::
hir
::
Crate
)
->
TestOptions
{
use
syntax
::
attr
::
AttrMetaMethods
;
use
syntax
::
attr
::
AttrNestedMetaItemMethods
;
use
syntax
::
print
::
pprust
;
let
mut
opts
=
TestOptions
{
...
...
@@ -162,7 +163,7 @@ fn scrape_test_config(krate: &::rustc::hir::Crate) -> TestOptions {
if
attr
.check_name
(
"attr"
)
{
if
let
Some
(
l
)
=
attr
.meta_item_list
()
{
for
item
in
l
{
opts
.attrs
.push
(
pprust
::
meta_item_to_string
(
item
));
opts
.attrs
.push
(
pprust
::
meta_
list_
item_to_string
(
item
));
}
}
}
...
...
src/librustdoc/visit_ast.rs
浏览文件 @
8250a26b
...
...
@@ -17,7 +17,7 @@
use
syntax
::
abi
;
use
syntax
::
ast
;
use
syntax
::
attr
;
use
syntax
::
attr
::
AttrMetaMethods
;
use
syntax
::
attr
::
{
AttrMetaMethods
,
AttrNestedMetaItemMethods
}
;
use
syntax_pos
::
Span
;
use
rustc
::
hir
::
map
as
hir_map
;
...
...
@@ -333,8 +333,8 @@ pub fn visit_item(&mut self, item: &hir::Item,
let
node
=
if
item
.vis
==
hir
::
Public
{
let
please_inline
=
item
.attrs
.iter
()
.any
(|
item
|
{
match
item
.meta_item_list
()
{
Some
(
list
)
if
&
item
.name
()[
..
]
==
"doc"
=>
{
list
.iter
()
.any
(|
i
|
&
i
.name
()[
..
]
==
"inline"
)
Some
(
list
)
if
item
.check_name
(
"doc"
)
=>
{
list
.iter
()
.any
(|
i
|
i
.check_name
(
"inline"
)
)
}
_
=>
false
,
}
...
...
src/libsyntax/ast.rs
浏览文件 @
8250a26b
...
...
@@ -439,6 +439,22 @@ pub struct Crate {
pub
exported_macros
:
Vec
<
MacroDef
>
,
}
/// A spanned compile-time attribute list item.
pub
type
NestedMetaItem
=
Spanned
<
NestedMetaItemKind
>
;
/// Possible values inside of compile-time attribute lists.
///
/// E.g. the '..' in `#[name(..)]`.
#[derive(Clone,
Eq,
RustcEncodable,
RustcDecodable,
Hash,
Debug,
PartialEq)]
pub
enum
NestedMetaItemKind
{
/// A full MetaItem, for recursive meta items.
MetaItem
(
P
<
MetaItem
>
),
/// A literal.
///
/// E.g. "foo", 64, true
Literal
(
Lit
),
}
/// A spanned compile-time attribute item.
///
/// E.g. `#[test]`, `#[derive(..)]` or `#[feature = "foo"]`
...
...
@@ -456,7 +472,7 @@ pub enum MetaItemKind {
/// List meta item.
///
/// E.g. `derive(..)` as in `#[derive(..)]`
List
(
InternedString
,
Vec
<
P
<
MetaItem
>
>
),
List
(
InternedString
,
Vec
<
NestedMetaItem
>
),
/// Name value meta item.
///
/// E.g. `feature = "foo"` as in `#[feature = "foo"]`
...
...
@@ -472,19 +488,21 @@ fn eq(&self, other: &MetaItemKind) -> bool {
Word
(
ref
no
)
=>
(
*
ns
)
==
(
*
no
),
_
=>
false
},
List
(
ref
ns
,
ref
miss
)
=>
match
*
other
{
List
(
ref
no
,
ref
miso
)
=>
{
ns
==
no
&&
miss
.iter
()
.all
(|
mi
|
{
miso
.iter
()
.any
(|
x
|
x
.node
==
mi
.node
)
})
}
_
=>
false
},
NameValue
(
ref
ns
,
ref
vs
)
=>
match
*
other
{
NameValue
(
ref
no
,
ref
vo
)
=>
{
(
*
ns
)
==
(
*
no
)
&&
vs
.node
==
vo
.node
}
_
=>
false
},
List
(
ref
ns
,
ref
miss
)
=>
match
*
other
{
List
(
ref
no
,
ref
miso
)
=>
{
ns
==
no
&&
miss
.iter
()
.all
(|
mi
|
miso
.iter
()
.any
(|
x
|
x
.node
==
mi
.node
))
}
_
=>
false
}
}
}
}
...
...
@@ -1105,6 +1123,30 @@ pub fn is_str(&self) -> bool {
_
=>
false
,
}
}
/// Returns true if this literal has no suffix. Note: this will return true
/// for literals with prefixes such as raw strings and byte strings.
pub
fn
is_unsuffixed
(
&
self
)
->
bool
{
match
*
self
{
// unsuffixed variants
LitKind
::
Str
(
..
)
=>
true
,
LitKind
::
ByteStr
(
..
)
=>
true
,
LitKind
::
Byte
(
..
)
=>
true
,
LitKind
::
Char
(
..
)
=>
true
,
LitKind
::
Int
(
_
,
LitIntType
::
Unsuffixed
)
=>
true
,
LitKind
::
FloatUnsuffixed
(
..
)
=>
true
,
LitKind
::
Bool
(
..
)
=>
true
,
// suffixed variants
LitKind
::
Int
(
_
,
LitIntType
::
Signed
(
..
))
=>
false
,
LitKind
::
Int
(
_
,
LitIntType
::
Unsigned
(
..
))
=>
false
,
LitKind
::
Float
(
..
)
=>
false
,
}
}
/// Returns true if this literal has a suffix.
pub
fn
is_suffixed
(
&
self
)
->
bool
{
!
self
.is_unsuffixed
()
}
}
// NB: If you change this, you'll probably want to change the corresponding
...
...
src/libsyntax/attr.rs
浏览文件 @
8250a26b
此差异已折叠。
点击以展开。
src/libsyntax/config.rs
浏览文件 @
8250a26b
...
...
@@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use
attr
::{
AttrMetaMethods
,
HasAttrs
};
use
attr
::{
AttrMetaMethods
,
AttrNestedMetaItemMethods
,
HasAttrs
};
use
feature_gate
::{
emit_feature_err
,
EXPLAIN_STMT_ATTR_SYNTAX
,
Features
,
get_features
,
GateIssue
};
use
fold
::
Folder
;
use
{
fold
,
attr
};
...
...
@@ -52,6 +52,7 @@ fn process_cfg_attr(&mut self, attr: ast::Attribute) -> Option<ast::Attribute> {
return
None
;
}
};
let
(
cfg
,
mi
)
=
match
(
attr_list
.len
(),
attr_list
.get
(
0
),
attr_list
.get
(
1
))
{
(
2
,
Some
(
cfg
),
Some
(
mi
))
=>
(
cfg
,
mi
),
_
=>
{
...
...
@@ -61,15 +62,24 @@ fn process_cfg_attr(&mut self, attr: ast::Attribute) -> Option<ast::Attribute> {
}
};
if
attr
::
cfg_matches
(
self
.config
,
&
cfg
,
self
.sess
,
self
.features
)
{
self
.process_cfg_attr
(
respan
(
mi
.span
,
ast
::
Attribute_
{
id
:
attr
::
mk_attr_id
(),
style
:
attr
.node.style
,
value
:
mi
.clone
(),
is_sugared_doc
:
false
,
}))
}
else
{
None
use
attr
::
cfg_matches
;
match
(
cfg
.meta_item
(),
mi
.meta_item
())
{
(
Some
(
cfg
),
Some
(
mi
))
=>
if
cfg_matches
(
self
.config
,
&
cfg
,
self
.sess
,
self
.features
)
{
self
.process_cfg_attr
(
respan
(
mi
.span
,
ast
::
Attribute_
{
id
:
attr
::
mk_attr_id
(),
style
:
attr
.node.style
,
value
:
mi
.clone
(),
is_sugared_doc
:
false
,
}))
}
else
{
None
},
_
=>
{
let
msg
=
"unexpected literal(s) in `#[cfg_attr(<cfg pattern>, <attr>)]`"
;
self
.sess.span_diagnostic
.span_err
(
attr
.span
,
msg
);
None
}
}
}
...
...
@@ -91,7 +101,12 @@ fn in_cfg(&mut self, attrs: &[ast::Attribute]) -> bool {
return
true
;
}
attr
::
cfg_matches
(
self
.config
,
&
mis
[
0
],
self
.sess
,
self
.features
)
if
!
mis
[
0
]
.is_meta_item
()
{
self
.sess.span_diagnostic
.span_err
(
mis
[
0
]
.span
,
"unexpected literal"
);
return
true
;
}
attr
::
cfg_matches
(
self
.config
,
mis
[
0
]
.meta_item
()
.unwrap
(),
self
.sess
,
self
.features
)
})
}
...
...
src/libsyntax/diagnostic_list.rs
浏览文件 @
8250a26b
...
...
@@ -161,6 +161,24 @@ fn main() {}
```
"##
,
E0565
:
r##"
A literal was used in an attribute that doesn't support literals.
Erroneous code example:
```compile_fail,E0565
#[inline("always")] // error: unsupported literal
pub fn something() {}
```
Literals in attributes are new and largely unsupported. Work to support literals
where appropriate is ongoing. Try using an unquoted name instead:
```
#[inline(always)]
pub fn something() {}
```
"##
,
}
register_diagnostics!
{
...
...
src/libsyntax/ext/build.rs
浏览文件 @
8250a26b
...
...
@@ -277,10 +277,13 @@ fn item_ty_poly(&self,
fn
attribute
(
&
self
,
sp
:
Span
,
mi
:
P
<
ast
::
MetaItem
>
)
->
ast
::
Attribute
;
fn
meta_word
(
&
self
,
sp
:
Span
,
w
:
InternedString
)
->
P
<
ast
::
MetaItem
>
;
fn
meta_list_item_word
(
&
self
,
sp
:
Span
,
w
:
InternedString
)
->
ast
::
NestedMetaItem
;
fn
meta_list
(
&
self
,
sp
:
Span
,
name
:
InternedString
,
mis
:
Vec
<
P
<
ast
::
MetaItem
>
>
)
mis
:
Vec
<
ast
::
NestedMetaItem
>
)
->
P
<
ast
::
MetaItem
>
;
fn
meta_name_value
(
&
self
,
sp
:
Span
,
...
...
@@ -1141,10 +1144,16 @@ fn attribute(&self, sp: Span, mi: P<ast::MetaItem>) -> ast::Attribute {
fn
meta_word
(
&
self
,
sp
:
Span
,
w
:
InternedString
)
->
P
<
ast
::
MetaItem
>
{
attr
::
mk_spanned_word_item
(
sp
,
w
)
}
fn
meta_list
(
&
self
,
sp
:
Span
,
name
:
InternedString
,
mis
:
Vec
<
P
<
ast
::
MetaItem
>>
)
fn
meta_list_item_word
(
&
self
,
sp
:
Span
,
w
:
InternedString
)
->
ast
::
NestedMetaItem
{
respan
(
sp
,
ast
::
NestedMetaItemKind
::
MetaItem
(
attr
::
mk_spanned_word_item
(
sp
,
w
)))
}
fn
meta_list
(
&
self
,
sp
:
Span
,
name
:
InternedString
,
mis
:
Vec
<
ast
::
NestedMetaItem
>
)
->
P
<
ast
::
MetaItem
>
{
attr
::
mk_spanned_list_item
(
sp
,
name
,
mis
)
}
fn
meta_name_value
(
&
self
,
sp
:
Span
,
name
:
InternedString
,
value
:
ast
::
LitKind
)
->
P
<
ast
::
MetaItem
>
{
attr
::
mk_spanned_name_value_item
(
sp
,
name
,
respan
(
sp
,
value
))
...
...
src/libsyntax/feature_gate.rs
浏览文件 @
8250a26b
...
...
@@ -26,10 +26,8 @@
use
self
::
AttributeGate
::
*
;
use
abi
::
Abi
;
use
ast
::{
NodeId
,
PatKind
};
use
ast
;
use
attr
;
use
attr
::
AttrMetaMethods
;
use
ast
::{
self
,
NodeId
,
PatKind
};
use
attr
::{
self
,
AttrMetaMethods
,
AttrNestedMetaItemMethods
};
use
codemap
::
CodeMap
;
use
syntax_pos
::
Span
;
use
errors
::
Handler
;
...
...
@@ -283,7 +281,10 @@ pub fn new() -> Features {
(
active
,
relaxed_adts
,
"1.12.0"
,
Some
(
35626
)),
// The `!` type
(
active
,
never_type
,
"1.13.0"
,
Some
(
35121
))
(
active
,
never_type
,
"1.13.0"
,
Some
(
35121
)),
// Allows all literals in attribute lists and values of key-value pairs.
(
active
,
attr_literals
,
"1.13.0"
,
Some
(
34981
))
);
declare_features!
(
...
...
@@ -831,11 +832,34 @@ fn check_abi(&self, abi: Abi, span: Span) {
}
}
fn
contains_novel_literal
(
item
:
&
ast
::
MetaItem
)
->
bool
{
use
ast
::
MetaItemKind
::
*
;
use
ast
::
NestedMetaItemKind
::
*
;
match
item
.node
{
Word
(
..
)
=>
false
,
NameValue
(
_
,
ref
lit
)
=>
!
lit
.node
.is_str
(),
List
(
_
,
ref
list
)
=>
list
.iter
()
.any
(|
li
|
{
match
li
.node
{
MetaItem
(
ref
mi
)
=>
contains_novel_literal
(
&**
mi
),
Literal
(
_
)
=>
true
,
}
}),
}
}
impl
<
'a
>
Visitor
for
PostExpansionVisitor
<
'a
>
{
fn
visit_attribute
(
&
mut
self
,
attr
:
&
ast
::
Attribute
)
{
if
!
self
.context.cm
.span_allows_unstable
(
attr
.span
)
{
// check for gated attributes
self
.context
.check_attribute
(
attr
,
false
);
}
if
contains_novel_literal
(
&*
(
attr
.node.value
))
{
gate_feature_post!
(
&
self
,
attr_literals
,
attr
.span
,
"non-string literals in attributes, or string
\
literals in top-level positions, are experimental"
);
}
}
fn
visit_name
(
&
mut
self
,
sp
:
Span
,
name
:
ast
::
Name
)
{
...
...
@@ -895,7 +919,7 @@ fn visit_item(&mut self, i: &ast::Item) {
for
attr
in
&
i
.attrs
{
if
attr
.name
()
==
"repr"
{
for
item
in
attr
.meta_item_list
()
.unwrap_or
(
&
[])
{
if
item
.
name
()
==
"simd"
{
if
item
.
check_name
(
"simd"
)
{
gate_feature_post!
(
&
self
,
repr_simd
,
i
.span
,
"SIMD types are experimental
\
and possibly buggy"
);
...
...
@@ -1155,13 +1179,14 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute]) -> F
}
Some
(
list
)
=>
{
for
mi
in
list
{
let
name
=
if
mi
.is_word
()
{
mi
.name
()
}
else
{
span_err!
(
span_handler
,
mi
.span
,
E0556
,
"malformed feature, expected just one word"
);
continue
};
let
name
=
if
let
Some
(
word
)
=
mi
.word
()
{
word
.name
()
}
else
{
span_err!
(
span_handler
,
mi
.span
,
E0556
,
"malformed feature, expected just one word"
);
continue
};
if
let
Some
(
&
(
_
,
_
,
_
,
setter
))
=
ACTIVE_FEATURES
.iter
()
.find
(|
&
&
(
n
,
_
,
_
,
_
)|
name
==
n
)
{
*
(
setter
(
&
mut
features
))
=
true
;
...
...
src/libsyntax/fold.rs
浏览文件 @
8250a26b
...
...
@@ -47,6 +47,10 @@ fn fold_meta_items(&mut self, meta_items: Vec<P<MetaItem>>) -> Vec<P<MetaItem>>
noop_fold_meta_items
(
meta_items
,
self
)
}
fn
fold_meta_list_item
(
&
mut
self
,
list_item
:
NestedMetaItem
)
->
NestedMetaItem
{
noop_fold_meta_list_item
(
list_item
,
self
)
}
fn
fold_meta_item
(
&
mut
self
,
meta_item
:
P
<
MetaItem
>
)
->
P
<
MetaItem
>
{
noop_fold_meta_item
(
meta_item
,
self
)
}
...
...
@@ -513,12 +517,25 @@ pub fn noop_fold_mac<T: Folder>(Spanned {node, span}: Mac, fld: &mut T) -> Mac {
}
}
pub
fn
noop_fold_meta_list_item
<
T
:
Folder
>
(
li
:
NestedMetaItem
,
fld
:
&
mut
T
)
->
NestedMetaItem
{
Spanned
{
node
:
match
li
.node
{
NestedMetaItemKind
::
MetaItem
(
mi
)
=>
{
NestedMetaItemKind
::
MetaItem
(
fld
.fold_meta_item
(
mi
))
},
NestedMetaItemKind
::
Literal
(
lit
)
=>
NestedMetaItemKind
::
Literal
(
lit
)
},
span
:
fld
.new_span
(
li
.span
)
}
}
pub
fn
noop_fold_meta_item
<
T
:
Folder
>
(
mi
:
P
<
MetaItem
>
,
fld
:
&
mut
T
)
->
P
<
MetaItem
>
{
mi
.map
(|
Spanned
{
node
,
span
}|
Spanned
{
node
:
match
node
{
MetaItemKind
::
Word
(
id
)
=>
MetaItemKind
::
Word
(
id
),
MetaItemKind
::
List
(
id
,
mis
)
=>
{
MetaItemKind
::
List
(
id
,
mis
.move_map
(|
e
|
fld
.fold_meta_item
(
e
)))
MetaItemKind
::
List
(
id
,
mis
.move_map
(|
e
|
fld
.fold_meta_
list_
item
(
e
)))
}
MetaItemKind
::
NameValue
(
id
,
s
)
=>
MetaItemKind
::
NameValue
(
id
,
s
)
},
...
...
src/libsyntax/parse/attr.rs
浏览文件 @
8250a26b
...
...
@@ -193,9 +193,26 @@ pub fn parse_inner_attributes(&mut self) -> PResult<'a, Vec<ast::Attribute>> {
Ok
(
attrs
)
}
/// matches meta_item = IDENT
/// | IDENT = lit
/// | IDENT meta_seq
fn
parse_unsuffixed_lit
(
&
mut
self
)
->
PResult
<
'a
,
ast
::
Lit
>
{
let
lit
=
self
.parse_lit
()
?
;
debug!
(
"Checking if {:?} is unusuffixed."
,
lit
);
if
!
lit
.node
.is_unsuffixed
()
{
let
msg
=
"suffixed literals are not allowed in attributes"
;
self
.diagnostic
()
.struct_span_err
(
lit
.span
,
msg
)
.help
(
"instead of using a suffixed literal
\
(1u8, 1.0f32, etc.), use an unsuffixed version
\
(1, 1.0, etc.)."
)
.emit
()
}
Ok
(
lit
)
}
/// Per RFC#1559, matches the following grammar:
///
/// meta_item : IDENT ( '=' UNSUFFIXED_LIT | '(' meta_item_inner? ')' )? ;
/// meta_item_inner : (meta_item | UNSUFFIXED_LIT) (',' meta_item_inner)? ;
pub
fn
parse_meta_item
(
&
mut
self
)
->
PResult
<
'a
,
P
<
ast
::
MetaItem
>>
{
let
nt_meta
=
match
self
.token
{
token
::
Interpolated
(
token
::
NtMeta
(
ref
e
))
=>
Some
(
e
.clone
()),
...
...
@@ -213,16 +230,7 @@ pub fn parse_meta_item(&mut self) -> PResult<'a, P<ast::MetaItem>> {
match
self
.token
{
token
::
Eq
=>
{
self
.bump
();
let
lit
=
self
.parse_lit
()
?
;
// FIXME #623 Non-string meta items are not serialized correctly;
// just forbid them for now
match
lit
.node
{
ast
::
LitKind
::
Str
(
..
)
=>
{}
_
=>
{
self
.span_err
(
lit
.span
,
"non-string literals are not allowed in meta-items"
);
}
}
let
lit
=
self
.parse_unsuffixed_lit
()
?
;
let
hi
=
self
.span.hi
;
Ok
(
P
(
spanned
(
lo
,
hi
,
ast
::
MetaItemKind
::
NameValue
(
name
,
lit
))))
}
...
...
@@ -238,11 +246,35 @@ pub fn parse_meta_item(&mut self) -> PResult<'a, P<ast::MetaItem>> {
}
}
/// matches meta_seq = ( COMMASEP(meta_item) )
fn
parse_meta_seq
(
&
mut
self
)
->
PResult
<
'a
,
Vec
<
P
<
ast
::
MetaItem
>>>
{
/// matches meta_item_inner : (meta_item | UNSUFFIXED_LIT) ;
fn
parse_meta_item_inner
(
&
mut
self
)
->
PResult
<
'a
,
ast
::
NestedMetaItem
>
{
let
sp
=
self
.span
;
let
lo
=
self
.span.lo
;
match
self
.parse_unsuffixed_lit
()
{
Ok
(
lit
)
=>
{
return
Ok
(
spanned
(
lo
,
self
.span.hi
,
ast
::
NestedMetaItemKind
::
Literal
(
lit
)))
}
Err
(
ref
mut
err
)
=>
self
.diagnostic
()
.cancel
(
err
)
}
match
self
.parse_meta_item
()
{
Ok
(
mi
)
=>
{
return
Ok
(
spanned
(
lo
,
self
.span.hi
,
ast
::
NestedMetaItemKind
::
MetaItem
(
mi
)))
}
Err
(
ref
mut
err
)
=>
self
.diagnostic
()
.cancel
(
err
)
}
let
found
=
self
.this_token_to_string
();
let
msg
=
format!
(
"expected unsuffixed literal or identifier, found {}"
,
found
);
Err
(
self
.diagnostic
()
.struct_span_err
(
sp
,
&
msg
))
}
/// matches meta_seq = ( COMMASEP(meta_item_inner) )
fn
parse_meta_seq
(
&
mut
self
)
->
PResult
<
'a
,
Vec
<
ast
::
NestedMetaItem
>>
{
self
.parse_unspanned_seq
(
&
token
::
OpenDelim
(
token
::
Paren
),
&
token
::
CloseDelim
(
token
::
Paren
),
SeqSep
::
trailing_allowed
(
token
::
Comma
),
|
p
:
&
mut
Parser
<
'a
>
|
p
.parse_meta_item
())
|
p
:
&
mut
Parser
<
'a
>
|
p
.parse_meta_item
_inner
())
}
}
src/libsyntax/print/pprust.rs
浏览文件 @
8250a26b
...
...
@@ -120,7 +120,7 @@ pub fn print_crate<'a>(cm: &'a CodeMap,
// of the feature gate, so we fake them up here.
// #![feature(prelude_import)]
let
prelude_import_meta
=
attr
::
mk_word_item
(
InternedString
::
new
(
"prelude_import"
));
let
prelude_import_meta
=
attr
::
mk_
list_
word_item
(
InternedString
::
new
(
"prelude_import"
));
let
list
=
attr
::
mk_list_item
(
InternedString
::
new
(
"feature"
),
vec!
[
prelude_import_meta
]);
let
fake_attr
=
attr
::
mk_attr_inner
(
attr
::
mk_attr_id
(),
list
);
...
...
@@ -406,6 +406,10 @@ pub fn block_to_string(blk: &ast::Block) -> String {
})
}
pub
fn
meta_list_item_to_string
(
li
:
&
ast
::
NestedMetaItem
)
->
String
{
to_string
(|
s
|
s
.print_meta_list_item
(
li
))
}
pub
fn
meta_item_to_string
(
mi
:
&
ast
::
MetaItem
)
->
String
{
to_string
(|
s
|
s
.print_meta_item
(
mi
))
}
...
...
@@ -764,6 +768,17 @@ fn print_attribute_inline(&mut self, attr: &ast::Attribute,
}
}
fn
print_meta_list_item
(
&
mut
self
,
item
:
&
ast
::
NestedMetaItem
)
->
io
::
Result
<
()
>
{
match
item
.node
{
ast
::
NestedMetaItemKind
::
MetaItem
(
ref
mi
)
=>
{
self
.print_meta_item
(
mi
)
},
ast
::
NestedMetaItemKind
::
Literal
(
ref
lit
)
=>
{
self
.print_literal
(
lit
)
}
}
}
fn
print_meta_item
(
&
mut
self
,
item
:
&
ast
::
MetaItem
)
->
io
::
Result
<
()
>
{
try!
(
self
.ibox
(
INDENT_UNIT
));
match
item
.node
{
...
...
@@ -780,7 +795,7 @@ fn print_meta_item(&mut self, item: &ast::MetaItem) -> io::Result<()> {
try!
(
self
.popen
());
try!
(
self
.commasep
(
Consistent
,
&
items
[
..
],
|
s
,
i
|
s
.print_meta_item
(
&
i
)));
|
s
,
i
|
s
.print_meta_
list_
item
(
&
i
)));
try!
(
self
.pclose
());
}
}
...
...
src/libsyntax/test.rs
浏览文件 @
8250a26b
...
...
@@ -19,8 +19,7 @@
use
std
::
slice
;
use
std
::
mem
;
use
std
::
vec
;
use
attr
::
AttrMetaMethods
;
use
attr
;
use
attr
::{
self
,
AttrMetaMethods
,
AttrNestedMetaItemMethods
};
use
syntax_pos
::{
self
,
DUMMY_SP
,
NO_EXPANSION
,
Span
,
FileMap
,
BytePos
};
use
std
::
rc
::
Rc
;
...
...
@@ -210,9 +209,8 @@ fn fold_item(&mut self, i: P<ast::Item>) -> SmallVector<P<ast::Item>> {
folded
.map
(|
ast
::
Item
{
id
,
ident
,
attrs
,
node
,
vis
,
span
}|
{
let
allow_str
=
InternedString
::
new
(
"allow"
);
let
dead_code_str
=
InternedString
::
new
(
"dead_code"
);
let
allow_dead_code_item
=
attr
::
mk_list_item
(
allow_str
,
vec!
[
attr
::
mk_word_item
(
dead_code_str
)]);
let
word_vec
=
vec!
[
attr
::
mk_list_word_item
(
dead_code_str
)];
let
allow_dead_code_item
=
attr
::
mk_list_item
(
allow_str
,
word_vec
);
let
allow_dead_code
=
attr
::
mk_attr_outer
(
attr
::
mk_attr_id
(),
allow_dead_code_item
);
...
...
@@ -413,6 +411,7 @@ fn should_panic(i: &ast::Item) -> ShouldPanic {
Some
(
attr
)
=>
{
let
msg
=
attr
.meta_item_list
()
.and_then
(|
list
|
list
.iter
()
.find
(|
mi
|
mi
.check_name
(
"expected"
)))
.and_then
(|
li
|
li
.meta_item
())
.and_then
(|
mi
|
mi
.value_str
());
ShouldPanic
::
Yes
(
msg
)
}
...
...
src/libsyntax_ext/deriving/cmp/eq.rs
浏览文件 @
8250a26b
...
...
@@ -40,7 +40,7 @@ fn cs_total_eq_assert(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<
}
let
inline
=
cx
.meta_word
(
span
,
InternedString
::
new
(
"inline"
));
let
hidden
=
cx
.meta_word
(
span
,
InternedString
::
new
(
"hidden"
));
let
hidden
=
cx
.meta_
list_item_
word
(
span
,
InternedString
::
new
(
"hidden"
));
let
doc
=
cx
.meta_list
(
span
,
InternedString
::
new
(
"doc"
),
vec!
[
hidden
]);
let
attrs
=
vec!
[
cx
.attribute
(
span
,
inline
),
cx
.attribute
(
span
,
doc
)];
let
trait_def
=
TraitDef
{
...
...
src/libsyntax_ext/deriving/generic/mod.rs
浏览文件 @
8250a26b
...
...
@@ -623,7 +623,7 @@ fn create_derived_impl(&self,
let
unused_qual
=
cx
.attribute
(
self
.span
,
cx
.meta_list
(
self
.span
,
InternedString
::
new
(
"allow"
),
vec!
[
cx
.meta_word
(
self
.span
,
vec!
[
cx
.meta_
list_item_
word
(
self
.span
,
InternedString
::
new
(
"unused_qualifications"
))]));
let
mut
a
=
vec!
[
attr
,
unused_qual
];
a
.extend
(
self
.attributes
.iter
()
.cloned
());
...
...
src/libsyntax_ext/deriving/mod.rs
浏览文件 @
8250a26b
...
...
@@ -11,7 +11,7 @@
//! The compiler code necessary to implement the `#[derive]` extensions.
use
syntax
::
ast
::{
self
,
MetaItem
};
use
syntax
::
attr
::
AttrMetaMethods
;
use
syntax
::
attr
::
{
AttrNestedMetaItemMethods
,
AttrMetaMethods
}
;
use
syntax
::
ext
::
base
::{
Annotatable
,
ExtCtxt
,
SyntaxEnv
};
use
syntax
::
ext
::
base
::{
MultiDecorator
,
MultiItemDecorator
,
MultiModifier
};
use
syntax
::
ext
::
build
::
AstBuilder
;
...
...
@@ -98,8 +98,8 @@ fn expand_derive(cx: &mut ExtCtxt,
let
mut
eq_span
=
None
;
for
titem
in
traits
.iter
()
.rev
()
{
let
tname
=
if
titem
.is_
word
()
{
titem
.name
()
let
tname
=
if
let
Some
(
word
)
=
titem
.
word
()
{
word
.name
()
}
else
{
cx
.span_err
(
titem
.span
,
"malformed `derive` entry"
);
continue
;
...
...
src/test/compile-fail-fulldeps/auxiliary/macro_crate_test.rs
浏览文件 @
8250a26b
...
...
@@ -17,7 +17,8 @@
extern
crate
rustc
;
extern
crate
rustc_plugin
;
use
syntax
::
ast
::{
self
,
Item
,
MetaItem
,
ImplItem
,
TraitItem
,
ItemKind
};
use
syntax
::
ast
::{
self
,
Item
,
MetaItem
,
ItemKind
};
use
syntax
::
attr
::{
AttrMetaMethods
,
AttrNestedMetaItemMethods
};
use
syntax
::
ext
::
base
::
*
;
use
syntax
::
parse
::{
self
,
token
};
use
syntax
::
ptr
::
P
;
...
...
@@ -62,8 +63,8 @@ fn expand_identity(cx: &mut ExtCtxt, _span: Span, tts: &[TokenTree])
}
fn
expand_into_foo_multi
(
cx
:
&
mut
ExtCtxt
,
sp
:
Span
,
attr
:
&
MetaItem
,
_
sp
:
Span
,
_
attr
:
&
MetaItem
,
it
:
Annotatable
)
->
Annotatable
{
match
it
{
Annotatable
::
Item
(
it
)
=>
{
...
...
@@ -72,7 +73,7 @@ fn expand_into_foo_multi(cx: &mut ExtCtxt,
..
(
*
quote_item!
(
cx
,
enum
Foo2
{
Bar2
,
Baz2
})
.unwrap
())
.clone
()
}))
}
Annotatable
::
ImplItem
(
it
)
=>
{
Annotatable
::
ImplItem
(
_
)
=>
{
quote_item!
(
cx
,
impl
X
{
fn
foo
(
&
self
)
->
i32
{
42
}
})
.unwrap
()
.and_then
(|
i
|
{
match
i
.node
{
ItemKind
::
Impl
(
_
,
_
,
_
,
_
,
_
,
mut
items
)
=>
{
...
...
@@ -82,7 +83,7 @@ fn expand_into_foo_multi(cx: &mut ExtCtxt,
}
})
}
Annotatable
::
TraitItem
(
it
)
=>
{
Annotatable
::
TraitItem
(
_
)
=>
{
quote_item!
(
cx
,
trait
X
{
fn
foo
(
&
self
)
->
i32
{
0
}
})
.unwrap
()
.and_then
(|
i
|
{
match
i
.node
{
ItemKind
::
Trait
(
_
,
_
,
_
,
mut
items
)
=>
{
...
...
@@ -97,15 +98,15 @@ fn expand_into_foo_multi(cx: &mut ExtCtxt,
// Create a duplicate of the annotatable, based on the MetaItem
fn
expand_duplicate
(
cx
:
&
mut
ExtCtxt
,
sp
:
Span
,
_
sp
:
Span
,
mi
:
&
MetaItem
,
it
:
&
Annotatable
,
push
:
&
mut
FnMut
(
Annotatable
))
{
let
copy_name
=
match
mi
.node
{
ast
::
MetaItemKind
::
List
(
_
,
ref
xs
)
=>
{
if
let
ast
::
MetaItemKind
::
Word
(
ref
w
)
=
xs
[
0
]
.node
{
token
::
str_to_ident
(
&
w
)
if
let
Some
(
word
)
=
xs
[
0
]
.word
()
{
token
::
str_to_ident
(
&
w
ord
.name
()
)
}
else
{
cx
.span_err
(
mi
.span
,
"Expected word"
);
return
;
...
...
src/test/compile-fail/E0565-1.rs
0 → 100644
浏览文件 @
8250a26b
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(attr_literals)]
// deprecated doesn't currently support literals
#[deprecated(
"since"
)]
//~ ERROR E0565
fn
f
()
{
}
fn
main
()
{
}
src/test/compile-fail/E0565.rs
0 → 100644
浏览文件 @
8250a26b
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(attr_literals)]
// repr currently doesn't support literals
#[repr(
"C"
)]
//~ ERROR E0565
struct
A
{
}
fn
main
()
{
}
src/test/compile-fail/attr-literals.rs
0 → 100644
浏览文件 @
8250a26b
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Check that literals in attributes parse just fine.
#![feature(rustc_attrs,
attr_literals)]
#![allow(dead_code)]
#![allow(unused_variables)]
#[fake_attr]
//~ ERROR attribute `fake_attr` is currently unknown
#[fake_attr(
100
)]
//~ ERROR attribute `fake_attr` is currently unknown
#[fake_attr(
1
,
2
,
3
)]
//~ ERROR attribute `fake_attr` is currently unknown
#[fake_attr(
"hello"
)]
//~ ERROR attribute `fake_attr` is currently unknown
#[fake_attr(name
=
"hello"
)]
//~ ERROR attribute `fake_attr` is currently unknown
#[fake_attr(
1
,
"hi"
,
key
=
12
,
true
,
false
)]
//~ ERROR attribute `fake_attr` is currently unknown
#[fake_attr(key
=
"hello"
,
val
=
10
)]
//~ ERROR attribute `fake_attr` is currently unknown
#[fake_attr(key(
"hello"
),
val(
10
))]
//~ ERROR attribute `fake_attr` is currently unknown
#[fake_attr(enabled
=
true
,
disabled
=
false
)]
//~ ERROR attribute `fake_attr` is currently unknown
#[fake_attr(
true
)]
//~ ERROR attribute `fake_attr` is currently unknown
#[fake_attr(pi
=
3.14159
)]
//~ ERROR attribute `fake_attr` is currently unknown
#[fake_attr(b
"hi"
)]
//~ ERROR attribute `fake_attr` is currently unknown
#[fake_doc(
r"doc"
)]
//~ ERROR attribute `fake_doc` is currently unknown
struct
Q
{
}
#[rustc_error]
fn
main
()
{
}
src/test/compile-fail/gated-attr-literals.rs
0 → 100644
浏览文件 @
8250a26b
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Check that literals in attributes don't parse without the feature gate.
#![feature(rustc_attrs)]
#![allow(dead_code)]
#![allow(unused_variables)]
#[fake_attr]
//~ ERROR attribute `fake_attr` is currently unknown
#[fake_attr(
100
)]
//~ ERROR attribute `fake_attr` is currently unknown
//~^ ERROR non-string literals in attributes
#[fake_attr(
1
,
2
,
3
)]
//~ ERROR attribute `fake_attr` is currently unknown
//~^ ERROR non-string literals in attributes
#[fake_attr(
"hello"
)]
//~ ERROR attribute `fake_attr` is currently unknown
//~^ ERROR string literals in top-level positions, are experimental
#[fake_attr(name
=
"hello"
)]
//~ ERROR attribute `fake_attr` is currently unknown
#[fake_attr(
1
,
"hi"
,
key
=
12
,
true
,
false
)]
//~ ERROR attribute `fake_attr` is currently unknown
//~^ ERROR non-string literals in attributes, or string literals in top-level positions
#[fake_attr(key
=
"hello"
,
val
=
10
)]
//~ ERROR attribute `fake_attr` is currently unknown
//~^ ERROR non-string literals in attributes
#[fake_attr(key(
"hello"
),
val(
10
))]
//~ ERROR attribute `fake_attr` is currently unknown
//~^ ERROR non-string literals in attributes, or string literals in top-level positions
#[fake_attr(enabled
=
true
,
disabled
=
false
)]
//~ ERROR attribute `fake_attr` is currently unknown
//~^ ERROR non-string literals in attributes
#[fake_attr(
true
)]
//~ ERROR attribute `fake_attr` is currently unknown
//~^ ERROR non-string literals in attributes
#[fake_attr(pi
=
3.14159
)]
//~ ERROR attribute `fake_attr` is currently unknown
//~^ ERROR non-string literals in attributes
#[fake_attr(b
"hi"
)]
//~ ERROR attribute `fake_attr` is currently unknown
//~^ ERROR string literals in top-level positions, are experimental
#[fake_doc(
r"doc"
)]
//~ ERROR attribute `fake_doc` is currently unknown
//~^ ERROR string literals in top-level positions, are experimental
struct
Q
{
}
#[rustc_error]
fn
main
()
{
}
src/test/parse-fail/suffixed-literal-meta.rs
0 → 100644
浏览文件 @
8250a26b
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// compile-flags: -Z parse-only
#[foo
=
1u
size]
//~ ERROR: suffixed literals are not allowed in attributes
#[foo
=
1u8
]
//~ ERROR: suffixed literals are not allowed in attributes
#[foo
=
1u16
]
//~ ERROR: suffixed literals are not allowed in attributes
#[foo
=
1u32
]
//~ ERROR: suffixed literals are not allowed in attributes
#[foo
=
1u64
]
//~ ERROR: suffixed literals are not allowed in attributes
#[foo
=
1
isize]
//~ ERROR: suffixed literals are not allowed in attributes
#[foo
=
1i8
]
//~ ERROR: suffixed literals are not allowed in attributes
#[foo
=
1i16
]
//~ ERROR: suffixed literals are not allowed in attributes
#[foo
=
1i32
]
//~ ERROR: suffixed literals are not allowed in attributes
#[foo
=
1i64
]
//~ ERROR: suffixed literals are not allowed in attributes
#[foo
=
1.0f32
]
//~ ERROR: suffixed literals are not allowed in attributes
#[foo
=
1.0f64
]
//~ ERROR: suffixed literals are not allowed in attributes
fn
main
()
{
}
src/test/p
arse-fail/non-str-meta
.rs
→
src/test/p
retty/attr-literals
.rs
浏览文件 @
8250a26b
...
...
@@ -8,10 +8,16 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// compile-flags: -Z parse-only
// pp-exact
// Tests literals in attributes.
// Issue #623 - non-string meta items are not serialized correctly;
// for now just forbid them
#![feature(custom_attribute,
attr_literals)]
#[foo
=
1
]
//~ ERROR: non-string literals are not allowed in meta-items
fn
main
()
{
}
fn
main
()
{
#![hello(
"hi"
,
1
,
2
,
1.012
,
pi
=
3.14
,
bye,
name(
"John"
))]
#[align
=
8
]
fn
f
()
{
}
#[vec(
1
,
2
,
3
)]
fn
g
()
{
}
}
src/test/run-pass-fulldeps/auxiliary/custom_derive_plugin.rs
浏览文件 @
8250a26b
...
...
@@ -24,7 +24,6 @@
use
syntax
::
ext
::
base
::{
MultiDecorator
,
ExtCtxt
,
Annotatable
};
use
syntax
::
ext
::
build
::
AstBuilder
;
use
syntax
::
parse
::
token
;
use
syntax
::
ptr
::
P
;
use
syntax_ext
::
deriving
::
generic
::{
cs_fold
,
TraitDef
,
MethodDef
,
combine_substructure
};
use
syntax_ext
::
deriving
::
generic
::
ty
::{
Literal
,
LifetimeBounds
,
Path
,
borrowed_explicit_self
};
use
syntax_pos
::
Span
;
...
...
src/test/run-pass-fulldeps/auxiliary/custom_derive_plugin_attr.rs
浏览文件 @
8250a26b
...
...
@@ -26,7 +26,7 @@
use
syntax
::
ext
::
build
::
AstBuilder
;
use
syntax
::
parse
::
token
;
use
syntax
::
ptr
::
P
;
use
syntax_ext
::
deriving
::
generic
::{
cs_fold
,
TraitDef
,
MethodDef
,
combine_substructure
};
use
syntax_ext
::
deriving
::
generic
::{
TraitDef
,
MethodDef
,
combine_substructure
};
use
syntax_ext
::
deriving
::
generic
::{
Substructure
,
Struct
,
EnumMatching
};
use
syntax_ext
::
deriving
::
generic
::
ty
::{
Literal
,
LifetimeBounds
,
Path
,
borrowed_explicit_self
};
use
syntax_pos
::
Span
;
...
...
src/test/run-pass-fulldeps/auxiliary/macro_crate_test.rs
浏览文件 @
8250a26b
...
...
@@ -17,8 +17,11 @@
extern
crate
rustc_plugin
;
extern
crate
syntax_pos
;
use
syntax
::
ast
::{
self
,
Item
,
MetaItem
,
ImplItem
,
TraitItem
,
ItemKind
};
use
syntax
::
ast
::{
self
,
Item
,
MetaItem
,
ItemKind
};
use
syntax
::
codemap
::
DUMMY_SP
;
use
syntax
::
attr
::{
AttrMetaMethods
,
AttrNestedMetaItemMethods
};
use
syntax
::
ext
::
base
::
*
;
use
syntax
::
ext
::
quote
::
rt
::
ToTokens
;
use
syntax
::
parse
::{
self
,
token
};
use
syntax
::
ptr
::
P
;
use
syntax
::
tokenstream
::
TokenTree
;
...
...
@@ -41,10 +44,13 @@ pub fn plugin_registrar(reg: &mut Registry) {
token
::
intern
(
"duplicate"
),
// FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
MultiDecorator
(
Box
::
new
(
expand_duplicate
)));
reg
.register_syntax_extension
(
token
::
intern
(
"caller"
),
// FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
MultiDecorator
(
Box
::
new
(
expand_caller
)));
}
fn
expand_make_a_1
(
cx
:
&
mut
ExtCtxt
,
sp
:
Span
,
tts
:
&
[
TokenTree
])
->
Box
<
MacResult
+
'static
>
{
fn
expand_make_a_1
(
cx
:
&
mut
ExtCtxt
,
sp
:
Span
,
tts
:
&
[
TokenTree
])
->
Box
<
MacResult
+
'static
>
{
if
!
tts
.is_empty
()
{
cx
.span_fatal
(
sp
,
"make_a_1 takes no arguments"
);
}
...
...
@@ -52,19 +58,18 @@ fn expand_make_a_1(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
}
// See Issue #15750
fn
expand_identity
(
cx
:
&
mut
ExtCtxt
,
_
span
:
Span
,
tts
:
&
[
TokenTree
])
->
Box
<
MacResult
+
'static
>
{
fn
expand_identity
(
cx
:
&
mut
ExtCtxt
,
_
span
:
Span
,
tts
:
&
[
TokenTree
])
->
Box
<
MacResult
+
'static
>
{
// Parse an expression and emit it unchanged.
let
mut
parser
=
parse
::
new_parser_from_tts
(
cx
.parse_sess
(),
cx
.cfg
(),
tts
.to_vec
());
let
mut
parser
=
parse
::
new_parser_from_tts
(
cx
.parse_sess
(),
cx
.cfg
(),
tts
.to_vec
());
let
expr
=
parser
.parse_expr
()
.unwrap
();
MacEager
::
expr
(
quote_expr!
(
&
mut
*
cx
,
$
expr
))
}
fn
expand_into_foo_multi
(
cx
:
&
mut
ExtCtxt
,
sp
:
Span
,
attr
:
&
MetaItem
,
it
:
Annotatable
)
->
Vec
<
Annotatable
>
{
_
sp
:
Span
,
_
attr
:
&
MetaItem
,
it
:
Annotatable
)
->
Vec
<
Annotatable
>
{
match
it
{
Annotatable
::
Item
(
it
)
=>
vec!
[
Annotatable
::
Item
(
P
(
Item
{
...
...
@@ -74,7 +79,7 @@ fn expand_into_foo_multi(cx: &mut ExtCtxt,
Annotatable
::
Item
(
quote_item!
(
cx
,
enum
Foo3
{
Bar
})
.unwrap
()),
Annotatable
::
Item
(
quote_item!
(
cx
,
#[cfg(any())]
fn
foo2
()
{})
.unwrap
()),
],
Annotatable
::
ImplItem
(
it
)
=>
vec!
[
Annotatable
::
ImplItem
(
_
it
)
=>
vec!
[
quote_item!
(
cx
,
impl
X
{
fn
foo
(
&
self
)
->
i32
{
42
}
})
.unwrap
()
.and_then
(|
i
|
{
match
i
.node
{
ItemKind
::
Impl
(
_
,
_
,
_
,
_
,
_
,
mut
items
)
=>
{
...
...
@@ -84,7 +89,7 @@ fn expand_into_foo_multi(cx: &mut ExtCtxt,
}
})
],
Annotatable
::
TraitItem
(
it
)
=>
vec!
[
Annotatable
::
TraitItem
(
_
it
)
=>
vec!
[
quote_item!
(
cx
,
trait
X
{
fn
foo
(
&
self
)
->
i32
{
0
}
})
.unwrap
()
.and_then
(|
i
|
{
match
i
.node
{
ItemKind
::
Trait
(
_
,
_
,
_
,
mut
items
)
=>
{
...
...
@@ -99,15 +104,14 @@ fn expand_into_foo_multi(cx: &mut ExtCtxt,
// Create a duplicate of the annotatable, based on the MetaItem
fn
expand_duplicate
(
cx
:
&
mut
ExtCtxt
,
sp
:
Span
,
_
sp
:
Span
,
mi
:
&
MetaItem
,
it
:
&
Annotatable
,
push
:
&
mut
FnMut
(
Annotatable
))
{
push
:
&
mut
FnMut
(
Annotatable
))
{
let
copy_name
=
match
mi
.node
{
ast
::
MetaItemKind
::
List
(
_
,
ref
xs
)
=>
{
if
let
ast
::
MetaItemKind
::
Word
(
ref
w
)
=
xs
[
0
]
.node
{
token
::
str_to_ident
(
&
w
)
if
let
Some
(
word
)
=
xs
[
0
]
.word
()
{
token
::
str_to_ident
(
&
w
ord
.name
()
)
}
else
{
cx
.span_err
(
mi
.span
,
"Expected word"
);
return
;
...
...
@@ -142,4 +146,69 @@ fn expand_duplicate(cx: &mut ExtCtxt,
}
}
pub
fn
token_separate
<
T
:
ToTokens
>
(
ecx
:
&
ExtCtxt
,
things
:
&
[
T
],
token
:
token
::
Token
)
->
Vec
<
TokenTree
>
{
let
mut
output
:
Vec
<
TokenTree
>
=
vec!
[];
for
(
i
,
thing
)
in
things
.iter
()
.enumerate
()
{
output
.extend
(
thing
.to_tokens
(
ecx
));
if
i
<
things
.len
()
-
1
{
output
.push
(
TokenTree
::
Token
(
DUMMY_SP
,
token
.clone
()));
}
}
output
}
fn
expand_caller
(
cx
:
&
mut
ExtCtxt
,
sp
:
Span
,
mi
:
&
MetaItem
,
it
:
&
Annotatable
,
push
:
&
mut
FnMut
(
Annotatable
))
{
let
(
orig_fn_name
,
ret_type
)
=
match
*
it
{
Annotatable
::
Item
(
ref
item
)
=>
match
item
.node
{
ItemKind
::
Fn
(
ref
decl
,
_
,
_
,
_
,
_
,
_
)
=>
{
(
item
.ident
,
&
decl
.output
)
}
_
=>
cx
.span_fatal
(
item
.span
,
"Only functions with return types can be annotated."
)
},
_
=>
cx
.span_fatal
(
sp
,
"Only functions can be annotated."
)
};
let
(
caller_name
,
arguments
)
=
if
let
Some
(
list
)
=
mi
.meta_item_list
()
{
if
list
.len
()
<
2
{
cx
.span_fatal
(
mi
.span
(),
"Need a function name and at least one parameter."
);
}
let
fn_name
=
match
list
[
0
]
.name
()
{
Some
(
name
)
=>
token
::
str_to_ident
(
&
name
),
None
=>
cx
.span_fatal
(
list
[
0
]
.span
(),
"First parameter must be an ident."
)
};
(
fn_name
,
&
list
[
1
..
])
}
else
{
cx
.span_fatal
(
mi
.span
,
"Expected list."
);
};
let
literals
:
Vec
<
ast
::
Lit
>
=
arguments
.iter
()
.map
(|
arg
|
{
if
let
Some
(
lit
)
=
arg
.literal
()
{
lit
.clone
()
}
else
{
cx
.span_fatal
(
arg
.span
(),
"Expected literal."
);
}
})
.collect
();
let
arguments
=
token_separate
(
cx
,
literals
.as_slice
(),
token
::
Comma
);
if
let
ast
::
FunctionRetTy
::
Ty
(
ref
rt
)
=
*
ret_type
{
push
(
Annotatable
::
Item
(
quote_item!
(
cx
,
fn
$
caller_name
()
->
$
rt
{
$
orig_fn_name
(
$
arguments
)
})
.unwrap
()))
}
else
{
push
(
Annotatable
::
Item
(
quote_item!
(
cx
,
fn
$
caller_name
()
{
$
orig_fn_name
(
$
arguments
)
})
.unwrap
()))
}
}
pub
fn
foo
()
{}
src/test/run-pass-fulldeps/auxiliary/plugin_args.rs
浏览文件 @
8250a26b
...
...
@@ -30,7 +30,7 @@
use
rustc_plugin
::
Registry
;
struct
Expander
{
args
:
Vec
<
P
<
ast
::
MetaItem
>
>
,
args
:
Vec
<
ast
::
NestedMetaItem
>
,
}
impl
TTMacroExpander
for
Expander
{
...
...
@@ -38,7 +38,7 @@ fn expand<'cx>(&self,
ecx
:
&
'cx
mut
ExtCtxt
,
sp
:
Span
,
_
:
&
[
tokenstream
::
TokenTree
])
->
Box
<
MacResult
+
'cx
>
{
let
args
=
self
.args
.iter
()
.map
(|
i
|
pprust
::
meta_
item_to_string
(
&*
i
))
let
args
=
self
.args
.iter
()
.map
(|
i
|
pprust
::
meta_
list_item_to_string
(
i
))
.collect
::
<
Vec
<
_
>>
()
.join
(
", "
);
let
interned
=
token
::
intern_and_get_ident
(
&
args
[
..
]);
MacEager
::
expr
(
ecx
.expr_str
(
sp
,
interned
))
...
...
src/test/run-pass-fulldeps/macro-crate-multi-decorator-literals.rs
0 → 100644
浏览文件 @
8250a26b
// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// aux-build:macro_crate_test.rs
// ignore-stage1
#![feature(plugin,
custom_attribute,
attr_literals)]
#![plugin(macro_crate_test)]
#[macro_use]
#[no_link]
extern
crate
macro_crate_test
;
// The `caller(name, args...)` attribute emits a new nullary function named
// `name` that calls the annotated function with `args`. As an example, consider
// the following:
//
// #[caller(simple, 1, "hello", 3.14)]
// fn f(num: isize, string: &'static str, float: f32) -> (isize, &'static str, float) {
// (num, string, float)
// }
//
// This results in a function named `simple` that calls `f(1, "hello", 3.14)`.
// As a result, the expression `simple()` evaluates to `(1, "helllo", 3.14)`.
#[caller(simple,
1
,
"hello"
,
3.14
)]
#[caller(simple1,
2
,
"bye"
,
6.28
)]
#[caller(simple2,
3
,
"hi"
,
1.01
)]
fn
f
(
num
:
isize
,
string
:
&
'static
str
,
float
:
f32
)
->
(
isize
,
&
'static
str
,
f32
)
{
(
num
,
string
,
float
)
}
#[caller(complex,
true
,
10
)]
#[caller(complex1,
false
,
15
)]
#[caller(complex2,
true
,
20
)]
fn
g
(
emit
:
bool
,
num
:
i32
)
->
Option
<
i32
>
{
match
emit
{
true
=>
Some
(
num
),
false
=>
None
}
}
fn
main
()
{
assert_eq!
(
simple
(),
(
1
,
"hello"
,
3.14
));
assert_eq!
(
simple1
(),
(
2
,
"bye"
,
6.28
));
assert_eq!
(
simple2
(),
(
3
,
"hi"
,
1.01
));
assert_eq!
(
complex
(),
Some
(
10
));
assert_eq!
(
complex1
(),
None
);
assert_eq!
(
complex2
(),
Some
(
20
));
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录