You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Cannot use select! with Receiver contained in a struct #12902
The select! macro doesn't work if you try to reference a Receiver (Port) in a struct. huon reviewed this in the IRC room and agreed I should file an issue on it.
Here are two attempts to do this and both fail at compile time:
use std::io::Timer;structA{c:Sender<~str>,p:Receiver<~str>}fndoes_not_compile(){let(ch, pt):(Sender<~str>,Receiver<~str>) = channel();let a = A{c: ch,p: pt};letmut timer = Timer::new().unwrap();let timeout = timer.oneshot(1000);select!(
s = a.p.recv() => println!("{:s}", s),// error: no rules expected the token `.`() = timeout.recv() => println!("time out!"));}fnalso_does_not_compile(){let(ch, pt):(Sender<~str>,Receiver<~str>) = channel();let a = A{c: ch,p: pt};letmut timer = Timer::new().unwrap();let timeout = timer.oneshot(1000);let p = &a.p;select!(
s = p.recv() => println!("{:s}", s),// see error below() = timeout.recv() => println!("time out!"));}/*<std macros>:7:37: 7:41 error: mismatched types: expected `&std::comm::Receiver<<generic #45>>` but found `&&std::comm::Receiver<~str>` (expected struct std::comm::Receiver but found &-ptr)<std macros>:7 $( let mut $rx = sel.handle(&$rx); )+^~~~<std macros>:1:1: 15:2 note: in expansion of select!selfport.rs:21:5: 24:7 note: expansion siteselfport.rs:22:42: 22:43 error: cannot determine a type for this bounded type parameter: unconstrained typeselfport.rs:22 s = p.recv() => println!("{:s}", s), // error: no rules expected the token `.`*/
I've hit this and it seems I can't move forward until it's resolved. (Well, "can't move forward" is strong; for now I'll just unwrap the macro manually.)
Is there any consensus on how this should be resolved? I'm happy to cut code but it's seems pretty open what direction to go in.
Note that this is "all or nothing" regarding the optional using syntax. Maybe someone with better macro-fu can come up with one where some options can have using and others not.
Hi guys, I have been using the select! implementation in my own code for a month now and it seems to be working ok. What needs to be done to get it merged?
I just ran into this issue as well. It's especially vexing since the struct that contains the receivers must be borrowed as a mutable reference inside the select! -- so this fails:
fndo_something(&mutself){let r1 = &self.r1;let r2 = &self.r2;select!{
a = r1.recv() => a.unwrap()(self),// ERROR! self.r1 is already borrowed!
b = r2.recv() => (),}}
It seems that the only reason select! only allows expressions of the form "ident.ident()" is so that the macro can use that first ident as a unique local variable name inside the expansion.
This could be solved if we could generate unique symbols in a macro expansion. Issue #9031 mentions this but was closed back when macro hygiene was implemented. Sadly, macro hygiene does not help here, since all the identifiers we need to distinguish have the same syntax context.
I've been poking and prodding at the macro syntax trying to figure out a way to do this that isn't horrible, special-cased, or just plain inconvenient, but I'm not sure it's reasonable to do without the ability to generate symbols. Maybe we do need a syntax extension after all?
Looking at it with a little less sleep deprivation, I think the current syntax of the select! macro just doesn't make sense. It uses a matcher for the method invoked on the receiver -- ostensibly supporting receivers whose receive method is spelled differently than recv()? However, it does not use that method name to invoke a member of the receiver named by $rx:ident, it invokes it on a Handle, which only supports recv(). (And Handle's implementation requires that the thing selected on be a Receiver<T> and calls its .recv()).
Removing the spurious .recv() from the required syntax does free up the macro to use an expr for the receiver. Then the only remaining difficulty is generating a unique variable name for each handle in the expansion. Perhaps a slight modification to the macro system would help here? I may just try to hack something together and see if it works.
Apparently I was wrong about not being able to do this with the current macro system. User talchas on #rust came up with this formulation that allows the use of an arbitrary expression as the receiver in a select! expansion: http://is.gd/F6Wy5D
A little bit hairier than the original, and it doesn't solve my borrowing problems, but I think it does make the macro much more generally useful. Any thoughts?
The select! macro is sort of defacto deprecated nowadays in the sense that "selection over a number of events" is best done with the futures crate outside the standard library. In that sense we're not going to be changing the current select! and as a result, I'm going to close this.
Activity
huonw commentedon Mar 15, 2014
cc @alexcrichton
Maybe the syntax could be changed to something like
so that the port can be a full expression. (Although, those idents are used for new variable names... so this may be tricky.)
alexcrichton commentedon Mar 15, 2014
The macro is what tripped me up when I wrote, this. Ideally you want something like:
But
$exprwill swallow the ident, so I had to force the left-hand side to be an ident. But this is all why thisselect!macro is experimental.apoelstra commentedon Jun 18, 2014
I've hit this and it seems I can't move forward until it's resolved. (Well, "can't move forward" is strong; for now I'll just unwrap the macro manually.)
Is there any consensus on how this should be resolved? I'm happy to cut code but it's seems pretty open what direction to go in.
apoelstra commentedon Jul 10, 2014
Here is my suggestion:
If people want to use something other than
.recv()they can, using the alternate syntaxHere is a sample implementation which makes no use of the
Selectstructure or unsafe code or allocations. Thanks much to @eddyb on IRC for helping to clean this up.https://gist.github.com/apoelstra/1b12e849f537485e970b
Note that this is "all or nothing" regarding the optional
usingsyntax. Maybe someone with better macro-fu can come up with one where some options can haveusingand others not.mackwic commentedon Jul 30, 2014
I just hit this bug on my code. Had to expand all our use of select! because of ownership errors.
Maybe multiple macros for multiple uses will do the trick ?
apoelstra commentedon Aug 29, 2014
Hi guys, I have been using the
select!implementation in my own code for a month now and it seems to be working ok. What needs to be done to get it merged?thehydroimpulse commentedon Sep 26, 2014
@apoelstra Did you ever send a PR for it?
apoelstra commentedon Sep 26, 2014
No, I'll do that now.
Remove `Select` structure; implement inline `select!` macro
tripped commentedon Aug 19, 2015
I just ran into this issue as well. It's especially vexing since the struct that contains the receivers must be borrowed as a mutable reference inside the select! -- so this fails:
It seems that the only reason select! only allows expressions of the form "ident.ident()" is so that the macro can use that first ident as a unique local variable name inside the expansion.
This could be solved if we could generate unique symbols in a macro expansion. Issue #9031 mentions this but was closed back when macro hygiene was implemented. Sadly, macro hygiene does not help here, since all the identifiers we need to distinguish have the same syntax context.
I've been poking and prodding at the macro syntax trying to figure out a way to do this that isn't horrible, special-cased, or just plain inconvenient, but I'm not sure it's reasonable to do without the ability to generate symbols. Maybe we do need a syntax extension after all?
tripped commentedon Aug 19, 2015
Looking at it with a little less sleep deprivation, I think the current syntax of the select! macro just doesn't make sense. It uses a matcher for the method invoked on the receiver -- ostensibly supporting receivers whose receive method is spelled differently than
recv()? However, it does not use that method name to invoke a member of the receiver named by$rx:ident, it invokes it on aHandle, which only supportsrecv(). (AndHandle's implementation requires that the thing selected on be aReceiver<T>and calls its.recv()).Removing the spurious
.recv()from the required syntax does free up the macro to use anexprfor the receiver. Then the only remaining difficulty is generating a unique variable name for each handle in the expansion. Perhaps a slight modification to the macro system would help here? I may just try to hack something together and see if it works.tripped commentedon Aug 19, 2015
Apparently I was wrong about not being able to do this with the current macro system. User talchas on #rust came up with this formulation that allows the use of an arbitrary expression as the receiver in a select! expansion: http://is.gd/F6Wy5D
A little bit hairier than the original, and it doesn't solve my borrowing problems, but I think it does make the macro much more generally useful. Any thoughts?
jFransham commentedon Dec 1, 2015
@tripped just a simple change to your suggestion, to stop macro clutter (this style is used in a bunch of internal macros) http://is.gd/bMLJK9
alexcrichton commentedon Aug 1, 2017
The
select!macro is sort of defacto deprecated nowadays in the sense that "selection over a number of events" is best done with thefuturescrate outside the standard library. In that sense we're not going to be changing the currentselect!and as a result, I'm going to close this.Auto merge of rust-lang#12902 - Veykril:item-scope, r=Veykril