What does the Rust error code E0495 mean? - rust

I'm using Rocket to make a web server and I'm trying to make a wrapper around the Responder trait so that my route methods can return any struct.
The code below does not compile because of an error about lifetimes that I don't fully understand. The error is not listed in the error index; it skips from E0492 to E0496.
Since this code uses Rocket, it requires the nightly compiler.
main.rs
#![feature(custom_attribute, proc_macro_hygiene, decl_macro)]
#[macro_use]
extern crate rocket;
extern crate rocket_contrib;
use rocket::{http::Status, response::Responder, Request};
use rocket_contrib::templates::Template;
fn main() {
rocket::Rocket::ignite().mount("/", routes![route]).launch();
}
#[get("/")]
fn route<'a>() -> DynamicResponder<'a> {
DynamicResponder::from(Template::render("template", ()))
}
struct DynamicResponder<'a> {
inner: Box<dyn Responder<'a> + 'a>,
}
impl<'r> DynamicResponder<'r> {
pub fn from<T: 'r>(responder: T) -> DynamicResponder<'r>
where
T: Responder<'r>,
{
DynamicResponder {
inner: Box::new(responder),
}
}
}
impl<'r> Responder<'r> for DynamicResponder<'r> {
fn respond_to<'b>(
self,
request: &'b Request,
) -> Result<rocket::response::Response<'r>, Status> {
self.inner.respond_to(request)
}
}
Cargo.toml
[package]
name = "rocketing_around"
version = "0.1.0"
[dependencies]
rocket = "0.4.0"
[dependencies.rocket_contrib]
version = "0.4.0"
default_features = false
features = [ "handlebars_templates" ]
Compiler message:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'r` due to conflicting requirements
--> src/main.rs:15:5
|
15 | DynamicResponder::from(Template::render("template", ()))
| ^^^^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 14:10...
--> src/main.rs:14:10
|
14 | fn route<'a>() -> DynamicResponder<'a> {
| ^^
= note: ...so that the expression is assignable:
expected DynamicResponder<'a>
found DynamicResponder<'_>
= note: but, the lifetime must be valid for the static lifetime...
= note: ...so that the types are compatible:
expected rocket::response::Responder<'_>
found rocket::response::Responder<'static>

What does the Rust error code E0495 mean?
The error code E0495 seems to be a catch-all for a variety of different situations where lifetime requirements can't be reconciled. The message already says that, and there are huge number of ways that you could write code where lifetimes don't match up properly, which is perhaps why it isn't listed with examples in the error index.
Type parameters, including lifetimes, are always determined by the caller. Looking at your particular example, a function signature like this:
fn route<'a>() -> DynamicResponder<'a> { ... }
means that, for any lifetime 'a chosen by the caller, references inside the returned DynamicResponder<'a> must be valid. But what could the references inside DynamicResponder<'a> even be in this situation? They can't be references to variables in the function body because those only live as long as the function. There are no arguments, so the only things that could be referenced by the DynamicResponder<'a> are things that live outside the function, i.e. statics.
You can fix the error by removing the lifetime variable and setting the lifetime parameter to the only lifetime that makes sense:
fn route() -> DynamicResponder<'static> { ... }

Related

actix web lifetime in web::Data

I am trying to work with Data in acitx web, but it wont work with a defined lifetime. Why am i getting this error and how do i fix it? implicit elided lifetime not allowed here assuming a 'static lifetime
#[get("/search/{query}/")]
async fn testing(search: Path<SearchIdentifier>,test: Data< Test >) -> Json<String> {...}
error[E0726]: implicit elided lifetime not allowed here
--> src/api/file.rs:86:62
|
86 | async fn testing(search: Path<SearchIdentifier>,test: Data< Test >) -> Json<String> {
| ^^^^^^- help: indicate the anonymous lifetime: `<'_>`
|
= note: assuming a `'static` lifetime...
pub struct Test<'a> {
test: Test<'a>,
}
impl<'a> Test<'a> {
pub fn new(conn: MysqlConnection) -> Self {
let test = Test { conn: &conn };
Self {test}
}
Test contains a lifetime - 'a. You omitted it. Usually, when you do that, the compiler uses the lifetime elision rules to figure out what the lifetime should be - in this case, for example, it would become:
fn testing<'a>(search: Path<SearchIdentifier>,test: Data<Test<'a>>) -> Json<String>
However, this is not a normal function. This is an async function. And async functions are not allowed to implicitly elide the lifetime - they have to explicitly elide it using '_, that is:
async fn testing(search: Path<SearchIdentifier>,test: Data<Test<'_>>) -> Json<String>
Or, of course, the fully-specified version with 'a.
The reason for that is that implicit lifetime elision on structs is considered a design mistake, because it does not allow you to reason easily about the lifetimes present in your function. In fact, I recommend putting at the crate root the following:
#![forbid(rust_2018_idioms)]
To (among other things) disallow that for any function, not just async.

How to make OwningRef work with iterators?

I have a RwLock protected global WORLD, and I want to write a function that read locks it and returns an iterator (of type Neighbors) that iterates over edges in a petgraph::stable_graph::StableGraph that is stored inside the global. I'm using OwningRef to deal with keeping the read lock guard alive after the function exits, which has worked for me in the past when just returning a field of World directly. I've included a compilable example and the error I'm getting below -- it seems there is some sort of type problem but I haven't been able to figure it out. I think it might have to do with OwningRef wanting to deal with a reference rather than an object containing a reference (Neighbors) but I'm not sure how to work around that.
Cargo.toml:
[package]
name = "problem_demo"
version = "0.1.0"
authors = ["Joseph Garvin <joseph.h.garvin#gmail.com>"]
edition = "2018"
[dependencies]
owning_ref="0.4.1"
once_cell="1.4.0"
petgraph={version="0.5.1", features=["serde-1"]}
main.rs:
use std::{sync::RwLock};
use once_cell::sync::OnceCell;
use owning_ref::RwLockReadGuardRef;
use petgraph::stable_graph::{StableGraph, Neighbors};
struct Bar {
data: i32
}
struct World {
graph: StableGraph<(), Bar, petgraph::Directed, u32>
}
pub static WORLD: OnceCell<RwLock<World>> = OnceCell::new();
fn neighbors(id: u32) -> Result<RwLockReadGuardRef<'static, World, Neighbors<'static, Bar, u32>>, Box<dyn std::error::Error>> {
RwLockReadGuardRef::new(WORLD.get().unwrap().read().unwrap())
.try_map(
|world: &World| -> std::result::Result<Neighbors<'static, Bar, u32>, Box<dyn std::error::Error>>
{
let neighbors = world.graph.neighbors_directed(
petgraph::graph::NodeIndex::new(id as usize),
petgraph::Direction::Outgoing
);
Ok(neighbors)
}
)
}
Errors:
error[E0271]: type mismatch resolving `for<'r> <[closure#src/main.rs:21:13: 29:14 id:_] as std::ops::FnOnce<(&'r World,)>>::Output == std::result::Result<&'r _, _>`
--> src/main.rs:20:10
|
20 | .try_map(
| ^^^^^^^ expected struct `petgraph::stable_graph::Neighbors`, found reference
|
= note: expected enum `std::result::Result<petgraph::stable_graph::Neighbors<'static, Bar>, std::boxed::Box<dyn std::error::Error>>`
found enum `std::result::Result<&_, _>`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0271`.
error: could not compile `playground`.
To learn more, run the command again with --verbose.

Why does a lazy-static value claim to not implement a trait that it clearly implements?

With the following code (an attempt to make an HTTP request using the reqwest crate), the compiler says that my value SID_URI does not implement the trait PolyfillTryInto. What's going on here? reqwest::Url clearly implements the private trait reqwest::into_url::PolyfillTryInto.
#[macro_use]
extern crate lazy_static;
extern crate reqwest;
static R_EMAIL: &str = "example#example.com";
static R_PASS: &str = "password";
static API_PUBKEY: &str = "99754106633f94d350db34d548d6091a";
static API_URI: &str = "https://example.com";
static AUTH_PATH: &str = "/api/v1";
lazy_static! {
static ref SID_URI: reqwest::Url = reqwest::Url::parse(&(API_URI.to_owned() + AUTH_PATH)).unwrap();
}
fn get_sid() -> Result<reqwest::Response, reqwest::Error> {
let client = reqwest::Client::new();
let params = [("ID", R_EMAIL), ("PW", R_PASS), ("KY", API_PUBKEY)];
let q = client.post(SID_URI).form(&params).send()?;
Ok(q)
}
fn main() {
assert!(get_sid().is_ok());
}
error[E0277]: the trait bound `SID_URI: reqwest::into_url::PolyfillTryInto` is not satisfied
--> src/main.rs:19:20
|
19 | let q = client.post(SID_URI).form(&params).send()?;
| ^^^^ the trait `reqwest::into_url::PolyfillTryInto` is not implemented for `SID_URI`
|
= note: required because of the requirements on the impl of `reqwest::IntoUrl` for `SID_URI`
The compiler isn't lying to you, you are just skipping over a relevant detail of the error message. Here's a self-contained example:
#[macro_use]
extern crate lazy_static;
struct Example;
trait ExampleTrait {}
impl ExampleTrait for Example {}
lazy_static! {
static ref EXAMPLE: Example = Example;
}
fn must_have_trait<T>(_: T)
where
T: ExampleTrait,
{
}
fn main() {
must_have_trait(EXAMPLE);
must_have_trait(42i32);
}
error[E0277]: the trait bound `EXAMPLE: ExampleTrait` is not satisfied
--> src/main.rs:19:5
|
19 | must_have_trait(EXAMPLE);
| ^^^^^^^^^^^^^^^ the trait `ExampleTrait` is not implemented for `EXAMPLE`
|
= note: required by `must_have_trait`
error[E0277]: the trait bound `i32: ExampleTrait` is not satisfied
--> src/main.rs:20:9
|
20 | must_have_trait(42i32);
| ^^^^^^^^^^^^^^^ the trait `ExampleTrait` is not implemented for `i32`
|
= note: required by `must_have_trait`
Compare the two error messages:
the trait bound `EXAMPLE: ExampleTrait` is not satisfied
the trait bound `i32: ExampleTrait` is not satisfied
The second error message doesn't say that 42 does not implement ExampleTrait, it says that i32 lacks the implementation. This error message shows the type that fails, not the name of the value! That means that EXAMPLE in the same context is referring to a type.
Lazy-static works by creating one-off types that wrap your value and provide thread-safe single initialization guarantees:
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.
This wrapper type does not implement your trait, only the wrapped type does. You will need to invoke Deref and then probably re-reference it to get to a &Url, assuming that a reference to a Url implements your trait:
must_have_trait(&*EXAMPLE);
Additionally, using the bare static variable would attempt to move it out of the static location (which would be a Very Bad Thing), so you always need to use it by reference.

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.

How do I get lifetime of reference to owned object? (cannot infer an appropriate lifetime for lifetime parameter)

How do I get this to compile?
extern crate collections;
fn print_x_from_table(table: collections::BTreeMap<String, String>) {
let x: &str = table
.get(&String::from_str("x"))
.map(|s: &String| &s[]) // ERROR!
.unwrap_or("");
println!("table contains x={}", x);
}
It gives this error:
src/rusttest.rs:5:22: 5:25 error: cannot infer an appropriate lifetime for lifetime parameter 'a in function call due to conflicting requirements
src/rusttest.rs:5 .map(|s: &String| &s[])
^~~
src/rusttest.rs:7:34: 7:35 note: first, the lifetime cannot outlive the expression at 7:33...
src/rusttest.rs:7 println!("table contains x={}", x);
^
note: in expansion of format_args!
<std macros>:2:43: 2:76 note: expansion site
<std macros>:1:1: 2:78 note: in expansion of println!
src/rusttest.rs:7:2: 7:37 note: expansion site
src/rusttest.rs:7:34: 7:35 note: ...so type `&str` of expression is valid during the expression
src/rusttest.rs:7 println!("table contains x={}", x);
If table were a reference parameter, I know that I could add a type parameter 'a to indicate how long s should live. But how do I do that when I own table?
extern crate collections;
fn print_x_from_ref_table<'a>(table: &'a collections::BTreeMap<String, String>) {
let x: &'a str = table
.get(&String::from_str("x"))
.map(|s: &'a String| &s[])
.unwrap_or("");
println!("table contains x={}", x);
}
I managed to get it working by avoiding using closures and using match instead. I think this works because in .map(|s| &s[]) the compiler gets confused and thinks the reference should live shorter than how long it actually lives for.
fn print_x_from_table(table: collections::BTreeMap<String, String>) {
let x = match table.get("x") {
Some(v) => &v[],
None => ""
};
println!("table contains x={}", x);
}
I think this is a limitation of the closure syntax. Check out these alternatives:
use std::ops::Deref;
use std::collections::HashMap;
fn inner<'a>(s: &'a String) -> &'a str { //'
&s[]
}
fn inner2(s: &String) -> &str {
&s[]
}
fn print_x_from_table(table: HashMap<String, String>) {
let x = table
.get("x")
// .map(|s: &String| &s[]) // ERROR!
// .map(inner) // OK
// .map(inner2) // OK
// .map(Deref::deref) // OK
.map(|s| &s[]) // OK
.unwrap_or("");
println!("table contains x={}", x);
}
fn main() {
}
In the second example, we use a function inner that has explicit named lifetimes that tie the input and the output together, letting the reference live beyond the closure. However, this is the exact case for lifetime elision, so inner2 is the same concept, but shorter. We could also cut out the middleman and just use the Deref::deref method directly.
The last example doesn't specify any types, so the compiler automatically inserts them and ties the references together (this last part is a guess based on observation, not intrinsic knowledge). This is probably what you'd see most of the time; it's not super common to specify types when you don't need to.
One potential "solution" would be if we could specify lifetimes ourselves on the closure definition. A hypothetical syntax like
<'a>|foo: &'a String| -> &'a str { foo.bar() }
could do the trick, but I don't know of any way to make that work.

Resources