Skip to content

Commit 77c11a1

Browse files
committed
Auto merge of #147 - Amanieu:spec, r=Amanieu
Future-proof specialization code As per @Centril's [comment](rust-lang/rust#70052 (comment))
2 parents d2414e4 + 3ca10cb commit 77c11a1

File tree

3 files changed

+42
-30
lines changed

3 files changed

+42
-30
lines changed

src/macros.rs

+15
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,18 @@ macro_rules! cfg_if {
5252
$(#[$m] $it)*
5353
};
5454
}
55+
56+
// Helper macro for specialization. This also helps avoid parse errors if the
57+
// default fn syntax for specialization changes in the future.
58+
#[cfg(feature = "nightly")]
59+
macro_rules! default_fn {
60+
($($tt:tt)*) => {
61+
default $($tt)*
62+
}
63+
}
64+
#[cfg(not(feature = "nightly"))]
65+
macro_rules! default_fn {
66+
($($tt:tt)*) => {
67+
$($tt)*
68+
}
69+
}

src/map.rs

+23-21
Original file line numberDiff line numberDiff line change
@@ -206,32 +206,34 @@ impl<K: Clone, V: Clone, S: Clone> Clone for HashMap<K, V, S> {
206206
// want the table to have elements hashed with the wrong hash_builder.
207207
let hash_builder = source.hash_builder.clone();
208208

209-
#[cfg(not(feature = "nightly"))]
210-
{
211-
self.table.clone_from(&source.table);
212-
}
213-
#[cfg(feature = "nightly")]
214-
{
215-
trait HashClone<S> {
216-
fn clone_from(&mut self, source: &Self, hash_builder: &S);
217-
}
218-
impl<K: Clone, V: Clone, S> HashClone<S> for HashMap<K, V, S> {
219-
default fn clone_from(&mut self, source: &Self, _hash_builder: &S) {
209+
// For backward-compatibility reasons we can't make the Clone impl
210+
// depend on K: Hash + Eq and S: BuildHasher. However we can exploit
211+
// this using specialization, which allows us to reuse the existing
212+
// storage of the current HashMap to insert the cloned elements into.
213+
trait HashClone<S> {
214+
fn clone_from(&mut self, source: &Self, hash_builder: &S);
215+
}
216+
impl<K: Clone, V: Clone, S> HashClone<S> for HashMap<K, V, S> {
217+
#[cfg_attr(feature = "inline-more", inline)]
218+
default_fn! {
219+
fn clone_from(&mut self, source: &Self, _hash_builder: &S) {
220220
self.table.clone_from(&source.table);
221221
}
222222
}
223-
impl<K: Clone, V: Clone, S> HashClone<S> for HashMap<K, V, S>
224-
where
225-
K: Eq + Hash,
226-
S: BuildHasher,
227-
{
228-
fn clone_from(&mut self, source: &Self, hash_builder: &S) {
229-
self.table
230-
.clone_from_with_hasher(&source.table, |x| make_hash(hash_builder, &x.0));
231-
}
223+
}
224+
#[cfg(feature = "nightly")]
225+
impl<K: Clone, V: Clone, S> HashClone<S> for HashMap<K, V, S>
226+
where
227+
K: Eq + Hash,
228+
S: BuildHasher,
229+
{
230+
#[cfg_attr(feature = "inline-more", inline)]
231+
fn clone_from(&mut self, source: &Self, hash_builder: &S) {
232+
self.table
233+
.clone_from_with_hasher(&source.table, |x| make_hash(hash_builder, &x.0));
232234
}
233-
HashClone::clone_from(self, source, &hash_builder);
234235
}
236+
HashClone::clone_from(self, source, &hash_builder);
235237

236238
// Update hash_builder only if we successfully cloned all elements.
237239
self.hash_builder = hash_builder;

src/raw/mod.rs

+4-9
Original file line numberDiff line numberDiff line change
@@ -1045,16 +1045,11 @@ trait RawTableClone {
10451045
unsafe fn clone_from_spec(&mut self, source: &Self, on_panic: impl FnMut(&mut Self));
10461046
}
10471047
impl<T: Clone> RawTableClone for RawTable<T> {
1048-
#[cfg(feature = "nightly")]
10491048
#[cfg_attr(feature = "inline-more", inline)]
1050-
default unsafe fn clone_from_spec(&mut self, source: &Self, on_panic: impl FnMut(&mut Self)) {
1051-
self.clone_from_impl(source, on_panic);
1052-
}
1053-
1054-
#[cfg(not(feature = "nightly"))]
1055-
#[cfg_attr(feature = "inline-more", inline)]
1056-
unsafe fn clone_from_spec(&mut self, source: &Self, on_panic: impl FnMut(&mut Self)) {
1057-
self.clone_from_impl(source, on_panic);
1049+
default_fn! {
1050+
unsafe fn clone_from_spec(&mut self, source: &Self, on_panic: impl FnMut(&mut Self)) {
1051+
self.clone_from_impl(source, on_panic);
1052+
}
10581053
}
10591054
}
10601055
#[cfg(feature = "nightly")]

0 commit comments

Comments
 (0)