# Pre-RFC: Underscore functions

**URL:** https://internals.rust-lang.org/t/pre-rfc-underscore-functions/8237
**Category:** language design
**Created:** [August 18, 2018, 11:34am UTC](https://internals.rust-lang.org/t/pre-rfc-underscore-functions/8237 "2018-08-18T11:34:43Z")
**Posts on this page:** 12
**Page:** 1

<div class="post-metadata">

### Author: ![upsuper](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/upsuper/32/1074_2.png) [@upsuper](https://internals.rust-lang.org/u/upsuper)
#### Post date: [August 18, 2018, 11:34am UTC](https://internals.rust-lang.org/t/pre-rfc-underscore-functions/8237/1 "2018-08-18T11:34:43Z")

</div>

# Summary

Allow using underscore (`_`) as name on function definitions, and such functions does not have a name, so they cannot be invoked, and multiple such functions are allowed in one scope without triggering redefinition error.

# Motivation

Rust currently doesn’t have any kind of official compile-time static assertion, however, there are various tricks used to implement such assertions. For example, `std::mem::transmute` is usually used to check size of a type like following:

```rust
std::mem::transmute::<TypeToCheck, [u8; EXPECTED_SIZE]>();

```

However, this trick can only be used inside function body (i.e. it doesn’t work on the top level), so people have to do something like

```rust
fn _assert_type() {
    std::mem::transmute::<TypeToCheck, [u8; EXPECTED_SIZE]>();
}

```

If you want to build a macro to generate such static assertion, you would be in a dilemma: you either need to require your users to wrap your macro inside a function, or the macro can only be used once in each scope, because macros cannot generate random names as function name to avoid conflicts with itself.

If one can declare an underscore function with the characteristics described in the summary section, macros would be able to simply wrap everything in such function, and then they can be used everywhere without restrictions they currently face.

# Guide-level explanation

If a function has name `_` (a single underscore), it doesn’t create a function in the current scope, which means it cannot be invoked, and there can be multiple function definitions with the same name in a scope. Although it isn’t otherwise usable, compiler still checks the code inside. This is useful in macros to create an anonymous function body scope for wrapping statements only allowed in that context.

For example,

```rust
macro_rules! assert_size {
    ($type:ty => $n:expr) => {
        fn _() {
            ::std::mem::transmute::<$type, [u8; $n]>();
        }
    }
}
assert_size!(Option<bool> => 1);
assert_size!(Option<Option<bool>> => 1);

```

# Reference-level explanation

(Not sure what to write here.)

# Drawbacks

Similar to the special behavior of `_` in let bindings, this may cause confusions.

# Rationale and alternatives

To solve the problem that macros need function scope without conflicting with itself, there are several alternatives.

## Add special macro to generate identifiers with serial number

For example, add a macro `serial!(prefix_)` which generates a different identifier every time it is invoked, for example, it generates `prefix_1`, `prefix_2`, `prefix_3`, etc.

(This can probably be implemented as a proc macro, actually.)

Pros:

- It is probably implementable from library without touching the language.
- Even if implemented in std, it just needs an additional macro, no changes to core language is needed.

Cons:

- It generates redundant names which are generally not useful.
- (Maybe it would add symbols to files or even binaries? Maybe affect reproducible build?)

## Allow namespace scoping on the top level context

Allow putting functions inside scopes even on the top level context, and such scopes can isolate function definitions so that they don’t conflict. For example:

```rust
mod a {
    { fn foo() {} }
    { fn foo() {} }
}

```

Pros:

- Straightforward in concept?
- Useful in other cases?

Cons:

- Maybe adding such support would be troublesome for compiler implementation?

## Underscope module

This is the same thing as the proposal but on the module name.

Pros:

- Maybe can be used to create module level context in macros? (Would we want that?)

Cons:

- Macros would need two level wrappers to do what they want to do, which feels redundant.

# Prior art

(Not sure)

---

<div class="post-metadata">

### Author: ![Nemo157](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nemo157/32/11585_2.png) [@Nemo157](https://internals.rust-lang.org/u/Nemo157)
#### Post date: [August 18, 2018, 12:16pm UTC](https://internals.rust-lang.org/t/pre-rfc-underscore-functions/8237/3 "2018-08-18T12:16:58Z")

</div>

An alternative proposed recently was unnamed consts for the exact same purpose:

> [@Allow 'const \_'?](https://internals.rust-lang.org/t/allow-const/8231):
>
> Currently, it’s illegal to create a constant with the name \_. I propose that we allow this, giving it the same semantics as let \_ = ... - namely, that the result is discarded. Constants are often used for the side effect of determining whether some code compiles. This is used in serde, for example, to determine whether certain properties hold about a type. Currently, serde has to do naming tricks like: const \_NAME\_THATS\_UNLIKELY\_TO\_ALREADY\_BE\_USED: () = { \<expression that won't compile if cert…

---

<div class="post-metadata">

### Author: ![qnighy](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/qnighy/32/2195_2.png) [@qnighy](https://internals.rust-lang.org/u/qnighy)
#### Post date: [August 18, 2018, 12:20pm UTC](https://internals.rust-lang.org/t/pre-rfc-underscore-functions/8237/4 "2018-08-18T12:20:00Z")

</div>

Macros 2.0 may have item-level hygiene, allowing to distinguish every `_assert_type`s: [https://play.rust-lang.org/?gist=619360907fa99d4e14c4c39c78050d2c&version=nightly&mode=debug&edition=2015](https://play.rust-lang.org/?gist=619360907fa99d4e14c4c39c78050d2c&version=nightly&mode=debug&edition=2015)

---

<div class="post-metadata">

### Author: ![upsuper](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/upsuper/32/1074_2.png) [@upsuper](https://internals.rust-lang.org/u/upsuper)
#### Post date: [August 18, 2018, 1:33pm UTC](https://internals.rust-lang.org/t/pre-rfc-underscore-functions/8237/5 "2018-08-18T13:33:13Z")

</div>

What’s this…?

---

<div class="post-metadata">

### Author: ![upsuper](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/upsuper/32/1074_2.png) [@upsuper](https://internals.rust-lang.org/u/upsuper)
#### Post date: [August 18, 2018, 1:34pm UTC](https://internals.rust-lang.org/t/pre-rfc-underscore-functions/8237/6 "2018-08-18T13:34:25Z")

</div>

const is probably less powerful than function, since there may be statements not usable in const measurement context (I believe `transmute` doesn’t work in const, does it?)

---

<div class="post-metadata">

### Author: ![upsuper](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/upsuper/32/1074_2.png) [@upsuper](https://internals.rust-lang.org/u/upsuper)
#### Post date: [August 18, 2018, 1:35pm UTC](https://internals.rust-lang.org/t/pre-rfc-underscore-functions/8237/7 "2018-08-18T13:35:35Z")

</div>

Oh, that’s cool. With that, I guess there is nothing needed from this RFC anymore.

---

<div class="post-metadata">

### Author: ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)
#### Post date: [August 18, 2018, 10:42pm UTC](https://internals.rust-lang.org/t/pre-rfc-underscore-functions/8237/8 "2018-08-18T22:42:15Z")

</div>

As another alternative, what about adding compile-time static assertions? If we had those, would we still need this?

---

<div class="post-metadata">

### Author: ![earthengine](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/earthengine/32/2577_2.png) [@earthengine](https://internals.rust-lang.org/u/earthengine)
#### Post date: [August 18, 2018, 11:09pm UTC](https://internals.rust-lang.org/t/pre-rfc-underscore-functions/8237/9 "2018-08-18T23:09:11Z")

</div>

> [@josh](#):
>
> As another alternative, what about adding compile-time static assertions? If we had those, would we still need this?

yes we still need it.

```rust
let v=10;
//As v is Copy it will still valid after use.
//But the following explicitly says we don't need it any more.
//put this in a macro will need Macro 2.0 or any of the alternatives.
enum ANewType{}; #[allow(unused_variable)] let v:ANewType;

```

---

<div class="post-metadata">

### Author: ![upsuper](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/upsuper/32/1074_2.png) [@upsuper](https://internals.rust-lang.org/u/upsuper)
#### Post date: [August 18, 2018, 11:49pm UTC](https://internals.rust-lang.org/t/pre-rfc-underscore-functions/8237/10 "2018-08-18T23:49:47Z")

</div>

There may be many different use cases for such macros, and compile-time static assertions may not cover all of them immediately.

Actually, some of them are tricky and not widely needed, but still valid. For example, my [assert-impl](https://github.com/upsuper/assert-impl) macro utilize multiple choice error to enforce types not to implement a given trait. To fully support this kind of usages, Rust may need some compile-time reflection functionality, which is rather non-trivial I would suppose.

---

<div class="post-metadata">

### Author: ![Nemo157](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nemo157/32/11585_2.png) [@Nemo157](https://internals.rust-lang.org/u/Nemo157)
#### Post date: [August 19, 2018, 11:26am UTC](https://internals.rust-lang.org/t/pre-rfc-underscore-functions/8237/11 "2018-08-19T11:26:28Z")

</div>

It requires a few more features such as specialization and const trait functions, but your `assert_impl!` macro should be possible as a static assertion for much nicer error messages, [something like this playground](https://play.rust-lang.org/?gist=2441de79d5e91e6c4f237ee043bfd784&version=nightly&mode=debug&edition=2015).

---

<div class="post-metadata">

### Author: ![mcy](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mcy/32/6512_2.png) [@mcy](https://internals.rust-lang.org/u/mcy)
#### Post date: [August 19, 2018, 9:49pm UTC](https://internals.rust-lang.org/t/pre-rfc-underscore-functions/8237/12 "2018-08-19T21:49:42Z")

</div>

You actually don’t need this, in the precense of `const _`. You can just write this:

```rust
const _: fn() = || {
    // non-const fun
};

```

---

<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:30am UTC](https://internals.rust-lang.org/t/pre-rfc-underscore-functions/8237/13 "2019-03-25T08:30:44Z")

</div>

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