Skip to content

Commit 8b186df

Browse files
committed
Add recovery for use of removed box syntax
1 parent a8d5950 commit 8b186df

File tree

5 files changed

+105
-10
lines changed

5 files changed

+105
-10
lines changed

compiler/rustc_parse/src/parser/expr.rs

+28
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use super::{
88

99
use crate::errors;
1010
use crate::maybe_recover_from_interpolated_ty_qpath;
11+
use ast::{Path, PathSegment};
1112
use core::mem;
1213
use rustc_ast::ptr::P;
1314
use rustc_ast::token::{self, Delimiter, Token, TokenKind};
@@ -29,6 +30,7 @@ use rustc_session::errors::{report_lit_error, ExprParenthesesNeeded};
2930
use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP;
3031
use rustc_session::lint::BuiltinLintDiagnostics;
3132
use rustc_span::source_map::{self, Span, Spanned};
33+
use rustc_span::symbol::kw::PathRoot;
3234
use rustc_span::symbol::{kw, sym, Ident, Symbol};
3335
use rustc_span::{BytePos, Pos};
3436
use thin_vec::{thin_vec, ThinVec};
@@ -607,6 +609,9 @@ impl<'a> Parser<'a> {
607609
let operand_expr = this.parse_expr_dot_or_call(Default::default())?;
608610
this.recover_from_prefix_increment(operand_expr, pre_span, starts_stmt)
609611
}
612+
token::Ident(..) if this.token.is_keyword(kw::Box) => {
613+
make_it!(this, attrs, |this, _| this.parse_expr_box(lo))
614+
}
610615
token::Ident(..) if this.may_recover() && this.is_mistaken_not_ident_negation() => {
611616
make_it!(this, attrs, |this, _| this.recover_not_expr(lo))
612617
}
@@ -633,6 +638,29 @@ impl<'a> Parser<'a> {
633638
self.parse_expr_unary(lo, UnOp::Not)
634639
}
635640

641+
/// Parse `box expr` - this syntax has been removed, but we still parse this
642+
/// for now to provide an automated way to fix usages of it
643+
fn parse_expr_box(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
644+
let (span, expr) = self.parse_expr_prefix_common(lo)?;
645+
let code = self.sess.source_map().span_to_snippet(span.with_lo(lo.hi())).unwrap();
646+
self.sess.emit_err(errors::BoxSyntaxRemoved { span, code: code.trim() });
647+
// So typechecking works, parse `box <expr>` as `::std::boxed::Box::new(expr)`
648+
let path = Path {
649+
span,
650+
segments: [
651+
PathSegment::from_ident(Ident::with_dummy_span(PathRoot)),
652+
PathSegment::from_ident(Ident::with_dummy_span(sym::std)),
653+
PathSegment::from_ident(Ident::from_str("boxed")),
654+
PathSegment::from_ident(Ident::from_str("Box")),
655+
PathSegment::from_ident(Ident::with_dummy_span(sym::new)),
656+
]
657+
.into(),
658+
tokens: None,
659+
};
660+
let path = self.mk_expr(span, ExprKind::Path(None, path));
661+
Ok((span, self.mk_call(path, ThinVec::from([expr]))))
662+
}
663+
636664
fn is_mistaken_not_ident_negation(&self) -> bool {
637665
let token_cannot_continue_expr = |t: &Token| match t.uninterpolate().kind {
638666
// These tokens can start an expression after `!`, but
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// run-rustfix
2+
3+
fn main() {
4+
#[allow(dead_code)]
5+
struct T {
6+
a: u8,
7+
b: u8,
8+
}
9+
let _ = Box::new(()); //~ ERROR `box_syntax` has been removed
10+
let _ = Box::new(1); //~ ERROR `box_syntax` has been removed
11+
let _ = Box::new(T { a: 12, b: 18 }); //~ ERROR `box_syntax` has been removed
12+
let _ = Box::new([5; 30]); //~ ERROR `box_syntax` has been removed
13+
let _: Box<()> = Box::new(()); //~ ERROR `box_syntax` has been removed
14+
}

tests/ui/parser/removed-syntax-box.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1+
// run-rustfix
2+
13
fn main() {
4+
#[allow(dead_code)]
25
struct T {
36
a: u8,
47
b: u8,
58
}
6-
let _ = box () //~ ERROR expected expression, found reserved keyword `box`
7-
let _ = box 1;
8-
let _ = box T { a: 12, b: 18 };
9-
let _ = box [5; 30];
9+
let _ = box (); //~ ERROR `box_syntax` has been removed
10+
let _ = box 1; //~ ERROR `box_syntax` has been removed
11+
let _ = box T { a: 12, b: 18 }; //~ ERROR `box_syntax` has been removed
12+
let _ = box [5; 30]; //~ ERROR `box_syntax` has been removed
13+
let _: Box<()> = box (); //~ ERROR `box_syntax` has been removed
1014
}
+54-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,57 @@
1-
error: expected expression, found reserved keyword `box`
2-
--> $DIR/removed-syntax-box.rs:6:13
1+
error: `box_syntax` has been removed
2+
--> $DIR/removed-syntax-box.rs:9:13
33
|
4-
LL | let _ = box ()
5-
| ^^^ expected expression
4+
LL | let _ = box ();
5+
| ^^^^^^
6+
|
7+
help: use `Box::new()` instead
8+
|
9+
LL | let _ = Box::new(());
10+
| ~~~~~~~~~~~~
11+
12+
error: `box_syntax` has been removed
13+
--> $DIR/removed-syntax-box.rs:10:13
14+
|
15+
LL | let _ = box 1;
16+
| ^^^^^
17+
|
18+
help: use `Box::new()` instead
19+
|
20+
LL | let _ = Box::new(1);
21+
| ~~~~~~~~~~~
22+
23+
error: `box_syntax` has been removed
24+
--> $DIR/removed-syntax-box.rs:11:13
25+
|
26+
LL | let _ = box T { a: 12, b: 18 };
27+
| ^^^^^^^^^^^^^^^^^^^^^^
28+
|
29+
help: use `Box::new()` instead
30+
|
31+
LL | let _ = Box::new(T { a: 12, b: 18 });
32+
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
33+
34+
error: `box_syntax` has been removed
35+
--> $DIR/removed-syntax-box.rs:12:13
36+
|
37+
LL | let _ = box [5; 30];
38+
| ^^^^^^^^^^^
39+
|
40+
help: use `Box::new()` instead
41+
|
42+
LL | let _ = Box::new([5; 30]);
43+
| ~~~~~~~~~~~~~~~~~
44+
45+
error: `box_syntax` has been removed
46+
--> $DIR/removed-syntax-box.rs:13:22
47+
|
48+
LL | let _: Box<()> = box ();
49+
| ^^^^^^
50+
|
51+
help: use `Box::new()` instead
52+
|
53+
LL | let _: Box<()> = Box::new(());
54+
| ~~~~~~~~~~~~
655

7-
error: aborting due to previous error
56+
error: aborting due to 5 previous errors
857

tests/ui/unpretty/box.stdout

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@ extern crate std;
1010
fn main() {
1111
let _ =
1212
#[rustc_box]
13-
Box::new (1);
13+
Box::new(1);
1414
}

0 commit comments

Comments
 (0)