Skip to content

Commit 5599f2a

Browse files
committed
fix #105226, Detect spurious ; before assoc fn body
1 parent 703d95e commit 5599f2a

File tree

3 files changed

+62
-3
lines changed

3 files changed

+62
-3
lines changed

compiler/rustc_parse/src/parser/item.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -707,9 +707,9 @@ impl<'a> Parser<'a> {
707707
}
708708
match parse_item(self) {
709709
Ok(None) => {
710-
let is_unnecessary_semicolon = !items.is_empty()
710+
let mut is_unnecessary_semicolon = !items.is_empty()
711711
// When the close delim is `)` in a case like the following, `token.kind` is expected to be `token::CloseDelim(Delimiter::Parenthesis)`,
712-
// but the actual `token.kind` is `token::CloseDelim(Delimiter::Bracket)`.
712+
// but the actual `token.kind` is `token::CloseDelim(Delimiter::Brace)`.
713713
// This is because the `token.kind` of the close delim is treated as the same as
714714
// that of the open delim in `TokenTreesReader::parse_token_tree`, even if the delimiters of them are different.
715715
// Therefore, `token.kind` should not be compared here.
@@ -728,7 +728,13 @@ impl<'a> Parser<'a> {
728728
.span_to_snippet(self.prev_token.span)
729729
.map_or(false, |snippet| snippet == "}")
730730
&& self.token.kind == token::Semi;
731-
let semicolon_span = self.token.span;
731+
let mut semicolon_span = self.token.span;
732+
if !is_unnecessary_semicolon {
733+
// #105369, Detect spurious `;` before assoc fn body
734+
is_unnecessary_semicolon = self.token == token::OpenDelim(Delimiter::Brace)
735+
&& self.prev_token.kind == token::Semi;
736+
semicolon_span = self.prev_token.span;
737+
}
732738
// We have to bail or we'll potentially never make progress.
733739
let non_item_span = self.token.span;
734740
let is_let = self.token.is_keyword(kw::Let);
+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
use std::fmt;
2+
3+
struct S {
4+
}
5+
6+
impl S {
7+
fn hello<P>(&self, val: &P) where P: fmt::Display; {
8+
//~^ ERROR non-item in item list
9+
//~| ERROR associated function in `impl` without body
10+
println!("val: {}", val);
11+
}
12+
}
13+
14+
impl S {
15+
fn hello_empty<P>(&self, val: &P) where P: fmt::Display;
16+
//~^ ERROR associated function in `impl` without body
17+
}
18+
19+
fn main() {
20+
let s = S{};
21+
s.hello(&32);
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
error: non-item in item list
2+
--> $DIR/issue-105226.rs:7:56
3+
|
4+
LL | impl S {
5+
| - item list starts here
6+
LL | fn hello<P>(&self, val: &P) where P: fmt::Display; {
7+
| - ^ non-item starts here
8+
| |
9+
| help: consider removing this semicolon
10+
...
11+
LL | }
12+
| - item list ends here
13+
14+
error: associated function in `impl` without body
15+
--> $DIR/issue-105226.rs:7:5
16+
|
17+
LL | fn hello<P>(&self, val: &P) where P: fmt::Display; {
18+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
19+
| |
20+
| help: provide a definition for the function: `{ <body> }`
21+
22+
error: associated function in `impl` without body
23+
--> $DIR/issue-105226.rs:15:5
24+
|
25+
LL | fn hello_empty<P>(&self, val: &P) where P: fmt::Display;
26+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
27+
| |
28+
| help: provide a definition for the function: `{ <body> }`
29+
30+
error: aborting due to 3 previous errors
31+

0 commit comments

Comments
 (0)