You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

318 lines
18 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!DOCTYPE HTML>
<html lang="zh-CN" class="light sidebar-visible" dir="ltr">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>1.64 - Rust语言圣经(Rust Course)</title>
<!-- Custom HTML head -->
<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" 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/style.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语言圣经(Rust Course)</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-course" 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-course/edit/main/src/appendix/rust-versions/1.64.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="rust-新版解读--164--重点-intofuture--cargo-优化"><a class="header" href="#rust-新版解读--164--重点-intofuture--cargo-优化">Rust 新版解读 | 1.64 | 重点: <code>IntoFuture</code> , Cargo 优化</a></h1>
<blockquote>
<p>Rust 1.64 官方 release doc: <a href="https://blog.rust-lang.org/2022/09/22/Rust-1.64.0.html">Announcing Rust 1.64.0 | Rust Blog</a></p>
</blockquote>
<p>通过 <a href="https://www.rust-lang.org/tools/install">rustup</a> 安装的同学可以使用以下命令升级到 1.64 版本:</p>
<pre><code class="language-shell">$ rustup update stable
</code></pre>
<h2 id="使用-intofuture-增强-await"><a class="header" href="#使用-intofuture-增强-await">使用 <code>IntoFuture</code> 增强 <code>.await</code></a></h2>
<p>1.64 稳定了 <code>IntoFuture</code> trait不同于用在 <code>for ... in ...</code><code>IntoIterator</code> trait<code>IntoFuture</code> 增强了 <code>.awiat</code> 关键字。现在 <code>.await</code> 可以 await 除了 futures 外,还可以 await 任何实现了 <code>IntoFuture</code> trait 并经此转换成 <code>Future</code> 的对象。这可以让你的 api 对用户更加优化。</p>
<p>举一个用在网络存储供应端的例子:</p>
<pre><pre class="playground"><code class="language-rust edition2021"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span>pub struct Error { ... }
pub struct StorageResponse { ... }:
pub struct StorageRequest(bool);
impl StorageRequest {
/// 实例化一个 `StorageRequest`
pub fn new() -&gt; Self { ... }
/// 是否开启 debug 模式
pub fn set_debug(self, b: bool) -&gt; Self { ... }
/// 发送请求并接受回复
pub async fn send(self) -&gt; Result&lt;StorageResponse, Error&gt; { ... }
}
<span class="boring">}</span></code></pre></pre>
<p>通常地使用方法可能类似如下代码:</p>
<pre><pre class="playground"><code class="language-rust edition2021"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span>let response = StorageRequest::new() // 1. 实例化
.set_debug(true) // 2. 设置一些选项
.send() // 3. 构造 future
.await?; // 4. 执行 future ,传递 error
<span class="boring">}</span></code></pre></pre>
<p>这个代码已经不错了,不过 1.64 后可以做的更好。使用 <code>IntoFuture</code> ,把第三步的 “构造 future ” 和 第四步的 “执行 future ” 合并到一个步骤里:</p>
<pre><code class="language-RUST">let response = StorageRequest::new() // 1. 实例化
.set_debug(true) // 2. 设置一些选项
.await?; // 3. 构造并执行 future ,传递 error
</code></pre>
<p>想要实现上面的效果,我们需要给 <code>StorageRequest</code> 实现 <code>IntoFuture</code> trait。<code>IntoFuture</code> 需要确定好要返回的 future可以用下面的代码来实现</p>
<pre><pre class="playground"><code class="language-rust edition2021"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span>// 首先需要引入一些必须的类型
use std::pin::Pin;
use std::future::{Future, IntoFuture};
pub struct Error { ... }
pub struct StorageResponse { ... }
pub struct StorageRequest(bool);
impl StorageRequest {
/// 实例化一个 `StorageRequest`
pub fn new() -&gt; Self { ... }
/// 是否开启 debug 模式
pub fn set_debug(self, b: bool) -&gt; Self { ... }
/// 发送请求并接受回复
pub async fn send(self) -&gt; Result&lt;StorageResponse, Error&gt; { ... }
}
// 新的实现内容
// 1. 定义好返回的 future 类型
pub type StorageRequestFuture = Pin&lt;Box&lt;dyn Future&lt;Output = Result&lt;StorageResponse, Error&gt;&gt; + Send + 'static&gt;&gt;
// 2. 给 `StorageRequest` 实现 `IntoFuture`
impl IntoFuture for StorageRequest {
type IntoFuture = StorageRequestFuture;
type Output = &lt;StorageRequestFuture as Future&gt;::Output;
fn into_future(self) -&gt; Self::IntoFuture {
Box::pin(self.send())
}
}
<span class="boring">}</span></code></pre></pre>
<p>这确实需要多写一点实现代码,不过可以给用户提供一个更简单的 api 。</p>
<p>未来Rust 异步团队 希望能够通过给类型别名提供 <code>impl Trait</code> <a href="https://rust-lang.github.io/impl-trait-initiative/explainer/tait.html">Type Alias Impl Trait</a>,来简化定义 futures 实现 <code>IntoFuture</code> 的代码;再想办法移除 <code>Box</code> 来提升性能。</p>
<h2 id="core-和-alloc-中和-c-语言兼容的-ffi-类型"><a class="header" href="#core-和-alloc-中和-c-语言兼容的-ffi-类型"><code>core</code><code>alloc</code> 中和 C 语言兼容的 FFI 类型</a></h2>
<p>当调用 C-ABI 或者调用 C-ABI 的时候Rust 代码通常会使用诸如 <code>c_uint</code> 或者 <code>c_ulong</code> 的类型别名来匹配目标语言里的对应类型。</p>
<p>在次之前,这些类型别名仅在 <code>std</code> 里可用,而在嵌入式或者其它仅能使用 <code>core</code> 或者 <code>alloc</code> 的场景下无法使用。</p>
<p>1.64 里在 <code>core::ffi</code> 里提供了所有 <code>c_*</code> 的类型别名,还有 <code>core::ffi::CStr</code> 对应 C 的字符串,还有仅用 <code>alloc</code> 库情况下可以用 <code>alloc::ffi::CString</code> 来对应 C 的字符串。</p>
<h2 id="可以通过-rustup-来使用-rust-analyzer"><a class="header" href="#可以通过-rustup-来使用-rust-analyzer">可以通过 rustup 来使用 rust-analyzer</a></h2>
<p>rust-analyzer 现在被加进 Rust 工具集里了。这让在各平台上下载使用 rust-analyzer 更加方便。通过 <a href="https://rust-lang.github.io/rustup/concepts/components.html">rustup component</a> 来安装:</p>
<pre><code class="language-shell">rustup component add rust-analyzer
</code></pre>
<p>目前,使用 rustup 安装的版本,需要这样启用:</p>
<pre><code class="language-shell">rustup run stable rust-analyzer
</code></pre>
<p>下一次 rustup 的发布本把会提供一个内置的代理,来运行对应版本的 rust-analyzer 。</p>
<h2 id="cargo-优化workspace-继承和多目标构建"><a class="header" href="#cargo-优化workspace-继承和多目标构建">Cargo 优化workspace 继承和多目标构建</a></h2>
<p>当在一个 Cargo workspace 里管理多个相关的库/产品时,现在可以避免在多个库里使用相同的字段值了,比如相同的版本号,仓库链接,<code>rust-version</code>。在更新的时候也可以更容易地保持这些信息地一致性。更多细节可以参考:</p>
<ul>
<li><a href="https://doc.rust-lang.org/cargo/reference/workspaces.html#the-package-table">workspace.package</a></li>
<li><a href="https://doc.rust-lang.org/cargo/reference/workspaces.html#the-dependencies-table">workspace.dependencies</a></li>
<li><a href="https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#inheriting-a-dependency-from-a-workspace">"inheriting a dependency from a workspace"</a></li>
</ul>
<p>另外在构建多个目标地时候,现在可以直接传递多个 <code>--target</code> 选项给 <code>cargo build</code> 来一次性编译所有目标。也可以在 <code>.cargo/config.toml</code> 里设置一个 <code>build.target</code> 的 array 来改变默认构建时的对象。</p>
<h2 id="稳定api--others"><a class="header" href="#稳定api--others">稳定API &amp;&amp; Others</a></h2>
<p>更多稳定API列表和其它更新内容请参考原文最后 <a href="https://blog.rust-lang.org/2022/09/22/Rust-1.64.0.html#stabilized-apis">stabilized-apis</a></p>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="../../appendix/rust-versions/1.63.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="../../appendix/rust-versions/1.65.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="../../appendix/rust-versions/1.63.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="../../appendix/rust-versions/1.65.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/custom2.js"></script>
<script src="../../assets/bigPicture.js"></script>
</div>
</body>
</html>