Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Define queries using a proc macro #56462

Merged
merged 4 commits into from
Mar 19, 2019
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 18 additions & 7 deletions src/librustc/dep_graph/dep_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ impl DefId {
}
}

define_dep_nodes!( <'tcx>
rustc_dep_node_append!([define_dep_nodes!][ <'tcx>
// We use this for most things when incr. comp. is turned off.
[] Null,

Expand Down Expand Up @@ -492,9 +492,6 @@ define_dep_nodes!( <'tcx>
// table in the tcx (or elsewhere) maps to one of these
// nodes.
[] AssociatedItems(DefId),
[] TypeOfItem(DefId),
[] GenericsOfItem(DefId),
[] PredicatesOfItem(DefId),
[] ExplicitPredicatesOfItem(DefId),
[] PredicatesDefinedOnItem(DefId),
[] InferredOutlivesOf(DefId),
Expand Down Expand Up @@ -570,7 +567,6 @@ define_dep_nodes!( <'tcx>
[] FnArgNames(DefId),
[] RenderedConst(DefId),
[] DylibDepFormats(CrateNum),
[] IsPanicRuntime(CrateNum),
[] IsCompilerBuiltins(CrateNum),
[] HasGlobalAllocator(CrateNum),
[] HasPanicHandler(CrateNum),
Expand All @@ -588,7 +584,6 @@ define_dep_nodes!( <'tcx>
[] CheckTraitItemWellFormed(DefId),
[] CheckImplItemWellFormed(DefId),
[] ReachableNonGenerics(CrateNum),
[] NativeLibraries(CrateNum),
[] EntryFn(CrateNum),
[] PluginRegistrarFn(CrateNum),
[] ProcMacroDeclsStatic(CrateNum),
Expand Down Expand Up @@ -679,7 +674,23 @@ define_dep_nodes!( <'tcx>

[] UpstreamMonomorphizations(CrateNum),
[] UpstreamMonomorphizationsFor(DefId),
);
]);

pub trait RecoverKey<'tcx>: Sized {
fn recover(tcx: TyCtxt<'_, 'tcx, 'tcx>, dep_node: &DepNode) -> Option<Self>;
}

impl RecoverKey<'tcx> for CrateNum {
fn recover(tcx: TyCtxt<'_, 'tcx, 'tcx>, dep_node: &DepNode) -> Option<Self> {
dep_node.extract_def_id(tcx).map(|id| id.krate)
}
}

impl RecoverKey<'tcx> for DefId {
fn recover(tcx: TyCtxt<'_, 'tcx, 'tcx>, dep_node: &DepNode) -> Option<Self> {
dep_node.extract_def_id(tcx)
}
}

trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug {
const CAN_RECONSTRUCT_QUERY_KEY: bool;
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/dep_graph/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ mod serialized;
pub mod cgu_reuse_tracker;

pub use self::dep_tracking_map::{DepTrackingMap, DepTrackingMapConfig};
pub use self::dep_node::{DepNode, DepKind, DepConstructor, WorkProductId, label_strs};
pub use self::dep_node::{DepNode, DepKind, DepConstructor, WorkProductId, RecoverKey, label_strs};
pub use self::graph::{DepGraph, WorkProduct, DepNodeIndex, DepNodeColor, TaskDeps, hash_result};
pub use self::graph::WorkProductFileKind;
pub use self::prev::PreviousDepGraph;
Expand Down
6 changes: 6 additions & 0 deletions src/librustc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@
#![feature(test)]
#![feature(in_band_lifetimes)]
#![feature(crate_visibility_modifier)]
#![feature(proc_macro_hygiene)]
#![feature(log_syntax)]

#![recursion_limit="512"]

Expand All @@ -69,6 +71,7 @@ extern crate getopts;
#[macro_use] extern crate scoped_tls;
#[cfg(windows)]
extern crate libc;
#[macro_use] extern crate rustc_macros;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW wherever possible it'd be great to stop using #[macro_use] for new macro-based code

#[macro_use] extern crate rustc_data_structures;

#[macro_use] extern crate log;
Expand Down Expand Up @@ -96,6 +99,9 @@ mod macros;
// registered before they are used.
pub mod diagnostics;

#[macro_use]
pub mod query;

pub mod cfg;
pub mod dep_graph;
pub mod hir;
Expand Down
66 changes: 66 additions & 0 deletions src/librustc/query/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
use crate::ty::query::QueryDescription;
use crate::ty::query::queries;
use crate::ty::TyCtxt;
use crate::ty;
use crate::hir::def_id::CrateNum;
use crate::dep_graph::SerializedDepNodeIndex;
use std::borrow::Cow;

// Each of these queries corresponds to a function pointer field in the
// `Providers` struct for requesting a value of that type, and a method
// on `tcx: TyCtxt` (and `tcx.at(span)`) for doing that request in a way
// which memoizes and does dep-graph tracking, wrapping around the actual
// `Providers` that the driver creates (using several `rustc_*` crates).
//
// The result type of each query must implement `Clone`, and additionally
// `ty::query::values::Value`, which produces an appropriate placeholder
// (error) value if the query resulted in a query cycle.
// Queries marked with `fatal_cycle` do not need the latter implementation,
// as they will raise an fatal error on query cycles instead.
rustc_queries! {
Other {
/// Records the type of every item.
query type_of(key: DefId) -> Ty<'tcx> {
cache { key.is_local() }
}

/// Maps from the `DefId` of an item (trait/struct/enum/fn) to its
/// associated generics.
query generics_of(key: DefId) -> &'tcx ty::Generics {
cache { key.is_local() }
load_cached(tcx, id) {
let generics: Option<ty::Generics> = tcx.queries.on_disk_cache
.try_load_query_result(tcx, id);
generics.map(|x| tcx.alloc_generics(x))
}
}

/// Maps from the `DefId` of an item (trait/struct/enum/fn) to the
/// predicates (where-clauses) that must be proven true in order
/// to reference it. This is almost always the "predicates query"
/// that you want.
///
/// `predicates_of` builds on `predicates_defined_on` -- in fact,
/// it is almost always the same as that query, except for the
/// case of traits. For traits, `predicates_of` contains
/// an additional `Self: Trait<...>` predicate that users don't
/// actually write. This reflects the fact that to invoke the
/// trait (e.g., via `Default::default`) you must supply types
/// that actually implement the trait. (However, this extra
/// predicate gets in the way of some checks, which are intended
/// to operate over only the actual where-clauses written by the
/// user.)
query predicates_of(_: DefId) -> Lrc<ty::GenericPredicates<'tcx>> {}

query native_libraries(_: CrateNum) -> Lrc<Vec<NativeLibrary>> {
desc { "looking up the native libraries of a linked crate" }
}
}

Codegen {
query is_panic_runtime(_: CrateNum) -> bool {
fatal_cycle
desc { "checking if the crate is_panic_runtime" }
}
}
}
32 changes: 2 additions & 30 deletions src/librustc/ty/query/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub trait QueryConfig<'tcx> {
type Value: Clone;
}

pub(super) trait QueryAccessors<'tcx>: QueryConfig<'tcx> {
pub(crate) trait QueryAccessors<'tcx>: QueryConfig<'tcx> {
fn query(key: Self::Key) -> Query<'tcx>;

// Don't use this method to access query results, instead use the methods on TyCtxt
Expand All @@ -53,7 +53,7 @@ pub(super) trait QueryAccessors<'tcx>: QueryConfig<'tcx> {
fn handle_cycle_error(tcx: TyCtxt<'_, 'tcx, '_>, error: CycleError<'tcx>) -> Self::Value;
}

pub(super) trait QueryDescription<'tcx>: QueryAccessors<'tcx> {
pub(crate) trait QueryDescription<'tcx>: QueryAccessors<'tcx> {
fn describe(tcx: TyCtxt<'_, '_, '_>, key: Self::Key) -> Cow<'static, str>;

#[inline]
Expand Down Expand Up @@ -587,12 +587,6 @@ impl<'tcx> QueryDescription<'tcx> for queries::dylib_dependency_formats<'tcx> {
}
}

impl<'tcx> QueryDescription<'tcx> for queries::is_panic_runtime<'tcx> {
fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
"checking if the crate is_panic_runtime".into()
}
}

impl<'tcx> QueryDescription<'tcx> for queries::is_compiler_builtins<'tcx> {
fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
"checking if the crate is_compiler_builtins".into()
Expand Down Expand Up @@ -671,12 +665,6 @@ impl<'tcx> QueryDescription<'tcx> for queries::reachable_non_generics<'tcx> {
}
}

impl<'tcx> QueryDescription<'tcx> for queries::native_libraries<'tcx> {
fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
"looking up the native libraries of a linked crate".into()
}
}

impl<'tcx> QueryDescription<'tcx> for queries::foreign_modules<'tcx> {
fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
"looking up the foreign modules of a linked crate".into()
Expand Down Expand Up @@ -949,21 +937,6 @@ impl<'tcx> QueryDescription<'tcx> for queries::instance_def_size_estimate<'tcx>
}
}

impl<'tcx> QueryDescription<'tcx> for queries::generics_of<'tcx> {
#[inline]
fn cache_on_disk(_: TyCtxt<'_, 'tcx, 'tcx>, def_id: Self::Key) -> bool {
def_id.is_local()
}

fn try_load_from_disk<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
id: SerializedDepNodeIndex)
-> Option<Self::Value> {
let generics: Option<ty::Generics> = tcx.queries.on_disk_cache
.try_load_query_result(tcx, id);
generics.map(|x| tcx.alloc_generics(x))
}
}

impl<'tcx> QueryDescription<'tcx> for queries::program_clauses_for<'tcx> {
fn describe(_tcx: TyCtxt<'_, '_, '_>, _: DefId) -> Cow<'static, str> {
"generating chalk-style clauses".into()
Expand Down Expand Up @@ -1027,7 +1000,6 @@ impl_disk_cacheable_query!(borrowck, |_, def_id| def_id.is_local());
impl_disk_cacheable_query!(mir_const_qualif, |_, def_id| def_id.is_local());
impl_disk_cacheable_query!(check_match, |_, def_id| def_id.is_local());
impl_disk_cacheable_query!(def_symbol_name, |_, _| true);
impl_disk_cacheable_query!(type_of, |_, def_id| def_id.is_local());
impl_disk_cacheable_query!(predicates_of, |_, def_id| def_id.is_local());
impl_disk_cacheable_query!(used_trait_imports, |_, def_id| def_id.is_local());
impl_disk_cacheable_query!(codegen_fn_attrs, |_, _| true);
Expand Down
37 changes: 6 additions & 31 deletions src/librustc/ty/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,14 @@ mod values;
use self::values::Value;

mod config;
pub(crate) use self::config::QueryDescription;
pub use self::config::QueryConfig;
use self::config::{QueryAccessors, QueryDescription};
use self::config::QueryAccessors;

mod on_disk_cache;
pub use self::on_disk_cache::OnDiskCache;

// Each of these quries corresponds to a function pointer field in the
// Each of these queries corresponds to a function pointer field in the
// `Providers` struct for requesting a value of that type, and a method
// on `tcx: TyCtxt` (and `tcx.at(span)`) for doing that request in a way
// which memoizes and does dep-graph tracking, wrapping around the actual
Expand All @@ -97,35 +98,12 @@ pub use self::on_disk_cache::OnDiskCache;
// (error) value if the query resulted in a query cycle.
// Queries marked with `fatal_cycle` do not need the latter implementation,
// as they will raise an fatal error on query cycles instead.
define_queries! { <'tcx>

rustc_query_append! { [define_queries!][ <'tcx>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is mind-bending, but cool!

Other {
/// Run analysis passes on the crate
[] fn analysis: Analysis(CrateNum) -> Result<(), ErrorReported>,

/// Records the type of every item.
[] fn type_of: TypeOfItem(DefId) -> Ty<'tcx>,

/// Maps from the `DefId` of an item (trait/struct/enum/fn) to its
/// associated generics.
[] fn generics_of: GenericsOfItem(DefId) -> &'tcx ty::Generics,

/// Maps from the `DefId` of an item (trait/struct/enum/fn) to the
/// predicates (where-clauses) that must be proven true in order
/// to reference it. This is almost always the "predicates query"
/// that you want.
///
/// `predicates_of` builds on `predicates_defined_on` -- in fact,
/// it is almost always the same as that query, except for the
/// case of traits. For traits, `predicates_of` contains
/// an additional `Self: Trait<...>` predicate that users don't
/// actually write. This reflects the fact that to invoke the
/// trait (e.g., via `Default::default`) you must supply types
/// that actually implement the trait. (However, this extra
/// predicate gets in the way of some checks, which are intended
/// to operate over only the actual where-clauses written by the
/// user.)
[] fn predicates_of: PredicatesOfItem(DefId) -> Lrc<ty::GenericPredicates<'tcx>>,

/// Maps from the `DefId` of an item (trait/struct/enum/fn) to the
/// predicates (where-clauses) directly defined on it. This is
/// equal to the `explicit_predicates_of` predicates plus the
Expand Down Expand Up @@ -446,7 +424,6 @@ define_queries! { <'tcx>
},

Codegen {
[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 has_panic_handler: HasPanicHandler(CrateNum) -> bool,
Expand Down Expand Up @@ -504,8 +481,6 @@ define_queries! { <'tcx>
},

Other {
[] fn native_libraries: NativeLibraries(CrateNum) -> Lrc<Vec<NativeLibrary>>,

[] fn foreign_modules: ForeignModules(CrateNum) -> Lrc<Vec<ForeignModule>>,

/// Identifies the entry-point (e.g., the `main` function) for a given
Expand Down Expand Up @@ -752,7 +727,7 @@ define_queries! { <'tcx>
[] fn wasm_import_module_map: WasmImportModuleMap(CrateNum)
-> Lrc<FxHashMap<DefId, String>>,
},
}
]}

//////////////////////////////////////////////////////////////////////
// These functions are little shims used to find the dep-node for a
Expand Down
Loading