Skip to content

Commit 4bc7ba2

Browse files
committed
Check for PreserveBaseOverridesAttribute
Covariant returns were introduced with .NET 5. For all earlier runtimes, the last commit may have relaxed method signature comparison too much. We can resolve this by checking for a specific custom attribute that .NET compilers are expected to put on override methods using covariant returns. Reference: https://github.com/dotnet/runtime/blob/main/docs/design/features/covariant-return-methods.md
1 parent d27ef43 commit 4bc7ba2

File tree

1 file changed

+9
-4
lines changed

1 file changed

+9
-4
lines changed

src/Castle.Core/DynamicProxy/Generators/MethodSignatureComparer.cs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ internal class MethodSignatureComparer : IEqualityComparer<MethodInfo>
2222
{
2323
public static readonly MethodSignatureComparer Instance = new MethodSignatureComparer();
2424

25+
private static readonly Type preserveBaseOverridesAttribute = Type.GetType("System.Runtime.CompilerServices.PreserveBaseOverridesAttribute", throwOnError: false);
26+
2527
public bool EqualGenericParameters(MethodInfo x, MethodInfo y)
2628
{
2729
if (x.IsGenericMethod != y.IsGenericMethod)
@@ -77,7 +79,7 @@ public bool EqualParameters(MethodInfo x, MethodInfo y)
7779
return true;
7880
}
7981

80-
public bool EqualSignatureTypes(Type x, Type y, bool precise = true)
82+
public bool EqualSignatureTypes(Type x, Type y, MethodInfo xm = null)
8183
{
8284
if (x.IsGenericParameter != y.IsGenericParameter)
8385
{
@@ -122,9 +124,12 @@ public bool EqualSignatureTypes(Type x, Type y, bool precise = true)
122124
{
123125
if (!x.Equals(y))
124126
{
125-
if (!precise && y.IsAssignableFrom(x)) // .NET 5+ covariant returns
127+
// This enables covariant method returns for .NET 5 and newer.
128+
// No need to check for runtime support, since such methods are marked with a custom attribute;
129+
// see https://github.com/dotnet/runtime/blob/main/docs/design/features/covariant-return-methods.md.
130+
if (xm != null && preserveBaseOverridesAttribute != null && xm.IsDefined(preserveBaseOverridesAttribute, inherit: false))
126131
{
127-
return true;
132+
return y.IsAssignableFrom(x);
128133
}
129134

130135
return false;
@@ -147,7 +152,7 @@ public bool Equals(MethodInfo x, MethodInfo y)
147152

148153
return EqualNames(x, y) &&
149154
EqualGenericParameters(x, y) &&
150-
EqualSignatureTypes(x.ReturnType, y.ReturnType, precise: false) &&
155+
EqualSignatureTypes(x.ReturnType, y.ReturnType, x) &&
151156
EqualParameters(x, y);
152157
}
153158

0 commit comments

Comments
 (0)