blob: 804ea3ed0f87f42bb9cf4cb57eb4f09b6b7417cb [file]
// Part of the Crubit project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
extern crate rustc_hir;
extern crate rustc_middle;
extern crate rustc_span;
use crate::adt_core_bindings::AdtCoreBindings;
use crate::code_snippet::{ApiSnippets, CcSnippet, CrubitAbiTypeWithCcPrereqs};
use crate::fully_qualified_name::FullyQualifiedName;
use crate::include_guard::IncludeGuard;
use crate::sugared_ty::SugaredTy;
use crate::type_location::TypeLocation;
use arc_anyhow::Result;
use code_gen_utils::CcInclude;
use dyn_format::Format;
use error_report::{ErrorReporting, ReportFatalError};
use proc_macro2::{Ident, TokenStream};
use rustc_middle::ty::{Ty, TyCtxt};
use rustc_span::def_id::{CrateNum, DefId};
use rustc_span::Symbol;
use std::collections::HashMap;
use std::rc::Rc;
memoized::query_group! {
pub trait BindingsGenerator<'tcx> {
#[input]
/// Compilation context for the crate that the bindings should be generated
/// for.
fn tcx(&self) -> TyCtxt<'tcx>;
#[input]
/// Name of the `extern` crate that bindings should be generated for.
/// If `None`, bindings will be generated for the crate currently being compiled.
fn source_crate_name(&self) -> Option<Rc<str>>;
#[input]
/// Format specifier for `#include` Crubit C++ support library headers,
/// using `{header}` as the place holder. Example:
/// `<crubit/support/{header}>` results in `#include
/// <crubit/support/hdr.h>`.
fn crubit_support_path_format(&self) -> Format<1>;
#[input]
/// Format specifier for path cross-references in "Generated from" comments.
///
/// Inputs are `{path}` and `{line}` respectively.
fn crubit_debug_path_format(&self) -> Option<Format<2>>;
#[input]
/// The default features enabled on all crates, if not present in `crate_name_to_features`.
fn default_features(&self) -> flagset::FlagSet<crubit_feature::CrubitFeature>;
#[input]
/// A map from a crate name to the include paths of the corresponding C++
/// headers This is used when formatting a type exported from another
/// crate.
// TODO(b/271857814): A crate name might not be globally unique - the key needs to also cover
// a "hash" of the crate version and compilation flags.
fn crate_name_to_include_paths(&self) -> Rc<HashMap<Rc<str>, Vec<CcInclude>>>;
#[input]
/// A map from a crate name to the features enabled on that crate. The special name `self`
/// refers to the current crate.
// TODO(b/271857814): A crate name might not be globally unique - the key needs to also cover
// a "hash" of the crate version and compilation flags.
fn crate_name_to_features(&self) -> Rc<HashMap<Rc<str>, flagset::FlagSet<crubit_feature::CrubitFeature>>>;
#[input]
/// A map from a crate name to the top-level namespace of the C++ bindings. The special name
/// `self` refers to the current crate.
fn crate_name_to_namespace(&self) -> Rc<HashMap<Rc<str>, Rc<str>>>;
#[input]
fn crate_renames(&self) -> Rc<HashMap<Rc<str>, Rc<str>>>;
#[input]
/// Error collector for generating reports of errors encountered during the generation of bindings.
fn errors(&self) -> Rc<dyn ErrorReporting>;
#[input]
/// A collection of errors that should cause bindings generation to fail.
///
/// These errors should be issued only in response to misusage of Crubit itself, such as
/// incorrect use of Crubit-specific annotations.
fn fatal_errors(&self) -> Rc<dyn ReportFatalError>;
#[input]
fn no_thunk_name_mangling(&self) -> bool;
#[input]
fn h_out_include_guard(&self) -> IncludeGuard;
/// The `CrateNum` of the crate that the bindings should be generated for.
/// This will be `LOCAL_CRATE` if no `source_crate_name` was provided.
fn source_crate_num(&self) -> CrateNum;
/// Returns the include for the given Crubit runtime support header.
///
/// Implementation: cc_bindings_from_rs/generate_bindings/lib.rs?q=function:support_header
fn support_header(&self, suffix: &'tcx str) -> CcInclude;
/// Returns the representation attributes for the given definition.
///
/// TODO: Replace calls to this function with direct call to `repr.transparent()`
/// and `repr.c()` etc.
///
/// Implementation: cc_bindings_from_rs/generate_bindings/query_compiler.rs?q=function:repr_attrs
fn repr_attrs(&self, did: DefId) -> Rc<[rustc_hir::attrs::ReprAttr]>;
/// Computes a mapping from a `DefId` to a `FullyQualifiedName` for all
/// not-directly-public symbols that are reexported by a `use` statement.
///
/// Implementation: cc_bindings_from_rs/generate_bindings/lib.rs?q=function:reexported_symbol_canonical_name_mapping
fn reexported_symbol_canonical_name_mapping(&self) -> HashMap<DefId, FullyQualifiedName>;
/// Formats a C++ identifier, if possible.
///
/// Implementation: cc_bindings_from_rs/generate_bindings/format_type.rs?q=function:format_cc_ident
fn format_cc_ident(&self, ident: Symbol) -> Result<Ident>;
/// Formats the top-level namespace for the given crate, e.g. as `self::foo`, or
/// `somecrate::foo`.
///
/// Implementation: cc_bindings_from_rs/generate_bindings/format_type.rs?q=function:format_top_level_ns_for_crate
fn format_top_level_ns_for_crate(&self, krate: CrateNum) -> Rc<[Symbol]>;
/// Formats `ty` into a `CcSnippet` that represents how the type should be
/// spelled in a C++ declaration of a function parameter or field.
///
/// Implementation: cc_bindings_from_rs/generate_bindings/format_type.rs?q=function:format_ty_for_cc
fn format_ty_for_cc(
&self,
ty: SugaredTy<'tcx>,
location: TypeLocation,
) -> Result<CcSnippet>;
/// Formats `ty` into a `CcSnippet` that represents how the type should be
/// spelled in a C++ declaration of a function parameter or field.
///
/// Implementation: cc_bindings_from_rs/generate_bindings/format_type.rs?q=function:format_ty_for_rs
fn format_ty_for_rs(
&self,
ty: Ty<'tcx>
) -> Result<TokenStream>;
/// Generates a default constructor for an ADT if possible (i.e. if the `Default`
/// trait is implemented for the ADT). Returns an error otherwise (e.g. if
/// there is no `Default` impl, then the default constructor will be
/// `=delete`d in the returned snippet).
/// Implementation: cc_bindings_from_rs/generate_bindings/lib.rs?q=function:generate_default_ctor
fn generate_default_ctor(
&self,
core: Rc<AdtCoreBindings<'tcx>>,
) -> Result<ApiSnippets, ApiSnippets>;
/// Generates the copy constructor and the copy-assignment operator for an ADT if
/// possible (i.e. if the `Clone` trait is implemented for the ADT). Returns an
/// error otherwise (e.g. if there is no `Clone` impl, then the copy constructor
/// and assignment operator will be `=delete`d in the returned snippet).
///
/// Implementation: cc_bindings_from_rs/generate_bindings/lib.rs?q=function:generate_copy_ctor_and_assignment_operator
fn generate_copy_ctor_and_assignment_operator(
&self,
core: Rc<AdtCoreBindings<'tcx>>,
) -> Result<ApiSnippets, ApiSnippets>;
/// Generates the move constructor and the move-assignment operator for an ADT if
/// possible (it depends on various factors like `needs_drop`, `is_unpin` and
/// implementations of `Default` and/or `Clone` traits). Returns an error
/// otherwise (the error's `ApiSnippets` contain a `=delete`d declaration).
///
/// Implementation: cc_bindings_from_rs/generate_bindings/lib.rs?q=function:generate_move_ctor_and_assignment_operator
fn generate_move_ctor_and_assignment_operator(
&self,
core: Rc<AdtCoreBindings<'tcx>>,
) -> Result<ApiSnippets, ApiSnippets>;
/// Generates bindings for a HIR item idenfied by `def_id`. Returns `None` if
/// the item can be ignored. Returns an `Err` if the bindings could not be
/// generated.
///
/// Will panic if `def_id` is invalid (i.e. doesn't identify a HIR item).
///
/// Implementation: cc_bindings_from_rs/generate_bindings/lib.rs?q=function:generate_item
fn generate_item(&self, def_id: DefId) -> Result<Option<ApiSnippets>>;
/// Generates bindings for a function with the given `local_def_id`.
///
/// Will panic if `local_def_id`
/// - is invalid
/// - doesn't identify a function
///
/// Implementation: cc_bindings_from_rs/generate_bindings/generate_function.rs?q=function:generate_function
fn generate_function(&self, def_id: DefId) -> Result<ApiSnippets>;
/// Generates the bindings for the core of an algebraic data type (an ADT - a
/// struct, an enum, or a union) represented by `def_id`.
///
/// The "core" means things that are necessary for a successful binding (e.g.
/// inability to generate a correct C++ destructor means that the ADT cannot
/// have any bindings). "core" excludes things that are A) infallible (e.g.
/// struct or union fields which can always be translated into private, opaque
/// blobs of bytes) or B) optional (e.g. a problematic instance method
/// can just be ignored, unlike a problematic destructor). The split between
/// fallible "core" and non-fallible "rest" is motivated by the need to avoid
/// cycles / infinite recursion (e.g. when processing fields that refer back to
/// the struct type, possible with an indirection of a pointer).
///
/// `generate_adt_core` is used both to 1) generate bindings for the core of an
/// ADT, and 2) check if formatting would have succeeded (e.g. when called from
/// `format_ty`). The 2nd case is needed for ADTs defined in any crate.
fn generate_adt_core(&self, def_id: DefId) -> Result<Rc<AdtCoreBindings<'tcx>>>;
fn crubit_abi_type_from_ty(&self, ty: Ty<'tcx>) -> Result<CrubitAbiTypeWithCcPrereqs>;
/// Gathers all `From` trait impls for the current crate and provides a mapping from the
/// argument type to the impl. This is useful for determining `From` impls of ADTs where the
/// ADT appears as an argument rather than a self type (i.e. `impl From<Adt> for i32`).
///
/// It could make sense to expand this functionality to other single argument traits, but
/// there are open design questions if we want to support _any_ trait. How do we map from a
/// list of arguments to an implementation? For more complicated use cases it's probably
/// better to evoke the trait solver directly rather than going through this mapping. For that
/// reason, this function is currently limited to `From` specifically.
///
/// Implementation: cc_bindings_from_rs/generate_bindings/generate_struct_and_union.rs?q=function:local_from_trait_impls_by_argument
fn from_trait_impls_by_argument(&self, crate_num: CrateNum) -> Rc<HashMap<Ty<'tcx>, Vec<DefId>>>;
}
pub struct Database;
}