@@ -163,7 +163,7 @@ macro_rules! s {
163163 ) * ) ;
164164
165165 ( it: $( #[ $attr: meta] ) * $pub: vis union $i: ident { $( $field: tt) * } ) => (
166- compile_error!( "unions cannot derive extra traits, use s_no_extra_traits instead" ) ;
166+ :: core :: compile_error!( "unions cannot derive extra traits, use s_no_extra_traits instead" ) ;
167167 ) ;
168168
169169 ( it: $( #[ $attr: meta] ) * $pub: vis struct $i: ident { $( $field: tt) * } ) => (
@@ -253,19 +253,19 @@ macro_rules! s_no_extra_traits {
253253/// Like [`s`], but also generates a `Default` impl for every struct in the block.
254254macro_rules! s_with_default {
255255 ( $(
256- $( #[ $attr: meta ] ) *
256+ $( #$attr: tt ) *
257257 $pub: vis $t: ident $i: ident { $( $field: tt) * }
258258 ) * ) => ( $(
259- s_with_default!( it: $( #[ $attr] ) * $pub $t $i { $( $field) * } ) ;
259+ s_with_default!( it: $( #$attr) * $pub $t $i { $( $field) * } ) ;
260260 ) * ) ;
261261
262- ( it: $( #[ $attr: meta ] ) * $pub: vis union $i: ident { $( $field: tt) * } ) => (
263- compile_error!(
262+ ( it: $( #$attr: tt ) * $pub: vis union $i: ident { $( $field: tt) * } ) => (
263+ :: core :: compile_error!(
264264 "unions cannot derive extra traits, use s_no_extra_traits_with_default instead"
265265 ) ;
266266 ) ;
267267
268- ( it: $( #[ $attr: meta ] ) * $pub: vis struct $i: ident { $( $field: tt) * } ) => (
268+ ( it: $( #$attr: tt ) * $pub: vis struct $i: ident { $( $field: tt) * } ) => (
269269 struct_with_default! {
270270 attrs: {
271271 #[ repr( C ) ]
@@ -280,7 +280,7 @@ macro_rules! s_with_default {
280280 ) ]
281281 #[ allow( deprecated) ]
282282 }
283- $( #[ $attr] ) * $pub struct $i { $( $field) * }
283+ $( #$attr) * $pub struct $i { $( $field) * }
284284 }
285285 ) ;
286286}
@@ -291,19 +291,19 @@ macro_rules! s_with_default {
291291/// union type supplies its own default via `#[custom_default(...)]`.
292292macro_rules! s_no_extra_traits_with_default {
293293 ( $(
294- $( #[ $attr: meta ] ) *
294+ $( #$attr: tt ) *
295295 $pub: vis $t: ident $i: ident { $( $field: tt) * }
296296 ) * ) => ( $(
297- s_no_extra_traits_with_default!( it: $( #[ $attr] ) * $pub $t $i { $( $field) * } ) ;
297+ s_no_extra_traits_with_default!( it: $( #$attr) * $pub $t $i { $( $field) * } ) ;
298298 ) * ) ;
299299
300- ( it: $( #[ $attr: meta ] ) * $pub: vis union $i: ident { $( $field: tt) * } ) => (
300+ ( it: $( #$attr: tt ) * $pub: vis union $i: ident { $( $field: tt) * } ) => (
301301 #[ repr( C ) ]
302302 #[ :: core:: prelude:: v1:: derive(
303303 :: core:: clone:: Clone ,
304304 :: core:: marker:: Copy ,
305305 ) ]
306- $( #[ $attr] ) *
306+ $( #$attr) *
307307 $pub union $i { $( $field) * }
308308
309309 impl :: core:: fmt:: Debug for $i {
@@ -313,7 +313,7 @@ macro_rules! s_no_extra_traits_with_default {
313313 }
314314 ) ;
315315
316- ( it: $( #[ $attr: meta ] ) * $pub: vis struct $i: ident { $( $field: tt) * } ) => (
316+ ( it: $( #$attr: tt ) * $pub: vis struct $i: ident { $( $field: tt) * } ) => (
317317 struct_with_default! {
318318 attrs: {
319319 #[ repr( C ) ]
@@ -323,7 +323,7 @@ macro_rules! s_no_extra_traits_with_default {
323323 :: core:: fmt:: Debug ,
324324 ) ]
325325 }
326- $( #[ $attr] ) * $pub struct $i { $( $field) * }
326+ $( #$attr) * $pub struct $i { $( $field) * }
327327 }
328328 ) ;
329329}
@@ -343,12 +343,12 @@ macro_rules! struct_with_default {
343343 // which is merged with the struct's own attributes.
344344 (
345345 attrs: { $( $attrs: tt) * }
346- $( #[ $attr: meta ] ) *
346+ $( #$attr: tt ) *
347347 $vis: vis struct $name: ident { $( $body: tt) * }
348348 ) => {
349349 struct_with_default! {
350350 @struct
351- attrs: { $( $attrs) * $( #[ $attr] ) * }
351+ attrs: { $( $attrs) * $( #$attr) * }
352352 vis: { $vis }
353353 name: { $name }
354354 processed_fields: { }
@@ -414,7 +414,7 @@ macro_rules! struct_with_default {
414414 }
415415 } ;
416416
417- // done
417+ // done with `Default`, start scanning for the `exhaustive` attribute
418418 (
419419 @struct
420420 attrs: { $( $attrs: tt) * }
@@ -424,18 +424,112 @@ macro_rules! struct_with_default {
424424 processed_field_defaults: { $( $processed_field_defaults: tt) * }
425425 remaining_fields: { }
426426 ) => {
427- $( $attrs) *
428- $vis struct $name { $( $processed_fields) * }
427+ struct_with_default! {
428+ @attr
429+ attrs: { $( $attrs) * }
430+ processed_attrs: { }
431+ found: { false }
432+ vis: { $vis }
433+ name: { $name }
434+ processed_fields: { $( $processed_fields) * }
435+ processed_field_defaults: { $( $processed_field_defaults) * }
436+ }
437+ } ;
438+
439+ // done with `Default` and `exhaustive`; we hand off handling the basecase
440+ // of either adding the private field or not to the `fin` macro.
441+ (
442+ @attr
443+ attrs: { }
444+ processed_attrs: { $( $attrs: tt) * }
445+ found: { $found: tt }
446+ vis: { $vis: vis }
447+ name: { $name: ident }
448+ processed_fields: { $( $processed_fields: tt) * }
449+ processed_field_defaults: { $( $processed_field_defaults: tt) * }
450+ ) => {
451+ fin! { $found decl: $( $attrs) * $vis $name { $( $processed_fields) * } }
429452
430453 impl :: core:: default :: Default for $name {
431- // Field attributes (`#[cfg]`, doc comments) get forwarded to the initializer too.
432- // Docs are harmless there but trip the lint, so silence it.
454+ // Field attributes (`#[cfg]`, doc comments) get forwarded to the
455+ // initializer too. Docs are harmless there but trip the lint, so
456+ // silence it.
433457 #[ allow( unused_doc_comments) ]
434458 fn default ( ) -> Self {
435- Self { $( $processed_field_defaults) * }
459+ fin! { $found default : { $ ( $processed_field_defaults) * } }
436460 }
437461 }
438462 } ;
463+
464+ // found `exhaustive`; parameter `found` is not matched against `false` in
465+ // case somebody annotates a `struct` with more than one `exhaustive`. If we
466+ // didn't match a wildcard, that attribute would go down to the general case
467+ // of the muncher and add it to the packed matcher of `processed_attrs`.
468+ (
469+ @attr
470+ attrs: { #[ exhaustive] $( $attrs: tt) * }
471+ processed_attrs: { $( $prev_attrs: tt) * }
472+ found: { $_: tt }
473+ vis: { $vis: vis }
474+ name: { $name: ident }
475+ processed_fields: { $( $processed_fields: tt) * }
476+ processed_field_defaults: { $( $processed_field_defaults: tt) * }
477+ ) => {
478+ struct_with_default! {
479+ @attr
480+ attrs: { $( $attrs) * }
481+ processed_attrs: { $( $prev_attrs) * }
482+ found: { true }
483+ vis: { $vis }
484+ name: { $name }
485+ processed_fields: { $( $processed_fields) * }
486+ processed_field_defaults: { $( $processed_field_defaults) * }
487+ }
488+ } ;
489+
490+ // we've not found `exhaustive`; we keep munching to see whether it's still
491+ // there
492+ (
493+ @attr
494+ attrs: { #$other: tt $( $attrs: tt) * }
495+ processed_attrs: { $( $prev_attrs: tt) * }
496+ found: { $found: tt }
497+ vis: { $vis: vis }
498+ name: { $name: ident }
499+ processed_fields: { $( $processed_fields: tt) * }
500+ processed_field_defaults: { $( $processed_field_defaults: tt) * }
501+ ) => {
502+ struct_with_default! {
503+ @attr
504+ attrs: { $( $attrs) * }
505+ processed_attrs: { $( $prev_attrs) * #$other }
506+ found: { $found }
507+ vis: { $vis }
508+ name: { $name }
509+ processed_fields: { $( $processed_fields) * }
510+ processed_field_defaults: { $( $processed_field_defaults) * }
511+ }
512+ } ;
513+ }
514+
515+ /// Helper macro for `struct_with_default`. Prints the basecase item with either
516+ /// the private `non_exhaustive` field or not.
517+ macro_rules! fin {
518+ ( true decl: $( #[ $attr: meta] ) * $vis: vis $name: ident { $( $field: tt) * } ) => {
519+ $( #[ $attr] ) *
520+ $vis struct $name { $( $field) * }
521+ } ;
522+ ( true default : { $( $field_default: tt) * } ) => {
523+ Self { $( $field_default) * }
524+ } ;
525+
526+ ( false decl: $( #[ $attr: meta] ) * $vis: vis $name: ident { $( $field: tt) * } ) => {
527+ $( #[ $attr] ) *
528+ $vis struct $name { $( $field) * __non_exhaustive: ( ) }
529+ } ;
530+ ( false default : { $( $field_default: tt) * } ) => {
531+ Self { $( $field_default) * __non_exhaustive: ( ) }
532+ } ;
439533}
440534
441535/// Create an uninhabited type that can't be constructed. It implements `Debug`, `Clone`,
@@ -620,7 +714,7 @@ macro_rules! f {
620714 fn $i: ident ( $( $arg: ident: $argty: ty) ,* $( , ) ?) -> $ret: ty
621715 $body: block
622716 ) => {
623- compile_error!( "either `safe` or `unsafe` must be specified" ) ;
717+ :: core :: compile_error!( "either `safe` or `unsafe` must be specified" ) ;
624718 } ;
625719}
626720
0 commit comments