Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
cbc9f683
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,发现更多精彩内容 >>
提交
cbc9f683
编写于
12月 05, 2019
作者:
M
Mazdak Farrokhzad
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
derive: avoid parse_in_attr
上级
bbcda98d
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
90 addition
and
80 deletion
+90
-80
src/librustc_parse/lib.rs
src/librustc_parse/lib.rs
+1
-1
src/librustc_parse/parser/path.rs
src/librustc_parse/parser/path.rs
+0
-37
src/libsyntax_expand/proc_macro.rs
src/libsyntax_expand/proc_macro.rs
+62
-25
src/test/ui/malformed/malformed-derive-entry.rs
src/test/ui/malformed/malformed-derive-entry.rs
+6
-2
src/test/ui/malformed/malformed-derive-entry.stderr
src/test/ui/malformed/malformed-derive-entry.stderr
+20
-7
src/test/ui/span/macro-ty-params.rs
src/test/ui/span/macro-ty-params.rs
+0
-1
src/test/ui/span/macro-ty-params.stderr
src/test/ui/span/macro-ty-params.stderr
+1
-7
未找到文件。
src/librustc_parse/lib.rs
浏览文件 @
cbc9f683
...
...
@@ -285,7 +285,7 @@ pub fn parse_in<'a, T>(
}
/// Runs the given subparser `f` on the tokens of the given `attr`'s item.
pub
fn
parse_in_attr
<
'a
,
T
>
(
fn
parse_in_attr
<
'a
,
T
>
(
sess
:
&
'a
ParseSess
,
attr
:
&
ast
::
Attribute
,
f
:
impl
FnMut
(
&
mut
Parser
<
'a
>
)
->
PResult
<
'a
,
T
>
,
...
...
src/librustc_parse/parser/path.rs
浏览文件 @
cbc9f683
...
...
@@ -3,7 +3,6 @@
use
rustc_errors
::{
PResult
,
Applicability
,
pluralize
};
use
syntax
::
ast
::{
self
,
QSelf
,
Path
,
PathSegment
,
Ident
,
ParenthesizedArgs
,
AngleBracketedArgs
};
use
syntax
::
ast
::{
AnonConst
,
GenericArg
,
AssocTyConstraint
,
AssocTyConstraintKind
,
BlockCheckMode
};
use
syntax
::
ast
::
MacArgs
;
use
syntax
::
ThinVec
;
use
syntax
::
token
::{
self
,
Token
};
use
syntax_pos
::
source_map
::{
Span
,
BytePos
};
...
...
@@ -109,42 +108,6 @@ pub fn parse_path(&mut self, style: PathStyle) -> PResult<'a, Path> {
Ok
(
Path
{
segments
,
span
:
lo
.to
(
self
.prev_span
)
})
}
/// Like `parse_path`, but also supports parsing `Word` meta items into paths for
/// backwards-compatibility. This is used when parsing derive macro paths in `#[derive]`
/// attributes.
fn
parse_path_allowing_meta
(
&
mut
self
,
style
:
PathStyle
)
->
PResult
<
'a
,
Path
>
{
let
meta_ident
=
match
self
.token.kind
{
token
::
Interpolated
(
ref
nt
)
=>
match
**
nt
{
token
::
NtMeta
(
ref
item
)
=>
match
item
.args
{
MacArgs
::
Empty
=>
Some
(
item
.path
.clone
()),
_
=>
None
,
},
_
=>
None
,
},
_
=>
None
,
};
if
let
Some
(
path
)
=
meta_ident
{
self
.bump
();
return
Ok
(
path
);
}
self
.parse_path
(
style
)
}
/// Parse a list of paths inside `#[derive(path_0, ..., path_n)]`.
pub
fn
parse_derive_paths
(
&
mut
self
)
->
PResult
<
'a
,
Vec
<
Path
>>
{
self
.expect
(
&
token
::
OpenDelim
(
token
::
Paren
))
?
;
let
mut
list
=
Vec
::
new
();
while
!
self
.eat
(
&
token
::
CloseDelim
(
token
::
Paren
))
{
let
path
=
self
.parse_path_allowing_meta
(
PathStyle
::
Mod
)
?
;
list
.push
(
path
);
if
!
self
.eat
(
&
token
::
Comma
)
{
self
.expect
(
&
token
::
CloseDelim
(
token
::
Paren
))
?
;
break
}
}
Ok
(
list
)
}
pub
(
super
)
fn
parse_path_segments
(
&
mut
self
,
segments
:
&
mut
Vec
<
PathSegment
>
,
...
...
src/libsyntax_expand/proc_macro.rs
浏览文件 @
cbc9f683
use
crate
::
base
::{
self
,
*
};
use
crate
::
proc_macro_server
;
use
syntax
::
ast
::{
self
,
ItemKind
,
M
acArgs
};
use
syntax
::
ast
::{
self
,
ItemKind
,
M
etaItemKind
,
NestedMetaItem
};
use
syntax
::
errors
::{
Applicability
,
FatalError
};
use
syntax
::
symbol
::
sym
;
use
syntax
::
token
;
...
...
@@ -171,34 +171,71 @@ fn expand(&self,
if
!
attr
.has_name
(
sym
::
derive
)
{
return
true
;
}
if
!
attr
.is_meta_item_list
()
{
cx
.struct_span_err
(
attr
.span
,
"malformed `derive` attribute input"
)
.span_suggestion
(
attr
.span
,
"missing traits to be derived"
,
"#[derive(Trait1, Trait2, ...)]"
.to_owned
(),
Applicability
::
HasPlaceholders
,
)
.emit
();
return
false
;
}
let
parse_derive_paths
=
|
attr
:
&
ast
::
Attribute
|
{
if
let
MacArgs
::
Empty
=
attr
.get_normal_item
()
.args
{
return
Ok
(
Vec
::
new
());
// 1) First let's ensure that it's a meta item.
let
nmis
=
match
attr
.meta_item_list
()
{
None
=>
{
cx
.struct_span_err
(
attr
.span
,
"malformed `derive` attribute input"
)
.span_suggestion
(
attr
.span
,
"missing traits to be derived"
,
"#[derive(Trait1, Trait2, ...)]"
.to_owned
(),
Applicability
::
HasPlaceholders
,
)
.emit
();
return
false
;
}
rustc_parse
::
parse_in_attr
(
cx
.parse_sess
,
attr
,
|
p
|
p
.parse_derive_paths
())
Some
(
x
)
=>
x
,
};
match
parse_derive_paths
(
attr
)
{
Ok
(
traits
)
=>
{
result
.extend
(
traits
);
true
}
Err
(
mut
e
)
=>
{
e
.emit
();
false
}
}
let
mut
retain_in_fm
=
true
;
let
mut
retain_in_map
=
true
;
let
traits
=
nmis
.into_iter
()
// 2) Moreover, let's ensure we have a path and not `#[derive("foo")]`.
.filter_map
(|
nmi
|
match
nmi
{
NestedMetaItem
::
Literal
(
lit
)
=>
{
retain_in_fm
=
false
;
cx
.struct_span_err
(
lit
.span
,
"expected path to a trait, found literal"
)
.help
(
"for example, write `#[derive(Debug)]` for `Debug`"
)
.emit
();
None
}
NestedMetaItem
::
MetaItem
(
mi
)
=>
Some
(
mi
),
})
// 3) Finally, we only accept `#[derive($path_0, $path_1, ..)]`
// but not e.g. `#[derive($path_0 = "value", $path_1(abc))]`.
// In this case we can still at least determine that the user
// wanted this trait to be derived, so let's keep it.
.map
(|
mi
|
{
let
mut
traits_dont_accept
=
|
title
,
action
|
{
retain_in_map
=
false
;
let
sp
=
mi
.span
.with_lo
(
mi
.path.span
.hi
());
cx
.struct_span_err
(
sp
,
title
)
.span_suggestion
(
sp
,
action
,
String
::
new
(),
Applicability
::
MachineApplicable
,
)
.emit
();
};
match
&
mi
.kind
{
MetaItemKind
::
List
(
..
)
=>
traits_dont_accept
(
"traits in `#[derive(...)]` don't accept arguments"
,
"remove the arguments"
,
),
MetaItemKind
::
NameValue
(
..
)
=>
traits_dont_accept
(
"traits in `#[derive(...)]` don't accept values"
,
"remove the value"
,
),
MetaItemKind
::
Word
=>
{}
}
mi
.path
});
result
.extend
(
traits
);
retain_in_fm
&&
retain_in_map
});
result
}
src/test/ui/malformed/malformed-derive-entry.rs
浏览文件 @
cbc9f683
#[derive(Copy(Bad))]
//~ ERROR expected one of `)`, `,`, or `::`, found `(`
#[derive(Copy(Bad))]
//~^ ERROR traits in `#[derive(...)]` don't accept arguments
//~| ERROR the trait bound
struct
Test1
;
#[derive(Copy=
"bad"
)]
//~ ERROR expected one of `)`, `,`, or `::`, found `=`
#[derive(Copy=
"bad"
)]
//~^ ERROR traits in `#[derive(...)]` don't accept values
//~| ERROR the trait bound
struct
Test2
;
#[derive]
//~ ERROR malformed `derive` attribute input
...
...
src/test/ui/malformed/malformed-derive-entry.stderr
浏览文件 @
cbc9f683
error:
expected one of `)`, `,`, or `::`, found `(`
error:
traits in `#[derive(...)]` don't accept arguments
--> $DIR/malformed-derive-entry.rs:1:14
|
LL | #[derive(Copy(Bad))]
| ^
expected one of `)`, `,`, or `::`
| ^
^^^^ help: remove the arguments
error:
expected one of `)`, `,`, or `::`, found `=`
--> $DIR/malformed-derive-entry.rs:
4
:14
error:
traits in `#[derive(...)]` don't accept values
--> $DIR/malformed-derive-entry.rs:
6
:14
|
LL | #[derive(Copy="bad")]
| ^
expected one of `)`, `,`, or `::`
| ^
^^^^^ help: remove the value
error: malformed `derive` attribute input
--> $DIR/malformed-derive-entry.rs:
7
:1
--> $DIR/malformed-derive-entry.rs:
11
:1
|
LL | #[derive]
| ^^^^^^^^^ help: missing traits to be derived: `#[derive(Trait1, Trait2, ...)]`
error: aborting due to 3 previous errors
error[E0277]: the trait bound `Test1: std::clone::Clone` is not satisfied
--> $DIR/malformed-derive-entry.rs:1:10
|
LL | #[derive(Copy(Bad))]
| ^^^^ the trait `std::clone::Clone` is not implemented for `Test1`
error[E0277]: the trait bound `Test2: std::clone::Clone` is not satisfied
--> $DIR/malformed-derive-entry.rs:6:10
|
LL | #[derive(Copy="bad")]
| ^^^^ the trait `std::clone::Clone` is not implemented for `Test2`
error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0277`.
src/test/ui/span/macro-ty-params.rs
浏览文件 @
cbc9f683
...
...
@@ -10,5 +10,4 @@ fn main() {
foo
::
<
T
>!
();
//~ ERROR generic arguments in macro path
foo
::
<>!
();
//~ ERROR generic arguments in macro path
m!
(
Default
<>
);
//~ ERROR generic arguments in macro path
//~^ ERROR unexpected generic arguments in path
}
src/test/ui/span/macro-ty-params.stderr
浏览文件 @
cbc9f683
...
...
@@ -10,17 +10,11 @@ error: generic arguments in macro path
LL | foo::<>!();
| ^^
error: unexpected generic arguments in path
--> $DIR/macro-ty-params.rs:12:8
|
LL | m!(Default<>);
| ^^^^^^^^^
error: generic arguments in macro path
--> $DIR/macro-ty-params.rs:12:15
|
LL | m!(Default<>);
| ^^
error: aborting due to
4
previous errors
error: aborting due to
3
previous errors
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录