-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make explicit struct layout compatible with generics. #43486
Comments
I believe that the restriction stems from the fact that the CLR does not permit overlap of struct and reference type fields, regardless of generics. In your example, this would be admissible if, for example, |
I may have misunderstood what you're saying here, but the size of a generic struct is unbounded at runtime. |
I can imagine that this reason might caused by difficulties from GC perspective (which at least in theory could be solved by conservative GC approach), but it would be great to hear about other challenges, if there are any.
I think you've meant at compile time. Unless I misunderstood something, at some point it must be known to the runtime (since we need to allocate a frame on stack of certain size for any struct). |
Would it be possible to lift this restriction when all types involved are blittable at least? |
This might be similar to the change I made to support marshalling blittable generics: #103 The runtime side changes ended up being small (~75 lines, which includes comments and newlines), while I added some significant test coverage (~10k lines). |
I have got this working locally with a ~4 line change and it so far seems to be working with everything (throws when the reified layout is invalid). The check was in |
Any update on that? |
struct PromiseMethodBuilder<T>
{
[StructLayout(LayoutKind.Explicit)]
private struct RefWrapper
{
// Both types are reference types, so it should be fine.
// But the runtime complains because it's using generics.
[FieldOffset(0)]
internal AsyncPromiseRef<T> _async;
[FieldOffset(0)]
internal PromiseRef<T> _task;
}
private RefWrapper _ref;
private T _result;
} |
Both cases should be allowed [StructLayout(LayoutKind.Explicit)]
public struct Foo<T> where T : unmanaged
{
[FieldOffset(0)]
public T Value;
}
[StructLayout(LayoutKind.Explicit)]
public struct Bar<T> where T : class
{
[FieldOffset(0)]
public T Value;
} |
I wonder if it would be possible to give some traction to this? It would really help for some native interop scenarios, and it could be constrained to |
Really need this feature as well. |
Perhaps it can also be extended to any generic type [StructLayout(LayoutKind.Explicit)]
struct Custom<T> {
static readonly T DefaultT = default(T);
[FieldOffset(0)]
int A;
[FieldOffset(4)]
int B;
} |
Right now .NET doesn't allow to combine generics with structures and explicit layout, eg.:
However pattern like this - a.k.a tagged union - is quite popular and often used in other languages, including Rust, OCaml, Haskell or even C.
While this can be done in other ways, but each of them fails in its unique ways:
Anticipating the question how is runtime supposed to determine size of such generic struct, it's the same way as in the languages mentioned above: a dynamically sized, but the size is known to be a maximum possible size required to store the data.
The text was updated successfully, but these errors were encountered: