@@ -8,13 +8,14 @@ use failure::{bail, ensure};
8
8
use log:: debug;
9
9
10
10
use crate :: core:: interning:: InternedString ;
11
- use crate :: core:: { Dependency , FeatureValue , PackageId , SourceId , Summary } ;
11
+ use crate :: core:: { Dependency , PackageId , SourceId , Summary } ;
12
12
use crate :: util:: CargoResult ;
13
13
use crate :: util:: Graph ;
14
14
15
+ use super :: dep_cache;
15
16
use super :: dep_cache:: RegistryQueryer ;
16
17
use super :: errors:: ActivateResult ;
17
- use super :: types:: { ConflictMap , ConflictReason , DepInfo , Method } ;
18
+ use super :: types:: { ConflictMap , DepInfo , Method } ;
18
19
19
20
pub use super :: encode:: { EncodableDependency , EncodablePackageId , EncodableResolve } ;
20
21
pub use super :: encode:: { Metadata , WorkspaceResolve } ;
@@ -150,15 +151,25 @@ impl Context {
150
151
151
152
pub fn build_deps (
152
153
& mut self ,
153
- registry : & mut RegistryQueryer < ' _ > ,
154
+ registry : & mut dep_cache :: RegistryQueryer < ' _ > ,
154
155
parent : Option < PackageId > ,
155
156
candidate : & Summary ,
156
157
method : & Method < ' _ > ,
157
158
) -> ActivateResult < Vec < DepInfo > > {
158
159
// First, figure out our set of dependencies based on the requested set
159
160
// of features. This also calculates what features we're going to enable
160
161
// for our own dependencies.
161
- let deps = self . resolve_features ( parent, candidate, method) ?;
162
+ let ( used_features, deps) = dep_cache:: resolve_features ( parent, candidate, method) ?;
163
+
164
+ // Record what list of features is active for this package.
165
+ if !used_features. is_empty ( ) {
166
+ Rc :: make_mut (
167
+ self . resolve_features
168
+ . entry ( candidate. package_id ( ) )
169
+ . or_insert_with ( || Rc :: new ( HashSet :: with_capacity ( used_features. len ( ) ) ) ) ,
170
+ )
171
+ . extend ( used_features) ;
172
+ }
162
173
163
174
// Next, transform all dependencies into a list of possible candidates
164
175
// which can satisfy that dependency.
@@ -212,110 +223,6 @@ impl Context {
212
223
Some ( max)
213
224
}
214
225
215
- /// Returns all dependencies and the features we want from them.
216
- pub fn resolve_features < ' b > (
217
- & mut self ,
218
- parent : Option < PackageId > ,
219
- s : & ' b Summary ,
220
- method : & ' b Method < ' _ > ,
221
- ) -> ActivateResult < Vec < ( Dependency , Vec < InternedString > ) > > {
222
- let dev_deps = match * method {
223
- Method :: Everything => true ,
224
- Method :: Required { dev_deps, .. } => dev_deps,
225
- } ;
226
-
227
- // First, filter by dev-dependencies.
228
- let deps = s. dependencies ( ) ;
229
- let deps = deps. iter ( ) . filter ( |d| d. is_transitive ( ) || dev_deps) ;
230
-
231
- let reqs = build_requirements ( s, method) ?;
232
- let mut ret = Vec :: new ( ) ;
233
- let mut used_features = HashSet :: new ( ) ;
234
- let default_dep = ( false , Vec :: new ( ) ) ;
235
-
236
- // Next, collect all actually enabled dependencies and their features.
237
- for dep in deps {
238
- // Skip optional dependencies, but not those enabled through a
239
- // feature
240
- if dep. is_optional ( ) && !reqs. deps . contains_key ( & dep. name_in_toml ( ) ) {
241
- continue ;
242
- }
243
- // So we want this dependency. Move the features we want from
244
- // `feature_deps` to `ret` and register ourselves as using this
245
- // name.
246
- let base = reqs. deps . get ( & dep. name_in_toml ( ) ) . unwrap_or ( & default_dep) ;
247
- used_features. insert ( dep. name_in_toml ( ) ) ;
248
- let always_required = !dep. is_optional ( )
249
- && !s
250
- . dependencies ( )
251
- . iter ( )
252
- . any ( |d| d. is_optional ( ) && d. name_in_toml ( ) == dep. name_in_toml ( ) ) ;
253
- if always_required && base. 0 {
254
- return Err ( match parent {
255
- None => failure:: format_err!(
256
- "Package `{}` does not have feature `{}`. It has a required dependency \
257
- with that name, but only optional dependencies can be used as features.",
258
- s. package_id( ) ,
259
- dep. name_in_toml( )
260
- )
261
- . into ( ) ,
262
- Some ( p) => (
263
- p. package_id ( ) ,
264
- ConflictReason :: RequiredDependencyAsFeatures ( dep. name_in_toml ( ) ) ,
265
- )
266
- . into ( ) ,
267
- } ) ;
268
- }
269
- let mut base = base. 1 . clone ( ) ;
270
- base. extend ( dep. features ( ) . iter ( ) ) ;
271
- for feature in base. iter ( ) {
272
- if feature. contains ( '/' ) {
273
- return Err ( failure:: format_err!(
274
- "feature names may not contain slashes: `{}`" ,
275
- feature
276
- )
277
- . into ( ) ) ;
278
- }
279
- }
280
- ret. push ( ( dep. clone ( ) , base) ) ;
281
- }
282
-
283
- // Any entries in `reqs.dep` which weren't used are bugs in that the
284
- // package does not actually have those dependencies. We classified
285
- // them as dependencies in the first place because there is no such
286
- // feature, either.
287
- let remaining = reqs
288
- . deps
289
- . keys ( )
290
- . cloned ( )
291
- . filter ( |s| !used_features. contains ( s) )
292
- . collect :: < Vec < _ > > ( ) ;
293
- if !remaining. is_empty ( ) {
294
- let features = remaining. join ( ", " ) ;
295
- return Err ( match parent {
296
- None => failure:: format_err!(
297
- "Package `{}` does not have these features: `{}`" ,
298
- s. package_id( ) ,
299
- features
300
- )
301
- . into ( ) ,
302
- Some ( p) => ( p, ConflictReason :: MissingFeatures ( features) ) . into ( ) ,
303
- } ) ;
304
- }
305
-
306
- // Record what list of features is active for this package.
307
- if !reqs. used . is_empty ( ) {
308
- Rc :: make_mut (
309
- self . resolve_features
310
- . entry ( s. package_id ( ) )
311
- . or_insert_with ( || Rc :: new ( HashSet :: with_capacity ( reqs. used . len ( ) ) ) ) ,
312
- )
313
- . extend ( reqs. used ) ;
314
- }
315
-
316
- Ok ( ret)
317
- }
318
-
319
226
pub fn resolve_replacements (
320
227
& self ,
321
228
registry : & RegistryQueryer < ' _ > ,
@@ -342,136 +249,3 @@ impl Context {
342
249
graph
343
250
}
344
251
}
345
-
346
- /// Takes requested features for a single package from the input `Method` and
347
- /// recurses to find all requested features, dependencies and requested
348
- /// dependency features in a `Requirements` object, returning it to the resolver.
349
- fn build_requirements < ' a , ' b : ' a > (
350
- s : & ' a Summary ,
351
- method : & ' b Method < ' _ > ,
352
- ) -> CargoResult < Requirements < ' a > > {
353
- let mut reqs = Requirements :: new ( s) ;
354
-
355
- match * method {
356
- Method :: Everything
357
- | Method :: Required {
358
- all_features : true , ..
359
- } => {
360
- for key in s. features ( ) . keys ( ) {
361
- reqs. require_feature ( * key) ?;
362
- }
363
- for dep in s. dependencies ( ) . iter ( ) . filter ( |d| d. is_optional ( ) ) {
364
- reqs. require_dependency ( dep. name_in_toml ( ) ) ;
365
- }
366
- }
367
- Method :: Required {
368
- all_features : false ,
369
- features : requested,
370
- ..
371
- } => {
372
- for & f in requested. iter ( ) {
373
- reqs. require_value ( & FeatureValue :: new ( f, s) ) ?;
374
- }
375
- }
376
- }
377
- match * method {
378
- Method :: Everything
379
- | Method :: Required {
380
- uses_default_features : true ,
381
- ..
382
- } => {
383
- if s. features ( ) . contains_key ( "default" ) {
384
- reqs. require_feature ( InternedString :: new ( "default" ) ) ?;
385
- }
386
- }
387
- Method :: Required {
388
- uses_default_features : false ,
389
- ..
390
- } => { }
391
- }
392
- Ok ( reqs)
393
- }
394
-
395
- struct Requirements < ' a > {
396
- summary : & ' a Summary ,
397
- // The deps map is a mapping of package name to list of features enabled.
398
- // Each package should be enabled, and each package should have the
399
- // specified set of features enabled. The boolean indicates whether this
400
- // package was specifically requested (rather than just requesting features
401
- // *within* this package).
402
- deps : HashMap < InternedString , ( bool , Vec < InternedString > ) > ,
403
- // The used features set is the set of features which this local package had
404
- // enabled, which is later used when compiling to instruct the code what
405
- // features were enabled.
406
- used : HashSet < InternedString > ,
407
- visited : HashSet < InternedString > ,
408
- }
409
-
410
- impl Requirements < ' _ > {
411
- fn new ( summary : & Summary ) -> Requirements < ' _ > {
412
- Requirements {
413
- summary,
414
- deps : HashMap :: new ( ) ,
415
- used : HashSet :: new ( ) ,
416
- visited : HashSet :: new ( ) ,
417
- }
418
- }
419
-
420
- fn require_crate_feature ( & mut self , package : InternedString , feat : InternedString ) {
421
- self . used . insert ( package) ;
422
- self . deps
423
- . entry ( package)
424
- . or_insert ( ( false , Vec :: new ( ) ) )
425
- . 1
426
- . push ( feat) ;
427
- }
428
-
429
- fn seen ( & mut self , feat : InternedString ) -> bool {
430
- if self . visited . insert ( feat) {
431
- self . used . insert ( feat) ;
432
- false
433
- } else {
434
- true
435
- }
436
- }
437
-
438
- fn require_dependency ( & mut self , pkg : InternedString ) {
439
- if self . seen ( pkg) {
440
- return ;
441
- }
442
- self . deps . entry ( pkg) . or_insert ( ( false , Vec :: new ( ) ) ) . 0 = true ;
443
- }
444
-
445
- fn require_feature ( & mut self , feat : InternedString ) -> CargoResult < ( ) > {
446
- if feat. is_empty ( ) || self . seen ( feat) {
447
- return Ok ( ( ) ) ;
448
- }
449
- for fv in self
450
- . summary
451
- . features ( )
452
- . get ( feat. as_str ( ) )
453
- . expect ( "must be a valid feature" )
454
- {
455
- match * fv {
456
- FeatureValue :: Feature ( ref dep_feat) if * * dep_feat == * feat => failure:: bail!(
457
- "cyclic feature dependency: feature `{}` depends on itself" ,
458
- feat
459
- ) ,
460
- _ => { }
461
- }
462
- self . require_value ( fv) ?;
463
- }
464
- Ok ( ( ) )
465
- }
466
-
467
- fn require_value ( & mut self , fv : & FeatureValue ) -> CargoResult < ( ) > {
468
- match fv {
469
- FeatureValue :: Feature ( feat) => self . require_feature ( * feat) ?,
470
- FeatureValue :: Crate ( dep) => self . require_dependency ( * dep) ,
471
- FeatureValue :: CrateFeature ( dep, dep_feat) => {
472
- self . require_crate_feature ( * dep, * dep_feat)
473
- }
474
- } ;
475
- Ok ( ( ) )
476
- }
477
- }
0 commit comments