@@ -79,12 +79,93 @@ impl fmt::Display for InvalidRustTarget {
79
79
}
80
80
}
81
81
82
+ /// This macro defines the Rust editions supported by bindgen.
83
+ macro_rules! define_rust_editions {
84
+ ( $( $variant: ident( $value: literal) => $minor: literal, ) * ) => {
85
+ #[ derive( Clone , Copy , Debug , PartialEq , Eq , Hash , PartialOrd , Ord ) ]
86
+ pub enum RustEdition {
87
+ $(
88
+ #[ doc = concat!( "The " , stringify!( $value) , " edition of Rust." ) ]
89
+ $variant,
90
+ ) *
91
+ }
92
+
93
+ impl FromStr for RustEdition {
94
+ type Err = InvalidRustEdition ;
95
+
96
+ fn from_str( s: & str ) -> Result <Self , Self :: Err > {
97
+ match s {
98
+ $( stringify!( $value) => Ok ( Self :: $variant) , ) *
99
+ _ => Err ( InvalidRustEdition ( s. to_owned( ) ) ) ,
100
+ }
101
+ }
102
+ }
103
+
104
+ impl fmt:: Display for RustEdition {
105
+ fn fmt( & self , f: & mut fmt:: Formatter <' _>) -> fmt:: Result {
106
+ match self {
107
+ $( Self :: $variant => stringify!( $value) . fmt( f) , ) *
108
+ }
109
+ }
110
+ }
111
+
112
+ impl RustEdition {
113
+ pub ( crate ) const ALL : [ Self ; [ $( $value, ) * ] . len( ) ] = [ $( Self :: $variant, ) * ] ;
114
+
115
+ pub ( crate ) fn is_available( self , target: RustTarget ) -> bool {
116
+ let Some ( minor) = target. minor( ) else {
117
+ return true ;
118
+ } ;
119
+
120
+ match self {
121
+ $( Self :: $variant => $minor <= minor, ) *
122
+ }
123
+ }
124
+ }
125
+ }
126
+ }
127
+
128
+ #[ derive( Debug ) ]
129
+ pub struct InvalidRustEdition ( String ) ;
130
+
131
+ impl fmt:: Display for InvalidRustEdition {
132
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
133
+ write ! ( f, "\" {}\" is not a valid Rust edition" , self . 0 )
134
+ }
135
+ }
136
+
137
+ impl std:: error:: Error for InvalidRustEdition { }
138
+
139
+ define_rust_editions ! {
140
+ Edition2018 ( 2018 ) => 31 ,
141
+ Edition2021 ( 2021 ) => 56 ,
142
+ + Edition2024 ( 2024 ) => 85 ,
143
+ }
144
+
145
+ impl RustTarget {
146
+ /// Returns the latest edition supported by this target.
147
+ pub ( crate ) fn latest_edition ( self ) -> RustEdition {
148
+ RustEdition :: ALL
149
+ . iter ( )
150
+ . rev ( )
151
+ . find ( |edition| edition. is_available ( self ) )
152
+ . copied ( )
153
+ . expect ( "bindgen should always support at least one edition" )
154
+ }
155
+ }
156
+
157
+ impl Default for RustEdition {
158
+ fn default ( ) -> Self {
159
+ RustTarget :: default ( ) . latest_edition ( )
160
+ }
161
+ }
162
+
82
163
/// This macro defines the [`RustTarget`] and [`RustFeatures`] types.
83
164
macro_rules! define_rust_targets {
84
165
(
85
- Nightly => { $( $nightly_feature: ident $( : #$issue: literal) ?) ,* $( , ) ?} $( , ) ?
166
+ Nightly => { $( $nightly_feature: ident $( ( $nightly_edition : literal ) ) | * $ ( : #$issue: literal) ?) ,* $( , ) ?} $( , ) ?
86
167
$(
87
- $variant: ident( $minor: literal) => { $( $feature: ident $( : #$pull: literal) ?) ,* $( , ) ?} ,
168
+ $variant: ident( $minor: literal) => { $( $feature: ident $( ( $edition : literal ) ) | * $ ( : #$pull: literal) ?) ,* $( , ) ?} ,
88
169
) *
89
170
$( , ) ?
90
171
) => {
@@ -163,7 +244,7 @@ define_rust_targets! {
163
244
} ,
164
245
Stable_1_77 ( 77 ) => {
165
246
offset_of: #106655 ,
166
- literal_cstr: #117472 ,
247
+ literal_cstr( 2021 ) | ( 2024 ) : #117472 ,
167
248
} ,
168
249
Stable_1_73 ( 73 ) => { thiscall_abi: #42202 } ,
169
250
Stable_1_71 ( 71 ) => { c_unwind_abi: #106075 } ,
@@ -306,6 +387,26 @@ impl Default for RustFeatures {
306
387
mod test {
307
388
use super :: * ;
308
389
390
+ #[ test]
391
+ fn release_versions_for_editions ( ) {
392
+ assert_eq ! (
393
+ "1.33" . parse:: <RustTarget >( ) . unwrap( ) . latest_edition( ) ,
394
+ RustEdition :: Edition2018
395
+ ) ;
396
+ assert_eq ! (
397
+ "1.56" . parse:: <RustTarget >( ) . unwrap( ) . latest_edition( ) ,
398
+ RustEdition :: Edition2021
399
+ ) ;
400
+ assert_eq ! (
401
+ "1.85" . parse:: <RustTarget >( ) . unwrap( ) . latest_edition( ) ,
402
+ RustEdition :: Edition2024
403
+ ) ;
404
+ assert_eq ! (
405
+ "nightly" . parse:: <RustTarget >( ) . unwrap( ) . latest_edition( ) ,
406
+ RustEdition :: Edition2024
407
+ ) ;
408
+ }
409
+
309
410
#[ test]
310
411
fn target_features ( ) {
311
412
let features = RustFeatures :: from ( RustTarget :: Stable_1_71 ) ;
0 commit comments