Skip to content

Commit 96edbd6

Browse files
committed
Strip frontmatter in fewer places
1 parent ec87250 commit 96edbd6

File tree

21 files changed

+193
-107
lines changed

21 files changed

+193
-107
lines changed

compiler/rustc_builtin_macros/src/source_util.rs

Lines changed: 44 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@ use rustc_expand::base::{
1313
};
1414
use rustc_expand::module::DirOwnership;
1515
use rustc_lint_defs::BuiltinLintDiag;
16-
use rustc_parse::parser::{ForceCollect, Parser};
16+
use rustc_parse::lexer::StripTokens;
17+
use rustc_parse::parser::ForceCollect;
1718
use rustc_parse::{new_parser_from_file, unwrap_or_emit_fatal, utf8_error};
1819
use rustc_session::lint::builtin::INCOMPLETE_INCLUDE;
20+
use rustc_session::parse::ParseSess;
1921
use rustc_span::source_map::SourceMap;
2022
use rustc_span::{ByteSymbol, Pos, Span, Symbol};
2123
use smallvec::SmallVec;
@@ -114,64 +116,76 @@ pub(crate) fn expand_include<'cx>(
114116
let ExpandResult::Ready(mac) = get_single_str_from_tts(cx, sp, tts, "include!") else {
115117
return ExpandResult::Retry(());
116118
};
117-
let file = match mac {
118-
Ok(file) => file,
119+
let path = match mac {
120+
Ok(path) => path,
119121
Err(guar) => return ExpandResult::Ready(DummyResult::any(sp, guar)),
120122
};
121123
// The file will be added to the code map by the parser
122-
let file = match resolve_path(&cx.sess, file.as_str(), sp) {
123-
Ok(f) => f,
124+
let path = match resolve_path(&cx.sess, path.as_str(), sp) {
125+
Ok(path) => path,
124126
Err(err) => {
125127
let guar = err.emit();
126128
return ExpandResult::Ready(DummyResult::any(sp, guar));
127129
}
128130
};
129-
let p = unwrap_or_emit_fatal(new_parser_from_file(cx.psess(), &file, Some(sp)));
130131

131132
// If in the included file we have e.g., `mod bar;`,
132-
// then the path of `bar.rs` should be relative to the directory of `file`.
133+
// then the path of `bar.rs` should be relative to the directory of `path`.
133134
// See https://github.com/rust-lang/rust/pull/69838/files#r395217057 for a discussion.
134135
// `MacroExpander::fully_expand_fragment` later restores, so "stack discipline" is maintained.
135-
let dir_path = file.parent().unwrap_or(&file).to_owned();
136+
let dir_path = path.parent().unwrap_or(&path).to_owned();
136137
cx.current_expansion.module = Rc::new(cx.current_expansion.module.with_dir_path(dir_path));
137138
cx.current_expansion.dir_ownership = DirOwnership::Owned { relative: None };
138139

139140
struct ExpandInclude<'a> {
140-
p: Parser<'a>,
141+
psess: &'a ParseSess,
142+
path: PathBuf,
141143
node_id: ast::NodeId,
144+
span: Span,
142145
}
143146
impl<'a> MacResult for ExpandInclude<'a> {
144-
fn make_expr(mut self: Box<ExpandInclude<'a>>) -> Option<Box<ast::Expr>> {
145-
let expr = parse_expr(&mut self.p).ok()?;
146-
if self.p.token != token::Eof {
147-
self.p.psess.buffer_lint(
147+
fn make_expr(self: Box<ExpandInclude<'a>>) -> Option<Box<ast::Expr>> {
148+
let mut p = unwrap_or_emit_fatal(new_parser_from_file(
149+
self.psess,
150+
&self.path,
151+
// Don't strip frontmatter for backward compatibility, `---` may be the start of a
152+
// manifold negation. FIXME: Ideally, we wouldn't strip shebangs here either.
153+
StripTokens::Shebang,
154+
Some(self.span),
155+
));
156+
let expr = parse_expr(&mut p).ok()?;
157+
if p.token != token::Eof {
158+
p.psess.buffer_lint(
148159
INCOMPLETE_INCLUDE,
149-
self.p.token.span,
160+
p.token.span,
150161
self.node_id,
151162
BuiltinLintDiag::IncompleteInclude,
152163
);
153164
}
154165
Some(expr)
155166
}
156167

157-
fn make_items(mut self: Box<ExpandInclude<'a>>) -> Option<SmallVec<[Box<ast::Item>; 1]>> {
168+
fn make_items(self: Box<ExpandInclude<'a>>) -> Option<SmallVec<[Box<ast::Item>; 1]>> {
169+
let mut p = unwrap_or_emit_fatal(new_parser_from_file(
170+
self.psess,
171+
&self.path,
172+
StripTokens::ShebangAndFrontmatter,
173+
Some(self.span),
174+
));
158175
let mut ret = SmallVec::new();
159176
loop {
160-
match self.p.parse_item(ForceCollect::No) {
177+
match p.parse_item(ForceCollect::No) {
161178
Err(err) => {
162179
err.emit();
163180
break;
164181
}
165182
Ok(Some(item)) => ret.push(item),
166183
Ok(None) => {
167-
if self.p.token != token::Eof {
168-
self.p
169-
.dcx()
170-
.create_err(errors::ExpectedItem {
171-
span: self.p.token.span,
172-
token: &pprust::token_to_string(&self.p.token),
173-
})
174-
.emit();
184+
if p.token != token::Eof {
185+
p.dcx().emit_err(errors::ExpectedItem {
186+
span: p.token.span,
187+
token: &pprust::token_to_string(&p.token),
188+
});
175189
}
176190

177191
break;
@@ -182,7 +196,12 @@ pub(crate) fn expand_include<'cx>(
182196
}
183197
}
184198

185-
ExpandResult::Ready(Box::new(ExpandInclude { p, node_id: cx.current_expansion.lint_node_id }))
199+
ExpandResult::Ready(Box::new(ExpandInclude {
200+
psess: cx.psess(),
201+
path,
202+
node_id: cx.current_expansion.lint_node_id,
203+
span: sp,
204+
}))
186205
}
187206

188207
/// Expand `include_str!($input)` to the content of the UTF-8-encoded file given by path `$input` as a string literal.

compiler/rustc_driver_impl/src/lib.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ use rustc_lint::unerased_lint_store;
5151
use rustc_metadata::creader::MetadataLoader;
5252
use rustc_metadata::locator;
5353
use rustc_middle::ty::TyCtxt;
54+
use rustc_parse::lexer::StripTokens;
5455
use rustc_parse::{new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal};
5556
use rustc_session::config::{
5657
CG_OPTIONS, CrateType, ErrorOutputType, Input, OptionDesc, OutFileName, OutputType, Sysroot,
@@ -1288,10 +1289,15 @@ fn warn_on_confusing_output_filename_flag(
12881289

12891290
fn parse_crate_attrs<'a>(sess: &'a Session) -> PResult<'a, ast::AttrVec> {
12901291
let mut parser = unwrap_or_emit_fatal(match &sess.io.input {
1291-
Input::File(file) => new_parser_from_file(&sess.psess, file, None),
1292-
Input::Str { name, input } => {
1293-
new_parser_from_source_str(&sess.psess, name.clone(), input.clone())
1292+
Input::File(file) => {
1293+
new_parser_from_file(&sess.psess, file, StripTokens::ShebangAndFrontmatter, None)
12941294
}
1295+
Input::Str { name, input } => new_parser_from_source_str(
1296+
&sess.psess,
1297+
name.clone(),
1298+
input.clone(),
1299+
StripTokens::ShebangAndFrontmatter,
1300+
),
12951301
});
12961302
parser.parse_inner_attributes()
12971303
}

compiler/rustc_expand/src/module.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use std::path::{self, Path, PathBuf};
44
use rustc_ast::{AttrVec, Attribute, Inline, Item, ModSpans};
55
use rustc_attr_parsing::validate_attr;
66
use rustc_errors::{Diag, ErrorGuaranteed};
7+
use rustc_parse::lexer::StripTokens;
78
use rustc_parse::{exp, new_parser_from_file, unwrap_or_emit_fatal};
89
use rustc_session::Session;
910
use rustc_session::parse::ParseSess;
@@ -67,8 +68,12 @@ pub(crate) fn parse_external_mod(
6768
}
6869

6970
// Actually parse the external file as a module.
70-
let mut parser =
71-
unwrap_or_emit_fatal(new_parser_from_file(&sess.psess, &mp.file_path, Some(span)));
71+
let mut parser = unwrap_or_emit_fatal(new_parser_from_file(
72+
&sess.psess,
73+
&mp.file_path,
74+
StripTokens::ShebangAndFrontmatter,
75+
Some(span),
76+
));
7277
let (inner_attrs, items, inner_span) =
7378
parser.parse_mod(exp!(Eof)).map_err(|err| ModError::ParserError(err))?;
7479
attrs.extend(inner_attrs);

compiler/rustc_expand/src/proc_macro_server.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use rustc_ast::util::literal::escape_byte_str_symbol;
88
use rustc_ast_pretty::pprust;
99
use rustc_data_structures::fx::FxHashMap;
1010
use rustc_errors::{Diag, ErrorGuaranteed, MultiSpan, PResult};
11-
use rustc_parse::lexer::nfc_normalize;
11+
use rustc_parse::lexer::{StripTokens, nfc_normalize};
1212
use rustc_parse::parser::Parser;
1313
use rustc_parse::{exp, new_parser_from_source_str, source_str_to_stream, unwrap_or_emit_fatal};
1414
use rustc_proc_macro::bridge::{
@@ -485,8 +485,13 @@ impl server::FreeFunctions for Rustc<'_, '_> {
485485

486486
fn literal_from_str(&mut self, s: &str) -> Result<Literal<Self::Span, Self::Symbol>, ()> {
487487
let name = FileName::proc_macro_source_code(s);
488-
let mut parser =
489-
unwrap_or_emit_fatal(new_parser_from_source_str(self.psess(), name, s.to_owned()));
488+
489+
let mut parser = unwrap_or_emit_fatal(new_parser_from_source_str(
490+
self.psess(),
491+
name,
492+
s.to_owned(),
493+
StripTokens::Nothing,
494+
));
490495

491496
let first_span = parser.token.span.data();
492497
let minus_present = parser.eat(exp!(Minus));

compiler/rustc_interface/src/interface.rs

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ use rustc_lint::LintStore;
1313
use rustc_middle::ty;
1414
use rustc_middle::ty::CurrentGcx;
1515
use rustc_middle::util::Providers;
16-
use rustc_parse::new_parser_from_simple_source_str;
16+
use rustc_parse::lexer::StripTokens;
17+
use rustc_parse::new_parser_from_source_str;
1718
use rustc_parse::parser::attr::AllowLeadingUnsafe;
1819
use rustc_query_impl::QueryCtxt;
1920
use rustc_query_system::query::print_query_stack;
@@ -68,7 +69,8 @@ pub(crate) fn parse_cfg(dcx: DiagCtxtHandle<'_>, cfgs: Vec<String>) -> Cfg {
6869
};
6970
}
7071

71-
match new_parser_from_simple_source_str(&psess, filename, s.to_string()) {
72+
match new_parser_from_source_str(&psess, filename, s.to_string(), StripTokens::Nothing)
73+
{
7274
Ok(mut parser) => match parser.parse_meta_item(AllowLeadingUnsafe::No) {
7375
Ok(meta_item) if parser.token == token::Eof => {
7476
if meta_item.path.segments.len() != 1 {
@@ -166,13 +168,15 @@ pub(crate) fn parse_check_cfg(dcx: DiagCtxtHandle<'_>, specs: Vec<String>) -> Ch
166168
error!("expected `cfg(name, values(\"value1\", \"value2\", ... \"valueN\"))`")
167169
};
168170

169-
let mut parser = match new_parser_from_simple_source_str(&psess, filename, s.to_string()) {
170-
Ok(parser) => parser,
171-
Err(errs) => {
172-
errs.into_iter().for_each(|err| err.cancel());
173-
expected_error();
174-
}
175-
};
171+
let mut parser =
172+
match new_parser_from_source_str(&psess, filename, s.to_string(), StripTokens::Nothing)
173+
{
174+
Ok(parser) => parser,
175+
Err(errs) => {
176+
errs.into_iter().for_each(|err| err.cancel());
177+
expected_error();
178+
}
179+
};
176180

177181
let meta_item = match parser.parse_meta_item(AllowLeadingUnsafe::No) {
178182
Ok(meta_item) if parser.token == token::Eof => meta_item,

compiler/rustc_interface/src/passes.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use rustc_middle::arena::Arena;
2727
use rustc_middle::dep_graph::DepsType;
2828
use rustc_middle::ty::{self, CurrentGcx, GlobalCtxt, RegisteredTools, TyCtxt};
2929
use rustc_middle::util::Providers;
30+
use rustc_parse::lexer::StripTokens;
3031
use rustc_parse::{new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal};
3132
use rustc_passes::{abi_test, input_stats, layout_test};
3233
use rustc_resolve::{Resolver, ResolverOutputs};
@@ -51,10 +52,18 @@ pub fn parse<'a>(sess: &'a Session) -> ast::Crate {
5152
let mut krate = sess
5253
.time("parse_crate", || {
5354
let mut parser = unwrap_or_emit_fatal(match &sess.io.input {
54-
Input::File(file) => new_parser_from_file(&sess.psess, file, None),
55-
Input::Str { input, name } => {
56-
new_parser_from_source_str(&sess.psess, name.clone(), input.clone())
57-
}
55+
Input::File(file) => new_parser_from_file(
56+
&sess.psess,
57+
file,
58+
StripTokens::ShebangAndFrontmatter,
59+
None,
60+
),
61+
Input::Str { input, name } => new_parser_from_source_str(
62+
&sess.psess,
63+
name.clone(),
64+
input.clone(),
65+
StripTokens::ShebangAndFrontmatter,
66+
),
5867
});
5968
parser.parse_crate_mod()
6069
})

compiler/rustc_parse/src/lexer/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ pub(crate) struct UnmatchedDelim {
4545
}
4646

4747
/// Which tokens should be stripped before lexing the tokens.
48-
pub(crate) enum StripTokens {
48+
pub enum StripTokens {
4949
/// Strip both shebang and frontmatter.
5050
ShebangAndFrontmatter,
5151
/// Strip the shebang but not frontmatter.

compiler/rustc_parse/src/lib.rs

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -54,29 +54,18 @@ pub fn unwrap_or_emit_fatal<T>(expr: Result<T, Vec<Diag<'_>>>) -> T {
5454
}
5555
}
5656

57-
/// Creates a new parser from a source string. On failure, the errors must be consumed via
58-
/// `unwrap_or_emit_fatal`, `emit`, `cancel`, etc., otherwise a panic will occur when they are
59-
/// dropped.
60-
pub fn new_parser_from_source_str(
61-
psess: &ParseSess,
62-
name: FileName,
63-
source: String,
64-
) -> Result<Parser<'_>, Vec<Diag<'_>>> {
65-
let source_file = psess.source_map().new_source_file(name, source);
66-
new_parser_from_source_file(psess, source_file, StripTokens::ShebangAndFrontmatter)
67-
}
68-
69-
/// Creates a new parser from a simple (no shebang, no frontmatter) source string.
57+
/// Creates a new parser from a source string.
7058
///
7159
/// On failure, the errors must be consumed via `unwrap_or_emit_fatal`, `emit`, `cancel`,
7260
/// etc., otherwise a panic will occur when they are dropped.
73-
pub fn new_parser_from_simple_source_str(
61+
pub fn new_parser_from_source_str(
7462
psess: &ParseSess,
7563
name: FileName,
7664
source: String,
65+
strip_tokens: StripTokens,
7766
) -> Result<Parser<'_>, Vec<Diag<'_>>> {
7867
let source_file = psess.source_map().new_source_file(name, source);
79-
new_parser_from_source_file(psess, source_file, StripTokens::Nothing)
68+
new_parser_from_source_file(psess, source_file, strip_tokens)
8069
}
8170

8271
/// Creates a new parser from a filename. On failure, the errors must be consumed via
@@ -87,6 +76,7 @@ pub fn new_parser_from_simple_source_str(
8776
pub fn new_parser_from_file<'a>(
8877
psess: &'a ParseSess,
8978
path: &Path,
79+
strip_tokens: StripTokens,
9080
sp: Option<Span>,
9181
) -> Result<Parser<'a>, Vec<Diag<'a>>> {
9282
let sm = psess.source_map();
@@ -110,7 +100,7 @@ pub fn new_parser_from_file<'a>(
110100
}
111101
err.emit();
112102
});
113-
new_parser_from_source_file(psess, source_file, StripTokens::ShebangAndFrontmatter)
103+
new_parser_from_source_file(psess, source_file, strip_tokens)
114104
}
115105

116106
pub fn utf8_error<E: EmissionGuarantee>(
@@ -172,20 +162,26 @@ fn new_parser_from_source_file(
172162
Ok(parser)
173163
}
174164

165+
/// Given a source string, produces a sequence of token trees.
166+
///
167+
/// NOTE: This only strips shebangs, not frontmatter!
175168
pub fn source_str_to_stream(
176169
psess: &ParseSess,
177170
name: FileName,
178171
source: String,
179172
override_span: Option<Span>,
180173
) -> Result<TokenStream, Vec<Diag<'_>>> {
181174
let source_file = psess.source_map().new_source_file(name, source);
182-
// used mainly for `proc_macro` and the likes, not for our parsing purposes, so don't parse
183-
// frontmatters as frontmatters, but for compatibility reason still strip the shebang
175+
// FIXME(frontmatter): Consider stripping frontmatter in a future edition. We can't strip them
176+
// in the current edition since that would be breaking.
177+
// See also <https://github.com/rust-lang/rust/issues/145520>.
178+
// Alternatively, stop stripping shebangs here, too, if T-lang and crater approve.
184179
source_file_to_stream(psess, source_file, override_span, StripTokens::Shebang)
185180
}
186181

187-
/// Given a source file, produces a sequence of token trees. Returns any buffered errors from
188-
/// parsing the token stream.
182+
/// Given a source file, produces a sequence of token trees.
183+
///
184+
/// Returns any buffered errors from parsing the token stream.
189185
fn source_file_to_stream<'psess>(
190186
psess: &'psess ParseSess,
191187
source_file: Arc<SourceFile>,

0 commit comments

Comments
 (0)