[Pre-RFC] Inferred struct initializer (2)


Support for a language with! literal that allows initializing an inferred struct.


It is a common practice to use struct initializers in the form Struct {} for options containers.

This prevents importing or aliasing types, as well as omits the name of common options types, context types, and node types.

use my_library::LargeOptions;

function(LargeOptions { ..default() });
function(with! { .. });

Guide-level explanation

The with! literal is used for initializing a struct without specifying its path. It supports the same contents as with struct initializers. It additionally supports an empty trailing .. component, equivalent to ..Default::default().

struct S { x: f64, y: f64 }

let object: S = with! { x: 10.0, y: 10.0 };
let object: S = with! {}; // ERROR: missing fields

Reference-level explanation

The with! literal is implemented as a native language macro whose contents resemble the braced contents of a struct initializer.

  • The with! expression requires a type annotation.
  • If an empty .. component appears, the inferred struct must implement Default, and the initializer uses Default::default() as a base object.


The syntax may or may not be familiar to everyone.

Rationale and alternatives

This design is a bit more verbose than other proposals (such as _ {}), but always retains conciseness as it uses existing Rust syntax and introduces solely a native macro.

It is currently possible to implement a similiar macro, but always requiring a base object as there is no way to know the inferred struct's path. As such, this proposal allows initializing structs without a .. component.

Prior art

Languages such as JavaScript and VBScript support a legacy with statement used for a similiar purpose, but historically used for chaining operations on an existing object.

With object
    .X = 10
    .Y = 10

Unresolved questions


Future possibilities


I do not really follow what you mean here. Could you share a short code snippet that highlights the problem and how the proposed with! would fix it?

1 Like

But that's not quite the case, is it?


struct S { x: f64, y: f64 }

let object = with! { x: 10.0, y: 10.0 };

Without annotating the type of object, what should this code do?

As the proposal mentions, there is another version of this idea, and that uses the _ { field0: true, field1: 42 } syntax or some variety of it. That has the added benefit of not looking like a macro invocation. The macro-invocation like syntax probably would be more trouble than it's worth because of the syntactic ambiguity it would introduce for the Rust parser, illustrated by this snippet:

with! { x: 10.0, y: 10.0 } 

From the POV of the parser, would that expression be a macro invocation or a with!-expression?


Can you elaborate why a macro-looking thing is the best syntax for this? Why is that better than, say, let object: S = .{ x: 10.0, y: 10.0 };?

It should fail with a type inference error, same as if you do let object = Default::default(); without constraining it.

You can actually do this today, albeit only in the ..default() form, using the macro in Pre-pre-RFC: syntactic sugar for `Default::default()` - #7 by scottmcm


I had already replied those questions before...

Here's an example:

use my_library::LargeOptions;

function(LargeOptions { ..default() });
function(with! { .. });

You still haven't explained what problem you're trying to solve. Why is this a better approach than _ { field: value }?

If we want to add a feature like this, there's no reason we need to confine it to a macro; we should choose the best design we can.


I'm sorry, I should have been more clear. I wasn't confused about the behavior.

The answer was meant as a rhetorical answer to, and refutation of, the quote that I started that post with, i.e. I meant to say that the with!-literal just moves the need to specify the type from the syntactic construct itself to the binding, rather than allowing its omission entirely.


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