Swap an instance of a type to another type

Is it possible to swap an instance of type A to type B if both types are of the same memory structure or layout

struct A { 
     var a: UInt 
     var b: Int 
     var c: Any?
}  
Struct B { 
     var a: UInt 
     var b: Int 
     var c: Any? 
}  
var instanceofA: A = A() 
// Then convert instanceofA into type B using reflection 
// Or something of that kind 

Not an expert, but UnsafeRawPointer.load(fromByteOffset:as:) is one thing that comes to mind.

unsafeBitCast(instanceOfA, to: B.self).

The unsafe is in the name for a reason, so you’d generally be better off writing an initialiser for each type that takes the other type, but if you know the types have identical layout/contents it should be okay. The Any in your example gives me pause, though; I’m not entirely certain that reference counting will do the right thing in this case.

Unsure of the intent here, but if both structures conformed to a protocol with those fields in it, you wouldn’t need to do anything dangerous.

Even if type A methods' list and type B methods' list are different?

Can you explain more about the background here? Any time anyone mentions “same memory structure or layout” I start to get nervous because the compiler makes very few guarantees about type layout, meaning that you often end up relying on things that work today but could potentially fail in the future.

Share and Enjoy

Quinn “The Eskimo!” @ DTS @ Apple

7 Likes

I agree with @eskimo: whatever you're asking for seems like it's not something you really want. unsafeBitCast and friends rely deeply on compiler behaviour, and in general you don't want to get too far into making assumptions about the structure layout algorithm.

In this case you doubly don't want to do this because Any? may hold a reference type, which means it is itself a potentially reference counted object. That means that running a bit cast or similar approach is likely to go badly. In principle it's ok to do if you never use the A any longer, but it'd be better to just ask for it to be turned into a B, which you can do by writing the appropriate initializer.

The better thing to do is to write an initializer:

2 Likes