Commit 2655d3d1 authored by Anton Bikineev's avatar Anton Bikineev Committed by V8 LUCI CQ

api: Allow v8::Maybe<MovableType>.

Change-Id: I29bcdf3302f37568e8c8925e70a01ba342c17925
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3606229Reviewed-by: 's avatarMichael Lippautz <mlippautz@chromium.org>
Commit-Queue: Anton Bikineev <bikineev@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80288}
parent 896f6e74
...@@ -5,6 +5,9 @@ ...@@ -5,6 +5,9 @@
#ifndef INCLUDE_V8_MAYBE_H_ #ifndef INCLUDE_V8_MAYBE_H_
#define INCLUDE_V8_MAYBE_H_ #define INCLUDE_V8_MAYBE_H_
#include <type_traits>
#include <utility>
#include "v8-internal.h" // NOLINT(build/include_directory) #include "v8-internal.h" // NOLINT(build/include_directory)
#include "v8config.h" // NOLINT(build/include_directory) #include "v8config.h" // NOLINT(build/include_directory)
...@@ -57,11 +60,20 @@ class Maybe { ...@@ -57,11 +60,20 @@ class Maybe {
* Converts this Maybe<> to a value of type T. If this Maybe<> is * Converts this Maybe<> to a value of type T. If this Maybe<> is
* nothing (empty), V8 will crash the process. * nothing (empty), V8 will crash the process.
*/ */
V8_INLINE T FromJust() const { V8_INLINE T FromJust() const& {
if (V8_UNLIKELY(!IsJust())) api_internal::FromJustIsNothing(); if (V8_UNLIKELY(!IsJust())) api_internal::FromJustIsNothing();
return value_; return value_;
} }
/**
* Converts this Maybe<> to a value of type T. If this Maybe<> is
* nothing (empty), V8 will crash the process.
*/
V8_INLINE T FromJust() && {
if (V8_UNLIKELY(!IsJust())) api_internal::FromJustIsNothing();
return std::move(value_);
}
/** /**
* Converts this Maybe<> to a value of type T, using a default value if this * Converts this Maybe<> to a value of type T, using a default value if this
* Maybe<> is nothing (empty). * Maybe<> is nothing (empty).
...@@ -82,6 +94,7 @@ class Maybe { ...@@ -82,6 +94,7 @@ class Maybe {
private: private:
Maybe() : has_value_(false) {} Maybe() : has_value_(false) {}
explicit Maybe(const T& t) : has_value_(true), value_(t) {} explicit Maybe(const T& t) : has_value_(true), value_(t) {}
explicit Maybe(T&& t) : has_value_(true), value_(std::move(t)) {}
bool has_value_; bool has_value_;
T value_; T value_;
...@@ -90,6 +103,8 @@ class Maybe { ...@@ -90,6 +103,8 @@ class Maybe {
friend Maybe<U> Nothing(); friend Maybe<U> Nothing();
template <class U> template <class U>
friend Maybe<U> Just(const U& u); friend Maybe<U> Just(const U& u);
template <class U, std::enable_if_t<!std::is_lvalue_reference_v<U>>*>
friend Maybe<U> Just(U&& u);
}; };
template <class T> template <class T>
...@@ -102,6 +117,14 @@ inline Maybe<T> Just(const T& t) { ...@@ -102,6 +117,14 @@ inline Maybe<T> Just(const T& t) {
return Maybe<T>(t); return Maybe<T>(t);
} }
// Don't use forwarding references here but instead use two overloads.
// Forwarding references only work when type deduction takes place, which is not
// the case for callsites such as Just<Type>(t).
template <class T, std::enable_if_t<!std::is_lvalue_reference_v<T>>* = nullptr>
inline Maybe<T> Just(T&& t) {
return Maybe<T>(std::move(t));
}
// A template specialization of Maybe<T> for the case of T = void. // A template specialization of Maybe<T> for the case of T = void.
template <> template <>
class Maybe<void> { class Maybe<void> {
......
...@@ -216,6 +216,7 @@ v8_source_set("unittests_sources") { ...@@ -216,6 +216,7 @@ v8_source_set("unittests_sources") {
"api/isolate-unittest.cc", "api/isolate-unittest.cc",
"api/remote-object-unittest.cc", "api/remote-object-unittest.cc",
"api/resource-constraints-unittest.cc", "api/resource-constraints-unittest.cc",
"api/v8-maybe-unittest.cc",
"api/v8-object-unittest.cc", "api/v8-object-unittest.cc",
"base/address-region-unittest.cc", "base/address-region-unittest.cc",
"base/atomic-utils-unittest.cc", "base/atomic-utils-unittest.cc",
......
// Copyright 2022 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "include/v8-maybe.h"
#include "src/base/compiler-specific.h"
#include "src/base/macros.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace v8 {
namespace internal {
namespace {
struct Movable {
Movable() = default;
Movable(const Movable&) = delete;
Movable& operator=(const Movable&) = delete;
Movable(Movable&&) V8_NOEXCEPT = default;
Movable& operator=(Movable&&) V8_NOEXCEPT = default;
};
} // namespace
TEST(MaybeTest, AllowMovableTypes) {
Maybe<Movable> m1 = Just(Movable{});
EXPECT_TRUE(m1.IsJust());
Maybe<Movable> m2 = Just<Movable>({});
EXPECT_TRUE(m2.IsJust());
Maybe<Movable> m3 = Nothing<Movable>();
EXPECT_TRUE(m3.IsNothing());
Maybe<Movable> m4 = Just(Movable{});
Movable mm = std::move(m4).FromJust();
USE(mm);
}
} // namespace internal
} // namespace v8
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment