Method exists but the following trait bounds were not satisfied (generics) - rust

I have a working function foo, which compiles without error:
use chrono;
fn foo() {
let now = chrono::offset::Local::now();
let mut buf = String::new();
buf.push_str(&now.format("%Y/%m/%d").to_string());
}
When I try to extract the now variable to a parameter:
fn foo<T: chrono::TimeZone>(now: chrono::DateTime<T>) {
let mut buf = String::new();
buf.push_str(&now.format("%Y/%m/%d").to_string());
}
I run into this error when compiling:
error[E0599]: no method named `format` found for struct `chrono::DateTime<T>` in the current scope
--> src/lib.rs:108:35
|
108 | buf.push_str(&now.format("%Y/%m/%d").to_string());
| ^^^^^^ method not found in `chrono::DateTime<T>`
|
= note: the method `format` exists but the following trait bounds were not satisfied:
`<T as chrono::TimeZone>::Offset: std::fmt::Display`
The note says that format exists (it does, as in the first code snippet), but trait bounds aren't satisfied. How do I specify the missing trait bound to make this compile?
I'm guessing it should be possible somehow, considering that the first snippet compiles and I'm only extracting the same type as a parameter.
Related chrono docs: https://docs.rs/chrono/0.4.19/chrono/struct.DateTime.html

I took a look at the impl block for DateTime. It had code of the form below. I updated the function's signature to match, and it now compiles successfully.
fn foo<T: chrono::TimeZone>(now: chrono::DateTime<T>)
where
T::Offset: std::fmt::Display, {
...
}

Related

Method cannot be called on Option due to unsatisfied trait bounds, needs to be iterator

I know that the cloned() here is unnecessary but I want to know why it requires that Values implement the Iterator trait.
Minimal reproducible example
#[derive(Debug, Clone)]
enum Values {
Foo,
Bar
}
fn f(mut values: impl Iterator<Item=Values>) {
// (HERE) Why to clone Option<Values> should implement Iterator???
if let Some(v1) = values.next().cloned() {
if let Some(v2) = values.next() {
println!("Foo");
}
}
}
fn main() {
let mut values = vec![
Values::Foo,
Values::Bar
];
f(values.into_iter());
}
Error
error[E0599]: the method `cloned` exists for enum `Option<Values>`, but its trait bounds were not satisfied
--> src/main.rs:8:37
|
8 | if let Some(v1) = values.next().cloned() {
| ^^^^^^ method cannot be called on `Option<Values>` due to
unsatisfied trait bounds
|
= note: the following trait bounds were not satisfied:
`Option<Values>: Iterator`
which is required by `&mut Option<Values>: Iterator`
Playground
link
There are two applicable cloned functions, Iterator::cloned and Option::cloned.
The Option::cloned does not apply in this case, since it is only available for types like Option<&T>. In the example it is a Option<Value> which is not a reference.
Iterator::cloned could apply, if the trait bound Option<Values>: Iterator
is satisfied, which is why this is part of the suggestion.
Both functions would be wrong in this context to use.
Maybe you meant to use the clone function which would indeed be unnecessary.
Option::cloned() is only defined if the value inside is a reference. For example, you could call it if the paramters was values: impl Iterator<Item = &Values>, which would make the result of next() an Option<&Values>.
You parameter values: impl Iterator<Item = Values> means that the iterator owns the values. The values are moved out of the iterator as you iterate through it so the clone would be unnecessary. I assume that this is just an artifact of it being a minimum reproducible example.
The error is confusing because the compiler is trying to help you by suggesting traits you could implement that do have a cloned() method, and the choices are:
Option<&T>
I where I: Iterator<Item = &T>
It unfortunately has chosen the one that doesn't apply in your situation.

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
}

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");
}

Why can't I reuse a &mut reference after passing it to a function that accepts a generic type?

Why doesn't this code compile:
fn use_cursor(cursor: &mut io::Cursor<&mut Vec<u8>>) {
// do some work
}
fn take_reference(data: &mut Vec<u8>) {
{
let mut buf = io::Cursor::new(data);
use_cursor(&mut buf);
}
data.len();
}
fn produce_data() {
let mut data = Vec::new();
take_reference(&mut data);
data.len();
}
The error in this case is:
error[E0382]: use of moved value: `*data`
--> src/main.rs:14:5
|
9 | let mut buf = io::Cursor::new(data);
| ---- value moved here
...
14 | data.len();
| ^^^^ value used here after move
|
= note: move occurs because `data` has type `&mut std::vec::Vec<u8>`, which does not implement the `Copy` trait
The signature of io::Cursor::new is such that it takes ownership of its argument. In this case, the argument is a mutable reference to a Vec.
pub fn new(inner: T) -> Cursor<T>
It sort of makes sense to me; because Cursor::new takes ownership of its argument (and not a reference) we can't use that value later on. At the same time it doesn't make sense: we essentially only pass a mutable reference and the cursor goes out of scope afterwards anyway.
In the produce_data function we also pass a mutable reference to take_reference, and it doesn't produce a error when trying to use data again, unlike inside take_reference.
I found it possible to 'reclaim' the reference by using Cursor.into_inner(), but it feels a bit weird to do it manually, since in normal use-cases the borrow-checker is perfectly capable of doing it itself.
Is there a nicer solution to this problem than using .into_inner()? Maybe there's something else I don't understand about the borrow-checker?
Normally, when you pass a mutable reference to a function, the compiler implicitly performs a reborrow. This produces a new borrow with a shorter lifetime.
When the parameter is generic (and is not of the form &mut T), the compiler doesn't do this reborrowing automatically1. However, you can do it manually by dereferencing your existing mutable reference and then referencing it again:
fn take_reference(data: &mut Vec<u8>) {
{
let mut buf = io::Cursor::new(&mut *data);
use_cursor(&mut buf);
}
data.len();
}
1 — This is because the current compiler architecture only allows a chance to do a coercion if both the source and target types are known at the coercion site.

Closure in the return type for a Rust function [duplicate]

This question already has answers here:
Returning a closure from a function
(4 answers)
Closed 5 years ago.
I wrote the following Rust program to print out only command-line arguments that are integers. It works perfectly:
use std::env;
fn main() {
for i in env::args().filter_map(|arg| arg.parse::<i32>().ok()) {
println!("{}", i);
}
}
I then attempted to re-write the program to abstract the filter into a function. This version does not compile.
use std::env::Args;
use std::env;
use std::iter::FilterMap;
// Version 2
fn main() {
for i in nums(&env::args()) {
println!("{}", i);
}
}
fn nums<F: Fn(String) -> Option<i32>>(args: &Args) -> FilterMap<Args,F> {
args.filter_map(|arg| arg.parse::<i32>().ok())
}
It produces the following compilation errors:
Compiling iterator_return_type v0.1.0 (file:///Users/gabriel/AllProjects/SentimentAnalysis/iterator_return_type)
error[E0282]: type annotations needed
--> src/main.rs:16:9
|
16 | for i in nums(&env::args()) {
| ^ cannot infer type for `_`
error: the type of this value must be known in this context
--> src/main.rs:22:27
|
22 | args.filter_map(|arg| arg.parse::<i32>().ok())
| ^^^^^^^^^^^^^^^^^^
error[E0308]: mismatched types
--> src/main.rs:22:21
|
22 | args.filter_map(|arg| arg.parse::<i32>().ok())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter, found closure
|
= note: expected type `F`
found type `[closure#src/main.rs:22:21: 22:50]`
error: aborting due to previous error(s)
error: Could not compile `iterator_return_type`.
What I find particularly confusing is the final compilation error. I do not understand how else I might specify a closure type.
Thanks!
impl Trait and Box<Trait> solution can be applied to both iteratorsand closures, both of them are just traits! The difference is you have to use them in the closure case.
If you want to use impl Trait, then your code will look like this (note that Args should be passed by value):
#![feature(conservative_impl_trait)]
use std::env::Args;
use std::env;
use std::iter::FilterMap;
fn main() {
for i in nums(env::args()) {
println!("{}", i);
}
}
fn nums(args: Args) -> FilterMap<Args, impl FnMut(String) -> Option<i32>> {
args.filter_map(|arg| arg.parse::<i32>().ok())
}
However, you usually need not expose the detail of the iterator type; therefore you can do it like this way:
fn nums(args: Args) -> impl Iterator<Item = i32> {
args.filter_map(|arg| arg.parse::<i32>().ok())
}
What if you want to use stable Rust? Unfortunately you'll have to use boxing for now.
fn nums(args: Args) -> Box<Iterator<Item = i32>> {
Box::new(args.filter_map(|arg| arg.parse::<i32>().ok()))
}
Why can't you describe a full type of closures, despite that you can describe an iterator like Zip<Drain<'a, i32>, IntoIter<&'b str>>? There are two reasons:
Closure types are anonymous by nature; you'll have to anonymize (impl Fn()) or box (Box<Fn()>) them if you want to return them.
The interface for closure traits is unstable; you can't implement them (impl Fn() for YourType { .. }) stably.
Then why doesn't your code work? The reason is:
If you want to pass closures to a function, the caller decides its type. In this case you can write fn foo<T: Fn()>() { .. }.
If you want to pass closures from a function, the callee decides its type. In this case you'll have to use impl Trait.
RFC 1951 will change this distinction. You will be able to use impl Trait in both cases.

Resources