These are chat archives for rust-lang/rust

26th
Sep 2017
Rui Azevedo
@neu-rah
Sep 26 2017 01:56
hi all
Rui Azevedo
@neu-rah
Sep 26 2017 02:50
can I have a 'const static' or is something like that in the horizon? I know data is by default immutable, but having a non-mut static data data latter complains that " 'static` cannot be shared between threads safely" is bothering me. The problem is solved by using const instead of static but it arises latter in other form, when assigning a mut to a const data reference the compiler says the data might not live enough, guess that is because it was sprinkled over the code when needed, so I do really need some const data that is static (have a fixed address)
Rui Azevedo
@neu-rah
Sep 26 2017 02:55
or maybe I'm totally wrong here.. just because I'm a rust noob
Aleksey Kladov
@matklad
Sep 26 2017 06:37
@neu-rah it would be helpful to see some example code for your problem.
In general, rust works pretty well for sharing global data via statics: you only have to make sure that the data is thread safe (because statics can be accessed from any thread)
so, something like static X: usize = 0 would be forbidden, while static X: AtomicUsize = ATOMIC_USIZE_INIT is perfectly fine.
Rui Azevedo
@neu-rah
Sep 26 2017 06:42
sory for my simplistic view, i fail to see why immutable data cant be shared, whats the problem? no one will change it
still gona clean up my code to post a more succinct example
Aleksey Kladov
@matklad
Sep 26 2017 06:48
@neu-rah immutable data can be shared just fine. If the compiler complains that the data can't be shared, it probably means that it is not immutable :)
Hm, and I guess my examples are wrong :)
Rui Azevedo
@neu-rah
Sep 26 2017 06:50
should i paste here or is there any site that i can put it?
Aleksey Kladov
@matklad
Sep 26 2017 06:51
https://play.rust-lang.org/ is the best place to share rust snippets
ok, on the current version I've used cont.. but there's the complain it might not live long enough
if I use static instead of const then I have the not safe to share error
Aleksey Kladov
@matklad
Sep 26 2017 06:57
@neu-rah you'll need to add Sync bound like this: trait AsOption<'a>: Sync
The problem is that the type of Menu says that it can contain any kind of AsOption
And some implementations of AsOption might not be threadsafe (for example, an AsOption might contain Cell<i32> inside).
By adding : Sync you oblige all implementors of AsOption to gurantee thread safety.
I think the confusion here is that non mut data in rust is not actually guranteed to be immutable.
There are various types with interior mutability, such as Cell or Mutex, which allow to mutate data via a non-mut reference.
Rui Azevedo
@neu-rah
Sep 26 2017 07:01
ohh, that was unexpected
still I had the sensation that the problem was because I was declaring the struct with lifetime arguments.. so they can contain anything
my expectation was that it would be refined to the concrete case
Aleksey Kladov
@matklad
Sep 26 2017 07:02
Hm, I don't think that lifetimes are a problem here, the problem is thread safety.
Rui Azevedo
@neu-rah
Sep 26 2017 07:02
because of that I've removed all lifetime arguments from structs
same result
then i got really confused
'I think the confusion here is that non mut data in rust is not actually guaranteed to be immutable.' ... you bet that is confusing :D
I was used to haskell.. where immutable really means it
Aleksey Kladov
@matklad
Sep 26 2017 07:06
Yeah, the correct term for &mut would be "unique reference", and for & "potentially shared reference".
Usually, to mutate something you need unique access to it in Rust, but it's not always the case .
Rui Azevedo
@neu-rah
Sep 26 2017 07:07
so, const would be a nice synonym, can we have const with fixed known address? :D
Aleksey Kladov
@matklad
Sep 26 2017 07:08
This is basically what static is.
Rui Azevedo
@neu-rah
Sep 26 2017 07:10
quite, but when using const then the compiler assumed really non mutable data and require no further guarantees of safe Sync , i thought that was nice
apart the short lived problem cause by const not being allocated but instead used as lazy data
Aleksey Kladov
@matklad
Sep 26 2017 07:12
Well, I think it would be possible to add Immutable trait bound like Sync, but then you'll have to add AsOption: Immutable anyway, to specify that an immutable menu can hold only immutable options.
Rui Azevedo
@neu-rah
Sep 26 2017 07:14
or some trait to const to make it allocated
Immutable trait would add more fuel to the fire I guess, because if you say to people that data is immutable by default then it would be harder to explain that trait
or 'const static' :D
Aleksey Kladov
@matklad
Sep 26 2017 07:17
And I don't think you often want 100% true immutability anyway: it's nice to be able to stick some AtomicUsizes to count calls for cheap profiling for example :)
Like, Sync is the minimal gurantee you need to share data safely, and Rust requires exactly it.
Rui Azevedo
@neu-rah
Sep 26 2017 07:18
did i mention haskeller? hehehe
also I use C++ for AVR, and progmem is immutable, for good
all the trouble came from me coding rust and thinking on future avr application where we sometimes fit data into flash memory to save ram
flash memory can only be changed when programming the chip
BTW is that Sync zero cost?
Aleksey Kladov
@matklad
Sep 26 2017 07:23
Sure! It's just a marker
Rui Azevedo
@neu-rah
Sep 26 2017 07:23
ok, then I might go with it :D
thanks for enlighten me
Roman Proskuryakov
@kpp
Sep 26 2017 12:52
Hello, how do I match a enum variant without destructuring it?
[E0532]
Dmitriy
@dpogretskiy
Sep 26 2017 12:52
var@ EnumType::EnumValue { .. } =>
Roman Proskuryakov
@kpp
Sep 26 2017 12:53
Great!
@dpogretskiy ty
Dmitriy
@dpogretskiy
Sep 26 2017 12:53
almost as good as if you could really not destructure
Andrey Lesnikov
@ozkriff
Sep 26 2017 12:53
Roman Proskuryakov
@kpp
Sep 26 2017 12:55
@ozkriff I have. Fixed example: State::Failed(ref msg), which is not what I want to
I don't care what fields are inside variant
Or maybe I could use variant methods over enum method + match self { A {..} => method_a(self) }?
Dmitriy
@dpogretskiy
Sep 26 2017 12:57
also there is problem with pattern matching if you for example match ET::EV { ref val1, ref va2 } and not use say val1, you get warning which suggests you to replace it with _val1, which is not working for obvious reasons
@kpp this one will not work
Andrey Lesnikov
@ozkriff
Sep 26 2017 12:58
Why not match on reference if you don't want to consume the value?
Dmitriy
@dpogretskiy
Sep 26 2017 12:58
basically it's method_a(self)
Andrey Lesnikov
@ozkriff
Sep 26 2017 12:59
@dpogretskiy ET::EV { ref va2, .. } should work then
Dmitriy
@dpogretskiy
Sep 26 2017 12:59
enums are tricky, actually, you can't distinguish them other than match over
@ozkriff yeah, but compiler suggests to use _val1
it's just misleading warning
nothing else
@kpp enum values are not separate types, it's just type of enum
so you can't define method which works on particular variant by type
Roman Proskuryakov
@kpp
Sep 26 2017 13:01
OK
How ugly is this code?
    fn to_bytes<'a>(buf: (&'a mut [u8], usize), packet: Packet) -> Result<(&'a mut [u8], usize), GenError> {
        match packet {
            Packet::RouteRequest {..} => to_bytes_route_request(buf, packet),
            Packet::RouteResponse {..} => to_bytes_route_response(buf, packet),
            Packet::ConnectNotification {..} => to_bytes_connect_notification(buf, packet),
            Packet::DisconnectNotification {..} => to_bytes_disconnect_notification(buf, packet),
            Packet::PingRequest {..} => to_bytes_ping_request(buf, packet),
            Packet::PongResponse {..} => to_bytes_pong_response(buf, packet),
            Packet::OobSend {..} => to_bytes_oob_send(buf, packet),
            Packet::OobReceive {..} => to_bytes_oob_recv(buf, packet),
            Packet::Data {..} => to_bytes_data(buf, packet)
        }
    }
fn to_bytes_route_request<'a>(buf: (&'a mut [u8], usize), packet: Packet) -> Result<(&'a mut [u8], usize), GenError> {
    match packet {
        Packet::RouteRequest { peer_pk } => {
            do_gen!(buf,
                gen_be_u8!(0x00) >>
                gen_slice!(peer_pk.as_ref())
            )
        },
        _ => Err(GenError::NotYetImplemented)
    }
}
Is there any way to fix it?
Andrey Lesnikov
@ozkriff
Sep 26 2017 13:02

it's just misleading warning

yep :( It should suggest at least something like val1: ref _val1 (though it looks much uglier then just ..)

Dmitriy
@dpogretskiy
Sep 26 2017 13:02
does it compile?
Roman Proskuryakov
@kpp
Sep 26 2017 13:02
yes
Dmitriy
@dpogretskiy
Sep 26 2017 13:03
neat :smile:
Roman Proskuryakov
@kpp
Sep 26 2017 13:03
)))
Dmitriy
@dpogretskiy
Sep 26 2017 13:03
actually this approach looks scalaesque
basically this one is okay, except for to_bytes_route_request
and others are same i assume
they match for no reason basically
Roman Proskuryakov
@kpp
Sep 26 2017 13:05
Well
Dmitriy
@dpogretskiy
Sep 26 2017 13:05
you need to split packet type from packet payload, i guess
Andrey Lesnikov
@ozkriff
Sep 26 2017 13:05
Why can't you implement it as a trait for Packet?
Roman Proskuryakov
@kpp
Sep 26 2017 13:05
it is

But as I was said

so you can't define method which works on particular variant by type

Dmitriy
@dpogretskiy
Sep 26 2017 13:06
struct Packet { tpe: PacketType, payload: Vec<u8/whatever> }
so you match type and send payload, to tobytes* function
Roman Proskuryakov
@kpp
Sep 26 2017 13:07
Haha. There is an exception in the proto
first byte 0x01-0x09 is a type
but if it is 0x10-0xF0 it is a payload
so Data has no PacketType or it has a PacketType::Data(id)
Dmitriy
@dpogretskiy
Sep 26 2017 13:10
looks like you can parse it
Roman Proskuryakov
@kpp
Sep 26 2017 13:10
And splitting it to struct Packet { tpe: PacketType, payload: Vec<u8/whatever> } wont help
I can
Because the user code will have to handle PacketType and destructuring the payload as a separate operation
While it is naturally the only one op
Dmitriy
@dpogretskiy
Sep 26 2017 13:13
what is a use case? i don't quite get it :smile:
Denis Lisov
@tanriol
Sep 26 2017 13:13
Why do you want to have separate functions for to_bytes_...?
Dmitriy
@dpogretskiy
Sep 26 2017 13:17
so i guess the difference of those tobytes* funcs is gen_be_u8![0x00] part, and maybe some more
Roman Proskuryakov
@kpp
Sep 26 2017 13:18
@dpogretskiy you are right
well, I may rewrite it using trait
Dmitriy
@dpogretskiy
Sep 26 2017 13:19
that's where you can match types
so you can either has fewer functions or more functions, and make it shorter
Roman Proskuryakov
@kpp
Sep 26 2017 13:20
I see
from_bytes -> &PacketTrait
right?
Dmitriy
@dpogretskiy
Sep 26 2017 13:21
that will introduce lifetimes
and make you life miserable :smile:
Roman Proskuryakov
@kpp
Sep 26 2017 13:21
:D
and the user may check it's type and cast to exact struct
Dmitriy
@dpogretskiy
Sep 26 2017 13:22
if you don't want to use boxing, then raw structs are the way to go
for end user it's better to separate packet type and payload, or he will have to do same thing you do
rust is really restrictive about stuff
Denis Lisov
@tanriol
Sep 26 2017 13:24
You may want to have separate structures for different packet types.
And an enum that can contain any of them.
Dmitriy
@dpogretskiy
Sep 26 2017 13:25
@tanriol nice catch
that's the easiest polymorphism that does not hurt in rust
Roman Proskuryakov
@kpp
Sep 26 2017 13:27
okay
seems like it's fine when I know the type of what I received in bytes
like let x: X = X::from_bytes(bytes)
but what would it be for a generic Packet::from_bytes in this case?
lemonxah
@lemonxah
Sep 26 2017 13:29
i am a bit late to the conversation
but what about having ADT for the packet?
Roman Proskuryakov
@kpp
Sep 26 2017 13:29
It is already
people didn't like my version of:
    fn to_bytes<'a>(buf: (&'a mut [u8], usize), packet: Packet) -> Result<(&'a mut [u8], usize), GenError> {
        match packet {
            Packet::RouteRequest {..} => to_bytes_route_request(buf, packet),
            Packet::RouteResponse {..} => to_bytes_route_response(buf, packet),
            Packet::ConnectNotification {..} => to_bytes_connect_notification(buf, packet),
            Packet::DisconnectNotification {..} => to_bytes_disconnect_notification(buf, packet),
            Packet::PingRequest {..} => to_bytes_ping_request(buf, packet),
            Packet::PongResponse {..} => to_bytes_pong_response(buf, packet),
            Packet::OobSend {..} => to_bytes_oob_send(buf, packet),
            Packet::OobReceive {..} => to_bytes_oob_recv(buf, packet),
            Packet::Data {..} => to_bytes_data(buf, packet)
        }
    }
So I try to improve it
Dmitriy
@dpogretskiy
Sep 26 2017 13:30
basically enums are terrible :smile:
Denis Lisov
@tanriol
Sep 26 2017 13:31
struct PingRequest { ... }
enum Request {
    PingRequest(PingRequest),
    ...
}
lemonxah
@lemonxah
Sep 26 2017 13:31
why are they terrible?
Dmitriy
@dpogretskiy
Sep 26 2017 13:31
only way to go around them is pattern match all over the place
if you have enum Packet { Packet1(bytes: &[u8]), Packet1(bytes: &[u8]) }
you can't get bytes event if type and name are the same
Roman Proskuryakov
@kpp
Sep 26 2017 13:33
let me ask you again
lemonxah
@lemonxah
Sep 26 2017 13:34
i dont understand what you mean @dpogretskiy
Roman Proskuryakov
@kpp
Sep 26 2017 13:34
seems like it's fine when I know the type of what I received in bytes
like let x: X = X::from_bytes(bytes)
but what would it be for a generic Packet::from_bytes in this case?
lemonxah
@lemonxah
Sep 26 2017 13:34
and why is pattern mathcing a bad idea?
Andrey Lesnikov
@ozkriff
Sep 26 2017 13:34
@dpogretskiy they are not terrible :( It just means that they are a wrong tool for that particular situation :(
Dmitriy
@dpogretskiy
Sep 26 2017 13:35
pattern matching is great, but when it's only way to go, you don't want to use enums for say every ADT you define
Roman Proskuryakov
@kpp
Sep 26 2017 13:35
So please help me.
Diggory Blake
@Diggsey
Sep 26 2017 13:36
@dpogretskiy enum PacketType { Packet1, Packet2 } struct Packet<'a> { packet_type: PacketType, bytes: &'a [u8] }
Roman Proskuryakov
@kpp
Sep 26 2017 13:36
What should return my generic Packet::from_bytes?
lemonxah
@lemonxah
Sep 26 2017 13:36
and again .. why is pattern matching bad if its the only way to go with an enum? i dont undestand
@kpp i would have Said that it should Return a Packet
if you dont know what type it is you are receiveing how are you going to type it?
Denis Lisov
@tanriol
Sep 26 2017 13:37
@kpp I'd suggest the return value is an enum of all packet types you can parse. Each variant of this enum contains a struct with the packet fields.
lemonxah
@lemonxah
Sep 26 2017 13:37
so for me this is the exact use case for an enum
Roman Proskuryakov
@kpp
Sep 26 2017 13:38
seems reasonable
thank you
Dmitriy
@dpogretskiy
Sep 26 2017 13:39
@lemonxah it's just rust enums and rust pattern matching, c++ enums are worst, and in say Scala you have so many ways to define enums and get around them, it's not even funny
lemonxah
@lemonxah
Sep 26 2017 13:40
scala enums are bad, but you dont use enums in scala you use case objects instead
but isn't enums in rust supposed to be like scala case classes?
Dmitriy
@dpogretskiy
Sep 26 2017 13:40
abstract sealed classes and such
lemonxah
@lemonxah
Sep 26 2017 13:40
which all inherits from 1 sealed trait
Dmitriy
@dpogretskiy
Sep 26 2017 13:41
but you don't have to pattern match ever if you don't want to
so if you want to use such thing in rust, thinking you can be flexible about it, think twice
Roman Proskuryakov
@kpp
Sep 26 2017 14:40
So
@lemonxah does it looks like you were talking about?
Denis Lisov
@tanriol
Sep 26 2017 15:56
Looks very nice, yes. However, in buf.extend_from_slice(&stack_buf); did you mean &stack_buf[..produced]?
Aravindh Sridharan
@hardvain
Sep 26 2017 16:17
In the page https://rustbyexample.com/scope/borrow/freeze.html , shouldnt the compiler error message be assignment to immutably borrowed _mutable_integer occurs hereinstead of assignment to borrowed _mutable_integer occurs here?
My bad. Found the reason. Kindly ignore the above message.
TatriX
@TatriX
Sep 26 2017 21:04
I'd like to write a simple http service. Which crate should I take to make it?
elias
@ejmg
Sep 26 2017 21:04
For serving?
TatriX
@TatriX
Sep 26 2017 21:04
Yes, http server, simple routes. Something like this
elias
@ejmg
Sep 26 2017 21:05
Gotham-rs seems promising. It handles things you'd have to setup with Hyper.
TatriX
@TatriX
Sep 26 2017 21:05
Thanks, I'll take a look
stevensonmt
@stevensonmt
Sep 26 2017 21:23
TatriX
@TatriX
Sep 26 2017 21:24
Oh, cool! Thanks!