From: Niko Matsakis Date: Fri, 28 Apr 2017 16:09:15 +0000 (-0400) Subject: adjust the macro to allow for `multi` modifier X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=1d675ce0a3e323b390bdbd7c8b5bdf80909ca6a1;p=rust.git adjust the macro to allow for `multi` modifier --- diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index a3e5a14dbac..d3954326e7b 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -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; diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index f2bfd23b189..dff58d78f82 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -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>>,) + $(#[$attr])* $($pub)* $name: RefCell>>,) } }; + // 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>>,) + 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` 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 } }; }