From 42eb2725be0c5e77ca4d6614ac2963f007e25a75 Mon Sep 17 00:00:00 2001 From: 0xPoe Date: Sun, 18 May 2025 21:54:27 +0200 Subject: [PATCH 1/2] refactor: replace InternedString with Cow in IndexPackage Signed-off-by: 0xPoe --- src/cargo/sources/registry/index/mod.rs | 57 ++++++++++++++++--------- 1 file changed, 36 insertions(+), 21 deletions(-) diff --git a/src/cargo/sources/registry/index/mod.rs b/src/cargo/sources/registry/index/mod.rs index eb745142680..c47e393eaf2 100644 --- a/src/cargo/sources/registry/index/mod.rs +++ b/src/cargo/sources/registry/index/mod.rs @@ -198,7 +198,8 @@ impl IndexSummary { #[derive(Deserialize, Serialize)] pub struct IndexPackage<'a> { /// Name of the package. - pub name: InternedString, + #[serde(borrow)] + pub name: Cow<'a, str>, /// The version of this dependency. pub vers: Version, /// All kinds of direct dependencies of the package, including dev and @@ -207,14 +208,14 @@ pub struct IndexPackage<'a> { pub deps: Vec>, /// Set of features defined for the package, i.e., `[features]` table. #[serde(default)] - pub features: BTreeMap>, + pub features: BTreeMap, Vec>>, /// This field contains features with new, extended syntax. Specifically, /// namespaced features (`dep:`) and weak dependencies (`pkg?/feat`). /// /// This is separated from `features` because versions older than 1.19 /// will fail to load due to not being able to parse the new syntax, even /// with a `Cargo.lock` file. - pub features2: Option>>, + pub features2: Option, Vec>>>, /// Checksum for verifying the integrity of the corresponding downloaded package. pub cksum: String, /// If `true`, Cargo will skip this version when resolving. @@ -226,7 +227,7 @@ pub struct IndexPackage<'a> { /// /// Added early 2018 (see ), /// can be `None` if published before then. - pub links: Option, + pub links: Option>, /// Required version of rust /// /// Corresponds to `package.rust-version`. @@ -263,7 +264,11 @@ impl IndexPackage<'_> { fn to_summary(&self, source_id: SourceId) -> CargoResult { // ****CAUTION**** Please be extremely careful with returning errors, see // `IndexSummary::parse` for details - let pkgid = PackageId::new(self.name.into(), self.vers.clone(), source_id); + let pkgid = PackageId::new( + InternedString::new(&self.name), + self.vers.clone(), + source_id, + ); let deps = self .deps .iter() @@ -272,24 +277,31 @@ impl IndexPackage<'_> { let mut features = self.features.clone(); if let Some(features2) = &self.features2 { for (name, values) in features2 { - features.entry(*name).or_default().extend(values); + features + .entry(name.clone()) + .or_default() + .extend(values.iter().cloned()); } } - let mut summary = Summary::new( - pkgid, - deps, - &features, - self.links, - self.rust_version.clone(), - )?; + let features = features + .into_iter() + .map(|(name, values)| { + ( + InternedString::new(&name), + values.iter().map(|v| InternedString::new(&v)).collect(), + ) + }) + .collect::>(); + let links = self.links.as_ref().map(|l| InternedString::new(&l)); + let mut summary = Summary::new(pkgid, deps, &features, links, self.rust_version.clone())?; summary.set_checksum(self.cksum.clone()); Ok(summary) } } #[derive(Deserialize, Serialize)] -struct IndexPackageMinimum { - name: InternedString, +struct IndexPackageMinimum<'a> { + name: Cow<'a, str>, vers: Version, } @@ -308,13 +320,14 @@ struct IndexPackageV { pub struct RegistryDependency<'a> { /// Name of the dependency. If the dependency is renamed, the original /// would be stored in [`RegistryDependency::package`]. - pub name: InternedString, + #[serde(borrow)] + pub name: Cow<'a, str>, /// The SemVer requirement for this dependency. #[serde(borrow)] pub req: Cow<'a, str>, /// Set of features enabled for this dependency. #[serde(default)] - pub features: Vec, + pub features: Vec>, /// Whether or not this is an optional dependency. #[serde(default)] pub optional: bool, @@ -329,7 +342,7 @@ pub struct RegistryDependency<'a> { // `None` if it is from the same index. pub registry: Option>, /// The original name if the dependency is renamed. - pub package: Option, + pub package: Option>, /// Whether or not this is a public dependency. Unstable. See [RFC 1977]. /// /// [RFC 1977]: https://rust-lang.github.io/rfcs/1977-public-private-dependencies.html @@ -759,7 +772,7 @@ impl IndexSummary { Ok((index, summary)) => (index, summary, true), Err(err) => { let Ok(IndexPackageMinimum { name, vers }) = - serde_json::from_slice::(line) + serde_json::from_slice::>(line) else { // If we can't recover, prefer the original error return Err(err); @@ -833,9 +846,10 @@ impl<'a> RegistryDependency<'a> { default }; - let mut dep = Dependency::parse(package.unwrap_or(name), Some(&req), id)?; + let interned_name = InternedString::new(package.as_ref().unwrap_or(&name)); + let mut dep = Dependency::parse(interned_name, Some(&req), id)?; if package.is_some() { - dep.set_explicit_name_in_toml(name); + dep.set_explicit_name_in_toml(InternedString::new(&name)); } let kind = match kind.as_deref().unwrap_or("") { "dev" => DepKind::Development, @@ -869,6 +883,7 @@ impl<'a> RegistryDependency<'a> { dep.set_artifact(artifact); } + let features = features.iter().map(|f| InternedString::new(&f)); dep.set_optional(optional) .set_default_features(default_features) .set_features(features) From 5fe108db8e7ca4fecad29319fd859d12e8ca2588 Mon Sep 17 00:00:00 2001 From: 0xPoe Date: Mon, 26 May 2025 16:17:50 +0200 Subject: [PATCH 2/2] refactor: implement From Cow trait for the InternedString Signed-off-by: 0xPoe --- src/cargo/core/compiler/fingerprint/mod.rs | 2 +- src/cargo/sources/registry/index/mod.rs | 25 ++++++---------------- src/cargo/util/interning.rs | 19 ++++++++-------- 3 files changed, 17 insertions(+), 29 deletions(-) diff --git a/src/cargo/core/compiler/fingerprint/mod.rs b/src/cargo/core/compiler/fingerprint/mod.rs index 1df368ee050..00ba5c4af08 100644 --- a/src/cargo/core/compiler/fingerprint/mod.rs +++ b/src/cargo/core/compiler/fingerprint/mod.rs @@ -694,7 +694,7 @@ impl<'de> Deserialize<'de> for DepFingerprint { let (pkg_id, name, public, hash) = <(u64, String, bool, u64)>::deserialize(d)?; Ok(DepFingerprint { pkg_id, - name: InternedString::new(&name), + name: name.into(), public, fingerprint: Arc::new(Fingerprint { memoized_hash: Mutex::new(Some(hash)), diff --git a/src/cargo/sources/registry/index/mod.rs b/src/cargo/sources/registry/index/mod.rs index c47e393eaf2..14fb276fcd6 100644 --- a/src/cargo/sources/registry/index/mod.rs +++ b/src/cargo/sources/registry/index/mod.rs @@ -264,35 +264,23 @@ impl IndexPackage<'_> { fn to_summary(&self, source_id: SourceId) -> CargoResult { // ****CAUTION**** Please be extremely careful with returning errors, see // `IndexSummary::parse` for details - let pkgid = PackageId::new( - InternedString::new(&self.name), - self.vers.clone(), - source_id, - ); + let pkgid = PackageId::new(self.name.as_ref().into(), self.vers.clone(), source_id); let deps = self .deps .iter() .map(|dep| dep.clone().into_dep(source_id)) .collect::>>()?; let mut features = self.features.clone(); - if let Some(features2) = &self.features2 { + if let Some(features2) = self.features2.clone() { for (name, values) in features2 { - features - .entry(name.clone()) - .or_default() - .extend(values.iter().cloned()); + features.entry(name).or_default().extend(values); } } let features = features .into_iter() - .map(|(name, values)| { - ( - InternedString::new(&name), - values.iter().map(|v| InternedString::new(&v)).collect(), - ) - }) + .map(|(name, values)| (name.into(), values.into_iter().map(|v| v.into()).collect())) .collect::>(); - let links = self.links.as_ref().map(|l| InternedString::new(&l)); + let links: Option = self.links.as_ref().map(|l| l.as_ref().into()); let mut summary = Summary::new(pkgid, deps, &features, links, self.rust_version.clone())?; summary.set_checksum(self.cksum.clone()); Ok(summary) @@ -849,7 +837,7 @@ impl<'a> RegistryDependency<'a> { let interned_name = InternedString::new(package.as_ref().unwrap_or(&name)); let mut dep = Dependency::parse(interned_name, Some(&req), id)?; if package.is_some() { - dep.set_explicit_name_in_toml(InternedString::new(&name)); + dep.set_explicit_name_in_toml(name); } let kind = match kind.as_deref().unwrap_or("") { "dev" => DepKind::Development, @@ -883,7 +871,6 @@ impl<'a> RegistryDependency<'a> { dep.set_artifact(artifact); } - let features = features.iter().map(|f| InternedString::new(&f)); dep.set_optional(optional) .set_default_features(default_features) .set_features(features) diff --git a/src/cargo/util/interning.rs b/src/cargo/util/interning.rs index 61ecae54ea7..37a47d422e0 100644 --- a/src/cargo/util/interning.rs +++ b/src/cargo/util/interning.rs @@ -47,7 +47,7 @@ impl<'a> From<&'a String> for InternedString { impl From for InternedString { fn from(item: String) -> Self { - InternedString::from_cow(item.into()) + InternedString::from(Cow::Owned(item)) } } @@ -69,14 +69,8 @@ impl<'a> PartialEq<&'a str> for InternedString { } } -impl Eq for InternedString {} - -impl InternedString { - pub fn new(s: &str) -> InternedString { - InternedString::from_cow(s.into()) - } - - fn from_cow<'a>(cs: Cow<'a, str>) -> InternedString { +impl<'a> From> for InternedString { + fn from(cs: Cow<'a, str>) -> Self { let mut cache = interned_storage(); let s = cache.get(cs.as_ref()).copied().unwrap_or_else(|| { let s = cs.into_owned().leak(); @@ -86,7 +80,14 @@ impl InternedString { InternedString { inner: s } } +} + +impl Eq for InternedString {} +impl InternedString { + pub fn new(s: &str) -> InternedString { + InternedString::from(Cow::Borrowed(s)) + } pub fn as_str(&self) -> &'static str { self.inner }