Skip to content

Support type transformations in FRU (functional record update) syntax #1975

@abonander

Description

@abonander

I remember discussing this a while ago. I thought I had an issue open somewhere for this but I guess not.

It's currently not allowed to use FRU (functional record update) syntax to return a transformed type, i.e.:

struct Foo<T> {
    val: T,
    tag: &'static str,
}

impl<T> Foo<T> {
    fn transform<U>(self, val: U) -> Foo<U> {
        Foo { val: val, .. self }
    }
}

will throw a "mismatched type" error with the span of self in the FRU literal because it is of type Foo<T> and not Foo<U>, even though the remaining fields of self are compatible.

According to RFC 736, FRU is supposed to be just syntactic sugar for a full struct literal, but a full struct literal works in this case because it doesn't place any restriction on the type of self.

Possible solutions:

  • Move fields nominally (foo: <tail expr>.foo, bar: <tail expr>.bar, etc.) and typecheck them individually, not typechecking the tail expression at all. This could allow FRU to work even between otherwise incompatible types which have compatible fields. I like this one more but it may be too implicit for some, and I gather that we don't want to add too much meaning to field names.

  • Only check equality of the outermost type constructor between the FRU literal and the tail expression, i.e. check that Foo<T> ~= Foo<U>; then, typecheck the moved fields individually. This would allow the above use-case but disallow using an entirely different type as the source or destination.

As far as I understand it, this should be backwards-compatible since it would strictly allow more code to compile.

Edit: clarify generic params

Metadata

Metadata

Assignees

No one assigned

    Labels

    T-langRelevant to the language team, which will review and decide on the RFC.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions