Marcel Hlopko | 42abfc8 | 2021-08-09 07:03:17 +0000 | [diff] [blame] | 1 | // Part of the Crubit project, under the Apache License v2.0 with LLVM |
| 2 | // Exceptions. See /LICENSE for license information. |
| 3 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 4 | |
Devin Jeanpierre | 8cd8ae7 | 2022-06-29 18:59:40 -0700 | [diff] [blame] | 5 | //! Types and deserialization logic for IR. See docs in |
| 6 | //! `rs_bindings_from_cc/ir.h` for more |
| 7 | //! information. |
| 8 | |
Michael VanBemmel | f5cbdf4 | 2022-10-14 17:00:11 -0700 | [diff] [blame] | 9 | use arc_anyhow::{anyhow, bail, Context, Error, Result}; |
| 10 | use once_cell::unsync::OnceCell; |
Devin Jeanpierre | d61c6d7 | 2023-02-02 14:30:19 -0800 | [diff] [blame] | 11 | use proc_macro2::TokenStream; |
| 12 | use quote::{quote, ToTokens}; |
Marcel Hlopko | 42abfc8 | 2021-08-09 07:03:17 +0000 | [diff] [blame] | 13 | use serde::Deserialize; |
Devin Jeanpierre | 9886fb4 | 2022-04-01 04:31:20 -0700 | [diff] [blame] | 14 | use std::collections::hash_map::{Entry, HashMap}; |
Devin Jeanpierre | 7eb0404 | 2021-12-03 07:19:22 +0000 | [diff] [blame] | 15 | use std::convert::TryFrom; |
Devin Jeanpierre | ab8732a | 2023-03-22 19:09:03 -0700 | [diff] [blame] | 16 | use std::fmt::{self, Debug, Display, Formatter}; |
Michael VanBemmel | f5cbdf4 | 2022-10-14 17:00:11 -0700 | [diff] [blame] | 17 | use std::hash::{Hash, Hasher}; |
Marcel Hlopko | 42abfc8 | 2021-08-09 07:03:17 +0000 | [diff] [blame] | 18 | use std::io::Read; |
Devin Jeanpierre | 8cd8ae7 | 2022-06-29 18:59:40 -0700 | [diff] [blame] | 19 | use std::rc::Rc; |
Marcel Hlopko | 42abfc8 | 2021-08-09 07:03:17 +0000 | [diff] [blame] | 20 | |
Devin Jeanpierre | ab8732a | 2023-03-22 19:09:03 -0700 | [diff] [blame] | 21 | /// Common data about all items. |
| 22 | pub trait GenericItem { |
| 23 | fn id(&self) -> ItemId; |
| 24 | /// The name of the item, readable by programmers. |
| 25 | /// |
| 26 | /// For example, `void Foo();` should have name `Foo`. |
| 27 | fn debug_name(&self, ir: &IR) -> Rc<str>; |
| 28 | |
| 29 | /// The recorded source location, or None if none is present. |
| 30 | fn source_loc(&self) -> Option<Rc<str>>; |
| 31 | } |
| 32 | |
| 33 | impl<T> GenericItem for Rc<T> |
| 34 | where |
| 35 | T: GenericItem + ?Sized, |
| 36 | { |
| 37 | fn id(&self) -> ItemId { |
| 38 | (**self).id() |
| 39 | } |
| 40 | fn debug_name(&self, ir: &IR) -> Rc<str> { |
| 41 | (**self).debug_name(ir) |
| 42 | } |
| 43 | fn source_loc(&self) -> Option<Rc<str>> { |
| 44 | (**self).source_loc() |
| 45 | } |
| 46 | } |
| 47 | |
Marcel Hlopko | 3b9bf9e | 2021-11-29 08:25:14 +0000 | [diff] [blame] | 48 | /// Deserialize `IR` from JSON given as a reader. |
Marcel Hlopko | 42abfc8 | 2021-08-09 07:03:17 +0000 | [diff] [blame] | 49 | pub fn deserialize_ir<R: Read>(reader: R) -> Result<IR> { |
Marcel Hlopko | 3b9bf9e | 2021-11-29 08:25:14 +0000 | [diff] [blame] | 50 | let flat_ir = serde_json::from_reader(reader)?; |
Lukasz Anforowicz | 578ba8b | 2023-05-15 11:15:51 -0700 | [diff] [blame] | 51 | Ok(make_ir(flat_ir)) |
Marcel Hlopko | 3b9bf9e | 2021-11-29 08:25:14 +0000 | [diff] [blame] | 52 | } |
| 53 | |
Marcel Hlopko | 3b9bf9e | 2021-11-29 08:25:14 +0000 | [diff] [blame] | 54 | /// Create a testing `IR` instance from given parts. This function does not use |
| 55 | /// any mock values. |
Devin Jeanpierre | 6ed0f60 | 2023-03-01 17:22:54 -0800 | [diff] [blame] | 56 | pub fn make_ir_from_parts<CrubitFeatures>( |
Marcel Hlopko | 3b9bf9e | 2021-11-29 08:25:14 +0000 | [diff] [blame] | 57 | items: Vec<Item>, |
Lukasz Anforowicz | 121338a | 2022-11-01 14:28:32 -0700 | [diff] [blame] | 58 | public_headers: Vec<HeaderName>, |
Googler | 6c3de12 | 2022-03-28 11:40:41 +0000 | [diff] [blame] | 59 | current_target: BazelLabel, |
Rosica Dejanovska | b2bd59e | 2022-04-11 09:02:03 -0700 | [diff] [blame] | 60 | top_level_item_ids: Vec<ItemId>, |
Googler | 841386c | 2022-11-29 07:42:32 -0800 | [diff] [blame] | 61 | crate_root_path: Option<Rc<str>>, |
Devin Jeanpierre | 6ed0f60 | 2023-03-01 17:22:54 -0800 | [diff] [blame] | 62 | crubit_features: HashMap<BazelLabel, CrubitFeatures>, |
Lukasz Anforowicz | 578ba8b | 2023-05-15 11:15:51 -0700 | [diff] [blame] | 63 | ) -> IR |
Devin Jeanpierre | 6ed0f60 | 2023-03-01 17:22:54 -0800 | [diff] [blame] | 64 | where |
| 65 | CrubitFeatures: Into<flagset::FlagSet<CrubitFeature>>, |
| 66 | { |
| 67 | make_ir(FlatIR { |
| 68 | public_headers, |
| 69 | current_target, |
| 70 | items, |
| 71 | top_level_item_ids, |
| 72 | crate_root_path, |
| 73 | crubit_features: crubit_features |
| 74 | .into_iter() |
| 75 | .map(|(label, features)| (label, CrubitFeaturesIR(features.into()))) |
| 76 | .collect(), |
| 77 | }) |
Marcel Hlopko | 3b9bf9e | 2021-11-29 08:25:14 +0000 | [diff] [blame] | 78 | } |
| 79 | |
Lukasz Anforowicz | 578ba8b | 2023-05-15 11:15:51 -0700 | [diff] [blame] | 80 | fn make_ir(flat_ir: FlatIR) -> IR { |
Marcel Hlopko | 3b9bf9e | 2021-11-29 08:25:14 +0000 | [diff] [blame] | 81 | let mut used_decl_ids = HashMap::new(); |
| 82 | for item in &flat_ir.items { |
Rosica Dejanovska | 10accf1 | 2022-03-31 04:47:58 -0700 | [diff] [blame] | 83 | if let Some(existing_decl) = used_decl_ids.insert(item.id(), item) { |
Lukasz Anforowicz | 578ba8b | 2023-05-15 11:15:51 -0700 | [diff] [blame] | 84 | panic!("Duplicate decl_id found in {:?} and {:?}", existing_decl, item); |
Marcel Hlopko | 3b9bf9e | 2021-11-29 08:25:14 +0000 | [diff] [blame] | 85 | } |
| 86 | } |
Rosica Dejanovska | d638cf5 | 2022-03-23 15:45:01 +0000 | [diff] [blame] | 87 | let item_id_to_item_idx = flat_ir |
Marcel Hlopko | 3b9bf9e | 2021-11-29 08:25:14 +0000 | [diff] [blame] | 88 | .items |
| 89 | .iter() |
| 90 | .enumerate() |
Rosica Dejanovska | 10accf1 | 2022-03-31 04:47:58 -0700 | [diff] [blame] | 91 | .map(|(idx, item)| (item.id(), idx)) |
Marcel Hlopko | 3b9bf9e | 2021-11-29 08:25:14 +0000 | [diff] [blame] | 92 | .collect::<HashMap<_, _>>(); |
Devin Jeanpierre | 9886fb4 | 2022-04-01 04:31:20 -0700 | [diff] [blame] | 93 | |
Marcel Hlopko | af682a0 | 2022-04-08 07:27:14 -0700 | [diff] [blame] | 94 | let mut lifetimes: HashMap<LifetimeId, LifetimeName> = HashMap::new(); |
Devin Jeanpierre | 9886fb4 | 2022-04-01 04:31:20 -0700 | [diff] [blame] | 95 | for item in &flat_ir.items { |
| 96 | let lifetime_params = match item { |
Devin Jeanpierre | 8cd8ae7 | 2022-06-29 18:59:40 -0700 | [diff] [blame] | 97 | Item::Record(record) => &record.lifetime_params, |
| 98 | Item::Func(func) => &func.lifetime_params, |
Devin Jeanpierre | 9886fb4 | 2022-04-01 04:31:20 -0700 | [diff] [blame] | 99 | _ => continue, |
| 100 | }; |
| 101 | for lifetime in lifetime_params { |
Devin Jeanpierre | d2b7a8f | 2022-04-01 04:37:16 -0700 | [diff] [blame] | 102 | match lifetimes.entry(lifetime.id) { |
Devin Jeanpierre | 9886fb4 | 2022-04-01 04:31:20 -0700 | [diff] [blame] | 103 | Entry::Occupied(occupied) => { |
Lukasz Anforowicz | 578ba8b | 2023-05-15 11:15:51 -0700 | [diff] [blame] | 104 | panic!( |
Devin Jeanpierre | 6af160e | 2022-09-21 05:30:34 -0700 | [diff] [blame] | 105 | "Duplicate use of lifetime ID {:?} in item {item:?} for names: '{}, '{}", |
Devin Jeanpierre | 9886fb4 | 2022-04-01 04:31:20 -0700 | [diff] [blame] | 106 | lifetime.id, |
Devin Jeanpierre | d2b7a8f | 2022-04-01 04:37:16 -0700 | [diff] [blame] | 107 | &occupied.get().name, |
Devin Jeanpierre | 9886fb4 | 2022-04-01 04:31:20 -0700 | [diff] [blame] | 108 | &lifetime.name |
| 109 | ) |
| 110 | } |
| 111 | Entry::Vacant(vacant) => { |
Devin Jeanpierre | d2b7a8f | 2022-04-01 04:37:16 -0700 | [diff] [blame] | 112 | vacant.insert(lifetime.clone()); |
Devin Jeanpierre | 9886fb4 | 2022-04-01 04:31:20 -0700 | [diff] [blame] | 113 | } |
| 114 | } |
| 115 | } |
| 116 | } |
Rosica Dejanovska | 93aeafb | 2022-06-01 07:05:31 -0700 | [diff] [blame] | 117 | let mut namespace_id_to_number_of_reopened_namespaces = HashMap::new(); |
| 118 | let mut reopened_namespace_id_to_idx = HashMap::new(); |
| 119 | |
| 120 | flat_ir |
| 121 | .items |
| 122 | .iter() |
| 123 | .filter_map(|item| match item { |
| 124 | Item::Namespace(ns) if ns.owning_target == flat_ir.current_target => { |
| 125 | Some((ns.canonical_namespace_id, ns.id)) |
| 126 | } |
| 127 | _ => None, |
| 128 | }) |
| 129 | .for_each(|(canonical_id, id)| { |
| 130 | let current_count = |
| 131 | *namespace_id_to_number_of_reopened_namespaces.entry(canonical_id).or_insert(0); |
| 132 | reopened_namespace_id_to_idx.insert(id, current_count); |
| 133 | namespace_id_to_number_of_reopened_namespaces.insert(canonical_id, current_count + 1); |
| 134 | }); |
| 135 | |
Felipe de A. Mello Pereira | 3a95372 | 2023-03-02 05:37:36 -0800 | [diff] [blame] | 136 | let mut function_name_to_functions = HashMap::<UnqualifiedIdentifier, Vec<Rc<Func>>>::new(); |
| 137 | flat_ir |
| 138 | .items |
| 139 | .iter() |
| 140 | .filter_map(|item| match item { |
| 141 | Item::Func(func) => Some(func), |
| 142 | _ => None, |
| 143 | }) |
| 144 | .for_each(|f| { |
| 145 | function_name_to_functions.entry(f.name.clone()).or_default().push(f.clone()); |
| 146 | }); |
| 147 | |
Lukasz Anforowicz | 578ba8b | 2023-05-15 11:15:51 -0700 | [diff] [blame] | 148 | IR { |
Rosica Dejanovska | 93aeafb | 2022-06-01 07:05:31 -0700 | [diff] [blame] | 149 | flat_ir, |
| 150 | item_id_to_item_idx, |
| 151 | lifetimes, |
| 152 | namespace_id_to_number_of_reopened_namespaces, |
| 153 | reopened_namespace_id_to_idx, |
Felipe de A. Mello Pereira | 3a95372 | 2023-03-02 05:37:36 -0800 | [diff] [blame] | 154 | function_name_to_functions, |
Lukasz Anforowicz | 578ba8b | 2023-05-15 11:15:51 -0700 | [diff] [blame] | 155 | } |
Marcel Hlopko | 42abfc8 | 2021-08-09 07:03:17 +0000 | [diff] [blame] | 156 | } |
| 157 | |
| 158 | #[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize)] |
Devin Jeanpierre | f238403 | 2023-03-10 14:26:27 -0800 | [diff] [blame] | 159 | #[serde(deny_unknown_fields)] |
Marcel Hlopko | f1123c8 | 2021-08-19 11:38:52 +0000 | [diff] [blame] | 160 | pub struct HeaderName { |
Lukasz Anforowicz | 434c469 | 2022-11-01 14:05:24 -0700 | [diff] [blame] | 161 | pub name: Rc<str>, |
Marcel Hlopko | f1123c8 | 2021-08-19 11:38:52 +0000 | [diff] [blame] | 162 | } |
| 163 | |
Googler | 64e4edb | 2021-12-03 12:17:38 +0000 | [diff] [blame] | 164 | #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy, Deserialize)] |
Devin Jeanpierre | f238403 | 2023-03-10 14:26:27 -0800 | [diff] [blame] | 165 | #[serde(deny_unknown_fields)] |
Googler | 64e4edb | 2021-12-03 12:17:38 +0000 | [diff] [blame] | 166 | #[serde(transparent)] |
| 167 | pub struct LifetimeId(pub i32); |
| 168 | |
| 169 | #[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize)] |
Devin Jeanpierre | f238403 | 2023-03-10 14:26:27 -0800 | [diff] [blame] | 170 | #[serde(deny_unknown_fields)] |
Marcel Hlopko | af682a0 | 2022-04-08 07:27:14 -0700 | [diff] [blame] | 171 | pub struct LifetimeName { |
Devin Jeanpierre | b2b6cf8 | 2022-07-07 01:49:27 -0700 | [diff] [blame] | 172 | pub name: Rc<str>, |
Googler | 64e4edb | 2021-12-03 12:17:38 +0000 | [diff] [blame] | 173 | pub id: LifetimeId, |
| 174 | } |
| 175 | |
Marcel Hlopko | f1123c8 | 2021-08-19 11:38:52 +0000 | [diff] [blame] | 176 | #[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize)] |
Devin Jeanpierre | f238403 | 2023-03-10 14:26:27 -0800 | [diff] [blame] | 177 | #[serde(deny_unknown_fields)] |
Devin Jeanpierre | 09c6f45 | 2021-09-29 07:34:24 +0000 | [diff] [blame] | 178 | pub struct RsType { |
Googler | 841386c | 2022-11-29 07:42:32 -0800 | [diff] [blame] | 179 | pub name: Option<Rc<str>>, |
Devin Jeanpierre | 409f6f6 | 2022-07-07 02:00:26 -0700 | [diff] [blame] | 180 | pub lifetime_args: Rc<[LifetimeId]>, |
| 181 | pub type_args: Rc<[RsType]>, |
Rosica Dejanovska | d638cf5 | 2022-03-23 15:45:01 +0000 | [diff] [blame] | 182 | pub decl_id: Option<ItemId>, |
Devin Jeanpierre | 09c6f45 | 2021-09-29 07:34:24 +0000 | [diff] [blame] | 183 | } |
| 184 | |
Lukasz Anforowicz | 4ad012b | 2021-12-15 18:13:40 +0000 | [diff] [blame] | 185 | impl RsType { |
| 186 | pub fn is_unit_type(&self) -> bool { |
| 187 | self.name.as_deref() == Some("()") |
| 188 | } |
| 189 | } |
| 190 | |
Devin Jeanpierre | 09c6f45 | 2021-09-29 07:34:24 +0000 | [diff] [blame] | 191 | #[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize)] |
Devin Jeanpierre | f238403 | 2023-03-10 14:26:27 -0800 | [diff] [blame] | 192 | #[serde(deny_unknown_fields)] |
Devin Jeanpierre | 09c6f45 | 2021-09-29 07:34:24 +0000 | [diff] [blame] | 193 | pub struct CcType { |
Googler | 841386c | 2022-11-29 07:42:32 -0800 | [diff] [blame] | 194 | pub name: Option<Rc<str>>, |
Devin Jeanpierre | 09c6f45 | 2021-09-29 07:34:24 +0000 | [diff] [blame] | 195 | pub is_const: bool, |
Googler | ff7fc23 | 2021-12-02 09:43:00 +0000 | [diff] [blame] | 196 | pub type_args: Vec<CcType>, |
Rosica Dejanovska | d638cf5 | 2022-03-23 15:45:01 +0000 | [diff] [blame] | 197 | pub decl_id: Option<ItemId>, |
Devin Jeanpierre | 09c6f45 | 2021-09-29 07:34:24 +0000 | [diff] [blame] | 198 | } |
| 199 | |
Marcel Hlopko | 264b9ad | 2021-12-02 21:06:44 +0000 | [diff] [blame] | 200 | pub trait TypeWithDeclId { |
Rosica Dejanovska | d638cf5 | 2022-03-23 15:45:01 +0000 | [diff] [blame] | 201 | fn decl_id(&self) -> Option<ItemId>; |
Marcel Hlopko | c0956cf | 2021-11-29 08:31:28 +0000 | [diff] [blame] | 202 | } |
| 203 | |
Marcel Hlopko | 264b9ad | 2021-12-02 21:06:44 +0000 | [diff] [blame] | 204 | impl TypeWithDeclId for RsType { |
Rosica Dejanovska | d638cf5 | 2022-03-23 15:45:01 +0000 | [diff] [blame] | 205 | fn decl_id(&self) -> Option<ItemId> { |
Marcel Hlopko | c0956cf | 2021-11-29 08:31:28 +0000 | [diff] [blame] | 206 | self.decl_id |
| 207 | } |
| 208 | } |
| 209 | |
Marcel Hlopko | 264b9ad | 2021-12-02 21:06:44 +0000 | [diff] [blame] | 210 | impl TypeWithDeclId for CcType { |
Rosica Dejanovska | d638cf5 | 2022-03-23 15:45:01 +0000 | [diff] [blame] | 211 | fn decl_id(&self) -> Option<ItemId> { |
Marcel Hlopko | c0956cf | 2021-11-29 08:31:28 +0000 | [diff] [blame] | 212 | self.decl_id |
| 213 | } |
| 214 | } |
| 215 | |
Devin Jeanpierre | 09c6f45 | 2021-09-29 07:34:24 +0000 | [diff] [blame] | 216 | #[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize)] |
Devin Jeanpierre | f238403 | 2023-03-10 14:26:27 -0800 | [diff] [blame] | 217 | #[serde(deny_unknown_fields)] |
Devin Jeanpierre | 09c6f45 | 2021-09-29 07:34:24 +0000 | [diff] [blame] | 218 | pub struct MappedType { |
| 219 | pub rs_type: RsType, |
| 220 | pub cc_type: CcType, |
Marcel Hlopko | 42abfc8 | 2021-08-09 07:03:17 +0000 | [diff] [blame] | 221 | } |
| 222 | |
Marcel Hlopko | afdc502 | 2021-12-16 14:31:19 +0000 | [diff] [blame] | 223 | #[derive(PartialEq, Eq, Hash, Clone, Deserialize)] |
Devin Jeanpierre | f238403 | 2023-03-10 14:26:27 -0800 | [diff] [blame] | 224 | #[serde(deny_unknown_fields)] |
Marcel Hlopko | 42abfc8 | 2021-08-09 07:03:17 +0000 | [diff] [blame] | 225 | pub struct Identifier { |
Lukasz Anforowicz | 8c1a6c4 | 2022-11-23 16:18:09 -0800 | [diff] [blame] | 226 | pub identifier: Rc<str>, |
Marcel Hlopko | 42abfc8 | 2021-08-09 07:03:17 +0000 | [diff] [blame] | 227 | } |
| 228 | |
Devin Jeanpierre | ab8732a | 2023-03-22 19:09:03 -0700 | [diff] [blame] | 229 | impl Display for Identifier { |
Marcel Hlopko | afdc502 | 2021-12-16 14:31:19 +0000 | [diff] [blame] | 230 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
Devin Jeanpierre | ab8732a | 2023-03-22 19:09:03 -0700 | [diff] [blame] | 231 | write!(f, "{}", self.identifier) |
| 232 | } |
| 233 | } |
| 234 | |
| 235 | impl Debug for Identifier { |
| 236 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 237 | write!(f, "\"{}\"", self.identifier) |
Marcel Hlopko | afdc502 | 2021-12-16 14:31:19 +0000 | [diff] [blame] | 238 | } |
| 239 | } |
| 240 | |
Teddy Katz | 76fa42b | 2022-02-23 01:22:56 +0000 | [diff] [blame] | 241 | #[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, Deserialize)] |
Devin Jeanpierre | f238403 | 2023-03-10 14:26:27 -0800 | [diff] [blame] | 242 | #[serde(deny_unknown_fields)] |
Teddy Katz | 76fa42b | 2022-02-23 01:22:56 +0000 | [diff] [blame] | 243 | pub struct IntegerConstant { |
| 244 | pub is_negative: bool, |
| 245 | pub wrapped_value: u64, |
| 246 | } |
| 247 | |
Lukasz Anforowicz | 9c663ca | 2022-02-09 01:33:31 +0000 | [diff] [blame] | 248 | #[derive(PartialEq, Eq, Hash, Clone, Deserialize)] |
Devin Jeanpierre | f238403 | 2023-03-10 14:26:27 -0800 | [diff] [blame] | 249 | #[serde(deny_unknown_fields)] |
Lukasz Anforowicz | 9c663ca | 2022-02-09 01:33:31 +0000 | [diff] [blame] | 250 | pub struct Operator { |
Googler | 408ef40 | 2022-11-28 02:59:28 -0800 | [diff] [blame] | 251 | pub name: Rc<str>, |
Lukasz Anforowicz | 9c663ca | 2022-02-09 01:33:31 +0000 | [diff] [blame] | 252 | } |
| 253 | |
| 254 | impl Operator { |
| 255 | pub fn cc_name(&self) -> String { |
| 256 | let separator = match self.name.chars().next() { |
| 257 | Some(c) if c.is_alphabetic() => " ", |
| 258 | _ => "", |
| 259 | }; |
| 260 | format!("operator{separator}{name}", separator = separator, name = self.name) |
| 261 | } |
| 262 | } |
| 263 | |
Devin Jeanpierre | ab8732a | 2023-03-22 19:09:03 -0700 | [diff] [blame] | 264 | impl Debug for Operator { |
Lukasz Anforowicz | 9c663ca | 2022-02-09 01:33:31 +0000 | [diff] [blame] | 265 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
Devin Jeanpierre | ab8732a | 2023-03-22 19:09:03 -0700 | [diff] [blame] | 266 | write!(f, "\"{}\"", self.cc_name()) |
Lukasz Anforowicz | 9c663ca | 2022-02-09 01:33:31 +0000 | [diff] [blame] | 267 | } |
| 268 | } |
| 269 | |
Marcel Hlopko | 9c150da | 2021-11-12 10:30:03 +0000 | [diff] [blame] | 270 | #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy, Deserialize)] |
| 271 | #[serde(transparent)] |
Lukasz Anforowicz | 14732b2 | 2022-06-02 09:11:08 -0700 | [diff] [blame] | 272 | pub struct ItemId(usize); |
| 273 | |
| 274 | impl ItemId { |
| 275 | pub fn new_for_testing(value: usize) -> Self { |
| 276 | Self(value) |
| 277 | } |
| 278 | } |
| 279 | |
| 280 | impl ToTokens for ItemId { |
| 281 | fn to_tokens(&self, tokens: &mut TokenStream) { |
| 282 | proc_macro2::Literal::usize_unsuffixed(self.0).to_tokens(tokens) |
| 283 | } |
| 284 | } |
Marcel Hlopko | 9c150da | 2021-11-12 10:30:03 +0000 | [diff] [blame] | 285 | |
Devin Jeanpierre | 89230f3 | 2023-03-15 12:27:02 -0700 | [diff] [blame] | 286 | /// A Bazel label, e.g. `//foo:bar`. |
Marcel Hlopko | 42abfc8 | 2021-08-09 07:03:17 +0000 | [diff] [blame] | 287 | #[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize)] |
Marcel Hlopko | 80441c1 | 2021-11-12 10:43:18 +0000 | [diff] [blame] | 288 | #[serde(transparent)] |
Googler | c2102ee | 2022-11-29 07:18:24 -0800 | [diff] [blame] | 289 | pub struct BazelLabel(pub Rc<str>); |
Marcel Hlopko | 80441c1 | 2021-11-12 10:43:18 +0000 | [diff] [blame] | 290 | |
Googler | 6c3de12 | 2022-03-28 11:40:41 +0000 | [diff] [blame] | 291 | impl BazelLabel { |
Devin Jeanpierre | 89230f3 | 2023-03-15 12:27:02 -0700 | [diff] [blame] | 292 | /// Returns the target name. E.g. `bar` for `//foo:bar`. |
Devin Jeanpierre | 084ebbd | 2022-04-01 04:32:46 -0700 | [diff] [blame] | 293 | pub fn target_name(&self) -> &str { |
Devin Jeanpierre | 89230f3 | 2023-03-15 12:27:02 -0700 | [diff] [blame] | 294 | if let Some((_package, target_name)) = self.0.split_once(':') { |
| 295 | return target_name; |
Marcel Hlopko | a0f3866 | 2021-12-03 08:45:26 +0000 | [diff] [blame] | 296 | } |
Devin Jeanpierre | 89230f3 | 2023-03-15 12:27:02 -0700 | [diff] [blame] | 297 | if let Some((_, last_package_component)) = self.0.rsplit_once('/') { |
| 298 | return last_package_component; |
| 299 | } |
| 300 | &self.0 |
Marcel Hlopko | a0f3866 | 2021-12-03 08:45:26 +0000 | [diff] [blame] | 301 | } |
| 302 | } |
| 303 | |
Googler | 6c3de12 | 2022-03-28 11:40:41 +0000 | [diff] [blame] | 304 | impl<T: Into<String>> From<T> for BazelLabel { |
Marcel Hlopko | 80441c1 | 2021-11-12 10:43:18 +0000 | [diff] [blame] | 305 | fn from(label: T) -> Self { |
Googler | c2102ee | 2022-11-29 07:18:24 -0800 | [diff] [blame] | 306 | Self(label.into().into()) |
Marcel Hlopko | 80441c1 | 2021-11-12 10:43:18 +0000 | [diff] [blame] | 307 | } |
| 308 | } |
| 309 | |
Devin Jeanpierre | ab8732a | 2023-03-22 19:09:03 -0700 | [diff] [blame] | 310 | impl Display for BazelLabel { |
| 311 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
Devin Jeanpierre | dff6528 | 2023-03-14 20:32:28 -0700 | [diff] [blame] | 312 | write!(f, "{}", &*self.0) |
| 313 | } |
| 314 | } |
| 315 | |
Marcel Hlopko | afdc502 | 2021-12-16 14:31:19 +0000 | [diff] [blame] | 316 | #[derive(PartialEq, Eq, Hash, Clone, Deserialize)] |
Devin Jeanpierre | f2ec871 | 2021-10-13 20:47:16 +0000 | [diff] [blame] | 317 | pub enum UnqualifiedIdentifier { |
| 318 | Identifier(Identifier), |
Lukasz Anforowicz | 9c663ca | 2022-02-09 01:33:31 +0000 | [diff] [blame] | 319 | Operator(Operator), |
Devin Jeanpierre | f2ec871 | 2021-10-13 20:47:16 +0000 | [diff] [blame] | 320 | Constructor, |
| 321 | Destructor, |
| 322 | } |
| 323 | |
Marcel Hlopko | 36ced2d | 2021-12-02 10:47:37 +0000 | [diff] [blame] | 324 | impl UnqualifiedIdentifier { |
| 325 | pub fn identifier_as_str(&self) -> Option<&str> { |
| 326 | match self { |
Lukasz Anforowicz | 8c1a6c4 | 2022-11-23 16:18:09 -0800 | [diff] [blame] | 327 | UnqualifiedIdentifier::Identifier(identifier) => Some(identifier.identifier.as_ref()), |
Marcel Hlopko | 36ced2d | 2021-12-02 10:47:37 +0000 | [diff] [blame] | 328 | _ => None, |
| 329 | } |
| 330 | } |
| 331 | } |
| 332 | |
Devin Jeanpierre | ab8732a | 2023-03-22 19:09:03 -0700 | [diff] [blame] | 333 | impl Debug for UnqualifiedIdentifier { |
Marcel Hlopko | afdc502 | 2021-12-16 14:31:19 +0000 | [diff] [blame] | 334 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 335 | match self { |
Devin Jeanpierre | ab8732a | 2023-03-22 19:09:03 -0700 | [diff] [blame] | 336 | UnqualifiedIdentifier::Identifier(identifier) => Debug::fmt(identifier, f), |
| 337 | UnqualifiedIdentifier::Operator(op) => Debug::fmt(op, f), |
Marcel Hlopko | afdc502 | 2021-12-16 14:31:19 +0000 | [diff] [blame] | 338 | UnqualifiedIdentifier::Constructor => f.write_str("Constructor"), |
| 339 | UnqualifiedIdentifier::Destructor => f.write_str("Destructor"), |
| 340 | } |
| 341 | } |
| 342 | } |
| 343 | |
Devin Jeanpierre | 435d71f | 2022-10-04 22:18:50 -0700 | [diff] [blame] | 344 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Deserialize)] |
Devin Jeanpierre | c6877bb | 2021-10-13 20:47:54 +0000 | [diff] [blame] | 345 | pub enum ReferenceQualification { |
| 346 | LValue, |
| 347 | RValue, |
| 348 | Unqualified, |
| 349 | } |
| 350 | |
| 351 | #[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize)] |
Devin Jeanpierre | f238403 | 2023-03-10 14:26:27 -0800 | [diff] [blame] | 352 | #[serde(deny_unknown_fields)] |
Devin Jeanpierre | c6877bb | 2021-10-13 20:47:54 +0000 | [diff] [blame] | 353 | pub struct InstanceMethodMetadata { |
| 354 | pub reference: ReferenceQualification, |
| 355 | pub is_const: bool, |
| 356 | pub is_virtual: bool, |
| 357 | } |
| 358 | |
| 359 | #[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize)] |
Devin Jeanpierre | f238403 | 2023-03-10 14:26:27 -0800 | [diff] [blame] | 360 | #[serde(deny_unknown_fields)] |
Devin Jeanpierre | c6877bb | 2021-10-13 20:47:54 +0000 | [diff] [blame] | 361 | pub struct MemberFuncMetadata { |
Rosica Dejanovska | d638cf5 | 2022-03-23 15:45:01 +0000 | [diff] [blame] | 362 | pub record_id: ItemId, |
Devin Jeanpierre | c6877bb | 2021-10-13 20:47:54 +0000 | [diff] [blame] | 363 | pub instance_method_metadata: Option<InstanceMethodMetadata>, |
| 364 | } |
| 365 | |
| 366 | #[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize)] |
Devin Jeanpierre | f238403 | 2023-03-10 14:26:27 -0800 | [diff] [blame] | 367 | #[serde(deny_unknown_fields)] |
Marcel Hlopko | 42abfc8 | 2021-08-09 07:03:17 +0000 | [diff] [blame] | 368 | pub struct FuncParam { |
| 369 | #[serde(rename(deserialize = "type"))] |
Devin Jeanpierre | 09c6f45 | 2021-09-29 07:34:24 +0000 | [diff] [blame] | 370 | pub type_: MappedType, |
Marcel Hlopko | 42abfc8 | 2021-08-09 07:03:17 +0000 | [diff] [blame] | 371 | pub identifier: Identifier, |
| 372 | } |
| 373 | |
| 374 | #[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize)] |
Devin Jeanpierre | f238403 | 2023-03-10 14:26:27 -0800 | [diff] [blame] | 375 | #[serde(deny_unknown_fields)] |
Marcel Hlopko | 42abfc8 | 2021-08-09 07:03:17 +0000 | [diff] [blame] | 376 | pub struct Func { |
Devin Jeanpierre | f2ec871 | 2021-10-13 20:47:16 +0000 | [diff] [blame] | 377 | pub name: UnqualifiedIdentifier, |
Googler | 6c3de12 | 2022-03-28 11:40:41 +0000 | [diff] [blame] | 378 | pub owning_target: BazelLabel, |
Googler | c2102ee | 2022-11-29 07:18:24 -0800 | [diff] [blame] | 379 | pub mangled_name: Rc<str>, |
Googler | 841386c | 2022-11-29 07:42:32 -0800 | [diff] [blame] | 380 | pub doc_comment: Option<Rc<str>>, |
Devin Jeanpierre | 09c6f45 | 2021-09-29 07:34:24 +0000 | [diff] [blame] | 381 | pub return_type: MappedType, |
Marcel Hlopko | 42abfc8 | 2021-08-09 07:03:17 +0000 | [diff] [blame] | 382 | pub params: Vec<FuncParam>, |
Devin Jeanpierre | 6bb8180 | 2022-08-10 02:08:47 -0700 | [diff] [blame] | 383 | /// For tests and internal use only. |
| 384 | /// |
| 385 | /// Prefer to reconstruct the lifetime params from the parameter types, as |
| 386 | /// needed. This allows new parameters and lifetimes to be added that were |
| 387 | /// not originally part of the IR. |
Marcel Hlopko | af682a0 | 2022-04-08 07:27:14 -0700 | [diff] [blame] | 388 | pub lifetime_params: Vec<LifetimeName>, |
Marcel Hlopko | 3164eee | 2021-08-24 20:09:22 +0000 | [diff] [blame] | 389 | pub is_inline: bool, |
Devin Jeanpierre | c6877bb | 2021-10-13 20:47:54 +0000 | [diff] [blame] | 390 | pub member_func_metadata: Option<MemberFuncMetadata>, |
Lukasz Anforowicz | 0b6a6ac | 2022-03-22 22:32:23 +0000 | [diff] [blame] | 391 | pub has_c_calling_convention: bool, |
Lukasz Anforowicz | b1ff2e5 | 2022-05-16 10:54:23 -0700 | [diff] [blame] | 392 | pub is_member_or_descendant_of_class_template: bool, |
Googler | 442733c | 2023-01-23 01:05:35 -0800 | [diff] [blame] | 393 | pub source_loc: Rc<str>, |
Rosica Dejanovska | d638cf5 | 2022-03-23 15:45:01 +0000 | [diff] [blame] | 394 | pub id: ItemId, |
Rosica Dejanovska | e91d299 | 2022-05-05 05:31:39 -0700 | [diff] [blame] | 395 | pub enclosing_namespace_id: Option<ItemId>, |
Michael VanBemmel | 7a4d4c0 | 2022-07-27 13:21:47 -0700 | [diff] [blame] | 396 | pub adl_enclosing_record: Option<ItemId>, |
Marcel Hlopko | 42abfc8 | 2021-08-09 07:03:17 +0000 | [diff] [blame] | 397 | } |
| 398 | |
Devin Jeanpierre | ab8732a | 2023-03-22 19:09:03 -0700 | [diff] [blame] | 399 | impl GenericItem for Func { |
| 400 | fn id(&self) -> ItemId { |
| 401 | self.id |
| 402 | } |
| 403 | fn debug_name(&self, ir: &IR) -> Rc<str> { |
| 404 | let record: Option<Rc<str>> = ir.record_for_member_func(self).map(|r| r.debug_name(ir)); |
| 405 | let record: Option<&str> = record.as_deref(); |
| 406 | |
| 407 | let func_name = match &self.name { |
| 408 | UnqualifiedIdentifier::Identifier(id) => id.identifier.to_string(), |
| 409 | UnqualifiedIdentifier::Operator(op) => op.cc_name(), |
| 410 | UnqualifiedIdentifier::Destructor => { |
| 411 | format!("~{}", record.expect("destructor must be associated with a record")) |
| 412 | } |
| 413 | UnqualifiedIdentifier::Constructor => { |
| 414 | record.expect("constructor must be associated with a record").to_string() |
| 415 | } |
| 416 | }; |
| 417 | |
| 418 | if let Some(record_name) = record { |
| 419 | format!("{}::{}", record_name, func_name).into() |
| 420 | } else { |
| 421 | func_name.into() |
| 422 | } |
| 423 | } |
| 424 | fn source_loc(&self) -> Option<Rc<str>> { |
| 425 | Some(self.source_loc.clone()) |
| 426 | } |
| 427 | } |
| 428 | |
Lukasz Anforowicz | 231a3bb | 2022-01-12 14:05:59 +0000 | [diff] [blame] | 429 | impl Func { |
| 430 | pub fn is_instance_method(&self) -> bool { |
| 431 | self.member_func_metadata |
| 432 | .as_ref() |
| 433 | .filter(|meta| meta.instance_method_metadata.is_some()) |
| 434 | .is_some() |
| 435 | } |
| 436 | } |
| 437 | |
Googler | 2294c70 | 2021-09-17 07:32:07 +0000 | [diff] [blame] | 438 | #[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, Deserialize)] |
| 439 | pub enum AccessSpecifier { |
| 440 | Public, |
| 441 | Protected, |
| 442 | Private, |
| 443 | } |
| 444 | |
Marcel Hlopko | 42abfc8 | 2021-08-09 07:03:17 +0000 | [diff] [blame] | 445 | #[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize)] |
Devin Jeanpierre | f238403 | 2023-03-10 14:26:27 -0800 | [diff] [blame] | 446 | #[serde(deny_unknown_fields)] |
Marcel Hlopko | b4b2874 | 2021-09-15 12:45:20 +0000 | [diff] [blame] | 447 | pub struct Field { |
Michael Forster | 7a00491 | 2022-05-12 07:45:57 -0700 | [diff] [blame] | 448 | pub identifier: Option<Identifier>, |
Googler | 841386c | 2022-11-29 07:42:32 -0800 | [diff] [blame] | 449 | pub doc_comment: Option<Rc<str>>, |
Marcel Hlopko | b4b2874 | 2021-09-15 12:45:20 +0000 | [diff] [blame] | 450 | #[serde(rename(deserialize = "type"))] |
Lukasz Anforowicz | fea0db9 | 2022-05-17 17:28:04 -0700 | [diff] [blame] | 451 | pub type_: Result<MappedType, String>, |
Googler | 2294c70 | 2021-09-17 07:32:07 +0000 | [diff] [blame] | 452 | pub access: AccessSpecifier, |
Googler | 5ea8864 | 2021-09-29 08:05:59 +0000 | [diff] [blame] | 453 | pub offset: usize, |
Lukasz Anforowicz | 5765bb8 | 2022-05-17 17:21:06 -0700 | [diff] [blame] | 454 | pub size: usize, |
Devin Jeanpierre | b69bcae | 2022-02-03 09:45:50 +0000 | [diff] [blame] | 455 | pub is_no_unique_address: bool, |
Michael Forster | 82c02d3 | 2022-05-20 21:47:33 -0700 | [diff] [blame] | 456 | pub is_bitfield: bool, |
Kinuko Yasuda | 6ff59f1 | 2022-08-11 08:41:45 -0700 | [diff] [blame] | 457 | // TODO(kinuko): Consider removing this, it is a duplicate of the same information |
| 458 | // in `Record`. |
| 459 | pub is_inheritable: bool, |
Marcel Hlopko | b4b2874 | 2021-09-15 12:45:20 +0000 | [diff] [blame] | 460 | } |
| 461 | |
| 462 | #[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize)] |
Lukasz Anforowicz | ff7df4a | 2022-06-02 14:27:45 -0700 | [diff] [blame] | 463 | pub enum SpecialMemberFunc { |
Devin Jeanpierre | 8fc6b43 | 2021-10-05 11:41:53 +0000 | [diff] [blame] | 464 | Trivial, |
Devin Jeanpierre | be2f33b | 2021-10-21 12:54:19 +0000 | [diff] [blame] | 465 | NontrivialMembers, |
Devin Jeanpierre | 7b62e95 | 2021-12-08 21:43:30 +0000 | [diff] [blame] | 466 | NontrivialUserDefined, |
Lukasz Anforowicz | ff7df4a | 2022-06-02 14:27:45 -0700 | [diff] [blame] | 467 | Unavailable, |
Devin Jeanpierre | 8fc6b43 | 2021-10-05 11:41:53 +0000 | [diff] [blame] | 468 | } |
| 469 | |
| 470 | #[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize)] |
Devin Jeanpierre | f238403 | 2023-03-10 14:26:27 -0800 | [diff] [blame] | 471 | #[serde(deny_unknown_fields)] |
Devin Jeanpierre | 5677702 | 2022-02-03 01:57:15 +0000 | [diff] [blame] | 472 | pub struct BaseClass { |
Rosica Dejanovska | d638cf5 | 2022-03-23 15:45:01 +0000 | [diff] [blame] | 473 | pub base_record_id: ItemId, |
Devin Jeanpierre | 5677702 | 2022-02-03 01:57:15 +0000 | [diff] [blame] | 474 | pub offset: Option<i64>, |
| 475 | } |
| 476 | |
| 477 | #[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize)] |
Devin Jeanpierre | f238403 | 2023-03-10 14:26:27 -0800 | [diff] [blame] | 478 | #[serde(deny_unknown_fields)] |
Devin Jeanpierre | c0543eb | 2022-04-20 16:00:34 -0700 | [diff] [blame] | 479 | pub struct IncompleteRecord { |
Googler | c2102ee | 2022-11-29 07:18:24 -0800 | [diff] [blame] | 480 | pub cc_name: Rc<str>, |
| 481 | pub rs_name: Rc<str>, |
Devin Jeanpierre | c0543eb | 2022-04-20 16:00:34 -0700 | [diff] [blame] | 482 | pub id: ItemId, |
| 483 | pub owning_target: BazelLabel, |
Lukasz Anforowicz | 8dd5179 | 2022-08-31 10:11:17 -0700 | [diff] [blame] | 484 | pub record_type: RecordType, |
Rosica Dejanovska | e91d299 | 2022-05-05 05:31:39 -0700 | [diff] [blame] | 485 | pub enclosing_namespace_id: Option<ItemId>, |
Devin Jeanpierre | c0543eb | 2022-04-20 16:00:34 -0700 | [diff] [blame] | 486 | } |
| 487 | |
Devin Jeanpierre | ab8732a | 2023-03-22 19:09:03 -0700 | [diff] [blame] | 488 | impl GenericItem for IncompleteRecord { |
| 489 | fn id(&self) -> ItemId { |
| 490 | self.id |
| 491 | } |
| 492 | fn debug_name(&self, _: &IR) -> Rc<str> { |
| 493 | self.cc_name.clone() |
| 494 | } |
| 495 | fn source_loc(&self) -> Option<Rc<str>> { |
| 496 | None |
| 497 | } |
| 498 | } |
| 499 | |
Lukasz Anforowicz | d4742ff | 2022-07-11 17:05:02 -0700 | [diff] [blame] | 500 | #[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, Deserialize)] |
| 501 | pub enum RecordType { |
| 502 | Struct, |
| 503 | Union, |
| 504 | Class, |
| 505 | } |
| 506 | |
Lukasz Anforowicz | 8dd5179 | 2022-08-31 10:11:17 -0700 | [diff] [blame] | 507 | impl ToTokens for RecordType { |
| 508 | fn to_tokens(&self, tokens: &mut TokenStream) { |
| 509 | let tag = match self { |
| 510 | RecordType::Struct => quote! { struct }, |
| 511 | RecordType::Union => quote! { union }, |
| 512 | RecordType::Class => quote! { class }, |
| 513 | }; |
| 514 | tag.to_tokens(tokens) |
| 515 | } |
| 516 | } |
| 517 | |
Devin Jeanpierre | c0543eb | 2022-04-20 16:00:34 -0700 | [diff] [blame] | 518 | #[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize)] |
Devin Jeanpierre | f238403 | 2023-03-10 14:26:27 -0800 | [diff] [blame] | 519 | #[serde(deny_unknown_fields)] |
Devin Jeanpierre | 1e2d324 | 2023-05-15 12:21:59 -0700 | [diff] [blame] | 520 | pub struct SizeAlign { |
| 521 | pub size: usize, |
| 522 | pub alignment: usize, |
| 523 | } |
| 524 | |
| 525 | #[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize)] |
| 526 | #[serde(deny_unknown_fields)] |
Marcel Hlopko | b4b2874 | 2021-09-15 12:45:20 +0000 | [diff] [blame] | 527 | pub struct Record { |
Googler | c2102ee | 2022-11-29 07:18:24 -0800 | [diff] [blame] | 528 | pub rs_name: Rc<str>, |
| 529 | pub cc_name: Rc<str>, |
| 530 | pub mangled_cc_name: Rc<str>, |
Rosica Dejanovska | d638cf5 | 2022-03-23 15:45:01 +0000 | [diff] [blame] | 531 | pub id: ItemId, |
Googler | 6c3de12 | 2022-03-28 11:40:41 +0000 | [diff] [blame] | 532 | pub owning_target: BazelLabel, |
Devin Jeanpierre | 3f0d068 | 2023-04-13 14:47:28 -0700 | [diff] [blame] | 533 | /// The target containing the template definition, if this is a templated |
| 534 | /// record type. |
| 535 | pub defining_target: Option<BazelLabel>, |
Googler | 841386c | 2022-11-29 07:42:32 -0800 | [diff] [blame] | 536 | pub doc_comment: Option<Rc<str>>, |
Googler | afd18fb | 2023-01-25 12:55:07 -0800 | [diff] [blame] | 537 | pub source_loc: Rc<str>, |
Devin Jeanpierre | 5677702 | 2022-02-03 01:57:15 +0000 | [diff] [blame] | 538 | pub unambiguous_public_bases: Vec<BaseClass>, |
Marcel Hlopko | b4b2874 | 2021-09-15 12:45:20 +0000 | [diff] [blame] | 539 | pub fields: Vec<Field>, |
Marcel Hlopko | af682a0 | 2022-04-08 07:27:14 -0700 | [diff] [blame] | 540 | pub lifetime_params: Vec<LifetimeName>, |
Devin Jeanpierre | 1e2d324 | 2023-05-15 12:21:59 -0700 | [diff] [blame] | 541 | pub size_align: SizeAlign, |
Devin Jeanpierre | 1221c2a | 2022-05-05 22:36:22 -0700 | [diff] [blame] | 542 | pub is_derived_class: bool, |
Devin Jeanpierre | c80e624 | 2022-02-03 01:56:40 +0000 | [diff] [blame] | 543 | pub override_alignment: bool, |
Devin Jeanpierre | 8fc6b43 | 2021-10-05 11:41:53 +0000 | [diff] [blame] | 544 | pub copy_constructor: SpecialMemberFunc, |
| 545 | pub move_constructor: SpecialMemberFunc, |
| 546 | pub destructor: SpecialMemberFunc, |
Devin Jeanpierre | b2cd021 | 2021-10-01 07:16:23 +0000 | [diff] [blame] | 547 | pub is_trivial_abi: bool, |
Teddy Katz | d2cd142 | 2022-04-04 09:41:33 -0700 | [diff] [blame] | 548 | pub is_inheritable: bool, |
Devin Jeanpierre | ccb6767 | 2022-08-17 10:05:47 -0700 | [diff] [blame] | 549 | pub is_abstract: bool, |
Lukasz Anforowicz | d4742ff | 2022-07-11 17:05:02 -0700 | [diff] [blame] | 550 | pub record_type: RecordType, |
Devin Jeanpierre | a2be2a2 | 2022-05-18 18:59:05 -0700 | [diff] [blame] | 551 | pub is_aggregate: bool, |
Kinuko Yasuda | 8dd8464 | 2022-08-17 09:19:47 -0700 | [diff] [blame] | 552 | pub is_anon_record_with_typedef: bool, |
Rosica Dejanovska | b2bd59e | 2022-04-11 09:02:03 -0700 | [diff] [blame] | 553 | pub child_item_ids: Vec<ItemId>, |
Rosica Dejanovska | e91d299 | 2022-05-05 05:31:39 -0700 | [diff] [blame] | 554 | pub enclosing_namespace_id: Option<ItemId>, |
Marcel Hlopko | b4b2874 | 2021-09-15 12:45:20 +0000 | [diff] [blame] | 555 | } |
| 556 | |
Devin Jeanpierre | ab8732a | 2023-03-22 19:09:03 -0700 | [diff] [blame] | 557 | impl GenericItem for Record { |
| 558 | fn id(&self) -> ItemId { |
| 559 | self.id |
| 560 | } |
| 561 | fn debug_name(&self, _: &IR) -> Rc<str> { |
| 562 | self.cc_name.clone() |
| 563 | } |
| 564 | fn source_loc(&self) -> Option<Rc<str>> { |
| 565 | Some(self.source_loc.clone()) |
| 566 | } |
| 567 | } |
| 568 | |
Marcel Hlopko | a0f3866 | 2021-12-03 08:45:26 +0000 | [diff] [blame] | 569 | impl Record { |
Devin Jeanpierre | e6e1665 | 2021-12-22 15:54:46 +0000 | [diff] [blame] | 570 | /// Whether this type has Rust-like object semantics for mutating |
| 571 | /// assignment, and can be passed by mut reference as a result. |
| 572 | /// |
| 573 | /// If a type `T` is mut reference safe, it can be possed as a `&mut T` |
| 574 | /// safely. Otherwise, mutable references must use `Pin<&mut T>`. |
| 575 | /// |
| 576 | /// Conditions: |
| 577 | /// |
| 578 | /// 1. It is trivially relocatable, and thus can be passed by value and have |
| 579 | /// its memory directly mutated by Rust using memcpy-like |
| 580 | /// assignment/swap. |
| 581 | /// |
| 582 | /// 2. It cannot overlap with any other objects. In particular, it cannot be |
| 583 | /// inherited from, as inheritance allows for the tail padding to be |
| 584 | /// reused by other objects. |
| 585 | /// |
| 586 | /// (In future versions, we could also include types which are POD for |
| 587 | /// the purpose of layout, but this is less predictable to C++ users, |
| 588 | /// and ABI-specific.) |
| 589 | /// |
| 590 | /// We are assuming, for the moment, that no object is stored in a |
| 591 | /// `[[no_unique_address]]` variable. Much like packed structs and |
| 592 | /// the like, users of `[[no_unique_address]]` must be very careful |
| 593 | /// when passing mutable references to Rust. |
| 594 | /// |
| 595 | /// Described in more detail at: docs/unpin |
Devin Jeanpierre | e6e1665 | 2021-12-22 15:54:46 +0000 | [diff] [blame] | 596 | pub fn is_unpin(&self) -> bool { |
Kinuko Yasuda | 6ff59f1 | 2022-08-11 08:41:45 -0700 | [diff] [blame] | 597 | self.is_trivial_abi && !self.is_inheritable && self.fields.iter().all(|f| !f.is_inheritable) |
Devin Jeanpierre | e6e1665 | 2021-12-22 15:54:46 +0000 | [diff] [blame] | 598 | } |
Lukasz Anforowicz | d4742ff | 2022-07-11 17:05:02 -0700 | [diff] [blame] | 599 | |
| 600 | pub fn is_union(&self) -> bool { |
| 601 | match self.record_type { |
| 602 | RecordType::Union => true, |
| 603 | RecordType::Struct | RecordType::Class => false, |
| 604 | } |
| 605 | } |
Marcel Hlopko | a0f3866 | 2021-12-03 08:45:26 +0000 | [diff] [blame] | 606 | } |
| 607 | |
Michael Forster | 7ef8073 | 2021-10-01 18:12:19 +0000 | [diff] [blame] | 608 | #[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize)] |
Devin Jeanpierre | f238403 | 2023-03-10 14:26:27 -0800 | [diff] [blame] | 609 | #[serde(deny_unknown_fields)] |
Teddy Katz | 76fa42b | 2022-02-23 01:22:56 +0000 | [diff] [blame] | 610 | pub struct Enum { |
| 611 | pub identifier: Identifier, |
Rosica Dejanovska | d638cf5 | 2022-03-23 15:45:01 +0000 | [diff] [blame] | 612 | pub id: ItemId, |
Googler | 6c3de12 | 2022-03-28 11:40:41 +0000 | [diff] [blame] | 613 | pub owning_target: BazelLabel, |
Googler | afd18fb | 2023-01-25 12:55:07 -0800 | [diff] [blame] | 614 | pub source_loc: Rc<str>, |
Teddy Katz | 76fa42b | 2022-02-23 01:22:56 +0000 | [diff] [blame] | 615 | pub underlying_type: MappedType, |
| 616 | pub enumerators: Vec<Enumerator>, |
Rosica Dejanovska | e91d299 | 2022-05-05 05:31:39 -0700 | [diff] [blame] | 617 | pub enclosing_namespace_id: Option<ItemId>, |
Teddy Katz | 76fa42b | 2022-02-23 01:22:56 +0000 | [diff] [blame] | 618 | } |
| 619 | |
Devin Jeanpierre | ab8732a | 2023-03-22 19:09:03 -0700 | [diff] [blame] | 620 | impl GenericItem for Enum { |
| 621 | fn id(&self) -> ItemId { |
| 622 | self.id |
| 623 | } |
| 624 | fn debug_name(&self, _: &IR) -> Rc<str> { |
Devin Jeanpierre | 861697a | 2023-04-13 14:35:27 -0700 | [diff] [blame] | 625 | self.identifier.identifier.clone() |
Devin Jeanpierre | ab8732a | 2023-03-22 19:09:03 -0700 | [diff] [blame] | 626 | } |
| 627 | fn source_loc(&self) -> Option<Rc<str>> { |
| 628 | Some(self.source_loc.clone()) |
| 629 | } |
| 630 | } |
| 631 | |
Teddy Katz | 76fa42b | 2022-02-23 01:22:56 +0000 | [diff] [blame] | 632 | #[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize)] |
Devin Jeanpierre | f238403 | 2023-03-10 14:26:27 -0800 | [diff] [blame] | 633 | #[serde(deny_unknown_fields)] |
Teddy Katz | 76fa42b | 2022-02-23 01:22:56 +0000 | [diff] [blame] | 634 | pub struct Enumerator { |
| 635 | pub identifier: Identifier, |
| 636 | pub value: IntegerConstant, |
| 637 | } |
| 638 | |
| 639 | #[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize)] |
Devin Jeanpierre | f238403 | 2023-03-10 14:26:27 -0800 | [diff] [blame] | 640 | #[serde(deny_unknown_fields)] |
Googler | 098c458 | 2022-01-10 12:29:34 +0000 | [diff] [blame] | 641 | pub struct TypeAlias { |
| 642 | pub identifier: Identifier, |
Rosica Dejanovska | d638cf5 | 2022-03-23 15:45:01 +0000 | [diff] [blame] | 643 | pub id: ItemId, |
Googler | 6c3de12 | 2022-03-28 11:40:41 +0000 | [diff] [blame] | 644 | pub owning_target: BazelLabel, |
Googler | 841386c | 2022-11-29 07:42:32 -0800 | [diff] [blame] | 645 | pub doc_comment: Option<Rc<str>>, |
Googler | 098c458 | 2022-01-10 12:29:34 +0000 | [diff] [blame] | 646 | pub underlying_type: MappedType, |
Googler | 442733c | 2023-01-23 01:05:35 -0800 | [diff] [blame] | 647 | pub source_loc: Rc<str>, |
Devin Jeanpierre | 5fecde5 | 2022-09-14 06:53:39 -0700 | [diff] [blame] | 648 | pub enclosing_record_id: Option<ItemId>, |
Rosica Dejanovska | e91d299 | 2022-05-05 05:31:39 -0700 | [diff] [blame] | 649 | pub enclosing_namespace_id: Option<ItemId>, |
Googler | 098c458 | 2022-01-10 12:29:34 +0000 | [diff] [blame] | 650 | } |
| 651 | |
Devin Jeanpierre | ab8732a | 2023-03-22 19:09:03 -0700 | [diff] [blame] | 652 | impl GenericItem for TypeAlias { |
| 653 | fn id(&self) -> ItemId { |
| 654 | self.id |
| 655 | } |
| 656 | fn debug_name(&self, _: &IR) -> Rc<str> { |
Devin Jeanpierre | 861697a | 2023-04-13 14:35:27 -0700 | [diff] [blame] | 657 | self.identifier.identifier.clone() |
Devin Jeanpierre | ab8732a | 2023-03-22 19:09:03 -0700 | [diff] [blame] | 658 | } |
| 659 | fn source_loc(&self) -> Option<Rc<str>> { |
| 660 | Some(self.source_loc.clone()) |
| 661 | } |
| 662 | } |
| 663 | |
Michael VanBemmel | f5cbdf4 | 2022-10-14 17:00:11 -0700 | [diff] [blame] | 664 | /// A wrapper type that does not contribute to equality or hashing. All |
| 665 | /// instances are equal. |
| 666 | #[derive(Clone, Copy, Default)] |
| 667 | struct IgnoredField<T>(T); |
| 668 | |
| 669 | impl<T> Debug for IgnoredField<T> { |
| 670 | fn fmt(&self, f: &mut Formatter) -> fmt::Result { |
| 671 | write!(f, "_") |
| 672 | } |
| 673 | } |
| 674 | |
| 675 | impl<T> PartialEq for IgnoredField<T> { |
| 676 | fn eq(&self, _other: &Self) -> bool { |
| 677 | true |
| 678 | } |
| 679 | } |
| 680 | |
| 681 | impl<T> Eq for IgnoredField<T> {} |
| 682 | |
| 683 | impl<T> Hash for IgnoredField<T> { |
| 684 | fn hash<H: Hasher>(&self, _state: &mut H) {} |
| 685 | } |
| 686 | |
Michael Forster | 6a184ad | 2021-10-12 13:04:05 +0000 | [diff] [blame] | 687 | #[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize)] |
Devin Jeanpierre | f238403 | 2023-03-10 14:26:27 -0800 | [diff] [blame] | 688 | #[serde(deny_unknown_fields)] |
Michael Forster | 523dbd4 | 2021-10-12 11:05:44 +0000 | [diff] [blame] | 689 | pub struct UnsupportedItem { |
Googler | c2102ee | 2022-11-29 07:18:24 -0800 | [diff] [blame] | 690 | pub name: Rc<str>, |
| 691 | message: Rc<str>, |
Devin Jeanpierre | ab8732a | 2023-03-22 19:09:03 -0700 | [diff] [blame] | 692 | pub source_loc: Option<Rc<str>>, |
Rosica Dejanovska | d638cf5 | 2022-03-23 15:45:01 +0000 | [diff] [blame] | 693 | pub id: ItemId, |
Michael VanBemmel | f5cbdf4 | 2022-10-14 17:00:11 -0700 | [diff] [blame] | 694 | #[serde(skip)] |
| 695 | cause: IgnoredField<OnceCell<Error>>, |
| 696 | } |
| 697 | |
Devin Jeanpierre | ab8732a | 2023-03-22 19:09:03 -0700 | [diff] [blame] | 698 | impl GenericItem for UnsupportedItem { |
| 699 | fn id(&self) -> ItemId { |
| 700 | self.id |
| 701 | } |
| 702 | fn debug_name(&self, _: &IR) -> Rc<str> { |
| 703 | self.name.clone() |
| 704 | } |
| 705 | fn source_loc(&self) -> Option<Rc<str>> { |
| 706 | self.source_loc.clone() |
| 707 | } |
| 708 | } |
| 709 | |
Michael VanBemmel | f5cbdf4 | 2022-10-14 17:00:11 -0700 | [diff] [blame] | 710 | impl UnsupportedItem { |
Devin Jeanpierre | ab8732a | 2023-03-22 19:09:03 -0700 | [diff] [blame] | 711 | fn new(ir: &IR, item: &impl GenericItem, message: Rc<str>, cause: Option<Error>) -> Self { |
Googler | c2102ee | 2022-11-29 07:18:24 -0800 | [diff] [blame] | 712 | Self { |
Devin Jeanpierre | ab8732a | 2023-03-22 19:09:03 -0700 | [diff] [blame] | 713 | name: item.debug_name(ir), |
| 714 | message, |
| 715 | source_loc: item.source_loc(), |
| 716 | id: item.id(), |
| 717 | cause: IgnoredField(cause.map(OnceCell::from).unwrap_or_default()), |
Googler | c2102ee | 2022-11-29 07:18:24 -0800 | [diff] [blame] | 718 | } |
Michael VanBemmel | f5cbdf4 | 2022-10-14 17:00:11 -0700 | [diff] [blame] | 719 | } |
Devin Jeanpierre | ab8732a | 2023-03-22 19:09:03 -0700 | [diff] [blame] | 720 | |
| 721 | pub fn new_with_message(ir: &IR, item: &impl GenericItem, message: impl Into<Rc<str>>) -> Self { |
| 722 | Self::new(ir, item, message.into(), None) |
Michael VanBemmel | f5cbdf4 | 2022-10-14 17:00:11 -0700 | [diff] [blame] | 723 | } |
Devin Jeanpierre | ab8732a | 2023-03-22 19:09:03 -0700 | [diff] [blame] | 724 | pub fn new_with_cause(ir: &IR, item: &impl GenericItem, cause: Error) -> Self { |
Devin Jeanpierre | 851a641 | 2023-04-13 14:38:14 -0700 | [diff] [blame] | 725 | Self::new(ir, item, format!("{cause:#}").into(), Some(cause)) |
Devin Jeanpierre | ab8732a | 2023-03-22 19:09:03 -0700 | [diff] [blame] | 726 | } |
| 727 | |
Michael VanBemmel | f5cbdf4 | 2022-10-14 17:00:11 -0700 | [diff] [blame] | 728 | pub fn message(&self) -> &str { |
Googler | c2102ee | 2022-11-29 07:18:24 -0800 | [diff] [blame] | 729 | self.message.as_ref() |
Michael VanBemmel | f5cbdf4 | 2022-10-14 17:00:11 -0700 | [diff] [blame] | 730 | } |
| 731 | |
| 732 | pub fn cause(&self) -> &Error { |
Googler | c2102ee | 2022-11-29 07:18:24 -0800 | [diff] [blame] | 733 | self.cause.0.get_or_init(|| anyhow!(self.message.as_ref().to_owned())) |
Michael VanBemmel | f5cbdf4 | 2022-10-14 17:00:11 -0700 | [diff] [blame] | 734 | } |
Michael Forster | 523dbd4 | 2021-10-12 11:05:44 +0000 | [diff] [blame] | 735 | } |
| 736 | |
| 737 | #[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize)] |
Devin Jeanpierre | f238403 | 2023-03-10 14:26:27 -0800 | [diff] [blame] | 738 | #[serde(deny_unknown_fields)] |
Michael Forster | f1dce42 | 2021-10-13 09:50:16 +0000 | [diff] [blame] | 739 | pub struct Comment { |
Googler | c2102ee | 2022-11-29 07:18:24 -0800 | [diff] [blame] | 740 | pub text: Rc<str>, |
Rosica Dejanovska | d638cf5 | 2022-03-23 15:45:01 +0000 | [diff] [blame] | 741 | pub id: ItemId, |
Michael Forster | f1dce42 | 2021-10-13 09:50:16 +0000 | [diff] [blame] | 742 | } |
| 743 | |
Devin Jeanpierre | ab8732a | 2023-03-22 19:09:03 -0700 | [diff] [blame] | 744 | impl GenericItem for Comment { |
| 745 | fn id(&self) -> ItemId { |
| 746 | self.id |
| 747 | } |
| 748 | fn debug_name(&self, _: &IR) -> Rc<str> { |
| 749 | "comment".into() |
| 750 | } |
| 751 | fn source_loc(&self) -> Option<Rc<str>> { |
| 752 | None |
| 753 | } |
| 754 | } |
| 755 | |
Michael Forster | f1dce42 | 2021-10-13 09:50:16 +0000 | [diff] [blame] | 756 | #[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize)] |
Devin Jeanpierre | f238403 | 2023-03-10 14:26:27 -0800 | [diff] [blame] | 757 | #[serde(deny_unknown_fields)] |
Rosica Dejanovska | dd9a903 | 2022-04-12 07:34:41 -0700 | [diff] [blame] | 758 | pub struct Namespace { |
| 759 | pub name: Identifier, |
| 760 | pub id: ItemId, |
Rosica Dejanovska | 6efd17f | 2022-05-11 08:09:57 -0700 | [diff] [blame] | 761 | pub canonical_namespace_id: ItemId, |
Rosica Dejanovska | 36aefad | 2022-05-12 03:53:14 -0700 | [diff] [blame] | 762 | pub owning_target: BazelLabel, |
Rosica Dejanovska | dd9a903 | 2022-04-12 07:34:41 -0700 | [diff] [blame] | 763 | #[serde(default)] |
| 764 | pub child_item_ids: Vec<ItemId>, |
Rosica Dejanovska | e91d299 | 2022-05-05 05:31:39 -0700 | [diff] [blame] | 765 | pub enclosing_namespace_id: Option<ItemId>, |
Devin Jeanpierre | fe6aaea | 2022-09-09 12:33:50 -0700 | [diff] [blame] | 766 | pub is_inline: bool, |
Rosica Dejanovska | dd9a903 | 2022-04-12 07:34:41 -0700 | [diff] [blame] | 767 | } |
| 768 | |
Devin Jeanpierre | ab8732a | 2023-03-22 19:09:03 -0700 | [diff] [blame] | 769 | impl GenericItem for Namespace { |
| 770 | fn id(&self) -> ItemId { |
| 771 | self.id |
| 772 | } |
| 773 | fn debug_name(&self, _: &IR) -> Rc<str> { |
| 774 | self.name.to_string().into() |
| 775 | } |
| 776 | fn source_loc(&self) -> Option<Rc<str>> { |
| 777 | None |
| 778 | } |
| 779 | } |
| 780 | |
Rosica Dejanovska | dd9a903 | 2022-04-12 07:34:41 -0700 | [diff] [blame] | 781 | #[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize)] |
Devin Jeanpierre | f238403 | 2023-03-10 14:26:27 -0800 | [diff] [blame] | 782 | #[serde(deny_unknown_fields)] |
Devin Jeanpierre | 96bf0bd | 2022-10-04 20:32:15 -0700 | [diff] [blame] | 783 | pub struct UseMod { |
| 784 | pub path: Rc<str>, |
| 785 | pub mod_name: Identifier, |
| 786 | pub id: ItemId, |
| 787 | } |
| 788 | |
Devin Jeanpierre | ab8732a | 2023-03-22 19:09:03 -0700 | [diff] [blame] | 789 | impl GenericItem for UseMod { |
| 790 | fn id(&self) -> ItemId { |
| 791 | self.id |
| 792 | } |
| 793 | fn debug_name(&self, _: &IR) -> Rc<str> { |
| 794 | format!("[internal] use mod {}::* = {}", self.mod_name, self.path).into() |
| 795 | } |
| 796 | fn source_loc(&self) -> Option<Rc<str>> { |
| 797 | None |
| 798 | } |
| 799 | } |
| 800 | |
Devin Jeanpierre | 96bf0bd | 2022-10-04 20:32:15 -0700 | [diff] [blame] | 801 | #[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize)] |
Devin Jeanpierre | 93e800e | 2023-05-08 12:55:53 -0700 | [diff] [blame] | 802 | #[serde(deny_unknown_fields)] |
| 803 | pub struct TypeMapOverride { |
Devin Jeanpierre | b7f8e28 | 2023-05-26 16:03:12 -0700 | [diff] [blame] | 804 | pub rs_name: Rc<str>, |
| 805 | pub cc_name: Rc<str>, |
Devin Jeanpierre | 93e800e | 2023-05-08 12:55:53 -0700 | [diff] [blame] | 806 | pub owning_target: BazelLabel, |
Devin Jeanpierre | 1e2d324 | 2023-05-15 12:21:59 -0700 | [diff] [blame] | 807 | pub size_align: Option<SizeAlign>, |
Devin Jeanpierre | c850c77 | 2023-05-30 17:14:19 -0700 | [diff] [blame] | 808 | pub is_same_abi: bool, |
Devin Jeanpierre | 93e800e | 2023-05-08 12:55:53 -0700 | [diff] [blame] | 809 | pub id: ItemId, |
| 810 | } |
| 811 | |
| 812 | impl GenericItem for TypeMapOverride { |
| 813 | fn id(&self) -> ItemId { |
| 814 | self.id |
| 815 | } |
| 816 | fn debug_name(&self, _: &IR) -> Rc<str> { |
Devin Jeanpierre | b7f8e28 | 2023-05-26 16:03:12 -0700 | [diff] [blame] | 817 | self.cc_name.clone() |
Devin Jeanpierre | 93e800e | 2023-05-08 12:55:53 -0700 | [diff] [blame] | 818 | } |
| 819 | fn source_loc(&self) -> Option<Rc<str>> { |
| 820 | None |
| 821 | } |
| 822 | } |
| 823 | |
| 824 | #[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize)] |
Michael Forster | 7ef8073 | 2021-10-01 18:12:19 +0000 | [diff] [blame] | 825 | pub enum Item { |
Devin Jeanpierre | 8cd8ae7 | 2022-06-29 18:59:40 -0700 | [diff] [blame] | 826 | Func(Rc<Func>), |
| 827 | IncompleteRecord(Rc<IncompleteRecord>), |
| 828 | Record(Rc<Record>), |
| 829 | Enum(Rc<Enum>), |
| 830 | TypeAlias(Rc<TypeAlias>), |
| 831 | UnsupportedItem(Rc<UnsupportedItem>), |
| 832 | Comment(Rc<Comment>), |
| 833 | Namespace(Rc<Namespace>), |
Devin Jeanpierre | 96bf0bd | 2022-10-04 20:32:15 -0700 | [diff] [blame] | 834 | UseMod(Rc<UseMod>), |
Devin Jeanpierre | 93e800e | 2023-05-08 12:55:53 -0700 | [diff] [blame] | 835 | TypeMapOverride(Rc<TypeMapOverride>), |
Michael Forster | 7ef8073 | 2021-10-01 18:12:19 +0000 | [diff] [blame] | 836 | } |
| 837 | |
Devin Jeanpierre | ab8732a | 2023-03-22 19:09:03 -0700 | [diff] [blame] | 838 | macro_rules! forward_item { |
| 839 | (match $item:ident { _($item_name:ident) => $expr:expr $(,)? }) => { |
| 840 | match $item { |
Devin Jeanpierre | 93e800e | 2023-05-08 12:55:53 -0700 | [diff] [blame] | 841 | Item::Func($item_name) => $expr, |
| 842 | Item::IncompleteRecord($item_name) => $expr, |
| 843 | Item::Record($item_name) => $expr, |
| 844 | Item::Enum($item_name) => $expr, |
| 845 | Item::TypeAlias($item_name) => $expr, |
| 846 | Item::UnsupportedItem($item_name) => $expr, |
| 847 | Item::Comment($item_name) => $expr, |
| 848 | Item::Namespace($item_name) => $expr, |
| 849 | Item::UseMod($item_name) => $expr, |
| 850 | Item::TypeMapOverride($item_name) => $expr, |
| 851 | } |
Devin Jeanpierre | ab8732a | 2023-03-22 19:09:03 -0700 | [diff] [blame] | 852 | }; |
| 853 | } |
| 854 | |
| 855 | impl GenericItem for Item { |
Rosica Dejanovska | 10accf1 | 2022-03-31 04:47:58 -0700 | [diff] [blame] | 856 | fn id(&self) -> ItemId { |
Devin Jeanpierre | ab8732a | 2023-03-22 19:09:03 -0700 | [diff] [blame] | 857 | forward_item! { |
| 858 | match self { |
| 859 | _(x) => x.id() |
| 860 | } |
Marcel Hlopko | 3b9bf9e | 2021-11-29 08:25:14 +0000 | [diff] [blame] | 861 | } |
| 862 | } |
Devin Jeanpierre | ab8732a | 2023-03-22 19:09:03 -0700 | [diff] [blame] | 863 | fn debug_name(&self, ir: &IR) -> Rc<str> { |
| 864 | forward_item! { |
| 865 | match self { |
| 866 | _(x) => x.debug_name(ir) |
| 867 | } |
| 868 | } |
| 869 | } |
| 870 | fn source_loc(&self) -> Option<Rc<str>> { |
| 871 | forward_item! { |
| 872 | match self { |
| 873 | _(x) => x.source_loc() |
| 874 | } |
| 875 | } |
| 876 | } |
| 877 | } |
| 878 | |
| 879 | impl Item { |
Rosica Dejanovska | e91d299 | 2022-05-05 05:31:39 -0700 | [diff] [blame] | 880 | pub fn enclosing_namespace_id(&self) -> Option<ItemId> { |
| 881 | match self { |
| 882 | Item::Record(record) => record.enclosing_namespace_id, |
| 883 | Item::IncompleteRecord(record) => record.enclosing_namespace_id, |
| 884 | Item::Enum(enum_) => enum_.enclosing_namespace_id, |
| 885 | Item::Func(func) => func.enclosing_namespace_id, |
| 886 | Item::Namespace(namespace) => namespace.enclosing_namespace_id, |
| 887 | Item::TypeAlias(type_alias) => type_alias.enclosing_namespace_id, |
Devin Jeanpierre | ec88b69 | 2023-02-14 07:03:08 -0800 | [diff] [blame] | 888 | Item::Comment(..) => None, |
| 889 | Item::UnsupportedItem(..) => None, |
| 890 | Item::UseMod(..) => None, |
Devin Jeanpierre | 93e800e | 2023-05-08 12:55:53 -0700 | [diff] [blame] | 891 | Item::TypeMapOverride(..) => None, |
Devin Jeanpierre | ec88b69 | 2023-02-14 07:03:08 -0800 | [diff] [blame] | 892 | } |
| 893 | } |
| 894 | |
Devin Jeanpierre | 3f0d068 | 2023-04-13 14:47:28 -0700 | [diff] [blame] | 895 | /// Returns the target that this was defined in, if it was defined somewhere |
| 896 | /// other than `owning_target()`. |
Devin Jeanpierre | dff6528 | 2023-03-14 20:32:28 -0700 | [diff] [blame] | 897 | pub fn defining_target(&self) -> Option<&BazelLabel> { |
Devin Jeanpierre | 3f0d068 | 2023-04-13 14:47:28 -0700 | [diff] [blame] | 898 | match self { |
| 899 | Item::Record(record) => record.defining_target.as_ref(), |
| 900 | _ => None, |
| 901 | } |
Devin Jeanpierre | dff6528 | 2023-03-14 20:32:28 -0700 | [diff] [blame] | 902 | } |
| 903 | |
Devin Jeanpierre | ec88b69 | 2023-02-14 07:03:08 -0800 | [diff] [blame] | 904 | /// Returns the target that this should generate source code in. |
| 905 | pub fn owning_target(&self) -> Option<&BazelLabel> { |
| 906 | match self { |
Devin Jeanpierre | 6b1d71a | 2023-03-14 17:50:38 -0700 | [diff] [blame] | 907 | Item::Func(func) => Some(&func.owning_target), |
Devin Jeanpierre | ec88b69 | 2023-02-14 07:03:08 -0800 | [diff] [blame] | 908 | Item::IncompleteRecord(record) => Some(&record.owning_target), |
| 909 | Item::Record(record) => Some(&record.owning_target), |
| 910 | Item::Enum(e) => Some(&e.owning_target), |
| 911 | Item::TypeAlias(type_alias) => Some(&type_alias.owning_target), |
| 912 | Item::UnsupportedItem(..) => None, |
| 913 | Item::Comment(..) => None, |
| 914 | Item::Namespace(..) => None, |
| 915 | Item::UseMod(..) => None, |
Devin Jeanpierre | 93e800e | 2023-05-08 12:55:53 -0700 | [diff] [blame] | 916 | Item::TypeMapOverride(type_override) => Some(&type_override.owning_target), |
Rosica Dejanovska | e91d299 | 2022-05-05 05:31:39 -0700 | [diff] [blame] | 917 | } |
| 918 | } |
Marcel Hlopko | 3b9bf9e | 2021-11-29 08:25:14 +0000 | [diff] [blame] | 919 | } |
| 920 | |
Devin Jeanpierre | ccfefc8 | 2021-10-27 10:54:00 +0000 | [diff] [blame] | 921 | impl From<Func> for Item { |
| 922 | fn from(func: Func) -> Item { |
Devin Jeanpierre | 8cd8ae7 | 2022-06-29 18:59:40 -0700 | [diff] [blame] | 923 | Item::Func(Rc::new(func)) |
Devin Jeanpierre | ccfefc8 | 2021-10-27 10:54:00 +0000 | [diff] [blame] | 924 | } |
| 925 | } |
| 926 | |
Devin Jeanpierre | 8cd8ae7 | 2022-06-29 18:59:40 -0700 | [diff] [blame] | 927 | impl<'a> TryFrom<&'a Item> for &'a Rc<Func> { |
Michael VanBemmel | f5cbdf4 | 2022-10-14 17:00:11 -0700 | [diff] [blame] | 928 | type Error = Error; |
Devin Jeanpierre | 7eb0404 | 2021-12-03 07:19:22 +0000 | [diff] [blame] | 929 | fn try_from(value: &'a Item) -> Result<Self, Self::Error> { |
Devin Jeanpierre | 3a0cc5a | 2022-07-12 09:36:34 -0700 | [diff] [blame] | 930 | if let Item::Func(f) = value { Ok(f) } else { bail!("Not a Func: {:#?}", value) } |
Devin Jeanpierre | 7eb0404 | 2021-12-03 07:19:22 +0000 | [diff] [blame] | 931 | } |
| 932 | } |
| 933 | |
Devin Jeanpierre | ccfefc8 | 2021-10-27 10:54:00 +0000 | [diff] [blame] | 934 | impl From<Record> for Item { |
| 935 | fn from(record: Record) -> Item { |
Devin Jeanpierre | 8cd8ae7 | 2022-06-29 18:59:40 -0700 | [diff] [blame] | 936 | Item::Record(Rc::new(record)) |
Devin Jeanpierre | ccfefc8 | 2021-10-27 10:54:00 +0000 | [diff] [blame] | 937 | } |
| 938 | } |
| 939 | |
Devin Jeanpierre | 8cd8ae7 | 2022-06-29 18:59:40 -0700 | [diff] [blame] | 940 | impl<'a> TryFrom<&'a Item> for &'a Rc<Record> { |
Michael VanBemmel | f5cbdf4 | 2022-10-14 17:00:11 -0700 | [diff] [blame] | 941 | type Error = Error; |
Devin Jeanpierre | 7eb0404 | 2021-12-03 07:19:22 +0000 | [diff] [blame] | 942 | fn try_from(value: &'a Item) -> Result<Self, Self::Error> { |
Devin Jeanpierre | 7ed8c6f | 2022-08-01 13:41:02 -0700 | [diff] [blame] | 943 | if let Item::Record(r) = value { Ok(r) } else { bail!("Not a Record: {:#?}", value) } |
Devin Jeanpierre | 7eb0404 | 2021-12-03 07:19:22 +0000 | [diff] [blame] | 944 | } |
| 945 | } |
| 946 | |
Devin Jeanpierre | ccfefc8 | 2021-10-27 10:54:00 +0000 | [diff] [blame] | 947 | impl From<UnsupportedItem> for Item { |
| 948 | fn from(unsupported: UnsupportedItem) -> Item { |
Devin Jeanpierre | 8cd8ae7 | 2022-06-29 18:59:40 -0700 | [diff] [blame] | 949 | Item::UnsupportedItem(Rc::new(unsupported)) |
Devin Jeanpierre | ccfefc8 | 2021-10-27 10:54:00 +0000 | [diff] [blame] | 950 | } |
| 951 | } |
| 952 | |
Devin Jeanpierre | 8cd8ae7 | 2022-06-29 18:59:40 -0700 | [diff] [blame] | 953 | impl<'a> TryFrom<&'a Item> for &'a Rc<UnsupportedItem> { |
Michael VanBemmel | f5cbdf4 | 2022-10-14 17:00:11 -0700 | [diff] [blame] | 954 | type Error = Error; |
Devin Jeanpierre | 7eb0404 | 2021-12-03 07:19:22 +0000 | [diff] [blame] | 955 | fn try_from(value: &'a Item) -> Result<Self, Self::Error> { |
| 956 | if let Item::UnsupportedItem(u) = value { |
| 957 | Ok(u) |
| 958 | } else { |
Devin Jeanpierre | 3a0cc5a | 2022-07-12 09:36:34 -0700 | [diff] [blame] | 959 | bail!("Not an UnsupportedItem: {:#?}", value) |
Devin Jeanpierre | 7eb0404 | 2021-12-03 07:19:22 +0000 | [diff] [blame] | 960 | } |
| 961 | } |
| 962 | } |
| 963 | |
Devin Jeanpierre | ccfefc8 | 2021-10-27 10:54:00 +0000 | [diff] [blame] | 964 | impl From<Comment> for Item { |
| 965 | fn from(comment: Comment) -> Item { |
Devin Jeanpierre | 8cd8ae7 | 2022-06-29 18:59:40 -0700 | [diff] [blame] | 966 | Item::Comment(Rc::new(comment)) |
Devin Jeanpierre | ccfefc8 | 2021-10-27 10:54:00 +0000 | [diff] [blame] | 967 | } |
| 968 | } |
| 969 | |
Devin Jeanpierre | 8cd8ae7 | 2022-06-29 18:59:40 -0700 | [diff] [blame] | 970 | impl<'a> TryFrom<&'a Item> for &'a Rc<Comment> { |
Michael VanBemmel | f5cbdf4 | 2022-10-14 17:00:11 -0700 | [diff] [blame] | 971 | type Error = Error; |
Devin Jeanpierre | 7eb0404 | 2021-12-03 07:19:22 +0000 | [diff] [blame] | 972 | fn try_from(value: &'a Item) -> Result<Self, Self::Error> { |
Devin Jeanpierre | 7ed8c6f | 2022-08-01 13:41:02 -0700 | [diff] [blame] | 973 | if let Item::Comment(c) = value { Ok(c) } else { bail!("Not a Comment: {:#?}", value) } |
Devin Jeanpierre | 7eb0404 | 2021-12-03 07:19:22 +0000 | [diff] [blame] | 974 | } |
| 975 | } |
| 976 | |
Devin Jeanpierre | 6ed0f60 | 2023-03-01 17:22:54 -0800 | [diff] [blame] | 977 | flagset::flags! { |
| 978 | pub enum CrubitFeature : u8 { |
| 979 | Supported, |
| 980 | /// Experimental is never *set* without also setting Supported, but we allow it to be |
| 981 | /// *required* without also requiring Supported, so that error messages can be more direct. |
| 982 | Experimental, |
| 983 | } |
| 984 | } |
| 985 | |
| 986 | impl CrubitFeature { |
| 987 | /// The name of this feature. |
| 988 | pub fn short_name(&self) -> &'static str { |
| 989 | match self { |
| 990 | Self::Supported => "supported", |
| 991 | Self::Experimental => "experimental", |
| 992 | } |
| 993 | } |
Devin Jeanpierre | dff6528 | 2023-03-14 20:32:28 -0700 | [diff] [blame] | 994 | |
| 995 | /// The aspect hint required to enable this feature. |
| 996 | pub fn aspect_hint(&self) -> &'static str { |
| 997 | match self { |
Lukasz Anforowicz | aaa2a0f | 2023-04-11 09:01:14 -0700 | [diff] [blame] | 998 | Self::Supported => "//:supported", |
| 999 | Self::Experimental => "//:experimental", |
Devin Jeanpierre | dff6528 | 2023-03-14 20:32:28 -0700 | [diff] [blame] | 1000 | } |
| 1001 | } |
Devin Jeanpierre | 6ed0f60 | 2023-03-01 17:22:54 -0800 | [diff] [blame] | 1002 | } |
| 1003 | |
| 1004 | /// A newtype around a flagset of features, so that it can be deserialized from |
| 1005 | /// an array of strings instead of an integer. |
| 1006 | #[derive(Debug, Default, PartialEq, Eq, Clone)] |
| 1007 | struct CrubitFeaturesIR(pub(crate) flagset::FlagSet<CrubitFeature>); |
| 1008 | |
| 1009 | impl<'de> serde::Deserialize<'de> for CrubitFeaturesIR { |
| 1010 | fn deserialize<D>(deserializer: D) -> Result<CrubitFeaturesIR, D::Error> |
| 1011 | where |
| 1012 | D: serde::Deserializer<'de>, |
| 1013 | { |
| 1014 | let mut features = flagset::FlagSet::<CrubitFeature>::default(); |
| 1015 | for feature in <Vec<String> as serde::Deserialize<'de>>::deserialize(deserializer)? { |
| 1016 | features |= match &*feature { |
| 1017 | "experimental" => CrubitFeature::Experimental, |
| 1018 | "supported" => CrubitFeature::Supported, |
| 1019 | other => { |
| 1020 | return Err(<D::Error as serde::de::Error>::custom(format!( |
| 1021 | "Unexpected Crubit feature: {other}" |
| 1022 | ))); |
| 1023 | } |
| 1024 | }; |
| 1025 | } |
| 1026 | Ok(CrubitFeaturesIR(features)) |
| 1027 | } |
| 1028 | } |
| 1029 | |
Devin Jeanpierre | 319bcac | 2023-03-14 17:49:08 -0700 | [diff] [blame] | 1030 | #[derive(PartialEq, Eq, Clone, Deserialize)] |
Devin Jeanpierre | f238403 | 2023-03-10 14:26:27 -0800 | [diff] [blame] | 1031 | #[serde(deny_unknown_fields, rename(deserialize = "IR"))] |
Marcel Hlopko | 3b9bf9e | 2021-11-29 08:25:14 +0000 | [diff] [blame] | 1032 | struct FlatIR { |
| 1033 | #[serde(default)] |
Lukasz Anforowicz | 121338a | 2022-11-01 14:28:32 -0700 | [diff] [blame] | 1034 | public_headers: Vec<HeaderName>, |
Googler | 6c3de12 | 2022-03-28 11:40:41 +0000 | [diff] [blame] | 1035 | current_target: BazelLabel, |
Marcel Hlopko | 3b9bf9e | 2021-11-29 08:25:14 +0000 | [diff] [blame] | 1036 | #[serde(default)] |
| 1037 | items: Vec<Item>, |
Rosica Dejanovska | b2bd59e | 2022-04-11 09:02:03 -0700 | [diff] [blame] | 1038 | #[serde(default)] |
| 1039 | top_level_item_ids: Vec<ItemId>, |
Marcel Hlopko | b4d5d8e | 2022-11-16 03:15:00 -0800 | [diff] [blame] | 1040 | #[serde(default)] |
Googler | 841386c | 2022-11-29 07:42:32 -0800 | [diff] [blame] | 1041 | crate_root_path: Option<Rc<str>>, |
Devin Jeanpierre | 6ed0f60 | 2023-03-01 17:22:54 -0800 | [diff] [blame] | 1042 | #[serde(default)] |
| 1043 | crubit_features: HashMap<BazelLabel, CrubitFeaturesIR>, |
Marcel Hlopko | 3b9bf9e | 2021-11-29 08:25:14 +0000 | [diff] [blame] | 1044 | } |
| 1045 | |
Devin Jeanpierre | 319bcac | 2023-03-14 17:49:08 -0700 | [diff] [blame] | 1046 | /// A custom debug impl that wraps the HashMap in rustfmt-friendly notation. |
| 1047 | /// |
| 1048 | /// See b/272530008. |
Devin Jeanpierre | ab8732a | 2023-03-22 19:09:03 -0700 | [diff] [blame] | 1049 | impl Debug for FlatIR { |
| 1050 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
Devin Jeanpierre | 319bcac | 2023-03-14 17:49:08 -0700 | [diff] [blame] | 1051 | struct DebugHashMap<T: Debug>(pub T); |
Devin Jeanpierre | ab8732a | 2023-03-22 19:09:03 -0700 | [diff] [blame] | 1052 | impl<T: Debug> Debug for DebugHashMap<T> { |
| 1053 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
Devin Jeanpierre | 319bcac | 2023-03-14 17:49:08 -0700 | [diff] [blame] | 1054 | // prefix the hash map with `hash_map!` so that the output can be fed to |
| 1055 | // rustfmt. The end result is something like `hash_map!{k:v, |
| 1056 | // k2:v2}`, which reads well. |
| 1057 | write!(f, "hash_map!")?; |
Devin Jeanpierre | ab8732a | 2023-03-22 19:09:03 -0700 | [diff] [blame] | 1058 | Debug::fmt(&self.0, f) |
Devin Jeanpierre | 319bcac | 2023-03-14 17:49:08 -0700 | [diff] [blame] | 1059 | } |
| 1060 | } |
| 1061 | // exhaustive-match so we don't forget to add fields to Debug when we add to |
| 1062 | // FlatIR. |
| 1063 | let FlatIR { |
| 1064 | public_headers, |
| 1065 | current_target, |
| 1066 | items, |
| 1067 | top_level_item_ids, |
| 1068 | crate_root_path, |
| 1069 | crubit_features, |
| 1070 | } = self; |
| 1071 | f.debug_struct("FlatIR") |
| 1072 | .field("public_headers", public_headers) |
| 1073 | .field("current_target", current_target) |
| 1074 | .field("items", items) |
| 1075 | .field("top_level_item_ids", top_level_item_ids) |
| 1076 | .field("crate_root_path", crate_root_path) |
| 1077 | .field("crubit_features", &DebugHashMap(crubit_features)) |
| 1078 | .finish() |
| 1079 | } |
| 1080 | } |
| 1081 | |
Marcel Hlopko | 3b9bf9e | 2021-11-29 08:25:14 +0000 | [diff] [blame] | 1082 | /// Struct providing the necessary information about the API of a C++ target to |
| 1083 | /// enable generation of Rust bindings source code (both `rs_api.rs` and |
| 1084 | /// `rs_api_impl.cc` files). |
| 1085 | #[derive(PartialEq, Debug)] |
Marcel Hlopko | 42abfc8 | 2021-08-09 07:03:17 +0000 | [diff] [blame] | 1086 | pub struct IR { |
Marcel Hlopko | 3b9bf9e | 2021-11-29 08:25:14 +0000 | [diff] [blame] | 1087 | flat_ir: FlatIR, |
| 1088 | // A map from a `decl_id` to an index of an `Item` in the `flat_ir.items` vec. |
Rosica Dejanovska | d638cf5 | 2022-03-23 15:45:01 +0000 | [diff] [blame] | 1089 | item_id_to_item_idx: HashMap<ItemId, usize>, |
Marcel Hlopko | af682a0 | 2022-04-08 07:27:14 -0700 | [diff] [blame] | 1090 | lifetimes: HashMap<LifetimeId, LifetimeName>, |
Rosica Dejanovska | 93aeafb | 2022-06-01 07:05:31 -0700 | [diff] [blame] | 1091 | namespace_id_to_number_of_reopened_namespaces: HashMap<ItemId, usize>, |
| 1092 | reopened_namespace_id_to_idx: HashMap<ItemId, usize>, |
Felipe de A. Mello Pereira | 3a95372 | 2023-03-02 05:37:36 -0800 | [diff] [blame] | 1093 | function_name_to_functions: HashMap<UnqualifiedIdentifier, Vec<Rc<Func>>>, |
Michael Forster | 7ef8073 | 2021-10-01 18:12:19 +0000 | [diff] [blame] | 1094 | } |
| 1095 | |
| 1096 | impl IR { |
Marcel Hlopko | 3b9bf9e | 2021-11-29 08:25:14 +0000 | [diff] [blame] | 1097 | pub fn items(&self) -> impl Iterator<Item = &Item> { |
| 1098 | self.flat_ir.items.iter() |
| 1099 | } |
| 1100 | |
Rosica Dejanovska | b2bd59e | 2022-04-11 09:02:03 -0700 | [diff] [blame] | 1101 | pub fn top_level_item_ids(&self) -> impl Iterator<Item = &ItemId> { |
| 1102 | self.flat_ir.top_level_item_ids.iter() |
| 1103 | } |
| 1104 | |
Marcel Hlopko | 3b9bf9e | 2021-11-29 08:25:14 +0000 | [diff] [blame] | 1105 | pub fn items_mut(&mut self) -> impl Iterator<Item = &mut Item> { |
| 1106 | self.flat_ir.items.iter_mut() |
| 1107 | } |
| 1108 | |
Lukasz Anforowicz | 121338a | 2022-11-01 14:28:32 -0700 | [diff] [blame] | 1109 | pub fn public_headers(&self) -> impl Iterator<Item = &HeaderName> { |
| 1110 | self.flat_ir.public_headers.iter() |
Marcel Hlopko | 3b9bf9e | 2021-11-29 08:25:14 +0000 | [diff] [blame] | 1111 | } |
| 1112 | |
Devin Jeanpierre | 8cd8ae7 | 2022-06-29 18:59:40 -0700 | [diff] [blame] | 1113 | pub fn functions(&self) -> impl Iterator<Item = &Rc<Func>> { |
Marcel Hlopko | 3b9bf9e | 2021-11-29 08:25:14 +0000 | [diff] [blame] | 1114 | self.items().filter_map(|item| match item { |
Michael Forster | 7ef8073 | 2021-10-01 18:12:19 +0000 | [diff] [blame] | 1115 | Item::Func(func) => Some(func), |
| 1116 | _ => None, |
| 1117 | }) |
| 1118 | } |
| 1119 | |
Devin Jeanpierre | 8cd8ae7 | 2022-06-29 18:59:40 -0700 | [diff] [blame] | 1120 | pub fn records(&self) -> impl Iterator<Item = &Rc<Record>> { |
Marcel Hlopko | 3b9bf9e | 2021-11-29 08:25:14 +0000 | [diff] [blame] | 1121 | self.items().filter_map(|item| match item { |
Michael Forster | 7ef8073 | 2021-10-01 18:12:19 +0000 | [diff] [blame] | 1122 | Item::Record(func) => Some(func), |
| 1123 | _ => None, |
| 1124 | }) |
| 1125 | } |
Marcel Hlopko | c0956cf | 2021-11-29 08:31:28 +0000 | [diff] [blame] | 1126 | |
Devin Jeanpierre | 8cd8ae7 | 2022-06-29 18:59:40 -0700 | [diff] [blame] | 1127 | pub fn unsupported_items(&self) -> impl Iterator<Item = &Rc<UnsupportedItem>> { |
Marcel Hlopko | 4c660dd | 2021-12-02 09:52:47 +0000 | [diff] [blame] | 1128 | self.items().filter_map(|item| match item { |
| 1129 | Item::UnsupportedItem(unsupported_item) => Some(unsupported_item), |
| 1130 | _ => None, |
| 1131 | }) |
| 1132 | } |
| 1133 | |
Devin Jeanpierre | 8cd8ae7 | 2022-06-29 18:59:40 -0700 | [diff] [blame] | 1134 | pub fn comments(&self) -> impl Iterator<Item = &Rc<Comment>> { |
Rosica Dejanovska | d638cf5 | 2022-03-23 15:45:01 +0000 | [diff] [blame] | 1135 | self.items().filter_map(|item| match item { |
| 1136 | Item::Comment(comment) => Some(comment), |
| 1137 | _ => None, |
| 1138 | }) |
| 1139 | } |
| 1140 | |
Devin Jeanpierre | 8cd8ae7 | 2022-06-29 18:59:40 -0700 | [diff] [blame] | 1141 | pub fn namespaces(&self) -> impl Iterator<Item = &Rc<Namespace>> { |
Rosica Dejanovska | dd9a903 | 2022-04-12 07:34:41 -0700 | [diff] [blame] | 1142 | self.items().filter_map(|item| match item { |
| 1143 | Item::Namespace(ns) => Some(ns), |
| 1144 | _ => None, |
| 1145 | }) |
| 1146 | } |
| 1147 | |
Googler | 6a0a525 | 2022-01-11 14:08:09 +0000 | [diff] [blame] | 1148 | pub fn item_for_type<T>(&self, ty: &T) -> Result<&Item> |
Marcel Hlopko | c0956cf | 2021-11-29 08:31:28 +0000 | [diff] [blame] | 1149 | where |
Michael VanBemmel | f5cbdf4 | 2022-10-14 17:00:11 -0700 | [diff] [blame] | 1150 | T: TypeWithDeclId + Debug, |
Marcel Hlopko | c0956cf | 2021-11-29 08:31:28 +0000 | [diff] [blame] | 1151 | { |
Marcel Hlopko | 264b9ad | 2021-12-02 21:06:44 +0000 | [diff] [blame] | 1152 | if let Some(decl_id) = ty.decl_id() { |
Lukasz Anforowicz | e1ade88 | 2023-05-15 11:23:47 -0700 | [diff] [blame] | 1153 | Ok(self.find_untyped_decl(decl_id)) |
Marcel Hlopko | c0956cf | 2021-11-29 08:31:28 +0000 | [diff] [blame] | 1154 | } else { |
Googler | 6a0a525 | 2022-01-11 14:08:09 +0000 | [diff] [blame] | 1155 | bail!("Type {:?} does not have an associated item.", ty) |
Marcel Hlopko | c0956cf | 2021-11-29 08:31:28 +0000 | [diff] [blame] | 1156 | } |
| 1157 | } |
Devin Jeanpierre | 7eb0404 | 2021-12-03 07:19:22 +0000 | [diff] [blame] | 1158 | |
Rosica Dejanovska | d638cf5 | 2022-03-23 15:45:01 +0000 | [diff] [blame] | 1159 | pub fn find_decl<'a, T>(&'a self, decl_id: ItemId) -> Result<&'a T> |
Lukasz Anforowicz | 4404725 | 2022-03-23 13:04:48 +0000 | [diff] [blame] | 1160 | where |
| 1161 | &'a T: TryFrom<&'a Item>, |
| 1162 | { |
Lukasz Anforowicz | e1ade88 | 2023-05-15 11:23:47 -0700 | [diff] [blame] | 1163 | self.find_untyped_decl(decl_id).try_into().map_err(|_| { |
| 1164 | anyhow!("DeclId {:?} doesn't refer to a {}", decl_id, std::any::type_name::<T>()) |
Lukasz Anforowicz | 4404725 | 2022-03-23 13:04:48 +0000 | [diff] [blame] | 1165 | }) |
| 1166 | } |
| 1167 | |
Lukasz Anforowicz | e1ade88 | 2023-05-15 11:23:47 -0700 | [diff] [blame] | 1168 | fn find_untyped_decl(&self, decl_id: ItemId) -> &Item { |
Devin Jeanpierre | 7eb0404 | 2021-12-03 07:19:22 +0000 | [diff] [blame] | 1169 | let idx = *self |
Rosica Dejanovska | d638cf5 | 2022-03-23 15:45:01 +0000 | [diff] [blame] | 1170 | .item_id_to_item_idx |
Devin Jeanpierre | 7eb0404 | 2021-12-03 07:19:22 +0000 | [diff] [blame] | 1171 | .get(&decl_id) |
Lukasz Anforowicz | e1ade88 | 2023-05-15 11:23:47 -0700 | [diff] [blame] | 1172 | .unwrap_or_else(|| panic!("Couldn't find decl_id {:?} in the IR.", decl_id)); |
| 1173 | self.flat_ir |
| 1174 | .items |
| 1175 | .get(idx) |
| 1176 | .unwrap_or_else(|| panic!("Couldn't find an item at idx {}", idx)) |
Devin Jeanpierre | 7eb0404 | 2021-12-03 07:19:22 +0000 | [diff] [blame] | 1177 | } |
Marcel Hlopko | a0f3866 | 2021-12-03 08:45:26 +0000 | [diff] [blame] | 1178 | |
Devin Jeanpierre | 6ed0f60 | 2023-03-01 17:22:54 -0800 | [diff] [blame] | 1179 | /// Returns whether `target` is the current target. |
Googler | 6c3de12 | 2022-03-28 11:40:41 +0000 | [diff] [blame] | 1180 | pub fn is_current_target(&self, target: &BazelLabel) -> bool { |
Marcel Hlopko | a0f3866 | 2021-12-03 08:45:26 +0000 | [diff] [blame] | 1181 | // TODO(hlopko): Make this be a pointer comparison, now it's comparing string |
| 1182 | // values. |
Lukasz Anforowicz | 5b3f530 | 2022-02-07 01:04:47 +0000 | [diff] [blame] | 1183 | *target == *self.current_target() |
| 1184 | } |
| 1185 | |
Devin Jeanpierre | 6ed0f60 | 2023-03-01 17:22:54 -0800 | [diff] [blame] | 1186 | /// Returns the Crubit features enabled for the given `target`. |
| 1187 | #[must_use] |
| 1188 | pub fn target_crubit_features(&self, target: &BazelLabel) -> flagset::FlagSet<CrubitFeature> { |
| 1189 | self.flat_ir.crubit_features.get(target).cloned().unwrap_or_default().0 |
| 1190 | } |
| 1191 | |
Devin Jeanpierre | 319bcac | 2023-03-14 17:49:08 -0700 | [diff] [blame] | 1192 | /// Returns a mutable reference to the Crubit features enabled for the given |
| 1193 | /// `target`. |
| 1194 | /// |
| 1195 | /// Since IR is generally only held immutably, this is only useful for |
| 1196 | /// testing. |
| 1197 | #[must_use] |
| 1198 | pub fn target_crubit_features_mut( |
| 1199 | &mut self, |
| 1200 | target: &BazelLabel, |
| 1201 | ) -> &mut flagset::FlagSet<CrubitFeature> { |
| 1202 | // TODO(jeanpierreda): migrate to raw_entry_mut when stable. |
| 1203 | // (target is taken by reference exactly because ideally this function would use |
| 1204 | // the raw entry API.) |
| 1205 | &mut self.flat_ir.crubit_features.entry(target.clone()).or_default().0 |
| 1206 | } |
| 1207 | |
Googler | 6c3de12 | 2022-03-28 11:40:41 +0000 | [diff] [blame] | 1208 | pub fn current_target(&self) -> &BazelLabel { |
Lukasz Anforowicz | 5b3f530 | 2022-02-07 01:04:47 +0000 | [diff] [blame] | 1209 | &self.flat_ir.current_target |
Googler | 6a0a525 | 2022-01-11 14:08:09 +0000 | [diff] [blame] | 1210 | } |
| 1211 | |
Marcel Hlopko | 016cab0 | 2021-12-16 14:29:35 +0000 | [diff] [blame] | 1212 | // Returns the standard Debug print string for the `flat_ir`. The reason why we |
| 1213 | // don't use the debug print of `Self` is that `Self` contains HashMaps, and |
| 1214 | // their debug print produces content that is not valid Rust code. |
| 1215 | // `token_stream_matchers` (hacky) implementation parses the debug print and |
| 1216 | // chokes on HashMaps. Therefore this method. |
| 1217 | // |
| 1218 | // Used for `token_stream_matchers`, do not use for anything else. |
| 1219 | pub fn flat_ir_debug_print(&self) -> String { |
| 1220 | format!("{:?}", self.flat_ir) |
| 1221 | } |
Devin Jeanpierre | 9886fb4 | 2022-04-01 04:31:20 -0700 | [diff] [blame] | 1222 | |
Marcel Hlopko | af682a0 | 2022-04-08 07:27:14 -0700 | [diff] [blame] | 1223 | pub fn get_lifetime(&self, lifetime_id: LifetimeId) -> Option<&LifetimeName> { |
Devin Jeanpierre | d2b7a8f | 2022-04-01 04:37:16 -0700 | [diff] [blame] | 1224 | self.lifetimes.get(&lifetime_id) |
Devin Jeanpierre | 9886fb4 | 2022-04-01 04:31:20 -0700 | [diff] [blame] | 1225 | } |
Rosica Dejanovska | 93aeafb | 2022-06-01 07:05:31 -0700 | [diff] [blame] | 1226 | |
| 1227 | pub fn get_reopened_namespace_idx(&self, id: ItemId) -> Result<usize> { |
| 1228 | Ok(*self.reopened_namespace_id_to_idx.get(&id).with_context(|| { |
| 1229 | format!("Could not find the reopened namespace index for namespace {:?}.", id) |
| 1230 | })?) |
| 1231 | } |
| 1232 | |
| 1233 | pub fn is_last_reopened_namespace(&self, id: ItemId, canonical_id: ItemId) -> Result<bool> { |
| 1234 | let idx = self.get_reopened_namespace_idx(id)?; |
| 1235 | let last_item_idx = self |
| 1236 | .namespace_id_to_number_of_reopened_namespaces |
| 1237 | .get(&canonical_id) |
| 1238 | .with_context(|| { |
| 1239 | format!( |
| 1240 | "Could not find number of reopened namespaces for namespace {:?}.", |
| 1241 | canonical_id |
| 1242 | ) |
| 1243 | })? - 1; |
| 1244 | Ok(idx == last_item_idx) |
| 1245 | } |
Devin Jeanpierre | bdfb4d9 | 2022-06-17 01:17:01 -0700 | [diff] [blame] | 1246 | |
Devin Jeanpierre | b7f8e28 | 2023-05-26 16:03:12 -0700 | [diff] [blame] | 1247 | /// Returns the `Item` defining `func`, or `None` if `func` is not a |
Devin Jeanpierre | bdfb4d9 | 2022-06-17 01:17:01 -0700 | [diff] [blame] | 1248 | /// member function. |
| 1249 | /// |
Devin Jeanpierre | b7f8e28 | 2023-05-26 16:03:12 -0700 | [diff] [blame] | 1250 | /// Note that even if `func` is a member function, the associated record |
| 1251 | /// might not be a Record IR Item (e.g. it has its type changed via |
| 1252 | /// crubit_internal_rust_type). |
| 1253 | pub fn record_for_member_func(&self, func: &Func) -> Option<&Item> { |
Devin Jeanpierre | bdfb4d9 | 2022-06-17 01:17:01 -0700 | [diff] [blame] | 1254 | if let Some(meta) = func.member_func_metadata.as_ref() { |
Devin Jeanpierre | b7f8e28 | 2023-05-26 16:03:12 -0700 | [diff] [blame] | 1255 | Some(self.find_untyped_decl(meta.record_id)) |
Devin Jeanpierre | bdfb4d9 | 2022-06-17 01:17:01 -0700 | [diff] [blame] | 1256 | } else { |
Devin Jeanpierre | 95b7c2f | 2023-03-14 21:01:16 -0700 | [diff] [blame] | 1257 | None |
Devin Jeanpierre | bdfb4d9 | 2022-06-17 01:17:01 -0700 | [diff] [blame] | 1258 | } |
| 1259 | } |
Marcel Hlopko | b4d5d8e | 2022-11-16 03:15:00 -0800 | [diff] [blame] | 1260 | |
Lukasz Anforowicz | 8e5042c | 2023-01-03 11:19:07 -0800 | [diff] [blame] | 1261 | pub fn crate_root_path(&self) -> Option<Rc<str>> { |
| 1262 | self.flat_ir.crate_root_path.clone() |
Marcel Hlopko | b4d5d8e | 2022-11-16 03:15:00 -0800 | [diff] [blame] | 1263 | } |
Felipe de A. Mello Pereira | 3a95372 | 2023-03-02 05:37:36 -0800 | [diff] [blame] | 1264 | |
| 1265 | pub fn get_functions_by_name( |
| 1266 | &self, |
| 1267 | function_name: &UnqualifiedIdentifier, |
| 1268 | ) -> impl Iterator<Item = &Rc<Func>> { |
| 1269 | self.function_name_to_functions.get(function_name).map_or([].iter(), |v| v.iter()) |
| 1270 | } |
Marcel Hlopko | 42abfc8 | 2021-08-09 07:03:17 +0000 | [diff] [blame] | 1271 | } |
| 1272 | |
| 1273 | #[cfg(test)] |
| 1274 | mod tests { |
| 1275 | use super::*; |
| 1276 | |
| 1277 | #[test] |
Marcel Hlopko | afdc502 | 2021-12-16 14:31:19 +0000 | [diff] [blame] | 1278 | fn test_identifier_debug_print() { |
Lukasz Anforowicz | 8c1a6c4 | 2022-11-23 16:18:09 -0800 | [diff] [blame] | 1279 | assert_eq!(format!("{:?}", Identifier { identifier: "hello".into() }), "\"hello\""); |
Marcel Hlopko | afdc502 | 2021-12-16 14:31:19 +0000 | [diff] [blame] | 1280 | } |
| 1281 | |
| 1282 | #[test] |
| 1283 | fn test_unqualified_identifier_debug_print() { |
| 1284 | assert_eq!( |
| 1285 | format!( |
| 1286 | "{:?}", |
Lukasz Anforowicz | 8c1a6c4 | 2022-11-23 16:18:09 -0800 | [diff] [blame] | 1287 | UnqualifiedIdentifier::Identifier(Identifier { identifier: "hello".into() }) |
Marcel Hlopko | afdc502 | 2021-12-16 14:31:19 +0000 | [diff] [blame] | 1288 | ), |
| 1289 | "\"hello\"" |
| 1290 | ); |
| 1291 | assert_eq!(format!("{:?}", UnqualifiedIdentifier::Constructor), "Constructor"); |
| 1292 | assert_eq!(format!("{:?}", UnqualifiedIdentifier::Destructor), "Destructor"); |
| 1293 | } |
| 1294 | |
| 1295 | #[test] |
Googler | a921463 | 2021-09-17 08:16:29 +0000 | [diff] [blame] | 1296 | fn test_used_headers() { |
Marcel Hlopko | 42abfc8 | 2021-08-09 07:03:17 +0000 | [diff] [blame] | 1297 | let input = r#" |
| 1298 | { |
Lukasz Anforowicz | 121338a | 2022-11-01 14:28:32 -0700 | [diff] [blame] | 1299 | "public_headers": [{ "name": "foo/bar.h" }], |
Marcel Hlopko | 80441c1 | 2021-11-12 10:43:18 +0000 | [diff] [blame] | 1300 | "current_target": "//foo:bar" |
Googler | a921463 | 2021-09-17 08:16:29 +0000 | [diff] [blame] | 1301 | } |
| 1302 | "#; |
| 1303 | let ir = deserialize_ir(input.as_bytes()).unwrap(); |
Marcel Hlopko | 3b9bf9e | 2021-11-29 08:25:14 +0000 | [diff] [blame] | 1304 | let expected = FlatIR { |
Lukasz Anforowicz | 121338a | 2022-11-01 14:28:32 -0700 | [diff] [blame] | 1305 | public_headers: vec![HeaderName { name: "foo/bar.h".into() }], |
Marcel Hlopko | 80441c1 | 2021-11-12 10:43:18 +0000 | [diff] [blame] | 1306 | current_target: "//foo:bar".into(), |
Rosica Dejanovska | b2bd59e | 2022-04-11 09:02:03 -0700 | [diff] [blame] | 1307 | top_level_item_ids: vec![], |
Marcel Hlopko | 80441c1 | 2021-11-12 10:43:18 +0000 | [diff] [blame] | 1308 | items: vec![], |
Marcel Hlopko | b4d5d8e | 2022-11-16 03:15:00 -0800 | [diff] [blame] | 1309 | crate_root_path: None, |
Devin Jeanpierre | 6ed0f60 | 2023-03-01 17:22:54 -0800 | [diff] [blame] | 1310 | crubit_features: Default::default(), |
Googler | a921463 | 2021-09-17 08:16:29 +0000 | [diff] [blame] | 1311 | }; |
Marcel Hlopko | 3b9bf9e | 2021-11-29 08:25:14 +0000 | [diff] [blame] | 1312 | assert_eq!(ir.flat_ir, expected); |
Googler | a921463 | 2021-09-17 08:16:29 +0000 | [diff] [blame] | 1313 | } |
Marcel Hlopko | b4d5d8e | 2022-11-16 03:15:00 -0800 | [diff] [blame] | 1314 | |
| 1315 | #[test] |
| 1316 | fn test_empty_crate_root_path() { |
| 1317 | let input = "{ \"current_target\": \"//foo:bar\" }"; |
| 1318 | let ir = deserialize_ir(input.as_bytes()).unwrap(); |
| 1319 | assert_eq!(ir.crate_root_path(), None); |
| 1320 | } |
| 1321 | |
| 1322 | #[test] |
| 1323 | fn test_crate_root_path() { |
| 1324 | let input = r#" |
| 1325 | { |
| 1326 | "crate_root_path": "__cc_template_instantiations_rs_api", |
| 1327 | "current_target": "//foo:bar" |
| 1328 | } |
| 1329 | "#; |
| 1330 | let ir = deserialize_ir(input.as_bytes()).unwrap(); |
Lukasz Anforowicz | 8e5042c | 2023-01-03 11:19:07 -0800 | [diff] [blame] | 1331 | assert_eq!(ir.crate_root_path().as_deref(), Some("__cc_template_instantiations_rs_api")); |
Marcel Hlopko | b4d5d8e | 2022-11-16 03:15:00 -0800 | [diff] [blame] | 1332 | } |
Devin Jeanpierre | 89230f3 | 2023-03-15 12:27:02 -0700 | [diff] [blame] | 1333 | |
| 1334 | #[test] |
| 1335 | fn test_bazel_label_target() { |
| 1336 | let label: BazelLabel = "//foo:bar".into(); |
| 1337 | assert_eq!(label.target_name(), "bar"); |
| 1338 | } |
| 1339 | |
| 1340 | #[test] |
| 1341 | fn test_bazel_label_target_dotless() { |
| 1342 | let label: BazelLabel = "//foo".into(); |
| 1343 | assert_eq!(label.target_name(), "foo"); |
| 1344 | } |
| 1345 | |
| 1346 | #[test] |
| 1347 | fn test_bazel_label_dotless_slashless() { |
| 1348 | let label: BazelLabel = "foo".into(); |
| 1349 | assert_eq!(label.target_name(), "foo"); |
| 1350 | } |
| 1351 | |
| 1352 | /// These are not labels, but there is an unambiguous interpretation of |
| 1353 | /// what their target should be that lets us keep going. |
| 1354 | #[test] |
| 1355 | fn test_bazel_label_empty_target() { |
| 1356 | for s in ["foo:", "foo/", ""] { |
| 1357 | let label: BazelLabel = s.into(); |
| 1358 | assert_eq!(label.target_name(), "", "label={s:?}"); |
| 1359 | } |
| 1360 | } |
Marcel Hlopko | 42abfc8 | 2021-08-09 07:03:17 +0000 | [diff] [blame] | 1361 | } |