Storage(Type),
/// Cache the query to disk if the `Expr` returns true.
- Cache(Option<(IdentOrWild, IdentOrWild)>, Block),
+ Cache(Option<IdentOrWild>, Block),
/// Custom code to load the query from disk.
LoadCached(Ident, Ident, Block),
/// Always evaluate the query, ignoring its dependencies
EvalAlways(Ident),
+
+ /// Use a separate query provider for local and extern crates
+ SeparateProvideExtern(Ident),
+
+ /// Always remap the ParamEnv's constness before hashing and passing to the query provider
+ RemapEnvConstness(Ident),
}
impl Parse for QueryModifier {
let args;
parenthesized!(args in input);
let tcx = args.parse()?;
- args.parse::<Token![,]>()?;
- let value = args.parse()?;
- Some((tcx, value))
+ Some(tcx)
} else {
None
};
Ok(QueryModifier::Anon(modifier))
} else if modifier == "eval_always" {
Ok(QueryModifier::EvalAlways(modifier))
+ } else if modifier == "separate_provide_extern" {
+ Ok(QueryModifier::SeparateProvideExtern(modifier))
+ } else if modifier == "remap_env_constness" {
+ Ok(QueryModifier::RemapEnvConstness(modifier))
} else {
Err(Error::new(modifier.span(), "unknown query modifier"))
}
storage: Option<Type>,
/// Cache the query to disk if the `Block` returns true.
- cache: Option<(Option<(IdentOrWild, IdentOrWild)>, Block)>,
+ cache: Option<(Option<IdentOrWild>, Block)>,
/// Custom code to load the query from disk.
load_cached: Option<(Ident, Ident, Block)>,
// Always evaluate the query, ignoring its dependencies
eval_always: Option<Ident>,
+
+ /// Use a separate query provider for local and extern crates
+ separate_provide_extern: Option<Ident>,
+
+ /// Always remap the ParamEnv's constness before hashing.
+ remap_env_constness: Option<Ident>,
}
/// Process query modifiers into a struct, erroring on duplicates
let mut no_hash = None;
let mut anon = None;
let mut eval_always = None;
+ let mut separate_provide_extern = None;
+ let mut remap_env_constness = None;
for modifier in query.modifiers.0.drain(..) {
match modifier {
QueryModifier::LoadCached(tcx, id, block) => {
}
eval_always = Some(ident);
}
+ QueryModifier::SeparateProvideExtern(ident) => {
+ if separate_provide_extern.is_some() {
+ panic!(
+ "duplicate modifier `separate_provide_extern` for query `{}`",
+ query.name
+ );
+ }
+ separate_provide_extern = Some(ident);
+ }
+ QueryModifier::RemapEnvConstness(ident) => {
+ if remap_env_constness.is_some() {
+ panic!("duplicate modifier `remap_env_constness` for query `{}`", query.name);
+ }
+ remap_env_constness = Some(ident)
+ }
}
}
let desc = desc.unwrap_or_else(|| {
no_hash,
anon,
eval_always,
+ separate_provide_extern,
+ remap_env_constness,
}
}
let try_load_from_disk = if let Some((tcx, id, block)) = modifiers.load_cached.as_ref() {
// Use custom code to load the query from disk
quote! {
- #[inline]
- fn try_load_from_disk(
- #tcx: QueryCtxt<'tcx>,
- #id: SerializedDepNodeIndex
- ) -> Option<Self::Value> {
- #block
- }
+ const TRY_LOAD_FROM_DISK: Option<fn(QueryCtxt<$tcx>, SerializedDepNodeIndex) -> Option<Self::Value>>
+ = Some(|#tcx, #id| { #block });
}
} else {
// Use the default code to load the query from disk
quote! {
- #[inline]
- fn try_load_from_disk(
- tcx: QueryCtxt<'tcx>,
- id: SerializedDepNodeIndex
- ) -> Option<Self::Value> {
- tcx.on_disk_cache().as_ref()?.try_load_query_result(*tcx, id)
- }
+ const TRY_LOAD_FROM_DISK: Option<fn(QueryCtxt<$tcx>, SerializedDepNodeIndex) -> Option<Self::Value>>
+ = Some(|tcx, id| tcx.on_disk_cache().as_ref()?.try_load_query_result(*tcx, id));
}
};
let tcx = args
.as_ref()
.map(|t| {
- let t = &(t.0).0;
- quote! { #t }
- })
- .unwrap_or_else(|| quote! { _ });
- let value = args
- .as_ref()
- .map(|t| {
- let t = &(t.1).0;
+ let t = &t.0;
quote! { #t }
})
.unwrap_or_else(|| quote! { _ });
// expr is a `Block`, meaning that `{ #expr }` gets expanded
// to `{ { stmts... } }`, which triggers the `unused_braces` lint.
quote! {
- #[inline]
#[allow(unused_variables, unused_braces)]
- fn cache_on_disk(
- #tcx: QueryCtxt<'tcx>,
- #key: &Self::Key,
- #value: Option<&Self::Value>
- ) -> bool {
+ #[inline]
+ fn cache_on_disk(#tcx: TyCtxt<'tcx>, #key: &Self::Key) -> bool {
#expr
}
if modifiers.load_cached.is_some() {
panic!("load_cached modifier on query `{}` without a cache modifier", name);
}
- quote! {}
+ quote! {
+ #[inline]
+ fn cache_on_disk(_: TyCtxt<'tcx>, _: &Self::Key) -> bool {
+ false
+ }
+
+ const TRY_LOAD_FROM_DISK: Option<fn(QueryCtxt<$tcx>, SerializedDepNodeIndex) -> Option<Self::Value>> = None;
+ }
};
let (tcx, desc) = modifiers.desc;
let desc = quote! {
#[allow(unused_variables)]
- fn describe(tcx: QueryCtxt<'tcx>, key: Self::Key) -> String {
+ fn describe(tcx: QueryCtxt<$tcx>, key: Self::Key) -> String {
let (#tcx, #key) = (*tcx, key);
::rustc_middle::ty::print::with_no_trimmed_paths(|| format!(#desc).into())
}
};
impls.extend(quote! {
- impl<'tcx> QueryDescription<QueryCtxt<'tcx>> for queries::#name<'tcx> {
+ (#name<$tcx:tt>) => {
#desc
#cache
- }
+ };
});
}
if let Some(eval_always) = &modifiers.eval_always {
attributes.push(quote! { (#eval_always) });
};
+ // Pass on the separate_provide_extern modifier
+ if let Some(separate_provide_extern) = &modifiers.separate_provide_extern {
+ attributes.push(quote! { (#separate_provide_extern) });
+ }
+ // Pass on the remap_env_constness modifier
+ if let Some(remap_env_constness) = &modifiers.remap_env_constness {
+ attributes.push(quote! { (#remap_env_constness) });
+ }
// This uses the span of the query definition for the commas,
// which can be important if we later encounter any ambiguity
}
#[macro_export]
macro_rules! rustc_query_description {
- () => { #query_description_stream }
+ #query_description_stream
}
})
}