Implement RFC 1268

This patch allows overlap to occur between any two impls of a trait for
traits which have no associated items.

Several compile-fail tests around coherence had to be changed to add at
least one item to the trait they test against.

Ref #29864
This commit is contained in:
Sean Griffin 2017-02-25 16:16:27 -05:00 committed by Corey Farwell
parent f0ca5d4bad
commit 4aca540018
20 changed files with 64 additions and 21 deletions

View File

@ -155,6 +155,11 @@ pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
return r;
}
if tcx.impl_always_allowed_to_overlap(impl1_def_id)
&& tcx.impl_always_allowed_to_overlap(impl2_def_id) {
return true;
}
// The feature gate should prevent introducing new specializations, but not
// taking advantage of upstream ones.
if !tcx.sess.features.borrow().specialization &&

View File

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

View File

@ -2227,6 +2227,16 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
queries::impl_trait_ref::get(self, DUMMY_SP, id)
}
/// Returns true if the impl is positive and is for a triat which contains
/// no items
pub fn impl_always_allowed_to_overlap(self, def_id: DefId) -> bool {
self.trait_impl_polarity(def_id) == hir::ImplPolarity::Positive
&& self.impl_trait_ref(def_id)
.map_or(false, |trait_ref| {
self.associated_item_def_ids(trait_ref.def_id).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

@ -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

@ -20,8 +20,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

@ -34,7 +34,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

@ -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,23 @@
// 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.
trait MyMarker {}
impl<T: Copy> MyMarker for T {}
impl<T: Eq> MyMarker for T {}
fn foo<T: MyMarker>(t: T) -> T {
t
}
fn main() {
assert_eq!(1, foo(1));
assert_eq!(vec![1], foo(vec![1]));
}