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 @@ -371,6 +371,11 @@ pub(crate) fn generate_associated_item<'tcx>(
if !is_supported_associated_item(tcx, def_id) {
return None;
}
// Associated items resolve names via `symbol_unqualified_name`, which - unlike
// `symbol_canonical_name` - does not consult `should_receive_bindings`.
if crate::should_receive_bindings(db, def_id).is_err() {
return None;
}
crate::error_scope!(db, def_id);
let result = match assoc_item.kind {
ty::AssocKind::Fn { .. } => {
Expand Down
50 changes: 50 additions & 0 deletions cc_bindings_from_rs/test/do_not_bind/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
load(
"@rules_rust//rust:defs.bzl",
"rust_library",
)
load(
"//cc_bindings_from_rs/bazel_support:cc_bindings_from_rust_rule.bzl",
"cc_bindings_from_rust",
)
load(
"//cc_bindings_from_rs/test/golden:golden_test.bzl",
"golden_test",
)
load("//common:crubit_wrapper_macros_oss.bzl", "crubit_cc_test")

package(default_applicable_licenses = ["//:license"])

rust_library(
name = "do_not_bind",
testonly = 1,
srcs = ["do_not_bind.rs"],
aspect_hints = [
"//features:experimental",
],
proc_macro_deps = [
"//support:crubit_annotate",
],
)

cc_bindings_from_rust(
name = "do_not_bind_cc_api",
testonly = 1,
crate = ":do_not_bind",
)

golden_test(
name = "do_not_bind_golden_test",
basename = "do_not_bind",
golden_h = "do_not_bind_cc_api.h",
golden_rs = "do_not_bind_cc_api_impl.rs",
rust_library = "do_not_bind",
)

crubit_cc_test(
name = "do_not_bind_test",
srcs = ["do_not_bind_test.cc"],
deps = [
":do_not_bind_cc_api",
"//testing/base/public:gunit_main",
],
)
47 changes: 47 additions & 0 deletions cc_bindings_from_rs/test/do_not_bind/do_not_bind.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Part of the Crubit project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

//! Coverage for `#[crubit_annotate::do_not_bind]` across the item kinds it
//! claims to support. Each suppressed item is paired with an unsuppressed
//! control so the golden distinguishes "suppressed" from "never bound".

pub struct Struct {
pub value: i32,
}

pub trait Trait {
fn suppressed_trait_method(&self) -> i32;
fn bound_trait_method(&self) -> i32;
}

#[crubit_annotate::do_not_bind]
pub fn suppressed_free_fn() -> i32 {
1
}

pub fn bound_free_fn() -> i32 {
2
}

impl Struct {
#[crubit_annotate::do_not_bind]
pub fn suppressed_inherent_method(&self) -> i32 {
3
}

pub fn bound_inherent_method(&self) -> i32 {
4
}
}

impl Trait for Struct {
#[crubit_annotate::do_not_bind]
fn suppressed_trait_method(&self) -> i32 {
5
}

fn bound_trait_method(&self) -> i32 {
6
}
}
100 changes: 100 additions & 0 deletions cc_bindings_from_rs/test/do_not_bind/do_not_bind_cc_api.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Part of the Crubit project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

// Automatically @generated C++ bindings for the following Rust crate:
// do_not_bind_golden

// clang-format off
#ifndef THIRD_PARTY_CRUBIT_CC_BINDINGS_FROM_RS_TEST_DO_NOT_BIND_DO_NOT_BIND_GOLDEN
#define THIRD_PARTY_CRUBIT_CC_BINDINGS_FROM_RS_TEST_DO_NOT_BIND_DO_NOT_BIND_GOLDEN

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
#pragma clang diagnostic ignored "-Wunused-private-field"
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#pragma clang diagnostic ignored "-Wignored-attributes"
#include "support/annotations_internal.h"
#include "support/rs_std/traits.h"

#include <cstddef>
#include <cstdint>
#include <type_traits>

namespace do_not_bind {

struct CRUBIT_INTERNAL_RUST_TYPE(":: do_not_bind_golden :: Struct") alignas(4)
[[clang::trivial_abi]] Struct final {
public:
::std::int32_t bound_inherent_method() const;

::std::int32_t value{};

private:
static void __crubit_field_offset_assertions();
};

struct CRUBIT_INTERNAL_RUST_TYPE(":: do_not_bind_golden :: Trait") Trait {
template <typename T>
using impl = rs_std::impl<T, Trait>;
};

::std::int32_t bound_free_fn();

} // namespace do_not_bind

template <>
struct rs_std::impl<::do_not_bind::Struct, ::do_not_bind::Trait> {
static constexpr bool kIsImplemented = true;

static ::std::int32_t bound_trait_method(::do_not_bind::Struct const& self);
};

namespace do_not_bind {

static_assert(
sizeof(Struct) == 4,
"Verify that ADT layout didn't change since this header got generated");
static_assert(
alignof(Struct) == 4,
"Verify that ADT layout didn't change since this header got generated");
static_assert(::std::is_trivially_destructible_v<Struct>);
static_assert(::std::is_trivially_move_constructible_v<::do_not_bind::Struct>);
static_assert(::std::is_trivially_move_assignable_v<::do_not_bind::Struct>);
namespace __crubit_internal {
extern "C" ::std::int32_t __crubit_thunk_bound_uinherent_umethod(
::do_not_bind::Struct const&);
}
inline ::std::int32_t Struct::bound_inherent_method() const {
auto&& self = *this;
return __crubit_internal::__crubit_thunk_bound_uinherent_umethod(self);
}
inline void Struct::__crubit_field_offset_assertions() {
static_assert(0 == offsetof(Struct, value));
}
namespace __crubit_internal {
extern "C" ::std::int32_t __crubit_thunk_bound_ufree_ufn();
}
inline ::std::int32_t bound_free_fn() {
return __crubit_internal::__crubit_thunk_bound_ufree_ufn();
}

} // namespace do_not_bind

namespace do_not_bind {
namespace __crubit_internal {
extern "C" ::std::int32_t
__crubit_thunk_Trait_ubound_utrait_umethod_udo_unot_ubind_ugolden_x0000003a_x0000003aStruct(
::do_not_bind::Struct const&);
}
} // namespace do_not_bind
inline ::std::int32_t
rs_std::impl<::do_not_bind::Struct, ::do_not_bind::Trait>::bound_trait_method(
::do_not_bind::Struct const& self) {
return do_not_bind::__crubit_internal::
__crubit_thunk_Trait_ubound_utrait_umethod_udo_unot_ubind_ugolden_x0000003a_x0000003aStruct(
self);
}

#pragma clang diagnostic pop
#endif // THIRD_PARTY_CRUBIT_CC_BINDINGS_FROM_RS_TEST_DO_NOT_BIND_DO_NOT_BIND_GOLDEN
34 changes: 34 additions & 0 deletions cc_bindings_from_rs/test/do_not_bind/do_not_bind_cc_api_impl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Part of the Crubit project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

// Automatically @generated C++ bindings for the following Rust crate:
// do_not_bind_golden

#![allow(unused_unsafe, deprecated, non_snake_case, unreachable_code)]
#![allow(improper_ctypes_definitions)]
#![deny(warnings)]

extern crate alloc;
extern crate core;
const _: () = assert!(::std::mem::size_of::<::do_not_bind_golden::Struct>() == 4);
const _: () = assert!(::std::mem::align_of::<::do_not_bind_golden::Struct>() == 4);
#[unsafe(no_mangle)]
unsafe extern "C" fn __crubit_thunk_bound_uinherent_umethod(
__self: &'static ::do_not_bind_golden::Struct,
) -> i32 {
unsafe { ::do_not_bind_golden::Struct::bound_inherent_method(__self) }
}
const _: () = assert!(::core::mem::offset_of!(::do_not_bind_golden::Struct, value) == 0);
#[unsafe(no_mangle)]
unsafe extern "C" fn __crubit_thunk_bound_ufree_ufn() -> i32 {
unsafe { ::do_not_bind_golden::bound_free_fn() }
}
#[unsafe(no_mangle)]
unsafe extern "C" fn __crubit_thunk_Trait_ubound_utrait_umethod_udo_unot_ubind_ugolden_x0000003a_x0000003aStruct(
__self: &'static ::do_not_bind_golden::Struct,
) -> i32 {
unsafe {
<::do_not_bind_golden::Struct as ::do_not_bind_golden::Trait>::bound_trait_method(__self)
}
}
41 changes: 41 additions & 0 deletions cc_bindings_from_rs/test/do_not_bind/do_not_bind_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Part of the Crubit project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include "cc_bindings_from_rs/test/do_not_bind/do_not_bind.h"

#include "gtest/gtest.h"

namespace do_not_bind {
namespace {

using TraitImpl = rs_std::impl<Struct, Trait>;

// `do_not_bind` used to parse and then be silently dropped on associated items,
// so assert absence directly rather than relying only on the golden. These must
// be dependent on `T` for the requires-expression to soft-fail.
template <typename T>
concept HasSuppressedInherentMethod =
requires(const T& s) { s.suppressed_inherent_method(); };

template <typename T>
concept HasSuppressedTraitMethod = requires(const T& s) {
rs_std::impl<T, Trait>::suppressed_trait_method(s);
};

static_assert(!HasSuppressedInherentMethod<Struct>);
static_assert(!HasSuppressedTraitMethod<Struct>);

TEST(DoNotBindTest, UnannotatedItemsStillReceiveBindings) {
Struct s = {.value = 0};
EXPECT_EQ(bound_free_fn(), 2);
EXPECT_EQ(s.bound_inherent_method(), 4);
EXPECT_EQ(TraitImpl::bound_trait_method(s), 6);
}

TEST(DoNotBindTest, SuppressingOneMethodKeepsTheTraitImplemented) {
static_assert(TraitImpl::kIsImplemented);
}

} // namespace
} // namespace do_not_bind
Loading