mirror of
https://github.com/Dhghomon/easy_rust
synced 2024-11-15 18:13:23 +00:00
561 lines
33 KiB
HTML
561 lines
33 KiB
HTML
<!DOCTYPE HTML>
|
|
<html lang="en" class="sidebar-visible no-js light">
|
|
<head>
|
|
<!-- Book generated using mdBook -->
|
|
<meta charset="UTF-8">
|
|
<title> Lifetimes - Easy Rust</title>
|
|
|
|
|
|
|
|
|
|
<!-- Custom HTML head -->
|
|
|
|
|
|
|
|
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
|
<meta name="description" content="">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<meta name="theme-color" content="#ffffff" />
|
|
|
|
|
|
<link rel="icon" href="favicon.svg">
|
|
|
|
|
|
<link rel="shortcut icon" href="favicon.png">
|
|
|
|
<link rel="stylesheet" href="css/variables.css">
|
|
<link rel="stylesheet" href="css/general.css">
|
|
<link rel="stylesheet" href="css/chrome.css">
|
|
|
|
<link rel="stylesheet" href="css/print.css" media="print">
|
|
|
|
|
|
<!-- Fonts -->
|
|
<link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
|
|
|
|
<link rel="stylesheet" href="fonts/fonts.css">
|
|
|
|
|
|
<!-- Highlight.js Stylesheets -->
|
|
<link rel="stylesheet" href="highlight.css">
|
|
<link rel="stylesheet" href="tomorrow-night.css">
|
|
<link rel="stylesheet" href="ayu-highlight.css">
|
|
|
|
<!-- Custom theme stylesheets -->
|
|
|
|
|
|
|
|
</head>
|
|
<body>
|
|
<!-- Provide site root to javascript -->
|
|
<script type="text/javascript">
|
|
var path_to_root = "";
|
|
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light";
|
|
</script>
|
|
|
|
<!-- Work around some values being stored in localStorage wrapped in quotes -->
|
|
<script type="text/javascript">
|
|
try {
|
|
var theme = localStorage.getItem('mdbook-theme');
|
|
var sidebar = localStorage.getItem('mdbook-sidebar');
|
|
|
|
if (theme.startsWith('"') && theme.endsWith('"')) {
|
|
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
|
|
}
|
|
|
|
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
|
|
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
|
|
}
|
|
} catch (e) { }
|
|
</script>
|
|
|
|
<!-- Set the theme before any content is loaded, prevents flash -->
|
|
<script type="text/javascript">
|
|
var theme;
|
|
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
|
|
if (theme === null || theme === undefined) { theme = default_theme; }
|
|
var html = document.querySelector('html');
|
|
html.classList.remove('no-js')
|
|
html.classList.remove('light')
|
|
html.classList.add(theme);
|
|
html.classList.add('js');
|
|
</script>
|
|
|
|
<!-- Hide / unhide sidebar before it is displayed -->
|
|
<script type="text/javascript">
|
|
var html = document.querySelector('html');
|
|
var sidebar = 'hidden';
|
|
if (document.body.clientWidth >= 1080) {
|
|
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
|
|
sidebar = sidebar || 'visible';
|
|
}
|
|
html.classList.remove('sidebar-visible');
|
|
html.classList.add("sidebar-" + sidebar);
|
|
</script>
|
|
|
|
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
|
<div class="sidebar-scrollbox">
|
|
<ol class="chapter"><li class="chapter-item expanded "><a href="Chapter_0.html"><strong aria-hidden="true">1.</strong> Updates</a></li><li class="chapter-item expanded "><a href="Chapter_1.html"><strong aria-hidden="true">2.</strong> Introduction</a></li><li class="chapter-item expanded "><a href="Chapter_2.html"><strong aria-hidden="true">3.</strong> Who am I?</a></li><li class="chapter-item expanded "><a href="Chapter_3.html"><strong aria-hidden="true">4.</strong> Writing Rust in Easy English</a></li><li class="chapter-item expanded "><a href="Chapter_4.html"><strong aria-hidden="true">5.</strong> Rust Playground</a></li><li class="chapter-item expanded "><a href="Chapter_5.html"><strong aria-hidden="true">6.</strong> 🚧 and ⚠️</a></li><li class="chapter-item expanded "><a href="Chapter_6.html"><strong aria-hidden="true">7.</strong> Comments</a></li><li class="chapter-item expanded "><a href="Chapter_7.html"><strong aria-hidden="true">8.</strong> Types</a></li><li class="chapter-item expanded "><a href="Chapter_8.html"><strong aria-hidden="true">9.</strong> Type inference</a></li><li class="chapter-item expanded "><a href="Chapter_9.html"><strong aria-hidden="true">10.</strong> Printing 'hello, world!'</a></li><li class="chapter-item expanded "><a href="Chapter_10.html"><strong aria-hidden="true">11.</strong> Display and debug</a></li><li class="chapter-item expanded "><a href="Chapter_11.html"><strong aria-hidden="true">12.</strong> Mutability (changing)</a></li><li class="chapter-item expanded "><a href="Chapter_12.html"><strong aria-hidden="true">13.</strong> The stack, the heap, and pointers</a></li><li class="chapter-item expanded "><a href="Chapter_13.html"><strong aria-hidden="true">14.</strong> More about printing</a></li><li class="chapter-item expanded "><a href="Chapter_14.html"><strong aria-hidden="true">15.</strong> Strings</a></li><li class="chapter-item expanded "><a href="Chapter_15.html"><strong aria-hidden="true">16.</strong> const and static</a></li><li class="chapter-item expanded "><a href="Chapter_16.html"><strong aria-hidden="true">17.</strong> More on references</a></li><li class="chapter-item expanded "><a href="Chapter_17.html"><strong aria-hidden="true">18.</strong> Mutable references</a></li><li class="chapter-item expanded "><a href="Chapter_18.html"><strong aria-hidden="true">19.</strong> Giving references to functions</a></li><li class="chapter-item expanded "><a href="Chapter_19.html"><strong aria-hidden="true">20.</strong> Copy types</a></li><li class="chapter-item expanded "><a href="Chapter_20.html"><strong aria-hidden="true">21.</strong> Collection types</a></li><li class="chapter-item expanded "><a href="Chapter_21.html"><strong aria-hidden="true">22.</strong> Vectors</a></li><li class="chapter-item expanded "><a href="Chapter_22.html"><strong aria-hidden="true">23.</strong> Tuples</a></li><li class="chapter-item expanded "><a href="Chapter_23.html"><strong aria-hidden="true">24.</strong> Control flow</a></li><li class="chapter-item expanded "><a href="Chapter_24.html"><strong aria-hidden="true">25.</strong> Structs</a></li><li class="chapter-item expanded "><a href="Chapter_25.html"><strong aria-hidden="true">26.</strong> Enums</a></li><li class="chapter-item expanded "><a href="Chapter_26.html"><strong aria-hidden="true">27.</strong> Loops</a></li><li class="chapter-item expanded "><a href="Chapter_27.html"><strong aria-hidden="true">28.</strong> Implementing structs and enums</a></li><li class="chapter-item expanded "><a href="Chapter_28.html"><strong aria-hidden="true">29.</strong> Destructuring</a></li><li class="chapter-item expanded "><a href="Chapter_29.html"><strong aria-hidden="true">30.</strong> References and the dot operator</a></li><li class="chapter-item expanded "><a href="Chapter_30.html"><strong aria-hidden="true">31.</strong> Generics</a></li><li class="chapter-item expanded "><a href="Chapter_31.html"><strong aria-hidden="true">32.</strong> Option and Result</a></li><li class="chapter-item expanded "><a href="Chapter_32.html"><strong aria-hidden="true">33.</strong> Other collections</a></li><li class="chapter-item expanded "><a href="Chapter_33.html"><strong aria-hidden="true">34.</strong> The ? operator</a></li><li class="chapter-item expanded "><a href="Chapter_34.html"><strong aria-hidden="true">35.</strong> Traits</a></li><li class="chapter-item expanded "><a href="Chapter_35.html"><strong aria-hidden="true">36.</strong> Chaining methods</a></li><li class="chapter-item expanded "><a href="Chapter_36.html"><strong aria-hidden="true">37.</strong> Iterators</a></li><li class="chapter-item expanded "><a href="Chapter_37.html"><strong aria-hidden="true">38.</strong> Closures</a></li><li class="chapter-item expanded "><a href="Chapter_38.html"><strong aria-hidden="true">39.</strong> The dbg! macro and .inspect</a></li><li class="chapter-item expanded "><a href="Chapter_39.html"><strong aria-hidden="true">40.</strong> Types of &str</a></li><li class="chapter-item expanded "><a href="Chapter_40.html" class="active"><strong aria-hidden="true">41.</strong> Lifetimes</a></li><li class="chapter-item expanded "><a href="Chapter_41.html"><strong aria-hidden="true">42.</strong> Interior mutability</a></li><li class="chapter-item expanded "><a href="Chapter_42.html"><strong aria-hidden="true">43.</strong> Cow</a></li><li class="chapter-item expanded "><a href="Chapter_43.html"><strong aria-hidden="true">44.</strong> Type aliases</a></li><li class="chapter-item expanded "><a href="Chapter_44.html"><strong aria-hidden="true">45.</strong> The todo! macro</a></li><li class="chapter-item expanded "><a href="Chapter_45.html"><strong aria-hidden="true">46.</strong> Rc</a></li><li class="chapter-item expanded "><a href="Chapter_46.html"><strong aria-hidden="true">47.</strong> Multiple threads</a></li><li class="chapter-item expanded "><a href="Chapter_47.html"><strong aria-hidden="true">48.</strong> Closures in functions</a></li><li class="chapter-item expanded "><a href="Chapter_48.html"><strong aria-hidden="true">49.</strong> impl Trait</a></li><li class="chapter-item expanded "><a href="Chapter_49.html"><strong aria-hidden="true">50.</strong> Arc</a></li><li class="chapter-item expanded "><a href="Chapter_50.html"><strong aria-hidden="true">51.</strong> Channels</a></li><li class="chapter-item expanded "><a href="Chapter_51.html"><strong aria-hidden="true">52.</strong> Reading Rust documentation</a></li><li class="chapter-item expanded "><a href="Chapter_52.html"><strong aria-hidden="true">53.</strong> Attributes</a></li><li class="chapter-item expanded "><a href="Chapter_53.html"><strong aria-hidden="true">54.</strong> Box</a></li><li class="chapter-item expanded "><a href="Chapter_54.html"><strong aria-hidden="true">55.</strong> Box around traits</a></li><li class="chapter-item expanded "><a href="Chapter_55.html"><strong aria-hidden="true">56.</strong> Default and the builder pattern</a></li><li class="chapter-item expanded "><a href="Chapter_56.html"><strong aria-hidden="true">57.</strong> Deref and DerefMut</a></li><li class="chapter-item expanded "><a href="Chapter_57.html"><strong aria-hidden="true">58.</strong> Crates and modules</a></li><li class="chapter-item expanded "><a href="Chapter_58.html"><strong aria-hidden="true">59.</strong> Testing</a></li><li class="chapter-item expanded "><a href="Chapter_59.html"><strong aria-hidden="true">60.</strong> External crates</a></li><li class="chapter-item expanded "><a href="Chapter_60.html"><strong aria-hidden="true">61.</strong> A tour of the standard library</a></li><li class="chapter-item expanded "><a href="Chapter_61.html"><strong aria-hidden="true">62.</strong> Writing macros</a></li><li class="chapter-item expanded "><a href="Chapter_62.html"><strong aria-hidden="true">63.</strong> cargo</a></li><li class="chapter-item expanded "><a href="Chapter_63.html"><strong aria-hidden="true">64.</strong> Taking user input</a></li><li class="chapter-item expanded "><a href="Chapter_64.html"><strong aria-hidden="true">65.</strong> Using files</a></li><li class="chapter-item expanded "><a href="Chapter_65.html"><strong aria-hidden="true">66.</strong> cargo doc</a></li><li class="chapter-item expanded "><a href="Chapter_66.html"><strong aria-hidden="true">67.</strong> The end?</a></li></ol>
|
|
</div>
|
|
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
|
|
</nav>
|
|
|
|
<div id="page-wrapper" class="page-wrapper">
|
|
|
|
<div class="page">
|
|
|
|
<div id="menu-bar-hover-placeholder"></div>
|
|
<div id="menu-bar" class="menu-bar sticky bordered">
|
|
<div class="left-buttons">
|
|
<button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
|
|
<i class="fa fa-bars"></i>
|
|
</button>
|
|
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
|
|
<i class="fa fa-paint-brush"></i>
|
|
</button>
|
|
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
|
|
<li role="none"><button role="menuitem" class="theme" id="light">Light (default)</button></li>
|
|
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
|
|
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
|
|
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
|
|
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
|
|
</ul>
|
|
|
|
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
|
|
<i class="fa fa-search"></i>
|
|
</button>
|
|
|
|
</div>
|
|
|
|
<h1 class="menu-title">Easy Rust</h1>
|
|
|
|
<div class="right-buttons">
|
|
|
|
<a href="print.html" title="Print this book" aria-label="Print this book">
|
|
<i id="print-button" class="fa fa-print"></i>
|
|
</a>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<div id="search-wrapper" class="hidden">
|
|
<form id="searchbar-outer" class="searchbar-outer">
|
|
<input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
|
|
</form>
|
|
<div id="searchresults-outer" class="searchresults-outer hidden">
|
|
<div id="searchresults-header" class="searchresults-header"></div>
|
|
<ul id="searchresults">
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
|
|
<script type="text/javascript">
|
|
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
|
|
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
|
|
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
|
|
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
|
|
});
|
|
</script>
|
|
|
|
<div id="content" class="content">
|
|
<main>
|
|
<h2 id="lifetimes"><a class="header" href="#lifetimes">Lifetimes</a></h2>
|
|
<p>A lifetime means "how long the variable lives". You only need to think about lifetimes with references. This is because references can't live longer than the object they come from. For example, this function does not work:</p>
|
|
<pre><pre class="playground"><code class="language-rust">fn returns_reference() -> &str {
|
|
let my_string = String::from("I am a string");
|
|
&my_string // ⚠️
|
|
}
|
|
|
|
fn main() {}
|
|
</code></pre></pre>
|
|
<p>The problem is that <code>my_string</code> only lives inside <code>returns_reference</code>. We try to return <code>&my_string</code>, but <code>&my_string</code> can't exist without <code>my_string</code>. So the compiler says no.</p>
|
|
<p>This code also doesn't work:</p>
|
|
<pre><pre class="playground"><code class="language-rust">fn returns_str() -> &str {
|
|
let my_string = String::from("I am a string");
|
|
"I am a str" // ⚠️
|
|
}
|
|
|
|
fn main() {
|
|
let my_str = returns_str();
|
|
println!("{}", my_str);
|
|
}
|
|
</code></pre></pre>
|
|
<p>But it almost works. The compiler says:</p>
|
|
<pre><code class="language-text">error[E0106]: missing lifetime specifier
|
|
--> src\main.rs:6:21
|
|
|
|
|
6 | fn returns_str() -> &str {
|
|
| ^ expected named lifetime parameter
|
|
|
|
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
|
|
help: consider using the `'static` lifetime
|
|
|
|
|
6 | fn returns_str() -> &'static str {
|
|
| ^^^^^^^^
|
|
</code></pre>
|
|
<p><code>missing lifetime specifier</code> means that we need to add a <code>'</code> with the lifetime. Then it says that it <code>contains a borrowed value, but there is no value for it to be borrowed from</code>. That means that <code>I am a str</code> isn't borrowed from anything. It says <code>consider using the 'static lifetime</code> by writing <code>&'static str</code>. So it thinks we should try saying that this is a string literal.</p>
|
|
<p>Now it works:</p>
|
|
<pre><pre class="playground"><code class="language-rust">fn returns_str() -> &'static str {
|
|
let my_string = String::from("I am a string");
|
|
"I am a str"
|
|
}
|
|
|
|
fn main() {
|
|
let my_str = returns_str();
|
|
println!("{}", my_str);
|
|
}
|
|
</code></pre></pre>
|
|
<p>That's because we returned a <code>&str</code> with a lifetime of <code>static</code>. Meanwhile, <code>my_string</code> can only be returned as a <code>String</code>: we can't return a reference to it because it is going to die in the next line.</p>
|
|
<p>So now <code>fn returns_str() -> &'static str</code> tells Rust: "don't worry, we will only return a string literal". String literals live for the whole program, so Rust is happy. You'll notice that this is similar to generics. When we tell the compiler something like <code><T: Display></code>, we promise that we will only use inputs with <code>Display</code>. Lifetimes are similar: we are not changing any variable lifetimes. We are just telling the compiler what the lifetimes of the inputs will be.</p>
|
|
<p>But <code>'static</code> is not the only lifetime. Actually, every variable has a lifetime, but usually we don't have to write it. The compiler is pretty smart and can usually figure out for itself. We only have to write the lifetime when the compiler doesn't know.</p>
|
|
<p>Here is an example of another lifetime. Imagine we want to create a <code>City</code> struct and give it a <code>&str</code> for the name. We might want to do that because it gives faster performance than with <code>String</code>. So we write it like this, but it won't work yet:</p>
|
|
<pre><pre class="playground"><code class="language-rust">#[derive(Debug)]
|
|
struct City {
|
|
name: &str, // ⚠️
|
|
date_founded: u32,
|
|
}
|
|
|
|
fn main() {
|
|
let my_city = City {
|
|
name: "Ichinomiya",
|
|
date_founded: 1921,
|
|
};
|
|
}
|
|
</code></pre></pre>
|
|
<p>The compiler says:</p>
|
|
<pre><code class="language-text">error[E0106]: missing lifetime specifier
|
|
--> src\main.rs:3:11
|
|
|
|
|
3 | name: &str,
|
|
| ^ expected named lifetime parameter
|
|
|
|
|
help: consider introducing a named lifetime parameter
|
|
|
|
|
2 | struct City<'a> {
|
|
3 | name: &'a str,
|
|
|
|
|
</code></pre>
|
|
<p>Rust needs a lifetime for <code>&str</code> because <code>&str</code> is a reference. What happens when the value that <code>name</code> points to is dropped? That would be unsafe.</p>
|
|
<p>What about <code>'static</code>, will that work? We used it before. Let's try:</p>
|
|
<pre><pre class="playground"><code class="language-rust">#[derive(Debug)]
|
|
struct City {
|
|
name: &'static str, // change &str to &'static str
|
|
date_founded: u32,
|
|
}
|
|
|
|
fn main() {
|
|
let my_city = City {
|
|
name: "Ichinomiya",
|
|
date_founded: 1921,
|
|
};
|
|
|
|
println!("{} was founded in {}", my_city.name, my_city.date_founded);
|
|
}
|
|
</code></pre></pre>
|
|
<p>Okay, that works. And maybe this is what you wanted for the struct. However, note that we can only take "string literals", so not references to something else. So this will not work:</p>
|
|
<pre><pre class="playground"><code class="language-rust">#[derive(Debug)]
|
|
struct City {
|
|
name: &'static str, // must live for the whole program
|
|
date_founded: u32,
|
|
}
|
|
|
|
fn main() {
|
|
let city_names = vec!["Ichinomiya".to_string(), "Kurume".to_string()]; // city_names does not live for the whole program
|
|
|
|
let my_city = City {
|
|
name: &city_names[0], // ⚠️ This is a &str, but not a &'static str. It is a reference to a value inside city_names
|
|
date_founded: 1921,
|
|
};
|
|
|
|
println!("{} was founded in {}", my_city.name, my_city.date_founded);
|
|
}
|
|
</code></pre></pre>
|
|
<p>The compiler says:</p>
|
|
<pre><code class="language-text">error[E0597]: `city_names` does not live long enough
|
|
--> src\main.rs:12:16
|
|
|
|
|
12 | name: &city_names[0],
|
|
| ^^^^^^^^^^
|
|
| |
|
|
| borrowed value does not live long enough
|
|
| requires that `city_names` is borrowed for `'static`
|
|
...
|
|
18 | }
|
|
| - `city_names` dropped here while still borrowed
|
|
</code></pre>
|
|
<p>This is important to understand, because the reference we gave it actually lives long enough. But we promised that we would only give it a <code>&'static str</code>, and that is the problem.</p>
|
|
<p>So now we will try what the compiler suggested before. It said to try writing <code>struct City<'a></code> and <code>name: &'a str</code>. This means that it will only take a reference for <code>name</code> if it lives as long as <code>City</code>.</p>
|
|
<pre><pre class="playground"><code class="language-rust">#[derive(Debug)]
|
|
struct City<'a> { // City has lifetime 'a
|
|
name: &'a str, // and name also has lifetime 'a.
|
|
date_founded: u32,
|
|
}
|
|
|
|
fn main() {
|
|
let city_names = vec!["Ichinomiya".to_string(), "Kurume".to_string()];
|
|
|
|
let my_city = City {
|
|
name: &city_names[0],
|
|
date_founded: 1921,
|
|
};
|
|
|
|
println!("{} was founded in {}", my_city.name, my_city.date_founded);
|
|
}
|
|
</code></pre></pre>
|
|
<p>Also remember that you can write anything instead of <code>'a</code> if you want. This is also similar to generics where we write <code>T</code> and <code>U</code> but can actually write anything.</p>
|
|
<pre><pre class="playground"><code class="language-rust">#[derive(Debug)]
|
|
struct City<'city> { // The lifetime is now called 'city
|
|
name: &'city str, // and name has the 'city lifetime
|
|
date_founded: u32,
|
|
}
|
|
|
|
fn main() {}
|
|
</code></pre></pre>
|
|
<p>So usually you will write <code>'a, 'b, 'c</code> etc. because it is quick and the usual way to write. But you can always change it if you want. One good tip is that changing the lifetime to a "human-readable" name can help you read code if it is very complicated.</p>
|
|
<p>Let's look at the comparison to traits for generics again. For example:</p>
|
|
<pre><pre class="playground"><code class="language-rust">use std::fmt::Display;
|
|
|
|
fn prints<T: Display>(input: T) {
|
|
println!("T is {}", input);
|
|
}
|
|
|
|
fn main() {}
|
|
</code></pre></pre>
|
|
<p>When you write <code>T: Display</code>, it means "please only take T if it has Display".
|
|
It does not mean: "I am giving Display to T".</p>
|
|
<p>The same is true for lifetimes. When you write 'a here:</p>
|
|
<pre><pre class="playground"><code class="language-rust">#[derive(Debug)]
|
|
struct City<'a> {
|
|
name: &'a str,
|
|
date_founded: u32,
|
|
}
|
|
|
|
fn main() {}
|
|
</code></pre></pre>
|
|
<p>It means "please only take an input for <code>name</code> if it lives at least as long as <code>City</code>".
|
|
It does not mean: "I will make the input for <code>name</code> live as long as <code>City</code>".</p>
|
|
<p>Now we can learn about <code><'_></code> that we saw before. This is called the "anonymous lifetime" and is an indicator that references are being used. Rust will suggest it to you when you are implementing structs, for example. Here is one struct that almost works, but not yet:</p>
|
|
<pre><pre class="playground"><code class="language-rust"> // ⚠️
|
|
struct Adventurer<'a> {
|
|
name: &'a str,
|
|
hit_points: u32,
|
|
}
|
|
|
|
impl Adventurer {
|
|
fn take_damage(&mut self) {
|
|
self.hit_points -= 20;
|
|
println!("{} has {} hit points left!", self.name, self.hit_points);
|
|
}
|
|
}
|
|
|
|
fn main() {}
|
|
</code></pre></pre>
|
|
<p>So we did what we needed to do for the <code>struct</code>: first we said that <code>name</code> comes from a <code>&str</code>. That means we need a lifetime, so we gave it <code><'a></code>. Then we had to do the same for the <code>struct</code> to show that they are at least as long as this lifetime. But then Rust tells us to do this:</p>
|
|
<pre><code class="language-text">error[E0726]: implicit elided lifetime not allowed here
|
|
--> src\main.rs:6:6
|
|
|
|
|
6 | impl Adventurer {
|
|
| ^^^^^^^^^^- help: indicate the anonymous lifetime: `<'_>`
|
|
</code></pre>
|
|
<p>It wants us to add that anonymous lifetime to show that there is a reference being used. So if we write that, it will be happy:</p>
|
|
<pre><pre class="playground"><code class="language-rust">struct Adventurer<'a> {
|
|
name: &'a str,
|
|
hit_points: u32,
|
|
}
|
|
|
|
impl Adventurer<'_> {
|
|
fn take_damage(&mut self) {
|
|
self.hit_points -= 20;
|
|
println!("{} has {} hit points left!", self.name, self.hit_points);
|
|
}
|
|
}
|
|
|
|
fn main() {}
|
|
</code></pre></pre>
|
|
<p>This lifetime was made so that you don't always have to write things like <code>impl<'a> Adventurer<'a></code>, because the struct already shows the lifetime.</p>
|
|
<p>Lifetimes can be difficult in Rust, but here are some tips to avoid getting too stressed about them:</p>
|
|
<ul>
|
|
<li>You can stay with owned types, use clones etc. if you want to avoid them for the time being.</li>
|
|
<li>Much of the time, when the compiler wants a lifetime you will just end up writing <'a> here and there and then it will work. It's just a way of saying "don't worry, I won't give you anything that doesn't live long enough".</li>
|
|
<li>You can explore lifetimes just a bit at a time. Write some code with owned values, then make one a reference. The compiler will start to complain, but also give some suggestions. And if it gets too complicated, you can undo it and try again next time.</li>
|
|
</ul>
|
|
<p>Let's do this with our code and see what the compiler says. First we'll go back and take the lifetimes out, and also implement <code>Display</code>. <code>Display</code> will just print the <code>Adventurer</code>'s name.</p>
|
|
<pre><pre class="playground"><code class="language-rust">// ⚠️
|
|
struct Adventurer {
|
|
name: &str,
|
|
hit_points: u32,
|
|
}
|
|
|
|
impl Adventurer {
|
|
fn take_damage(&mut self) {
|
|
self.hit_points -= 20;
|
|
println!("{} has {} hit points left!", self.name, self.hit_points);
|
|
}
|
|
}
|
|
|
|
impl std::fmt::Display for Adventurer {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
write!(f, "{} has {} hit points.", self.name, self.hit_points)
|
|
}
|
|
}
|
|
|
|
fn main() {}
|
|
</code></pre></pre>
|
|
<p>First complaint is this:</p>
|
|
<pre><code class="language-text">error[E0106]: missing lifetime specifier
|
|
--> src\main.rs:2:11
|
|
|
|
|
2 | name: &str,
|
|
| ^ expected named lifetime parameter
|
|
|
|
|
help: consider introducing a named lifetime parameter
|
|
|
|
|
1 | struct Adventurer<'a> {
|
|
2 | name: &'a str,
|
|
|
|
|
</code></pre>
|
|
<p>It suggests what to do: <code><'a></code> after Adventurer, and <code>&'a str</code>. So we do that:</p>
|
|
<pre><pre class="playground"><code class="language-rust">// ⚠️
|
|
struct Adventurer<'a> {
|
|
name: &'a str,
|
|
hit_points: u32,
|
|
}
|
|
|
|
impl Adventurer {
|
|
fn take_damage(&mut self) {
|
|
self.hit_points -= 20;
|
|
println!("{} has {} hit points left!", self.name, self.hit_points);
|
|
}
|
|
}
|
|
|
|
impl std::fmt::Display for Adventurer {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
write!(f, "{} has {} hit points.", self.name, self.hit_points)
|
|
}
|
|
}
|
|
|
|
fn main() {}
|
|
</code></pre></pre>
|
|
<p>Now it's happy with those parts, but is wondering about the <code>impl</code> blocks. It wants us to mention that it's using references:</p>
|
|
<pre><code class="language-text">error[E0726]: implicit elided lifetime not allowed here
|
|
--> src\main.rs:6:6
|
|
|
|
|
6 | impl Adventurer {
|
|
| ^^^^^^^^^^- help: indicate the anonymous lifetime: `<'_>`
|
|
|
|
error[E0726]: implicit elided lifetime not allowed here
|
|
--> src\main.rs:12:28
|
|
|
|
|
12 | impl std::fmt::Display for Adventurer {
|
|
| ^^^^^^^^^^- help: indicate the anonymous lifetime: `<'_>`
|
|
</code></pre>
|
|
<p>Okay, so we will write those in...and now it works! Now we can make an <code>Adventurer</code> and do some things with it.</p>
|
|
<pre><pre class="playground"><code class="language-rust">struct Adventurer<'a> {
|
|
name: &'a str,
|
|
hit_points: u32,
|
|
}
|
|
|
|
impl Adventurer<'_> {
|
|
fn take_damage(&mut self) {
|
|
self.hit_points -= 20;
|
|
println!("{} has {} hit points left!", self.name, self.hit_points);
|
|
}
|
|
}
|
|
|
|
impl std::fmt::Display for Adventurer<'_> {
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
write!(f, "{} has {} hit points.", self.name, self.hit_points)
|
|
}
|
|
}
|
|
|
|
fn main() {
|
|
let mut billy = Adventurer {
|
|
name: "Billy",
|
|
hit_points: 100_000,
|
|
};
|
|
println!("{}", billy);
|
|
billy.take_damage();
|
|
}
|
|
</code></pre></pre>
|
|
<p>This prints:</p>
|
|
<pre><code class="language-text">Billy has 100000 hit points.
|
|
Billy has 99980 hit points left!
|
|
</code></pre>
|
|
<p>So you can see that lifetimes are often just the compiler wanting to make sure. And it is usually smart enough to almost guess at what lifetimes you want, and just needs you to tell it so it can be certain.</p>
|
|
|
|
</main>
|
|
|
|
<nav class="nav-wrapper" aria-label="Page navigation">
|
|
<!-- Mobile navigation buttons -->
|
|
|
|
<a rel="prev" href="Chapter_39.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
|
<i class="fa fa-angle-left"></i>
|
|
</a>
|
|
|
|
|
|
|
|
<a rel="next" href="Chapter_41.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
|
<i class="fa fa-angle-right"></i>
|
|
</a>
|
|
|
|
|
|
<div style="clear: both"></div>
|
|
</nav>
|
|
</div>
|
|
</div>
|
|
|
|
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
|
|
|
<a rel="prev" href="Chapter_39.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
|
<i class="fa fa-angle-left"></i>
|
|
</a>
|
|
|
|
|
|
|
|
<a rel="next" href="Chapter_41.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
|
<i class="fa fa-angle-right"></i>
|
|
</a>
|
|
|
|
</nav>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<script type="text/javascript">
|
|
window.playground_copyable = true;
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<script src="elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
|
|
<script src="mark.min.js" type="text/javascript" charset="utf-8"></script>
|
|
<script src="searcher.js" type="text/javascript" charset="utf-8"></script>
|
|
|
|
|
|
<script src="clipboard.min.js" type="text/javascript" charset="utf-8"></script>
|
|
<script src="highlight.js" type="text/javascript" charset="utf-8"></script>
|
|
<script src="book.js" type="text/javascript" charset="utf-8"></script>
|
|
|
|
<!-- Custom JS scripts -->
|
|
|
|
|
|
|
|
|
|
</body>
|
|
</html>
|