【问题标题】:Unable to compile Rust with no_std/lang_items无法使用 no_std/lang_items 编译 Rust
【发布时间】:2015-02-21 17:51:17
【问题描述】:

我正在尝试建立一个与dueboot 非常相似的项目。也就是说,嵌入式 ARM 上的 Rust。现在,我只能编译 Rust 代码,但我无法编译它。

我基本上完全从那个项目中复制了 rust 代码,但我并不完全理解 lang_items 功能。

#![feature(asm)]
#![feature(lang_items)]
#![feature(no_std)]

#![no_std]

use arduino::{init, delay, pinMode, digitalWrite, analogWrite, LOW, HIGH, OUTPUT};
mod arduino;

#[lang="sized"]
trait Sized {}

#[lang="copy"]
trait Copy {}

#[lang="sync"]
trait Sync {}

static PWM:u32 = 2;
static LED:u32 = 11;

#[no_mangle]
pub fn main() {
  // ...
}

尝试按上述方式编译代码,会导致此错误:

main.rs:11:1: 11:15 error: parameter `Self` is never used
main.rs:11 trait Sized {}
           ^~~~~~~~~~~~~~
main.rs:14:1: 14:14 error: parameter `Self` is never used
main.rs:14 trait Copy {}
           ^~~~~~~~~~~~~
main.rs:17:1: 17:14 error: parameter `Self` is never used
main.rs:17 trait Sync {}
           ^~~~~~~~~~~~~
error: aborting due to 3 previous errors

我还尝试注释掉与lang_items 相关的所有行,包括顶部的特征行。这是生成的错误消息:

// more lines of the same message
error: requires `sized` lang_item
error: requires `sized` lang_item
error: requires `sized` lang_item
error: requires `sized` lang_item
error: requires `sized` lang_item
error: aborting due to 54 previous errors

截至昨天,我正在使用 master 构建的 rust。

有什么建议吗?

【问题讨论】:

  • 只是一个疯狂的猜测(根本无法编译您的代码):尝试使这些特征unsafe:pub unsafe trait Copy {}
  • 仍然抱怨parameter 'Self' is never used。抱歉 - 完整的代码在上面的 repo 中,它似乎不适用于最新的 Rust。
  • 您可以尝试使用trait Blah : ::std::marker::MarkerTrait。见:doc.rust-lang.org/std/marker/trait.MarkerTrait.html
  • @BurntSushi5 这有点困难,因为 OP 不能使用 std ;)
  • 我建议复制 MarkerTraitPhantomFn,但这似乎会导致 LLVM 断言。

标签: rust


【解决方案1】:

前几天,Rust 增加了所有类型参数必须出现在 trait 的方法中的规则(RFC 738)。但是由于Sized(以及CopySync)没有自己的任何方法,所以它默认违反了这个规则。

官方的解决方法是将 trait 标记为 PhantomFn,这样可以消除错误:

#![feature(asm)]
#![feature(lang_items)]
#![feature(no_std)]

#![no_std]

use arduino::{init, delay, pinMode, digitalWrite, analogWrite, LOW, HIGH, OUTPUT};
mod arduino;

// Copied from <http://doc.rust-lang.org/core/marker/trait.PhantomFn.html>
#[lang="phantom_fn"]
trait PhantomFn<A: ?Sized, R: ?Sized = ()> {}

#[lang="sized"]
trait Sized: PhantomFn<Self> {}

#[lang="copy"]
trait Copy: PhantomFn<Self> {}

#[lang="sync"]
trait Sync: PhantomFn<Self> {}

static PWM:u32 = 2;
static LED:u32 = 11;

#[no_mangle]
pub fn main() {
  // ...
}

此更改应该使代码再次编译。

附录:什么是 lang 项?

lang 项 是编译器标记为“特殊”的符号。一些例子是:

  • 堆分配器

  • panic 上的展开程序

  • 确保类型安全的类型和特征,例如 SendDropPhantomData

  • 运算符重载的特征,如AddEqDeref

您可以在lang_items.rs 中找到它们的列表。

这些项目对语言的语义至关重要,但在编译器本身中实现是不切实际的。所以我们把它们放在标准库中,用特殊的注解告诉编译器它们在哪里。

现在,虽然您可以自己定义这些项目,但建议改为链接到 core,它会为您声明这些语言项目。但我不确定这对你的设置有多好。

【讨论】:

  • 你能编译这个吗?我得到了:Assertion failed: (isa&lt;X&gt;(Val) &amp;&amp; "cast&lt;Ty&gt;() argument of incompatible type!"), function cast, file /Users/shep/Projects/rust/src/llvm/include/llvm/Support/Casting.h, line 237.
  • 我确实得到了一个最小的示例(没有 Arduino 的东西)来编译——但是没有 Homebrew 也没有 Arduino,我觉得设置整个工具链不值得。此外,我认为断言是正交的,适合单独的问题。
  • 如果您像构建脚本一样将其编译为库 (--crate-type lib),而不是可执行文件,则它可以工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-19
  • 1970-01-01
  • 2021-10-31
  • 1970-01-01
  • 2021-06-07
相关资源
最近更新 更多