Browse Source

Merge pull request #3527 from jjonescz/allows-ref-struct

Support `allows ref struct` constraint
pull/3529/head
Daniel Grunwald 5 months ago committed by GitHub
parent
commit
2ca6e22384
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 6
      ICSharpCode.Decompiler.Tests/DisassemblerPrettyTestRunner.cs
  2. 1
      ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
  3. 2
      ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs
  4. 45
      ICSharpCode.Decompiler.Tests/TestCases/Disassembler/Pretty/GenericConstraints.il
  5. 6
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Generics.cs
  6. 6
      ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs
  7. 5
      ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
  8. 5
      ICSharpCode.Decompiler/TypeSystem/ITypeParameter.cs
  9. 1
      ICSharpCode.Decompiler/TypeSystem/Implementation/AbstractTypeParameter.cs
  10. 1
      ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultTypeParameter.cs
  11. 1
      ICSharpCode.Decompiler/TypeSystem/Implementation/DummyTypeParameter.cs
  12. 1
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeParameter.cs
  13. 1
      ICSharpCode.Decompiler/TypeSystem/Implementation/NullabilityAnnotatedType.cs
  14. 1
      ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedMethod.cs
  15. 4
      ICSharpCode.Decompiler/TypeSystem/TypeUtils.cs

6
ICSharpCode.Decompiler.Tests/DisassemblerPrettyTestRunner.cs

@ -52,6 +52,12 @@ namespace ICSharpCode.Decompiler.Tests
} }
} }
[Test]
public async Task GenericConstraints()
{
await Run();
}
[Test] [Test]
public async Task SecurityDeclarations() public async Task SecurityDeclarations()
{ {

1
ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj

@ -91,6 +91,7 @@
<None Include="TestCases\Correctness\StackTests.il" /> <None Include="TestCases\Correctness\StackTests.il" />
<None Include="TestCases\Correctness\StackTypes.il" /> <None Include="TestCases\Correctness\StackTypes.il" />
<None Include="TestCases\Correctness\Uninit.vb" /> <None Include="TestCases\Correctness\Uninit.vb" />
<None Include="TestCases\Disassembler\Pretty\GenericConstraints.il" />
<None Include="TestCases\Disassembler\Pretty\InterfaceImplAttributes.il" /> <None Include="TestCases\Disassembler\Pretty\InterfaceImplAttributes.il" />
<None Include="TestCases\Disassembler\Pretty\SortMembers.expected.il" /> <None Include="TestCases\Disassembler\Pretty\SortMembers.expected.il" />
<None Include="TestCases\Disassembler\Pretty\SortMembers.il" /> <None Include="TestCases\Disassembler\Pretty\SortMembers.il" />

2
ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs

@ -792,7 +792,7 @@ namespace ICSharpCode.Decompiler.Tests
configureDecompiler?.Invoke(settings); configureDecompiler?.Invoke(settings);
var decompiled = await Tester.DecompileCSharp(exeFile, settings).ConfigureAwait(false); var decompiled = await Tester.DecompileCSharp(exeFile, settings).ConfigureAwait(false);
// 3. Compile // 3. Compare
CodeAssert.FilesAreEqual(csFile, decompiled, Tester.GetPreprocessorSymbols(cscOptions).Append("EXPECTED_OUTPUT").ToArray()); CodeAssert.FilesAreEqual(csFile, decompiled, Tester.GetPreprocessorSymbols(cscOptions).Append("EXPECTED_OUTPUT").ToArray());
Tester.RepeatOnIOError(() => File.Delete(decompiled)); Tester.RepeatOnIOError(() => File.Delete(decompiled));
} }

45
ICSharpCode.Decompiler.Tests/TestCases/Disassembler/Pretty/GenericConstraints.il

@ -0,0 +1,45 @@
.assembly extern mscorlib
{
.publickeytoken = (
b7 7a 5c 56 19 34 e0 89
)
.ver 4:0:0:0
}
.assembly GenericConstraints
{
.custom instance void [mscorlib]System.Reflection.AssemblyFileVersionAttribute::.ctor(string) = (
01 00 07 31 2e 30 2e 30 2e 30 00 00
)
.hash algorithm 0x00008004 // SHA1
.ver 1:0:0:0
}
.module GenericConstraints.dll
.imagebase 0x10000000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WindowsCui
.corflags 0x00000001 // ILOnly
.class private auto ansi '<Module>'
{
} // end of class <Module>
.class public auto ansi beforefieldinit TestType`1<byreflike T>
extends [mscorlib]System.Object
{
// Methods
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x2050
// Header size: 1
// Code size: 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method TestType::.ctor
} // end of class TestType

6
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Generics.cs

@ -293,6 +293,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
} }
#endif #endif
#if NET90
public static void AllowsRefStruct<T>() where T : allows ref struct
{
}
#endif
public static void Issue1959(int a, int b, int? c) public static void Issue1959(int a, int b, int? c)
{ {
// This line requires parentheses around `a < b` to avoid a grammar ambiguity. // This line requires parentheses around `a < b` to avoid a grammar ambiguity.

6
ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs

@ -2465,7 +2465,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
internal Constraint ConvertTypeParameterConstraint(ITypeParameter tp) internal Constraint ConvertTypeParameterConstraint(ITypeParameter tp)
{ {
if (!tp.HasDefaultConstructorConstraint && !tp.HasReferenceTypeConstraint && !tp.HasValueTypeConstraint && tp.NullabilityConstraint != Nullability.NotNullable && tp.DirectBaseTypes.All(IsObjectOrValueType)) if (!tp.HasDefaultConstructorConstraint && !tp.HasReferenceTypeConstraint && !tp.HasValueTypeConstraint && !tp.AllowsRefLikeType && tp.NullabilityConstraint != Nullability.NotNullable && tp.DirectBaseTypes.All(IsObjectOrValueType))
{ {
return null; return null;
} }
@ -2518,6 +2518,10 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
{ {
c.BaseTypes.Add(new PrimitiveType("new")); c.BaseTypes.Add(new PrimitiveType("new"));
} }
if (tp.AllowsRefLikeType)
{
c.BaseTypes.Add(new PrimitiveType("allows ref struct"));
}
return c; return c;
} }

5
ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs

@ -28,6 +28,7 @@ using System.Threading;
using ICSharpCode.Decompiler.DebugInfo; using ICSharpCode.Decompiler.DebugInfo;
using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.Decompiler.Disassembler namespace ICSharpCode.Decompiler.Disassembler
{ {
@ -1733,6 +1734,10 @@ namespace ICSharpCode.Decompiler.Disassembler
{ {
output.Write("valuetype "); output.Write("valuetype ");
} }
if ((gp.Attributes & TypeUtils.AllowByRefLike) == TypeUtils.AllowByRefLike)
{
output.Write("byreflike ");
}
if ((gp.Attributes & GenericParameterAttributes.DefaultConstructorConstraint) == GenericParameterAttributes.DefaultConstructorConstraint) if ((gp.Attributes & GenericParameterAttributes.DefaultConstructorConstraint) == GenericParameterAttributes.DefaultConstructorConstraint)
{ {
output.Write(".ctor "); output.Write(".ctor ");

5
ICSharpCode.Decompiler/TypeSystem/ITypeParameter.cs

@ -97,6 +97,11 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// </summary> /// </summary>
bool HasUnmanagedConstraint { get; } bool HasUnmanagedConstraint { get; }
/// <summary>
/// <see langword="true"/> if the <c>allows ref struct</c> constraint is specified for the type parameter.
/// </summary>
bool AllowsRefLikeType { get; }
/// <summary> /// <summary>
/// Nullability of the reference type constraint. (e.g. "where T : class?"). /// Nullability of the reference type constraint. (e.g. "where T : class?").
/// ///

1
ICSharpCode.Decompiler/TypeSystem/Implementation/AbstractTypeParameter.cs

@ -175,6 +175,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public abstract bool HasReferenceTypeConstraint { get; } public abstract bool HasReferenceTypeConstraint { get; }
public abstract bool HasValueTypeConstraint { get; } public abstract bool HasValueTypeConstraint { get; }
public abstract bool HasUnmanagedConstraint { get; } public abstract bool HasUnmanagedConstraint { get; }
public abstract bool AllowsRefLikeType { get; }
public abstract Nullability NullabilityConstraint { get; } public abstract Nullability NullabilityConstraint { get; }
public TypeKind Kind { public TypeKind Kind {

1
ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultTypeParameter.cs

@ -71,6 +71,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public override bool HasReferenceTypeConstraint => hasReferenceTypeConstraint; public override bool HasReferenceTypeConstraint => hasReferenceTypeConstraint;
public override bool HasDefaultConstructorConstraint => hasDefaultConstructorConstraint; public override bool HasDefaultConstructorConstraint => hasDefaultConstructorConstraint;
public override bool HasUnmanagedConstraint => false; public override bool HasUnmanagedConstraint => false;
public override bool AllowsRefLikeType => false;
public override Nullability NullabilityConstraint => nullabilityConstraint; public override Nullability NullabilityConstraint => nullabilityConstraint;
public override IReadOnlyList<TypeConstraint> TypeConstraints { get; } public override IReadOnlyList<TypeConstraint> TypeConstraints { get; }

1
ICSharpCode.Decompiler/TypeSystem/Implementation/DummyTypeParameter.cs

@ -179,6 +179,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
bool ITypeParameter.HasReferenceTypeConstraint => false; bool ITypeParameter.HasReferenceTypeConstraint => false;
bool ITypeParameter.HasValueTypeConstraint => false; bool ITypeParameter.HasValueTypeConstraint => false;
bool ITypeParameter.HasUnmanagedConstraint => false; bool ITypeParameter.HasUnmanagedConstraint => false;
bool ITypeParameter.AllowsRefLikeType => false;
Nullability ITypeParameter.NullabilityConstraint => Nullability.Oblivious; Nullability ITypeParameter.NullabilityConstraint => Nullability.Oblivious;
IReadOnlyList<TypeConstraint> ITypeParameter.TypeConstraints => EmptyList<TypeConstraint>.Instance; IReadOnlyList<TypeConstraint> ITypeParameter.TypeConstraints => EmptyList<TypeConstraint>.Instance;

1
ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeParameter.cs

@ -119,6 +119,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public override bool HasDefaultConstructorConstraint => (attr & GenericParameterAttributes.DefaultConstructorConstraint) != 0; public override bool HasDefaultConstructorConstraint => (attr & GenericParameterAttributes.DefaultConstructorConstraint) != 0;
public override bool HasReferenceTypeConstraint => (attr & GenericParameterAttributes.ReferenceTypeConstraint) != 0; public override bool HasReferenceTypeConstraint => (attr & GenericParameterAttributes.ReferenceTypeConstraint) != 0;
public override bool HasValueTypeConstraint => (attr & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0; public override bool HasValueTypeConstraint => (attr & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0;
public override bool AllowsRefLikeType => (attr & TypeUtils.AllowByRefLike) != 0;
public override bool HasUnmanagedConstraint { public override bool HasUnmanagedConstraint {
get { get {

1
ICSharpCode.Decompiler/TypeSystem/Implementation/NullabilityAnnotatedType.cs

@ -115,6 +115,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
bool ITypeParameter.HasReferenceTypeConstraint => baseType.HasReferenceTypeConstraint; bool ITypeParameter.HasReferenceTypeConstraint => baseType.HasReferenceTypeConstraint;
bool ITypeParameter.HasValueTypeConstraint => baseType.HasValueTypeConstraint; bool ITypeParameter.HasValueTypeConstraint => baseType.HasValueTypeConstraint;
bool ITypeParameter.HasUnmanagedConstraint => baseType.HasUnmanagedConstraint; bool ITypeParameter.HasUnmanagedConstraint => baseType.HasUnmanagedConstraint;
bool ITypeParameter.AllowsRefLikeType => baseType.AllowsRefLikeType;
Nullability ITypeParameter.NullabilityConstraint => baseType.NullabilityConstraint; Nullability ITypeParameter.NullabilityConstraint => baseType.NullabilityConstraint;
IReadOnlyList<TypeConstraint> ITypeParameter.TypeConstraints => baseType.TypeConstraints; IReadOnlyList<TypeConstraint> ITypeParameter.TypeConstraints => baseType.TypeConstraints;
SymbolKind ISymbol.SymbolKind => SymbolKind.TypeParameter; SymbolKind ISymbol.SymbolKind => SymbolKind.TypeParameter;

1
ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedMethod.cs

@ -278,6 +278,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public override bool HasReferenceTypeConstraint => baseTp.HasReferenceTypeConstraint; public override bool HasReferenceTypeConstraint => baseTp.HasReferenceTypeConstraint;
public override bool HasDefaultConstructorConstraint => baseTp.HasDefaultConstructorConstraint; public override bool HasDefaultConstructorConstraint => baseTp.HasDefaultConstructorConstraint;
public override bool HasUnmanagedConstraint => baseTp.HasUnmanagedConstraint; public override bool HasUnmanagedConstraint => baseTp.HasUnmanagedConstraint;
public override bool AllowsRefLikeType => baseTp.AllowsRefLikeType;
public override Nullability NullabilityConstraint => baseTp.NullabilityConstraint; public override Nullability NullabilityConstraint => baseTp.NullabilityConstraint;

4
ICSharpCode.Decompiler/TypeSystem/TypeUtils.cs

@ -16,6 +16,8 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System.Reflection;
using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.TypeSystem.Implementation; using ICSharpCode.Decompiler.TypeSystem.Implementation;
@ -25,6 +27,8 @@ namespace ICSharpCode.Decompiler.TypeSystem
{ {
public const int NativeIntSize = 6; // between 4 (Int32) and 8 (Int64) public const int NativeIntSize = 6; // between 4 (Int32) and 8 (Int64)
public const GenericParameterAttributes AllowByRefLike = (GenericParameterAttributes)0x0020;
/// <summary> /// <summary>
/// Gets the size (in bytes) of the input type. /// Gets the size (in bytes) of the input type.
/// Returns <c>NativeIntSize</c> for pointer-sized types. /// Returns <c>NativeIntSize</c> for pointer-sized types.

Loading…
Cancel
Save