I am trying to convert the lua bridge from Swift 2 to Swift 3. I am not the original author, so there are those aspects of the library that I don’t know very well, and the original author seems not interested in continuing to work on the project. I have most of the conversion, but there remains one place that I was stuck and could not understand. I tried searching on SO and the Internet, but could not find anything that could help me solve the problem.
If someone is interested in the full source code, here is my fork of the project on github: https://github.com/weyhan/lua4swift (My changes in the Swift3 branch)
Let me set the context for the error I'm stuck with. There is a Userdata class, especially in the userdataPointer<T>() -> UnsafeMutablePointer<T> lua_touserdata function c lua_touserdata returns the address of the userdata block as the pointer type void * .
Original code written in Swift 2:
public class Userdata: StoredValue { public func userdataPointer<T>() -> UnsafeMutablePointer<T> { push(vm) let ptr = lua_touserdata(vm.vm, -1) vm.pop() return UnsafeMutablePointer<T>(ptr) } public func toCustomType<T: CustomTypeInstance>() -> T { return userdataPointer().memory } public func toAny() -> Any { return userdataPointer().memory } override public func kind() -> Kind { return .Userdata } }
After converting using the Xcode 8 migration tool, Xcode complains about the return line with the Cannot invoke initializer for type 'UnsafeMutablePointer<T>' with an argument list of type '(UnsafeMutableRawPointer?)' :
return UnsafeMutablePointer<T>(ptr)
I fixed it with
return (ptr?.assumingMemoryBound(to: T.self))!
Following the change above, now Xcode 8 now complains about the calling operator in createCustomType :
public func createCustomType<T: CustomTypeInstance>(setup: (CustomType<T>) -> Void) -> CustomType<T> { lua_createtable(vm, 0, 0) let lib = CustomType<T>(self) pop() setup(lib) registry[T.luaTypeName()] = lib lib.becomeMetatableFor(lib) lib["__index"] = lib lib["__name"] = T.luaTypeName() let gc = lib.gc lib["__gc"] = createFunction([CustomType<T>.arg]) { args in let ud = args.userdata // ******* Here the line that is causing problem in Swift 3 (ud.userdataPointer() as UnsafeMutablePointer<Void>).destroy() // ******* let o: T = ud.toCustomType() gc?(o) return .Nothing } if let eq = lib.eq { lib["__eq"] = createFunction([CustomType<T>.arg, CustomType<T>.arg]) { args in let a: T = args.customType() let b: T = args.customType() return .Value(eq(a, b)) } } return lib }
Where I stuck the line:
(ud.userdataPointer() as UnsafeMutablePointer<Void>).destroy()
I believe that the original author is trying to clear the memory block, where the pointer returned by calling userdataPointer() points to.
Using the Xcode 8 automated migration tool, the above string is converted as shown below:
(ud.userdataPointer() as UnsafeMutableRawPointer).deinitialize()
However, now Xcode complains that Cannot convert call result type 'UnsafeMutablePointer<_>' to expected type 'UnsafeMutableRawPointer' .
From my research, changing the return string in userdataPointer seems correct, so I think the problem is with casting to UnsafeMutableRawPointer. I tried to drop the cast in UnsafeMutableRawPointer and call ud.userdataPointer().deinitialize() directly, but I get this error Generic parameter 'T' could not be inferred .
Other things I've tried are converting UnsafeMutablePointer to UnsafeMutableRawPointer, but this always leads to Xcode 8 complaining about something else. Any suggestion on how to make this work?