From 7f024de78676c878b67949887c14005f794da2f2 Mon Sep 17 00:00:00 2001
From: ds5678 <49847914+ds5678@users.noreply.github.com>
Date: Sun, 30 Mar 2025 14:16:43 -0700
Subject: [PATCH] Don't include generic constraints in generated explicit
overrides
---
.../ICSharpCode.Decompiler.Tests.csproj | 3 +
.../ILPrettyTestRunner.cs | 6 ++
.../PrettyTestRunner.cs | 6 ++
.../TestCases/ILPretty/Issue3442.cs | 19 +++++
.../TestCases/ILPretty/Issue3442.il | 78 +++++++++++++++++++
.../TestCases/Pretty/Issue3442.cs | 13 ++++
.../CSharp/CSharpDecompiler.cs | 3 +-
7 files changed, 126 insertions(+), 2 deletions(-)
create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue3442.cs
create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue3442.il
create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3442.cs
diff --git a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
index fbec1c348..60823cac8 100644
--- a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
+++ b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
@@ -93,6 +93,7 @@
+
@@ -131,9 +132,11 @@
+
+
diff --git a/ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs b/ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs
index 5a86d4e81..aebbf8c09 100644
--- a/ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs
+++ b/ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs
@@ -213,6 +213,12 @@ namespace ICSharpCode.Decompiler.Tests
await Run();
}
+ [Test]
+ public async Task Issue3442()
+ {
+ await Run();
+ }
+
[Test]
public async Task Issue2260SwitchString()
{
diff --git a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs
index ac457d450..178e15a9d 100644
--- a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs
+++ b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs
@@ -610,6 +610,12 @@ namespace ICSharpCode.Decompiler.Tests
await RunForLibrary(cscOptions: cscOptions);
}
+ [Test]
+ public async Task Issue3442([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
+ {
+ await RunForLibrary(cscOptions: cscOptions);
+ }
+
[Test]
public async Task AssemblyCustomAttributes([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
diff --git a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue3442.cs b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue3442.cs
new file mode 100644
index 000000000..6f1c35f7a
--- /dev/null
+++ b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue3442.cs
@@ -0,0 +1,19 @@
+namespace ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3442
+{
+ public class Class : Interface
+ {
+ private void M() where T : Interface
+ {
+ }
+
+ void Interface.M()
+ {
+ //ILSpy generated this explicit interface implementation from .override directive in M
+ this.M();
+ }
+ }
+ public interface Interface
+ {
+ void M() where T : Interface;
+ }
+}
diff --git a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue3442.il b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue3442.il
new file mode 100644
index 000000000..eb06e4072
--- /dev/null
+++ b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue3442.il
@@ -0,0 +1,78 @@
+.assembly extern System.Runtime
+{
+ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
+ .ver 4:0:0:0
+}
+
+.assembly Issue3442
+{
+ .custom instance void [System.Runtime]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = (
+ 01 00 08 00 00 00 00 00
+ )
+ .custom instance void [System.Runtime]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = (
+ 01 00 01 00 54 02 16 57 72 61 70 4e 6f 6e 45 78
+ 63 65 70 74 69 6f 6e 54 68 72 6f 77 73 01
+ )
+ .custom instance void [System.Runtime]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [System.Runtime]System.Diagnostics.DebuggableAttribute/DebuggingModes) = (
+ 01 00 02 00 00 00 00 00
+ )
+ .permissionset reqmin = (
+ 2e 01 80 8a 53 79 73 74 65 6d 2e 53 65 63 75 72
+ 69 74 79 2e 50 65 72 6d 69 73 73 69 6f 6e 73 2e
+ 53 65 63 75 72 69 74 79 50 65 72 6d 69 73 73 69
+ 6f 6e 41 74 74 72 69 62 75 74 65 2c 20 53 79 73
+ 74 65 6d 2e 52 75 6e 74 69 6d 65 2c 20 56 65 72
+ 73 69 6f 6e 3d 39 2e 30 2e 30 2e 30 2c 20 43 75
+ 6c 74 75 72 65 3d 6e 65 75 74 72 61 6c 2c 20 50
+ 75 62 6c 69 63 4b 65 79 54 6f 6b 65 6e 3d 62 30
+ 33 66 35 66 37 66 31 31 64 35 30 61 33 61 15 01
+ 54 02 10 53 6b 69 70 56 65 72 69 66 69 63 61 74
+ 69 6f 6e 01
+ )
+ .hash algorithm 0x00008004 // SHA1
+ .ver 0:0:0:0
+}
+
+.class private auto ansi ''
+{
+} // end of class
+
+.class interface public auto ansi abstract beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3442.Interface
+{
+ // Methods
+ .method public hidebysig newslot abstract virtual
+ instance void M<(ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3442.Interface) T> () cil managed
+ {
+ } // end of method Interface::M
+
+} // end of class ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3442.Interface
+
+.class public auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3442.Class
+ extends [System.Runtime]System.Object
+ implements ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3442.Interface
+{
+ // Methods
+ .method private final hidebysig newslot virtual
+ instance void M<(ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3442.Interface) T> () cil managed
+ {
+ .override method instance void ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3442.Interface::M()
+ // Method begins at RVA 0x2050
+ // Code size 1 (0x1)
+ .maxstack 8
+
+ IL_0000: ret
+ } // end of method Class::M
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor () cil managed
+ {
+ // Method begins at RVA 0x2052
+ // Code size 7 (0x7)
+ .maxstack 8
+
+ IL_0000: ldarg.0
+ IL_0001: call instance void [System.Runtime]System.Object::.ctor()
+ IL_0006: ret
+ } // end of method Class::.ctor
+
+} // end of class ICSharpCode.Decompiler.Tests.TestCases.ILPretty.Issue3442.Class
\ No newline at end of file
diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3442.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3442.cs
new file mode 100644
index 000000000..1c2b02dc4
--- /dev/null
+++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3442.cs
@@ -0,0 +1,13 @@
+namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.Issue3442
+{
+ public class Class : Interface
+ {
+ void Interface.M()
+ {
+ }
+ }
+ public interface Interface
+ {
+ void M() where T : Interface;
+ }
+}
\ No newline at end of file
diff --git a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
index 6c881715f..b239da3a2 100644
--- a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
+++ b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
@@ -1167,8 +1167,7 @@ namespace ICSharpCode.Decompiler.CSharp
methodDecl.TypeParameters.AddRange(memberDecl.GetChildrenByRole(Roles.TypeParameter)
.Select(n => (TypeParameterDeclaration)n.Clone()));
methodDecl.Parameters.AddRange(memberDecl.GetChildrenByRole(Roles.Parameter).Select(n => n.Clone()));
- methodDecl.Constraints.AddRange(memberDecl.GetChildrenByRole(Roles.Constraint)
- .Select(n => (Constraint)n.Clone()));
+ // Constraints are not copied because explicit interface implementations cannot have constraints. CS0460
methodDecl.Body = new BlockStatement();
methodDecl.Body.AddChild(new Comment(