@@ -53,6 +53,7 @@ pub struct CompilerCache<S = Settings> {
5353}
5454
5555impl < S > CompilerCache < S > {
56+ /// Creates a new empty cache.
5657 pub fn new ( format : String , paths : ProjectPaths , preprocessed : bool ) -> Self {
5758 Self {
5859 format,
@@ -118,11 +119,10 @@ impl<S: CompilerSettings> CompilerCache<S> {
118119 /// cache.join_artifacts_files(project.artifacts_path());
119120 /// # Ok::<_, Box<dyn std::error::Error>>(())
120121 /// ```
121- #[ instrument( name = "CompilerCache::read" , skip_all ) ]
122+ #[ instrument( name = "CompilerCache::read" , err ) ]
122123 pub fn read ( path : & Path ) -> Result < Self > {
123- trace ! ( "reading solfiles cache at {}" , path. display( ) ) ;
124124 let cache: Self = utils:: read_json_file ( path) ?;
125- trace ! ( "read cache \" {} \" with {} entries" , cache. format , cache. files. len( ) ) ;
125+ trace ! ( cache. format , cache. files = cache. files. len( ) , "read cache" ) ;
126126 Ok ( cache)
127127 }
128128
@@ -787,43 +787,51 @@ impl<T: ArtifactOutput<CompilerContract = C::CompilerContract>, C: Compiler>
787787 }
788788
789789 /// Returns whether we are missing artifacts for the given file and version.
790- #[ instrument( level = "trace" , skip( self ) ) ]
791790 fn is_missing_artifacts ( & self , file : & Path , version : & Version , profile : & str ) -> bool {
791+ self . is_missing_artifacts_impl ( file, version, profile) . is_err ( )
792+ }
793+
794+ /// Returns whether we are missing artifacts for the given file and version.
795+ #[ instrument( level = "trace" , name = "is_missing_artifacts" , skip( self ) , ret) ]
796+ fn is_missing_artifacts_impl (
797+ & self ,
798+ file : & Path ,
799+ version : & Version ,
800+ profile : & str ,
801+ ) -> Result < ( ) , & ' static str > {
792802 let Some ( entry) = self . cache . entry ( file) else {
793- trace ! ( "missing cache entry" ) ;
794- return true ;
803+ return Err ( "missing cache entry" ) ;
795804 } ;
796805
797806 // only check artifact's existence if the file generated artifacts.
798807 // e.g. a solidity file consisting only of import statements (like interfaces that
799808 // re-export) do not create artifacts
800809 if entry. seen_by_compiler && entry. artifacts . is_empty ( ) {
801- trace ! ( "no artifacts" ) ;
802- return false ;
810+ return Ok ( ( ) ) ;
803811 }
804812
805813 if !entry. contains ( version, profile) {
806- trace ! ( "missing linked artifacts" ) ;
807- return true ;
814+ return Err ( "missing linked artifacts" ) ;
808815 }
809816
810- if entry. artifacts_for_version ( version) . any ( |artifact| {
811- let missing_artifact = !self . cached_artifacts . has_artifact ( & artifact. path ) ;
812- if missing_artifact {
813- trace ! ( "missing artifact \" {}\" " , artifact. path. display( ) ) ;
814- }
815- missing_artifact
816- } ) {
817- return true ;
817+ if entry
818+ . artifacts_for_version ( version)
819+ . any ( |artifact| !self . cached_artifacts . has_artifact ( & artifact. path ) )
820+ {
821+ return Err ( "missing artifact" ) ;
818822 }
819823
820824 // If any requested extra files are missing for any artifact, mark source as dirty to
821825 // generate them
822- self . missing_extra_files ( )
826+ if self . missing_extra_files ( ) {
827+ return Err ( "missing extra files" ) ;
828+ }
829+
830+ Ok ( ( ) )
823831 }
824832
825833 // Walks over all cache entries, detects dirty files and removes them from cache.
826- fn find_and_remove_dirty ( & mut self ) {
834+ fn remove_dirty_sources ( & mut self ) {
827835 fn populate_dirty_files < P : SourceParser > (
828836 file : & Path ,
829837 dirty_files : & mut HashSet < PathBuf > ,
@@ -839,41 +847,7 @@ impl<T: ArtifactOutput<CompilerContract = C::CompilerContract>, C: Compiler>
839847 }
840848 }
841849
842- let existing_profiles = self . project . settings_profiles ( ) . collect :: < BTreeMap < _ , _ > > ( ) ;
843-
844- let mut dirty_profiles = HashSet :: new ( ) ;
845- for ( profile, settings) in & self . cache . profiles {
846- if !existing_profiles. get ( profile. as_str ( ) ) . is_some_and ( |p| p. can_use_cached ( settings) )
847- {
848- trace ! ( "dirty profile: {}" , profile) ;
849- dirty_profiles. insert ( profile. clone ( ) ) ;
850- }
851- }
852-
853- for profile in & dirty_profiles {
854- self . cache . profiles . remove ( profile) ;
855- }
856-
857- self . cache . files . retain ( |_, entry| {
858- // keep entries which already had no artifacts
859- if entry. artifacts . is_empty ( ) {
860- return true ;
861- }
862- entry. artifacts . retain ( |_, artifacts| {
863- artifacts. retain ( |_, artifacts| {
864- artifacts. retain ( |profile, _| !dirty_profiles. contains ( profile) ) ;
865- !artifacts. is_empty ( )
866- } ) ;
867- !artifacts. is_empty ( )
868- } ) ;
869- !entry. artifacts . is_empty ( )
870- } ) ;
871-
872- for ( profile, settings) in existing_profiles {
873- if !self . cache . profiles . contains_key ( profile) {
874- self . cache . profiles . insert ( profile. to_string ( ) , settings. clone ( ) ) ;
875- }
876- }
850+ self . update_profiles ( ) ;
877851
878852 // Iterate over existing cache entries.
879853 let files = self . cache . files . keys ( ) . cloned ( ) . collect :: < HashSet < _ > > ( ) ;
@@ -899,7 +873,7 @@ impl<T: ArtifactOutput<CompilerContract = C::CompilerContract>, C: Compiler>
899873
900874 // Pre-add all sources that are guaranteed to be dirty
901875 for file in sources. keys ( ) {
902- if self . is_dirty_impl ( file, false ) {
876+ if self . is_dirty ( file, false ) {
903877 self . dirty_sources . insert ( file. clone ( ) ) ;
904878 }
905879 }
@@ -928,7 +902,7 @@ impl<T: ArtifactOutput<CompilerContract = C::CompilerContract>, C: Compiler>
928902 } else if !is_src
929903 && self . dirty_sources . contains ( import)
930904 && ( !self . is_source_file ( import)
931- || self . is_dirty_impl ( import, true )
905+ || self . is_dirty ( import, true )
932906 || self . cache . mocks . contains ( file) )
933907 {
934908 if self . cache . mocks . contains ( file) {
@@ -953,36 +927,76 @@ impl<T: ArtifactOutput<CompilerContract = C::CompilerContract>, C: Compiler>
953927 }
954928 }
955929
956- fn is_dirty_impl ( & self , file : & Path , use_interface_repr : bool ) -> bool {
930+ /// Updates the profiles in the cache, removing those which are dirty alongside their artifacts.
931+ fn update_profiles ( & mut self ) {
932+ let existing_profiles = self . project . settings_profiles ( ) . collect :: < BTreeMap < _ , _ > > ( ) ;
933+
934+ let mut dirty_profiles = HashSet :: new ( ) ;
935+ for ( profile, settings) in & self . cache . profiles {
936+ if !existing_profiles. get ( profile. as_str ( ) ) . is_some_and ( |p| p. can_use_cached ( settings) )
937+ {
938+ dirty_profiles. insert ( profile. clone ( ) ) ;
939+ }
940+ }
941+
942+ for profile in & dirty_profiles {
943+ trace ! ( profile, "removing dirty profile and artifacts" ) ;
944+ self . cache . profiles . remove ( profile) ;
945+ }
946+
947+ for ( profile, settings) in existing_profiles {
948+ if !self . cache . profiles . contains_key ( profile) {
949+ trace ! ( profile, "adding new profile" ) ;
950+ self . cache . profiles . insert ( profile. to_string ( ) , settings. clone ( ) ) ;
951+ }
952+ }
953+
954+ self . cache . files . retain ( |_, entry| {
955+ // keep entries which already had no artifacts
956+ if entry. artifacts . is_empty ( ) {
957+ return true ;
958+ }
959+ entry. artifacts . retain ( |_, artifacts| {
960+ artifacts. retain ( |_, artifacts| {
961+ artifacts. retain ( |profile, _| !dirty_profiles. contains ( profile) ) ;
962+ !artifacts. is_empty ( )
963+ } ) ;
964+ !artifacts. is_empty ( )
965+ } ) ;
966+ !entry. artifacts . is_empty ( )
967+ } ) ;
968+ }
969+
970+ fn is_dirty ( & self , file : & Path , use_interface_repr : bool ) -> bool {
971+ self . is_dirty_impl ( file, use_interface_repr) . is_err ( )
972+ }
973+
974+ #[ instrument( level = "trace" , name = "is_dirty" , skip( self ) , ret) ]
975+ fn is_dirty_impl ( & self , file : & Path , use_interface_repr : bool ) -> Result < ( ) , & ' static str > {
957976 let Some ( entry) = self . cache . entry ( file) else {
958- trace ! ( "missing cache entry" ) ;
959- return true ;
977+ return Err ( "missing cache entry" ) ;
960978 } ;
961979
962980 if use_interface_repr && self . cache . preprocessed {
963981 let Some ( interface_hash) = self . interface_repr_hashes . get ( file) else {
964- trace ! ( "missing interface hash" ) ;
965- return true ;
982+ return Err ( "missing interface hash" ) ;
966983 } ;
967984
968985 if entry. interface_repr_hash . as_ref ( ) != Some ( interface_hash) {
969- trace ! ( "interface hash changed" ) ;
970- return true ;
971- } ;
986+ return Err ( "interface hash changed" ) ;
987+ }
972988 } else {
973989 let Some ( content_hash) = self . content_hashes . get ( file) else {
974- trace ! ( "missing content hash" ) ;
975- return true ;
990+ return Err ( "missing content hash" ) ;
976991 } ;
977992
978993 if entry. content_hash != * content_hash {
979- trace ! ( "content hash changed" ) ;
980- return true ;
994+ return Err ( "content hash changed" ) ;
981995 }
982996 }
983997
984998 // all things match, can be reused
985- false
999+ Ok ( ( ) )
9861000 }
9871001
9881002 /// Adds the file's hashes to the set if not set yet
@@ -1155,7 +1169,7 @@ impl<'a, T: ArtifactOutput<CompilerContract = C::CompilerContract>, C: Compiler>
11551169 pub fn remove_dirty_sources ( & mut self ) {
11561170 match self {
11571171 ArtifactsCache :: Ephemeral ( ..) => { }
1158- ArtifactsCache :: Cached ( cache) => cache. find_and_remove_dirty ( ) ,
1172+ ArtifactsCache :: Cached ( cache) => cache. remove_dirty_sources ( ) ,
11591173 }
11601174 }
11611175
0 commit comments