I have an error that i do not understand when i compile my rust code.
error: lifetime may not live long enough
--> src\tls_rustls.rs:88:9
|
51 | impl<'a> Tls<Certificate> for EstClientRustls<'a> {
| -- lifetime `'a` defined here
52 | fn open(&mut self, host: &str, port: i32, chain: &Vec<Certificate>) {
| - let's call the lifetime of this reference `'1`
...
88 | self.tls = Some(tls);
| ^^^^^^^^^^^^^^^^^^^^ assignment requires that `'1` must outlive `'a`
The code that generates the error is:
pub trait Tls<T> {
fn open(&mut self, host: &str, port: i32, chain: &Vec<T>);
fn close(&self);
}
pub struct EstClientRustls<'a> {
client: Option<ClientConnection>,
sock: Option<TcpStream>,
tls: Option<Stream<'a, ClientConnection, TcpStream>>
}
impl<'a> Tls<Certificate> for EstClientRustls<'a> {
fn open(&mut self, host: &str, port: i32, chain: &Vec<Certificate>) {
let client = ClientConnection::new(rc_config, tls_server_name).unwrap();
let sock = TcpStream::connect(host_port).unwrap();
self.client = Some(client);
self.sock = Some(sock);
let tls = Stream::new(
self.client.as_mut().unwrap(),
self.sock.as_mut().unwrap());
self.tls = Some(tls);
}
}
Anyone can help me?
Technical notes:
rustc 1.64.0 (a55dd71d5 2022-09-19)
libraries:
rustls -> "0.20.7"
rustls-pemfile -> "1.0.1"
x509-parser -> "0.14.0"
Solution thanks to Ali Mirghasemi
Change the trait definition to
pub trait Tls<'a, T> {
fn open(&'a mut self, host: &str, port: i32, chain: &Vec<T>);
fn close(&self);
}
and the implementation itself to
fn open(&'a mut self, host: &str, port: i32, chain: &Vec<Certificate>) {
solve the problem
Related
I'm getting this error with a sample code at this rust playground
Compiling playground v0.0.1 (/playground)
error[E0597]: `text` does not live long enough
--> src/main.rs:34:38
|
34 | let item = NotLongEnough { text: &text };
| ^^^^^ borrowed value does not live long enough
35 | let mut wrapper = Container { buf: Vec::new() };
36 | wrapper.add(Box::new(item));
| -------------- cast requires that `text` is borrowed for `'static`
...
40 | }
| - `text` dropped here while still borrowed
error: aborting due to previous error
For more information about this error, try `rustc --explain E0597`.
error: could not compile `playground`
To learn more, run the command again with --verbose.
The contents are:
trait TestTrait {
fn get_text(&self) -> &str;
}
#[derive(Copy, Clone)]
struct NotLongEnough<'a> {
text: &'a str,
}
impl<'a> TestTrait for NotLongEnough<'a> {
fn get_text(&self) -> &str {
self.text
}
}
struct Container {
buf: Vec<Box<dyn TestTrait>>,
}
impl Container {
pub fn add(&mut self, item: Box<dyn TestTrait>) {
self.buf.push(item);
}
pub fn output(&self) {
for item in &self.buf {
println!("{}", item.get_text());
}
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let text = "test".to_owned();
let item = NotLongEnough { text: &text };
let mut wrapper = Container { buf: Vec::new() };
wrapper.add(Box::new(item));
wrapper.output();
Ok(())
}
I have no clue why cast requires that text is borrowed for 'static
Could someone please help me with this? I've no idea what I've done wrong.
TLDR: Fixed version
The problem is in your Container definition:
struct Container {
buf: Vec<Box<dyn TestTrait>>,
}
The statement dyn TestTrait is equivalent to dyn TestTrait + 'static, meaning that your trait objects must not contain any references with lifetime less than 'static.
In order to fix the problem, you have to replace that trait bound with a less strict one:
struct Container<'a> {
buf: Vec<Box<dyn TestTrait + 'a>>,
}
Now instead of 'static, the container requires 'a. And you have to apply that change to the implementation as well:
pub fn add(&mut self, item: Box<dyn TestTrait + 'a>) { // notice the new trait-bound
self.buf.push(item);
}
Relevant resources:
Trait bounds
If I remove the 'static lifetime of the final argument, the program compiles. If I add it back, it fails. To me, it seems both should be valid. Minimal reproduction:
use std::io;
struct Foo {
user: String,
pass: String,
}
impl Foo {
async fn not_works(
&mut self,
user: &str,
pass: &str,
app_name: &'static str,
) -> io::Result<()> {
self.user = user.to_string() + app_name;
self.pass = pass.to_string();
self.do_stuff().await
}
async fn works(&mut self, user: &str, pass: &str, app_name: &str) -> io::Result<()> {
self.user = user.to_string() + app_name;
self.pass = pass.to_string();
self.do_stuff().await
}
async fn do_stuff(&self) -> io::Result<()> {
Ok(())
}
}
#[tokio::main]
async fn main() {
let mut foo = Foo {
user: "".to_string(),
pass: "".to_string(),
};
foo.not_works("test", "password", "foobar").await.unwrap();
}
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> src/main.rs:14:10
|
14 | ) -> io::Result<()> {
| ^^^^^^^^^^^^^^
|
note: hidden type `impl Future` captures lifetime smaller than the function body
--> src/main.rs:14:10
|
14 | ) -> io::Result<()> {
| ^^^^^^^^^^^^^^
It's much more likely the bug is in my understanding and not the compiler though. What am I missing?
This is a limitation of the async fn implementation. Basically, it tries to unify all lifetimes to be the same, and in this case they can't be all 'static.
This works:
fn workaround<'a>(
&'a mut self,
user: &'a str,
pass: &'a str,
app_name: &'static str,
) -> impl Future<Output = io::Result<()>> + 'a {
async move {
self.user = user.to_string() + app_name;
self.pass = pass.to_string();
self.do_stuff().await
}
}
I had some problems when I tried to create a custom iterator. The non-mutable version worked fine but when copying the same function to create a mutable version, a lifetime error appeared. This is a simplified version of my problem:
struct Test {
map: HashMap<u32, String>
}
impl Test {
pub fn iter(&self, start: u32, end: u32) -> impl Iterator<Item = &String> {
(start..=end).filter_map(move |i| {
self.map.get(&i)
})
}
pub fn iter_mut(&mut self, start: u32, end: u32) -> impl Iterator<Item = &mut String> {
(start..=end).filter_map(move |i| {
self.map.get_mut(&i)
})
}
}
The iter function works fine but the iter_mut function doesn't compile with this error:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/main.rs:21:22
|
21 | self.map.get_mut(&i)
| ^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime `'_` as defined on the body at 20:34...
--> src/main.rs:20:34
|
20 | (start..=end).filter_map(|i| {
| ^^^
note: ...so that closure can access `self`
--> src/main.rs:21:13
|
21 | self.map.get_mut(&i)
| ^^^^^^^^
note: but, the lifetime must be valid for the anonymous lifetime defined on the method body at 19:21...
--> src/main.rs:19:21
|
19 | pub fn iter_mut(&mut self, start: u32, end: u32) -> impl Iterator<Item = &mut String> {
| ^^^^^^^^^
note: ...so that the types are compatible
--> src/main.rs:19:57
|
19 | pub fn iter_mut(&mut self, start: u32, end: u32) -> impl Iterator<Item = &mut String> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: expected `std::option::Option<&mut std::string::String>`
found `std::option::Option<&mut std::string::String>`
As said Todd, compile error on iter_mut likely occurs due to creation many mutable references to the same HashMap, but I'm not sure about that. You can do something like that:
struct Test {
map: HashMap<u32, String>
}
impl Test {
pub fn iter(&self, start: u32, end: u32) -> impl Iterator<Item=&String> {
self.map
.iter()
.filter_map(move |k| {
if (start..=end).contains(k.0) {
Some(k.1)
} else {
None
}
})
}
pub fn iter_mut(&mut self, start: u32, end: u32) -> impl Iterator<Item=&mut String> {
self.map
.iter_mut()
.filter_map(move |k| {
if (start..=end).contains(k.0) {
Some(k.1)
} else {
None
}
})
}
}
I read the builder pattern and then tried to build 2 different builders (Header and Request) as follows:
use std::ascii::AsciiExt;
#[derive(PartialEq, Debug)]
pub struct Headers<'a> (pub Vec<(&'a str, String)>);
impl<'a> Headers<'a> {
pub fn replace(&'a mut self, name: &'a str, value:&str) -> &mut Headers<'a> {
self.0.retain(|&(key, _)|!name.eq_ignore_ascii_case(key));
self.0.push((name, value.to_string()));
self
}
}
#[derive(PartialEq, Debug)]
pub struct Request<'a> {
pub headers: Headers<'a>,
}
impl<'a> Request<'a> {
pub fn header(&'a mut self, name: &'a str, value:&'a str) -> &mut Request<'a> {
self.headers.replace(name, value);
self
}
}
Why does Header compile fine but Request fails with:
error[E0499]: cannot borrow `*self` as mutable more than once at a time
--> src/api.rs:154:9
|
153 | self.headers.replace(name, value);
| ------------ first mutable borrow occurs here
154 | self
| ^^^^ second mutable borrow occurs here
155 | }
| - first borrow ends here
You have an issue with your lifetimes: you are re-using the same lifetime ('a) for too many different things, so that when the compiler attempts to use a single lifetime for all those 'a you get a confusing error message.
The solution is simple: do not use 'a everywhere you can put a lifetime, but only where it's necessary.
It is unnecessary to use &'a mut self, the instance (self) does not need to have the same lifetime as the &str it contains! (and actually, cannot really):
impl<'a> Headers<'a> {
pub fn replace(&mut self, name: &'a str, value: &str) -> &mut Headers<'a> {
self.0.retain(|&(key, _)|!name.eq_ignore_ascii_case(key));
self.0.push((name, value.to_string()));
self
}
}
impl<'a> Request<'a> {
pub fn header(&mut self, name: &'a str, value: &str) -> &mut Request<'a> {
self.headers.replace(name, value);
self
}
}
I have a struct UrlShortener:
pub struct UrlShortener {
client: hyper::Client,
}
impl UrlShortener {
pub fn new() -> UrlShortener {
UrlShortener {
client: hyper::Client::new(),
}
}
pub fn get(&self, url: &str) -> Result<String, Error> {
let mut response = MyProvider.request(url, &self.client).send().unwrap();
/// ...
}
}
The MyProvider looks like this:
pub trait Provider {
fn name(&self) -> &str;
fn request(&self, url: &str, client: &hyper::Client) -> hyper::client::RequestBuilder;
}
pub struct MyProvider;
impl Provider for MyProvider {
fn name(&self) -> &str {
"myprovider"
}
fn request(&self, url: &str, client: &hyper::Client) -> hyper::client::RequestBuilder {
client.get(&format!("http://example.com/create.php?format=simple&url={}", url))
}
}
The I tried to compile it at first time it did not work:
src/lib.rs:21:16: 21:19 error: cannot infer an appropriate lifetime for autoref due to conflicting requirements [E0495]
src/lib.rs:21 client.get(&format!("http://example.com/create.php?format=simple&url={}", url))
^~~
src/lib.rs:20:5: 22:6 help: consider using an explicit lifetime parameter as shown: fn request<'a>(&'a self, url: &str, client: &'a hyper::Client)
-> hyper::client::RequestBuilder
src/lib.rs:20 fn request(&self, url: &str, client: &hyper::Client) -> hyper::client::RequestBuilder {
src/lib.rs:21 client.get(&format!("http://example.com/create.php?format=simple&url={}", url))
src/lib.rs:22 }
error: aborting due to previous error
error: Could not compile `urlshortener`.
I've changed it according the compiler's advice and it is working okay.
fn request<'a>(&'a self, url: &str, client: &'a hyper::Client) -> hyper::client::RequestBuilder {
client.get(&format!("http://example.com/create.php?format=simple&url={}", url))
}
The question here is why does it work? What is in my mind:
'a lifetime for self in the Provider is different from the lifetime of client: &hyper::Client because these objects are in different places: MyProvider is on the stack and client is a field of the structure of the method I use.
So I think compiler compiles it successfully but it may lead to a runtime error or crash. Am I wrong?
"Correct" solution from my point of view would be:
fn request<'a, 'b>(&'a self, url: &str, client: &'b hyper::Client) -> hyper::client::RequestBuilder {
So I think compiler compiles it successfully but it may lead to a runtime error or crash.
Unless you are using some unsafe {} code, this can't happen in Rust. Rust always statically checks bounds and it doesn't matter whether the variables are on stack or heap or are fields or whatever.
As for Rust's suggestions: since RequestBuilder has a lifetime itself the following function:
fn request(&self, url: &str, client: &hyper::Client) -> hyper::client::RequestBuilder;
is equivalent to:
fn request<'a, 'b, 'c>(&'a self, url: &'b str, client: &'c hyper::Client) -> hyper::client::RequestBuilder<'a>;
// ^^ ^^
because of the elisions rules. Note the important rule for that examples:
If there are multiple input lifetimes, but one of them is &self or &mut self, the lifetime of self is assigned to all elided output lifetimes.
And that's when Rust gives you a misleading suggestion. In your function, the return value depends on client but not actually on self. Rust propose you to give self and client the same lifetime (ie. 'a == 'c):
fn request<'a, 'b>(&'a self, url: &'b str, client: &'a hyper::Client) -> hyper::client::RequestBuilder<'a>;
// ^^ ^^ ^^
But it would be sufficient to have:
fn request<'a, 'b, 'c>(&'a self, url: &'b str, client: &'c hyper::Client) -> hyper::client::RequestBuilder<'c>;
// ^^ ^^ ^^
which can be written with elision:
fn request<'c>(&self, url: &str, client: &'c hyper::Client) -> hyper::client::RequestBuilder<'c>;
// ^^ ^^