-
Notifications
You must be signed in to change notification settings - Fork 62
Expand file tree
/
Copy pathdb.rs
More file actions
241 lines (212 loc) · 11.3 KB
/
db.rs
File metadata and controls
241 lines (212 loc) · 11.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
// 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
use crate::code_snippet::{
ApiSnippets, BindingsInfo, NoBindingsReason, ResolvedTypeName, Visibility,
};
use crate::function_types::{FunctionId, GeneratedFunction, ImplKind};
use crate::rs_snippet::{LifetimeOptions, RsTypeKind, Safety};
use arc_anyhow::{anyhow, Result};
use crubit_abi_type::CrubitAbiType;
use error_report::{ErrorReporting, ReportFatalError};
use ffi_types::Environment;
use ir::{BazelLabel, CcType, Enum, Field, Func, Record, UnqualifiedIdentifier, IR};
use proc_macro2::Ident;
use std::collections::HashMap;
use std::rc::Rc;
#[unsafe(no_mangle)]
pub fn test_again() {}
#[derive(Clone)]
pub struct CodegenFunctions {
pub generate_enum: fn(&BindingsGenerator, Rc<Enum>) -> Result<ApiSnippets>,
pub generate_item: fn(&BindingsGenerator, ir::Item) -> Result<ApiSnippets>,
pub generate_record: fn(&BindingsGenerator, Rc<Record>) -> Result<ApiSnippets>,
}
memoized::query_group! {
pub struct BindingsGenerator<'db> {
#[input]
fn ir(&self) -> &'db IR;
#[input]
fn errors(&self) -> &'db 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) -> &'db dyn ReportFatalError;
#[input]
fn environment(&self) -> Environment;
#[input]
/// Feature flag enabling Kythe annotations
fn kythe_annotations(&self) -> bool;
#[input]
fn codegen_functions(&self) -> CodegenFunctions;
#[break_cycles_with = Safety::Safe]
/// Returns whether the given Rust type is an unsafe type, such as a raw pointer.
///
/// Returns `None` if the type is safe.
///
/// Implementation: rs_bindings_from_cc/generate_bindings/lib.rs?q=function:rs_type_kind_safety
fn rs_type_kind_safety(&self, rs_type_kind: RsTypeKind) -> Safety;
#[break_cycles_with = Safety::Safe]
/// Returns whether the given field is unsafe to access.
///
/// Implementation: rs_bindings_from_cc/generate_bindings/lib.rs?q=function:record_field_safety
fn record_field_safety(&self, field: Field) -> Safety;
#[break_cycles_with = Safety::Safe]
/// Returns whether the given record is unsafe.
///
/// A record may be unsafe due to an explicitly annotation, or by being a union,
/// or by having an unsafe public field (see `record_field_safety`).
///
/// Implementation: rs_bindings_from_cc/generate_bindings/lib.rs?q=function:record_safety
fn record_safety(&self, record: Rc<Record>) -> Safety;
/// Returns the bindings info for the given item, or an error if the item is not supported.
///
/// Implementation: rs_bindings_from_cc/generate_bindings/has_bindings.rs?q=function:has_bindings
fn has_bindings(&self, item: ir::Item) -> Result<BindingsInfo, NoBindingsReason>;
/// Returns the Rust type kind of the given C++ type, optionally filling in missing
/// reference lifetimes with the elided lifetime (`'_`).
///
/// An `Ok()` return value does not necessarily imply that the resulting `RsTypeKind` is
/// usable in APIs: callers must also check the result of `type_visibility()` for
/// the type, to see if it is usable within a specific crate. Eventually, all types will
/// have a successful non-error return value, even if the type is not generally usable.
/// Instead, restrictions will always be done via `type_visibility`.
///
/// TODO(b/409128537): never return `Err` here, instead check `type_visibility`
///
/// Implementation: rs_bindings_from_cc/generate_bindings/rs_type_kind.rs?q=function:rs_type_kind_with_lifetime_elision
fn rs_type_kind_with_lifetime_elision(&self, cc_type: CcType, lifetime_options: LifetimeOptions) -> Result<RsTypeKind>;
/// Returns the generated bindings for the given function.
///
/// `derived_record` is a derived class type which re-exports `func` as a
/// method on this record. `func` must be a method on a base class of
/// `derived_record`, if present.
///
/// Returns:
///
/// * `Err(_)`: couldn't import the function, emit an `UnsupportedItem`.
/// * `Ok(None)`: the function imported as "nothing". (For example, a defaulted
/// destructor might be mapped to no `Drop` impl at all.)
/// * `Ok(GeneratedFunction)`: The Rust function definition,
/// thunk FFI definition, and function ID.
///
/// Note that unlike other `generate_*` functions, this function may return `Ok()` but still
/// fail to generate bindings (if `GeneratedFunction.status` is `Err`), and may fail
/// to generate bindings even if `has_bindings` would return `Ok`. In general, one cannot
/// rely on the bindings of a function being generated correctly, except for `Drop`.
///
/// Implementation: rs_bindings_from_cc/generate_bindings/generate_function.rs?q=function:generate_function
fn generate_function(&self, func: Rc<Func>, derived_record: Option<Rc<Record>>) -> Result<Option<GeneratedFunction>>;
/// You should call is_function_ambiguous() instead.
///
/// Identifies all functions having overloads that we can't import (yet).
///
/// TODO(b/213280424): Implement support for overloaded functions.
///
/// Implementation: rs_bindings_from_cc/generate_bindings/generate_function.rs?q=function:overload_sets
fn overload_sets(&self) -> Rc<HashMap<Rc<FunctionId>, Option<ir::ItemId>>>;
/// Returns whether the given record either implements or derives the Clone
/// trait.
///
/// Implementation: rs_bindings_from_cc/generate_bindings/generate_function.rs?q=function:is_record_clonable
fn is_record_clonable(&self, record: Rc<Record>) -> bool;
/// Returns the generated bindings for a function with the given name and param
/// types. If none exists, returns None.
///
/// Implementation: rs_bindings_from_cc/generate_bindings/generate_function.rs?q=function:get_binding
fn get_binding(
&self,
expected_function_name: UnqualifiedIdentifier,
expected_param_types: Vec<RsTypeKind>,
) -> Option<(Ident, ImplKind)>;
/// Returns a collection of unqualified member functions of the given record.
///
/// Implementation: rs_bindings_from_cc/generate_bindings/generate_struct_and_union.rs?q=function:collect_unqualified_member_functions
fn collect_unqualified_member_functions(
&self,
record: Rc<Record>,
) -> Rc<[Rc<Func>]>;
/// Returns the `CrubitAbiType` for the given `RsTypeKind`.
///
/// Implementation: rs_bindings_from_cc/generate_bindings/lib.rs?q=function:crubit_abi_type
fn crubit_abi_type(&self, rs_type_kind: RsTypeKind) -> Result<CrubitAbiType>;
// You should probably use `type_visibility()` instead of this function.
fn type_target_restriction(&self, rs_type_kind: RsTypeKind) -> Result<Option<BazelLabel>>;
/// Resolves type names to a map from name to ResolvedTypeName.
///
/// This only checks the type namespace, as described here:
/// https://doc.rust-lang.org/reference/names/namespaces.html.
///
/// Implementation: rs_bindings_from_cc/generate_bindings/has_bindings.rs?q=function:resolve_type_names
fn resolve_type_names(&self, parent: Rc<Record>) -> Result<Rc<HashMap<Rc<str>, ResolvedTypeName>>>;
/// Returns whether the given type ensures that the memory for all publicly accessible
/// fields is initialized.
///
/// Implementation: rs_bindings_from_cc/generate_bindings/lib.rs?q=function:is_default_initialized
fn is_default_initialized(&self, rs_type_kind: RsTypeKind) -> Result<bool>;
#[provided]
/// Returns the generated bindings for the given enum.
///
/// Implementation: rs_bindings_from_cc/generate_bindings/generate_enum.rs?q=function:generate_enum
fn generate_enum(&self, enum_: Rc<Enum>) -> Result<ApiSnippets> {
(self.codegen_functions().generate_enum)(self, enum_)
}
#[provided]
/// Returns the generated bindings for an item, or `Err` if bindings generation
/// failed in such a way as to make the generated bindings as a whole invalid.
///
/// Implementation: rs_bindings_from_cc/generate_bindings/lib.rs?q=function:generate_item
fn generate_item(&self, item: ir::Item) -> Result<ApiSnippets> {
(self.codegen_functions().generate_item)(self, item)
}
#[provided]
/// Returns the generated bindings for the given record, along with associated safety
/// assertions.
///
/// Implementation: rs_bindings_from_cc/generate_bindings/generate_struct_and_union.rs?q=function:generate_record
fn generate_record(&self, record: Rc<Record>) -> Result<ApiSnippets> {
(self.codegen_functions().generate_record)(self, record)
}
#[provided]
/// Returns the Rust type kind of the given C++ type.
///
/// This differs from `rs_type_kind_with_lifetime_elision` in that it replaces references
/// with missing lifetimes with pointer types.
fn rs_type_kind(&self, cc_type: CcType) -> Result<RsTypeKind> {
self.rs_type_kind_with_lifetime_elision(cc_type, LifetimeOptions::default())
}
#[provided]
/// Returns true if an ItemId refers to a function that cannot receive bindings, because
/// it is overloaded and ambiguous.
///
/// This does not include functions that are overloaded, where all but one overload is
/// deprecated.
fn is_ambiguous_function(&self, function_id: &FunctionId, item_id: ir::ItemId) -> bool {
match self.overload_sets().get(function_id) {
None => false,
Some(id) => *id != Some(item_id),
}
}
#[provided]
/// Returns the `Visibility` of the `rs_type_kind` in the given `library`.
fn type_visibility(&self, library: &BazelLabel, rs_type_kind: RsTypeKind) -> Result<Visibility> {
match self.type_target_restriction(rs_type_kind.clone())? {
Some(label) if &label != library => {
let rs_type_kind = rs_type_kind.display(self);
Err(anyhow!("{rs_type_kind} is `pub(crate)` in {label}"))
}
Some(_) => Ok(Visibility::PubCrate),
None => {
for subtype in rs_type_kind.dfs_iter() {
if let RsTypeKind::Error { visibility_override, .. } = subtype {
return Ok(visibility_override.unwrap_or(Visibility::PubCrate));
}
}
Ok(Visibility::Public)
}
}
}
}
}