aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def/src/nameres
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_def/src/nameres')
-rw-r--r--crates/hir_def/src/nameres/collector.rs30
-rw-r--r--crates/hir_def/src/nameres/tests/macros.rs18
2 files changed, 39 insertions, 9 deletions
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index 9b108bfe7..014ea4de4 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -16,6 +16,7 @@ use hir_expand::{
16 FragmentKind, HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, 16 FragmentKind, HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
17}; 17};
18use hir_expand::{InFile, MacroCallLoc}; 18use hir_expand::{InFile, MacroCallLoc};
19use itertools::Itertools;
19use rustc_hash::{FxHashMap, FxHashSet}; 20use rustc_hash::{FxHashMap, FxHashSet};
20use syntax::ast; 21use syntax::ast;
21 22
@@ -1516,14 +1517,27 @@ impl ModCollector<'_, '_> {
1516 fn resolve_attributes(&mut self, attrs: &Attrs, mod_item: ModItem) -> Result<(), ()> { 1517 fn resolve_attributes(&mut self, attrs: &Attrs, mod_item: ModItem) -> Result<(), ()> {
1517 let mut ignore_up_to = 1518 let mut ignore_up_to =
1518 self.def_collector.skip_attrs.get(&InFile::new(self.file_id, mod_item)).copied(); 1519 self.def_collector.skip_attrs.get(&InFile::new(self.file_id, mod_item)).copied();
1519 for attr in attrs.iter().skip_while(|attr| match ignore_up_to { 1520 let iter = attrs
1520 Some(id) if attr.id == id => { 1521 .iter()
1521 ignore_up_to = None; 1522 .dedup_by(|a, b| {
1522 true 1523 // FIXME: this should not be required, all attributes on an item should have a
1523 } 1524 // unique ID!
1524 Some(_) => true, 1525 // Still, this occurs because `#[cfg_attr]` can "expand" to multiple attributes:
1525 None => false, 1526 // #[cfg_attr(not(off), unresolved, unresolved)]
1526 }) { 1527 // struct S;
1528 // We should come up with a different way to ID attributes.
1529 a.id == b.id
1530 })
1531 .skip_while(|attr| match ignore_up_to {
1532 Some(id) if attr.id == id => {
1533 ignore_up_to = None;
1534 true
1535 }
1536 Some(_) => true,
1537 None => false,
1538 });
1539
1540 for attr in iter {
1527 if attr.path.as_ident() == Some(&hir_expand::name![derive]) { 1541 if attr.path.as_ident() == Some(&hir_expand::name![derive]) {
1528 self.collect_derive(attr, mod_item); 1542 self.collect_derive(attr, mod_item);
1529 } else if self.is_builtin_or_registered_attr(&attr.path) { 1543 } else if self.is_builtin_or_registered_attr(&attr.path) {
diff --git a/crates/hir_def/src/nameres/tests/macros.rs b/crates/hir_def/src/nameres/tests/macros.rs
index 133b2d818..3065efd65 100644
--- a/crates/hir_def/src/nameres/tests/macros.rs
+++ b/crates/hir_def/src/nameres/tests/macros.rs
@@ -737,6 +737,7 @@ fn unresolved_attributes_fall_back_track_per_file_moditems() {
737 737
738#[test] 738#[test]
739fn unresolved_attrs_extern_block_hang() { 739fn unresolved_attrs_extern_block_hang() {
740 // Regression test for https://github.com/rust-analyzer/rust-analyzer/issues/8905
740 check( 741 check(
741 r#" 742 r#"
742#[unresolved] 743#[unresolved]
@@ -790,7 +791,22 @@ fn derive() {}
790 crate 791 crate
791 S: t v 792 S: t v
792 "#]], 793 "#]],
793 ) 794 );
795}
796
797#[test]
798fn unresolved_attr_with_cfg_attr_hang() {
799 // Another regression test for https://github.com/rust-analyzer/rust-analyzer/issues/8905
800 check(
801 r#"
802#[cfg_attr(not(off), unresolved, unresolved)]
803struct S;
804 "#,
805 expect![[r#"
806 crate
807 S: t v
808 "#]],
809 );
794} 810}
795 811
796#[test] 812#[test]