Skip to content

Commit 15c3c2d

Browse files
Add support for InlineArrayConversion
1 parent 2c925f4 commit 15c3c2d

File tree

5 files changed

+59
-4
lines changed

5 files changed

+59
-4
lines changed

ICSharpCode.Decompiler.Tests/TestCases/Correctness/Conversions.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
// #include "../../../ICSharpCode.Decompiler/Util/CSharpPrimitiveCast.cs"
2020

2121
using System;
22+
using System.Runtime.CompilerServices;
2223

2324
using ICSharpCode.Decompiler.Util;
2425

@@ -111,6 +112,9 @@ static void Main(string[] args)
111112

112113
Console.WriteLine(ReadZeroTerminatedString("Hello World!".Length));
113114
C1.Test();
115+
#if ROSLYN2 && !NET40
116+
C3.Run();
117+
#endif
114118
}
115119

116120
static void RunTest(bool checkForOverflow)
@@ -199,4 +203,32 @@ public static implicit operator C1(C2 c)
199203
return new C1();
200204
}
201205
}
206+
207+
#if ROSLYN2 && !NET40
208+
class C3
209+
{
210+
[InlineArray(4)] struct MyArray { private int elem; }
211+
212+
static void Foo(object o)
213+
{
214+
Console.WriteLine("Foo(object) called");
215+
}
216+
217+
static void Foo(ReadOnlySpan<int> o)
218+
{
219+
Console.WriteLine("Foo(ReadOnlySpan<int>) called");
220+
}
221+
222+
static void Test(MyArray arr)
223+
{
224+
Foo((object)arr);
225+
}
226+
227+
public static void Run()
228+
{
229+
Console.WriteLine("C3.Run() called");
230+
Test(default);
231+
}
232+
}
233+
#endif
202234
}

ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineArrayTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,9 @@ public void OverloadResolution()
9191
Byte16 buffer2 = GetByte16();
9292
Receiver((ReadOnlySpan<byte>)buffer2);
9393
Byte16 buffer3 = GetByte16();
94-
ReceiverSpan((Span<byte>)buffer3);
94+
ReceiverSpan(buffer3);
9595
Byte16 buffer4 = GetByte16();
96-
ReceiverReadOnlySpan((ReadOnlySpan<byte>)buffer4);
96+
ReceiverReadOnlySpan(buffer4);
9797
}
9898

9999
public Byte16 GetByte16()

ICSharpCode.Decompiler/CSharp/Resolver/CSharpConversions.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,12 +230,20 @@ Conversion StandardImplicitConversion(IType fromType, IType toType, bool allowTu
230230
if (c != Conversion.None)
231231
return c;
232232
}
233+
if ((toType.IsKnownType(KnownTypeCode.SpanOfT) || toType.IsKnownType(KnownTypeCode.ReadOnlySpanOfT))
234+
&& fromType.IsInlineArrayType())
235+
{
236+
var @field = fromType.GetFields(f => !f.IsStatic, GetMemberOptions.IgnoreInheritedMembers).FirstOrDefault();
237+
var spanElementType = toType.TypeArguments[0];
238+
if (field != null && IdentityConversion(field.ReturnType, spanElementType))
239+
return Conversion.InlineArrayConversion;
240+
}
233241
return Conversion.None;
234242
}
235243

236244
/// <summary>
237245
/// Gets whether the type 'fromType' is convertible to 'toType'
238-
/// using one of the conversions allowed when satisying constraints (§4.4.4)
246+
/// using one of the conversions allowed when satisfying constraints (§4.4.4)
239247
/// </summary>
240248
public bool IsConstraintConvertible(IType fromType, IType toType)
241249
{

ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,11 +112,14 @@ public enum KnownAttribute
112112

113113
// C# 11 attributes:
114114
RequiredAttribute,
115+
116+
// C# 12 attributes:
117+
InlineArray,
115118
}
116119

117120
public static class KnownAttributes
118121
{
119-
internal const int Count = (int)KnownAttribute.RequiredAttribute + 1;
122+
internal const int Count = (int)KnownAttribute.InlineArray + 1;
120123

121124
static readonly TopLevelTypeName[] typeNames = new TopLevelTypeName[Count]{
122125
default,
@@ -186,6 +189,8 @@ public static class KnownAttributes
186189
new TopLevelTypeName("System.Runtime.CompilerServices", "PreserveBaseOverridesAttribute"),
187190
// C# 11 attributes:
188191
new TopLevelTypeName("System.Runtime.CompilerServices", "RequiredMemberAttribute"),
192+
// C# 12 attributes:
193+
new TopLevelTypeName("System.Runtime.CompilerServices", "InlineArrayAttribute"),
189194
};
190195

191196
public static ref readonly TopLevelTypeName GetTypeName(this KnownAttribute attr)

ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,16 @@ bool IsUnmanagedTypeInternal(IType type)
306306
}
307307
}
308308

309+
public static bool IsInlineArrayType(this IType type)
310+
{
311+
if (type.Kind != TypeKind.Struct)
312+
return false;
313+
var td = type.GetDefinition();
314+
if (td == null)
315+
return false;
316+
return td.HasAttribute(KnownAttribute.InlineArray);
317+
}
318+
309319
/// <summary>
310320
/// Gets whether the type is the specified known type.
311321
/// For generic known types, this returns true for any parameterization of the type (and also for the definition itself).

0 commit comments

Comments
 (0)