]> git.lizzy.rs Git - rust.git/commitdiff
adjust the macro to allow for `multi` modifier
authorNiko Matsakis <niko@alum.mit.edu>
Fri, 28 Apr 2017 16:09:15 +0000 (12:09 -0400)
committerNiko Matsakis <niko@alum.mit.edu>
Tue, 2 May 2017 18:01:36 +0000 (14:01 -0400)
src/librustc/lib.rs
src/librustc/ty/maps.rs

index a3e5a14dbac7f96ddecb2f46c4f72d4a2f21eeec..d3954326e7b721c28586f0c001bbc82d3e703a6c 100644 (file)
@@ -43,6 +43,9 @@
 #![feature(unboxed_closures)]
 #![feature(discriminant_value)]
 #![feature(sort_unstable)]
+#![feature(trace_macros)]
+
+#![recursion_limit="128"]
 
 extern crate arena;
 extern crate core;
index f2bfd23b189402960be824be529a23e58e6fdde0..dff58d78f8235b1e1216c01a616c33a8bf24e7ca 100644 (file)
@@ -387,8 +387,7 @@ macro_rules! define_maps {
        [$($modifiers:tt)*] $name:ident: $node:ident($K:ty) -> $V:ty,)*) => {
         define_map_struct! {
             tcx: $tcx,
-            input: ($(([$($attr)*] [$($modifiers)*] $name))*),
-            output: ()
+            input: ($(([$($modifiers)*] [$($attr)*] [$name]))*)
         }
 
         impl<$tcx> Maps<$tcx> {
@@ -536,8 +535,10 @@ pub fn $name(self, key: $K) -> $V {
             })*
         }
 
-        pub struct Providers<$tcx> {
-            $(pub $name: for<'a> fn(TyCtxt<'a, $tcx, $tcx>, $K) -> $V),*
+        define_provider_struct! {
+            tcx: $tcx,
+            input: ($(([$($modifiers)*] [$name] [$K] [$V]))*),
+            output: ()
         }
 
         impl<$tcx> Copy for Providers<$tcx> {}
@@ -558,6 +559,17 @@ fn default() -> Self {
 }
 
 macro_rules! define_map_struct {
+    // Initial state
+    (tcx: $tcx:tt,
+     input: $input:tt) => {
+        define_map_struct! {
+            tcx: $tcx,
+            input: $input,
+            output: ()
+        }
+    };
+
+    // Final output
     (tcx: $tcx:tt,
      input: (),
      output: ($($output:tt)*)) => {
@@ -568,26 +580,121 @@ pub struct Maps<$tcx> {
         }
     };
 
-    // Detect things with the `pub` modifier
+    // Field recognized and ready to shift into the output
     (tcx: $tcx:tt,
-     input: (([$($attr:meta)*] [pub] $name:ident) $($input:tt)*),
+     ready: ([$($pub:tt)*] [$($attr:tt)*] [$name:ident]),
+     input: $input:tt,
      output: ($($output:tt)*)) => {
         define_map_struct! {
             tcx: $tcx,
-            input: ($($input)*),
+            input: $input,
             output: ($($output)*
-                     $(#[$attr])* pub $name: RefCell<DepTrackingMap<queries::$name<$tcx>>>,)
+                     $(#[$attr])* $($pub)* $name: RefCell<DepTrackingMap<queries::$name<$tcx>>>,)
         }
     };
 
+    // Detect things with the `pub` modifier
     (tcx: $tcx:tt,
-     input: (([$($attr:meta)*] [$($modifiers:tt)*] $name:ident) $($input:tt)*),
-     output: ($($output:tt)*)) => {
+     input: (([pub $($other_modifiers:tt)*] $attrs:tt $name:tt) $($input:tt)*),
+     output: $output:tt) => {
         define_map_struct! {
             tcx: $tcx,
+            ready: ([pub] $attrs $name),
             input: ($($input)*),
+            output: $output
+        }
+    };
+
+    // No modifiers left? This is a private item.
+    (tcx: $tcx:tt,
+     input: (([] $attrs:tt $name:tt) $($input:tt)*),
+     output: $output:tt) => {
+        define_map_struct! {
+            tcx: $tcx,
+            ready: ([pub] $attrs $name),
+            input: ($($input)*),
+            output: $output
+        }
+    };
+
+    // Skip other modifiers
+    (tcx: $tcx:tt,
+     input: (([$other_modifier:tt $($modifiers:tt)*] $($fields:tt)*) $($input:tt)*),
+     output: $output:tt) => {
+        define_map_struct! {
+            tcx: $tcx,
+            input: (([$($modifiers)*] $($fields)*) $($input)*),
+            output: $output
+        }
+    };
+}
+
+macro_rules! define_provider_struct {
+    // Initial state:
+    (tcx: $tcx:tt, input: $input:tt) => {
+        define_provider_struct! {
+            tcx: $tcx,
+            input: $input,
+            output: ()
+        }
+    };
+
+    // Final state:
+    (tcx: $tcx:tt,
+     input: (),
+     output: ($($output:tt)*)) => {
+        pub struct Providers<$tcx> {
+            $($output)*
+        }
+    };
+
+    // Something ready to shift:
+    (tcx: $tcx:tt,
+     ready: ([$name:ident] [$K:ty] [$R:ty]),
+     input: $input:tt,
+     output: ($($output:tt)*)) => {
+        define_provider_struct! {
+            tcx: $tcx,
+            input: $input,
             output: ($($output)*
-                     $(#[$attr])* $name: RefCell<DepTrackingMap<queries::$name<$tcx>>>,)
+                     pub $name: for<'a> fn(TyCtxt<'a, $tcx, $tcx>, $K) -> $R,)
+        }
+    };
+
+    // The `multi` modifier indicates a **multiquery**, in which case
+    // the function returns a `FxHashMap<K,V>` instead of just a value
+    // `V`.
+    (tcx: $tcx:tt,
+     input: (([multi $($other_modifiers:tt)*] $name:tt [$K:ty] [$V:ty]) $($input:tt)*),
+     output: $output:tt) => {
+        define_provider_struct! {
+            tcx: $tcx,
+            ready: ($name [$K] [FxHashMap<$K,$V>]),
+            input: ($($input)*),
+            output: $output
+        }
+    };
+
+    // Regular queries produce a `V` only.
+    (tcx: $tcx:tt,
+     input: (([] $name:tt $K:tt $V:tt) $($input:tt)*),
+     output: $output:tt) => {
+        define_provider_struct! {
+            tcx: $tcx,
+            ready: ($name $K $V),
+            input: ($($input)*),
+            output: $output
+        }
+    };
+
+    // Skip modifiers other than `multi`.
+    (tcx: $tcx:tt,
+     input: (([$other_modifier:tt $($modifiers:tt)*] $($fields:tt)*) $($input:tt)*),
+     output: $output:tt) => {
+        define_provider_struct! {
+            tcx: $tcx,
+            input: (([$($modifiers)*] $($fields)*) $($input)*),
+            output: $output
         }
     };
 }