Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
21fdd549
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,发现更多精彩内容 >>
提交
21fdd549
编写于
5月 01, 2022
作者:
T
threadexception
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Improves parser diagnostics, fixes #93867
上级
d201c812
变更
22
隐藏空白更改
内联
并排
Showing
22 changed file
with
135 addition
and
33 deletion
+135
-33
compiler/rustc_parse/src/parser/diagnostics.rs
compiler/rustc_parse/src/parser/diagnostics.rs
+30
-0
compiler/rustc_parse/src/parser/expr.rs
compiler/rustc_parse/src/parser/expr.rs
+22
-4
compiler/rustc_parse/src/parser/mod.rs
compiler/rustc_parse/src/parser/mod.rs
+16
-0
compiler/rustc_parse/src/parser/path.rs
compiler/rustc_parse/src/parser/path.rs
+16
-4
compiler/rustc_parse/src/parser/stmt.rs
compiler/rustc_parse/src/parser/stmt.rs
+4
-1
src/test/ui/parser/can-begin-expr-check.rs
src/test/ui/parser/can-begin-expr-check.rs
+1
-1
src/test/ui/parser/can-begin-expr-check.stderr
src/test/ui/parser/can-begin-expr-check.stderr
+2
-2
src/test/ui/parser/duplicate-visibility.rs
src/test/ui/parser/duplicate-visibility.rs
+2
-2
src/test/ui/parser/duplicate-visibility.stderr
src/test/ui/parser/duplicate-visibility.stderr
+2
-2
src/test/ui/parser/issues/issue-20616-2.rs
src/test/ui/parser/issues/issue-20616-2.rs
+1
-1
src/test/ui/parser/issues/issue-20616-2.stderr
src/test/ui/parser/issues/issue-20616-2.stderr
+2
-2
src/test/ui/parser/issues/issue-62660.rs
src/test/ui/parser/issues/issue-62660.rs
+1
-1
src/test/ui/parser/issues/issue-62660.stderr
src/test/ui/parser/issues/issue-62660.stderr
+2
-2
src/test/ui/parser/issues/issue-84117.rs
src/test/ui/parser/issues/issue-84117.rs
+1
-1
src/test/ui/parser/issues/issue-84117.stderr
src/test/ui/parser/issues/issue-84117.stderr
+2
-2
src/test/ui/parser/issues/issue-93282.stderr
src/test/ui/parser/issues/issue-93282.stderr
+2
-2
src/test/ui/parser/issues/issue-93867.rs
src/test/ui/parser/issues/issue-93867.rs
+10
-0
src/test/ui/parser/issues/issue-93867.stderr
src/test/ui/parser/issues/issue-93867.stderr
+13
-0
src/test/ui/parser/lifetime-semicolon.fixed
src/test/ui/parser/lifetime-semicolon.fixed
+1
-1
src/test/ui/parser/lifetime-semicolon.rs
src/test/ui/parser/lifetime-semicolon.rs
+1
-1
src/test/ui/parser/lifetime-semicolon.stderr
src/test/ui/parser/lifetime-semicolon.stderr
+2
-2
src/test/ui/parser/require-parens-for-chained-comparison.stderr
...st/ui/parser/require-parens-for-chained-comparison.stderr
+2
-2
未找到文件。
compiler/rustc_parse/src/parser/diagnostics.rs
浏览文件 @
21fdd549
...
...
@@ -29,6 +29,7 @@
use
std
::
mem
::
take
;
use
crate
::
parser
;
use
tracing
::{
debug
,
trace
};
const
TURBOFISH_SUGGESTION_STR
:
&
str
=
...
...
@@ -400,6 +401,35 @@ fn tokens_to_string(tokens: &[TokenType]) -> String {
.map
(|
x
|
TokenType
::
Token
(
x
.clone
()))
.chain
(
inedible
.iter
()
.map
(|
x
|
TokenType
::
Token
(
x
.clone
())))
.chain
(
self
.expected_tokens
.iter
()
.cloned
())
.filter_map
(|
token
|
{
// filter out suggestions which suggest the same token which was found and deemed incorrect
fn
is_ident_eq_keyword
(
found
:
&
TokenKind
,
expected
:
&
TokenType
)
->
bool
{
if
let
TokenKind
::
Ident
(
current_sym
,
_
)
=
found
{
if
let
TokenType
::
Keyword
(
suggested_sym
)
=
expected
{
return
current_sym
==
suggested_sym
;
}
}
false
}
if
token
!=
parser
::
TokenType
::
Token
(
self
.token.kind
.clone
())
{
let
eq
=
is_ident_eq_keyword
(
&
self
.token.kind
,
&
token
);
// if the suggestion is a keyword and the found token is an ident,
// the content of which are equal to the suggestion's content,
// we can remove that suggestion (see the return None statement below)
// if this isn't the case however, and the suggestion is a token the
// content of which is the same as the found token's, we remove it as well
if
!
eq
{
if
let
TokenType
::
Token
(
kind
)
=
&
token
{
if
kind
==
&
self
.token.kind
{
return
None
;
}
}
return
Some
(
token
);
}
}
return
None
;
})
.collect
::
<
Vec
<
_
>>
();
expected
.sort_by_cached_key
(|
x
|
x
.to_string
());
expected
.dedup
();
...
...
compiler/rustc_parse/src/parser/expr.rs
浏览文件 @
21fdd549
...
...
@@ -977,12 +977,26 @@ pub(super) fn parse_dot_or_call_expr_with(
fn
parse_dot_or_call_expr_with_
(
&
mut
self
,
mut
e
:
P
<
Expr
>
,
lo
:
Span
)
->
PResult
<
'a
,
P
<
Expr
>>
{
loop
{
if
self
.eat
(
&
token
::
Question
)
{
let
has_question
=
if
self
.prev_token.kind
==
TokenKind
::
Ident
(
kw
::
Return
,
false
)
{
// we are using noexpect here because we don't expect a `?` directly after a `return`
// which could be suggested otherwise
self
.eat_noexpect
(
&
token
::
Question
)
}
else
{
self
.eat
(
&
token
::
Question
)
};
if
has_question
{
// `expr?`
e
=
self
.mk_expr
(
lo
.to
(
self
.prev_token.span
),
ExprKind
::
Try
(
e
),
AttrVec
::
new
());
continue
;
}
if
self
.eat
(
&
token
::
Dot
)
{
let
has_dot
=
if
self
.prev_token.kind
==
TokenKind
::
Ident
(
kw
::
Return
,
false
)
{
// we are using noexpect here because we don't expect a `.` directly after a `return`
// which could be suggested otherwise
self
.eat_noexpect
(
&
token
::
Dot
)
}
else
{
self
.eat
(
&
token
::
Dot
)
};
if
has_dot
{
// expr.f
e
=
self
.parse_dot_suffix_expr
(
lo
,
e
)
?
;
continue
;
...
...
@@ -1536,9 +1550,13 @@ fn parse_labeled_expr(
self
.parse_for_expr
(
label
,
lo
,
attrs
)
}
else
if
self
.eat_keyword
(
kw
::
Loop
)
{
self
.parse_loop_expr
(
label
,
lo
,
attrs
)
}
else
if
self
.check
(
&
token
::
OpenDelim
(
Delimiter
::
Brace
))
||
self
.token
.is_whole_block
()
{
}
else
if
self
.check_noexpect
(
&
token
::
OpenDelim
(
Delimiter
::
Brace
))
||
self
.token
.is_whole_block
()
{
self
.parse_block_expr
(
label
,
lo
,
BlockCheckMode
::
Default
,
attrs
)
}
else
if
!
ate_colon
&&
(
self
.check
(
&
TokenKind
::
Comma
)
||
self
.check
(
&
TokenKind
::
Gt
))
{
}
else
if
!
ate_colon
&&
(
self
.check_noexpect
(
&
TokenKind
::
Comma
)
||
self
.check_noexpect
(
&
TokenKind
::
Gt
))
{
// We're probably inside of a `Path<'a>` that needs a turbofish
let
msg
=
"expected `while`, `for`, `loop` or `{` after a label"
;
self
.struct_span_err
(
self
.token.span
,
msg
)
.span_label
(
self
.token.span
,
msg
)
.emit
();
...
...
compiler/rustc_parse/src/parser/mod.rs
浏览文件 @
21fdd549
...
...
@@ -548,6 +548,22 @@ fn check(&mut self, tok: &TokenKind) -> bool {
is_present
}
fn
check_noexpect
(
&
self
,
tok
:
&
TokenKind
)
->
bool
{
self
.token
==
*
tok
}
/// Consumes a token 'tok' if it exists. Returns whether the given token was present.
///
/// the main purpose of this function is to reduce the cluttering of the suggestions list
/// which using the normal eat method could introduce in some cases.
pub
fn
eat_noexpect
(
&
mut
self
,
tok
:
&
TokenKind
)
->
bool
{
let
is_present
=
self
.check_noexpect
(
tok
);
if
is_present
{
self
.bump
()
}
is_present
}
/// Consumes a token 'tok' if it exists. Returns whether the given token was present.
pub
fn
eat
(
&
mut
self
,
tok
:
&
TokenKind
)
->
bool
{
let
is_present
=
self
.check
(
tok
);
...
...
compiler/rustc_parse/src/parser/path.rs
浏览文件 @
21fdd549
...
...
@@ -2,7 +2,7 @@
use
super
::{
Parser
,
Restrictions
,
TokenType
};
use
crate
::
maybe_whole
;
use
rustc_ast
::
ptr
::
P
;
use
rustc_ast
::
token
::{
self
,
Delimiter
,
Token
};
use
rustc_ast
::
token
::{
self
,
Delimiter
,
Token
,
TokenKind
};
use
rustc_ast
::{
self
as
ast
,
AngleBracketedArg
,
AngleBracketedArgs
,
AnonConst
,
AssocConstraint
,
AssocConstraintKind
,
BlockCheckMode
,
GenericArg
,
GenericArgs
,
Generics
,
ParenthesizedArgs
,
...
...
@@ -96,7 +96,7 @@ pub(super) fn parse_qpath(&mut self, style: PathStyle) -> PResult<'a, (QSelf, Pa
/// ^ help: use double colon
/// ```
fn
recover_colon_before_qpath_proj
(
&
mut
self
)
->
bool
{
if
self
.token.kind
!=
token
::
Colon
if
!
self
.check_noexpect
(
&
TokenKind
::
Colon
)
||
self
.look_ahead
(
1
,
|
t
|
!
t
.is_ident
()
||
t
.is_reserved_ident
())
{
return
false
;
...
...
@@ -478,7 +478,7 @@ pub(super) fn parse_angle_args(
while
let
Some
(
arg
)
=
self
.parse_angle_arg
(
ty_generics
)
?
{
args
.push
(
arg
);
if
!
self
.eat
(
&
token
::
Comma
)
{
if
self
.
token.kind
==
token
::
Semi
if
self
.
check_noexpect
(
&
TokenKind
::
Semi
)
&&
self
.look_ahead
(
1
,
|
t
|
t
.is_ident
()
||
t
.is_lifetime
())
{
// Add `>` to the list of expected tokens.
...
...
@@ -517,7 +517,11 @@ fn parse_angle_arg(
let
arg
=
self
.parse_generic_arg
(
ty_generics
)
?
;
match
arg
{
Some
(
arg
)
=>
{
if
self
.check
(
&
token
::
Colon
)
|
self
.check
(
&
token
::
Eq
)
{
// we are using noexpect here because we first want to find out if either `=` or `:`
// is present and then use that info to push the other token onto the tokens list
let
separated
=
self
.check_noexpect
(
&
token
::
Colon
)
||
self
.check_noexpect
(
&
token
::
Eq
);
if
separated
&&
(
self
.check
(
&
token
::
Colon
)
|
self
.check
(
&
token
::
Eq
))
{
let
arg_span
=
arg
.span
();
let
(
binder
,
ident
,
gen_args
)
=
match
self
.get_ident_from_generic_arg
(
&
arg
)
{
Ok
(
ident_gen_args
)
=>
ident_gen_args
,
...
...
@@ -553,6 +557,14 @@ fn parse_angle_arg(
AssocConstraint
{
id
:
ast
::
DUMMY_NODE_ID
,
ident
,
gen_args
,
kind
,
span
};
Ok
(
Some
(
AngleBracketedArg
::
Constraint
(
constraint
)))
}
else
{
// we only want to suggest `:` and `=` in contexts where the previous token
// is an ident and the current token or the next token is an ident
if
self
.prev_token
.is_ident
()
&&
(
self
.token
.is_ident
()
||
self
.look_ahead
(
1
,
|
token
|
token
.is_ident
()))
{
self
.check
(
&
token
::
Colon
);
self
.check
(
&
token
::
Eq
);
}
Ok
(
Some
(
AngleBracketedArg
::
Arg
(
arg
)))
}
}
...
...
compiler/rustc_parse/src/parser/stmt.rs
浏览文件 @
21fdd549
...
...
@@ -262,7 +262,10 @@ fn parse_local(&mut self, attrs: AttrVec) -> PResult<'a, P<Local>> {
if
let
Ok
(
snip
)
=
self
.span_to_snippet
(
pat
.span
)
{
err
.span_label
(
pat
.span
,
format!
(
"while parsing the type for `{}`"
,
snip
));
}
let
err
=
if
self
.check
(
&
token
::
Eq
)
{
// we use noexpect here because we don't actually expect Eq to be here
// but we are still checking for it in order to be able to handle it if
// it is there
let
err
=
if
self
.check_noexpect
(
&
token
::
Eq
)
{
err
.emit
();
None
}
else
{
...
...
src/test/ui/parser/can-begin-expr-check.rs
浏览文件 @
21fdd549
...
...
@@ -16,5 +16,5 @@ pub fn main() {
return
break
as
();
}
return
enum
;
//~ ERROR expected one of `
.`, `;`, `?
`, `}`, or an operator, found keyword `enum`
return
enum
;
//~ ERROR expected one of `
;
`, `}`, or an operator, found keyword `enum`
}
src/test/ui/parser/can-begin-expr-check.stderr
浏览文件 @
21fdd549
error: expected one of `
.`, `;`, `?
`, `}`, or an operator, found keyword `enum`
error: expected one of `
;
`, `}`, or an operator, found keyword `enum`
--> $DIR/can-begin-expr-check.rs:19:12
|
LL | return enum;
| ^^^^ expected one of `
.`, `;`, `?
`, `}`, or an operator
| ^^^^ expected one of `
;
`, `}`, or an operator
error: aborting due to previous error
src/test/ui/parser/duplicate-visibility.rs
浏览文件 @
21fdd549
...
...
@@ -2,8 +2,8 @@ fn main() {}
extern
"C"
{
//~ NOTE while parsing this item list starting here
pub
pub
fn
foo
();
//~^ ERROR expected one of `(`, `async`, `const`, `default`, `extern`, `fn`, `
pub`, `
unsafe`, or `use`, found keyword `pub`
//~| NOTE expected one of
9
possible tokens
//~^ ERROR expected one of `(`, `async`, `const`, `default`, `extern`, `fn`, `unsafe`, or `use`, found keyword `pub`
//~| NOTE expected one of
8
possible tokens
//~| HELP there is already a visibility modifier, remove one
//~| NOTE explicit visibility first seen here
}
//~ NOTE the item list ends here
src/test/ui/parser/duplicate-visibility.stderr
浏览文件 @
21fdd549
error: expected one of `(`, `async`, `const`, `default`, `extern`, `fn`, `
pub`, `
unsafe`, or `use`, found keyword `pub`
error: expected one of `(`, `async`, `const`, `default`, `extern`, `fn`, `unsafe`, or `use`, found keyword `pub`
--> $DIR/duplicate-visibility.rs:4:9
|
LL | extern "C" {
...
...
@@ -6,7 +6,7 @@ LL | extern "C" {
LL | pub pub fn foo();
| ^^^
| |
| expected one of
9
possible tokens
| expected one of
8
possible tokens
| help: there is already a visibility modifier, remove one
...
LL | }
...
...
src/test/ui/parser/issues/issue-20616-2.rs
浏览文件 @
21fdd549
...
...
@@ -9,7 +9,7 @@
//type Type_1<'a T> = &'a T; // error: expected `,` or `>` after lifetime name, found `T`
type
Type_2
=
Type_1_
<
'static
()
>
;
//~ error: expected one of `,`
, `:`, `=`,
or `>`, found `(`
type
Type_2
=
Type_1_
<
'static
()
>
;
//~ error: expected one of `,` or `>`, found `(`
//type Type_3<T> = Box<T,,>; // error: expected type, found `,`
...
...
src/test/ui/parser/issues/issue-20616-2.stderr
浏览文件 @
21fdd549
error: expected one of `,`
, `:`, `=`,
or `>`, found `(`
error: expected one of `,` or `>`, found `(`
--> $DIR/issue-20616-2.rs:12:31
|
LL | type Type_2 = Type_1_<'static ()>;
| ^ expected one of `,`
, `:`, `=`,
or `>`
| ^ expected one of `,` or `>`
|
help: you might have meant to end the type parameters here
|
...
...
src/test/ui/parser/issues/issue-62660.rs
浏览文件 @
21fdd549
...
...
@@ -5,7 +5,7 @@
impl
Foo
{
pub
fn
foo
(
_
:
i32
,
self
:
Box
<
Self
)
{}
//~^ ERROR expected one of `!`, `(`, `+`, `,`, `::`, `
:`, `<`, `=
`, or `>`, found `)`
//~^ ERROR expected one of `!`, `(`, `+`, `,`, `::`, `
<
`, or `>`, found `)`
}
fn
main
()
{}
src/test/ui/parser/issues/issue-62660.stderr
浏览文件 @
21fdd549
error: expected one of `!`, `(`, `+`, `,`, `::`, `
:`, `<`, `=
`, or `>`, found `)`
error: expected one of `!`, `(`, `+`, `,`, `::`, `
<
`, or `>`, found `)`
--> $DIR/issue-62660.rs:7:38
|
LL | pub fn foo(_: i32, self: Box<Self) {}
| ^ expected one of
9
possible tokens
| ^ expected one of
7
possible tokens
|
help: you might have meant to end the type parameters here
|
...
...
src/test/ui/parser/issues/issue-84117.rs
浏览文件 @
21fdd549
...
...
@@ -6,4 +6,4 @@ fn main() {
//~| ERROR expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `,`
//~| ERROR expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `,`
}
//~^ ERROR expected one of `,`
, `:`, `=`,
or `>`, found `}`
//~^ ERROR expected one of `,` or `>`, found `}`
src/test/ui/parser/issues/issue-84117.stderr
浏览文件 @
21fdd549
...
...
@@ -21,11 +21,11 @@ error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, fo
LL | let outer_local:e_outer<&str, { let inner_local:e_inner<&str, }
| ^ expected one of 8 possible tokens
error: expected one of `,`
, `:`, `=`,
or `>`, found `}`
error: expected one of `,` or `>`, found `}`
--> $DIR/issue-84117.rs:8:1
|
LL | let outer_local:e_outer<&str, { let inner_local:e_inner<&str, }
| ----------- while parsing the type for `outer_local` - expected one of `,`
, `:`, `=`,
or `>`
| ----------- while parsing the type for `outer_local` - expected one of `,` or `>`
...
LL | }
| ^ unexpected token
...
...
src/test/ui/parser/issues/issue-93282.stderr
浏览文件 @
21fdd549
...
...
@@ -4,11 +4,11 @@ error: expected `while`, `for`, `loop` or `{` after a label
LL | f<'a,>
| ^ expected `while`, `for`, `loop` or `{` after a label
error: expected one of `.`, `:`, `;`, `?`, `for`, `loop`, `while`, `
{`, `
}`, or an operator, found `,`
error: expected one of `.`, `:`, `;`, `?`, `for`, `loop`, `while`, `}`, or an operator, found `,`
--> $DIR/issue-93282.rs:2:9
|
LL | f<'a,>
| ^ expected one of
10
possible tokens
| ^ expected one of
9
possible tokens
|
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
|
...
...
src/test/ui/parser/issues/issue-93867.rs
0 → 100644
浏览文件 @
21fdd549
pub
struct
Entry
<
'a
,
K
,
V
>
{
k
:
&
'a
mut
K
,
v
:
V
,
}
pub
fn
entry
<
'a
,
K
,
V
>
()
->
Entry
<
'a
K
,
V
>
{
// ^ missing comma
//~^^ expected one of `,` or `>`, found `K`
unimplemented!
()
}
src/test/ui/parser/issues/issue-93867.stderr
0 → 100644
浏览文件 @
21fdd549
error: expected one of `,` or `>`, found `K`
--> $DIR/issue-93867.rs:6:38
|
LL | pub fn entry<'a, K, V>() -> Entry<'a K, V> {
| ^ expected one of `,` or `>`
|
help: you might have meant to end the type parameters here
|
LL | pub fn entry<'a, K, V>() -> Entry<'a> K, V> {
| +
error: aborting due to previous error
src/test/ui/parser/lifetime-semicolon.fixed
浏览文件 @
21fdd549
...
...
@@ -5,6 +5,6 @@ struct Foo<'a, 'b> {
}
fn foo<'a, 'b>(_x: &mut Foo<'a, 'b>) {}
//~^ ERROR expected one of `,`
, `:`, `=`,
or `>`, found `;`
//~^ ERROR expected one of `,` or `>`, found `;`
fn main() {}
src/test/ui/parser/lifetime-semicolon.rs
浏览文件 @
21fdd549
...
...
@@ -5,6 +5,6 @@ struct Foo<'a, 'b> {
}
fn
foo
<
'a
,
'b
>
(
_
x
:
&
mut
Foo
<
'a
;
'b
>
)
{}
//~^ ERROR expected one of `,`
, `:`, `=`,
or `>`, found `;`
//~^ ERROR expected one of `,` or `>`, found `;`
fn
main
()
{}
src/test/ui/parser/lifetime-semicolon.stderr
浏览文件 @
21fdd549
error: expected one of `,`
, `:`, `=`,
or `>`, found `;`
error: expected one of `,` or `>`, found `;`
--> $DIR/lifetime-semicolon.rs:7:31
|
LL | fn foo<'a, 'b>(_x: &mut Foo<'a; 'b>) {}
| ^ expected one of `,`
, `:`, `=`,
or `>`
| ^ expected one of `,` or `>`
|
help: use a comma to separate type parameters
|
...
...
src/test/ui/parser/require-parens-for-chained-comparison.stderr
浏览文件 @
21fdd549
...
...
@@ -59,11 +59,11 @@ error: expected `while`, `for`, `loop` or `{` after a label
LL | let _ = f<'_, i8>();
| ^ expected `while`, `for`, `loop` or `{` after a label
error: expected one of `.`, `:`, `;`, `?`, `else`, `for`, `loop`, `while`,
`{`,
or an operator, found `,`
error: expected one of `.`, `:`, `;`, `?`, `else`, `for`, `loop`, `while`, or an operator, found `,`
--> $DIR/require-parens-for-chained-comparison.rs:22:17
|
LL | let _ = f<'_, i8>();
| ^ expected one of
10
possible tokens
| ^ expected one of
9
possible tokens
|
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
|
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录