@@ -598,51 +598,83 @@ impl Qualif for IsNotImplicitlyPromotable {
598598 }
599599}
600600
601- // Ensure the `IDX` values are sequential (`0..QUALIF_COUNT`).
602- macro_rules! define_qualif_indices {
601+ macro_rules! define_qualifs {
602+ // Top-level, non-recursive mode
603+
604+ ( $( $Q: ident ) ,* $( , ) ? ) => {
605+ /// Executes `body` once for each implementor of `Qualif`.
606+ ///
607+ /// This macro overloads closure syntax to put the type of each `Qualif` as well as
608+ /// a value of that type into scope for `body`. For example, the following code would print
609+ /// the result of `in_any_value_of_ty` for each `Qualif` (assuming `cx` and `ty` are
610+ /// already in scope).
611+ ///
612+ /// ```
613+ /// for_each_qualif!(|q: Q| dbg!(Q::in_any_value_of_ty(cx, ty)));
614+ /// ```
615+ ///
616+ /// Note that the type annotation for the closure argument (the `Q` in `q: Q`) is
617+ /// mandatory and must be a valid identifier (it is used as the name of a type alias within
618+ /// the macro).
619+ macro_rules! for_each_qualif {
620+ ( |$q: ident : $ty: ident| $body: expr ) => {
621+ {
622+ $(
623+ ( |$q| {
624+ #[ allow( unused) ]
625+ type $ty = $Q;
626+ $body
627+ } ) ( $Q) ;
628+ ) *
629+ }
630+ }
631+ }
632+
633+ // Enter recursive mode to assign a numeric index to each `Qualif`
634+ define_qualifs!( 0 => $( $Q ) ,* ) ;
635+ } ;
636+
637+ // Recursive mode
638+
603639 ( $i: expr => $first: ident $( , $rest: ident) * ) => {
604640 impl QualifIdx for $first {
605641 const IDX : usize = $i;
606642 }
607643
608- define_qualif_indices !( $i + 1 => $( $rest) ,* ) ;
644+ define_qualifs !( $i + 1 => $( $rest) ,* ) ;
609645 } ;
610646 ( $i: expr =>) => {
611647 const QUALIF_COUNT : usize = $i;
612648 } ;
613649}
614650
615- define_qualif_indices ! (
616- 0 => HasMutInterior , NeedsDrop , IsNotPromotable , IsNotImplicitlyPromotable
651+ define_qualifs ! (
652+ HasMutInterior , NeedsDrop , IsNotPromotable , IsNotImplicitlyPromotable
617653) ;
618654static_assert ! ( QUALIF_COUNT == 4 ) ;
619655
620656impl ConstCx < ' _ , ' tcx > {
621657 fn qualifs_in_any_value_of_ty ( & self , ty : Ty < ' tcx > ) -> PerQualif < bool > {
622658 let mut qualifs = PerQualif :: default ( ) ;
623- qualifs[ HasMutInterior ] = HasMutInterior :: in_any_value_of_ty ( self , ty) . unwrap_or ( false ) ;
624- qualifs[ NeedsDrop ] = NeedsDrop :: in_any_value_of_ty ( self , ty) . unwrap_or ( false ) ;
625- qualifs[ IsNotPromotable ] = IsNotPromotable :: in_any_value_of_ty ( self , ty) . unwrap_or ( false ) ;
626- qualifs[ IsNotImplicitlyPromotable ] =
627- IsNotImplicitlyPromotable :: in_any_value_of_ty ( self , ty) . unwrap_or ( false ) ;
659+ for_each_qualif ! ( |q: Q | {
660+ qualifs[ q] = Q :: in_any_value_of_ty( self , ty) . unwrap_or( false ) ;
661+ } ) ;
628662 qualifs
629663 }
630664
631665 fn qualifs_in_local ( & self , local : Local ) -> PerQualif < bool > {
632666 let mut qualifs = PerQualif :: default ( ) ;
633- qualifs[ HasMutInterior ] = HasMutInterior :: in_local ( self , local) ;
634- qualifs[ NeedsDrop ] = NeedsDrop :: in_local ( self , local) ;
635- qualifs[ IsNotPromotable ] = IsNotPromotable :: in_local ( self , local) ;
636- qualifs[ IsNotImplicitlyPromotable ] = IsNotImplicitlyPromotable :: in_local ( self , local) ;
667+ for_each_qualif ! ( |q: Q | {
668+ qualifs[ q] = Q :: in_local( self , local) ;
669+ } ) ;
637670 qualifs
638671 }
639672
640673 fn qualifs_in_value ( & self , source : ValueSource < ' _ , ' tcx > ) -> PerQualif < bool > {
641674 let mut qualifs = PerQualif :: default ( ) ;
642- qualifs[ HasMutInterior ] = HasMutInterior :: in_value ( self , source) ;
643- qualifs[ NeedsDrop ] = NeedsDrop :: in_value ( self , source) ;
644- qualifs[ IsNotPromotable ] = IsNotPromotable :: in_value ( self , source) ;
645- qualifs[ IsNotImplicitlyPromotable ] = IsNotImplicitlyPromotable :: in_value ( self , source) ;
675+ for_each_qualif ! ( |q: Q | {
676+ qualifs[ q] = Q :: in_value( self , source) ;
677+ } ) ;
646678 qualifs
647679 }
648680}
0 commit comments