Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

coherence: fix is_knowable logic #46192

Merged
merged 6 commits into from
Dec 6, 2017
Merged

Conversation

arielb1
Copy link
Contributor

@arielb1 arielb1 commented Nov 22, 2017

A trait-ref that passes the orphan-check rules can still be implemented in a crate downstream from our crate (for example, LocalType for LocalTrait<_> might be matched by a LocalType for LocalTrait<TypeFromDownstreamCrate>), and this should be known by the is_knowable logic.

Trait selection had a hackfix for this, but it's an hacky fix that does not handle all cases. This patch removes it.

fixes #43355.

r? @nikomatsakis

Needs a crater run

@arielb1 arielb1 added the S-waiting-on-crater Status: Waiting on a crater run to be completed. label Nov 22, 2017
@arielb1 arielb1 changed the title coherence: types from this crate aren't local in downstream crates coherence: fix is_knowable logic Nov 22, 2017
@arielb1
Copy link
Contributor Author

arielb1 commented Nov 23, 2017

@bors try

@bors
Copy link
Contributor

bors commented Nov 23, 2017

⌛ Trying commit 5360699 with merge faf75254806fa54615158a9058c5a50b81dc8006...

@arielb1
Copy link
Contributor Author

arielb1 commented Nov 23, 2017

@bors r- retry

@bors
Copy link
Contributor

bors commented Nov 23, 2017

⌛ Trying commit 5360699 with merge 999ab8e65bc12abb057c3e7ba58a538ae3ab7c57...

@arielb1
Copy link
Contributor Author

arielb1 commented Nov 23, 2017

@bors untry

@arielb1
Copy link
Contributor Author

arielb1 commented Nov 23, 2017

@bors retry

@bors
Copy link
Contributor

bors commented Nov 23, 2017

⌛ Trying commit 5360699 with merge 0bac3d526df71b0959316897d8d8b8d1baf6b4f1...

@arielb1
Copy link
Contributor Author

arielb1 commented Nov 23, 2017

@bors try retry

@bors
Copy link
Contributor

bors commented Nov 23, 2017

⌛ Trying commit 4c08ed5 with merge 0c5e181...

bors added a commit that referenced this pull request Nov 23, 2017
coherence: fix is_knowable logic

A trait-ref that passes the orphan-check rules can still be implemented in a crate downstream from our crate (for example, `LocalType for LocalTrait<_>` might be matched by a `LocalType for LocalTrait<TypeFromDownstreamCrate>`), and this should be known by the `is_knowable`  logic.

Trait selection had a hackfix for this, but it's an hacky fix that does not handle all cases. This patch removes it.

cc #43355.

FIXME: make this a soft error. I suppose we'll crater first.

r? @nikomatsakis

Needs a crater run
@bors
Copy link
Contributor

bors commented Nov 23, 2017

☀️ Test successful - status-travis
State: approved= try=True

@arielb1 arielb1 changed the title coherence: fix is_knowable logic [needs crater] coherence: fix is_knowable logic Nov 25, 2017
@aidanhs
Copy link
Member

aidanhs commented Nov 27, 2017

Crater run started.

@bors
Copy link
Contributor

bors commented Dec 2, 2017

☔ The latest upstream changes (presumably #46430) made this pull request unmergeable. Please resolve the merge conflicts.

@aidanhs
Copy link
Member

aidanhs commented Dec 4, 2017

Hi @arielb1 (crater requester), @nikomatsakis (reviewer)! Crater results are at: http://cargobomb-reports.s3.amazonaws.com/pr-46192/index.html. 'Blacklisted' crates (spurious failures etc) can be found here. If you see any spurious failures not on the list, please make a PR against that file.

(interested observers: Crater is a tool for testing the impact of changes on the crates.io ecosystem. You can find out more at the repo if you're curious)

@arielb1
Copy link
Contributor Author

arielb1 commented Dec 4, 2017

Regressions:

crossbeam-epoch-0.1.0 & bow-1.0.3 (yay I broke Servo, but this is no longer a dependency)

impl<T> Into<Box<T>> for Owned<T>
 = note: conflicting implementation in crate `core`:
 - impl<T, U> core::convert::Into<U> for T
   where U: core::convert::From<T>;

This is a problem because any joker can write this (on nightly, but some variants are probably possible using #[fundamental] traits on stable - e.g. if Bow implemented FnOnce):

#![feature(optin_builtin_traits)]

pub struct Foo;
pub auto trait Xyz {}
impl !Xyz for Foo {}
impl !Xyz for Box<Foo> {}

impl<T: Xyz> From<T> for Box<Foo> {
    fn from(_: T) -> Self { Box::new(Foo) }
}

fn main() {
    let _foo = <Box<Foo>>::from(());
}

Which would cause a coherence conflict on linking for the trait-ref <Owned<Foo> as Into<Box<Foo>>>. This is a link-safety issue, so the impl must not be allowed.

I think the only fix is to not use Into but instead use an into_box function.

glib v0.1.3

impl<'a, T: ?Sized + SetValue> SetValue for &'a T {
impl<T: IsA<Object>> SetValue for T {

This causes a conflict because downstream crates can implement IsA<Object> for both T and &T, unless we check this impl in every downstream crate.

The crate author had actually encountered some other coherence problems with this approach, and removed this in a new version of their crate: gtk-rs/glib@b36de4e#diff-dd26c2766e65aca43e4228e64ebd0cf8

I don't see any crates depending on glib 0.1.3 itself.

ocl v0.15.0

rusqlite v0.10.3

rusqlcipher v0.14.6

This is basically the same issue as glib - attempt to implement a trait for both T: Trait and &T where T: Trait.

impl<'a, E> From<E> for EventArray where E: Into<Event>
impl<'a, E> From<&'a E> for EventArray where E: Into<Event> + Clone
impl<'a, T: ?Sized> From<&'a T> for ToSqlOutput<'a> where &'a T: Into<ValueRef<'a>>
impl<'a, T: Into<Value>> From<T> for ToSqlOutput<'a>

This is still an issue in the newest crate version, probably need to talk with the crate authors

lru-disk-cache v0.1.0 (aka sccache)

impl<K, V> CountableMeter<K, V> for Count {
impl<K, V, T: Meter<K, V, Measure=usize>> CountableMeter<K, V> for T {

This is a conflict because coherence can't see that <Count as Meter<K, V>>::Measure = () can't coexist with <Count as Meter<K, V>>::Measure = usize.

This can be fixed by the crate author by breaking the associated type to a type parameter:

use std::borrow::Borrow;
/// A trait for measuring the size of a cache entry.
///
/// If you implement this trait, you should use `usize` as the `Measure` type, otherwise you will
/// also have to implement [`CountableMeter`][countablemeter].
///
/// [countablemeter]: trait.Meter.html
pub trait Meter<K, V> {
    /// The type used to store measurements.
    type Measure: Default + Copy;
    /// Calculate the size of `key` and `value`.
    fn measure<Q: ?Sized>(&self, key: &Q, value: &V) -> Self::Measure
        where K: Borrow<Q>;
}

/// Size limit based on a simple count of cache items.
pub struct Count;

impl<K, V> Meter<K, V> for Count {
   /// Don't store anything, the measurement can be derived from the map.
    type Measure = ();

    /// Don't actually count anything either.
    fn measure<Q: ?Sized>(&self, _: &Q, _: &V) -> ()
        where K: Borrow<Q>
    {}
}

/// A trait to allow the default `Count` measurement to not store an
/// extraneous counter.
pub trait CountableMeter<K, V>: Meter<K, V> {
    /// Add `amount` to `current` and return the sum.
    fn add(&self, current: Self::Measure, amount: Self::Measure) -> Self::Measure;
    /// Subtract `amount` from `current` and return the difference.
    fn sub(&self, current: Self::Measure, amount: Self::Measure) -> Self::Measure;
    /// Return `current` as a `usize` if possible, otherwise return `None`.
    ///
    /// If this method returns `None` the cache will use the number of cache entries as
    /// its size.
    fn size(&self, current: Self::Measure) -> Option<usize>;
}

/// `Count` is all no-ops, the number of entries in the map is the size.
impl<K, V, T: Meter<K, V>> CountableMeter<K, V> for T
    where T: CountableMeterWithMeasure<K, V, <T as Meter<K, V>>::Measure>
{

    fn add(&self, current: Self::Measure, amount: Self::Measure) -> Self::Measure {
        CountableMeterWithMeasure::add(self, current, amount)
    }
    
    fn sub(&self, current: Self::Measure, amount: Self::Measure) -> Self::Measure {
        CountableMeterWithMeasure::sub(self, current, amount)
    }

    fn size(&self, current: Self::Measure) -> Option<usize> {
        CountableMeterWithMeasure::size(self, current)
    }
}


pub trait CountableMeterWithMeasure<K, V, M> {
    /// Add `amount` to `current` and return the sum.
    fn add(&self, current: M, amount: M) -> M;
    /// Subtract `amount` from `current` and return the difference.
    fn sub(&self, current: M, amount: M) -> M;
    /// Return `current` as a `usize` if possible, otherwise return `None`.
    ///
    /// If this method returns `None` the cache will use the number of cache entries as
    /// its size.
    fn size(&self, current: M) -> Option<usize>;
}


/// For any other `Meter` with `Measure=usize`, just do the simple math.
impl<K, V, T> CountableMeterWithMeasure<K, V, usize> for T {
    fn add(&self, current: usize, amount: usize) -> usize {
        current + amount
    }
    fn sub(&self, current: usize, amount: usize) -> usize {
        current - amount
    }
    fn size(&self, current: usize) -> Option<usize> { Some(current) }
}

impl<K, V> CountableMeterWithMeasure<K, V, ()> for Count {
    fn add(&self, current: (), amount: ()) {}
    fn sub(&self, current: (), amount: ()) {}
    fn size(&self, current: ()) -> Option<usize> { None }
}
fn main() {}

Copy link
Contributor

@nikomatsakis nikomatsakis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left a few documentation nits.

/// impl<T> IntoIterator for Vec<T>
/// impl<T: Iterator> IntoIterator for T
/// ```
/// We need to be able to prove that `Option<$0>: !Iterator` for every type $0.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: s/Option/Vec/, right?

}

/// Check whether a trait-ref is potentially implementable by a crate.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is wonderful.

@nikomatsakis
Copy link
Contributor

@arielb1 this only issues warnings presently, right? Seems like we ought to land it, no? r=me, if you agree.

@arielb1
Copy link
Contributor Author

arielb1 commented Dec 5, 2017

Yea this only issues warnings. I'll land this.

luser added a commit to mozilla/sccache that referenced this pull request Dec 5, 2017
@luser
Copy link
Contributor

luser commented Dec 5, 2017

I pushed a fix to lru-disk-cache in sccache, thanks for providing working code!
mozilla/sccache@d148529

@kennytm kennytm added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-crater Status: Waiting on a crater run to be completed. labels Dec 5, 2017
@arielb1
Copy link
Contributor Author

arielb1 commented Dec 5, 2017

@bors r=nikomatsakis

@bors
Copy link
Contributor

bors commented Dec 5, 2017

📌 Commit 11f22ab has been approved by nikomatsakis

@arielb1
Copy link
Contributor Author

arielb1 commented Dec 5, 2017

@bors r=nikomatsakis

@bors
Copy link
Contributor

bors commented Dec 5, 2017

📌 Commit 425c2c3 has been approved by nikomatsakis

@arielb1 arielb1 changed the title [needs crater] coherence: fix is_knowable logic coherence: fix is_knowable logic Dec 5, 2017
@bors
Copy link
Contributor

bors commented Dec 6, 2017

⌛ Testing commit 425c2c3 with merge 6536e05...

bors added a commit that referenced this pull request Dec 6, 2017
coherence: fix is_knowable logic

A trait-ref that passes the orphan-check rules can still be implemented in a crate downstream from our crate (for example, `LocalType for LocalTrait<_>` might be matched by a `LocalType for LocalTrait<TypeFromDownstreamCrate>`), and this should be known by the `is_knowable`  logic.

Trait selection had a hackfix for this, but it's an hacky fix that does not handle all cases. This patch removes it.

fixes #43355.

r? @nikomatsakis

Needs a crater run
@bors
Copy link
Contributor

bors commented Dec 6, 2017

💔 Test failed - status-travis

@kennytm
Copy link
Member

kennytm commented Dec 6, 2017

@bors retry #44159

ERROR:  Could not find a valid gem 'aws-sdk-resources' (= 2.10.97) in any repository

@kennytm kennytm added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Dec 6, 2017
@bors
Copy link
Contributor

bors commented Dec 6, 2017

⌛ Testing commit 425c2c3 with merge 632ad19...

bors added a commit that referenced this pull request Dec 6, 2017
coherence: fix is_knowable logic

A trait-ref that passes the orphan-check rules can still be implemented in a crate downstream from our crate (for example, `LocalType for LocalTrait<_>` might be matched by a `LocalType for LocalTrait<TypeFromDownstreamCrate>`), and this should be known by the `is_knowable`  logic.

Trait selection had a hackfix for this, but it's an hacky fix that does not handle all cases. This patch removes it.

fixes #43355.

r? @nikomatsakis

Needs a crater run
@bors
Copy link
Contributor

bors commented Dec 6, 2017

☀️ Test successful - status-appveyor, status-travis
Approved by: nikomatsakis
Pushing 632ad19 to master...

@bors bors merged commit 425c2c3 into rust-lang:master Dec 6, 2017
aidanhs pushed a commit to aidanhs/sccache that referenced this pull request May 17, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Overlap checking with downstream impl is insufficient w.r.t. fundamental types; causes ICE
6 participants