Is there any way to create an alias of a specific FnMut? - syntax

I want to work with FnMut(&[f32]) -> f32,
to not copy/paste full signature, I want to introduce some kind of alias, but
type Boo = FnMut(&[f32]) -> f32;
fn f<F: Boo>(mut f: F) {}
Causes a compiler error:
error[E0404]: expected trait, found type alias `Boo`
--> src/main.rs:3:13
|
3 | fn f<F: Boo>(mut f: F) {}
| ^^^ type aliases cannot be used for traits
I then tried:
trait Boo: FnMut(&[f32]) -> f32 {}
fn f<F: Boo>(mut f: F) {}
it compiled, but if I try to use Boo in place of trait in another place:
trait Boo: FnMut(&[f32]) -> f32 {}
struct X(Vec<Box<Boo>>);
I get:
error[E0191]: the value of the associated type `Output` (from the trait `std::ops::FnOnce`) must be specified
--> src/main.rs:3:18
|
3 | struct X(Vec<Box<Boo>>);
| ^^^ missing associated type `Output` value
Is there any way to create an alias of a specific FnMut which I can use
instead of FnMut(&[f32]) -> f32?

Trait aliases are not currently part of the language. However, there is an accepted RFC for exactly that. It's hard to predict exactly when it will be implemented, but accepting the RFC represents a commitment to implement it at some point in the future.
The reason for your error is that your Boo trait is a subtype of FnMut and any implementation must also provide the required associated type Output. But the compiler still doesn't know which implementation will be provided, so you need to tell it what the type of Output will be:
struct X(Vec<Box<Boo<Output = f32>>>);
This is a little clunky, and I feel like it's an area for improvement. Intuitively, it seems that Output could be inferred from -> f32, but I could be wrong here.
Even with that error fixed, Boo is strictly a subtype of FnMut(&[f32]) so you can't just provide any closure where Boo is expected. That closure must also implement your trait. You can do this as a blanket implementation for all FnMut(&[f32]) -> f32, like this:
impl <F> Boo for F where F: FnMut(&[f32]) -> f32 {}
Now any Boo is an FnMut(&[f32]) -> f32 (by subtyping), and any FnMut(&[f32]) -> f32 is a Boo (by the blanket implementation).

Related

Can traits be used on enum types?

I read through the trait documentation and found a neat definition for using traits on structs. Is it possible to use traits on enum types? I have seen answers that say no, but they are 3 years old and don't quite do what I'm trying to do.
I tried to do this:
#[derive(Debug, Copy, Clone)]
pub enum SceneType {
Cutscene,
Game,
Menu,
Pause,
Credits,
Exit,
}
//We want to guarantee every SceneType can be played statically
trait Playable {
fn play();
}
impl Playable for SceneType::Cutscene {
fn play() {}
}
error[E0573]: expected type, found variant `SceneType::Cutscene`
--> src/main.rs:16:19
|
16 | impl Playable for SceneType::Cutscene {
| ^^^^^^^^^^^^^^^^^^^
| |
| not a type
| help: you can try using the variant's enum: `SceneType`
I don't understand this error because the enum it references is in the same file. If I really can't use traits on enum variants, is there any way I can guarantee any enum trait must implement certain methods?
Can traits be used on enum types?
Yes. In fact, you already have multiple traits defined for your enum; the traits Debug, Copy and Clone:
#[derive(Debug, Copy, Clone)]
pub enum SceneType
The problem is that you aren't attempting to implement Playable for your enum, you are trying to implement it for one of the enum's variants. Enum variants are not types.
As the error message tells you:
help: you can try using the variant's enum: `SceneType`
impl Playable for SceneType {
fn play() {}
}
See also:
Can struct-like enums be used as types?
Is there a way to use existing structs as enum variants?
If you want to implement a trait for Playable (i.e. for all enum variants) then the answer is quite simply: Yes you can. And Shepmaster's answer details how to do that.
However, if you really only want one enum variant to be Playable and not the others, then Rust doesn't directly support that, but there's an idiom I've seen used to emulate it. Instead of
enum MyEnum {
A(i32, i32),
B(String),
}
you explicitly implement each enum variant as a separate struct, so
enum MyEnum {
A(A),
B(B),
}
struct A {
x: i32,
y: i32,
}
struct B {
name: String,
}
And then you can impl Playable for A without impl Playable for B. Whenever you want to call it, pattern match the MyEnum and, if you get an A, you can call play in your example on the result of the pattern match.
I don't recommend using this pattern for every enum you write, as it does make the code a decent bit more verbose and requires some boilerplate constructor methods to make it palatable. But for complicated enums with a lot of options, this sort of pattern can make the code easier to reason about, especially if you have a lot of traits or functions that only really apply to a couple of the enum possibilities.
Edit: Truly apologize; this answer isn't about
every SceneType can be played statically
Old answer
Try generics:
#[derive(Debug, Copy, Clone)]
pub enum SceneType <Cutscene>
where
Cutscene: Playable
{
Cutscene(Cutscene),
Game,
Menu,
Pause,
Credits,
Exit,
}
//We want to guarantee every SceneType can be played statically
// Notice: add `pub` as enum
pub trait Playable {
fn play();
}
// create struct for inner of SceneType::Cutscene
struct Cutscene {
// ...
}
// impl to specific Cutscene
impl Playable for Cutscene {
fn play() {}
}
Test it:
fn main () {
let cutscene = Cutscene{};
let scenetype = SceneType::Cutscene(cutscene);
}
A downside I realized is that the generics are static. When there are more than one generics for an enum, all generics must be specified.
enum E <A, B>
where
A: SomeTrait1,
B: SomeTrait2,
{
Enum1(A),
Enum2(B),
}
trait SomeTrait1 {}
trait SomeTrait2 {}
struct S1 {}
impl SomeTrait1 for S1{}
struct S2 {}
impl SomeTrait2 for S2{}
struct X1 {}
impl SomeTrait1 for X1{}
fn main () {
// specify the generics
E::<S1, S2>::Enum1(S1{});
E::<X1, S2>::Enum1(X1{});
//error[E0282]: type annotations needed
// --> src/main.rs:26:5
// |
//33 | E::Enum1(S1{});
// | ^^^^^^^^ cannot infer type for type parameter `B` declared on the enum `E`
// E::Enum1(S1{});
// E::Enum1(X1{});
}

How can I define a trait with arguments and return types like Fn?

I'm confused by the following code (Listing 13-9):
struct Cacher<T>
where
T: Fn(i32) -> i32,
{
calculation: T,
value: Option<i32>,
}
I understand that Fn is a trait, but usually a trait has no argument and returned type. How can I define a trait like Fn?
I tried to look at the definition (actually it's FnOnce, but Fn has FnMut bound and FnMut has FnOnce bound...), but I'm still confused. What is the meaning of that <Args>? Then also something written about it in the Nomicon; but I do not understand it:
Where Fn(a, b, c) -> d is itself just sugar for the unstable real Fn trait
How can I define a trait with arguments and return types like Fn?
If you mean the syntax MyTrait(A) -> B, you cannot. Traits with "arguments" and "return types" are special and are restricted to the Fn, FnMut and FnOnce traits. This is hard-coded into the compiler. There's even a specific error message for it:
error: parenthetical notation is only stable when used with `Fn`-family traits (see issue #29625)
--> src/main.rs:5:8
|
5 | A: MyTrait(A) -> B,
| ^^^^^^^^^^^^^^^
That being said, this syntax desugars into the standard trait syntax. You can see what FnOnce is from the docs:
pub trait FnOnce<Args> {
type Output;
extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
}
The compiler converts Fn(A, B, C) -> Z into Fn<(A, B, C), Output = Z>. Args is a standard trait generic type parameter and Output is a standard associated type. The "rust-call" ABI is some internal compiler machinery that makes this a bit more efficient and can be ignored most of the time.
You are completely allowed to create your own traits with generic parameters and associated types. You just are not allowed to use the parenthetical notation.

How to extend the lifetimes of Strings within functions of traits that require returning &str?

Problem
I am trying to implement the std::error::Error trait on a enum. Some elements of the enum are Enum Variants, and I would like to generate a different error message containing the data from the variant. However with the implementation below the formatted String that Deref to &str don't live long enough.
The general solution is to return a String. However, this is not an option here as the returned type must be &str as specified by the Error trait.
Example: Playground link
It is important to note that the variants may not contain usize, and might instead be another enum, or struct etc.
use std::fmt;
use std::fmt::{Display, Formatter};
use std::error;
#[derive(Debug)]
enum EnumError {
A,
B(usize),
C(usize),
D,
}
impl error::Error for EnumError {
fn description(&self) -> &str {
use EnumError::*;
match *self {
A => "A happened",
B(value) => &*format!("B happened info: {:?}", value),
C(value) => &*format!("B happened info: {:?}", value),
D => "D happened",
}
}
}
impl Display for EnumError {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
use std::error::Error;
write!(f, "{}", self.description())
}
}
fn main() {}
The string you create needs to be owned by something. When you create a local string in the method, you have to transfer its ownership to the caller. But since you have to return &str, this is not an option.
The way around it would be to store the string in the struct itself. You can declare the enum value as B(usize, String), put the description there when you create it, and then return it with
B(_, ref descr) => descr
To be frank, description is not supposed to be a terribly detailed message, it just needs to give a general description of what kind of error this is, this is why it returns &str. I didn't see instances of writing any dynamic data into the description in the standard library, usually it's just a static string. Display implementation is a different matter though, in there you can be much more verbose.

Rust: How to specify lifetimes in closure arguments?

I'm writing a parser generator as a project to learn rust, and I'm running into something I can't figure out with lifetimes and closures. Here's my simplified case (sorry it's as complex as it is, but I need to have the custom iterator in the real version and it seems to make a difference in the compiler's behavior):
Playpen link: http://is.gd/rRm2aa
struct MyIter<'stat, T:Iterator<&'stat str>>{
source: T
}
impl<'stat, T:Iterator<&'stat str>> Iterator<&'stat str> for MyIter<'stat, T>{
fn next(&mut self) -> Option<&'stat str>{
self.source.next()
}
}
struct Scanner<'stat,T:Iterator<&'stat str>>{
input: T
}
impl<'main> Scanner<'main, MyIter<'main,::std::str::Graphemes<'main>>>{
fn scan_literal(&'main mut self) -> Option<String>{
let mut token = String::from_str("");
fn get_chunk<'scan_literal,'main>(result:&'scan_literal mut String,
input: &'main mut MyIter<'main,::std::str::Graphemes<'main>>)
-> Option<&'scan_literal mut String>{
Some(input.take_while(|&chr| chr != "\"")
.fold(result, |&mut acc, chr|{
acc.push_str(chr);
&mut acc
}))
}
get_chunk(&mut token,&mut self.input);
println!("token is {}", token);
Some(token)
}
}
fn main(){
let mut scanner = Scanner{input:MyIter{source:"\"foo\"".graphemes(true)}};
scanner.scan_literal();
}
There are two problems I know of here. First, I have to shadow the 'main lifetime in the get_chunk function (I tried using the one in the impl, but the compiler complains that 'main is undefined inside get_chunk). I think it will still work out because the call to get_chunk later will match the 'main from the impl with the 'main from get_chunk, but I'm not sure that's right.
The second problem is that the &mut acc inside the closure needs to have a lifetime of 'scan_literal in order to work like I want it to (accumulating characters until the first " is encountered for this example). I can't add an explicit lifetime to &mut acc though, and the compiler says its lifetime is limited to the closure itself, and thus I can't return the reference to use in the next iteration of fold. I've gotten the function to compile and run in various other ways, but I don't understand what the problem is here.
My main question is: Is there any way to explicitly specify the lifetime of an argument to a closure? If not, is there a better way to accumulate the string using fold without doing multiple copies?
First, about lifetimes. Functions defined inside other functions are static, they are not connected with their outside code in any way. Consequently, their lifetime parameters are completely independent. You don't want to use 'main as a lifetime parameter for get_chunk() because it will shadow the outer 'main lifetime and give nothing but confusion.
Next, about closures. This expression:
|&mut acc, chr| ...
very likely does not what you really think it does. Closure/function arguments allow irrefutable patterns in them, and & have special meaning in patterns. Namely, it dereferences the value it is matched against, and assigns its identifier to this dereferenced value:
let x: int = 10i;
let p: &int = &x;
match p {
&y => println!("{}", y) // prints 10
}
You can think of & in a pattern as an opposite to & in an expression: in an expression it means "take a reference", in a pattern it means "remove the reference".
mut, however, does not belong to & in patterns; it belongs to the identifier and means that the variable with this identifier is mutable, i.e. you should write not
|&mut acc, chr| ...
but
|& mut acc, chr| ...
You may be interested in this RFC which is exactly about this quirk in the language syntax.
It looks like that you want to do a very strange thing, I'm not sure I understand where you're getting at. It is very likely that you are confusing different string kinds. First of all, you should read the official guide which explains ownership and borrowing and when to use them (you may also want to read the unfinished ownership guide; it will soon get into the main documentation tree), and then you should read strings guide.
Anyway, your problem can be solved in much simpler and generic way:
#[deriving(Clone)]
struct MyIter<'s, T: Iterator<&'s str>> {
source: T
}
impl<'s, T: Iterator<&'s str>> Iterator<&'s str> for MyIter<'s, T>{
fn next(&mut self) -> Option<&'s str>{ // '
self.source.next()
}
}
#[deriving(Clone)]
struct Scanner<'s, T: Iterator<&'s str>> {
input: T
}
impl<'m, T: Iterator<&'m str>> Scanner<'m, T> { // '
fn scan_literal(&mut self) -> Option<String>{
fn get_chunk<'a, T: Iterator<&'a str>>(input: T) -> Option<String> {
Some(
input.take_while(|&chr| chr != "\"")
.fold(String::new(), |mut acc, chr| {
acc.push_str(chr);
acc
})
)
}
let token = get_chunk(self.input.by_ref());
println!("token is {}", token);
token
}
}
fn main(){
let mut scanner = Scanner{
input: MyIter {
source: "\"foo\"".graphemes(true)
}
};
scanner.scan_literal();
}
You don't need to pass external references into the closure; you can generate a String directly in fold() operation. I also generified your code and made it more idiomatic.
Note that now impl for Scanner also works with arbitrary iterators returning &str. It is very likely that you want to write this instead of specializing Scanner to work only with MyIter with Graphemes inside it. by_ref() operation turns &mut I where I is an Iterator<T> into J, where J is an Iterator<T>. It allows further chaining of iterators even if you only have a mutable reference to the original iterator.
By the way, your code is also incomplete; it will only return Some("") because the take_while() will stop at the first quote and won't scan further. You should rewrite it to take initial quote into account.

What types are valid for the `self` parameter of a method?

I wanted to create a method that only works where the self parameter was an Rc. I saw that I could use Box, so I thought I might try to mimic how that works:
use std::rc::Rc;
use std::sync::Arc;
struct Bar;
impl Bar {
fn consuming(self) {}
fn reference(&self) {}
fn mutable_reference(&mut self) {}
fn boxed(self: Box<Bar>) {}
fn ref_count(self: Rc<Bar>) {}
fn atomic_ref_count(self: Arc<Bar>) {}
}
fn main() {}
Yields these errors:
error[E0308]: mismatched method receiver
--> a.rs:11:18
|
11 | fn ref_count(self: Rc<Bar>) {}
| ^^^^ expected struct `Bar`, found struct `std::rc::Rc`
|
= note: expected type `Bar`
= note: found type `std::rc::Rc<Bar>`
error[E0308]: mismatched method receiver
--> a.rs:12:25
|
12 | fn atomic_ref_count(self: Arc<Bar>) {}
| ^^^^ expected struct `Bar`, found struct `std::sync::Arc`
|
= note: expected type `Bar`
= note: found type `std::sync::Arc<Bar>`
This is with Rust 1.15.1.
Before Rust 1.33, there are only four valid method receivers:
struct Foo;
impl Foo {
fn by_val(self: Foo) {} // a.k.a. by_val(self)
fn by_ref(self: &Foo) {} // a.k.a. by_ref(&self)
fn by_mut_ref(self: &mut Foo) {} // a.k.a. by_mut_ref(&mut self)
fn by_box(self: Box<Foo>) {} // no short form
}
fn main() {}
Originally, Rust didn't have this explicit self form, only self, &self, &mut self and ~self (the old name for Box). This changed so that only by-value and by-references have the short-hand built-in syntax, since they are the common cases, and have very key language properties, while all smart pointers (including Box) require the explicit form.
As of Rust 1.33, some additional selected types are available for use as self:
Rc
Arc
Pin
This means that the original example now works:
use std::{rc::Rc, sync::Arc};
struct Bar;
impl Bar {
fn consuming(self) { println!("self") }
fn reference(&self) { println!("&self") }
fn mut_reference(&mut self) { println!("&mut self") }
fn boxed(self: Box<Bar>) { println!("Box") }
fn ref_count(self: Rc<Bar>) { println!("Rc") }
fn atomic_ref_count(self: Arc<Bar>) { println!("Arc") }
}
fn main() {
Bar.consuming();
Bar.reference();
Bar.mut_reference();
Box::new(Bar).boxed();
Rc::new(Bar).ref_count();
Arc::new(Bar).atomic_ref_count();
}
However, the impl handling hasn't yet been fully generalised to match the syntax, so user-created types still don't work. Progress on this is being made under the feature flag arbitrary_self_types and discussion is taking place in the tracking issue 44874.
(Something to look forward to!)
It's now possible to use arbitrary types for self, including Arc<Self>, but the feature is considered unstable and thus requires adding this crate attribute:
#![feature(arbitrary_self_types)]
Using feature crate attributes requires using nightly Rust.

Resources