Skip to content

Commit 1ff5975

Browse files
committed
Auto merge of #6342 - dwijnand:intern-SourceId, r=Eh2406
Intern SourceId Refs #6207 sibling of #6332
2 parents 99bea3b + 9b22eb1 commit 1ff5975

File tree

2 files changed

+46
-37
lines changed

2 files changed

+46
-37
lines changed

src/cargo/core/source/source_id.rs

Lines changed: 44 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
use std::cmp::{self, Ordering};
2+
use std::collections::HashSet;
23
use std::fmt::{self, Formatter};
34
use std::hash::{self, Hash};
45
use std::path::Path;
5-
use std::sync::Arc;
6+
use std::ptr;
7+
use std::sync::Mutex;
68
use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT};
79
use std::sync::atomic::Ordering::SeqCst;
810

@@ -16,13 +18,17 @@ use sources::{GitSource, PathSource, RegistrySource, CRATES_IO_INDEX};
1618
use sources::DirectorySource;
1719
use util::{CargoResult, Config, ToUrl};
1820

21+
lazy_static! {
22+
static ref SOURCE_ID_CACHE: Mutex<HashSet<&'static SourceIdInner>> = Mutex::new(HashSet::new());
23+
}
24+
1925
/// Unique identifier for a source of packages.
20-
#[derive(Clone, Eq, Debug)]
26+
#[derive(Clone, Copy, Eq, Debug)]
2127
pub struct SourceId {
22-
inner: Arc<SourceIdInner>,
28+
inner: &'static SourceIdInner,
2329
}
2430

25-
#[derive(Eq, Clone, Debug)]
31+
#[derive(PartialEq, Eq, Clone, Debug, Hash)]
2632
struct SourceIdInner {
2733
/// The source URL
2834
url: Url,
@@ -68,18 +74,28 @@ impl SourceId {
6874
///
6975
/// The canonical url will be calculated, but the precise field will not
7076
fn new(kind: Kind, url: Url) -> CargoResult<SourceId> {
71-
let source_id = SourceId {
72-
inner: Arc::new(SourceIdInner {
77+
let source_id = SourceId::wrap(
78+
SourceIdInner {
7379
kind,
7480
canonical_url: git::canonicalize_url(&url)?,
7581
url,
7682
precise: None,
7783
name: None,
78-
}),
79-
};
84+
}
85+
);
8086
Ok(source_id)
8187
}
8288

89+
fn wrap(inner: SourceIdInner) -> SourceId {
90+
let mut cache = SOURCE_ID_CACHE.lock().unwrap();
91+
let inner = cache.get(&inner).map(|&x| x).unwrap_or_else(|| {
92+
let inner = Box::leak(Box::new(inner));
93+
cache.insert(inner);
94+
inner
95+
});
96+
SourceId { inner }
97+
}
98+
8399
/// Parses a source URL and returns the corresponding ID.
84100
///
85101
/// ## Example
@@ -193,15 +209,15 @@ impl SourceId {
193209

194210
pub fn alt_registry(config: &Config, key: &str) -> CargoResult<SourceId> {
195211
let url = config.get_registry_index(key)?;
196-
Ok(SourceId {
197-
inner: Arc::new(SourceIdInner {
212+
Ok(SourceId::wrap(
213+
SourceIdInner {
198214
kind: Kind::Registry,
199215
canonical_url: git::canonicalize_url(&url)?,
200216
url,
201217
precise: None,
202218
name: Some(key.to_string()),
203-
}),
204-
})
219+
}
220+
))
205221
}
206222

207223
/// Get this source URL
@@ -288,12 +304,12 @@ impl SourceId {
288304

289305
/// Create a new SourceId from this source with the given `precise`
290306
pub fn with_precise(&self, v: Option<String>) -> SourceId {
291-
SourceId {
292-
inner: Arc::new(SourceIdInner {
307+
SourceId::wrap(
308+
SourceIdInner {
293309
precise: v,
294310
..(*self.inner).clone()
295-
}),
296-
}
311+
}
312+
)
297313
}
298314

299315
/// Whether the remote registry is the standard https://crates.io
@@ -326,12 +342,6 @@ impl SourceId {
326342
}
327343
}
328344

329-
impl PartialEq for SourceId {
330-
fn eq(&self, other: &SourceId) -> bool {
331-
(*self.inner).eq(&*other.inner)
332-
}
333-
}
334-
335345
impl PartialOrd for SourceId {
336346
fn partial_cmp(&self, other: &SourceId) -> Option<Ordering> {
337347
Some(self.cmp(other))
@@ -425,24 +435,23 @@ impl fmt::Display for SourceId {
425435
}
426436
}
427437

428-
// This custom implementation handles situations such as when two git sources
429-
// point at *almost* the same URL, but not quite, even when they actually point
430-
// to the same repository.
431-
/// This method tests for self and other values to be equal, and is used by ==.
432-
///
433-
/// For git repositories, the canonical url is checked.
434-
impl PartialEq for SourceIdInner {
435-
fn eq(&self, other: &SourceIdInner) -> bool {
436-
if self.kind != other.kind {
438+
// Custom equality defined as canonical URL equality for git sources and
439+
// URL equality for other sources, ignoring the `precise` and `name` fields.
440+
impl PartialEq for SourceId {
441+
fn eq(&self, other: &SourceId) -> bool {
442+
if ptr::eq(self.inner, other.inner) {
443+
return true;
444+
}
445+
if self.inner.kind != other.inner.kind {
437446
return false;
438447
}
439-
if self.url == other.url {
448+
if self.inner.url == other.inner.url {
440449
return true;
441450
}
442451

443-
match (&self.kind, &other.kind) {
444-
(&Kind::Git(ref ref1), &Kind::Git(ref ref2)) => {
445-
ref1 == ref2 && self.canonical_url == other.canonical_url
452+
match (&self.inner.kind, &other.inner.kind) {
453+
(Kind::Git(ref1), Kind::Git(ref2)) => {
454+
ref1 == ref2 && self.inner.canonical_url == other.inner.canonical_url
446455
}
447456
_ => false,
448457
}

src/cargo/ops/resolve.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ pub fn resolve_with_previous<'a, 'cfg>(
150150
//
151151
// TODO: This seems like a hokey reason to single out the registry as being
152152
// different
153-
let mut to_avoid_sources = HashSet::new();
153+
let mut to_avoid_sources: HashSet<&SourceId> = HashSet::new();
154154
if let Some(to_avoid) = to_avoid {
155155
to_avoid_sources.extend(
156156
to_avoid
@@ -161,7 +161,7 @@ pub fn resolve_with_previous<'a, 'cfg>(
161161
}
162162

163163
let keep = |p: &&'a PackageId| {
164-
!to_avoid_sources.contains(&p.source_id()) && match to_avoid {
164+
!to_avoid_sources.contains(p.source_id()) && match to_avoid {
165165
Some(set) => !set.contains(p),
166166
None => true,
167167
}

0 commit comments

Comments
 (0)