mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-25 20:43:21 +00:00
Merge #3429
3429: Fix panic on eager expansion r=matklad a=edwin0cheng When lazy expanding inside an eager macro, its *parent* file of that lazy macro call must be already exists such that a panic is occurred because that parent file is the eager macro we are processing. This PR fix this bug by store the argument syntax node as another eager macro id for that purpose. Personally I don't know if it is a good answer for this bug. Co-authored-by: Edwin Cheng <edwin0cheng@gmail.com>
This commit is contained in:
commit
437329d3f5
2 changed files with 39 additions and 2 deletions
|
@ -37,9 +37,25 @@ pub fn expand_eager_macro(
|
|||
) -> Option<EagerMacroId> {
|
||||
let args = macro_call.value.token_tree()?;
|
||||
let parsed_args = mbe::ast_to_token_tree(&args)?.0;
|
||||
let parsed_args = mbe::token_tree_to_syntax_node(&parsed_args, FragmentKind::Expr).ok()?.0;
|
||||
let result = eager_macro_recur(db, macro_call.with_value(parsed_args.syntax_node()), resolver)?;
|
||||
|
||||
// Note:
|
||||
// When `lazy_expand` is called, its *parent* file must be already exists.
|
||||
// Here we store an eager macro id for the argument expanded subtree here
|
||||
// for that purpose.
|
||||
let arg_id: MacroCallId = db
|
||||
.intern_eager_expansion({
|
||||
EagerCallLoc {
|
||||
def,
|
||||
fragment: FragmentKind::Expr,
|
||||
subtree: Arc::new(parsed_args.clone()),
|
||||
file_id: macro_call.file_id,
|
||||
}
|
||||
})
|
||||
.into();
|
||||
|
||||
let parsed_args = mbe::token_tree_to_syntax_node(&parsed_args, FragmentKind::Expr).ok()?.0;
|
||||
let result =
|
||||
eager_macro_recur(db, InFile::new(arg_id.as_file(), parsed_args.syntax_node()), resolver)?;
|
||||
let subtree = to_subtree(&result)?;
|
||||
|
||||
if let MacroDefKind::BuiltInEager(eager) = def.kind {
|
||||
|
|
|
@ -438,6 +438,27 @@ fn main() {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn infer_builtin_macros_concat_with_lazy() {
|
||||
assert_snapshot!(
|
||||
infer(r#"
|
||||
macro_rules! hello {() => {"hello"}}
|
||||
|
||||
#[rustc_builtin_macro]
|
||||
macro_rules! concat {() => {}}
|
||||
|
||||
fn main() {
|
||||
let x = concat!(hello!(), concat!("world", "!"));
|
||||
}
|
||||
"#),
|
||||
@r###"
|
||||
![0; 13) '"helloworld!"': &str
|
||||
[104; 161) '{ ...")); }': ()
|
||||
[114; 115) 'x': &str
|
||||
"###
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn infer_derive_clone_simple() {
|
||||
let (db, pos) = TestDB::with_position(
|
||||
|
|
Loading…
Reference in a new issue