# Allow non-\`mut\` statics in patterns

**URL:** https://internals.rust-lang.org/t/allow-non-mut-statics-in-patterns/17145
**Category:** language design
**Created:** [August 7, 2022, 3:10pm UTC](https://internals.rust-lang.org/t/allow-non-mut-statics-in-patterns/17145 "2022-08-07T15:10:45Z")
**Posts on this page:** 17
**Page:** 1

<div class="post-metadata">

### Author: ![Jules-Bertholet](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jules-bertholet/32/10671_2.png) [@Jules-Bertholet](https://internals.rust-lang.org/u/Jules-Bertholet)
#### Post date: [August 7, 2022, 3:10pm UTC](https://internals.rust-lang.org/t/allow-non-mut-statics-in-patterns/17145/1 "2022-08-07T15:10:46Z")

</div>

Currently, the below code fails with [`E0530`](https://doc.rust-lang.org/stable/error-index.html#E0530):

```rust
static ZERO: i32 = 0;

fn whee(x: i32) {
    match x {
        ZERO => println!("x is zero"),
        _ => println!("x is not zero"),
    }
}

```

Are there any reasons not to accept this code, with the `ZERO` pattern behaving as if `ZERO` was a `const`? Note that `UnsafeCell` does not implement `StructuralEq`, so interior mutable statics could not be used this way.

* * *

### Motivation

I'm trying to build the Rust standard library for [cosmopolitan libc](https://justine.lol/cosmopolitan/index.html). Cosmopolitan provides an interface that mostly matches POSIX, with one exception: many constants like `ENOSYS` are defined instead as statics that are initialized once before `main` to the proper platform-specific value. The Rust stdlib matches on these constants in many places; rewriting all those `match` statements would be a large maintenance burden.

---

<div class="post-metadata">

### Author: ![ExpHP](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/exphp/32/6208_2.png) [@ExpHP](https://internals.rust-lang.org/u/ExpHP)
#### Post date: [August 7, 2022, 5:04pm UTC](https://internals.rust-lang.org/t/allow-non-mut-statics-in-patterns/17145/2 "2022-08-07T17:04:40Z")

</div>

> [@Jules-Bertholet](#):
>
> I'm trying to build the Rust standard library for [cosmopolitan libc](https://justine.lol/cosmopolitan/index.html). Cosmopolitan provides an interface that mostly matches POSIX, with one exception: many constants like `ENOSYS` are defined instead as statics that are initialized once before `main` to the proper platform-specific value. The Rust stdlib matches on these constants in many places; rewriting all those `match` statements would be a large maintenance burden.

Given this motivation, you are effectively needing `match` to be able to equality match its input against a value only known at runtime. (the static). This would have very different codegen from the status quo, and implications on things like match exhaustiveness or branch reachability. It feels strange to think that rust might add support for this, but only for `static`s and not for e.g. locals. (the only possible justification I can think of is that one could say that it is "path expressions" which are allowed to be used in a match)

---

<div class="post-metadata">

### Author: ![Jules-Bertholet](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jules-bertholet/32/10671_2.png) [@Jules-Bertholet](https://internals.rust-lang.org/u/Jules-Bertholet)
#### Post date: [August 7, 2022, 6:25pm UTC](https://internals.rust-lang.org/t/allow-non-mut-statics-in-patterns/17145/3 "2022-08-07T18:25:30Z")

</div>

> [@ExpHP](#):
>
> you are effectively needing `match` to be able to equality match its input against a value only known at runtime. (the static). This would have very different codegen from the status quo, and implications on things like match exhaustiveness or branch reachability. It feels strange to think that rust might add support for this, but only for statics and not for e.g. locals.

When the `static` is defined by Rust, the compiler does know its value at compile-time; there should be difference between this csse and `const` in terms of exhaustiveness or reachability checking in patterns. When the `static` is declared inside an `extern` block, as in my motivating example, the Rust compiler doesn't know its value at compile time, and therefore can't use it to inform reachability or exhaustiveness checks. However, by the time any Rust code is running at runtime, its value will already have been fixed. If you define "constant" as "value won't change at runtime", an `extern`-block `static` is conceptually a constant value as well.

(Also, allowing patterns to refer to the values of locals would be a breaking change. This AFAIK is not)

---

<div class="post-metadata">

### Author: ![semicoleon](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/semicoleon/32/7397_2.png) [@semicoleon](https://internals.rust-lang.org/u/semicoleon)
#### Post date: [August 7, 2022, 7:57pm UTC](https://internals.rust-lang.org/t/allow-non-mut-statics-in-patterns/17145/4 "2022-08-07T19:57:00Z")

</div>

I may be missing something, but it looks to me like ENOSYS is defined as a `const` in cosmopolitan to me

> <https://github.com/jart/cosmopolitan/blob/af3df0893bd39c6f9d8d6bfa519fed51330c9123/libc/errno.h#L17>

---

<div class="post-metadata">

### Author: ![Jules-Bertholet](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jules-bertholet/32/10671_2.png) [@Jules-Bertholet](https://internals.rust-lang.org/u/Jules-Bertholet)
#### Post date: [August 7, 2022, 8:48pm UTC](https://internals.rust-lang.org/t/allow-non-mut-statics-in-patterns/17145/5 "2022-08-07T20:48:41Z")

</div>

`extern const` in C is equivalent to `extern "C" { pub static ... }` (not `static mut`) in Rust. A Rust `const` would be like a C `#define`

---

<div class="post-metadata">

### Author: ![tvallotton](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tvallotton/32/8153_2.png) [@tvallotton](https://internals.rust-lang.org/u/tvallotton)
#### Post date: [August 9, 2022, 12:10am UTC](https://internals.rust-lang.org/t/allow-non-mut-statics-in-patterns/17145/6 "2022-08-09T00:10:22Z")

</div>

I think this can be sidestepped very easilly right now like this:

```rust
 match x {
        val => if val == ZERO => println!("x is zero"),
        _ => println!("x is not zero"),
    }
}

```

It may not be very satisfying, but as it was said before, pattern matching and equality aren't quite the same thing.

---

<div class="post-metadata">

### Author: ![Jules-Bertholet](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jules-bertholet/32/10671_2.png) [@Jules-Bertholet](https://internals.rust-lang.org/u/Jules-Bertholet)
#### Post date: [August 9, 2022, 4:11pm UTC](https://internals.rust-lang.org/t/allow-non-mut-statics-in-patterns/17145/7 "2022-08-09T16:11:28Z")

</div>

> [@tvallotton](#):
>
> It may not be very satisfying

This solution makes me sad because it would mean rewriting much of the standard library to accommodate my niche target—and I doubt the Rust libs team would want something like that merged upstream. Maybe my use case is just too niche; but on the other hand, if the implementation is not too complex, I see no reason not to allow this feature.

---

<div class="post-metadata">

### Author: ![semicoleon](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/semicoleon/32/7397_2.png) [@semicoleon](https://internals.rust-lang.org/u/semicoleon)
#### Post date: [August 9, 2022, 5:42pm UTC](https://internals.rust-lang.org/t/allow-non-mut-statics-in-patterns/17145/8 "2022-08-09T17:42:19Z")

</div>

Patterns are compile time information matched against a runtime value. Making patterns depend on runtime information (even information that is guaranteed not to change once main is called) is a significant change to how pattern matching works. I think you'd probably need an actual RFC to hash out all the details of how that would actually work.

That being said, I totally get why you don't want to change all of those match blocks in the standard library. It may be worth asking the libs team for their input on solutions that are likeliest to get upstreamed.

---

<div class="post-metadata">

### Author: ![Jules-Bertholet](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jules-bertholet/32/10671_2.png) [@Jules-Bertholet](https://internals.rust-lang.org/u/Jules-Bertholet)
#### Post date: [August 9, 2022, 6:57pm UTC](https://internals.rust-lang.org/t/allow-non-mut-statics-in-patterns/17145/9 "2022-08-09T18:57:08Z")

</div>

> [@semicoleon](#):
>
> I think you'd probably need an actual RFC to hash out all the details of how that would actually work

For sure. I'm looking for obvious reasons not to have this feature, before I commit to the effort of hashing out details.

In any case, this is not the only new Rust feature needed for my use case; [trusted extern statics](https://github.com/rust-lang/lang-team/issues/149) would likely also be necessary.

---

<div class="post-metadata">

### Author: ![crlf0710](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/crlf0710/32/1987_2.png) [@crlf0710](https://internals.rust-lang.org/u/crlf0710)
#### Post date: [August 10, 2022, 5:28am UTC](https://internals.rust-lang.org/t/allow-non-mut-statics-in-patterns/17145/10 "2022-08-10T05:28:50Z")

</div>

If proc-macros are available to `std`, just use a `cfg_attr(xxx_platform, rewrite_macro)` on it, and rewrite the code pattern to the usable one inside the macro, will do all the magic, right?

---

<div class="post-metadata">

### Author: ![hyeonu](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/hyeonu/32/2162_2.png) [@hyeonu](https://internals.rust-lang.org/u/hyeonu)
#### Post date: [August 10, 2022, 6:31am UTC](https://internals.rust-lang.org/t/allow-non-mut-statics-in-patterns/17145/11 "2022-08-10T06:31:10Z")

</div>

I might be wrong, but it seems the constants are actually constant within single platform. Is it true?

> <https://github.com/jart/cosmopolitan/blob/master/libc/sysv/consts.sh>

If it's guaranteed you can make cosmopolitan target per platform with hardcoded platform specific constants.

---

<div class="post-metadata">

### Author: ![bjorn3](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bjorn3/32/2736_2.png) [@bjorn3](https://internals.rust-lang.org/u/bjorn3)
#### Post date: [August 10, 2022, 10:21am UTC](https://internals.rust-lang.org/t/allow-non-mut-statics-in-patterns/17145/12 "2022-08-10T10:21:37Z")

</div>

The whole point of cosmopolitan is that a single executable works on any platform supported by it without requiring recompilation AFAIK.

---

<div class="post-metadata">

### Author: ![NoamB](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/noamb/32/6998_2.png) [@NoamB](https://internals.rust-lang.org/u/NoamB)
#### Post date: [August 10, 2022, 8:39pm UTC](https://internals.rust-lang.org/t/allow-non-mut-statics-in-patterns/17145/13 "2022-08-10T20:39:08Z")

</div>

An alternative approach could be to have std import the constants as constants (for example, Linux's constants), and have the `errno` or `cvt` functions convert between the platform values and the Linux values. This of course won't fix any user code which tries to match against `ENOSYS` for example, but neither would rewriting the matches. I don't know how this would work for non-errno constants.

---

<div class="post-metadata">

### Author: ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)
#### Post date: [August 11, 2022, 9:26am UTC](https://internals.rust-lang.org/t/allow-non-mut-statics-in-patterns/17145/14 "2022-08-11T09:26:37Z")

</div>

std and rustc can't use standard procedural macros because of bootstrapping issues. Instead, they use directly implemented proc-macro-likes which are written against the compiler-internal types rather than the proc\_macro bridge types.

---

<div class="post-metadata">

### Author: ![Jules-Bertholet](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jules-bertholet/32/10671_2.png) [@Jules-Bertholet](https://internals.rust-lang.org/u/Jules-Bertholet)
#### Post date: [August 14, 2022, 2:53pm UTC](https://internals.rust-lang.org/t/allow-non-mut-statics-in-patterns/17145/15 "2022-08-14T14:53:38Z")

</div>

Update: I've implemented this feature at [GitHub - Jules-Bertholet/rust at statics\_in\_patterns](https://github.com/Jules-Bertholet/rust/tree/statics_in_patterns)

---

<div class="post-metadata">

### Author: ![Jules-Bertholet](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jules-bertholet/32/10671_2.png) [@Jules-Bertholet](https://internals.rust-lang.org/u/Jules-Bertholet)
#### Post date: [August 17, 2022, 11:51am UTC](https://internals.rust-lang.org/t/allow-non-mut-statics-in-patterns/17145/16 "2022-08-17T11:51:27Z")

</div>

Update: [RFC posted](https://github.com/rust-lang/rfcs/pull/3305)

---

<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: [November 15, 2022, 11:52am UTC](https://internals.rust-lang.org/t/allow-non-mut-statics-in-patterns/17145/17 "2022-11-15T11:52:24Z")

</div>

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