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.