Record-update syntax does not support transforming types


#1

I expected something like the following to work:

struct Foo<A, B, C> {
    a: A,
    b: B,
    // Assume there's a bunch more fields here so this would be a pain to copy 
    // when you're just changing one type
}

impl<A, B, C> Foo<A, B, C> {
    fn update_b<B_>(self, b: B_) -> Foo<A, B_> {
        Foo { b: b, .. self }
    }
}

However, I get a mismatched types error:

<anon>:8:24: 8:28 error: mismatched types:
 expected `Foo<_, B_>`,
    found `Foo<A, B>`
(expected type parameter,
    found a different type parameter) [E0308]
<anon>:8         Foo { b: b, .. self }
                                ^~~~
<anon>:8:24: 8:28 help: see the detailed explanation for E0308

I understand the problem, I was just hoping that the record update syntax would have been able to transform the type so I didn’t have to copy all the fields by hand.

Is this trivial to implement in the language? It would be forward-compatible AFAICT.


#2

I would think of this as a natural extension to the record update syntax.


#3

This is part of the reason why I ended up ditching strongly-typed builders entirely from a project of mine.


#4

In general, we’ve been adopting the semantics that ..foo is effectively short-hand for copying over the remaining fields – so one might imagine just removing any need for the two types to have any relationship at all, and instead simply require that it be some struct with fields of suitable names.


#5

That sounds a lot like row polymorphism.


#6

While we’re writing our Christmas lists, I’d also love anonymous record types for things like pulling (potentially subsets of) fields out of (for example) struct variants. I’d love, love, love to be able to do Variant(..fields) => { fields.thing } in a match without having to explicitly bind all the little blighters individually.


#7

Variant types would mean you can do v @ Variant {..} and v.thing would work.