Skip to content

Commit 796bfcc

Browse files
bors[bot]Veykril
andauthored
Merge #10127
10127: fix: When descending tokens don't bail on failed macro call expansions r=Veykril a=Veykril (with `#[test]` expansion enabled) ![image](https://user-images.githubusercontent.com/3757771/131887786-ced9988b-80fa-4e8f-b114-337572950cc3.png) The problem was pretty simple, since we go through the ancestors we first try to expand the macro call node we are in since in attributed items these are valid syntaxnodes instead of TokenTrees, we then fail the expansion since the expansion only exists in the attribute expanded file and therefor skip the attribute expansion due to returning immediately. So instead of breaking out we just continue looking up the ancestors. Fixes #10115 bors r+ Co-authored-by: Lukas Wirth <[email protected]>
2 parents 2aee17e + 0fee14b commit 796bfcc

File tree

1 file changed

+57
-49
lines changed

1 file changed

+57
-49
lines changed

crates/hir/src/semantics.rs

+57-49
Original file line numberDiff line numberDiff line change
@@ -467,65 +467,73 @@ impl<'db> SemanticsImpl<'db> {
467467
let mut queue = vec![InFile::new(sa.file_id, token)];
468468
let mut cache = self.expansion_info_cache.borrow_mut();
469469
let mut res = smallvec![];
470+
// Remap the next token in the queue into a macro call its in, if it is not being remapped
471+
// either due to not being in a macro-call or because its unused push it into the result vec,
472+
// otherwise push the remapped tokens back into the queue as they can potentially be remapped again.
470473
while let Some(token) = queue.pop() {
471474
self.db.unwind_if_cancelled();
472475

473476
let was_not_remapped = (|| {
474477
for node in token.value.ancestors() {
475-
match_ast! {
476-
match node {
477-
ast::MacroCall(macro_call) => {
478-
let tt = macro_call.token_tree()?;
479-
let l_delim = match tt.left_delimiter_token() {
480-
Some(it) => it.text_range().end(),
481-
None => tt.syntax().text_range().start()
482-
};
483-
let r_delim = match tt.right_delimiter_token() {
484-
Some(it) => it.text_range().start(),
485-
None => tt.syntax().text_range().end()
486-
};
487-
if !TextRange::new(l_delim, r_delim).contains_range(token.value.text_range()) {
488-
return None;
489-
}
490-
let file_id = sa.expand(self.db, token.with_value(&macro_call))?;
491-
let tokens = cache
492-
.entry(file_id)
493-
.or_insert_with(|| file_id.expansion_info(self.db.upcast()))
494-
.as_ref()?
495-
.map_token_down(self.db.upcast(), None, token.as_ref())?;
496-
497-
let len = queue.len();
498-
queue.extend(tokens.inspect(|token| {
499-
if let Some(parent) = token.value.parent() {
500-
self.cache(find_root(&parent), token.file_id);
501-
}
502-
}));
503-
return (queue.len() != len).then(|| ());
504-
},
505-
ast::Item(item) => {
506-
if let Some(call_id) = self.with_ctx(|ctx| ctx.item_to_macro_call(token.with_value(item.clone()))) {
507-
let file_id = call_id.as_file();
508-
let tokens = cache
509-
.entry(file_id)
510-
.or_insert_with(|| file_id.expansion_info(self.db.upcast()))
511-
.as_ref()?
512-
.map_token_down(self.db.upcast(), Some(item), token.as_ref())?;
513-
514-
let len = queue.len();
515-
queue.extend(tokens.inspect(|token| {
516-
if let Some(parent) = token.value.parent() {
517-
self.cache(find_root(&parent), token.file_id);
518-
}
519-
}));
520-
return (queue.len() != len).then(|| ());
478+
if let Some(macro_call) = ast::MacroCall::cast(node.clone()) {
479+
let tt = match macro_call.token_tree() {
480+
Some(tt) => tt,
481+
None => continue,
482+
};
483+
let l_delim = match tt.left_delimiter_token() {
484+
Some(it) => it.text_range().end(),
485+
None => tt.syntax().text_range().start(),
486+
};
487+
let r_delim = match tt.right_delimiter_token() {
488+
Some(it) => it.text_range().start(),
489+
None => tt.syntax().text_range().end(),
490+
};
491+
if !TextRange::new(l_delim, r_delim)
492+
.contains_range(token.value.text_range())
493+
{
494+
continue;
495+
}
496+
let file_id = match sa.expand(self.db, token.with_value(&macro_call)) {
497+
Some(file_id) => file_id,
498+
None => continue,
499+
};
500+
let tokens = cache
501+
.entry(file_id)
502+
.or_insert_with(|| file_id.expansion_info(self.db.upcast()))
503+
.as_ref()?
504+
.map_token_down(self.db.upcast(), None, token.as_ref())?;
505+
506+
let len = queue.len();
507+
queue.extend(tokens.inspect(|token| {
508+
if let Some(parent) = token.value.parent() {
509+
self.cache(find_root(&parent), token.file_id);
510+
}
511+
}));
512+
return (queue.len() != len).then(|| ());
513+
} else if let Some(item) = ast::Item::cast(node.clone()) {
514+
if let Some(call_id) = self
515+
.with_ctx(|ctx| ctx.item_to_macro_call(token.with_value(item.clone())))
516+
{
517+
let file_id = call_id.as_file();
518+
let tokens = cache
519+
.entry(file_id)
520+
.or_insert_with(|| file_id.expansion_info(self.db.upcast()))
521+
.as_ref()?
522+
.map_token_down(self.db.upcast(), Some(item), token.as_ref())?;
523+
524+
let len = queue.len();
525+
queue.extend(tokens.inspect(|token| {
526+
if let Some(parent) = token.value.parent() {
527+
self.cache(find_root(&parent), token.file_id);
521528
}
522-
},
523-
_ => {}
529+
}));
530+
return (queue.len() != len).then(|| ());
524531
}
525532
}
526533
}
527534
None
528-
})().is_none();
535+
})()
536+
.is_none();
529537
if was_not_remapped {
530538
res.push(token.value)
531539
}

0 commit comments

Comments
 (0)