Skip to content

Commit 782bc6a

Browse files
[Interop][SwiftToCxx] Moving swift::Expected to _SwiftStdlibCxxOverlay.h
1 parent 74450be commit 782bc6a

File tree

3 files changed

+200
-141
lines changed

3 files changed

+200
-141
lines changed

lib/PrintAsClang/_SwiftCxxInteroperability.h

Lines changed: 0 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -195,119 +195,6 @@ template <class T> inline void *_Nonnull getOpaquePointer(T &value) {
195195

196196
} // namespace _impl
197197

198-
constexpr static std::size_t max(std::size_t a, std::size_t b) {
199-
return a > b ? a : b;
200-
}
201-
202-
} // namespace _impl
203-
204-
/// The Expected class has either an error or an value.
205-
template<class T>
206-
class Expected {
207-
public:
208-
209-
/// Default
210-
constexpr Expected() noexcept {
211-
new (&buffer) Error();
212-
has_val = false;
213-
}
214-
215-
constexpr Expected(const swift::Error& error_val) noexcept {
216-
new (&buffer) Error(error_val);
217-
has_val = false;
218-
}
219-
220-
constexpr Expected(const T &val) noexcept {
221-
new (&buffer) T(val);
222-
has_val = true;
223-
}
224-
225-
/// Copy
226-
constexpr Expected(Expected const& other) noexcept {
227-
if (other.has_value())
228-
new (&buffer) T(other.value());
229-
else
230-
new (&buffer) Error(other.error());
231-
232-
has_val = other.has_value();
233-
}
234-
235-
/// Move
236-
// FIXME: Implement move semantics when move Swift values is possible
237-
constexpr Expected(Expected&&) noexcept { abort(); }
238-
239-
~Expected() noexcept {
240-
if (has_value())
241-
reinterpret_cast<const T *>(buffer)->~T();
242-
else
243-
reinterpret_cast<swift::Error *>(buffer)->~Error();
244-
}
245-
246-
/// assignment
247-
constexpr auto operator=(Expected&& other) noexcept = delete;
248-
constexpr auto operator=(Expected&) noexcept = delete;
249-
250-
/// For accessing T's members
251-
constexpr T const *_Nonnull operator->() const noexcept {
252-
if (!has_value())
253-
abort();
254-
return reinterpret_cast<const T *>(buffer);
255-
}
256-
257-
constexpr T *_Nonnull operator->() noexcept {
258-
if (!has_value())
259-
abort();
260-
return reinterpret_cast<T *>(buffer);
261-
}
262-
263-
/// Getting reference to T
264-
constexpr T const &operator*() const & noexcept {
265-
if (!has_value())
266-
abort();
267-
return reinterpret_cast<const T &>(buffer);
268-
}
269-
270-
constexpr T &operator*() & noexcept {
271-
if (!has_value())
272-
abort();
273-
return reinterpret_cast<T &>(buffer);
274-
}
275-
276-
constexpr explicit operator bool() const noexcept { return has_value(); }
277-
278-
// Get value, if not exists abort
279-
constexpr T const& value() const& {
280-
if (!has_value())
281-
abort();
282-
return *reinterpret_cast<const T *>(buffer);
283-
}
284-
285-
constexpr T& value() & {
286-
if (!has_value())
287-
abort();
288-
return *reinterpret_cast<T *>(buffer);
289-
}
290-
291-
// Get error
292-
constexpr swift::Error const& error() const& {
293-
if (has_value())
294-
abort();
295-
return reinterpret_cast<const swift::Error&>(buffer);
296-
}
297-
298-
constexpr swift::Error& error() & {
299-
if (has_value())
300-
abort();
301-
return reinterpret_cast<swift::Error&>(buffer);
302-
}
303-
304-
constexpr bool has_value() const noexcept { return has_val; }
305-
306-
private:
307-
alignas(_impl::max(alignof(T), alignof(swift::Error))) char buffer[_impl::max(sizeof(T), sizeof(swift::Error))];
308-
bool has_val;
309-
};
310-
311198
#pragma clang diagnostic pop
312199

313200
} // namespace swift

lib/PrintAsClang/_SwiftStdlibCxxOverlay.h

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,4 +179,177 @@ class Error {
179179
void *_Nonnull opaqueValue = nullptr;
180180
};
181181

182+
namespace _impl {
183+
184+
constexpr static std::size_t max(std::size_t a, std::size_t b) {
185+
return a > b ? a : b;
186+
}
187+
188+
} // namespace _impl
189+
190+
/// The Expected class has either an error or an value.
191+
template<class T>
192+
class Expected {
193+
public:
194+
195+
/// Default
196+
constexpr Expected() noexcept {
197+
new (&buffer) Error();
198+
has_val = false;
199+
}
200+
201+
constexpr Expected(const Swift::Error& error_val) noexcept {
202+
new (&buffer) Error(error_val);
203+
has_val = false;
204+
}
205+
206+
constexpr Expected(const T &val) noexcept {
207+
new (&buffer) T(val);
208+
has_val = true;
209+
}
210+
211+
/// Copy
212+
constexpr Expected(Expected const& other) noexcept {
213+
if (other.has_value())
214+
new (&buffer) T(other.value());
215+
else
216+
new (&buffer) Error(other.error());
217+
218+
has_val = other.has_value();
219+
}
220+
221+
/// Move
222+
// FIXME: Implement move semantics when move Swift values is possible
223+
constexpr Expected(Expected&&) noexcept { abort(); }
224+
225+
~Expected() noexcept {
226+
if (has_value())
227+
reinterpret_cast<const T *>(buffer)->~T();
228+
else
229+
reinterpret_cast<Swift::Error *>(buffer)->~Error();
230+
}
231+
232+
/// assignment
233+
constexpr auto operator=(Expected&& other) noexcept = delete;
234+
constexpr auto operator=(Expected&) noexcept = delete;
235+
236+
/// For accessing T's members
237+
constexpr T const *_Nonnull operator->() const noexcept {
238+
if (!has_value())
239+
abort();
240+
return reinterpret_cast<const T *>(buffer);
241+
}
242+
243+
constexpr T *_Nonnull operator->() noexcept {
244+
if (!has_value())
245+
abort();
246+
return reinterpret_cast<T *>(buffer);
247+
}
248+
249+
/// Getting reference to T
250+
constexpr T const &operator*() const & noexcept {
251+
if (!has_value())
252+
abort();
253+
return reinterpret_cast<const T &>(buffer);
254+
}
255+
256+
constexpr T &operator*() & noexcept {
257+
if (!has_value())
258+
abort();
259+
return reinterpret_cast<T &>(buffer);
260+
}
261+
262+
constexpr explicit operator bool() const noexcept { return has_value(); }
263+
264+
// Get value, if not exists abort
265+
constexpr T const& value() const& {
266+
if (!has_value())
267+
abort();
268+
return *reinterpret_cast<const T *>(buffer);
269+
}
270+
271+
constexpr T& value() & {
272+
if (!has_value())
273+
abort();
274+
return *reinterpret_cast<T *>(buffer);
275+
}
276+
277+
// Get error
278+
constexpr Swift::Error const& error() const& {
279+
if (has_value())
280+
abort();
281+
return reinterpret_cast<const Swift::Error&>(buffer);
282+
}
283+
284+
constexpr Swift::Error& error() & {
285+
if (has_value())
286+
abort();
287+
return reinterpret_cast<Swift::Error&>(buffer);
288+
}
289+
290+
constexpr bool has_value() const noexcept { return has_val; }
291+
292+
private:
293+
alignas(_impl::max(alignof(T), alignof(Swift::Error))) char buffer[_impl::max(sizeof(T), sizeof(Swift::Error))];
294+
bool has_val;
295+
};
296+
297+
template<>
298+
class Expected<void> {
299+
public:
300+
/// Default
301+
Expected() noexcept {
302+
new (&buffer) Error();
303+
has_val = false;
304+
}
305+
306+
Expected(const Swift::Error& error_val) noexcept {
307+
new (&buffer) Error(error_val);
308+
has_val = false;
309+
}
310+
311+
312+
/// Copy
313+
Expected(Expected const& other) noexcept {
314+
if (other.has_value())
315+
abort();
316+
else
317+
new (&buffer) Error(other.error());
318+
319+
has_val = other.has_value();
320+
}
321+
322+
/// Move
323+
// FIXME: Implement move semantics when move swift values is possible
324+
[[noreturn]] Expected(Expected&&) noexcept { abort(); }
325+
326+
~Expected() noexcept {
327+
reinterpret_cast<Swift::Error *>(buffer)->~Error();
328+
}
329+
330+
/// assignment
331+
constexpr auto operator=(Expected&& other) noexcept = delete;
332+
constexpr auto operator=(Expected&) noexcept = delete;
333+
334+
335+
constexpr explicit operator bool() const noexcept { return has_value(); }
336+
337+
// Get error
338+
constexpr Swift::Error const& error() const& {
339+
if (has_value())
340+
abort();
341+
return reinterpret_cast<const Swift::Error&>(buffer);
342+
}
343+
344+
constexpr Swift::Error& error() & {
345+
if (has_value())
346+
abort();
347+
return reinterpret_cast<Swift::Error&>(buffer);
348+
}
349+
350+
constexpr bool has_value() const noexcept { return has_val; }
351+
private:
352+
alignas(alignof(Swift::Error)) char buffer[sizeof(Swift::Error)];
353+
bool has_val;
354+
};
182355
#endif

test/Interop/SwiftToCxx/functions/swift-expected-execution.cpp

Lines changed: 27 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// RUN: %empty-directory(%t)
22

3-
// RUN: %target-swift-frontend %S/swift-functions-errors.swift -typecheck -module-name Functions -clang-header-expose-decls=has-expose-attr -emit-clang-header-path %t/functions.h
3+
// RUN: %target-swift-frontend %S/swift-functions-errors.swift -typecheck -module-name Functions -Xcc -fno-exceptions -enable-experimental-cxx-interop -emit-clang-header-path %t/functions.h
44

5-
// RUN: %target-interop-build-clangxx -c %s -I %t -o %t/swift-expected-execution.o
5+
// RUN: %target-interop-build-clangxx -fno-exceptions -c %s -I %t -fno-exceptions -o %t/swift-expected-execution.o
66
// RUN: %target-interop-build-swift %S/swift-functions-errors.swift -o %t/swift-expected-execution -Xlinker %t/swift-expected-execution.o -module-name Functions -Xfrontend -entry-point-function-name -Xfrontend swiftMain
77

88
// RUN: %target-codesign %t/swift-expected-execution
@@ -17,24 +17,24 @@
1717
int main() {
1818

1919
// Test Empty Constructor
20-
auto testIntEmpty = swift::Expected<int>();
20+
auto testIntEmpty = Swift::Expected<int>();
2121

2222
// Test Error Constructor
23-
swift::Error e;
24-
auto testIntError = swift::Expected<int>(e);
23+
Swift::Error e;
24+
auto testIntError = Swift::Expected<int>(e);
2525

2626
// Test Value Constructor
27-
auto testIntValue = swift::Expected<int>(42);
27+
auto testIntValue = Swift::Expected<int>(42);
2828

2929
// Test Copy Constructor
3030
auto testCopy = testIntEmpty;
3131

3232
// TODO: Test Move Constructor
3333

3434
// Test Destructor
35-
auto testDestEmpty = swift::Expected<int>();
36-
auto testDestInt = swift::Expected<int>(42);
37-
auto testDestError = swift::Expected<int>(e);
35+
auto testDestEmpty = Swift::Expected<int>();
36+
auto testDestInt = Swift::Expected<int>(42);
37+
auto testDestError = Swift::Expected<int>(e);
3838
testDestEmpty.~Expected();
3939
testDestInt.~Expected();
4040
testDestError.~Expected();
@@ -73,23 +73,22 @@ int main() {
7373
if (testIntValue.value() == 42)
7474
printf("Test get T's Value\n");
7575

76-
// Test get swift::Error (const)
77-
try {
78-
Functions::throwFunction();
79-
} catch (swift::Error& e) {
80-
const auto errorExp = swift::Expected<int>(e);
81-
auto err = errorExp.error(); // using const function
82-
auto errorVal = err.as<Functions::NaiveErrors>();
83-
errorVal.getMessage();
76+
// Test get Swift::Error (const)
77+
const auto constExpectedResult = Functions::throwFunctionWithPossibleReturn(0);
78+
if (!constExpectedResult.has_value()) {
79+
auto constError = constExpectedResult.error(); // using const function
80+
auto optionalError = constError.as<Functions::NaiveErrors>();
81+
auto errorValue = optionalError.get();
82+
errorValue.getMessage();
8483
}
8584

86-
// Test get swift::Error
87-
try {
88-
Functions::throwFunction();
89-
} catch (swift::Error& e) {
90-
auto err = swift::Expected<int>(e).error();
91-
auto errorVal = err.as<Functions::NaiveErrors>();
92-
errorVal.getMessage();
85+
// Test get Swift::Error
86+
auto expectedResult = Functions::throwFunctionWithPossibleReturn(0);
87+
if (!expectedResult.has_value()) {
88+
auto error = expectedResult.error();
89+
auto optionalError = error.as<Functions::NaiveErrors>();
90+
auto errorValue = optionalError.get();
91+
errorValue.getMessage();
9392
}
9493

9594
// Test has Value
@@ -108,9 +107,9 @@ int main() {
108107
// CHECK-NEXT: Test operator bool
109108
// CHECK-NEXT: Test get T's Value (const)
110109
// CHECK-NEXT: Test get T's Value
111-
// CHECK-NEXT: passThrowFunction
112-
// CHECK-NEXT: throwError
113-
// CHECK-NEXT: passThrowFunction
114-
// CHECK-NEXT: throwError
110+
// CHECK-NEXT: passThrowFunctionWithPossibleReturn
111+
// CHECK-NEXT: returnError
112+
// CHECK-NEXT: passThrowFunctionWithPossibleReturn
113+
// CHECK-NEXT: returnError
115114
// CHECK-NEXT: testIntValue has a value
116115
// CHECK-NEXT: testIntError doesn't have a value

0 commit comments

Comments
 (0)