Skip to content

Commit 4ba5068

Browse files
committed
Auto merge of rust-lang#77135 - Aaron1011:pretty-ignore-paren, r=petrochenkov
Refactor AST pretty-printing to allow skipping insertion of extra parens Fixes rust-lang#75734 Makes progress towards rust-lang#43081 Unblocks PR rust-lang#76130 When pretty-printing an AST node, we may insert additional parenthesis to ensure that precedence is properly preserved in code we output. However, the proc macro implementation relies on comparing a pretty-printed AST node to the captured `TokenStream`. Inserting extra parenthesis changes the structure of the reparsed `TokenStream`, making the comparison fail. This PR refactors the AST pretty-printing code to allow skipping the insertion of additional parenthesis. Several freestanding methods are moved to trait methods on `PrintState`, which keep track of an internal `insert_extra_parens` flag. This flag is normally `true`, but we expose a public method which allows pretty-printing a nonterminal with `insert_extra_parens = false`. To avoid changing the public interface of `rustc_ast_pretty`, the freestanding `_to_string` methods are changed to delegate to a newly-crated `State`. The main pretty-printing code is moved to a new `state` module to ensure that it does not accidentally call any of these public helper functions (instead, the internal functions with the same name should be used).
2 parents f243a2a + 9a6ea38 commit 4ba5068

File tree

14 files changed

+633
-197
lines changed

14 files changed

+633
-197
lines changed

compiler/rustc_ast/src/token.rs

+16-5
Original file line numberDiff line numberDiff line change
@@ -810,25 +810,36 @@ impl Nonterminal {
810810
if let ExpnKind::Macro(_, macro_name) = orig_span.ctxt().outer_expn_data().kind {
811811
let filename = source_map.span_to_filename(orig_span);
812812
if let FileName::Real(RealFileName::Named(path)) = filename {
813-
let matches_prefix = |prefix| {
814-
// Check for a path that ends with 'prefix*/src/lib.rs'
813+
let matches_prefix = |prefix, filename| {
814+
// Check for a path that ends with 'prefix*/src/<filename>'
815815
let mut iter = path.components().rev();
816-
iter.next().and_then(|p| p.as_os_str().to_str()) == Some("lib.rs")
816+
iter.next().and_then(|p| p.as_os_str().to_str()) == Some(filename)
817817
&& iter.next().and_then(|p| p.as_os_str().to_str()) == Some("src")
818818
&& iter
819819
.next()
820820
.and_then(|p| p.as_os_str().to_str())
821821
.map_or(false, |p| p.starts_with(prefix))
822822
};
823823

824-
if (macro_name == sym::impl_macros && matches_prefix("time-macros-impl"))
825-
|| (macro_name == sym::arrays && matches_prefix("js-sys"))
824+
if (macro_name == sym::impl_macros
825+
&& matches_prefix("time-macros-impl", "lib.rs"))
826+
|| (macro_name == sym::arrays && matches_prefix("js-sys", "lib.rs"))
826827
{
827828
let snippet = source_map.span_to_snippet(orig_span);
828829
if snippet.as_deref() == Ok("$name") {
829830
return Some((*ident, *is_raw));
830831
}
831832
}
833+
834+
if macro_name == sym::tuple_from_req
835+
&& (matches_prefix("actix-web", "extract.rs")
836+
|| matches_prefix("actori-web", "extract.rs"))
837+
{
838+
let snippet = source_map.span_to_snippet(orig_span);
839+
if snippet.as_deref() == Ok("$T") {
840+
return Some((*ident, *is_raw));
841+
}
842+
}
832843
}
833844
}
834845
}
+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
#[cfg(test)]
2+
mod tests;
3+
4+
pub mod state;
5+
pub use state::{print_crate, AnnNode, Comments, PpAnn, PrintState, State};
6+
7+
use rustc_ast as ast;
8+
use rustc_ast::token::{Nonterminal, Token, TokenKind};
9+
use rustc_ast::tokenstream::{TokenStream, TokenTree};
10+
11+
pub fn nonterminal_to_string_no_extra_parens(nt: &Nonterminal) -> String {
12+
let state = State::without_insert_extra_parens();
13+
state.nonterminal_to_string(nt)
14+
}
15+
16+
pub fn nonterminal_to_string(nt: &Nonterminal) -> String {
17+
State::new().nonterminal_to_string(nt)
18+
}
19+
20+
/// Print the token kind precisely, without converting `$crate` into its respective crate name.
21+
pub fn token_kind_to_string(tok: &TokenKind) -> String {
22+
State::new().token_kind_to_string(tok)
23+
}
24+
25+
/// Print the token precisely, without converting `$crate` into its respective crate name.
26+
pub fn token_to_string(token: &Token) -> String {
27+
State::new().token_to_string(token)
28+
}
29+
30+
pub fn token_to_string_ext(token: &Token, convert_dollar_crate: bool) -> String {
31+
State::new().token_to_string_ext(token, convert_dollar_crate)
32+
}
33+
34+
pub fn ty_to_string(ty: &ast::Ty) -> String {
35+
State::new().ty_to_string(ty)
36+
}
37+
38+
pub fn bounds_to_string(bounds: &[ast::GenericBound]) -> String {
39+
State::new().bounds_to_string(bounds)
40+
}
41+
42+
pub fn pat_to_string(pat: &ast::Pat) -> String {
43+
State::new().pat_to_string(pat)
44+
}
45+
46+
pub fn expr_to_string(e: &ast::Expr) -> String {
47+
State::new().expr_to_string(e)
48+
}
49+
50+
pub fn tt_to_string(tt: &TokenTree) -> String {
51+
State::new().tt_to_string(tt)
52+
}
53+
54+
pub fn tts_to_string(tokens: &TokenStream) -> String {
55+
State::new().tts_to_string(tokens)
56+
}
57+
58+
pub fn stmt_to_string(stmt: &ast::Stmt) -> String {
59+
State::new().stmt_to_string(stmt)
60+
}
61+
62+
pub fn item_to_string(i: &ast::Item) -> String {
63+
State::new().item_to_string(i)
64+
}
65+
66+
pub fn generic_params_to_string(generic_params: &[ast::GenericParam]) -> String {
67+
State::new().generic_params_to_string(generic_params)
68+
}
69+
70+
pub fn path_to_string(p: &ast::Path) -> String {
71+
State::new().path_to_string(p)
72+
}
73+
74+
pub fn path_segment_to_string(p: &ast::PathSegment) -> String {
75+
State::new().path_segment_to_string(p)
76+
}
77+
78+
pub fn vis_to_string(v: &ast::Visibility) -> String {
79+
State::new().vis_to_string(v)
80+
}
81+
82+
pub fn block_to_string(blk: &ast::Block) -> String {
83+
State::new().block_to_string(blk)
84+
}
85+
86+
pub fn meta_list_item_to_string(li: &ast::NestedMetaItem) -> String {
87+
State::new().meta_list_item_to_string(li)
88+
}
89+
90+
pub fn attr_item_to_string(ai: &ast::AttrItem) -> String {
91+
State::new().attr_item_to_string(ai)
92+
}
93+
94+
pub fn attribute_to_string(attr: &ast::Attribute) -> String {
95+
State::new().attribute_to_string(attr)
96+
}
97+
98+
pub fn param_to_string(arg: &ast::Param) -> String {
99+
State::new().param_to_string(arg)
100+
}
101+
102+
pub fn to_string(f: impl FnOnce(&mut State<'_>)) -> String {
103+
State::new().to_string(f)
104+
}

0 commit comments

Comments
 (0)