@@ -98,9 +98,13 @@ impl UnusedDepState {
9898 } else {
9999 continue ;
100100 } ;
101- state
102- . externs
103- . insert ( dep. extern_crate_name , ExternState { manifest_deps } ) ;
101+ state. externs . insert (
102+ dep. extern_crate_name ,
103+ ExternState {
104+ unit : dep. unit . clone ( ) ,
105+ manifest_deps,
106+ } ,
107+ ) ;
104108 }
105109 }
106110
@@ -229,6 +233,14 @@ impl UnusedDepState {
229233 ) ;
230234 continue ;
231235 }
236+ if is_transitive_dep ( & extern_state. unit , & state. unused_externs , build_runner) {
237+ debug ! (
238+ "pkg {} v{} ({dep_kind:?}): ignoring unused extern `{ext}`, may be activating features" ,
239+ pkg_id. name( ) ,
240+ pkg_id. version( ) ,
241+ ) ;
242+ continue ;
243+ }
232244
233245 // Implicitly added dependencies (in the same crate) aren't interesting
234246 let dependency = if let Some ( dependency) = & extern_state. manifest_deps {
@@ -332,6 +344,7 @@ struct DependenciesState {
332344
333345#[ derive( Clone ) ]
334346struct ExternState {
347+ unit : Unit ,
335348 manifest_deps : Option < Vec < Dependency > > ,
336349}
337350
@@ -359,3 +372,34 @@ fn unit_desc(unit: &Unit) -> String {
359372 unit. mode,
360373 )
361374}
375+
376+ #[ instrument( skip_all) ]
377+ fn is_transitive_dep (
378+ direct_dep_unit : & Unit ,
379+ unused_externs : & IndexMap < Unit , Vec < InternedString > > ,
380+ build_runner : & mut BuildRunner < ' _ , ' _ > ,
381+ ) -> bool {
382+ let mut queue = std:: collections:: VecDeque :: new ( ) ;
383+ for root_unit in unused_externs. keys ( ) {
384+ for unit_dep in build_runner. unit_deps ( root_unit) {
385+ if root_unit. pkg . package_id ( ) == unit_dep. unit . pkg . package_id ( ) {
386+ continue ;
387+ }
388+ if unit_dep. unit == * direct_dep_unit {
389+ continue ;
390+ }
391+ queue. push_back ( & unit_dep. unit ) ;
392+ }
393+ }
394+
395+ while let Some ( dep_unit) = queue. pop_front ( ) {
396+ for unit_dep in build_runner. unit_deps ( dep_unit) {
397+ if unit_dep. unit == * direct_dep_unit {
398+ return true ;
399+ }
400+ queue. push_back ( & unit_dep. unit ) ;
401+ }
402+ }
403+
404+ false
405+ }
0 commit comments