From 1508cda2f6009c107292e487f3d5a8e5ad19fced Mon Sep 17 00:00:00 2001
From: Nikita Lutsenko <nlutsenko@me.com>
Date: Wed, 23 Nov 2016 11:49:23 -0800
Subject: [PATCH 1/2] Add BFVoid macro.

---
 Bolts.xcodeproj/project.pbxproj | 16 ++++++++++++++++
 Bolts/Common/BFGeneric.h        | 25 +++++++++++++++++++++++++
 Bolts/Common/Bolts.h            |  1 +
 3 files changed, 42 insertions(+)
 create mode 100644 Bolts/Common/BFGeneric.h

diff --git a/Bolts.xcodeproj/project.pbxproj b/Bolts.xcodeproj/project.pbxproj
index cd94871..1a77030 100644
--- a/Bolts.xcodeproj/project.pbxproj
+++ b/Bolts.xcodeproj/project.pbxproj
@@ -59,6 +59,13 @@
 		8103FA6B19900A84000BAE3F /* BFTask.m in Sources */ = {isa = PBXBuildFile; fileRef = 8103FA5119900A84000BAE3F /* BFTask.m */; };
 		8103FA6D19900A84000BAE3F /* BFTaskCompletionSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 8103FA5319900A84000BAE3F /* BFTaskCompletionSource.m */; };
 		8103FA6F19900A84000BAE3F /* Bolts.m in Sources */ = {isa = PBXBuildFile; fileRef = 8103FA5519900A84000BAE3F /* Bolts.m */; };
+		8160B82C1DE6277200C6E285 /* BFGeneric.h in Headers */ = {isa = PBXBuildFile; fileRef = 8160B82B1DE6277200C6E285 /* BFGeneric.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		8160B82D1DE6277200C6E285 /* BFGeneric.h in Headers */ = {isa = PBXBuildFile; fileRef = 8160B82B1DE6277200C6E285 /* BFGeneric.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		8160B82E1DE6277200C6E285 /* BFGeneric.h in Headers */ = {isa = PBXBuildFile; fileRef = 8160B82B1DE6277200C6E285 /* BFGeneric.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		8160B82F1DE6277200C6E285 /* BFGeneric.h in Headers */ = {isa = PBXBuildFile; fileRef = 8160B82B1DE6277200C6E285 /* BFGeneric.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		8160B8301DE6277200C6E285 /* BFGeneric.h in Headers */ = {isa = PBXBuildFile; fileRef = 8160B82B1DE6277200C6E285 /* BFGeneric.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		8160B8311DE6277200C6E285 /* BFGeneric.h in Headers */ = {isa = PBXBuildFile; fileRef = 8160B82B1DE6277200C6E285 /* BFGeneric.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		8160B8321DE6277200C6E285 /* BFGeneric.h in Headers */ = {isa = PBXBuildFile; fileRef = 8160B82B1DE6277200C6E285 /* BFGeneric.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		8178F9861BB0F87700AD289D /* BFTaskCompletionSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 8103FA5319900A84000BAE3F /* BFTaskCompletionSource.m */; };
 		8178F9871BB0F87700AD289D /* BFTask.m in Sources */ = {isa = PBXBuildFile; fileRef = 8103FA5119900A84000BAE3F /* BFTask.m */; };
 		8178F9881BB0F87700AD289D /* Bolts.m in Sources */ = {isa = PBXBuildFile; fileRef = 8103FA5519900A84000BAE3F /* Bolts.m */; };
@@ -266,6 +273,7 @@
 		8103FA6619900A84000BAE3F /* BFWebViewAppLinkResolver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BFWebViewAppLinkResolver.h; sourceTree = "<group>"; };
 		8103FA6719900A84000BAE3F /* BFWebViewAppLinkResolver.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BFWebViewAppLinkResolver.m; sourceTree = "<group>"; };
 		814916E11AD5D46600EE7C63 /* iOS.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; name = iOS.modulemap; path = Resources/iOS.modulemap; sourceTree = "<group>"; };
+		8160B82B1DE6277200C6E285 /* BFGeneric.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BFGeneric.h; sourceTree = "<group>"; };
 		8178F99C1BB0F87700AD289D /* Bolts.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Bolts.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		819573F11C2B8ECB00BFCA39 /* Bolts.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Bolts.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		81AB8BB11D36D7BD00066F63 /* Version.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Version.xcconfig; sourceTree = "<group>"; };
@@ -441,6 +449,7 @@
 			children = (
 				8103FA5419900A84000BAE3F /* Bolts.h */,
 				8103FA5519900A84000BAE3F /* Bolts.m */,
+				8160B82B1DE6277200C6E285 /* BFGeneric.h */,
 				8103FA5019900A84000BAE3F /* BFTask.h */,
 				8103FA5119900A84000BAE3F /* BFTask.m */,
 				81CD06291CEED28A00497F47 /* BFTask+Exceptions.h */,
@@ -653,6 +662,7 @@
 			files = (
 				1D5D7DBA1BE3CE8200FD67C7 /* BFWebViewAppLinkResolver.h in Headers */,
 				81CD062B1CEED28A00497F47 /* BFTask+Exceptions.h in Headers */,
+				8160B82D1DE6277200C6E285 /* BFGeneric.h in Headers */,
 				81CF830D1D0B559800633946 /* BFAppLinkReturnToRefererView_Internal.h in Headers */,
 				81CF83111D0B559800633946 /* BFURL_Internal.h in Headers */,
 				1D5D7DBB1BE3CE8200FD67C7 /* BFCancellationTokenRegistration.h in Headers */,
@@ -686,6 +696,7 @@
 				8178F9931BB0F87700AD289D /* BFExecutor.h in Headers */,
 				8178F9951BB0F87700AD289D /* BFTaskCompletionSource.h in Headers */,
 				8178F9971BB0F87700AD289D /* Bolts.h in Headers */,
+				8160B8311DE6277200C6E285 /* BFGeneric.h in Headers */,
 				8178F9981BB0F87700AD289D /* BFCancellationToken.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -701,6 +712,7 @@
 				819573E81C2B8ECB00BFCA39 /* BFExecutor.h in Headers */,
 				819573EA1C2B8ECB00BFCA39 /* BFTaskCompletionSource.h in Headers */,
 				819573EC1C2B8ECB00BFCA39 /* Bolts.h in Headers */,
+				8160B8321DE6277200C6E285 /* BFGeneric.h in Headers */,
 				819573ED1C2B8ECB00BFCA39 /* BFCancellationToken.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -716,6 +728,7 @@
 				81D0EE8819AFAA240000AE75 /* BFExecutor.h in Headers */,
 				81D0EE8A19AFAA2C0000AE75 /* BFTaskCompletionSource.h in Headers */,
 				81D0EE8319AFAA0E0000AE75 /* Bolts.h in Headers */,
+				8160B82E1DE6277200C6E285 /* BFGeneric.h in Headers */,
 				7C60AEC81ACF1A0100747DD7 /* BFCancellationToken.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -731,6 +744,7 @@
 				81E94D611C2B8BF200A6291E /* BFExecutor.h in Headers */,
 				81E94D631C2B8BF200A6291E /* BFTaskCompletionSource.h in Headers */,
 				81E94D651C2B8BF200A6291E /* Bolts.h in Headers */,
+				8160B8301DE6277200C6E285 /* BFGeneric.h in Headers */,
 				81E94D661C2B8BF200A6291E /* BFCancellationToken.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -741,6 +755,7 @@
 			files = (
 				81ED94311BE1481900795F05 /* BFWebViewAppLinkResolver.h in Headers */,
 				81CD062A1CEED28A00497F47 /* BFTask+Exceptions.h in Headers */,
+				8160B82C1DE6277200C6E285 /* BFGeneric.h in Headers */,
 				81CF830C1D0B559800633946 /* BFAppLinkReturnToRefererView_Internal.h in Headers */,
 				81CF83101D0B559800633946 /* BFURL_Internal.h in Headers */,
 				81ED941D1BE147CF00795F05 /* BFCancellationTokenRegistration.h in Headers */,
@@ -774,6 +789,7 @@
 				F5AFC9F91BA752750076E927 /* BFExecutor.h in Headers */,
 				F5AFC9FB1BA752750076E927 /* BFTaskCompletionSource.h in Headers */,
 				F5AFC9FD1BA752750076E927 /* Bolts.h in Headers */,
+				8160B82F1DE6277200C6E285 /* BFGeneric.h in Headers */,
 				F5AFC9FE1BA752750076E927 /* BFCancellationToken.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
diff --git a/Bolts/Common/BFGeneric.h b/Bolts/Common/BFGeneric.h
new file mode 100644
index 0000000..99b2cf7
--- /dev/null
+++ b/Bolts/Common/BFGeneric.h
@@ -0,0 +1,25 @@
+/*
+ *  Copyright (c) 2014, Facebook, Inc.
+ *  All rights reserved.
+ *
+ *  This source code is licensed under the BSD-style license found in the
+ *  LICENSE file in the root directory of this source tree. An additional grant
+ *  of patent rights can be found in the PATENTS file in the same directory.
+ *
+ */
+
+#import <Foundation/Foundation.h>
+
+#pragma once
+
+/**
+ This exists to use along with `BFTask` and `BFTaskCompletionSource`.
+
+ Instead of returning a `BFTask` with no generic type, or a generic type of 'NSNull'
+ when there is no usable result from a task, we use the type 'BFVoid', which will always have a value of `nil`.
+
+ This allows you to provide a more enforced API contract to the caller,
+ as sending any message to `BFVoid` will result in a compile time error.
+ */
+@class _BFVoid_Nonexistant;
+typedef _BFVoid_Nonexistant *BFVoid;
diff --git a/Bolts/Common/Bolts.h b/Bolts/Common/Bolts.h
index 907e4a2..d90a999 100644
--- a/Bolts/Common/Bolts.h
+++ b/Bolts/Common/Bolts.h
@@ -12,6 +12,7 @@
 #import <Bolts/BFCancellationTokenRegistration.h>
 #import <Bolts/BFCancellationTokenSource.h>
 #import <Bolts/BFExecutor.h>
+#import <Bolts/BFGeneric.h>
 #import <Bolts/BFTask.h>
 #import <Bolts/BFTask+Exceptions.h>
 #import <Bolts/BFTaskCompletionSource.h>
-- 
GitLab


From 2528be4a69cc373a0dfc2a603e94a63cdbf3c945 Mon Sep 17 00:00:00 2001
From: Nikita Lutsenko <nlutsenko@me.com>
Date: Wed, 23 Nov 2016 11:49:40 -0800
Subject: [PATCH 2/2] Update BFTask.taskWithDelay to use BFVoid.

---
 Bolts/Common/BFTask.h | 5 +++--
 Bolts/Common/BFTask.m | 4 ++--
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/Bolts/Common/BFTask.h b/Bolts/Common/BFTask.h
index a84f37d..37c1bd7 100644
--- a/Bolts/Common/BFTask.h
+++ b/Bolts/Common/BFTask.h
@@ -11,6 +11,7 @@
 #import <Foundation/Foundation.h>
 
 #import <Bolts/BFCancellationToken.h>
+#import <Bolts/BFGeneric.h>
 
 NS_ASSUME_NONNULL_BEGIN
 
@@ -116,7 +117,7 @@ __attribute__((deprecated("`BFTask` exception handling is deprecated and will be
  @param millis The approximate number of milliseconds to wait before the
  task will be finished (with result == nil).
  */
-+ (instancetype)taskWithDelay:(int)millis;
++ (BFTask<BFVoid> *)taskWithDelay:(int)millis;
 
 /*!
  Returns a task that will be completed a certain amount of time in the future.
@@ -124,7 +125,7 @@ __attribute__((deprecated("`BFTask` exception handling is deprecated and will be
  task will be finished (with result == nil).
  @param token The cancellation token (optional).
  */
-+ (instancetype)taskWithDelay:(int)millis cancellationToken:(nullable BFCancellationToken *)token;
++ (BFTask<BFVoid> *)taskWithDelay:(int)millis cancellationToken:(nullable BFCancellationToken *)token;
 
 /*!
  Returns a task that will be completed after the given block completes with
diff --git a/Bolts/Common/BFTask.m b/Bolts/Common/BFTask.m
index 2346600..356cbbc 100644
--- a/Bolts/Common/BFTask.m
+++ b/Bolts/Common/BFTask.m
@@ -254,7 +254,7 @@ NSString *const BFTaskMultipleExceptionsUserInfoKey = @"exceptions";
 }
 
 
-+ (instancetype)taskWithDelay:(int)millis {
++ (BFTask<BFVoid> *)taskWithDelay:(int)millis {
     BFTaskCompletionSource *tcs = [BFTaskCompletionSource taskCompletionSource];
     dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, millis * NSEC_PER_MSEC);
     dispatch_after(popTime, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
@@ -263,7 +263,7 @@ NSString *const BFTaskMultipleExceptionsUserInfoKey = @"exceptions";
     return tcs.task;
 }
 
-+ (instancetype)taskWithDelay:(int)millis cancellationToken:(nullable BFCancellationToken *)token {
++ (BFTask<BFVoid> *)taskWithDelay:(int)millis cancellationToken:(nullable BFCancellationToken *)token {
     if (token.cancellationRequested) {
         return [BFTask cancelledTask];
     }
-- 
GitLab