2311rust,到35版本更新
1.32.0
rustup self update
rustup update stable
rustup
更新自己.
dbg
宏
打印
调试,你需要:
let x = 5;
println!("{:?}", x);
//甚至可能是
println!("{:#?}", x);
在Rust1.32.0
中,为此
添加了个新的dbg!
宏:
fn main() {
let x = 5;
dbg!(x);
}
如果运行此程序
,会看到:
[src/main.rs:4] x = 5
你获得了调用此文件的文件和行号
,及名字和值
.此外,println!
打印到标准输出
,所以要用eprintln!
打印到标准错误.dbg!
干活,然后在stderr
输出.
看看阶乘
示例:
fn factorial(n: u32) -> u32 {
if n <= 1 {
n
} else {
n * factorial(n - 1)
}
}
如果想调试
它,可用eprintln
这样:
fn factorial(n: u32) -> u32 {
eprintln!("n: {}", n);
if n <= 1 {
eprintln!("n <= 1");
n
} else {
let n = n * factorial(n - 1);
eprintln!("n: {}", n);
n
}
}
想在每次迭代
时记录n
,并为每个分支
提供某种环境.查看factorial(4)
的输出:
n: 4
n: 3
n: 2
n: 1
n <= 1
n: 2
n: 6
n: 24
使用dbg!
fn factorial(n: u32) -> u32 {
if dbg!(n <= 1) {
dbg!(1)
} else {
dbg!(n * factorial(n - 1))
}
}
得到的输出:
[src/main.rs:3] n <= 1 = false
[src/main.rs:3] n <= 1 = false
[src/main.rs:3] n <= 1 = false
[src/main.rs:3] n <= 1 = true
[src/main.rs:4] 1 = 1
[src/main.rs:5] n * factorial(n - 1) = 2
[src/main.rs:5] n * factorial(n - 1) = 6
[src/main.rs:5] n * factorial(n - 1) = 24
[src/main.rs:11] factorial(4) = 24
因为dbg!
宏返回正在调试
的值,而不是eprintln!
版的返回()
,不能更改
代码结构.
默认删除jemalloc
Rust1.28
发布了可选择
全局分配器的方法,就开始计划把默认
分配器切换到系统
分配器,并允许你通过crate
使用jemalloc
.在Rust1.32
中,终于完成了这项工作,默认,你获得程序
的系统
分配器.
如果想继续使用jemalloc
,这里.在你的Cargo.toml
中:
jemallocator = "0.1.8"
在仓库
根目录:
#[global_allocator]
static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;
就是这样!如果不需要jemalloc
,不会强加给你,如果确实
需要它,只需几行代码
即可.
最终模块改进
现在叫"统一路径
",它允许以前无效
的导入路径语句按非导入
路径完全相同方式解析.如:
enum Color { Red, Green, Blue }
use Color::*;
此代码以前未编译,因为use
语句必须以super,self
或crate
开头.现在编译器
支持统一路径
,此代码将起作用,并执行期望操作:导入use
语句上方定义
的Color
枚举的变体.
改进宏
首先,添加了新的字面匹配器
,这里:
macro_rules! m {
($lt:literal) => {};
}
fn main() {
m!("some string literal");
}
字面
与任意类型
字面匹配:串字面,数字字面,符字面
.
在2018
版中,也可用macro_rules
宏如下用?
:
macro_rules! bar {
($(a)?) => {}
}
?
匹配模式
的零次或一次
重复,类似*/+
.
稳定库
制作了19
个函数const fn
,且所有整数
数值原语
,现在都提供与字节数组
间带指定
字节序的转换函数
.
六个
函数分别叫to_<endian>_bytes
和from_<endian>_bytes
,其中<endian>
是以下函数之一:
ne
-原生字节序
le
-小端
be
-大端
货物特点
Cargo
的cargo c
为cargo check
的别名,现在允许在注册URL
中使用用户名
.
1.33.0
稳定版
改进const fn
现在,使用const fn
可做更多:
const fn foo((x, y): (u8, u8)) { ... }
//析构模式.
1,let
绑定与可变let
绑定
let x = 1;//绑定
let mut x = 1;//可变绑定.
2,(如x=y
)赋值
和赋值符号
(如x+=y
)式,即使
赋值目标是投影
(如结构字段或索引操作
,如x[3]=42
)
3,式
语句(如3;
)
4,还可在const fn
中如下调用const unsafe fn
:
const unsafe fn foo() -> i32 { 5 }
const fn bar() -> i32 {
unsafe { foo() }
}
固定
两类固定:std::pin::Pin<P>
类型和Unpin
标记特征.std::pin
的核心思想:
有时,要保证对象不会移动
,典型示例
是构建自引用结构
,移动
指向自身指针的对象
会使它们失效,从而导致未定义行为
.
Pin<P>
确保指针
是固定
的.
按_
导入
现在可按_
导入项目.允许导入
特征的实现
,且名字空间
中没有
该名.如
use std::io::Read as _;
//允许,因为模块中只有一个"读取".
pub trait Read {}
稳定库
1,overflowing_{add,sub,mul,shl,shr}
方法,现在是所有数值类型
的常量函数
.
2,rotate_left,rotate_right
和wrapping_{add,sub,mul,shl,shr}
方法,现在是所有数值类型
的常量函数
.
3,is_positive
和is_negative
方法现在是所有整数值
类型的常量函数
.
4,所有NonZero
类型的get
方法现在都是const
.
5,count_ones,count_zeros,leading_zeros,trailing_zeros,swap_bytes,from_be,from_le,to_beto_le
方法,现在对所有数值类型
都是常量.
6,Ipv4Addr::new
现在是const
函数.
此外,这些API
已稳定:
1,unix::FileExt::read_exact_at
和unix::FileExt::write_all_at
.
2,Option::transpose
和Result::transpose
3,convert::identity
4,pin::Pin
和marker::Unpin
(如上)
5,marker::PhantomPinned
6,Vec::resize_with
和VecDeque::resize_with
7,持续时间::as_millis
,持续时间::as_micros
和持续时间::as_nanos
.
在1.34.0
稳定版
在此版本中,Cargo
支持备用
注册.它与crates.io
共存,因此你可编写依赖于crates.io
和自定义注册表中的crate
的软件.
然而,crates.io
上的仓库不能依赖外部
注册.
要使用备用注册,必须添加如下行到.cargo/config
中.可在(~/.cargo/config)
你的主目录中,也可在相对包
目录添加此文件
.
[registries]
my-registry = { index = "https://my-intranet:8080/git/index" }
在Cargo.toml
中指定依赖项时,请用注册表项让Cargo
知道想从备用
注册表中取crate
:
[dependencies]
other-crate = { version = "1.0", registry = "my-registry" }
作为crate
作者,如果想把注册crate
发布到备用表,首先要用cargo login
命令,把认证
令牌保存到~/.cargo/credentials
中:
cargo login --registry=my-registry
然后,可用--registry
标志指示
发布时要使用的注册表
:
cargo publish --registry=my-registry
文档测试中用?
RFC1937
提议增加了对在fnmain(),#[test]
函数和doctests
中使用?
符号的支持,允许它们返回Option<T>
或Result<T,E>
,错误值
会导致fn main()
中的非零
退出码,而在测试
时会导致测试失败
.
此版本中,在doctests
完全支持?
.现在,可在文档测试中编写
以下内容:
/// ```rust
/// use std::io;
/// let mut input = String::new();
/// io::stdin().read_line(&mut input)?;
/// # Ok::<(), io::Error>(())
/// ```
fn my_func() {}
仍必须在文档测试
底部,指定要使用
的错误类型.
自定义属性接受任意令牌流
Rust
中过程宏
可定义使用的自定义属性
.目前,限制为根据指定语法的路径和字面树
,如:
#[foo(bar)]
#[foo = "bar"]
#[foo = 0]
#[foo(bar = true)]
#[foo(bar, baz(quux, foo = "bar"))]
与过程宏
不同,这些助手属性
不能接受分隔符
中的任意令牌流
,因此无法编写#[range(0..10)]
或#[bound(T:MyTrait)]
.过程宏crate
改用串来指定此语法,如#[range("0..10")]
.
在该Rust
版本中,#[attr($tokens)]
自定义属性与宏
一样,现在接受$tokens
中的任意令牌流.
TryFrom
和TryInto
允许易出错
类型转换的TryFrom
和TryInto
特征已稳定.
如,整数
类型的from_be_bytes
和相关带数组方法
,但数据
一般通过切片
读入.手动转换
切片和数组很麻烦.有了新的特征
,就可用.try_into()
内联完成.
let num = u32::from_be_bytes(slice.try_into()?);
对不会失败
的转换(如u8
到u32
),添加了Infallible
类型.这样,允许对所有现有的From
实现全面实现TryFrom
.未来,可能想将Infallible
变成!
(从不)类型.
弃用FN before_exec
,选择unsafe fn pre_exec
在Unix
类系统上,CommandExt::before_exec
函数在调用exec
之前,允许调度要运行的闭包
.
提供的闭包
在分叉
后的子进程
环境中运行.即资源(如文件描述符和内存映射区域
)可能会重复.即,现在可复制非Copy
类型的值到其他
进程中,同时在父进程
中保留
原值.
这样就有可能导致未定义行为
,并破坏了不重复的假设
.
因此,应按不安全
标记该before_exec
函数.该版本的Rust
中,弃用了fn before_exec
,并使用unsafe fn pre_exec
.
调用CommandExt::pre_exec
时,由你确保闭包
不会因无效使用
这些重复项而违反库不变性
.如果你提供的库与before_exec
类似,请同样考虑弃用
并提供不安全
替代方法.
稳定库
在1.34.0
中,扩展了稳定的原子整数类型集
,现在提供了从8位(AtomicU8)
到64
位的有符号和正变体
.
以前,(如NonZeroU8
)非零正整数
类型是稳定的.这使得Option<NonZeroU8>
的大小与u8
相同.在该Rust
版本中,(如NonZeroI8
)签名版本,已稳定下来.
iter::from_fn
和iter::successors
函数已稳定.前者允许从Fn Mut()->Option<T>
构造迭代器
.要从向量
中迭代
弹出元素,现在可编写from_fn(||vec.pop())
.
同时,后者
创建了个每个连续项
都根据前一项
计算的新迭代器
.
此外,这些API
已稳定:
Any::type_id
Error::type_id
slice::sort_by_cached_key
str::escape_debug
str::escape_default
str::escape_unicode
str::split_ascii_whitespace
Instant::checked_add
Instant::checked_sub
SystemTime::checked_add
SystemTime::checked_sub
1.34.1
稳定版修复
以下代码片中,期望
方法需要dep:&D
,但dep
的实际类型是&&D
:
dependencies.iter().filter(|dep| dep.required());
Clippy
错误地建议了.filter(Dependency::required)
,因为借用的差异,编译器拒绝
了.
clippy::missing_const_for_fn
中的误报
修复了missing_const_for_fn
棉绒中的另一个误报.此lint
没有考虑到trait
实现中的函数不能是const fn
.如,给定以下代码片时,触发lint
:
#[derive(PartialEq, Eq)] //警告:是一个`const_fn`
struct Point(isize, isize);
impl std::ops::Add for Point {
type Output = Self;
fn add(self, other: Self) -> Self { //警告:是一个`const_fn`
Point(self.0 + other.0, self.1 + other.1)
}
}
1.34.2
稳定版
SeanMcArthur
报告了个影响标准库
的安全漏洞,该漏洞导致在手动实现Error::type_id
方法返回错误的TypeId
时,Error::downcast
系列方法执行不合理的转换,从而导致越界读取/写入
等安全问题.