mismatched types in Pallet - rust

The error is shown when i follow step to expose the contracts pallet api.
https://substrate.dev/docs/en/tutorials/add-a-pallet-to-your-runtime/#install-the-node-template
I followed the steps all the way and fixed another error that was associating the ContractExecResult::Success. Now i have trouble with these 2 errors.
I believe it has something to do with its syntax or maybe an updated library api that the tutorial has not updated to yet.
$ cargo check -p node-template-runtime
Compiling node-template-runtime v2.0.0-rc5 (C:\substrate-node-template2\runtime)
error: failed to run custom build command for `node-template-runtime v2.0.0-rc5 (C:\substrate-node-template2\runtime)`
Caused by:
process didn't exit successfully: `C:\substrate-node-template2\target\debug\build\node-template-runtime-8af1699a702fd7e8\build-script-build` (exit code: 1)
--- stdout
Executing build command: "rustup" "run" "nightly" "cargo" "rustc" "--target=wasm32-unknown-unknown" "--manifest-path=C:\\substrate-node-template2\\target\\debug\\wbuild\\node-template-runtime\\Cargo.toml" "--color=always" "--release"
--- stderr
Compiling wasm-build-runner-impl v1.0.0 (C:\substrate-node-template2\target\debug\wbuild-runner\node-template-runtime6610820868370414452)
Finished dev [unoptimized + debuginfo] target(s) in 0.75s
Running `C:\substrate-node-template2\target\debug\wbuild-runner\node-template-runtime6610820868370414452\target\x86_64-pc-windows-msvc\debug\wasm-build-runner-impl.exe`
Compiling node-template-runtime v2.0.0-rc5 (C:\substrate-node-template2\runtime)
error[E0308]: mismatched types
--> C:\substrate-node-template2\runtime\src\lib.rs:477:17
|
476 | match exec_result {
| ----------- this expression has type `(core::result::Result<pallet_contracts::ExecReturnValue, sp_runtime::DispatchError>, u64)`
477 | Ok(v) => ContractExecResult::Success{
| ^^^^^ expected tuple, found enum `core::result::Result`
|
= note: expected tuple `(core::result::Result<pallet_contracts::ExecReturnValue, sp_runtime::DispatchError>, u64)`
found enum `core::result::Result<_, _>`
error[E0308]: mismatched types
--> C:\substrate-node-template2\runtime\src\lib.rs:482:17
|
476 | match exec_result {
| ----------- this expression has type `(core::result::Result<pallet_contracts::ExecReturnValue, sp_runtime::DispatchError>, u64)`
...
482 | Err(_) => ContractExecResult::Error,
| ^^^^^^ expected tuple, found enum `core::result::Result`
|
= note: expected tuple `(core::result::Result<pallet_contracts::ExecReturnValue, sp_runtime::DispatchError>, u64)`
found enum `core::result::Result<_, _>`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0308`.
error: could not compile `node-template-runtime`.
To learn more, run the command again with --verbose.
error: process didn't exit successfully: `C:\substrate-node-template2\target\debug\wbuild-runner\node-template-runtime6610820868370414452\target\x86_64-pc-windows-msvc\debug\wasm-build-runner-impl.exe` (exit code: 1)
here is the code that is in runtime\src\lib.rs that the tutorial had me add that is causing the issue, and my modified code where 'flags' and 'gas_consumed' is added and 'status' was removed.
/*** Add This Block ***/
impl contracts_rpc_runtime_api::ContractsApi<Block, AccountId, Balance, BlockNumber>
for Runtime
{
fn call(
origin: AccountId,
dest: AccountId,
value: Balance,
gas_limit: u64,
input_data: Vec<u8>,
) -> ContractExecResult {
let exec_result =
Contracts::bare_call(origin, dest.into(), value, gas_limit, input_data);
match exec_result {
Ok(v) => ContractExecResult::Success{
flags: v.status,
data: v.data,
gas_consumed: v.gas_consumed,
},
Err(_) => ContractExecResult::Error,
}
}
fn get_storage(
address: AccountId,
key: [u8; 32],
) -> contracts_primitives::GetStorageResult {
Contracts::get_storage(address, key)
}
fn rent_projection(
address: AccountId,
) -> contracts_primitives::RentProjectionResult<BlockNumber> {
Contracts::rent_projection(address)
}
}
/*** End Added Block ***/

Based on the output, it looks like you are using version 2.0.0-rc5 of the node template. At the moment, the Contracts pallet tutorial is up-to-date as of v2.0.0-rc4. Can you clone the node template from that branch and use that as a starting point? git clone -b v2.0.0-rc4 --depth 1 https://github.com/substrate-developer-hub/substrate-node-template

Starting v2.0.0-rc5, the bare_call function in Contracts pallet returns ExecResult and Gas, which can be seen at line 633, whereas only ExecResult is returned on the previous version of the Contracts pallet.
In order to continue with the tutorial, I did some tweaks with the provided code snippet in the tutorial. Here's the version of my code.
fn call(
origin: AccountId,
dest: AccountId,
value: Balance,
gas_limit: u64,
input_data: Vec<u8>,
) -> ContractExecResult {
let exec_result =
Contracts::bare_call(origin, dest.into(), value, gas_limit, input_data);
match exec_result {
(Ok(v), gas) => ContractExecResult::Success {
flags: v.flags.bits(),
data: v.data,
gas_consumed: gas,
},
(Err(_), _) => ContractExecResult::Error,
}
}
Note: I'm fairly new with Rust so my code is probably not the most optimal solution.

Related

How to call a function from an impl in an ident

How do I call a function from an struct received on a macro?
My actual case is different but I reduced the issue to this piece of code:
macro_rules! macro_test {
($foo:ident) => {
{
println!("{}", <$foo>.to_string());
}
}
}
fn main() {
let ss = "sim";
macro_test!(ss);
}
It doesn't compile and I have found no clear answer on how to call <$received>.function().
The error:
Compiling playground v0.0.1 (/playground)
error: expected `::`, found `.`
--> src/main.rs:4:34
|
4 | println!("{}", <$foo>.to_string());
| ^ expected `::`
...
11 | macro_test!(ss);
| --------------- in this macro invocation
|
= note: this error originates in the macro `macro_test` (in Nightly builds, run with -Z macro-backtrace for more info)
The playgorund to test it does not compile. I have not found a way to call methods of an ident inside a macro.

function `print` is used but why it warn me `unused`?

Here is the function lies in huangjj27:env_logger/src/writer/wasm.rs
//! logging functions from wasm-bindgen.
//!
//! Here use the one-param logging functions, all messages should be transformed
//! to string before passing to the functions. Note that we only need this
//! module for `wasm32-unknown-unknown` target
#![cfg(all(target_arch = "wasm32", target_vendor = "unknown"))]
// use log::Level;
use wasm_bindgen::prelude::*;
use crate::fmt::glob::Target;
pub(in crate::fmt::writer) fn print(msg: &str, t: Target) {
// work around for unused variable
let _ = t;
log(&msg);
}
As is shown above, the wasm module will only compile with wasm32-unknown-unknown target. And the print function is used in huangjj27:env_loggersrc\fmt\writer\termcolor\shim_impl.rs:
// huangjj27:env_loggersrc\fmt\writer\termcolor\shim_impl.rs: 32-48
pub(in crate::fmt::writer) fn print(&self, buf: &Buffer) -> io::Result<()> {
// This impl uses the `eprint` and `print` macros
// instead of using the streams directly.
// This is so their output can be captured by `cargo test`
let log = String::from_utf8_lossy(&buf.0);
#[cfg(all(target_arch = "wasm32", target_vendor = "unknown"))]
wasm::print(&log, self.target);
#[cfg(not(all(target_arch = "wasm32", target_vendor = "unknown")))]
match self.target {
Target::Stderr => eprint!("{}", log),
Target::Stdout => print!("{}", log),
}
Ok(())
}
then I test it with the node:
wasm-pack test --node -- --no-default-features --test node
then I get this confusing denied unused issue:
[INFO]: Checking for the Wasm target...
Compiling env_logger v0.8.2 (C:\Users\huangjj27\Documents\codes\env_logger)
error: function is never used: `print`
--> src\fmt\writer\wasm.rs:13:31
|
13 | pub(in crate::fmt::writer) fn print(msg: &str, t: Target) {
| ^^^^^
|
note: lint level defined here
--> src\lib.rs:280:54
|
280 | #![deny(missing_debug_implementations, missing_docs, warnings)]
| ^^^^^^^^
= note: `#[deny(dead_code)]` implied by `#[deny(warnings)]`
error: function is never used: `print`
--> src\fmt\writer\wasm.rs:13:31
|
13 | pub(in crate::fmt::writer) fn print(msg: &str, t: Target) {
| ^^^^^
|
note: lint level defined here
--> src\lib.rs:280:54
|
280 | #![deny(missing_debug_implementations, missing_docs, warnings)]
| ^^^^^^^^
= note: `#[deny(dead_code)]` implied by `#[deny(warnings)]`
error: aborting due to previous error
error: could not compile `env_logger`.
warning: build failed, waiting for other jobs to finish...
error: aborting due to previous error
error: could not compile `env_logger`.
To learn more, run the command again with --verbose.
Error: Compilation of your program failed
Caused by: failed to execute `cargo build`: exited with exit code: 101
full command: "cargo" "build" "--tests" "--target" "wasm32-unknown-unknown"
My questions are:
Why does the warning come out, while I indeed use the function wasm::print somewhere?
How could I deal with this problem? Working around or fixing it is ok (but I still need to keep the lint config enabled).
If you only use a function in other unused functions, then it will still give you the warning. If you want to disable the warning on that one function, you can do that by putting #[allow(dead_code)] on the line before the function header.

Scoping Issues when referring value from Struct Instance in Rust

So I have this program and everything is working just as I want it to. The only problem is "student1.name" at the bottom. I wanted to replace "self.name" with "student1.name", but i'm having Scoping Issues. "self.name" was working perfectly fine. Here is my code:
fn main() {
let student1 = IOT_student {
name: String::from("Husayn Abbas"),
age: 13,
education: String::from("O Levels"),
};
let instructor1 = IOT_instructor {
name: String::from("Imran Ali"),
age: 25,
};
println!("{}", student1.ask_Questions());
println!("{}", instructor1.ask_Questions());
}
trait Questions {
fn ask_Questions(&self) -> String;
}
struct IOT_student {
name: String,
age: i8,
education: String,
}
struct IOT_instructor {
name: String,
age: i8,
}
impl Questions for IOT_student {
fn ask_Questions(&self) -> String {
return format!("Zoom session will be LIVE, Zoom recording will not be available. Quarter 2 studio recorded videos are available on Portal.");
}
}
impl Questions for IOT_instructor {
fn ask_Questions(&self) -> String {
return format!("{} In case of any issue email to education#piaic.org", student1::name);
}
}
And here is my output:
Compiling IOT_Assignment_2 v0.1.0 (/home/memelord/Documents/PIAIC Quarter 2 IOT Assignments/IOT_Assignment_2)
error[E0425]: cannot find value `student1` in this scope
--> src/main.rs:40:80
|
40 | return format!("{} In case of any issue email to education#piaic.org", student1.name);
| ^^^^^^^^ not found in this scope
warning: type `IOT_student` should have an upper camel case name
--> src/main.rs:21:8
|
21 | struct IOT_student {
| ^^^^^^^^^^^ help: convert the identifier to upper camel case: `IotStudent`
|
= note: `#[warn(non_camel_case_types)]` on by default
warning: type `IOT_instructor` should have an upper camel case name
--> src/main.rs:27:8
|
27 | struct IOT_instructor {
| ^^^^^^^^^^^^^^ help: convert the identifier to upper camel case: `IotInstructor`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0425`.
error: could not compile `IOT_Assignment_2`.
To learn more, run the command again with --verbose.
Have any ideas why this is happening (i'm a Rust beginner so please try to make your explanation simple)?
The trait implementation methods are in completely different universe than the function calling them.
If you want to be able to use the name of a student in the call, you have to add an argument to the function. Example:
impl Questions for IOT_instructor {
fn ask_Questions(&self, student: &IOT_student) -> String {
return format!("{} In case of any issue email to education#piaic.org", student.name);
}
}
Now call like:
println!("{}", instructor1.ask_Questions(&student1));

Rust actix_web::main "expected `std::result::Result<(), std::io::Error>` because of return type" but suggested type doesen't work

I'm new to rust and started experimenting with actix_web and sqlx. the goal is to create a simple, open-source Blog engine, but after I implemented the CLI argument parser and basic SQL connection pool, the code doesn't compile anymore. I'm getting the following error:
error[E0308]: mismatched types
--> src/main.rs:17:1
|
17 | #[actix_web::main]
| ^^^^^^^^^^^^^^^^^^
| |
| expected enum `std::result::Result`, found `()`
| help: try using a variant of the expected enum: `Ok(#[actix_web::main])`
18 | async fn main() -> std::io::Result<()> {
| ------------------- expected `std::result::Result<(), std::io::Error>` because of return type
|
= note: expected enum `std::result::Result<(), std::io::Error>`
found unit type `()`
= note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.
error: could not compile `rusty_read`.
To learn more, run the command again with --verbose.
the error suggests to use std::result::Result<(), std::io::Error> as return type, but I get the same error when replacing the current return type with it:
error[E0308]: mismatched types
--> src/main.rs:17:1
|
17 | #[actix_web::main]
| ^^^^^^^^^^^^^^^^^^
| |
| expected enum `std::result::Result`, found `()`
| help: try using a variant of the expected enum: `Ok(#[actix_web::main])`
18 | async fn main() -> std::result::Result<(), std::io::Error> {
| --------------------------------------- expected `std::result::Result<(), std::io::Error>` because of return type
|
= note: expected enum `std::result::Result<(), std::io::Error>`
found unit type `()`
= note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.
error: could not compile `rusty_read`.
To learn more, run the command again with --verbose.
so far I couldn't find anybody with the same issue and could not find any reason for it.
My Code:
/Cargo.toml
[package]
name = "rusty_read"
version = "0.1.0"
authors = ["LeMoonStar <webmaster#unitcore.de>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
actix-web = "3.0.0-beta.1"
rust-ini = "0.15"
sqlx = { version = "0.4.0-beta.1", features = [ "all-databases", "any", "tls" ] }
clap = "2"
/src/main.rs
use actix_web::{get, web, App, HttpServer, Responder};
use ini::Ini;
use sqlx::pool::Pool;
use sqlx::any;
#[get("/")]
async fn index() -> impl Responder {
format!("index")
}
#[get("/article/{id}")]
async fn article(info: web::Path<u32>) -> impl Responder {
format!("article nr.{}", info)
}
#[actix_web::main]
async fn main() -> std::result::Result<(), std::io::Error> {
let conf = Ini::load_from_file("conf.ini").unwrap_or(Ini::load_from_str("[Server]
bindAddress = \"127.0.0.1:8080\"
[Database]
url = \"mysql://user:password#localhost/blog\"
").unwrap());
let matches = clap::App::new("Rusty Read")
.version("0.1 INDEV")
.author("LeMoonStar <webmaster#unitcore.de>")
.about("a blog engine written in rust")
.subcommand(clap::SubCommand::with_name("config")
.about("sets various configurations for the blog")
.arg(clap::Arg::with_name("address")
.short("a")
.long("adress")
.help("sets the address the http server binds on (eg. 127.0.0.1:8080)")
.takes_value(true))
.arg(clap::Arg::with_name("database")
.short("d")
.long("database")
.help("sets the url to the database (eg. mysql://user:password#localhost/blog)")
.takes_value(true)))
.subcommand(clap::SubCommand::with_name("init_database")
.about("Initializes the database which is set in the conf.ini file (or with the config command)"))
.get_matches();
if let Some(matches) = matches.subcommand_matches("config") {
if matches.is_present("address") {
conf.section(Some("Server")).unwrap()
.insert("bindAddress", "127.0.0.1:8080");
}
if matches.is_present("database") {
conf.section(Some("Database")).unwrap()
.insert("url", "mysql://user:password#localhost/blog");
}
} else if let Some(matches) = matches.subcommand_matches("init_database") {
} else {
let mut section = conf.section(Some("Server")).expect("conf.ini requires a [Server] section.");
let bind_address = section.get("bindAddress").expect("conf.ini's [Server] section requires a bindAdress.");
section = conf.section(Some("Database")).expect("conf.ini requires a [Database] section.");
let db_url = section.get("url").expect("conf.ini's [Database] section requires a url.");
let pool = Pool::<any::Any>::connect(db_url).await.expect("database connection pool could not be created.");
HttpServer::new(move || {
App::new()
.service(article)
.service(index)
.data(pool.clone())
})
.bind(bind_address).expect("could not bind http server")
.run()
.await;
}
}
I hope someone can help me with this problem since I can't continue to work on the project, while this problem is present.
the Ok(()) is actually working.. I've tried to copy-pasting all of your code before, and do cargo check i got the same problem as you write there on the comment. then I tried to clean the code inside the main function and then copy-pasting your code again piece by piece. after adding Ok(()) as the return of the main. and the error changed before I even finished the copy-pasting. see
the screenshot of different error on my local.
then I tried to fix it by adding clone() like below:
..
conf.section(Some("Server")).unwrap().clone()
..
conf.section(Some("Database")).unwrap().clone()
..
and then I cargo run it. and the server works fine! see the screenshot here.

Rust lifetimes, data flows into other references

I wrote the following code that filters a stream of data which worked fine until I changed from parsing simple numbers to also have types that are bound to lifetimes like &str and &[u8].
use wirefilter::{ExecutionContext, Filter, Scheme};
lazy_static::lazy_static! {
static ref SCHEME: Scheme = Scheme! {
port: Int,
name: Bytes,
};
}
#[derive(Debug)]
struct MyStruct {
port: i32,
name: String,
}
impl MyStruct {
fn scheme() -> &'static Scheme {
&SCHEME
}
fn filter_matches<'s>(&self, filter: &Filter<'s>) -> bool {
let mut ctx = ExecutionContext::new(Self::scheme());
ctx.set_field_value("port", self.port).unwrap();
ctx.set_field_value("name", self.name.as_str()).unwrap();
filter.execute(&ctx).unwrap()
}
}
fn main() -> Result<(), failure::Error> {
let data = expensive_data_iterator();
let scheme = MyStruct::scheme();
let filter = scheme
.parse("port in {2 5} && name matches \"http.*\"")?
.compile();
for my_struct in data
.filter(|my_struct| my_struct.filter_matches(&filter))
.take(2)
{
println!("{:?}", my_struct);
}
Ok(())
}
fn expensive_data_iterator() -> impl Iterator<Item = MyStruct> {
(0..).map(|port| MyStruct {
port,
name: format!("http {}", port % 2),
})
}
If I try to compile it the compiler will fail with this:
error[E0623]: lifetime mismatch
--> src/main.rs:26:16
|
21 | fn filter_matches<'s>(&self, filter: &Filter<'s>) -> bool {
| ----- ----------
| |
| these two types are declared with different lifetimes...
...
26 | filter.execute(&ctx).unwrap()
| ^^^^^^^ ...but data from `self` flows into `filter` here
error: aborting due to previous error
error: Could not compile `wirefilter_playground`.
To learn more, run the command again with --verbose.
Process finished with exit code 101
my first thought was that self and filter should have the same lifetime in fn filter_matches<'s>(&self, filter: &Filter<'s>) -> bool but if I change the signature to fn filter_matches<'s>(&'s self, filter: &Filter<'s>) -> bool I will start getting this error:
error: borrowed data cannot be stored outside of its closure
--> src/main.rs:38:29
|
33 | let filter = scheme
| ------ ...so that variable is valid at time of its declaration
...
38 | .filter(|my_struct| my_struct.filter_matches(&filter))
| ----------- ^^^^^^^^^ -------------- cannot infer an appropriate lifetime...
| | |
| | cannot be stored outside of its closure
| borrowed data cannot outlive this closure
error: aborting due to previous error
error: Could not compile `wirefilter_playground`.
To learn more, run the command again with --verbose.
Process finished with exit code 101
I am failing to understand the reason, Filter<'s> is bound to SCHEME which is lazily generated and is bound to 'static which makes sense not allowing filter.execute to take reference to &self.name.as_str() because it would be outlived but, isn't filter.execute(&ctx) which the signature is pub fn execute(&self, ctx: &ExecutionContext<'s>) -> Result<bool, SchemeMismatchError> supposed to drop the references as soon as it finishes as the result of it has not other lifetimes?
In order to try and compile the code above, you can use this Cargo.toml:
[package]
name = "wirefilter_playground"
version = "0.1.0"
edition = "2018"
[dependencies]
wirefilter-engine = "0.6.1"
failure = "0.1.5"
lazy_static = "1.3.0"
PS: That could be solved by compiling the as inside filter_matches method but that would be sort of bad because the user would only get the parse error when trying to filter and it could potentially be slower.
I see 2 ways to solve this problem:
1) extend lifetime of self.name. This can be achieved by collecting expensive_data_iterator into, say, Vec.
--- let data = expensive_data_iterator();
+++ let data: Vec<_> = expensive_data_iterator().collect();
2) reduce lifetime of filter.
--- let filter = scheme.parse("...")?.compile();
+++ let filter = scheme.parse("...")?;
--- .filter(|my_struct| my_struct.filter_matches(&filter))
+++ .filter(|my_struct| my_struct.filter_matches(&filter.clone().compile()))
I omitted some other minor changes. And yes, filter_matches<'s>(&'s self, ...) is mandatory in either case.
PS yes, 2nd option works because my_struct outlives filter. Well, if both approaches are somewhat bad, then you can combine them! Process data by chunks, collecting each one into vector.
const N: usize = 10; // or any other size
loop {
let cur_chunk: Vec<_> = data.by_ref().take(N).collect();
if cur_chunk.is_empty() {
break;
}
let cur_filter = filter.clone().compile();
// etc
}
it uses only O(N) memory and compiles filter N times less

Resources