confusing lifetime inference
1087a8a
Opened by Jay at
Consider following snippet:
use std::error::Error;
use std::io::{self, ErrorKind};
fn caused_of<'a>(mut err: &'a (Error + 'static)) -> Option<&'a io::Error> {
loop {
match err.downcast_ref::<io::Error>() {
None => match err.cause() {
None => return None,
Some(cause) => err = cause,
},
d => return d,
}
}
}
fn main() {
let e = io::Error::new(ErrorKind::Other, "oh no!");
println!("{:?}", caused_of(&e));
}
According to Book, cause's lifetime should be err's lifetime. which is 'a, so it should be safe to assign cause to err directly. But I got following warnnings:
test.rs:8:34: 8:39 error: cannot infer an appropriate lifetime for autoref due to conflicting requirements [E0495]
test.rs:8 None => match err.cause() {
^~~~~
test.rs:8:30: 8:41 note: first, the lifetime cannot outlive the method call at 8:29...
test.rs:8 None => match err.cause() {
^~~~~~~~~~~
test.rs:8:30: 8:33 note: ...so that method receiver is valid for the method call
test.rs:8 None => match err.cause() {
^~~
test.rs:5:75: 15:25 note: but, the lifetime must be valid for the lifetime 'a as defined on the block at 5:74...
test.rs:5 fn caused_of<'a>(mut err: &'a (Error + 'static)) -> Option<&'a io::Error> {
^
test.rs:10:48: 10:53 note: ...so that trait type parameters matches those specified on the impl (expected std::ops::CoerceUnsized<&'a std::error::Error + 'static>, found std::ops::CoerceUnsized<&std::error::Error + 'static>)
test.rs:10 Some(cause) => err = cause,
^~~~~
error: aborting due to previous error
Am I missing something here?
The problem is that
fn causereturns a&'a (Error+'a)rather than an&'a (Error+'static).@nikomatsakis: that sounds like a good test case for the new regionck error messages.
Ariel Ben-Yehuda at 2016-05-10 05:27:09
Is there any good way to iterate all the cause of
errorto find if the specificerrorexists?Jay at 2016-05-10 05:37:07
-
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements --> src/main.rs:8:31 | 8 | None => match err.cause() { | ^^^^^ | note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 5:1... --> src/main.rs:5:1 | 5 | fn caused_of<'a>(mut err: &'a (Error + 'static)) -> Option<&'a io::Error> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...so that reference does not outlive borrowed content --> src/main.rs:8:27 | 8 | None => match err.cause() { | ^^^ = note: but, the lifetime must be valid for the static lifetime... = note: ...so that the expression is assignable: expected &'a std::error::Error + 'static found &std::error::Error
Update, minimal changes:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements --> src/main.rs:8:31 | 8 | None => match err.cause() { | ^^^^^ | note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 5:14... --> src/main.rs:5:14 | 5 | fn caused_of<'a>(mut err: &'a (Error + 'static)) -> Option<&'a io::Error> { | ^^ note: ...so that reference does not outlive borrowed content --> src/main.rs:8:27 | 8 | None => match err.cause() { | ^^^ = note: but, the lifetime must be valid for the static lifetime... = note: ...so that the expression is assignable: expected &'a (dyn std::error::Error + 'static) found &dyn std::error::ErrorEsteban Kuber at 2018-02-10 01:37:04
Output with nll enabled:
error: lifetime may not live long enough --> src/main.rs:11:32 | 6 | fn caused_of<'a>(mut err: &'a (Error + 'static)) -> Option<&'a io::Error> { | -- lifetime `'a` defined here ... 11 | Some(cause) => err = cause, | ^^^^^^^^^^^ cast requires that `'a` must outlive `'static`Esteban Kuber at 2019-07-20 02:31:59
Triage: no change since nll.
Esteban Kuber at 2023-10-19 18:36:42