Re: [rust-dev] instantiating parameterized impls
Hi David, My current thinking on the matter is that eventually, I would like to take advantage of the coherence rules to permit a program like this. Coherence means that given a specific type T and trait U, we can always tell whether T implements U. This implies that we could do the check as you described it. However, implementing this is a bit far off. I think it is best done as part of a general rewrite of the trait and method resolution code. I have started that, but put it on hold to deal with #6801 (borrowck treatment of closures) and then the treatment of moves and zeroing (#5016). Also, I am not sure how much of this has been discussed and agreed to. One of my longstanding to do items is to write up my thinking on trait resolution as a blog post and then discuss at a meeting. You are giving me some motivation to do that, since I'd love to be able to point you to a fully explained blog post :) Niko On Thu, Sep 05, 2013 at 09:29:59AM -0700, David Renshaw wrote: Hi, When I try to compile the below program, why do I get a conflicting implementations error? I do not define any implementations of Bar, so the parameterized impl of Foo should never get instantiated, right? --- trait Foo { fn foo() - Self; } trait Bar : std::num::Zero { } impl T : Bar Foo for T { fn foo() - T { std::num::Zero::zero() } } impl Foo for u16 { fn foo () - u16 { 100 } } fn main() { // should be 100 let x : u16 = Foo::foo(); printfln!(%s, x); } // error: conflicting implementations for trait `Foo` -- When I asked about this on IRC, cmr indicated that this is probably the intended behavior of rustc, but that most people want to change it. Is that true, and when can we expect a fix? Thanks, David ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
[rust-dev] instantiating parameterized impls
Hi, When I try to compile the below program, why do I get a conflicting implementations error? I do not define any implementations of Bar, so the parameterized impl of Foo should never get instantiated, right? --- trait Foo { fn foo() - Self; } trait Bar : std::num::Zero { } impl T : Bar Foo for T { fn foo() - T { std::num::Zero::zero() } } impl Foo for u16 { fn foo () - u16 { 100 } } fn main() { // should be 100 let x : u16 = Foo::foo(); printfln!(%s, x); } // error: conflicting implementations for trait `Foo` -- When I asked about this on IRC, cmr indicated that this is probably the intended behavior of rustc, but that most people want to change it. Is that true, and when can we expect a fix? Thanks, David ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] instantiating parameterized impls
On Thu, Sep 5, 2013 at 9:29 AM, David Renshaw dwrens...@gmail.com wrote: Hi, When I try to compile the below program, why do I get a conflicting implementations error? I do not define any implementations of Bar, so the parameterized impl of Foo should never get instantiated, right? --- trait Foo { fn foo() - Self; } trait Bar : std::num::Zero { } impl T : Bar Foo for T { fn foo() - T { std::num::Zero::zero() } } impl Foo for u16 { fn foo () - u16 { 100 } } fn main() { // should be 100 let x : u16 = Foo::foo(); printfln!(%s, x); } // error: conflicting implementations for trait `Foo` -- The reason is that there is no guarantee that you will never use this code in a context where another module defines an impl of Bar for u16. In that scenario, you would have two different impls of Foo for u16, and no way to disambiguate. In Haskell, this is called the overlapping instances problem; it happens because traits in Rust, and type classes in Haskell, are open rather than closed (when you define a trait, you don't have any way of knowing all the impls of it for a particular type). When I asked about this on IRC, cmr indicated that this is probably the intended behavior of rustc, but that most people want to change it. Is that true, and when can we expect a fix? I'm not sure that most people want to change it. Handling the issue in general is quite subtle (see http://web.cecs.pdx.edu/~jgmorris/pubs/morris-icfp2010-instances.pdf ). One workaround is to use newtypes: struct WrapperT { x: T } ... impl T: Bar Foo for WrapperT { ... and then there's no ambiguity. Cheers, Tim -- Tim Chevalier * http://catamorphism.org/ * Often in error, never in doubt Being queer is not about a right to privacy; it is about the freedom to be public, to just be who we are. -- anonymous, June 1990 ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] instantiating parameterized impls
On Thu, Sep 5, 2013 at 3:36 PM, Tim Chevalier catamorph...@gmail.comwrote: The reason is that there is no guarantee that you will never use this code in a context where another module defines an impl of Bar for u16. In that scenario, you would have two different impls of Foo for u16, and no way to disambiguate. In Haskell, this is called the overlapping instances problem; it happens because traits in Rust, and type classes in Haskell, are open rather than closed (when you define a trait, you don't have any way of knowing all the impls of it for a particular type). Strictly speaking, you know about all impls of Bar for all types available to your crate when you compile your crate, and if you own Bar, then you even know that new impls can't be introduced in your dependencies which could break your code. You could even have `impl T: Bar Foo for T` and `implT: Baz Foo for T`, as long as you own at least one of Bar or Baz, since it is then possible for the compiler to know that types in other crates which depend on yours can't implement both. Its just a matter of how smart you want the compiler to be, and how much you want to avoid changes up the dependency chain being able to break things down the dependency chain (which isn't entirely avoidable anyways). ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev