<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><br class=""></div><div class="">Currently, APIs that get imported with COpaquePointer make Swift *less* safe than C. Fixing this seems like a breaking change, since it would change the meaning of existing code that uses COpaquePointer. </div><div class=""><br class=""></div><div class="">As a motivating example consider:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><div class="">import Darwin</div><div class=""><br class=""></div><div class=""><div class="">var state = copyfile_state_alloc()</div><div class="">print("state = \(state.dynamicType) \(state)")</div><div class=""><br class=""></div><div class="">let acl = acl_init(1)</div><div class="">print("acl = \(acl.dynamicType) \(acl)")</div><div class=""><br class=""></div><div class="">state = acl</div><div class="">print("state = \(state.dynamicType) \(state)")</div></div></div><div class=""><br class=""></div></blockquote><div class="">I’m just using these types since they use opaque structs and are easy to create in this sample, but this pattern is fairly common in other C APIs that try to encapsulate their implementation.</div><div class=""><br class=""></div><div class="">This compiles and builds, silently accepting the bogus code:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><div style="margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">DEVELOPER_DIR=/Applications/Xcode-8.0b1.app/Contents/Developer swift c-unsafety.swift</span></div><div style="margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">state = Optional<OpaquePointer> Optional(0x00007f9db481b3d0)</span></div><div style="margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">acl = Optional<OpaquePointer> Optional(0x00007f9db2944c00)</span></div><div style="margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">state = Optional<OpaquePointer> Optional(0x00007f9db2944c00)</span></div></div></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""><br class=""></span></div></blockquote>The equivalent C version:<div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><div class=""><div class="">copyfile_state_t state = state = copyfile_state_alloc();</div><div class="">acl_t acl = acl_init(1);</div><div class="">state = acl;</div></div></div><div class=""><br class=""></div></blockquote><div class=""><div class="">produces a warning:</div><div class=""><br class=""></div></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><div class=""><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures;" class="">c-unsafety.c:10:8: </span><span style="font-variant-ligatures: no-common-ligatures;" class="">warning: </span><span style="font-variant-ligatures: no-common-ligatures;" class="">incompatible pointer types assigning to 'copyfile_state_t' (aka 'struct _copyfile_state *') from 'acl_t' (aka 'struct _acl *')</span></div><div class=""><span style="font-variant-ligatures: no-common-ligatures" class=""><b class=""><br class=""></b></span></div></div></div></div></blockquote><br class=""><div class="">Would it be feasible to import these sorts of pointers in a safe(r) way by making COpaquePointer generic and faking up a struct tag type? So, these might get imported with something equivalent to:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class="">struct <span style="font-family: Menlo; font-size: 11px;" class="">_acl</span> {}</div><div class="">typealias <span style="font-family: Menlo; font-size: 11px;" class="">acl_t</span> = COpaquePointer<<span style="font-family: Menlo; font-size: 11px;" class="">_acl</span>></div><div class=""><br class=""></div></blockquote>A further problem, though, is that other examples of this use `const` to form a very basic `isa` relationship between two types. For example:<div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div style="margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures;" class="">typedef</span><span style="font-variant-ligatures: no-common-ligatures;" class=""> </span><span style="font-variant-ligatures: no-common-ligatures;" class="">const</span><span style="font-variant-ligatures: no-common-ligatures;" class=""> </span><span style="font-variant-ligatures: no-common-ligatures;" class="">struct</span><span style="font-variant-ligatures: no-common-ligatures;" class=""> </span><span style="font-variant-ligatures: no-common-ligatures;" class="">OpaqueJSContext</span><span style="font-variant-ligatures: no-common-ligatures;" class="">* JSContextRef;</span></div><div style="margin: 0px; line-height: normal; min-height: 16px;" class=""><span style="font-variant-ligatures: no-common-ligatures;" class="">typedef</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures;" class="">struct</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures;" class="">OpaqueJSContext</span><span style="font-variant-ligatures: no-common-ligatures" class="">* JSGlobalContextRef;</span></div></blockquote><div class=""> </div><div class="">so this approach wouldn’t solve casting between these two C types, but perhaps the name of tagging struct could indicate the `const` (“Const_ OpaqueJSContext”?) or maybe COpaquePointer could be used for `const` and a MutableCOpaquePointer type could be added for the non-const case?</div><div class=""><br class=""></div><div class="">There would also be issues if one Swift module tried to pass one of these to another; the made-up struct tag would need to be in some global namespace to avoid errors passing A.COpaquePointer<OpaqueFoo> to B.COpaquePointer<OpaqueFoo> (though really I don’t consider this to be a big problem -- the surface level API of a Swift module using C libraries that deal with C API should mostly try to hide that internally).</div><div class=""><br class=""></div><div class="">In my “real” cases, I’ve been trying to *immediately* wrap the COpaquePointer in a struct of my own, but this doesn’t handle the ‘isa-like’ relationship between a const/non-const variant of an opaque struct pointer, is much more verbose, and it is easy to mess it up and accidentally cross the streams. And of course, with all the contortions Swift goes to try to be safe, this regression in safety from C is puzzling.</div><div class=""><br class=""></div><div class="">Thanks!</div><div class=""><br class=""></div><div class="">-tim</div><div class=""><font face="Menlo" class=""><span style="font-size: 11px;" class=""><b class=""><br class=""></b></span></font></div></body></html>