# Weak linkage

**URL:** <https://internals.rust-lang.org/t/weak-linkage/3165>\
**Category:** language design\
**Created:** [February 10, 2016, 6:45am UTC](https://internals.rust-lang.org/t/weak-linkage/3165 "2016-02-10T06:45:13Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![jethrogb](https://avatars.discourse-cdn.com/v4/letter/j/43a26b/32.png) [@jethrogb](https://internals.rust-lang.org/u/jethrogb)\
**Post date:** [February 10, 2016, 6:45am UTC](https://internals.rust-lang.org/t/weak-linkage/3165/1 "2016-02-10T06:45:13Z")

</div>

While investigating a [linkage bug](https://github.com/rust-lang/rust/issues/31508), I stumbled upon the weak linkage handling in Rust and I think it’s currently quite questionable. This topic is to brainstorm about a better design.

First of all, to remove all confusion anyone (including myself) might have about weak linkage, here’s how it works. When you define a weak symbol and don’t link it in, referencing that symbol directly is illegal. Conversely, obtaining a pointer to that symbol results in NULL. Consider the following C code

```rust
#include <stdio.h>

extern __attribute__ ((weak)) void weakfunc();
extern __attribute__ ((weak)) void(*weakfuncptr)();
extern __attribute__ ((weak)) void* weakvar;

void main() {
    printf("%p %p %p\n",&weakfunc,&weakfuncptr,&weakvar);
}

```

which results in this LLVM code

```rust
declare extern_weak void @weakfunc(...) #1
@weakfuncptr = extern_weak global void (...)*
@weakvar = extern_weak global i8*

```

and the program prints `(nil) (nil) (nil)`. If you would’ve typed `printf("%p\n",weakvar)` you would have gotten a segfault.

Now that we understand how weak linkage actually works in practice, we can think about what we want in Rust. See issue [31508](https://github.com/rust-lang/rust/issues/31508) and PRs [12556](https://github.com/rust-lang/rust/pull/12556) and [11978](https://github.com/rust-lang/rust/pull/11978) on how weak linkage currently works in Rust. One of the main arguments for the current design is something about non-nullable types. However, this does not seem to have anything to do with whether a type is nullable. It has to do with whether one can safely use a particular variable at all. There are some subtleties with functions and function pointers, so I think it makes more sense to consider the variable case first and extend from there.

It does seem that requiring everything to go through a pointer to the weak symbol makes a lot of sense, but the chosen syntax really does not. Perhaps we can make referencing a weak symbol unsafe (like a static mut) and provider a safe wrapper type/macro. The wrapper would would essentially be `Option<&T>` for a weak symbol of type `T`. What are other people’s thoughts?

Side note: This would be the converse of the C weakfunc definition in Rust, but it doesn’t work at all (no linkage specified in LLVM):

```rust
extern {
    #[linkage="extern_weak"] fn weakfunc();
}

```

---

<div class="post-metadata">

**Author:** ![alexcrichton](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/alexcrichton/32/4501_2.png) [@alexcrichton](https://internals.rust-lang.org/u/alexcrichton)\
**Post date:** [February 10, 2016, 5:25pm UTC](https://internals.rust-lang.org/t/weak-linkage/3165/2 "2016-02-10T17:25:36Z")

</div>

> [@jethrogb](#):
>
> One of the main arguments for the current design is something about non-nullable types. However, this does not seem to have anything to do with whether a type is nullable.

This was the main rationale for requiring pointers, because otherwise it was basically impossible to actually test whether a weak pointer was null or not. For example:

```rust
extern {
    #[linkage = "extern_weak"]
    static FOO: i32;
}

fn foo() -> &'static i32 { &FOO }

```

This is valid Rust code, yet if we _just_ applied the `extern_weak` annotation to the definition of LLVM, this would actually return a null pointer, which is a type system violation for the representation of `&T`. Along the same lines, there's not actually _any_ way to test whether `&FOO` is null or not, because by definition (in Rust) that returns `&T` which is not null.

This is basically the same story for function pointers as well, where they're non-nullable so if you want to test for null they can't be represented as a null pointer.

* * *

So that's at least the problem that the current restrictions are trying to solve, and I'd be more than ok tweaking them! I think, however, that we still need to be sure there's a typesafe way to test whether a weak value is null or not in Rust

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [March 25, 2019, 8:25am UTC](https://internals.rust-lang.org/t/weak-linkage/3165/3 "2019-03-25T08:25:46Z")

</div>

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
