These are chat archives for rust-lang/rust

4th
Jan 2017
Aleksey Kladov
@matklad
Jan 04 2017 07:22
@matanelevi works on my machine if I directly call rustc. Perhaps something is wrong with your Cargo config?
Matanel Levi
@matanelevi
Jan 04 2017 07:24
@matklad probably.. Thanks for checking :)
xialvjun
@xialvjun
Jan 04 2017 13:39
Box::new pub fn new(x: T) -> Box<T> It doesn't contain T: ?Sized, then why can we Box::new(move |x: i32| x + num)?
Swoorup Joshi
@Swoorup
Jan 04 2017 14:02
@matklad how does the compilation time compare
between C++ D and rust
my workflow heavily is edit and compile cycle
Diggory Blake
@Diggsey
Jan 04 2017 14:16
@xialvjun: closures are sized
each closure has its own anonymous type of sufficient size to hold all of the captured variables
xialvjun
@xialvjun
Jan 04 2017 14:25
thanks @Diggsey . Got it, it just like dynamic dispatch and static dispatch.
Diggory Blake
@Diggsey
Jan 04 2017 14:25
yeah, closures in rust will use static dispatch unless you box them
Aleksey Kladov
@matklad
Jan 04 2017 14:32
@Swoorup compile times are pretty terrible in Rust at the moment, though there's been a great progress recently and it is expected that they drop down radically for usual edit/compile cycle once precise incremental compilation is implemented.
Swoorup Joshi
@Swoorup
Jan 04 2017 14:54
so currently a single change triggers a whole recompilation?
i have read about that
Aleksey Kladov
@matklad
Jan 04 2017 14:56
The recompilation of a crate. Huge Rust projects usually split into several crates. And of course dependencies and stdlib are their own crates, so you don't recompile them.
Swoorup Joshi
@Swoorup
Jan 04 2017 15:01
i see, what about in comparison to C++ projects. C++ is especially problematic with includes
unless you do precompiled headers, forward declarations which are ugly and like a hack to me
compiling Rust from scratch took about the same time as C++.
Swoorup Joshi
@Swoorup
Jan 04 2017 15:08
rust is slightly better?
Aleksey Kladov
@matklad
Jan 04 2017 15:10
In my measurements that was the case, but I don't think that my single point of data is statistically significant :)
Swoorup Joshi
@Swoorup
Jan 04 2017 15:14
I am currently building a vulkan based renderer.
Have been looking into D mostly, but rust is taking away my attention right now
Aleksey Kladov
@matklad
Jan 04 2017 15:14
Are you using vulkano? https://github.com/tomaka/vulkano
Swoorup Joshi
@Swoorup
Jan 04 2017 15:15
nop,
its look very close to vulkan hpp
i was thinking to port vulkan-hpp to D, but I might just learn rust now
and use vulkano instead
Jonas Platte
@jplatte
Jan 04 2017 16:55
@Swoorup If you properly split your code into multiple crates, and none of them are ridiculously big, compilation times should be fine. I think fully compiling a small-ish rust crate takes about as long as recompiling half of a similar C++ code base because you changed some header file. So not that bad IMHO, especially considering it's being worked on very actively, and considering that heavy usage of generics in Rust doesn't increase compile times nearly as much as heavy usage of templates in C++.
Also cargo is very nice to work with, so it's actually quite easy to split your stuff into multiple crates for a better separation of concerns, and the added bonus of better recompile times.
Aleksey Kladov
@matklad
Jan 04 2017 16:59

@jplatte note however that generics in Rust work pretty similar to the templates in C++ compilation wise: because of the monopolization, the bulk of the work happens during the compilation of the crate than uses generics, even if they are defined in some other crate. There are some "mir-based optimization" which should ameliorate this issue, but they are not in stable yet, and even with then you have to codegen every time anyway.

And I 100% agree that Cargo and Rust modules/crate structure make physical design of libraries and application a pleasure!

Jonas Platte
@jplatte
Jan 04 2017 17:02
@matklad Yeah I know that Rust generates new code for every statically dispatched generic fn invocation, but doesn't it only do typeck + borrowck once, so it's still much better than C++? Or have I simply not seen huge compile times yet because I can't do metaprogramming yet in Rust? :D
Aleksey Kladov
@matklad
Jan 04 2017 17:06

but doesn't it only do typeck + borrowck once,

It does, but this doesn't help that much, because the bottleneck in the compiler is actually code generation. The idea of mir-based optimization is to optimize generics such that less IR is thrown to LLVM.

Jonas Platte
@jplatte
Jan 04 2017 17:44
Ahh, right. I heard sth. about the amount of LLVM IR generated being one of the major culprits for the current (clean) build times
Swoorup Joshi
@Swoorup
Jan 04 2017 18:14
@jplatte regarding times of increased compilation when a single header in C++ is changed, so in comparison with rust when changing small function or perhaps macro, this will now outdo C++ when incremental compilation are supported?
Jonas Platte
@jplatte
Jan 04 2017 18:15
Oh yeah with incremental compilation build times should be way better than in C++.
Swoorup Joshi
@Swoorup
Jan 04 2017 18:15
i have exactly this problem, and it irks me when i see people use all sorts of tricks like precompiled headers/ forward declaration to make their compilation faster in C++
John C F
@critiqjo
Jan 04 2017 19:05
Is it always safe to mem::transmute a reference of type T to a reference of type U which is a newtype of T (i.e. struct U(T);) since there won't be a change in memory layout?
If not, when is it not safe?
Alexander Ronald Altman
@pthariensflame
Jan 04 2017 20:31
It may not be safe (depending on details) if U has an explicit Drop impl.
John C F
@critiqjo
Jan 04 2017 20:33
But Drop will not be called, right? Since it is just a reference? What am I missing?
Aleksey Kladov
@matklad
Jan 04 2017 20:33
@critiqjo docs advice to go via pointers in this case: https://doc.rust-lang.org/std/mem/fn.transmute.html#alternatives
And nomicon says that "Transmuting between non-repr(C) types is UB" . Perhaps it's somehow possible to avoid transmute altogether in this case? Why do you need it?
John C F
@critiqjo
Jan 04 2017 20:47
@matklad Thanks! I haven't read that yet. I found this approach in tokio-proto crate. They do it to circumvent "inference problems" as they stated in the comments when dealing with "simple" pipeline/multiplex servers as "streaming" pipeline/multiplex servers. Of course they don't impl Drop for LiftProto. (See example uses).
Alexander Ronald Altman
@pthariensflame
Jan 04 2017 20:49
@critiqjo Consider the following code:
use std::mem;
struct T(i32);
struct U(T);
impl Drop for U {
    fn drop(&mut self) {
        println!("`U::drop` called with internal value {}.", (self.0).0)
    }
}
fn main() {
    let mut x: T = T(14);
    let x_ref: &mut T = &mut x;
    let y_ref: &mut U = unsafe { mem::transmute(x_ref) };
    let mut y = U(T(2));
    mem::swap(&mut y, y_ref);
    drop(y)
}
This will invoke the Drop impl for U, and you can play with it in here to confirm.
John C F
@critiqjo
Jan 04 2017 20:53
@pthariensflame Yes, but as I said, I'm not asking about transmuting the entire value. It's just the reference that is transmuted, like in the tokio-proto crate (linked above).
Alexander Ronald Altman
@pthariensflame
Jan 04 2017 20:53
Also, as demonstrated in the following snippet, it screws up lifetimes completely:
use std::mem;
fn main() {
    let mut x: i32 = 14;
    let x_ref: &mut i32 = &mut x;
    let _: &'static mut i32 = unsafe { mem::transmute(x_ref) };
    // The fact that this compiles without warnings is erroneous in itself.
}
@critiqjo transmute is only applied to a reference, in both snippets.
In fact, it’s doing exactly the same thing that tokio is in the linked code.
John C F
@critiqjo
Jan 04 2017 20:56
@pthariensflame In tokio code, the lifetime is preserved, and they are dealing with shared references.
Alexander Ronald Altman
@pthariensflame
Jan 04 2017 20:56
The only reason tokio’s usage is “safe” is that LiftProto has no Drop impl.
Also, yes, that the lifetime is preserved.
You asked when transmuting between a newtype and it’s representation was not okay; I gave an answer. :)
If you preserve lifetimes and don’t deal with Drop, even transmuting mutable references is okay.
John C F
@critiqjo
Jan 04 2017 20:57
Yes, I believe it is not okay to use it in a way that messes up the lifetimes!
Also, your examples makes it very clear to be very careful when dealing with mutable references...
When following that pattern shown in tokio, I believe it doesn't make sense to impl Drop for the newtype anyway.
So, thanks for pointing out the pitfalls! @pthariensflame
Alexander Ronald Altman
@pthariensflame
Jan 04 2017 23:30
NP!