rust icon indicating copy to clipboard operation
rust copied to clipboard

Tracking Issue for RFC 2528: type-changing struct update syntax

Open joshtriplett opened this issue 3 years ago • 3 comments

This is a tracking issue for RFC 2528 (rust-lang/rfcs#2528), type-changing struct update syntax.

The feature gate for the issue will be #![feature(type_changing_struct_update)].

There is a dedicated Zulip stream: #project-type-changing-struct-update

About tracking issues

Tracking issues are used to record the overall progress of implementation. They are also used as hubs connecting to other relevant issues, e.g., bugs or open design questions. A tracking issue is however not meant for large scale discussion, questions, or bug reports about a feature. Instead, open a dedicated issue for the specific matter and add the relevant feature gate label.

Steps

Unresolved Questions

  • [ ] Type inference: when implementing this, we need to confirm that it won't adversely affect type inference.

"Further generalization" in the RFC would be the subject of future RFCs, not something we need to track in this tracking issue.

Implementation history

  • Feature gate: https://github.com/rust-lang/rust/pull/89730
  • Implementation: https://github.com/rust-lang/rust/pull/90035

joshtriplett avatar Jun 22 '21 21:06 joshtriplett

It looks like this has been implemented; are there any further known issues or blockers with it?

joshtriplett avatar Jul 27 '22 17:07 joshtriplett

I'm eagerly awaiting stabilisation of this feature! Is there anything that still needs to be done?

Rua avatar Sep 18 '22 06:09 Rua

It looks like this has been implemented; are there any further known issues or blockers with it?

Yes, i created #101970 to track it

crlf0710 avatar Sep 18 '22 09:09 crlf0710

This feature would be useful in bootloader development when different stages of bootloading would handover structures with small modifications. For example, bootstrap module would provide main function like:

fn main(param: Parameters) -> Handover {
    // ....
}

where Handover share most of fields with Parameters, but only small subset of fields are changed in declaration. This will be ideal to express the way Rust ownership works in embedded: one peripheral is wrapped in a structure to show it cannot be initialized or dropped twice. Thus, the wrapper struct should be provided as-is in Handover. We can do like this:

fn main(param: Parameters) -> Handover {
    let serial = Serial::new(param.uart0, /* ... */);
    // ....
    Handover { serial, ..param }
    // instead of: Handover { serial, periph_1: param.periph_1, periph_2: param.periph_2, periph_3: param.periph_3, /* ... */ }
}

We can now avoid repeat passing peripheral fields in bootload stage handovering, where there would typically be dozens of peripheral fields whose ownerships are going to be transfered.

I'll express my idea in playground link: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=7fb79bb65cce97cc785b78d9aca1e656

In this way, type changing struct update syntax will have an obvious code size reduction, which will help a lot in embedded development.

luojia65 avatar Mar 30 '23 15:03 luojia65

@luojia65 This feature is only for changing the generic arguments of the struct, e.g: going from Foo<Bar> to Foo<Baz>.

What you want sound like what's in the Rationales and Alternatives section of the RFC for this feature, except that it doesn't talk about going between structs with an intersection of fields.

rodrimati1992 avatar Mar 30 '23 18:03 rodrimati1992

This would work nicely with the arg struct pattern to allow providing default arguments for functions that take closures i.e.

struct Args<A: FnMut(), B: FnMut()> {
    pub a: A,
    pub b: B,
}

static NO_OP: fn() = ||{};
static DEFAULT_ARGS: Args<fn(), fn()> = Args { a: NO_OP, b: NO_OP };

// -- snip --

let arg = Arg {
  a: || println!("My non-default closure"),
  ..DEFAULT_ARGS
}
func_with_closure_args(arg);

(playground) (SO question for more context)

rcywongaa avatar Mar 12 '24 11:03 rcywongaa