-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Need negative trait bound #42721
Comments
Negative bounds have a lot of issues. Like the fact that implementing a trait becomes a breaking change. There's some related discussion in rust-lang/rfcs#1834 . There's probably more discussion in the internals forum. |
Oh and you might want to have a look at specialization. I think it allows your case without the Pandora's box of issues that negative trait bounds brings with it. |
AFAICT #![feature(optin_builtin_traits)]
trait NotEq {}
impl NotEq for .. {}
impl<X> !NotEq for (X, X) {}
struct X<A>(A);
impl<A, B> From<X<B>> for X<A>
where
A: From<B>,
(A, B): NotEq,
{
fn from(a: X<B>) -> Self { X(a.0.into()) }
}
fn main() {} |
Does that works for a struct with (u8, u8)? Considering how oibit (Send/Sync) works, I don't think it would.. |
+1 I'm having trouble with implementing Debug for structs that have fields which are not Debug:
Another solution for my case would be if such a pattern could be implemented:
|
@axos88 This is already supported through specialization. #![feature(specialization)]
use std::fmt::{self, Debug};
enum MyOption<T> {
None,
Some(T)
}
impl<T> Debug for MyOption<T> {
default fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
MyOption::None => write!(f, "Unset"),
MyOption::Some(_) => write!(f, "An unprintable value"),
}
}
}
impl<T: Debug> Debug for MyOption<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
MyOption::None => write!(f, "Unset"),
MyOption::Some(t) => t.fmt(f),
}
}
}
struct Unprintable;
fn main() {
println!("{:?}", MyOption::Some(1234));
println!("{:?}", MyOption::Some(Unprintable));
println!("{:?}", MyOption::None::<Unprintable>);
} |
@kennethbgoodin more complicated use cases are not possible with trait specialization. For example: #![feature(specialization)]
trait Integer {
fn to_int(&self) -> i32;
}
trait Collection {
fn to_vec(&self) -> Vec<i32>;
}
trait PrintAnything {
fn print(&self) -> String;
}
impl<T> PrintAnything for T {
default fn print(&self) -> String {
format!("unprintable")
}
}
impl<T: Integer> PrintAnything for T {
fn print(&self) -> String {
format!("int {}", self.to_int())
}
}
impl<T: Collection> PrintAnything for T {
fn print(&self) -> String {
format!("collection {:?}", self.to_vec())
}
}
|
It is possible if specialization is enhanced to recognize intersection (previously attempted in #49624) i.e. impl<T> PrintAnything for T { ... }
impl<T: Integer> PrintAnything for T { ... }
impl<T: Collection> PrintAnything for T { ... }
impl<T: Integer + Collection> PrintAnything for T { ... } (If you need to specialize to N traits like these you'll need 2N impls) |
@kennytm That doesn't seem like a solution for anything with N >= 4... |
Would a subset of negative bounds be less problematic? For example, |
#68004 should probably be mentioned here. It's obviously not a complete negative bounds feature, and the motivation is largely unrelated, but it's a step in this direction. |
I have run into pretty much the same situation. |
Another example which requires negative trait bounds: trait Foo { .. }
trait Bar { .. }
impl<T: Foo> Bar for T { .. }
impl<T: Foo> Foo for &T { .. }
impl<T: Bar> Bar for &T { .. } I am not sure if specialization can help here. |
In my opinion, negative trait bounds is something we do need as a feature in the language along with specialization.
|
This could be address by mandating complementary implementations. So if you want to write something like impl<T: !Foo> Bar for T { \* ... *\ } you'd be forced to implement impl<T: Foo> Bar for T { \* ... *\ } Therefore implementing |
It's produces error:
May'be shall implement contruction:
The text was updated successfully, but these errors were encountered: