Skip to content

Commit ba0e1c9

Browse files
committed
Address review comments: fix span and add run-rustfix
- Change error span to start from 'const' keyword instead of binop RHS - Add decl_lo parameter to missing_semi_from_binop() for better spans - Add run-rustfix directive to test file - Simplify test to focus on const item recovery cases
1 parent 6f40616 commit ba0e1c9

6 files changed

Lines changed: 74 additions & 71 deletions

File tree

compiler/rustc_parse/src/parser/item.rs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@ use rustc_ast::ast::*;
66
use rustc_ast::token::{self, Delimiter, InvisibleOrigin, MetaVarKind, TokenKind};
77
use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree};
88
use rustc_ast::util::case::Case;
9-
use rustc_ast::{
10-
attr, {self as ast},
11-
};
9+
use rustc_ast::{self as ast};
1210
use rustc_ast_pretty::pprust;
1311
use rustc_errors::codes::*;
1412
use rustc_errors::{Applicability, PResult, StashKey, inline_fluent, struct_span_code_err};
@@ -286,7 +284,7 @@ impl<'a> Parser<'a> {
286284
// CONST ITEM
287285
self.recover_const_mut(const_span);
288286
self.recover_missing_kw_before_item()?;
289-
let (ident, generics, ty, rhs_kind) = self.parse_const_item(false)?;
287+
let (ident, generics, ty, rhs_kind) = self.parse_const_item(false, const_span)?;
290288
ItemKind::Const(Box::new(ConstItem {
291289
defaultness: def_(),
292290
ident,
@@ -307,7 +305,7 @@ impl<'a> Parser<'a> {
307305
// TYPE CONST (mgca)
308306
self.recover_const_mut(const_span);
309307
self.recover_missing_kw_before_item()?;
310-
let (ident, generics, ty, rhs_kind) = self.parse_const_item(true)?;
308+
let (ident, generics, ty, rhs_kind) = self.parse_const_item(true, const_span)?;
311309
// Make sure this is only allowed if the feature gate is enabled.
312310
// #![feature(mgca_type_const_syntax)]
313311
self.psess.gated_spans.gate(sym::mgca_type_const_syntax, lo.to(const_span));
@@ -1545,6 +1543,7 @@ impl<'a> Parser<'a> {
15451543
fn parse_const_item(
15461544
&mut self,
15471545
const_arg: bool,
1546+
const_span: Span,
15481547
) -> PResult<'a, (Ident, Generics, Box<Ty>, ConstItemRhsKind)> {
15491548
let ident = self.parse_ident_or_underscore()?;
15501549

@@ -1636,8 +1635,8 @@ impl<'a> Parser<'a> {
16361635

16371636
generics.where_clause = where_clause;
16381637

1639-
if let Some(recovered_rhs) = self.try_recover_const_missing_semi(&rhs) {
1640-
return Ok((ident, generics, ty, Some(ConstItemRhs::Body(recovered_rhs))));
1638+
if let Some(rhs) = self.try_recover_const_missing_semi(&rhs, const_span) {
1639+
return Ok((ident, generics, ty, ConstItemRhsKind::Body { rhs: Some(rhs) }));
16411640
}
16421641
self.expect_semi()?;
16431642

@@ -3499,17 +3498,23 @@ impl<'a> Parser<'a> {
34993498
/// (e.g., `foo() \n &bar` was parsed as `foo() & bar`).
35003499
///
35013500
/// Returns a corrected expression if recovery is successful.
3502-
fn try_recover_const_missing_semi(&mut self, rhs: &Option<ConstItemRhs>) -> Option<Box<Expr>> {
3501+
fn try_recover_const_missing_semi(
3502+
&mut self,
3503+
rhs: &ConstItemRhsKind,
3504+
const_span: Span,
3505+
) -> Option<Box<Expr>> {
35033506
if self.token == TokenKind::Semi {
35043507
return None;
35053508
}
3506-
let Some(ConstItemRhs::Body(rhs)) = rhs else {
3509+
let ConstItemRhsKind::Body { rhs: Some(rhs) } = rhs else {
35073510
return None;
35083511
};
35093512
if !self.in_fn_body || !self.may_recover() || rhs.span.from_expansion() {
35103513
return None;
35113514
}
3512-
if let Some((span, guar)) = self.missing_semi_from_binop("const", rhs) {
3515+
if let Some((span, guar)) =
3516+
self.missing_semi_from_binop("const", rhs, Some(const_span.shrink_to_lo()))
3517+
{
35133518
self.fn_body_missing_semi_guar = Some(guar);
35143519
Some(self.mk_expr(span, ExprKind::Err(guar)))
35153520
} else {

compiler/rustc_parse/src/parser/mod.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ use rustc_ast::tokenstream::{
3434
use rustc_ast::util::case::Case;
3535
use rustc_ast::util::classify;
3636
use rustc_ast::{
37-
self as ast, AnonConst, AttrArgs, AttrId, BinOpKind, BlockCheckMode, ByRef, Const,
38-
CoroutineKind, DUMMY_NODE_ID, DelimArgs, Expr, ExprKind, Extern, HasAttrs, HasTokens,
39-
MgcaDisambiguation, Mutability, Recovered, Safety, StrLit, Visibility, VisibilityKind,
37+
self as ast, AnonConst, AttrArgs, AttrId, BinOpKind, ByRef, Const, CoroutineKind,
38+
DUMMY_NODE_ID, DelimArgs, Expr, ExprKind, Extern, HasAttrs, HasTokens, MgcaDisambiguation,
39+
Mutability, Recovered, Safety, StrLit, Visibility, VisibilityKind,
4040
};
4141
use rustc_ast_pretty::pprust;
4242
use rustc_data_structures::debug_assert_matches;
@@ -235,7 +235,7 @@ pub struct Parser<'a> {
235235
recovery: Recovery = Recovery::Allowed,
236236
/// Whether we're parsing a function body.
237237
in_fn_body: bool = false,
238-
/// Whether we have detected a missing semicolon in the function body.
238+
/// Whether we have detected a missing semicolon in function body.
239239
pub fn_body_missing_semi_guar: Option<ErrorGuaranteed> = None,
240240
}
241241

@@ -1648,6 +1648,7 @@ impl<'a> Parser<'a> {
16481648
&self,
16491649
kind_desc: &str,
16501650
expr: &Expr,
1651+
decl_lo: Option<Span>,
16511652
) -> Option<(Span, ErrorGuaranteed)> {
16521653
if self.token == TokenKind::Semi {
16531654
return None;
@@ -1668,7 +1669,9 @@ impl<'a> Parser<'a> {
16681669
.struct_span_err(lhs_end_span, format!("expected `;`, found {token_str}"));
16691670
err.span_label(self.token.span, "unexpected token");
16701671

1671-
let continuation_span = lhs_end_span.until(rhs.span.shrink_to_hi());
1672+
// Use the declaration start if provided, otherwise fall back to lhs_end_span.
1673+
let continuation_start = decl_lo.unwrap_or(lhs_end_span);
1674+
let continuation_span = continuation_start.until(rhs.span.shrink_to_hi());
16721675
err.span_label(
16731676
continuation_span,
16741677
format!(

compiler/rustc_parse/src/parser/stmt.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -929,7 +929,9 @@ impl<'a> Parser<'a> {
929929
LocalKind::Init(expr) | LocalKind::InitElse(expr, _) => expr,
930930
LocalKind::Decl => return None,
931931
};
932-
if let Some((span, guar)) = self.missing_semi_from_binop("`let` binding", expr) {
932+
if let Some((span, guar)) =
933+
self.missing_semi_from_binop("`let` binding", expr, Some(local.span.shrink_to_lo()))
934+
{
933935
self.fn_body_missing_semi_guar = Some(guar);
934936
*expr = self.mk_expr(span, ExprKind::Err(guar));
935937
return Some(guar);
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//@ run-rustfix
2+
#![feature(const_trait_impl)]
3+
#![allow(dead_code)]
4+
#![allow(unused)]
5+
6+
const trait ConstDefault {
7+
fn const_default() -> Self;
8+
}
9+
10+
impl const ConstDefault for u8 {
11+
fn const_default() -> Self { 0 }
12+
}
13+
14+
const fn val() -> u8 {
15+
42
16+
}
17+
18+
const C: u8 = u8::const_default()
19+
&1; //~ ERROR expected `;`, found keyword `const`
20+
21+
const fn foo() -> &'static u8 {
22+
const C: u8 = u8::const_default(); //~ ERROR expected `;`
23+
&C
24+
}
25+
26+
const fn bar() {
27+
const C: u8 = 1
28+
+ 2; //~ ERROR expected `;`, found `}`
29+
}
30+
31+
const fn baz() {
32+
const C: u8 = 1
33+
+ val(); //~ ERROR expected `;`, found `}`
34+
}
35+
36+
fn main() {}

tests/ui/parser/const-recover-semi-issue-151149.rs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
//@ run-rustfix
12
#![feature(const_trait_impl)]
3+
#![allow(dead_code)]
4+
#![allow(unused)]
25

36
const trait ConstDefault {
47
fn const_default() -> Self;
@@ -20,19 +23,14 @@ const fn foo() -> &'static u8 {
2023
&C
2124
}
2225

23-
const fn bar() -> u8 { //~ ERROR mismatched types
26+
const fn bar() {
2427
const C: u8 = 1
2528
+ 2 //~ ERROR expected `;`, found `}`
2629
}
2730

28-
const fn baz() -> u8 { //~ ERROR mismatched types
31+
const fn baz() {
2932
const C: u8 = 1
3033
+ val() //~ ERROR expected `;`, found `}`
3134
}
3235

33-
fn buzz() -> &'static u8 {
34-
let r = 1 //~ ERROR expected `;`
35-
&r
36-
}
37-
3836
fn main() {}
Lines changed: 7 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: expected `;`, found keyword `const`
2-
--> $DIR/const-recover-semi-issue-151149.rs:16:3
2+
--> $DIR/const-recover-semi-issue-151149.rs:19:3
33
|
44
LL | &1
55
| ^ help: add `;` here
@@ -8,17 +8,17 @@ LL | const fn foo() -> &'static u8 {
88
| ----- unexpected token
99

1010
error: expected `;`, found `}`
11-
--> $DIR/const-recover-semi-issue-151149.rs:19:38
11+
--> $DIR/const-recover-semi-issue-151149.rs:22:38
1212
|
1313
LL | const C: u8 = u8::const_default()
14-
| ______________________________________^
14+
| _____- ^
1515
LL | | &C
1616
| |______- to finish parsing this const, expected this to be followed by a `;`
1717
LL | }
1818
| - unexpected token
1919
|
2020
note: the const was parsed as having a bit-and binary expression
21-
--> $DIR/const-recover-semi-issue-151149.rs:19:19
21+
--> $DIR/const-recover-semi-issue-151149.rs:22:19
2222
|
2323
LL | const C: u8 = u8::const_default()
2424
| ------------------- parsed as the left-hand expression
@@ -32,61 +32,20 @@ LL | const C: u8 = u8::const_default();
3232
| +
3333

3434
error: expected `;`, found `}`
35-
--> $DIR/const-recover-semi-issue-151149.rs:25:9
35+
--> $DIR/const-recover-semi-issue-151149.rs:28:9
3636
|
3737
LL | + 2
3838
| ^ help: add `;` here
3939
LL | }
4040
| - unexpected token
4141

4242
error: expected `;`, found `}`
43-
--> $DIR/const-recover-semi-issue-151149.rs:30:13
43+
--> $DIR/const-recover-semi-issue-151149.rs:33:13
4444
|
4545
LL | + val()
4646
| ^ help: add `;` here
4747
LL | }
4848
| - unexpected token
4949

50-
error: expected `;`, found `}`
51-
--> $DIR/const-recover-semi-issue-151149.rs:34:14
52-
|
53-
LL | let r = 1
54-
| ______________^
55-
LL | | &r
56-
| |______- to finish parsing this `let` binding, expected this to be followed by a `;`
57-
LL | }
58-
| - unexpected token
59-
|
60-
note: the `let` binding was parsed as having a bit-and binary expression
61-
--> $DIR/const-recover-semi-issue-151149.rs:34:13
62-
|
63-
LL | let r = 1
64-
| - parsed as the left-hand expression
65-
LL | &r
66-
| -- parsed as the right-hand expression
67-
| |
68-
| this was parsed as a bit-and
69-
help: you may have meant to write a `;` to terminate the `let` binding earlier
70-
|
71-
LL | let r = 1;
72-
| +
73-
74-
error[E0308]: mismatched types
75-
--> $DIR/const-recover-semi-issue-151149.rs:23:19
76-
|
77-
LL | const fn bar() -> u8 {
78-
| --- ^^ expected `u8`, found `()`
79-
| |
80-
| implicitly returns `()` as its body has no tail or `return` expression
81-
82-
error[E0308]: mismatched types
83-
--> $DIR/const-recover-semi-issue-151149.rs:28:19
84-
|
85-
LL | const fn baz() -> u8 {
86-
| --- ^^ expected `u8`, found `()`
87-
| |
88-
| implicitly returns `()` as its body has no tail or `return` expression
89-
90-
error: aborting due to 7 previous errors
50+
error: aborting due to 4 previous errors
9151

92-
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)