Skip to content

Commit 2aab4c9

Browse files
thunderseethecopybara-github
authored andcommitted
Add C++ rs_std::usize and rs_std::isize wrappers in int.h
These will be used by template specializations to disambiguate between a specialization of `usize` and `u64`/`u32` (or `isize and `i64`/`i32`) when those might be the same type in C++. `rs_std::usize` and `rs_std::isize` will always be considered a new type in C++ and will never overlap with fundamental types. PiperOrigin-RevId: 949185268
1 parent 226b2e7 commit 2aab4c9

5 files changed

Lines changed: 245 additions & 0 deletions

File tree

support/rs_std/BUILD

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,33 @@ cc_library(
3636
],
3737
)
3838

39+
cc_library(
40+
name = "int",
41+
hdrs = ["int.h"],
42+
aspect_hints = ["//features:experimental"],
43+
compatible_with = ["//buildenv/target:non_prod"],
44+
tags = [
45+
"alt_dep=//support/public:int",
46+
"avoid_dep",
47+
],
48+
visibility = [
49+
"//visibility:public",
50+
],
51+
deps = [
52+
"//support:annotations",
53+
],
54+
)
55+
56+
crubit_cc_test(
57+
name = "int_test",
58+
srcs = ["int_test.cc"],
59+
deps = [
60+
":int",
61+
"@fuzztest//:fuzztest_gtest_main",
62+
"@googletest//:gmock",
63+
],
64+
)
65+
3966
alias(
4067
name = "rs_char",
4168
actual = "//support/rs_std:char",

support/rs_std/BUILD.gn

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,23 @@ source_set("dyn_erased_future_cc") {
6565
]
6666
}
6767

68+
source_set("int") {
69+
public_configs = [ "$crubit_src_dir:config" ]
70+
if (defined(crubit_gn_configs_to_remove)) {
71+
configs -= crubit_gn_configs_to_remove
72+
}
73+
if (defined(crubit_gn_support_configs_to_add)) {
74+
configs += crubit_gn_support_configs_to_add
75+
}
76+
77+
public = [
78+
"int.h",
79+
]
80+
deps = [
81+
"$crubit_src_dir/support:annotations",
82+
]
83+
}
84+
6885
source_set("iterator_adapter") {
6986
public_configs = [ "$crubit_src_dir:config" ]
7087
if (defined(crubit_gn_configs_to_remove)) {
@@ -330,6 +347,7 @@ group("rs_std_cpp") {
330347
":char",
331348
":dyn_callable",
332349
":dyn_erased_future_cc",
350+
":int",
333351
":iterator_adapter",
334352
":lossy_formatter_for_bindings",
335353
":option",

support/rs_std/CMakeLists.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,19 @@ target_link_libraries(crubit_support_rs_std_dyn_erased_future_cc INTERFACE
4949
crubit_support_rs_std_waker
5050
)
5151

52+
add_library(crubit_support_rs_std_int INTERFACE
53+
"int.h"
54+
)
55+
set_target_properties(crubit_support_rs_std_int PROPERTIES LINKER_LANGUAGE CXX)
56+
57+
target_include_directories(crubit_support_rs_std_int INTERFACE
58+
"${CMAKE_CURRENT_SOURCE_DIR}/../.."
59+
)
60+
61+
target_link_libraries(crubit_support_rs_std_int INTERFACE
62+
crubit_support_annotations
63+
)
64+
5265
add_library(crubit_support_rs_std_iterator_adapter INTERFACE
5366
"iterator_adapter.h"
5467
)

support/rs_std/int.h

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
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+
// IWYU pragma: private, include "support/rs_std/int.h"
6+
7+
#ifndef CRUBIT_SUPPORT_RS_STD_INT_H_
8+
#define CRUBIT_SUPPORT_RS_STD_INT_H_
9+
10+
#include <compare>
11+
#include <cstdint>
12+
#include <type_traits>
13+
14+
#include "support/annotations.h"
15+
16+
namespace rs_std {
17+
18+
// `rs_std::usize` is a C++ representation of the `usize` type from Rust when
19+
// used as a template argument inside template specializations (such as
20+
// `rs_std::Option<T>`). This prevents C++ explicit template specialization
21+
// redefinition errors or overload collisions between `usize`, `u64`, and `u32`.
22+
class CRUBIT_INTERNAL_RUST_TYPE("usize") CRUBIT_INTERNAL_SAME_ABI usize final {
23+
public:
24+
constexpr usize() noexcept = default;
25+
26+
// Implicit constructing conversion from standard integer types.
27+
// NOLINTNEXTLINE(google-explicit-constructor)
28+
constexpr usize(::std::uintptr_t value) noexcept : value_(value) {}
29+
30+
constexpr usize(const usize&) noexcept = default;
31+
constexpr usize& operator=(const usize&) noexcept = default;
32+
33+
// Implicit conversion back to `::std::uintptr_t` for seamless indexing and
34+
// arithmetic in C++.
35+
// NOLINTNEXTLINE(google-explicit-constructor)
36+
constexpr operator ::std::uintptr_t() const noexcept { return value_; }
37+
38+
friend constexpr bool operator==(usize lhs, usize rhs) noexcept = default;
39+
friend constexpr std::strong_ordering operator<=>(
40+
usize lhs, usize rhs) noexcept = default;
41+
42+
friend constexpr usize operator+(usize lhs, usize rhs) noexcept {
43+
return usize(lhs.value_ + rhs.value_);
44+
}
45+
friend constexpr usize operator-(usize lhs, usize rhs) noexcept {
46+
return usize(lhs.value_ - rhs.value_);
47+
}
48+
constexpr usize& operator+=(usize rhs) noexcept {
49+
value_ += rhs.value_;
50+
return *this;
51+
}
52+
constexpr usize& operator-=(usize rhs) noexcept {
53+
value_ -= rhs.value_;
54+
return *this;
55+
}
56+
57+
private:
58+
::std::uintptr_t value_ = 0;
59+
};
60+
61+
static_assert(sizeof(usize) == sizeof(::std::uintptr_t));
62+
static_assert(alignof(usize) == alignof(::std::uintptr_t));
63+
static_assert(::std::is_trivially_copyable_v<usize>);
64+
static_assert(::std::is_trivially_destructible_v<usize>);
65+
66+
// `rs_std::isize` is a C++ representation of the `isize` type from Rust when
67+
// used as a template argument inside template specializations (such as
68+
// `rs_std::Option<T>`). This prevents C++ explicit template specialization
69+
// redefinition errors or overload collisions between `isize`, `i64`, and `i32`.
70+
class CRUBIT_INTERNAL_RUST_TYPE("isize") CRUBIT_INTERNAL_SAME_ABI isize final {
71+
public:
72+
constexpr isize() noexcept = default;
73+
74+
// Implicit constructing conversion from standard integer types.
75+
// NOLINTNEXTLINE(google-explicit-constructor)
76+
constexpr isize(::std::intptr_t value) noexcept : value_(value) {}
77+
78+
constexpr isize(const isize&) noexcept = default;
79+
constexpr isize& operator=(const isize&) noexcept = default;
80+
81+
// Implicit conversion back to `::std::intptr_t` for seamless arithmetic and
82+
// conversion in C++.
83+
// NOLINTNEXTLINE(google-explicit-constructor)
84+
constexpr operator ::std::intptr_t() const noexcept { return value_; }
85+
86+
friend constexpr bool operator==(isize lhs, isize rhs) noexcept = default;
87+
friend constexpr auto operator<=>(isize lhs, isize rhs) noexcept = default;
88+
89+
friend constexpr isize operator+(isize lhs, isize rhs) noexcept {
90+
return isize(lhs.value_ + rhs.value_);
91+
}
92+
friend constexpr isize operator-(isize lhs, isize rhs) noexcept {
93+
return isize(lhs.value_ - rhs.value_);
94+
}
95+
constexpr isize& operator+=(isize rhs) noexcept {
96+
value_ += rhs.value_;
97+
return *this;
98+
}
99+
constexpr isize& operator-=(isize rhs) noexcept {
100+
value_ -= rhs.value_;
101+
return *this;
102+
}
103+
104+
private:
105+
::std::intptr_t value_ = 0;
106+
};
107+
108+
static_assert(sizeof(isize) == sizeof(::std::intptr_t));
109+
static_assert(alignof(isize) == alignof(::std::intptr_t));
110+
static_assert(::std::is_trivially_copyable_v<isize>);
111+
static_assert(::std::is_trivially_destructible_v<isize>);
112+
113+
} // namespace rs_std
114+
115+
#endif // CRUBIT_SUPPORT_RS_STD_INT_H_

support/rs_std/int_test.cc

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
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 "support/rs_std/int.h"
6+
7+
#include <cstdint>
8+
#include <type_traits>
9+
10+
#include "gtest/gtest.h"
11+
12+
namespace {
13+
14+
static_assert(std::is_nothrow_default_constructible_v<rs_std::usize>);
15+
static_assert(std::is_trivially_destructible_v<rs_std::usize>);
16+
static_assert(std::is_trivially_copyable_v<rs_std::usize>);
17+
static_assert(std::is_trivially_copy_constructible_v<rs_std::usize>);
18+
static_assert(std::is_trivially_copy_assignable_v<rs_std::usize>);
19+
static_assert(std::is_trivially_move_constructible_v<rs_std::usize>);
20+
static_assert(std::is_trivially_move_assignable_v<rs_std::usize>);
21+
static_assert(sizeof(rs_std::usize) == sizeof(std::uintptr_t));
22+
static_assert(alignof(rs_std::usize) == alignof(std::uintptr_t));
23+
24+
static_assert(std::is_nothrow_default_constructible_v<rs_std::isize>);
25+
static_assert(std::is_trivially_destructible_v<rs_std::isize>);
26+
static_assert(std::is_trivially_copyable_v<rs_std::isize>);
27+
static_assert(std::is_trivially_copy_constructible_v<rs_std::isize>);
28+
static_assert(std::is_trivially_copy_assignable_v<rs_std::isize>);
29+
static_assert(std::is_trivially_move_constructible_v<rs_std::isize>);
30+
static_assert(std::is_trivially_move_assignable_v<rs_std::isize>);
31+
static_assert(sizeof(rs_std::isize) == sizeof(std::intptr_t));
32+
static_assert(alignof(rs_std::isize) == alignof(std::intptr_t));
33+
34+
TEST(UsizeTest, DefaultConstructor) {
35+
rs_std::usize value;
36+
EXPECT_EQ(value, rs_std::usize(0));
37+
}
38+
39+
TEST(UsizeTest, ImplicitConversions) {
40+
rs_std::usize val = 42;
41+
std::uintptr_t raw = val;
42+
EXPECT_EQ(raw, 42);
43+
}
44+
45+
TEST(UsizeTest, ArithmeticAndComparisons) {
46+
rs_std::usize a = 10;
47+
rs_std::usize b = 20;
48+
EXPECT_LT(a, b);
49+
EXPECT_EQ(a + b, rs_std::usize(30));
50+
EXPECT_EQ(b - a, rs_std::usize(10));
51+
}
52+
53+
TEST(IsizeTest, DefaultConstructor) {
54+
rs_std::isize value;
55+
EXPECT_EQ(value, rs_std::isize(0));
56+
}
57+
58+
TEST(IsizeTest, ImplicitConversions) {
59+
rs_std::isize val = -42;
60+
std::intptr_t raw = val;
61+
EXPECT_EQ(raw, -42);
62+
}
63+
64+
TEST(IsizeTest, ArithmeticAndComparisons) {
65+
rs_std::isize a = -10;
66+
rs_std::isize b = 20;
67+
EXPECT_LT(a, b);
68+
EXPECT_EQ(a + b, rs_std::isize(10));
69+
EXPECT_EQ(b - a, rs_std::isize(30));
70+
}
71+
72+
} // namespace

0 commit comments

Comments
 (0)