9046: fix: make `include!` etc. work in expression position r=jonas-schievink a=jonas-schievink

This PR removes determination of fragment kinds from the eager macro implementations. The fragment kind is always determined by the syntax position in which a macro is invoked, not by the macro implementation, even for eager macros.

This makes `include!` work in expression position, and should have the same effect for all macros that may be used in different positions.

bors r+

Co-authored-by: Jonas Schievink <jonasschievink@gmail.com>
This commit is contained in:
bors[bot] 2021-05-29 15:19:44 +00:00 committed by GitHub
commit 8cd98bde39
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 35 additions and 23 deletions

View file

@ -8,7 +8,6 @@ use base_db::{AnchoredPath, Edition, FileId};
use cfg::CfgExpr;
use either::Either;
use mbe::{parse_exprs_with_sep, parse_to_token_tree, ExpandResult};
use parser::FragmentKind;
use syntax::ast::{self, AstToken};
macro_rules! register_builtin {
@ -47,7 +46,7 @@ macro_rules! register_builtin {
let expander = match *self {
$( EagerExpander::$e_kind => $e_expand, )*
};
expander(db,arg_id,tt)
expander(db, arg_id, tt)
}
}
@ -64,14 +63,13 @@ macro_rules! register_builtin {
#[derive(Debug)]
pub struct ExpandedEager {
pub(crate) subtree: tt::Subtree,
pub(crate) fragment: FragmentKind,
/// The included file ID of the include macro.
pub(crate) included_file: Option<FileId>,
}
impl ExpandedEager {
fn new(subtree: tt::Subtree, fragment: FragmentKind) -> Self {
ExpandedEager { subtree, fragment, included_file: None }
fn new(subtree: tt::Subtree) -> Self {
ExpandedEager { subtree, included_file: None }
}
}
@ -340,7 +338,7 @@ fn compile_error_expand(
_ => mbe::ExpandError::BindingError("`compile_error!` argument must be a string".into()),
};
ExpandResult { value: Some(ExpandedEager::new(quote! {}, FragmentKind::Items)), err: Some(err) }
ExpandResult { value: Some(ExpandedEager::new(quote! {})), err: Some(err) }
}
fn concat_expand(
@ -371,7 +369,7 @@ fn concat_expand(
}
}
}
ExpandResult { value: Some(ExpandedEager::new(quote!(#text), FragmentKind::Expr)), err }
ExpandResult { value: Some(ExpandedEager::new(quote!(#text))), err }
}
fn concat_idents_expand(
@ -393,7 +391,7 @@ fn concat_idents_expand(
}
}
let ident = tt::Ident { text: ident.into(), id: tt::TokenId::unspecified() };
ExpandResult { value: Some(ExpandedEager::new(quote!(#ident), FragmentKind::Expr)), err }
ExpandResult { value: Some(ExpandedEager::new(quote!(#ident))), err }
}
fn relative_file(
@ -442,14 +440,7 @@ fn include_expand(
match res {
Ok((subtree, file_id)) => {
// FIXME:
// Handle include as expression
ExpandResult::ok(Some(ExpandedEager {
subtree,
fragment: FragmentKind::Items,
included_file: Some(file_id),
}))
ExpandResult::ok(Some(ExpandedEager { subtree, included_file: Some(file_id) }))
}
Err(e) => ExpandResult::only_err(e),
}
@ -472,7 +463,7 @@ fn include_bytes_expand(
id: tt::TokenId::unspecified(),
}))],
};
ExpandResult::ok(Some(ExpandedEager::new(res, FragmentKind::Expr)))
ExpandResult::ok(Some(ExpandedEager::new(res)))
}
fn include_str_expand(
@ -492,14 +483,14 @@ fn include_str_expand(
let file_id = match relative_file(db, arg_id.into(), &path, true) {
Ok(file_id) => file_id,
Err(_) => {
return ExpandResult::ok(Some(ExpandedEager::new(quote!(""), FragmentKind::Expr)));
return ExpandResult::ok(Some(ExpandedEager::new(quote!(""))));
}
};
let text = db.file_text(file_id);
let text = &*text;
ExpandResult::ok(Some(ExpandedEager::new(quote!(#text), FragmentKind::Expr)))
ExpandResult::ok(Some(ExpandedEager::new(quote!(#text))))
}
fn get_env_inner(db: &dyn AstDatabase, arg_id: MacroCallId, key: &str) -> Option<String> {
@ -535,7 +526,7 @@ fn env_expand(
});
let expanded = quote! { #s };
ExpandResult { value: Some(ExpandedEager::new(expanded, FragmentKind::Expr)), err }
ExpandResult { value: Some(ExpandedEager::new(expanded)), err }
}
fn option_env_expand(
@ -553,7 +544,7 @@ fn option_env_expand(
Some(s) => quote! { std::option::Some(#s) },
};
ExpandResult::ok(Some(ExpandedEager::new(expanded, FragmentKind::Expr)))
ExpandResult::ok(Some(ExpandedEager::new(expanded)))
}
#[cfg(test)]
@ -565,6 +556,7 @@ mod tests {
};
use base_db::{fixture::WithFixture, SourceDatabase};
use expect_test::{expect, Expect};
use parser::FragmentKind;
use std::sync::Arc;
use syntax::ast::NameOwner;
@ -617,6 +609,7 @@ mod tests {
local_inner: false,
};
let fragment = crate::to_fragment_kind(&macro_call);
let args = macro_call.token_tree().unwrap();
let parsed_args = mbe::ast_to_token_tree(&args).0;
let call_id = AstId::new(file_id.into(), ast_id_map.ast_id(&macro_call));
@ -639,7 +632,7 @@ mod tests {
arg_or_expansion: Arc::new(expanded.subtree),
included_file: expanded.included_file,
}),
kind: MacroCallKind::FnLike { ast_id: call_id, fragment: expanded.fragment },
kind: MacroCallKind::FnLike { ast_id: call_id, fragment },
};
let id: MacroCallId = db.intern_macro(loc).into();

View file

@ -113,6 +113,7 @@ pub fn expand_eager_macro(
let ast_map = db.ast_id_map(macro_call.file_id);
let call_id = InFile::new(macro_call.file_id, ast_map.ast_id(&macro_call.value));
let fragment = crate::to_fragment_kind(&macro_call.value);
// Note:
// When `lazy_expand` is called, its *parent* file must be already exists.
@ -152,7 +153,7 @@ pub fn expand_eager_macro(
arg_or_expansion: Arc::new(expanded.subtree),
included_file: expanded.included_file,
}),
kind: MacroCallKind::FnLike { ast_id: call_id, fragment: expanded.fragment },
kind: MacroCallKind::FnLike { ast_id: call_id, fragment },
};
Ok(db.intern_macro(loc))

View file

@ -751,6 +751,24 @@ fn bar() -> u32 {0}
);
}
#[test]
fn infer_builtin_macros_include_expression() {
check_types(
r#"
//- /main.rs
#[rustc_builtin_macro]
macro_rules! include {() => {}}
fn main() {
let i = include!("bla.rs");
i;
//^ i32
}
//- /bla.rs
0
"#,
)
}
#[test]
fn infer_builtin_macros_include_child_mod() {
check_types(