Bug 60298 - LayoutKind.Explicit, Size = 12 ignored with 64bit alignment
Summary: LayoutKind.Explicit, Size = 12 ignored with 64bit alignment
Alias: None
Product: Runtime
Classification: Mono
Component: Interop ()
Version: master
Hardware: PC Mac OS
: --- normal
Target Milestone: Future Cycle (TBD)
Assignee: Bugzilla
Depends on:
Reported: 2017-10-20 19:55 UTC by David Karlaš
Modified: 2018-01-24 18:26 UTC (History)
5 users (show)

Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.

Please create a new report on GitHub or Developer Community with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:

Description David Karlaš 2017-10-20 19:55:23 UTC
Example below outputs on .NET 64bit:
but on Mono 64bit(32bit works fine) it outputs:


using System;
using System.Runtime.InteropServices;

class MainClass
    [StructLayout(LayoutKind.Explicit, Size = 12)]
    private struct Sha1Hash
        private long Data1;

        private int Data3;

    public static void Main(string[] args)
            var size = sizeof(Sha1Hash);

This was uncovered by https://github.com/dotnet/roslyn/blob/f629039/src/Workspaces/Core/Portable/Workspace/Solution/Checksum.cs#L28
Comment 1 Ludovic Henry 2017-10-20 19:57:21 UTC
I can reproduce with Mono (2017-10/a3943e28cf8)
Comment 2 Zoltan Varga 2017-10-22 21:02:05 UTC
This is caused by:
Comment 3 Zoltan Varga 2017-10-23 18:56:45 UTC
The explicit layout directive is supposed to only affect unmanaged layout, so the sizeof (T) should still return the managed size imho.
Comment 4 Zoltan Varga 2017-10-23 19:03:21 UTC
According to the ecma spec:

[Rationale: The definition of a value type can change between the time the CIL is generated and the time that it is loaded for execution. Thus, the size of the type is not always known when the CIL is generated. The sizeof instruction allows CIL code to determine the size at runtime without the need to call into the Framework class library. The computation can occur entirely at runtime or at CIL-to-native-code compilation time. sizeof returns the total size that would be occupied by each element in an array of this type – including any padding the implementation chooses to add. Specifically, array elements lie sizeof bytes apart. end rationale]

So the implementation is free to add padding, like mono does. I don't think it is a bug, more like roslyn is depending on an implementation detail.
Comment 5 Zoltan Varga 2017-12-11 22:43:05 UTC
Comment 6 Dustin Campbell 2017-12-12 17:11:10 UTC
Adding some details from a mail thread with Sam Harwell to ensure they're documented:

> The explicit layout directive is supposed to only affect unmanaged layout …

This is an incorrect statement. In ECMA-335 §II.10.7 there are two statements which make this clear:

* Fields can be accessed using pointer arithmetic and ldind to load the field indirectly or stind to store the field indirectly …
* Note: Metadata that controls instance layout is not a “hint,” it is an integral part of the VES that shall be supported by all conforming implementations of the CLI.

> So the implementation is free to add padding, like mono does.

I’m finding it hard to believe this. The most direct evidence that padding was not intended here comes from the following statement in the informative text of §II.22.8:

* If Parent indexes an ExplicitLayout type, then … PackingSize shall be 0. (It makes no sense to provide explicit offsets for each field, as well as a packing size.) [ERROR]

This interpretation is further supported by §I.9.5 (Class layout). This section explicitly provides for the CLI to modify the layout according to limitations defined in source code. The definitions of autolayout and sequentiallayout provide for the runtime to modify alignments, but no such provision is provided for explicitlayout. Rather, explicitlayout provides only for the alignment of instances of the type itself (using .size), an interpretation of the wording which is confirmed by the informative text of §II.22.8.
Comment 7 Ludovic Henry 2018-01-24 18:26:00 UTC
This landed in master with https://github.com/mono/mono/commit/6b58f1317732b9cbf6ec61921e76d7d48e362104.

It is being backported to mono:2017-12 with https://github.com/mono/mono/pull/6653