blob: 5f081e000556c3bf82e79002f5e89e100255f06c [file] [edit]
// 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
// IWYU pragma: private, include "support/annotations.h"
#ifndef CRUBIT_SUPPORT_ANNOTATIONS_INTERNAL_H_
#define CRUBIT_SUPPORT_ANNOTATIONS_INTERNAL_H_
#if defined(__clang__)
#define CRUBIT_TRIVIAL_ABI [[clang::trivial_abi]]
#define CRUBIT_VIEW [[gsl::Pointer]]
#if __has_cpp_attribute(clang::lifetimebound)
#define CRUBIT_LIFETIME_BOUND [[clang::lifetimebound]]
#elif __has_attribute(lifetimebound)
#define CRUBIT_LIFETIME_BOUND __attribute__((lifetimebound))
#else
#define CRUBIT_LIFETIME_BOUND
#endif
#define crubit_nonnull _Nonnull
#define crubit_nullable _Nullable
#else
#define CRUBIT_TRIVIAL_ABI
#define CRUBIT_VIEW
#define CRUBIT_LIFETIME_BOUND
#define crubit_nonnull
#define crubit_nullable
#endif
#if defined(_MSC_VER) && !defined(__clang__)
#define CRUBIT_UNREACHABLE() __assume(false)
#else
#define CRUBIT_UNREACHABLE() __builtin_unreachable()
#endif
// Style waiver granted in crubit.rs-style-waiver-attribute-annotate
#if defined(__clang__) && __has_cpp_attribute(clang::annotate) && \
__has_cpp_attribute(clang::annotate_type)
#define CRUBIT_INTERNAL_ANNOTATE(...) [[clang::annotate(__VA_ARGS__)]]
#define CRUBIT_INTERNAL_ANNOTATE_TYPE(...) [[clang::annotate_type(__VA_ARGS__)]]
#else
#define CRUBIT_INTERNAL_ANNOTATE(...)
#define CRUBIT_INTERNAL_ANNOTATE_TYPE(...)
#endif
#define CRUBIT_INTERNAL_EXPAND_AND_CONCAT_IMPL(a, b) a##b
#define CRUBIT_INTERNAL_EXPAND_AND_CONCAT(a, b) \
CRUBIT_INTERNAL_EXPAND_AND_CONCAT_IMPL(a, b)
namespace crubit::rust_type {
// Helper for CRUBIT_INTERNAL_RUST_TYPE. This type should never be used
// directly.
template <typename...>
struct Args {};
// Helper for CRUBIT_INTERNAL_RUST_TYPE. Instantiations of this type can be used
// to represent const-generic arguments in Rust.
//
// Example:
//
// ```cpp
// template <typename T, int N>
// struct CRUBIT_INTERNAL_RUST_TYPE("MyType", T, crubit::rust_type::Const<N>)
// MyType {};
// ```
//
// `MyType<T, 123>` in C++ will then be mapped to `MyType<T, 123>` in Rust.
template <auto>
struct Const {};
} // namespace crubit::rust_type
// Unsafe: disables bindings, and reinterprets all uses of this type as `t`.
//
// This attribute completely disables automated bindings for the type which it
// appertains to. All uses of that type are replaced with uses of `t`, which
// must be a Rust type which exists and is guaranteed to be available by that
// name.
//
// This can be applied to a struct, class, or enum.
//
// If CRUBIT_INTERNAL_SAME_ABI is also specified, then the Rust
// type will be assumed to be exactly C ABI compatible (not just of identical
// layout) with `t`.
//
// For example, this C++ header:
//
// ```c++
// struct
// CRUBIT_INTERNAL_RUST_TYPE("char")
// CRUBIT_INTERNAL_SAME_ABI
// CharT {
// std::uint32_t c;
// };
// CharT foo() { return {0};}
// ```
//
// Becomes this Rust interface:
//
// ```rust
// pub fn foo() -> char; // returns '\0'
// ```
//
// How to spell `t`:
//
// A path in `t` is spelled from the point of view of the Rust crate that
// corresponds to the Bazel target defining the annotated C++ declaration (when
// that target is the one bindings are being generated for, this is the crate
// being generated):
//
// * `::some_crate::path::To::Type` names a crate explicitly: the first path
// segment is a crate name, and the path is used exactly as spelled.
// * `crate::path::To::Type` refers to that crate itself. Use this spelling
// for items defined in the same target as the annotated declaration,
// rather than naming that target's crate, so that the path keeps working
// when the crate is renamed, e.g. by crate name mangling
// (`use_label_encoded_names_for_deps`).
// * `path::To::Type` is relative to the root of that same crate, i.e. it is
// equivalent to `crate::path::To::Type`. Its first path segment names a
// module, not a crate.
//
// SAFETY:
// If the type is not layout-compatible with `t`, the behavior is undefined.
#define CRUBIT_INTERNAL_RUST_TYPE(t, ...) \
CRUBIT_INTERNAL_ANNOTATE("crubit_internal_rust_type", t, \
crubit::rust_type::Args<__VA_ARGS__>())
// Unsafe: forces a type to be treated as C abi compatible with its rust
// equivalent.
//
// This only has any effect when used in combination with
// CRUBIT_INTERNAL_RUST_TYPE. For all other types, C ABI compatibility can be
// inferred automatically, and overriding the decision is always a bug.
//
// SAFETY:
// If the type is not ABI-compatible with its Rust equivalent, the behavior is
// undefined.
#define CRUBIT_INTERNAL_SAME_ABI \
CRUBIT_INTERNAL_ANNOTATE("crubit_internal_same_abi")
// (Optional) The target that owns the Rust type for CRUBIT_INTERNAL_RUST_TYPE.
// Format: "//package:target" or a short-form like "@abseil-cpp//absl/status".
//
// This is only meaningful for a Rust type spelled as an explicit
// `::some_crate::path::To::Type` path (see "How to spell `t`" above): when
// crate name mangling is enabled (e.g. `use_label_encoded_names_for_deps`) and
// `some_crate` matches the target name of the hint, `some_crate` is replaced
// with the mangled crate name of the hint target. It is required when the C++
// type's owning target differs from the target providing its Rust bindings
// (e.g. `absl::StatusOr` in `@abseil-cpp//absl/status:statusor`, whose Rust
// type is provided by `@abseil-cpp//absl/status:status`); otherwise the
// owning target is inferred.
//
// The other two spellings need no hint: their crate is already the one
// corresponding to the target defining the annotated declaration, and Crubit
// spells it with the mangled crate name where necessary. In particular, a
// relative path is *not* rewritten, since its first segment names a module
// rather than a crate.
#define CRUBIT_INTERNAL_RUST_TYPE_LABEL_HINT(label_hint) \
CRUBIT_INTERNAL_ANNOTATE("crubit_internal_rust_type_label_hint", label_hint)
#define CRUBIT_INTERNAL_RUST_TYPE_WITH_HINT(t, label_hint, ...) \
CRUBIT_INTERNAL_RUST_TYPE(t, __VA_ARGS__) \
CRUBIT_INTERNAL_RUST_TYPE_LABEL_HINT(label_hint)
#endif // CRUBIT_SUPPORT_ANNOTATIONS_INTERNAL_H_