How to convert a String into a &'static str

Rust

Rust Problem Overview


How do I convert a String into a &str? More specifically, I would like to convert it into a str with the static lifetime (&'static str).

Rust Solutions


Solution 1 - Rust

Updated for Rust 1.0

You cannot obtain &'static str from a String because Strings may not live for the entire life of your program, and that's what &'static lifetime means. You can only get a slice parameterized by String own lifetime from it.

To go from a String to a slice &'a str you can use slicing syntax:

let s: String = "abcdefg".to_owned();
let s_slice: &str = &s[..];  // take a full slice of the string

Alternatively, you can use the fact that String implements Deref<Target=str> and perform an explicit reborrowing:

let s_slice: &str = &*s;  // s  : String 
                          // *s : str (via Deref<Target=str>)
                          // &*s: &str

There is even another way which allows for even more concise syntax but it can only be used if the compiler is able to determine the desired target type (e.g. in function arguments or explicitly typed variable bindings). It is called deref coercion and it allows using just & operator, and the compiler will automatically insert an appropriate amount of *s based on the context:

let s_slice: &str = &s;  // okay

fn take_name(name: &str) { ... }
take_name(&s);           // okay as well

let not_correct = &s;    // this will give &String, not &str,
                         // because the compiler does not know
                         // that you want a &str

Note that this pattern is not unique for String/&str - you can use it with every pair of types which are connected through Deref, for example, with CString/CStr and OsString/OsStr from std::ffi module or PathBuf/Path from std::path module.

Solution 2 - Rust

You can do it, but it involves leaking the memory of the String. This is not something you should do lightly. By leaking the memory of the String, we guarantee that the memory will never be freed (thus the leak). Therefore, any references to the inner object can be interpreted as having the 'static lifetime.

fn string_to_static_str(s: String) -> &'static str {
    Box::leak(s.into_boxed_str())
}
 
fn main() {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).unwrap();
    let s: &'static str = string_to_static_str(s);
}

Solution 3 - Rust

As of Rust version 1.26, it is possible to convert a String to &'static str without using unsafe code:

fn string_to_static_str(s: String) -> &'static str {
    Box::leak(s.into_boxed_str())
}

This converts the String instance into a boxed str and immediately leaks it. This frees all excess capacity the string may currently occupy.

Note that there are almost always solutions that are preferable over leaking objects, e.g. using the crossbeam crate if you want to share state between threads.

Solution 4 - Rust

TL;DR: you can get a &'static str from a String which itself has a 'static lifetime.

Although the other answers are correct and most useful, there's a (not so useful) edge case, where you can indeed convert a String to a &'static str:

The lifetime of a reference must always be shorter or equal to the lifetime of the referenced object. I.e. the referenced object has to live longer (or equal long) than the reference. Since 'static means the entire lifetime of a program, a longer lifetime does not exist. But an equal lifetime will be sufficient. So if a String has a lifetime of 'static, you can get a &'static str reference from it.

Creating a static of type String has theoretically become possible with Rust 1.31 when the const fn feature was released. Unfortunately, the only const function returning a String is String::new() currently, and it's still behind a feature gate (so Rust nightly is required for now).

So the following code does the desired conversion (using nightly) ...and actually has no practical use except for completeness of showing that it is possible in this edge case.

#![feature(const_string_new)]

static MY_STRING: String = String::new();

fn do_something(_: &'static str) {
    // ...
}

fn main() {
    do_something(&MY_STRING);
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionChristophView Question on Stackoverflow
Solution 1 - RustVladimir MatveevView Answer on Stackoverflow
Solution 2 - Rustoli_obkView Answer on Stackoverflow
Solution 3 - RustSven MarnachView Answer on Stackoverflow
Solution 4 - RustZargonyView Answer on Stackoverflow