我有这个枚举类型:
enum Animal {
Dog(i32),
Cat(u8),
}
Run Code Online (Sandbox Code Playgroud)
现在我有一个将此类型作为参数的函数.我知道(出于某种原因)输入总是一个Cat.我想实现这个目标:
fn count_legs_of_cat(animal: Animal) -> u8 {
if let Animal::Cat(c) = animal { c } else { unreachable!() }
}
Run Code Online (Sandbox Code Playgroud)
我可以写这个更短和/或更惯用的吗?
所以我有以下宏代码我正在尝试调试.我是从Rust Book的"The Deep end"一节中读到的.我重命名宏中的变量,以更密切地关注这篇文章.
我的目标是让程序打印出BCT程序的每一行.我很清楚这是编译器很重.
rustc给我的唯一错误是:
user@debian:~/rust/macros$ rustc --pretty expanded src/main.rs -Z unstable-options > src/main.precomp.rs
src/main.rs:151:34: 151:35 error: no rules expected the token `0`
src/main.rs:151 bct!(0, 1, 1, 1, 0, 0, 0; 1, 0);
Run Code Online (Sandbox Code Playgroud)
我可以采取什么步骤,以找出其中的宏观问题是从哪里来的?
这是我的代码:
fn main() {
{
// "Bitwise Cyclic Tag" automation through macros
macro_rules! bct {
// cmd 0: 0 ... => ...
(0, $($program:tt),* ; $_head:tt)
=> (bct_p!($($program),*, 0 ; ));
(0, $($program:tt),* ; $_head:tt, $($tail:tt),*)
=> …Run Code Online (Sandbox Code Playgroud) 几天前,通过Emscripten对JavaScript进行交叉编译终于在夜间播出.我想以glium这种方式编译项目.但是,许多板条箱中仍然存在许多与Emscripten相关的错误.虽然维护人员通常会快速修复这些错误,但他们并不一定会立即将这些错误修复程序发布到crates.io.
在我的情况下,glium取决于glutin.glutin有一个现在修复的错误,但只在git存储库中,而不是在crates.io. 注意:glutin不是我项目的直接依赖; 只是一个间接的通过glium!
我怎么知道货物使用的glutin存储库作为来源glutin,而不是crates.io?
我想使用https://rust.godbolt.org查看此函数的程序集输出:
fn add(a: u8, b: u8) -> u8 {
a + b
}
Run Code Online (Sandbox Code Playgroud)
在网站上粘贴这个工作正常,但显示了很多组装.鉴于rustc默认情况下在调试模式下编译我的代码,这并不奇怪.当我通过传递-O给编译器在发布模式下编译时,根本没有输出!
我究竟做错了什么?为什么Rust编译器会在发布模式下删除所有内容?
我想看看一个小的Rust函数的程序集输出:
pub fn double(n: u8) -> u8 {
n + n
}
Run Code Online (Sandbox Code Playgroud)
我使用Godbolt Compiler Explorer来生成和查看程序集(-O当然还有标志).它显示了这个输出:
example::double:
push rbp
mov rbp, rsp
add dil, dil
mov eax, edi
pop rbp
ret
Run Code Online (Sandbox Code Playgroud)
现在我有点困惑,因为有这似乎并没有做任何有用的几个指令:push rbp,mov rbp, rsp和pop rbp.根据我的理解,我认为单独执行这三个指令没有任何副作用.那么为什么Rust优化器不会删除那些无用的指令呢?
为了比较,我还测试了一个C++版本:
unsigned char doubleN(unsigned char n) {
return n + n;
}
Run Code Online (Sandbox Code Playgroud)
程序集输出(带-O标志):
doubleN(unsigned char): # @doubleN(unsigned char)
add dil, dil
mov eax, edi
ret
Run Code Online (Sandbox Code Playgroud)
事实上,这里缺少上面那些"无用的"指令,正如我对优化输出所期望的那样.
如果类型是引用,我想有一个工具从类型中删除引用.像这样的东西(伪代码):
remove_ref(i32) == i32
remove_ref(&i32) == i32
remove_ref(&&i32) == i32
remove_ref(&mut i32) == i32
Run Code Online (Sandbox Code Playgroud)
C++ std::remove_reference在标准库中有完全符合我的要求.我尝试在Rust中实现相同的功能,但我无法使其正常工作.现在,在Rust中"输出"类型的唯一方法是关于特征的关联类型(我认为).我试过这样的事情(游乐场):
#![feature(specialization)]
trait RemoveRef {
type WithoutRef;
}
default impl<T> RemoveRef for T {
type WithoutRef = T;
}
impl<'a, T: RemoveRef> RemoveRef for &'a T {
type WithoutRef = T::WithoutRef;
}
Run Code Online (Sandbox Code Playgroud)
事实上,这编译.有希望!(是的,这还没有考虑到可变引用).但是,当我尝试使用它时,一切都会爆炸:
let _: <i32 as RemoveRef>::WithoutRef = 3;
let _: <&i32 as RemoveRef>::WithoutRef = 3;
let _: <&&i32 as RemoveRef>::WithoutRef = 3;
Run Code Online (Sandbox Code Playgroud)
第一行导致"溢出评估要求i32: RemoveRef".另外两行产生错误"特征限制&i32: RemoveRef不满足".我不确定我是否只是不理解这一点,或者是否打破了专业化.(相关:我在这里 …
综观该std::sync::atomic模块,可以看到很多不同的Atomic*类型,如AtomicU32,AtomicI16和更多。这是为什么?
锈病泛型和-在我看来-这将是可能增加一个通用的Atomic<T>,其中T由模块中定义的一些特质界(在Java中上下的命名:Atomicable)。该特征将通过可以以原子方式处理的类型来实现,并且用户可以使用Atomic<u32>而不是AtomicU32。
为什么没有通用名称Atomic<T>?为什么会有许多不同的类型呢?
我很困惑Rust生态系统中用于几个宏观事物的许多术语.有人可以澄清一下哪些宏/语法扩展/编译器插件以及解释这些术语之间的关系?
fn works<'a>(foo: &Option<&'a mut String>, s: &'a mut String) {}
fn error<'a>(foo: &RefCell<Option<&'a mut String>>, s: &'a mut String) {}
let mut s = "hi".to_string();
let foo = None;
works(&foo, &mut s);
// with this, it errors
// let bar = RefCell::new(None);
// error(&bar, &mut s);
s.len();
Run Code Online (Sandbox Code Playgroud)
如果我在注释中添加两行,则会发生以下错误:
error[E0502]: cannot borrow `s` as immutable because it is also borrowed as mutable
--> <anon>:16:5
|
14 | error(&bar, &mut s);
| - mutable borrow occurs here
15 |
16 | s.len(); …Run Code Online (Sandbox Code Playgroud) 在Blandy和Orendorff 的《Programming Rust》的第322页上是这样的说法:
...铁锈...认识到,有一种简单的方法可以将数字从1
n求和:总和始终等于n * (n+1) / 2。
这当然是相当众所周知的等效项,但是编译器如何识别它?我猜这是在LLVM优化过程中进行的,但是LLVM是否以某种方式从第一原理中推导了等效性,或者它只是具有一些可以简化为算术运算的“公共循环计算”?
compiler-construction compiler-optimization rust llvm-codegen
rust ×10
llvm-codegen ×2
assembly ×1
atomic ×1
enums ×1
macros ×1
rust-cargo ×1
rust-macros ×1
x86-64 ×1