Skip to content

Commit 444df0c

Browse files
committed
fix(resolver): Remove unused public-deps error handling
To implement rust-lang/rfcs#3516, we need to decouple the resolver's behavior from the unstable flag. Since the code path is now dead, I went ahead and removed it.
1 parent 71cd3a9 commit 444df0c

File tree

3 files changed

+8
-259
lines changed

3 files changed

+8
-259
lines changed

src/cargo/core/resolver/context.rs

+3-202
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,6 @@ pub struct Context {
2222
pub resolve_features: im_rc::HashMap<PackageId, FeaturesSet>,
2323
/// get the package that will be linking to a native library by its links attribute
2424
pub links: im_rc::HashMap<InternedString, PackageId>,
25-
/// for each package the list of names it can see,
26-
/// then for each name the exact version that name represents and whether the name is public.
27-
pub public_dependency: Option<PublicDependency>,
2825

2926
/// a way to look up for a package in activations what packages required it
3027
/// and all of the exact deps that it fulfilled.
@@ -74,16 +71,11 @@ impl PackageId {
7471
}
7572

7673
impl Context {
77-
pub fn new(check_public_visible_dependencies: bool) -> Context {
74+
pub fn new() -> Context {
7875
Context {
7976
age: 0,
8077
resolve_features: im_rc::HashMap::new(),
8178
links: im_rc::HashMap::new(),
82-
public_dependency: if check_public_visible_dependencies {
83-
Some(PublicDependency::new())
84-
} else {
85-
None
86-
},
8779
parents: Graph::new(),
8880
activations: im_rc::HashMap::new(),
8981
}
@@ -192,42 +184,6 @@ impl Context {
192184
.and_then(|(s, l)| if s.package_id() == id { Some(*l) } else { None })
193185
}
194186

195-
/// If the conflict reason on the package still applies returns the `ContextAge` when it was added
196-
pub fn still_applies(&self, id: PackageId, reason: &ConflictReason) -> Option<ContextAge> {
197-
self.is_active(id).and_then(|mut max| {
198-
match reason {
199-
ConflictReason::PublicDependency(name) => {
200-
if &id == name {
201-
return Some(max);
202-
}
203-
max = std::cmp::max(max, self.is_active(*name)?);
204-
max = std::cmp::max(
205-
max,
206-
self.public_dependency
207-
.as_ref()
208-
.unwrap()
209-
.can_see_item(*name, id)?,
210-
);
211-
}
212-
ConflictReason::PubliclyExports(name) => {
213-
if &id == name {
214-
return Some(max);
215-
}
216-
max = std::cmp::max(max, self.is_active(*name)?);
217-
max = std::cmp::max(
218-
max,
219-
self.public_dependency
220-
.as_ref()
221-
.unwrap()
222-
.publicly_exports_item(*name, id)?,
223-
);
224-
}
225-
_ => {}
226-
}
227-
Some(max)
228-
})
229-
}
230-
231187
/// Checks whether all of `parent` and the keys of `conflicting activations`
232188
/// are still active.
233189
/// If so returns the `ContextAge` when the newest one was added.
@@ -241,8 +197,8 @@ impl Context {
241197
max = std::cmp::max(max, self.is_active(parent)?);
242198
}
243199

244-
for (id, reason) in conflicting_activations.iter() {
245-
max = std::cmp::max(max, self.still_applies(*id, reason)?);
200+
for id in conflicting_activations.keys() {
201+
max = std::cmp::max(max, self.is_active(*id)?);
246202
}
247203
Some(max)
248204
}
@@ -280,158 +236,3 @@ impl Graph<PackageId, im_rc::HashSet<Dependency>> {
280236
.map(|(grand, d)| (*grand, d.iter().any(|x| x.is_public())))
281237
}
282238
}
283-
284-
#[derive(Clone, Debug, Default)]
285-
pub struct PublicDependency {
286-
/// For each active package the set of all the names it can see,
287-
/// for each name the exact package that name resolves to,
288-
/// the `ContextAge` when it was first visible,
289-
/// and the `ContextAge` when it was first exported.
290-
inner: im_rc::HashMap<
291-
PackageId,
292-
im_rc::HashMap<InternedString, (PackageId, ContextAge, Option<ContextAge>)>,
293-
>,
294-
}
295-
296-
impl PublicDependency {
297-
fn new() -> Self {
298-
PublicDependency {
299-
inner: im_rc::HashMap::new(),
300-
}
301-
}
302-
fn publicly_exports(&self, candidate_pid: PackageId) -> Vec<PackageId> {
303-
self.inner
304-
.get(&candidate_pid) // if we have seen it before
305-
.iter()
306-
.flat_map(|x| x.values()) // all the things we have stored
307-
.filter(|x| x.2.is_some()) // as publicly exported
308-
.map(|x| x.0)
309-
.chain(Some(candidate_pid)) // but even if not we know that everything exports itself
310-
.collect()
311-
}
312-
fn publicly_exports_item(
313-
&self,
314-
candidate_pid: PackageId,
315-
target: PackageId,
316-
) -> Option<ContextAge> {
317-
debug_assert_ne!(candidate_pid, target);
318-
let out = self
319-
.inner
320-
.get(&candidate_pid)
321-
.and_then(|names| names.get(&target.name()))
322-
.filter(|(p, _, _)| *p == target)
323-
.and_then(|(_, _, age)| *age);
324-
debug_assert_eq!(
325-
out.is_some(),
326-
self.publicly_exports(candidate_pid).contains(&target)
327-
);
328-
out
329-
}
330-
pub fn can_see_item(&self, candidate_pid: PackageId, target: PackageId) -> Option<ContextAge> {
331-
self.inner
332-
.get(&candidate_pid)
333-
.and_then(|names| names.get(&target.name()))
334-
.filter(|(p, _, _)| *p == target)
335-
.map(|(_, age, _)| *age)
336-
}
337-
pub fn add_edge(
338-
&mut self,
339-
candidate_pid: PackageId,
340-
parent_pid: PackageId,
341-
is_public: bool,
342-
age: ContextAge,
343-
parents: &Graph<PackageId, im_rc::HashSet<Dependency>>,
344-
) {
345-
// one tricky part is that `candidate_pid` may already be active and
346-
// have public dependencies of its own. So we not only need to mark
347-
// `candidate_pid` as visible to its parents but also all of its existing
348-
// publicly exported dependencies.
349-
for c in self.publicly_exports(candidate_pid) {
350-
// for each (transitive) parent that can newly see `t`
351-
let mut stack = vec![(parent_pid, is_public)];
352-
while let Some((p, public)) = stack.pop() {
353-
match self.inner.entry(p).or_default().entry(c.name()) {
354-
im_rc::hashmap::Entry::Occupied(mut o) => {
355-
// the (transitive) parent can already see something by `c`s name, it had better be `c`.
356-
assert_eq!(o.get().0, c);
357-
if o.get().2.is_some() {
358-
// The previous time the parent saw `c`, it was a public dependency.
359-
// So all of its parents already know about `c`
360-
// and we can save some time by stopping now.
361-
continue;
362-
}
363-
if public {
364-
// Mark that `c` has now bean seen publicly
365-
let old_age = o.get().1;
366-
o.insert((c, old_age, if public { Some(age) } else { None }));
367-
}
368-
}
369-
im_rc::hashmap::Entry::Vacant(v) => {
370-
// The (transitive) parent does not have anything by `c`s name,
371-
// so we add `c`.
372-
v.insert((c, age, if public { Some(age) } else { None }));
373-
}
374-
}
375-
// if `candidate_pid` was a private dependency of `p` then `p` parents can't see `c` thru `p`
376-
if public {
377-
// if it was public, then we add all of `p`s parents to be checked
378-
stack.extend(parents.parents_of(p));
379-
}
380-
}
381-
}
382-
}
383-
pub fn can_add_edge(
384-
&self,
385-
b_id: PackageId,
386-
parent: PackageId,
387-
is_public: bool,
388-
parents: &Graph<PackageId, im_rc::HashSet<Dependency>>,
389-
) -> Result<
390-
(),
391-
(
392-
((PackageId, ConflictReason), (PackageId, ConflictReason)),
393-
Option<(PackageId, ConflictReason)>,
394-
),
395-
> {
396-
// one tricky part is that `candidate_pid` may already be active and
397-
// have public dependencies of its own. So we not only need to check
398-
// `b_id` as visible to its parents but also all of its existing
399-
// publicly exported dependencies.
400-
for t in self.publicly_exports(b_id) {
401-
// for each (transitive) parent that can newly see `t`
402-
let mut stack = vec![(parent, is_public)];
403-
while let Some((p, public)) = stack.pop() {
404-
// TODO: don't look at the same thing more than once
405-
if let Some(o) = self.inner.get(&p).and_then(|x| x.get(&t.name())) {
406-
if o.0 != t {
407-
// the (transitive) parent can already see a different version by `t`s name.
408-
// So, adding `b` will cause `p` to have a public dependency conflict on `t`.
409-
return Err((
410-
(o.0, ConflictReason::PublicDependency(p)), // p can see the other version and
411-
(parent, ConflictReason::PublicDependency(p)), // p can see us
412-
))
413-
.map_err(|e| {
414-
if t == b_id {
415-
(e, None)
416-
} else {
417-
(e, Some((t, ConflictReason::PubliclyExports(b_id))))
418-
}
419-
});
420-
}
421-
if o.2.is_some() {
422-
// The previous time the parent saw `t`, it was a public dependency.
423-
// So all of its parents already know about `t`
424-
// and we can save some time by stopping now.
425-
continue;
426-
}
427-
}
428-
// if `b` was a private dependency of `p` then `p` parents can't see `t` thru `p`
429-
if public {
430-
// if it was public, then we add all of `p`s parents to be checked
431-
stack.extend(parents.parents_of(p));
432-
}
433-
}
434-
}
435-
Ok(())
436-
}
437-
}

src/cargo/core/resolver/mod.rs

+5-53
Original file line numberDiff line numberDiff line change
@@ -120,24 +120,12 @@ mod version_prefs;
120120
///
121121
/// * `config` - a location to print warnings and such, or `None` if no warnings
122122
/// should be printed
123-
///
124-
/// * `check_public_visible_dependencies` - a flag for whether to enforce the restrictions
125-
/// introduced in the "public & private dependencies" RFC (1977). The current implementation
126-
/// makes sure that there is only one version of each name visible to each package.
127-
///
128-
/// But there are 2 stable ways to directly depend on different versions of the same name.
129-
/// 1. Use the renamed dependencies functionality
130-
/// 2. Use 'cfg({})' dependencies functionality
131-
///
132-
/// When we have a decision for how to implement is without breaking existing functionality
133-
/// this flag can be removed.
134123
pub fn resolve(
135124
summaries: &[(Summary, ResolveOpts)],
136125
replacements: &[(PackageIdSpec, Dependency)],
137126
registry: &mut dyn Registry,
138127
version_prefs: &VersionPreferences,
139128
config: Option<&Config>,
140-
check_public_visible_dependencies: bool,
141129
) -> CargoResult<Resolve> {
142130
let _p = profile::start("resolving");
143131
let first_version = match config {
@@ -148,7 +136,7 @@ pub fn resolve(
148136
};
149137
let mut registry = RegistryQueryer::new(registry, replacements, version_prefs);
150138
let cx = loop {
151-
let cx = Context::new(check_public_visible_dependencies);
139+
let cx = Context::new();
152140
let cx = activate_deps_loop(cx, &mut registry, summaries, first_version, config)?;
153141
if registry.reset_pending() {
154142
break cx;
@@ -286,12 +274,7 @@ fn activate_deps_loop(
286274
let mut backtracked = false;
287275

288276
loop {
289-
let next = remaining_candidates.next(
290-
&mut conflicting_activations,
291-
&cx,
292-
&dep,
293-
parent.package_id(),
294-
);
277+
let next = remaining_candidates.next(&mut conflicting_activations, &cx);
295278

296279
let (candidate, has_another) = next.ok_or(()).or_else(|_| {
297280
// If we get here then our `remaining_candidates` was just
@@ -649,15 +632,6 @@ fn activate(
649632
.link(candidate_pid, parent_pid)
650633
// and associate dep with that edge
651634
.insert(dep.clone());
652-
if let Some(public_dependency) = cx.public_dependency.as_mut() {
653-
public_dependency.add_edge(
654-
candidate_pid,
655-
parent_pid,
656-
dep.is_public(),
657-
cx.age,
658-
&cx.parents,
659-
);
660-
}
661635
}
662636

663637
let activated = cx.flag_activated(&candidate, opts, parent)?;
@@ -772,8 +746,6 @@ impl RemainingCandidates {
772746
&mut self,
773747
conflicting_prev_active: &mut ConflictMap,
774748
cx: &Context,
775-
dep: &Dependency,
776-
parent: PackageId,
777749
) -> Option<(Summary, bool)> {
778750
for b in self.remaining.by_ref() {
779751
let b_id = b.package_id();
@@ -808,23 +780,6 @@ impl RemainingCandidates {
808780
continue;
809781
}
810782
}
811-
// We may still have to reject do to a public dependency conflict. If one of any of our
812-
// ancestors that can see us already knows about a different crate with this name then
813-
// we have to reject this candidate. Additionally this candidate may already have been
814-
// activated and have public dependants of its own,
815-
// all of witch also need to be checked the same way.
816-
if let Some(public_dependency) = cx.public_dependency.as_ref() {
817-
if let Err(((c1, c2), c3)) =
818-
public_dependency.can_add_edge(b_id, parent, dep.is_public(), &cx.parents)
819-
{
820-
conflicting_prev_active.insert(c1.0, c1.1);
821-
conflicting_prev_active.insert(c2.0, c2.1);
822-
if let Some(c3) = c3 {
823-
conflicting_prev_active.insert(c3.0, c3.1);
824-
}
825-
continue;
826-
}
827-
}
828783

829784
// Well if we made it this far then we've got a valid dependency. We
830785
// want this iterator to be inherently "peekable" so we don't
@@ -1001,12 +956,9 @@ fn find_candidate(
1001956
};
1002957

1003958
while let Some(mut frame) = backtrack_stack.pop() {
1004-
let next = frame.remaining_candidates.next(
1005-
&mut frame.conflicting_activations,
1006-
&frame.context,
1007-
&frame.dep,
1008-
frame.parent.package_id(),
1009-
);
959+
let next = frame
960+
.remaining_candidates
961+
.next(&mut frame.conflicting_activations, &frame.context);
1010962
let Some((candidate, has_another)) = next else {
1011963
continue;
1012964
};

src/cargo/ops/resolve.rs

-4
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ use crate::core::resolver::{
6464
self, HasDevUnits, Resolve, ResolveOpts, ResolveVersion, VersionOrdering, VersionPreferences,
6565
};
6666
use crate::core::summary::Summary;
67-
use crate::core::Feature;
6867
use crate::core::{GitReference, PackageId, PackageIdSpec, PackageSet, SourceId, Workspace};
6968
use crate::ops;
7069
use crate::sources::PathSource;
@@ -512,9 +511,6 @@ pub fn resolve_with_previous<'cfg>(
512511
registry,
513512
&version_prefs,
514513
Some(ws.config()),
515-
ws.unstable_features()
516-
.require(Feature::public_dependency())
517-
.is_ok(),
518514
)?;
519515
let patches: Vec<_> = registry
520516
.patches()

0 commit comments

Comments
 (0)