@@ -802,3 +802,83 @@ macro_rules! impl_size_eq {
802
802
} ;
803
803
} ;
804
804
}
805
+
806
+ macro_rules! const_fn {
807
+ (
808
+ $vis: vis $name: ident $( < $( $tyvar: ident) ,* >) ?
809
+ ( $( $arg: ident: $argty: ty) ,* ) -> $retty: ty
810
+ $(
811
+ where $( $wheretyvar: ident: $wherebound: path, ) *
812
+ ) ?
813
+ $body: block
814
+ ) => {
815
+ #[ allow( non_camel_case_types) ]
816
+ $vis trait $name $( < $( $tyvar) ,* >) ?
817
+ where Self : crate :: util:: macros:: HasArgs <( $( $argty, ) * ) , Args = ( $( $argty, ) * ) >,
818
+ $(
819
+ $( $wheretyvar: $wherebound) ,*
820
+ ) ?
821
+ {
822
+ const ARGS : Self :: Args ;
823
+
824
+ const __RETURN: $retty = {
825
+ let ( $( $arg) ,* ) = Self :: ARGS ;
826
+ loop {
827
+ break $body;
828
+ }
829
+ } ;
830
+ }
831
+ } ;
832
+ }
833
+
834
+ macro_rules! call_const_fn {
835
+ (
836
+ $name: ident $( :: $names: ident) * $( :: < $( $ty: ty) ,* >) ? ( $( $arg: expr) ,* )
837
+ ) => {
838
+ {
839
+ enum Call { }
840
+
841
+ impl $name $( :: $names) * $( < $( $ty) ,* >) ? for Call {
842
+ const ARGS : Self :: Args = ( $( $arg, ) * ) ;
843
+ }
844
+
845
+ <Call as $name $( :: $names) * $( :: < $( $ty) ,* >) ?>:: __RETURN
846
+ }
847
+ } ;
848
+ }
849
+
850
+ // Used in the implementation of `const_fn!`.
851
+ pub ( crate ) trait HasArgs < A > {
852
+ type Args ;
853
+ }
854
+
855
+ impl < A , T > HasArgs < A > for T {
856
+ type Args = A ;
857
+ }
858
+
859
+ mod tests {
860
+ #[ test]
861
+ fn test_const_fn ( ) {
862
+ trait Foo {
863
+ const N : usize ;
864
+ }
865
+
866
+ impl Foo for ( ) {
867
+ const N : usize = 5 ;
868
+ }
869
+
870
+ const_fn ! ( foobar<T >( _t: T , n: usize ) -> usize
871
+ where
872
+ T : Foo ,
873
+ T : Copy ,
874
+ {
875
+ T :: N * n
876
+ } ) ;
877
+
878
+ const BLAH : usize = call_const_fn ! ( foobar:: <( ) >( ( ) , 4 ) ) ;
879
+
880
+ const _: ( ) = {
881
+ static_assert ! ( => BLAH == 20 ) ;
882
+ } ;
883
+ }
884
+ }
0 commit comments