Commit cded1f89 authored by Kenton Varda's avatar Kenton Varda

Disallow initializing `Maybe<T>` from `T*`.

I think I imagined once upon a time that this would be a convenient way to deal with external interfaces that like to return nullable pointers. However, in practice it is used nowhere in KJ or Cap'n Proto, and it recently hid a bug in my code where I had assigned a `Maybe<T>` from an `Own<T>`. We can introduce a `fromNullablePointer()` helper or something if that turns out to be useful.
parent f94b1a6f
......@@ -199,38 +199,6 @@ TEST(Common, Maybe) {
EXPECT_EQ("foo", s);
}
{
Maybe<int> m = &i;
EXPECT_FALSE(m == nullptr);
EXPECT_TRUE(m != nullptr);
KJ_IF_MAYBE(v, m) {
EXPECT_NE(v, &i);
EXPECT_EQ(234, *v);
} else {
ADD_FAILURE();
}
KJ_IF_MAYBE(v, mv(m)) {
EXPECT_NE(v, &i);
EXPECT_EQ(234, *v);
} else {
ADD_FAILURE();
}
}
{
Maybe<int> m = implicitCast<int*>(nullptr);
EXPECT_TRUE(m == nullptr);
EXPECT_FALSE(m != nullptr);
KJ_IF_MAYBE(v, m) {
ADD_FAILURE();
EXPECT_EQ(0, *v); // avoid unused warning
}
KJ_IF_MAYBE(v, mv(m)) {
ADD_FAILURE();
EXPECT_EQ(0, *v); // avoid unused warning
}
}
{
// Test a case where an implicit conversion didn't used to happen correctly.
Maybe<ImplicitToInt> m(ImplicitToInt { 123 });
......
......@@ -935,10 +935,6 @@ public:
: isSet(true) {
ctor(value, t);
}
inline NullableValue(const T* t)
: isSet(t != nullptr) {
if (isSet) ctor(value, *t);
}
template <typename U>
inline NullableValue(NullableValue<U>&& other)
: isSet(other.isSet) {
......@@ -1010,14 +1006,6 @@ public:
inline NullableValue& operator=(T&& other) { emplace(kj::mv(other)); return *this; }
inline NullableValue& operator=(T& other) { emplace(other); return *this; }
inline NullableValue& operator=(const T& other) { emplace(other); return *this; }
inline NullableValue& operator=(const T* other) {
if (other == nullptr) {
*this = nullptr;
} else {
emplace(*other);
}
return *this;
}
template <typename U>
inline NullableValue& operator=(NullableValue<U>&& other) {
if (other.isSet) {
......@@ -1056,6 +1044,11 @@ public:
inline bool operator==(decltype(nullptr)) const { return !isSet; }
inline bool operator!=(decltype(nullptr)) const { return isSet; }
NullableValue(const T* t) = delete;
NullableValue& operator=(const T* other) = delete;
// We used to permit assigning a Maybe<T> directly from a T*, and the assignment would check for
// nullness. This turned out never to be useful, and sometimes to be dangerous.
private:
bool isSet;
......@@ -1109,7 +1102,6 @@ public:
Maybe(T&& t): ptr(kj::mv(t)) {}
Maybe(T& t): ptr(t) {}
Maybe(const T& t): ptr(t) {}
Maybe(const T* t): ptr(t) {}
Maybe(Maybe&& other): ptr(kj::mv(other.ptr)) {}
Maybe(const Maybe& other): ptr(other.ptr) {}
Maybe(Maybe& other): ptr(other.ptr) {}
......@@ -1147,7 +1139,6 @@ public:
inline Maybe& operator=(T&& other) { ptr = kj::mv(other); return *this; }
inline Maybe& operator=(T& other) { ptr = other; return *this; }
inline Maybe& operator=(const T& other) { ptr = other; return *this; }
inline Maybe& operator=(const T* other) { ptr = other; return *this; }
inline Maybe& operator=(Maybe&& other) { ptr = kj::mv(other.ptr); return *this; }
inline Maybe& operator=(Maybe& other) { ptr = other.ptr; return *this; }
......@@ -1177,6 +1168,11 @@ public:
inline bool operator==(decltype(nullptr)) const { return ptr == nullptr; }
inline bool operator!=(decltype(nullptr)) const { return ptr != nullptr; }
Maybe(const T* t) = delete;
Maybe& operator=(const T* other) = delete;
// We used to permit assigning a Maybe<T> directly from a T*, and the assignment would check for
// nullness. This turned out never to be useful, and sometimes to be dangerous.
T& orDefault(T& defaultValue) & {
if (ptr == nullptr) {
return defaultValue;
......
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