From c95da67cbecffc02894f15e4896aa10c06a4c4a5 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 13 Feb 2021 18:24:49 +0100 Subject: [PATCH] Fix extension method calls on `this in`. --- ICSharpCode.Decompiler/CSharp/Resolver/CSharpResolver.cs | 7 ++++++- .../CSharp/Resolver/MethodGroupResolveResult.cs | 1 + .../CSharp/Resolver/OverloadResolution.cs | 7 +++++-- .../CSharp/Transforms/IntroduceExtensionMethods.cs | 7 +++++-- 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/ICSharpCode.Decompiler/CSharp/Resolver/CSharpResolver.cs b/ICSharpCode.Decompiler/CSharp/Resolver/CSharpResolver.cs index 4def735e5..27e173e1b 100644 --- a/ICSharpCode.Decompiler/CSharp/Resolver/CSharpResolver.cs +++ b/ICSharpCode.Decompiler/CSharp/Resolver/CSharpResolver.cs @@ -2158,12 +2158,17 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver if (method.Parameters.Count == 0) return false; IType thisParameterType = method.Parameters[0].Type; + if (thisParameterType.Kind == TypeKind.ByReference) + { + // extension method with `this in` or `this ref` + thisParameterType = ((ByReferenceType)thisParameterType).ElementType; + } if (useTypeInference && method.TypeParameters.Count > 0) { // We need to infer type arguments from targetType: TypeInference ti = new TypeInference(compilation, conversions); ResolveResult[] arguments = { new ResolveResult(targetType) }; - IType[] parameterTypes = { method.Parameters[0].Type }; + IType[] parameterTypes = { thisParameterType }; var inferredTypes = ti.InferTypeArguments(method.TypeParameters, arguments, parameterTypes, out _); var substitution = new TypeParameterSubstitution(null, inferredTypes); // Validate that the types that could be inferred (aren't unknown) satisfy the constraints: diff --git a/ICSharpCode.Decompiler/CSharp/Resolver/MethodGroupResolveResult.cs b/ICSharpCode.Decompiler/CSharp/Resolver/MethodGroupResolveResult.cs index 30529bbeb..d08108c22 100644 --- a/ICSharpCode.Decompiler/CSharp/Resolver/MethodGroupResolveResult.cs +++ b/ICSharpCode.Decompiler/CSharp/Resolver/MethodGroupResolveResult.cs @@ -271,6 +271,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver extOr.AllowOptionalParameters = allowOptionalParameters; extOr.IsExtensionMethodInvocation = true; extOr.CheckForOverflow = checkForOverflow; + extOr.AllowImplicitIn = allowImplicitIn; foreach (var g in extensionMethods) { diff --git a/ICSharpCode.Decompiler/CSharp/Resolver/OverloadResolution.cs b/ICSharpCode.Decompiler/CSharp/Resolver/OverloadResolution.cs index e2727948c..09fd186f7 100644 --- a/ICSharpCode.Decompiler/CSharp/Resolver/OverloadResolution.cs +++ b/ICSharpCode.Decompiler/CSharp/Resolver/OverloadResolution.cs @@ -669,8 +669,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } else { - if (paramRefKind == ReferenceKind.In && AllowImplicitIn - && candidate.ParameterTypes[parameterIndex].SkipModifiers() is ByReferenceType brt) + // AllowImplicitIn: `in` parameters can be filled implicitly without `in` DirectionExpression + // IsExtensionMethodInvocation: `this ref` and `this in` parameters can be filled implicitly + if (((paramRefKind == ReferenceKind.In && AllowImplicitIn) + || (IsExtensionMethodInvocation && parameterIndex == 0 && (paramRefKind == ReferenceKind.In || paramRefKind == ReferenceKind.Ref)) + ) && candidate.ParameterTypes[parameterIndex].SkipModifiers() is ByReferenceType brt) { // Treat the parameter as if it was not declared "in" for the following steps // (applicability + better function member) diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceExtensionMethods.cs b/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceExtensionMethods.cs index b1459639f..3a3071512 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceExtensionMethods.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceExtensionMethods.cs @@ -16,7 +16,6 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; @@ -181,6 +180,10 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms { target = new ConversionResolveResult(method.Parameters[0].Type, crr, Conversion.NullLiteralConversion); } + else if (target is ByReferenceResolveResult brrr) + { + target = brrr.ElementResult; + } ResolveResult[] args = new ResolveResult[invocationExpression.Arguments.Count - 1]; string[] argNames = null; int pos = 0; @@ -238,4 +241,4 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms return CanTransformToExtensionMethodCall(resolver, method, typeArgs, targetType, paramTypes, argumentNames: paramNames); } } -} \ No newline at end of file +}