Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -737,7 +737,7 @@ impl RsTypeKind {
// the forward declaration.
if let RsTypeKind::Record { record, .. } = &underlying_type {
if record.owning_target != type_alias.owning_target
&& record.defining_target() != Some(&type_alias.owning_target)
&& record.defining_target(ir) != Some(&type_alias.owning_target)
{
return Ok(underlying_type);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,9 @@ impl ir::GenericItem for TestItem {
fn owning_target(&self) -> Option<BazelLabel> {
None
}
fn defining_target<'a>(&'a self, _ir: &'a IR) -> Option<&'a BazelLabel> {
None
}
fn debug_name(&self, _: &IR) -> Rc<str> {
"test_item".into()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,14 +107,15 @@ fn get_field_rs_type_kind_for_layout(
if field.is_no_unique_address {
bail!("`[[no_unique_address]]` attribute was present.");
}
let ir = db.ir();
match &field.unknown_attr {
Err(e) => bail!("{e}"),
Ok(None) => (),
Ok(Some(unknown_attr)) => {
// Both the template definition and its instantiation should enable experimental
// features.
for target in record.defining_target().into_iter().chain([&record.owning_target]) {
let enabled_features = db.ir().target_crubit_features(target);
for target in record.defining_target(ir).into_iter().chain([&record.owning_target]) {
let enabled_features = ir.target_crubit_features(target);
ensure!(
enabled_features.contains(crubit_feature::CrubitFeature::Experimental),
"crubit.rs/errors/unknown_attribute: unknown field attributes are only \
Expand All @@ -134,8 +135,8 @@ fn get_field_rs_type_kind_for_layout(
bail!("Bridge-by-value types are not supported in struct fields.")
}

for target in record.defining_target().into_iter().chain([&record.owning_target]) {
let enabled_features = db.ir().target_crubit_features(target);
for target in record.defining_target(ir).into_iter().chain([&record.owning_target]) {
let enabled_features = ir.target_crubit_features(target);
let (missing_features, reason) = type_kind.required_crubit_features(db, enabled_features);
ensure!(
missing_features.is_empty(),
Expand All @@ -150,8 +151,8 @@ fn get_field_rs_type_kind_for_layout(
//
// Users can still work around this with accessor functions.
if record.should_implement_drop() && !record.is_union() && needs_manually_drop(&type_kind) {
for target in record.defining_target().into_iter().chain([&record.owning_target]) {
let enabled_features = db.ir().target_crubit_features(target);
for target in record.defining_target(ir).into_iter().chain([&record.owning_target]) {
let enabled_features = ir.target_crubit_features(target);
ensure!(
enabled_features.contains(crubit_feature::CrubitFeature::Experimental),
"nontrivial fields would be destroyed in the wrong order"
Expand Down Expand Up @@ -609,7 +610,7 @@ pub fn generate_record(db: &BindingsGenerator, record: Rc<Record>) -> Result<Api
// Both the template definition and its instantiation should enable experimental
// features.
let mut crubit_features = ir.target_crubit_features(&record.owning_target);
if let Some(defining_target) = record.defining_target() {
if let Some(defining_target) = record.defining_target(ir) {
crubit_features |= ir.target_crubit_features(defining_target);
}
let mut upcast_impls = vec![];
Expand Down
14 changes: 8 additions & 6 deletions rs_bindings_from_cc/generate_bindings/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1022,12 +1022,13 @@ fn crubit_abi_type(db: &BindingsGenerator, rs_type_kind: RsTypeKind) -> Result<C
bail!("Void pointer bridge types are not allowed within composable bridging")
}
BridgeRsTypeKind::ProtoMessageBridge { .. } => {
let ir = db.ir();
let target =
original_type.defining_target().unwrap_or(&original_type.owning_target);
original_type.defining_target(ir).unwrap_or(&original_type.owning_target);
let rust_abi_path =
make_rust_abi_path_from_str("ProtoMessageRustBridge", db.ir(), target);
make_rust_abi_path_from_str("ProtoMessageRustBridge", ir, target);

let cpp_namespace_qualifier = db.ir().namespace_qualifier(original_type.as_ref());
let cpp_namespace_qualifier = ir.namespace_qualifier(original_type.as_ref());

// Rust message types are exported to crate root, but we need the full namespace for the C++ ABI.
let merged_cpp_abi_path = cpp_namespace_qualifier.parts().join("::")
Expand All @@ -1038,16 +1039,17 @@ fn crubit_abi_type(db: &BindingsGenerator, rs_type_kind: RsTypeKind) -> Result<C
proto_message_rust_bridge: rust_abi_path,
rust_proto_path: make_rust_abi_path_from_str(
original_type.rs_name.identifier.as_ref(),
db.ir(),
ir,
target,
),
cpp_proto_path: make_cpp_abi_path_from_str(&merged_cpp_abi_path)?,
})
}
BridgeRsTypeKind::Bridge { abi_rust, abi_cpp, generic_types, .. } => {
let ir = db.ir();
let target =
original_type.defining_target().unwrap_or(&original_type.owning_target);
let rust_abi_path = make_rust_abi_path_from_str(&abi_rust, db.ir(), target);
original_type.defining_target(ir).unwrap_or(&original_type.owning_target);
let rust_abi_path = make_rust_abi_path_from_str(&abi_rust, ir, target);

let cpp_abi_path = make_cpp_abi_path_from_str(&abi_cpp)?;

Expand Down
71 changes: 52 additions & 19 deletions rs_bindings_from_cc/ir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ pub trait GenericItem {
/// The Bazel target which owns the bindings for this item.
fn owning_target(&self) -> Option<BazelLabel>;

/// Returns the target that this item was defined in, if it was defined somewhere other than
/// `owning_target()`. This may be `Some` for class template specializations and their member
/// functions and is `None` otherwise.
fn defining_target<'a>(&'a self, ir: &'a IR) -> Option<&'a BazelLabel>;

/// The name of the item, readable by programmers.
///
/// For example, `void Foo();` should have name `Foo`.
Expand Down Expand Up @@ -66,6 +71,9 @@ where
fn owning_target(&self) -> Option<BazelLabel> {
(**self).owning_target()
}
fn defining_target<'a>(&'a self, ir: &'a IR) -> Option<&'a BazelLabel> {
(**self).defining_target(ir)
}
fn debug_name(&self, ir: &IR) -> Rc<str> {
(**self).debug_name(ir)
}
Expand Down Expand Up @@ -910,6 +918,10 @@ impl GenericItem for Func {
fn owning_target(&self) -> Option<BazelLabel> {
Some(self.owning_target.clone())
}
fn defining_target<'a>(&'a self, ir: &'a IR) -> Option<&'a BazelLabel> {
// There is only a defining target if we have an enclosing item and it's a record.
ir.find_decl::<Rc<Record>>(self.enclosing_item_id?).ok()?.defining_target(ir)
}
fn debug_name(&self, ir: &IR) -> Rc<str> {
let mut name = ir.namespace_qualifier(self).format_for_cc_debug();
let record_name = || -> Option<Rc<str>> {
Expand Down Expand Up @@ -967,11 +979,6 @@ impl Func {
pub fn is_instance_method(&self) -> bool {
self.instance_method_metadata.is_some()
}

pub fn defining_target<'ir>(&self, ir: &'ir IR) -> Option<&'ir BazelLabel> {
// There is only a defining target if we have an enclosing item and it's a record.
ir.find_decl::<Rc<Record>>(self.enclosing_item_id?).ok()?.defining_target()
}
}

#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, Deserialize)]
Expand Down Expand Up @@ -1048,6 +1055,9 @@ impl GenericItem for IncompleteRecord {
fn owning_target(&self) -> Option<BazelLabel> {
Some(self.owning_target.clone())
}
fn defining_target<'a>(&'a self, _ir: &'a IR) -> Option<&'a BazelLabel> {
None
}
fn debug_name(&self, ir: &IR) -> Rc<str> {
format!("{}{}", ir.namespace_qualifier(self).format_for_cc_debug(), self.cc_name.identifier)
.into()
Expand Down Expand Up @@ -1269,6 +1279,9 @@ impl GenericItem for Record {
fn owning_target(&self) -> Option<BazelLabel> {
Some(self.owning_target.clone())
}
fn defining_target<'a>(&'a self, _ir: &'a IR) -> Option<&'a BazelLabel> {
self.template_specialization.as_ref().map(|ts| &ts.defining_target)
}
fn debug_name(&self, ir: &IR) -> Rc<str> {
format!("{}{}", ir.namespace_qualifier(self).format_for_cc_debug(), self.cc_name.identifier)
.into()
Expand Down Expand Up @@ -1389,10 +1402,6 @@ impl Record {
}) | None
)
}

pub fn defining_target(&self) -> Option<&BazelLabel> {
self.template_specialization.as_ref().map(|ts| &ts.defining_target)
}
}

#[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize)]
Expand Down Expand Up @@ -1422,6 +1431,9 @@ impl GenericItem for Constant {
fn owning_target(&self) -> Option<BazelLabel> {
Some(self.owning_target.clone())
}
fn defining_target<'a>(&'a self, _ir: &'a IR) -> Option<&'a BazelLabel> {
None
}
fn debug_name(&self, ir: &IR) -> Rc<str> {
format!("{}{}", ir.namespace_qualifier(self).format_for_cc_debug(), self.cc_name.identifier)
.into()
Expand Down Expand Up @@ -1468,6 +1480,9 @@ impl GenericItem for GlobalVar {
fn owning_target(&self) -> Option<BazelLabel> {
Some(self.owning_target.clone())
}
fn defining_target<'a>(&'a self, _ir: &'a IR) -> Option<&'a BazelLabel> {
None
}
fn debug_name(&self, ir: &IR) -> Rc<str> {
format!("{}{}", ir.namespace_qualifier(self).format_for_cc_debug(), self.cc_name.identifier)
.into()
Expand Down Expand Up @@ -1519,6 +1534,9 @@ impl GenericItem for Enum {
fn owning_target(&self) -> Option<BazelLabel> {
Some(self.owning_target.clone())
}
fn defining_target<'a>(&'a self, _ir: &'a IR) -> Option<&'a BazelLabel> {
None
}
fn debug_name(&self, ir: &IR) -> Rc<str> {
format!("{}{}", ir.namespace_qualifier(self).format_for_cc_debug(), self.cc_name.identifier)
.into()
Expand Down Expand Up @@ -1573,6 +1591,9 @@ impl GenericItem for TypeAlias {
fn owning_target(&self) -> Option<BazelLabel> {
Some(self.owning_target.clone())
}
fn defining_target<'a>(&'a self, _ir: &'a IR) -> Option<&'a BazelLabel> {
None
}
fn debug_name(&self, ir: &IR) -> Rc<str> {
format!("{}{}", ir.namespace_qualifier(self).format_for_cc_debug(), self.cc_name.identifier)
.into()
Expand Down Expand Up @@ -1704,6 +1725,9 @@ impl GenericItem for UnsupportedItem {
fn owning_target(&self) -> Option<BazelLabel> {
None
}
fn defining_target<'a>(&'a self, _ir: &'a IR) -> Option<&'a BazelLabel> {
None
}
fn debug_name(&self, _: &IR) -> Rc<str> {
// Note: name is supposed to be populated with the `debug_name()` of the unsupported item.
self.name.clone()
Expand Down Expand Up @@ -1803,6 +1827,9 @@ impl GenericItem for Comment {
fn owning_target(&self) -> Option<BazelLabel> {
None
}
fn defining_target<'a>(&'a self, _ir: &'a IR) -> Option<&'a BazelLabel> {
None
}
fn debug_name(&self, _: &IR) -> Rc<str> {
"<comment>".into()
}
Expand Down Expand Up @@ -1848,6 +1875,9 @@ impl GenericItem for Namespace {
fn owning_target(&self) -> Option<BazelLabel> {
Some(self.owning_target.clone())
}
fn defining_target<'a>(&'a self, _ir: &'a IR) -> Option<&'a BazelLabel> {
None
}
fn debug_name(&self, ir: &IR) -> Rc<str> {
format!("{}{}", ir.namespace_qualifier(self).format_for_cc_debug(), self.cc_name.identifier)
.into()
Expand Down Expand Up @@ -1885,6 +1915,9 @@ impl GenericItem for UseMod {
fn owning_target(&self) -> Option<BazelLabel> {
None
}
fn defining_target<'a>(&'a self, _ir: &'a IR) -> Option<&'a BazelLabel> {
None
}
fn debug_name(&self, _: &IR) -> Rc<str> {
format!("<[internal] use mod {}::* = {}>", self.mod_name, self.path).into()
}
Expand Down Expand Up @@ -1927,6 +1960,9 @@ impl GenericItem for ExistingRustType {
fn owning_target(&self) -> Option<BazelLabel> {
Some(self.owning_target.clone())
}
fn defining_target<'a>(&'a self, _ir: &'a IR) -> Option<&'a BazelLabel> {
None
}
fn debug_name(&self, ir: &IR) -> Rc<str> {
format!("{}{}", ir.namespace_qualifier(self).format_for_cc_debug(), self.cc_name).into()
}
Expand Down Expand Up @@ -2001,6 +2037,13 @@ impl GenericItem for Item {
}
}
}
fn defining_target<'a>(&'a self, ir: &'a IR) -> Option<&'a BazelLabel> {
forward_item! {
match self {
_(x) => x.defining_target(ir)
}
}
}
fn debug_name(&self, ir: &IR) -> Rc<str> {
forward_item! {
match self {
Expand Down Expand Up @@ -2058,16 +2101,6 @@ impl Item {
}
}

/// Returns the target that this was defined in, if it was defined somewhere
/// other than `owning_target()`.
pub fn defining_target<'a, 'ir: 'a>(&'a self, ir: &'ir IR) -> Option<&'a BazelLabel> {
match self {
Item::Func(func) => func.defining_target(ir),
Item::Record(record) => record.defining_target(),
_ => None,
}
}

/// Returns true if this corresponds to the definition of a new name for a
/// type.
pub fn is_type_definition(&self) -> bool {
Expand Down