从这个简单的C程序开始:
void nothing(void) {}
int main() {
int i;
for (i = 0; i < 10; ++i) {
nothing();
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我的传递输出如下:
注意:IR语句为绿色.
; Function Attrs: nounwind readnone ssp uwtable
define void @nothing() #0 {
entry:
ret void
}
; Function Attrs: nounwind readnone ssp uwtable
define i32 @main() #0 {
entry:
ret i32 0
}
Run Code Online (Sandbox Code Playgroud)
问:使用O3其认为是最高级别的优化,为什么没有nothing功能尚未消除的死代码?
我很困惑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) 我有一个功能,Rust的/ LLVM的优化失败并导致恐慌(在发布版本中),而未优化的代码(调试版本)工作正常.如果我比较生成的汇编代码,我甚至无法理解优化器试图完成的任务.(原因可能是这个函数使用内联汇编程序.)
有没有办法告诉Rust在优化过程中单独保留某些功能,还是必须关闭所有优化?
这是具体功能:
#[naked]
pub extern "C" fn dispatch_svc(){
Cpu::save_context();
let mut nr: u32 = 0;
unsafe {
asm!("ldr r0, [lr, #-4]
bic $0, r0, #0xff000000":"=r"(nr)::"r0":"volatile")
};
swi_service_routine(nr);
Cpu::restore_context_and_return();
}
Run Code Online (Sandbox Code Playgroud) 我有一个Box<dyn Any>,我知道基础类型,所以我想在Box::downcast()(源)中优化测试.
首先我试过std::hint::unreachable_unchecked():
pub unsafe fn downcast() -> Box<i32> {
let value = any();
if let Ok(value) = value.downcast() {
value
} else {
std::hint::unreachable_unchecked()
}
}
Run Code Online (Sandbox Code Playgroud)
和
pub unsafe fn downcast() -> Box<i32> {
any().downcast().map_err(|_| std::hint::unreachable_unchecked()).unwrap()
}
Run Code Online (Sandbox Code Playgroud)
与rustc -C opt-level=3两个结果在该(40行中省略):
example::downcast:
push rbx
sub rsp, 16
call any@PLT
mov rbx, rax
mov qword ptr [rsp], rax
mov qword ptr [rsp + 8], rdx
mov rdi, rax
call qword ptr …Run Code Online (Sandbox Code Playgroud) optimization assembly compiler-optimization rust llvm-codegen
我正在编写一个程序宏,它工作正常,但我无法以符合人体工程学的方式报告错误.使用panic!"工作"但不优雅,并且不会很好地向用户显示错误消息.
我知道我可以在解析a时报告错误TokenStream,但是在解析之后我需要在遍历AST时产生错误.
宏调用如下所示:
attr_test! {
#[bool]
FOO
}
Run Code Online (Sandbox Code Playgroud)
并应输出:
const FOO: bool = false;
Run Code Online (Sandbox Code Playgroud)
这是宏代码:
extern crate proc_macro;
use quote::quote;
use syn::parse::{Parse, ParseStream, Result};
use syn::{Attribute, parse_macro_input, Ident, Meta};
struct AttrTest {
attributes: Vec<Attribute>,
name: Ident,
}
impl Parse for AttrTest {
fn parse(input: ParseStream) -> Result<Self> {
Ok(AttrTest {
attributes: input.call(Attribute::parse_outer)?,
name: input.parse()?,
})
}
}
#[proc_macro]
pub fn attr_test(tokens: proc_macro::TokenStream) -> proc_macro::TokenStream {
let test: AttrTest = parse_macro_input!(tokens);
let name = test.name;
let first_att …Run Code Online (Sandbox Code Playgroud) 我有个特质Foo。如果那些实现者实现了另一个特征(Clone在本示例中),我想强迫实现者定义一个方法。我的想法(游乐场):
trait Foo {
// Note: in my real application, the trait has other methods as well,
// so I can't simply add `Clone` as super trait
fn foo(&self)
where
Self: Clone;
}
struct NoClone;
impl Foo for NoClone {}
Run Code Online (Sandbox Code Playgroud)
可悲的是,这导致:
error[E0046]: not all trait items implemented, missing: `foo`
--> src/lib.rs:8:1
|
2 | / fn foo(&self)
3 | | where
4 | | Self: Clone;
| |____________________- `foo` from trait
... …Run Code Online (Sandbox Code Playgroud) 我有以下代码(游乐场):
// Two dummy functions, both with the signature `fn(u32) -> bool`
fn foo(x: u32) -> bool {
x % 2 == 0
}
fn bar(x: u32) -> bool {
x == 27
}
fn call_both<F>(a: F, b: F)
where
F: Fn(u32) -> bool,
{
a(5);
b(5);
}
fn main() {
call_both(foo, bar); // <-- error
}
Run Code Online (Sandbox Code Playgroud)
对我来说,它看起来这应该是编译foo和bar具有相同的签名:fn(u32) -> bool.然而,我收到以下错误:
error[E0308]: mismatched types
--> src/main.rs:20:20
|
20 | call_both(foo, bar);
| ^^^ …Run Code Online (Sandbox Code Playgroud) 我有一个非常大的结构(在堆上和堆栈上),我在函数中使用。大多数时候,我想要该结构的一个简单变量,因为我直接对大结构进行操作。然而,在某一时刻,我被迫(通过函数签名)将此结构传递到切片内部。
struct VeryBig(Vec<String>, [u64; 50]);
fn takes_slice(_: &[VeryBig]) {}
fn main() {
let foo = VeryBig(vec!["Ferris".to_string(); 100], [27; 50]);
// Use `foo` directly a bunch of times
takes_slice(&foo); // <-- mismatched type
// Use `foo` directly a bunch of times
}
Run Code Online (Sandbox Code Playgroud)
这显然并且可以理解地导致了这个错误:
error[E0308]: mismatched types
--> src/main.rs:10:17
|
10 | takes_slice(&foo); // <-- mismatched type
| ^^^^ expected slice, found struct `VeryBig`
|
= note: expected type `&[VeryBig]`
found type `&VeryBig`
Run Code Online (Sandbox Code Playgroud)
所以我想知道:解决这个问题的最佳方法是什么?我可以只制作foo一个[VeryBig; 1],但这意味着我必须在foo[0] …
在我的项目的相当低级的部分中,函数接收可变的原始数据切片(&mut [u32]在这种情况下)。此数据应以小端序写入作者。
现在,仅此一项就不成问题,但是所有这些必须快速。我评估了我的应用程序,并将其确定为关键路径之一。特别是,如果不需要更改字节序(因为我们已经在一个小的字节序系统上),那么就不会有任何开销。
这是我的代码(Playground):
use std::{io, mem, slice};
fn write_data(mut w: impl io::Write, data: &mut [u32]) -> Result<(), io::Error> {
adjust_endianness(data);
// Is this safe?
let bytes = unsafe {
let len = data.len() * mem::size_of::<u32>();
let ptr = data.as_ptr() as *const u8;
slice::from_raw_parts(ptr, len)
};
w.write_all(bytes)
}
fn adjust_endianness(_: &mut [u32]) {
// implementation omitted
}
Run Code Online (Sandbox Code Playgroud)
adjust_endianness更改位置的字节序(这很好,因为错误的字节序u32是垃圾,但仍然是有效的u32)。
该代码有效,但关键问题是:这样安全吗?特别是,在某个时刻,data并且bytes两者都存在,它们是同一数据的一个可变且一个不变的切片。听起来很不好,对吧?
另一方面,我可以这样做:
let bytes = &data[..];
Run Code Online (Sandbox Code Playgroud)
这样,我也有这两个方面。所不同的只是 …
rust ×9
llvm-codegen ×3
optimization ×2
assembly ×1
c ×1
clang ×1
llvm-clang ×1
llvm-ir ×1
macros ×1
rust-macros ×1
slice ×1
traits ×1
unsafe ×1