Support for a language with! literal that allows initializing an inferred struct.
Motivation
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.
Drawbacks
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.
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?
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.