Skip to content

Commit f97b528

Browse files
committed
Use lifetimebound and normalize the Array API
get() should return Option<const T&> to match get_mut().
1 parent 32db84b commit f97b528

File tree

7 files changed

+48
-47
lines changed

7 files changed

+48
-47
lines changed

subspace/choice/choice.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "subspace/choice/__private/storage.h"
2828
#include "subspace/choice/__private/type_list.h"
2929
#include "subspace/choice/choice_types.h"
30+
#include "subspace/macros/lifetimebound.h"
3031
#include "subspace/macros/no_unique_address.h"
3132
#include "subspace/marker/unsafe.h"
3233
#include "subspace/mem/clone.h"
@@ -614,7 +615,7 @@ class Choice<__private::TypeList<Ts...>, Tags...> final {
614615
/// types is not known here.
615616
template <auto Tag, class... Ts>
616617
[[nodiscard]] inline constexpr auto choice(
617-
Ts&&... vs sus_if_clang([[clang::lifetimebound]])) noexcept {
618+
Ts&&... vs sus_lifetimebound) noexcept {
618619
if constexpr (sizeof...(Ts) == 0) {
619620
return __private::ChoiceMarkerVoid<Tag>();
620621
} else if constexpr (sizeof...(Ts) == 1) {

subspace/containers/array.h

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,9 @@
2626
#include "subspace/containers/__private/array_marker.h"
2727
#include "subspace/containers/__private/slice_iter.h"
2828
#include "subspace/containers/slice.h"
29-
#include "subspace/fn/fn_box_defn.h"
3029
#include "subspace/fn/fn_concepts.h"
3130
#include "subspace/fn/run_fn.h"
32-
#include "subspace/macros/compiler.h"
31+
#include "subspace/macros/lifetimebound.h"
3332
#include "subspace/marker/unsafe.h"
3433
#include "subspace/mem/clone.h"
3534
#include "subspace/mem/copy.h"
@@ -172,17 +171,17 @@ class Array final {
172171
constexpr usize len() const& noexcept { return N; }
173172

174173
/// Returns a const reference to the element at index `i`.
175-
constexpr Option<const T&> at(usize i) const& noexcept
174+
constexpr Option<const T&> get(usize i) const& noexcept sus_lifetimebound
176175
requires(N > 0)
177176
{
178177
if (i.primitive_value >= N) [[unlikely]]
179178
return Option<const T&>::none();
180179
return Option<const T&>::some(storage_.data_[i.primitive_value]);
181180
}
182-
constexpr Option<const T&> at(usize i) && = delete;
181+
constexpr Option<const T&> get(usize i) && = delete;
183182

184183
/// Returns a mutable reference to the element at index `i`.
185-
constexpr Option<T&> get_mut(usize i) & noexcept
184+
constexpr Option<T&> get_mut(usize i) & noexcept sus_lifetimebound
186185
requires(N > 0)
187186
{
188187
if (i.primitive_value >= N) [[unlikely]]
@@ -195,8 +194,8 @@ class Array final {
195194
/// # Safety
196195
/// The index `i` must be inside the bounds of the array or Undefined
197196
/// Behaviour results.
198-
constexpr inline const T& get_unchecked(::sus::marker::UnsafeFnMarker,
199-
usize i) const& noexcept
197+
constexpr inline const T& get_unchecked(
198+
::sus::marker::UnsafeFnMarker, usize i) const& noexcept sus_lifetimebound
200199
requires(N > 0)
201200
{
202201
return storage_.data_[i.primitive_value];
@@ -210,63 +209,64 @@ class Array final {
210209
/// The index `i` must be inside the bounds of the array or Undefined
211210
/// Behaviour results.
212211
constexpr inline T& get_unchecked_mut(::sus::marker::UnsafeFnMarker,
213-
usize i) & noexcept
212+
usize i) & noexcept sus_lifetimebound
214213
requires(N > 0)
215214
{
216215
return storage_.data_[i.primitive_value];
217216
}
218217

219-
constexpr inline const T& operator[](usize i) const& noexcept {
218+
constexpr inline const T& operator[](usize i) const& noexcept
219+
sus_lifetimebound {
220220
check(i.primitive_value < N);
221221
return storage_.data_[i.primitive_value];
222222
}
223223
constexpr inline const T& operator[](usize i) && = delete;
224224

225-
constexpr inline T& operator[](usize i) & noexcept {
225+
constexpr inline T& operator[](usize i) & noexcept sus_lifetimebound {
226226
check(i.primitive_value < N);
227227
return storage_.data_[i.primitive_value];
228228
}
229229

230230
/// Returns a const pointer to the first element in the array.
231-
inline const T* as_ptr() const& noexcept
231+
inline const T* as_ptr() const& noexcept sus_lifetimebound
232232
requires(N > 0)
233233
{
234234
return storage_.data_;
235235
}
236236
const T* as_ptr() && = delete;
237237

238238
/// Returns a mutable pointer to the first element in the array.
239-
inline T* as_mut_ptr() & noexcept
239+
inline T* as_mut_ptr() & noexcept sus_lifetimebound
240240
requires(N > 0)
241241
{
242242
return storage_.data_;
243243
}
244244

245245
// Returns a slice that references all the elements of the array as const
246246
// references.
247-
constexpr Slice<const T> as_ref() const& noexcept {
247+
constexpr Slice<const T> as_slice() const& noexcept sus_lifetimebound {
248248
return Slice<const T>::from(storage_.data_);
249249
}
250-
constexpr Slice<const T> as_ref() && = delete;
250+
constexpr Slice<const T> as_slice() && = delete;
251251

252252
// Returns a slice that references all the elements of the array as mutable
253253
// references.
254-
constexpr Slice<T> as_mut() & noexcept {
254+
constexpr Slice<T> as_mut_slice() & noexcept sus_lifetimebound {
255255
return Slice<T>::from(storage_.data_);
256256
}
257257

258258
/// Returns an iterator over all the elements in the array, visited in the
259259
/// same order they appear in the array. The iterator gives const access to
260260
/// each element.
261-
constexpr SliceIter<const T&> iter() const& noexcept {
261+
constexpr SliceIter<const T&> iter() const& noexcept sus_lifetimebound {
262262
return SliceIter<const T&>::with(storage_.data_, N);
263263
}
264264
constexpr SliceIter<const T&> iter() && = delete;
265265

266266
/// Returns an iterator over all the elements in the array, visited in the
267267
/// same order they appear in the array. The iterator gives mutable access to
268268
/// each element.
269-
constexpr SliceIterMut<T&> iter_mut() & noexcept {
269+
constexpr SliceIterMut<T&> iter_mut() & noexcept sus_lifetimebound {
270270
return SliceIterMut<T&>::with(storage_.data_, N);
271271
}
272272

@@ -331,7 +331,8 @@ class Array final {
331331
template <class U, size_t... Is>
332332
constexpr inline auto eq_impl(const Array<U, N>& r,
333333
std::index_sequence<Is...>) const& noexcept {
334-
return (... && (at(Is) == r.at(Is)));
334+
return (... && (get_unchecked(::sus::marker::unsafe_fn, Is) ==
335+
r.get_unchecked(::sus::marker::unsafe_fn, Is)));
335336
};
336337

337338
// Using a union ensures that the default constructor doesn't initialize
@@ -350,7 +351,8 @@ namespace __private {
350351
template <size_t I, class O, class T, class U, size_t N>
351352
constexpr inline bool array_cmp_impl(O& val, const Array<T, N>& l,
352353
const Array<U, N>& r) noexcept {
353-
auto cmp = l.at(I) <=> r.at(I);
354+
auto cmp = l.get_unchecked(::sus::marker::unsafe_fn, I) <=>
355+
r.get_unchecked(::sus::marker::unsafe_fn, I);
354356
// Allow downgrading from equal to equivalent, but not the inverse.
355357
if (cmp != 0) val = cmp;
356358
// Short circuit by returning true when we find a difference.
@@ -432,7 +434,7 @@ auto get(Array<T, N>&& a) noexcept {
432434
template <class... Ts>
433435
requires(sizeof...(Ts) > 0)
434436
[[nodiscard]] inline constexpr auto array(
435-
Ts&&... vs sus_if_clang([[clang::lifetimebound]])) noexcept {
437+
Ts&&... vs sus_lifetimebound) noexcept {
436438
return __private::ArrayMarker<Ts...>(
437439
::sus::tuple_type::Tuple<Ts&&...>::with(::sus::forward<Ts>(vs)...));
438440
}

subspace/containers/array_unittest.cc

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -232,14 +232,14 @@ TEST(Array, Get) {
232232
constexpr auto r = []() constexpr {
233233
constexpr auto a =
234234
Array<int, 5>::with_initializer([i = 0]() mutable { return ++i; });
235-
return a.at(2_usize).unwrap();
235+
return a.get(2_usize).unwrap();
236236
}();
237237
static_assert(std::same_as<decltype(r), const int>);
238238
EXPECT_EQ(3, r);
239239
}
240240
{
241241
auto a = Array<int, 5>::with_initializer([i = 0]() mutable { return ++i; });
242-
EXPECT_EQ(3, a.at(2_usize).unwrap());
242+
EXPECT_EQ(3, a.get(2_usize).unwrap());
243243
}
244244
}
245245

@@ -481,18 +481,18 @@ TEST(ArrayDeathTest, Index) {
481481
#endif
482482
}
483483

484-
TEST(Array, AsRef) {
484+
TEST(Array, AsSlice) {
485485
auto x = [](sus::Slice<const i32>) {};
486486
const auto ac = Array<i32, 3>::with_value(2);
487487
auto am = Array<i32, 3>::with_value(2);
488-
x(ac.as_ref());
489-
x(am.as_ref());
488+
x(ac.as_slice());
489+
x(am.as_slice());
490490
}
491491

492-
TEST(Array, AsMut) {
492+
TEST(Array, AsMutSlice) {
493493
auto x = [](sus::Slice<i32>) {};
494494
auto am = Array<i32, 3>::with_value(2);
495-
x(am.as_mut());
495+
x(am.as_mut_slice());
496496
}
497497

498498
TEST(Array, Clone) {

subspace/containers/slice_unittest.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ TEST(Slice, Sort) {
427427
);
428428
// clang-format on
429429

430-
Slice<Sortable> s = unsorted.as_mut();
430+
Slice<Sortable> s = unsorted.as_mut_slice();
431431
s.sort();
432432
for (usize i = 0u; i < s.len(); i += 1u) {
433433
EXPECT_EQ(sorted[i], s[i]);
@@ -460,7 +460,7 @@ TEST(Slice, SortBy) {
460460
);
461461
// clang-format on
462462

463-
Slice<Sortable> s = unsorted.as_mut();
463+
Slice<Sortable> s = unsorted.as_mut_slice();
464464
// Sorts backward.
465465
s.sort_by([](const auto& a, const auto& b) { return b <=> a; });
466466
for (usize i = 0u; i < s.len(); i += 1u) {
@@ -472,7 +472,7 @@ TEST(Slice, SortUnstable) {
472472
sus::Array<i32, 6> unsorted = sus::array(3, 4, 2, 1, 6, 5);
473473
sus::Array<i32, 6> sorted = sus::array(1, 2, 3, 4, 5, 6);
474474

475-
Slice<i32> s = unsorted.as_mut();
475+
Slice<i32> s = unsorted.as_mut_slice();
476476
s.sort_unstable();
477477
for (usize i = 0u; i < s.len(); i += 1u) {
478478
EXPECT_EQ(sorted[i], s[i]);
@@ -483,7 +483,7 @@ TEST(Slice, SortUnstableBy) {
483483
sus::Array<i32, 6> unsorted = sus::array(3, 4, 2, 1, 6, 5);
484484
sus::Array<i32, 6> sorted = sus::array(6, 5, 4, 3, 2, 1);
485485

486-
Slice<i32> s = unsorted.as_mut();
486+
Slice<i32> s = unsorted.as_mut_slice();
487487
// Sorts backward.
488488
s.sort_unstable_by([](const auto& a, const auto& b) { return b <=> a; });
489489
for (usize i = 0u; i < s.len(); i += 1u) {

subspace/containers/vec.h

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
#include "subspace/fn/run_fn.h"
2828
#include "subspace/iter/from_iterator.h"
2929
#include "subspace/iter/into_iterator.h"
30-
#include "subspace/macros/compiler.h"
3130
#include "subspace/macros/lifetimebound.h"
3231
#include "subspace/mem/move.h"
3332
#include "subspace/mem/relocate.h"
@@ -446,8 +445,8 @@ class Vec {
446445
void sort() { as_mut_slice().sort(); }
447446

448447
/// #[doc.inherit=[n]sus::[n]containers::[r]Slice::[f]sort_by]
449-
template <::sus::fn::FnMut<::sus::fn::NonVoid(const T&, const T&)> F,
450-
int&..., class R = std::invoke_result_t<F, const T&, const T&>>
448+
template <::sus::fn::FnMut<::sus::fn::NonVoid(const T&, const T&)> F, int&...,
449+
class R = std::invoke_result_t<F, const T&, const T&>>
451450
requires(::sus::ops::Ordering<R>)
452451
void sort_by(F compare) {
453452
as_mut_slice().sort_by(sus::move(compare));
@@ -457,8 +456,8 @@ class Vec {
457456
void sort_unstable() { as_mut_slice().sort(); }
458457

459458
/// #[doc.inherit=[n]sus::[n]containers::[r]Slice::[f]sort_unstable_by]
460-
template <::sus::fn::FnMut<::sus::fn::NonVoid(const T&, const T&)> F,
461-
int&..., class R = std::invoke_result_t<F, const T&, const T&>>
459+
template <::sus::fn::FnMut<::sus::fn::NonVoid(const T&, const T&)> F, int&...,
460+
class R = std::invoke_result_t<F, const T&, const T&>>
462461
requires(::sus::ops::Ordering<R>)
463462
void sort_unstable_by(F compare) {
464463
as_mut_slice().sort_by(sus::move(compare));
@@ -597,8 +596,7 @@ using sus::iter::__private::end;
597596
// the result of `sus::vec()` as a function argument or return value.
598597
template <class... Ts>
599598
requires(sizeof...(Ts) > 0)
600-
[[nodiscard]] inline constexpr auto vec(
601-
Ts&&... vs sus_if_clang([[clang::lifetimebound]])) noexcept {
599+
[[nodiscard]] inline constexpr auto vec(Ts&&... vs sus_lifetimebound) noexcept {
602600
return __private::VecMarker<Ts...>(
603601
::sus::tuple_type::Tuple<Ts&&...>::with(::sus::forward<Ts>(vs)...));
604602
}

subspace/result/result.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -706,8 +706,7 @@ using sus::iter::__private::end;
706706
/// construct Result<T, E>. This is to deduce the actual types `T` and `E` when
707707
/// it is constructed, avoid specifying them both here, and support conversions.
708708
template <class T>
709-
[[nodiscard]] inline constexpr auto ok(
710-
T&& t sus_if_clang([[clang::lifetimebound]])) noexcept {
709+
[[nodiscard]] inline constexpr auto ok(T&& t sus_lifetimebound) noexcept {
711710
return __private::OkMarker<T&&>(::sus::forward<T>(t));
712711
}
713712

@@ -717,8 +716,7 @@ template <class T>
717716
/// construct Result<T, E>. This is to deduce the actual types `T` and `E` when
718717
/// it is constructed, avoid specifying them both here, and support conversions.
719718
template <class E>
720-
[[nodiscard]] inline constexpr auto err(
721-
E&& e sus_if_clang([[clang::lifetimebound]])) noexcept {
719+
[[nodiscard]] inline constexpr auto err(E&& e sus_lifetimebound) noexcept {
722720
return __private::ErrMarker<E&&>(::sus::forward<E>(e));
723721
}
724722

subspace/tuple/tuple.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "subspace/assertions/check.h"
2121
#include "subspace/construct/default.h"
2222
#include "subspace/macros/__private/compiler_bugs.h"
23+
#include "subspace/macros/lifetimebound.h"
2324
#include "subspace/macros/no_unique_address.h"
2425
#include "subspace/mem/clone.h"
2526
#include "subspace/mem/copy.h"
@@ -74,15 +75,16 @@ class Tuple final {
7475
///
7576
/// The Tuple's contained types must all be #Default, and will be
7677
/// constructed through that trait.
78+
// clang-format off
7779
inline constexpr Tuple() noexcept
78-
//clang-format off
7980
requires(!((std::is_trivially_default_constructible_v<T> && ... &&
8081
std::is_trivially_default_constructible_v<Ts>) &&
81-
!(std::is_reference_v<T> || ... || std::is_reference_v<Ts>)) &&
82+
!(std::is_reference_v<T> || ... || std::is_reference_v<Ts>)
83+
) &&
8284
(::sus::construct::Default<T> && ... &&
8385
::sus::construct::Default<Ts>))
84-
//clang-format on
8586
: Tuple(T(), Ts()...) {}
87+
// clang-format on
8688

8789
Tuple()
8890
requires((std::is_trivially_default_constructible_v<T> && ... &&
@@ -263,7 +265,7 @@ struct TupleMarker {
263265
template <class... Ts>
264266
requires(sizeof...(Ts) > 0)
265267
[[nodiscard]] inline constexpr auto tuple(
266-
Ts&&... vs sus_if_clang([[clang::lifetimebound]])) noexcept {
268+
Ts&&... vs sus_lifetimebound) noexcept {
267269
return __private::TupleMarker<Ts...>(
268270
::sus::tuple_type::Tuple<Ts&&...>::with(::sus::forward<Ts>(vs)...));
269271
}

0 commit comments

Comments
 (0)