Auto merge of #41312 - frewsxcv:rollup, r=frewsxcv

Rollup of 2 pull requests

- Successful merges: #41125, #41309
- Failed merges:
This commit is contained in:
bors 2017-04-15 02:06:20 +00:00
commit be1a74e4d3
29 changed files with 367 additions and 55 deletions

View File

@ -136,6 +136,7 @@
- [optin_builtin_traits](optin-builtin-traits.md)
- [option_entry](option-entry.md)
- [osstring_shrink_to_fit](osstring-shrink-to-fit.md)
- [overlapping_marker_traits](overlapping-marker-traits.md)
- [panic_abort](panic-abort.md)
- [panic_runtime](panic-runtime.md)
- [panic_unwind](panic-unwind.md)

View File

@ -0,0 +1,7 @@
# `overlapping_marker_traits`
The tracking issue for this feature is: [#29864]
[#29864]: https://github.com/rust-lang/rust/issues/29864
------------------------

View File

@ -107,29 +107,25 @@ mod sip;
/// A hashable type.
///
/// The `H` type parameter is an abstract hash state that is used by the `Hash`
/// to compute the hash.
/// Types implementing `Hash` are able to be [`hash`]ed with an instance of
/// [`Hasher`].
///
/// If you are also implementing [`Eq`], there is an additional property that
/// is important:
/// ## Implementing `Hash`
///
/// ```text
/// k1 == k2 -> hash(k1) == hash(k2)
/// You can derive `Hash` with `#[derive(Hash)]` if all fields implement `Hash`.
/// The resulting hash will be the combination of the values from calling
/// [`hash`] on each field.
///
/// ```
/// #[derive(Hash)]
/// struct Rustacean {
/// name: String,
/// country: String,
/// }
/// ```
///
/// In other words, if two keys are equal, their hashes should also be equal.
/// [`HashMap`] and [`HashSet`] both rely on this behavior.
///
/// ## Derivable
///
/// This trait can be used with `#[derive]` if all fields implement `Hash`.
/// When `derive`d, the resulting hash will be the combination of the values
/// from calling [`.hash`] on each field.
///
/// ## How can I implement `Hash`?
///
/// If you need more control over how a value is hashed, you need to implement
/// the `Hash` trait:
/// If you need more control over how a value is hashed, you can of course
/// implement the `Hash` trait yourself:
///
/// ```
/// use std::hash::{Hash, Hasher};
@ -148,17 +144,60 @@ mod sip;
/// }
/// ```
///
/// ## `Hash` and `Eq`
///
/// When implementing both `Hash` and [`Eq`], it is important that the following
/// property holds:
///
/// ```text
/// k1 == k2 -> hash(k1) == hash(k2)
/// ```
///
/// In other words, if two keys are equal, their hashes must also be equal.
/// [`HashMap`] and [`HashSet`] both rely on this behavior.
///
/// Thankfully, you won't need to worry about upholding this property when
/// deriving both [`Eq`] and `Hash` with `#[derive(PartialEq, Eq, Hash)]`.
///
/// [`Eq`]: ../../std/cmp/trait.Eq.html
/// [`Hasher`]: trait.Hasher.html
/// [`HashMap`]: ../../std/collections/struct.HashMap.html
/// [`HashSet`]: ../../std/collections/struct.HashSet.html
/// [`.hash`]: #tymethod.hash
/// [`hash`]: #tymethod.hash
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Hash {
/// Feeds this value into the state given, updating the hasher as necessary.
/// Feeds this value into the given [`Hasher`].
///
/// # Examples
///
/// ```
/// use std::collections::hash_map::DefaultHasher;
/// use std::hash::{Hash, Hasher};
///
/// let mut hasher = DefaultHasher::new();
/// 7920.hash(&mut hasher);
/// println!("Hash is {:x}!", hasher.finish());
/// ```
///
/// [`Hasher`]: trait.Hasher.html
#[stable(feature = "rust1", since = "1.0.0")]
fn hash<H: Hasher>(&self, state: &mut H);
/// Feeds a slice of this type into the state provided.
/// Feeds a slice of this type into the given [`Hasher`].
///
/// # Examples
///
/// ```
/// use std::collections::hash_map::DefaultHasher;
/// use std::hash::{Hash, Hasher};
///
/// let mut hasher = DefaultHasher::new();
/// let numbers = [6, 28, 496, 8128];
/// Hash::hash_slice(&numbers, &mut hasher);
/// println!("Hash is {:x}!", hasher.finish());
/// ```
///
/// [`Hasher`]: trait.Hasher.html
#[stable(feature = "hash_slice", since = "1.3.0")]
fn hash_slice<H: Hasher>(data: &[Self], state: &mut H)
where Self: Sized
@ -169,18 +208,73 @@ pub trait Hash {
}
}
/// A trait which represents the ability to hash an arbitrary stream of bytes.
/// A trait for hashing an arbitrary stream of bytes.
///
/// Instances of `Hasher` usually represent state that is changed while hashing
/// data.
///
/// `Hasher` provides a fairly basic interface for retrieving the generated hash
/// (with [`finish`]), and writing integers as well as slices of bytes into an
/// instance (with [`write`] and [`write_u8`] etc.). Most of the time, `Hasher`
/// instances are used in conjunction with the [`Hash`] trait.
///
/// # Examples
///
/// ```
/// use std::collections::hash_map::DefaultHasher;
/// use std::hash::Hasher;
///
/// let mut hasher = DefaultHasher::new();
///
/// hasher.write_u32(1989);
/// hasher.write_u8(11);
/// hasher.write_u8(9);
/// hasher.write(b"Huh?");
///
/// println!("Hash is {:x}!", hasher.finish());
/// ```
///
/// [`Hash`]: trait.Hash.html
/// [`finish`]: #tymethod.finish
/// [`write`]: #tymethod.write
/// [`write_u8`]: #method.write_u8
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Hasher {
/// Completes a round of hashing, producing the output hash generated.
///
/// # Examples
///
/// ```
/// use std::collections::hash_map::DefaultHasher;
/// use std::hash::Hasher;
///
/// let mut hasher = DefaultHasher::new();
/// hasher.write(b"Cool!");
///
/// println!("Hash is {:x}!", hasher.finish());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn finish(&self) -> u64;
/// Writes some data into this `Hasher`.
///
/// # Examples
///
/// ```
/// use std::collections::hash_map::DefaultHasher;
/// use std::hash::Hasher;
///
/// let mut hasher = DefaultHasher::new();
/// let data = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef];
///
/// hasher.write(&data);
///
/// println!("Hash is {:x}!", hasher.finish());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn write(&mut self, bytes: &[u8]);
/// Write a single `u8` into this hasher.
/// Writes a single `u8` into this hasher.
#[inline]
#[stable(feature = "hasher_write", since = "1.3.0")]
fn write_u8(&mut self, i: u8) {
@ -258,12 +352,35 @@ pub trait Hasher {
}
}
/// A `BuildHasher` is typically used as a factory for instances of `Hasher`
/// which a `HashMap` can then use to hash keys independently.
/// A trait for creating instances of [`Hasher`].
///
/// Note that for each instance of `BuildHasher`, the created hashers should be
/// identical. That is, if the same stream of bytes is fed into each hasher, the
/// same output will also be generated.
/// A `BuildHasher` is typically used (e.g. by [`HashMap`]) to create
/// [`Hasher`]s for each key such that they are hashed independently of one
/// another, since [`Hasher`]s contain state.
///
/// For each instance of `BuildHasher`, the [`Hasher`]s created by
/// [`build_hasher`] should be identical. That is, if the same stream of bytes
/// is fed into each hasher, the same output will also be generated.
///
/// # Examples
///
/// ```
/// use std::collections::hash_map::RandomState;
/// use std::hash::{BuildHasher, Hasher};
///
/// let s = RandomState::new();
/// let mut hasher_1 = s.build_hasher();
/// let mut hasher_2 = s.build_hasher();
///
/// hasher_1.write_u32(8128);
/// hasher_2.write_u32(8128);
///
/// assert_eq!(hasher_1.finish(), hasher_2.finish());
/// ```
///
/// [`build_hasher`]: #tymethod.build_hasher
/// [`Hasher`]: trait.Hasher.html
/// [`HashMap`]: ../../std/collections/struct.HashMap.html
#[stable(since = "1.7.0", feature = "build_hasher")]
pub trait BuildHasher {
/// Type of the hasher that will be created.
@ -272,6 +389,9 @@ pub trait BuildHasher {
/// Creates a new hasher.
///
/// Each call to `build_hasher` on the same instance should produce identical
/// [`Hasher`]s.
///
/// # Examples
///
/// ```
@ -281,15 +401,23 @@ pub trait BuildHasher {
/// let s = RandomState::new();
/// let new_s = s.build_hasher();
/// ```
///
/// [`Hasher`]: trait.Hasher.html
#[stable(since = "1.7.0", feature = "build_hasher")]
fn build_hasher(&self) -> Self::Hasher;
}
/// The `BuildHasherDefault` structure is used in scenarios where one has a
/// type that implements [`Hasher`] and [`Default`], but needs that type to
/// implement [`BuildHasher`].
/// Used to create a default [`BuildHasher`] instance for types that implement
/// [`Hasher`] and [`Default`].
///
/// This structure is zero-sized and does not need construction.
/// `BuildHasherDefault<H>` can be used when a type `H` implements [`Hasher`] and
/// [`Default`], and you need a corresponding [`BuildHasher`] instance, but none is
/// defined.
///
/// Any `BuildHasherDefault` is [zero-sized]. It can be created with
/// [`default`][method.Default]. When using `BuildHasherDefault` with [`HashMap`] or
/// [`HashSet`], this doesn't need to be done, since they implement appropriate
/// [`Default`] instances themselves.
///
/// # Examples
///
@ -322,8 +450,11 @@ pub trait BuildHasher {
///
/// [`BuildHasher`]: trait.BuildHasher.html
/// [`Default`]: ../default/trait.Default.html
/// [method.default]: #method.default
/// [`Hasher`]: trait.Hasher.html
/// [`HashMap`]: ../../std/collections/struct.HashMap.html
/// [`HashSet`]: ../../std/collections/struct.HashSet.html
/// [zero-sized]: https://doc.rust-lang.org/nomicon/exotic-sizes.html#zero-sized-types-zsts
#[stable(since = "1.7.0", feature = "build_hasher")]
pub struct BuildHasherDefault<H>(marker::PhantomData<H>);

View File

@ -1736,7 +1736,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
if other.evaluation == EvaluatedToOk {
if let ImplCandidate(victim_def) = victim.candidate {
let tcx = self.tcx().global_tcx();
return traits::specializes(tcx, other_def, victim_def);
return traits::specializes(tcx, other_def, victim_def) ||
tcx.impls_are_allowed_to_overlap(other_def, victim_def);
}
}

View File

@ -113,6 +113,10 @@ impl<'a, 'gcx, 'tcx> Children {
possible_sibling,
impl_def_id);
if let Some(impl_header) = overlap {
if tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling) {
return Ok((false, false));
}
let le = specializes(tcx, impl_def_id, possible_sibling);
let ge = specializes(tcx, possible_sibling, impl_def_id);

View File

@ -2227,6 +2227,25 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
queries::impl_trait_ref::get(self, DUMMY_SP, id)
}
/// Returns true if the impls are the same polarity and are implementing
/// a trait which contains no items
pub fn impls_are_allowed_to_overlap(self, def_id1: DefId, def_id2: DefId) -> bool {
if !self.sess.features.borrow().overlapping_marker_traits {
return false;
}
let trait1_is_empty = self.impl_trait_ref(def_id1)
.map_or(false, |trait_ref| {
self.associated_item_def_ids(trait_ref.def_id).is_empty()
});
let trait2_is_empty = self.impl_trait_ref(def_id2)
.map_or(false, |trait_ref| {
self.associated_item_def_ids(trait_ref.def_id).is_empty()
});
self.trait_impl_polarity(def_id1) == self.trait_impl_polarity(def_id2)
&& trait1_is_empty
&& trait2_is_empty
}
// Returns `ty::VariantDef` if `def` refers to a struct,
// or variant or their constructors, panics otherwise.
pub fn expect_variant_def(self, def: Def) -> &'tcx VariantDef {

View File

@ -349,6 +349,9 @@ declare_features! (
// Allows module-level inline assembly by way of global_asm!()
(active, global_asm, "1.18.0", Some(35119)),
// Allows overlapping impls of marker traits
(active, overlapping_marker_traits, "1.18.0", Some(29864)),
);
declare_features! (

View File

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
trait MyTrait {}
trait MyTrait { fn foo() {} }
impl Drop for MyTrait {
//~^ ERROR E0120

View File

@ -9,6 +9,7 @@
// except according to those terms.
pub trait Foo {
fn foo() {}
}
impl Foo for isize {

View File

@ -9,6 +9,7 @@
// except according to those terms.
#![feature(optin_builtin_traits)]
#![feature(overlapping_marker_traits)]
trait MyTrait {}
@ -20,8 +21,8 @@ impl<T: MyTrait> !Send for TestType<T> {}
//~^ ERROR conflicting implementations of trait `std::marker::Send`
unsafe impl<T:'static> Send for TestType<T> {}
//~^ ERROR conflicting implementations of trait `std::marker::Send`
impl !Send for TestType<i32> {}
//~^ ERROR conflicting implementations of trait `std::marker::Send`
fn main() {}

View File

@ -10,7 +10,7 @@
#![feature(optin_builtin_traits)]
trait MyTrait {}
trait MyTrait { fn foo() {} }
impl MyTrait for .. {}
//~^ ERROR redundant default implementations of trait `MyTrait`

View File

@ -9,6 +9,7 @@
// except according to those terms.
#![feature(optin_builtin_traits)]
#![feature(overlapping_marker_traits)]
use std::marker::Copy;
@ -34,7 +35,6 @@ unsafe impl Send for [MyType] {}
unsafe impl Send for &'static [NotSync] {}
//~^ ERROR E0117
//~| ERROR E0119
fn main() {
}

View File

@ -10,7 +10,7 @@
// Test that you cannot *directly* dispatch on lifetime requirements
trait MyTrait {}
trait MyTrait { fn foo() {} }
impl<T> MyTrait for T {}
impl<T: 'static> MyTrait for T {} //~ ERROR E0119

View File

@ -17,6 +17,7 @@
// Seems pretty basic, but then there was issue #24241. :)
trait From<U> {
fn foo() {}
}
impl <T> From<T> for T {

View File

@ -8,22 +8,22 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
trait Foo {}
trait Foo { fn foo() {} }
impl<T> Foo for T {}
impl<U> Foo for U {} //~ ERROR conflicting implementations of trait `Foo`:
trait Bar {}
trait Bar { fn bar() {} }
impl<T> Bar for (T, u8) {}
impl<T> Bar for (u8, T) {} //~ ERROR conflicting implementations of trait `Bar` for type `(u8, u8)`:
trait Baz<T> {}
trait Baz<T> { fn baz() {} }
impl<T> Baz<u8> for T {}
impl<T> Baz<T> for u8 {} //~ ERROR conflicting implementations of trait `Baz<u8>` for type `u8`:
trait Quux<U, V> {}
trait Quux<U, V> { fn quux() {} }
impl<T, U, V> Quux<U, V> for T {}
impl<T, U> Quux<U, U> for T {} //~ ERROR conflicting implementations of trait `Quux<_, _>`:

View File

@ -15,7 +15,7 @@
// due to the orphan rules. Therefore, `A::Item` may yet turn out to
// be `i32`.
pub trait Foo<P> {}
pub trait Foo<P> { fn foo() {} }
pub trait Bar {
type Output: 'static;

View File

@ -13,7 +13,7 @@
use std::marker::PhantomData;
pub trait Foo<P> {}
pub trait Foo<P> { fn foo() {} }
impl <P, T: Foo<P>> Foo<P> for Option<T> {}

View File

@ -10,7 +10,7 @@
use std::marker::PhantomData;
pub trait Foo<P> {}
pub trait Foo<P> { fn foo() {} }
pub trait Bar {
type Output: 'static;

View File

@ -20,7 +20,7 @@ extern crate coherence_copy_like_lib as lib;
struct MyType { x: i32 }
trait MyTrait { }
trait MyTrait { fn foo() {} }
impl<T: lib::MyCopy> MyTrait for T { }
// `MyFundamentalStruct` is declared fundamental, so we can test that

View File

@ -20,7 +20,7 @@ extern crate coherence_copy_like_lib as lib;
struct MyType { x: i32 }
trait MyTrait { }
trait MyTrait { fn foo() {} }
impl<T: lib::MyCopy> MyTrait for T { }
// `MyFundamentalStruct` is declared fundamental, so we can test that

View File

@ -19,7 +19,7 @@ extern crate coherence_copy_like_lib as lib;
struct MyType { x: i32 }
trait MyTrait { }
trait MyTrait { fn foo() {} }
impl<T: lib::MyCopy> MyTrait for T { }

View File

@ -17,7 +17,7 @@ extern crate coherence_copy_like_lib as lib;
struct MyType { x: i32 }
trait MyTrait { }
trait MyTrait { fn foo() {} }
impl<T: lib::MyCopy> MyTrait for T { }
// `MyStruct` is not declared fundamental, therefore this would

View File

@ -17,7 +17,7 @@ extern crate coherence_copy_like_lib as lib;
struct MyType { x: i32 }
trait MyTrait { }
trait MyTrait { fn foo() {} }
impl<T: lib::MyCopy> MyTrait for T { }
// Tuples are not fundamental, therefore this would require that

View File

@ -0,0 +1,19 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::fmt::{Debug, Display};
trait MyMarker {}
impl<T: Display> MyMarker for T {}
impl<T: Debug> MyMarker for T {}
//~^ ERROR E0119
fn main() {}

View File

@ -0,0 +1,41 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Test for RFC 1268: we allow overlapping impls of marker traits,
// that is, traits without items. In this case, a type `T` is
// `MyMarker` if it is either `Debug` or `Display`. This test just
// checks that we don't consider **all** types to be `MyMarker`. See
// also the companion test in
// `run-pass/overlap-permitted-for-marker-traits.rs`.
#![feature(overlapping_marker_traits)]
#![feature(optin_builtin_traits)]
use std::fmt::{Debug, Display};
trait Marker {}
impl<T: Debug> Marker for T {}
impl<T: Display> Marker for T {}
fn is_marker<T: Marker>() { }
struct NotDebugOrDisplay;
fn main() {
// Debug && Display:
is_marker::<i32>();
// Debug && !Display:
is_marker::<Vec<i32>>();
// !Debug && !Display
is_marker::<NotDebugOrDisplay>(); //~ ERROR
}

View File

@ -10,19 +10,19 @@
#![feature(specialization)]
trait Foo {}
trait Foo { fn foo() {} }
impl<T: Clone> Foo for T {}
impl<T> Foo for Vec<T> {} //~ ERROR E0119
trait Bar {}
trait Bar { fn bar() {} }
impl<T> Bar for (T, u8) {}
impl<T> Bar for (u8, T) {} //~ ERROR E0119
trait Baz<U> {}
trait Baz<U> { fn baz() {} }
impl<T> Baz<T> for u8 {}
impl<T> Baz<u8> for T {} //~ ERROR E0119
trait Qux {}
trait Qux { fn qux() {} }
impl<T: Clone> Qux for T {}
impl<T: Eq> Qux for T {} //~ ERROR E0119

View File

@ -0,0 +1,27 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(overlapping_marker_traits)]
#![feature(specialization)]
trait MyMarker {}
impl<T> MyMarker for T {}
impl<T> MyMarker for Vec<T> {}
fn foo<T: MyMarker>(t: T) -> T {
t
}
fn main() {
assert_eq!(1, foo(1));
assert_eq!(2.0, foo(2.0));
assert_eq!(vec![1], foo(vec![1]));
}

View File

@ -0,0 +1,20 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(overlapping_marker_traits)]
#![feature(optin_builtin_traits)]
// Overlapping negative impls for `MyStruct` are permitted:
struct MyStruct;
impl !Send for MyStruct {}
impl !Send for MyStruct {}
fn main() {
}

View File

@ -0,0 +1,36 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Tests for RFC 1268: we allow overlapping impls of marker traits,
// that is, traits without items. In this case, a type `T` is
// `MyMarker` if it is either `Debug` or `Display`.
#![feature(overlapping_marker_traits)]
#![feature(optin_builtin_traits)]
use std::fmt::{Debug, Display};
trait MyMarker {}
impl<T: Debug> MyMarker for T {}
impl<T: Display> MyMarker for T {}
fn foo<T: MyMarker>(t: T) -> T {
t
}
fn main() {
// Debug && Display:
assert_eq!(1, foo(1));
assert_eq!(2.0, foo(2.0));
// Debug && !Display:
assert_eq!(vec![1], foo(vec![1]));
}