can't use implemented trait in other file rust - rust

so i have got two files main.rs and utils.rs
I implemented StringUtils method on utils.rs but when I try to use the method in main.rs
it gives me this error
error[E0599]: no method named `slice` found for reference `&str` in the current scope
--> src\main.rs:89:50
|
89 | let text: String = self.inner.clone().as_str().slice(self.start, self.current);
| ^^^^^ method not found in `&str`
|
= help: items from traits can only be used if the trait is implemented and in scope
note: `StringUtils` defines an item `slice`, perhaps you need to implement it
--> src\util.rs:25:1
|
25 | trait StringUtils {
| ^^^^^^^^^^^^^^^^^
// main.rs
mod utils;
use utils::*;
...
fn add_token0(&mut self, token_type: TokenType) {
let text: String = self.inner.clone().as_str().slice(self.start, self.current);
// error: no method named `slice` found for reference `&str` in the current scope
}
...
but I implemented it already on utils.rs
// utils.rs
...
trait StringUtils {
...
fn slice(&self, range: impl RangeBounds<usize>) -> &str;
...
}
impl StringUtils for str {
...
fn slice(&self, range: impl RangeBounds<usize>) -> &str {
...
}
...
}
...
why doesn't my implementation work, and is there any way to solve it or I can only implement StringUtils on main.rs?

A substantively equivalent example appears in the section Paths for Referring to an Item in the Module Tree in The Rust Programming Language (which if you haven't read, I would suggest).
The short version is that any item (e.g., trait, function definition) within a module that you would like to be visible to other modules should have some variant of a pub visibility modifier. In your instant example, this manifests as needing to make the StringUtils trait pub (or some other variant exposing it to the containing module).
In fact, if you attempt to import StringUtils directly, via use utils::StringUtils instead of a glob import, you'd get the following error message:
error[E0603]: trait `StringUtils` is private
--> src/lib.rs:7:12
|
7 | use utils::StringUtils;
| ^^^^^^^^^^^ private trait
|
note: the trait `StringUtils` is defined here
--> src/lib.rs:19:5
|
19 | trait StringUtils {
| ^^^^^^^^^^^^^^^^^
Which would link to this explanation of one way to fix it. So if we do pub trait StringUtils { ... } instead, there are no issues relating to using the trait.
You would still have the issue #trentcl mentions concerning the incorrect number of parameters to slice, and I presume self.start..self.current (or the inclusive version) should be the range passed instead.
Finally, there is an error relating to your type annotation of text as StringUtils::slice would return &str, not String. Depending on what you want, you should either change the trait and its implementations or take a look at ways to go between &str and String and the differences between them.
(playground).
You may want to have a more restrictive visibility modifier, like pub(crate) or pub(super) which restrict visibility to the containing crate or the containing module, respectively.
A more exhaustive explanation of this can be found in the relevant section in The Rust Reference.

Related

Can I create a compile error to check if a trait has another trait as a supertrait?

I'm creating a macro that parses a user-generated trait and creates helper functions for it. I have type restrictions on some of the arguments used, so I've been following the example in the quote crate to generate some code that'll throw a compilation error if a trait isn't implemented. It's not perfect but it gets the job done:
struct _AssertSync where #ty: Sync;
I'd also like to be able to check if the trait has Hash as a supertrait. If I follow the same pattern, I get an error:
struct _AssertHash where dyn #tr: Hash;
A complete example:
use std::hash::Hash;
trait BadBoi {}
trait GoodBoi: Hash {}
struct _AssertHash
where
dyn GoodBoi: Hash;
error[E0038]: the trait `GoodBoi` cannot be made into an object
--> src/lib.rs:6:39
|
4 | trait GoodBoi: Hash {}
| ------- this trait cannot be made into an object...
5 |
6 | struct _AssertHash where dyn GoodBoi: Hash;
| ^^^^ the trait `GoodBoi` cannot be made into an object
|
= help: consider moving `hash` to another trait
Is there any way for me to get around this?
You can check a supertrait-relationship by using two functions, for example:
fn _assert_hash_supertrait<T: $tr>() {
fn requires_hash<T: Hash>() {}
let _ = requires_hash::<T>;
}
This only compiles if the bound T: $tr implies T: Hash. And the only way that's the case if Hash is a super-trait of $tr. Also see this helpful Q&A.
Full example (Playground):
trait BadBoi {}
trait GoodBoi: Hash {}
macro_rules! foo {
($tr:ident) => {
fn _assert_hash_supertrait<T: $tr>() {
fn requires_hash<T: Hash>() {}
let _ = requires_hash::<T>;
}
}
}
//foo!(GoodBoi);
foo!(BadBoi);
Of course in this solution, calling foo! twice errors because assert_hash_supertrait is defined twice, but solving that is not part of this question.

Trait std::convert::From<String> not implemented for hyper::body::Body

lazy_static::lazy_static! {
static ref file_data: String = fs::read_to_string("static/login.html").expect("unable to read from static/login.html");
}
#[tokio::main]
async fn main() {
// code omitted
let login = warp::path("login").map(move || warp::reply::html(file_data));
// code omitted
}
Compile error:
error[E0277]: the trait bound `hyper::body::body::Body: std::convert::From<file_data>` is not satisfied
--> src/main.rs:45:49
|
45 | let login = warp::path("login").map(move || warp::reply::html(file_data));
| ^^^^^^^^^^^^^^^^^ the trait `std::convert::From<file_data>` is not implemented for `hyper::body::body::Body`
|
::: /home/ichi/.cargo/registry/src/github.com-1ecc6299db9ec823/warp-0.2.3/src/reply.rs:170:11
|
170 | Body: From<T>,
| ------- required by this bound in `warp::reply::html`
|
= help: the following implementations were found:
<hyper::body::body::Body as std::convert::From<&'static [u8]>>
<hyper::body::body::Body as std::convert::From<&'static str>>
<hyper::body::body::Body as std::convert::From<bytes::bytes::Bytes>>
<hyper::body::body::Body as std::convert::From<std::borrow::Cow<'static, [u8]>>>
and 4 others
I am trying to pass a String to a closure. According to the documentation, From<String> is implemented for hyper::body::Body and file_data is of type String. So why am I getting this error?
From lazy_static
For a given static ref NAME: TYPE = EXPR;, the macro generates a unique type that implements Deref<TYPE> and stores it in a static with name NAME. (Attributes end up attaching to this type.)
That is, the type of the variable is not TYPE!
This is why you see the error
the trait `std::convert::From<file_data>` is not implemented for `hyper::body::body::Body`
^^^^^^^^^
You'd probably have better luck explicitly de-referencing or cloning the global variable: warp::reply::html(&*file_data) or warp::reply::html(file_data.clone()).
The issue here is that lazy_static creates a wrapper type that references your data, and hyper doesn't know how to handle it. You could use file_data.clone() to clone the referenced data and construct a body from that, but in this case there's actually a simpler method. Since your string has a fixed value and Body implements From<&'static str>, you don't actually need a heap-allocated String or lazy_static at all: You can use the following code which just uses a constant string slice that can be used directly.
const FILE_DATA: &str = "test";
#[tokio::main]
async fn main() {
// code omitted
let login = warp::path("login").map(move || warp::reply::html(FILE_DATA));
// code omitted
}

parity_codec::codec::Input is not implemented for Vec<u8> when decoding an extrinsic into a struct

How would I decode the standard Substrate extrinsic format into a Transaction object in a way where it would be possible to get the Sender, preferably as a string?
I have started with this code with a hardcoded sample extrinsic data for testing in the extrinsic_hex variable:
use hex::decode;
use hex_literal::hex;
use parity_codec::{Decode, Encode, Input};
use primitives::generic::UncheckedMortalExtrinsic;
use std::fmt;
use std::fmt::Debug;
fn main() {
let extrinsic_hex: &'static str = "81ffd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d3c6b8941e2976034e67bdd1a999c3eff4403c8ceaf717f18d9760ab18573ab2ce870e9b751c2f14dd9883e54746e1eb6639978ceab49968c25176cc0d2507205040003000ca10f";
let result = hex::decode(extrinsic_hex);
match result {
Ok(v1) => {
let extr_option = UncheckedMortalExtrinsic::decode(&mut v1);
()
}
_ => {
println!("Error decoding");
()
}
}
}
The error I get is:
error: duplicate lang item in crate `sr_io`: `panic_impl`.
|
= note: first defined in crate `std`.
error: duplicate lang item in crate `sr_io`: `oom`.
|
= note: first defined in crate `std`.
error[E0277]: the trait bound `std::vec::Vec<u8>: parity_codec::codec::Input` is not satisfied
--> core/decaddr/src/main.rs:13:20
|
13 | let extr_option=UncheckedMortalExtrinsic::decode(&mut v1);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `parity_codec::codec::Input` is not implemented for `std::vec::Vec<u8>`
|
= note: required by `parity_codec::codec::Decode::decode`
Let's pretend that the error error: duplicate lang item in cratesr_io:panic_impl. doesn't exist for now.
If I am understanding correctly, it doesn't work because Vec doesn't implement the parity_codec::Input trait, am I right? If so, how would one add this trait to Vec? Or better said, what are the functions from the Substrate framework I am missing so the Input trait is automatically provided?
If so, how would one add this trait to Vec ?
In your code, you can't. For coherence reasons, Rust says that an implementation of a trait X for a type Y must exist in the crate for X or the crate for Y.
Or better said, what are the functions from Susbtrate framework I am missing so the Input trait is automatically provided?
If you look at the "Implementors" part of the Input trait documentation - you can see that every type that implements std::io::Read will implement Input.
As the comments say, the implementation that is useful for you is the one on &[u8], which exists because it implements std::io::Read.

How to specify that all implementers of a trait must also implement Serialize?

I am curious to see how much boilerplate one can save through built-in reflection.
A little background
My idea behind structured logging is to use various small tailored types to separate content from representation. Instead of unstructured logger.info("Found a bar with {} foos", bar.foo) one uses something like logger.info(FoundBar{ _bar: bar })
My Rust-ish approach
define a Log trait
provide a default implementation that calls the Serde machinery to serialize the type (to JSON in this example)
define loggable types easily by letting them "inherit" the default implementation
profit
Define the trait, providing a default impl:
trait Log {
fn to_log(&self) -> String {
serde_json::to_string(&self).unwrap()
}
}
(RLS is already drawing angry red squiggles, but bear with me)
Define a simple type to be logged:
#[derive(Serialize)]
struct Message {
msg: String,
}
and let it use the default implementation:
impl Log for Message {}
and finally the polymorphic logging function defined in terms of the trait:
fn log(log: &Log) {
println!("serialized = {}", log.to_log());
}
The compiler complains:
error[E0277]: the trait bound `Self: _IMPL_DESERIALIZE_FOR_Message::_serde::Serialize` is not satisfied
--> src\main.rs:8:9
|
8 | serde_json::to_string(&self).unwrap()
| ^^^^^^^^^^^^^^^^^^^^^ the trait `_IMPL_DESERIALIZE_FOR_Message::_serde::Serialize` is not implemented for `Self`
|
= help: consider adding a `where Self: _IMPL_DESERIALIZE_FOR_Message::_serde::Serialize` bound
= note: required because of the requirements on the impl of `_IMPL_DESERIALIZE_FOR_Message::_serde::Serialize` for `&Self`
= note: required by `serde_json::ser::to_string`
Adding the where Self suggestion to my trait function only produces different errors (error[E0433]: failed to resolve. Use of undeclared type or module _IMPL_DESERIALIZE_FOR_Message), but apart from that it seems like a Bad Idea(TM) to have this implementation detail of Serde leak into my code.
How do I portably constrain my trait (using where?) to only apply to types that have the correct derive? Even better, can I "inject" the derive functionality into types using the trait?
If you create a MCVE of your problem on the playground, you get a more accurate error:
error[E0277]: the trait bound `Self: serde::Serialize` is not satisfied
--> src/lib.rs:6:9
|
6 | serde_json::to_string(&self).unwrap()
| ^^^^^^^^^^^^^^^^^^^^^ the trait `serde::Serialize` is not implemented for `Self`
|
= help: consider adding a `where Self: serde::Serialize` bound
= note: required because of the requirements on the impl of `serde::Serialize` for `&Self`
= note: required by `serde_json::ser::to_string`
Following the suggestion, but using the idiomatic supertrait syntax, answers your question:
trait Log: serde::Serialize {
fn to_log(&self) -> String {
serde_json::to_string(&self).unwrap()
}
}
You'll need to change your log function for object-safety reasons:
fn log(log: &impl Log) {
println!("serialized = {}", log.to_log());
}
See also:
The trait cannot be made into an object
Unable to create a polymorphic type because the trait cannot be made into an object
How to implement `serde::Serialize` for a boxed trait object?
How can deserialization of polymorphic trait objects be added in Rust if at all?
Using trait inheritance works, but using the right Serde trait, not the compiler-suggested one:
trait Log: serde::Serialize {
fn to_log(&self) -> String {
serde_json::to_string(&self).unwrap()
}
}

Is it good practice to require associated Error types implement Debug trait?

I've run into a problem with piston2d-graphics crate. When I try to use expect() method on Result that I get from graphics::character::CharacterCache::character method, it turns out I can't — because it requires the Error type of the Result to implement std::fmt::Debug trait:
error[E0599]: no method named `expect` found for type `std::result::Result<graphics::character::Character<'_, <G as graphics::Graphics>::Texture>, <C as graphics::character::CharacterCache>::Error>` in the current scope
--> src/some_file.rs:44:53
|
44 | let ch_glyph = glyphs.character(34, ch).expect("Couldn't load character");
| ^^^^^^
|
= note: the method `expect` exists but the following trait bounds were not satisfied:
`<C as graphics::character::CharacterCache>::Error : std::fmt::Debug`
Error here is an associated (nested) type in CharacterCache trait. I can easily submit a PR that adds the requirement and then add it's implementation with a simple derive macro to all other crates. It seems reasonable, because expect() and other related methods are used in Rust all the time, but I'm not sure. Is it the Rust way, or are there reasons not to do it?
I describe the question using example of it's occurrence, but it has nothing specific to do with Piston, my question is about general pattern in Rust. So tag rust-piston is unrelated, please don't add it to the question.
Is it good practice to require associated Error types implement Debug trait?
Yes, when possible. Maybe they forget it.
A way to solve this problem is to use map_err(), here a MCVE of the problem:
struct Error;
fn foo() -> Result<(), Error> {
Ok(())
}
fn main() {
foo().expect("no error");
}
error[E0599]: no method named `expect` found for type `std::result::Result<(), Error>` in the current scope
--> src/main.rs:8:11
|
8 | foo().expect("no error");
| ^^^^^^
|
= note: the method `expect` exists but the following trait bounds were not satisfied:
`Error : std::fmt::Debug`
Use map_err() to produce an error that implement Debug, that could be your own custom Error, In the following exemple, I just return () as Error:
struct Error;
fn foo() -> Result<(), Error> {
Ok(())
}
fn main() {
foo().map_err(|_| ()).expect("no error");
}

Resources