Contamination of &str and return - how to?


#1

A bit hard to explain, but I have a trait I’m implementing for my class, which is

    trait Parse{
      parse_functionDefinition<'input>(input: &'input str,
                 state: &mut ParseState, pos: usize) -> RuleResult<(), &str> 
    }

The trait is not defined by me so I can’t change the signiture. In my implementation I do something in the lines:

    let var = some_other_func(input);
    match var{
         Ok(id) => Ok(()),
         Err(var) => Err(var + " - variable undefined") 
    }

Obviously this gives a compile error since var does not live long enough. My question is since the Err must take a &str and what my function returns is Result<usize, String>, is there anyway that I can achieve what I intend, or there is nothing?


#2

Stealing from my own SO answer from a similar question:

If the trait says &str, there’s nothing for it: you cannot return a String.


Edit: … without doing evil things like leaking memory or diving into unsafe code, but seriously, don’t do that. Just return "variable undefined" if you can’t change the trait itself.

Edit 2: And I mean, who uses &str as an error type? Sadists, that’s who. At least use Cow<str>!


#3

I know, its part of a parser package, I might actually try to edit the code maybe in order to change this. For instance I think its ok the parser to keep the source as &str, but no idea why it was decided for the errors (my guess is since he has only 'static &str as error messages he just kept it simple. Never the less, I do not want to go to any unsafe code, since I prefer to mitigate any mistakes of my own. But thanks for the answer at least I’m sure that this is impossible.

EDIT: Aparently, he is using that because he has a HashSet with all of the “expected” future options and since str has no known size at compile time, there is no way with it. So I might need to change to String in the end.


#4

Technically it is possible to cast a String to &'static str, by leaking the underlying buffer:

use std::mem;

fn leak_string(buf: String) -> &'static str {
    let ptr = &*buf as *const str;
    // *Don't* deallocate the original String
    mem::forget(buf);
    // Since the buffer is never deallocated, it's safe to return a reference to it
    unsafe { mem::transmute::<*const str, &'static str>(ptr) }
}

It’s not a common thing to do though.