@@ -17,8 +17,9 @@ use std::{iter, mem};
1717
1818use flycheck:: { FlycheckConfig , FlycheckHandle } ;
1919use hir:: { db:: DefDatabase , Change , ProcMacros } ;
20+ use ide:: CrateId ;
2021use ide_db:: {
21- base_db:: { salsa:: Durability , CrateGraph , ProcMacroPaths } ,
22+ base_db:: { salsa:: Durability , CrateGraph , CrateOrigin , ProcMacroPaths , Version } ,
2223 FxHashMap ,
2324} ;
2425use itertools:: Itertools ;
@@ -28,7 +29,7 @@ use project_model::{ProjectWorkspace, WorkspaceBuildScripts};
2829use rustc_hash:: FxHashSet ;
2930use stdx:: { format_to, thread:: ThreadIntent } ;
3031use triomphe:: Arc ;
31- use vfs:: { AbsPath , ChangeKind } ;
32+ use vfs:: { AbsPath , AbsPathBuf , ChangeKind } ;
3233
3334use crate :: {
3435 config:: { Config , FilesWatcher , LinkedProject } ,
@@ -532,7 +533,7 @@ impl GlobalState {
532533 // deleted or created we trigger a reconstruction of the crate graph
533534 let mut crate_graph_file_dependencies = FxHashSet :: default ( ) ;
534535
535- let mut load = |path : & AbsPath | {
536+ let load = |path : & AbsPath | {
536537 let _p = tracing:: span!( tracing:: Level :: DEBUG , "switch_workspaces::load" ) . entered ( ) ;
537538 let vfs_path = vfs:: VfsPath :: from ( path. to_path_buf ( ) ) ;
538539 crate_graph_file_dependencies. insert ( vfs_path. clone ( ) ) ;
@@ -547,56 +548,8 @@ impl GlobalState {
547548 }
548549 } ;
549550
550- let mut crate_graph = CrateGraph :: default ( ) ;
551- let mut proc_macro_paths = Vec :: default ( ) ;
552- let mut layouts = Vec :: default ( ) ;
553- let mut toolchains = Vec :: default ( ) ;
554- let e = Err ( Arc :: from ( "missing layout" ) ) ;
555- for ws in & * * self . workspaces {
556- let ( other, mut crate_proc_macros) =
557- ws. to_crate_graph ( & mut load, self . config . extra_env ( ) ) ;
558- let num_layouts = layouts. len ( ) ;
559- let num_toolchains = toolchains. len ( ) ;
560- let ( toolchain, layout) = match ws {
561- ProjectWorkspace :: Cargo { toolchain, target_layout, .. }
562- | ProjectWorkspace :: Json { toolchain, target_layout, .. } => {
563- ( toolchain. clone ( ) , target_layout. clone ( ) )
564- }
565- ProjectWorkspace :: DetachedFiles { .. } => {
566- ( None , Err ( "detached files have no layout" . into ( ) ) )
567- }
568- } ;
569-
570- let mapping = crate_graph. extend (
571- other,
572- & mut crate_proc_macros,
573- |( cg_id, _cg_data) , ( _o_id, _o_data) | {
574- // if the newly created crate graph's layout is equal to the crate of the merged graph, then
575- // we can merge the crates.
576- layouts[ cg_id. into_raw ( ) . into_u32 ( ) as usize ] == layout
577- && toolchains[ cg_id. into_raw ( ) . into_u32 ( ) as usize ] == toolchain
578- } ,
579- ) ;
580- // Populate the side tables for the newly merged crates
581- mapping. values ( ) . for_each ( |val| {
582- let idx = val. into_raw ( ) . into_u32 ( ) as usize ;
583- // we only need to consider crates that were not merged and remapped, as the
584- // ones that were remapped already have the correct layout and toolchain
585- if idx >= num_layouts {
586- if layouts. len ( ) <= idx {
587- layouts. resize ( idx + 1 , e. clone ( ) ) ;
588- }
589- layouts[ idx] = layout. clone ( ) ;
590- }
591- if idx >= num_toolchains {
592- if toolchains. len ( ) <= idx {
593- toolchains. resize ( idx + 1 , None ) ;
594- }
595- toolchains[ idx] = toolchain. clone ( ) ;
596- }
597- } ) ;
598- proc_macro_paths. push ( crate_proc_macros) ;
599- }
551+ let ( crate_graph, proc_macro_paths, layouts, toolchains) =
552+ ws_to_crate_graph ( & self . workspaces , self . config . extra_env ( ) , load) ;
600553
601554 let mut change = Change :: new ( ) ;
602555 if self . config . expand_proc_macros ( ) {
@@ -609,6 +562,8 @@ impl GlobalState {
609562 self . fetch_proc_macros_queue . request_op ( cause, proc_macro_paths) ;
610563 }
611564 change. set_crate_graph ( crate_graph) ;
565+ change. set_target_data_layouts ( layouts) ;
566+ change. set_toolchains ( toolchains) ;
612567 self . analysis_host . apply_change ( change) ;
613568 self . crate_graph_file_dependencies = crate_graph_file_dependencies;
614569 }
@@ -719,6 +674,97 @@ impl GlobalState {
719674 }
720675}
721676
677+ // FIXME: Move this into load-cargo?
678+ pub fn ws_to_crate_graph (
679+ workspaces : & [ ProjectWorkspace ] ,
680+ extra_env : & FxHashMap < String , String > ,
681+ mut load : impl FnMut ( & AbsPath ) -> Option < vfs:: FileId > ,
682+ ) -> (
683+ CrateGraph ,
684+ Vec < FxHashMap < CrateId , Result < ( Option < String > , AbsPathBuf ) , String > > > ,
685+ Vec < Result < Arc < str > , Arc < str > > > ,
686+ Vec < Option < Version > > ,
687+ ) {
688+ let mut crate_graph = CrateGraph :: default ( ) ;
689+ let mut proc_macro_paths = Vec :: default ( ) ;
690+ let mut layouts = Vec :: default ( ) ;
691+ let mut toolchains = Vec :: default ( ) ;
692+ let e = Err ( Arc :: from ( "missing layout" ) ) ;
693+ for ws in workspaces {
694+ let ( other, mut crate_proc_macros) = ws. to_crate_graph ( & mut load, extra_env) ;
695+ let num_layouts = layouts. len ( ) ;
696+ let num_toolchains = toolchains. len ( ) ;
697+ let ( toolchain, layout) = match ws {
698+ ProjectWorkspace :: Cargo { toolchain, target_layout, .. }
699+ | ProjectWorkspace :: Json { toolchain, target_layout, .. } => {
700+ ( toolchain. clone ( ) , target_layout. clone ( ) )
701+ }
702+ ProjectWorkspace :: DetachedFiles { .. } => {
703+ ( None , Err ( "detached files have no layout" . into ( ) ) )
704+ }
705+ } ;
706+
707+ let mapping = crate_graph. extend (
708+ other,
709+ & mut crate_proc_macros,
710+ |( cg_id, _cg_data) , ( _o_id, _o_data) | {
711+ // if the newly created crate graph's layout is equal to the crate of the merged graph, then
712+ // we can merge the crates.
713+ let id = cg_id. into_raw ( ) . into_u32 ( ) as usize ;
714+ if layouts[ id] == layout && toolchains[ id] == toolchain {
715+ let ( res, update) = match ( & _cg_data. origin , & _o_data. origin ) {
716+ ( a, b)
717+ if a == b && _cg_data. eq_ignoring_origin_and_deps ( _o_data, false ) =>
718+ {
719+ ( true , false )
720+ }
721+ ( a @ CrateOrigin :: Local { .. } , CrateOrigin :: Library { .. } )
722+ | ( a @ CrateOrigin :: Library { .. } , CrateOrigin :: Local { .. } )
723+ if _cg_data. eq_ignoring_origin_and_deps ( _o_data, true ) =>
724+ {
725+ // If the origins differ, check if the two crates are equal without
726+ // considering the dev dependencies, if they are, they most likely are in
727+ // different loaded workspaces which may cause issues. We keep the local
728+ // version and discard the library one as the local version may have
729+ // dev-dependencies that we want to keep resolving. See #15656 for more
730+ // information.
731+ ( true , !a. is_local ( ) )
732+ }
733+ ( _, _) => ( false , false ) ,
734+ } ;
735+ if res && update {
736+ _cg_data. origin = _o_data. origin . clone ( ) ;
737+ _cg_data. dependencies = _o_data. dependencies . clone ( ) ;
738+ }
739+ res
740+ } else {
741+ false
742+ }
743+ } ,
744+ ) ;
745+ // Populate the side tables for the newly merged crates
746+ mapping. values ( ) . for_each ( |val| {
747+ let idx = val. into_raw ( ) . into_u32 ( ) as usize ;
748+ // we only need to consider crates that were not merged and remapped, as the
749+ // ones that were remapped already have the correct layout and toolchain
750+ if idx >= num_layouts {
751+ if layouts. len ( ) <= idx {
752+ layouts. resize ( idx + 1 , e. clone ( ) ) ;
753+ }
754+ layouts[ idx] = layout. clone ( ) ;
755+ }
756+ if idx >= num_toolchains {
757+ if toolchains. len ( ) <= idx {
758+ toolchains. resize ( idx + 1 , None ) ;
759+ }
760+ toolchains[ idx] = toolchain. clone ( ) ;
761+ }
762+ } ) ;
763+ proc_macro_paths. push ( crate_proc_macros) ;
764+ }
765+ ( crate_graph, proc_macro_paths, layouts, toolchains)
766+ }
767+
722768pub ( crate ) fn should_refresh_for_change ( path : & AbsPath , change_kind : ChangeKind ) -> bool {
723769 const IMPLICIT_TARGET_FILES : & [ & str ] = & [ "build.rs" , "src/main.rs" , "src/lib.rs" ] ;
724770 const IMPLICIT_TARGET_DIRS : & [ & str ] = & [ "src/bin" , "examples" , "tests" , "benches" ] ;
0 commit comments