-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Description
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