1
0
mirror of https://github.com/google/comprehensive-rust.git synced 2025-06-09 19:07:30 +02:00

Updates for Rust 1.82 (#2449)

Rust 1.82 adds `&raw` expressions, and marks some attributes as unsafe.
This commit is contained in:
Andrew Walbran 2024-11-01 07:39:56 +00:00 committed by GitHub
parent 2bba470415
commit f8882190f3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
24 changed files with 100 additions and 72 deletions

View File

@ -55,6 +55,9 @@ jobs:
- name: Setup Rust cache - name: Setup Rust cache
uses: ./.github/workflows/setup-rust-cache uses: ./.github/workflows/setup-rust-cache
- name: Update Rust
run: rustup update
- name: Build Rust code - name: Build Rust code
run: cargo build run: cargo build
@ -89,7 +92,9 @@ jobs:
sudo apt install gcc-aarch64-linux-gnu sudo apt install gcc-aarch64-linux-gnu
- name: Install toolchain - name: Install toolchain
run: rustup target add ${{ matrix.target }} run: |
rustup update
rustup target add ${{ matrix.target }}
- name: Build Rust code - name: Build Rust code
working-directory: ${{ matrix.directory }} working-directory: ${{ matrix.directory }}
@ -140,6 +145,9 @@ jobs:
sudo apt update sudo apt update
sudo apt install gettext sudo apt install gettext
- name: Update Rust
run: rustup update
- name: Install mdbook - name: Install mdbook
uses: ./.github/workflows/install-mdbook uses: ./.github/workflows/install-mdbook

View File

@ -20,7 +20,8 @@ use jni::sys::jstring;
use jni::JNIEnv; use jni::JNIEnv;
/// HelloWorld::hello method implementation. /// HelloWorld::hello method implementation.
#[no_mangle] // SAFETY: There is no other global function of this name.
#[unsafe(no_mangle)]
pub extern "system" fn Java_HelloWorld_hello( pub extern "system" fn Java_HelloWorld_hello(
mut env: JNIEnv, mut env: JNIEnv,
_class: JClass, _class: JClass,

View File

@ -6,14 +6,13 @@ Similarly, you can export Rust functions and call them from C.
You can do it by hand if you want: You can do it by hand if you want:
```rust ```rust
extern "C" { unsafe extern "C" {
fn abs(x: i32) -> i32; safe fn abs(x: i32) -> i32;
} }
fn main() { fn main() {
let x = -42; let x = -42;
// SAFETY: `abs` doesn't have any safety requirements. let abs_x = abs(x);
let abs_x = unsafe { abs(x) };
println!("{x}, {abs_x}"); println!("{x}, {abs_x}");
} }
``` ```

View File

@ -3,14 +3,13 @@
We can declare external functions by hand: We can declare external functions by hand:
```rust ```rust
extern "C" { unsafe extern "C" {
fn abs(x: i32) -> i32; safe fn abs(x: i32) -> i32;
} }
fn main() { fn main() {
let x = -42; let x = -42;
// SAFETY: `abs` doesn't have any safety requirements. let abs_x = abs(x);
let abs_x = unsafe { abs(x) };
println!("{x}, {abs_x}"); println!("{x}, {abs_x}");
} }
``` ```

View File

@ -42,8 +42,8 @@ Build, push, and run the binary on your device:
<details> <details>
`#[no_mangle]` disables Rust's usual name mangling, so the exported symbol will `#[unsafe(no_mangle)]` disables Rust's usual name mangling, so the exported
just be the name of the function. You can also use symbol will just be the name of the function. You can also use
`#[export_name = "some_name"]` to specify whatever name you want. `#[unsafe(export_name = "some_name")]` to specify whatever name you want.
</details> </details>

View File

@ -19,7 +19,8 @@
use std::os::raw::c_int; use std::os::raw::c_int;
/// Analyze the numbers. /// Analyze the numbers.
#[no_mangle] // SAFETY: There is no other global function of this name.
#[unsafe(no_mangle)]
pub extern "C" fn analyze_numbers(x: c_int, y: c_int) { pub extern "C" fn analyze_numbers(x: c_int, y: c_int) {
if x < y { if x < y {
println!("x ({x}) is smallest!"); println!("x ({x}) is smallest!");

View File

@ -8,7 +8,7 @@ Now let's use the new `Registers` struct in our driver.
<details> <details>
- Note the use of `addr_of!` / `addr_of_mut!` to get pointers to individual - Note the use of `&raw const` / `&raw mut` to get pointers to individual fields
fields without creating an intermediate reference, which would be unsound. without creating an intermediate reference, which would be unsound.
</details> </details>

View File

@ -17,49 +17,57 @@ use log::error;
use smccc::psci::system_off; use smccc::psci::system_off;
use smccc::Hvc; use smccc::Hvc;
#[no_mangle] // SAFETY: There is no other global function of this name.
#[unsafe(no_mangle)]
extern "C" fn sync_exception_current(_elr: u64, _spsr: u64) { extern "C" fn sync_exception_current(_elr: u64, _spsr: u64) {
error!("sync_exception_current"); error!("sync_exception_current");
system_off::<Hvc>().unwrap(); system_off::<Hvc>().unwrap();
} }
#[no_mangle] // SAFETY: There is no other global function of this name.
#[unsafe(no_mangle)]
extern "C" fn irq_current(_elr: u64, _spsr: u64) { extern "C" fn irq_current(_elr: u64, _spsr: u64) {
error!("irq_current"); error!("irq_current");
system_off::<Hvc>().unwrap(); system_off::<Hvc>().unwrap();
} }
#[no_mangle] // SAFETY: There is no other global function of this name.
#[unsafe(no_mangle)]
extern "C" fn fiq_current(_elr: u64, _spsr: u64) { extern "C" fn fiq_current(_elr: u64, _spsr: u64) {
error!("fiq_current"); error!("fiq_current");
system_off::<Hvc>().unwrap(); system_off::<Hvc>().unwrap();
} }
#[no_mangle] // SAFETY: There is no other global function of this name.
#[unsafe(no_mangle)]
extern "C" fn serr_current(_elr: u64, _spsr: u64) { extern "C" fn serr_current(_elr: u64, _spsr: u64) {
error!("serr_current"); error!("serr_current");
system_off::<Hvc>().unwrap(); system_off::<Hvc>().unwrap();
} }
#[no_mangle] // SAFETY: There is no other global function of this name.
#[unsafe(no_mangle)]
extern "C" fn sync_lower(_elr: u64, _spsr: u64) { extern "C" fn sync_lower(_elr: u64, _spsr: u64) {
error!("sync_lower"); error!("sync_lower");
system_off::<Hvc>().unwrap(); system_off::<Hvc>().unwrap();
} }
#[no_mangle] // SAFETY: There is no other global function of this name.
#[unsafe(no_mangle)]
extern "C" fn irq_lower(_elr: u64, _spsr: u64) { extern "C" fn irq_lower(_elr: u64, _spsr: u64) {
error!("irq_lower"); error!("irq_lower");
system_off::<Hvc>().unwrap(); system_off::<Hvc>().unwrap();
} }
#[no_mangle] // SAFETY: There is no other global function of this name.
#[unsafe(no_mangle)]
extern "C" fn fiq_lower(_elr: u64, _spsr: u64) { extern "C" fn fiq_lower(_elr: u64, _spsr: u64) {
error!("fiq_lower"); error!("fiq_lower");
system_off::<Hvc>().unwrap(); system_off::<Hvc>().unwrap();
} }
#[no_mangle] // SAFETY: There is no other global function of this name.
#[unsafe(no_mangle)]
extern "C" fn serr_lower(_elr: u64, _spsr: u64) { extern "C" fn serr_lower(_elr: u64, _spsr: u64) {
error!("serr_lower"); error!("serr_lower");
system_off::<Hvc>().unwrap(); system_off::<Hvc>().unwrap();

View File

@ -29,7 +29,8 @@ use smccc::Hvc;
/// Base address of the primary PL011 UART. /// Base address of the primary PL011 UART.
const PL011_BASE_ADDRESS: *mut u32 = 0x900_0000 as _; const PL011_BASE_ADDRESS: *mut u32 = 0x900_0000 as _;
#[no_mangle] // SAFETY: There is no other global function of this name.
#[unsafe(no_mangle)]
extern "C" fn main(x0: u64, x1: u64, x2: u64, x3: u64) { extern "C" fn main(x0: u64, x1: u64, x2: u64, x3: u64) {
// SAFETY: `PL011_BASE_ADDRESS` is the base address of a PL011 device, and // SAFETY: `PL011_BASE_ADDRESS` is the base address of a PL011 device, and
// nothing else accesses that address range. // nothing else accesses that address range.

View File

@ -29,7 +29,8 @@ use smccc::Hvc;
/// Base address of the primary PL011 UART. /// Base address of the primary PL011 UART.
const PL011_BASE_ADDRESS: *mut u32 = 0x900_0000 as _; const PL011_BASE_ADDRESS: *mut u32 = 0x900_0000 as _;
#[no_mangle] // SAFETY: There is no other global function of this name.
#[unsafe(no_mangle)]
extern "C" fn main(x0: u64, x1: u64, x2: u64, x3: u64) { extern "C" fn main(x0: u64, x1: u64, x2: u64, x3: u64) {
// SAFETY: `PL011_BASE_ADDRESS` is the base address of a PL011 device, and // SAFETY: `PL011_BASE_ADDRESS` is the base address of a PL011 device, and
// nothing else accesses that address range. // nothing else accesses that address range.

View File

@ -29,7 +29,8 @@ use smccc::Hvc;
/// Base address of the primary PL011 UART. /// Base address of the primary PL011 UART.
const PL011_BASE_ADDRESS: *mut u8 = 0x900_0000 as _; const PL011_BASE_ADDRESS: *mut u8 = 0x900_0000 as _;
#[no_mangle] // SAFETY: There is no other global function of this name.
#[unsafe(no_mangle)]
extern "C" fn main(x0: u64, x1: u64, x2: u64, x3: u64) { extern "C" fn main(x0: u64, x1: u64, x2: u64, x3: u64) {
// SAFETY: `PL011_BASE_ADDRESS` is the base address of a PL011 device, and // SAFETY: `PL011_BASE_ADDRESS` is the base address of a PL011 device, and
// nothing else accesses that address range. // nothing else accesses that address range.

View File

@ -23,7 +23,8 @@ mod exceptions;
const PSCI_SYSTEM_OFF: u32 = 0x84000008; const PSCI_SYSTEM_OFF: u32 = 0x84000008;
#[no_mangle] // SAFETY: There is no other global function of this name.
#[unsafe(no_mangle)]
extern "C" fn main(_x0: u64, _x1: u64, _x2: u64, _x3: u64) { extern "C" fn main(_x0: u64, _x1: u64, _x2: u64, _x3: u64) {
// SAFETY: this only uses the declared registers and doesn't do anything // SAFETY: this only uses the declared registers and doesn't do anything
// with memory. // with memory.

View File

@ -13,7 +13,6 @@
// limitations under the License. // limitations under the License.
use core::fmt::{self, Write}; use core::fmt::{self, Write};
use core::ptr::{addr_of, addr_of_mut};
// ANCHOR: Flags // ANCHOR: Flags
use bitflags::bitflags; use bitflags::bitflags;
@ -124,7 +123,7 @@ impl Uart {
// of a PL011 device which is appropriately mapped. // of a PL011 device which is appropriately mapped.
unsafe { unsafe {
// Write to the TX buffer. // Write to the TX buffer.
addr_of_mut!((*self.registers).dr).write_volatile(byte.into()); (&raw mut (*self.registers).dr).write_volatile(byte.into());
} }
// Wait until the UART is no longer busy. // Wait until the UART is no longer busy.
@ -139,7 +138,7 @@ impl Uart {
} else { } else {
// SAFETY: We know that self.registers points to the control // SAFETY: We know that self.registers points to the control
// registers of a PL011 device which is appropriately mapped. // registers of a PL011 device which is appropriately mapped.
let data = unsafe { addr_of!((*self.registers).dr).read_volatile() }; let data = unsafe { (&raw const (*self.registers).dr).read_volatile() };
// TODO: Check for error conditions in bits 8-11. // TODO: Check for error conditions in bits 8-11.
Some(data as u8) Some(data as u8)
} }
@ -148,7 +147,7 @@ impl Uart {
fn read_flag_register(&self) -> Flags { fn read_flag_register(&self) -> Flags {
// SAFETY: We know that self.registers points to the control registers // SAFETY: We know that self.registers points to the control registers
// of a PL011 device which is appropriately mapped. // of a PL011 device which is appropriately mapped.
unsafe { addr_of!((*self.registers).fr).read_volatile() } unsafe { (&raw const (*self.registers).fr).read_volatile() }
} }
} }
// ANCHOR_END: Uart // ANCHOR_END: Uart

View File

@ -20,8 +20,8 @@ for all these functions.)
inline assembly code, and ignore its contents afterwards. We need to use inline assembly code, and ignore its contents afterwards. We need to use
`inout` rather than `in` because the call could potentially clobber the `inout` rather than `in` because the call could potentially clobber the
contents of the registers. contents of the registers.
- This `main` function needs to be `#[no_mangle]` and `extern "C"` because it is - This `main` function needs to be `#[unsafe(no_mangle)]` and `extern "C"`
called from our entry point in `entry.S`. because it is called from our entry point in `entry.S`.
- `_x0``_x3` are the values of registers `x0``x3`, which are conventionally - `_x0``_x3` are the values of registers `x0``x3`, which are conventionally
used by the bootloader to pass things like a pointer to the device tree. used by the bootloader to pass things like a pointer to the device tree.
According to the standard aarch64 calling convention (which is what According to the standard aarch64 calling convention (which is what

View File

@ -2,7 +2,7 @@
- Use [`pointer::read_volatile`] and [`pointer::write_volatile`]. - Use [`pointer::read_volatile`] and [`pointer::write_volatile`].
- Never hold a reference. - Never hold a reference.
- Use [`addr_of!`] to get fields of structs without creating an intermediate - Use `&raw` to get fields of structs without creating an intermediate
reference. reference.
[`pointer::read_volatile`]: https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.read_volatile [`pointer::read_volatile`]: https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.read_volatile
@ -19,7 +19,8 @@
- Some existing crates for volatile access to hardware do hold references, but - Some existing crates for volatile access to hardware do hold references, but
this is unsound. Whenever a reference exist, the compiler may choose to this is unsound. Whenever a reference exist, the compiler may choose to
dereference it. dereference it.
- Use the `addr_of!` macro to get struct field pointers from a pointer to the - Use `&raw` to get struct field pointers from a pointer to the struct.
struct. - For compatibility with old versions of Rust you can use the [`addr_of!`] macro
instead.
</details> </details>

View File

@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#[link_section = ".vector_table.interrupts"] #[unsafe(link_section = ".vector_table.interrupts")]
#[no_mangle] // SAFETY: There is no other global variable of this name.
#[unsafe(no_mangle)]
pub static __INTERRUPTS: [usize; 1] = [0]; pub static __INTERRUPTS: [usize; 1] = [0];

View File

@ -17,13 +17,15 @@ use log::{error, info, trace};
use smccc::psci::system_off; use smccc::psci::system_off;
use smccc::Hvc; use smccc::Hvc;
#[no_mangle] // SAFETY: There is no other global function of this name.
#[unsafe(no_mangle)]
extern "C" fn sync_exception_current(_elr: u64, _spsr: u64) { extern "C" fn sync_exception_current(_elr: u64, _spsr: u64) {
error!("sync_exception_current"); error!("sync_exception_current");
system_off::<Hvc>().unwrap(); system_off::<Hvc>().unwrap();
} }
#[no_mangle] // SAFETY: There is no other global function of this name.
#[unsafe(no_mangle)]
extern "C" fn irq_current(_elr: u64, _spsr: u64) { extern "C" fn irq_current(_elr: u64, _spsr: u64) {
trace!("irq_current"); trace!("irq_current");
let intid = let intid =
@ -31,37 +33,43 @@ extern "C" fn irq_current(_elr: u64, _spsr: u64) {
info!("IRQ {intid:?}"); info!("IRQ {intid:?}");
} }
#[no_mangle] // SAFETY: There is no other global function of this name.
#[unsafe(no_mangle)]
extern "C" fn fiq_current(_elr: u64, _spsr: u64) { extern "C" fn fiq_current(_elr: u64, _spsr: u64) {
error!("fiq_current"); error!("fiq_current");
system_off::<Hvc>().unwrap(); system_off::<Hvc>().unwrap();
} }
#[no_mangle] // SAFETY: There is no other global function of this name.
#[unsafe(no_mangle)]
extern "C" fn serr_current(_elr: u64, _spsr: u64) { extern "C" fn serr_current(_elr: u64, _spsr: u64) {
error!("serr_current"); error!("serr_current");
system_off::<Hvc>().unwrap(); system_off::<Hvc>().unwrap();
} }
#[no_mangle] // SAFETY: There is no other global function of this name.
#[unsafe(no_mangle)]
extern "C" fn sync_lower(_elr: u64, _spsr: u64) { extern "C" fn sync_lower(_elr: u64, _spsr: u64) {
error!("sync_lower"); error!("sync_lower");
system_off::<Hvc>().unwrap(); system_off::<Hvc>().unwrap();
} }
#[no_mangle] // SAFETY: There is no other global function of this name.
#[unsafe(no_mangle)]
extern "C" fn irq_lower(_elr: u64, _spsr: u64) { extern "C" fn irq_lower(_elr: u64, _spsr: u64) {
error!("irq_lower"); error!("irq_lower");
system_off::<Hvc>().unwrap(); system_off::<Hvc>().unwrap();
} }
#[no_mangle] // SAFETY: There is no other global function of this name.
#[unsafe(no_mangle)]
extern "C" fn fiq_lower(_elr: u64, _spsr: u64) { extern "C" fn fiq_lower(_elr: u64, _spsr: u64) {
error!("fiq_lower"); error!("fiq_lower");
system_off::<Hvc>().unwrap(); system_off::<Hvc>().unwrap();
} }
#[no_mangle] // SAFETY: There is no other global function of this name.
#[unsafe(no_mangle)]
extern "C" fn serr_lower(_elr: u64, _spsr: u64) { extern "C" fn serr_lower(_elr: u64, _spsr: u64) {
error!("serr_lower"); error!("serr_lower");
system_off::<Hvc>().unwrap(); system_off::<Hvc>().unwrap();

View File

@ -50,7 +50,8 @@ const PL031_BASE_ADDRESS: *mut u32 = 0x901_0000 as _;
const PL031_IRQ: IntId = IntId::spi(2); const PL031_IRQ: IntId = IntId::spi(2);
// ANCHOR: main // ANCHOR: main
#[no_mangle] // SAFETY: There is no other global function of this name.
#[unsafe(no_mangle)]
extern "C" fn main(x0: u64, x1: u64, x2: u64, x3: u64) { extern "C" fn main(x0: u64, x1: u64, x2: u64, x3: u64) {
// SAFETY: `PL011_BASE_ADDRESS` is the base address of a PL011 device, and // SAFETY: `PL011_BASE_ADDRESS` is the base address of a PL011 device, and
// nothing else accesses that address range. // nothing else accesses that address range.

View File

@ -15,7 +15,6 @@
#![allow(unused)] #![allow(unused)]
use core::fmt::{self, Write}; use core::fmt::{self, Write};
use core::ptr::{addr_of, addr_of_mut};
// ANCHOR: Flags // ANCHOR: Flags
use bitflags::bitflags; use bitflags::bitflags;
@ -126,7 +125,7 @@ impl Uart {
// of a PL011 device which is appropriately mapped. // of a PL011 device which is appropriately mapped.
unsafe { unsafe {
// Write to the TX buffer. // Write to the TX buffer.
addr_of_mut!((*self.registers).dr).write_volatile(byte.into()); (&raw mut (*self.registers).dr).write_volatile(byte.into());
} }
// Wait until the UART is no longer busy. // Wait until the UART is no longer busy.
@ -141,7 +140,7 @@ impl Uart {
} else { } else {
// SAFETY: We know that self.registers points to the control // SAFETY: We know that self.registers points to the control
// registers of a PL011 device which is appropriately mapped. // registers of a PL011 device which is appropriately mapped.
let data = unsafe { addr_of!((*self.registers).dr).read_volatile() }; let data = unsafe { (&raw const (*self.registers).dr).read_volatile() };
// TODO: Check for error conditions in bits 8-11. // TODO: Check for error conditions in bits 8-11.
Some(data as u8) Some(data as u8)
} }
@ -150,7 +149,7 @@ impl Uart {
fn read_flag_register(&self) -> Flags { fn read_flag_register(&self) -> Flags {
// SAFETY: We know that self.registers points to the control registers // SAFETY: We know that self.registers points to the control registers
// of a PL011 device which is appropriately mapped. // of a PL011 device which is appropriately mapped.
unsafe { addr_of!((*self.registers).fr).read_volatile() } unsafe { (&raw const (*self.registers).fr).read_volatile() }
} }
} }
// ANCHOR_END: Uart // ANCHOR_END: Uart

View File

@ -13,8 +13,6 @@
// limitations under the License. // limitations under the License.
// ANCHOR: solution // ANCHOR: solution
use core::ptr::{addr_of, addr_of_mut};
#[repr(C, align(4))] #[repr(C, align(4))]
struct Registers { struct Registers {
/// Data register /// Data register
@ -63,7 +61,7 @@ impl Rtc {
pub fn read(&self) -> u32 { pub fn read(&self) -> u32 {
// SAFETY: We know that self.registers points to the control registers // SAFETY: We know that self.registers points to the control registers
// of a PL031 device which is appropriately mapped. // of a PL031 device which is appropriately mapped.
unsafe { addr_of!((*self.registers).dr).read_volatile() } unsafe { (&raw const (*self.registers).dr).read_volatile() }
} }
/// Writes a match value. When the RTC value matches this then an interrupt /// Writes a match value. When the RTC value matches this then an interrupt
@ -71,7 +69,7 @@ impl Rtc {
pub fn set_match(&mut self, value: u32) { pub fn set_match(&mut self, value: u32) {
// SAFETY: We know that self.registers points to the control registers // SAFETY: We know that self.registers points to the control registers
// of a PL031 device which is appropriately mapped. // of a PL031 device which is appropriately mapped.
unsafe { addr_of_mut!((*self.registers).mr).write_volatile(value) } unsafe { (&raw mut (*self.registers).mr).write_volatile(value) }
} }
/// Returns whether the match register matches the RTC value, whether or not /// Returns whether the match register matches the RTC value, whether or not
@ -79,7 +77,7 @@ impl Rtc {
pub fn matched(&self) -> bool { pub fn matched(&self) -> bool {
// SAFETY: We know that self.registers points to the control registers // SAFETY: We know that self.registers points to the control registers
// of a PL031 device which is appropriately mapped. // of a PL031 device which is appropriately mapped.
let ris = unsafe { addr_of!((*self.registers).ris).read_volatile() }; let ris = unsafe { (&raw const (*self.registers).ris).read_volatile() };
(ris & 0x01) != 0 (ris & 0x01) != 0
} }
@ -90,7 +88,7 @@ impl Rtc {
pub fn interrupt_pending(&self) -> bool { pub fn interrupt_pending(&self) -> bool {
// SAFETY: We know that self.registers points to the control registers // SAFETY: We know that self.registers points to the control registers
// of a PL031 device which is appropriately mapped. // of a PL031 device which is appropriately mapped.
let ris = unsafe { addr_of!((*self.registers).mis).read_volatile() }; let ris = unsafe { (&raw const (*self.registers).mis).read_volatile() };
(ris & 0x01) != 0 (ris & 0x01) != 0
} }
@ -102,14 +100,14 @@ impl Rtc {
let imsc = if mask { 0x01 } else { 0x00 }; let imsc = if mask { 0x01 } else { 0x00 };
// SAFETY: We know that self.registers points to the control registers // SAFETY: We know that self.registers points to the control registers
// of a PL031 device which is appropriately mapped. // of a PL031 device which is appropriately mapped.
unsafe { addr_of_mut!((*self.registers).imsc).write_volatile(imsc) } unsafe { (&raw mut (*self.registers).imsc).write_volatile(imsc) }
} }
/// Clears a pending interrupt, if any. /// Clears a pending interrupt, if any.
pub fn clear_interrupt(&mut self) { pub fn clear_interrupt(&mut self) {
// SAFETY: We know that self.registers points to the control registers // SAFETY: We know that self.registers points to the control registers
// of a PL031 device which is appropriately mapped. // of a PL031 device which is appropriately mapped.
unsafe { addr_of_mut!((*self.registers).icr).write_volatile(0x01) } unsafe { (&raw mut (*self.registers).icr).write_volatile(0x01) }
} }
} }

View File

@ -4,7 +4,8 @@ In your Chromium build, add a new Rust target to `//ui/base/BUILD.gn`
containing: containing:
```rust ```rust
#[no_mangle] // SAFETY: There is no other global function of this name.
#[unsafe(no_mangle)]
pub extern "C" fn hello_from_rust() { pub extern "C" fn hello_from_rust() {
println!("Hello from Rust!") println!("Hello from Rust!")
} }
@ -32,7 +33,7 @@ subsequent exercises. If you've succeeded, you will be able to use right-click
## Where to find help ## Where to find help
- The options available to the [`rust_static_library` gn template][0] - The options available to the [`rust_static_library` gn template][0]
- Information about [`#[no_mangle]`][1] - Information about [`#[unsafe(no_mangle)]`][1]
- Information about [`extern "C"`][2] - Information about [`extern "C"`][2]
- Information about gn's [`--export-rust-project`][3] switch - Information about gn's [`--export-rust-project`][3] switch
- [How to install rust-analyzer in VSCode][4] - [How to install rust-analyzer in VSCode][4]
@ -45,9 +46,9 @@ This example is unusual because it boils down to the lowest-common-denominator
interop language, C. Both C++ and Rust can natively declare and call C ABI interop language, C. Both C++ and Rust can natively declare and call C ABI
functions. Later in the course, we'll connect C++ directly to Rust. functions. Later in the course, we'll connect C++ directly to Rust.
`allow_unsafe = true` is required here because `#[no_mangle]` might allow Rust `allow_unsafe = true` is required here because `#[unsafe(no_mangle)]` might
to generate two functions with the same name, and Rust can no longer guarantee allow Rust to generate two functions with the same name, and Rust can no longer
that the right one is called. guarantee that the right one is called.
If you need a pure Rust executable, you can also do that using the If you need a pure Rust executable, you can also do that using the
`rust_executable` gn template. `rust_executable` gn template.

View File

@ -6,7 +6,7 @@
specifies a single function, to be called from C++, called `hello_from_rust`, specifies a single function, to be called from C++, called `hello_from_rust`,
taking no parameters and returning no value. taking no parameters and returning no value.
- Modify your previous `hello_from_rust` function to remove `extern "C"` and - Modify your previous `hello_from_rust` function to remove `extern "C"` and
`#[no_mangle]`. This is now just a standard Rust function. `#[unsafe(no_mangle)]`. This is now just a standard Rust function.
- Modify your `gn` target to build these bindings. - Modify your `gn` target to build these bindings.
- In your C++ code, remove the forward-declaration of `hello_from_rust`. - In your C++ code, remove the forward-declaration of `hello_from_rust`.
Instead, include the generated header file. Instead, include the generated header file.

View File

@ -10,7 +10,7 @@ Creating pointers is safe, but dereferencing them requires `unsafe`:
fn main() { fn main() {
let mut s = String::from("careful!"); let mut s = String::from("careful!");
let r1 = &mut s as *mut String; let r1 = &raw mut s;
let r2 = r1 as *const String; let r2 = r1 as *const String;
// SAFETY: r1 and r2 were obtained from references and so are guaranteed to // SAFETY: r1 and r2 were obtained from references and so are guaranteed to

View File

@ -51,11 +51,11 @@ mod ffi {
pub d_name: [c_char; 1024], pub d_name: [c_char; 1024],
} }
extern "C" { unsafe extern "C" {
pub fn opendir(s: *const c_char) -> *mut DIR; pub unsafe fn opendir(s: *const c_char) -> *mut DIR;
#[cfg(not(all(target_os = "macos", target_arch = "x86_64")))] #[cfg(not(all(target_os = "macos", target_arch = "x86_64")))]
pub fn readdir(s: *mut DIR) -> *const dirent; pub unsafe fn readdir(s: *mut DIR) -> *const dirent;
// See https://github.com/rust-lang/libc/issues/414 and the section on // See https://github.com/rust-lang/libc/issues/414 and the section on
// _DARWIN_FEATURE_64_BIT_INODE in the macOS man page for stat(2). // _DARWIN_FEATURE_64_BIT_INODE in the macOS man page for stat(2).
@ -64,9 +64,9 @@ mod ffi {
// to macOS (as opposed to iOS / wearOS / etc.) on Intel and PowerPC. // to macOS (as opposed to iOS / wearOS / etc.) on Intel and PowerPC.
#[cfg(all(target_os = "macos", target_arch = "x86_64"))] #[cfg(all(target_os = "macos", target_arch = "x86_64"))]
#[link_name = "readdir$INODE64"] #[link_name = "readdir$INODE64"]
pub fn readdir(s: *mut DIR) -> *const dirent; pub unsafe fn readdir(s: *mut DIR) -> *const dirent;
pub fn closedir(s: *mut DIR) -> c_int; pub unsafe fn closedir(s: *mut DIR) -> c_int;
} }
} }