// a way that memoizes and does dep-graph tracking,
// wrapping around the actual chain of providers that
// the driver creates (using several `rustc_*` crates).
+//
+// The result of query must implement Clone. They must also implement ty::maps::values::Value
+// which produces an appropiate error value if the query resulted in a query cycle.
+// Queries marked with `fatal_cycle` do not need that implementation
+// as they will raise an fatal error on query cycles instead.
define_maps! { <'tcx>
/// Records the type of every item.
[] fn type_of: TypeOfItem(DefId) -> Ty<'tcx>,
[] fn dylib_dependency_formats: DylibDepFormats(CrateNum)
-> Rc<Vec<(CrateNum, LinkagePreference)>>,
- [] fn is_panic_runtime: IsPanicRuntime(CrateNum) -> bool,
- [] fn is_compiler_builtins: IsCompilerBuiltins(CrateNum) -> bool,
- [] fn has_global_allocator: HasGlobalAllocator(CrateNum) -> bool,
- [] fn is_sanitizer_runtime: IsSanitizerRuntime(CrateNum) -> bool,
- [] fn is_profiler_runtime: IsProfilerRuntime(CrateNum) -> bool,
- [] fn panic_strategy: GetPanicStrategy(CrateNum) -> PanicStrategy,
- [] fn is_no_builtins: IsNoBuiltins(CrateNum) -> bool,
+ [fatal_cycle] fn is_panic_runtime: IsPanicRuntime(CrateNum) -> bool,
+ [fatal_cycle] fn is_compiler_builtins: IsCompilerBuiltins(CrateNum) -> bool,
+ [fatal_cycle] fn has_global_allocator: HasGlobalAllocator(CrateNum) -> bool,
+ [fatal_cycle] fn is_sanitizer_runtime: IsSanitizerRuntime(CrateNum) -> bool,
+ [fatal_cycle] fn is_profiler_runtime: IsProfilerRuntime(CrateNum) -> bool,
+ [fatal_cycle] fn panic_strategy: GetPanicStrategy(CrateNum) -> PanicStrategy,
+ [fatal_cycle] fn is_no_builtins: IsNoBuiltins(CrateNum) -> bool,
[] fn extern_crate: ExternCrate(DefId) -> Rc<Option<ExternCrate>>,
}
}
+macro_rules! handle_cycle_error {
+ ([][$this: expr]) => {{
+ Value::from_cycle_error($this.global_tcx())
+ }};
+ ([fatal_cycle$(, $modifiers:ident)*][$this:expr]) => {{
+ $this.tcx.sess.abort_if_errors();
+ unreachable!();
+ }};
+ ([$other:ident$(, $modifiers:ident)*][$($args:tt)*]) => {
+ handle_cycle_error!([$($modifiers),*][$($args)*])
+ };
+}
+
macro_rules! define_maps {
(<$tcx:tt>
$($(#[$attr:meta])*
pub fn $name(self, key: $K) -> $V {
queries::$name::try_get(self.tcx, self.span, key).unwrap_or_else(|mut e| {
e.emit();
- Value::from_cycle_error(self.global_tcx())
+ handle_cycle_error!([$($modifiers)*][self])
})
})*
}
macro_rules! define_map_struct {
(tcx: $tcx:tt,
- input: ($(([$(modifiers:tt)*] [$($attr:tt)*] [$name:ident]))*)) => {
+ input: ($(([$($modifiers:tt)*] [$($attr:tt)*] [$name:ident]))*)) => {
pub struct Maps<$tcx> {
providers: IndexVec<CrateNum, Providers<$tcx>>,
query_stack: RefCell<Vec<(Span, Query<$tcx>)>>,