Skip to content

Commit d4a54a7

Browse files
thunderseethecopybara-github
authored andcommitted
Generate bindings to trait implementations of C++ types.
Previously, we needlessly excluded these implementations that referenced a type with a `cpp_type` annotation due to the `adt_needs_bindings` check. This adds a specific carve out for that when considering implementations. PiperOrigin-RevId: 885623459
1 parent 6ea64e9 commit d4a54a7

7 files changed

Lines changed: 183 additions & 3 deletions

File tree

cc_bindings_from_rs/generate_bindings/lib.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -935,7 +935,7 @@ fn generate_trait<'tcx>(
935935
(quote! { template <#(#template_params),*> }, quote! { #trait_name<#(#template_args),*> })
936936
};
937937

938-
let main_api = CcSnippet::with_include(
938+
let mut main_api = CcSnippet::with_include(
939939
quote! {
940940
__NEWLINE__ #doc_comment
941941
#template_prefix
@@ -947,6 +947,7 @@ fn generate_trait<'tcx>(
947947
},
948948
db.support_header("rs_std/traits.h"),
949949
);
950+
main_api.prereqs.includes.insert(db.support_header("annotations_internal.h"));
950951
Ok(ApiSnippets { main_api, ..Default::default() })
951952
}
952953

@@ -1673,7 +1674,11 @@ fn generate_trait_impls<'a, 'tcx>(
16731674
.filter_map(move |(simple_ty, impl_def_ids)| match simple_ty {
16741675
SimplifiedType::Adt(did) => {
16751676
// Only bind implementations for supported ADTs.
1676-
if db.adt_needs_bindings(*did).is_err() {
1677+
let canonical_name = db.symbol_canonical_name(*did)?;
1678+
// We explicitly want to allow ADTs that specify cpp_type.
1679+
// These are typically C++ types that have generated Rust bindings.
1680+
if canonical_name.unqualified.cpp_type.is_none()
1681+
&& db.adt_needs_bindings(*did).is_err() {
16771682
return None;
16781683
}
16791684
let crate_name = tcx.crate_name(did.krate);
@@ -1682,7 +1687,7 @@ fn generate_trait_impls<'a, 'tcx>(
16821687
if ["std", "core", "alloc"].contains(&crate_name.as_str()) {
16831688
return None;
16841689
}
1685-
let adt_cc_name = db.symbol_canonical_name(*did)?.format_for_cc(db).ok()?;
1690+
let adt_cc_name = canonical_name.format_for_cc(db).ok()?;
16861691
Some((adt_cc_name, trait_def_id, impl_def_ids))
16871692
}
16881693
// TODO: b/457803426 - Support trait implementations for non-adt types.
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
load(
2+
"@rules_cc//cc:cc_library.bzl",
3+
"cc_library",
4+
)
5+
load(
6+
"@rules_rust//rust:defs.bzl",
7+
"rust_library",
8+
)
9+
load(
10+
"//cc_bindings_from_rs/bazel_support:cc_bindings_from_rust_rule.bzl",
11+
"cc_bindings_from_rust",
12+
)
13+
load(
14+
"//cc_bindings_from_rs/test/golden:golden_test.bzl",
15+
"golden_test",
16+
)
17+
load(
18+
"//common:crubit_wrapper_macros_oss.bzl",
19+
"crubit_cc_test",
20+
)
21+
22+
package(default_applicable_licenses = ["//:license"])
23+
24+
cc_library(
25+
name = "cc_type",
26+
hdrs = ["cc_type.h"],
27+
aspect_hints = ["//features:supported"],
28+
)
29+
30+
rust_library(
31+
name = "trait",
32+
testonly = 1,
33+
srcs = ["trait.rs"],
34+
cc_deps = [":cc_type"],
35+
)
36+
37+
cc_bindings_from_rust(
38+
name = "trait_cc_api",
39+
testonly = 1,
40+
crate = ":trait",
41+
)
42+
43+
golden_test(
44+
name = "trait_golden_test",
45+
basename = "trait",
46+
golden_h = "trait_cc_api.h",
47+
golden_rs = "trait_cc_api_impl.rs",
48+
rust_library = "trait",
49+
)
50+
51+
crubit_cc_test(
52+
name = "trait_test",
53+
srcs = ["trait_test.cc"],
54+
deps = [
55+
":cc_type",
56+
":trait_cc_api",
57+
"//testing/base/public:gunit_main",
58+
],
59+
)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
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+
#ifndef THIRD_PARTY_CRUBIT_CC_BINDINGS_FROM_RS_TEST_TRAITS_FOR_CC_TYPE_CC_TYPE_H_
5+
#define THIRD_PARTY_CRUBIT_CC_BINDINGS_FROM_RS_TEST_TRAITS_FOR_CC_TYPE_CC_TYPE_H_
6+
7+
struct CcType {
8+
int value;
9+
};
10+
11+
#endif // THIRD_PARTY_CRUBIT_CC_BINDINGS_FROM_RS_TEST_TRAITS_FOR_CC_TYPE_CC_TYPE_H_
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
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+
5+
pub trait Trait {
6+
fn get_value(&self) -> i32;
7+
}
8+
9+
impl Trait for cc_type::CcType {
10+
fn get_value(&self) -> i32 {
11+
self.value
12+
}
13+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
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+
5+
// Automatically @generated C++ bindings for the following Rust crate:
6+
// trait_golden
7+
// Features: supported, types
8+
9+
// clang-format off
10+
#ifndef THIRD_PARTY_CRUBIT_CC_BINDINGS_FROM_RS_TEST_TRAITS_FOR_CC_TYPE_TRAIT_GOLDEN
11+
#define THIRD_PARTY_CRUBIT_CC_BINDINGS_FROM_RS_TEST_TRAITS_FOR_CC_TYPE_TRAIT_GOLDEN
12+
13+
#pragma clang diagnostic push
14+
#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
15+
#pragma clang diagnostic ignored "-Wunused-private-field"
16+
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
17+
#include "support/annotations_internal.h"
18+
#include "support/rs_std/traits.h"
19+
20+
#include <cstdint>
21+
22+
#include "cc_bindings_from_rs/test/traits/for_cc_type/cc_type.h"
23+
24+
namespace trait {
25+
26+
// Generated from:
27+
// cc_bindings_from_rs/test/traits/for_cc_type/trait.rs;l=5
28+
struct CRUBIT_INTERNAL_RUST_TYPE(":: trait_golden :: Trait") Trait {
29+
template <typename T>
30+
using impl = rs_std::impl<T, Trait>;
31+
};
32+
33+
} // namespace trait
34+
35+
template <>
36+
struct rs_std::impl<CcType, ::trait::Trait> {
37+
static constexpr bool kIsImplemented = true;
38+
39+
// Generated from:
40+
// cc_bindings_from_rs/test/traits/for_cc_type/trait.rs;l=10
41+
static std::int32_t get_value(CcType const& self);
42+
};
43+
44+
namespace trait {
45+
namespace __crubit_internal {
46+
extern "C" std::int32_t __crubit_thunk_Trait_uget_uvalue(CcType const&);
47+
}
48+
} // namespace trait
49+
inline std::int32_t rs_std::impl<CcType, ::trait::Trait>::get_value(
50+
CcType const& self) {
51+
return trait::__crubit_internal::__crubit_thunk_Trait_uget_uvalue(self);
52+
}
53+
54+
#pragma clang diagnostic pop
55+
#endif // THIRD_PARTY_CRUBIT_CC_BINDINGS_FROM_RS_TEST_TRAITS_FOR_CC_TYPE_TRAIT_GOLDEN
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
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+
5+
// Automatically @generated C++ bindings for the following Rust crate:
6+
// trait_golden
7+
// Features: supported, types
8+
9+
#![allow(unused_unsafe, deprecated, non_snake_case, unreachable_code)]
10+
#![allow(improper_ctypes_definitions)]
11+
#![deny(warnings)]
12+
13+
extern crate alloc;
14+
extern crate core;
15+
#[unsafe(no_mangle)]
16+
unsafe extern "C" fn __crubit_thunk_Trait_uget_uvalue(__self: &'static ::cc_type::CcType) -> i32 {
17+
unsafe { <::cc_type::CcType as ::trait_golden::Trait>::get_value(__self) }
18+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
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+
5+
#include "cc_bindings_from_rs/test/traits/for_cc_type/trait.h"
6+
7+
#include "gtest/gtest.h"
8+
#include "cc_bindings_from_rs/test/traits/for_cc_type/cc_type.h"
9+
10+
namespace crubit {
11+
namespace {
12+
13+
TEST(ForCcTypeTraitTest, CcTypeImpl) {
14+
CcType cc_val = {123};
15+
EXPECT_EQ(trait::Trait::impl<CcType>::get_value(cc_val), 123);
16+
}
17+
18+
} // namespace
19+
} // namespace crubit

0 commit comments

Comments
 (0)