Skip to content

Commit

Permalink
Support parsing #![feature(default_field_values)]
Browse files Browse the repository at this point in the history
- RFC: rust-lang/rfcs#3681
- Tracking issue: rust-lang/rust#132162
- Feature gate: `#![feature(default_field_values)]`

```rust
struct Pet {
    name: Option<String>,
    age: i128 = 42,
    //        ^^^^
}
```

Fix dtolnay#1774.
  • Loading branch information
estebank committed Mar 6, 2025
1 parent aed58d1 commit 6671f48
Show file tree
Hide file tree
Showing 12 changed files with 167 additions and 1 deletion.
12 changes: 12 additions & 0 deletions src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,11 @@ ast_struct! {
pub colon_token: Option<Token![:]>,

pub ty: Type,

/// Default value: `field_name: i32 = 1`
///
/// `#![feature(default_field_values)]`
pub default: Option<(Token![=], Expr)>,
}
}

Expand Down Expand Up @@ -345,6 +350,11 @@ pub(crate) mod parsing {
} else {
input.parse()?
};
let mut default: Option<(Token![=], Expr)> = None;
if input.peek(Token![=]) {
let eq_token: Token![=] = input.parse()?;
default = Some((eq_token, input.parse()?));
}

Ok(Field {
attrs,
Expand All @@ -353,6 +363,7 @@ pub(crate) mod parsing {
ident: Some(ident),
colon_token: Some(colon_token),
ty,
default,
})
}

Expand All @@ -366,6 +377,7 @@ pub(crate) mod parsing {
ident: None,
colon_token: None,
ty: input.parse()?,
default: None,
})
}
}
Expand Down
1 change: 1 addition & 0 deletions src/gen/clone.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/gen/debug.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/gen/eq.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/gen/fold.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/gen/hash.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions src/gen/visit.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions src/gen/visit_mut.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 8 additions & 1 deletion src/parse_quote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ impl<T: Parse> ParseQuote for T {

use crate::punctuated::Punctuated;
#[cfg(any(feature = "full", feature = "derive"))]
use crate::{attr, Attribute, Field, FieldMutability, Ident, Type, Visibility};
use crate::{attr, Attribute, Expr, Field, FieldMutability, Ident, Type, Visibility};
#[cfg(feature = "full")]
use crate::{Arm, Block, Pat, Stmt};

Expand Down Expand Up @@ -194,13 +194,20 @@ impl ParseQuote for Field {

let ty: Type = input.parse()?;

let mut default: Option<(Token![=], Expr)> = None;
if is_named && input.peek(Token![=]) {
let eq_token: Token![=] = input.parse()?;
default = Some((eq_token, input.parse()?));
}

Ok(Field {
attrs,
vis,
mutability: FieldMutability::None,
ident,
colon_token,
ty,
default,
})
}
}
Expand Down
12 changes: 12 additions & 0 deletions syn.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions tests/debug/gen.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

108 changes: 108 additions & 0 deletions tests/test_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,114 @@ fn test_impl_visibility() {
snapshot!(tokens as Item, @"Item::Verbatim(`pub default unsafe impl union { }`)");
}

#[test]
fn test_default_field_values() {
let tokens = quote! {
struct Foo {
field_int: i32 = 42,
field_const: i32 = const { 42 },
}
};
snapshot!(tokens as Item, @r#"
Item::Struct {
vis: Visibility::Inherited,
ident: "Foo",
generics: Generics,
fields: Fields::Named {
named: [
Field {
vis: Visibility::Inherited,
ident: Some("field_int"),
colon_token: Some,
ty: Type::Path {
path: Path {
segments: [
PathSegment {
ident: "i32",
},
],
},
},
default: Some(Expr::Lit {
lit: 42,
}),
},
Token![,],
Field {
vis: Visibility::Inherited,
ident: Some("field_const"),
colon_token: Some,
ty: Type::Path {
path: Path {
segments: [
PathSegment {
ident: "i32",
},
],
},
},
default: Some(Expr::Const {
block: Block {
stmts: [
Stmt::Expr(
Expr::Lit {
lit: 42,
},
None,
),
],
},
}),
},
Token![,],
],
},
}
"#);

let tokens = quote! {
enum Foo {
Bar {
field: i32 = 42,
}
}
};
snapshot!(tokens as Item, @r#"
Item::Enum {
vis: Visibility::Inherited,
ident: "Foo",
generics: Generics,
variants: [
Variant {
ident: "Bar",
fields: Fields::Named {
named: [
Field {
vis: Visibility::Inherited,
ident: Some("field"),
colon_token: Some,
ty: Type::Path {
path: Path {
segments: [
PathSegment {
ident: "i32",
},
],
},
},
default: Some(Expr::Lit {
lit: 42,
}),
},
Token![,],
],
},
},
],
}
"#);
}

#[test]
fn test_impl_type_parameter_defaults() {
#[cfg(any())]
Expand Down

0 comments on commit 6671f48

Please sign in to comment.