diff --git a/src/cargo/core/dependency.rs b/src/cargo/core/dependency.rs index 262c3753874..975238e66dd 100644 --- a/src/cargo/core/dependency.rs +++ b/src/cargo/core/dependency.rs @@ -11,7 +11,7 @@ use serde::Serialize; use crate::core::interning::InternedString; use crate::core::{PackageId, SourceId, Summary}; use crate::util::errors::{CargoResult, CargoResultExt}; -use crate::util::{Cfg, CfgExpr, Config}; +use crate::util::{Cfg, CfgExpr, Config, SemVersionReq, ToSemverReq}; /// Information about a dependency requested by a Cargo manifest. /// Cheap to copy. @@ -26,7 +26,7 @@ struct Inner { name: InternedString, source_id: SourceId, registry_id: Option, - req: VersionReq, + req: SemVersionReq, specified_req: bool, kind: Kind, only_match_name: bool, @@ -92,8 +92,8 @@ fn parse_req_with_deprecated( name: &str, req: &str, extra: Option<(PackageId, &Config)>, -) -> CargoResult { - match VersionReq::parse(req) { +) -> CargoResult { + match req.to_semver_req() { Err(ReqParseError::DeprecatedVersionRequirement(requirement)) => { let (inside, config) = match extra { Some(pair) => pair, @@ -118,11 +118,11 @@ this warning. ); config.shell().warn(&msg)?; - Ok(requirement) + Ok(SemVersionReq::new(requirement)) } Err(e) => { - let err: CargoResult = Err(e.into()); - let v: VersionReq = err.chain_err(|| { + let err: CargoResult = Err(e.into()); + let v: SemVersionReq = err.chain_err(|| { format!( "failed to parse the version requirement `{}` for dependency `{}`", req, name @@ -160,7 +160,7 @@ impl Dependency { let arg = Some((inside, config)); let (specified_req, version_req) = match version { Some(v) => (true, parse_req_with_deprecated(name, v, arg)?), - None => (false, VersionReq::any()), + None => (false, SemVersionReq::any()), }; let mut ret = Dependency::new_override(name, source_id); @@ -181,7 +181,7 @@ impl Dependency { ) -> CargoResult { let (specified_req, version_req) = match version { Some(v) => (true, parse_req_with_deprecated(name, v, None)?), - None => (false, VersionReq::any()), + None => (false, SemVersionReq::any()), }; let mut ret = Dependency::new_override(name, source_id); @@ -201,7 +201,7 @@ impl Dependency { name: InternedString::new(name), source_id, registry_id: None, - req: VersionReq::any(), + req: SemVersionReq::any(), kind: Kind::Normal, only_match_name: true, optional: false, @@ -215,7 +215,7 @@ impl Dependency { } pub fn version_req(&self) -> &VersionReq { - &self.inner.req + &self.inner.req.value() } /// This is the name of this `Dependency` as listed in `Cargo.toml`. @@ -335,7 +335,7 @@ impl Dependency { } /// Set the version requirement for this dependency - pub fn set_version_req(&mut self, req: VersionReq) -> &mut Dependency { + pub fn set_version_req(&mut self, req: SemVersionReq) -> &mut Dependency { Rc::make_mut(&mut self.inner).req = req; self } @@ -353,7 +353,7 @@ impl Dependency { /// Lock this dependency to depending on the specified package id pub fn lock_to(&mut self, id: PackageId) -> &mut Dependency { assert_eq!(self.inner.source_id, id.source_id()); - assert!(self.inner.req.matches(id.version())); + assert!(self.inner.req.value().matches(id.version())); trace!( "locking dep from `{}` with `{}` at {} to {}", self.package_name(), @@ -361,7 +361,7 @@ impl Dependency { self.source_id(), id ); - self.set_version_req(VersionReq::exact(id.version())) + self.set_version_req(SemVersionReq::exact(id.sem_version())) .set_source_id(id.source_id()) } @@ -414,7 +414,7 @@ impl Dependency { pub fn matches_id(&self, id: PackageId) -> bool { self.inner.name == id.name() && (self.inner.only_match_name - || (self.inner.req.matches(id.version()) && self.inner.source_id == id.source_id())) + || (self.inner.req.value().matches(id.version()) && self.inner.source_id == id.source_id())) } pub fn map_source(mut self, to_replace: SourceId, replace_with: SourceId) -> Dependency { diff --git a/src/cargo/core/package_id.rs b/src/cargo/core/package_id.rs index 784a3491573..c380c00fa53 100644 --- a/src/cargo/core/package_id.rs +++ b/src/cargo/core/package_id.rs @@ -12,7 +12,7 @@ use serde::ser; use crate::core::interning::InternedString; use crate::core::source::SourceId; -use crate::util::{CargoResult, ToSemver}; +use crate::util::{CargoResult, SemVersion, ToSemver}; lazy_static::lazy_static! { static ref PACKAGE_ID_CACHE: Mutex> = @@ -28,7 +28,7 @@ pub struct PackageId { #[derive(PartialOrd, Eq, Ord)] struct PackageIdInner { name: InternedString, - version: semver::Version, + version: SemVersion, source_id: SourceId, } @@ -76,7 +76,7 @@ impl<'de> de::Deserialize<'de> for PackageId { Some(s) => s, None => return Err(de::Error::custom("invalid serialized PackageId")), }; - let version = semver::Version::parse(version).map_err(de::Error::custom)?; + let version = version.to_semver().map_err(de::Error::custom)?; let url = match s.next() { Some(s) => s, None => return Err(de::Error::custom("invalid serialized PackageId")), @@ -88,11 +88,7 @@ impl<'de> de::Deserialize<'de> for PackageId { }; let source_id = SourceId::from_url(url).map_err(de::Error::custom)?; - Ok(PackageId::wrap(PackageIdInner { - name: InternedString::new(name), - version, - source_id, - })) + Ok(PackageId::pure(InternedString::new(name), version, source_id)) } } @@ -116,17 +112,14 @@ impl<'a> Hash for PackageId { } impl PackageId { - pub fn new(name: &str, version: T, sid: SourceId) -> CargoResult { - let v = version.to_semver()?; - - Ok(PackageId::wrap(PackageIdInner { - name: InternedString::new(name), - version: v, - source_id: sid, - })) + pub fn new(name: &str, version: V, source_id: SourceId) -> CargoResult { + let version = version.to_semver()?; + let name = InternedString::new(name); + Ok(PackageId::pure(name, version, source_id)) } - fn wrap(inner: PackageIdInner) -> PackageId { + pub fn pure(name: InternedString, version: SemVersion, source_id: SourceId) -> PackageId { + let inner = PackageIdInner { name, version, source_id }; let mut cache = PACKAGE_ID_CACHE.lock().unwrap(); let inner = cache.get(&inner).cloned().unwrap_or_else(|| { let inner = Box::leak(Box::new(inner)); @@ -140,26 +133,29 @@ impl PackageId { self.inner.name } pub fn version(self) -> &'static semver::Version { - &self.inner.version + self.inner.version.value() + } + pub fn sem_version(self) -> SemVersion { + self.inner.version } pub fn source_id(self) -> SourceId { self.inner.source_id } pub fn with_precise(self, precise: Option) -> PackageId { - PackageId::wrap(PackageIdInner { - name: self.inner.name, - version: self.inner.version.clone(), - source_id: self.inner.source_id.with_precise(precise), - }) + PackageId::pure( + self.inner.name, + self.inner.version.clone(), + self.inner.source_id.with_precise(precise), + ) } pub fn with_source_id(self, source: SourceId) -> PackageId { - PackageId::wrap(PackageIdInner { - name: self.inner.name, - version: self.inner.version.clone(), - source_id: source, - }) + PackageId::pure( + self.inner.name, + self.inner.version.clone(), + source + ) } pub fn stable_hash(self, workspace: &Path) -> PackageIdStableHash<'_> { diff --git a/src/cargo/core/package_id_spec.rs b/src/cargo/core/package_id_spec.rs index a2cb6171b80..2a91cdce920 100644 --- a/src/cargo/core/package_id_spec.rs +++ b/src/cargo/core/package_id_spec.rs @@ -1,13 +1,12 @@ use std::collections::HashMap; use std::fmt; -use semver::Version; use serde::{de, ser}; use url::Url; use crate::core::PackageId; use crate::util::errors::{CargoResult, CargoResultExt}; -use crate::util::{validate_package_name, ToSemver, ToUrl}; +use crate::util::{validate_package_name, SemVersion, ToSemver, ToUrl}; /// Some or all of the data required to identify a package: /// @@ -21,7 +20,7 @@ use crate::util::{validate_package_name, ToSemver, ToUrl}; #[derive(Clone, PartialEq, Eq, Debug, Hash, Ord, PartialOrd)] pub struct PackageIdSpec { name: String, - version: Option, + version: Option, url: Option, } @@ -61,7 +60,7 @@ impl PackageIdSpec { let mut parts = spec.splitn(2, ':'); let name = parts.next().unwrap(); let version = match parts.next() { - Some(version) => Some(Version::parse(version)?), + Some(version) => Some(version.to_semver()?), None => None, }; validate_package_name(name, "pkgid", "")?; @@ -87,7 +86,7 @@ impl PackageIdSpec { pub fn from_package_id(package_id: PackageId) -> PackageIdSpec { PackageIdSpec { name: package_id.name().to_string(), - version: Some(package_id.version().clone()), + version: Some(package_id.sem_version()), url: Some(package_id.source_id().url().clone()), } } @@ -143,8 +142,8 @@ impl PackageIdSpec { &self.name } - pub fn version(&self) -> Option<&Version> { - self.version.as_ref() + pub fn version(&self) -> Option { + self.version } pub fn url(&self) -> Option<&Url> { @@ -162,7 +161,7 @@ impl PackageIdSpec { } if let Some(ref v) = self.version { - if v != package_id.version() { + if v != &package_id.sem_version() { return false; } } @@ -274,7 +273,7 @@ impl<'de> de::Deserialize<'de> for PackageIdSpec { mod tests { use super::PackageIdSpec; use crate::core::{PackageId, SourceId}; - use semver::Version; + use crate::util::ToSemver; use url::Url; #[test] @@ -289,7 +288,7 @@ mod tests { "http://crates.io/foo#1.2.3", PackageIdSpec { name: "foo".to_string(), - version: Some(Version::parse("1.2.3").unwrap()), + version: Some("1.2.3".to_semver().unwrap()), url: Some(Url::parse("http://crates.io/foo").unwrap()), }, ); @@ -297,7 +296,7 @@ mod tests { "http://crates.io/foo#bar:1.2.3", PackageIdSpec { name: "bar".to_string(), - version: Some(Version::parse("1.2.3").unwrap()), + version: Some("1.2.3".to_semver().unwrap()), url: Some(Url::parse("http://crates.io/foo").unwrap()), }, ); @@ -313,7 +312,7 @@ mod tests { "crates.io/foo#1.2.3", PackageIdSpec { name: "foo".to_string(), - version: Some(Version::parse("1.2.3").unwrap()), + version: Some("1.2.3".to_semver().unwrap()), url: Some(Url::parse("cargo://crates.io/foo").unwrap()), }, ); @@ -329,7 +328,7 @@ mod tests { "crates.io/foo#bar:1.2.3", PackageIdSpec { name: "bar".to_string(), - version: Some(Version::parse("1.2.3").unwrap()), + version: Some("1.2.3".to_semver().unwrap()), url: Some(Url::parse("cargo://crates.io/foo").unwrap()), }, ); @@ -345,7 +344,7 @@ mod tests { "foo:1.2.3", PackageIdSpec { name: "foo".to_string(), - version: Some(Version::parse("1.2.3").unwrap()), + version: Some("1.2.3".to_semver().unwrap()), url: None, }, ); diff --git a/src/cargo/core/registry.rs b/src/cargo/core/registry.rs index 533b4cb0b72..dd2a936ae1d 100644 --- a/src/cargo/core/registry.rs +++ b/src/cargo/core/registry.rs @@ -1,14 +1,13 @@ use std::collections::HashMap; use log::{debug, trace}; -use semver::VersionReq; use url::Url; use crate::core::PackageSet; use crate::core::{Dependency, PackageId, Source, SourceId, SourceMap, Summary}; use crate::sources::config::SourceConfigMap; use crate::util::errors::{CargoResult, CargoResultExt}; -use crate::util::{profile, Config}; +use crate::util::{profile, Config, SemVersionReq}; /// Source of information about a group of packages. /// @@ -645,7 +644,7 @@ fn lock(locked: &LockedMap, patches: &HashMap>, summary: Sum if patch_locked { trace!("\tthird hit on {}", patch_id); - let req = VersionReq::exact(patch_id.version()); + let req = SemVersionReq::exact(patch_id.sem_version()); let mut dep = dep; dep.set_version_req(req); return dep; diff --git a/src/cargo/core/resolver/errors.rs b/src/cargo/core/resolver/errors.rs index 217523e8655..e6a357eee53 100644 --- a/src/cargo/core/resolver/errors.rs +++ b/src/cargo/core/resolver/errors.rs @@ -3,9 +3,8 @@ use std::fmt; use crate::core::{Dependency, PackageId, Registry, Summary}; use crate::util::lev_distance::lev_distance; -use crate::util::Config; +use crate::util::{Config, ToSemverReq}; use failure::{Error, Fail}; -use semver; use super::context::Context; use super::types::{Candidate, ConflictReason}; @@ -170,7 +169,7 @@ pub(super) fn activation_error( // Maybe the user mistyped the ver_req? Like `dep="2"` when `dep="0.2"` // was meant. So we re-query the registry with `deb="*"` so we can // list a few versions that were actually found. - let all_req = semver::VersionReq::parse("*").unwrap(); + let all_req = "*".to_semver_req().unwrap(); let mut new_dep = dep.clone(); new_dep.set_version_req(all_req); let mut candidates = match registry.query_vec(&new_dep, false) { diff --git a/src/cargo/ops/cargo_install.rs b/src/cargo/ops/cargo_install.rs index dd1523a1ee0..e4627e34e45 100644 --- a/src/cargo/ops/cargo_install.rs +++ b/src/cargo/ops/cargo_install.rs @@ -6,7 +6,6 @@ use std::path::{Path, PathBuf}; use std::sync::Arc; use std::{env, fs}; -use semver::{Version, VersionReq}; use serde::{Deserialize, Serialize}; use tempfile::Builder as TempFileBuilder; @@ -19,7 +18,7 @@ use crate::ops::{self, CompileFilter}; use crate::sources::{GitSource, PathSource, SourceConfigMap}; use crate::util::errors::{CargoResult, CargoResultExt}; use crate::util::paths; -use crate::util::{internal, Config}; +use crate::util::{internal, Config, ToSemver, ToSemverReq}; use crate::util::{FileLock, Filesystem}; #[derive(Deserialize, Serialize)] @@ -445,7 +444,7 @@ where })?; match first { - '<' | '>' | '=' | '^' | '~' => match v.parse::() { + '<' | '>' | '=' | '^' | '~' => match v.to_semver_req() { Ok(v) => Some(v.to_string()), Err(_) => failure::bail!( "the `--vers` provided, `{}`, is \ @@ -456,7 +455,7 @@ where v ), }, - _ => match v.parse::() { + _ => match v.to_semver() { Ok(v) => Some(format!("={}", v)), Err(_) => { let mut msg = format!( @@ -473,7 +472,7 @@ where // If it is not a valid version but it is a valid version // requirement, add a note to the warning - if v.parse::().is_ok() { + if v.to_semver_req().is_ok() { msg.push_str(&format!( "\nif you want to specify semver range, \ add an explicit qualifier, like ^{}", diff --git a/src/cargo/sources/registry/index.rs b/src/cargo/sources/registry/index.rs index 353115535c4..ffd98826c29 100644 --- a/src/cargo/sources/registry/index.rs +++ b/src/cargo/sources/registry/index.rs @@ -3,13 +3,12 @@ use std::path::Path; use std::str; use log::{info, trace}; -use semver::Version; use crate::core::dependency::Dependency; use crate::core::{PackageId, SourceId, Summary}; use crate::sources::registry::RegistryData; use crate::sources::registry::{RegistryPackage, INDEX_LOCK}; -use crate::util::{internal, CargoResult, Config, Filesystem}; +use crate::util::{internal, CargoResult, Config, Filesystem, SemVersion, ToSemver}; /// Crates.io treats hyphen and underscores as interchangeable /// but, the index and old cargo do not. So the index must store uncanonicalized version @@ -101,7 +100,7 @@ pub struct RegistryIndex<'cfg> { source_id: SourceId, path: Filesystem, cache: HashMap<&'static str, Vec<(Summary, bool)>>, - hashes: HashMap<&'static str, HashMap>, // (name, vers) => cksum + hashes: HashMap<&'static str, HashMap>, // (name, vers) => cksum config: &'cfg Config, locked: bool, } @@ -126,7 +125,7 @@ impl<'cfg> RegistryIndex<'cfg> { /// Return the hash listed for a specified PackageId. pub fn hash(&mut self, pkg: PackageId, load: &mut dyn RegistryData) -> CargoResult { let name = pkg.name().as_str(); - let version = pkg.version(); + let version = &pkg.sem_version(); if let Some(s) = self.hashes.get(name).and_then(|v| v.get(version)) { return Ok(s.clone()); } @@ -254,7 +253,8 @@ impl<'cfg> RegistryIndex<'cfg> { yanked, links, } = serde_json::from_str(line)?; - let pkgid = PackageId::new(&name, &vers, self.source_id)?; + let vers = SemVersion::new(vers); + let pkgid = PackageId::new(&name, vers, self.source_id)?; let name = pkgid.name(); let deps = deps .into_iter() @@ -293,7 +293,7 @@ impl<'cfg> RegistryIndex<'cfg> { let mut vers = p[name.len() + 1..].splitn(2, "->"); if dep .version_req() - .matches(&Version::parse(vers.next().unwrap()).unwrap()) + .matches(vers.next().unwrap().to_semver().unwrap().value()) { vers.next().unwrap() == s.version().to_string() } else { diff --git a/src/cargo/util/mod.rs b/src/cargo/util/mod.rs index 2860133445e..5aacf3d8ea3 100644 --- a/src/cargo/util/mod.rs +++ b/src/cargo/util/mod.rs @@ -19,7 +19,7 @@ pub use self::progress::{Progress, ProgressStyle}; pub use self::read2::read2; pub use self::rustc::Rustc; pub use self::sha256::Sha256; -pub use self::to_semver::ToSemver; +pub use self::to_semver::{SemVersion, SemVersionReq, ToSemver, ToSemverReq}; pub use self::to_url::ToUrl; pub use self::vcs::{existing_vcs_repo, FossilRepo, GitRepo, HgRepo, PijulRepo}; diff --git a/src/cargo/util/to_semver.rs b/src/cargo/util/to_semver.rs index 65cc078fd29..dfa7859ffc2 100644 --- a/src/cargo/util/to_semver.rs +++ b/src/cargo/util/to_semver.rs @@ -1,33 +1,171 @@ +use std::collections::HashSet; +use std::fmt; +use std::ptr; +use std::sync::Mutex; + +use semver::{Version, VersionReq}; +use semver::ReqParseError; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + use crate::util::errors::CargoResult; -use semver::Version; + +lazy_static::lazy_static! { + static ref SEM_VERSION_CACHE: Mutex> = + Mutex::new(HashSet::new()); + static ref SEM_VERSION_REQ_CACHE: Mutex> = + Mutex::new(HashSet::new()); +} + +#[derive(Clone, Copy, Eq, Hash, PartialOrd, Ord)] +pub struct SemVersion { + inner: &'static Version, +} + +impl SemVersion { + pub fn new(version: Version) -> SemVersion { + let mut cache = SEM_VERSION_CACHE.lock().unwrap(); + let version = cache.get(&version).cloned().unwrap_or_else(|| { + let version = Box::leak(Box::new(version)); + cache.insert(version); + version + }); + SemVersion { inner: version } + } + + pub fn value(&self) -> &'static Version { + self.inner + } +} + +impl PartialEq for SemVersion { + fn eq(&self, other: &SemVersion) -> bool { + ptr::eq(self.inner, other.inner) + } +} + +impl Serialize for SemVersion { + fn serialize(&self, ser: S) -> Result where S: Serializer { + self.inner.serialize(ser) + } +} + +impl<'de> Deserialize<'de> for SemVersion { + fn deserialize(de: D) -> Result where D: Deserializer<'de> { + Ok(SemVersion::new(::deserialize(de)?)) + } +} + +impl fmt::Debug for SemVersion { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(self.inner, f) + } +} + +impl fmt::Display for SemVersion { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self.inner, f) + } +} + pub trait ToSemver { - fn to_semver(self) -> CargoResult; + fn to_semver(self) -> CargoResult; } -impl ToSemver for Version { - fn to_semver(self) -> CargoResult { +impl ToSemver for SemVersion { + fn to_semver(self) -> CargoResult { Ok(self) } } impl<'a> ToSemver for &'a str { - fn to_semver(self) -> CargoResult { + fn to_semver(self) -> CargoResult { match Version::parse(self) { - Ok(v) => Ok(v), + Ok(v) => Ok(SemVersion::new(v)), Err(..) => Err(failure::format_err!("cannot parse '{}' as a semver", self)), } } } impl<'a> ToSemver for &'a String { - fn to_semver(self) -> CargoResult { + fn to_semver(self) -> CargoResult { (**self).to_semver() } } -impl<'a> ToSemver for &'a Version { - fn to_semver(self) -> CargoResult { +impl<'a> ToSemver for &'a SemVersion { + fn to_semver(self) -> CargoResult { Ok(self.clone()) } } + + +#[derive(Clone, Copy, Eq, Hash, PartialOrd, Ord)] +pub struct SemVersionReq { + inner: &'static VersionReq, +} + +impl SemVersionReq { + pub fn new(req: VersionReq) -> SemVersionReq { + let mut cache = SEM_VERSION_REQ_CACHE.lock().unwrap(); + let req = cache.get(&req).cloned().unwrap_or_else(|| { + let req = Box::leak(Box::new(req)); + cache.insert(req); + req + }); + SemVersionReq { inner: req } + } + + pub fn any() -> SemVersionReq { + SemVersionReq::new(VersionReq::any()) + } + + pub fn exact(version: SemVersion) -> SemVersionReq { + SemVersionReq::new(VersionReq::exact(version.inner)) + } + + pub fn value(&self) -> &'static VersionReq { + self.inner + } +} + +impl PartialEq for SemVersionReq { + fn eq(&self, other: &SemVersionReq) -> bool { + ptr::eq(self.inner, other.inner) + } +} + +impl Serialize for SemVersionReq { + fn serialize(&self, ser: S) -> Result where S: Serializer { + self.inner.serialize(ser) + } +} + +impl<'de> Deserialize<'de> for SemVersionReq { + fn deserialize(de: D) -> Result where D: Deserializer<'de> { + Ok(SemVersionReq::new(::deserialize(de)?)) + } +} + +impl fmt::Debug for SemVersionReq { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(self.inner, f) + } +} + +impl fmt::Display for SemVersionReq { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self.inner, f) + } +} + + +pub trait ToSemverReq { + fn to_semver_req(self) -> Result; +} + +impl<'a> ToSemverReq for &'a str { + fn to_semver_req(self) -> Result { + Ok(SemVersionReq::new(VersionReq::parse(self)?)) + } +} diff --git a/src/cargo/util/toml/mod.rs b/src/cargo/util/toml/mod.rs index 53e0d7ad8b3..379ea314761 100644 --- a/src/cargo/util/toml/mod.rs +++ b/src/cargo/util/toml/mod.rs @@ -6,7 +6,6 @@ use std::rc::Rc; use std::str; use log::{debug, trace}; -use semver::{self, VersionReq}; use serde::de; use serde::ser; use serde::{Deserialize, Serialize}; @@ -21,7 +20,7 @@ use crate::core::{GitReference, PackageIdSpec, SourceId, WorkspaceConfig, Worksp use crate::sources::{CRATES_IO_INDEX, CRATES_IO_REGISTRY}; use crate::util::errors::{CargoResult, CargoResultExt, ManifestError}; use crate::util::paths; -use crate::util::{self, validate_package_name, Config, ToUrl}; +use crate::util::{self, validate_package_name, Config, SemVersion, SemVersionReq, ToUrl}; mod targets; use self::targets::targets; @@ -615,7 +614,7 @@ impl<'de> de::Deserialize<'de> for VecStringOrBool { pub struct TomlProject { edition: Option, name: String, - version: semver::Version, + version: SemVersion, authors: Option>, build: Option, metabuild: Option, @@ -1181,7 +1180,7 @@ impl TomlManifest { spec ) })?; - dep.set_version_req(VersionReq::exact(version)); + dep.set_version_req(SemVersionReq::exact(version)); } replace.push((spec, dep)); }