Skip to content

Commit 336f342

Browse files
Eh2406aleksator
andauthored
fix: don't panic on Range::none() dependencies (#55)
* fix: don't panic on Range::none() dependencies * fix: check packages don't depend on themselves * style: reword ForbiddenEmptyDependency description * style: rename newly introduced error types Co-authored-by: Alex Tokarev <[email protected]>
1 parent 4f1e355 commit 336f342

File tree

4 files changed

+73
-3
lines changed

4 files changed

+73
-3
lines changed

src/error.rs

+28
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,34 @@ pub enum PubGrubError<P: Package, V: Version> {
4343
source: Box<dyn std::error::Error>,
4444
},
4545

46+
/// Error arising when the implementer of
47+
/// [DependencyProvider](crate::solver::DependencyProvider)
48+
/// returned a dependency on an empty range.
49+
/// This technically means that the package can not be selected,
50+
/// but is clearly some kind of mistake.
51+
#[error("Package {dependent} required by {package} {version} depends on the empty set")]
52+
DependencyOnTheEmptySet {
53+
/// Package whose dependencies we want.
54+
package: P,
55+
/// Version of the package for which we want the dependencies.
56+
version: V,
57+
/// The dependent package that requires us to pick from the empty set.
58+
dependent: P,
59+
},
60+
61+
/// Error arising when the implementer of
62+
/// [DependencyProvider](crate::solver::DependencyProvider)
63+
/// returned a dependency on the requested package.
64+
/// This technically means that the package directly depends on itself,
65+
/// and is clearly some kind of mistake.
66+
#[error("{package} {version} depends on itself")]
67+
SelfDependency {
68+
/// Package whose dependencies we want.
69+
package: P,
70+
/// Version of the package for which we want the dependencies.
71+
version: V,
72+
},
73+
4674
/// Error arising when the implementer of [DependencyProvider](crate::solver::DependencyProvider)
4775
/// returned an error in the method [should_cancel](crate::solver::DependencyProvider::should_cancel).
4876
#[error("We should cancel")]

src/solver.rs

+16-1
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,22 @@ pub fn resolve<P: Package, V: Version>(
140140
});
141141
continue;
142142
}
143-
Dependencies::Known(x) => x,
143+
Dependencies::Known(x) => {
144+
if x.contains_key(&p) {
145+
return Err(PubGrubError::SelfDependency {
146+
package: p.clone(),
147+
version: v.clone(),
148+
});
149+
}
150+
if let Some((dependent, _)) = x.iter().find(|(_, r)| r == &&Range::none()) {
151+
return Err(PubGrubError::DependencyOnTheEmptySet {
152+
package: p.clone(),
153+
version: v.clone(),
154+
dependent: dependent.clone(),
155+
});
156+
}
157+
x
158+
}
144159
};
145160

146161
// Add that package and version if the dependencies are not problematic.

tests/proptest.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -326,8 +326,8 @@ proptest! {
326326
(Ok(l), Ok(r)) => assert_eq!(l, r),
327327
(Err(PubGrubError::NoSolution(derivation_l)), Err(PubGrubError::NoSolution(derivation_r))) => {
328328
prop_assert_eq!(
329-
DefaultStringReporter::report(&derivation_l).to_string(),
330-
DefaultStringReporter::report(&derivation_r).to_string()
329+
DefaultStringReporter::report(&derivation_l),
330+
DefaultStringReporter::report(&derivation_r)
331331
)},
332332
_ => panic!("not the same result")
333333
}

tests/tests.rs

+27
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// SPDX-License-Identifier: MPL-2.0
22

3+
use pubgrub::error::PubGrubError;
34
use pubgrub::range::Range;
45
use pubgrub::solver::{resolve, OfflineDependencyProvider};
56
use pubgrub::version::NumberVersion;
@@ -25,3 +26,29 @@ fn same_result_on_repeated_runs() {
2526
}
2627
}
2728
}
29+
30+
#[test]
31+
fn should_always_find_a_satisfier() {
32+
let mut dependency_provider = OfflineDependencyProvider::<_, NumberVersion>::new();
33+
dependency_provider.add_dependencies("a", 0, vec![("b", Range::none())]);
34+
assert!(matches!(
35+
resolve(&dependency_provider, "a", 0),
36+
Err(PubGrubError::DependencyOnTheEmptySet { .. })
37+
));
38+
39+
dependency_provider.add_dependencies("c", 0, vec![("a", Range::any())]);
40+
assert!(matches!(
41+
resolve(&dependency_provider, "c", 0),
42+
Err(PubGrubError::DependencyOnTheEmptySet { .. })
43+
));
44+
}
45+
46+
#[test]
47+
fn cannot_depend_on_self() {
48+
let mut dependency_provider = OfflineDependencyProvider::<_, NumberVersion>::new();
49+
dependency_provider.add_dependencies("a", 0, vec![("a", Range::any())]);
50+
assert!(matches!(
51+
resolve(&dependency_provider, "a", 0),
52+
Err(PubGrubError::SelfDependency { .. })
53+
));
54+
}

0 commit comments

Comments
 (0)