delay expand macro bang when there has indeterminate path

This commit is contained in:
bohan 2024-03-12 10:55:17 +08:00
parent 5a6c1aa2bc
commit 8fcdf54a6b
22 changed files with 509 additions and 263 deletions

View file

@ -3,10 +3,9 @@ use rustc_ast::ptr::P;
use rustc_ast::token;
use rustc_ast::tokenstream::TokenStream;
use rustc_ast_pretty::pprust;
use rustc_expand::base::{
check_zero_tts, get_single_str_from_tts, parse_expr, resolve_path, DummyResult, ExtCtxt,
MacEager, MacResult,
};
use rustc_expand::base::{check_zero_tts, get_single_str_from_tts, parse_expr, resolve_path};
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt};
use rustc_expand::base::{MacEager, MacResult, MacroExpanderResult};
use rustc_expand::module::DirOwnership;
use rustc_parse::new_parser_from_file;
use rustc_parse::parser::{ForceCollect, Parser};
@ -26,14 +25,14 @@ pub fn expand_line(
cx: &mut ExtCtxt<'_>,
sp: Span,
tts: TokenStream,
) -> Box<dyn MacResult + 'static> {
) -> MacroExpanderResult<'static> {
let sp = cx.with_def_site_ctxt(sp);
check_zero_tts(cx, sp, tts, "line!");
let topmost = cx.expansion_cause().unwrap_or(sp);
let loc = cx.source_map().lookup_char_pos(topmost.lo());
MacEager::expr(cx.expr_u32(topmost, loc.line as u32))
ExpandResult::Ready(MacEager::expr(cx.expr_u32(topmost, loc.line as u32)))
}
/* column!(): expands to the current column number */
@ -41,14 +40,14 @@ pub fn expand_column(
cx: &mut ExtCtxt<'_>,
sp: Span,
tts: TokenStream,
) -> Box<dyn MacResult + 'static> {
) -> MacroExpanderResult<'static> {
let sp = cx.with_def_site_ctxt(sp);
check_zero_tts(cx, sp, tts, "column!");
let topmost = cx.expansion_cause().unwrap_or(sp);
let loc = cx.source_map().lookup_char_pos(topmost.lo());
MacEager::expr(cx.expr_u32(topmost, loc.col.to_usize() as u32 + 1))
ExpandResult::Ready(MacEager::expr(cx.expr_u32(topmost, loc.col.to_usize() as u32 + 1)))
}
/// file!(): expands to the current filename */
@ -58,7 +57,7 @@ pub fn expand_file(
cx: &mut ExtCtxt<'_>,
sp: Span,
tts: TokenStream,
) -> Box<dyn MacResult + 'static> {
) -> MacroExpanderResult<'static> {
let sp = cx.with_def_site_ctxt(sp);
check_zero_tts(cx, sp, tts, "file!");
@ -66,35 +65,35 @@ pub fn expand_file(
let loc = cx.source_map().lookup_char_pos(topmost.lo());
use rustc_session::{config::RemapPathScopeComponents, RemapFileNameExt};
MacEager::expr(cx.expr_str(
ExpandResult::Ready(MacEager::expr(cx.expr_str(
topmost,
Symbol::intern(
&loc.file.name.for_scope(cx.sess, RemapPathScopeComponents::MACRO).to_string_lossy(),
),
))
)))
}
pub fn expand_stringify(
cx: &mut ExtCtxt<'_>,
sp: Span,
tts: TokenStream,
) -> Box<dyn MacResult + 'static> {
) -> MacroExpanderResult<'static> {
let sp = cx.with_def_site_ctxt(sp);
let s = pprust::tts_to_string(&tts);
MacEager::expr(cx.expr_str(sp, Symbol::intern(&s)))
ExpandResult::Ready(MacEager::expr(cx.expr_str(sp, Symbol::intern(&s))))
}
pub fn expand_mod(
cx: &mut ExtCtxt<'_>,
sp: Span,
tts: TokenStream,
) -> Box<dyn MacResult + 'static> {
) -> MacroExpanderResult<'static> {
let sp = cx.with_def_site_ctxt(sp);
check_zero_tts(cx, sp, tts, "module_path!");
let mod_path = &cx.current_expansion.module.mod_path;
let string = mod_path.iter().map(|x| x.to_string()).collect::<Vec<String>>().join("::");
MacEager::expr(cx.expr_str(sp, Symbol::intern(&string)))
ExpandResult::Ready(MacEager::expr(cx.expr_str(sp, Symbol::intern(&string))))
}
/// include! : parse the given file as an expr
@ -104,18 +103,21 @@ pub fn expand_include<'cx>(
cx: &'cx mut ExtCtxt<'_>,
sp: Span,
tts: TokenStream,
) -> Box<dyn MacResult + 'cx> {
) -> MacroExpanderResult<'cx> {
let sp = cx.with_def_site_ctxt(sp);
let file = match get_single_str_from_tts(cx, sp, tts, "include!") {
let ExpandResult::Ready(mac) = get_single_str_from_tts(cx, sp, tts, "include!") else {
return ExpandResult::Retry(());
};
let file = match mac {
Ok(file) => file,
Err(guar) => return DummyResult::any(sp, guar),
Err(guar) => return ExpandResult::Ready(DummyResult::any(sp, guar)),
};
// The file will be added to the code map by the parser
let file = match resolve_path(&cx.sess, file.as_str(), sp) {
Ok(f) => f,
Err(err) => {
let guar = err.emit();
return DummyResult::any(sp, guar);
return ExpandResult::Ready(DummyResult::any(sp, guar));
}
};
let p = new_parser_from_file(cx.psess(), &file, Some(sp));
@ -128,12 +130,12 @@ pub fn expand_include<'cx>(
cx.current_expansion.module = Rc::new(cx.current_expansion.module.with_dir_path(dir_path));
cx.current_expansion.dir_ownership = DirOwnership::Owned { relative: None };
struct ExpandResult<'a> {
struct ExpandInclude<'a> {
p: Parser<'a>,
node_id: ast::NodeId,
}
impl<'a> MacResult for ExpandResult<'a> {
fn make_expr(mut self: Box<ExpandResult<'a>>) -> Option<P<ast::Expr>> {
impl<'a> MacResult for ExpandInclude<'a> {
fn make_expr(mut self: Box<ExpandInclude<'a>>) -> Option<P<ast::Expr>> {
let expr = parse_expr(&mut self.p).ok()?;
if self.p.token != token::Eof {
self.p.psess.buffer_lint(
@ -146,7 +148,7 @@ pub fn expand_include<'cx>(
Some(expr)
}
fn make_items(mut self: Box<ExpandResult<'a>>) -> Option<SmallVec<[P<ast::Item>; 1]>> {
fn make_items(mut self: Box<ExpandInclude<'a>>) -> Option<SmallVec<[P<ast::Item>; 1]>> {
let mut ret = SmallVec::new();
loop {
match self.p.parse_item(ForceCollect::No) {
@ -170,7 +172,7 @@ pub fn expand_include<'cx>(
}
}
Box::new(ExpandResult { p, node_id: cx.current_expansion.lint_node_id })
ExpandResult::Ready(Box::new(ExpandInclude { p, node_id: cx.current_expansion.lint_node_id }))
}
/// `include_str!`: read the given file, insert it as a literal string expr
@ -178,20 +180,23 @@ pub fn expand_include_str(
cx: &mut ExtCtxt<'_>,
sp: Span,
tts: TokenStream,
) -> Box<dyn MacResult + 'static> {
) -> MacroExpanderResult<'static> {
let sp = cx.with_def_site_ctxt(sp);
let file = match get_single_str_from_tts(cx, sp, tts, "include_str!") {
let ExpandResult::Ready(mac) = get_single_str_from_tts(cx, sp, tts, "include_str!") else {
return ExpandResult::Retry(());
};
let file = match mac {
Ok(file) => file,
Err(guar) => return DummyResult::any(sp, guar),
Err(guar) => return ExpandResult::Ready(DummyResult::any(sp, guar)),
};
let file = match resolve_path(&cx.sess, file.as_str(), sp) {
Ok(f) => f,
Err(err) => {
let guar = err.emit();
return DummyResult::any(sp, guar);
return ExpandResult::Ready(DummyResult::any(sp, guar));
}
};
match cx.source_map().load_binary_file(&file) {
ExpandResult::Ready(match cx.source_map().load_binary_file(&file) {
Ok(bytes) => match std::str::from_utf8(&bytes) {
Ok(src) => {
let interned_src = Symbol::intern(src);
@ -206,27 +211,30 @@ pub fn expand_include_str(
let guar = cx.dcx().span_err(sp, format!("couldn't read {}: {}", file.display(), e));
DummyResult::any(sp, guar)
}
}
})
}
pub fn expand_include_bytes(
cx: &mut ExtCtxt<'_>,
sp: Span,
tts: TokenStream,
) -> Box<dyn MacResult + 'static> {
) -> MacroExpanderResult<'static> {
let sp = cx.with_def_site_ctxt(sp);
let file = match get_single_str_from_tts(cx, sp, tts, "include_bytes!") {
let ExpandResult::Ready(mac) = get_single_str_from_tts(cx, sp, tts, "include_bytes!") else {
return ExpandResult::Retry(());
};
let file = match mac {
Ok(file) => file,
Err(guar) => return DummyResult::any(sp, guar),
Err(guar) => return ExpandResult::Ready(DummyResult::any(sp, guar)),
};
let file = match resolve_path(&cx.sess, file.as_str(), sp) {
Ok(f) => f,
Err(err) => {
let guar = err.emit();
return DummyResult::any(sp, guar);
return ExpandResult::Ready(DummyResult::any(sp, guar));
}
};
match cx.source_map().load_binary_file(&file) {
ExpandResult::Ready(match cx.source_map().load_binary_file(&file) {
Ok(bytes) => {
let expr = cx.expr(sp, ast::ExprKind::IncludedBytes(bytes));
MacEager::expr(expr)
@ -235,5 +243,5 @@ pub fn expand_include_bytes(
let guar = cx.dcx().span_err(sp, format!("couldn't read {}: {}", file.display(), e));
DummyResult::any(sp, guar)
}
}
})
}