Skip to content

cross-crate inlining breaks compare of functions passed between crates #117047

Closed
@AzazKamaz

Description

@AzazKamaz

This code panics when compiled with #116505 with cross-crate inlining being turned on:

// src/main.rs
use lib;
fn main() { lib::verify(lib::create()); }
// src/lib.rs
fn inner() {}
pub fn create() -> fn() { inner }
pub fn verify(value: fn()) { assert_eq!(value, inner as fn()) }
# Cargo.toml
[package]
name = "lib"
version = "0.1.0"
edition = "2021"

cargo +nightly-2023-10-18 run --release - ok
cargo +nightly-2023-10-19 run --release - panics
cargo +nightly-2023-10-19 run - ok (opt-level = 2 incremental = false to panic)

It is clearly caused by #116505 because:

  • it is ok on ca89f73 but panics on 5d5edf0
  • it requires opt-level = 2, incremental = false and not -Zcross-crate-inline-threshold=0 (feature to be enabled)

Ways to fix this minimal example:

  • make create() inline(never) - probably this is not a root cause fix
  • set -Zcross-crate-inline-threshold=0

Originally I found this problem in Embassy (embedded framework using async). They are using such a comparison to ensure that passed Waker was created by the Embassy executor. In Embassy it is possible to fix it by either:

  • making from_task() inline(never)
  • or making VTABLE static

Meta

rustc +nightly --version --verbose (bug still here):

rustc 1.75.0-nightly (1c05d50c8 2023-10-21)
binary: rustc
commit-hash: 1c05d50c8403c56d9a8b6fb871f15aaa26fb5d07
commit-date: 2023-10-21
host: aarch64-apple-darwin
release: 1.75.0-nightly
LLVM version: 17.0.3
Precise versions (just skip, too much extra info)

rustup build - ok

rustc 1.75.0-nightly (09df6108c 2023-10-17)
binary: rustc
commit-hash: 09df6108c84fdec400043d99d9ee232336fd5a9f
commit-date: 2023-10-17
host: aarch64-apple-darwin
release: 1.75.0-nightly
LLVM version: 17.0.2

custom build - ok

rustc 1.75.0-nightly (ca89f732e 2023-10-18)
binary: rustc
commit-hash: ca89f732ec0f910fc92111a45dd7e6829baa9d4b
commit-date: 2023-10-18
host: aarch64-apple-darwin
release: 1.75.0-nightly
LLVM version: 17.0.3

custom build - panics

rustc 1.75.0-nightly (5d5edf024 2023-10-18)
binary: rustc
commit-hash: 5d5edf0248d967baa6ac5cbea09b91c7c9947942
commit-date: 2023-10-18
host: aarch64-apple-darwin
release: 1.75.0-nightly
LLVM version: 17.0.3

rustup build - panics

rustc 1.75.0-nightly (0039d739d 2023-10-18)
binary: rustc
commit-hash: 0039d739d40a076334e111488946441378d11cd7
commit-date: 2023-10-18
host: aarch64-apple-darwin
release: 1.75.0-nightly
LLVM version: 17.0.3

Backtrace

stack backtrace:
   0: _rust_begin_unwind
   1: core::panicking::panic_fmt
   2: core::panicking::assert_failed_inner
   3: core::panicking::assert_failed
   4: lib::verify

Example more like in Embassy

// src/lib.rs
#![feature(waker_getters)]

use core::task::{RawWaker, RawWakerVTable, Waker};

const VTABLE: RawWakerVTable = RawWakerVTable::new(clone, wake, wake, drop);

unsafe fn clone(p: *const ()) -> RawWaker { RawWaker::new(p, &VTABLE) }
unsafe fn wake(_: *const ()) {}
unsafe fn drop(_: *const ()) {}

pub fn create() -> Waker {
    unsafe { Waker::from_raw(clone(core::ptr::null())) }
}

pub fn verify(waker: Waker) {
    assert_eq!(waker.as_raw().vtable(), &VTABLE);
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions