Trait is not implemented for the type `&A` when passing an array of pairs to a function - pointers

I am trying to write the function set which calls the Rust LMDB library (docs), and an example I'm working off of.
I can't for the life of me get this to work. Here is my current attempt:
fn main() {
let env = getenv("duperdb");
let dbhandle = get_dbhandle("", &env);
let txn = new_transaction(&env);
let vec = vec![("foo", "another text"), ("bar", "and another")];
set(&dbhandle, &env, &vec);
let reader = env.get_reader().unwrap();
let db = reader.bind(&dbhandle);
let note = db.get::<&str>("foo").unwrap();
println!("NOTE: {}", note);
}
Where set is defined as:
pub fn set<A: ToMdbValue, B: ToMdbValue>(
handle: &DbHandle,
env: &Environment,
pairs: &Vec<(&A, &B)>) -> () {
let txn = new_transaction(&env);
{
let db = txn.bind(&handle);
for &(id, note) in pairs.iter() {
db.set(&id, &note).unwrap();
}
}
match txn.commit() {
Err(_) => panic!("Failed to commit!"),
Ok(_) => (),
}
}
This spits out the following error:
src/db/wrapper.rs:28:20: 28:23 error: the trait `lmdb::traits::ToMdbValue` is not implemented for the type `&A` [E0277]
src/db/wrapper.rs:28 db.set(&id, &note).unwrap();
^~~
I also tried db.set(id, note).unwrap();, but this time I get:
src/main.rs:13:5: 13:8 error: the trait `core::marker::Sized` is not implemented for the type `str` [E0277]
src/main.rs:13 set(&dbhandle, &env, &vec);
^~~
src/main.rs:13:5: 13:8 help: run `rustc --explain E0277` to see a detailed explanation
src/main.rs:13:5: 13:8 note: `str` does not have a constant size known at compile-time
src/main.rs:13:5: 13:8 note: required by `dupernote::db::wrapper::set`
src/main.rs:13:5: 13:8 error: the trait `lmdb_rs::traits::ToMdbValue` is not implemented for the type `str` [E0277]
src/main.rs:13 set(&dbhandle, &env, &vec);
^~~
I also tried stuff like:
for (id, note) in pairs.iter() {
db.set(id, note).unwrap();
}
But that doesn't work either... I don't fully understand why. Doesn't id and note have type &str, not str?

Here's an MCVE of your problem:
trait Example {}
impl Example for i32 {}
fn library_call<T>(value: T)
where T: Example,
{}
fn user_call<T>(values: &[T])
where T: Example,
{
for i in values {
library_call(i);
}
}
fn main() {
let values = vec![1, 2, 3];
user_call(&values);
}
With the error:
error: the trait `Example` is not implemented for the type `&T` [E0277]
library_call(i);
^~~~~~~~~~~~
The error message is exactly correct - Example is not implemented for &T, it's only guaranteed to be implemented for T. &T and T are different types.
Instead, you need to indicate that a reference to the generic type implements the trait you need:
fn user_call<T>(values: &[T])
where for <'a> &'a T: Example,
And then you need to make sure that a reference to the concrete type actually implements the trait:
impl<'a> Example for &'a i32 {}
Or a broader version:
impl<'a, T> Example for &'a T
where T: Example
{}
See also When should I not implement a trait for references to implementors of that trait?

The definition of the function that gives you an error (if I'm reading the docs right):
fn set(&self, key: &ToMdbValue, value: &ToMdbValue) -> MdbResult<()>
key must be a reference to a trait object. You are trying to pass a reference to a generic type implmementing ToMdbValue.
https://doc.rust-lang.org/book/trait-objects.html
I can't verify but this should work:
pub fn set(handle: &DbHandle, env: &Environment, pairs: &Vec<(&ToMdbValue, &ToMdbValue)>) -> () {
let txn = new_transaction(&env);
{
let db = txn.bind(&handle);
for &(id, note) in pairs.iter() {
db.set(id, note).unwrap();
}
}
match txn.commit() {
Err(_) => panic!("Failed to commit!"),
Ok(_) => (),
}
}
Other things: you may want to work with boxed trait objects Box<ToMdbValue>. The link above explains it. You should pass a &[YourType] rather than &Vec<[YourType]>.

I managed to get it working. I'm not sure how kosher this solution is, but I'll post it.
So now, in main(), I do the following (example with an (int, string) kv pair):
let k = 1;
let val = "hello there";
let vec = vec![(&k, &val)];
set(&dbhandle, &env, &vec);
I had to declare them separately since vec![(&1, &"hello there")] threw an error of the form borrowed value does not live long enough.
set now looks like this:
pub fn set<A, B>(handle: &DbHandle, env: &Environment, pairs: &Vec<(&A, &B)>)
-> ()
where A: ToMdbValue,
B: ToMdbValue {
let txn = new_transaction(&env);
{
let db = txn.bind(&handle);
for &(id, note) in pairs.iter() {
db.set(id, note).unwrap();
}
}
match txn.commit() {
Err(_) => panic!("Failed to commit!"),
Ok(_) => (),
}
}

Related

How to convert Vec<Item> to Vec<String>?

I have the following object, and trying to convert Vec<Courses> and retrieve CourseName.
pub struct Schools {
pub courses: Vec<CourseName>,
}
pub struct CourseName(String);
impl CourseName {
pub fn as_str(&self) -> &str {
&self.0[..]
}
}
Trying to get the Vec<String>, but my following approach does not work,
assigned_courses:Vec<String> = courses.iter().map(|c| c.clone().as_str()).collect()
getting the following error:
value of type `Vec<std::string::String>` cannot be built from `std::iter::Iterator<Item=&str>`
Update:
The map closure receives a &CourseName so clone just copies the reference. What you instead want is to access the tuple and clone the inner String with c.0.
let assigned_courses: Vec<String> = courses.iter().map(|c| c.0.clone()).collect();
Alternatively, if references to the course names are enough, then instead you can use as_str on the inner String.
let assigned_courses: Vec<&str> = schools.courses.iter().map(|c| c.0.as_str()).collect();
To fix the "private field" error. You can add a visibility modifier, e.g.
pub struct CourseName(pub String);
However, it's probably better to keep it as private, and instead add a method like as_str().
impl CourseName {
pub fn as_str(&self) -> &str {
&self.0
}
}
Then resulting in:
let assigned_courses: Vec<String> = schools.courses.iter().map(|c| c.as_str().to_string()).collect();
Alternatively, you could also impl AsRef<str> and/or Display for CourseName, to make everything more generalized.
Assuming that CourseName is just to have a typed version instead of a String. Then you could instead impl Display for CourseName.
use std::fmt;
pub struct CourseName(String);
impl fmt::Display for CourseName {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}
This allows you to do println!("{}, course") along with course.to_string().
let assigned_courses: Vec<String> = schools.courses.iter().map(|c| c.to_string()).collect();
Working example:
#[derive(Debug)]
pub struct CourseName(pub String);
fn courses_to_strings(list: &[CourseName]) -> Vec<String> {
list.iter().map(|course| course.0.clone()).collect()
}
fn main() {
let courses: Vec<CourseName> = vec![
CourseName("a".to_string()),
CourseName("b".to_string())
];
let strings = courses_to_strings(&courses);
dbg!(strings);
}
playground
All you needed to do was clone the String instead of the CourseName tuple struct in your map function, and also add the pub visibility modifier to the internal String.

How to implement a Future or Stream that polls an async fn?

I have a struct Test I want to implement std::future::Future that would poll function:
use std::{
future::Future,
pin::Pin,
task::{Context, Poll},
};
struct Test;
impl Test {
async fn function(&mut self) {}
}
impl Future for Test {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
match self.function() {
Poll::Pending => Poll::Pending,
Poll::Ready(_) => Poll::Ready(()),
}
}
}
That didn't work:
error[E0308]: mismatched types
--> src/lib.rs:17:13
|
10 | async fn function(&mut self) {}
| - the `Output` of this `async fn`'s expected opaque type
...
17 | Poll::Pending => Poll::Pending,
| ^^^^^^^^^^^^^ expected opaque type, found enum `Poll`
|
= note: expected opaque type `impl Future`
found enum `Poll<_>`
error[E0308]: mismatched types
--> src/lib.rs:18:13
|
10 | async fn function(&mut self) {}
| - the `Output` of this `async fn`'s expected opaque type
...
18 | Poll::Ready(_) => Poll::Ready(()),
| ^^^^^^^^^^^^^^ expected opaque type, found enum `Poll`
|
= note: expected opaque type `impl Future`
found enum `Poll<_>`
I understand that function must be called once, the returned Future must be stored somewhere in the struct, and then the saved future must be polled. I tried this:
struct Test(Option<Box<Pin<dyn Future<Output = ()>>>>);
impl Test {
async fn function(&mut self) {}
fn new() -> Self {
let mut s = Self(None);
s.0 = Some(Box::pin(s.function()));
s
}
}
That also didn't work:
error[E0277]: the size for values of type `(dyn Future<Output = ()> + 'static)` cannot be known at compilation time
--> src/lib.rs:7:13
|
7 | struct Test(Option<Box<Pin<dyn Future<Output = ()>>>>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `(dyn Future<Output = ()> + 'static)`
After I call function() I have taken a &mut reference of Test, because of that I can't change the Test variable, and therefore can't store the returned Future inside the Test.
I did get an unsafe solution (inspired by this)
struct Test<'a>(Option<BoxFuture<'a, ()>>);
impl Test<'_> {
async fn function(&mut self) {
println!("I'm alive!");
}
fn new() -> Self {
let mut s = Self(None);
s.0 = Some(unsafe { &mut *(&mut s as *mut Self) }.function().boxed());
s
}
}
impl Future for Test<'_> {
type Output = ();
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
self.0.as_mut().unwrap().poll_unpin(cx)
}
}
I hope that there is another way.
Though there are times when you may want to do things similar to what you're trying to accomplish here, they are a rarity. So most people reading this, maybe even OP, may wish to restructure such that struct state and data used for a single async execution are different objects.
To answer your question, yes it is somewhat possible. Unless you want to absolutely resort to unsafe code you will need to use Mutex and Arc. All fields you wish to manipulate inside the async fn will have to be wrapped inside a Mutex and the function itself will accept an Arc<Self>.
I must stress, however, that this is not a beautiful solution and you probably don't want to do this. Depending on your specific case your solution may vary, but my guess of what OP is trying to accomplish while using Streams would be better solved by something similar to this gist that I wrote.
use std::{
future::Future,
pin::Pin,
sync::{Arc, Mutex},
};
struct Test {
state: Mutex<Option<Pin<Box<dyn Future<Output = ()>>>>>,
// if available use your async library's Mutex to `.await` locks on `buffer` instead
buffer: Mutex<Vec<u8>>,
}
impl Test {
async fn function(self: Arc<Self>) {
for i in 0..16u8 {
let data: Vec<u8> = vec![i]; // = fs::read(&format("file-{}.txt", i)).await.unwrap();
let mut buflock = self.buffer.lock().unwrap();
buflock.extend_from_slice(&data);
}
}
pub fn new() -> Arc<Self> {
let s = Arc::new(Self {
state: Default::default(),
buffer: Default::default(),
});
{
// start by trying to aquire a lock to the Mutex of the Box
let mut lock = s.state.lock().unwrap();
// create boxed future
let b = Box::pin(s.clone().function());
// insert value into the mutex
*lock = Some(b);
} // block causes the lock to be released
s
}
}
impl Future for Test {
type Output = ();
fn poll(
self: std::pin::Pin<&mut Self>,
ctx: &mut std::task::Context<'_>,
) -> std::task::Poll<<Self as std::future::Future>::Output> {
let mut lock = self.state.lock().unwrap();
let fut: &mut Pin<Box<dyn Future<Output = ()>>> = lock.as_mut().unwrap();
Future::poll(fut.as_mut(), ctx)
}
}
I'm not sure what you want to achieve and why, but I suspect that you're trying to implement Future for Test based on some ancient tutorial or misunderstanding and just overcomplicating things.
You don't have to implement Future manually. An async function
async fn function(...) {...}
is really just syntax sugar translated behind the scenes into something like
fn function(...) -> Future<()> {...}
All you have to do is to use the result of the function the same way as any future, e.g. use await on it or call block a reactor until it's finished. E.g. based on your first version, you can simply call:
let mut test = Test{};
test.function().await;
UPDATE1
Based on your descriptions I still think you're trying to overcomplicate this minimal working snippet without the need to manually implement Future for anything:
async fn asyncio() { println!("Doing async IO"); }
struct Test {
count: u32,
}
impl Test {
async fn function(&mut self) {
asyncio().await;
self.count += 1;
}
}
#[tokio::main]
async fn main() {
let mut test = Test{count: 0};
test.function().await;
println!("Count: {}", test.count);
}

How to return a function that returns a trait in Rust

My goal is to implement a function that returns another function, which returns some trait. To be more specific, the returned function should itself return a Future.
To return a function that returns a concrete type, we obviously can do this:
fn returns_closure() -> impl Fn(i32) -> i32 {
|x| x + 1
}
But what if instead of i32 we want to return a Future?
I tried the following:
use futures::Future;
fn factory() -> (impl Fn() -> impl Future) {
|| async {
// some async code
}
}
This does not work because the second impl keyword is not allowed:
error[E0562] `impl Trait` not allowed outside of function and inherent method return types
What is the best way to solve this issue?
I don't know of any way to do this on stable Rust. However, you can use a type alias for an opaque type (also known as existential type) on Rust nightly like this (playground):
#![feature(type_alias_impl_trait)]
use futures::Future;
type Fut<O> = impl Future<Output = O>;
fn factory<O>() -> impl Fn() -> Fut<O> {
|| async {
todo!()
}
}

Unable to return a vector of string slices: borrowed value does not live long enough

I'm new to Rust and I'm having some trouble with the borrow checker. I don't understand why this code won't compile. Sorry if this is close to a previously answered question but I can't seem to find a solution in the other questions I've looked at.
I understand the similarity to Return local String as a slice (&str) but in that case it is just one string being returned and not enough for me to reason with my code in which I am trying to return a vector. From what I understand, I am trying to return references to str types that will go out of scope at the end of the function block and so should I be mapping that vector of &str into a vector of String? I am not so concerned about the performance effects of converting &str to String. First I'd just like to get it working.
This is the code, the error is in the lex function.
use std::io::prelude::*;
use std::fs::File;
use std::env;
fn open(mut s: &mut String, filename: &String) {
let mut f = match File::open(&filename) {
Err(_) => panic!("Couldn't open file"),
Ok(file) => file,
};
match f.read_to_string(&mut s) {
Err(_) => panic!("Couldn't read file"),
Ok(_) => println!("File read successfully"),
};
}
fn lex(s: &String) -> Vec<&str> {
let token_string: String = s.replace("(", " ( ")
.replace(")", " ) ");
let token_list: Vec<&str> = token_string.split_whitespace()
.collect();
token_list
}
fn main() {
let args: Vec<_> = env::args().collect();
if args.len() < 2 {
panic!("Please provide a filename");
} else {
let ref filename = args[1];
let mut s = String::new();
open(&mut s, filename);
let token_list: Vec<&str> = lex(&s);
println!("{:?}", token_list);
}
}
Here is the error message
error: borrowed value does not live long enough
self.0.borrow().values.get(idx)
^~~~~~~~~~~~~~~
reference must be valid for the anonymous lifetime #1 defined on the block at 23:54...
pub fn value(&self, idx: usize) -> Option<&Value> {
^
note: ...but borrowed value is only valid for the block at 23:54
pub fn value(&self, idx: usize) -> Option<&Value> {
^
I'm finding it hard to reason with this code because with my level of experience with Rust I can't visualise the lifetimes of these variables. Any help would be appreciated as I've spent an hour or two trying to figure this out.
The problem is that you're allocating a new String (token_string) inside the lex function and then returning an array of references to it, but token_string will get dropped (and the memory freed) as soon as it falls out of scope at the end of the function.
fn lex(s: &String) -> Vec<&str> {
let token_string: String = s.replace("(", " ( ") // <-- new String allocated
.replace(")", " ) ");
let token_list: Vec<&str> = token_string.split_whitespace()
.collect();
token_list // <-- this is just an array of wide pointers into token_string
} // <-- token_string gets freed here, so the returned pointers
// would be pointing to memory that's already been dropped!
There's a couple of ways to address this. One would be to force the caller of lex to pass in the buffer that you want to use to collect into. This would change the signature to fn lex<'a>(input: &String, buffer: &'a mut String) -> Vec<&'a str> This signature would specify that the lifetimes of the returned &strs will be at least as long as the lifetime of the buffer that's passed in.
Another way would be to just return a Vec<String> instead of Vec<&str> if you can tolerate the extra allocations.

Returning Error Enumeration with an Arbitrary Variable

I have a function in Rust using try! that attempts to collect all files in a directory recursively and insert them into a vector. Because the function uses try! to check errors, the compiler seems to expect an io::Result return from the function, and doesn't let me include the vector because the try! macro only returns a result. I need the vector to be returned.
Code is as follows:
mod os{
use std::io;
use std::fs::{self, DirEntry};
//use std::fs;
use std::path::Path;
// one possible implementation of walking a directory only visiting files
pub fn visit_dirs(dir: &Path, cb: &Fn(&DirEntry)) -> (io::Result<()>,Vec<String>) {
let mut filevec: Vec<String> = Vec::new();
if try!(fs::metadata(dir)).is_dir() {
for entry in try!(fs::read_dir(dir)) {
let entry = try!(entry);
if try!(fs::metadata(entry.path())).is_dir() {
try!(visit_dirs(&entry.path(), cb));
} else {
cb(&entry);
}
}
}
(Ok(()),filevec)
}
fn push_path_to_vec(p:&DirEntry,v:Vec<String>){
v.push(p.path().to_str().unwrap().to_string());
}}
Here is the error:
<std macros>:5:8: 6:42 error: mismatched types:
expected `(core::result::Result<(), std::io::error::Error>, collections::vec::Vec<collections::string::String>)`
found `core::result::Result<_, _>`
(expected tuple,
found enum `core::result::Result`) [E0308]
I wonder if there's any idiomatic way to do this that I've missed.
The return type of visit_dirs is wrong. The function should return a Result, but right now it returns a tuple. Since try! only works for functions returning a Result, your code doesn't compile. You can change the return value of visit_dirs in order to fix it:
pub fn visit_dirs(dir: &Path, cb: &Fn(&DirEntry)) -> io::Result<Vec<String>>
The new definition means that a Vec<String> will be stored in the Result upon success. With some minor tweaks, the code is accepted by the compiler (see below)
mod os{
use std::io;
use std::fs::{self, DirEntry};
//use std::fs;
use std::path::Path;
// one possible implementation of walking a directory only visiting files
pub fn visit_dirs(dir: &Path, cb: &Fn(&DirEntry)) -> io::Result<Vec<String>> {
let mut filevec: Vec<String> = Vec::new();
if try!(fs::metadata(dir)).is_dir() {
for entry in try!(fs::read_dir(dir)) {
let entry = try!(entry);
if try!(fs::metadata(entry.path())).is_dir() {
try!(visit_dirs(&entry.path(), cb));
} else {
cb(&entry);
}
}
}
Ok(filevec)
}
fn push_path_to_vec(p:&DirEntry,mut v:Vec<String>){
v.push(p.path().to_str().unwrap().to_string());
}}

Resources