Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I return an &str value generated from a String?

Tags:

rust

lifetime

I'm having some trouble trying to grasp why I can't return an &str value generated from a String (goodness, when will as_str be ready?) and I'm doing something wrong. I get this idea because nothing that I do makes the value live long enough to use.

I'm trying to implement error::Error for a custom struct:

impl error::Error for LexicalError {
    fn description(&self) -> &str {
        let s = format!("{}", self);

        // s doesn't live long enough to do this, I've tried 
        // cloning s and using that, but still the clone doesn't
        // live long enough.
        s.trim()
    }

    fn cause(&self) -> Option<&error::Error> {
        None
    }
}

(for the complete snippet, here is the playpen)

I can't figure out how to return an &str from description, I'd like to reuse the Display logic, unless of course I'm completely misunderstanding what description should be returning (perhaps the short description of the issue). Either, I get the same issue with the return of format!(...) which is a variable I can't seem to get to live long enough to be useful to me.

like image 529
Brandon Buck Avatar asked Apr 21 '15 19:04

Brandon Buck


People also ask

Why is Amazon not giving me the option to return?

Amazon.com doesn't accept returns for items fulfilled by third-party sellers. The seller determines the return policy. You can see specific information per item in Your Orders. If the item you purchased from Amazon.com is returnable, you'll see a message saying so when you select Return or Replace Item in Your Orders.

Why is there no refund option on Shopee?

The Return/Refund button will be greyed out for the time being. You can check your parcel's expected delivery date at the top of your Order Details page. The Return/Refund option will be made available when: Expected delivery date has passed, but you have yet to receive your parcel.

How do I return something without a receipt?

If you don't have a receipt, try to make the return within 30 days and the company may be able to find your purchase in its system if you used a debit or credit card for the transaction.


1 Answers

First, let’s take a look at what lifetime is actually expected. There is an implicit lifetime in the signature of description:

fn description(&self) -> &str
// Can be rewritten as
fn description<'a>(&'a self) -> &'a str

The returned pointer must be valid for at least as long as self. Now consider s. It will hold a String, an owned string, and it goes out of scope at the end of the function. It would be invalid to return &s, because s is gone when the function returns. trim returns a string slice that borrows s, but the slice is again only valid for as long as s is.

You need to return a string slice that outlives the method call, so this rules out anything on the stack. If you were free to choose the return type, a solution would be to move the string out of the function. For that an owned string would be required, and then the return type would be String, not &str. Unfortunately, you are not free to choose the return type here.

To return a string slice that outlives the method call, I see two options:

  1. Use a &'static string slice. This will certainly outlive the call, but it requires that the string be known at compile time. String literals have type &'static str. This is a suitable option if the description does not contain any dynamic data.

  2. Store an owned string in LexicalError itself. This ensures that you can return a pointer to it that is valid for the entire lifetime of self. You can add a field desc: String to LexicalError and do the formatting when the error is constructed. Then the method would be implemented as

    fn description(&self) -> &str {
        &self.desc
    }
    

    For re-use, you can make Display write the same string.

According to the documentation of Error, Display may be used to provide additional detail. If you wish to include dynamic data in the error, then Display is a great place to format it, but you can omit it for description. This would allow the first approach to be used.

like image 75
Ruud Avatar answered Nov 03 '22 10:11

Ruud