-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Conversation
a583d9e
to
b2302bb
Compare
b2302bb
to
5360699
Compare
@bors try |
⌛ Trying commit 5360699 with merge faf75254806fa54615158a9058c5a50b81dc8006... |
@bors r- retry |
⌛ Trying commit 5360699 with merge 999ab8e65bc12abb057c3e7ba58a538ae3ab7c57... |
@bors untry |
@bors retry |
⌛ Trying commit 5360699 with merge 0bac3d526df71b0959316897d8d8b8d1baf6b4f1... |
@bors try retry |
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
☀️ Test successful - status-travis |
Crater run started. |
c4ca8e3
to
11f22ab
Compare
☔ The latest upstream changes (presumably #46430) made this pull request unmergeable. Please resolve the merge conflicts. |
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) |
Regressions: crossbeam-epoch-0.1.0 & bow-1.0.3 (yay I broke Servo, but this is no longer a dependency)
This is a problem because any joker can write this (on nightly, but some variants are probably possible using #![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 I think the only fix is to not use glib v0.1.3
This causes a conflict because downstream crates can implement 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 ocl v0.15.0rusqlite v0.10.3rusqlcipher v0.14.6This is basically the same issue as impl<'a, E> From<E> for EventArray where E: Into<Event>
impl<'a, E> From<&'a E> for EventArray where E: Into<Event> + Clone
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)
This is a conflict because coherence can't see that 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() {} |
There was a problem hiding this 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.
src/librustc/traits/coherence.rs
Outdated
/// 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. |
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is wonderful.
@arielb1 this only issues warnings presently, right? Seems like we ought to land it, no? r=me, if you agree. |
Yea this only issues warnings. I'll land this. |
Patch as suggested by @arielb1: rust-lang/rust#46192 (comment)
I pushed a fix to lru-disk-cache in sccache, thanks for providing working code! |
@bors r=nikomatsakis |
📌 Commit 11f22ab has been approved by |
11f22ab
to
425c2c3
Compare
@bors r=nikomatsakis |
📌 Commit 425c2c3 has been approved by |
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
💔 Test failed - status-travis |
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
☀️ Test successful - status-appveyor, status-travis |
Patch as suggested by @arielb1: rust-lang/rust#46192 (comment)
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 aLocalType for LocalTrait<TypeFromDownstreamCrate>
), and this should be known by theis_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