These are chat archives for rust-lang/rust

7th
Nov 2018
AllowFlame
@AllowFlame
Nov 07 2018 04:41

Is it possible to cast implemented type from "impl trait" type?

for example

trait TA { }

enum EA {
    v1
}

impl TA for EA {
    ...
}

fn ab_ret_fun() -> impl TA {
    EA::v1
}
let v = ab_ret_fun();
let ev = v as EA;

last line of code is an error and not compiled
Any hint would be appreciated

matrixbot
@matrixbot
Nov 07 2018 04:45
bspeice Can you assert a type here? Specifically I'd be interested to know if let v: EA = ab_ret_fun(); is allowed.
bspeice The casting you're trying to do with as doesn't make much sense in this context.
AllowFlame
@AllowFlame
Nov 07 2018 04:51
@matrixbot Thank you for responding, However, sadly that code you have suggested can’t be compiled. I got following message.
= note: expected type EA
found type impl TA
matrixbot
@matrixbot
Nov 07 2018 05:02
bspeice Yeah, sounds about right. Only thing I can say without knowing more is that it doesn't make sense to return "impl TA" when you're guaranteed to return EA instead; There's probably something you could do with returning &TA and that would be fine, but you're now starting to worry about reference lifetime (specifically the owned value generated in this function is guaranteed to immediately drop and invalidate returned references).
AllowFlame
@AllowFlame
Nov 07 2018 05:13

@matrixbot Very interesting idea. I didn’t think about &TA returning. Actually, I want to do pattern matching with enum value which is implemented a trait. My playground code is

trait TA { }

enum EA {
    v1
}

impl TA for EA {
}

fn ab_ret_fun() -> &'static TA {
    &EA::v1
}

fn main() {
    let v = ab_ret_fun();
    match v {
        &EA::v1 => println!("v1"),
    }

}

and the code can’t be compiled

matrixbot
@matrixbot
Nov 07 2018 05:17
bspeice So, this is actually impossible; EA implements TA, but you can't "match" on a trait implementation. I'd seriously take a look at if traits are a good idea here; you can add an impl EA block as well if you're just trying to get access to some functions defined within context of EA.
AllowFlame
@AllowFlame
Nov 07 2018 05:29
@matrixbot Thank you. I’ll try another way. :)
Zakarum
@omni-viral
Nov 07 2018 06:59
FWIF I usually use Any here
@matrixbot @AllowFlame
Optimizer usually is able to remove redundant boxing/unboxing
AllowFlame
@AllowFlame
Nov 07 2018 07:21
@omni-viral Thanks for useful information. :)
aohan237
@aohan237
Nov 07 2018 08:12
is rust macro still under development? is there any macro tutorial?
Zakarum
@omni-viral
Nov 07 2018 08:12
@aohan237 Not everything works
But mostly stable
IIRC only function-like macro that result in expression are not stable yet
No idea why
aohan237
@aohan237
Nov 07 2018 08:23
@omni-viral thanks.
when will macro be stable and tutorial will be available
Zakarum
@omni-viral
Nov 07 2018 08:24
Tutorial for derive macro applies pretty well
You just has more options for input
aohan237
@aohan237
Nov 07 2018 08:25
where is it?
can you offer me the tutorial link?
aohan237
@aohan237
Nov 07 2018 08:27
no...i think it will not enough..
Zakarum
@omni-viral
Nov 07 2018 08:27
What else do you need?
aohan237
@aohan237
Nov 07 2018 08:27
say in another way
Zakarum
@omni-viral
Nov 07 2018 08:28
I wrote my first proc-macros after reading this
aohan237
@aohan237
Nov 07 2018 08:29
how can i serialize string to rust struct or fn
only macro can do this?
Zakarum
@omni-viral
Nov 07 2018 08:29
how can i serialize string to rust struct?
You mean deserialize?
aohan237
@aohan237
Nov 07 2018 08:29
yeah
Zakarum
@omni-viral
Nov 07 2018 08:30

You want this?

foo!("struct Foo { x: u32 }") become struct Foo { x: u32 }?

That's simple
aohan237
@aohan237
Nov 07 2018 08:30
may be something like this...you can think of something like rpc
Zakarum
@omni-viral
Nov 07 2018 08:30
You can't do it in runtime
aohan237
@aohan237
Nov 07 2018 08:31
so how to do this?
Zakarum
@omni-viral
Nov 07 2018 08:31
Only with string literal, or read from file during build
aohan237
@aohan237
Nov 07 2018 08:31
。。。
so let's talk about this topic. how to make an simple rpc in rust
Zakarum
@omni-viral
Nov 07 2018 08:33
Predefine structs for messages.
Use serde to serialize - deserialize.
Then fn send_message(socket: &mut Socket, message: impl Message) will serialize your data and send over the channel.
fn receive_message(socket: &mut Socket) -> AnyMessage will receive data from channel and deserialize it into some message. AnyMessage is enum that covers all message types
Roughly like this
Now I maybe understood you incorrectly and you want just deserialize bytes into structural data.
There is serde crate that use proc-macro to implement serialization and deserialization and pretty much everyone use it.
aohan237
@aohan237
Nov 07 2018 08:38
my critical problem is how the serialized data find the right service and the right fn? will i have to make something register map to look for?
for instance, "service:aaa,fn:bbb",how this message be deserialized to the right struct and the right fn
Zakarum
@omni-viral
Nov 07 2018 08:39
What do you mean by deserializing in fn? Invoking said fn?
If so then you'd need map with all fns
And register them at start time
For sevice you do the same. You deserialize service field, read it and route message to it
aohan237
@aohan237
Nov 07 2018 08:44
then get this simple problem. if you have a struct service,how do you know its fn
Zakarum
@omni-viral
Nov 07 2018 08:44
Lets say all your messages has a header
struct MessageHeader { service: String, fn: String }
aohan237
@aohan237
Nov 07 2018 08:45
yeah this is the message
Zakarum
@omni-viral
Nov 07 2018 08:45
Now you do services.find(header.service).and_then(move |service| service.invoke(header.fn)
aohan237
@aohan237
Nov 07 2018 08:46
header.fn is the trick
fn is String and header.fn is a pointer
Zakarum
@omni-viral
Nov 07 2018 08:46

And then in fn invoke(&mut self, fn: String)

fns.find(fn).and_then(|fn| fn())

aohan237
@aohan237
Nov 07 2018 08:46
how this works
Zakarum
@omni-viral
Nov 07 2018 08:46
header.fn is String
You can't send pointers
Well. You can
But it makes no sense
aohan237
@aohan237
Nov 07 2018 08:47
fns is what?
Zakarum
@omni-viral
Nov 07 2018 08:47
fns: HashMap<String, fn()>
aohan237
@aohan237
Nov 07 2018 08:48
so, fns: HashMap<String, fn()> how String and fn() bind?
the string and fn you must write down manually?
Zakarum
@omni-viral
Nov 07 2018 08:48
Kinda )
aohan237
@aohan237
Nov 07 2018 08:48
...
that's the trick
if you have lots of service?
you wrote down all of them?
Zakarum
@omni-viral
Nov 07 2018 08:49
You wrote all those fns manually
aohan237
@aohan237
Nov 07 2018 08:49
the map string?
Zakarum
@omni-viral
Nov 07 2018 08:49
The fns themselves
aohan237
@aohan237
Nov 07 2018 08:51
somethine like grpc
you only need to register the struct instance or else
you dont need to write down the string and fn map manually
that's the trick
in python it is extremely simple
but in rust
Zakarum
@omni-viral
Nov 07 2018 08:52
So you have a struct with fns?
aohan237
@aohan237
Nov 07 2018 08:53
the point is , you dont have to write down <String,fn> manually
Zakarum
@omni-viral
Nov 07 2018 08:53
Like
impl ServiceFoo {
  fn do_foo() { ... }
  fn do_bar() { ... }
}
aohan237
@aohan237
Nov 07 2018 08:53
the String is the trick
Zakarum
@omni-viral
Nov 07 2018 08:54
I try to help you. I need more info about what you have.
aohan237
@aohan237
Nov 07 2018 08:54
let's move on your ServiceFoo
then you will register this service?
right?
Zakarum
@omni-viral
Nov 07 2018 08:55
Well. If you have impl block like this you can create a proc-attribute-macro for it
#[rpc-service]
impl ServiceFoo {
  fn do_foo() { ... }
  fn do_bar() { ... }
}
aohan237
@aohan237
Nov 07 2018 08:55
servicemap={'Service.do_foo',Service.do_foo}
something like this
?
Zakarum
@omni-viral
Nov 07 2018 08:56
And this attribute will expand in
impl SerivceFoo {
  fn register() -> Service {
     ...
  }
}
And this function will fill fn map
And return it in Service struct
aohan237
@aohan237
Nov 07 2018 08:57
yeah, then finally come to macro..
Zakarum
@omni-viral
Nov 07 2018 08:59
Well. If this is what you need then you should be able to do it since 1.30
Start from
#[proc_macro_attribute]
pub fn rpc_service(attr: TokenStream, item: TokenStream) -> TokenStream {
   ...
}
Use syn to parse tokens into AST
And quote to convert AST back to tokens
aohan237
@aohan237
Nov 07 2018 09:01
yeah,maybe this solve but where is the document i can refer to..
Zakarum
@omni-viral
Nov 07 2018 09:02
What kind of document?
aohan237
@aohan237
Nov 07 2018 09:02
reference book?
how to use this macro?
Zakarum
@omni-viral
Nov 07 2018 09:02
To use attribute macro you just need to add attribute to the item
aohan237
@aohan237
Nov 07 2018 09:03
To use attribute macro you just need to add attribute to the item
Zakarum
@omni-viral
Nov 07 2018 09:03
Writing attibute macro almost identical to writing proc-derive-macro
aohan237
@aohan237
Nov 07 2018 09:03
how...
Zakarum
@omni-viral
Nov 07 2018 09:03

You have

item

Make it

#[attribute-name]
item
That's it
aohan237
@aohan237
Nov 07 2018 09:04
so where can i find this usage instruction?
aohan237
@aohan237
Nov 07 2018 09:08
thanks for your kindly explain...i will go to learn it
aohan237
@aohan237
Nov 07 2018 09:26
another question , when will async/await available...
Zakarum
@omni-viral
Nov 07 2018 09:44
¯\_(ツ)_/¯
aohan237
@aohan237
Nov 07 2018 09:47
LOL~~
Michal 'vorner' Vaner
@vorner
Nov 07 2018 09:54
Rust should ship with async/await about the end of this year (at least I haven't seen any update on that that'd be saying it won't). But then there'll be probably some time for libraries to adopt.
kraigher
@kraigher
Nov 07 2018 09:57
Question: Is it possible to serialize a rust object into untyped serde_json object without first serializing the rust object to a string and then deserializing the string into an untyped serde_json object?
Michal 'vorner' Vaner
@vorner
Nov 07 2018 10:01
kraigher
@kraigher
Nov 07 2018 10:03
Yes, thank you!
It tried to search for it but was obviously using the wrong terminology
Zakarum
@omni-viral
Nov 07 2018 10:35
@vorner Some libraries develop with nightly features and already has partial async/await support.
But they still provide stable way to do everything.
aohan237
@aohan237
Nov 07 2018 10:36
like torio-async?
...
Tim Robinson
@1tgr
Nov 07 2018 10:37
Tokio and related libraries will need some changes for async/await?
Michal 'vorner' Vaner
@vorner
Nov 07 2018 11:31
Well, they still use futures-0.1. And async-await will produce some incompatible version of futures (futures-0.3, maybe?), so yes. I think there are some kinds of compat-conversion things, but there will probably be some changes to make the new one the default.
Michael(LAI)
@Michael-Lfx
Nov 07 2018 14:54
Is it better not to obey OOP of Java style when programming in Rust due to lifetime and borrow check limitation? If yes, what is the best practice about OOP in Rust? I often encounter with second borrow problem when rewriting C++ project in Rust.
Any help is appreciated.
Michal 'vorner' Vaner
@vorner
Nov 07 2018 15:03
@Michael-Lfx Well, Rust is not „naturally“ OOP language. So, in some cases, you might just give up on OOP modelling altogether. But it highly depends on what you do.
Lyle Mantooth
@IslandUsurper
Nov 07 2018 15:04

what is the best practice about OOP in Rust?

Don't. Rust doesn't have inheritance so you can't use a lot of the typical OOP patterns, but traits are a lot like interfaces. It also doesn't come with a garbage collector, so you have to pay more attention to how long your data is alive.

I'd suggest trying to write Rust in a more functional style, using limited mutability when that makes things easier. (Because there's still no GC.)

Tim Robinson
@1tgr
Nov 07 2018 15:04
I’m guessing the problem with the borrow checker and traditional OOP is something like this http://smallcultfollowing.com/babysteps/blog/2018/11/01/after-nll-interprocedural-conflicts/
When you have lots of fields and methods on a single struct it’s easy to hit borrow checker errors when you start mutating data, or calling &mut self methods
Agree to write Rust code in a more functional style, or break large structs into several small ones like the article says
Michael(LAI)
@Michael-Lfx
Nov 07 2018 16:41
@vorner I am porting an OpenGL ES+EGL driver project from C++ to Rust which originally is heavily implemented on OO. In the processing of rewriting there are lots of errors from borrow checker.
@IslandUsurper Thanks. I am not familiar with functional programming...
Michael(LAI)
@Michael-Lfx
Nov 07 2018 16:52

@1tgr > break large structs into several small ones like the article says

How to maintain their relationship in a nice way when breaking into small structs? Lets say we have a Context:

class Context {
  class ResourceManager { //... lots of fields} 
  ResourceManager *mResourceManager;

  class StateManager { //... lots of fields} 
  StateManager *mStateManager; 

  //... lots of fields
}
Roman Proskuryakov
@kpp
Nov 07 2018 21:46
Hi. I need to create a wasm client with async web socket. Is it possible in theory? Are there working solutions?