aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorJonas Schievink <[email protected]>2020-10-22 18:19:18 +0100
committerJonas Schievink <[email protected]>2020-10-22 18:19:18 +0100
commit3421b645e6f7d15ddad0e8e526d8a7db09b72516 (patch)
treee1ec7d37bd63ccc7f0e18b39479c0860b7fc5d9b /crates
parent978cc936491d23bd38ef18aa98ddcc7472ef5f54 (diff)
Emit better #[cfg] diagnostics
Diffstat (limited to 'crates')
-rw-r--r--crates/hir_def/src/attr.rs14
-rw-r--r--crates/hir_def/src/diagnostics.rs14
-rw-r--r--crates/hir_def/src/nameres.rs16
-rw-r--r--crates/hir_def/src/nameres/collector.rs29
-rw-r--r--crates/hir_def/src/nameres/tests/diagnostics.rs22
-rw-r--r--crates/ide/src/hover.rs4
-rw-r--r--crates/ide/src/runnables.rs84
-rw-r--r--crates/rust-analyzer/src/cargo_target_spec.rs4
-rw-r--r--crates/rust-analyzer/src/to_proto.rs2
9 files changed, 124 insertions, 65 deletions
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs
index dea552a60..b2ce7ca3c 100644
--- a/crates/hir_def/src/attr.rs
+++ b/crates/hir_def/src/attr.rs
@@ -125,12 +125,20 @@ impl Attrs {
125 AttrQuery { attrs: self, key } 125 AttrQuery { attrs: self, key }
126 } 126 }
127 127
128 pub fn cfg(&self) -> impl Iterator<Item = CfgExpr> + '_ { 128 pub fn cfg(&self) -> Option<CfgExpr> {
129 // FIXME: handle cfg_attr :-) 129 // FIXME: handle cfg_attr :-)
130 self.by_key("cfg").tt_values().map(CfgExpr::parse) 130 let mut cfgs = self.by_key("cfg").tt_values().map(CfgExpr::parse).collect::<Vec<_>>();
131 match cfgs.len() {
132 0 => None,
133 1 => Some(cfgs.pop().unwrap()),
134 _ => Some(CfgExpr::All(cfgs)),
135 }
131 } 136 }
132 pub(crate) fn is_cfg_enabled(&self, cfg_options: &CfgOptions) -> bool { 137 pub(crate) fn is_cfg_enabled(&self, cfg_options: &CfgOptions) -> bool {
133 self.cfg().all(|cfg| cfg_options.check(&cfg) != Some(false)) 138 match self.cfg() {
139 None => true,
140 Some(cfg) => cfg_options.check(&cfg) != Some(false),
141 }
134 } 142 }
135} 143}
136 144
diff --git a/crates/hir_def/src/diagnostics.rs b/crates/hir_def/src/diagnostics.rs
index c9c08b01f..34a6a8d4b 100644
--- a/crates/hir_def/src/diagnostics.rs
+++ b/crates/hir_def/src/diagnostics.rs
@@ -1,7 +1,9 @@
1//! Diagnostics produced by `hir_def`. 1//! Diagnostics produced by `hir_def`.
2 2
3use std::any::Any; 3use std::any::Any;
4use std::fmt::Write;
4 5
6use cfg::{CfgExpr, CfgOptions, DnfExpr};
5use hir_expand::diagnostics::{Diagnostic, DiagnosticCode}; 7use hir_expand::diagnostics::{Diagnostic, DiagnosticCode};
6use syntax::{ast, AstPtr, SyntaxNodePtr}; 8use syntax::{ast, AstPtr, SyntaxNodePtr};
7 9
@@ -94,6 +96,8 @@ impl Diagnostic for UnresolvedImport {
94pub struct InactiveCode { 96pub struct InactiveCode {
95 pub file: HirFileId, 97 pub file: HirFileId,
96 pub node: SyntaxNodePtr, 98 pub node: SyntaxNodePtr,
99 pub cfg: CfgExpr,
100 pub opts: CfgOptions,
97} 101}
98 102
99impl Diagnostic for InactiveCode { 103impl Diagnostic for InactiveCode {
@@ -101,8 +105,14 @@ impl Diagnostic for InactiveCode {
101 DiagnosticCode("inactive-code") 105 DiagnosticCode("inactive-code")
102 } 106 }
103 fn message(&self) -> String { 107 fn message(&self) -> String {
104 // FIXME: say *why* it is configured out 108 let inactive = DnfExpr::new(self.cfg.clone()).why_inactive(&self.opts);
105 "code is inactive due to #[cfg] directives".to_string() 109 let mut buf = "code is inactive due to #[cfg] directives".to_string();
110
111 if let Some(inactive) = inactive {
112 write!(buf, ": {}", inactive).unwrap();
113 }
114
115 buf
106 } 116 }
107 fn display_source(&self) -> InFile<SyntaxNodePtr> { 117 fn display_source(&self) -> InFile<SyntaxNodePtr> {
108 InFile::new(self.file, self.node.clone()) 118 InFile::new(self.file, self.node.clone())
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs
index 01a28aeeb..eb41d324e 100644
--- a/crates/hir_def/src/nameres.rs
+++ b/crates/hir_def/src/nameres.rs
@@ -283,6 +283,7 @@ pub enum ModuleSource {
283} 283}
284 284
285mod diagnostics { 285mod diagnostics {
286 use cfg::{CfgExpr, CfgOptions};
286 use hir_expand::diagnostics::DiagnosticSink; 287 use hir_expand::diagnostics::DiagnosticSink;
287 use hir_expand::hygiene::Hygiene; 288 use hir_expand::hygiene::Hygiene;
288 use hir_expand::InFile; 289 use hir_expand::InFile;
@@ -299,7 +300,7 @@ mod diagnostics {
299 300
300 UnresolvedImport { ast: AstId<ast::Use>, index: usize }, 301 UnresolvedImport { ast: AstId<ast::Use>, index: usize },
301 302
302 UnconfiguredCode { ast: InFile<SyntaxNodePtr> }, 303 UnconfiguredCode { ast: InFile<SyntaxNodePtr>, cfg: CfgExpr, opts: CfgOptions },
303 } 304 }
304 305
305 #[derive(Debug, PartialEq, Eq)] 306 #[derive(Debug, PartialEq, Eq)]
@@ -341,8 +342,10 @@ mod diagnostics {
341 pub(super) fn unconfigured_code( 342 pub(super) fn unconfigured_code(
342 container: LocalModuleId, 343 container: LocalModuleId,
343 ast: InFile<SyntaxNodePtr>, 344 ast: InFile<SyntaxNodePtr>,
345 cfg: CfgExpr,
346 opts: CfgOptions,
344 ) -> Self { 347 ) -> Self {
345 Self { in_module: container, kind: DiagnosticKind::UnconfiguredCode { ast } } 348 Self { in_module: container, kind: DiagnosticKind::UnconfiguredCode { ast, cfg, opts } }
346 } 349 }
347 350
348 pub(super) fn add_to( 351 pub(super) fn add_to(
@@ -395,8 +398,13 @@ mod diagnostics {
395 } 398 }
396 } 399 }
397 400
398 DiagnosticKind::UnconfiguredCode { ast } => { 401 DiagnosticKind::UnconfiguredCode { ast, cfg, opts } => {
399 sink.push(InactiveCode { file: ast.file_id, node: ast.value.clone() }); 402 sink.push(InactiveCode {
403 file: ast.file_id,
404 node: ast.value.clone(),
405 cfg: cfg.clone(),
406 opts: opts.clone(),
407 });
400 } 408 }
401 } 409 }
402 } 410 }
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index bff8edb62..f30172d90 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -6,7 +6,7 @@
6use std::iter; 6use std::iter;
7 7
8use base_db::{CrateId, FileId, ProcMacroId}; 8use base_db::{CrateId, FileId, ProcMacroId};
9use cfg::CfgOptions; 9use cfg::{CfgExpr, CfgOptions};
10use hir_expand::InFile; 10use hir_expand::InFile;
11use hir_expand::{ 11use hir_expand::{
12 ast_id_map::FileAstId, 12 ast_id_map::FileAstId,
@@ -900,7 +900,8 @@ impl ModCollector<'_, '_> {
900 // `#[macro_use] extern crate` is hoisted to imports macros before collecting 900 // `#[macro_use] extern crate` is hoisted to imports macros before collecting
901 // any other items. 901 // any other items.
902 for item in items { 902 for item in items {
903 if self.is_cfg_enabled(self.item_tree.attrs((*item).into())) { 903 let attrs = self.item_tree.attrs((*item).into());
904 if attrs.cfg().map_or(true, |cfg| self.is_cfg_enabled(&cfg)) {
904 if let ModItem::ExternCrate(id) = item { 905 if let ModItem::ExternCrate(id) = item {
905 let import = self.item_tree[*id].clone(); 906 let import = self.item_tree[*id].clone();
906 if import.is_macro_use { 907 if import.is_macro_use {
@@ -912,9 +913,11 @@ impl ModCollector<'_, '_> {
912 913
913 for &item in items { 914 for &item in items {
914 let attrs = self.item_tree.attrs(item.into()); 915 let attrs = self.item_tree.attrs(item.into());
915 if !self.is_cfg_enabled(attrs) { 916 if let Some(cfg) = attrs.cfg() {
916 self.emit_unconfigured_diagnostic(item); 917 if !self.is_cfg_enabled(&cfg) {
917 continue; 918 self.emit_unconfigured_diagnostic(item, &cfg);
919 continue;
920 }
918 } 921 }
919 let module = 922 let module =
920 ModuleId { krate: self.def_collector.def_map.krate, local_id: self.module_id }; 923 ModuleId { krate: self.def_collector.def_map.krate, local_id: self.module_id };
@@ -1321,20 +1324,22 @@ impl ModCollector<'_, '_> {
1321 } 1324 }
1322 } 1325 }
1323 1326
1324 fn is_cfg_enabled(&self, attrs: &Attrs) -> bool { 1327 fn is_cfg_enabled(&self, cfg: &CfgExpr) -> bool {
1325 attrs.is_cfg_enabled(self.def_collector.cfg_options) 1328 self.def_collector.cfg_options.check(cfg) != Some(false)
1326 } 1329 }
1327 1330
1328 fn emit_unconfigured_diagnostic(&mut self, item: ModItem) { 1331 fn emit_unconfigured_diagnostic(&mut self, item: ModItem, cfg: &CfgExpr) {
1329 let ast_id = item.ast_id(self.item_tree); 1332 let ast_id = item.ast_id(self.item_tree);
1330 let id_map = self.def_collector.db.ast_id_map(self.file_id); 1333 let id_map = self.def_collector.db.ast_id_map(self.file_id);
1331 let syntax_ptr = id_map.get(ast_id).syntax_node_ptr(); 1334 let syntax_ptr = id_map.get(ast_id).syntax_node_ptr();
1332 1335
1333 let ast_node = InFile::new(self.file_id, syntax_ptr); 1336 let ast_node = InFile::new(self.file_id, syntax_ptr);
1334 self.def_collector 1337 self.def_collector.def_map.diagnostics.push(DefDiagnostic::unconfigured_code(
1335 .def_map 1338 self.module_id,
1336 .diagnostics 1339 ast_node,
1337 .push(DefDiagnostic::unconfigured_code(self.module_id, ast_node)); 1340 cfg.clone(),
1341 self.def_collector.cfg_options.clone(),
1342 ));
1338 } 1343 }
1339} 1344}
1340 1345
diff --git a/crates/hir_def/src/nameres/tests/diagnostics.rs b/crates/hir_def/src/nameres/tests/diagnostics.rs
index 576b813d2..5972248de 100644
--- a/crates/hir_def/src/nameres/tests/diagnostics.rs
+++ b/crates/hir_def/src/nameres/tests/diagnostics.rs
@@ -129,3 +129,25 @@ fn unresolved_module() {
129 ", 129 ",
130 ); 130 );
131} 131}
132
133#[test]
134fn inactive_item() {
135 // Additional tests in `cfg` crate. This only tests disabled cfgs.
136
137 check_diagnostics(
138 r#"
139 //- /lib.rs
140 #[cfg(no)] pub fn f() {}
141 //^^^^^^^^^^^^^^^^^^^^^^^^ code is inactive due to #[cfg] directives: no is disabled
142
143 #[cfg(no)] #[cfg(no2)] mod m;
144 //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ code is inactive due to #[cfg] directives: no and no2 are disabled
145
146 #[cfg(all(not(a), b))] enum E {}
147 //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ code is inactive due to #[cfg] directives: b is disabled
148
149 #[cfg(feature = "std")] use std;
150 //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ code is inactive due to #[cfg] directives: feature = "std" is disabled
151 "#,
152 );
153}
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs
index 6466422c5..0332c7be0 100644
--- a/crates/ide/src/hover.rs
+++ b/crates/ide/src/hover.rs
@@ -2128,7 +2128,7 @@ fn foo_<|>test() {}
2128 ignore: false, 2128 ignore: false,
2129 }, 2129 },
2130 }, 2130 },
2131 cfg_exprs: [], 2131 cfg: None,
2132 }, 2132 },
2133 ), 2133 ),
2134 ] 2134 ]
@@ -2166,7 +2166,7 @@ mod tests<|> {
2166 kind: TestMod { 2166 kind: TestMod {
2167 path: "tests", 2167 path: "tests",
2168 }, 2168 },
2169 cfg_exprs: [], 2169 cfg: None,
2170 }, 2170 },
2171 ), 2171 ),
2172 ] 2172 ]
diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs
index 752ef2f21..eb82456ad 100644
--- a/crates/ide/src/runnables.rs
+++ b/crates/ide/src/runnables.rs
@@ -15,7 +15,7 @@ use crate::{display::ToNav, FileId, NavigationTarget};
15pub struct Runnable { 15pub struct Runnable {
16 pub nav: NavigationTarget, 16 pub nav: NavigationTarget,
17 pub kind: RunnableKind, 17 pub kind: RunnableKind,
18 pub cfg_exprs: Vec<CfgExpr>, 18 pub cfg: Option<CfgExpr>,
19} 19}
20 20
21#[derive(Debug, Clone)] 21#[derive(Debug, Clone)]
@@ -168,7 +168,7 @@ fn runnable_fn(
168 }; 168 };
169 169
170 let attrs = Attrs::from_attrs_owner(sema.db, InFile::new(HirFileId::from(file_id), &fn_def)); 170 let attrs = Attrs::from_attrs_owner(sema.db, InFile::new(HirFileId::from(file_id), &fn_def));
171 let cfg_exprs = attrs.cfg().collect(); 171 let cfg = attrs.cfg();
172 172
173 let nav = if let RunnableKind::DocTest { .. } = kind { 173 let nav = if let RunnableKind::DocTest { .. } = kind {
174 NavigationTarget::from_doc_commented( 174 NavigationTarget::from_doc_commented(
@@ -179,7 +179,7 @@ fn runnable_fn(
179 } else { 179 } else {
180 NavigationTarget::from_named(sema.db, InFile::new(file_id.into(), &fn_def)) 180 NavigationTarget::from_named(sema.db, InFile::new(file_id.into(), &fn_def))
181 }; 181 };
182 Some(Runnable { nav, kind, cfg_exprs }) 182 Some(Runnable { nav, kind, cfg })
183} 183}
184 184
185#[derive(Debug, Copy, Clone)] 185#[derive(Debug, Copy, Clone)]
@@ -255,9 +255,9 @@ fn runnable_mod(
255 .join("::"); 255 .join("::");
256 256
257 let attrs = Attrs::from_attrs_owner(sema.db, InFile::new(HirFileId::from(file_id), &module)); 257 let attrs = Attrs::from_attrs_owner(sema.db, InFile::new(HirFileId::from(file_id), &module));
258 let cfg_exprs = attrs.cfg().collect(); 258 let cfg = attrs.cfg();
259 let nav = module_def.to_nav(sema.db); 259 let nav = module_def.to_nav(sema.db);
260 Some(Runnable { nav, kind: RunnableKind::TestMod { path }, cfg_exprs }) 260 Some(Runnable { nav, kind: RunnableKind::TestMod { path }, cfg })
261} 261}
262 262
263// We could create runnables for modules with number_of_test_submodules > 0, 263// We could create runnables for modules with number_of_test_submodules > 0,
@@ -348,7 +348,7 @@ fn bench() {}
348 docs: None, 348 docs: None,
349 }, 349 },
350 kind: Bin, 350 kind: Bin,
351 cfg_exprs: [], 351 cfg: None,
352 }, 352 },
353 Runnable { 353 Runnable {
354 nav: NavigationTarget { 354 nav: NavigationTarget {
@@ -373,7 +373,7 @@ fn bench() {}
373 ignore: false, 373 ignore: false,
374 }, 374 },
375 }, 375 },
376 cfg_exprs: [], 376 cfg: None,
377 }, 377 },
378 Runnable { 378 Runnable {
379 nav: NavigationTarget { 379 nav: NavigationTarget {
@@ -398,7 +398,7 @@ fn bench() {}
398 ignore: true, 398 ignore: true,
399 }, 399 },
400 }, 400 },
401 cfg_exprs: [], 401 cfg: None,
402 }, 402 },
403 Runnable { 403 Runnable {
404 nav: NavigationTarget { 404 nav: NavigationTarget {
@@ -420,7 +420,7 @@ fn bench() {}
420 "bench", 420 "bench",
421 ), 421 ),
422 }, 422 },
423 cfg_exprs: [], 423 cfg: None,
424 }, 424 },
425 ] 425 ]
426 "#]], 426 "#]],
@@ -507,7 +507,7 @@ fn should_have_no_runnable_6() {}
507 docs: None, 507 docs: None,
508 }, 508 },
509 kind: Bin, 509 kind: Bin,
510 cfg_exprs: [], 510 cfg: None,
511 }, 511 },
512 Runnable { 512 Runnable {
513 nav: NavigationTarget { 513 nav: NavigationTarget {
@@ -527,7 +527,7 @@ fn should_have_no_runnable_6() {}
527 "should_have_runnable", 527 "should_have_runnable",
528 ), 528 ),
529 }, 529 },
530 cfg_exprs: [], 530 cfg: None,
531 }, 531 },
532 Runnable { 532 Runnable {
533 nav: NavigationTarget { 533 nav: NavigationTarget {
@@ -547,7 +547,7 @@ fn should_have_no_runnable_6() {}
547 "should_have_runnable_1", 547 "should_have_runnable_1",
548 ), 548 ),
549 }, 549 },
550 cfg_exprs: [], 550 cfg: None,
551 }, 551 },
552 Runnable { 552 Runnable {
553 nav: NavigationTarget { 553 nav: NavigationTarget {
@@ -567,7 +567,7 @@ fn should_have_no_runnable_6() {}
567 "should_have_runnable_2", 567 "should_have_runnable_2",
568 ), 568 ),
569 }, 569 },
570 cfg_exprs: [], 570 cfg: None,
571 }, 571 },
572 ] 572 ]
573 "#]], 573 "#]],
@@ -609,7 +609,7 @@ impl Data {
609 docs: None, 609 docs: None,
610 }, 610 },
611 kind: Bin, 611 kind: Bin,
612 cfg_exprs: [], 612 cfg: None,
613 }, 613 },
614 Runnable { 614 Runnable {
615 nav: NavigationTarget { 615 nav: NavigationTarget {
@@ -629,7 +629,7 @@ impl Data {
629 "Data::foo", 629 "Data::foo",
630 ), 630 ),
631 }, 631 },
632 cfg_exprs: [], 632 cfg: None,
633 }, 633 },
634 ] 634 ]
635 "#]], 635 "#]],
@@ -668,7 +668,7 @@ mod test_mod {
668 kind: TestMod { 668 kind: TestMod {
669 path: "test_mod", 669 path: "test_mod",
670 }, 670 },
671 cfg_exprs: [], 671 cfg: None,
672 }, 672 },
673 Runnable { 673 Runnable {
674 nav: NavigationTarget { 674 nav: NavigationTarget {
@@ -693,7 +693,7 @@ mod test_mod {
693 ignore: false, 693 ignore: false,
694 }, 694 },
695 }, 695 },
696 cfg_exprs: [], 696 cfg: None,
697 }, 697 },
698 ] 698 ]
699 "#]], 699 "#]],
@@ -748,7 +748,7 @@ mod root_tests {
748 kind: TestMod { 748 kind: TestMod {
749 path: "root_tests::nested_tests_0", 749 path: "root_tests::nested_tests_0",
750 }, 750 },
751 cfg_exprs: [], 751 cfg: None,
752 }, 752 },
753 Runnable { 753 Runnable {
754 nav: NavigationTarget { 754 nav: NavigationTarget {
@@ -768,7 +768,7 @@ mod root_tests {
768 kind: TestMod { 768 kind: TestMod {
769 path: "root_tests::nested_tests_0::nested_tests_1", 769 path: "root_tests::nested_tests_0::nested_tests_1",
770 }, 770 },
771 cfg_exprs: [], 771 cfg: None,
772 }, 772 },
773 Runnable { 773 Runnable {
774 nav: NavigationTarget { 774 nav: NavigationTarget {
@@ -793,7 +793,7 @@ mod root_tests {
793 ignore: false, 793 ignore: false,
794 }, 794 },
795 }, 795 },
796 cfg_exprs: [], 796 cfg: None,
797 }, 797 },
798 Runnable { 798 Runnable {
799 nav: NavigationTarget { 799 nav: NavigationTarget {
@@ -818,7 +818,7 @@ mod root_tests {
818 ignore: false, 818 ignore: false,
819 }, 819 },
820 }, 820 },
821 cfg_exprs: [], 821 cfg: None,
822 }, 822 },
823 Runnable { 823 Runnable {
824 nav: NavigationTarget { 824 nav: NavigationTarget {
@@ -838,7 +838,7 @@ mod root_tests {
838 kind: TestMod { 838 kind: TestMod {
839 path: "root_tests::nested_tests_0::nested_tests_2", 839 path: "root_tests::nested_tests_0::nested_tests_2",
840 }, 840 },
841 cfg_exprs: [], 841 cfg: None,
842 }, 842 },
843 Runnable { 843 Runnable {
844 nav: NavigationTarget { 844 nav: NavigationTarget {
@@ -863,7 +863,7 @@ mod root_tests {
863 ignore: false, 863 ignore: false,
864 }, 864 },
865 }, 865 },
866 cfg_exprs: [], 866 cfg: None,
867 }, 867 },
868 ] 868 ]
869 "#]], 869 "#]],
@@ -906,12 +906,14 @@ fn test_foo1() {}
906 ignore: false, 906 ignore: false,
907 }, 907 },
908 }, 908 },
909 cfg_exprs: [ 909 cfg: Some(
910 KeyValue { 910 Atom(
911 key: "feature", 911 KeyValue {
912 value: "foo", 912 key: "feature",
913 }, 913 value: "foo",
914 ], 914 },
915 ),
916 ),
915 }, 917 },
916 ] 918 ]
917 "#]], 919 "#]],
@@ -954,20 +956,24 @@ fn test_foo1() {}
954 ignore: false, 956 ignore: false,
955 }, 957 },
956 }, 958 },
957 cfg_exprs: [ 959 cfg: Some(
958 All( 960 All(
959 [ 961 [
960 KeyValue { 962 Atom(
961 key: "feature", 963 KeyValue {
962 value: "foo", 964 key: "feature",
963 }, 965 value: "foo",
964 KeyValue { 966 },
965 key: "feature", 967 ),
966 value: "bar", 968 Atom(
967 }, 969 KeyValue {
970 key: "feature",
971 value: "bar",
972 },
973 ),
968 ], 974 ],
969 ), 975 ),
970 ], 976 ),
971 }, 977 },
972 ] 978 ]
973 "#]], 979 "#]],
diff --git a/crates/rust-analyzer/src/cargo_target_spec.rs b/crates/rust-analyzer/src/cargo_target_spec.rs
index 7da935464..1ab72bd91 100644
--- a/crates/rust-analyzer/src/cargo_target_spec.rs
+++ b/crates/rust-analyzer/src/cargo_target_spec.rs
@@ -24,7 +24,7 @@ impl CargoTargetSpec {
24 snap: &GlobalStateSnapshot, 24 snap: &GlobalStateSnapshot,
25 spec: Option<CargoTargetSpec>, 25 spec: Option<CargoTargetSpec>,
26 kind: &RunnableKind, 26 kind: &RunnableKind,
27 cfgs: &[CfgExpr], 27 cfg: &Option<CfgExpr>,
28 ) -> Result<(Vec<String>, Vec<String>)> { 28 ) -> Result<(Vec<String>, Vec<String>)> {
29 let mut args = Vec::new(); 29 let mut args = Vec::new();
30 let mut extra_args = Vec::new(); 30 let mut extra_args = Vec::new();
@@ -87,7 +87,7 @@ impl CargoTargetSpec {
87 args.push("--all-features".to_string()); 87 args.push("--all-features".to_string());
88 } else { 88 } else {
89 let mut features = Vec::new(); 89 let mut features = Vec::new();
90 for cfg in cfgs { 90 if let Some(cfg) = cfg.as_ref() {
91 required_features(cfg, &mut features); 91 required_features(cfg, &mut features);
92 } 92 }
93 for feature in &snap.config.cargo.features { 93 for feature in &snap.config.cargo.features {
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs
index aeacde0f7..121357a5a 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -745,7 +745,7 @@ pub(crate) fn runnable(
745 let workspace_root = spec.as_ref().map(|it| it.workspace_root.clone()); 745 let workspace_root = spec.as_ref().map(|it| it.workspace_root.clone());
746 let target = spec.as_ref().map(|s| s.target.clone()); 746 let target = spec.as_ref().map(|s| s.target.clone());
747 let (cargo_args, executable_args) = 747 let (cargo_args, executable_args) =
748 CargoTargetSpec::runnable_args(snap, spec, &runnable.kind, &runnable.cfg_exprs)?; 748 CargoTargetSpec::runnable_args(snap, spec, &runnable.kind, &runnable.cfg)?;
749 let label = runnable.label(target); 749 let label = runnable.label(target);
750 let location = location_link(snap, None, runnable.nav)?; 750 let location = location_link(snap, None, runnable.nav)?;
751 751