diff options
| author | bohan <bohan-zhang@foxmail.com> | 2024-03-12 10:55:17 +0800 | 
|---|---|---|
| committer | bohan <bohan-zhang@foxmail.com> | 2024-03-13 16:11:16 +0800 | 
| commit | 8fcdf54a6b98c129e951caf3a97cbf20db677ee3 (patch) | |
| tree | f34b8d1a37fdbe0e539f2c38e91b74a4358d98ef /compiler/rustc_expand/src | |
| parent | 5a6c1aa2bccfcbfa42f486a54c09bd698378faef (diff) | |
| download | rust-8fcdf54a6b98c129e951caf3a97cbf20db677ee3.tar.gz rust-8fcdf54a6b98c129e951caf3a97cbf20db677ee3.zip | |
delay expand macro bang when there has indeterminate path
Diffstat (limited to 'compiler/rustc_expand/src')
| -rw-r--r-- | compiler/rustc_expand/src/base.rs | 95 | ||||
| -rw-r--r-- | compiler/rustc_expand/src/expand.rs | 13 | ||||
| -rw-r--r-- | compiler/rustc_expand/src/mbe/macro_rules.rs | 14 | 
3 files changed, 89 insertions, 33 deletions
| diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 69dfb48919c..30ee02ea3c0 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -245,6 +245,15 @@ pub enum ExpandResult<T, U> { Retry(U), } +impl<T, U> ExpandResult<T, U> { + pub fn map<E, F: FnOnce(T) -> E>(self, f: F) -> ExpandResult<E, U> { + match self { + ExpandResult::Ready(t) => ExpandResult::Ready(f(t)), + ExpandResult::Retry(u) => ExpandResult::Retry(u), + } + } +} + pub trait MultiItemModifier { /// `meta_item` is the attribute, and `item` is the item being modified. fn expand( @@ -330,22 +339,24 @@ pub trait TTMacroExpander { ecx: &'cx mut ExtCtxt<'_>, span: Span, input: TokenStream, - ) -> Box<dyn MacResult + 'cx>; + ) -> MacroExpanderResult<'cx>; } +pub type MacroExpanderResult<'cx> = ExpandResult<Box<dyn MacResult + 'cx>, ()>; + pub type MacroExpanderFn = - for<'cx> fn(&'cx mut ExtCtxt<'_>, Span, TokenStream) -> Box<dyn MacResult + 'cx>; + for<'cx> fn(&'cx mut ExtCtxt<'_>, Span, TokenStream) -> MacroExpanderResult<'cx>; impl<F> TTMacroExpander for F where - F: for<'cx> Fn(&'cx mut ExtCtxt<'_>, Span, TokenStream) -> Box<dyn MacResult + 'cx>, + F: for<'cx> Fn(&'cx mut ExtCtxt<'_>, Span, TokenStream) -> MacroExpanderResult<'cx>, { fn expand<'cx>( &self, ecx: &'cx mut ExtCtxt<'_>, span: Span, input: TokenStream, - ) -> Box<dyn MacResult + 'cx> { + ) -> MacroExpanderResult<'cx> { self(ecx, span, input) } } @@ -904,8 +915,11 @@ impl SyntaxExtension { cx: &'cx mut ExtCtxt<'_>, span: Span, _: TokenStream, - ) -> Box<dyn MacResult + 'cx> { - DummyResult::any(span, cx.dcx().span_delayed_bug(span, "expanded a dummy bang macro")) + ) -> MacroExpanderResult<'cx> { + ExpandResult::Ready(DummyResult::any( + span, + cx.dcx().span_delayed_bug(span, "expanded a dummy bang macro"), + )) } SyntaxExtension::default(SyntaxExtensionKind::LegacyBang(Box::new(expander)), edition) } @@ -1008,6 +1022,11 @@ pub trait ResolverExpand { expn_id: LocalExpnId, path: &ast::Path, ) -> Result<bool, Indeterminate>; + fn macro_accessible( + &mut self, + expn_id: LocalExpnId, + path: &ast::Path, + ) -> Result<bool, Indeterminate>; /// Decodes the proc-macro quoted span in the specified crate, with the specified id. /// No caching is performed. @@ -1253,6 +1272,15 @@ pub fn resolve_path(sess: &Session, path: impl Into<PathBuf>, span: Span) -> PRe } } +/// `Ok` represents successfully retrieving the string literal at the correct +/// position, e.g., `println("abc")`. +type ExprToSpannedStringResult<'a> = Result<(Symbol, ast::StrStyle, Span), UnexpectedExprKind<'a>>; + +/// - `Ok` is returned when the conversion to a string literal is unsuccessful, +/// but another type of expression is obtained instead. +/// - `Err` is returned when the conversion process fails. +type UnexpectedExprKind<'a> = Result<(Diag<'a>, bool /* has_suggestions */), ErrorGuaranteed>; + /// Extracts a string literal from the macro expanded version of `expr`, /// returning a diagnostic error of `err_msg` if `expr` is not a string literal. /// The returned bool indicates whether an applicable suggestion has already been @@ -1264,17 +1292,23 @@ pub fn expr_to_spanned_string<'a>( cx: &'a mut ExtCtxt<'_>, expr: P<ast::Expr>, err_msg: &'static str, -) -> Result< - (Symbol, ast::StrStyle, Span), - Result<(Diag<'a>, bool /* has_suggestions */), ErrorGuaranteed>, -> { +) -> ExpandResult<ExprToSpannedStringResult<'a>, ()> { + if !cx.force_mode + && let ast::ExprKind::MacCall(m) = &expr.kind + && cx.resolver.macro_accessible(cx.current_expansion.id, &m.path).is_err() + { + return ExpandResult::Retry(()); + } + // Perform eager expansion on the expression. // We want to be able to handle e.g., `concat!("foo", "bar")`. let expr = cx.expander().fully_expand_fragment(AstFragment::Expr(expr)).make_expr(); - Err(match expr.kind { + ExpandResult::Ready(Err(match expr.kind { ast::ExprKind::Lit(token_lit) => match ast::LitKind::from_token_lit(token_lit) { - Ok(ast::LitKind::Str(s, style)) => return Ok((s, style, expr.span)), + Ok(ast::LitKind::Str(s, style)) => { + return ExpandResult::Ready(Ok((s, style, expr.span))); + } Ok(ast::LitKind::ByteStr(..)) => { let mut err = cx.dcx().struct_span_err(expr.span, err_msg); let span = expr.span.shrink_to_lo(); @@ -1295,7 +1329,7 @@ pub fn expr_to_spanned_string<'a>( cx.dcx().span_bug(expr.span, "tried to get a string literal from `ExprKind::Dummy`") } _ => Ok((cx.dcx().struct_span_err(expr.span, err_msg), false)), - }) + })) } /// Extracts a string literal from the macro expanded version of `expr`, @@ -1305,13 +1339,14 @@ pub fn expr_to_string( cx: &mut ExtCtxt<'_>, expr: P<ast::Expr>, err_msg: &'static str, -) -> Result<(Symbol, ast::StrStyle), ErrorGuaranteed> { - expr_to_spanned_string(cx, expr, err_msg) - .map_err(|err| match err { +) -> ExpandResult<Result<(Symbol, ast::StrStyle), ErrorGuaranteed>, ()> { + expr_to_spanned_string(cx, expr, err_msg).map(|res| { + res.map_err(|err| match err { Ok((err, _)) => err.emit(), Err(guar) => guar, }) .map(|(symbol, style, _)| (symbol, style)) + }) } /// Non-fatally assert that `tts` is empty. Note that this function @@ -1343,19 +1378,22 @@ pub fn get_single_str_from_tts( span: Span, tts: TokenStream, name: &str, -) -> Result<Symbol, ErrorGuaranteed> { +) -> ExpandResult<Result<Symbol, ErrorGuaranteed>, ()> { let mut p = cx.new_parser_from_tts(tts); if p.token == token::Eof { let guar = cx.dcx().emit_err(errors::OnlyOneArgument { span, name }); - return Err(guar); + return ExpandResult::Ready(Err(guar)); } - let ret = parse_expr(&mut p)?; + let ret = match parse_expr(&mut p) { + Ok(ret) => ret, + Err(guar) => return ExpandResult::Ready(Err(guar)), + }; let _ = p.eat(&token::Comma); if p.token != token::Eof { cx.dcx().emit_err(errors::OnlyOneArgument { span, name }); } - expr_to_string(cx, ret, "argument must be a string literal").map(|(s, _)| s) + expr_to_string(cx, ret, "argument must be a string literal").map(|s| s.map(|(s, _)| s)) } /// Extracts comma-separated expressions from `tts`. @@ -1363,11 +1401,20 @@ pub fn get_single_str_from_tts( pub fn get_exprs_from_tts( cx: &mut ExtCtxt<'_>, tts: TokenStream, -) -> Result<Vec<P<ast::Expr>>, ErrorGuaranteed> { +) -> ExpandResult<Result<Vec<P<ast::Expr>>, ErrorGuaranteed>, ()> { let mut p = cx.new_parser_from_tts(tts); let mut es = Vec::new(); while p.token != token::Eof { - let expr = parse_expr(&mut p)?; + let expr = match parse_expr(&mut p) { + Ok(expr) => expr, + Err(guar) => return ExpandResult::Ready(Err(guar)), + }; + if !cx.force_mode + && let ast::ExprKind::MacCall(m) = &expr.kind + && cx.resolver.macro_accessible(cx.current_expansion.id, &m.path).is_err() + { + return ExpandResult::Retry(()); + } // Perform eager expansion on the expression. // We want to be able to handle e.g., `concat!("foo", "bar")`. @@ -1379,10 +1426,10 @@ pub fn get_exprs_from_tts( } if p.token != token::Eof { let guar = cx.dcx().emit_err(errors::ExpectedCommaInList { span: p.token.span }); - return Err(guar); + return ExpandResult::Ready(Err(guar)); } } - Ok(es) + ExpandResult::Ready(Ok(es)) } pub fn parse_macro_name_and_helper_attrs( diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index fcc439e71f9..3544a8f0a8d 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -659,7 +659,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let (fragment_kind, span) = (invoc.fragment_kind, invoc.span()); ExpandResult::Ready(match invoc.kind { - InvocationKind::Bang { mac, .. } => match ext { + InvocationKind::Bang { mac, span } => match ext { SyntaxExtensionKind::Bang(expander) => { match expander.expand(self.cx, span, mac.args.tokens.clone()) { Ok(tok_result) => { @@ -669,7 +669,16 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } } SyntaxExtensionKind::LegacyBang(expander) => { - let tok_result = expander.expand(self.cx, span, mac.args.tokens.clone()); + let tok_result = match expander.expand(self.cx, span, mac.args.tokens.clone()) { + ExpandResult::Ready(tok_result) => tok_result, + ExpandResult::Retry(_) => { + // retry the original + return ExpandResult::Retry(Invocation { + kind: InvocationKind::Bang { mac, span }, + ..invoc + }); + } + }; let result = if let Some(result) = fragment_kind.make_from(tok_result) { result } else { diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 8903fc45def..3f29d7f7465 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -1,5 +1,5 @@ -use crate::base::{DummyResult, ExtCtxt, MacResult, TTMacroExpander}; -use crate::base::{SyntaxExtension, SyntaxExtensionKind}; +use crate::base::{DummyResult, SyntaxExtension, SyntaxExtensionKind}; +use crate::base::{ExpandResult, ExtCtxt, MacResult, MacroExpanderResult, TTMacroExpander}; use crate::expand::{ensure_complete_parse, parse_ast_fragment, AstFragment, AstFragmentKind}; use crate::mbe; use crate::mbe::diagnostics::{annotate_doc_comment, parse_failure_msg}; @@ -111,8 +111,8 @@ impl TTMacroExpander for MacroRulesMacroExpander { cx: &'cx mut ExtCtxt<'_>, sp: Span, input: TokenStream, - ) -> Box<dyn MacResult + 'cx> { - expand_macro( + ) -> MacroExpanderResult<'cx> { + ExpandResult::Ready(expand_macro( cx, sp, self.span, @@ -122,7 +122,7 @@ impl TTMacroExpander for MacroRulesMacroExpander { input, &self.lhses, &self.rhses, - ) + )) } } @@ -134,8 +134,8 @@ impl TTMacroExpander for DummyExpander { _: &'cx mut ExtCtxt<'_>, span: Span, _: TokenStream, - ) -> Box<dyn MacResult + 'cx> { - DummyResult::any(span, self.0) + ) -> ExpandResult<Box<dyn MacResult + 'cx>, ()> { + ExpandResult::Ready(DummyResult::any(span, self.0)) } } | 
