@@ -7,7 +7,7 @@ use std::{collections::VecDeque, fmt, fs, path::Path, process::Command};
7
7
use anyhow:: { format_err, Context , Result } ;
8
8
use base_db:: { CrateDisplayName , CrateGraph , CrateId , CrateName , Edition , Env , FileId , ProcMacro } ;
9
9
use cargo_workspace:: DepKind ;
10
- use cfg:: { CfgAtom , CfgDiff , CfgOptions } ;
10
+ use cfg:: { CfgDiff , CfgOptions } ;
11
11
use paths:: { AbsPath , AbsPathBuf } ;
12
12
use proc_macro_api:: ProcMacroClient ;
13
13
use rustc_hash:: { FxHashMap , FxHashSet } ;
@@ -22,6 +22,8 @@ use crate::{
22
22
Sysroot , TargetKind ,
23
23
} ;
24
24
25
+ pub type CfgOverrides = FxHashMap < String , CfgDiff > ;
26
+
25
27
/// `PackageRoot` describes a package root folder.
26
28
/// Which may be an external dependency, or a member of
27
29
/// the current workspace.
@@ -46,6 +48,7 @@ pub enum ProjectWorkspace {
46
48
/// FIXME: make this a per-crate map, as, eg, build.rs might have a
47
49
/// different target.
48
50
rustc_cfg : Vec < CfgFlag > ,
51
+ cfg_overrides : CfgOverrides ,
49
52
} ,
50
53
/// Project workspace was manually specified using a `rust-project.json` file.
51
54
Json { project : ProjectJson , sysroot : Option < Sysroot > , rustc_cfg : Vec < CfgFlag > } ,
@@ -67,7 +70,7 @@ impl fmt::Debug for ProjectWorkspace {
67
70
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
68
71
// Make sure this isn't too verbose.
69
72
match self {
70
- ProjectWorkspace :: Cargo { cargo, sysroot, rustc, rustc_cfg } => f
73
+ ProjectWorkspace :: Cargo { cargo, sysroot, rustc, rustc_cfg, cfg_overrides } => f
71
74
. debug_struct ( "Cargo" )
72
75
. field ( "root" , & cargo. workspace_root ( ) . file_name ( ) )
73
76
. field ( "n_packages" , & cargo. packages ( ) . len ( ) )
@@ -77,6 +80,7 @@ impl fmt::Debug for ProjectWorkspace {
77
80
& rustc. as_ref ( ) . map_or ( 0 , |rc| rc. packages ( ) . len ( ) ) ,
78
81
)
79
82
. field ( "n_rustc_cfg" , & rustc_cfg. len ( ) )
83
+ . field ( "n_cfg_overrides" , & cfg_overrides. len ( ) )
80
84
. finish ( ) ,
81
85
ProjectWorkspace :: Json { project, sysroot, rustc_cfg } => {
82
86
let mut debug_struct = f. debug_struct ( "Json" ) ;
@@ -164,7 +168,9 @@ impl ProjectWorkspace {
164
168
} ;
165
169
166
170
let rustc_cfg = rustc_cfg:: get ( Some ( & cargo_toml) , config. target . as_deref ( ) ) ;
167
- ProjectWorkspace :: Cargo { cargo, sysroot, rustc, rustc_cfg }
171
+
172
+ let cfg_overrides = config. cfg_overrides ( ) ;
173
+ ProjectWorkspace :: Cargo { cargo, sysroot, rustc, rustc_cfg, cfg_overrides }
168
174
}
169
175
} ;
170
176
@@ -213,43 +219,45 @@ impl ProjectWorkspace {
213
219
} )
214
220
} ) )
215
221
. collect :: < Vec < _ > > ( ) ,
216
- ProjectWorkspace :: Cargo { cargo, sysroot, rustc, rustc_cfg : _ } => cargo
217
- . packages ( )
218
- . map ( |pkg| {
219
- let is_member = cargo[ pkg] . is_member ;
220
- let pkg_root = cargo[ pkg] . root ( ) . to_path_buf ( ) ;
221
-
222
- let mut include = vec ! [ pkg_root. clone( ) ] ;
223
- include. extend (
224
- build_data
225
- . and_then ( |it| it. get ( cargo. workspace_root ( ) ) )
226
- . and_then ( |map| map. get ( & cargo[ pkg] . id ) )
227
- . and_then ( |it| it. out_dir . clone ( ) ) ,
228
- ) ;
222
+ ProjectWorkspace :: Cargo { cargo, sysroot, rustc, rustc_cfg : _, cfg_overrides : _ } => {
223
+ cargo
224
+ . packages ( )
225
+ . map ( |pkg| {
226
+ let is_member = cargo[ pkg] . is_member ;
227
+ let pkg_root = cargo[ pkg] . root ( ) . to_path_buf ( ) ;
228
+
229
+ let mut include = vec ! [ pkg_root. clone( ) ] ;
230
+ include. extend (
231
+ build_data
232
+ . and_then ( |it| it. get ( cargo. workspace_root ( ) ) )
233
+ . and_then ( |map| map. get ( & cargo[ pkg] . id ) )
234
+ . and_then ( |it| it. out_dir . clone ( ) ) ,
235
+ ) ;
229
236
230
- let mut exclude = vec ! [ pkg_root. join( ".git" ) ] ;
231
- if is_member {
232
- exclude. push ( pkg_root. join ( "target" ) ) ;
233
- } else {
234
- exclude. push ( pkg_root. join ( "tests" ) ) ;
235
- exclude. push ( pkg_root. join ( "examples" ) ) ;
236
- exclude. push ( pkg_root. join ( "benches" ) ) ;
237
- }
238
- PackageRoot { is_member, include, exclude }
239
- } )
240
- . chain ( sysroot. crates ( ) . map ( |krate| PackageRoot {
241
- is_member : false ,
242
- include : vec ! [ sysroot[ krate] . root_dir( ) . to_path_buf( ) ] ,
243
- exclude : Vec :: new ( ) ,
244
- } ) )
245
- . chain ( rustc. into_iter ( ) . flat_map ( |rustc| {
246
- rustc. packages ( ) . map ( move |krate| PackageRoot {
237
+ let mut exclude = vec ! [ pkg_root. join( ".git" ) ] ;
238
+ if is_member {
239
+ exclude. push ( pkg_root. join ( "target" ) ) ;
240
+ } else {
241
+ exclude. push ( pkg_root. join ( "tests" ) ) ;
242
+ exclude. push ( pkg_root. join ( "examples" ) ) ;
243
+ exclude. push ( pkg_root. join ( "benches" ) ) ;
244
+ }
245
+ PackageRoot { is_member, include, exclude }
246
+ } )
247
+ . chain ( sysroot. crates ( ) . map ( |krate| PackageRoot {
247
248
is_member : false ,
248
- include : vec ! [ rustc [ krate] . root ( ) . to_path_buf( ) ] ,
249
+ include : vec ! [ sysroot [ krate] . root_dir ( ) . to_path_buf( ) ] ,
249
250
exclude : Vec :: new ( ) ,
250
- } )
251
- } ) )
252
- . collect ( ) ,
251
+ } ) )
252
+ . chain ( rustc. into_iter ( ) . flat_map ( |rustc| {
253
+ rustc. packages ( ) . map ( move |krate| PackageRoot {
254
+ is_member : false ,
255
+ include : vec ! [ rustc[ krate] . root( ) . to_path_buf( ) ] ,
256
+ exclude : Vec :: new ( ) ,
257
+ } )
258
+ } ) )
259
+ . collect ( )
260
+ }
253
261
ProjectWorkspace :: DetachedFiles { files, sysroot, .. } => files
254
262
. into_iter ( )
255
263
. map ( |detached_file| PackageRoot {
@@ -299,16 +307,22 @@ impl ProjectWorkspace {
299
307
project,
300
308
sysroot,
301
309
) ,
302
- ProjectWorkspace :: Cargo { cargo, sysroot, rustc, rustc_cfg } => cargo_to_crate_graph (
303
- rustc_cfg. clone ( ) ,
304
- & proc_macro_loader,
305
- load,
306
- cargo,
307
- build_data. and_then ( |it| it. get ( cargo. workspace_root ( ) ) ) ,
308
- sysroot,
309
- rustc,
310
- rustc. as_ref ( ) . zip ( build_data) . and_then ( |( it, map) | map. get ( it. workspace_root ( ) ) ) ,
311
- ) ,
310
+ ProjectWorkspace :: Cargo { cargo, sysroot, rustc, rustc_cfg, cfg_overrides } => {
311
+ cargo_to_crate_graph (
312
+ rustc_cfg. clone ( ) ,
313
+ cfg_overrides,
314
+ & proc_macro_loader,
315
+ load,
316
+ cargo,
317
+ build_data. and_then ( |it| it. get ( cargo. workspace_root ( ) ) ) ,
318
+ sysroot,
319
+ rustc,
320
+ rustc
321
+ . as_ref ( )
322
+ . zip ( build_data)
323
+ . and_then ( |( it, map) | map. get ( it. workspace_root ( ) ) ) ,
324
+ )
325
+ }
312
326
ProjectWorkspace :: DetachedFiles { files, sysroot, rustc_cfg } => {
313
327
detached_files_to_crate_graph ( rustc_cfg. clone ( ) , load, files, sysroot)
314
328
}
@@ -398,6 +412,7 @@ fn project_json_to_crate_graph(
398
412
399
413
fn cargo_to_crate_graph (
400
414
rustc_cfg : Vec < CfgFlag > ,
415
+ override_cfg : & CfgOverrides ,
401
416
proc_macro_loader : & dyn Fn ( & Path ) -> Vec < ProcMacro > ,
402
417
load : & mut dyn FnMut ( & AbsPath ) -> Option < FileId > ,
403
418
cargo : & CargoWorkspace ,
@@ -427,15 +442,16 @@ fn cargo_to_crate_graph(
427
442
for pkg in cargo. packages ( ) {
428
443
let mut cfg_options = & cfg_options;
429
444
let mut replaced_cfg_options;
430
- if cargo[ pkg] . name == "core" {
431
- // FIXME: in the specific case of libcore in rust-lang/rust (i.e. it is not coming from
432
- // a sysroot), there's a `#![cfg(not(test))]` at the top of it that makes its contents
433
- // get ignored by r-a. We should implement a more general solution for this
445
+ if let Some ( overrides) = override_cfg. get ( & cargo[ pkg] . name ) {
446
+ // FIXME: this is sort of a hack to deal with #![cfg(not(test))] vanishing such as seen
447
+ // in ed25519_dalek (#7243), and libcore (#9203) (although you only hit that one while
448
+ // working on rust-lang/rust as that's the only time it appears outside sysroot).
449
+ //
450
+ // A more ideal solution might be to reanalyze crates based on where the cursor is and
451
+ // figure out the set of cfgs that would have to apply to make it active.
434
452
435
453
replaced_cfg_options = cfg_options. clone ( ) ;
436
- replaced_cfg_options. apply_diff (
437
- CfgDiff :: new ( Default :: default ( ) , vec ! [ CfgAtom :: Flag ( "test" . into( ) ) ] ) . unwrap ( ) ,
438
- ) ;
454
+ replaced_cfg_options. apply_diff ( overrides. clone ( ) ) ;
439
455
cfg_options = & replaced_cfg_options;
440
456
} ;
441
457
0 commit comments