When one wants to show that trait returning Result should never fail the Infallible is used as an error type like in example below:
trait Foo {
type T;
type E: std::error::Error;
fn bar() -> Result<Self::T, Self::E>;
}
impl Foo for () {
type T = ();
type E = std::convert::Infallible;
fn bar() -> Result<Self::T, Self::E> { Ok(()) }
}
But what should one do with implementation that will always return Err and never Ok? Is there idiomatic way to fill the blank below:
impl Foo for MyCustomError {
type T = //what to put here as "never returned type";
type E = MyCustomError;
fn bar() -> Result<Self::T, Self::E> { Err(MyCustomError) }
}
Once never stabilizes you can just use that.
#![feature(never)]
impl Foo for MyCustomError {
type T = !;
type E = MyCustomError;
fn bar() -> Result<Self::T, Self::E> { Err(MyCustomError) }
}
Until then we can construct our own empty enum:
enum Void {}
impl Foo for MyCustomError {
type T = Void;
type E = MyCustomError;
fn bar() -> Result<Self::T, Self::E> { Err(MyCustomError) }
}
which can't be constructed for obvious reasons, Rust also sees that and optimizes accordingly.
Or use void::Void or Infallible which except for the different traits each implements are essentially the same.
Related
What is the correct syntax to return a function in Rust?
The following code does not compile, thanks.
fn identity<T>(a: T) -> T {
return a;
};
fn right<T>(a: T) -> Fn {
return identity;
};
Here (playground) is a minimal example:
fn identity<T>(a: T) -> T {
return a;
}
fn right<T>(_a: T) -> impl Fn(T) -> T {
return identity;
}
fn main() {
println!("{}", right(0)(42))
}
You need to:
Specify the input argument and output types within the signature, i.e. Fn(T) -> T.
Specify that right's return type implements the trait Fn(T) -> T.
Alternatively, you could also have written the function pointer fn(T) -> T as the return type. Since this is not a trait, you would not need the impl keyword:
fn right<T>(_a: T) -> fn(T) -> T {
return identity;
}
Only fn items and non-capturing closures can be coerced to function pointers, so, while simpler, this will not work in all cases.
This is the best I came up with:
fn identity<T>(a: T) -> T {
return a;
}
fn right<T>() -> &'static dyn Fn(T)->T {
return &identity::<T>;
}
fn main() {
println!("{}", right()(3.1415));
}
playground <-- test it by yourself.
Explanation
&'static dyn Fn(T)->T means that it returns a reference to some object that satisfy the Fn(T)->T trait (because yes Fn(T)->T is indeed a trait, not a type).
Self answer after two answers from others:
I came up with this:
fn identity<T>(a: T) -> T {
a
};
fn right<T, U>(_a: T) -> fn(U) -> U {
identity
};
The return type of right does not have to be identical to input of T of identity.
I'd like to instruct the Rust compiler to not evaluate an argument under any circumstance. Here is an example:
#![allow(dead_code)]
trait CheckTrait {
fn check(b : bool);
}
struct CheckStructA {}
struct CheckStructB {}
impl CheckTrait for CheckStructA {
fn check(_b : bool) {
println!("CheckStructA");
}
}
impl CheckTrait for CheckStructB {
// compiler: do not evaluate the argument _b
fn check(_b : bool) {
}
}
fn show_stuff_a() -> bool {
println!("Show stuff A");
true
}
fn show_stuff_b() -> bool {
println!("Show stuff B");
true
}
fn test_a<T : CheckTrait>(_ : T) {
T::check(show_stuff_a());
}
fn test_b<T : CheckTrait>(_ : T) {
T::check(show_stuff_b());
}
fn main() {
test_a(CheckStructA{});
test_b(CheckStructB{});
}
Here CheckStructB is effectively a disabled version of CheckStructA. Where the comment is, I would like to be able to instruct the compiler not to evaluate whatever expression computes _b for CheckStructB::check, but still evaluate whatever expression would compute _b for CheckStructA::check. The consequence on this code is that it would still output "Show Stuff A" to the console, but not output "Show Stuff B" to the console.
In C# this can be done by replacing the comment with [System.Diagnostics.Conditional("DoNotEverTurnThisOn")] . I do not want to define the types inside a macro because that breaks intellisense.
How do I do it in Rust?
Only evaluating arguments as necessary is called Lazy Evaluation.
In languages like Haskell, for which Lazy Evaluation is the default, an argument or variable of type bool is not actually represented as a bool immediately, instead it is represented as a "thunk" which contains the function to call and its own arguments (potentially thunks).
In Rust, since Eager Evaluation is the default, you need to explicitly represent laziness in the type of the argument or valuable. This is generally done by asking not for T but for FnOnce() -> T instead.
Therefore, you would rewrite check as:
fn check<F: FnOnce() -> bool>(condition: F);
Then, it's up to the implementation to either evaluate F or not, and if not evaluated nothing is executed.
Note: if you do not want a generic check, you can take Box<FnOnce() -> bool> as an argument; it will however require a heap allocation... just like in Haskell.
Let's see some code! Playground link
trait CheckTrait {
fn check<F: FnOnce() -> bool>(b: F);
}
struct CheckStructA {}
struct CheckStructB {}
impl CheckTrait for CheckStructA {
fn check<F: FnOnce() -> bool>(b: F) {
b();
println!("CheckStructA");
}
}
impl CheckTrait for CheckStructB {
fn check<F: FnOnce() -> bool>(_b: F) {
println!("CheckStructB");
}
}
fn show_stuff_a() -> bool {
println!("Show stuff A");
true
}
fn show_stuff_b() -> bool {
println!("Show stuff B");
true
}
fn test_a<T : CheckTrait>(_ : T) {
T::check(|| show_stuff_a());
}
fn test_b<T : CheckTrait>(_ : T) {
T::check(|| show_stuff_b());
}
fn main() {
test_a(CheckStructA{});
test_b(CheckStructB{});
}
I would like to be able to pass a generic function to another function (in this case a closure), without losing the "genericness" of the passed function. Since that's a pretty convoluted statement, here's an example:
use std::fmt::Debug;
fn test<F, I: Debug>(gen: F) where F: Fn(fn(I) -> I) -> I {
fn input<I: Debug>(x: I) -> I {
x
}
println!("{:?}", gen(input));
}
fn main() {
test(|input| {
input(10);
input(10.0)
});
}
This will not compile, because the value of input is type inferenced and no longer generic.
Full error:
<anon>:14:15: 14:19 error: mismatched types:
expected `_`,
found `_`
(expected integral variable,
found floating-point variable) [E0308]
<anon>:14 input(10.0)
^~~~
Is such a thing possible in rust?
edit:
Based on the solutions given, I've used the following to solve a similar problem:
#![feature(unboxed_closures)]
#![feature(fn_traits)]
use std::ops::Fn;
use std::ops::Add;
use std::ops::FnMut;
use std::fmt::Debug;
struct Builder;
impl Builder {
pub fn build<A: Add<B>, B: Add<A>>(&self) -> fn(A, B) -> <A as std::ops::Add<B>>::Output {
fn c<A: Add<B>, B: Add<A>>(a: A, b: B) -> <A as std::ops::Add<B>>::Output {
a + b
}
return c;
}
}
impl<A: Add<B>, B: Add<A>> Fn<(A, B)> for Builder {
extern "rust-call" fn call(&self, args: (A, B)) -> <A as std::ops::Add<B>>::Output {
let (a1, a2) = args;
self.build()(a1, a2)
}
}
impl<A: Add<B>, B: Add<A>> FnMut<(A, B)> for Builder {
extern "rust-call" fn call_mut(&mut self, args: (A, B)) -> <A as std::ops::Add<B>>::Output {
let (a1, a2) = args;
self.build()(a1, a2)
}
}
impl<A: Add<B>, B: Add<A>> FnOnce<(A, B)> for Builder {
type Output = <A as std::ops::Add<B>>::Output;
extern "rust-call" fn call_once(self, args: (A, B)) -> <A as std::ops::Add<B>>::Output {
let (a1, a2) = args;
self.build()(a1, a2)
}
}
fn test<F, I: Debug>(gen: F) where F: Fn(Builder) -> I {
let b = Builder;
println!("{:?}", gen(b));
}
fn main() {
test(|builder| {
builder(10, 10);
builder(10.1, 10.0)
});
}
As has been mentioned, unfortunately the call is monomorphized at the call site, so you cannot pass a generic function, you can only pass a monomorphized version of the generic function.
What you can pass, however, is a function builder:
use std::fmt::Debug;
struct Builder;
impl Builder {
fn build<I: Debug>(&self) -> fn(I) -> I {
fn input<I: Debug>(x: I) -> I { x }
input
}
}
fn test<F, T: Debug>(gen: F)
where F: Fn(Builder) -> T
{
let builder = Builder;
println!("{:?}", gen(builder));
}
fn main() {
test(|builder| {
builder.build()(10);
builder.build()(10.0)
});
}
The Builder is able to generate instances of input on demand.
Very interesting question! I'm pretty sure it's not possible like that.
Rust generics work by monomorphizing functions. This means that the Rust compiler will generate the machine code of the function for every concrete type the function is invoked with. Within one call of a function, the generic parameters are fixed. So since you call test exactly once in main, the generic parameters are fixed for that call.
This implies that the closure type is fixed and that the input parameter of the closure has a concrete type, too. The compiler deduces all the types for us, but if we would try to annotate these, we quickly notice that we run into the same problem as the compiler:
test::<_, usize> // we can't ever spell out a closure type, therefore '_'
(|input: fn(usize) -> usize| // we can't have a generic closure right now
{
input(10); // works
input(10.0) // doesn't work
});
This looks a lot like a use case for higher kinded types and generic closures. Both of those features are not available in Rust yet, AFAIK.
However, you can still achieve what you want by using dynamic dispatch:
fn test<F, I: Debug>(gen: F) where F: Fn(fn(Box<Debug>) -> Box<Debug>) -> I {
fn input(x: Box<Debug>) -> Box<Debug> {
x
}
println!("{:?}", gen(input));
}
fn main() {
test(|input| {
input(Box::new(10));
input(Box::new(10.0))
});
}
Of course, this is not as nice as the generic version, but at least it works. Also: if you don't actually need ownership in input, you can change Box<Debug> to &Debug.
I was under the impression that these two things were only semantically different.
However, this is possible:
struct Foo;
trait Bar<T> {
fn resolve(&self) -> T;
}
impl Bar<isize> for Foo {
fn resolve(&self) -> isize {
return 0isize;
}
}
impl Bar<usize> for Foo {
fn resolve(&self) -> usize {
return 1usize;
}
}
#[test]
fn test_foo() {
let foo = Foo;
assert!((&foo as &Bar<isize>).resolve() == 0isize);
assert!((&foo as &Bar<usize>).resolve() == 1usize);
}
While this is not:
struct Foo;
trait Bar {
type T;
fn resolve(&self) -> Self::T;
}
impl Bar for Foo {
type T = isize;
fn resolve(&self) -> isize {
return 0isize;
}
}
impl Bar for Foo {
type T = usize;
fn resolve(&self) -> usize {
return 1usize;
}
}
#[test]
fn test_foo() {
let foo = Foo;
assert!((&foo as &Bar<T = isize>).resolve() == 0isize);
assert!((&foo as &Bar<T = usize>).resolve() == 1isize);
}
It generates:
<anon>:8:1: 13:2 error: conflicting implementations for trait `Bar` [E0119]
<anon>: 8 impl Bar for Foo {
<anon>: 9 type T = isize;
<anon>:10 fn resolve(&self) -> isize {
<anon>:11 return 0isize;
<anon>:12 }
<anon>:13 }
Am I missing something?
Is there a special syntax for what I'm trying to achieve, or is there really a... technical... distinction between a generic and an associated type?
Is there some circumstance in which an associated type has a tangible (rather than purely code prettiness) benefit over using a generic?
I'll repeat my comment: it is true that type parameters and associated types are only semantically different. However, that's the main point why they are both present in the language - they do their own separate jobs, so it is not "just" semantic difference, it is the whole reason for their existence as a separate thing from type parameters.
Note that I do not even touch syntactic differences. Of course it is absolutely natural that there are syntactic differences. These are separate features after all; if they had no syntactic differences, then how you would distinguish between them? Their syntactic difference is closely tied to the semantic difference, because the way associated types are defined makes it clear that they have "output" position, compared to "input" position of type parameters, but technically both type parameters and associated types (and also the implicit Self, parameter, by the way) are the same thing.
For anyone else who finds this question, there is also another technical distinction between type parameters and associated types as well.
If you attempt to implement a trait with an associated type you may see the error:
src/lib.rs:10:1: 15:2 error: the impl does not reference any types
defined in this crate; only traits defined in the current crate can
be implemented for arbitrary types [E0117]
If you have traits exported in a crate bar:
pub trait BarParam<TRtn> {
fn bar() -> TRtn;
}
pub trait BarAssoc {
type TRtn;
fn bar() -> Self::TRtn;
}
You will find that a crate importing these traits will only be able to implement:
impl<'a> BarParam<Foo> for &'a str {
fn bar() -> Foo {
return Foo;
}
}
While attempting to implement:
impl<'a> BarAssoc for &'a str {
type TRtn = Foo;
fn bar() -> Foo {
return Foo;
}
}
Will result in the error above.
Frankly I'm not really sure what's going on here, so if you do, by all means add a comment or another answer; but this is a tangible reason to avoid associated types when you're writing a crate.
I initially assumed you could do this, because the documentation (http://doc.rust-lang.org/rust.html#implementations) suggests you can:
trait Bar<T> {
fn ex(&self) -> T;
}
struct Foo {
y:f64
}
impl Bar<int> for Foo {
fn ex(&self) -> int {
return self.y.floor() as int;
}
}
impl Bar<uint> for Foo {
fn ex(&self) -> uint {
if (self.y < 0.0) {
return 0u;
}
return self.y.floor() as uint;
}
}
...but that doesn't seem to work. I get errors like:
error: multiple applicable methods in scope
error: expected Bar<uint>, but found Bar<int> (expected uint but found int)
error: expected Bar<int>, but found Bar<uint> (expected int but found uint)
So I figured perhaps Foo has to be generic for this to work, so each specific Foo has it's own Bar implementation on it:
trait Bar<T> {
fn ex(&self) -> T;
}
struct Foo<T> {
y:f64
}
impl<T> Foo<T> {
fn new<U>(value:f64) -> Foo<U> {
return Foo { y: value } as Foo<U>;
}
}
impl Bar<int> for Foo<int> {
fn ex(&self) -> int {
return self.y.floor() as int;
}
}
impl Bar<uint> for Foo<uint> {
fn ex(&self) -> uint {
if (self.y < 0.0) {
return 0u;
}
return self.y.floor() as uint;
}
}
fn main() {
let z = Foo::new::<int>(100.5);
let q = Foo::new::<uint>(101.5);
let i:int = z.ex();
let j:uint = q.ex();
}
...but my constructor seems to not work:
x.rs:11:12: 11:38 error: non-scalar cast: `Foo<<generic #1>>` as `Foo<U>`
x.rs:11 return Foo { y: value } as Foo<U>;
^~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
Edit: I also tried:
impl<T> Foo<T> {
fn new<U>(value:f64) -> Foo<U> {
let rtn:Foo<U> = Foo { y: value };
return rtn;
}
}
Which solve the casting error, but results in:
x.rs:32:11: 32:26 error: cannot determine a type for this expression: unconstrained type
x.rs:32 let z = Foo::new::<int>(100.5);
^~~~~~~~~~~~~~~
O_o I have no idea what that means.
How do you do this?
The impl Bar<int> for Foo and impl Bar<uint> for Foo is an error because, at the moment, only one impl is allowed per trait, type pair (ignoring parameters on the trait). I went into more detail in this answer, including a work around using a secondary trait that avoids having to make Foo generic (which is probably not what you want).
trait BarForFoo {
fn do_ex(foo: &Foo) -> Self;
}
impl BarForFoo for int {
fn do_ex(foo: &Foo) -> int {
foo.y.floor() as int
}
}
impl BarForFoo for uint {
fn do_ex(foo: &Foo) -> uint {
foo.y.max(0.0).floor() as uint
}
}
impl<T: BarForFoo> Bar<T> for Foo {
fn ex(&self) -> T { BarForFoo::do_ex(self) }
}
The second error is because you have two type parameters T and U "in scope" for the new function, but are only specifying one (U). The T needs to be specified by writing Foo::<int>::..., however I don't think this is what you want, instead, you should be using the T generic in the new function:
impl<T> Foo<T> {
fn new(value: f64) -> Foo<T> { ... }
}
As background, the compiler needs to know the concrete type of T because the implementation of new could change:
impl<T> Foo<T> {
fn new<U>(value:f64) -> Foo<U> {
Foo { y: value + std::mem::size_of::<T>() as f64 }
}
}
and then Foo::<()>::new::<int>(0.0) would give y == 0.0, but Foo::<u64>::new::<int>(0.0) would give y == 8.0.