aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/src/dependency_resolver
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-05-23 23:14:52 +0900
committernsfisis <nsfisis@gmail.com>2026-05-23 23:15:14 +0900
commitdbdecaf5a1c54a876b7ee0153d58dd39b1080f97 (patch)
treef13f2ced03c803dcbc42a5672458b3cb19ff0f30 /crates/shirabe/src/dependency_resolver
parentf5b987a00712211b7ce56300851182bda904e97b (diff)
downloadphp-shirabe-dbdecaf5a1c54a876b7ee0153d58dd39b1080f97.tar.gz
php-shirabe-dbdecaf5a1c54a876b7ee0153d58dd39b1080f97.tar.zst
php-shirabe-dbdecaf5a1c54a876b7ee0153d58dd39b1080f97.zip
refactor(semver): change ConstraintInterface to a closed enum
Replace the dyn ConstraintInterface trait objects with an AnyConstraint enum closing over its four implementors (Simple, Multi, MatchAll, MatchNone), mirroring the earlier Rule enum conversion. Rename constraint.rs to simple_constraint.rs to match the renamed Constraint type. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe/src/dependency_resolver')
-rw-r--r--crates/shirabe/src/dependency_resolver/default_policy.rs13
-rw-r--r--crates/shirabe/src/dependency_resolver/pool.rs38
-rw-r--r--crates/shirabe/src/dependency_resolver/pool_builder.rs88
-rw-r--r--crates/shirabe/src/dependency_resolver/pool_optimizer.rs84
-rw-r--r--crates/shirabe/src/dependency_resolver/problem.rs105
-rw-r--r--crates/shirabe/src/dependency_resolver/request.rs10
-rw-r--r--crates/shirabe/src/dependency_resolver/rule.rs36
-rw-r--r--crates/shirabe/src/dependency_resolver/rule_set_generator.rs18
-rw-r--r--crates/shirabe/src/dependency_resolver/security_advisory_pool_filter.rs7
-rw-r--r--crates/shirabe/src/dependency_resolver/solver.rs9
10 files changed, 229 insertions, 179 deletions
diff --git a/crates/shirabe/src/dependency_resolver/default_policy.rs b/crates/shirabe/src/dependency_resolver/default_policy.rs
index c24e382..cc33b81 100644
--- a/crates/shirabe/src/dependency_resolver/default_policy.rs
+++ b/crates/shirabe/src/dependency_resolver/default_policy.rs
@@ -5,7 +5,8 @@ use std::cell::RefCell;
use indexmap::IndexMap;
use shirabe_semver::compiling_matcher::CompilingMatcher;
-use shirabe_semver::constraint::Constraint;
+use shirabe_semver::constraint::AnyConstraint;
+use shirabe_semver::constraint::SimpleConstraint;
use crate::dependency_resolver::PolicyInterface;
use crate::dependency_resolver::Pool;
@@ -209,14 +210,16 @@ impl PolicyInterface for DefaultPolicy {
if (a.is_dev() && a.get_version().starts_with("dev-"))
|| (b.is_dev() && b.get_version().starts_with("dev-"))
{
- let constraint = Constraint::new(operator, b.get_version());
- let version = Constraint::new("==", a.get_version());
+ let constraint =
+ SimpleConstraint::new(operator.to_string(), b.get_version().to_string(), None);
+ let version =
+ SimpleConstraint::new("==".to_string(), a.get_version().to_string(), None);
return constraint.match_specific(&version, true);
}
CompilingMatcher::r#match(
- &Constraint::new(operator, b.get_version()),
- Constraint::OP_EQ,
+ &SimpleConstraint::new(operator.to_string(), b.get_version().to_string(), None).into(),
+ SimpleConstraint::OP_EQ,
a.get_version().to_string(),
)
}
diff --git a/crates/shirabe/src/dependency_resolver/pool.rs b/crates/shirabe/src/dependency_resolver/pool.rs
index e43eb53..771f363 100644
--- a/crates/shirabe/src/dependency_resolver/pool.rs
+++ b/crates/shirabe/src/dependency_resolver/pool.rs
@@ -5,8 +5,8 @@ use std::fmt;
use indexmap::IndexMap;
use shirabe_php_shim::{Countable, STR_PAD_LEFT, abs, spl_object_hash, str_pad};
use shirabe_semver::compiling_matcher::CompilingMatcher;
-use shirabe_semver::constraint::Constraint;
-use shirabe_semver::constraint::ConstraintInterface;
+use shirabe_semver::constraint::AnyConstraint;
+use shirabe_semver::constraint::SimpleConstraint;
use crate::advisory::PartialSecurityAdvisory;
use crate::package::BasePackage;
@@ -70,7 +70,7 @@ impl Pool {
pub fn get_removed_versions(
&self,
name: &str,
- constraint: &dyn ConstraintInterface,
+ constraint: &AnyConstraint,
) -> IndexMap<String, String> {
let Some(versions) = self.removed_versions.get(name) else {
return IndexMap::new();
@@ -78,7 +78,9 @@ impl Pool {
let mut result: IndexMap<String, String> = IndexMap::new();
for (version, pretty_version) in versions {
- if constraint.matches(&Constraint::new("==", version)) {
+ if constraint
+ .matches(&SimpleConstraint::new("==".to_string(), version.to_string(), None).into())
+ {
result.insert(version.clone(), pretty_version.clone());
}
}
@@ -110,7 +112,7 @@ impl Pool {
pub fn is_security_removed_package_version(
&self,
package_name: &str,
- constraint: Option<&dyn ConstraintInterface>,
+ constraint: Option<&AnyConstraint>,
) -> bool {
let empty = IndexMap::new();
let versions = self
@@ -119,7 +121,9 @@ impl Pool {
.unwrap_or(&empty);
for (version, _package_with_security_advisories) in versions {
if let Some(c) = constraint {
- if c.matches(&Constraint::new("==", version)) {
+ if c.matches(
+ &SimpleConstraint::new("==".to_string(), version.to_string(), None).into(),
+ ) {
return true;
}
}
@@ -132,7 +136,7 @@ impl Pool {
pub fn get_security_advisory_identifiers_for_package_version(
&self,
package_name: &str,
- constraint: Option<&dyn ConstraintInterface>,
+ constraint: Option<&AnyConstraint>,
) -> Vec<String> {
let empty = IndexMap::new();
let versions = self
@@ -141,7 +145,9 @@ impl Pool {
.unwrap_or(&empty);
for (version, package_with_security_advisories) in versions {
if let Some(c) = constraint {
- if c.matches(&Constraint::new("==", version)) {
+ if c.matches(
+ &SimpleConstraint::new("==".to_string(), version.to_string(), None).into(),
+ ) {
return package_with_security_advisories
.iter()
.map(|advisory| advisory.advisory_id.clone())
@@ -156,7 +162,7 @@ impl Pool {
pub fn is_abandoned_removed_package_version(
&self,
package_name: &str,
- constraint: Option<&dyn ConstraintInterface>,
+ constraint: Option<&AnyConstraint>,
) -> bool {
let empty = IndexMap::new();
let versions = self
@@ -165,7 +171,9 @@ impl Pool {
.unwrap_or(&empty);
for (version, _pretty_version) in versions {
if let Some(c) = constraint {
- if c.matches(&Constraint::new("==", version)) {
+ if c.matches(
+ &SimpleConstraint::new("==".to_string(), version.to_string(), None).into(),
+ ) {
return true;
}
}
@@ -226,11 +234,11 @@ impl Pool {
pub fn what_provides(
&mut self,
name: &str,
- constraint: Option<&dyn ConstraintInterface>,
+ constraint: Option<&AnyConstraint>,
) -> Vec<Box<dyn BasePackage>> {
// PHP: $key = (string) $constraint;
let key = match constraint {
- Some(c) => c.__to_string(),
+ Some(c) => c.to_string(),
None => String::new(),
};
if let Some(by_key) = self.provider_cache.get(name) {
@@ -254,7 +262,7 @@ impl Pool {
pub(crate) fn compute_what_provides(
&self,
name: &str,
- constraint: Option<&dyn ConstraintInterface>,
+ constraint: Option<&AnyConstraint>,
) -> Vec<Box<dyn BasePackage>> {
let Some(candidates) = self.package_by_name.get(name) else {
return vec![];
@@ -306,7 +314,7 @@ impl Pool {
&self,
candidate: &dyn BasePackage,
name: &str,
- constraint: Option<&dyn ConstraintInterface>,
+ constraint: Option<&AnyConstraint>,
) -> bool {
let candidate_name = candidate.get_name();
let candidate_version = candidate.get_version();
@@ -315,7 +323,7 @@ impl Pool {
return constraint.is_none()
|| CompilingMatcher::r#match(
constraint.unwrap(),
- Constraint::OP_EQ,
+ SimpleConstraint::OP_EQ,
candidate_version.to_string(),
);
}
diff --git a/crates/shirabe/src/dependency_resolver/pool_builder.rs b/crates/shirabe/src/dependency_resolver/pool_builder.rs
index fcc0339..f80ef38 100644
--- a/crates/shirabe/src/dependency_resolver/pool_builder.rs
+++ b/crates/shirabe/src/dependency_resolver/pool_builder.rs
@@ -11,10 +11,10 @@ use shirabe_php_shim::{
array_search, array_search_mixed, count, in_array, microtime, number_format, round,
spl_object_hash, sprintf, strpos,
};
-use shirabe_semver::constraint::Constraint;
-use shirabe_semver::constraint::ConstraintInterface;
+use shirabe_semver::constraint::AnyConstraint;
use shirabe_semver::constraint::MatchAllConstraint;
use shirabe_semver::constraint::MultiConstraint;
+use shirabe_semver::constraint::SimpleConstraint;
use crate::dependency_resolver::Pool;
use crate::dependency_resolver::PoolOptimizer;
@@ -41,13 +41,13 @@ pub struct PoolBuilder {
stability_flags: IndexMap<String, i64>,
root_aliases: IndexMap<String, IndexMap<String, IndexMap<String, String>>>,
root_references: IndexMap<String, String>,
- temporary_constraints: IndexMap<String, Box<dyn ConstraintInterface>>,
+ temporary_constraints: IndexMap<String, AnyConstraint>,
event_dispatcher: Option<std::rc::Rc<std::cell::RefCell<EventDispatcher>>>,
pool_optimizer: Option<PoolOptimizer>,
io: Box<dyn IOInterface>,
alias_map: IndexMap<String, IndexMap<i64, AliasPackage>>,
- packages_to_load: IndexMap<String, Box<dyn ConstraintInterface>>,
- loaded_packages: IndexMap<String, Box<dyn ConstraintInterface>>,
+ packages_to_load: IndexMap<String, AnyConstraint>,
+ loaded_packages: IndexMap<String, AnyConstraint>,
loaded_per_repo: IndexMap<i64, IndexMap<String, IndexMap<String, Box<dyn PackageInterface>>>>,
packages: IndexMap<i64, Box<dyn BasePackage>>,
unacceptable_fixed_or_locked_packages: Vec<Box<dyn BasePackage>>,
@@ -88,7 +88,7 @@ impl PoolBuilder {
io: Box<dyn IOInterface>,
event_dispatcher: Option<std::rc::Rc<std::cell::RefCell<EventDispatcher>>>,
pool_optimizer: Option<PoolOptimizer>,
- temporary_constraints: IndexMap<String, Box<dyn ConstraintInterface>>,
+ temporary_constraints: IndexMap<String, AnyConstraint>,
security_advisory_pool_filter: Option<SecurityAdvisoryPoolFilter>,
) -> Self {
Self {
@@ -195,14 +195,14 @@ impl PoolBuilder {
// loading any packages
self.loaded_packages.insert(
package.get_name().to_string(),
- Box::new(MatchAllConstraint::new()),
+ MatchAllConstraint::new(None).into(),
);
// replace means conflict, so if a fixed package replaces a name, no need to load that one, packages would conflict anyways
for (_k, link) in &package.get_replaces() {
self.loaded_packages.insert(
link.get_target().to_string(),
- Box::new(MatchAllConstraint::new()),
+ MatchAllConstraint::new(None).into(),
);
}
@@ -238,7 +238,7 @@ impl PoolBuilder {
}
self.packages_to_load
- .insert(package_name.clone(), constraint.clone_box());
+ .insert(package_name.clone(), constraint.clone());
self.max_extended_reqs.insert(package_name.clone(), true);
}
@@ -271,7 +271,7 @@ impl PoolBuilder {
for package_name in package.get_names(true) {
let constraint = match self.temporary_constraints.get(&package_name) {
- Some(c) => c.clone_box(),
+ Some(c) => c.clone(),
None => continue,
};
@@ -288,7 +288,8 @@ impl PoolBuilder {
let mut found = false;
for (_idx, version) in &package_and_aliases {
- if CompilingMatcher::matches(&*constraint, Constraint::OP_EQ, version) {
+ if CompilingMatcher::matches(&constraint, SimpleConstraint::OP_EQ, version)
+ {
found = true;
}
}
@@ -377,9 +378,9 @@ impl PoolBuilder {
&mut self,
request: &Request,
name: &str,
- constraint: &dyn ConstraintInterface,
+ constraint: &AnyConstraint,
) {
- let constraint = constraint.clone_box();
+ let constraint = constraint.clone();
// Skip platform requires at this stage
if PlatformRepository::is_platform_package(name) {
return;
@@ -398,8 +399,8 @@ impl PoolBuilder {
let root_requires = request.get_requires();
let mut constraint = constraint;
if let Some(root_constraint) = root_requires.get(name) {
- if !Intervals::is_subset_of(&*constraint, &**root_constraint).unwrap_or(false) {
- constraint = root_constraint.clone_box();
+ if !Intervals::is_subset_of(&constraint, root_constraint).unwrap_or(false) {
+ constraint = root_constraint.clone();
}
}
@@ -410,17 +411,18 @@ impl PoolBuilder {
// MultiConstraint::create() will optimize anyway)
if let Some(existing) = self.packages_to_load.get(name) {
// Already marked for loading and this does not expand the constraint to be loaded, nothing to do
- if Intervals::is_subset_of(&*constraint, &**existing).unwrap_or(false) {
+ if Intervals::is_subset_of(&constraint, existing).unwrap_or(false) {
return;
}
// extend the constraint to be loaded
constraint = Intervals::compact_constraint(
MultiConstraint::create(
- vec![existing.clone_box(), constraint.clone_box()],
+ vec![existing.clone(), constraint.clone()],
false,
+ None,
)
- .unwrap_or_else(|_| Box::new(MatchAllConstraint::new())),
+ .unwrap_or_else(|_| MatchAllConstraint::new(None).into()),
);
}
@@ -431,7 +433,7 @@ impl PoolBuilder {
// No need to load this package with this constraint because it is
// a subset of the constraint with which we have already loaded packages
- if Intervals::is_subset_of(&*constraint, &**self.loaded_packages.get(name).unwrap())
+ if Intervals::is_subset_of(&constraint, self.loaded_packages.get(name).unwrap())
.unwrap_or(false)
{
return;
@@ -444,13 +446,11 @@ impl PoolBuilder {
name.to_string(),
Intervals::compact_constraint(
MultiConstraint::create(
- vec![
- self.loaded_packages.get(name).unwrap().clone_box(),
- constraint,
- ],
+ vec![self.loaded_packages.get(name).unwrap().clone(), constraint],
false,
+ None,
)
- .unwrap_or_else(|_| Box::new(MatchAllConstraint::new())),
+ .unwrap_or_else(|_| MatchAllConstraint::new(None).into()),
),
);
self.loaded_packages.shift_remove(name);
@@ -475,23 +475,23 @@ impl PoolBuilder {
for name in to_remove {
self.packages_to_load.shift_remove(&name);
}
- let snapshot: Vec<(String, Box<dyn ConstraintInterface>)> = self
+ let snapshot: Vec<(String, AnyConstraint)> = self
.packages_to_load
.iter()
- .map(|(k, v)| (k.clone(), v.clone_box()))
+ .map(|(k, v)| (k.clone(), v.clone()))
.collect();
for (name, constraint) in &snapshot {
self.loaded_packages
- .insert(name.clone(), constraint.clone_box());
+ .insert(name.clone(), constraint.clone());
}
// Load packages in chunks of 50 to prevent memory usage build-up due to caches of all sorts
// TODO(phase-b): array_chunk shim signature expects &[T]; build IndexMap chunks manually.
- let mut package_batches: Vec<IndexMap<String, Box<dyn ConstraintInterface>>> = {
- let mut chunks: Vec<IndexMap<String, Box<dyn ConstraintInterface>>> = Vec::new();
- let mut current: IndexMap<String, Box<dyn ConstraintInterface>> = IndexMap::new();
+ let mut package_batches: Vec<IndexMap<String, AnyConstraint>> = {
+ let mut chunks: Vec<IndexMap<String, AnyConstraint>> = Vec::new();
+ let mut current: IndexMap<String, AnyConstraint> = IndexMap::new();
for (k, v) in self.packages_to_load.iter() {
- current.insert(k.clone(), v.clone_box());
+ current.insert(k.clone(), v.clone());
if current.len() as i64 >= Self::LOAD_BATCH_SIZE {
chunks.push(std::mem::take(&mut current));
}
@@ -525,11 +525,11 @@ impl PoolBuilder {
// Iterate by index because we mutate package_batches inside the loop.
for batch_index in 0..package_batches.len() {
- let package_batch: IndexMap<String, Option<Box<dyn ConstraintInterface>>> =
- package_batches[batch_index]
- .iter()
- .map(|(k, v)| (k.clone(), Some(v.clone_box())))
- .collect();
+ let package_batch: IndexMap<String, Option<AnyConstraint>> = package_batches
+ [batch_index]
+ .iter()
+ .map(|(k, v)| (k.clone(), Some(v.clone())))
+ .collect();
let result = repository.load_packages(
package_batch,
self.acceptable_stabilities.clone(),
@@ -598,18 +598,18 @@ impl PoolBuilder {
}
// PHP: array_chunk(array_merge(...$packageBatches), self::LOAD_BATCH_SIZE, true)
- let mut merged: IndexMap<String, Box<dyn ConstraintInterface>> = IndexMap::new();
+ let mut merged: IndexMap<String, AnyConstraint> = IndexMap::new();
for batch in &package_batches {
for (k, v) in batch {
- merged.insert(k.clone(), v.clone_box());
+ merged.insert(k.clone(), v.clone());
}
}
// Rebuild chunks from merged.
package_batches = {
- let mut chunks: Vec<IndexMap<String, Box<dyn ConstraintInterface>>> = Vec::new();
- let mut current: IndexMap<String, Box<dyn ConstraintInterface>> = IndexMap::new();
+ let mut chunks: Vec<IndexMap<String, AnyConstraint>> = Vec::new();
+ let mut current: IndexMap<String, AnyConstraint> = IndexMap::new();
for (k, v) in merged.iter() {
- current.insert(k.clone(), v.clone_box());
+ current.insert(k.clone(), v.clone());
if current.len() as i64 >= Self::LOAD_BATCH_SIZE {
chunks.push(std::mem::take(&mut current));
}
@@ -929,7 +929,7 @@ impl PoolBuilder {
self.mark_package_name_for_loading(
request,
&replacer_name,
- &MatchAllConstraint::new(),
+ &MatchAllConstraint::new(None).into(),
);
} else {
let pkgs: Vec<Box<dyn BasePackage>> =
@@ -1050,8 +1050,8 @@ impl PoolBuilder {
fn mark_package_name_for_loading_if_required(&mut self, request: &Request, name: &str) {
if self.is_root_require(request, name) {
- let cons = request.get_requires()[name].clone_box();
- self.mark_package_name_for_loading(request, name, &*cons);
+ let cons = request.get_requires()[name].clone();
+ self.mark_package_name_for_loading(request, name, &cons);
}
let pkgs: Vec<Box<dyn BasePackage>> =
diff --git a/crates/shirabe/src/dependency_resolver/pool_optimizer.rs b/crates/shirabe/src/dependency_resolver/pool_optimizer.rs
index 326587a..27b3ffb 100644
--- a/crates/shirabe/src/dependency_resolver/pool_optimizer.rs
+++ b/crates/shirabe/src/dependency_resolver/pool_optimizer.rs
@@ -6,9 +6,9 @@ use anyhow::Result;
use indexmap::IndexMap;
use shirabe_php_shim::{LogicException, PhpMixed, implode, ksort, spl_object_hash};
use shirabe_semver::compiling_matcher::CompilingMatcher;
-use shirabe_semver::constraint::Constraint;
-use shirabe_semver::constraint::ConstraintInterface;
+use shirabe_semver::constraint::AnyConstraint;
use shirabe_semver::constraint::MultiConstraint;
+use shirabe_semver::constraint::SimpleConstraint;
use shirabe_semver::intervals::Intervals;
use crate::dependency_resolver::PolicyInterface;
@@ -29,12 +29,10 @@ pub struct PoolOptimizer {
irremovable_packages: IndexMap<i64, bool>,
/// @var array<string, array<string, ConstraintInterface>>
- require_constraints_per_package:
- IndexMap<String, IndexMap<String, Box<dyn ConstraintInterface>>>,
+ require_constraints_per_package: IndexMap<String, IndexMap<String, AnyConstraint>>,
/// @var array<string, array<string, ConstraintInterface>>
- conflict_constraints_per_package:
- IndexMap<String, IndexMap<String, Box<dyn ConstraintInterface>>>,
+ conflict_constraints_per_package: IndexMap<String, IndexMap<String, AnyConstraint>>,
/// @var array<int, true>
packages_to_remove: IndexMap<i64, bool>,
@@ -90,23 +88,27 @@ impl PoolOptimizer {
}
fn prepare(&mut self, request: &Request, pool: &Pool) {
- let mut irremovable_package_constraint_groups: IndexMap<
- String,
- Vec<Box<dyn ConstraintInterface>>,
- > = IndexMap::new();
+ let mut irremovable_package_constraint_groups: IndexMap<String, Vec<AnyConstraint>> =
+ IndexMap::new();
// Mark fixed or locked packages as irremovable
for (_, package) in request.get_fixed_or_locked_packages() {
irremovable_package_constraint_groups
.entry(PackageInterface::get_name(package.as_ref()).to_string())
.or_insert_with(Vec::new)
- .push(Box::new(Constraint::new("==", package.get_version())));
+ .push(
+ SimpleConstraint::new(
+ "==".to_string(),
+ package.get_version().to_string(),
+ None,
+ )
+ .into(),
+ );
}
// Extract requested package requirements
for (require, constraint) in request.get_requires() {
- // TODO(phase-b): clone Box<dyn ConstraintInterface>
- self.extract_require_constraints_per_package(require, todo!("constraint.clone_box()"));
+ self.extract_require_constraints_per_package(require, constraint.clone());
}
// First pass over all packages to extract information and mark package constraints irremovable
@@ -115,16 +117,14 @@ impl PoolOptimizer {
for link in package.get_requires().values() {
self.extract_require_constraints_per_package(
link.get_target(),
- // TODO(phase-b): clone constraint
- todo!("link.get_constraint().clone_box()"),
+ link.get_constraint().clone(),
);
}
// Extract package conflicts
for link in package.get_conflicts().values() {
self.extract_conflict_constraints_per_package(
link.get_target(),
- // TODO(phase-b): clone constraint
- todo!("link.get_constraint().clone_box()"),
+ link.get_constraint().clone(),
);
}
@@ -138,16 +138,14 @@ impl PoolOptimizer {
}
}
- let mut irremovable_package_constraints: IndexMap<String, Box<dyn ConstraintInterface>> =
- IndexMap::new();
+ let mut irremovable_package_constraints: IndexMap<String, AnyConstraint> = IndexMap::new();
for (package_name, constraints) in irremovable_package_constraint_groups {
- // TODO(phase-b): MultiConstraint::new signature; move ownership of constraints vec
irremovable_package_constraints.insert(
package_name,
if 1 == constraints.len() {
- todo!("constraints[0] moved out")
+ constraints.into_iter().next().unwrap()
} else {
- Box::new(MultiConstraint::new(constraints, false))
+ MultiConstraint::new(constraints, false, None).into()
},
);
}
@@ -165,8 +163,8 @@ impl PoolOptimizer {
.get(PackageInterface::get_name(package.as_ref()))
.unwrap();
if CompilingMatcher::r#match(
- constraint.as_ref(),
- Constraint::OP_EQ,
+ constraint,
+ SimpleConstraint::OP_EQ,
package.get_version().to_string(),
) {
self.mark_package_irremovable(package.as_ref());
@@ -262,8 +260,8 @@ impl PoolOptimizer {
let mut group_hash_parts: Vec<String> = vec![];
if CompilingMatcher::r#match(
- require_constraint.as_ref(),
- Constraint::OP_EQ,
+ require_constraint,
+ SimpleConstraint::OP_EQ,
package.get_version().to_string(),
) {
group_hash_parts.push(format!(
@@ -276,7 +274,7 @@ impl PoolOptimizer {
for (_, link) in package.get_replaces() {
if CompilingMatcher::r#match(
link.get_constraint(),
- Constraint::OP_EQ,
+ SimpleConstraint::OP_EQ,
package.get_version().to_string(),
) {
// Use the same hash part as the regular require hash because that's what the replacement does
@@ -293,8 +291,8 @@ impl PoolOptimizer {
{
for (_, conflict_constraint) in conflict_constraints {
if CompilingMatcher::r#match(
- conflict_constraint.as_ref(),
- Constraint::OP_EQ,
+ conflict_constraint,
+ SimpleConstraint::OP_EQ,
package.get_version().to_string(),
) {
group_hash_parts.push(format!(
@@ -415,7 +413,7 @@ impl PoolOptimizer {
// performance more than the additional few packages that could be filtered out would benefit the process.
subhash.insert(
link.get_target().to_string(),
- link.get_constraint().__to_string(),
+ link.get_constraint().to_string(),
);
}
@@ -638,7 +636,7 @@ impl PoolOptimizer {
if false
== CompilingMatcher::r#match(
link_constraint,
- Constraint::OP_EQ,
+ SimpleConstraint::OP_EQ,
version_str,
)
{
@@ -662,13 +660,13 @@ impl PoolOptimizer {
fn extract_require_constraints_per_package(
&mut self,
package: &str,
- constraint: Box<dyn ConstraintInterface>,
+ constraint: AnyConstraint,
) {
for expanded in self.expand_disjunctive_multi_constraints(constraint) {
self.require_constraints_per_package
.entry(package.to_string())
.or_insert_with(IndexMap::new)
- .insert(expanded.__to_string(), expanded);
+ .insert(expanded.to_string(), expanded);
}
}
@@ -680,32 +678,28 @@ impl PoolOptimizer {
fn extract_conflict_constraints_per_package(
&mut self,
package: &str,
- constraint: Box<dyn ConstraintInterface>,
+ constraint: AnyConstraint,
) {
for expanded in self.expand_disjunctive_multi_constraints(constraint) {
self.conflict_constraints_per_package
.entry(package.to_string())
.or_insert_with(IndexMap::new)
- .insert(expanded.__to_string(), expanded);
+ .insert(expanded.to_string(), expanded);
}
}
/// @return ConstraintInterface[]
fn expand_disjunctive_multi_constraints(
&self,
- constraint: Box<dyn ConstraintInterface>,
- ) -> Vec<Box<dyn ConstraintInterface>> {
- let constraint = Intervals::compact_constraint(&*constraint).unwrap_or(constraint);
+ constraint: AnyConstraint,
+ ) -> Vec<AnyConstraint> {
+ let constraint = Intervals::compact_constraint(&constraint).unwrap_or(constraint);
- if let Some(multi) = constraint.as_any().downcast_ref::<MultiConstraint>() {
- if multi.is_disjunctive() {
+ if let Some(multi) = constraint.as_multi_constraint() {
+ if multi.is_disjunctive_mc() {
// No need to call ourselves recursively here because Intervals::compactConstraint() ensures that there
// are no nested disjunctive MultiConstraint instances possible
- return multi
- .get_constraints()
- .iter()
- .map(|c| c.clone_box())
- .collect();
+ return multi.get_constraints().iter().map(|c| c.clone()).collect();
}
}
diff --git a/crates/shirabe/src/dependency_resolver/problem.rs b/crates/shirabe/src/dependency_resolver/problem.rs
index a69a4a2..4436ec8 100644
--- a/crates/shirabe/src/dependency_resolver/problem.rs
+++ b/crates/shirabe/src/dependency_resolver/problem.rs
@@ -9,9 +9,9 @@ use shirabe_php_shim::{
phpversion, spl_object_hash, sprintf, str_replace, str_starts_with, stripos, strpos,
strtolower, substr, substr_count, version_compare,
};
-use shirabe_semver::constraint::Constraint;
-use shirabe_semver::constraint::ConstraintInterface;
+use shirabe_semver::constraint::AnyConstraint;
use shirabe_semver::constraint::MultiConstraint;
+use shirabe_semver::constraint::SimpleConstraint;
use crate::advisory::SecurityAdvisory;
use crate::dependency_resolver::Pool;
@@ -92,14 +92,13 @@ impl Problem {
let reason_data = rule_ref.get_reason_data();
// TODO(phase-b): reason_data for RULE_ROOT_REQUIRE; extract via ReasonData::RootRequire variant.
- let (package_name, constraint): (String, Option<&dyn ConstraintInterface>) =
- match reason_data {
- rule::ReasonData::RootRequire {
- package_name,
- constraint,
- } => (package_name.clone(), Some(constraint.as_ref())),
- _ => (String::new(), None),
- };
+ let (package_name, constraint): (String, Option<&AnyConstraint>) = match reason_data {
+ rule::ReasonData::RootRequire {
+ package_name,
+ constraint,
+ } => (package_name.clone(), Some(constraint)),
+ _ => (String::new(), None),
+ };
let packages = pool.compute_what_provides(&package_name, constraint);
if packages.len() == 0 {
@@ -393,7 +392,7 @@ impl Problem {
pool: &mut Pool,
is_verbose: bool,
package_name: &str,
- constraint: Option<&dyn ConstraintInterface>,
+ constraint: Option<&AnyConstraint>,
) -> (String, String) {
if PlatformRepository::is_platform_package(package_name) {
// handle php/php-*/hhvm
@@ -572,7 +571,7 @@ impl Problem {
if let Some(c) = constraint {
if c.is_constraint()
- && c.get_operator() == Constraint::STR_OP_EQ
+ && c.get_operator() == SimpleConstraint::STR_OP_EQ
&& Preg::is_match3(r"{^dev-.*#.*}", &c.get_pretty_string(), None).unwrap_or(false)
{
let new_constraint =
@@ -580,17 +579,25 @@ impl Problem {
.unwrap_or_else(|_| c.get_pretty_string());
let packages = repository_set.find_packages(
package_name,
- Some(Box::new(MultiConstraint::new(
- vec![
- Box::new(Constraint::new(Constraint::STR_OP_EQ, &new_constraint))
- as Box<dyn ConstraintInterface>,
- Box::new(Constraint::new(
- Constraint::STR_OP_EQ,
- &str_replace("#", "+", &new_constraint),
- )) as Box<dyn ConstraintInterface>,
- ],
- false,
- ))),
+ Some(
+ MultiConstraint::new(
+ vec![
+ AnyConstraint::Simple(SimpleConstraint::new(
+ SimpleConstraint::STR_OP_EQ.to_string(),
+ new_constraint.clone(),
+ None,
+ )),
+ AnyConstraint::Simple(SimpleConstraint::new(
+ SimpleConstraint::STR_OP_EQ.to_string(),
+ str_replace("#", "+", &new_constraint),
+ None,
+ )),
+ ],
+ false,
+ None,
+ )
+ .into(),
+ ),
0,
);
if packages.len() > 0 {
@@ -618,15 +625,21 @@ impl Problem {
// first check if the actual requested package is found in normal conditions
// if so it must mean it is rejected by another constraint than the one given here
- let packages =
- repository_set.find_packages(package_name, constraint.map(|c| c.clone_box()), 0);
+ let packages = repository_set.find_packages(package_name, constraint.map(|c| c.clone()), 0);
if packages.len() > 0 {
let root_reqs = repository_set.get_root_requires();
if root_reqs.contains_key(package_name) {
let filtered: Vec<&Box<dyn BasePackage>> = packages
.iter()
.filter(|p| {
- root_reqs[package_name].matches(&Constraint::new("==", p.get_version()))
+ root_reqs[package_name].matches(
+ &SimpleConstraint::new(
+ "==".to_string(),
+ p.get_version().to_string(),
+ None,
+ )
+ .into(),
+ )
})
.collect();
if filtered.len() == 0 {
@@ -663,7 +676,14 @@ impl Problem {
let filtered: Vec<&Box<dyn BasePackage>> = packages
.iter()
.filter(|p| {
- temp_reqs[&name].matches(&Constraint::new("==", p.get_version()))
+ temp_reqs[&name].matches(
+ &SimpleConstraint::new(
+ "==".to_string(),
+ p.get_version().to_string(),
+ None,
+ )
+ .into(),
+ )
})
.collect();
if filtered.len() == 0 {
@@ -696,10 +716,23 @@ impl Problem {
}
if let Some(ref lp) = locked_package {
- let fixed_constraint = Constraint::new("==", lp.get_version());
+ let fixed_constraint = AnyConstraint::from(SimpleConstraint::new(
+ "==".to_string(),
+ lp.get_version().to_string(),
+ None,
+ ));
let filtered: Vec<&Box<dyn BasePackage>> = packages
.iter()
- .filter(|p| fixed_constraint.matches(&Constraint::new("==", p.get_version())))
+ .filter(|p| {
+ fixed_constraint.matches(
+ &SimpleConstraint::new(
+ "==".to_string(),
+ p.get_version().to_string(),
+ None,
+ )
+ .into(),
+ )
+ })
.collect();
if filtered.len() == 0 {
return (
@@ -837,14 +870,14 @@ impl Problem {
// check if the package is found when bypassing stability checks
let packages = repository_set.find_packages(
package_name,
- constraint.map(|c| c.clone_box()),
+ constraint.map(|c| c.clone()),
RepositorySet::ALLOW_UNACCEPTABLE_STABILITIES,
);
if packages.len() > 0 {
// we must first verify if a valid package would be found in a lower priority repository
let all_repos_packages = repository_set.find_packages(
package_name,
- constraint.map(|c| c.clone_box()),
+ constraint.map(|c| c.clone()),
RepositorySet::ALLOW_SHADOWED_REPOSITORIES,
);
if all_repos_packages.len() > 0 {
@@ -887,7 +920,7 @@ impl Problem {
// we must first verify if a valid package would be found in a lower priority repository
let all_repos_packages = repository_set.find_packages(
package_name,
- constraint.map(|c| c.clone_box()),
+ constraint.map(|c| c.clone()),
RepositorySet::ALLOW_SHADOWED_REPOSITORIES,
);
if all_repos_packages.len() > 0 {
@@ -993,7 +1026,7 @@ impl Problem {
packages: &Vec<Box<dyn BasePackage>>,
is_verbose: bool,
pool: Option<&Pool>,
- constraint: Option<&dyn ConstraintInterface>,
+ constraint: Option<&AnyConstraint>,
use_removed_version_group: bool,
) -> String {
struct PreparedEntry {
@@ -1213,7 +1246,7 @@ impl Problem {
higher_repo_packages: &Vec<Box<dyn BasePackage>>,
all_repos_packages: &Vec<Box<dyn BasePackage>>,
reason: &str,
- constraint: Option<&dyn ConstraintInterface>,
+ constraint: Option<&AnyConstraint>,
) -> (String, String) {
let mut next_repo_packages: Vec<Box<dyn BasePackage>> = Vec::new();
let mut next_repo: Option<Box<dyn crate::repository::RepositoryInterface>> = None;
@@ -1346,10 +1379,10 @@ impl Problem {
}
/// Turns a constraint into text usable in a sentence describing a request
- pub(crate) fn constraint_to_text(constraint: Option<&dyn ConstraintInterface>) -> String {
+ pub(crate) fn constraint_to_text(constraint: Option<&AnyConstraint>) -> String {
if let Some(c) = constraint {
if c.is_constraint()
- && c.get_operator() == Constraint::STR_OP_EQ
+ && c.get_operator() == SimpleConstraint::STR_OP_EQ
&& !str_starts_with(&c.get_version(), "dev-")
{
if !Preg::is_match3(r"{^\d+(?:\.\d+)*$}", &c.get_pretty_string(), None)
diff --git a/crates/shirabe/src/dependency_resolver/request.rs b/crates/shirabe/src/dependency_resolver/request.rs
index d181bd2..e2bfc3c 100644
--- a/crates/shirabe/src/dependency_resolver/request.rs
+++ b/crates/shirabe/src/dependency_resolver/request.rs
@@ -2,7 +2,7 @@
use indexmap::IndexMap;
use shirabe_php_shim::{LogicException, spl_object_hash, strtolower};
-use shirabe_semver::constraint::ConstraintInterface;
+use shirabe_semver::constraint::AnyConstraint;
use shirabe_semver::constraint::MatchAllConstraint;
use crate::package::BasePackage;
@@ -43,7 +43,7 @@ pub enum UpdateAllowTransitiveDeps {
#[derive(Debug)]
pub struct Request {
pub(crate) locked_repository: Option<LockArrayRepository>,
- pub(crate) requires: IndexMap<String, Box<dyn ConstraintInterface>>,
+ pub(crate) requires: IndexMap<String, AnyConstraint>,
pub(crate) fixed_packages: IndexMap<String, Box<dyn BasePackage>>,
pub(crate) locked_packages: IndexMap<String, Box<dyn BasePackage>>,
pub(crate) fixed_locked_packages: IndexMap<String, Box<dyn BasePackage>>,
@@ -69,10 +69,10 @@ impl Request {
pub fn require_name(
&mut self,
package_name: &str,
- constraint: Option<Box<dyn ConstraintInterface>>,
+ constraint: Option<AnyConstraint>,
) -> anyhow::Result<()> {
let package_name = strtolower(package_name);
- let constraint = constraint.unwrap_or_else(|| Box::new(MatchAllConstraint::new()));
+ let constraint = constraint.unwrap_or_else(|| MatchAllConstraint::new(None).into());
if self.requires.contains_key(&package_name) {
return Err(LogicException {
message: format!(
@@ -155,7 +155,7 @@ impl Request {
== UpdateAllowTransitiveDeps::UpdateListedWithTransitiveDeps
}
- pub fn get_requires(&self) -> &IndexMap<String, Box<dyn ConstraintInterface>> {
+ pub fn get_requires(&self) -> &IndexMap<String, AnyConstraint> {
&self.requires
}
diff --git a/crates/shirabe/src/dependency_resolver/rule.rs b/crates/shirabe/src/dependency_resolver/rule.rs
index 90223e2..fbc8521 100644
--- a/crates/shirabe/src/dependency_resolver/rule.rs
+++ b/crates/shirabe/src/dependency_resolver/rule.rs
@@ -10,8 +10,8 @@ use shirabe_php_shim::{
LogicException, PhpMixed, RuntimeException, abs, array_filter, array_keys, array_shift,
array_values, implode, is_object,
};
-use shirabe_semver::constraint::Constraint;
-use shirabe_semver::constraint::ConstraintInterface;
+use shirabe_semver::constraint::AnyConstraint;
+use shirabe_semver::constraint::SimpleConstraint;
use crate::dependency_resolver::GenericRule;
use crate::dependency_resolver::MultiConflictRule;
@@ -36,7 +36,7 @@ pub enum ReasonData {
Int(i64),
RootRequire {
package_name: String,
- constraint: Box<dyn ConstraintInterface>,
+ constraint: AnyConstraint,
},
Fixed {
package: Box<dyn BasePackage>,
@@ -238,10 +238,14 @@ impl Rule {
if pool.is_unacceptable_fixed_or_locked_package(p) {
return true;
}
- if !link
- .get_constraint()
- .matches(&Constraint::new("=", p.get_version()))
- {
+ if !link.get_constraint().matches(
+ &SimpleConstraint::new(
+ "=".to_string(),
+ p.get_version().to_string(),
+ None,
+ )
+ .into(),
+ ) {
return true;
}
// required package was locked but has been unlocked and still matches
@@ -275,7 +279,14 @@ impl Rule {
if pool.is_unacceptable_fixed_or_locked_package(p) {
return true;
}
- if !constraint.matches(&Constraint::new("=", p.get_version())) {
+ if !constraint.matches(
+ &SimpleConstraint::new(
+ "=".to_string(),
+ p.get_version().to_string(),
+ None,
+ )
+ .into(),
+ ) {
return true;
}
break;
@@ -345,12 +356,11 @@ impl Rule {
match self.get_reason() {
r if r == RULE_ROOT_REQUIRE => {
let reason_data = self.get_reason_data();
- let (package_name, constraint): (&str, &dyn ConstraintInterface) = match reason_data
- {
+ let (package_name, constraint): (&str, &AnyConstraint) = match reason_data {
ReasonData::RootRequire {
package_name,
constraint,
- } => (package_name.as_str(), constraint.as_ref()),
+ } => (package_name.as_str(), constraint),
_ => return String::new(),
};
@@ -712,7 +722,7 @@ impl Rule {
pool: &Pool,
packages: Vec<Box<dyn BasePackage>>,
is_verbose: bool,
- constraint: Option<&dyn ConstraintInterface>,
+ constraint: Option<&AnyConstraint>,
use_removed_version_group: bool,
) -> String {
Problem::get_package_list(
@@ -730,7 +740,7 @@ impl Rule {
pool: &Pool,
literals: &[i64],
is_verbose: bool,
- constraint: Option<&dyn ConstraintInterface>,
+ constraint: Option<&AnyConstraint>,
use_removed_version_group: bool,
) -> String {
let mut packages: Vec<Box<dyn BasePackage>> = vec![];
diff --git a/crates/shirabe/src/dependency_resolver/rule_set_generator.rs b/crates/shirabe/src/dependency_resolver/rule_set_generator.rs
index 45f1331..076ce42 100644
--- a/crates/shirabe/src/dependency_resolver/rule_set_generator.rs
+++ b/crates/shirabe/src/dependency_resolver/rule_set_generator.rs
@@ -205,14 +205,14 @@ impl RuleSetGenerator {
}
for link in package.get_requires().values() {
- let mut constraint = link.get_constraint().clone_box();
+ let mut constraint = link.get_constraint().clone();
if platform_requirement_filter.is_ignored(link.get_target()) {
continue;
} else if let Some(ignore_list_filter) = platform_requirement_filter
.as_any()
.downcast_ref::<IgnoreListPlatformRequirementFilter>(
) {
- let fallback = constraint.clone_box();
+ let fallback = constraint.clone();
constraint = ignore_list_filter
.filter_constraint(link.get_target(), constraint, true)
.unwrap_or(fallback);
@@ -221,7 +221,7 @@ impl RuleSetGenerator {
let possible_requires: Vec<Box<dyn PackageInterface>> = self
.pool
.borrow_mut()
- .what_provides(link.get_target(), Some(&*constraint))
+ .what_provides(link.get_target(), Some(&constraint))
.into_iter()
.map(|p| p.clone_package_box())
.collect();
@@ -258,14 +258,14 @@ impl RuleSetGenerator {
continue;
}
- let mut constraint = link.get_constraint().clone_box();
+ let mut constraint = link.get_constraint().clone();
if platform_requirement_filter.is_ignored(link.get_target()) {
continue;
} else if let Some(ignore_list_filter) = platform_requirement_filter
.as_any()
.downcast_ref::<IgnoreListPlatformRequirementFilter>(
) {
- let fallback = constraint.clone_box();
+ let fallback = constraint.clone();
constraint = ignore_list_filter
.filter_constraint(link.get_target(), constraint, false)
.unwrap_or(fallback);
@@ -274,7 +274,7 @@ impl RuleSetGenerator {
let conflicts = self
.pool
.borrow_mut()
- .what_provides(link.get_target(), Some(&*constraint));
+ .what_provides(link.get_target(), Some(&constraint));
for conflict in &conflicts {
// define the conflict rule for regular packages, for alias packages it's only needed if the name
@@ -354,14 +354,14 @@ impl RuleSetGenerator {
}
for (package_name, constraint) in request.get_requires() {
- let mut constraint = constraint.clone_box();
+ let mut constraint = constraint.clone();
if platform_requirement_filter.is_ignored(package_name) {
continue;
} else if let Some(ignore_list_filter) = platform_requirement_filter
.as_any()
.downcast_ref::<IgnoreListPlatformRequirementFilter>(
) {
- let fallback = constraint.clone_box();
+ let fallback = constraint.clone();
constraint = ignore_list_filter
.filter_constraint(package_name, constraint, true)
.unwrap_or(fallback);
@@ -370,7 +370,7 @@ impl RuleSetGenerator {
let packages: Vec<Box<dyn PackageInterface>> = self
.pool
.borrow_mut()
- .what_provides(package_name, Some(&*constraint))
+ .what_provides(package_name, Some(&constraint))
.into_iter()
.map(|p| p.clone_package_box())
.collect();
diff --git a/crates/shirabe/src/dependency_resolver/security_advisory_pool_filter.rs b/crates/shirabe/src/dependency_resolver/security_advisory_pool_filter.rs
index 742a709..4daf641 100644
--- a/crates/shirabe/src/dependency_resolver/security_advisory_pool_filter.rs
+++ b/crates/shirabe/src/dependency_resolver/security_advisory_pool_filter.rs
@@ -8,7 +8,8 @@ use crate::dependency_resolver::Request;
use crate::package::PackageInterface;
use crate::repository::RepositoryInterface;
use indexmap::IndexMap;
-use shirabe_semver::constraint::Constraint;
+use shirabe_semver::constraint::AnyConstraint;
+use shirabe_semver::constraint::SimpleConstraint;
#[derive(Debug)]
pub struct SecurityAdvisoryPoolFilter {
@@ -64,7 +65,9 @@ impl SecurityAdvisoryPoolFilter {
continue;
}
- let package_constraint = Constraint::new("==", package.get_version());
+ let package_constraint =
+ SimpleConstraint::new("==".to_string(), package.get_version().to_string(), None)
+ .into();
for advisory in &advisory_map[&package_name] {
// advisory is PartialSecurityAdvisory or SecurityAdvisory; both have affected_versions: Box<dyn ConstraintInterface>
if advisory.affected_versions.matches(&package_constraint) {
diff --git a/crates/shirabe/src/dependency_resolver/solver.rs b/crates/shirabe/src/dependency_resolver/solver.rs
index e4539d2..820f792 100644
--- a/crates/shirabe/src/dependency_resolver/solver.rs
+++ b/crates/shirabe/src/dependency_resolver/solver.rs
@@ -8,7 +8,7 @@ use indexmap::IndexMap;
use shirabe_php_shim::{
PhpMixed, array_pop, array_shift, array_unshift, microtime, spl_object_hash, sprintf,
};
-use shirabe_semver::constraint::ConstraintInterface;
+use shirabe_semver::constraint::AnyConstraint;
use crate::dependency_resolver::Decisions;
use crate::dependency_resolver::GenericRule;
@@ -189,8 +189,8 @@ impl Solver {
// TODO(phase-b): ConstraintInterface is a PHP class — Box<dyn ConstraintInterface>
// cannot be cloned. We borrow the original constraint and only allocate a fresh
// box when the ignore filter rewrites it.
- let mut filtered: Option<Box<dyn ConstraintInterface>> = None;
- let constraint_ref: &dyn ConstraintInterface = constraint.as_ref();
+ let mut filtered: Option<AnyConstraint> = None;
+ let constraint_ref: &AnyConstraint = constraint;
if platform_requirement_filter.is_ignored(package_name) {
continue;
} else if let Some(ignore_filter) = platform_requirement_filter
@@ -204,8 +204,7 @@ impl Solver {
let _ = &mut filtered;
}
- let active_constraint: &dyn ConstraintInterface =
- filtered.as_deref().unwrap_or(constraint_ref);
+ let active_constraint: &AnyConstraint = filtered.as_ref().unwrap_or(constraint_ref);
if self
.pool