Skip to content

Commit be1a74e

Browse files
committed
Auto merge of #41312 - frewsxcv:rollup, r=frewsxcv
Rollup of 2 pull requests - Successful merges: #41125, #41309 - Failed merges:
2 parents f0ca5d4 + 3adcd1c commit be1a74e

29 files changed

+367
-55
lines changed

Diff for: src/doc/unstable-book/src/SUMMARY.md

+1
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@
136136
- [optin_builtin_traits](optin-builtin-traits.md)
137137
- [option_entry](option-entry.md)
138138
- [osstring_shrink_to_fit](osstring-shrink-to-fit.md)
139+
- [overlapping_marker_traits](overlapping-marker-traits.md)
139140
- [panic_abort](panic-abort.md)
140141
- [panic_runtime](panic-runtime.md)
141142
- [panic_unwind](panic-unwind.md)
+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# `overlapping_marker_traits`
2+
3+
The tracking issue for this feature is: [#29864]
4+
5+
[#29864]: https://github.com/rust-lang/rust/issues/29864
6+
7+
------------------------

Diff for: src/libcore/hash/mod.rs

+164-33
Original file line numberDiff line numberDiff line change
@@ -107,29 +107,25 @@ mod sip;
107107

108108
/// A hashable type.
109109
///
110-
/// The `H` type parameter is an abstract hash state that is used by the `Hash`
111-
/// to compute the hash.
110+
/// Types implementing `Hash` are able to be [`hash`]ed with an instance of
111+
/// [`Hasher`].
112112
///
113-
/// If you are also implementing [`Eq`], there is an additional property that
114-
/// is important:
113+
/// ## Implementing `Hash`
115114
///
116-
/// ```text
117-
/// k1 == k2 -> hash(k1) == hash(k2)
118-
/// ```
119-
///
120-
/// In other words, if two keys are equal, their hashes should also be equal.
121-
/// [`HashMap`] and [`HashSet`] both rely on this behavior.
115+
/// You can derive `Hash` with `#[derive(Hash)]` if all fields implement `Hash`.
116+
/// The resulting hash will be the combination of the values from calling
117+
/// [`hash`] on each field.
122118
///
123-
/// ## Derivable
124-
///
125-
/// This trait can be used with `#[derive]` if all fields implement `Hash`.
126-
/// When `derive`d, the resulting hash will be the combination of the values
127-
/// from calling [`.hash`] on each field.
128-
///
129-
/// ## How can I implement `Hash`?
119+
/// ```
120+
/// #[derive(Hash)]
121+
/// struct Rustacean {
122+
/// name: String,
123+
/// country: String,
124+
/// }
125+
/// ```
130126
///
131-
/// If you need more control over how a value is hashed, you need to implement
132-
/// the `Hash` trait:
127+
/// If you need more control over how a value is hashed, you can of course
128+
/// implement the `Hash` trait yourself:
133129
///
134130
/// ```
135131
/// use std::hash::{Hash, Hasher};
@@ -148,17 +144,60 @@ mod sip;
148144
/// }
149145
/// ```
150146
///
147+
/// ## `Hash` and `Eq`
148+
///
149+
/// When implementing both `Hash` and [`Eq`], it is important that the following
150+
/// property holds:
151+
///
152+
/// ```text
153+
/// k1 == k2 -> hash(k1) == hash(k2)
154+
/// ```
155+
///
156+
/// In other words, if two keys are equal, their hashes must also be equal.
157+
/// [`HashMap`] and [`HashSet`] both rely on this behavior.
158+
///
159+
/// Thankfully, you won't need to worry about upholding this property when
160+
/// deriving both [`Eq`] and `Hash` with `#[derive(PartialEq, Eq, Hash)]`.
161+
///
151162
/// [`Eq`]: ../../std/cmp/trait.Eq.html
163+
/// [`Hasher`]: trait.Hasher.html
152164
/// [`HashMap`]: ../../std/collections/struct.HashMap.html
153165
/// [`HashSet`]: ../../std/collections/struct.HashSet.html
154-
/// [`.hash`]: #tymethod.hash
166+
/// [`hash`]: #tymethod.hash
155167
#[stable(feature = "rust1", since = "1.0.0")]
156168
pub trait Hash {
157-
/// Feeds this value into the state given, updating the hasher as necessary.
169+
/// Feeds this value into the given [`Hasher`].
170+
///
171+
/// # Examples
172+
///
173+
/// ```
174+
/// use std::collections::hash_map::DefaultHasher;
175+
/// use std::hash::{Hash, Hasher};
176+
///
177+
/// let mut hasher = DefaultHasher::new();
178+
/// 7920.hash(&mut hasher);
179+
/// println!("Hash is {:x}!", hasher.finish());
180+
/// ```
181+
///
182+
/// [`Hasher`]: trait.Hasher.html
158183
#[stable(feature = "rust1", since = "1.0.0")]
159184
fn hash<H: Hasher>(&self, state: &mut H);
160185

161-
/// Feeds a slice of this type into the state provided.
186+
/// Feeds a slice of this type into the given [`Hasher`].
187+
///
188+
/// # Examples
189+
///
190+
/// ```
191+
/// use std::collections::hash_map::DefaultHasher;
192+
/// use std::hash::{Hash, Hasher};
193+
///
194+
/// let mut hasher = DefaultHasher::new();
195+
/// let numbers = [6, 28, 496, 8128];
196+
/// Hash::hash_slice(&numbers, &mut hasher);
197+
/// println!("Hash is {:x}!", hasher.finish());
198+
/// ```
199+
///
200+
/// [`Hasher`]: trait.Hasher.html
162201
#[stable(feature = "hash_slice", since = "1.3.0")]
163202
fn hash_slice<H: Hasher>(data: &[Self], state: &mut H)
164203
where Self: Sized
@@ -169,18 +208,73 @@ pub trait Hash {
169208
}
170209
}
171210

172-
/// A trait which represents the ability to hash an arbitrary stream of bytes.
211+
/// A trait for hashing an arbitrary stream of bytes.
212+
///
213+
/// Instances of `Hasher` usually represent state that is changed while hashing
214+
/// data.
215+
///
216+
/// `Hasher` provides a fairly basic interface for retrieving the generated hash
217+
/// (with [`finish`]), and writing integers as well as slices of bytes into an
218+
/// instance (with [`write`] and [`write_u8`] etc.). Most of the time, `Hasher`
219+
/// instances are used in conjunction with the [`Hash`] trait.
220+
///
221+
/// # Examples
222+
///
223+
/// ```
224+
/// use std::collections::hash_map::DefaultHasher;
225+
/// use std::hash::Hasher;
226+
///
227+
/// let mut hasher = DefaultHasher::new();
228+
///
229+
/// hasher.write_u32(1989);
230+
/// hasher.write_u8(11);
231+
/// hasher.write_u8(9);
232+
/// hasher.write(b"Huh?");
233+
///
234+
/// println!("Hash is {:x}!", hasher.finish());
235+
/// ```
236+
///
237+
/// [`Hash`]: trait.Hash.html
238+
/// [`finish`]: #tymethod.finish
239+
/// [`write`]: #tymethod.write
240+
/// [`write_u8`]: #method.write_u8
173241
#[stable(feature = "rust1", since = "1.0.0")]
174242
pub trait Hasher {
175243
/// Completes a round of hashing, producing the output hash generated.
244+
///
245+
/// # Examples
246+
///
247+
/// ```
248+
/// use std::collections::hash_map::DefaultHasher;
249+
/// use std::hash::Hasher;
250+
///
251+
/// let mut hasher = DefaultHasher::new();
252+
/// hasher.write(b"Cool!");
253+
///
254+
/// println!("Hash is {:x}!", hasher.finish());
255+
/// ```
176256
#[stable(feature = "rust1", since = "1.0.0")]
177257
fn finish(&self) -> u64;
178258

179259
/// Writes some data into this `Hasher`.
260+
///
261+
/// # Examples
262+
///
263+
/// ```
264+
/// use std::collections::hash_map::DefaultHasher;
265+
/// use std::hash::Hasher;
266+
///
267+
/// let mut hasher = DefaultHasher::new();
268+
/// let data = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef];
269+
///
270+
/// hasher.write(&data);
271+
///
272+
/// println!("Hash is {:x}!", hasher.finish());
273+
/// ```
180274
#[stable(feature = "rust1", since = "1.0.0")]
181275
fn write(&mut self, bytes: &[u8]);
182276

183-
/// Write a single `u8` into this hasher.
277+
/// Writes a single `u8` into this hasher.
184278
#[inline]
185279
#[stable(feature = "hasher_write", since = "1.3.0")]
186280
fn write_u8(&mut self, i: u8) {
@@ -258,12 +352,35 @@ pub trait Hasher {
258352
}
259353
}
260354

261-
/// A `BuildHasher` is typically used as a factory for instances of `Hasher`
262-
/// which a `HashMap` can then use to hash keys independently.
355+
/// A trait for creating instances of [`Hasher`].
356+
///
357+
/// A `BuildHasher` is typically used (e.g. by [`HashMap`]) to create
358+
/// [`Hasher`]s for each key such that they are hashed independently of one
359+
/// another, since [`Hasher`]s contain state.
360+
///
361+
/// For each instance of `BuildHasher`, the [`Hasher`]s created by
362+
/// [`build_hasher`] should be identical. That is, if the same stream of bytes
363+
/// is fed into each hasher, the same output will also be generated.
364+
///
365+
/// # Examples
366+
///
367+
/// ```
368+
/// use std::collections::hash_map::RandomState;
369+
/// use std::hash::{BuildHasher, Hasher};
370+
///
371+
/// let s = RandomState::new();
372+
/// let mut hasher_1 = s.build_hasher();
373+
/// let mut hasher_2 = s.build_hasher();
263374
///
264-
/// Note that for each instance of `BuildHasher`, the created hashers should be
265-
/// identical. That is, if the same stream of bytes is fed into each hasher, the
266-
/// same output will also be generated.
375+
/// hasher_1.write_u32(8128);
376+
/// hasher_2.write_u32(8128);
377+
///
378+
/// assert_eq!(hasher_1.finish(), hasher_2.finish());
379+
/// ```
380+
///
381+
/// [`build_hasher`]: #tymethod.build_hasher
382+
/// [`Hasher`]: trait.Hasher.html
383+
/// [`HashMap`]: ../../std/collections/struct.HashMap.html
267384
#[stable(since = "1.7.0", feature = "build_hasher")]
268385
pub trait BuildHasher {
269386
/// Type of the hasher that will be created.
@@ -272,6 +389,9 @@ pub trait BuildHasher {
272389

273390
/// Creates a new hasher.
274391
///
392+
/// Each call to `build_hasher` on the same instance should produce identical
393+
/// [`Hasher`]s.
394+
///
275395
/// # Examples
276396
///
277397
/// ```
@@ -281,15 +401,23 @@ pub trait BuildHasher {
281401
/// let s = RandomState::new();
282402
/// let new_s = s.build_hasher();
283403
/// ```
404+
///
405+
/// [`Hasher`]: trait.Hasher.html
284406
#[stable(since = "1.7.0", feature = "build_hasher")]
285407
fn build_hasher(&self) -> Self::Hasher;
286408
}
287409

288-
/// The `BuildHasherDefault` structure is used in scenarios where one has a
289-
/// type that implements [`Hasher`] and [`Default`], but needs that type to
290-
/// implement [`BuildHasher`].
410+
/// Used to create a default [`BuildHasher`] instance for types that implement
411+
/// [`Hasher`] and [`Default`].
291412
///
292-
/// This structure is zero-sized and does not need construction.
413+
/// `BuildHasherDefault<H>` can be used when a type `H` implements [`Hasher`] and
414+
/// [`Default`], and you need a corresponding [`BuildHasher`] instance, but none is
415+
/// defined.
416+
///
417+
/// Any `BuildHasherDefault` is [zero-sized]. It can be created with
418+
/// [`default`][method.Default]. When using `BuildHasherDefault` with [`HashMap`] or
419+
/// [`HashSet`], this doesn't need to be done, since they implement appropriate
420+
/// [`Default`] instances themselves.
293421
///
294422
/// # Examples
295423
///
@@ -322,8 +450,11 @@ pub trait BuildHasher {
322450
///
323451
/// [`BuildHasher`]: trait.BuildHasher.html
324452
/// [`Default`]: ../default/trait.Default.html
453+
/// [method.default]: #method.default
325454
/// [`Hasher`]: trait.Hasher.html
326455
/// [`HashMap`]: ../../std/collections/struct.HashMap.html
456+
/// [`HashSet`]: ../../std/collections/struct.HashSet.html
457+
/// [zero-sized]: https://doc.rust-lang.org/nomicon/exotic-sizes.html#zero-sized-types-zsts
327458
#[stable(since = "1.7.0", feature = "build_hasher")]
328459
pub struct BuildHasherDefault<H>(marker::PhantomData<H>);
329460

Diff for: src/librustc/traits/select.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1736,7 +1736,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
17361736
if other.evaluation == EvaluatedToOk {
17371737
if let ImplCandidate(victim_def) = victim.candidate {
17381738
let tcx = self.tcx().global_tcx();
1739-
return traits::specializes(tcx, other_def, victim_def);
1739+
return traits::specializes(tcx, other_def, victim_def) ||
1740+
tcx.impls_are_allowed_to_overlap(other_def, victim_def);
17401741
}
17411742
}
17421743

Diff for: src/librustc/traits/specialize/specialization_graph.rs

+4
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,10 @@ impl<'a, 'gcx, 'tcx> Children {
113113
possible_sibling,
114114
impl_def_id);
115115
if let Some(impl_header) = overlap {
116+
if tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling) {
117+
return Ok((false, false));
118+
}
119+
116120
let le = specializes(tcx, impl_def_id, possible_sibling);
117121
let ge = specializes(tcx, possible_sibling, impl_def_id);
118122

Diff for: src/librustc/ty/mod.rs

+19
Original file line numberDiff line numberDiff line change
@@ -2227,6 +2227,25 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
22272227
queries::impl_trait_ref::get(self, DUMMY_SP, id)
22282228
}
22292229

2230+
/// Returns true if the impls are the same polarity and are implementing
2231+
/// a trait which contains no items
2232+
pub fn impls_are_allowed_to_overlap(self, def_id1: DefId, def_id2: DefId) -> bool {
2233+
if !self.sess.features.borrow().overlapping_marker_traits {
2234+
return false;
2235+
}
2236+
let trait1_is_empty = self.impl_trait_ref(def_id1)
2237+
.map_or(false, |trait_ref| {
2238+
self.associated_item_def_ids(trait_ref.def_id).is_empty()
2239+
});
2240+
let trait2_is_empty = self.impl_trait_ref(def_id2)
2241+
.map_or(false, |trait_ref| {
2242+
self.associated_item_def_ids(trait_ref.def_id).is_empty()
2243+
});
2244+
self.trait_impl_polarity(def_id1) == self.trait_impl_polarity(def_id2)
2245+
&& trait1_is_empty
2246+
&& trait2_is_empty
2247+
}
2248+
22302249
// Returns `ty::VariantDef` if `def` refers to a struct,
22312250
// or variant or their constructors, panics otherwise.
22322251
pub fn expect_variant_def(self, def: Def) -> &'tcx VariantDef {

Diff for: src/libsyntax/feature_gate.rs

+3
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,9 @@ declare_features! (
349349

350350
// Allows module-level inline assembly by way of global_asm!()
351351
(active, global_asm, "1.18.0", Some(35119)),
352+
353+
// Allows overlapping impls of marker traits
354+
(active, overlapping_marker_traits, "1.18.0", Some(29864)),
352355
);
353356

354357
declare_features! (

Diff for: src/test/compile-fail/E0120.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
trait MyTrait {}
11+
trait MyTrait { fn foo() {} }
1212

1313
impl Drop for MyTrait {
1414
//~^ ERROR E0120

Diff for: src/test/compile-fail/auxiliary/trait_impl_conflict.rs

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
// except according to those terms.
1010

1111
pub trait Foo {
12+
fn foo() {}
1213
}
1314

1415
impl Foo for isize {

Diff for: src/test/compile-fail/coherence-conflicting-negative-trait-impl.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
// except according to those terms.
1010

1111
#![feature(optin_builtin_traits)]
12+
#![feature(overlapping_marker_traits)]
1213

1314
trait MyTrait {}
1415

@@ -20,8 +21,8 @@ impl<T: MyTrait> !Send for TestType<T> {}
2021
//~^ ERROR conflicting implementations of trait `std::marker::Send`
2122

2223
unsafe impl<T:'static> Send for TestType<T> {}
23-
//~^ ERROR conflicting implementations of trait `std::marker::Send`
2424

2525
impl !Send for TestType<i32> {}
26+
//~^ ERROR conflicting implementations of trait `std::marker::Send`
2627

2728
fn main() {}

Diff for: src/test/compile-fail/coherence-default-trait-impl.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
#![feature(optin_builtin_traits)]
1212

13-
trait MyTrait {}
13+
trait MyTrait { fn foo() {} }
1414

1515
impl MyTrait for .. {}
1616
//~^ ERROR redundant default implementations of trait `MyTrait`

0 commit comments

Comments
 (0)