mirror of
https://github.com/sunface/rust-by-practice.git
synced 2025-08-13 23:14:45 +00:00
deploy
This commit is contained in:
481
lifetime/advance.html
Normal file
481
lifetime/advance.html
Normal file
@@ -0,0 +1,481 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en" class="light sidebar-visible" dir="ltr">
|
||||
<head>
|
||||
<!-- Book generated using mdBook -->
|
||||
<meta charset="UTF-8">
|
||||
<title>advanced - Rust By Practice</title>
|
||||
|
||||
|
||||
<!-- Custom HTML head -->
|
||||
|
||||
<meta name="description" content="Learn Rust with Example, Exercise and real Practice, written with ❤️ by https://course.rs team">
|
||||
<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" id="highlight-css" href="../highlight.css">
|
||||
<link rel="stylesheet" id="tomorrow-night-css" href="../tomorrow-night.css">
|
||||
<link rel="stylesheet" id="ayu-highlight-css" href="../ayu-highlight.css">
|
||||
|
||||
<!-- Custom theme stylesheets -->
|
||||
<link rel="stylesheet" href="../theme/style1.css">
|
||||
|
||||
|
||||
<!-- Provide site root and default themes to javascript -->
|
||||
<script>
|
||||
const path_to_root = "../";
|
||||
const default_light_theme = "light";
|
||||
const default_dark_theme = "navy";
|
||||
</script>
|
||||
<!-- Start loading toc.js asap -->
|
||||
<script src="../toc.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="body-container">
|
||||
<!-- Work around some values being stored in localStorage wrapped in quotes -->
|
||||
<script>
|
||||
try {
|
||||
let theme = localStorage.getItem('mdbook-theme');
|
||||
let 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>
|
||||
const default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? default_dark_theme : default_light_theme;
|
||||
let theme;
|
||||
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
|
||||
if (theme === null || theme === undefined) { theme = default_theme; }
|
||||
const html = document.documentElement;
|
||||
html.classList.remove('light')
|
||||
html.classList.add(theme);
|
||||
html.classList.add("js");
|
||||
</script>
|
||||
|
||||
<input type="checkbox" id="sidebar-toggle-anchor" class="hidden">
|
||||
|
||||
<!-- Hide / unhide sidebar before it is displayed -->
|
||||
<script>
|
||||
let sidebar = null;
|
||||
const sidebar_toggle = document.getElementById("sidebar-toggle-anchor");
|
||||
if (document.body.clientWidth >= 1080) {
|
||||
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
|
||||
sidebar = sidebar || 'visible';
|
||||
} else {
|
||||
sidebar = 'hidden';
|
||||
}
|
||||
sidebar_toggle.checked = sidebar === 'visible';
|
||||
html.classList.remove('sidebar-visible');
|
||||
html.classList.add("sidebar-" + sidebar);
|
||||
</script>
|
||||
|
||||
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
||||
<!-- populated by js -->
|
||||
<mdbook-sidebar-scrollbox class="sidebar-scrollbox"></mdbook-sidebar-scrollbox>
|
||||
<noscript>
|
||||
<iframe class="sidebar-iframe-outer" src="../toc.html"></iframe>
|
||||
</noscript>
|
||||
<div id="sidebar-resize-handle" class="sidebar-resize-handle">
|
||||
<div class="sidebar-resize-indicator"></div>
|
||||
</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">
|
||||
<div class="left-buttons">
|
||||
<label id="sidebar-toggle" class="icon-button" for="sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
|
||||
<i class="fa fa-bars"></i>
|
||||
</label>
|
||||
<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="default_theme">Auto</button></li>
|
||||
<li role="none"><button role="menuitem" class="theme" id="light">Light</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">Rust By Practice</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>
|
||||
<a href="https://github.com/sunface/rust-by-practice" title="Git repository" aria-label="Git repository">
|
||||
<i id="git-repository-button" class="fa fa-github"></i>
|
||||
</a>
|
||||
<a href="https://github.com/sunface/rust-by-practice/edit/master/en/src/lifetime/advance.md" title="Suggest an edit" aria-label="Suggest an edit">
|
||||
<i id="git-edit-button" class="fa fa-edit"></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>
|
||||
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>
|
||||
<h1 id="advance-lifetime"><a class="header" href="#advance-lifetime">Advance lifetime</a></h1>
|
||||
<h2 id="trait-bounds"><a class="header" href="#trait-bounds">Trait Bounds</a></h2>
|
||||
<p>Just like generic types can be bounded, lifetimes can also be bounded as below:</p>
|
||||
<ul>
|
||||
<li><code>T: 'a</code>,all references in <code>T</code> must outlive the lifetime <code>'a</code></li>
|
||||
<li><code>T: Trait + 'a</code>: <code>T</code> must implement trait <code>Trait</code> and all references in <code>T</code> must outlive <code>'a</code></li>
|
||||
</ul>
|
||||
<p><strong>Example</strong></p>
|
||||
<pre><pre class="playground"><code class="language-rust editable edition2021">use std::fmt::Debug; // Trait to bound with.
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Ref<'a, T: 'a>(&'a T);
|
||||
// `Ref` contains a reference to a generic type `T` that has
|
||||
// an unknown lifetime `'a`. `T` is bounded such that any
|
||||
// *references* in `T` must outlive `'a`. Additionally, the lifetime
|
||||
// of `Ref` may not exceed `'a`.
|
||||
|
||||
// A generic function which prints using the `Debug` trait.
|
||||
fn print<T>(t: T) where
|
||||
T: Debug {
|
||||
println!("`print`: t is {:?}", t);
|
||||
}
|
||||
|
||||
// Here a reference to `T` is taken where `T` implements
|
||||
// `Debug` and all *references* in `T` outlive `'a`. In
|
||||
// addition, `'a` must outlive the function.
|
||||
fn print_ref<'a, T>(t: &'a T) where
|
||||
T: Debug + 'a {
|
||||
println!("`print_ref`: t is {:?}", t);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x = 7;
|
||||
let ref_x = Ref(&x);
|
||||
|
||||
print_ref(&ref_x);
|
||||
print(ref_x);
|
||||
}</code></pre></pre>
|
||||
<ol>
|
||||
<li>🌟</li>
|
||||
</ol>
|
||||
<pre><pre class="playground"><code class="language-rust editable edition2021">/* Annotate struct with lifetime:
|
||||
1. `r` and `s` must have different lifetimes
|
||||
2. lifetime of `s` is bigger than that of 'r'
|
||||
*/
|
||||
struct DoubleRef<T> {
|
||||
r: &T,
|
||||
s: &T
|
||||
}
|
||||
fn main() {
|
||||
println!("Success!")
|
||||
}</code></pre></pre>
|
||||
<ol start="2">
|
||||
<li>🌟🌟</li>
|
||||
</ol>
|
||||
<pre><pre class="playground"><code class="language-rust editable edition2021">/* Adding trait bounds to make it work */
|
||||
struct ImportantExcerpt<'a> {
|
||||
part: &'a str,
|
||||
}
|
||||
|
||||
impl<'a, 'b> ImportantExcerpt<'a> {
|
||||
fn announce_and_return_part(&'a self, announcement: &'b str) -> &'b str {
|
||||
println!("Attention please: {}", announcement);
|
||||
self.part
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("Success!")
|
||||
}</code></pre></pre>
|
||||
<ol start="3">
|
||||
<li>🌟🌟</li>
|
||||
</ol>
|
||||
<pre><pre class="playground"><code class="language-rust editable edition2021">/* Adding trait bounds to make it work */
|
||||
fn f<'a, 'b>(x: &'a i32, mut y: &'b i32) {
|
||||
y = x;
|
||||
let r: &'b &'a i32 = &&0;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("Success!")
|
||||
}</code></pre></pre>
|
||||
<h2 id="hrtbhigher-ranked-trait-bounds"><a class="header" href="#hrtbhigher-ranked-trait-bounds">HRTB(Higher-ranked trait bounds)</a></h2>
|
||||
<p>Type bounds may be higher ranked over lifetimes. These bounds specify a bound is true for all lifetimes. For example, a bound such as <code>for<'a> &'a T: PartialEq<i32></code> would require an implementation like:</p>
|
||||
<pre><pre class="playground"><code class="language-rust edition2021"><span class="boring">#![allow(unused)]
|
||||
</span><span class="boring">fn main() {
|
||||
</span>impl<'a> PartialEq<i32> for &'a T {
|
||||
// ...
|
||||
}
|
||||
<span class="boring">}</span></code></pre></pre>
|
||||
<p>and could then be used to compare a <code>&'a T</code> with any lifetime to an <code>i32</code>.</p>
|
||||
<p>Only a higher-ranked bound can be used here, because the lifetime of the reference is shorter than any possible lifetime parameter on the function.</p>
|
||||
<ol start="4">
|
||||
<li>🌟🌟🌟</li>
|
||||
</ol>
|
||||
<pre><pre class="playground"><code class="language-rust editable edition2021">/* Adding HRTB to make it work!*/
|
||||
fn call_on_ref_zero<'a, F>(f: F) where F: Fn(&'a i32) {
|
||||
let zero = 0;
|
||||
f(&zero);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("Success!");
|
||||
}</code></pre></pre>
|
||||
<h2 id="nll-non-lexical-lifetime"><a class="header" href="#nll-non-lexical-lifetime">NLL (Non-Lexical Lifetime)</a></h2>
|
||||
<p>Before explaining NLL, let's see some code first:</p>
|
||||
<pre><pre class="playground"><code class="language-rust edition2021">fn main() {
|
||||
let mut s = String::from("hello");
|
||||
|
||||
let r1 = &s;
|
||||
let r2 = &s;
|
||||
println!("{} and {}", r1, r2);
|
||||
|
||||
let r3 = &mut s;
|
||||
println!("{}", r3);
|
||||
}</code></pre></pre>
|
||||
<p>Based on our current knowledge, this code will cause en error due to violating the borrowing rules in Rust.</p>
|
||||
<p>But if you <code>cargo run</code> it, then everything will be ok, so what's going on here?</p>
|
||||
<p>The ability of the compiler to tell that a reference is no longer used at a point before the end of the scope, is called <strong>Non-Lexical Lifetimes</strong> (<strong>NLL</strong> for short).</p>
|
||||
<p>With this ability the compiler knows when is the last time that a reference is used and optimizing the borrowing rules based on this knowledge.</p>
|
||||
<pre><pre class="playground"><code class="language-rust edition2021"><span class="boring">#![allow(unused)]
|
||||
</span><span class="boring">fn main() {
|
||||
</span>let mut u = 0i32;
|
||||
let mut v = 1i32;
|
||||
let mut w = 2i32;
|
||||
|
||||
// lifetime of `a` = α ∪ β ∪ γ
|
||||
let mut a = &mut u; // --+ α. lifetime of `&mut u` --+ lexical "lifetime" of `&mut u`,`&mut u`, `&mut w` and `a`
|
||||
use(a); // | |
|
||||
*a = 3; // <-----------------+ |
|
||||
... // |
|
||||
a = &mut v; // --+ β. lifetime of `&mut v` |
|
||||
use(a); // | |
|
||||
*a = 4; // <-----------------+ |
|
||||
... // |
|
||||
a = &mut w; // --+ γ. lifetime of `&mut w` |
|
||||
use(a); // | |
|
||||
*a = 5; // <-----------------+ <--------------------------+
|
||||
<span class="boring">}</span></code></pre></pre>
|
||||
<h2 id="reborrow"><a class="header" href="#reborrow">Reborrow</a></h2>
|
||||
<p>After learning NLL, we can easily understand reborrow now.</p>
|
||||
<p><strong>Example</strong></p>
|
||||
<pre><pre class="playground"><code class="language-rust edition2021">#[derive(Debug)]
|
||||
struct Point {
|
||||
x: i32,
|
||||
y: i32,
|
||||
}
|
||||
|
||||
impl Point {
|
||||
fn move_to(&mut self, x: i32, y: i32) {
|
||||
self.x = x;
|
||||
self.y = y;
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut p = Point { x: 0, y: 0 };
|
||||
let r = &mut p;
|
||||
// Here comes the reborrow
|
||||
let rr: &Point = &*r;
|
||||
|
||||
println!("{:?}", rr); // Reborrow ends here, NLL introduced
|
||||
|
||||
// Reborrow is over, we can continue using `r` now
|
||||
r.move_to(10, 10);
|
||||
println!("{:?}", r);
|
||||
}</code></pre></pre>
|
||||
<ol start="5">
|
||||
<li>🌟🌟</li>
|
||||
</ol>
|
||||
<pre><pre class="playground"><code class="language-rust editable edition2021">/* Make it work by reordering some code */
|
||||
fn main() {
|
||||
let mut data = 10;
|
||||
let ref1 = &mut data;
|
||||
let ref2 = &mut *ref1;
|
||||
|
||||
*ref1 += 1;
|
||||
*ref2 += 2;
|
||||
|
||||
println!("{}", data);
|
||||
}</code></pre></pre>
|
||||
<h2 id="unbound-lifetime"><a class="header" href="#unbound-lifetime">Unbound lifetime</a></h2>
|
||||
<p>See more info in <a href="https://doc.rust-lang.org/nomicon/unbounded-lifetimes.html">Nomicon - Unbounded Lifetimes</a>.</p>
|
||||
<h2 id="more-elision-rules"><a class="header" href="#more-elision-rules">More elision rules</a></h2>
|
||||
<pre><pre class="playground"><code class="language-rust edition2021"><span class="boring">#![allow(unused)]
|
||||
</span><span class="boring">fn main() {
|
||||
</span>impl<'a> Reader for BufReader<'a> {
|
||||
// 'a is not used in the following methods
|
||||
}
|
||||
|
||||
// can be written as :
|
||||
impl Reader for BufReader<'_> {
|
||||
|
||||
}
|
||||
<span class="boring">}</span></code></pre></pre>
|
||||
<pre><pre class="playground"><code class="language-rust edition2021"><span class="boring">#![allow(unused)]
|
||||
</span><span class="boring">fn main() {
|
||||
</span>// Rust 2015
|
||||
struct Ref<'a, T: 'a> {
|
||||
field: &'a T
|
||||
}
|
||||
|
||||
// Rust 2018
|
||||
struct Ref<'a, T> {
|
||||
field: &'a T
|
||||
}
|
||||
<span class="boring">}</span></code></pre></pre>
|
||||
<h2 id="a-difficult-exercise"><a class="header" href="#a-difficult-exercise">A difficult exercise</a></h2>
|
||||
<ol start="6">
|
||||
<li>🌟🌟🌟🌟</li>
|
||||
</ol>
|
||||
<pre><pre class="playground"><code class="language-rust editable edition2021">/* Make it work */
|
||||
struct Interface<'a> {
|
||||
manager: &'a mut Manager<'a>
|
||||
}
|
||||
|
||||
impl<'a> Interface<'a> {
|
||||
pub fn noop(self) {
|
||||
println!("interface consumed");
|
||||
}
|
||||
}
|
||||
|
||||
struct Manager<'a> {
|
||||
text: &'a str
|
||||
}
|
||||
|
||||
struct List<'a> {
|
||||
manager: Manager<'a>,
|
||||
}
|
||||
|
||||
impl<'a> List<'a> {
|
||||
pub fn get_interface(&'a mut self) -> Interface {
|
||||
Interface {
|
||||
manager: &mut self.manager
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut list = List {
|
||||
manager: Manager {
|
||||
text: "hello"
|
||||
}
|
||||
};
|
||||
|
||||
list.get_interface().noop();
|
||||
|
||||
println!("Interface should be dropped here and the borrow released");
|
||||
|
||||
use_list(&list);
|
||||
}
|
||||
|
||||
fn use_list(list: &List) {
|
||||
println!("{}", list.manager.text);
|
||||
}</code></pre></pre>
|
||||
<blockquote>
|
||||
<p>You can find the solutions <a href="https://github.com/sunface/rust-by-practice/blob/master/solutions/lifetime/advance.md">here</a>(under the solutions path), but only use it when you need it :)</p>
|
||||
</blockquote>
|
||||
|
||||
</main>
|
||||
|
||||
<nav class="nav-wrapper" aria-label="Page navigation">
|
||||
<!-- Mobile navigation buttons -->
|
||||
<a rel="prev" href="../lifetime/static.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 prefetch" href="../functional-programing/intro.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="../lifetime/static.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 prefetch" href="../functional-programing/intro.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>
|
||||
window.playground_copyable = true;
|
||||
</script>
|
||||
|
||||
<script src="../ace.js"></script>
|
||||
<script src="../editor.js"></script>
|
||||
<script src="../mode-rust.js"></script>
|
||||
<script src="../theme-dawn.js"></script>
|
||||
<script src="../theme-tomorrow_night.js"></script>
|
||||
|
||||
<script src="../elasticlunr.min.js"></script>
|
||||
<script src="../mark.min.js"></script>
|
||||
<script src="../searcher.js"></script>
|
||||
|
||||
<script src="../clipboard.min.js"></script>
|
||||
<script src="../highlight.js"></script>
|
||||
<script src="../book.js"></script>
|
||||
|
||||
<!-- Custom JS scripts -->
|
||||
<script src="../assets/custom3.js"></script>
|
||||
<script src="../assets/lang1.js"></script>
|
||||
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
559
lifetime/basic.html
Normal file
559
lifetime/basic.html
Normal file
@@ -0,0 +1,559 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en" class="light sidebar-visible" dir="ltr">
|
||||
<head>
|
||||
<!-- Book generated using mdBook -->
|
||||
<meta charset="UTF-8">
|
||||
<title>basic - Rust By Practice</title>
|
||||
|
||||
|
||||
<!-- Custom HTML head -->
|
||||
|
||||
<meta name="description" content="Learn Rust with Example, Exercise and real Practice, written with ❤️ by https://course.rs team">
|
||||
<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" id="highlight-css" href="../highlight.css">
|
||||
<link rel="stylesheet" id="tomorrow-night-css" href="../tomorrow-night.css">
|
||||
<link rel="stylesheet" id="ayu-highlight-css" href="../ayu-highlight.css">
|
||||
|
||||
<!-- Custom theme stylesheets -->
|
||||
<link rel="stylesheet" href="../theme/style1.css">
|
||||
|
||||
|
||||
<!-- Provide site root and default themes to javascript -->
|
||||
<script>
|
||||
const path_to_root = "../";
|
||||
const default_light_theme = "light";
|
||||
const default_dark_theme = "navy";
|
||||
</script>
|
||||
<!-- Start loading toc.js asap -->
|
||||
<script src="../toc.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="body-container">
|
||||
<!-- Work around some values being stored in localStorage wrapped in quotes -->
|
||||
<script>
|
||||
try {
|
||||
let theme = localStorage.getItem('mdbook-theme');
|
||||
let 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>
|
||||
const default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? default_dark_theme : default_light_theme;
|
||||
let theme;
|
||||
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
|
||||
if (theme === null || theme === undefined) { theme = default_theme; }
|
||||
const html = document.documentElement;
|
||||
html.classList.remove('light')
|
||||
html.classList.add(theme);
|
||||
html.classList.add("js");
|
||||
</script>
|
||||
|
||||
<input type="checkbox" id="sidebar-toggle-anchor" class="hidden">
|
||||
|
||||
<!-- Hide / unhide sidebar before it is displayed -->
|
||||
<script>
|
||||
let sidebar = null;
|
||||
const sidebar_toggle = document.getElementById("sidebar-toggle-anchor");
|
||||
if (document.body.clientWidth >= 1080) {
|
||||
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
|
||||
sidebar = sidebar || 'visible';
|
||||
} else {
|
||||
sidebar = 'hidden';
|
||||
}
|
||||
sidebar_toggle.checked = sidebar === 'visible';
|
||||
html.classList.remove('sidebar-visible');
|
||||
html.classList.add("sidebar-" + sidebar);
|
||||
</script>
|
||||
|
||||
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
||||
<!-- populated by js -->
|
||||
<mdbook-sidebar-scrollbox class="sidebar-scrollbox"></mdbook-sidebar-scrollbox>
|
||||
<noscript>
|
||||
<iframe class="sidebar-iframe-outer" src="../toc.html"></iframe>
|
||||
</noscript>
|
||||
<div id="sidebar-resize-handle" class="sidebar-resize-handle">
|
||||
<div class="sidebar-resize-indicator"></div>
|
||||
</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">
|
||||
<div class="left-buttons">
|
||||
<label id="sidebar-toggle" class="icon-button" for="sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
|
||||
<i class="fa fa-bars"></i>
|
||||
</label>
|
||||
<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="default_theme">Auto</button></li>
|
||||
<li role="none"><button role="menuitem" class="theme" id="light">Light</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">Rust By Practice</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>
|
||||
<a href="https://github.com/sunface/rust-by-practice" title="Git repository" aria-label="Git repository">
|
||||
<i id="git-repository-button" class="fa fa-github"></i>
|
||||
</a>
|
||||
<a href="https://github.com/sunface/rust-by-practice/edit/master/en/src/lifetime/basic.md" title="Suggest an edit" aria-label="Suggest an edit">
|
||||
<i id="git-edit-button" class="fa fa-edit"></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>
|
||||
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="lifetime"><a class="header" href="#lifetime">Lifetime</a></h2>
|
||||
<p>The compiler uses lifetime to ensure all borrows are valid. Typically, a variable's lifetime begins when it is created and ends when it is destroyed.</p>
|
||||
<h2 id="the-scope-of-lifetime"><a class="header" href="#the-scope-of-lifetime">The scope of lifetime</a></h2>
|
||||
<ol>
|
||||
<li>🌟</li>
|
||||
</ol>
|
||||
<pre><pre class="playground"><code class="language-rust editable edition2021">/* Annotate the lifetime of `i` and `borrow2` */
|
||||
|
||||
// Lifetimes are annotated below with lines denoting the creation
|
||||
// and destruction of each variable.
|
||||
// `i` has the longest lifetime because its scope entirely encloses
|
||||
// both `borrow1` and `borrow2`. The duration of `borrow1` compared
|
||||
// to `borrow2` is irrelevant since they are disjoint.
|
||||
fn main() {
|
||||
let i = 3;
|
||||
{
|
||||
let borrow1 = &i; // `borrow1` lifetime starts. ──┐
|
||||
// │
|
||||
println!("borrow1: {}", borrow1); // │
|
||||
} // `borrow1 ends. ──────────────────────────────────┘
|
||||
{
|
||||
let borrow2 = &i;
|
||||
|
||||
println!("borrow2: {}", borrow2);
|
||||
}
|
||||
} </code></pre></pre>
|
||||
<ol start="2">
|
||||
<li>🌟🌟</li>
|
||||
</ol>
|
||||
<p><strong>Example</strong></p>
|
||||
<pre><pre class="playground"><code class="language-rust edition2021"><span class="boring">#![allow(unused)]
|
||||
</span><span class="boring">fn main() {
|
||||
</span>{
|
||||
let x = 5; // ----------+-- 'b
|
||||
// |
|
||||
let r = &x; // --+-- 'a |
|
||||
// | |
|
||||
println!("r: {}", r); // | |
|
||||
// --+ |
|
||||
} // ----------+
|
||||
<span class="boring">}</span></code></pre></pre>
|
||||
<pre><pre class="playground"><code class="language-rust editable edition2021">/* Annotate `r` and `x` as above, and explain why this code fails to compile, in the lifetime aspect. */
|
||||
|
||||
fn main() {
|
||||
{
|
||||
let r; // ---------+-- 'a
|
||||
// |
|
||||
{ // |
|
||||
let x = 5; // -+-- 'b |
|
||||
r = &x; // | |
|
||||
} // -+ |
|
||||
// |
|
||||
println!("r: {}", r); // |
|
||||
} // ---------+
|
||||
}</code></pre></pre>
|
||||
<h2 id="lifetime-annotating"><a class="header" href="#lifetime-annotating">Lifetime annotating</a></h2>
|
||||
<p>The <strong>borrow checker uses explicit lifetime annotations</strong> to determine how long a reference should be valid.</p>
|
||||
<p>But for us users, in most cases, there is no need to annotate the lifetime, because there are several elision rules, before learning these rules, we need to know how to annotate lifetime manually.</p>
|
||||
<h4 id="function"><a class="header" href="#function">Function</a></h4>
|
||||
<p>Ignoring elision rules, lifetimes in function signatures have a few constraints:</p>
|
||||
<ul>
|
||||
<li>Any reference must have an annotated lifetime</li>
|
||||
<li>Any reference being returned must have the same lifetime as one of the inputs or be static</li>
|
||||
</ul>
|
||||
<p><strong>Example</strong></p>
|
||||
<pre><pre class="playground"><code class="language-rust editable edition2021">// One input reference with lifetime `'a` which must live
|
||||
// at least as long as the function.
|
||||
fn print_one<'a>(x: &'a i32) {
|
||||
println!("`print_one`: x is {}", x);
|
||||
}
|
||||
|
||||
// Mutable references are possible with lifetimes as well.
|
||||
fn add_one<'a>(x: &'a mut i32) {
|
||||
*x += 1;
|
||||
}
|
||||
|
||||
// Multiple elements with different lifetimes. In this case, it
|
||||
// would be fine for both to have the same lifetime `'a`, but
|
||||
// in more complex cases, different lifetimes may be required.
|
||||
fn print_multi<'a, 'b>(x: &'a i32, y: &'b i32) {
|
||||
println!("`print_multi`: x is {}, y is {}", x, y);
|
||||
}
|
||||
|
||||
// Returning references that have been passed in is acceptable.
|
||||
// However, the correct lifetime must be returned.
|
||||
fn pass_x<'a, 'b>(x: &'a i32, _: &'b i32) -> &'a i32 { x }
|
||||
|
||||
fn main() {
|
||||
let x = 7;
|
||||
let y = 9;
|
||||
|
||||
print_one(&x);
|
||||
print_multi(&x, &y);
|
||||
|
||||
let z = pass_x(&x, &y);
|
||||
print_one(z);
|
||||
|
||||
let mut t = 3;
|
||||
add_one(&mut t);
|
||||
print_one(&t);
|
||||
}</code></pre></pre>
|
||||
<ol start="3">
|
||||
<li>🌟</li>
|
||||
</ol>
|
||||
<pre><pre class="playground"><code class="language-rust editable edition2021">/* Make it work by adding proper lifetime annotation */
|
||||
fn longest(x: &str, y: &str) -> &str {
|
||||
if x.len() > y.len() {
|
||||
x
|
||||
} else {
|
||||
y
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}</code></pre></pre>
|
||||
<ol start="4">
|
||||
<li>🌟🌟🌟</li>
|
||||
</ol>
|
||||
<pre><pre class="playground"><code class="language-rust editable edition2021">// `'a` must live longer than the function.
|
||||
// Here, `&String::from("foo")` would create a `String`, followed by a
|
||||
// reference. Then the data is dropped upon exiting the scope, leaving
|
||||
// a reference to invalid data to be returned.
|
||||
|
||||
/* Fix the error in three ways */
|
||||
fn invalid_output<'a>() -> &'a String {
|
||||
&String::from("foo")
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}</code></pre></pre>
|
||||
<ol start="5">
|
||||
<li>🌟🌟</li>
|
||||
</ol>
|
||||
<pre><pre class="playground"><code class="language-rust editable edition2021">// `print_refs` takes two references to `i32` which have different
|
||||
// lifetimes `'a` and `'b`. These two lifetimes must both be at
|
||||
// least as long as the function `print_refs`.
|
||||
fn print_refs<'a, 'b>(x: &'a i32, y: &'b i32) {
|
||||
println!("x is {} and y is {}", x, y);
|
||||
}
|
||||
|
||||
/* Make it work */
|
||||
// A function which takes no arguments, but has a lifetime parameter `'a`.
|
||||
fn failed_borrow<'a>() {
|
||||
let _x = 12;
|
||||
|
||||
// ERROR: `_x` does not live long enough
|
||||
let y: &'a i32 = &_x;
|
||||
// Attempting to use the lifetime `'a` as an explicit type annotation
|
||||
// inside the function will fail because the lifetime of `&_x` is shorter
|
||||
// than `'a` . A short lifetime cannot be coerced into a longer one.
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let (four, nine) = (4, 9);
|
||||
|
||||
// Borrows (`&`) of both variables are passed into the function.
|
||||
print_refs(&four, &nine);
|
||||
// Any input which is borrowed must outlive the borrower.
|
||||
// In other words, the lifetime of `four` and `nine` must
|
||||
// be longer than that of `print_refs`.
|
||||
|
||||
failed_borrow();
|
||||
// `failed_borrow` contains no references to force `'a` to be
|
||||
// longer than the lifetime of the function, but `'a` is longer.
|
||||
// Because the lifetime is never constrained, it defaults to `'static`.
|
||||
}</code></pre></pre>
|
||||
<h4 id="structs"><a class="header" href="#structs">Structs</a></h4>
|
||||
<ol start="6">
|
||||
<li>🌟</li>
|
||||
</ol>
|
||||
<pre><pre class="playground"><code class="language-rust editable edition2021">/* Make it work by adding proper lifetime annotation */
|
||||
|
||||
// A type `Borrowed` which houses a reference to an
|
||||
// `i32`. The reference to `i32` must outlive `Borrowed`.
|
||||
#[derive(Debug)]
|
||||
struct Borrowed(&i32);
|
||||
|
||||
// Similarly, both references here must outlive this structure.
|
||||
#[derive(Debug)]
|
||||
struct NamedBorrowed {
|
||||
x: &i32,
|
||||
y: &i32,
|
||||
}
|
||||
|
||||
// An enum which is either an `i32` or a reference to one.
|
||||
#[derive(Debug)]
|
||||
enum Either {
|
||||
Num(i32),
|
||||
Ref(&i32),
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x = 18;
|
||||
let y = 15;
|
||||
|
||||
let single = Borrowed(&x);
|
||||
let double = NamedBorrowed { x: &x, y: &y };
|
||||
let reference = Either::Ref(&x);
|
||||
let number = Either::Num(y);
|
||||
|
||||
println!("x is borrowed in {:?}", single);
|
||||
println!("x and y are borrowed in {:?}", double);
|
||||
println!("x is borrowed in {:?}", reference);
|
||||
println!("y is *not* borrowed in {:?}", number);
|
||||
}</code></pre></pre>
|
||||
<ol start="7">
|
||||
<li>🌟🌟</li>
|
||||
</ol>
|
||||
<pre><pre class="playground"><code class="language-rust editable edition2021">/* Make it work */
|
||||
|
||||
#[derive(Debug)]
|
||||
struct NoCopyType {}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Example<'a, 'b> {
|
||||
a: &'a u32,
|
||||
b: &'b NoCopyType
|
||||
}
|
||||
|
||||
fn main()
|
||||
{
|
||||
/* 'a tied to fn-main stackframe */
|
||||
let var_a = 35;
|
||||
let example: Example;
|
||||
|
||||
{
|
||||
/* Lifetime 'b tied to new stackframe/scope */
|
||||
let var_b = NoCopyType {};
|
||||
|
||||
/* fixme */
|
||||
example = Example { a: &var_a, b: &var_b };
|
||||
}
|
||||
|
||||
println!("(Success!) {:?}", example);
|
||||
}</code></pre></pre>
|
||||
<ol start="8">
|
||||
<li>🌟🌟</li>
|
||||
</ol>
|
||||
<pre><pre class="playground"><code class="language-rust editable edition2021">
|
||||
#[derive(Debug)]
|
||||
struct NoCopyType {}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[allow(dead_code)]
|
||||
struct Example<'a, 'b> {
|
||||
a: &'a u32,
|
||||
b: &'b NoCopyType
|
||||
}
|
||||
|
||||
/* Fix function signature */
|
||||
fn fix_me(foo: &Example) -> &NoCopyType
|
||||
{ foo.b }
|
||||
|
||||
fn main()
|
||||
{
|
||||
let no_copy = NoCopyType {};
|
||||
let example = Example { a: &1, b: &no_copy };
|
||||
fix_me(&example);
|
||||
println!("Success!")
|
||||
}</code></pre></pre>
|
||||
<h2 id="method"><a class="header" href="#method">Method</a></h2>
|
||||
<p>Methods are annotated similarly to functions.</p>
|
||||
<p><strong>Example</strong></p>
|
||||
<pre><pre class="playground"><code class="language-rust editable edition2021">struct Owner(i32);
|
||||
|
||||
impl Owner {
|
||||
// Annotate lifetimes as in a standalone function.
|
||||
fn add_one<'a>(&'a mut self) { self.0 += 1; }
|
||||
fn print<'a>(&'a self) {
|
||||
println!("`print`: {}", self.0);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut owner = Owner(18);
|
||||
|
||||
owner.add_one();
|
||||
owner.print();
|
||||
}</code></pre></pre>
|
||||
<ol start="9">
|
||||
<li>🌟🌟</li>
|
||||
</ol>
|
||||
<pre><pre class="playground"><code class="language-rust editable edition2021">/* Make it work by adding proper lifetime annotations */
|
||||
struct ImportantExcerpt {
|
||||
part: &str,
|
||||
}
|
||||
|
||||
impl ImportantExcerpt {
|
||||
fn level(&'a self) -> i32 {
|
||||
3
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}</code></pre></pre>
|
||||
<h2 id="elision"><a class="header" href="#elision">Elision</a></h2>
|
||||
<p>Some lifetime patterns are so common that borrow checker will allow you to omit them to save typing and improve readability.</p>
|
||||
<p>This is known as <strong>Elision</strong>. Elision exist in Rust only because these patterns are common.</p>
|
||||
<p>For a more comprehensive understanding of elision, please see <a href="https://doc.rust-lang.org/book/ch10-03-lifetime-syntax.html#lifetime-elision">lifetime elision</a> in the official book.</p>
|
||||
<ol start="10">
|
||||
<li>🌟🌟</li>
|
||||
</ol>
|
||||
<pre><pre class="playground"><code class="language-rust editable edition2021">/* Remove all the lifetimes that can be elided */
|
||||
|
||||
fn input<'a>(x: &'a i32) {
|
||||
println!("`annotated_input`: {}", x);
|
||||
}
|
||||
|
||||
fn pass<'a>(x: &'a i32) -> &'a i32 { x }
|
||||
|
||||
fn longest<'a, 'b>(x: &'a str, y: &'b str) -> &'a str {
|
||||
x
|
||||
}
|
||||
|
||||
struct Owner(i32);
|
||||
|
||||
impl Owner {
|
||||
// Annotate lifetimes as in a standalone function.
|
||||
fn add_one<'a>(&'a mut self) { self.0 += 1; }
|
||||
fn print<'a>(&'a self) {
|
||||
println!("`print`: {}", self.0);
|
||||
}
|
||||
}
|
||||
|
||||
struct Person<'a> {
|
||||
age: u8,
|
||||
name: &'a str,
|
||||
}
|
||||
|
||||
enum Either<'a> {
|
||||
Num(i32),
|
||||
Ref(&'a i32),
|
||||
}
|
||||
|
||||
fn main() {}</code></pre></pre>
|
||||
<blockquote>
|
||||
<p>You can find the solutions <a href="https://github.com/sunface/rust-by-practice/blob/master/solutions/lifetime/basic.md">here</a>(under the solutions path), but only use it when you need it :)</p>
|
||||
</blockquote>
|
||||
|
||||
</main>
|
||||
|
||||
<nav class="nav-wrapper" aria-label="Page navigation">
|
||||
<!-- Mobile navigation buttons -->
|
||||
<a rel="prev" href="../lifetime/intro.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 prefetch" href="../lifetime/static.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="../lifetime/intro.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 prefetch" href="../lifetime/static.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>
|
||||
window.playground_copyable = true;
|
||||
</script>
|
||||
|
||||
<script src="../ace.js"></script>
|
||||
<script src="../editor.js"></script>
|
||||
<script src="../mode-rust.js"></script>
|
||||
<script src="../theme-dawn.js"></script>
|
||||
<script src="../theme-tomorrow_night.js"></script>
|
||||
|
||||
<script src="../elasticlunr.min.js"></script>
|
||||
<script src="../mark.min.js"></script>
|
||||
<script src="../searcher.js"></script>
|
||||
|
||||
<script src="../clipboard.min.js"></script>
|
||||
<script src="../highlight.js"></script>
|
||||
<script src="../book.js"></script>
|
||||
|
||||
<!-- Custom JS scripts -->
|
||||
<script src="../assets/custom3.js"></script>
|
||||
<script src="../assets/lang1.js"></script>
|
||||
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
229
lifetime/intro.html
Normal file
229
lifetime/intro.html
Normal file
@@ -0,0 +1,229 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en" class="light sidebar-visible" dir="ltr">
|
||||
<head>
|
||||
<!-- Book generated using mdBook -->
|
||||
<meta charset="UTF-8">
|
||||
<title>Lifetime - Rust By Practice</title>
|
||||
|
||||
|
||||
<!-- Custom HTML head -->
|
||||
|
||||
<meta name="description" content="Learn Rust with Example, Exercise and real Practice, written with ❤️ by https://course.rs team">
|
||||
<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" id="highlight-css" href="../highlight.css">
|
||||
<link rel="stylesheet" id="tomorrow-night-css" href="../tomorrow-night.css">
|
||||
<link rel="stylesheet" id="ayu-highlight-css" href="../ayu-highlight.css">
|
||||
|
||||
<!-- Custom theme stylesheets -->
|
||||
<link rel="stylesheet" href="../theme/style1.css">
|
||||
|
||||
|
||||
<!-- Provide site root and default themes to javascript -->
|
||||
<script>
|
||||
const path_to_root = "../";
|
||||
const default_light_theme = "light";
|
||||
const default_dark_theme = "navy";
|
||||
</script>
|
||||
<!-- Start loading toc.js asap -->
|
||||
<script src="../toc.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="body-container">
|
||||
<!-- Work around some values being stored in localStorage wrapped in quotes -->
|
||||
<script>
|
||||
try {
|
||||
let theme = localStorage.getItem('mdbook-theme');
|
||||
let 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>
|
||||
const default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? default_dark_theme : default_light_theme;
|
||||
let theme;
|
||||
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
|
||||
if (theme === null || theme === undefined) { theme = default_theme; }
|
||||
const html = document.documentElement;
|
||||
html.classList.remove('light')
|
||||
html.classList.add(theme);
|
||||
html.classList.add("js");
|
||||
</script>
|
||||
|
||||
<input type="checkbox" id="sidebar-toggle-anchor" class="hidden">
|
||||
|
||||
<!-- Hide / unhide sidebar before it is displayed -->
|
||||
<script>
|
||||
let sidebar = null;
|
||||
const sidebar_toggle = document.getElementById("sidebar-toggle-anchor");
|
||||
if (document.body.clientWidth >= 1080) {
|
||||
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
|
||||
sidebar = sidebar || 'visible';
|
||||
} else {
|
||||
sidebar = 'hidden';
|
||||
}
|
||||
sidebar_toggle.checked = sidebar === 'visible';
|
||||
html.classList.remove('sidebar-visible');
|
||||
html.classList.add("sidebar-" + sidebar);
|
||||
</script>
|
||||
|
||||
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
||||
<!-- populated by js -->
|
||||
<mdbook-sidebar-scrollbox class="sidebar-scrollbox"></mdbook-sidebar-scrollbox>
|
||||
<noscript>
|
||||
<iframe class="sidebar-iframe-outer" src="../toc.html"></iframe>
|
||||
</noscript>
|
||||
<div id="sidebar-resize-handle" class="sidebar-resize-handle">
|
||||
<div class="sidebar-resize-indicator"></div>
|
||||
</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">
|
||||
<div class="left-buttons">
|
||||
<label id="sidebar-toggle" class="icon-button" for="sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
|
||||
<i class="fa fa-bars"></i>
|
||||
</label>
|
||||
<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="default_theme">Auto</button></li>
|
||||
<li role="none"><button role="menuitem" class="theme" id="light">Light</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">Rust By Practice</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>
|
||||
<a href="https://github.com/sunface/rust-by-practice" title="Git repository" aria-label="Git repository">
|
||||
<i id="git-repository-button" class="fa fa-github"></i>
|
||||
</a>
|
||||
<a href="https://github.com/sunface/rust-by-practice/edit/master/en/src/lifetime/intro.md" title="Suggest an edit" aria-label="Suggest an edit">
|
||||
<i id="git-edit-button" class="fa fa-edit"></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>
|
||||
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>
|
||||
<h1 id="lifetime"><a class="header" href="#lifetime">Lifetime</a></h1>
|
||||
<p>Learning resources:</p>
|
||||
<ul>
|
||||
<li>English: <a href="https://doc.rust-lang.org/book/ch10-03-lifetime-syntax.html">Rust Book 10.3</a></li>
|
||||
<li>简体中文: <a href="https://course.rs/advance/lifetime/intro.html">Rust语言圣经 - 生命周期</a></li>
|
||||
</ul>
|
||||
|
||||
</main>
|
||||
|
||||
<nav class="nav-wrapper" aria-label="Page navigation">
|
||||
<!-- Mobile navigation buttons -->
|
||||
<a rel="prev" href="../formatted-output/formatting.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 prefetch" href="../lifetime/basic.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="../formatted-output/formatting.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 prefetch" href="../lifetime/basic.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>
|
||||
window.playground_copyable = true;
|
||||
</script>
|
||||
|
||||
<script src="../ace.js"></script>
|
||||
<script src="../editor.js"></script>
|
||||
<script src="../mode-rust.js"></script>
|
||||
<script src="../theme-dawn.js"></script>
|
||||
<script src="../theme-tomorrow_night.js"></script>
|
||||
|
||||
<script src="../elasticlunr.min.js"></script>
|
||||
<script src="../mark.min.js"></script>
|
||||
<script src="../searcher.js"></script>
|
||||
|
||||
<script src="../clipboard.min.js"></script>
|
||||
<script src="../highlight.js"></script>
|
||||
<script src="../book.js"></script>
|
||||
|
||||
<!-- Custom JS scripts -->
|
||||
<script src="../assets/custom3.js"></script>
|
||||
<script src="../assets/lang1.js"></script>
|
||||
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
405
lifetime/static.html
Normal file
405
lifetime/static.html
Normal file
@@ -0,0 +1,405 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en" class="light sidebar-visible" dir="ltr">
|
||||
<head>
|
||||
<!-- Book generated using mdBook -->
|
||||
<meta charset="UTF-8">
|
||||
<title>&'static and T: 'static - Rust By Practice</title>
|
||||
|
||||
|
||||
<!-- Custom HTML head -->
|
||||
|
||||
<meta name="description" content="Learn Rust with Example, Exercise and real Practice, written with ❤️ by https://course.rs team">
|
||||
<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" id="highlight-css" href="../highlight.css">
|
||||
<link rel="stylesheet" id="tomorrow-night-css" href="../tomorrow-night.css">
|
||||
<link rel="stylesheet" id="ayu-highlight-css" href="../ayu-highlight.css">
|
||||
|
||||
<!-- Custom theme stylesheets -->
|
||||
<link rel="stylesheet" href="../theme/style1.css">
|
||||
|
||||
|
||||
<!-- Provide site root and default themes to javascript -->
|
||||
<script>
|
||||
const path_to_root = "../";
|
||||
const default_light_theme = "light";
|
||||
const default_dark_theme = "navy";
|
||||
</script>
|
||||
<!-- Start loading toc.js asap -->
|
||||
<script src="../toc.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="body-container">
|
||||
<!-- Work around some values being stored in localStorage wrapped in quotes -->
|
||||
<script>
|
||||
try {
|
||||
let theme = localStorage.getItem('mdbook-theme');
|
||||
let 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>
|
||||
const default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? default_dark_theme : default_light_theme;
|
||||
let theme;
|
||||
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
|
||||
if (theme === null || theme === undefined) { theme = default_theme; }
|
||||
const html = document.documentElement;
|
||||
html.classList.remove('light')
|
||||
html.classList.add(theme);
|
||||
html.classList.add("js");
|
||||
</script>
|
||||
|
||||
<input type="checkbox" id="sidebar-toggle-anchor" class="hidden">
|
||||
|
||||
<!-- Hide / unhide sidebar before it is displayed -->
|
||||
<script>
|
||||
let sidebar = null;
|
||||
const sidebar_toggle = document.getElementById("sidebar-toggle-anchor");
|
||||
if (document.body.clientWidth >= 1080) {
|
||||
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
|
||||
sidebar = sidebar || 'visible';
|
||||
} else {
|
||||
sidebar = 'hidden';
|
||||
}
|
||||
sidebar_toggle.checked = sidebar === 'visible';
|
||||
html.classList.remove('sidebar-visible');
|
||||
html.classList.add("sidebar-" + sidebar);
|
||||
</script>
|
||||
|
||||
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
||||
<!-- populated by js -->
|
||||
<mdbook-sidebar-scrollbox class="sidebar-scrollbox"></mdbook-sidebar-scrollbox>
|
||||
<noscript>
|
||||
<iframe class="sidebar-iframe-outer" src="../toc.html"></iframe>
|
||||
</noscript>
|
||||
<div id="sidebar-resize-handle" class="sidebar-resize-handle">
|
||||
<div class="sidebar-resize-indicator"></div>
|
||||
</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">
|
||||
<div class="left-buttons">
|
||||
<label id="sidebar-toggle" class="icon-button" for="sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
|
||||
<i class="fa fa-bars"></i>
|
||||
</label>
|
||||
<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="default_theme">Auto</button></li>
|
||||
<li role="none"><button role="menuitem" class="theme" id="light">Light</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">Rust By Practice</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>
|
||||
<a href="https://github.com/sunface/rust-by-practice" title="Git repository" aria-label="Git repository">
|
||||
<i id="git-repository-button" class="fa fa-github"></i>
|
||||
</a>
|
||||
<a href="https://github.com/sunface/rust-by-practice/edit/master/en/src/lifetime/static.md" title="Suggest an edit" aria-label="Suggest an edit">
|
||||
<i id="git-edit-button" class="fa fa-edit"></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>
|
||||
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>
|
||||
<h1 id="static-and-t-static"><a class="header" href="#static-and-t-static">&'static and T: 'static</a></h1>
|
||||
<p><code>'static</code> is a reserved lifetime name, you might have encountered it several times:</p>
|
||||
<pre><pre class="playground"><code class="language-rust edition2021"><span class="boring">#![allow(unused)]
|
||||
</span><span class="boring">fn main() {
|
||||
</span>// A reference with 'static lifetime:
|
||||
let s: &'static str = "hello world";
|
||||
|
||||
// 'static as part of a trait bound:
|
||||
fn generic<T>(x: T) where T: 'static {}
|
||||
<span class="boring">}</span></code></pre></pre>
|
||||
<p>Though they are all <code>'static</code>, but subtly different.</p>
|
||||
<h2 id="static"><a class="header" href="#static">&'static</a></h2>
|
||||
<p>As a reference lifetime, <code>&'static</code> indicates the data pointed to by the reference lives as long as the running program. But it can still be coerced to a shorter lifetime.</p>
|
||||
<ol>
|
||||
<li>🌟🌟 There are several ways to make a variable with <code>'static</code> lifetime, two of them are stored in the read-only memory of the binary.</li>
|
||||
</ol>
|
||||
<pre><pre class="playground"><code class="language-rust editable edition2021">
|
||||
/* Fill in the blank in two ways */
|
||||
fn main() {
|
||||
__;
|
||||
need_static(v);
|
||||
|
||||
println!("Success!")
|
||||
}
|
||||
|
||||
fn need_static(r : &'static str) {
|
||||
assert_eq!(r, "hello");
|
||||
}</code></pre></pre>
|
||||
<ol start="2">
|
||||
<li>🌟🌟🌟🌟 Another way to make <code>'static</code> lifetime is using <code>Box::leak</code></li>
|
||||
</ol>
|
||||
<pre><pre class="playground"><code class="language-rust editable edition2021">#[derive(Debug)]
|
||||
struct Config {
|
||||
a: String,
|
||||
b: String,
|
||||
}
|
||||
static mut config: Option<&mut Config> = None;
|
||||
|
||||
/* Make it work without changing the function signatures of `init`*/
|
||||
fn init() -> Option<&'static mut Config> {
|
||||
Some(&mut Config {
|
||||
a: "A".to_string(),
|
||||
b: "B".to_string(),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
config = init();
|
||||
|
||||
println!("{:?}",config)
|
||||
}
|
||||
}</code></pre></pre>
|
||||
<ol start="3">
|
||||
<li>🌟 <code>&'static</code> only indicates that the data can live forever, not the reference. The latter one will be constrained by its scope.</li>
|
||||
</ol>
|
||||
<pre><pre class="playground"><code class="language-rust editable edition2021">fn main() {
|
||||
{
|
||||
// Make a `string` literal and print it:
|
||||
let static_string = "I'm in read-only memory";
|
||||
println!("static_string: {}", static_string);
|
||||
|
||||
// When `static_string` goes out of scope, the reference
|
||||
// can no longer be used, but the data remains in the binary.
|
||||
}
|
||||
|
||||
println!("static_string reference remains alive: {}", static_string);
|
||||
}</code></pre></pre>
|
||||
<ol start="4">
|
||||
<li><code>&'static</code> can be coerced to a shorter lifetime.</li>
|
||||
</ol>
|
||||
<p><strong>Example</strong></p>
|
||||
<pre><pre class="playground"><code class="language-rust editable edition2021">// Make a constant with `'static` lifetime.
|
||||
static NUM: i32 = 18;
|
||||
|
||||
// Returns a reference to `NUM` where its `'static`
|
||||
// lifetime is coerced to that of the input argument.
|
||||
fn coerce_static<'a>(_: &'a i32) -> &'a i32 {
|
||||
&NUM
|
||||
}
|
||||
|
||||
fn main() {
|
||||
{
|
||||
// Make an integer to use for `coerce_static`:
|
||||
let lifetime_num = 9;
|
||||
|
||||
// Coerce `NUM` to lifetime of `lifetime_num`:
|
||||
let coerced_static = coerce_static(&lifetime_num);
|
||||
|
||||
println!("coerced_static: {}", coerced_static);
|
||||
}
|
||||
|
||||
println!("NUM: {} stays accessible!", NUM);
|
||||
}</code></pre></pre>
|
||||
<h2 id="t-static"><a class="header" href="#t-static">T: 'static</a></h2>
|
||||
<p>As a trait bound, it means the type does not contain any non-static references. Eg. the receiver can hold on to the type for as long as they want and it will never become invalid until they drop it.</p>
|
||||
<p>It's important to understand this means that any owned data always passes a <code>'static </code>lifetime bound, but a reference to that owned data generally does not.</p>
|
||||
<ol start="5">
|
||||
<li>🌟🌟</li>
|
||||
</ol>
|
||||
<pre><pre class="playground"><code class="language-rust editable edition2021">/* Make it work */
|
||||
use std::fmt::Debug;
|
||||
|
||||
fn print_it<T: Debug + 'static>( input: T) {
|
||||
println!( "'static value passed in is: {:?}", input );
|
||||
}
|
||||
|
||||
fn print_it1( input: impl Debug + 'static ) {
|
||||
println!( "'static value passed in is: {:?}", input );
|
||||
}
|
||||
|
||||
|
||||
fn print_it2<T: Debug + 'static>( input: &T) {
|
||||
println!( "'static value passed in is: {:?}", input );
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// i is owned and contains no references, thus it's 'static:
|
||||
let i = 5;
|
||||
print_it(i);
|
||||
|
||||
// oops, &i only has the lifetime defined by the scope of
|
||||
// main(), so it's not 'static:
|
||||
print_it(&i);
|
||||
|
||||
print_it1(&i);
|
||||
|
||||
// but this one WORKS !
|
||||
print_it2(&i);
|
||||
}</code></pre></pre>
|
||||
<ol start="6">
|
||||
<li>🌟🌟🌟</li>
|
||||
</ol>
|
||||
<pre><pre class="playground"><code class="language-rust editable edition2021">use std::fmt::Display;
|
||||
|
||||
fn main() {
|
||||
let mut string = "First".to_owned();
|
||||
|
||||
string.push_str(string.to_uppercase().as_str());
|
||||
print_a(&string);
|
||||
print_b(&string);
|
||||
print_c(&string); // Compilation error
|
||||
print_d(&string); // Compilation error
|
||||
print_e(&string);
|
||||
print_f(&string);
|
||||
print_g(&string); // Compilation error
|
||||
}
|
||||
|
||||
fn print_a<T: Display + 'static>(t: &T) {
|
||||
println!("{}", t);
|
||||
}
|
||||
|
||||
fn print_b<T>(t: &T)
|
||||
where
|
||||
T: Display + 'static,
|
||||
{
|
||||
println!("{}", t);
|
||||
}
|
||||
|
||||
fn print_c(t: &'static dyn Display) {
|
||||
println!("{}", t)
|
||||
}
|
||||
|
||||
fn print_d(t: &'static impl Display) {
|
||||
println!("{}", t)
|
||||
}
|
||||
|
||||
fn print_e(t: &(dyn Display + 'static)) {
|
||||
println!("{}", t)
|
||||
}
|
||||
|
||||
fn print_f(t: &(impl Display + 'static)) {
|
||||
println!("{}", t)
|
||||
}
|
||||
|
||||
fn print_g(t: &'static String) {
|
||||
println!("{}", t);
|
||||
}</code></pre></pre>
|
||||
<blockquote>
|
||||
<p>You can find the solutions <a href="https://github.com/sunface/rust-by-practice/blob/master/solutions/lifetime/static.md">here</a>(under the solutions path), but only use it when you need it :)</p>
|
||||
</blockquote>
|
||||
|
||||
</main>
|
||||
|
||||
<nav class="nav-wrapper" aria-label="Page navigation">
|
||||
<!-- Mobile navigation buttons -->
|
||||
<a rel="prev" href="../lifetime/basic.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 prefetch" href="../lifetime/advance.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="../lifetime/basic.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 prefetch" href="../lifetime/advance.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>
|
||||
window.playground_copyable = true;
|
||||
</script>
|
||||
|
||||
<script src="../ace.js"></script>
|
||||
<script src="../editor.js"></script>
|
||||
<script src="../mode-rust.js"></script>
|
||||
<script src="../theme-dawn.js"></script>
|
||||
<script src="../theme-tomorrow_night.js"></script>
|
||||
|
||||
<script src="../elasticlunr.min.js"></script>
|
||||
<script src="../mark.min.js"></script>
|
||||
<script src="../searcher.js"></script>
|
||||
|
||||
<script src="../clipboard.min.js"></script>
|
||||
<script src="../highlight.js"></script>
|
||||
<script src="../book.js"></script>
|
||||
|
||||
<!-- Custom JS scripts -->
|
||||
<script src="../assets/custom3.js"></script>
|
||||
<script src="../assets/lang1.js"></script>
|
||||
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
Reference in New Issue
Block a user