Skip to content
This repository was archived by the owner on Dec 12, 2024. It is now read-only.
This repository was archived by the owner on Dec 12, 2024. It is now read-only.

[SoM] Functions that return protocol list types that throw will fail #22

@stephen-hawley

Description

@stephen-hawley

Dear Future Steve,

The problem is that in order to marshal something that contains a SwiftExistentialContainer, we need to know the size/stride of it. We can get this, but if SwiftExistentialContainer is embedded in a tuple, for example, we can't get its size using swift. We could hack in code to manually handle tuples (we did before, but it's gone now), but if anyone tries to call Metatypeof on a tuple containing one of these, it will fail. Sorry.

So what do we do?

We do a sleazy hack. We redefine all the SwiftExistentialContainer types to come in pairs:
SwiftExistentialContainerN which will be the existing SwiftExistentialContainerN structs and SwiftExistentialContainer<TIf0, ... TIfN>. Each of the generic versions would delegate to a non generic within it:

public SwiftExistentialContainer<TIf0> : ISwiftExistentialContainer {
public SwiftExistentialContainer1 Container { get; set; }
public Data0 { get { return Container.Data0 } set { Container.Data0 = value; } }
// etc
}

Next step is to change SwiftProtocolTypeAttribute to contain the library that defines the protocol (string) and the symbol for the protocol descriptor for that protocol. These symbols end in Mp in the mangling and do get picked up in the ProtocolContents when demangling a library. Add some helper methods to do the following:

  1. Get the ProtocolDescriptor for a type by getting its SwiftProtocolTypeAttribute and using the library and symbol to get the handle.
  2. Cache the protocol descriptor in the attribute.

Rewrite the various existential container factories to take a type list of the protocols they are binding to. Look at the Tuple code in StructMarshal for how to do this (basically, it's a switch with a bunch of typeof(SwiftExistentialContainer<,,,>).MakeType (types) to get the type object and then use reflection to get the default constructor.

Make all pinvokes take a ref to the non-generic version of any given container and make the local variables used for marshaling the strongly typed version which passes in its inner container.

Yes, this touches a lot of things, but the good news is that it will let us call Metatypeof on a generic existential container and do something useful with it.

Now comes the bad news (ish). For virtual methods that come in with one of these, I don't think we'll have any idea what the types are in any useful way. I mean maybe? They're going to be some interesting pinvoke callbacks, that's for sure.

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions