These are chat archives for rust-lang/rust

17th
Oct 2018
John
@gitlabaccount624_gitlab
Oct 17 2018 04:45
hi
there's no way i need to use an external crate just to get the current unix timestamp right?
John
@gitlabaccount624_gitlab
Oct 17 2018 05:05
uh oh
John
@gitlabaccount624_gitlab
Oct 17 2018 05:46
looks like it returns a SystemTime and not milliseconds/seconds?
trsh
@trsh
Oct 17 2018 07:30
What would be the best strategy to cut of a part of mutable vector?
Lyle Mantooth
@IslandUsurper
Oct 17 2018 14:24
@gitlabaccount624_gitlab, but it's easy to get the duration since UNIX_EPOCH, and you can get seconds or milliseconds (or nanoseconds!) from a Duration.
its one of the good 'ol trait object issues ;)
i'm unsure how to modify the trait function to make it to compile
the issue here as adviced by compiler is that the Trait function takes generic arguments
Denis Lisov
@tanriol
Oct 17 2018 15:16
Yeah, trait objects don't support that. What are you trying to do?
Kris
@VersBinarii
Oct 17 2018 15:18
Well, i was hoping i can make a generic function that simply can take any object implementing specific trait
so in this particular case the function would take a writer object
and the writer could be a console writer, JSON writer, file writer etc...
it just that im my particular case that data the trait function would take must implement some additional traits
hence the where T: Display+ OtherTrait<V>;
Kris
@VersBinarii
Oct 17 2018 15:24
so is this the only reason i cannot do this is because the trait function takes generic parameters?
Denis Lisov
@tanriol
Oct 17 2018 15:33
Not sure about "only", but that's a reason.
Kris
@VersBinarii
Oct 17 2018 15:35
hmmm, ok. I see what you mean.
Thanks for looking at this
i'll try to restructure the code in that case
Ichoran
@Ichoran
Oct 17 2018 15:35
Is there a workaround, or some docs that explain what you can and can't do with dyn Trait? I've run into similar issues before, and kinda worked around them, but not in any sort of intelligent way.
Denis Lisov
@tanriol
Oct 17 2018 15:37
You may be able to do roughly that if the parts of Display + OtherTrait<V> you need can be used as a trait object themselves, for example.
Ichoran
@Ichoran
Oct 17 2018 15:37
I haven't found a good source to clarify my mental model of what can be done with closures and dyn Trait and generics. I try to map it onto my model of, say, JVM class-based functions, and I get surprised all the time.
Lyle Mantooth
@IslandUsurper
Oct 17 2018 15:40
If you ever find one, I'd be interested in it too. Object-safety has never made sense to me why it is what it is, so I haven't even tried using dyn Trait anywhere.
Denis Lisov
@tanriol
Oct 17 2018 15:45
Have you already seen the object safety RFC?
As for "why", it's all pretty obvious if you have low-level language background. Basically, a trait object is represented internally as a tuple (object_ptr, vtable_ptr). Thus an object-safe trait is limited to what can be represented with these. For example, a generic method cannot be used through a vtable (vtable stores pointers to methods, but a generic method is actually a family of methods for different types, and you cannot generate every possible implementation).
Ichoran
@Ichoran
Oct 17 2018 15:51
A generic method absolutely can be implemented through a vtable; Java does it all the time. But you have to use only the vtable that you say the generic parameter has.
So I guess that Rust won't do that transformation of generic functions for you, from generic to erased?
(That is, in order to call a generic method you need to have an erased version of that generic method that is specialized to take and/or return the (object_ptr, vtable_ptr) version of the generic argument.)
Denis Lisov
@tanriol
Oct 17 2018 15:57
I guess it won't. This transformation is likely to be a potential footgun wrt performance - something that JIT is likely to specialize on the fly, but not so easy for compiled languages.
Ichoran
@Ichoran
Oct 17 2018 16:00
I suppose so, but I haven't found a good way to methodically do the manual transformation in cases where the loss in performance is acceptable. Then again, I didn't clearly recognize that's what was needed until a few seconds ago, so maybe I'll do better now :)
Ichoran
@Ichoran
Oct 17 2018 17:38
Is there a good way to do map on an array? That is, if you have some function A -> B and an array of type [A; n], can you get [B; n]?
I found https://llogiq.github.io/2016/04/28/arraymap.html but is there something built-in (yet?)?
Sylwester Rąpała
@xoac
Oct 17 2018 17:51
Hi I would need someone help that know unix (linux) nad libc. I want add support for RS485 to libc. I create rust-lang/libc#1095 that contains this definitions for musl tag source. I don't know how to define them for glibc (this should be defined here src/unix/notbsd/linux/other/*? or somewhere else
Ford
@fordN
Oct 17 2018 17:59
@Ichoran you can create an iterator over the Vector, map it, and then collect it back into a Vector....let a = [1, 2, 3]; let doubled = a.iter().map(|x| x * 2).collect::<Vec<i32>>();
Ichoran
@Ichoran
Oct 17 2018 17:59
Unfortunately, I actually do mean an array, not a Vec.
That is, doubled needs to have type [i32; 3] not Vec<i32>.
Ford
@fordN
Oct 17 2018 18:17
ahh i see. have you tried something like this turbofish instead::<[i32; 3]>()? or the equivalent on the left side. ... let doubled: [i32: 3] = a.iter.....
Ichoran
@Ichoran
Oct 17 2018 18:26
You can't collect from an iterator into an array because you don't know that the size is correct.
IslandUsurper @IslandUsurper thinks, "But ExactSizeIterator is a thing."
Lyle Mantooth
@IslandUsurper
Oct 17 2018 18:28
But that's still a dynamic size, not a static one like arrays.
Kris
@VersBinarii
Oct 17 2018 18:39
Hello again, so i changed the code a little bit to overcome the issue with the trait objects
i ended up however with something llike this: Vec<Box<Item>>
and i'm in need of implementing a Clone for this
so i camu up with the following:
impl Clone for Box<Item> { fn clone(&self) -> Box<Item> { self.clone() } }
It compiles and the program seem to be working i do however get:

[rustc]
function cannot return without recursing

cannot return without recursing

Kris
@VersBinarii
Oct 17 2018 18:45
Am i doing something stupid or is there a better way of implementing a Clone for Box<Trait>
Ichoran
@Ichoran
Oct 17 2018 18:46
That's not how you want to clone it. You want to Box::new(*self).
What you wrote just calls itself infinitely--you clone a boxed item by cloning the boxed item. Oops!
Er, maybe Box::new(*self.deref().clone()).
Ichoran
@Ichoran
Oct 17 2018 18:52
Except you don't need to if Item is clone(), which I guess it isn't?
Kris
@VersBinarii
Oct 17 2018 18:53
Both versions give me the:

the trait bound &dyn Item: Item is not satisfied

the trait Item is not implemented for &dyn Item

note: required for the cast to the object type dyn Item

Yes, the item objects that implement Item trait are Clone
Ichoran
@Ichoran
Oct 17 2018 18:57
Okay, but in general a dyn Trait is not Clone, I think.
Is there a reason you can't borrow?
Kris
@VersBinarii
Oct 17 2018 19:02
well... i obviously i try to borrow as much as possible. But, since i'm still kinda new to Rust, sometimes Borrow Checker goes into berserk mode. So i a clone is a way out :)
Ichoran
@Ichoran
Oct 17 2018 19:03
In general I try to avoid dyn Trait because I don't understand the rules surrounding it deeply enough.
Kris
@VersBinarii
Oct 17 2018 19:06
Yes. I guess i try to use this sort of stuff to build some sort of familiarity with it
I must say that the generics in Rust are not the easiest to use
at least for me
Ichoran
@Ichoran
Oct 17 2018 19:06
I think the generics are not so hard, but the dynamic dispatch is.
Kris
@VersBinarii
Oct 17 2018 19:07
yes
true
i understand where does the issues come from
and how strict the compiler must be to ensure all the safety
Ichoran
@Ichoran
Oct 17 2018 19:08
I'm used to languages (e.g. Scala) where everything is taken care of for me; all the fiddly details about allocation and erasure and so on are provided automatically by the language and I don't need to think through each step, and then when I do think through the steps I usually have to back off yet further because Rust is more conservative than is strictly necessary due to it being easier to implement and/or understand.
So I mostly try to ignore that whole part unless it's really critical.
Using generics explicitly with borrowing and all the rest still leaves a really lovely subset of the language.
Kris
@VersBinarii
Oct 17 2018 19:11
What i have found so far, which i thinkg is really great, is that whenever i come against some compiler obstacle
when i take a step back and tinker a bit with restructuring the code
i usually end up with a better overal structure
Ichoran
@Ichoran
Oct 17 2018 19:11
Yeah, I usually (not always!) find that stepping back and redoing things in a way that is more idiomatic for Rust results in better code overall.
Not always--there are some really useful idioms from other languages that are awkward or impossible in Rust--but it's rare enough so it's a minor irritation, not a major roadblock for getting things done.
Kris
@VersBinarii
Oct 17 2018 19:14
Yep. I come from C and Python. So i'm used to quickly coming up with some working proof of concept and then refining it later
this approach rarely work with Rust
;)
i keep however coming back to it
John
@gitlabaccount624_gitlab
Oct 17 2018 22:39
when does unsafe end?
like i made an unsafe function but to call it i need to wrap the call in unsafe as well. hmm?
i assume rust has unsafe code in it and i don't have to prefix every call to std with unsafe so .. uhh.. how's that work?
like, i have to wrap the function in unsafe, and the call to the function in unsafe, but not the call to THAT function in unsafe. why's it end there as opposed to go on forever?
Ichoran
@Ichoran
Oct 17 2018 22:48
unsafe on a function means "this thing may do something dangerous--use with care". unsafe in a block means, "I'm using dangerous stuff in here, but trust me, I've done it correctly"
So unsafe blocks shield the rest of your code from unsafe functions.
John
@gitlabaccount624_gitlab
Oct 17 2018 22:49
oh ok
Ichoran
@Ichoran
Oct 17 2018 22:49
(Of course they don't really do anything, they're just relaying your promise to have not mucked up what's inside them even though the compiler can't make its usual guarantees about behavior.)
John
@gitlabaccount624_gitlab
Oct 17 2018 22:50
yeah .. hmm .. it's kinda annoying because i call this function in all my handlers so i'd like to get rid of the repetitive unsafe block
oh wait i have idea
Ichoran
@Ichoran
Oct 17 2018 22:50
If the function is actually unsafe and you need it in all your handlers, that sounds like a lot of manual verification of things that might go wrong.
Maybe there's a way to abstract out the unsafe behavior into something that you only have to check once and can make safe, and then use that?
John
@gitlabaccount624_gitlab
Oct 17 2018 22:50
yeah hmm lemme try real quick
oh ok i can just change it from unsafe fn to just putting all the lines in the function in an unsafe block
that seems to work neato
Ichoran
@Ichoran
Oct 17 2018 22:52
You have just promised the compiler that the function isn't actually dangerous at all. Is this true?
John
@gitlabaccount624_gitlab
Oct 17 2018 22:52
yeah idc if it's dangerous tbh it doesn't need to be that accurate
i think i'm going to make a reddit post about it to make sure it's fine
actually yeah i'll type it up now
Ichoran
@Ichoran
Oct 17 2018 22:53

The compiler is really good at helping you avoid unsafe things if you let it. So if you go

fn nice(a: A, b: B) -> C {
  unsafe {
    all_sorts_of(a).crazy_dangerous_stuff(b)
  }
}

you end up losing one of the nicest properties of Rust, which is its safety.

John
@gitlabaccount624_gitlab
Oct 17 2018 22:54
yeah, can i make the post so i can give u all the context and u can tell me what u think??
Ichoran
@Ichoran
Oct 17 2018 22:54
Okay. What unsafe feature(s) are you using?
John
@gitlabaccount624_gitlab
Oct 17 2018 22:55
just multiple things accessing an array at same time
and mutating it
Ichoran
@Ichoran
Oct 17 2018 22:55
That sounds potentially dangerous. Why do you know it's okay?
John
@gitlabaccount624_gitlab
Oct 17 2018 22:55
well i don't that's what the post is for!
i think it's fine though so i wanna make post to confirm
Ichoran
@Ichoran
Oct 17 2018 22:55
Haha, fair enough.
(Incidentally--why reddit instead of StackOverflow? Better Rust community there? I don't really pay attention to either any more.)
Denis Lisov
@tanriol
Oct 17 2018 22:57
Most likely it's not safe :-)
John
@gitlabaccount624_gitlab
Oct 17 2018 22:57
hmm not sure i don't think anyone really uses stackoverflow for rust and i always get good responses on reddit
John
@gitlabaccount624_gitlab
Oct 17 2018 23:05
almost done with post.. longer than i thought it'd be..
John
@gitlabaccount624_gitlab
Oct 17 2018 23:10
is safe?
Ichoran
@Ichoran
Oct 17 2018 23:12
Certainly not for multi-threaded use if there's any way that two threads can come up with the same user ID.
John
@gitlabaccount624_gitlab
Oct 17 2018 23:13
wait did u read it?
really fast reader
Ichoran
@Ichoran
Oct 17 2018 23:14
Well, I just got to the point where you're reading from and then later updating a giant static array, without mutexes or anything :)
John
@gitlabaccount624_gitlab
Oct 17 2018 23:14
well i explain in words why i think it's fine in the middle of the post so make sure u don't miss that!
Ichoran
@Ichoran
Oct 17 2018 23:15
Yes, but you didn't say whether multiple user IDs could end up in different threads.
It's pretty easy for that to happen if you're, say, using Actix and pushing off some work into a Future. Your handler and the future could each be dealing with the same user.
John
@gitlabaccount624_gitlab
Oct 17 2018 23:16
hmm i think i mention that sec
So I was thinking, why even do synchronization methods? It's not a big deal if a user requests 2 routes at the exact same time and it only decrements tokens once. I'm just trying to prevent one user from making 100,000 requests per second. If they get one or two free ones it's no big deal.
Ichoran
@Ichoran
Oct 17 2018 23:17
So to me this seems pretty dangerous--you'd have to rely upon a usage convention.
John
@gitlabaccount624_gitlab
Oct 17 2018 23:17
not sure what you mean by that
Ichoran
@Ichoran
Oct 17 2018 23:18
I suppose you could say that it's okay that tokens might be "reused" by the same thread, but I'd still worry that (1) writes might not be atomic, so you might end up with 4 bytes from one thread and 4 bytes from another (you'd have to check whether that was possible), which would really clobber the counter.
John
@gitlabaccount624_gitlab
Oct 17 2018 23:19
it's one byte though?
Ichoran
@Ichoran
Oct 17 2018 23:19
And (2) ...um...I forgot what (2) was.
John
@gitlabaccount624_gitlab
Oct 17 2018 23:19
worst that could happen is a token counter got reset right?
Ichoran
@Ichoran
Oct 17 2018 23:22
Anyway, I need to catch a train. It doesn't look like it could crash your program, but it doesn't look like a great way to actually store the data that you need. I'd be very surprised if this were much of a bottleneck compared to the rest of the program--you can have CAS logic on each array element and still be quite fast.
John
@gitlabaccount624_gitlab
Oct 17 2018 23:24
hmmm idk it sounds like it's a worthy thing to optimize
since it runs on literally every request to the app and doesn't need to be that accurate
mutexes are like 50x slower than regular sets apparently
Denis Lisov
@tanriol
Oct 17 2018 23:27
I'd suggest doing it the other way around. First you write safe code, then you benchmark it and if it's too slow optimize it, possibly with unsafe
John
@gitlabaccount624_gitlab
Oct 17 2018 23:29
well i'm just doing this for fun and want to know if it's safe enough but generally i do that yes
trying to write a very efficient app server from the get-go. i have nothing but time on my hands so just for fun
but hopefully i don't have to preach to /r/rust about loving performance :p
Denis Lisov
@tanriol
Oct 17 2018 23:31
This one looks more or less safe (you're probably OK with, for example, accidentally resetting the counters for other users to their initial state, aren't you?)
The worst case here... well, it depends on the particular optimizations... the very worst case is probably a user losing his tokens at some point of time, which is probably not fatal too.
John
@gitlabaccount624_gitlab
Oct 17 2018 23:41
hooray!
yeah it doesn't need to be perfect. a reset every once in a while is fine i think
Denis Lisov
@tanriol
Oct 17 2018 23:45
...but still, my recommendation would be to not use unsafe code if you can do what you need without it. I've heard about many smart people who wrote unsafe code for every optimization they expected to be important... and failed (as in "the code was really not safe").
Just as a data point, I've been toying with Rust since 1.0 and I still don't trust myself to write unsafe code unless I have no other choice (FFI, etc.)
John
@gitlabaccount624_gitlab
Oct 17 2018 23:46
this is the only place in my app i'm going to be using unsafe