@@ -8,13 +8,14 @@ use failure::{bail, ensure};
88use log:: debug;
99
1010use crate :: core:: interning:: InternedString ;
11- use crate :: core:: { Dependency , FeatureValue , PackageId , SourceId , Summary } ;
11+ use crate :: core:: { Dependency , PackageId , SourceId , Summary } ;
1212use crate :: util:: CargoResult ;
1313use crate :: util:: Graph ;
1414
15+ use super :: dep_cache;
1516use super :: dep_cache:: RegistryQueryer ;
1617use super :: errors:: ActivateResult ;
17- use super :: types:: { ConflictMap , ConflictReason , DepInfo , Method } ;
18+ use super :: types:: { ConflictMap , DepInfo , Method } ;
1819
1920pub use super :: encode:: { EncodableDependency , EncodablePackageId , EncodableResolve } ;
2021pub use super :: encode:: { Metadata , WorkspaceResolve } ;
@@ -150,15 +151,25 @@ impl Context {
150151
151152 pub fn build_deps (
152153 & mut self ,
153- registry : & mut RegistryQueryer < ' _ > ,
154+ registry : & mut dep_cache :: RegistryQueryer < ' _ > ,
154155 parent : Option < PackageId > ,
155156 candidate : & Summary ,
156157 method : & Method < ' _ > ,
157158 ) -> ActivateResult < Vec < DepInfo > > {
158159 // First, figure out our set of dependencies based on the requested set
159160 // of features. This also calculates what features we're going to enable
160161 // 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+ }
162173
163174 // Next, transform all dependencies into a list of possible candidates
164175 // which can satisfy that dependency.
@@ -212,110 +223,6 @@ impl Context {
212223 Some ( max)
213224 }
214225
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-
319226 pub fn resolve_replacements (
320227 & self ,
321228 registry : & RegistryQueryer < ' _ > ,
@@ -342,136 +249,3 @@ impl Context {
342249 graph
343250 }
344251}
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