# Idea: associated items for functions

**URL:** https://internals.rust-lang.org/t/idea-associated-items-for-functions/7822
**Category:** Uncategorized
**Created:** [June 28, 2018, 8:35am UTC](https://internals.rust-lang.org/t/idea-associated-items-for-functions/7822 "2018-06-28T08:35:51Z")
**Posts on this page:** 12
**Page:** 1

<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: [June 28, 2018, 8:35am UTC](https://internals.rust-lang.org/t/idea-associated-items-for-functions/7822/1 "2018-06-28T08:35:51Z")

</div>

This is something I’ve wanted a lot. It would help when a function returns some type unique to that function, eg. when a function has it’s own error type:

```rust
fn eat_snacks() -> Result<(), self::eat_snacks::Error> {
    pub enum Error { .. };
    ...
}

```

It could also help when a function uses constants that you may want to be visible outside the function:

```rust
fn request_info_from_peers() {
    pub const NUM_REQUESTS_IN_PARALLEL: usize = 23;
    ...
}

#[test]
fn test_request_info_from_peers() {
    for i in 0..request_info_from_peers::NUM_REQUESTS_IN_PARALLEL {
        ...
    }
    ...
}

```

You get the idea. Is this something that anyone else wants?

---

<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: [June 28, 2018, 8:42am UTC](https://internals.rust-lang.org/t/idea-associated-items-for-functions/7822/2 "2018-06-28T08:42:05Z")

</div>

I know that I’d like this.

The problem is that a function currently defines neither a type nor a namespace.

```rust
fn f() {}
mod f {}
fn F() {}
struct F {}

```

This is valid today, and would have to become invalid if functions would be a type and/or namespace. This is _common_ today: tuple structs define a type and a function.

---

<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: [June 28, 2018, 9:16am UTC](https://internals.rust-lang.org/t/idea-associated-items-for-functions/7822/3 "2018-06-28T09:16:03Z")

</div>

We could just allow both at the same time. eg. this is valid:

```rust
mod foo {
    pub struct MyThing;
}

fn foo() {
    pub struct MyOtherThing;
}

```

But this is invalid:

```rust
mod foo {
    pub struct MyThing;
}

fn foo() {
    pub struct MyThing; // error: `MyThing` defined twice
}

```

It’s not super-elegant, but I don’t know if it would really cause problems in practice.

---

<div class="post-metadata">

### Author: ![Ixrec](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ixrec/32/6754_2.png) [@Ixrec](https://internals.rust-lang.org/u/Ixrec)
#### Post date: [June 28, 2018, 12:33pm UTC](https://internals.rust-lang.org/t/idea-associated-items-for-functions/7822/4 "2018-06-28T12:33:03Z")

</div>

This sounds like it’s just sugar for a `mod foo { pub fn ... }` and a `use foo::*;`. Is that correct? If not, what’s the difference?

---

<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: [June 28, 2018, 1:40pm UTC](https://internals.rust-lang.org/t/idea-associated-items-for-functions/7822/5 "2018-06-28T13:40:37Z")

</div>

@Ixrec I’m not exactly sure what you’re describing there. But yes, it’s possible to do this just with modules. eg.

```rust
fn foo() {
    pub struct Bar;
    ...
}

```

is the same as

```rust
mod foo {
    pub struct Bar;
}

fn foo() {
    use self::foo::*;
    ...
}

```

This feature wouldn’t let you do anything new and powerful. It’s just more convenient syntax.

---

<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: [June 28, 2018, 1:51pm UTC](https://internals.rust-lang.org/t/idea-associated-items-for-functions/7822/6 "2018-06-28T13:51:19Z")

</div>

One reason I want this is so that I can have the docs for my function also display the consts/types which are only relevant to that function, rather than making the user navigate to a module with the same name.

Also, we let types double as modules via inherent impls. So I don’t see why we can’t do the same thing for functions.

---

<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: [June 28, 2018, 2:39pm UTC](https://internals.rust-lang.org/t/idea-associated-items-for-functions/7822/7 "2018-06-28T14:39:09Z")

</div>

> [@canndrew](#):
>
> Also, we let types double as modules via inherent impls. So I don’t see why we can’t do the same thing for functions.

Name collisions in rust today are easily described in terms of two (or three) namespaces:

- modules/types
- values
- (and maybe macros)

To extend @CAD97's example with a few more cases:

```rust
// Currently allowed
fn f() {}
mod f {}
macro_rules! f {}

// Currently allowed
fn F() {}
struct F {}
macro_rules! F {}

// Currently forbidden!
mod x {}
struct x {}

// Currently forbidden!
const X: i32 = 0;
fn X() {}

```

ISTM that allowing fns to double as modules requires either:

- Making fns define modules under certain conditions (a breaking change if those conditions do not require novel syntax or attributes)
- Adding a fallback mechanism to path resolution. _shudder_

---

<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: [June 28, 2018, 5:39pm UTC](https://internals.rust-lang.org/t/idea-associated-items-for-functions/7822/8 "2018-06-28T17:39:01Z")

</div>

How about the following syntax?

```rust
// `fn` is in a function as `Self` is in an `impl`
// this lines up with the idea that 'fn would be the
// "fucntion body region/lifetime", as has been proposed elsewhere
fn eat_snacks() -> Result<(), fn::Error> {
    pub enum Error { .. };
    ...
}

const MY_ERROR: fn eat_snacks::Error = ..

// or, if it's in an impl,
const MY_ERROR: MyStruct::fn eat_snacks::Error = ..

```

AFAICT there should be no parsing ambiguities, since `fn` in non-item position must be followed by `(` currently ([playground](https://play.rust-lang.org/?gist=7157b62f281e513b65057097cc83fbf0&version=stable&mode=debug)). That said, while I feel vaguely grossed out by the space in `fn foo` appearing in a path, this is already present in `fn() -> T` (though I think you might need to include parens for that). We could go with `(fn eat_snacks)::Error` but I don’t like that either.

---

<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: [August 29, 2018, 5:38am UTC](https://internals.rust-lang.org/t/idea-associated-items-for-functions/7822/9 "2018-08-29T05:38:46Z")

</div>

Random thought: Another advantage to making every function/method it’s own type would be so that you can refer to them in trait bounds. eg. When I implement a trait, I should be able to relax the effects on methods like so:

```rust
struct MyConstEqType;

// Make `eq` a const fn, even though it's non-const in the trait definition.
impl PartialEq for MyConstEqType {
    const fn eq(&self, other: &MyConstEqType) -> bool {
        true
    }
}

```

I could then refer to types that have `const` equality by referring to the `eq` method:

```rust
fn takes_a_const_eq_argument<T>(val: T)
where
    T: PartialEq,
    T::eq: ConstFn(&T, &T) -> bool
{
   ...
}

```

---

<div class="post-metadata">

### Author: ![kuviman](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kuviman/32/4741_2.png) [@kuviman](https://internals.rust-lang.org/u/kuviman)
#### Post date: [October 9, 2018, 9:37am UTC](https://internals.rust-lang.org/t/idea-associated-items-for-functions/7822/10 "2018-10-09T09:37:33Z")

</div>

Doesn’t every function has its own type already? Like `fn () {fn_name}`

But currently there is no way to name it in code, so you cant add methods or impl traits for it. But what if we could?

I think it would be possible to name it just exactly like the function itself, if it is used in type’s context. Like this:

```rust
fn foo<T>() {}

fn main() {
    let f: foo<i32> = foo::<i32>;
}

```

This currently errors:

```rust
error[E0573]: expected type, found function `foo`
 --> src\lib.rs:4:12
  |
4 | let f: foo<i32> = foo::<i32>;
  | ^^^^^^^^ not a type

```

It works exactly the same way for structs, right?

```rust
struct Foo<T> {
    inner: T,
}

fn main() {
    let foo: Foo<i32> = Foo::<i32> {
        inner: 0,
    };
}

```

If this worked for fns, it would be possible to associate constants same way as for structs:

```rust
fn foo<T>() {}

impl foo<i32> {
    const FOO: i32 = 0;
}

trait HasConst {
    const CONST: i32;
}

impl<T> HasConst for foo<T> {
    const CONST: i32 = 123;
}

```

But I guess this would be a breaking change since this would forbid modules with same name as function.

---

<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: [October 10, 2018, 4:04pm UTC](https://internals.rust-lang.org/t/idea-associated-items-for-functions/7822/11 "2018-10-10T16:04:55Z")

</div>

There’s a couple of proposed fixes for being unnable to name the function (disclaimer, both syntaces are mine):

- Add the production like `fn $path` to the type grammar, that allows for explicitly naming function ZSTs. The space is obnoxious, since you’d have to write things like `(fn foo)::CONST`.
- Add the production `$expr::type` to the type grammar, like a C++ `decltype`. This takes an expression, but instead of evaluating it, types it and returns the type.

---

<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/idea-associated-items-for-functions/7822/12 "2019-03-25T08:30:26Z")

</div>

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