8918: fix: fix hang caused by non-unique attribute IDs r=jonas-schievink a=jonas-schievink

Fixes https://github.com/rust-analyzer/rust-analyzer/issues/8905 (again)

bors r+

Co-authored-by: Jonas Schievink <jonasschievink@gmail.com>
This commit is contained in:
bors[bot] 2021-05-22 00:31:17 +00:00 committed by GitHub
commit 3cfe2d0a5d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 39 additions and 9 deletions

View File

@ -16,6 +16,7 @@
FragmentKind, HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
};
use hir_expand::{InFile, MacroCallLoc};
use itertools::Itertools;
use rustc_hash::{FxHashMap, FxHashSet};
use syntax::ast;
@ -1516,14 +1517,27 @@ fn push_child_module(
fn resolve_attributes(&mut self, attrs: &Attrs, mod_item: ModItem) -> Result<(), ()> {
let mut ignore_up_to =
self.def_collector.skip_attrs.get(&InFile::new(self.file_id, mod_item)).copied();
for attr in attrs.iter().skip_while(|attr| match ignore_up_to {
Some(id) if attr.id == id => {
ignore_up_to = None;
true
}
Some(_) => true,
None => false,
}) {
let iter = attrs
.iter()
.dedup_by(|a, b| {
// FIXME: this should not be required, all attributes on an item should have a
// unique ID!
// Still, this occurs because `#[cfg_attr]` can "expand" to multiple attributes:
// #[cfg_attr(not(off), unresolved, unresolved)]
// struct S;
// We should come up with a different way to ID attributes.
a.id == b.id
})
.skip_while(|attr| match ignore_up_to {
Some(id) if attr.id == id => {
ignore_up_to = None;
true
}
Some(_) => true,
None => false,
});
for attr in iter {
if attr.path.as_ident() == Some(&hir_expand::name![derive]) {
self.collect_derive(attr, mod_item);
} else if self.is_builtin_or_registered_attr(&attr.path) {

View File

@ -737,6 +737,7 @@ fn unresolved_attributes_fall_back_track_per_file_moditems() {
#[test]
fn unresolved_attrs_extern_block_hang() {
// Regression test for https://github.com/rust-analyzer/rust-analyzer/issues/8905
check(
r#"
#[unresolved]
@ -790,7 +791,22 @@ fn derive() {}
crate
S: t v
"#]],
)
);
}
#[test]
fn unresolved_attr_with_cfg_attr_hang() {
// Another regression test for https://github.com/rust-analyzer/rust-analyzer/issues/8905
check(
r#"
#[cfg_attr(not(off), unresolved, unresolved)]
struct S;
"#,
expect![[r#"
crate
S: t v
"#]],
);
}
#[test]