From 3e57c7563432a276da955fa9689ace48a6c59523 Mon Sep 17 00:00:00 2001 From: Manuel Carrasco Date: Sun, 1 Dec 2019 16:33:21 -0300 Subject: [PATCH] Fix type inference issues with generic method calls. --- Backend/Analyses/TypeInferenceAnalysis.cs | 27 ++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/Backend/Analyses/TypeInferenceAnalysis.cs b/Backend/Analyses/TypeInferenceAnalysis.cs index b25cde66..ecf76e33 100644 --- a/Backend/Analyses/TypeInferenceAnalysis.cs +++ b/Backend/Analyses/TypeInferenceAnalysis.cs @@ -53,9 +53,30 @@ public override void Visit(CreateObjectInstruction instruction) public override void Visit(MethodCallInstruction instruction) { - if (instruction.HasResult) - { - instruction.Result.Type = instruction.Method.ReturnType; + if (instruction.HasResult) + { + /* + You have class A with method T Get(). + In IL a method call to A::Get() looks like: callvirt instance !0 class A`1::Get() + We want the int32 (generic argument) not the generic reference as the return type . + The returned value can also be used as the return value of the current method. + If the current method's return type is int32, then !0 is not compatible. + + int Foo(){ + A a = new A(); + int b = a.Get(); + return b; + } + */ + + if (instruction.Method.ReturnType is IGenericParameterReference genericParamRef) + { + if (genericParamRef.Kind == GenericParameterKind.Type) + instruction.Result.Type = instruction.Method.ContainingType.GenericArguments.ElementAt(genericParamRef.Index); + else + instruction.Result.Type = instruction.Method.GenericArguments.ElementAt(genericParamRef.Index); + } else + instruction.Result.Type = instruction.Method.ReturnType; } // Skip implicit "this" parameter.