Trait не реализован для типа `&A` при передаче массива пар в функцию
Я пытаюсь написать функцию set
которая вызывает библиотеку Rust LMDB( docs) и пример, над которым я работаю.
Я не могу на всю жизнь заставить это работать. Вот моя текущая попытка:
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);
}
куда set
определяется как:
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, ¬e).unwrap();
}
}
match txn.commit() {
Err(_) => panic!("Failed to commit!"),
Ok(_) => (),
}
}
Это выдает следующую ошибку:
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, ¬e).unwrap();
^~~
Я тоже пробовал db.set(id, note).unwrap();
, но на этот раз я получаю:
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);
^~~
Я также пробовал такие вещи, как:
for (id, note) in pairs.iter() {
db.set(id, note).unwrap();
}
Но это тоже не работает... Я не до конца понимаю почему. не id
а также note
иметь тип &str
не str
?
3 ответа
Мне удалось заставить его работать. Я не уверен, насколько кошерное это решение, но я выложу его.
Так что теперь, в main()
Я делаю следующее (пример с (int, string)
кв пара):
let k = 1;
let val = "hello there";
let vec = vec![(&k, &val)];
set(&dbhandle, &env, &vec);
Я должен был объявить их отдельно, так как vec![(&1, &"hello there")]
выкинул ошибку формы borrowed value does not live long enough
,
set
теперь выглядит так:
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(_) => (),
}
}
Вот MCVE вашей проблемы:
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);
}
С ошибкой:
error: the trait `Example` is not implemented for the type `&T` [E0277]
library_call(i);
^~~~~~~~~~~~
Сообщение об ошибке совершенно правильно - Example
не реализовано для &T
, это гарантированно будет реализовано только для T
, &T
а также T
разные типы.
Вместо этого вам нужно указать, что ссылка на универсальный тип реализует необходимую вам черту:
fn user_call<T>(values: &[T])
where for <'a> &'a T: Example,
И затем вам нужно убедиться, что ссылка на конкретный тип действительно реализует эту черту:
impl<'a> Example for &'a i32 {}
Или более широкая версия:
impl<'a, T> Example for &'a T
where T: Example
{}
См. Также, Когда я не должен реализовывать черту для ссылок на разработчиков этой черты?
Определение функции, которая выдает ошибку (если я правильно читаю документы):
fn set(&self, key: &ToMdbValue, value: &ToMdbValue) -> MdbResult<()>
key
должна быть ссылкой на объект черты. Вы пытаетесь передать ссылку на реализацию универсального типа ToMdbValue
,
https://doc.rust-lang.org/book/trait-objects.html
Я не могу проверить, но это должно работать:
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(_) => (),
}
}
Другие вещи: вы можете работать с объектами в штучной упаковке Box<ToMdbValue>
, Ссылка выше объясняет это. Вы должны пройти &[YourType]
скорее, чем &Vec<[YourType]>
,