From 6e68fd09edc7ed37fd76f703247b5410cd338bfe Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sun, 4 Jan 2015 20:35:06 -0500 Subject: Implement new orphan rule that requires that impls of remote traits meet the following two criteria: - the self type includes some local type; and, - type parameters in the self type must be constrained by a local type. A type parameter is called *constrained* if it appears in some type-parameter of a local type. Here are some examples that are accepted. In all of these examples, I assume that `Foo` is a trait defined in another crate. If `Foo` were defined in the local crate, then all the examples would be legal. - `impl Foo for LocalType` - `impl Foo for LocalType` -- T does not appear in Self, so it is OK - `impl Foo for LocalType` -- T here is constrained by LocalType - `impl Foo for (LocalType, T)` -- T here is constrained by LocalType Here are some illegal examples (again, these examples assume that `Foo` is not local to the current crate): - `impl Foo for int` -- the Self type is not local - `impl Foo for T` -- T appears in Self unconstrained by a local type - `impl Foo for (LocalType, T)` -- T appears in Self unconstrained by a local type This is a [breaking-change]. For the time being, you can opt out of the new rules by placing `#[old_orphan_check]` on the trait (and enabling the feature gate where the trait is defined). Longer term, you should restructure your traits to avoid the problem. Usually this means changing the order of parameters so that the "central" type parameter is in the `Self` position. As an example of that refactoring, consider the `BorrowFrom` trait: ```rust pub trait BorrowFrom for Sized? { fn borrow_from(owned: &Owned) -> &Self; } ``` As defined, this trait is commonly implemented for custom pointer types, such as `Arc`. Those impls follow the pattern: ```rust impl BorrowFrom> for T {...} ``` Unfortunately, this impl is illegal because the self type `T` is not local to the current crate. Therefore, we are going to change the order of the parameters, so that `BorrowFrom` becomes `Borrow`: ```rust pub trait Borrow for Sized? { fn borrow_from(owned: &Self) -> &Borrowed; } ``` Now the `Arc` impl is written: ```rust impl Borrow for Arc { ... } ``` This impl is legal because the self type (`Arc`) is local. --- src/libcore/borrow.rs | 4 ++++ src/libcore/cmp.rs | 1 + 2 files changed, 5 insertions(+) (limited to 'src/libcore') diff --git a/src/libcore/borrow.rs b/src/libcore/borrow.rs index 7e4d73d598d..ebb4bd88cf1 100644 --- a/src/libcore/borrow.rs +++ b/src/libcore/borrow.rs @@ -53,12 +53,14 @@ use option::Option; use self::Cow::*; /// A trait for borrowing data. +#[old_orphan_check] pub trait BorrowFrom for Sized? { /// Immutably borrow from an owned value. fn borrow_from(owned: &Owned) -> &Self; } /// A trait for mutably borrowing data. +#[old_orphan_check] pub trait BorrowFromMut for Sized? : BorrowFrom { /// Mutably borrow from an owned value. fn borrow_from_mut(owned: &mut Owned) -> &mut Self; @@ -91,6 +93,7 @@ impl<'a, T, Sized? B> BorrowFrom> for B where B: ToOwned { } /// Trait for moving into a `Cow` +#[old_orphan_check] pub trait IntoCow<'a, T, Sized? B> { /// Moves `self` into `Cow` fn into_cow(self) -> Cow<'a, T, B>; @@ -103,6 +106,7 @@ impl<'a, T, Sized? B> IntoCow<'a, T, B> for Cow<'a, T, B> where B: ToOwned { } /// A generalization of Clone to borrowed data. +#[old_orphan_check] pub trait ToOwned for Sized?: BorrowFrom { /// Create owned data from borrowed data, usually by copying. fn to_owned(&self) -> Owned; diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 13f9f5ccee9..90ff174c2bd 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -69,6 +69,7 @@ use option::Option::{self, Some, None}; /// only if `a != b`. #[lang="eq"] #[stable] +#[old_orphan_check] pub trait PartialEq for Sized? { /// This method tests for `self` and `other` values to be equal, and is used by `==`. #[stable] -- cgit 1.4.1-3-g733a5