diff --git a/src/cargo/core/dependency.rs b/src/cargo/core/dependency.rs index 20ef00c0f59..a22302da5fb 100644 --- a/src/cargo/core/dependency.rs +++ b/src/cargo/core/dependency.rs @@ -32,7 +32,7 @@ struct Inner { optional: bool, default_features: bool, - features: Vec, + features: Vec, // This dependency should be used only for this platform. // `None` means *all platforms*. @@ -64,6 +64,7 @@ impl ser::Serialize for Dependency { where S: ser::Serializer, { + let string_features: Vec<_> = self.features().iter().map(|s| s.to_string()).collect(); SerializedDependency { name: &*self.name(), source: self.source_id(), @@ -71,7 +72,7 @@ impl ser::Serialize for Dependency { kind: self.kind(), optional: self.is_optional(), uses_default_features: self.uses_default_features(), - features: self.features(), + features: &string_features, target: self.platform(), rename: self.rename(), }.serialize(s) @@ -250,7 +251,8 @@ impl Dependency { /// Sets the list of features requested for the package. pub fn set_features(&mut self, features: Vec) -> &mut Dependency { - Rc::make_mut(&mut self.inner).features = features; + Rc::make_mut(&mut self.inner).features = + features.iter().map(|s| InternedString::new(s)).collect(); self } @@ -334,7 +336,7 @@ impl Dependency { self.inner.default_features } /// Returns the list of features that are requested by the dependency. - pub fn features(&self) -> &[String] { + pub fn features(&self) -> &[InternedString] { &self.inner.features } diff --git a/src/cargo/core/resolver/context.rs b/src/cargo/core/resolver/context.rs index 2de77d39fc3..82786eb7166 100644 --- a/src/cargo/core/resolver/context.rs +++ b/src/cargo/core/resolver/context.rs @@ -1,13 +1,13 @@ use std::collections::{HashMap, HashSet}; use std::rc::Rc; -use core::{Dependency, FeatureValue, PackageId, SourceId, Summary}; use core::interning::InternedString; -use util::Graph; +use core::{Dependency, FeatureValue, PackageId, SourceId, Summary}; use util::CargoResult; +use util::Graph; -use super::types::{ActivateResult, ConflictReason, DepInfo, GraphNode, Method, RcList}; use super::types::RegistryQueryer; +use super::types::{ActivateResult, ConflictReason, DepInfo, GraphNode, Method, RcList}; pub use super::encode::{EncodableDependency, EncodablePackageId, EncodableResolve}; pub use super::encode::{Metadata, WorkspaceResolve}; @@ -160,7 +160,7 @@ impl Context { parent: Option<&Summary>, s: &'b Summary, method: &'b Method, - ) -> ActivateResult)>> { + ) -> ActivateResult)>> { let dev_deps = match *method { Method::Everything => true, Method::Required { dev_deps, .. } => dev_deps, @@ -182,7 +182,7 @@ impl Context { { requested .iter() - .map(|f| FeatureValue::new(f, s)) + .map(|&f| FeatureValue::new(f, s)) .collect::>() } else { vec![] @@ -210,7 +210,7 @@ impl Context { )); } let mut base = base.1; - base.extend(dep.features().iter().cloned()); + base.extend(dep.features().iter()); for feature in base.iter() { if feature.contains('/') { return Err( @@ -331,7 +331,7 @@ struct Requirements<'a> { // specified set of features enabled. The boolean indicates whether this // package was specifically requested (rather than just requesting features // *within* this package). - deps: HashMap<&'a str, (bool, Vec)>, + deps: HashMap<&'a str, (bool, Vec)>, // The used features set is the set of features which this local package had // enabled, which is later used when compiling to instruct the code what // features were enabled. @@ -349,13 +349,13 @@ impl<'r> Requirements<'r> { } } - fn require_crate_feature(&mut self, package: &'r str, feat: &'r str) { + fn require_crate_feature(&mut self, package: &'r str, feat: InternedString) { self.used.insert(package); self.deps .entry(package) .or_insert((false, Vec::new())) .1 - .push(feat.to_string()); + .push(feat); } fn seen(&mut self, feat: &'r str) -> bool { @@ -399,7 +399,7 @@ impl<'r> Requirements<'r> { match *fv { FeatureValue::Feature(ref feat) => self.require_feature(feat), FeatureValue::Crate(ref dep) => Ok(self.require_dependency(dep)), - FeatureValue::CrateFeature(ref dep, ref dep_feat) => { + FeatureValue::CrateFeature(ref dep, dep_feat) => { Ok(self.require_crate_feature(dep, dep_feat)) } } diff --git a/src/cargo/core/resolver/mod.rs b/src/cargo/core/resolver/mod.rs index 2a88bc5a1f5..0e123ded5f6 100644 --- a/src/cargo/core/resolver/mod.rs +++ b/src/cargo/core/resolver/mod.rs @@ -56,6 +56,7 @@ use semver; use core::{Dependency, PackageId, Registry, Summary}; use core::PackageIdSpec; +use core::interning::InternedString; use util::config::Config; use util::Graph; use util::errors::{CargoError, CargoResult}; @@ -670,7 +671,7 @@ struct BacktrackFrame { remaining_candidates: RemainingCandidates, parent: Summary, dep: Dependency, - features: Rc>, + features: Rc>, conflicting_activations: HashMap, } diff --git a/src/cargo/core/resolver/types.rs b/src/cargo/core/resolver/types.rs index c21822b7b32..8de61be776e 100644 --- a/src/cargo/core/resolver/types.rs +++ b/src/cargo/core/resolver/types.rs @@ -4,6 +4,7 @@ use std::ops::Range; use std::rc::Rc; use core::{Dependency, PackageId, PackageIdSpec, Registry, Summary}; +use core::interning::InternedString; use util::{CargoError, CargoResult}; pub struct RegistryQueryer<'a> { @@ -159,21 +160,21 @@ pub enum Method<'a> { Everything, // equivalent to Required { dev_deps: true, all_features: true, .. } Required { dev_deps: bool, - features: &'a [String], + features: &'a [InternedString], all_features: bool, uses_default_features: bool, }, } impl<'r> Method<'r> { - pub fn split_features(features: &[String]) -> Vec { + pub fn split_features(features: &[String]) -> Vec { features .iter() .flat_map(|s| s.split_whitespace()) .flat_map(|s| s.split(',')) .filter(|s| !s.is_empty()) - .map(|s| s.to_string()) - .collect::>() + .map(|s| InternedString::new(s)) + .collect::>() } } @@ -245,7 +246,7 @@ impl Ord for DepsFrame { // Information about the dependencies for a crate, a tuple of: // // (dependency info, candidates, features activated) -pub type DepInfo = (Dependency, Rc>, Rc>); +pub type DepInfo = (Dependency, Rc>, Rc>); pub type ActivateResult = Result; diff --git a/src/cargo/core/summary.rs b/src/cargo/core/summary.rs index 83846c8229e..a7afcdf9365 100644 --- a/src/cargo/core/summary.rs +++ b/src/cargo/core/summary.rs @@ -2,12 +2,11 @@ use std::collections::BTreeMap; use std::mem; use std::rc::Rc; -use semver::Version; - use serde::{Serialize, Serializer}; -use core::{Dependency, PackageId, SourceId}; use core::interning::InternedString; +use core::{Dependency, PackageId, SourceId}; +use semver::Version; use util::CargoResult; @@ -138,7 +137,7 @@ fn build_feature_map( for (feature, list) in features.iter() { let mut values = vec![]; for dep in list { - let val = FeatureValue::build(dep, |fs| (&features).get(fs).is_some()); + let val = FeatureValue::build(InternedString::new(dep), |fs| features.contains_key(fs)); if let &Feature(_) = &val { values.push(val); continue; @@ -201,7 +200,7 @@ pub enum FeatureValue { } impl FeatureValue { - fn build(feature: &str, is_feature: T) -> FeatureValue + fn build(feature: InternedString, is_feature: T) -> FeatureValue where T: Fn(&str) -> bool, { @@ -211,13 +210,13 @@ impl FeatureValue { let dep_feat = &dep_feat[1..]; FeatureValue::CrateFeature(InternedString::new(dep), InternedString::new(dep_feat)) } - None if is_feature(&feature) => FeatureValue::Feature(InternedString::new(feature)), - None => FeatureValue::Crate(InternedString::new(feature)), + None if is_feature(&feature) => FeatureValue::Feature(feature), + None => FeatureValue::Crate(feature), } } - pub fn new(feature: &str, s: &Summary) -> FeatureValue { - Self::build(feature, |fs| s.features().get(fs).is_some()) + pub fn new(feature: InternedString, s: &Summary) -> FeatureValue { + Self::build(feature, |fs| s.features().contains_key(fs)) } pub fn to_string(&self) -> String { diff --git a/src/cargo/ops/registry.rs b/src/cargo/ops/registry.rs index 64f4a8cb57d..463f5c4e24d 100644 --- a/src/cargo/ops/registry.rs +++ b/src/cargo/ops/registry.rs @@ -171,7 +171,7 @@ fn transmit( optional: dep.is_optional(), default_features: dep.uses_default_features(), name: dep.name().to_string(), - features: dep.features().to_vec(), + features: dep.features().iter().map(|s| s.to_string()).collect(), version_req: dep.version_req().to_string(), target: dep.platform().map(|s| s.to_string()), kind: match dep.kind() { diff --git a/src/cargo/ops/resolve.rs b/src/cargo/ops/resolve.rs index 89b87715000..e6a5d4e7576 100644 --- a/src/cargo/ops/resolve.rs +++ b/src/cargo/ops/resolve.rs @@ -472,9 +472,11 @@ fn register_previous_locks<'a>( // dependency on that crate to enable the feature. For now // this bug is better than the always updating registry // though... - if !ws.members().any(|pkg| pkg.package_id() == member.package_id()) && - (dep.is_optional() || !dep.is_transitive()) { - continue + if !ws.members() + .any(|pkg| pkg.package_id() == member.package_id()) + && (dep.is_optional() || !dep.is_transitive()) + { + continue; } // Ok if nothing matches, then we poison the source of this