diff --git a/README.md b/README.md
index 3006828..99e942b 100644
--- a/README.md
+++ b/README.md
@@ -75,6 +75,7 @@ It also includes the following optional runtime-supported polyfills:
- `[SuppressGCTransition]` (see [here](https://devblogs.microsoft.com/dotnet/improvements-in-native-code-interop-in-net-5-0/))
- `[DisableRuntimeMarshalling]` (see [here](https://learn.microsoft.com/dotnet/standard/native-interop/disabled-marshalling))
- `[UnsafeAccessor]` (see [here](https://github.com/dotnet/runtime/issues/81741))
+- `[InlineArray]` (see [here](https://learn.microsoft.com/dotnet/csharp/language-reference/proposals/csharp-12.0/inline-arrays))
# Options ⚙️
diff --git a/src/PolySharp.Package/README.md b/src/PolySharp.Package/README.md
index 3f419dc..3aa6f4c 100644
--- a/src/PolySharp.Package/README.md
+++ b/src/PolySharp.Package/README.md
@@ -73,6 +73,7 @@ It also includes the following optional runtime-supported polyfills:
- `[SuppressGCTransition]` (see [here](https://devblogs.microsoft.com/dotnet/improvements-in-native-code-interop-in-net-5-0/))
- `[DisableRuntimeMarshalling]` (see [here](https://learn.microsoft.com/dotnet/standard/native-interop/disabled-marshalling))
- `[UnsafeAccessor]` (see [here](https://github.com/dotnet/runtime/issues/81741))
+- `[InlineArray]` (see [here](https://learn.microsoft.com/dotnet/csharp/language-reference/proposals/csharp-12.0/inline-arrays))
# Options ⚙️
diff --git a/src/PolySharp.SourceGenerators/EmbeddedResources/RuntimeSupported/System.Runtime.CompilerServices.InlineArrayAttribute.cs b/src/PolySharp.SourceGenerators/EmbeddedResources/RuntimeSupported/System.Runtime.CompilerServices.InlineArrayAttribute.cs
new file mode 100644
index 0000000..6d3ccf0
--- /dev/null
+++ b/src/PolySharp.SourceGenerators/EmbeddedResources/RuntimeSupported/System.Runtime.CompilerServices.InlineArrayAttribute.cs
@@ -0,0 +1,44 @@
+//
+#pragma warning disable
+#nullable enable annotations
+
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace System.Runtime.CompilerServices2
+{
+ ///
+ /// Indicates that the instance's storage is sequentially replicated "length" times.
+ ///
+ ///
+ ///
+ /// This attribute can be used to annotate a type with a single field.
+ /// The runtime will replicate that field in the actual type layout as many times as is specified.
+ ///
+ ///
+ /// Here's an example of how an inline array type with 8 values can be declared:
+ ///
+ /// [InlineArray(8)]
+ /// struct Float8InlineArray
+ /// {
+ /// private float _value;
+ /// }
+ ///
+ ///
+ ///
+ [global::System.AttributeUsage(global::System.AttributeTargets.Struct, AllowMultiple = false)]
+ [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
+ [global::System.Diagnostics.Conditional("MULTI_TARGETING_SUPPORT_ATTRIBUTES")]
+ public sealed class InlineArrayAttribute : global::System.Attribute
+ {
+ /// Creates a new instance with the specified length.
+ /// The number of sequential fields to replicate in the inline array type.
+ public InlineArrayAttribute(int length)
+ {
+ Length = length;
+ }
+
+ /// Gets the number of sequential fields to replicate in the inline array type.
+ public int Length { get; }
+ }
+}
\ No newline at end of file
diff --git a/src/PolySharp.SourceGenerators/Models/SyntaxFixupType.cs b/src/PolySharp.SourceGenerators/Models/SyntaxFixupType.cs
index a89f62d..bc37406 100644
--- a/src/PolySharp.SourceGenerators/Models/SyntaxFixupType.cs
+++ b/src/PolySharp.SourceGenerators/Models/SyntaxFixupType.cs
@@ -27,5 +27,11 @@ internal enum SyntaxFixupType
/// Generates the [UnmanagedCallersOnly] type in the InteropServices2 dummy namespace.
///
/// This is needed when methods annotated with the attribute have to be assigned to delegates, which Roslyn will otherwise block.
- UseInteropServices2ForUnmanagedCallersOnlyAttribute = 1 << 2
+ UseInteropServices2ForUnmanagedCallersOnlyAttribute = 1 << 2,
+
+ ///
+ /// Generates a global using for the [InlineArray] type in the dummy namespace.
+ ///
+ /// This is always needed when the type is used, as the usage is entirely blocked in the normal namespace.
+ EmitGlobalUsingForInlineArrayAttribute = 1 << 3
}
diff --git a/src/PolySharp.SourceGenerators/PolyfillsGenerator.Polyfills.cs b/src/PolySharp.SourceGenerators/PolyfillsGenerator.Polyfills.cs
index 0895ee8..159a6dd 100644
--- a/src/PolySharp.SourceGenerators/PolyfillsGenerator.Polyfills.cs
+++ b/src/PolySharp.SourceGenerators/PolyfillsGenerator.Polyfills.cs
@@ -153,6 +153,13 @@ static SyntaxFixupType GetSyntaxFixupType(Compilation compilation, string name)
fixupType |= SyntaxFixupType.RemoveMethodImplAttributes;
}
+ // Emit the global using for the dummy [InlineArray] type, if allowed
+ if (name is "System.Runtime.CompilerServices.InlineArrayAttribute" &&
+ compilation.HasLanguageVersionAtLeastEqualTo(LanguageVersion.CSharp10))
+ {
+ fixupType |= SyntaxFixupType.EmitGlobalUsingForInlineArrayAttribute;
+ }
+
return fixupType;
}
@@ -287,6 +294,18 @@ private void EmitGeneratedType(SourceProductionContext context, GeneratedType ty
"System.Runtime.InteropServices2");
}
+ if ((type.FixupType & SyntaxFixupType.EmitGlobalUsingForInlineArrayAttribute) != 0)
+ {
+ // Generate a global using for [InlineArray]
+ adjustedSource = adjustedSource.Replace(
+ "namespace System.Runtime.CompilerServices2",
+ """
+ global using InlineArrayAttribute = global::System.Runtime.CompilerServices2.InlineArrayAttribute;
+
+ namespace System.Runtime.CompilerServices2
+ """);
+ }
+
sourceText = SourceText.From(adjustedSource, Encoding.UTF8);
}
else
diff --git a/tests/PolySharp.Tests/RuntimeSupport.cs b/tests/PolySharp.Tests/RuntimeSupport.cs
index 1e34a92..a4593fb 100644
--- a/tests/PolySharp.Tests/RuntimeSupport.cs
+++ b/tests/PolySharp.Tests/RuntimeSupport.cs
@@ -88,9 +88,9 @@ public void ReferenceSomeAssemblyFile()
internal class AccessorApis
{
-#pragma warning disable IDE0044
+#pragma warning disable CS0169, IDE0044
private int field;
-#pragma warning restore IDE0044
+#pragma warning restore CS0169, IDE0044
[StackTraceHidden]
public void HideMe()
@@ -99,4 +99,12 @@ public void HideMe()
[UnsafeAccessor(UnsafeAccessorKind.Field, Name = nameof(field))]
public static extern ref int GetField(RandomApis obj);
+}
+
+[InlineArray(16)]
+internal struct Int8
+{
+#pragma warning disable CS0169, IDE0044, IDE0051
+ private int value0;
+#pragma warning restore CS0169, IDE0044, IDE0051
}
\ No newline at end of file