Compiler error - mismatched types when trying to implement a proxy pattern in rust - rust

I trying to implement a proxy in Rust, allowing me to read a model, but also to perform mutable operations. To avoid having two different implementations of the proxy (one mutable, one immutable), I made the proxy implementation generic.
I would like the proxy to create other instances of self, in different situations, and this is where I got a type mismatch.
The code below reproduces the problem I have:
use std::borrow::{Borrow, BorrowMut};
struct Model {
data: Vec<u32>,
}
impl Model {
fn get_proxy(&self) -> Proxy<&Model> {
Proxy::new(self)
}
fn get_proxy_mut(&mut self) -> Proxy<&mut Model> {
Proxy::new(self)
}
}
struct Proxy<M: Borrow<Model>> {
model: M
}
impl<M: Borrow<Model>> Proxy<M> {
fn new(model: M) -> Self {
Self {model}
}
fn get_another(&self) -> Proxy<M> {
// FIRST ERROR here
self.model.borrow().get_proxy()
}
}
impl<M: BorrowMut<Model>> Proxy<M> {
fn get_another_mut(&mut self) -> Proxy<M> {
// SECOND ERROR here
self.model.borrow_mut().get_proxy_mut()
}
}
The first compiler error looks like
error[E0308]: mismatched types
--> src\sandbox.rs:28:9
|
21 | impl<'m, M: Borrow<Model>> Proxy<M> {
| - this type parameter
...
26 | fn get_another(&self) -> Proxy<M> {
| -------- expected `Proxy<M>` because of return type
27 | // FIRST ERROR here
28 | self.model.borrow().get_proxy()
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `M`, found `&Model`
|
= note: expected struct `Proxy<M>`
found struct `Proxy<&Model>`
Any idea how to fix the first error? (I assume the second one will be fixed in a similar way).

Related

How to define impl on standard types in Rust?

How can we define a wrapper type around an existing type and define functions over it?
I have tried the below code and I am getting this error
struct Deploy(u8);
impl Deploy {
fn values_yaml(self) -> u8 {
self+1
}
fn chart(self) -> u8 {
self+1
}
}
fn main() {
let a = Deploy(1);
println!("Hello, world! {:?}", a.chart());
}
error:
error[E0369]: cannot add `{integer}` to `Deploy`
--> src/main.rs:5:11
|
5 | self+1
| ----^- {integer}
| |
| Deploy
|
note: an implementation of `Add<_>` might be missing for `Deploy`
Any suggestion is most welcome.
You're dealing with a tuple struct, with tuple size 1. The elements of tuples are accessed via the usual syntax for tuples in Rust:
self.0
Alternatively, you can also match the fields similarly to regular tuples.
let Deploy(resource_type) = self;

Is there a way to bring all the traits from a module in scope without also importing other types?

I'm building a wrapper around a DLL. This DLL gives me access to a database engine which implements an OOP design pattern. This requires me to create multiple overlapping traits that cover all the functionality:
pub trait CursorStatement { /* ... */ }
pub trait CursorTable { /* ... */ }
pub trait CursorStatementTable { /* ... */ }
...
I want to be able to bring these traits in scope so that I can call the functions without having to list every trait. Right now I'm doing:
mod traittest;
use traittest::*;
fn test() -> Result<(), AceError> {
let t = traittest::Table::new(3, "ORDERS")?;
let c = traittest::Cursor { handle: 42 };
println!("t.fields={}", t.fields());
println!("c.fields={}", c.fields());
Ok(())
}
fn main() {
test().expect("success");
}
The problem with use foo::* is that it puts everything from the module into my namespace, which I don't want.
In the example above, I don't have to type traittest::Table or traittest::Cursor, I just have to type Table or Cursor. However, I want to have to prefix those objects with the module name so when I'm reading the code I know where the objects came from. I might want to create a Table object in my local file that is distinguished from the one coming from the module.
I also don't want to have to do the following because if I later have to add a new trait I will have to update a bunch of other source files that depend on this module:
mod traittest;
use traittest::{CursorStatement, CursorStatementTable, CursorTable, /* ... */};
I tried creating a Traits supertrait that would inherit all other traits as shown in Is there any way to create a type alias for multiple traits?, but it doesn't work because I can't implement the trait for anything because there's nothing that would be an implementation of every trait in the file:
pub trait Traits: CursorStatement, CursorTable, CursorStatementHandle, /* ... */ {}
If I could create a named scope for all the traits, that would work, but I can't figure out how to make Rust happy with this idea:
let traits = {
pub trait CursorTable { /* ... */ }
}
It looks like this trait_group macro might do the trick but it's not obvious to me how I could use it to solve my problem.
Here's my entire program
mod traittest {
#[derive(Debug)]
pub struct AceError {
code: u32,
description: String,
}
pub trait CursorTable {
fn get_handle(&self) -> u32; // impl's must write this function
fn fields(&self) -> String {
return format!("(get_handle() -> {})", self.get_handle());
}
}
pub struct Table {
pub handle: u32,
pub table_name: String,
}
pub struct Cursor {
pub handle: u32,
}
impl Table {
pub fn new(handle: u32, table_name: &str) -> Result<Table, AceError> {
let table = Table {
handle: handle,
table_name: table_name.to_string(),
};
return Ok(table);
}
}
impl CursorTable for Table {
fn get_handle(&self) -> u32 {
return self.handle;
}
}
impl CursorTable for Cursor {
fn get_handle(&self) -> u32 {
return self.handle;
}
}
pub trait Traits: CursorTable {} /* super trait to bring all other traits in scope */
}
use traittest::Traits;
fn test() -> Result<(), traittest::AceError> {
let t = traittest::Table::new(3, "ORDERS")?;
let c = traittest::Cursor { handle: 42 };
println!("t.fields={}", t.fields());
println!("c.fields={}", c.fields());
Ok(())
}
fn main() {
test().expect("success");
}
and here's the error I get:
warning: unused import: `traittest::Traits`
--> src/main.rs:49:5
|
49 | use traittest::Traits;
| ^^^^^^^^^^^^^^^^^
|
= note: `#[warn(unused_imports)]` on by default
error[E0599]: no method named `fields` found for struct `traittest::Table` in the current scope
--> src/main.rs:54:31
|
10 | fn fields(&self) -> String {
| ------
| |
| the method is available for `std::boxed::Box<traittest::Table>` here
| the method is available for `std::sync::Arc<traittest::Table>` here
| the method is available for `std::rc::Rc<traittest::Table>` here
...
15 | pub struct Table {
| ---------------- method `fields` not found for this
...
54 | println!("t.fields={}", t.fields());
| ^^^^^^ method not found in `traittest::Table`
|
= help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
|
49 | use crate::traittest::CursorTable;
|
error[E0599]: no method named `fields` found for struct `traittest::Cursor` in the current scope
--> src/main.rs:55:31
|
10 | fn fields(&self) -> String {
| ------
| |
| the method is available for `std::boxed::Box<traittest::Cursor>` here
| the method is available for `std::sync::Arc<traittest::Cursor>` here
| the method is available for `std::rc::Rc<traittest::Cursor>` here
...
20 | pub struct Cursor {
| ----------------- method `fields` not found for this
...
55 | println!("c.fields={}", c.fields());
| ^^^^^^ method not found in `traittest::Cursor`
|
= help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
|
49 | use crate::traittest::CursorTable;
|
I finally figured out a solution I can live with, in case anybody else is looking for a solution to this problem.
In your module where you define your traits, create a sub-module with all the traits, like so:
pub mod Traits
{
pub trait CursorTrait
{
fn get_handle ( &self ) -> u32; // impl's must write this function
fn fields ( &self ) -> String
{
return format! ( "(get_handle() -> {})", self.get_handle() );
}
}
}
Now in your other modules, if you want to bring the traits in scope without bringing in the entire module, you can just bring in the submodule, like so:
mod foo; use foo::Traits::*;

Substrate: How to integrate with the session module

I'm working on a toy validator addition module to better understand the workings of the session module. Here is my complete attempt on github.
I've got my code nearly working but I'm running into type-checking errors in my implementation of OnSessionEnding.
impl<T: Trait> OnSessionEnding<T::AccountId> for Module<T> {
fn on_session_ending(_ending_index: SessionIndex, _will_apply_at: SessionIndex) -> Option<Vec<T::AccountId>> {
match <QueuedValidator<T>>::get() {
Some(n00b) => {
// Get the list of current validators from the session module
let mut validators = session::Module::<T>::validators();
validators.push(T::ValidatorIdOf::convert(n00b.clone()).unwrap());
Some(validators.into())
}
None => None
}
}
}
// https://github.com/paritytech/substrate/blob/4a17a8aaa5042759d934abb10b1703ffdff7d902/bin/node-template/runtime/src/add_validator.rs#L66-L79
I'm not sure what the type-checker needs to understand that ValidatorId and AccountId are truly the same type as I've declared them to be.
impl session::Trait for Runtime {
// --snip--
type ValidatorId = <Self as system::Trait>::AccountId;
type ValidatorIdOf = ConvertInto;
}
// https://github.com/paritytech/substrate/blob/4a17a8aaa5042759d934abb10b1703ffdff7d902/bin/node-template/runtime/src/lib.rs#L250-L262
The exact error is
error[E0277]: the trait bound `add_validator::sr_api_hidden_includes_decl_storage::hidden_include::sr_primitives::substrate_application_crypto::substrate_primitives::sr_std::prelude::Vec<<T as palette_system::Trait>::AccountId>: core::convert::From<add_validator::sr_api_hidden_includes_decl_storage::hidden_include::sr_primitives::substrate_application_crypto::substrate_primitives::sr_std::prelude::Vec<<T as pallet_session::Trait>::ValidatorId>>` is not satisfied
--> /home/joshy/ProgrammingProjects/substrate/bin/node-template/runtime/src/add_validator.rs:73:10
|
73 | Some(validators.into())
| ^^^^^^^^^^^^^^^^^ the trait `core::convert::From<add_validator::sr_api_hidden_includes_decl_storage::hidden_include::sr_primitives::substrate_application_crypto::substrate_primitives::sr_std::prelude::Vec<<T as pallet_session::Trait>::ValidatorId>>` is not implemented for `add_validator::sr_api_hidden_includes_decl_storage::hidden_include::sr_primitives::substrate_application_crypto::substrate_primitives::sr_std::prelude::Vec<<T as palette_system::Trait>::AccountId>`
|
= note: required because of the requirements on the impl of `core::convert::Into<add_validator::sr_api_hidden_includes_decl_storage::hidden_include::sr_primitives::substrate_application_crypto::substrate_primitives::sr_std::prelude::Vec<<T as palette_system::Trait>::AccountId>>` for `add_validator::sr_api_hidden_includes_decl_storage::hidden_include::sr_primitives::substrate_application_crypto::substrate_primitives::sr_std::prelude::Vec<<T as pallet_session::Trait>::ValidatorId>`
Or without the final .into() it becomes
error[E0308]: mismatched types
--> /home/joshy/ProgrammingProjects/substrate/bin/node-template/runtime/src/add_validator.rs:73:10
|
73 | Some(validators)
| ^^^^^^^^^^ expected palette_system::Trait::AccountId, found pallet_session::Trait::ValidatorId
|
= note: expected type `add_validator::sr_api_hidden_includes_decl_storage::hidden_include::sr_primitives::substrate_application_crypto::substrate_primitives::sr_std::prelude::Vec<<T as palette_system::Trait>::AccountId>`
found type `add_validator::sr_api_hidden_includes_decl_storage::hidden_include::sr_primitives::substrate_application_crypto::substrate_primitives::sr_std::prelude::Vec<<T as pallet_session::Trait>::ValidatorId>`
To fix the build above, change the OnSessionEnding's type parameter to T::ValidatorId.
- impl<T: Trait> OnSessionEnding<T::AccountId> for Module<T> {
+ impl<T: Trait> OnSessionEnding<T::ValidatorId> for Module<T> {
Here is the full working implementation
impl<T: Trait> OnSessionEnding<T::ValidatorId> for Module<T> {
fn on_session_ending(_ending_index: SessionIndex, _will_apply_at: SessionIndex) -> Option<Vec<T::ValidatorId>> {
match <QueuedValidator<T>>::get() {
Some(n00b) => {
// Get the list of current validators from the session module
let mut validators = session::Module::<T>::validators();
// Add the new validator to the list
//TODO handle the unwrapping better
validators.push(T::ValidatorIdOf::convert(n00b.clone()).unwrap());
// Clear the queued validator from local storage
<QueuedValidator<T>>::kill();
// Return the vector of new validators
Some(validators)
}
None => None
}
}
}
(This answer is courtesy of #sushisource:matrix.org)

Rust lifetimes for struct references

I've just started with Rust but can't quite grasp lifetimes so I could resolve following issue by myself:
This test project is about simulating a bit to allow tracing it through various bitwise operations, e.g. let newbit = oldbit1 ^ oldbit2 and looking at newbit I can tell afterwards it came out of an XOR operation with oldbit1 and oldbit2 as operands.
#[derive(Copy,Clone)]
pub enum TraceOperation {
AND,
OR,
XOR,
NOT,
}
#[derive(Copy,Clone)]
pub struct TraceBit<'a> {
source_a: Option<&'a TraceBit<'a>>,
source_b: Option<&'a TraceBit<'a>>,
source_op: Option<TraceOperation>,
value: bool,
}
This compiles, but I don't fully understand why the lifetime parameters are needed that way. I assume that the compiler cannot expect that the members source_a and source_b live as long as the struct itself as this may not hold true, so explicit lifetimes are required.
is this assumption correct?
Further I don't fully understand why I have to re-specify the lifetime parameter for the reference type, i.e. why I have to write source_a: Option<&'a TraceBit<'a>> as opposed to source_a: Option<&'a TraceBit>.
What is the second lifetime used for? How do I read that line out loud? I have:
"source_a is a variable of type Option that may have Some reference (that is valid at least as long as the struct itself and as long as member source_b) to an instance of TraceBit"
My final issue is that I cannot make it to work using an overloaded operator:
use std::ops::BitXor;
impl<'a> BitXor for TraceBit<'a> {
type Output = Self;
fn bitxor(self, rhs: Self) -> Self {
let valA: usize = if self.value { 1 } else { 0 };
let valB: usize = if rhs.value { 1 } else { 0 };
let val = if valA ^ valB != 0 { true } else { false };
TraceBit { source_a: Some(&self), source_b: Some(&rhs), source_op: Some(TraceOperation::XOR), value: val }
}
}
This is basically pure guessing based on BitXor documentation. So what I try to do, in a very explicit manner, is to perform an xor operation on the two input variables and create a new TraceBit as output with the inputs stored in it as reference.
error[E0597]: `self` does not live long enough
--> libbittrace/src/lib.rs:37:30
|
37 | TraceBit { source_a: Some(&self), source_b: Some(&rhs), source_op: Some(TraceOperation::XOR), value: val }
| ^^^^ does not live long enough
38 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'a as defined on the impl at 31:1...
--> libbittrace/src/lib.rs:31:1
|
31 | / impl<'a> BitXor for TraceBit<'a> {
32 | | type Output = Self;
33 | | fn bitxor(self, rhs: Self) -> Self {
34 | | let valA: usize = if self.value { 1 } else { 0 };
... |
40 | |
41 | | }
| |_^
error[E0597]: `rhs` does not live long enough
--> libbittrace/src/lib.rs:37:53
|
37 | TraceBit { source_a: Some(&self), source_b: Some(&rhs), source_op: Some(TraceOperation::XOR), value: val }
| ^^^ does not live long enough
38 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'a as defined on the impl at 31:1...
--> libbittrace/src/lib.rs:31:1
|
31 | / impl<'a> BitXor for TraceBit<'a> {
32 | | type Output = Self;
33 | | fn bitxor(self, rhs: Self) -> Self {
34 | | let valA: usize = if self.value { 1 } else { 0 };
... |
40 | |
41 | | }
| |_^
error: aborting due to 2 previous errors
Seems like nothing lives longer than the xor operation itself, but how can I resolve this?
I've tried various workarounds/changes to the code but to no avail and in any way I rather like to understand the issue than guessing a correct solution....
Tree-like structures must use the Box pointer type (Option<Box<TraceBit>>). In general, in structs you should prefer owned types.
Rust references aren't mere pointers. They are borrows (compile-time read/write locks) of data that must exist as owned somewhere else.
So if you have an owned version of TraceBit:
pub struct TraceBit {
source_a: Option<Box<TraceBit>>,
}
then reference to it is of type: &'a TraceBit, but references to a type don't change how the type looks internally, so the type of source_a is still Box<TraceBit>. You can keep getting the &'a TraceBit references recursively step by step:
trace_bit = trace_bit.source_a.as_ref().unwrap();
but there's no construct in Rust where taking a reference to the root of a tree suddenly changes the whole tree into a tree of references, so the type you are creating can't exist, and that's why you can't get type annotations right.
Maybe instead of passing references around, you should use a contained and cloneable name type.
use std::rc::Rc;
#[derive(Debug)]
pub enum TraceOperation {
AND,
OR,
XOR,
NOT,
}
#[derive(Debug)]
pub enum BitName<T> {
Name(Rc<T>),
Combination(Rc<(TraceOperation, BitName<T>, BitName<T>)>),
}
impl<T> Clone for BitName<T> {
fn clone(&self) -> Self {
match self {
&BitName::Name(ref x) => BitName::Name(Rc::clone(x)),
&BitName::Combination(ref x) => BitName::Combination(Rc::clone(x)),
}
}
}
impl<T> From<T> for BitName<T> {
fn from(x:T) -> Self {
BitName::Name(Rc::new(x))
}
}
impl<T> BitName<T> {
pub fn combine(op : TraceOperation, a : &Self, b :&Self) -> Self {
BitName::Combination(Rc::new((op, (*a).clone(), (*b).clone())))
}
}
fn main() {
let x : BitName<String> = BitName::from(String::from("x"));
let y : BitName<String> = BitName::from(String::from("y"));
let xandy = BitName::combine(TraceOperation::AND, &x, &y);
println!("{:?}", xandy);
}

Rust template argument parser seems to be broken

I am pretty sure a code like this worked before:
fn f<F: fn()>(f: F) {
}
However, now it gives the following error:
error: expected one of `(`, `,`, `=`, `>`, `?`, `for`, lifetime, or path, found `fn`
--> src/main.rs:96:13
|
96 | fn f<F: fn()>(f: F) {
| -^^ unexpected token
| |
| expected one of 8 possible tokens here
Note that this compiles fine:
fn f(f: fn()) {
}
You must use the function trait:
fn f<F: Fn()>(f: F) {
}
fn is a function pointer, not a trait.
Note that you can also write this:
fn f(f: fn()) {
}

Resources