Re: [rust-dev] Mutable files

2014-07-22 Thread Tobias Müller
Patrick Walton pcwal...@mozilla.com wrote:
 On 7/21/14 2:22 PM, Tobias Müller wrote:
 We discussed this with Bartosz literally for weeks (him being a fan of
 auto_ptr for too long, later completely converted against it and I take
 credit for that :o)). With auto_ptr this was possible:
 
 auto_ptrint a(new int);
 auto_ptrint b = a;
 
 It would nullify a with copy syntax. That code won't compile with
 unique_ptr; you'd need an explicit move(a).
 
 It only got worse from there: passing into functions, member variables...
 
 MOVING WITH COPY SYNTAX DOES NOT WORK.
 
 It's cut and dried.

Please don't snip the attribution, that was a quote!

 ... in C++. Not in Rust. That's because, unlike C++, Rust is designed 
 from the ground up to support moves and copies in a first class way.
 
 It's just strange that you can change the semantic of an already existing
 operation just by adding new capabilities. Adding traits should define new
 operations with new semantics, not changing the semantics of existing
 operations. At least that's how it works for all other traits, and
 deviating from that is at least surprising.
 
 Hence the Opt-In Built-In Traits proposal

Opt-In built-In traits makes things a bit better but my point is still
valid. By adding Copy (implicitly or explicitly) you remove the possibility
of move semantics from the type.
Usually you don't work alone on a project and some coworker adding Copy to
a type that I expected to be Move may be fatal.

No other trait removed works like that.

 Maybe the syntax was just too heavy?
 
 Any syntax at all is too much. I am convinced of that.

I'm still not convinced but maybe my fear is unjustified. Time will tell.

Tobi

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Mutable files

2014-07-22 Thread Val Markovic
On Mon, Jul 21, 2014 at 2:45 PM, Patrick Walton pcwal...@mozilla.com
wrote:


  ... in C++. Not in Rust. That's because, unlike C++, Rust is designed
 from the ground up to support moves and copies in a first class way.


As a C++ dev, I feel the need to say THANK YOU for that. Rust being
designed with first-class move support is a major feature for me; it's
something I highlight when I talk about Rust with other C++ devs and it's
universally applauded.




  It's just strange that you can change the semantic of an already existing
 operation just by adding new capabilities. Adding traits should define new
 operations with new semantics, not changing the semantics of existing
 operations. At least that's how it works for all other traits, and
 deviating from that is at least surprising.


 Hence the Opt-In Built-In Traits proposal


  Maybe the syntax was just too heavy?


 Any syntax at all is too much. I am convinced of that.

 Patrick


 ___
 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


Re: [rust-dev] Mutable files

2014-07-22 Thread Huon Wilson

On 23/07/14 07:10, Tobias Müller wrote:



... in C++. Not in Rust. That's because, unlike C++, Rust is designed
from the ground up to support moves and copies in a first class way.


It's just strange that you can change the semantic of an already existing
operation just by adding new capabilities. Adding traits should define new
operations with new semantics, not changing the semantics of existing
operations. At least that's how it works for all other traits, and
deviating from that is at least surprising.

Hence the Opt-In Built-In Traits proposal

Opt-In built-In traits makes things a bit better but my point is still
valid. By adding Copy (implicitly or explicitly) you remove the possibility
of move semantics from the type.
Usually you don't work alone on a project and some coworker adding Copy to
a type that I expected to be Move may be fatal.

No other trait removed works like that.


You can't just add Copy to anything: the contents has to be Copy itself, 
and, you can't have a destructor on your type (i.e. a Drop 
implementation removes the possibility to be Copy). Thus, almost all 
types for which by-value uses *should* invalidate the source (i.e. move 
semantics) are automatically not Copy anyway.


The only way one can get a fatal error due to an incorrect Copy 
implementation is if the type with the impl is using `unsafe` code 
internally. In this case, that whole API needs to be considered very 
carefully anyway, ensuring correctness by avoiding Copy is just part of it.



I'll also note that an implementation of Copy just states the a 
byte-copy of a value is also a semantic copy, it doesn't offer any 
control over how the copy is performed. At runtime, by-value use of a 
Copy type is essentially identical to a by-value use of a non-Copy type 
(both are memcpy's of the bytes), the only major difference is the 
compiler statically prevents further uses of the source for non-Copy ones.



Huon
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Mutable files

2014-07-21 Thread David Henningsson



On 2014-07-21 06:06, Patrick Walton wrote:

On 7/20/14 9:04 PM, Patrick Walton wrote:

On 7/20/14 8:12 PM, David Henningsson wrote:

Cool, thanks for the answer. These restrictions seem somewhat complex.


They are required. Otherwise we would end up with a C++-like situation
where copies end up happening too frequently.


Also note that these rules, far from being complex, end up making the
language much simpler than C++, as copy (or D-like postblit)
constructors are not required. All Rust types, if they are copyable at
all, can be copied by simply moving bits around.


Fair enough. I just guess it takes a while getting used to, that you 
sometimes can't use a variable after you've sent it as a parameter to a 
function.


Also now having read the RFC for Opt-in builtin traits which you 
mentioned earlier, I think this RFC makes a lot of sense. Especially the 
API Stability and Pedagogy points would have been helpful here.


// David
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Mutable files

2014-07-21 Thread Patrick Walton

On 7/21/14 8:49 AM, Tobias Müller wrote:

Patrick Walton pcwal...@mozilla.com wrote:

On 7/20/14 8:12 PM, David Henningsson wrote:

  From a language design perspective, maybe it would be more intuitive to
have different syntaxes for copy and move, like:


As a rust newbie, that aspect aways makes me a bit nervous. Two quite
different operations with the same syntax and and simply changing a detail
in the struct can be enough to switch between the two.


This is the reason for Opt-In Built-In Traits.


AFAIK this also was one of the reasons (if not _the_ reason) why
std::auto_ptr was deprecated in C++.


No, `auto_ptr` was deprecated because it copies, not moves, making it 
hard to sensibly use in containers (among other things).


Comparisons between C++ aren't really relevant anyway because the 
compiler catches any use-after-move at *compile time*, rather than at 
runtime. This means that mistaking the two doesn't cause any harm:


* Causing a move when you thought you were copying results in a compiler 
error.


* Causing a copy when you thought you were moving is harmless, as any 
implicit copy in Rust has *exactly the same runtime semantics* as a 
move, except that the compiler prevents you from using the value again.


Again, we had that world before. It was extremely annoying to write 
move all over the place. Be careful what you wish for.


Patrick

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Mutable files

2014-07-21 Thread Tobias Müller
Patrick Walton pcwal...@mozilla.com wrote:
 On 7/21/14 8:49 AM, Tobias Müller wrote:
 As a rust newbie, that aspect aways makes me a bit nervous. Two quite
 different operations with the same syntax and and simply changing a detail
 in the struct can be enough to switch between the two.
 
 This is the reason for Opt-In Built-In Traits.
 
 AFAIK this also was one of the reasons (if not _the_ reason) why
 std::auto_ptr was deprecated in C++.
 
 No, `auto_ptr` was deprecated because it copies, not moves, making it 
 hard to sensibly use in containers (among other things).

Quoting Andrei Alexandrescu on digitalmars.d:

We discussed this with Bartosz literally for weeks (him being a fan of
auto_ptr for too long, later completely converted against it and I take
credit for that :o)). With auto_ptr this was possible:

auto_ptrint a(new int); 
auto_ptrint b = a;

It would nullify a with copy syntax. That code won't compile with
unique_ptr; you'd need an explicit move(a).

It only got worse from there: passing into functions, member variables...

MOVING WITH COPY SYNTAX DOES NOT WORK.

It's cut and dried.

Andrei
-

But you are right, Rust is not C++, it's actually the other way round that
makes me nervous.

 Comparisons between C++ aren't really relevant anyway because the 
 compiler catches any use-after-move at *compile time*, rather than at 
 runtime. This means that mistaking the two doesn't cause any harm:
 
 * Causing a move when you thought you were copying results in a compiler 
 error.

 * Causing a copy when you thought you were moving is harmless, as any 
 implicit copy in Rust has *exactly the same runtime semantics* as a 
 move, except that the compiler prevents you from using the value again.

From a performance point of view that may be true, but you may lose desired
semantics.

If you want an instance of a type to be move-only, but later decide that
copying that type is still useful in another place, then you lose the
guarantee in the first place.

It's just strange that you can change the semantic of an already existing
operation just by adding new capabilities. Adding traits should define new
operations with new semantics, not changing the semantics of existing
operations. At least that's how it works for all other traits, and
deviating from that is at least surprising.

 Again, we had that world before. It was extremely annoying to write 
 move all over the place. Be careful what you wish for.

Maybe the syntax was just too heavy?

Tobi

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Mutable files

2014-07-21 Thread Patrick Walton

On 7/21/14 2:22 PM, Tobias Müller wrote:

We discussed this with Bartosz literally for weeks (him being a fan of
auto_ptr for too long, later completely converted against it and I take
credit for that :o)). With auto_ptr this was possible:

auto_ptrint a(new int);
auto_ptrint b = a;

It would nullify a with copy syntax. That code won't compile with
unique_ptr; you'd need an explicit move(a).

It only got worse from there: passing into functions, member variables...

MOVING WITH COPY SYNTAX DOES NOT WORK.

It's cut and dried.


... in C++. Not in Rust. That's because, unlike C++, Rust is designed 
from the ground up to support moves and copies in a first class way.



It's just strange that you can change the semantic of an already existing
operation just by adding new capabilities. Adding traits should define new
operations with new semantics, not changing the semantics of existing
operations. At least that's how it works for all other traits, and
deviating from that is at least surprising.


Hence the Opt-In Built-In Traits proposal


Maybe the syntax was just too heavy?


Any syntax at all is too much. I am convinced of that.

Patrick

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


[rust-dev] Mutable files

2014-07-20 Thread David Henningsson

Hi,

Consider these two examples:

1)

let mut file = File::open(filename);
file.read(buf);

2)

let file = File::open(filename);
let mut reader = BufferedReader::new(file);
reader.read(buf);

My question is: in example 2, why doesn't BufferedReader need file to 
be mutable? After all, BufferedReader ends up calling file.read(), which 
needs a mutable reference to the file.


It looks like I'm able to bypass the mutability requirement, just 
because I wrap the file inside a BufferedReader?


// David
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Mutable files

2014-07-20 Thread Corey Richardson
That's right. `BufferedReader` takes the `Reader` it wraps by-value,
but the `read` method takes `mut self`. Moving something doesn't
require it to be stored in a mutable variable, but taking a `mut` to
it does.

On Sun, Jul 20, 2014 at 6:29 PM, David Henningsson di...@ubuntu.com wrote:
 Hi,

 Consider these two examples:

 1)

 let mut file = File::open(filename);
 file.read(buf);

 2)

 let file = File::open(filename);
 let mut reader = BufferedReader::new(file);
 reader.read(buf);

 My question is: in example 2, why doesn't BufferedReader need file to be
 mutable? After all, BufferedReader ends up calling file.read(), which needs
 a mutable reference to the file.

 It looks like I'm able to bypass the mutability requirement, just because
 I wrap the file inside a BufferedReader?

 // David
 ___
 Rust-dev mailing list
 Rust-dev@mozilla.org
 https://mail.mozilla.org/listinfo/rust-dev



-- 
http://octayn.net/
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Mutable files

2014-07-20 Thread Patrick Walton

On 7/20/14 6:29 PM, David Henningsson wrote:

Hi,

Consider these two examples:

1)

let mut file = File::open(filename);
file.read(buf);

2)

let file = File::open(filename);
let mut reader = BufferedReader::new(file);
reader.read(buf);

My question is: in example 2, why doesn't BufferedReader need file to
be mutable? After all, BufferedReader ends up calling file.read(), which
needs a mutable reference to the file.

It looks like I'm able to bypass the mutability requirement, just
because I wrap the file inside a BufferedReader?


Because `BufferedReader::new` moves `file` and takes ownership of it. 
(You can see this if you try to use `file` again: the compiler will 
prevent you.) Mutability is inherited through ownership in Rust: that 
is, the current owner determines the mutability of a piece of data. So, 
the mutability of `reader` determines the mutability of the `File` 
object at the time you try to read, and the mutability restriction is 
satisfied.


Patrick

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Mutable files

2014-07-20 Thread David Henningsson



On 2014-07-21 03:33, Patrick Walton wrote:

On 7/20/14 6:29 PM, David Henningsson wrote:

Hi,

Consider these two examples:

1)

let mut file = File::open(filename);
file.read(buf);

2)

let file = File::open(filename);
let mut reader = BufferedReader::new(file);
reader.read(buf);

My question is: in example 2, why doesn't BufferedReader need file to
be mutable? After all, BufferedReader ends up calling file.read(), which
needs a mutable reference to the file.

It looks like I'm able to bypass the mutability requirement, just
because I wrap the file inside a BufferedReader?


Because `BufferedReader::new` moves `file` and takes ownership of it.
(You can see this if you try to use `file` again: the compiler will
prevent you.) Mutability is inherited through ownership in Rust: that
is, the current owner determines the mutability of a piece of data. So,
the mutability of `reader` determines the mutability of the `File`
object at the time you try to read, and the mutability restriction is
satisfied.


Thanks for the quick answer!

I did two more examples to try to understand when things are moved:

3)
struct Dummy {
  foo: int,
  bar: int
}

let f = Dummy {foo: 10, bar: 5};
let mut g = f; // Here the assignment copies..?
println!({}, f.foo + g.foo); // Ok

4)

let f = File::open(filename);
let mut g = f; // Here the assignment moves..?
f.tell(); // Fails - use of moved value

How come that the assignment moves in example 4), and copies in example 3)?

// David
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Mutable files

2014-07-20 Thread Patrick Walton
Because Foo is a POD type (implements the Copy trait). Essentially, types that 
can be copied by copying bits only (not allocating) are POD types, and all 
others move.

This may be changed with the Opt-In Built-in Traits proposal so that POD types 
must be specially declared to implement Copy before they will copy.

Patrick

On July 20, 2014 7:39:35 PM PDT, David Henningsson di...@ubuntu.com wrote:


On 2014-07-21 03:33, Patrick Walton wrote:
 On 7/20/14 6:29 PM, David Henningsson wrote:
 Hi,

 Consider these two examples:

 1)

 let mut file = File::open(filename);
 file.read(buf);

 2)

 let file = File::open(filename);
 let mut reader = BufferedReader::new(file);
 reader.read(buf);

 My question is: in example 2, why doesn't BufferedReader need file
to
 be mutable? After all, BufferedReader ends up calling file.read(),
which
 needs a mutable reference to the file.

 It looks like I'm able to bypass the mutability requirement, just
 because I wrap the file inside a BufferedReader?

 Because `BufferedReader::new` moves `file` and takes ownership of it.
 (You can see this if you try to use `file` again: the compiler will
 prevent you.) Mutability is inherited through ownership in Rust: that
 is, the current owner determines the mutability of a piece of data.
So,
 the mutability of `reader` determines the mutability of the `File`
 object at the time you try to read, and the mutability restriction is
 satisfied.

Thanks for the quick answer!

I did two more examples to try to understand when things are moved:

3)
struct Dummy {
   foo: int,
   bar: int
}

let f = Dummy {foo: 10, bar: 5};
let mut g = f; // Here the assignment copies..?
println!({}, f.foo + g.foo); // Ok

4)

let f = File::open(filename);
let mut g = f; // Here the assignment moves..?
f.tell(); // Fails - use of moved value

How come that the assignment moves in example 4), and copies in example
3)?

// David

-- 
Sent from my Android phone with K-9 Mail. Please excuse my brevity.___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Mutable files

2014-07-20 Thread Steven Fackler
Some types are implicitly copyable. They implement the built-in trait Copy.
A type is Copy if it is

a) numeric primitive (e.g. f32 or uint), or
b) an immutable reference (e.g. Foo or str), or
c) a raw pointer (e.g. *const Foo or *mut Foo), or
d) a collection of Copy types (e.g. struct Foo { a: int, b: 'static str }).

In addition, if a type implements Drop, it is no longer Copy.

Steven Fackler


On Sun, Jul 20, 2014 at 7:39 PM, David Henningsson di...@ubuntu.com wrote:



 On 2014-07-21 03:33, Patrick Walton wrote:

 On 7/20/14 6:29 PM, David Henningsson wrote:

 Hi,

 Consider these two examples:

 1)

 let mut file = File::open(filename);
 file.read(buf);

 2)

 let file = File::open(filename);
 let mut reader = BufferedReader::new(file);
 reader.read(buf);

 My question is: in example 2, why doesn't BufferedReader need file to
 be mutable? After all, BufferedReader ends up calling file.read(), which
 needs a mutable reference to the file.

 It looks like I'm able to bypass the mutability requirement, just
 because I wrap the file inside a BufferedReader?


 Because `BufferedReader::new` moves `file` and takes ownership of it.
 (You can see this if you try to use `file` again: the compiler will
 prevent you.) Mutability is inherited through ownership in Rust: that
 is, the current owner determines the mutability of a piece of data. So,
 the mutability of `reader` determines the mutability of the `File`
 object at the time you try to read, and the mutability restriction is
 satisfied.


 Thanks for the quick answer!

 I did two more examples to try to understand when things are moved:

 3)
 struct Dummy {
   foo: int,
   bar: int
 }

 let f = Dummy {foo: 10, bar: 5};
 let mut g = f; // Here the assignment copies..?
 println!({}, f.foo + g.foo); // Ok

 4)

 let f = File::open(filename);
 let mut g = f; // Here the assignment moves..?
 f.tell(); // Fails - use of moved value

 How come that the assignment moves in example 4), and copies in example 3)?

 // 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


Re: [rust-dev] Mutable files

2014-07-20 Thread David Henningsson



On 2014-07-21 04:43, Steven Fackler wrote:

Some types are implicitly copyable. They implement the built-in trait
Copy. A type is Copy if it is

a) numeric primitive (e.g. f32 or uint), or
b) an immutable reference (e.g. Foo or str), or
c) a raw pointer (e.g. *const Foo or *mut Foo), or
d) a collection of Copy types (e.g. struct Foo { a: int, b: 'static str }).

In addition, if a type implements Drop, it is no longer Copy.

Steven Fackler


Cool, thanks for the answer. These restrictions seem somewhat complex.

This wasn't very intuitive for me, so just throwing this out (feel free 
to ignore if it has already been discussed :-) )


From a language design perspective, maybe it would be more intuitive to 
have different syntaxes for copy and move, like:


let mut g = f; /* Copies from f to g, error if f is a non-Copy type */

let mut g - f; /* Moves from f to g, error if trying to use f afterwards */

Or in the File/BufferedReader example, this would be something like:

let f = File::open(filename);
let mut reader = BufferedReader::new(- f); /* Bye bye f! */

I'm also afraid that if a library struct decides to change between a 
copy and non-copy type, this would cause subtle errors in users of that 
library that expected the other type. But if the compiler is guaranteed 
to catch all such errors even with today's handling, maybe that is not 
too much to worry about.






On Sun, Jul 20, 2014 at 7:39 PM, David Henningsson di...@ubuntu.com
mailto:di...@ubuntu.com wrote:



On 2014-07-21 03:33, Patrick Walton wrote:

On 7/20/14 6:29 PM, David Henningsson wrote:

Hi,

Consider these two examples:

1)

let mut file = File::open(filename);
file.read(buf);

2)

let file = File::open(filename);
let mut reader = BufferedReader::new(file);
reader.read(buf);

My question is: in example 2, why doesn't BufferedReader
need file to
be mutable? After all, BufferedReader ends up calling
file.read(), which
needs a mutable reference to the file.

It looks like I'm able to bypass the mutability
requirement, just
because I wrap the file inside a BufferedReader?


Because `BufferedReader::new` moves `file` and takes ownership
of it.
(You can see this if you try to use `file` again: the compiler will
prevent you.) Mutability is inherited through ownership in Rust:
that
is, the current owner determines the mutability of a piece of
data. So,
the mutability of `reader` determines the mutability of the `File`
object at the time you try to read, and the mutability
restriction is
satisfied.


Thanks for the quick answer!

I did two more examples to try to understand when things are moved:

3)
struct Dummy {
   foo: int,
   bar: int
}

let f = Dummy {foo: 10, bar: 5};
let mut g = f; // Here the assignment copies..?
println!({}, f.foo + g.foo); // Ok

4)

let f = File::open(filename);
let mut g = f; // Here the assignment moves..?
f.tell(); // Fails - use of moved value

How come that the assignment moves in example 4), and copies in
example 3)?

// David

_
Rust-dev mailing list
Rust-dev@mozilla.org mailto:Rust-dev@mozilla.org
https://mail.mozilla.org/__listinfo/rust-dev
https://mail.mozilla.org/listinfo/rust-dev



___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Mutable files

2014-07-20 Thread Patrick Walton

On 7/20/14 8:12 PM, David Henningsson wrote:

Cool, thanks for the answer. These restrictions seem somewhat complex.


They are required. Otherwise we would end up with a C++-like situation 
where copies end up happening too frequently.



This wasn't very intuitive for me, so just throwing this out (feel free
to ignore if it has already been discussed :-) )

 From a language design perspective, maybe it would be more intuitive to
have different syntaxes for copy and move, like:


There used to be a unary move operator. This was a huge pain.

match move x {
Some(move y) = foo(move z);
}

And so on. I don't want to go back to that world.

Patrick

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Mutable files

2014-07-20 Thread Patrick Walton

On 7/20/14 9:04 PM, Patrick Walton wrote:

On 7/20/14 8:12 PM, David Henningsson wrote:

Cool, thanks for the answer. These restrictions seem somewhat complex.


They are required. Otherwise we would end up with a C++-like situation
where copies end up happening too frequently.


Also note that these rules, far from being complex, end up making the 
language much simpler than C++, as copy (or D-like postblit) 
constructors are not required. All Rust types, if they are copyable at 
all, can be copied by simply moving bits around.


Patrick

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev