# Pre-RFC use function name as the type of the function

**URL:** <https://internals.rust-lang.org/t/pre-rfc-use-function-name-as-the-type-of-the-function/7951>\
**Category:** language design\
**Created:** [July 14, 2018, 1:06pm UTC](https://internals.rust-lang.org/t/pre-rfc-use-function-name-as-the-type-of-the-function/7951 "2018-07-14T13:06:00Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![DDOtten](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ddotten/32/4334_2.png) [@DDOtten](https://internals.rust-lang.org/u/DDOtten)\
**Post date:** [July 14, 2018, 1:06pm UTC](https://internals.rust-lang.org/t/pre-rfc-use-function-name-as-the-type-of-the-function/7951/1 "2018-07-14T13:06:00Z")

</div>

If we have a function `foo` this would have `foo` as the name of it’s type. This would allow us to name things that we can’t currently name, one example of this is `Map<slice::Iter<T>, foo>` for the result of calling `map(foo)` on a `slice::Iter<T>` where `foo` is a function taking `&T`. To me it is quite intuitive what `foo` means here (I actually tried doing this when I was learning rust).

This would not be a backwards compatible change. However because functions use `snake_case` and types use `CamelCase` I don’t think we would have a lot of breakage. Currently you would have to have a function and a type with the same name and ignore the lint that says you do not follow the naming convention for this change to break anything.

The only big things that we still can’t directly name with this change are closures, return types of functions with `impl Trait`, and in the future return types of [async functions](https://github.com/rust-lang/rust/issues/50547). A lot of times a closure can be changed to a function (if it does not capture anything) and `impl Trait` and async will be namable using [existential types](https://github.com/rust-lang/rfcs/pull/2071). Another benefit of this is that we can immediately get the output of `foo` using `foo::Ouput` because it implements the `Fn` traits. This is [another problem that came up](https://internals.rust-lang.org/t/pre-pre-rfc-async-methods-bounding-async-fns/7656?u=ddotten) with async functions.

An instance where this would be useful is a struct where it’s Iterators can be expresed as abother iterator with some functions called on in. This is why I chose `Map` as the example above, you could have some `struct Iter { inner: Map</**/, foo> }` and implement traits by delegating.

---

<div class="post-metadata">

**Author:** ![matklad](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/matklad/32/12266_2.png) [@matklad](https://internals.rust-lang.org/u/matklad)\
**Post date:** [July 14, 2018, 1:50pm UTC](https://internals.rust-lang.org/t/pre-rfc-use-function-name-as-the-type-of-the-function/7951/2 "2018-07-14T13:50:00Z")

</div>

An edge case: a tuple-struct definition defines both a type and a corresponding constructor function with the same name. Under this proposal, the type of constructor function would be unnameable I think?

Example: [https://play.rust-lang.org/?gist=3a98cb6ca3226c69ade8a165b63e1e48&version=stable&mode=debug&edition=2015](https://play.rust-lang.org/?gist=3a98cb6ca3226c69ade8a165b63e1e48&version=stable&mode=debug&edition=2015)

---

<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:** [July 14, 2018, 2:40pm UTC](https://internals.rust-lang.org/t/pre-rfc-use-function-name-as-the-type-of-the-function/7951/3 "2018-07-14T14:40:50Z")

</div>

An alternative that is not subject to @matklad’s problem is `fn name`, where `name` is more generally a (possibly UFCS) qualified path:

```rust
type Iter<'a, T> =
    std::iter::Map<
        std::slice::Iter<'a>,
        fn <T as Trait<A>>::method<B>,
    >;

```

Parentheses are not allowed to appear at the beginning of a path so I don’t think this is ambiguous. (It does give `fn` two different meanings in types though)

* * *

My guess though is that since named existentials _are_ planned, it’s better to double down on that feature than to provide multiple ways of achieving the same thing.

---

<div class="post-metadata">

**Author:** ![hanna-kruppe](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/hanna-kruppe/32/6540_2.png) [@hanna-kruppe](https://internals.rust-lang.org/u/hanna-kruppe)\
**Post date:** [July 14, 2018, 2:59pm UTC](https://internals.rust-lang.org/t/pre-rfc-use-function-name-as-the-type-of-the-function/7951/4 "2018-07-14T14:59:04Z")

</div>

A more general feature that side-steps all of the problems that have been identified (and more) is `typeof <expr>`.

---

<div class="post-metadata">

**Author:** ![DDOtten](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ddotten/32/4334_2.png) [@DDOtten](https://internals.rust-lang.org/u/DDOtten)\
**Post date:** [July 14, 2018, 8:36pm UTC](https://internals.rust-lang.org/t/pre-rfc-use-function-name-as-the-type-of-the-function/7951/5 "2018-07-14T20:36:54Z")

</div>

Maybe it is implemented as a function but I would consider the constructor to be something else. While the tuple struct uses `()` other structs use `{}` which differentiate them from other functions.

```rust
struct Foo(i32);
struct Bar { data: i32 }

fn main() {
    let x = Foo(0);
    let y = Bar { data: 0 };
}

```

Besides using this proposal if you really need to name a function that creates a struct you could always use something like `fn foo(data: i32) -> Foo { Foo(data) }`.

@ExpHP I would also be happy with `fn foo` however I don’t really see a reason to have the additional `fn` because we don’t do something like `struct name` or `enum name`.

---

<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:** [July 14, 2018, 9:11pm UTC](https://internals.rust-lang.org/t/pre-rfc-use-function-name-as-the-type-of-the-function/7951/6 "2018-07-14T21:11:49Z")

</div>

++, this is what I've suggested elsewhere and I think it side-steps all the annoying problems; I do think you want `fn <T as Trait<A>>::method::<B>` though... right? (never mind, I worked out a contrived example demonstrating you're right).

```rust
trait Foo<T> {
    const K: T;
}

fn foo<T: Default>() {}

impl<T> Foo<T> for fn foo<T> where T: Default {
  const K = T::default(); // yeah it's not const just humor me
}

const FOO_I32: i32 = fn foo<i32>::K; // once the parser hits a `fn` token 
                                     // it's no longer in expr mode

```

I think I also suggested at some point that within a function's scope (including paramteres and return type), it should be allowed to abbreviate as `fn` or similar (I imagine that some might want `fn` to be like `self` and refer to the unique value of the function's associated ZST, but writing something like `fn.type` would be ok, too).

> [@hanna-kruppe](#):
>
> A more general feature that side-steps all of the problems that have been identified (and more) is `typeof <expr>` .

I agree that we should have _some_ mechanism like this, but I'm opposed to the keyword `typeof`; I'm a bigger fan of `val.type` or `val::type`, since it avoids introducing a new keyword, and because Rust seems to me much more comfortable with method chaining than C++ is. See also Java, Scala, and Kotlin's respective `T.class`, `x.type`, and `x::class`. Certainly, I think that C++ spelling it `decltype(x)` was a mistake.

I also really hate multi-word keywords, but that's just me.

> [@DDOtten](#):
>
> Maybe it is implemented as a function but I would consider the constructor to be something else.

In fact, there's talk floated about of making `Bar`'s ctor be a function as well, by allowing `f { .. }` syntax for function calls. Not sure where all that went though. I think it's a nice feature that a tuple struct exposes its constructor as a bona-fide function, and changing this would produce a lot of churn anyways. Plus, types and values (which include functions) live in separate namespaces, and attempting to unify those is very much a "this kills the crab" scenario.

Also, something I'd really like is `fn foo::return` as sugar for `<fn foo as FnOnce<..>>::Output` (well, we can completely side-step the trait system, the desugaring is just for illustration) and maybe its friends like `fn foo::yield`.

---

<div class="post-metadata">

**Author:** ![DDOtten](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ddotten/32/4334_2.png) [@DDOtten](https://internals.rust-lang.org/u/DDOtten)\
**Post date:** [July 14, 2018, 9:30pm UTC](https://internals.rust-lang.org/t/pre-rfc-use-function-name-as-the-type-of-the-function/7951/7 "2018-07-14T21:30:45Z")

</div>

Why would you use `foo::return` when we already have `Output` from the `Fn` traits? I much prefer `foo::Output` which would be a side effect of this proposal.

---

<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:** [July 14, 2018, 9:56pm UTC](https://internals.rust-lang.org/t/pre-rfc-use-function-name-as-the-type-of-the-function/7951/8 "2018-07-14T21:56:13Z")

</div>

In order to get at the `FnOnce::Output` type you have to cast the type `<_ as FnOnce(..) -> _>::Output`. The `Output` associated type belongs to the trait, not the type itself. So just making the function type namable is not enough by itself.

You can try this yourself with some feature flags: create a struct, impl FnOnce, and try to get the `Output` associated type.

---

<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:** [July 16, 2018, 5:05am UTC](https://internals.rust-lang.org/t/pre-rfc-use-function-name-as-the-type-of-the-function/7951/9 "2018-07-16T05:05:44Z")

</div>

The problem is, this will be a breaking change. Currently functions do not preserve its name in type context. This means that function and module with same name can exist in same scope. So the code below is a totally valid rust code.

```rust
pub fn foo() -> SomeType{
    ...
}

pub mod foo {
    pub type Output = SomeOtherType;
}

```

So auto-declare function’s name as type name will be breaking change. Though in rust syntax level breakage like this is allowed between edition change, I don’t think this proposal is significant enough to justify it.

Suggestion: How about `fn::func_name`? It surely is a syntactic hack, but dudes in JS world found it’s useful 😉

---

<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:** [July 16, 2018, 7:09am UTC](https://internals.rust-lang.org/t/pre-rfc-use-function-name-as-the-type-of-the-function/7951/10 "2018-07-16T07:09:45Z")

</div>

See `type TypeOfFoo = fn foo;` above.

---

<div class="post-metadata">

**Author:** ![canndrew](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/canndrew/32/1676_2.png) [@canndrew](https://internals.rust-lang.org/u/canndrew)\
**Post date:** [July 17, 2018, 12:12am UTC](https://internals.rust-lang.org/t/pre-rfc-use-function-name-as-the-type-of-the-function/7951/11 "2018-07-17T00:12:39Z")

</div>

Since breaking changes are on the table, has anyone looked into how much of a breaking change this would be? Are there many crates out there that have functions and modules with the same name? How would we want rustfix to handle this?

---

<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-use-function-name-as-the-type-of-the-function/7951/12 "2019-03-25T08:30:31Z")

</div>

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