Bug 193056

Summary: Prefer RetainPtr<NSObject> to RetainPtr<NSObject *>
Product: WebKit Reporter: David Kilzer (:ddkilzer) <ddkilzer>
Component: Web Template FrameworkAssignee: David Kilzer (:ddkilzer) <ddkilzer>
Status: RESOLVED FIXED    
Severity: Normal CC: achristensen, andersca, bfulgham, cdumez, commit-queue, darin, dbates, ews-watchlist, jiewen_tan, mitz, mjs, webkit-bug-importer, ysuzuki
Priority: P2 Keywords: InRadar
Version: WebKit Local Build   
Hardware: Unspecified   
OS: Unspecified   
Attachments:
Description Flags
Patch v1
none
Patch v2 achristensen: review+, commit-queue: commit-queue-

Description David Kilzer (:ddkilzer) 2018-12-29 05:33:35 PST
Prefer RetainPtr<NSObject> to RetainPtr<NSObject *> because:
- It was the original intent based on Macieij's comment from r16987.
- The vast majority of RetainPtr<> use in WebKit already omits the '*' operator for NS types.  (Yay consistency!)
- We can write a style checker rule to enforce it.
- We can make adoptNS() and retainPtr() create the correct types using C++ template metaprogramming.

Note that RetainPtr<NSObject *> still works as it did before (and tests have been added to verify that it works with RetainPtr<NSObject>).

This change simply formalizes the preference for RetainPtr<NSObject> over RetainPtr<NSObject *>.
Comment 1 David Kilzer (:ddkilzer) 2018-12-29 05:49:04 PST
Created attachment 358136 [details]
Patch v1
Comment 2 David Kilzer (:ddkilzer) 2018-12-29 05:51:53 PST
Comment on attachment 358136 [details]
Patch v1

View in context: https://bugs.webkit.org/attachment.cgi?id=358136&action=review

> Source/WTF/wtf/RetainPtr.h:60
> +template<typename T> RetainPtr<typename std::conditional<std::is_convertible<T, id>::value && !std::is_same<T, id>::value, typename std::remove_pointer<T>::type, T>::type> adoptNS(T NS_RELEASES_ARGUMENT) WARN_UNUSED_RETURN;

After posting this patch, I just realized I might be able to do something simpler which matches the way that ValueType is defined:

-template<typename T> RetainPtr<typename std::conditional<std::is_convertible<T, id>::value && !std::is_same<T, id>::value, typename std::remove_pointer<T>::type, T>::type> adoptNS(T NS_RELEASES_ARGUMENT) WARN_UNUSED_RETURN;
+template<typename T> RetainPtr<typename std::remove_pointer<T>::type> adoptNS(T NS_RELEASES_ARGUMENT) WARN_UNUSED_RETURN;

Testing now.
Comment 3 EWS Watchlist 2018-12-29 05:52:21 PST
Attachment 358136 [details] did not pass style-queue:


ERROR: Tools/Scripts/webkitpy/style/checkers/cpp.py:3321:  at least two spaces before inline comment  [pep8/E261] [5]
Total errors found: 1 in 42 files


If any of these errors are false positives, please file a bug against check-webkit-style.
Comment 4 David Kilzer (:ddkilzer) 2018-12-29 10:01:15 PST
Comment on attachment 358136 [details]
Patch v1

View in context: https://bugs.webkit.org/attachment.cgi?id=358136&action=review

>> Source/WTF/wtf/RetainPtr.h:60
>> +template<typename T> RetainPtr<typename std::conditional<std::is_convertible<T, id>::value && !std::is_same<T, id>::value, typename std::remove_pointer<T>::type, T>::type> adoptNS(T NS_RELEASES_ARGUMENT) WARN_UNUSED_RETURN;
> 
> After posting this patch, I just realized I might be able to do something simpler which matches the way that ValueType is defined:
> 
> -template<typename T> RetainPtr<typename std::conditional<std::is_convertible<T, id>::value && !std::is_same<T, id>::value, typename std::remove_pointer<T>::type, T>::type> adoptNS(T NS_RELEASES_ARGUMENT) WARN_UNUSED_RETURN;
> +template<typename T> RetainPtr<typename std::remove_pointer<T>::type> adoptNS(T NS_RELEASES_ARGUMENT) WARN_UNUSED_RETURN;
> 
> Testing now.

Yes this can be simplified.  Making some changes now.
Comment 5 David Kilzer (:ddkilzer) 2018-12-29 10:02:48 PST
Comment on attachment 358136 [details]
Patch v1

View in context: https://bugs.webkit.org/attachment.cgi?id=358136&action=review

> Tools/TestWebKitAPI/Tests/WTF/cf/RetainPtr.cpp:168
> +    EXPECT_FALSE(optionalObject2.value());

This caused a RELEASE_ASSERT() for `optionalObject2` not having a value.  Needs to be:

    EXPECT_FALSE(optionalObject2);

> Tools/TestWebKitAPI/Tests/WTF/ns/RetainPtr.mm:253
> +    EXPECT_FALSE(optionalObject2.value());

This caused a RELEASE_ASSERT() for `optionalObject2` not having a value.  Needs to be:

    EXPECT_FALSE(optionalObject2);
Comment 6 David Kilzer (:ddkilzer) 2018-12-29 10:09:37 PST
The way std::remove_pointer<T> works is that it only removes explicit pointer operators from type T, even if type T is a pointer beneath a typedef.

That means:

typename std::remove_pointer<NSArray *>::type == NSArray

But that:

typename std::remove_pointer<NSArray>::type == NSArray
typename std::remove_pointer<id>::type == id
typename std::remove_pointer<CFArrayRef>::type == CFArrayRef

This is why ValueType uses an unconditional std::remove_pointer<t> in the RetainPtr class definition.
Comment 7 David Kilzer (:ddkilzer) 2018-12-29 10:42:47 PST
(In reply to David Kilzer (:ddkilzer) from comment #6)
> The way std::remove_pointer<T> works is that it only removes explicit
> pointer operators from type T, even if type T is a pointer beneath a typedef.
> 
> That means:
> 
> typename std::remove_pointer<NSArray *>::type == NSArray
> 
> But that:
> 
> typename std::remove_pointer<NSArray>::type == NSArray
> typename std::remove_pointer<id>::type == id
> typename std::remove_pointer<CFArrayRef>::type == CFArrayRef

And I'm wrong (yay tests!):

Tools/TestWebKitAPI/Tests/WTF/cf/RetainPtr.cpp:141:38: error: no viable conversion from 'RetainPtr<typename std::remove_pointer<const __CFNumber *>::type>' (aka 'RetainPtr<const __CFNumber>') to 'Optional<RetainPtr<CFNumberRef> >' (aka 'Optional<RetainPtr<const __CFNumber *> >')
    Optional<RetainPtr<CFNumberRef>> optionalObject2 = retainPtr(CFNumberCreate(kCFAllocatorDefault, kCFNumberFloatType,
 &value));
                                     ^                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~

I think it depends on how the type is defined by the compiler.
Comment 8 David Kilzer (:ddkilzer) 2018-12-29 13:40:32 PST
Created attachment 358140 [details]
Patch v2
Comment 9 David Kilzer (:ddkilzer) 2018-12-29 13:40:50 PST
Comment on attachment 358140 [details]
Patch v2

- Fix crashing TestWTF.RetainPtr tests.
- Defined shared typedef to clean up RetainPtr.h changes.
Comment 10 EWS Watchlist 2018-12-29 13:44:12 PST
Attachment 358140 [details] did not pass style-queue:


ERROR: Tools/Scripts/webkitpy/style/checkers/cpp.py:3321:  at least two spaces before inline comment  [pep8/E261] [5]
Total errors found: 1 in 42 files


If any of these errors are false positives, please file a bug against check-webkit-style.
Comment 11 Alex Christensen 2019-01-03 09:56:14 PST
Comment on attachment 358140 [details]
Patch v2

Was the motivation for doing all this work just style?
Comment 12 David Kilzer (:ddkilzer) 2019-01-03 12:09:05 PST
(In reply to Alex Christensen from comment #11)
> Comment on attachment 358140 [details]
> Patch v2
> 
> Was the motivation for doing all this work just style?

Yes, for consistency.  It's one of the primary reasons we have WebKit style guidelines.
Comment 13 David Kilzer (:ddkilzer) 2019-01-03 17:32:58 PST
Thanks for the review, Alex!  Waiting to land this until after the next branch.
Comment 14 WebKit Commit Bot 2019-01-07 13:33:41 PST
Comment on attachment 358140 [details]
Patch v2

Rejecting attachment 358140 [details] from commit-queue.

Failed to run "['/Volumes/Data/EWS/WebKit/Tools/Scripts/webkit-patch', '--status-host=webkit-queues.webkit.org', '--bot-id=webkit-cq-03', 'apply-attachment', '--no-update', '--non-interactive', 358140, '--port=mac']" exit_code: 2 cwd: /Volumes/Data/EWS/WebKit

Logging in as commit-queue@webkit.org...
Fetching: https://bugs.webkit.org/attachment.cgi?id=358140&action=edit
Fetching: https://bugs.webkit.org/show_bug.cgi?id=193056&ctype=xml&excludefield=attachmentdata
Processing 1 patch from 1 bug.
Processing patch 358140 from bug 193056.
Fetching: https://bugs.webkit.org/attachment.cgi?id=358140
Failed to run "[u'/Volumes/Data/EWS/WebKit/Tools/Scripts/svn-apply', '--force', '--reviewer', u'Alex Christensen']" exit_code: 1 cwd: /Volumes/Data/EWS/WebKit

Parsed 42 diffs from patch file(s).
patching file Source/WTF/ChangeLog
Hunk #1 succeeded at 1 with fuzz 3.
patching file Source/WebCore/ChangeLog
Hunk #1 succeeded at 1 with fuzz 3.
patching file Source/WebKit/ChangeLog
Hunk #1 succeeded at 1 with fuzz 3.
patching file Source/WebKitLegacy/mac/ChangeLog
Hunk #1 succeeded at 1 with fuzz 3.
patching file Source/WTF/wtf/RetainPtr.h
patching file Source/WTF/wtf/SchedulePair.h
patching file Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm
patching file Source/WebCore/platform/network/cf/AuthenticationChallenge.h
patching file Source/WebCore/platform/network/cocoa/NetworkStorageSessionCocoa.mm
patching file Source/WebKit/Shared/EntryPointUtilities/mac/XPCService/XPCServiceMain.mm
patching file Source/WebKit/UIProcess/API/Cocoa/_WKThumbnailView.mm
patching file Source/WebKit/UIProcess/ApplePay/WebPaymentCoordinatorProxy.h
patching file Source/WebKit/UIProcess/Cocoa/VideoFullscreenManagerProxy.h
patching file Source/WebKit/UIProcess/Plugins/PluginProcessProxy.h
patching file Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteLayerTreeHostIOS.mm
patching file Source/WebKit/WebProcess/WebPage/RemoteLayerTree/PlatformCALayerRemoteCustom.mm
patching file Source/WebKitLegacy/mac/Plugins/Hosted/NetscapePluginHostProxy.h
patching file Source/WebKitLegacy/mac/Plugins/Hosted/NetscapePluginInstanceProxy.h
patching file Source/WebKitLegacy/mac/Plugins/Hosted/NetscapePluginInstanceProxy.mm
patching file Source/WebKitLegacy/mac/Plugins/Hosted/ProxyInstance.mm
patching file Source/WebKitLegacy/mac/WebCoreSupport/WebGeolocationClient.mm
patching file Source/WebKitLegacy/mac/WebView/WebDataSource.mm
patching file Source/WebKitLegacy/mac/WebView/WebView.mm
patching file Tools/ChangeLog
Hunk #1 succeeded at 1 with fuzz 3.
patching file Tools/Scripts/webkitpy/style/checker.py
patching file Tools/Scripts/webkitpy/style/checkers/cpp.py
patching file Tools/Scripts/webkitpy/style/checkers/cpp_unittest.py
patching file Tools/TestRunnerShared/EventSerialization/mac/EventSerializerMac.h
patching file Tools/TestWebKitAPI/EditingTestHarness.h
patching file Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
Hunk #1 succeeded at 172 (offset 1 line).
Hunk #2 succeeded at 3806 (offset 24 lines).
patching file Tools/TestWebKitAPI/Tests/WTF/cf/RetainPtr.cpp
patching file Tools/TestWebKitAPI/Tests/WTF/ns/RetainPtr.mm
patching file Tools/TestWebKitAPI/Tests/WebKitCocoa/DownloadProgress.mm
patching file Tools/TestWebKitAPI/Tests/WebKitCocoa/IconLoadingDelegate.mm
patching file Tools/TestWebKitAPI/Tests/WebKitCocoa/JITEnabled.mm
patching file Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm
patching file Tools/TestWebKitAPI/Tests/WebKitCocoa/VideoControlsManager.mm
patching file Tools/TestWebKitAPI/Tests/WebKitCocoa/WebsitePolicies.mm
Hunk #1 FAILED at 865.
1 out of 1 hunk FAILED -- saving rejects to file Tools/TestWebKitAPI/Tests/WebKitCocoa/WebsitePolicies.mm.rej
patching file Tools/TestWebKitAPI/ios/DragAndDropSimulatorIOS.mm
patching file Tools/WebKitTestRunner/InjectedBundle/cocoa/ActivateFontsCocoa.mm
patching file Tools/WebKitTestRunner/InjectedBundle/ios/InjectedBundleIOS.mm
patching file Tools/WebKitTestRunner/cocoa/TestRunnerWKWebView.mm

Failed to run "[u'/Volumes/Data/EWS/WebKit/Tools/Scripts/svn-apply', '--force', '--reviewer', u'Alex Christensen']" exit_code: 1 cwd: /Volumes/Data/EWS/WebKit

Full output: https://webkit-queues.webkit.org/results/10661738
Comment 15 David Kilzer (:ddkilzer) 2019-01-07 16:03:32 PST
Committed r239709: <https://trac.webkit.org/changeset/239709>
Comment 16 David Kilzer (:ddkilzer) 2019-01-08 07:28:00 PST
<rdar://problem/47115086>