| r[expr.struct] | |
| # Struct expressions | |
| r[expr.struct.syntax] | |
| ```grammar,expressions | |
| StructExpression -> | |
| PathInExpression `{` (StructExprFields | StructBase)? `}` | |
| StructExprFields -> | |
| StructExprField (`,` StructExprField)* (`,` StructBase | `,`?) | |
| StructExprField -> | |
| OuterAttribute* | |
| ( | |
| IDENTIFIER | |
| | (IDENTIFIER | TUPLE_INDEX) `:` Expression | |
| ) | |
| StructBase -> `..` Expression | |
| ``` | |
| r[expr.struct.intro] | |
| A *struct expression* creates a struct, enum, or union value. It consists of a path to a [struct], [enum variant], or [union] item followed by the values for the fields of the item. | |
| The following are examples of struct expressions: | |
| ```rust | |
| # struct Point { x: f64, y: f64 } | |
| # struct NothingInMe { } | |
| # mod game { pub struct User<'a> { pub name: &'a str, pub age: u32, pub score: usize } } | |
| # enum Enum { Variant {} } | |
| Point {x: 10.0, y: 20.0}; | |
| NothingInMe {}; | |
| let u = game::User {name: "Joe", age: 35, score: 100_000}; | |
| Enum::Variant {}; | |
| ``` | |
| > [!NOTE] | |
| > Tuple structs and tuple enum variants are typically instantiated using a [call expression][expr.call] referring to the [constructor in the value namespace][items.struct.tuple]. These are distinct from a struct expression using curly braces referring to the constructor in the type namespace. | |
| > | |
| > ```rust | |
| > struct Position(i32, i32, i32); | |
| > Position(0, 0, 0); // Typical way of creating a tuple struct. | |
| > let c = Position; // `c` is a function that takes 3 arguments. | |
| > let pos = c(8, 6, 7); // Creates a `Position` value. | |
| > | |
| > enum Version { Triple(i32, i32, i32) }; | |
| > Version::Triple(0, 0, 0); | |
| > let f = Version::Triple; | |
| > let ver = f(8, 6, 7); | |
| > ``` | |
| > | |
| > The last segment of the call path cannot refer to a type alias: | |
| > | |
| > ```rust | |
| > trait Tr { type T; } | |
| > impl<T> Tr for T { type T = T; } | |
| > | |
| > struct Tuple(); | |
| > enum Enum { Tuple() } | |
| > | |
| > // <Unit as Tr>::T(); // causes an error -- `::T` is a type, not a value | |
| > <Enum as Tr>::T::Tuple(); // OK | |
| > ``` | |
| > | |
| > ---- | |
| > | |
| > Unit structs and unit enum variants are typically instantiated using a [path expression][expr.path] referring to the [constant in the value namespace][items.struct.unit]. | |
| > | |
| > ```rust | |
| > struct Gamma; | |
| > // Gamma unit value, referring to the const in the value namespace. | |
| > let a = Gamma; | |
| > // Exact same value as `a`, but constructed using a struct expression | |
| > // referring to the type namespace. | |
| > let b = Gamma {}; | |
| > | |
| > enum ColorSpace { Oklch } | |
| > let c = ColorSpace::Oklch; | |
| > let d = ColorSpace::Oklch {}; | |
| > ``` | |
| r[expr.struct.field] | |
| ## Field struct expression | |
| r[expr.struct.field.intro] | |
| A struct expression with fields enclosed in curly braces allows you to specify the value for each individual field in any order. The field name is separated from its value with a colon. | |
| r[expr.struct.field.union-constraint] | |
| A value of a [union] type can only be created using this syntax, and it must specify exactly one field. | |
| r[expr.struct.update] | |
| ## Functional update syntax | |
| r[expr.struct.update.intro] | |
| A struct expression that constructs a value of a struct type can terminate with the syntax `..` followed by an expression to denote a functional update. | |
| r[expr.struct.update.base-same-type] | |
| The expression following `..` (the base) must have the same struct type as the new struct type being formed. | |
| r[expr.struct.update.fields] | |
| The entire expression uses the given values for the fields that were specified and moves or copies the remaining fields from the base expression. | |
| r[expr.struct.update.visibility-constraint] | |
| As with all struct expressions, all of the fields of the struct must be [visible], even those not explicitly named. | |
| ```rust | |
| # struct Point3d { x: i32, y: i32, z: i32 } | |
| let mut base = Point3d {x: 1, y: 2, z: 3}; | |
| let y_ref = &mut base.y; | |
| Point3d {y: 0, z: 10, .. base}; // OK, only base.x is accessed | |
| drop(y_ref); | |
| ``` | |
| r[expr.struct.brace-restricted-positions] | |
| Struct expressions can't be used directly in a [loop] or [if] expression's head, or in the [scrutinee] of an [if let] or [match] expression. However, struct expressions can be used in these situations if they are within another expression, for example inside [parentheses]. | |
| r[expr.struct.tuple-field] | |
| The field names can be decimal integer values to specify indices for constructing tuple structs. This can be used with base structs to fill out the remaining indices not specified: | |
| ```rust | |
| struct Color(u8, u8, u8); | |
| let c1 = Color(0, 0, 0); // Typical way of creating a tuple struct. | |
| let c2 = Color{0: 255, 1: 127, 2: 0}; // Specifying fields by index. | |
| let c3 = Color{1: 0, ..c2}; // Fill out all other fields using a base struct. | |
| ``` | |
| r[expr.struct.field.named] | |
| ### Struct field init shorthand | |
| When initializing a data structure (struct, enum, union) with named (but not numbered) fields, it is allowed to write `fieldname` as a shorthand for `fieldname: fieldname`. This allows a compact syntax with less duplication. For example: | |
| ```rust | |
| # struct Point3d { x: i32, y: i32, z: i32 } | |
| # let x = 0; | |
| # let y_value = 0; | |
| # let z = 0; | |
| Point3d { x: x, y: y_value, z: z }; | |
| Point3d { x, y: y_value, z }; | |
| ``` | |
| [enum variant]: ../items/enumerations.md | |
| [if let]: if-expr.md#if-let-patterns | |
| [if]: if-expr.md#if-expressions | |
| [loop]: loop-expr.md | |
| [match]: match-expr.md | |
| [parentheses]: grouped-expr.md | |
| [struct]: ../items/structs.md | |
| [union]: ../items/unions.md | |
| [visible]: ../visibility-and-privacy.md | |
| [scrutinee]: ../glossary.md#scrutinee |