diff --git a/crates/hir-def/src/attrs.rs b/crates/hir-def/src/attrs.rs index f4a1a3130e20..14285299bf48 100644 --- a/crates/hir-def/src/attrs.rs +++ b/crates/hir-def/src/attrs.rs @@ -1051,17 +1051,25 @@ impl AttrFlags { collect_attrs::(db, owner.into(), |attr| { if let Meta::TokenTree { path, tt } = attr && path.is1("target_feature") - && let mut tt = TokenTreeChildren::new(&tt) - && let Some(NodeOrToken::Token(enable_ident)) = tt.next() - && enable_ident.text() == "enable" - && let Some(NodeOrToken::Token(eq_token)) = tt.next() - && eq_token.kind() == T![=] - && let Some(NodeOrToken::Token(features)) = tt.next() - && let Some(features) = ast::String::cast(features) - && let Ok(features) = features.value() - && tt.next().is_none() { - result.extend(features.split(',').map(Symbol::intern)); + let mut tt = TokenTreeChildren::new(&tt); + while let Some(NodeOrToken::Token(enable_ident)) = tt.next() + && enable_ident.text() == "enable" + && let Some(NodeOrToken::Token(eq_token)) = tt.next() + && eq_token.kind() == T![=] + && let Some(NodeOrToken::Token(features)) = tt.next() + && let Some(features) = ast::String::cast(features) + && let Ok(features) = features.value() + { + result.extend(features.split(',').map(Symbol::intern)); + if tt + .next() + .and_then(NodeOrToken::into_token) + .is_none_or(|it| it.kind() != T![,]) + { + break; + } + } } ControlFlow::Continue(()) }); diff --git a/crates/ide-diagnostics/src/handlers/missing_unsafe.rs b/crates/ide-diagnostics/src/handlers/missing_unsafe.rs index df1cd76cf707..59215f34a581 100644 --- a/crates/ide-diagnostics/src/handlers/missing_unsafe.rs +++ b/crates/ide-diagnostics/src/handlers/missing_unsafe.rs @@ -1094,4 +1094,19 @@ fn main() { "#, ); } + + #[test] + fn multiple_target_feature_enable() { + check_diagnostics( + r#" +#[target_feature(enable = "avx2,fma")] +fn foo() {} + +#[target_feature(enable = "avx2", enable = "fma")] +fn bar() { + foo(); +} + "#, + ); + } }