Re: [rust-dev] instantiating parameterized impls

2013-09-06 Thread Niko Matsakis
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

2013-09-05 Thread David Renshaw
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

2013-09-05 Thread Tim Chevalier
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

2013-09-05 Thread Steven Blenkinsop
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