Bug 144450

Summary: NeverDestroyed<T> objects should always use direct initialization
Product: WebKit Reporter: Zan Dobersek <zan>
Component: New BugsAssignee: Zan Dobersek <zan>
Status: NEW ---    
Severity: Normal CC: darin
Priority: P2    
Version: 528+ (Nightly build)   
Hardware: Unspecified   
OS: Unspecified   
Attachments:
Description Flags
Patch darin: review-

Description Zan Dobersek 2015-04-30 08:19:47 PDT
NeverDestroyed<T> objects should always use direct initialization
Comment 1 Zan Dobersek 2015-04-30 08:43:00 PDT
Created attachment 252059 [details]
Patch
Comment 2 Darin Adler 2015-05-02 07:31:44 PDT
Comment on attachment 252059 [details]
Patch

I don’t think we should make this change. Is there one case you can point to here where the different syntax results in different code?
Comment 3 Darin Adler 2015-05-02 07:34:22 PDT
Comment on attachment 252059 [details]
Patch

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

/Volumes/Data/EWS/WebKit/Source/WebCore/platform/network/ios/QuickLook.mm:62:45: error: no viable conversion from 'NSSet *' to 'NeverDestroyed<RetainPtr<NSSet> >'
    static NeverDestroyed<RetainPtr<NSSet>> set = QLPreviewGetSupportedMIMETypes();
                                            ^     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

> Source/WTF/wtf/Noncopyable.h:33
> +// FIXME: Move to a more generic place together with WTF_MAKE_NONCOPYABLE.
> +#define WTF_MAKE_NONMOVABLE(ClassName) \
> +    private: \
> +        ClassName(ClassName&&) = delete; \
> +        ClassName& operator=(ClassName&&) = delete; \

I think we should just write out the "= delete" for both this and non copyable. The macros date back to when this was much trickier to do in the language.

> Source/WebCore/html/HTMLBodyElement.cpp:143
> +    static NeverDestroyed<EventHandlerNameMap> map(createWindowEventHandlerNameMap());

This syntax looks like a function call to me. I prefer the modern syntax with { } if we insist on not using initialization style. But I think I don’t agree with the overall mission here. Have we ever had a real problem with this?
Comment 4 Zan Dobersek 2015-05-02 13:23:53 PDT
(In reply to comment #2)
> Comment on attachment 252059 [details]
> Patch
> 
> I don’t think we should make this change. Is there one case you can point to
> here where the different syntax results in different code?

There's apparently a guarantee that the copy initialization of a NeverDestroyed object with a to-be-wrapped object is optimized into a direct initialization as long as it's possible to convert the to-be-wrapped object into a NeverDestroyed object (which it is, due to the non-explicit NeverDestroyed constructor) and the NeverDestroyed class has a usable move constructor (which it does, since it's not deleted). Despite this optimisation, the move constructor actually requires for the to-be-wrapped object to be copyable, making it impossible to use such initialization with non-copyable classes.

I'd like to disable both of those conditions because that would enforce a uniform way of NeverDestroyed initialization. Given that NeverDestroyed is already non-copyable, there's no reason for it to be movable either. I can't see how a NeverDestroyed object could be ever moved around, but I'd prefer a compile-time prevention than relying on reviews to spot such oddities. The explicit constructor would just ensure there's no way of implicitly constructing NeverDestroyed objects.

So while there's no difference in the generated code, I propose the change for the sake of clarity and for preventive measures. This would require a broader cleanup, from making both NeverDestroyed and LazyNeverDestroyed non-movable to using braced initialization wherever NeverDestroyed is used.