Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

confusing lifetime inference #33529

Open
Tracked by #42516
BusyJay opened this issue May 10, 2016 · 5 comments
Open
Tracked by #42516

confusing lifetime inference #33529

BusyJay opened this issue May 10, 2016 · 5 comments
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-lifetimes Area: Lifetimes / regions A-typesystem Area: The type system C-enhancement Category: An issue proposing an enhancement or a PR with one. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@BusyJay
Copy link

BusyJay commented May 10, 2016

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?

@arielb1
Copy link
Contributor

arielb1 commented May 10, 2016

The problem is that fn cause returns a &'a (Error+'a) rather than an &'a (Error+'static).

@nikomatsakis: that sounds like a good test case for the new regionck error messages.

@BusyJay
Copy link
Author

BusyJay commented May 10, 2016

Is there any good way to iterate all the cause of error to find if the specific error exists?

@steveklabnik steveklabnik added A-typesystem Area: The type system A-diagnostics Area: Messages for errors, warnings, and lints A-lifetimes Area: Lifetimes / regions labels Sep 16, 2016
@Mark-Simulacrum Mark-Simulacrum added the C-enhancement Category: An issue proposing an enhancement or a PR with one. label Jul 25, 2017
@estebank
Copy link
Contributor

estebank commented Feb 10, 2018

Current output:

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::Error

@estebank
Copy link
Contributor

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`

@crlf0710 crlf0710 added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Jun 11, 2020
@estebank
Copy link
Contributor

Triage: no change since nll.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-lifetimes Area: Lifetimes / regions A-typesystem Area: The type system C-enhancement Category: An issue proposing an enhancement or a PR with one. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

6 participants