Skip to content

Commit 4cb124d

Browse files
authored
Unrolled build for rust-lang#134599
Rollup merge of rust-lang#134599 - dtolnay:fulldepsparser, r=fmease Detect invalid exprs in parser used by pretty-printer tests This PR fixes a bug in rust-lang#133730 inherited from rust-lang#43742. Before this fix, the test might silently only operate on a prefix of some of the test cases in this table: https://github.com/rust-lang/rust/blob/13170cd787cb733ed24842ee825bcbd98dc01476/tests/ui-fulldeps/pprust-parenthesis-insertion.rs#L57 For example, adding the test case `1 .. 2 .. 3` (a syntactically invalid expression) into the table would unexpectedly succeed the test instead of crashing at this unwrap: https://github.com/rust-lang/rust/blob/13170cd787cb733ed24842ee825bcbd98dc01476/tests/ui-fulldeps/pprust-parenthesis-insertion.rs#L199-L200 because `parse_expr` would successfully parse just `1 .. 2` and disregard the last `.. 3`. This PR adds a check that `parse_expr` reaches `Eof`, ensuring all the test cases actually test the whole expression they look like they are supposed to.
2 parents a2bcfae + 1f2028f commit 4cb124d

File tree

3 files changed

+62
-50
lines changed

3 files changed

+62
-50
lines changed

tests/ui-fulldeps/auxiliary/parser.rs

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#![feature(rustc_private)]
2+
3+
extern crate rustc_ast;
4+
extern crate rustc_driver;
5+
extern crate rustc_errors;
6+
extern crate rustc_parse;
7+
extern crate rustc_session;
8+
extern crate rustc_span;
9+
10+
use rustc_ast::ast::{DUMMY_NODE_ID, Expr};
11+
use rustc_ast::mut_visit::MutVisitor;
12+
use rustc_ast::node_id::NodeId;
13+
use rustc_ast::ptr::P;
14+
use rustc_ast::token;
15+
use rustc_errors::Diag;
16+
use rustc_parse::parser::Recovery;
17+
use rustc_session::parse::ParseSess;
18+
use rustc_span::{DUMMY_SP, FileName, Span};
19+
20+
pub fn parse_expr(psess: &ParseSess, source_code: &str) -> Option<P<Expr>> {
21+
let parser = rustc_parse::unwrap_or_emit_fatal(rustc_parse::new_parser_from_source_str(
22+
psess,
23+
FileName::anon_source_code(source_code),
24+
source_code.to_owned(),
25+
));
26+
27+
let mut parser = parser.recovery(Recovery::Forbidden);
28+
let mut expr = parser.parse_expr().map_err(Diag::cancel).ok()?;
29+
if parser.token != token::Eof {
30+
return None;
31+
}
32+
33+
Normalize.visit_expr(&mut expr);
34+
Some(expr)
35+
}
36+
37+
// Erase Span information that could distinguish between identical expressions
38+
// parsed from different source strings.
39+
struct Normalize;
40+
41+
impl MutVisitor for Normalize {
42+
const VISIT_TOKENS: bool = true;
43+
44+
fn visit_id(&mut self, id: &mut NodeId) {
45+
*id = DUMMY_NODE_ID;
46+
}
47+
48+
fn visit_span(&mut self, span: &mut Span) {
49+
*span = DUMMY_SP;
50+
}
51+
}

tests/ui-fulldeps/pprust-expr-roundtrip.rs

+4-14
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
//@ run-pass
22
//@ ignore-cross-compile
3+
//@ aux-crate: parser=parser.rs
4+
//@ edition: 2021
35

46
// The general idea of this test is to enumerate all "interesting" expressions and check that
57
// `parse(print(e)) == e` for all `e`. Here's what's interesting, for the purposes of this test:
@@ -21,7 +23,6 @@
2123

2224
extern crate rustc_ast;
2325
extern crate rustc_ast_pretty;
24-
extern crate rustc_data_structures;
2526
extern crate rustc_parse;
2627
extern crate rustc_session;
2728
extern crate rustc_span;
@@ -32,28 +33,17 @@ extern crate thin_vec;
3233
#[allow(unused_extern_crates)]
3334
extern crate rustc_driver;
3435

36+
use parser::parse_expr;
3537
use rustc_ast::mut_visit::{visit_clobber, MutVisitor};
3638
use rustc_ast::ptr::P;
3739
use rustc_ast::*;
3840
use rustc_ast_pretty::pprust;
39-
use rustc_parse::{new_parser_from_source_str, unwrap_or_emit_fatal};
4041
use rustc_session::parse::ParseSess;
4142
use rustc_span::source_map::Spanned;
4243
use rustc_span::symbol::Ident;
43-
use rustc_span::{FileName, DUMMY_SP};
44+
use rustc_span::DUMMY_SP;
4445
use thin_vec::{thin_vec, ThinVec};
4546

46-
fn parse_expr(psess: &ParseSess, src: &str) -> Option<P<Expr>> {
47-
let src_as_string = src.to_string();
48-
49-
let mut p = unwrap_or_emit_fatal(new_parser_from_source_str(
50-
psess,
51-
FileName::Custom(src_as_string.clone()),
52-
src_as_string,
53-
));
54-
p.parse_expr().map_err(|e| e.cancel()).ok()
55-
}
56-
5747
// Helper functions for building exprs
5848
fn expr(kind: ExprKind) -> P<Expr> {
5949
P(Expr { id: DUMMY_NODE_ID, kind, span: DUMMY_SP, attrs: AttrVec::new(), tokens: None })

tests/ui-fulldeps/pprust-parenthesis-insertion.rs

+7-36
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
//@ run-pass
22
//@ ignore-cross-compile
3+
//@ aux-crate: parser=parser.rs
4+
//@ edition: 2021
35

46
// This test covers the AST pretty-printer's automatic insertion of parentheses
57
// into unparenthesized syntax trees according to precedence and various grammar
@@ -31,24 +33,19 @@
3133

3234
extern crate rustc_ast;
3335
extern crate rustc_ast_pretty;
34-
extern crate rustc_driver;
35-
extern crate rustc_errors;
3636
extern crate rustc_parse;
3737
extern crate rustc_session;
3838
extern crate rustc_span;
3939

4040
use std::mem;
4141
use std::process::ExitCode;
4242

43-
use rustc_ast::ast::{DUMMY_NODE_ID, Expr, ExprKind};
43+
use parser::parse_expr;
44+
use rustc_ast::ast::{Expr, ExprKind};
4445
use rustc_ast::mut_visit::{self, DummyAstNode as _, MutVisitor};
45-
use rustc_ast::node_id::NodeId;
4646
use rustc_ast::ptr::P;
4747
use rustc_ast_pretty::pprust;
48-
use rustc_errors::Diag;
49-
use rustc_parse::parser::Recovery;
5048
use rustc_session::parse::ParseSess;
51-
use rustc_span::{DUMMY_SP, FileName, Span};
5249

5350
// Every parenthesis in the following expressions is re-inserted by the
5451
// pretty-printer.
@@ -156,34 +153,6 @@ impl MutVisitor for Unparenthesize {
156153
}
157154
}
158155

159-
// Erase Span information that could distinguish between identical expressions
160-
// parsed from different source strings.
161-
struct Normalize;
162-
163-
impl MutVisitor for Normalize {
164-
const VISIT_TOKENS: bool = true;
165-
166-
fn visit_id(&mut self, id: &mut NodeId) {
167-
*id = DUMMY_NODE_ID;
168-
}
169-
170-
fn visit_span(&mut self, span: &mut Span) {
171-
*span = DUMMY_SP;
172-
}
173-
}
174-
175-
fn parse_expr(psess: &ParseSess, source_code: &str) -> Option<P<Expr>> {
176-
let parser = rustc_parse::unwrap_or_emit_fatal(rustc_parse::new_parser_from_source_str(
177-
psess,
178-
FileName::anon_source_code(source_code),
179-
source_code.to_owned(),
180-
));
181-
182-
let mut expr = parser.recovery(Recovery::Forbidden).parse_expr().map_err(Diag::cancel).ok()?;
183-
Normalize.visit_expr(&mut expr);
184-
Some(expr)
185-
}
186-
187156
fn main() -> ExitCode {
188157
let mut status = ExitCode::SUCCESS;
189158
let mut fail = |description: &str, before: &str, after: &str| {
@@ -199,7 +168,9 @@ fn main() -> ExitCode {
199168
let psess = &ParseSess::new(vec![rustc_parse::DEFAULT_LOCALE_RESOURCE]);
200169

201170
for &source_code in EXPRS {
202-
let expr = parse_expr(psess, source_code).unwrap();
171+
let Some(expr) = parse_expr(psess, source_code) else {
172+
panic!("Failed to parse original test case: {source_code}");
173+
};
203174

204175
// Check for FALSE POSITIVE: pretty-printer inserting parentheses where not needed.
205176
// Pseudocode:

0 commit comments

Comments
 (0)