Question
I want to convert a Rust String into a &str. More specifically, I need to understand whether it can be converted into a string slice with the 'static lifetime, written as &'static str.
For example, I am trying to work with owned string data and then use it where a static string slice is expected. What is the correct way to do this in Rust, and what are the limitations?
let s: String = String::from("hello");
// How can this become &str?
// Can it become &'static str?
Short Answer
By the end of this page, you will understand the difference between String, &str, and &'static str in Rust, why a normal String cannot usually become &'static str, and what safe alternatives to use. You will also see when borrowing is enough, when leaking memory is technically possible, and how real Rust code usually handles this situation.
Concept
String and &str are closely related in Rust, but they are not the same type.
Stringis an owned, growable string stored on the heap.&stris a borrowed view into string data.&'static stris a borrowed string slice that is guaranteed to live for the entire duration of the program.
A String can easily be borrowed as a &str because the String owns the text data.
let s = String::from("hello");
let slice: &str = &s;
This works because slice only borrows from s, and s is still alive.
The important part is the lifetime. A borrowed &str can only live as long as the data it points to. Since a normal String is dropped when it goes out of scope, any borrowed from it also becomes invalid at that point.
Mental Model
Think of a String as a notebook that you own.
A &str is like letting someone read a page from your notebook. They can read it only while your notebook still exists.
A &'static str is like text carved into stone in a public square. It stays there for the entire lifetime of the program.
So:
String= owned notebook&str= borrowed page from the notebook&'static str= permanent inscription
If you create a String at runtime, it is not automatically permanent. Borrowing from it does not make it permanent either. The borrowed slice is still tied to the owner.
Syntax and Examples
Borrowing String as &str
This is the normal conversion:
let s = String::from("hello");
let slice1: &str = &s;
let slice2: &str = s.as_str();
println!("{} {}", slice1, slice2);
Both &s and s.as_str() give you a &str view into the string.
Why this is not &'static str
fn make_str() -> &str {
let s = String::from("hello");
s.as_str()
}
This does not compile, because is dropped when the function ends. Returning a reference to it would create a dangling reference.
Step by Step Execution
Consider this example:
fn main() {
let s = String::from("hello");
let slice = s.as_str();
println!("{}", slice);
}
Step by step:
-
let s = String::from("hello");- A
Stringis created on the heap. - The variable
sowns that heap data.
- A
-
let slice = s.as_str();slicebecomes a&strborrowing the contents ofs.- No new string is allocated.
slicepoints to the same text data owned bys.
-
println!("{}", slice);
Real World Use Cases
Borrow a String as &str
This is common when calling functions that only need read-only access:
fn print_name(name: &str) {
println!("{}", name);
}
let name = String::from("Ava");
print_name(&name);
Accept either String or &str
Many APIs take &str so callers can pass both string literals and borrowed String data.
fn is_empty_text(text: &str) -> bool {
text.trim().is_empty()
}
Use &'static str for fixed messages
Useful for constant labels, error messages, and compile-time text:
Real Codebase Usage
In real Rust projects, developers usually avoid forcing dynamic strings into &'static str.
Common patterns include:
1. Accept &str in function parameters
This is flexible and ergonomic.
fn log_message(msg: &str) {
println!("LOG: {}", msg);
}
Callers can pass:
- string literals
&String- string slices
2. Return String for computed text
If the function builds text dynamically, return ownership.
fn build_path(user: &str) -> String {
format!("/home/{}", user)
}
3. Use &'static str for fixed enums or constants
const APP_NAME: &str = "my_app";
Common Mistakes
Mistake 1: Assuming &str always means 'static
&str does not automatically mean &'static str.
let s = String::from("hello");
let slice: &str = &s; // valid
This slice only lives as long as s does.
Mistake 2: Returning a borrowed slice from a local String
Broken code:
fn bad() -> &str {
let s = String::from("hello");
&s
}
Why it fails:
sis dropped at the end of the function- the returned reference would dangle
Fix: return instead.
Comparisons
| Type | Owns data? | Growable? | Lifetime tied to owner? | Typical use |
|---|---|---|---|---|
String | Yes | Yes | No borrowed lifetime needed | Dynamic text you create or store |
&str | No | No | Yes | Temporary borrowed string view |
&'static str | No | No | Lives for whole program | String literals and fixed messages |
Box<str> | Yes | No | No borrowed lifetime needed | Owned immutable string data |
Cheat Sheet
Quick rules
String->&str: yesString->&'static str: not normally- String literal ->
&'static str: yes as_str()borrows; it does not extend lifetime
Common syntax
let s = String::from("hello");
let a: &str = &s;
let b: &str = s.as_str();
Static string literal
let msg: &'static str = "hello";
Return dynamic text
fn make_text() -> String {
::()
}
FAQ
Can I convert a String to &str in Rust?
Yes. Use &s or s.as_str().
Can I convert a String to &'static str safely?
Not in the normal sense. A runtime String does not live for the entire program, so it cannot naturally become &'static str.
Why do string literals have 'static lifetime?
Because they are stored in the program's compiled binary and exist for the whole runtime of the program.
What does as_str() do?
It returns a borrowed &str view into the String. It does not allocate and does not make the data static.
When should I return String instead of &str?
Return String when the text is created dynamically inside the function.
Is Box::leak a valid way to get ?
Mini Project
Description
Build a small Rust program that formats a user-facing message and demonstrates the difference between borrowed string slices, owned strings, and static string literals. This project is useful because these three forms appear constantly in real Rust programs such as CLI tools, web handlers, and validators.
Goal
Create a program that accepts dynamic text, prints it through functions using &str, returns computed text as String, and returns fixed labels as &'static str.
Requirements
- Write one function that accepts a
&strand prints it. - Write one function that returns a dynamic
Stringusingformat!. - Write one function that returns a fixed
&'static strlabel. - In
main, create aStringand pass it as a&str. - Print the results of all three functions to show the differences clearly.
Keep learning
Related questions
Accessing Cargo Package Metadata in Rust
Learn how to read Cargo package metadata like version, name, and authors in Rust using compile-time environment macros.
Associated Types vs Generic Type Parameters in Rust: When to Use Each
Learn when to use associated types vs generic parameters in Rust traits, with clear rules, examples, and practical API design advice.
Convert an Integer to a String in Rust
Learn the current Rust way to convert integers to strings, why `to_str()` no longer works, and when to use `to_string()` or `format!`.