11//! Checks the licenses of third-party dependencies.
22
3- use cargo_metadata:: { Metadata , Package , PackageId , Resolve } ;
4- use std:: collections:: { BTreeSet , HashSet } ;
3+ use cargo_metadata:: { DepKindInfo , Metadata , Package , PackageId } ;
4+ use std:: collections:: HashSet ;
55use std:: path:: Path ;
66
77/// These are licenses that are allowed for all crates, including the runtime,
@@ -98,14 +98,12 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
9898 "autocfg" ,
9999 "bitflags" ,
100100 "block-buffer" ,
101- "bumpalo" , // Included in Cargo's dep graph but only activated on wasm32-*-unknown.
102101 "cc" ,
103102 "cfg-if" ,
104103 "chalk-derive" ,
105104 "chalk-engine" ,
106105 "chalk-ir" ,
107106 "chalk-solve" ,
108- "chrono" ,
109107 "convert_case" , // dependency of derive_more
110108 "compiler_builtins" ,
111109 "cpufeatures" ,
@@ -124,11 +122,9 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
124122 "dlmalloc" ,
125123 "either" ,
126124 "ena" ,
127- "env_logger" ,
128125 "expect-test" ,
129126 "fallible-iterator" , // dependency of `thorin`
130127 "fastrand" ,
131- "filetime" ,
132128 "fixedbitset" ,
133129 "flate2" ,
134130 "fluent-bundle" ,
@@ -142,21 +138,18 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
142138 "gsgdt" ,
143139 "hashbrown" ,
144140 "hermit-abi" ,
145- "humantime" ,
146141 "icu_list" ,
147142 "icu_locid" ,
148143 "icu_provider" ,
149144 "icu_provider_adapters" ,
150145 "icu_provider_macros" ,
151- "if_chain" ,
152146 "indexmap" ,
153147 "instant" ,
154148 "intl-memoizer" ,
155149 "intl_pluralrules" ,
156150 "itertools" ,
157151 "itoa" ,
158152 "jobserver" ,
159- "js-sys" , // Included in Cargo's dep graph but only activated on wasm32-*-unknown.
160153 "lazy_static" ,
161154 "libc" ,
162155 "libloading" ,
@@ -171,8 +164,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
171164 "memmap2" ,
172165 "memoffset" ,
173166 "miniz_oxide" ,
174- "num-integer" ,
175- "num-traits" ,
176167 "num_cpus" ,
177168 "object" ,
178169 "odht" ,
@@ -190,7 +181,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
190181 "proc-macro2" ,
191182 "psm" ,
192183 "punycode" ,
193- "quick-error" ,
194184 "quote" ,
195185 "rand" ,
196186 "rand_chacha" ,
@@ -235,7 +225,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
235225 "thiserror-impl" ,
236226 "thorin-dwp" ,
237227 "thread_local" ,
238- "time" ,
239228 "tinystr" ,
240229 "tinyvec" ,
241230 "tinyvec_macros" ,
@@ -268,13 +257,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
268257 "valuable" ,
269258 "version_check" ,
270259 "wasi" ,
271- // vvv Included in Cargo's dep graph but only activated on wasm32-*-unknown.
272- "wasm-bindgen" ,
273- "wasm-bindgen-backend" ,
274- "wasm-bindgen-macro" ,
275- "wasm-bindgen-macro-support" ,
276- "wasm-bindgen-shared" ,
277- // ^^^ Included in Cargo's dep graph but only activated on wasm32-*-unknown.
278260 "winapi" ,
279261 "winapi-i686-pc-windows-gnu" ,
280262 "winapi-util" ,
@@ -485,73 +467,55 @@ fn check_permitted_dependencies(
485467 restricted_dependency_crates : & [ & ' static str ] ,
486468 bad : & mut bool ,
487469) {
470+ let mut deps = HashSet :: new ( ) ;
471+ for to_check in restricted_dependency_crates {
472+ let to_check = pkg_from_name ( metadata, to_check) ;
473+ use cargo_platform:: Cfg ;
474+ use std:: str:: FromStr ;
475+ // We don't expect the compiler to ever run on wasm32, so strip
476+ // out those dependencies to avoid polluting the permitted list.
477+ deps_of_filtered ( metadata, & to_check. id , & mut deps, & |dep_kinds| {
478+ dep_kinds. iter ( ) . any ( |dep_kind| {
479+ dep_kind
480+ . target
481+ . as_ref ( )
482+ . map ( |target| {
483+ !target. matches (
484+ "wasm32-unknown-unknown" ,
485+ & [
486+ Cfg :: from_str ( "target_arch=\" wasm32\" " ) . unwrap ( ) ,
487+ Cfg :: from_str ( "target_os=\" unknown\" " ) . unwrap ( ) ,
488+ ] ,
489+ )
490+ } )
491+ . unwrap_or ( true )
492+ } )
493+ } ) ;
494+ }
495+
488496 // Check that the PERMITTED_DEPENDENCIES does not have unused entries.
489- for name in permitted_dependencies {
490- if !metadata . packages . iter ( ) . any ( |p| p . name == * name ) {
497+ for permitted in permitted_dependencies {
498+ if !deps . iter ( ) . any ( |dep_id| & pkg_from_id ( metadata , dep_id ) . name == permitted ) {
491499 tidy_error ! (
492500 bad,
493- "could not find allowed package `{}`\n \
501+ "could not find allowed package `{permitted }`\n \
494502 Remove from PERMITTED_DEPENDENCIES list if it is no longer used.",
495- name
496503 ) ;
497504 }
498505 }
499- // Get the list in a convenient form.
500- let permitted_dependencies: HashSet < _ > = permitted_dependencies. iter ( ) . cloned ( ) . collect ( ) ;
501-
502- // Check dependencies.
503- let mut visited = BTreeSet :: new ( ) ;
504- let mut unapproved = BTreeSet :: new ( ) ;
505- for & krate in restricted_dependency_crates. iter ( ) {
506- let pkg = pkg_from_name ( metadata, krate) ;
507- let mut bad =
508- check_crate_dependencies ( & permitted_dependencies, metadata, & mut visited, pkg) ;
509- unapproved. append ( & mut bad) ;
510- }
511-
512- if !unapproved. is_empty ( ) {
513- tidy_error ! ( bad, "Dependencies for {} not explicitly permitted:" , descr) ;
514- for dep in unapproved {
515- println ! ( "* {dep}" ) ;
516- }
517- }
518- }
519-
520- /// Checks the dependencies of the given crate from the given cargo metadata to see if they are on
521- /// the list of permitted dependencies. Returns a list of disallowed dependencies.
522- fn check_crate_dependencies < ' a > (
523- permitted_dependencies : & ' a HashSet < & ' static str > ,
524- metadata : & ' a Metadata ,
525- visited : & mut BTreeSet < & ' a PackageId > ,
526- krate : & ' a Package ,
527- ) -> BTreeSet < & ' a PackageId > {
528- // This will contain bad deps.
529- let mut unapproved = BTreeSet :: new ( ) ;
530-
531- // Check if we have already visited this crate.
532- if visited. contains ( & krate. id ) {
533- return unapproved;
534- }
535506
536- visited. insert ( & krate. id ) ;
507+ // Get in a convenient form.
508+ let permitted_dependencies: HashSet < _ > = permitted_dependencies. iter ( ) . cloned ( ) . collect ( ) ;
537509
538- // If this path is in-tree, we don't require it to be explicitly permitted.
539- if krate. source . is_some ( ) {
540- // If this dependency is not on `PERMITTED_DEPENDENCIES`, add to bad set.
541- if !permitted_dependencies. contains ( krate. name . as_str ( ) ) {
542- unapproved. insert ( & krate. id ) ;
510+ for dep in deps {
511+ let dep = pkg_from_id ( metadata, dep) ;
512+ // If this path is in-tree, we don't require it to be explicitly permitted.
513+ if dep. source . is_some ( ) {
514+ if !permitted_dependencies. contains ( dep. name . as_str ( ) ) {
515+ tidy_error ! ( bad, "Dependency for {descr} not explicitly permitted: {}" , dep. id) ;
516+ }
543517 }
544518 }
545-
546- // Do a DFS in the crate graph.
547- let to_check = deps_of ( metadata, & krate. id ) ;
548-
549- for dep in to_check {
550- let mut bad = check_crate_dependencies ( permitted_dependencies, metadata, visited, dep) ;
551- unapproved. append ( & mut bad) ;
552- }
553-
554- unapproved
555519}
556520
557521/// Prevents multiple versions of some expensive crates.
@@ -588,24 +552,6 @@ fn check_crate_duplicate(
588552 }
589553}
590554
591- /// Returns a list of dependencies for the given package.
592- fn deps_of < ' a > ( metadata : & ' a Metadata , pkg_id : & ' a PackageId ) -> Vec < & ' a Package > {
593- let resolve = metadata. resolve . as_ref ( ) . unwrap ( ) ;
594- let node = resolve
595- . nodes
596- . iter ( )
597- . find ( |n| & n. id == pkg_id)
598- . unwrap_or_else ( || panic ! ( "could not find `{pkg_id}` in resolve" ) ) ;
599- node. deps
600- . iter ( )
601- . map ( |dep| {
602- metadata. packages . iter ( ) . find ( |pkg| pkg. id == dep. pkg ) . unwrap_or_else ( || {
603- panic ! ( "could not find dep `{}` for pkg `{}` in resolve" , dep. pkg, pkg_id)
604- } )
605- } )
606- . collect ( )
607- }
608-
609555/// Finds a package with the given name.
610556fn pkg_from_name < ' a > ( metadata : & ' a Metadata , name : & ' static str ) -> & ' a Package {
611557 let mut i = metadata. packages . iter ( ) . filter ( |p| p. name == name) ;
@@ -615,41 +561,57 @@ fn pkg_from_name<'a>(metadata: &'a Metadata, name: &'static str) -> &'a Package
615561 result
616562}
617563
564+ fn pkg_from_id < ' a > ( metadata : & ' a Metadata , id : & PackageId ) -> & ' a Package {
565+ metadata. packages . iter ( ) . find ( |p| & p. id == id) . unwrap ( )
566+ }
567+
618568/// Finds all the packages that are in the rust runtime.
619569fn compute_runtime_crates < ' a > ( metadata : & ' a Metadata ) -> HashSet < & ' a PackageId > {
620- let resolve = metadata. resolve . as_ref ( ) . unwrap ( ) ;
621570 let mut result = HashSet :: new ( ) ;
622571 for name in RUNTIME_CRATES {
623572 let id = & pkg_from_name ( metadata, name) . id ;
624- normal_deps_of_r ( resolve , id, & mut result) ;
573+ deps_of_filtered ( metadata , id, & mut result, & |_| true ) ;
625574 }
626575 result
627576}
628577
629- /// Recursively find all normal dependencies.
630- fn normal_deps_of_r < ' a > (
631- resolve : & ' a Resolve ,
578+ /// Recursively find all dependencies.
579+ fn deps_of_filtered < ' a > (
580+ metadata : & ' a Metadata ,
632581 pkg_id : & ' a PackageId ,
633582 result : & mut HashSet < & ' a PackageId > ,
583+ filter : & dyn Fn ( & [ DepKindInfo ] ) -> bool ,
634584) {
635585 if !result. insert ( pkg_id) {
636586 return ;
637587 }
638- let node = resolve
588+ let node = metadata
589+ . resolve
590+ . as_ref ( )
591+ . unwrap ( )
639592 . nodes
640593 . iter ( )
641594 . find ( |n| & n. id == pkg_id)
642595 . unwrap_or_else ( || panic ! ( "could not find `{pkg_id}` in resolve" ) ) ;
643596 for dep in & node. deps {
644- normal_deps_of_r ( resolve, & dep. pkg , result) ;
597+ if !filter ( & dep. dep_kinds ) {
598+ continue ;
599+ }
600+ deps_of_filtered ( metadata, & dep. pkg , result, filter) ;
645601 }
646602}
647603
604+ fn direct_deps_of < ' a > ( metadata : & ' a Metadata , pkg_id : & ' a PackageId ) -> Vec < & ' a Package > {
605+ let resolve = metadata. resolve . as_ref ( ) . unwrap ( ) ;
606+ let node = resolve. nodes . iter ( ) . find ( |n| & n. id == pkg_id) . unwrap ( ) ;
607+ node. deps . iter ( ) . map ( |dep| pkg_from_id ( metadata, & dep. pkg ) ) . collect ( )
608+ }
609+
648610fn check_rustfix ( metadata : & Metadata , bad : & mut bool ) {
649611 let cargo = pkg_from_name ( metadata, "cargo" ) ;
650612 let compiletest = pkg_from_name ( metadata, "compiletest" ) ;
651- let cargo_deps = deps_of ( metadata, & cargo. id ) ;
652- let compiletest_deps = deps_of ( metadata, & compiletest. id ) ;
613+ let cargo_deps = direct_deps_of ( metadata, & cargo. id ) ;
614+ let compiletest_deps = direct_deps_of ( metadata, & compiletest. id ) ;
653615 let cargo_rustfix = cargo_deps. iter ( ) . find ( |p| p. name == "rustfix" ) . unwrap ( ) ;
654616 let compiletest_rustfix = compiletest_deps. iter ( ) . find ( |p| p. name == "rustfix" ) . unwrap ( ) ;
655617 if cargo_rustfix. version != compiletest_rustfix. version {
0 commit comments