Skip to content

Commit a372cae

Browse files
committed
use a BTreeSet to store features
1 parent 949f49a commit a372cae

File tree

6 files changed

+44
-41
lines changed

6 files changed

+44
-41
lines changed

src/cargo/core/resolver/context.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::collections::{HashMap, HashSet};
1+
use std::collections::HashMap;
22
use std::num::NonZeroU64;
33
use std::rc::Rc;
44

@@ -20,6 +20,7 @@ use super::types::{ConflictMap, DepInfo, Method};
2020
pub use super::encode::{EncodableDependency, EncodablePackageId, EncodableResolve};
2121
pub use super::encode::{Metadata, WorkspaceResolve};
2222
pub use super::resolve::Resolve;
23+
use std::collections::btree_set::BTreeSet;
2324

2425
// A `Context` is basically a bunch of local resolution information which is
2526
// kept around for all `BacktrackFrame` instances. As a result, this runs the
@@ -29,7 +30,7 @@ pub use super::resolve::Resolve;
2930
pub struct Context {
3031
pub activations: Activations,
3132
/// list the features that are activated for each package
32-
pub resolve_features: im_rc::HashMap<PackageId, Rc<HashSet<InternedString>>>,
33+
pub resolve_features: im_rc::HashMap<PackageId, Rc<BTreeSet<InternedString>>>,
3334
/// get the package that will be linking to a native library by its links attribute
3435
pub links: im_rc::HashMap<InternedString, PackageId>,
3536
/// for each package the list of names it can see,
@@ -102,7 +103,7 @@ impl Context {
102103
/// Activate this summary by inserting it into our list of known activations.
103104
///
104105
/// Returns `true` if this summary with the given method is already activated.
105-
pub fn flag_activated(&mut self, summary: &Summary, method: &Method<'_>) -> CargoResult<bool> {
106+
pub fn flag_activated(&mut self, summary: &Summary, method: &Method) -> CargoResult<bool> {
106107
let id = summary.package_id();
107108
let age: ContextAge = self.age();
108109
match self.activations.entry(id.as_activations_key()) {
@@ -127,7 +128,7 @@ impl Context {
127128
}
128129
}
129130
debug!("checking if {} is already activated", summary.package_id());
130-
let (features, use_default) = match *method {
131+
let (features, use_default) = match method {
131132
Method::Everything
132133
| Method::Required {
133134
all_features: true, ..
@@ -142,7 +143,7 @@ impl Context {
142143
let has_default_feature = summary.features().contains_key("default");
143144
Ok(match self.resolve_features.get(&id) {
144145
Some(prev) => {
145-
features.iter().all(|f| prev.contains(f))
146+
features.is_subset(prev)
146147
&& (!use_default || prev.contains("default") || !has_default_feature)
147148
}
148149
None => features.is_empty() && (!use_default || !has_default_feature),
@@ -154,7 +155,7 @@ impl Context {
154155
registry: &mut dep_cache::RegistryQueryer<'_>,
155156
parent: Option<PackageId>,
156157
candidate: &Summary,
157-
method: &Method<'_>,
158+
method: &Method,
158159
) -> ActivateResult<Vec<DepInfo>> {
159160
// First, figure out our set of dependencies based on the requested set
160161
// of features. This also calculates what features we're going to enable
@@ -166,7 +167,7 @@ impl Context {
166167
Rc::make_mut(
167168
self.resolve_features
168169
.entry(candidate.package_id())
169-
.or_insert_with(|| Rc::new(HashSet::with_capacity(used_features.len()))),
170+
.or_insert_with(Rc::default),
170171
)
171172
.extend(used_features);
172173
}

src/cargo/core/resolver/dep_cache.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use std::cmp::Ordering;
2-
use std::collections::{HashMap, HashSet};
2+
use std::collections::{BTreeSet, HashMap, HashSet};
33
use std::rc::Rc;
44

55
use log::debug;
@@ -181,10 +181,10 @@ impl<'a> RegistryQueryer<'a> {
181181
pub fn resolve_features<'b>(
182182
parent: Option<PackageId>,
183183
s: &'b Summary,
184-
method: &'b Method<'_>,
184+
method: &'b Method,
185185
) -> ActivateResult<(
186186
HashSet<InternedString>,
187-
Vec<(Dependency, Vec<InternedString>)>,
187+
Vec<(Dependency, BTreeSet<InternedString>)>,
188188
)> {
189189
let dev_deps = match *method {
190190
Method::Everything => true,
@@ -198,7 +198,7 @@ pub fn resolve_features<'b>(
198198
let reqs = build_requirements(s, method)?;
199199
let mut ret = Vec::new();
200200
let mut used_features = HashSet::new();
201-
let default_dep = (false, Vec::new());
201+
let default_dep = (false, BTreeSet::new());
202202

203203
// Next, collect all actually enabled dependencies and their features.
204204
for dep in deps {
@@ -278,11 +278,11 @@ pub fn resolve_features<'b>(
278278
/// dependency features in a `Requirements` object, returning it to the resolver.
279279
fn build_requirements<'a, 'b: 'a>(
280280
s: &'a Summary,
281-
method: &'b Method<'_>,
281+
method: &'b Method,
282282
) -> CargoResult<Requirements<'a>> {
283283
let mut reqs = Requirements::new(s);
284284

285-
match *method {
285+
match method {
286286
Method::Everything
287287
| Method::Required {
288288
all_features: true, ..
@@ -329,7 +329,7 @@ struct Requirements<'a> {
329329
// specified set of features enabled. The boolean indicates whether this
330330
// package was specifically requested (rather than just requesting features
331331
// *within* this package).
332-
deps: HashMap<InternedString, (bool, Vec<InternedString>)>,
332+
deps: HashMap<InternedString, (bool, BTreeSet<InternedString>)>,
333333
// The used features set is the set of features which this local package had
334334
// enabled, which is later used when compiling to instruct the code what
335335
// features were enabled.
@@ -355,9 +355,9 @@ impl Requirements<'_> {
355355
self.used.insert(package);
356356
self.deps
357357
.entry(package)
358-
.or_insert((false, Vec::new()))
358+
.or_insert((false, BTreeSet::new()))
359359
.1
360-
.push(feat);
360+
.insert(feat);
361361
}
362362

363363
fn seen(&mut self, feat: InternedString) -> bool {
@@ -373,7 +373,7 @@ impl Requirements<'_> {
373373
if self.seen(pkg) {
374374
return;
375375
}
376-
self.deps.entry(pkg).or_insert((false, Vec::new())).0 = true;
376+
self.deps.entry(pkg).or_insert((false, BTreeSet::new())).0 = true;
377377
}
378378

379379
fn require_feature(&mut self, feat: InternedString) -> CargoResult<()> {

src/cargo/core/resolver/mod.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
//! that we're implementing something that probably shouldn't be allocating all
4848
//! over the place.
4949
50-
use std::collections::{BTreeMap, HashMap, HashSet};
50+
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
5151
use std::mem;
5252
use std::rc::Rc;
5353
use std::time::{Duration, Instant};
@@ -121,7 +121,7 @@ mod types;
121121
/// When we have a decision for how to implement is without breaking existing functionality
122122
/// this flag can be removed.
123123
pub fn resolve(
124-
summaries: &[(Summary, Method<'_>)],
124+
summaries: &[(Summary, Method)],
125125
replacements: &[(PackageIdSpec, Dependency)],
126126
registry: &mut dyn Registry,
127127
try_to_use: &HashSet<PackageId>,
@@ -169,7 +169,7 @@ pub fn resolve(
169169
fn activate_deps_loop(
170170
mut cx: Context,
171171
registry: &mut RegistryQueryer<'_>,
172-
summaries: &[(Summary, Method<'_>)],
172+
summaries: &[(Summary, Method)],
173173
config: Option<&Config>,
174174
) -> CargoResult<Context> {
175175
let mut backtrack_stack = Vec::new();
@@ -374,7 +374,7 @@ fn activate_deps_loop(
374374
let pid = candidate.summary.package_id();
375375
let method = Method::Required {
376376
dev_deps: false,
377-
features: &features,
377+
features: Rc::clone(&features),
378378
all_features: false,
379379
uses_default_features: dep.uses_default_features(),
380380
};
@@ -597,7 +597,7 @@ fn activate(
597597
registry: &mut RegistryQueryer<'_>,
598598
parent: Option<(&Summary, &Dependency)>,
599599
candidate: Candidate,
600-
method: &Method<'_>,
600+
method: &Method,
601601
) -> ActivateResult<Option<(DepsFrame, Duration)>> {
602602
let candidate_pid = candidate.summary.package_id();
603603
if let Some((parent, dep)) = parent {
@@ -704,7 +704,7 @@ struct BacktrackFrame {
704704
remaining_candidates: RemainingCandidates,
705705
parent: Summary,
706706
dep: Dependency,
707-
features: Rc<Vec<InternedString>>,
707+
features: Rc<BTreeSet<InternedString>>,
708708
conflicting_activations: ConflictMap,
709709
}
710710

src/cargo/core/resolver/types.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use std::cmp::Ordering;
2-
use std::collections::BTreeMap;
2+
use std::collections::{BTreeMap, BTreeSet};
33
use std::ops::Range;
44
use std::rc::Rc;
55
use std::time::{Duration, Instant};
@@ -89,26 +89,26 @@ impl ResolverProgress {
8989
}
9090
}
9191

92-
#[derive(Clone, Copy)]
93-
pub enum Method<'a> {
92+
#[derive(Clone)]
93+
pub enum Method {
9494
Everything, // equivalent to Required { dev_deps: true, all_features: true, .. }
9595
Required {
9696
dev_deps: bool,
97-
features: &'a [InternedString],
97+
features: Rc<BTreeSet<InternedString>>,
9898
all_features: bool,
9999
uses_default_features: bool,
100100
},
101101
}
102102

103-
impl<'r> Method<'r> {
104-
pub fn split_features(features: &[String]) -> Vec<InternedString> {
103+
impl Method {
104+
pub fn split_features(features: &[String]) -> BTreeSet<InternedString> {
105105
features
106106
.iter()
107107
.flat_map(|s| s.split_whitespace())
108108
.flat_map(|s| s.split(','))
109109
.filter(|s| !s.is_empty())
110-
.map(|s| InternedString::new(s))
111-
.collect::<Vec<InternedString>>()
110+
.map(InternedString::new)
111+
.collect::<BTreeSet<InternedString>>()
112112
}
113113
}
114114

@@ -221,7 +221,7 @@ impl RemainingDeps {
221221
// Information about the dependencies for a crate, a tuple of:
222222
//
223223
// (dependency info, candidates, features activated)
224-
pub type DepInfo = (Dependency, Rc<Vec<Candidate>>, Rc<Vec<InternedString>>);
224+
pub type DepInfo = (Dependency, Rc<Vec<Candidate>>, Rc<BTreeSet<InternedString>>);
225225

226226
/// All possible reasons that a package might fail to activate.
227227
///

src/cargo/ops/cargo_compile.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
use std::collections::{BTreeSet, HashMap, HashSet};
2424
use std::iter::FromIterator;
2525
use std::path::PathBuf;
26+
use std::rc::Rc;
2627
use std::sync::Arc;
2728

2829
use crate::core::compiler::{BuildConfig, BuildContext, Compilation, Context};
@@ -299,7 +300,7 @@ pub fn compile_ws<'a>(
299300
let features = Method::split_features(features);
300301
let method = Method::Required {
301302
dev_deps: ws.require_optional_deps() || filter.need_dev_deps(build_config.mode),
302-
features: &features,
303+
features: Rc::new(features),
303304
all_features,
304305
uses_default_features: !no_default_features,
305306
};

src/cargo/ops/resolve.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::collections::HashSet;
2+
use std::rc::Rc;
23

34
use log::{debug, trace};
45

@@ -43,7 +44,7 @@ pub fn resolve_ws_precisely<'a>(
4344
} else {
4445
Method::Required {
4546
dev_deps: true,
46-
features: &features,
47+
features: Rc::new(features),
4748
all_features: false,
4849
uses_default_features: !no_default_features,
4950
}
@@ -53,7 +54,7 @@ pub fn resolve_ws_precisely<'a>(
5354

5455
pub fn resolve_ws_with_method<'a>(
5556
ws: &Workspace<'a>,
56-
method: Method<'_>,
57+
method: Method,
5758
specs: &[PackageIdSpec],
5859
) -> CargoResult<(PackageSet<'a>, Resolve)> {
5960
let mut registry = PackageRegistry::new(ws.config())?;
@@ -138,7 +139,7 @@ fn resolve_with_registry<'cfg>(
138139
pub fn resolve_with_previous<'cfg>(
139140
registry: &mut PackageRegistry<'cfg>,
140141
ws: &Workspace<'cfg>,
141-
method: Method<'_>,
142+
method: Method,
142143
previous: Option<&Resolve>,
143144
to_avoid: Option<&HashSet<PackageId>>,
144145
specs: &[PackageIdSpec],
@@ -222,7 +223,7 @@ pub fn resolve_with_previous<'cfg>(
222223
let mut summaries = Vec::new();
223224
if ws.config().cli_unstable().package_features {
224225
let mut members = Vec::new();
225-
match method {
226+
match &method {
226227
Method::Everything => members.extend(ws.members()),
227228
Method::Required {
228229
features,
@@ -241,7 +242,7 @@ pub fn resolve_with_previous<'cfg>(
241242
// of current workspace. Add all packages from workspace to get `foo`
242243
// into the resolution graph.
243244
if members.is_empty() {
244-
if !(features.is_empty() && !all_features && uses_default_features) {
245+
if !(features.is_empty() && !all_features && *uses_default_features) {
245246
failure::bail!("cannot specify features for packages outside of workspace");
246247
}
247248
members.extend(ws.members());
@@ -250,7 +251,7 @@ pub fn resolve_with_previous<'cfg>(
250251
}
251252
for member in members {
252253
let summary = registry.lock(member.summary().clone());
253-
summaries.push((summary, method))
254+
summaries.push((summary, method.clone()))
254255
}
255256
} else {
256257
for member in ws.members() {
@@ -281,13 +282,13 @@ pub fn resolve_with_previous<'cfg>(
281282
} => {
282283
let base = Method::Required {
283284
dev_deps,
284-
features: &[],
285+
features: Rc::default(),
285286
all_features,
286287
uses_default_features: true,
287288
};
288289
let member_id = member.package_id();
289290
match ws.current_opt() {
290-
Some(current) if member_id == current.package_id() => method,
291+
Some(current) if member_id == current.package_id() => method.clone(),
291292
_ => {
292293
if specs.iter().any(|spec| spec.matches(member_id)) {
293294
base

0 commit comments

Comments
 (0)