# Anonymous/inferred field types

**URL:** <https://internals.rust-lang.org/t/anonymous-inferred-field-types/8935>\
**Category:** language design\
**Created:** [November 30, 2018, 4:55pm UTC](https://internals.rust-lang.org/t/anonymous-inferred-field-types/8935 "2018-11-30T16:55:05Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![dhardy](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dhardy/32/2399_2.png) [@dhardy](https://internals.rust-lang.org/u/dhardy)\
**Post date:** [November 30, 2018, 4:55pm UTC](https://internals.rust-lang.org/t/anonymous-inferred-field-types/8935/1 "2018-11-30T16:55:06Z")

</div>

Is there any effort to support type inference for struct fields?

I mean, right now I can write:

```rust
let x = foo();
let y: _ = foo();

```

(for some typed function `foo`), but if I want to put the result in a struct I can’t do:

```rust
struct S { x: _ } // a single-use struct
let s = S { x: foo() };

```

I can use generics, but this prevents me from doing anything _with_ the field except via trait implementation:

```rust
struct S<X> { x: X }
let s = S { x: foo() };
// now I can't do anything with `s.x` even if I know the type!

```

Of course, this is non-trivial to do since the compiler must somehow prove that the struct’s type is well-defined (exactly one possible type), but I think with some restrictions it should be possible.

There are two motivations:

- laziness (e.g. [see this example](https://schleiss.io/rust/2017/05/15/type-inference-for-private-fields.html))
- ability to store unnameable types (i.e. closures)

---

<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:** [November 30, 2018, 6:25pm UTC](https://internals.rust-lang.org/t/anonymous-inferred-field-types/8935/2 "2018-11-30T18:25:16Z")

</div>

(disclaimer: I’m just repeating stuff I’ve observed through the grapevine as it were)

There’s no intrinsic reason this cannot be supported; the algorithm that Rust implements for type inference is capable of full program inference. (I _think_ it’s roughly equivalent to the one Haskell uses? @Centril probably knows better than I on that one. (I saw you typing.))

The choice to limit inference to locally within a function was one of locality. The idea being that since the function is the point of division between units of logic in your program, it makes sense to provide anchor points _for the programmer_ to understand what’s going on.

It’s also about one of the key values of Rust, fearless refactoring. Touching the implementation of a function is only possible to change inference within that function (type, lifetime, or otherwise) (if you don’t touch the signature), so this maintains locality of concerns.

* * *

That said, there are some specific proposals (and associated limitations) that could make many times you’d want this easier:

- existential types, so you can give a name to the huge type that is then inferred
- `impl Trait` types outside function headers, which could be seen as just a shortcut for using an existential type (or a generic therefore being problematic)

Though both of these do require explicit trait bounds which the usage abides to.

* * *

When limited to private interfaces, though, I definitely see benefit in allowing (controlled) type inference for more things. I know @Centril’s Haskell workflow they’ve shared here before in related discussions is to write the impl and let the compiler provide the type (which is then added on), and stronger type inference could be potentially used for this.

To maintain locality, perhaps it wouldn’t be “full program” inference, but restrict the parameters to just the current module. I’m pretty sure that would cover most cases of private inference while still allowing an account of locality such that the programmer could still easily predict/understand the outcome.

---

<div class="post-metadata">

**Author:** ![dhardy](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dhardy/32/2399_2.png) [@dhardy](https://internals.rust-lang.org/u/dhardy)\
**Post date:** [November 30, 2018, 6:31pm UTC](https://internals.rust-lang.org/t/anonymous-inferred-field-types/8935/3 "2018-11-30T18:31:27Z")

</div>

I agree, requiring that type inference succeeds within the current module is a sensible bound and would satisfy my use-case.

Interesting point that we may not want inferred types escaping the current crate. I don’t _think_ this would cause any issues for my intended usage and sounds like a good thing.

---

<div class="post-metadata">

**Author:** ![Centril](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/centril/32/3334_2.png) [@Centril](https://internals.rust-lang.org/u/Centril)\
**Post date:** [November 30, 2018, 8:37pm UTC](https://internals.rust-lang.org/t/anonymous-inferred-field-types/8935/4 "2018-11-30T20:37:04Z")

</div>

> [@CAD97](#):
>
> There’s no intrinsic reason this cannot be supported; the algorithm that Rust implements for type inference is capable of full program inference. (I _think_ it’s roughly equivalent to the one Haskell uses? @Centril probably knows better than I on that one. (I saw you typing.))

AFAIK Rust employs bidirectional type checking with Hindley-Milner based inference limited to analysis inside functions (except for closures...) and for `impl Trait` a limited global type inference is done. @eddyb or @nikomatsakis know more.

> [@CAD97](#):
>
> existential types, so you can give a name to the huge type that is then inferred

This is already in the works and exists in the nightly compiler (see [https://github.com/rust-lang/rfcs/pull/2071](https://github.com/rust-lang/rfcs/pull/2071)). The main open question to resolve is the surface syntax. (See [https://github.com/rust-lang/rfcs/pull/2515](https://github.com/rust-lang/rfcs/pull/2515) for a proposal to resolve the surface syntax as `type Foo = impl Trait;`. I could see permiting `struct Foo { bar: impl Baz, }` if we do that.

> [@CAD97](#):
>
> I know @Centril’s Haskell workflow they’ve shared here before in related discussions is to write the impl and let the compiler provide the type (which is then added on), and stronger type inference could be potentially used for this.

To describe my workflow more in-depth, I have two modes:

1. Type driven mode: Here, I write the type signature first and then I try to get tooling to fill in the implementation for me (especially useful in a dependently typed language since more can be automatically filled in). In this case, I am developing to a specific API that I know ahead of time.

1. Impl / generalization mode.

> [@dhardy](#):
>
> ```rust
> struct S { x: _ } // a single-use struct
> let s = S { x: foo() };
> 
> ```

This use case of a single use struct is probably better served by structural records which I've proposed in [RFC: Structural Records by Centril · Pull Request #2584 · rust-lang/rfcs · GitHub](https://github.com/rust-lang/rfcs/pull/2584).

---

<div class="post-metadata">

**Author:** ![dhardy](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dhardy/32/2399_2.png) [@dhardy](https://internals.rust-lang.org/u/dhardy)\
**Post date:** [December 1, 2018, 10:13am UTC](https://internals.rust-lang.org/t/anonymous-inferred-field-types/8935/5 "2018-12-01T10:13:26Z")

</div>

My use-case requires custom trait implementations (currently achieved via a derive macro and custom attributes). I’m not sure your structural records accomplish that. Currently I use a macro to generate code like this:

```rust
{
    #[my_attr(...)]
    #[derive(Clone, Debug, MyTrait)]
    struct AnonStruct<A: MyTrait> {
        fixed_field: u8,
        gen_field: A,
    }

    impl<A: MyTrait> AnonStruct {
        // custom impls passed into macro
    }

    AnonStruct {
        fixed_field: 0,
        gen_field: field_val, // passed into macro by user
    }
}

```

Locally the struct has a name, but effectively the macro just returns an anonymous type with some trait bounds.

This approach works, except that within the impls the type of `gen_field` is merely `A: MyTrait`, which makes it more difficult to use than necessary.

(Actually, I already have support for explicit typing by the user, but as mentioned that’s not always possible due to use of closures and often not simple.)

---

<div class="post-metadata">

**Author:** ![Centril](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/centril/32/3334_2.png) [@Centril](https://internals.rust-lang.org/u/Centril)\
**Post date:** [December 1, 2018, 12:11pm UTC](https://internals.rust-lang.org/t/anonymous-inferred-field-types/8935/6 "2018-12-01T12:11:43Z")

</div>

Oh I see; in that case structural records would indeed not help much.

I think having `field: impl Trait` might be something within reach but I think it will be hard to convince others to accept `field: _` (not personally against it; I see the value it has for macros…).

The closest proposal I have written about this is [https://github.com/rust-lang/rfcs/pull/2524](https://github.com/rust-lang/rfcs/pull/2524) which could be extended to fields directly.

---

<div class="post-metadata">

**Author:** ![dhardy](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dhardy/32/2399_2.png) [@dhardy](https://internals.rust-lang.org/u/dhardy)\
**Post date:** [December 1, 2018, 1:15pm UTC](https://internals.rust-lang.org/t/anonymous-inferred-field-types/8935/7 "2018-12-01T13:15:54Z")

</div>

Ah! That’s exactly what I want!

For now I have worked around this by supporting arbitrary trait bounds and facilitating implementation of arbitrary traits. This adds quite a bit of complexity to the system, but probably has other uses too.

---

<div class="post-metadata">

**Author:** ![Soni](https://avatars.discourse-cdn.com/v4/letter/s/a3d4f5/32.png) [@Soni](https://internals.rust-lang.org/u/Soni)\
**Post date:** [December 1, 2018, 1:34pm UTC](https://internals.rust-lang.org/t/anonymous-inferred-field-types/8935/8 "2018-12-01T13:34:27Z")

</div>

Why not allow field type inference within functions/expression blocks _only_?

---

<div class="post-metadata">

**Author:** ![dhardy](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dhardy/32/2399_2.png) [@dhardy](https://internals.rust-lang.org/u/dhardy)\
**Post date:** [December 1, 2018, 3:22pm UTC](https://internals.rust-lang.org/t/anonymous-inferred-field-types/8935/9 "2018-12-01T15:22:57Z")

</div>

I guess that would also work. You want to comment on the RFC? I think this thread has served its purpose.

---

<div class="post-metadata">

**Author:** ![eddyb](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/eddyb/32/8411_2.png) [@eddyb](https://internals.rust-lang.org/u/eddyb)\
**Post date:** [December 2, 2018, 9:27am UTC](https://internals.rust-lang.org/t/anonymous-inferred-field-types/8935/10 "2018-12-02T09:27:29Z")

</div>

> [@Centril](#):
>
> for `impl Trait` a limited global type inference is done

I think "limited global inference" isn't specific enough to make it clear _just how limited_ it is.

The Rust compiler always did, and still does, inference _only_ in "function/constant body + nested closures" groups.

`impl Trait` and still-unimplemented features like `typeof`, `const X: _` and [diagnostic-only "`-> _`"](https://github.com/rust-lang/rust/issues/56132), share a certain property that makes them _much simpler_ than global type inference:  
_Full_ type information is required to be _locally inferred_ before being made available to the rest of the world, and cycles are forbidden (i.e. the type information dependencies between non-closure `fn`/`const` bodies forms a DAG).

Note that it _also_ must be easy to tell, _syntactically_ and/or by using name resolution results, the direction of edges on that DAG, e.g. whether a `const`'s type is declared and used for checking its body ("inwards"), _or_ whether the type obtained by checking the body should be used as the type of the `const` ("outwards").

> [@dhardy](#):
>
> ```rust
> // now I can't do anything with `s.x` even if I know the type!
> 
> ```

I'm not sure I understand the context for this. Are we talking about some `impl Bar for S<_>` that wants to see the type of `x` _from_ its construction, i.e. `foo()`?

The main problem I see with a `x: _` field is that it needs the body of the original function to _fully type-check_ before it can (soundly) have a "globally available type". We _could_ make it so the original function sees the "in-progress type", since it's the one responsible for its inference (if we can even determine that's the case).  
We do something like this for closures, but those are more limited in their interactions, than struct/enum fields.

A while back I "proposed" a syntax like this, for a similar purpose:

```rust
let s = struct {
    x: foo(),
    y: Default::default(),
} impl Bar {
    fn baz(&self) -> Self {
        Self {
            x: self.x.clone(),
            y: -1,
        }
    }
}

```

I included a field `y` that we could infer _from_ the `baz` method _into_ the original function, but we can only do this if we treat such an `impl` body like we treat closures, which _requires_ that the `struct` is "globally unnameable".

And this is where some subtlety comes into play: items defined inside a function body are still "globally relevant", even if perhaps somewhat private - the trait system lets you do e.g.:

```rust
impl OutsideTrait for OutsideType {
    type AssocType = S;
}

```

I don't even know that my proposed solution is fully workable _but_ it's very unlikely we'll ever implement anything in `rustc` that doesn't have its type information dependency DAG and inference groups simple and computed from syntax/name-resolutions (Haskell does something similar, after all, it's just simpler in their case because name resolution is enough AFAICT).

Which means that soundness issues would be caught by "cyclic dependency" compiler errors, with no _truly global_ mutable state in sight.

---

<div class="post-metadata">

**Author:** ![dhardy](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dhardy/32/2399_2.png) [@dhardy](https://internals.rust-lang.org/u/dhardy)\
**Post date:** [December 2, 2018, 11:49am UTC](https://internals.rust-lang.org/t/anonymous-inferred-field-types/8935/11 "2018-12-02T11:49:18Z")

</div>

@eddyb this is more-or-less what I’m after. Your `struct { ... } impl { ... }` syntax is, well, concise — but doesn’t leave room for application of derive macros, as far as I can tell.

Can a named struct private to a value-yielding block like in the example in [my third post above](https://internals.rust-lang.org/t/anonymous-inferred-field-types/8935/5?u=dhardy) not achieve the same thing, without new syntax?

I guess this requires an extra type-inference step within the function/block scope and successful construction of a DAG. I think however this can be sufficiently simple?

---

<div class="post-metadata">

**Author:** ![eddyb](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/eddyb/32/8411_2.png) [@eddyb](https://internals.rust-lang.org/u/eddyb)\
**Post date:** [December 2, 2018, 12:05pm UTC](https://internals.rust-lang.org/t/anonymous-inferred-field-types/8935/12 "2018-12-02T12:05:30Z")

</div>

Part of the problem is that it’s less syntactically “obvious” where the type information comes from: the enclosing function, or the methods on the `struct`?

You have to _pick_ one of them, and then _happen to be correct_, otherwise you’ll get a cycle error.

As for derives combined with my approach, I expect `#[derive(Clone)] struct { x, y }` to work and generate:

```rust
struct {
    x, y,
} impl Clone {
    fn clone(&self) -> Self {
        Self {
            x: Clone::clone(&self.x),
            y: Clone::clone(&self.y),
        }
    }
}

```

---

<div class="post-metadata">

**Author:** ![dhardy](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dhardy/32/2399_2.png) [@dhardy](https://internals.rust-lang.org/u/dhardy)\
**Post date:** [December 3, 2018, 10:58am UTC](https://internals.rust-lang.org/t/anonymous-inferred-field-types/8935/13 "2018-12-03T10:58:29Z")

</div>

That won’t work without significant changes to the [`DeriveInput`](https://docs.rs/syn/0.15/syn/struct.DeriveInput.html) data structure, which currently expects type information to be present. Also bear in mind that several derive macros make use of macros on fields, e.g. [serde](https://serde.rs/attributes.html) and some macros I am working on (related to 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:31am UTC](https://internals.rust-lang.org/t/anonymous-inferred-field-types/8935/14 "2019-03-25T08:31:14Z")

</div>

Closed on March 25, 2019, 8:31am UTC

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