Skip to content

#[linkage = "weak"] const fn accepted without warning #134451

Closed

Description

@HaoboGu

I'm trying to define a "weak" const in a library, which allows users to redefine their const. On stable Rust, there's no way to do it. On nightly, linkage feature seems the solution, but I found that it doesn't work as well. The following is the repro code:

// In library code:
#![feature(linkage)]

#[linkage = "weak"]
#[no_mangle]
const fn get_foo() -> i32 {
    0
}

pub const FOO: i32 = get_foo();

pub fn hello() {
    println!("hello: {}, {}", FOO, get_foo());
}

// In application code:
use linkage_weak_bug::hello;

#[no_mangle]
const fn get_foo() -> i32 {
    1
}

fn main() {
    // Output: hello: 0, 1
    // Expected: hello: 1, 1
    hello();
}

I uploaded a repo that could repro it: https://github.com/HaoboGu/linkage_weak_bug

Activity

  1. added
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    on Dec 18, 2024
  2. zopsicle commented on Dec 18, 2024

    @zopsicle
    Contributor

    Const items are always evaluated at compile time, which happens before linking, so this is expected. Perhaps const functions should not be allowed weak linkage, because it allows their compile-time and runtime behavior to differ.

  3. added
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    F-linkage#![feature(linkage)]`
    on Dec 18, 2024
  4. HaoboGu commented on Dec 18, 2024

    @HaoboGu
    Author

    I think it's valuable to have "weak constants" in Rust, just disallowing weak linkage for const fns is not we want.

    For example, in no_std env, it's very common to define a global channel with a fixed size:

    // This is a simplified code
    const CH_SIZE: usize = 4;
    static CHANNEL: Channel<CH_SIZE> = Channel::new();

    And, as a library author, we may want the CH_SIZE to be customizable by library users. It's impossible for Rust without using weak linkage now.

  5. changed the title [-][linkage = "weak"] doesn't work for const fn[/-] [+]`#[linkage = "weak"]` doesn't work for const fn[/+] on Dec 18, 2024
  6. added
    A-linkageArea: linking into static, shared libraries and binaries
    on Dec 18, 2024
  7. bjorn3 commented on Dec 18, 2024

    @bjorn3
    Member

    CHANNEL gets fully codegened when compiling the crate that contains it. To do this, it's full type needs to be known, which in turn requires CH_SIZE to be known. Note that the very fact if compilation succeeds or not and which functions get codegened can depend on the value of a const item or const function. As such weak linkage for const items and const functions can't work. And that is not even taking into account the fact that const items by definition don't have a symbol name unlike statics, but weak linkage matches on symbol name.

  8. added
    C-discussionCategory: Discussion or questions that doesn't represent real issues.
    and removed
    C-bugCategory: This is a bug.
    on Dec 18, 2024
  9. workingjubilee commented on Dec 18, 2024

    @workingjubilee
    Member

    Indeed, we may wish to investigate making this a compiler error.

    But first, while an expert on the linking side of things has spoken, let us consult the experts on the CTFE side of things. cc @rust-lang/wg-const-eval do any of you wish to entertain the possibility of a const fn having its symbol name overwritten at runtime, and users like @HaoboGu consequently seriously misunderstanding the model?

  10. workingjubilee commented on Dec 18, 2024

    @workingjubilee
    Member

    @HaoboGu The idea of "generic singletons" is an interesting idea, but it's absolutely not the way things work, and if it did work, it would have to be designed in such a way as to actually be evaluated without taking linkage into account.

  11. RalfJung commented on Dec 18, 2024

    @RalfJung
    Member

    No I don't think const fn intends to ever support terrible linker hacks like that. ;) If there's a use-case here, it should be solved with proper, type-safe Rust mechanisms, not at the linker level. What should even happen if 3 crates each overwrite get_foo (or CH_SIZE) with a different value? I don't see how we could have a sensible safe system here.

    Even on regular fn this is rather questionable, considering things like inlining. What even is the semantics here? When you call get_foo it non-deterministically calls some function with that name? AFAIK currently we have a safety requirement on no_mangle that there must be only one function with that name, so technically your code has UB. We probably want to adjust this to support weak linkage since people want to use their terrible linker hacks, but we should do so carefully.

  12. RalfJung commented on Dec 18, 2024

    @RalfJung
    Member

    And, as a library author, we may want the CH_SIZE to be customizable by library users.

    Constants are called that because they must be constant. It would be unsound to let anyone change them. The type system relies hard to the fact that the same constant has the same value everywhere in the crate graph.

    If you want to write your code in a way that is generic over some constant, you need to make it explicitly generic. We have mechanisms for that already (associated consts in a trait). I know that making an entire module generic can be annoying, but the solution for that definitely does not involve fundamentally changing the nature of consts in Rust; the solution is to explore module-level generics.

  13. 4 remaining items

  14. workingjubilee commented on Dec 18, 2024

    @workingjubilee
    Member

    Plausible. cc @m-ou-se if you have any thoughts (or not if not, it's just a data point of possible interest).

  15. removed
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    on Dec 19, 2024
  16. m-ou-se commented on Dec 19, 2024

    @m-ou-se
    Member

    Yeah that's definitely on our list. We're now calling our project "externally implementable items", and consts are also on our list of items, although not our first priority. We'll see how far we can get. :)

  17. workingjubilee commented on Dec 21, 2024

    @workingjubilee
    Member

    Cool!

    This issue is now about diagnostics! We should at least warn, probably compile error on this.

  18. changed the title [-]`#[linkage = "weak"]` doesn't work for const fn[/-] [+]`#[linkage = "weak"] const fn` accepted without warning[/+] on Dec 21, 2024
  19. added 6 commits that reference this issue on Jul 25, 2026
  20. added a commit that references this issue on Jul 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsA-linkageArea: linking into static, shared libraries and binariesC-discussionCategory: Discussion or questions that doesn't represent real issues.F-linkage#![feature(linkage)]`T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions