官方新闻
【官方讨论】2019年Rustc和RLS战略
官方主要考虑这些问题:
rustc如何帮助实现真正优秀的IDE体验?要达到这个目标,还需要考虑更多的子问题
- rustc如何才能更加易于维护和使用?
- 如何发展rustc的贡献者
- 如何提高rustc创新的步伐
- 如何解析和支持过程宏
- 如何将rustc暴露为更多的库
matklad 一直在重构libsyntax2的工作,将会非常适合过程宏和IDE
还需要改进rustc的增量编译支持,以配合IDE的响应时间。
更进一步提取像Chalk(trait系统)和Polonius(NLL借用检查器)这样的库,将rustc中复杂的问题,提取为单独的库,这些库倾向于遵循具有核心共享代码块以及进行单元测试的包装器的模式。但目前Chalk和Polonius还未投入使用。是否可以将MIR抽出来成为独立库? 还有很多问题需要考虑。
对于RLS来说,未来可能考虑使用查询系统(Query System),希望有更快的响应时间,还必须考虑如何确保RLS得到良好的维护。
该帖子评论区还有很多Niko的想法,感兴趣可以去阅读
模块系统更改已经进入FCP阶段
Rust 2018决定对模块系统进行简化,目前官方在测试它的两种形式:
- Anchored paths,其中use语句始终以外部包名称或关键字开头。 从子模块导入需要一个self::前缀
- Uniform paths,use语句也可以以本地项目名称开头
具体可以在Edtion Guide里查看.
Rust和WebAssembly 本周报告第7期
新工具和项目:
- 用Rust实现的Jczsolve Sudoku Solver(数独求解器),并编译到了wasm,在线示例
- Wasabi,WebAssembly的动态分析框架
- greenwasm, Rust实现的wasm规范(上面已介绍),即wasm引擎
另外还需要人手去做贡献,具体问题查看下面链接
Niko博文 Rust模式系列:为Rc<Vec<T>> 构建迭代器
问题: 给定Rc <Vec <u32 >>的所有权,我们可以编写一个返回impl Iterator <Item = u32>的函数吗?
fn iterate(data: Rc<Vec<u32>>) -> impl Iterator<Item = u32> {
... // what we want to write!
}
以下方案是错的:
fn iterate(data: Rc<Vec<u32>>) -> impl Iterator<Item = u32> {
data.iter().cloned() // `data` would be dropped while still borrowed
}
等价于:
fn iterate(data: Rc<Vec<u32>>) -> impl Iterator<Item = u32> {
let iterator = Iterator::new(&data); // <-- call to iter() returns this
let cloned_iterator = ClonedIterator::new(iterator); <-- call to cloned()
cloned_iterator
}
Rc<Vec<u32>>的问题在于,只拥有Vec<u32>的所有权,只能获得&Vec<u32>的引用,并且其生命周期只永远不会超过Rec<Vec<u32>>,所以导致,永远无法在数据上返回迭代器。
要编写这个函数,我们需要找到一些方法将数据的所有权返回给调用者,同时仍然产生一个迭代器。
fn iterate(data: Rc<Vec<u32>>) -> impl Iterator<Item = u32> {
let len = data.len();
(0..len).map(move |i| data[i])
}
这里正好因为当前Rc里的长度是固定的,可以使用这个技巧应用于其他类型。
fn iterate(data: Rc<Vec<String>>) -> impl Iterator<Item = String> {
let len = data.len();
(0..len).map(move |i| data[i].clone())
}
但要注意使用clone,还是所有权的问题。
未来如何扩展语言来解决这些问题?
- 支持自引用。自引用可以解决类似的问题,延长生命周期的使用。等NLL工作结束以后,就会考虑自引用如何在Rust中建模的问题了。
- 辅助值。 基于辅助值可以实现这样的函数签名
fn iterate<T>(data: Rc<Vec<T>>) -> impl Iterator<Item = &'aux T>, 生命周期参数可以借助辅助值aux来给予。
编译器之书新增了MIR借用检查章节内容
社区新闻
Tower Web: 扩展中间件堆栈
tower-web 0.2.2发布。基于tower stack构建的HTTP Web框架。 这篇文章主要介绍tower-web的中间件。
pub trait Middleware<S> {
/// The wrapped service request type
type Request;
/// The wrapped service response type
type Response;
/// The wrapped service's error type
type Error;
/// The wrapped service
type Service: Service<Request = Self::Request,
Response = Self::Response,
Error = Self::Error>;
/// Wrap the given service with the middleware, returning a new service
/// that has been decorated with the middleware.
fn wrap(&self, inner: S) -> Self::Service;
}
如果要实现一个记录日志的中间件,需要:
- 实现LogService,处理日志记录,实现Service trait
- 实现LogMiddleware,将日志记录添加到中间件堆栈中, 实现Middleware trait
- ResponseFuture ,如果中间件需要响应请求时可以采取的操作。
tower-web的中间件计划提供标准化的服务。接下来会把中间件提取出独立的库,然后考虑tower-web和wrap合并的计划。
请务必小心Travis的Rust缓存
Travis允许在.travis.yml中设置cache:cargo以启用Rust项目的缓存
缓存很棒:它避免了必须一直重建所有依赖项,从而加快构建速度。
travis文档说明了缓存:
请注意,我们的缓存不是网络本地,它仍然绑定到网络带宽和DNS解析。这会影响您可以存储在缓存中的内容。如果您在缓存中存储大于几百兆的存档,则不太可能看到速度大幅提升。
作者查看了他本地的缓存,大概有4.2G,可想而知,他的Travis缓存大概有5-7个GB之多。主要是因为Travis里缓存了target/ 和 .cargo/这些目录文件。缓存逐渐变大一般是两个原因:
- rustc是增量编译,其过程会产生大量的构建「副产品」,这些「副产品」会由Travis缓存,这些东西基本上没有用,但会积累。
- 过时的依赖库积累。有的库发了新版本,旧版本依旧会被Travis缓存。
解决办法:
target /不值得缓存- 〜/.cargo/bin/ 值得缓存
- 〜/ .cargo / registry / 不值得缓存
所以修改.travis.yml文件
# Need to cache the whole `.cargo` directory to keep .crates.toml for
# cargo-update to work
cache:
directories:
- /home/travis/.cargo
# But don't cache the cargo registry
before_cache:
- rm -rf /home/travis/.cargo/registry
作者经过这样设置,Travis缓存下降到只有68M。
这个经验不一定适合你的项目,请看情况而定。
syn库发布了0.15
提供了一个新的解析API,可以在语法无效的宏输入情况下智能地报告错误。
这个解析API很重要。因为在下周发布的Rust 1.29中将稳定 函数调用式的过程宏(functionlike!(...) )。
到目前为止,过程宏只能用作自定义派生,编译器为此保证语法上有效的输入,因此错误报告不是宏的责任。但是对于函数调用式的宏,调用者可以胡乱往里塞东西,所以必须需要有这样一个错误提示的功能。
随着向新解析API的过渡,syn将放弃使用nom样式的解析器组合子宏,转而使用普通的Rust函数和控制流。
也就是说,从0.15开始,就没有syn::synom::Synom这个trait了,只有syn::parse::Parse了。
【油管】Rust和Node.js语言设计: 关于Async编程的两个故事
前奏: 为了解决C10K问题
- 线程 ,太昂贵
- Reactor模式, Node.js使用的事件驱动库libuv就是Reactor模式,核心是提供了一个event-loop
Node.js语言设计 :
- 纯事件驱动
- 事件编程是其主要范式
- 为脚本语言构建并发编程无阻塞基础设施,基于libuv
- 单线程
Rust语言设计:
- 系统级编程语言,可直接和操作系统打交道
- Futures + mio = tokio
- Tokio实现了Reactor模式
使用gfx-rs实现的Veloren像素游戏世界
The voxel world of Veloren, written in Rust and rendered using gfx-rs
Datalust公司使用Rust
该公司构建的日志服务Seq5,最近引入了Rust,实现了Seq Native Storage。它是一种新的跨平台,特定于日志数据的存储引擎。
该文章记录了他们公司的技术栈,以及为什么需要重新构建存储引擎,以及从Rust中得到了什么?
在gfx-portability的Metal后端上运行RPCS3和Dolphin
- RPCS3是一个开源的Sony PlayStation 3仿真器,经过gfx-rs团队的努力,现在可以在RPCS3中渲染游戏。
- Dolphin是最近两款任天堂视频游戏机的模拟器:GameCube和Wii。
Ripgrep 0.10.0 发布
pwnies库 展示了docs.rs的XSS攻击
docs.rs允许任意包执行js,可被看作是xss的一种形式。但在docs.rs影响应该不大
onur的维护者回复:
docs.rs上线第一天我就知道这个问题了。但对我来说,这根本不是什么问题,它只是rustdoc的一个很好的功能。并且docs.rs没有使用任何类型的私人信息(实际上docs.rs根本没有使用任何cookie),因此实际上没有任何东西可以窃取XSS漏洞。
如果有人滥用这个并以某种方式伤害用户,我们基本上可以将该箱子的所有者列入黑名单。
博客与库
Rust的冒险:Futures 和 Tokio
该文章主要探讨了Futures和Tokio的运行时模型,值得阅读
LLVM如何优化函数
本文讲解LLVM优化的工作机制,值得仔细品读
Rust中可行性函子的探讨
比较学术的文章,作者试图在现有Rust实现基础上来探讨实现Monad抽象的可能性
L1 缓存和内存提取的时间差
本文测量了 内存中提取和L1缓存中提取的速度。使用Rust的内联汇编功能,而不是编写纯汇编代码。
结论:
从缓存中进行数据访问可以节省大约190个处理器周期。 结果当然会随处理器架构而变化。 Debug和Release模式方面没有太大区别,因为汇编代码没有被编译器优化。
ion:来自Redox的强大Shell
完全使用Rust实现,功能简单但强大,而且安全。性能超过dash,虽然和Redox一起发布,但是也可以用于其他*nix平台
不可思议的Rust原生类型
fn main(){
println!(“{}”,8.to_string() )
}
这段代码是否可以运行?请按你的直觉说出答案。
熟悉Rust的人,都知道,这个可以运行,因为其实是数字类型实现了ToString trait。
impl<T: fmt::Display + ?Sized> ToString for T
但是作者对此表示惊奇,还对比了Java、Python、C的处理原生类型的方式
他生成了相关调用的汇编代码:
; Cool stuff right here
call <T as alloc::string::ToString>::to_string@PLT
这篇文章让我看到了一个学习Rust的反例: 以传统编程语言的思维去学习Rust。
我真想建议他,要不然先看看trait ? 事实上已经有朋友在评论里告诉他了。
「油管 Hello Rust系列」Go vs Rust: 并发与竞态条件
新库 spirit:帮助创建Unix守护进程
使用教程
新库failsafe-rs
Rust实现的熔断器(circuit breaker),可以防止一个应用不断地去尝试一个很可能失败的操作。
Rust实现的ANSI Sql词法分析器和解析器
又一个文本编辑器实现
Py-Spy: Python程序的抽样分析器。
可视化Python程序中耗费时间的部分,而无需重新启动程序或以任何方式修改代码,也不会以任何方式中断正在运行的程序。
Facebook政治广告收集器
在浏览facebook的时候使用此插件,后台脚本会收集看到的广告。该扩展程序会向用户展示这些广告,并要求他们决定这些广告是否属于政治广告。在服务端,我们使用这些评级来训练一个朴素的贝叶斯分类器,然后自动评估我们收集的其他广告。该扩展程序还要求服务器提供分类器认为是政治性的最新广告,以便用户可以看到他们没有看到的政治广告。我们小心翼翼地通过不向我们的后端服务器发送识别信息来保护用户的隐私。
该项目后端基于Rust,现在整个项目开源,包括前端的浏览器插件,可以作为一个生产案例。