Skip to content

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

@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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions