<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[208670] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/208670">208670</a></dd>
<dt>Author</dt> <dd>jfbastien@apple.com</dd>
<dt>Date</dt> <dd>2016-11-13 11:28:36 -0800 (Sun, 13 Nov 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Implement WTF::Expected
https://bugs.webkit.org/show_bug.cgi?id=164526

Reviewed by Yusuke Suzuki.

std::expected isn't in C++17, and may be in C++20. It's a nice
complement to std::any / std::optional because it's a type-tagged
union which has a single expected result but could also contain an
error.

This would be useful in the WebAssembly parser, for example.

Using this implementation will allow us to provide feedback to the
standards committee and guide std::expected's design before it
gets standardized. I've already sent a bunch of feedback to the
author based on my experience implementing this.

This could supplement WTF::Either and WTF::ExceptionOr.

Source/WTF:

* WTF.xcodeproj/project.pbxproj:
* wtf/Compiler.h: Add RELAXED_CONSTEXPR
* wtf/Expected.h: Added.
(WTF::UnexpectedType::UnexpectedType):
(WTF::UnexpectedType::value):
(WTF::operator==):
(WTF::operator!=):
(WTF::operator&lt;):
(WTF::operator&gt;):
(WTF::operator&lt;=):
(WTF::operator&gt;=):
(WTF::makeUnexpected):
(WTF::ExpectedDetail::Throw):
(WTF::ExpectedDetail::ConstexprBase::ConstexprBase):
(WTF::ExpectedDetail::Base::Base):
(WTF::ExpectedDetail::Base::~Base):
(WTF::Expected::Expected):
(WTF::Expected::operator=):
(WTF::Expected::swap):
(WTF::Expected::operator-&gt;):
(WTF::Expected::operator*):
(WTF::Expected::operator bool):
(WTF::Expected::hasValue):
(WTF::Expected::value):
(WTF::Expected::error):
(WTF::Expected::getUnexpected):
(WTF::Expected::valueOr):
(WTF::swap):
(WTF::makeExpected):
(WTF::makeExpectedFromError):

Tools:

* TestWebKitAPI/CMakeLists.txt:
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WTF/Expected.cpp: Added.
(WTF::operator&lt;&lt;):
(TestWebKitAPI::TEST):
(TestWebKitAPI::foo::foo):
(TestWebKitAPI::foo::~foo):
(TestWebKitAPI::foo::operator==):
(TestWebKitAPI::operator&lt;&lt;):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWTFChangeLog">trunk/Source/WTF/ChangeLog</a></li>
<li><a href="#trunkSourceWTFWTFxcodeprojprojectpbxproj">trunk/Source/WTF/WTF.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWTFwtfCompilerh">trunk/Source/WTF/wtf/Compiler.h</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsDumpRenderTreePlatformMaccmake">trunk/Tools/DumpRenderTree/PlatformMac.cmake</a></li>
<li><a href="#trunkToolsTestWebKitAPICMakeListstxt">trunk/Tools/TestWebKitAPI/CMakeLists.txt</a></li>
<li><a href="#trunkToolsTestWebKitAPITestWebKitAPIxcodeprojprojectpbxproj">trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWTFwtfExpectedh">trunk/Source/WTF/wtf/Expected.h</a></li>
<li><a href="#trunkToolsTestWebKitAPITestsWTFExpectedcpp">trunk/Tools/TestWebKitAPI/Tests/WTF/Expected.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/ChangeLog (208669 => 208670)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/ChangeLog        2016-11-13 18:31:14 UTC (rev 208669)
+++ trunk/Source/WTF/ChangeLog        2016-11-13 19:28:36 UTC (rev 208670)
</span><span class="lines">@@ -1,3 +1,55 @@
</span><ins>+2016-11-13  JF Bastien  &lt;jfbastien@apple.com&gt;
+
+        Implement WTF::Expected
+        https://bugs.webkit.org/show_bug.cgi?id=164526
+
+        Reviewed by Yusuke Suzuki.
+
+        std::expected isn't in C++17, and may be in C++20. It's a nice
+        complement to std::any / std::optional because it's a type-tagged
+        union which has a single expected result but could also contain an
+        error.
+
+        This would be useful in the WebAssembly parser, for example.
+
+        Using this implementation will allow us to provide feedback to the
+        standards committee and guide std::expected's design before it
+        gets standardized. I've already sent a bunch of feedback to the
+        author based on my experience implementing this.
+
+        This could supplement WTF::Either and WTF::ExceptionOr.
+
+        * WTF.xcodeproj/project.pbxproj:
+        * wtf/Compiler.h: Add RELAXED_CONSTEXPR
+        * wtf/Expected.h: Added.
+        (WTF::UnexpectedType::UnexpectedType):
+        (WTF::UnexpectedType::value):
+        (WTF::operator==):
+        (WTF::operator!=):
+        (WTF::operator&lt;):
+        (WTF::operator&gt;):
+        (WTF::operator&lt;=):
+        (WTF::operator&gt;=):
+        (WTF::makeUnexpected):
+        (WTF::ExpectedDetail::Throw):
+        (WTF::ExpectedDetail::ConstexprBase::ConstexprBase):
+        (WTF::ExpectedDetail::Base::Base):
+        (WTF::ExpectedDetail::Base::~Base):
+        (WTF::Expected::Expected):
+        (WTF::Expected::operator=):
+        (WTF::Expected::swap):
+        (WTF::Expected::operator-&gt;):
+        (WTF::Expected::operator*):
+        (WTF::Expected::operator bool):
+        (WTF::Expected::hasValue):
+        (WTF::Expected::value):
+        (WTF::Expected::error):
+        (WTF::Expected::getUnexpected):
+        (WTF::Expected::valueOr):
+        (WTF::swap):
+        (WTF::makeExpected):
+        (WTF::makeExpectedFromError):
+
</ins><span class="cx"> 2016-11-11  Alex Christensen  &lt;achristensen@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Allow mutable lambdas in HashMap::ensure
</span></span></pre></div>
<a id="trunkSourceWTFWTFxcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/WTF.xcodeproj/project.pbxproj (208669 => 208670)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/WTF.xcodeproj/project.pbxproj        2016-11-13 18:31:14 UTC (rev 208669)
+++ trunk/Source/WTF/WTF.xcodeproj/project.pbxproj        2016-11-13 19:28:36 UTC (rev 208670)
</span><span class="lines">@@ -328,6 +328,7 @@
</span><span class="cx">                 A8A47486151A825B004123FF /* WTFThreadData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A8A4737A151A825B004123FF /* WTFThreadData.cpp */; };
</span><span class="cx">                 A8A47487151A825B004123FF /* WTFThreadData.h in Headers */ = {isa = PBXBuildFile; fileRef = A8A4737B151A825B004123FF /* WTFThreadData.h */; };
</span><span class="cx">                 A8A4748C151A8264004123FF /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = A8A4748B151A8264004123FF /* config.h */; };
</span><ins>+                AD7C434B1DD2A4A70026888B /* Expected.h in Headers */ = {isa = PBXBuildFile; fileRef = AD7C434A1DD2A4A70026888B /* Expected.h */; };
</ins><span class="cx">                 B38FD7BD168953E80065C969 /* FeatureDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = B38FD7BC168953E80065C969 /* FeatureDefines.h */; };
</span><span class="cx">                 C4F8A93719C65EB400B2B15D /* Stopwatch.h in Headers */ = {isa = PBXBuildFile; fileRef = C4F8A93619C65EB400B2B15D /* Stopwatch.h */; };
</span><span class="cx">                 C8B0E1A1E01A486EB95E0D11 /* IndexSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 3137E1D7DBD84AC38FAE4D34 /* IndexSet.h */; };
</span><span class="lines">@@ -695,6 +696,7 @@
</span><span class="cx">                 A8A4737A151A825B004123FF /* WTFThreadData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WTFThreadData.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 A8A4737B151A825B004123FF /* WTFThreadData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WTFThreadData.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 A8A4748B151A8264004123FF /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                AD7C434A1DD2A4A70026888B /* Expected.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Expected.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 B38FD7BC168953E80065C969 /* FeatureDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FeatureDefines.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 C4F8A93619C65EB400B2B15D /* Stopwatch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Stopwatch.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 CD5497AA15857D0300B5BC30 /* MediaTime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MediaTime.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -848,6 +850,7 @@
</span><span class="cx">                 A876DBD6151816E500DADB95 /* wtf */ = {
</span><span class="cx">                         isa = PBXGroup;
</span><span class="cx">                         children = (
</span><ins>+                                AD7C434A1DD2A4A70026888B /* Expected.h */,
</ins><span class="cx">                                 2CDED0F018115C3F004DBA70 /* cf */,
</span><span class="cx">                                 E4A0AD3B1A96251900536DF6 /* cocoa */,
</span><span class="cx">                                 A8A47281151A825A004123FF /* dtoa */,
</span><span class="lines">@@ -1457,6 +1460,7 @@
</span><span class="cx">                                 A8A4743E151A825B004123FF /* StringConcatenate.h in Headers */,
</span><span class="cx">                                 A8A4742C151A825B004123FF /* StringExtras.h in Headers */,
</span><span class="cx">                                 A8A4743F151A825B004123FF /* StringHash.h in Headers */,
</span><ins>+                                AD7C434B1DD2A4A70026888B /* Expected.h in Headers */,
</ins><span class="cx">                                 A748745417A0BDAE00FA04CB /* StringHashDumpContext.h in Headers */,
</span><span class="cx">                                 A8A47441151A825B004123FF /* StringImpl.h in Headers */,
</span><span class="cx">                                 A8A47442151A825B004123FF /* StringOperators.h in Headers */,
</span></span></pre></div>
<a id="trunkSourceWTFwtfCompilerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/Compiler.h (208669 => 208670)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/Compiler.h        2016-11-13 18:31:14 UTC (rev 208669)
+++ trunk/Source/WTF/wtf/Compiler.h        2016-11-13 19:28:36 UTC (rev 208670)
</span><span class="lines">@@ -72,7 +72,7 @@
</span><span class="cx"> #endif
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-#endif
</del><ins>+#endif // defined(__clang__)
</ins><span class="cx"> 
</span><span class="cx"> /* COMPILER(GCC_OR_CLANG) - GNU Compiler Collection or Clang */
</span><span class="cx"> #if defined(__GNUC__)
</span><span class="lines">@@ -144,6 +144,20 @@
</span><span class="cx"> #define WTF_COMPILER_SUPPORTS_EABI 1
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+/* RELAXED_CONSTEXPR */
+
+#if defined(__cpp_constexpr) &amp;&amp; __cpp_constexpr &gt;= 201304
+#define WTF_COMPILER_SUPPORTS_RELAXED_CONSTEXPR 1
+#endif
+
+#if !defined(RELAXED_CONSTEXPR)
+#if COMPILER_SUPPORTS(RELAXED_CONSTEXPR)
+#define RELAXED_CONSTEXPR constexpr
+#else
+#define RELAXED_CONSTEXPR
+#endif
+#endif
+
</ins><span class="cx"> #define ASAN_ENABLED COMPILER_HAS_CLANG_FEATURE(address_sanitizer)
</span><span class="cx"> 
</span><span class="cx"> #if ASAN_ENABLED
</span></span></pre></div>
<a id="trunkSourceWTFwtfExpectedh"></a>
<div class="addfile"><h4>Added: trunk/Source/WTF/wtf/Expected.h (0 => 208670)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/Expected.h                                (rev 0)
+++ trunk/Source/WTF/wtf/Expected.h        2016-11-13 19:28:36 UTC (rev 208670)
</span><span class="lines">@@ -0,0 +1,442 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// WTF::Expected is based on std::expected, as described here: http://wg21.link/p0323r1
+// The specification expects to throw. This implementation doesn't support exceptions, uses RELEASE_ASSERT instead.
+
+#pragma once
+
+#include &lt;cstdlib&gt;
+#include &lt;functional&gt;
+#include &lt;initializer_list&gt;
+#include &lt;type_traits&gt;
+#include &lt;utility&gt;
+#include &lt;wtf/Assertions.h&gt;
+#include &lt;wtf/Compiler.h&gt;
+#include &lt;wtf/Optional.h&gt;
+#include &lt;wtf/StdLibExtras.h&gt;
+
+namespace WTF {
+
+template &lt;class E&gt;
+class UnexpectedType {
+public:
+    UnexpectedType() = delete;
+    constexpr explicit UnexpectedType(const E&amp; e) : val(e) { }
+    constexpr explicit UnexpectedType(E&amp;&amp; e) : val(WTFMove(e)) { }
+    constexpr const E&amp; value() const { return val; }
+    RELAXED_CONSTEXPR E&amp; value() { return val; }
+
+private:
+    E val;
+};
+
+template &lt;class E&gt; constexpr bool operator==(const UnexpectedType&lt;E&gt;&amp; lhs, const UnexpectedType&lt;E&gt;&amp; rhs) { return lhs.value() == rhs.value(); }
+template &lt;class E&gt; constexpr bool operator!=(const UnexpectedType&lt;E&gt;&amp; lhs, const UnexpectedType&lt;E&gt;&amp; rhs) { return lhs.value() != rhs.value(); }
+template &lt;class E&gt; constexpr bool operator&lt;(const UnexpectedType&lt;E&gt;&amp; lhs, const UnexpectedType&lt;E&gt;&amp; rhs) { return lhs.value() &lt; rhs.value(); }
+template &lt;class E&gt; constexpr bool operator&gt;(const UnexpectedType&lt;E&gt;&amp; lhs, const UnexpectedType&lt;E&gt;&amp; rhs) { return lhs.value() &gt; rhs.value(); }
+template &lt;class E&gt; constexpr bool operator&lt;=(const UnexpectedType&lt;E&gt;&amp; lhs, const UnexpectedType&lt;E&gt;&amp; rhs) { return lhs.value() &lt;= rhs.value(); }
+template &lt;class E&gt; constexpr bool operator&gt;=(const UnexpectedType&lt;E&gt;&amp; lhs, const UnexpectedType&lt;E&gt;&amp; rhs) { return lhs.value() &gt;= rhs.value(); }
+
+template &lt;class E&gt; constexpr UnexpectedType&lt;std::decay_t&lt;E&gt;&gt; makeUnexpected(E&amp;&amp; v) { return UnexpectedType&lt;typename std::decay&lt;E&gt;::type&gt;(std::forward&lt;E&gt;(v)); }
+
+struct UnexpectTag {
+    UnexpectTag() = delete;
+};
+constexpr UnexpectTag Unexpect { };
+
+namespace ExpectedDetail {
+
+// Invoked where std::Expected would instead throw.
+NO_RETURN_DUE_TO_CRASH void Throw() { RELEASE_ASSERT_NOT_REACHED(); }
+
+static constexpr enum class ValueTagType { } ValueTag { };
+static constexpr enum class ErrorTagType { } ErrorTag { };
+
+template&lt;class T, std::enable_if_t&lt;std::is_trivially_destructible&lt;T&gt;::value&gt;* = nullptr&gt; void destroy(T&amp; t) { }
+template&lt;class T, std::enable_if_t&lt;!std::is_trivially_destructible&lt;T&gt;::value &amp;&amp; (std::is_class&lt;T&gt;::value || std::is_union&lt;T&gt;::value)&gt;* = nullptr&gt; void destroy(T&amp; t) { t.~T(); }
+
+template &lt;class T, class E&gt;
+union ConstexprStorage {
+    typedef T ValueType;
+    typedef E ErrorType;
+    char dummy;
+    ValueType val;
+    ErrorType err;
+    constexpr ConstexprStorage() : dummy() { }
+    constexpr ConstexprStorage(ValueTagType) : val() { }
+    constexpr ConstexprStorage(ErrorTagType) : err() { }
+    constexpr ConstexprStorage(ValueTagType, const ValueType&amp; v) : val(v) { }
+    constexpr ConstexprStorage(ErrorTagType, const ErrorType&amp; e) : err(e) { }
+    ~ConstexprStorage() = default;
+};
+
+template &lt;class T, class E&gt;
+union Storage {
+    typedef T ValueType;
+    typedef E ErrorType;
+    char dummy;
+    ValueType val;
+    ErrorType err;
+    constexpr Storage() : dummy() { }
+    constexpr Storage(ValueTagType) : val() { }
+    constexpr Storage(ErrorTagType) : err() { }
+    constexpr Storage(ValueTagType, const ValueType&amp; val) : val(val) { }
+    constexpr Storage(ErrorTagType, const ErrorType&amp; err) : err(err) { }
+    ~Storage() { }
+};
+
+template &lt;class E&gt;
+union ConstexprStorage&lt;void, E&gt; {
+    typedef void ValueType;
+    typedef E ErrorType;
+    char dummy;
+    ErrorType err;
+    constexpr ConstexprStorage() : dummy() { }
+    constexpr ConstexprStorage(ValueTagType) : dummy() { }
+    constexpr ConstexprStorage(ErrorTagType) : err() { }
+    constexpr ConstexprStorage(ErrorTagType, const ErrorType&amp; e) : err(e) { }
+    ~ConstexprStorage() = default;
+};
+
+template &lt;class E&gt;
+union Storage&lt;void, E&gt; {
+    typedef void ValueType;
+    typedef E ErrorType;
+    char dummy;
+    ErrorType err;
+    constexpr Storage() : dummy() { }
+    constexpr Storage(ValueTagType) : dummy() { }
+    constexpr Storage(ErrorTagType) : err() { }
+    constexpr Storage(ErrorTagType, const ErrorType&amp; err) : err(err) { }
+    ~Storage() { }
+};
+
+template &lt;class T, class E&gt;
+struct ConstexprBase {
+    typedef T ValueType;
+    typedef E ErrorType;
+    ConstexprStorage&lt;ValueType, ErrorType&gt; s;
+    bool has;
+    constexpr ConstexprBase() : s(), has(true) { }
+    constexpr ConstexprBase(ValueTagType tag) : s(tag), has(true) { }
+    constexpr ConstexprBase(ErrorTagType tag) : s(tag), has(false) { }
+    constexpr ConstexprBase(ValueTagType tag, const ValueType&amp; val) : s(tag, val), has(true) { }
+    constexpr ConstexprBase(ErrorTagType tag, const ErrorType&amp; err) : s(tag, err), has(false) { }
+    ~ConstexprBase() = default;
+};
+
+template &lt;class T, class E&gt;
+struct Base {
+    typedef T ValueType;
+    typedef E ErrorType;
+    Storage&lt;ValueType, ErrorType&gt; s;
+    bool has;
+    constexpr Base() : s(), has(true) { }
+    constexpr Base(ValueTagType tag) : s(tag), has(true) { }
+    constexpr Base(ErrorTagType tag) : s(tag), has(false) { }
+    constexpr Base(ValueTagType tag, const ValueType&amp; val) : s(tag, val), has(true) { }
+    constexpr Base(ErrorTagType tag, const ErrorType&amp; err) : s(tag, err), has(false) { }
+    Base(const Base&amp; o)
+        : has(o.has)
+    {
+        if (has)
+            ::new (&amp;s.val) ValueType(o.s.val);
+        else
+            ::new (&amp;s.err) ErrorType(o.s.err);
+    }
+    Base(Base&amp;&amp; o)
+        : has(o.has)
+    {
+        if (has)
+            ::new (&amp;s.val) ValueType(WTFMove(o.s.val));
+        else
+            ::new (&amp;s.err) ErrorType(WTFMove(o.s.err));
+    }
+    ~Base()
+    {
+        if (has)
+            destroy(s.val);
+        else
+            destroy(s.err);
+    }
+};
+
+template &lt;class E&gt;
+struct ConstexprBase&lt;void, E&gt; {
+    typedef void ValueType;
+    typedef E ErrorType;
+    ConstexprStorage&lt;ValueType, ErrorType&gt; s;
+    bool has;
+    constexpr ConstexprBase() : s(), has(true) { }
+    constexpr ConstexprBase(ValueTagType tag) : s(tag), has(true) { }
+    constexpr ConstexprBase(ErrorTagType tag) : s(tag), has(false) { }
+    constexpr ConstexprBase(ErrorTagType tag, const ErrorType&amp; err) : s(tag, err), has(false) { }
+    ~ConstexprBase() = default;
+};
+
+template &lt;class E&gt;
+struct Base&lt;void, E&gt; {
+    typedef void ValueType;
+    typedef E ErrorType;
+    Storage&lt;ValueType, ErrorType&gt; s;
+    bool has;
+    constexpr Base() : s(), has(true) { }
+    constexpr Base(ValueTagType tag) : s(tag), has(true) { }
+    constexpr Base(ErrorTagType tag) : s(tag), has(false) { }
+    constexpr Base(ErrorTagType tag, const ErrorType&amp; err) : s(tag, err), has(false) { }
+    Base(const Base&amp; o)
+        : has(o.has)
+    {
+        if (!has)
+            ::new (&amp;s.err) ErrorType(o.s.err);
+    }
+    Base(Base&amp;&amp; o)
+        : has(o.has)
+    {
+        if (!has)
+            ::new (&amp;s.err) ErrorType(WTFMove(o.s.err));
+    }
+    ~Base()
+    {
+        if (!has)
+            destroy(s.err);
+    }
+};
+
+template &lt;class T, class E&gt;
+using BaseSelect = typename std::conditional&lt;
+    ((std::is_void&lt;T&gt;::value || std::is_trivially_destructible&lt;T&gt;::value)
+        &amp;&amp; std::is_trivially_destructible&lt;E&gt;::value),
+    ConstexprBase&lt;typename std::remove_const&lt;T&gt;::type, typename std::remove_const&lt;E&gt;::type&gt;,
+    Base&lt;typename std::remove_const&lt;T&gt;::type, typename std::remove_const&lt;E&gt;::type&gt;
+&gt;::type;
+
+} // namespace ExpectedDetail
+
+template &lt;class T, class E&gt;
+class Expected : private ExpectedDetail::BaseSelect&lt;T, E&gt; {
+    typedef ExpectedDetail::BaseSelect&lt;T, E&gt; base;
+
+public:
+    typedef typename base::ValueType ValueType;
+    typedef typename base::ErrorType ErrorType;
+
+private:
+    typedef Expected&lt;ValueType, ErrorType&gt; type;
+
+public:
+    // template &lt;class U&gt; struct rebind { using type = Expected&lt;U, ErrorType&gt;; };
+
+    constexpr Expected() : base(ExpectedDetail::ValueTag) { }
+    Expected(const Expected&amp;) = default;
+    Expected(Expected&amp;&amp;) = default;
+    constexpr Expected(const ValueType&amp; e) : base(ExpectedDetail::ValueTag, e) { }
+    constexpr Expected(ValueType&amp;&amp; e) : base(ExpectedDetail::ValueTag, WTFMove(e)) { }
+    // template &lt;class... Args&gt; constexpr explicit Expected(in_place_t, Args&amp;&amp;...);
+    // template &lt;class U, class... Args&gt; constexpr explicit Expected(in_place_t, std::initializer_list&lt;U&gt;, Args&amp;&amp;...);
+    constexpr Expected(UnexpectedType&lt;ErrorType&gt; const&amp; u) : base(ExpectedDetail::ErrorTag, u.value()) { }
+    template &lt;class Err&gt; constexpr Expected(UnexpectedType&lt;Err&gt; const&amp; u) : base(ExpectedDetail::ErrorTag, u.value()) { }
+    // template &lt;class... Args&gt; constexpr explicit Expected(UnexpectTag, Args&amp;&amp;...);
+    // template &lt;class U, class... Args&gt; constexpr explicit Expected(UnexpectTag, std::initializer_list&lt;U&gt;, Args&amp;&amp;...);
+
+    ~Expected() = default;
+
+    Expected&amp; operator=(const Expected&amp; e) { type(e).swap(*this); return *this; }
+    Expected&amp; operator=(Expected&amp;&amp; e) { type(WTFMove(e)).swap(*this); return *this; }
+    template &lt;class U&gt; Expected&amp; operator=(U&amp;&amp; u) { type(WTFMove(u)).swap(*this); return *this; }
+    Expected&amp; operator=(const UnexpectedType&lt;ErrorType&gt;&amp; u) { type(u).swap(*this); return *this; }
+    Expected&amp; operator=(UnexpectedType&lt;ErrorType&gt;&amp;&amp; u) { type(WTFMove(u)).swap(*this); return *this; }
+    // template &lt;class... Args&gt; void emplace(Args&amp;&amp;...);
+    // template &lt;class U, class... Args&gt; void emplace(std::initializer_list&lt;U&gt;, Args&amp;&amp;...);
+
+    void swap(Expected&amp; o)
+    {
+        using std::swap;
+        if (base::has &amp;&amp; o.has)
+            swap(base::s.val, o.s.val);
+        else if (base::has &amp;&amp; !o.has) {
+            ErrorType e(WTFMove(o.s.err));
+            ::new (&amp;o.s.val) ValueType(WTFMove(base::s.val));
+            ::new (&amp;base::s.err) ErrorType(e);
+            swap(base::has, o.has);
+        } else if (!base::has &amp;&amp; o.has) {
+            ValueType v(WTFMove(o.s.val));
+            ::new (&amp;o.s.err) ErrorType(WTFMove(base::s.err));
+            ::new (&amp;base::s.val) ValueType(v);
+            swap(base::has, o.has);
+        } else
+            swap(base::s.err, o.s.err);
+    }
+
+    constexpr const ValueType* operator-&gt;() const { return &amp;base::s.val; }
+    ValueType* operator-&gt;() { return &amp;base::s.val; }
+    constexpr const ValueType&amp; operator*() const &amp; { return base::s.val; }
+    ValueType&amp; operator*() &amp; { return base::s.val; }
+    constexpr const ValueType&amp;&amp; operator*() const &amp;&amp; { return WTFMove(base::s.val); }
+    RELAXED_CONSTEXPR ValueType&amp;&amp; operator*() &amp;&amp; { return WTFMove(base::s.val); }
+    constexpr explicit operator bool() const { return base::has; }
+    constexpr bool hasValue() const { return base::has; }
+    constexpr const ValueType&amp; value() const &amp; { return base::has ? base::s.val : (ExpectedDetail::Throw(), base::s.val); }
+    RELAXED_CONSTEXPR ValueType&amp; value() &amp; { return base::has ? base::s.val : (ExpectedDetail::Throw(), base::s.val); }
+    constexpr const ValueType&amp;&amp; value() const &amp;&amp; { return base::has ? base::s.val : (ExpectedDetail::Throw(), base::s.val); }
+    RELAXED_CONSTEXPR ValueType&amp;&amp; value() &amp;&amp; { return base::has ? base::s.val : (ExpectedDetail::Throw(), base::s.val); }
+    constexpr const ErrorType&amp; error() const &amp; { return !base::has ? base::s.err : (ExpectedDetail::Throw(), base::s.err); }
+    ErrorType&amp; error() &amp; { return !base::has ? base::s.err : (ExpectedDetail::Throw(), base::s.err); }
+    RELAXED_CONSTEXPR ErrorType&amp;&amp; error() &amp;&amp; { return !base::has ? base::s.err : (ExpectedDetail::Throw(), base::s.err); }
+    constexpr const ErrorType&amp;&amp; error() const &amp;&amp; { return !base::has ? base::s.err : (ExpectedDetail::Throw(), base::s.err); }
+    constexpr UnexpectedType&lt;ErrorType&gt; getUnexpected() const { return UnexpectedType&lt;ErrorType&gt;(base::s.err); }
+    template &lt;class U&gt; constexpr ValueType valueOr(U&amp;&amp; u) const &amp; { return base::has ? **this : static_cast&lt;ValueType&gt;(std::forward&lt;U&gt;(u)); }
+    template &lt;class U&gt; ValueType valueOr(U&amp;&amp; u) &amp;&amp; { return base::has ? WTFMove(**this) : static_cast&lt;ValueType&gt;(std::forward&lt;U&gt;(u)); }
+};
+
+template &lt;class E&gt;
+class Expected&lt;void, E&gt; : private ExpectedDetail::BaseSelect&lt;void, E&gt; {
+    typedef ExpectedDetail::BaseSelect&lt;void, E&gt; base;
+
+public:
+    typedef typename base::ValueType ValueType;
+    typedef typename base::ErrorType ErrorType;
+
+private:
+    typedef Expected&lt;ValueType, ErrorType&gt; type;
+
+public:
+    // template &lt;class U&gt; struct rebind { typedef Expected&lt;U, ErrorType&gt; type; };
+
+    constexpr Expected() : base(ExpectedDetail::ValueTag) { }
+    Expected(const Expected&amp;) = default;
+    Expected(Expected&amp;&amp;) = default;
+    // constexpr explicit Expected(in_place_t);
+    constexpr Expected(UnexpectedType&lt;E&gt; const&amp; u) : base(ExpectedDetail::ErrorTag, u.value()) { }
+    template &lt;class Err&gt; constexpr Expected(UnexpectedType&lt;Err&gt; const&amp; u) : base(ExpectedDetail::ErrorTag, u.value()) { }
+
+    ~Expected() = default;
+
+    Expected&amp; operator=(const Expected&amp; e) { type(e).swap(*this); return *this; }
+    Expected&amp; operator=(Expected&amp;&amp; e) { type(WTFMove(e)).swap(*this); return *this; }
+    Expected&amp; operator=(const UnexpectedType&lt;E&gt;&amp; u) { type(u).swap(*this); return *this; } // Not in the current paper.
+    Expected&amp; operator=(UnexpectedType&lt;E&gt;&amp;&amp; u) { type(WTFMove(u)).swap(*this); return *this; } // Not in the current paper.
+    // void emplace();
+
+    void swap(Expected&amp; o)
+    {
+        using std::swap;
+        if (base::has &amp;&amp; o.has) {
+            // Do nothing.
+        } else if (base::has &amp;&amp; !o.has) {
+            ErrorType e(WTFMove(o.s.err));
+            ::new (&amp;base::s.err) ErrorType(e);
+            swap(base::has, o.has);
+        } else if (!base::has &amp;&amp; o.has) {
+            ::new (&amp;o.s.err) ErrorType(WTFMove(base::s.err));
+            swap(base::has, o.has);
+        } else
+            swap(base::s.err, o.s.err);
+    }
+
+    constexpr explicit operator bool() const { return base::has; }
+    constexpr bool hasValue() const { return base::has; }
+    void value() const { !base::has ? ExpectedDetail::Throw() : void(); }
+    constexpr const E&amp; error() const &amp; { return !base::has ? base::s.err : (ExpectedDetail::Throw(), base::s.err); }
+    E&amp; error() &amp; { return !base::has ? base::s.err : (ExpectedDetail::Throw(), base::s.err); } // Not in the current paper.
+    RELAXED_CONSTEXPR E&amp;&amp; error() &amp;&amp; { return !base::has ? base::s.err : (ExpectedDetail::Throw(), base::s.err); }
+    constexpr const E&amp;&amp; error() const &amp;&amp; { return !base::has ? base::s.err : (ExpectedDetail::Throw(), base::s.err); } // Not in the current paper.
+    // constexpr E&amp; error() &amp;;
+    constexpr UnexpectedType&lt;E&gt; getUnexpected() const { return UnexpectedType&lt;E&gt;(base::s.err); }
+};
+
+template &lt;class T, class E&gt; constexpr bool operator==(const Expected&lt;T, E&gt;&amp; x, const Expected&lt;T, E&gt;&amp; y) { return bool(x) == bool(y) &amp;&amp; (x ? x.value() == y.value() : x.error() == y.error()); }
+template &lt;class T, class E&gt; constexpr bool operator!=(const Expected&lt;T, E&gt;&amp; x, const Expected&lt;T, E&gt;&amp; y) { return !(x == y); }
+template &lt;class T, class E&gt; constexpr bool operator&lt;(const Expected&lt;T, E&gt;&amp; x, const Expected&lt;T, E&gt;&amp; y) { return (!bool(x) &amp;&amp; bool(y)) ? false : ((bool(x) &amp;&amp; !bool(y)) ? true : ((bool(x) &amp;&amp; bool(y)) ? x.value() &lt; y.value() : x.error() &lt; y.error())); }
+template &lt;class T, class E&gt; constexpr bool operator&gt;(const Expected&lt;T, E&gt;&amp; x, const Expected&lt;T, E&gt;&amp; y) { return !(x == y) &amp;&amp; !(x &lt; y); }
+template &lt;class T, class E&gt; constexpr bool operator&lt;=(const Expected&lt;T, E&gt;&amp; x, const Expected&lt;T, E&gt;&amp; y) { return (x == y) || (x &lt; y); }
+template &lt;class T, class E&gt; constexpr bool operator&gt;=(const Expected&lt;T, E&gt;&amp; x, const Expected&lt;T, E&gt;&amp; y) { return (x == y) || (x &gt; y); }
+
+template &lt;class E&gt; constexpr bool operator==(const Expected&lt;void, E&gt;&amp; x, const Expected&lt;void, E&gt;&amp; y) { return bool(x) == bool(y) &amp;&amp; (x ? true : x.error() == y.error()); } // Not in the current paper.
+template &lt;class E&gt; constexpr bool operator&lt;(const Expected&lt;void, E&gt;&amp; x, const Expected&lt;void, E&gt;&amp; y) { return (!bool(x) &amp;&amp; bool(y)) ? false : ((bool(x) &amp;&amp; !bool(y)) ? true : ((bool(x) &amp;&amp; bool(y)) ? false : x.error() &lt; y.error())); } // Not in the current paper.
+
+template &lt;class T, class E&gt; constexpr bool operator==(const Expected&lt;T, E&gt;&amp; x, const T&amp; y) { return x == Expected&lt;T, E&gt;(y); }
+template &lt;class T, class E&gt; constexpr bool operator==(const T&amp; x, const Expected&lt;T, E&gt;&amp; y) { return Expected&lt;T, E&gt;(x) == y; }
+template &lt;class T, class E&gt; constexpr bool operator!=(const Expected&lt;T, E&gt;&amp; x, const T&amp; y) { return x != Expected&lt;T, E&gt;(y); }
+template &lt;class T, class E&gt; constexpr bool operator!=(const T&amp; x, const Expected&lt;T, E&gt;&amp; y) { return Expected&lt;T, E&gt;(x) != y; }
+template &lt;class T, class E&gt; constexpr bool operator&lt;(const Expected&lt;T, E&gt;&amp; x, const T&amp; y) { return x &lt; Expected&lt;T, E&gt;(y); }
+template &lt;class T, class E&gt; constexpr bool operator&lt;(const T&amp; x, const Expected&lt;T, E&gt;&amp; y) { return Expected&lt;T, E&gt;(x) &lt; y; }
+template &lt;class T, class E&gt; constexpr bool operator&lt;=(const Expected&lt;T, E&gt;&amp; x, const T&amp; y) { return x &lt;= Expected&lt;T, E&gt;(y); }
+template &lt;class T, class E&gt; constexpr bool operator&lt;=(const T&amp; x, const Expected&lt;T, E&gt;&amp; y) { return Expected&lt;T, E&gt;(x) &lt;= y; }
+template &lt;class T, class E&gt; constexpr bool operator&gt;(const Expected&lt;T, E&gt;&amp; x, const T&amp; y) { return x &gt; Expected&lt;T, E&gt;(y); }
+template &lt;class T, class E&gt; constexpr bool operator&gt;(const T&amp; x, const Expected&lt;T, E&gt;&amp; y) { return Expected&lt;T, E&gt;(x) &gt; y; }
+template &lt;class T, class E&gt; constexpr bool operator&gt;=(const Expected&lt;T, E&gt;&amp; x, const T&amp; y) { return x &gt;= Expected&lt;T, E&gt;(y); }
+template &lt;class T, class E&gt; constexpr bool operator&gt;=(const T&amp; x, const Expected&lt;T, E&gt;&amp; y) { return Expected&lt;T, E&gt;(x) &gt;= y; }
+
+template &lt;class T, class E&gt; constexpr bool operator==(const Expected&lt;T, E&gt;&amp; x, const UnexpectedType&lt;E&gt;&amp; y) { return x == Expected&lt;T, E&gt;(y); }
+template &lt;class T, class E&gt; constexpr bool operator==(const UnexpectedType&lt;E&gt;&amp; x, const Expected&lt;T, E&gt;&amp; y) { return Expected&lt;T, E&gt;(x) == y; }
+template &lt;class T, class E&gt; constexpr bool operator!=(const Expected&lt;T, E&gt;&amp; x, const UnexpectedType&lt;E&gt;&amp; y) { return x != Expected&lt;T, E&gt;(y); }
+template &lt;class T, class E&gt; constexpr bool operator!=(const UnexpectedType&lt;E&gt;&amp; x, const Expected&lt;T, E&gt;&amp; y) { return Expected&lt;T, E&gt;(x) != y; }
+template &lt;class T, class E&gt; constexpr bool operator&lt;(const Expected&lt;T, E&gt;&amp; x, const UnexpectedType&lt;E&gt;&amp; y) { return x &lt; Expected&lt;T, E&gt;(y); }
+template &lt;class T, class E&gt; constexpr bool operator&lt;(const UnexpectedType&lt;E&gt;&amp; x, const Expected&lt;T, E&gt;&amp; y) {  return Expected&lt;T, E&gt;(x) &lt; y; }
+template &lt;class T, class E&gt; constexpr bool operator&lt;=(const Expected&lt;T, E&gt;&amp; x, const UnexpectedType&lt;E&gt;&amp; y) { return x &lt;= Expected&lt;T, E&gt;(y); }
+template &lt;class T, class E&gt; constexpr bool operator&lt;=(const UnexpectedType&lt;E&gt;&amp; x, const Expected&lt;T, E&gt;&amp; y) { return Expected&lt;T, E&gt;(x) &lt;= y; }
+template &lt;class T, class E&gt; constexpr bool operator&gt;(const Expected&lt;T, E&gt;&amp; x, const UnexpectedType&lt;E&gt;&amp; y) { return x &gt; Expected&lt;T, E&gt;(y); }
+template &lt;class T, class E&gt; constexpr bool operator&gt;(const UnexpectedType&lt;E&gt;&amp; x, const Expected&lt;T, E&gt;&amp; y) { return Expected&lt;T, E&gt;(x) &gt; y; }
+template &lt;class T, class E&gt; constexpr bool operator&gt;=(const Expected&lt;T, E&gt;&amp; x, const UnexpectedType&lt;E&gt;&amp; y) { return x &gt;= Expected&lt;T, E&gt;(y); }
+template &lt;class T, class E&gt; constexpr bool operator&gt;=(const UnexpectedType&lt;E&gt;&amp; x, const Expected&lt;T, E&gt;&amp; y) { return Expected&lt;T, E&gt;(x) &gt;= y; }
+
+template &lt;typename T, typename E&gt; void swap(Expected&lt;T, E&gt;&amp; x, Expected&lt;T, E&gt;&amp; y) { x.swap(y); }
+
+template &lt;class T, class E = WTF::NulloptTag&gt; constexpr Expected&lt;std::decay_t&lt;T&gt;, E&gt; makeExpected(T&amp;&amp; v)
+{
+    return Expected&lt;typename std::decay&lt;T&gt;::type, E&gt;(std::forward&lt;T&gt;(v));
+}
+template &lt;class T, class E&gt; constexpr Expected&lt;T, std::decay_t&lt;E&gt;&gt; makeExpectedFromError(E&amp;&amp; e) { return Expected&lt;T, std::decay_t&lt;E&gt;&gt;(makeUnexpected(e)); }
+template &lt;class T, class E, class U&gt; constexpr Expected&lt;T, E&gt; makeExpectedFromError(U&amp;&amp; u) { return Expected&lt;T, E&gt;(makeUnexpected(E { std::forward&lt;U&gt;(u) } )); }
+// template &lt;class F, class E = WTF::NulloptTag&gt; constexpr Expected&lt;typename std::result_of&lt;F&gt;::type, E&gt; makeExpected_from_call(F f);
+
+Expected&lt;void, WTF::NulloptTag&gt; makeExpected() { return Expected&lt;void, WTF::NulloptTag&gt;(); }
+
+} // namespace WTF
+
+namespace std {
+
+template &lt;class T, class E&gt; struct hash&lt;WTF::Expected&lt;T, E&gt;&gt; {
+    typedef WTF::Expected&lt;T, E&gt; argument_type;
+    typedef std::size_t result_type;
+    result_type operator()(argument_type const&amp; e) const { return e ? hash&lt;typename argument_type::ValueType&gt; { } (e.value()) : hash&lt;typename argument_type::ErrorType&gt; { } (e.error()); }
+};
+
+template &lt;class E&gt; struct hash&lt;WTF::Expected&lt;void, E&gt;&gt; {
+    typedef WTF::Expected&lt;void, E&gt; argument_type;
+    typedef std::size_t result_type;
+    result_type operator()(argument_type const&amp; e) const { return e ? 0 : hash&lt;typename argument_type::ErrorType&gt; { } (e.error()); }
+};
+
+}
+
+using WTF::UnexpectedType;
+using WTF::makeUnexpected;
+using WTF::Unexpect;
+using WTF::Expected;
+using WTF::makeExpected;
+using WTF::makeExpectedFromError;
</ins></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (208669 => 208670)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog        2016-11-13 18:31:14 UTC (rev 208669)
+++ trunk/Tools/ChangeLog        2016-11-13 19:28:36 UTC (rev 208670)
</span><span class="lines">@@ -1,3 +1,34 @@
</span><ins>+2016-11-13  JF Bastien  &lt;jfbastien@apple.com&gt;
+
+        Implement WTF::Expected
+        https://bugs.webkit.org/show_bug.cgi?id=164526
+
+        Reviewed by Yusuke Suzuki.
+
+        std::expected isn't in C++17, and may be in C++20. It's a nice
+        complement to std::any / std::optional because it's a type-tagged
+        union which has a single expected result but could also contain an
+        error.
+
+        This would be useful in the WebAssembly parser, for example.
+
+        Using this implementation will allow us to provide feedback to the
+        standards committee and guide std::expected's design before it
+        gets standardized. I've already sent a bunch of feedback to the
+        author based on my experience implementing this.
+
+        This could supplement WTF::Either and WTF::ExceptionOr.
+
+        * TestWebKitAPI/CMakeLists.txt:
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WTF/Expected.cpp: Added.
+        (WTF::operator&lt;&lt;):
+        (TestWebKitAPI::TEST):
+        (TestWebKitAPI::foo::foo):
+        (TestWebKitAPI::foo::~foo):
+        (TestWebKitAPI::foo::operator==):
+        (TestWebKitAPI::operator&lt;&lt;):
+
</ins><span class="cx"> 2016-11-12  Simon Fraser  &lt;simon.fraser@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Add a way to get the UI-side scrolling tree as text via UIScriptController
</span></span></pre></div>
<a id="trunkToolsDumpRenderTreePlatformMaccmake"></a>
<div class="modfile"><h4>Modified: trunk/Tools/DumpRenderTree/PlatformMac.cmake (208669 => 208670)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/DumpRenderTree/PlatformMac.cmake        2016-11-13 18:31:14 UTC (rev 208669)
+++ trunk/Tools/DumpRenderTree/PlatformMac.cmake        2016-11-13 19:28:36 UTC (rev 208670)
</span><span class="lines">@@ -76,7 +76,7 @@
</span><span class="cx">     mac/ObjCController.m
</span><span class="cx">     mac/ObjCPlugin.m
</span><span class="cx">     mac/ObjCPluginFunction.m
</span><del>-    mac/TextInputController.m
</del><ins>+    mac/TextInputControllerMac.m
</ins><span class="cx"> )
</span><span class="cx"> 
</span><span class="cx"> list(APPEND DumpRenderTree_Cpp_SOURCES
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPICMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Tools/TestWebKitAPI/CMakeLists.txt (208669 => 208670)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/CMakeLists.txt        2016-11-13 18:31:14 UTC (rev 208669)
+++ trunk/Tools/TestWebKitAPI/CMakeLists.txt        2016-11-13 19:28:36 UTC (rev 208670)
</span><span class="lines">@@ -50,6 +50,7 @@
</span><span class="cx">     ${TESTWEBKITAPI_DIR}/Tests/WTF/DateMath.cpp
</span><span class="cx">     ${TESTWEBKITAPI_DIR}/Tests/WTF/Deque.cpp
</span><span class="cx">     ${TESTWEBKITAPI_DIR}/Tests/WTF/EnumTraits.cpp
</span><ins>+    ${TESTWEBKITAPI_DIR}/Tests/WTF/Expected.cpp
</ins><span class="cx">     ${TESTWEBKITAPI_DIR}/Tests/WTF/HashCountedSet.cpp
</span><span class="cx">     ${TESTWEBKITAPI_DIR}/Tests/WTF/HashMap.cpp
</span><span class="cx">     ${TESTWEBKITAPI_DIR}/Tests/WTF/HashSet.cpp
</span><span class="lines">@@ -61,6 +62,7 @@
</span><span class="cx">     ${TESTWEBKITAPI_DIR}/Tests/WTF/MediaTime.cpp
</span><span class="cx">     ${TESTWEBKITAPI_DIR}/Tests/WTF/MetaAllocator.cpp
</span><span class="cx">     ${TESTWEBKITAPI_DIR}/Tests/WTF/NakedPtr.cpp
</span><ins>+    ${TESTWEBKITAPI_DIR}/Tests/WTF/Optional.cpp
</ins><span class="cx">     ${TESTWEBKITAPI_DIR}/Tests/WTF/OptionSet.cpp
</span><span class="cx">     ${TESTWEBKITAPI_DIR}/Tests/WTF/ParkingLot.cpp
</span><span class="cx">     ${TESTWEBKITAPI_DIR}/Tests/WTF/RedBlackTree.cpp
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPITestWebKitAPIxcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (208669 => 208670)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj        2016-11-13 18:31:14 UTC (rev 208669)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj        2016-11-13 19:28:36 UTC (rev 208670)
</span><span class="lines">@@ -455,6 +455,7 @@
</span><span class="cx">                 AD57AC201DA7465000FF1BDE /* DidRemoveFrameFromHiearchyInPageCache_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD57AC1E1DA7464D00FF1BDE /* DidRemoveFrameFromHiearchyInPageCache_Bundle.cpp */; };
</span><span class="cx">                 AD57AC211DA7465B00FF1BDE /* DidRemoveFrameFromHiearchyInPageCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD57AC1F1DA7464D00FF1BDE /* DidRemoveFrameFromHiearchyInPageCache.cpp */; };
</span><span class="cx">                 AD57AC221DA7466E00FF1BDE /* many-iframes.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = AD57AC1D1DA7463800FF1BDE /* many-iframes.html */; };
</span><ins>+                AD7C434D1DD2A54E0026888B /* Expected.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD7C434C1DD2A5470026888B /* Expected.cpp */; };
</ins><span class="cx">                 ADCEBBA61D9AE229002E283A /* Consume.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ADCEBBA51D99D4CF002E283A /* Consume.cpp */; };
</span><span class="cx">                 B55AD1D5179F3B3000AC1494 /* PreventImageLoadWithAutoResizing_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B55AD1D3179F3ABF00AC1494 /* PreventImageLoadWithAutoResizing_Bundle.cpp */; };
</span><span class="cx">                 B55F11B71517D03300915916 /* attributedStringCustomFont.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = B55F11B01517A2C400915916 /* attributedStringCustomFont.html */; };
</span><span class="lines">@@ -1112,6 +1113,7 @@
</span><span class="cx">                 AD57AC1D1DA7463800FF1BDE /* many-iframes.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = &quot;many-iframes.html&quot;; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 AD57AC1E1DA7464D00FF1BDE /* DidRemoveFrameFromHiearchyInPageCache_Bundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DidRemoveFrameFromHiearchyInPageCache_Bundle.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 AD57AC1F1DA7464D00FF1BDE /* DidRemoveFrameFromHiearchyInPageCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DidRemoveFrameFromHiearchyInPageCache.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                AD7C434C1DD2A5470026888B /* Expected.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Expected.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 ADCEBBA51D99D4CF002E283A /* Consume.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Consume.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 B4039F9C15E6D8B3007255D6 /* MathExtras.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MathExtras.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 B55AD1D1179F336600AC1494 /* PreventImageLoadWithAutoResizing.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = PreventImageLoadWithAutoResizing.mm; path = WebKit2ObjC/PreventImageLoadWithAutoResizing.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -1799,6 +1801,7 @@
</span><span class="cx">                 BC9096461255618900083756 /* WTF */ = {
</span><span class="cx">                         isa = PBXGroup;
</span><span class="cx">                         children = (
</span><ins>+                                AD7C434C1DD2A5470026888B /* Expected.cpp */,
</ins><span class="cx">                                 C0991C4F143C7D68007998F2 /* cf */,
</span><span class="cx">                                 7CBBA07519BB8A0900BBF025 /* darwin */,
</span><span class="cx">                                 BC029B1A1486B23800817DA9 /* ns */,
</span><span class="lines">@@ -2331,6 +2334,7 @@
</span><span class="cx">                                 7C83DEFE1D0A590C00FEBCF3 /* NakedPtr.cpp in Sources */,
</span><span class="cx">                                 7C83DF011D0A590C00FEBCF3 /* Optional.cpp in Sources */,
</span><span class="cx">                                 ADCEBBA61D9AE229002E283A /* Consume.cpp in Sources */,
</span><ins>+                                AD7C434D1DD2A54E0026888B /* Expected.cpp in Sources */,
</ins><span class="cx">                                 7C83DF021D0A590C00FEBCF3 /* OSObjectPtr.cpp in Sources */,
</span><span class="cx">                                 7C83DF591D0A590C00FEBCF3 /* ParkingLot.cpp in Sources */,
</span><span class="cx">                                 7C83DF131D0A590C00FEBCF3 /* RedBlackTree.cpp in Sources */,
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPITestsWTFExpectedcpp"></a>
<div class="addfile"><h4>Added: trunk/Tools/TestWebKitAPI/Tests/WTF/Expected.cpp (0 => 208670)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/Tests/WTF/Expected.cpp                                (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WTF/Expected.cpp        2016-11-13 19:28:36 UTC (rev 208670)
</span><span class="lines">@@ -0,0 +1,470 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include &quot;config.h&quot;
+
+#include &lt;string&gt;
+#include &lt;unordered_map&gt;
+
+#include &lt;wtf/Expected.h&gt;
+
+namespace WTF {
+
+template &lt;class E&gt; std::ostream&amp; operator&lt;&lt;(std::ostream&amp; os, const UnexpectedType&lt;E&gt;&amp; u)
+{
+    return os &lt;&lt; u.value();
+}
+
+template &lt;class T, class E&gt; std::ostream&amp; operator&lt;&lt;(std::ostream&amp; os, const Expected&lt;T, E&gt;&amp; e)
+{
+    if (e.hasValue())
+        return os &lt;&lt; e.value();
+    return os &lt;&lt; e.error();
+}
+
+template &lt;class E&gt; std::ostream&amp; operator&lt;&lt;(std::ostream&amp; os, const Expected&lt;void, E&gt;&amp; e)
+{
+    if (e.hasValue())
+        return os &lt;&lt; &quot;&quot;;
+    return os &lt;&lt; e.error();
+}
+
+}
+
+namespace TestWebKitAPI {
+
+constexpr const char* oops = &quot;oops&quot;;
+constexpr const char* foof = &quot;foof&quot;;
+
+TEST(WTF_Expected, UnexpectedType)
+{
+    {
+        auto u = UnexpectedType&lt;int&gt;(42);
+        EXPECT_EQ(u.value(), 42);
+        constexpr auto c = makeUnexpected(42);
+        EXPECT_EQ(c.value(), 42);
+        EXPECT_EQ(u, c);
+        EXPECT_FALSE(u != c);
+        EXPECT_FALSE(u &lt; c);
+        EXPECT_FALSE(u &gt; c);
+        EXPECT_LE(u, c);
+        EXPECT_GE(u, c);
+    }
+    {
+        auto c = makeUnexpected(oops);
+        EXPECT_EQ(c.value(), oops);
+    }
+    {
+        auto s = makeUnexpected(std::string(oops));
+        EXPECT_EQ(s.value(), oops);
+    }
+    {
+        constexpr auto s0 = makeUnexpected(oops);
+        constexpr auto s1(s0);
+        EXPECT_EQ(s0, s1);
+    }
+}
+
+struct foo {
+    int v;
+    foo(int v)
+        : v(v)
+    { }
+    ~foo() { }
+    bool operator==(const foo&amp; y) const { return v == y.v; }
+    friend std::ostream&amp; operator&lt;&lt;(std::ostream&amp;, const foo&amp;);
+};
+std::ostream&amp; operator&lt;&lt;(std::ostream&amp; os, const foo&amp; f) { return os &lt;&lt; f.v; }
+
+TEST(WTF_Expected, expected)
+{
+    typedef Expected&lt;int, const char*&gt; E;
+    typedef Expected&lt;int, const void*&gt; EV;
+    typedef Expected&lt;foo, const char*&gt; FooChar;
+    typedef Expected&lt;foo, std::string&gt; FooString;
+    {
+        auto e = E();
+        EXPECT_TRUE(e.hasValue());
+        EXPECT_EQ(e.value(), 0);
+        EXPECT_EQ(e.valueOr(3.14), 0);
+    }
+    {
+        constexpr E e;
+        EXPECT_TRUE(e.hasValue());
+        EXPECT_EQ(e.value(), 0);
+        EXPECT_EQ(e.valueOr(3.14), 0);
+    }
+    {
+        auto e = E(42);
+        EXPECT_TRUE(e.hasValue());
+        EXPECT_EQ(e.value(), 42);
+        EXPECT_EQ(e.valueOr(3.14), 42);
+        const auto e2(e);
+        EXPECT_TRUE(e2.hasValue());
+        EXPECT_EQ(e2.value(), 42);
+        EXPECT_EQ(e2.valueOr(3.14), 42);
+        E e3;
+        e3 = e2;
+        EXPECT_TRUE(e3.hasValue());
+        EXPECT_EQ(e3.value(), 42);
+        EXPECT_EQ(e3.valueOr(3.14), 42);
+        const E e4 = e2;
+        EXPECT_TRUE(e4.hasValue());
+        EXPECT_EQ(e4.value(), 42);
+        EXPECT_EQ(e4.valueOr(3.14), 42);
+    }
+    {
+        constexpr E c(42);
+        EXPECT_TRUE(c.hasValue());
+        EXPECT_EQ(c.value(), 42);
+        EXPECT_EQ(c.valueOr(3.14), 42);
+        constexpr const auto c2(c);
+        EXPECT_TRUE(c2.hasValue());
+        EXPECT_EQ(c2.value(), 42);
+        EXPECT_EQ(c2.valueOr(3.14), 42);
+    }
+    {
+        auto u = E(makeUnexpected(oops));
+        EXPECT_FALSE(u.hasValue());
+        EXPECT_EQ(u.error(), oops);
+        EXPECT_EQ(u.getUnexpected().value(), oops);
+        EXPECT_EQ(u.valueOr(3.14), 3);
+    }
+    {
+        auto uv = EV(makeUnexpected(oops));
+        EXPECT_FALSE(uv.hasValue());
+        EXPECT_EQ(uv.error(), oops);
+        EXPECT_EQ(uv.getUnexpected().value(), oops);
+        EXPECT_EQ(uv.valueOr(3.14), 3);
+    }
+    {
+        E e = makeUnexpected(oops);
+        EXPECT_FALSE(e.hasValue());
+        EXPECT_EQ(e.error(), oops);
+        EXPECT_EQ(e.getUnexpected().value(), oops);
+        EXPECT_EQ(e.valueOr(3.14), 3);
+    }
+    {
+        auto e = makeExpectedFromError&lt;int, const char*&gt;(oops);
+        EXPECT_FALSE(e.hasValue());
+        EXPECT_EQ(e.error(), oops);
+        EXPECT_EQ(e.getUnexpected().value(), oops);
+        EXPECT_EQ(e.valueOr(3.14), 3);
+    }
+    {
+        auto e = makeExpectedFromError&lt;int, const void*&gt;(oops);
+        EXPECT_FALSE(e.hasValue());
+        EXPECT_EQ(e.error(), oops);
+        EXPECT_EQ(e.getUnexpected().value(), oops);
+        EXPECT_EQ(e.valueOr(3.14), 3);
+    }
+    {
+        auto e = FooChar(42);
+        EXPECT_EQ(e-&gt;v, 42);
+        EXPECT_EQ((*e).v, 42);
+    }
+    {
+        auto e0 = E(42);
+        auto e1 = E(1024);
+        swap(e0, e1);
+        EXPECT_EQ(e0.value(), 1024);
+        EXPECT_EQ(e1.value(), 42);
+    }
+    {
+        auto e0 = E(makeUnexpected(oops));
+        auto e1 = E(makeUnexpected(foof));
+        swap(e0, e1);
+        EXPECT_EQ(e0.error(), foof);
+        EXPECT_EQ(e1.error(), oops);
+    }
+    {
+        FooChar c(foo(42));
+        EXPECT_EQ(c-&gt;v, 42);
+        EXPECT_EQ((*c).v, 42);
+    }
+    {
+        FooString s(foo(42));
+        EXPECT_EQ(s-&gt;v, 42);
+        EXPECT_EQ((*s).v, 42);
+        const char* message = &quot;very long failure string, for very bad failure cases&quot;;
+        FooString e0(makeUnexpected&lt;std::string&gt;(message));
+        FooString e1(makeUnexpected&lt;std::string&gt;(message));
+        FooString e2(makeUnexpected&lt;std::string&gt;(std::string()));
+        EXPECT_EQ(e0.error(), std::string(message));
+        EXPECT_EQ(e0, e1);
+        EXPECT_NE(e0, e2);
+        FooString* e4 = new FooString(makeUnexpected&lt;std::string&gt;(message));
+        FooString* e5 = new FooString(*e4);
+        EXPECT_EQ(e0, *e4);
+        delete e4;
+        EXPECT_EQ(e0, *e5);
+        delete e5;
+    }
+}
+
+TEST(WTF_Expected, Expected_void)
+{
+    typedef Expected&lt;void, const char*&gt; E;
+    typedef Expected&lt;void, const void*&gt; EV;
+    typedef Expected&lt;void, std::string&gt; String;
+    {
+        auto e = E();
+        EXPECT_TRUE(e.hasValue());
+        const auto e2(e);
+        EXPECT_TRUE(e2.hasValue());
+        EXPECT_EQ(e, e2);
+        E e3;
+        e3 = e2;
+        EXPECT_TRUE(e3.hasValue());
+        EXPECT_EQ(e, e3);
+    }
+    {
+        constexpr E c;
+        EXPECT_TRUE(c.hasValue());
+        constexpr const auto c2(c);
+        EXPECT_TRUE(c2.hasValue());
+        EXPECT_EQ(c, c2);
+    }
+    {
+        auto u = E(makeUnexpected(oops));
+        EXPECT_FALSE(u.hasValue());
+        EXPECT_EQ(u.error(), oops);
+        EXPECT_EQ(u.getUnexpected().value(), oops);
+    }
+    {
+        auto uv = EV(makeUnexpected(oops));
+        EXPECT_FALSE(uv.hasValue());
+        EXPECT_EQ(uv.error(), oops);
+        EXPECT_EQ(uv.getUnexpected().value(), oops);
+    }
+    {
+        E e = makeUnexpected(oops);
+        EXPECT_FALSE(e.hasValue());
+        EXPECT_EQ(e.error(), oops);
+        EXPECT_EQ(e.getUnexpected().value(), oops);
+    }
+    {
+        auto e = makeExpectedFromError&lt;void, const char*&gt;(oops);
+        EXPECT_FALSE(e.hasValue());
+        EXPECT_EQ(e.error(), oops);
+        EXPECT_EQ(e.getUnexpected().value(), oops);
+    }
+    {
+        auto e = makeExpectedFromError&lt;void, const void*&gt;(oops);
+        EXPECT_FALSE(e.hasValue());
+        EXPECT_EQ(e.error(), oops);
+        EXPECT_EQ(e.getUnexpected().value(), oops);
+    }
+    {
+        auto e0 = E();
+        auto e1 = E();
+        swap(e0, e1);
+        EXPECT_EQ(e0, e1);
+    }
+    {
+        auto e0 = E(makeUnexpected(oops));
+        auto e1 = E(makeUnexpected(foof));
+        swap(e0, e1);
+        EXPECT_EQ(e0.error(), foof);
+        EXPECT_EQ(e1.error(), oops);
+    }
+    {
+        const char* message = &quot;very long failure string, for very bad failure cases&quot;;
+        String e0(makeUnexpected&lt;std::string&gt;(message));
+        String e1(makeUnexpected&lt;std::string&gt;(message));
+        String e2(makeUnexpected&lt;std::string&gt;(std::string()));
+        EXPECT_EQ(e0.error(), std::string(message));
+        EXPECT_EQ(e0, e1);
+        EXPECT_NE(e0, e2);
+        String* e4 = new String(makeUnexpected&lt;std::string&gt;(message));
+        String* e5 = new String(*e4);
+        EXPECT_EQ(e0, *e4);
+        delete e4;
+        EXPECT_EQ(e0, *e5);
+        delete e5;
+    }
+}
+
+TEST(WTF_Expected, comparison)
+{
+    typedef Expected&lt;int, const char*&gt; Ex;
+    typedef Expected&lt;int, int&gt; Er;
+
+    // Two Expected, no errors.
+    EXPECT_EQ(Ex(42), Ex(42));
+    EXPECT_NE(Ex(42), Ex(1024));
+    EXPECT_LT(Ex(42), Ex(1024));
+    EXPECT_GT(Ex(1024), Ex(42));
+    EXPECT_LE(Ex(42), Ex(42));
+    EXPECT_GE(Ex(42), Ex(42));
+    EXPECT_LE(Ex(42), Ex(1024));
+    EXPECT_GE(Ex(1024), Ex(42));
+
+    EXPECT_FALSE(Ex(42) == Ex(1024));
+    EXPECT_FALSE(Ex(42) != Ex(42));
+    EXPECT_FALSE(Ex(1024) &lt; Ex(42));
+    EXPECT_FALSE(Ex(42) &gt; Ex(1024));
+    EXPECT_FALSE(Ex(1024) &lt; Ex(42));
+    EXPECT_FALSE(Ex(42) &gt;= Ex(1024));
+
+    // Two Expected, half errors.
+    EXPECT_FALSE(Ex(42) == Ex(makeUnexpected(oops)));
+    EXPECT_NE(Ex(42), Ex(makeUnexpected(oops)));
+    EXPECT_LT(Ex(42), Ex(makeUnexpected(oops)));
+    EXPECT_FALSE(Ex(42) &gt; Ex(makeUnexpected(oops)));
+    EXPECT_LE(Ex(42), Ex(makeUnexpected(oops)));
+    EXPECT_FALSE(Ex(42) &gt;= Ex(makeUnexpected(oops)));
+
+    EXPECT_FALSE(Ex(makeUnexpected(oops)) == Ex(42));
+    EXPECT_NE(Ex(makeUnexpected(oops)), Ex(42));
+    EXPECT_FALSE(Ex(makeUnexpected(oops)) &lt; Ex(42));
+    EXPECT_GT(Ex(makeUnexpected(oops)), Ex(42));
+    EXPECT_FALSE(Ex(makeUnexpected(oops)) &lt;= Ex(42));
+    EXPECT_GE(Ex(makeUnexpected(oops)), Ex(42));
+
+    // Two Expected, all errors.
+    EXPECT_EQ(Er(42), Er(42));
+    EXPECT_NE(Er(42), Er(1024));
+    EXPECT_LT(Er(42), Er(1024));
+    EXPECT_GT(Er(1024), Er(42));
+    EXPECT_LE(Er(42), Er(42));
+    EXPECT_GE(Er(42), Er(42));
+    EXPECT_LE(Er(42), Er(1024));
+    EXPECT_GE(Er(1024), Er(42));
+
+    EXPECT_FALSE(Er(42) == Er(1024));
+    EXPECT_FALSE(Er(42) != Er(42));
+    EXPECT_FALSE(Er(1024) &lt; Er(42));
+    EXPECT_FALSE(Er(42) &gt; Er(1024));
+    EXPECT_FALSE(Er(1024) &lt;= Er(42));
+    EXPECT_FALSE(Er(42) &gt;= Er(1024));
+
+    // One Expected, one value.
+    EXPECT_EQ(Ex(42), 42);
+    EXPECT_NE(Ex(42), 0);
+    EXPECT_LT(Ex(42), 1024);
+    EXPECT_GT(Ex(1024), 42);
+    EXPECT_LE(Ex(42), 42);
+    EXPECT_GE(Ex(42), 42);
+    EXPECT_LE(Ex(42), 1024);
+    EXPECT_GE(Ex(1024), 42);
+
+    EXPECT_FALSE(Ex(42) == 0);
+    EXPECT_FALSE(Ex(42) != 42);
+    EXPECT_FALSE(Ex(1024) &lt; 42);
+    EXPECT_FALSE(Ex(42) &gt; 1024);
+    EXPECT_FALSE(Ex(1024) &lt; 42);
+    EXPECT_FALSE(Ex(42) &gt;= 1024);
+
+    EXPECT_EQ(42, Ex(42));
+    EXPECT_NE(42, Ex(1024));
+    EXPECT_LT(42, Ex(1024));
+    EXPECT_GT(1024, Ex(42));
+    EXPECT_LE(42, Ex(42));
+    EXPECT_GE(42, Ex(42));
+    EXPECT_LE(42, Ex(1024));
+    EXPECT_GE(1024, Ex(42));
+
+    EXPECT_FALSE(42 == Ex(1024));
+    EXPECT_FALSE(42 != Ex(42));
+    EXPECT_FALSE(1024 &lt; Ex(42));
+    EXPECT_FALSE(42 &gt; Ex(1024));
+    EXPECT_FALSE(1024 &lt;= Ex(42));
+    EXPECT_FALSE(42 &gt;= Ex(1024));
+
+    // One Expected, one unexpected.
+    EXPECT_FALSE(Ex(42) == makeUnexpected(oops));
+    EXPECT_NE(Ex(42), makeUnexpected(oops));
+    EXPECT_LT(Ex(42), makeUnexpected(oops));
+    EXPECT_FALSE(Ex(42) &gt; makeUnexpected(oops));
+    EXPECT_LE(Ex(42), makeUnexpected(oops));
+    EXPECT_FALSE(Ex(42) &gt;= makeUnexpected(oops));
+
+    EXPECT_FALSE(makeUnexpected(oops) == Ex(42));
+    EXPECT_NE(makeUnexpected(oops), Ex(42));
+    EXPECT_FALSE(makeUnexpected(oops) &lt; Ex(42));
+    EXPECT_GT(makeUnexpected(oops), Ex(42));
+    EXPECT_FALSE(makeUnexpected(oops) &lt;= Ex(42));
+    EXPECT_GE(makeUnexpected(oops), Ex(42));
+}
+
+struct NonTrivialDtor {
+    ~NonTrivialDtor() { ++count; }
+    static int count;
+};
+int NonTrivialDtor::count = 0;
+
+TEST(WTF_Expected, destructors)
+{
+    typedef Expected&lt;NonTrivialDtor, const char*&gt; NT;
+    typedef Expected&lt;const char*, NonTrivialDtor&gt; TN;
+    typedef Expected&lt;NonTrivialDtor, NonTrivialDtor&gt; NN;
+    typedef Expected&lt;void, NonTrivialDtor&gt; VN;
+    EXPECT_EQ(NonTrivialDtor::count, 0);
+    { NT nt; }
+    EXPECT_EQ(NonTrivialDtor::count, 1);
+    { NT nt = makeUnexpected(oops); }
+    EXPECT_EQ(NonTrivialDtor::count, 1);
+    { TN tn; }
+    EXPECT_EQ(NonTrivialDtor::count, 1);
+    { TN tn = makeUnexpected(NonTrivialDtor()); }
+    EXPECT_EQ(NonTrivialDtor::count, 4);
+    { NN nn; }
+    EXPECT_EQ(NonTrivialDtor::count, 5);
+    { NN nn = makeUnexpected(NonTrivialDtor()); }
+    EXPECT_EQ(NonTrivialDtor::count, 8);
+    { VN vn; }
+    EXPECT_EQ(NonTrivialDtor::count, 8);
+    { VN vn = makeUnexpected(NonTrivialDtor()); }
+    EXPECT_EQ(NonTrivialDtor::count, 11);
+}
+
+TEST(WTF_Expected, hash)
+{
+    typedef Expected&lt;int, const char*&gt; E;
+    std::unordered_map&lt;E, int&gt; m;
+    m.insert({ E(42), 42 });
+    m.insert({ E(makeUnexpected(oops)), 5 });
+    m.insert({ E(1024), 1024 });
+    m.insert({ E(makeUnexpected(foof)), 0xf00f });
+    EXPECT_EQ(m[E(42)], 42);
+    EXPECT_EQ(m[E(1024)], 1024);
+    EXPECT_EQ(m[E(makeUnexpected(oops))], 5);
+    EXPECT_EQ(m[E(makeUnexpected(foof))], 0xf00f);
+}
+
+TEST(WTF_Expected, hash_void)
+{
+    typedef Expected&lt;void, const char*&gt; E;
+    std::unordered_map&lt;E, int&gt; m;
+    m.insert({ E(), 42 });
+    m.insert({ E(makeUnexpected(oops)), 5 });
+    m.insert({ E(makeUnexpected(foof)), 0xf00f });
+    EXPECT_EQ(m[E()], 42);
+    EXPECT_EQ(m[E(makeUnexpected(oops))], 5);
+    EXPECT_EQ(m[E(makeUnexpected(foof))], 0xf00f);
+}
+
+} // namespace TestWebkitAPI
</ins></span></pre>
</div>
</div>

</body>
</html>