I am having some confusion with generics and bounds and would appreciate some clarity on this.
I have a struct that requires a generic paramter.
pub struct DataState<P : JsonRpcClient> {
pub path: Sudo<SignerMiddleware<Provider<Provider<P>>, Bastion<SigningKey>>>,
pub wrapper: Wrapper<SignerMiddleware<Provider<Provider<P>>, Bastion<SigningKey>>>,
// pub rpc_url: String,
// pub key: String,
pub provder: Arc<SignerMiddleware<Provider<Http>, Bastion<SigningKey>>>,
}
#[post("/process")]
async fn process<P : JsonRpcClient>(field: web::Json<Region>, data: web::Data<DataState<P>>) -> impl Responder
// where P: JsonRpcClient
{
However , I get this error
|
126 | async fn process<P : JsonRpcClient>(field: web::Json<Region>, data: web::Data<DataState<P>>) -> impl Responder
| ^^^^ cannot infer type of the type parameter `P` declared on the function `process`
Related
I have the following code (constrained example). There is a serial protocol, modelled with Command and Responce enums using enum_dispatch crate - every variant in enum is represented with a struct. Transport struct taskes care of serialization, execution and deserialization of Commands, returning TransportResults back with generic Responce enum(generic impl) or specific struct(templated impl). The generic implementation works just fine, but the templated one fails to compile.
use enum_dispatch::enum_dispatch;
use thiserror::Error;
trait Value{/**/}
trait CommandResponce {type Responce}
#[enum_dipatch(Value)]
enum Command{
Cmd1(Cmd1)
// ...
}
struct Cmd1{}
impl Value for Cmd1{ /**/ }
#[enum_dipatch(Value)]
enum Responce{
Resp1(Resp1)
// ...
}
struct Resp1{}
impl Value for Resp1{/**/}
impl CommandResponce for Cmd1{ type Responce=Resp1 }
#[derive(Error, Debug)]
pub enum ProtocolError{/**/}
type ProtocolResult<T> = Result<T, ProtocolError>;
struct Transport {/**/}
impl Transport {
// generic
pub fn command_generic_with_addr(
&mut self, addr: &mut u8, c: Command
) -> ProtocolResult<Responce>{ /**/ }
// templated
pub fn command_with_addr<T: SerializeCommand + CommandResponce>(
&mut self, addr: &mut u8, c: T) -> ProtocolResult<T::Responce>
where
Command: From<T>, Responce: TryInto<T::Responce, Error=&'static str>,
Responce: TryInto<T::Responce, Error= CommandErrors> {
let resp: Responce = self.command_generic_with_addr(addr, Command::from(c))?;
let ret: T::Responce = resp.try_into()?;
Ok(ret)
}
}
fn main() -> eyre::Result<()>{
let t = Transport::new();
let addr : u8 = 0xFF;
t.command_with_addr(&mut addr, Cmd1{/**/})
}
When I try to compile code, identical to the one above, I get the following error:
error[E0284]: type annotations needed: cannot satisfy `<Responce as TryInto<<T as CommandResponce>::Responce>>::Error == _`
-->
|
85 | let ret: T::Responce = match resp.try_into() {
| ^^^^^^^^ cannot satisfy `<Responce as TryInto<<T as CommandResponce>::Responce>>::Error == _`
I can't understand, what is the error here - I thought I've stated all the neccessary type annotations in the Transport::command_with_addr member function.
Note, enum_dispatch uses the following code to generate try_into conversion, used in the code above:
impl #impl_generics core::convert::TryInto<#variant_type> for #enumname #ty_generics #where_clause {
type Error = &'static str;
fn try_into(self) -> ::core::result::Result<#variant_type, <Self as core::convert::TryInto<#variant_type>>::Error> {
//..
}
}
I am writing a struct that functions as a thin wrapper over an existing struct. The existing struct isn't fixed, so I've written it as a type parameter (see struct B below). I would like B to preserve convertibility (i.e. From/Into) based on the internal wrapped type, i.e. if A1 is convertible to A then B<A1> should be convertible to B<A> as well.
I tried the following code:
pub struct A {}
pub struct A1 {}
impl From<A1> for A {
fn from(a1: A1) -> Self {
Self {}
}
}
pub struct B<T> {
t: T,
other_stuff: String,
}
impl<T, U: Into<T>> From<B<U>> for B<T> {
fn from(b: B<U>) -> Self {
Self {
t: b.t.into(),
other_stuff: b.other_stuff,
}
}
}
pub fn main() {
// I would like this to work:
let ba1: B<A1> = B{ t: A1{}, other_stuff: "abc".to_owned() };
let ba: B<A> = ba1.into();
}
It produces a compilation error:
error[E0119]: conflicting implementations of trait `std::convert::From<B<_>>` for type `B<_>`:
--> src/main.rs:13:1
|
13 | impl<T, U: Into<T>> From<B<U>> for B<T> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: conflicting implementation in crate `core`:
- impl<T> std::convert::From<T> for T;
I think I understand why the error arises (because converting B<A> to B<A> is already defined), but how may I rewrite my code to avoid the error?
I am trying to decode APER messages and have issue creating nested structs with traits. I am using the asn1 library, but I have provided an example to illustrate the issue.
I need a model that can take a value that can be any struct (more or less).
Using boxes does not work since the serial trait is Sized. I cannot seem to get generics to work either since the decode function does not return the type.
How can I get past this?
use std::fmt::Error;
pub trait serial: Sized {
fn decode(&self) -> Result<Self, Error>;
}
pub struct Middle {
pub bottomCode: i32,
pub value: Box<dyn Bottom>,
}
impl serial for Middle {
fn decode(&self) -> Result<Self, Error> {
let code = 1;
if code == 1 {
Ok(Middle {
bottomCode: code,
value: Box::new(BottomA { a: 1 }),
})
} else {
Ok(Middle {
bottomCode: code,
value: Box::new(BottomB { b: 1 }),
})
}
}
}
pub trait Bottom: serial {}
pub struct BottomA {
pub a: i32,
}
impl Bottom for BottomA {}
pub struct BottomB {
pub b: i32,
}
impl Bottom for BottomB {}
error[E0038]: the trait `Bottom` cannot be made into an object
--> src/lib.rs:9:5
|
9 | pub value: Box<dyn Bottom>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bottom` cannot be made into an object
|
= note: the trait cannot require that `Self : Sized`
error[E0277]: the trait bound `BottomA: serial` is not satisfied
--> src/lib.rs:32:6
|
32 | impl Bottom for BottomA {}
| ^^^^^^ the trait `serial` is not implemented for `BottomA`
error[E0277]: the trait bound `BottomB: serial` is not satisfied
--> src/lib.rs:37:6
|
37 | impl Bottom for BottomB {}
| ^^^^^^ the trait `serial` is not implemented for `BottomB`
The serial trait represents the APerElement trait I'm trying to use from the ASN1 library, thus the return type and signature.
I want to be able to call Middle.decode() which will result in all children being decoded alongside it, and any children of those etc. For that reason, it made sense to implement serial for it as well.
How would someone achieve such behavior? Is it possible?
I'd like to implement the Responder trait for my Hero structure, but the following method signature (respond_to):
use rocket::{http::Status, response::Responder, Request, Response};
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
pub struct Hero {
pub id: Option<i32>,
pub name: String,
pub identity: String,
pub hometown: String,
pub age: i32,
}
impl Hero {
pub fn new(
num: Option<i32>,
name: String,
identity: String,
hometown: String,
age: i32,
) -> Hero {
Hero {
id: num,
name,
identity,
hometown,
age,
}
}
}
impl<'r> Responder<'r> for Hero {
fn respond_to(self, _request: &Request) -> Result<Response, Status> {
unimplemented!()
}
}
Throws a compilation error:
error[E0106]: missing lifetime specifier
--> src/main.rs:32:55
|
32 | fn respond_to(self, _request: &Request) -> Result<Response, Status> {
| ^^^^^^^^ expected lifetime parameter
|
= help: this function's return type contains a borrowed value, but the signature does not say which one of `_request`'s 2 lifetimes it is borrowed from
Dependencies:
[dependencies]
rocket = "0.4.2"
serde = {version = "1.0.99", features=["derive"]}
The documentation doesn't provide an example of how to provide lifetimes when a type is returned. How to specify lifetime when a type is returned?
The Responder trait is defined as:
pub trait Responder<'r> {
fn respond_to(self, request: &Request) -> response::Result<'r>;
}
The response::Result<'r> is defined as:
pub type Result<'r> = ::std::result::Result<self::Response<'r>, ::http::Status>;
Your method signature is:
fn respond_to(self, request: &Request) -> Result<Response, Status>;
As you can see, you just forgot to specify lifetime for the Response. The correct method signature is:
impl<'r> Responder<'r> for Hero {
fn respond_to(self, request: &Request) -> Result<Response<'r>, Status> {
unimplemented!()
}
}
A Mech carries a driver, which is a Named entity. At run-time, an omitted Mech constructor consults external source for the specific type of driver to use.
trait Named {
fn name(self) -> String;
}
struct Person {
first_name: String,
last_name: String
}
impl Named for Person {
fn name(self) -> String {
format!("{} {}", self.first_name, self.last_name)
}
}
pub struct Mech<'a> {
driver: Box<Named + 'a>,
}
impl<'a> Mech<'a> {
pub fn driver_name(self) -> String {
self.driver.name()
}
}
Method driver_name returns ownership to a String, for it to be further used in chained calls (in actual code it's a Command). It fails compilation with:
error[E0161]: cannot move a value of type Named + 'a: the size of Named + 'a cannot be statically determined
--> src/lib.rs:22:9
|
22 | self.driver.name()
| ^^^^^^^^^^^
Making the trait Sized fails the object safety:
trait Named: Sized {
fn name(self) -> String;
}
↓
error[E0038]: the trait `Named` cannot be made into an object
--> src/lib.rs:17:5
|
17 | driver: Box<Named + 'a>,
| ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Named` cannot be made into an object
|
= note: the trait cannot require that `Self : Sized`
Is there a way to make this pattern happen?
Is there anything fundamental that I seem to be missing?
In case this is impossible to achieve, what's a good way to work around it?
As the compiler hinted, the trait cannot be statically determined because you are dealing with dynamic dispatch. Ownership is still possible in this scenario using self: Box<Self>.
trait Named {
fn name(self: Box<Self>) -> String;
}
struct Person {
first_name: String,
last_name: String,
}
impl Named for Person {
fn name(self: Box<Self>) -> String {
format!("{} {}", self.first_name, self.last_name)
}
}
pub struct Mech<'a> {
driver: Box<Named + 'a>,
}
impl<'a> Mech<'a> {
pub fn driver_name(self) -> String {
self.driver.name()
}
}
fn main() {}