diff --git a/crates/hir-def/src/data.rs b/crates/hir-def/src/data.rs index 12bfbbe3084e..8e8b5c322f9e 100644 --- a/crates/hir-def/src/data.rs +++ b/crates/hir-def/src/data.rs @@ -2,7 +2,7 @@ use std::{mem, sync::Arc}; -use hir_expand::{name::Name, AstId, ExpandResult, HirFileId, InFile, MacroCallId}; +use hir_expand::{name::Name, AstId, ExpandResult, HirFileId, InFile, MacroCallId, MacroDefKind}; use syntax::ast; use crate::{ @@ -498,6 +498,17 @@ impl<'a> AssocItemCollector<'a> { if !self.db.enable_proc_attr_macros() { continue 'attrs; } + let loc = self.db.lookup_intern_macro_call(call_id); + if let MacroDefKind::ProcMacro(exp, ..) = loc.def.kind { + // If there's no expander for the proc macro (e.g. the + // proc macro is ignored, or building the proc macro + // crate failed), skip expansion like we would if it was + // disabled. This is analogous to the handling in + // `DefCollector::collect_macros`. + if exp.is_dummy() { + continue 'attrs; + } + } match self.expander.enter_expand_id(self.db, call_id) { ExpandResult { value: Some((mark, mac)), .. } => { self.collect_macro_items(mark, mac); diff --git a/crates/hir-ty/src/tests/macros.rs b/crates/hir-ty/src/tests/macros.rs index a4299d9f0500..a1ab6060e790 100644 --- a/crates/hir-ty/src/tests/macros.rs +++ b/crates/hir-ty/src/tests/macros.rs @@ -1274,3 +1274,65 @@ impl S { "#]], ); } + +#[test] +fn infer_in_unexpandable_attr_proc_macro_1() { + check_types( + r#" +//- /main.rs crate:main deps:mac +#[mac::attr_macro] +fn foo() { + let xxx = 1; + //^^^ i32 +} + +//- /mac.rs crate:mac +#![crate_type="proc-macro"] +#[proc_macro_attribute] +pub fn attr_macro() {} +"#, + ); +} + +#[test] +fn infer_in_unexpandable_attr_proc_macro_in_impl() { + check_types( + r#" +//- /main.rs crate:main deps:mac +struct Foo; +impl Foo { + #[mac::attr_macro] + fn foo() { + let xxx = 1; + //^^^ i32 + } +} + +//- /mac.rs crate:mac +#![crate_type="proc-macro"] +#[proc_macro_attribute] +pub fn attr_macro() {} +"#, + ); +} + +#[test] +fn infer_in_unexpandable_attr_proc_macro_in_trait() { + check_types( + r#" +//- /main.rs crate:main deps:mac +trait Foo { + #[mac::attr_macro] + fn foo() { + let xxx = 1; + //^^^ i32 + } +} + +//- /mac.rs crate:mac +#![crate_type="proc-macro"] +#[proc_macro_attribute] +pub fn attr_macro() {} +"#, + ); +} diff --git a/crates/ide-diagnostics/src/handlers/inactive_code.rs b/crates/ide-diagnostics/src/handlers/inactive_code.rs index 17243d612a45..97ea5c456a63 100644 --- a/crates/ide-diagnostics/src/handlers/inactive_code.rs +++ b/crates/ide-diagnostics/src/handlers/inactive_code.rs @@ -104,6 +104,25 @@ fn f() { ); } + #[test] + fn inactive_assoc_item() { + // FIXME these currently don't work, hence the * + check( + r#" +struct Foo; +impl Foo { + #[cfg(any())] pub fn f() {} + //*************************** weak: code is inactive due to #[cfg] directives +} + +trait Bar { + #[cfg(any())] pub fn f() {} + //*************************** weak: code is inactive due to #[cfg] directives +} +"#, + ); + } + /// Tests that `cfg` attributes behind `cfg_attr` is handled properly. #[test] fn inactive_via_cfg_attr() {