@@ -177,6 +177,10 @@ impl FeatureOpts {
177
177
if let ForceAllTargets :: Yes = force_all_targets {
178
178
opts. ignore_inactive_targets = false ;
179
179
}
180
+ if unstable_flags. weak_dep_features {
181
+ // Force this ON because it only works with the new resolver.
182
+ opts. new_resolver = true ;
183
+ }
180
184
Ok ( opts)
181
185
}
182
186
}
@@ -311,6 +315,15 @@ pub struct FeatureResolver<'a, 'cfg> {
311
315
/// This has to be separate from `FeatureOpts.decouple_host_deps` because
312
316
/// `for_host` tracking is also needed for `itarget` to work properly.
313
317
track_for_host : bool ,
318
+ /// `dep_name?/feat_name` features that will be activated if `dep_name` is
319
+ /// ever activated.
320
+ ///
321
+ /// The key is the `(package, for_host, dep_name)` of the package whose
322
+ /// dependency will trigger the addition of new features. The value is the
323
+ /// set of `(feature, dep_prefix)` features to activate (`dep_prefix` is a
324
+ /// bool that indicates if `dep:` prefix was used).
325
+ deferred_weak_dependencies :
326
+ HashMap < ( PackageId , bool , InternedString ) , HashSet < ( InternedString , bool ) > > ,
314
327
}
315
328
316
329
impl < ' a , ' cfg > FeatureResolver < ' a , ' cfg > {
@@ -353,6 +366,7 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
353
366
activated_dependencies : HashMap :: new ( ) ,
354
367
processed_deps : HashSet :: new ( ) ,
355
368
track_for_host,
369
+ deferred_weak_dependencies : HashMap :: new ( ) ,
356
370
} ;
357
371
r. do_resolve ( specs, requested_features) ?;
358
372
log:: debug!( "features={:#?}" , r. activated_features) ;
@@ -399,6 +413,7 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
399
413
for_host : bool ,
400
414
fvs : & [ FeatureValue ] ,
401
415
) -> CargoResult < ( ) > {
416
+ log:: trace!( "activate_pkg {} {}" , pkg_id. name( ) , for_host) ;
402
417
// Add an empty entry to ensure everything is covered. This is intended for
403
418
// finding bugs where the resolver missed something it should have visited.
404
419
// Remove this in the future if `activated_features` uses an empty default.
@@ -446,56 +461,28 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
446
461
for_host : bool ,
447
462
fv : & FeatureValue ,
448
463
) -> CargoResult < ( ) > {
464
+ log:: trace!( "activate_fv {} {} {}" , pkg_id. name( ) , for_host, fv) ;
449
465
match fv {
450
466
FeatureValue :: Feature ( f) => {
451
467
self . activate_rec ( pkg_id, for_host, * f) ?;
452
468
}
453
469
FeatureValue :: Dep { dep_name } => {
454
- // Mark this dependency as activated.
455
- self . activated_dependencies
456
- . entry ( ( pkg_id, self . opts . decouple_host_deps && for_host) )
457
- . or_default ( )
458
- . insert ( * dep_name) ;
459
- // Activate the optional dep.
460
- for ( dep_pkg_id, deps) in self . deps ( pkg_id, for_host) {
461
- for ( dep, dep_for_host) in deps {
462
- if dep. name_in_toml ( ) != * dep_name {
463
- continue ;
464
- }
465
- let fvs = self . fvs_from_dependency ( dep_pkg_id, dep) ;
466
- self . activate_pkg ( dep_pkg_id, dep_for_host, & fvs) ?;
467
- }
468
- }
470
+ self . activate_dependency ( pkg_id, for_host, * dep_name) ?;
469
471
}
470
472
FeatureValue :: DepFeature {
471
473
dep_name,
472
474
dep_feature,
473
475
dep_prefix,
476
+ weak,
474
477
} => {
475
- // Activate a feature within a dependency.
476
- for ( dep_pkg_id, deps) in self . deps ( pkg_id, for_host) {
477
- for ( dep, dep_for_host) in deps {
478
- if dep. name_in_toml ( ) != * dep_name {
479
- continue ;
480
- }
481
- if dep. is_optional ( ) {
482
- // Activate the dependency on self.
483
- let fv = FeatureValue :: Dep {
484
- dep_name : * dep_name,
485
- } ;
486
- self . activate_fv ( pkg_id, for_host, & fv) ?;
487
- if !dep_prefix {
488
- // To retain compatibility with old behavior,
489
- // this also enables a feature of the same
490
- // name.
491
- self . activate_rec ( pkg_id, for_host, * dep_name) ?;
492
- }
493
- }
494
- // Activate the feature on the dependency.
495
- let fv = FeatureValue :: new ( * dep_feature) ;
496
- self . activate_fv ( dep_pkg_id, dep_for_host, & fv) ?;
497
- }
498
- }
478
+ self . activate_dep_feature (
479
+ pkg_id,
480
+ for_host,
481
+ * dep_name,
482
+ * dep_feature,
483
+ * dep_prefix,
484
+ * weak,
485
+ ) ?;
499
486
}
500
487
}
501
488
Ok ( ( ) )
@@ -509,6 +496,12 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
509
496
for_host : bool ,
510
497
feature_to_enable : InternedString ,
511
498
) -> CargoResult < ( ) > {
499
+ log:: trace!(
500
+ "activate_rec {} {} feat={}" ,
501
+ pkg_id. name( ) ,
502
+ for_host,
503
+ feature_to_enable
504
+ ) ;
512
505
let enabled = self
513
506
. activated_features
514
507
. entry ( ( pkg_id, self . opts . decouple_host_deps && for_host) )
@@ -539,6 +532,110 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
539
532
Ok ( ( ) )
540
533
}
541
534
535
+ /// Activate a dependency (`dep:dep_name` syntax).
536
+ fn activate_dependency (
537
+ & mut self ,
538
+ pkg_id : PackageId ,
539
+ for_host : bool ,
540
+ dep_name : InternedString ,
541
+ ) -> CargoResult < ( ) > {
542
+ // Mark this dependency as activated.
543
+ let save_for_host = self . opts . decouple_host_deps && for_host;
544
+ self . activated_dependencies
545
+ . entry ( ( pkg_id, save_for_host) )
546
+ . or_default ( )
547
+ . insert ( dep_name) ;
548
+ // Check for any deferred features.
549
+ let to_enable = self
550
+ . deferred_weak_dependencies
551
+ . remove ( & ( pkg_id, for_host, dep_name) ) ;
552
+ // Activate the optional dep.
553
+ for ( dep_pkg_id, deps) in self . deps ( pkg_id, for_host) {
554
+ for ( dep, dep_for_host) in deps {
555
+ if dep. name_in_toml ( ) != dep_name {
556
+ continue ;
557
+ }
558
+ if let Some ( to_enable) = & to_enable {
559
+ for ( dep_feature, dep_prefix) in to_enable {
560
+ log:: trace!(
561
+ "activate deferred {} {} -> {}/{}" ,
562
+ pkg_id. name( ) ,
563
+ for_host,
564
+ dep_name,
565
+ dep_feature
566
+ ) ;
567
+ if !dep_prefix {
568
+ self . activate_rec ( pkg_id, for_host, dep_name) ?;
569
+ }
570
+ let fv = FeatureValue :: new ( * dep_feature) ;
571
+ self . activate_fv ( dep_pkg_id, dep_for_host, & fv) ?;
572
+ }
573
+ }
574
+ let fvs = self . fvs_from_dependency ( dep_pkg_id, dep) ;
575
+ self . activate_pkg ( dep_pkg_id, dep_for_host, & fvs) ?;
576
+ }
577
+ }
578
+ Ok ( ( ) )
579
+ }
580
+
581
+ /// Activate a feature within a dependency (`dep_name/feat_name` syntax).
582
+ fn activate_dep_feature (
583
+ & mut self ,
584
+ pkg_id : PackageId ,
585
+ for_host : bool ,
586
+ dep_name : InternedString ,
587
+ dep_feature : InternedString ,
588
+ dep_prefix : bool ,
589
+ weak : bool ,
590
+ ) -> CargoResult < ( ) > {
591
+ for ( dep_pkg_id, deps) in self . deps ( pkg_id, for_host) {
592
+ for ( dep, dep_for_host) in deps {
593
+ if dep. name_in_toml ( ) != dep_name {
594
+ continue ;
595
+ }
596
+ if dep. is_optional ( ) {
597
+ let save_for_host = self . opts . decouple_host_deps && for_host;
598
+ if weak
599
+ && !self
600
+ . activated_dependencies
601
+ . get ( & ( pkg_id, save_for_host) )
602
+ . map ( |deps| deps. contains ( & dep_name) )
603
+ . unwrap_or ( false )
604
+ {
605
+ // This is weak, but not yet activated. Defer in case
606
+ // something comes along later and enables it.
607
+ log:: trace!(
608
+ "deferring feature {} {} -> {}/{}" ,
609
+ pkg_id. name( ) ,
610
+ for_host,
611
+ dep_name,
612
+ dep_feature
613
+ ) ;
614
+ self . deferred_weak_dependencies
615
+ . entry ( ( pkg_id, for_host, dep_name) )
616
+ . or_default ( )
617
+ . insert ( ( dep_feature, dep_prefix) ) ;
618
+ continue ;
619
+ }
620
+
621
+ // Activate the dependency on self.
622
+ let fv = FeatureValue :: Dep { dep_name } ;
623
+ self . activate_fv ( pkg_id, for_host, & fv) ?;
624
+ if !dep_prefix {
625
+ // To retain compatibility with old behavior,
626
+ // this also enables a feature of the same
627
+ // name.
628
+ self . activate_rec ( pkg_id, for_host, dep_name) ?;
629
+ }
630
+ }
631
+ // Activate the feature on the dependency.
632
+ let fv = FeatureValue :: new ( dep_feature) ;
633
+ self . activate_fv ( dep_pkg_id, dep_for_host, & fv) ?;
634
+ }
635
+ }
636
+ Ok ( ( ) )
637
+ }
638
+
542
639
/// Returns Vec of FeatureValues from a Dependency definition.
543
640
fn fvs_from_dependency ( & self , dep_id : PackageId , dep : & Dependency ) -> Vec < FeatureValue > {
544
641
let summary = self . resolve . summary ( dep_id) ;
0 commit comments