Skip to content

Commit

Permalink
removes unclear TODO + adds a couple of tests to improve coverage (#303)
Browse files Browse the repository at this point in the history
  • Loading branch information
adrianoc committed Oct 13, 2024
1 parent c3d1d8c commit 21790e9
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 11 deletions.
52 changes: 43 additions & 9 deletions Cecilifier.Core.Tests/Tests/Unit/StructSpecificTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -434,23 +434,57 @@ public void TestRefTarget_Struct(string target)
@"\k<il>Stfld, fld_value_1\);"));
}

[Test]
public void CallOnValueType_ThroughInterface_IsConstrained()
[TestCase(
"""
int Call<T>() where T : struct, Itf => Get<T>().M(42);
static T Get<T>() where T : struct, Itf => default(T);
""",
"""
(\s+il_call_\d+\.Emit\(OpCodes\.)Call, gi_get_\d+\);
\s+var l_tmp_\d+ = new VariableDefinition\(gp_T_\d+\);
\s+m_call_\d+\.Body\.Variables.Add\(l_tmp_\d+\);
\1Stloc, l_tmp_\d+\);
\1Ldloca_S, l_tmp_\d+\);
""",
TestName = "On Return")]
[TestCase(
"int Call<T>(T t) where T : struct, Itf => t.M(42);",
@"\s+il_call_15.Emit\(OpCodes\.Ldarga, p_t_\d+\);",
TestName = "On Parameter")]
[TestCase(
"int Call<T>(T t) where T : struct, Itf { T local = t; return local.M(42); }",
@"\s+il_call_15.Emit\(OpCodes\.Ldloca, l_local_\d+\);",
TestName = "On Local")]
[TestCase(
"""
class Field<T> where T : struct, Itf
{
public T field;
public int Call() => field.M(42);
}
""",
"""
//field.M\(42\)
\s+il_call_\d+.Emit\(OpCodes\.Ldarg_0\);
\s+il_call_\d+.Emit\(OpCodes\.Ldflda, fld_field_\d+\);
""",
TestName = "On Field")]
public void CallOnValueType_ThroughInterface_IsConstrained(string t, string loadTargetOfCallIlRegex)
{
var result = RunCecilifier("""
int Call<T>(T t) where T : struct, Itf => t.M(42);
var result = RunCecilifier($$"""
{{t}}
interface Itf { int M(int i); } // The important part here is that M() has at least one parameter.
struct Foo : Itf { public int M(int i) => i; }
""");

Assert.That(
result.GeneratedCode.ReadToEnd(),
Does.Match("""
(\s+il_call_15.Emit\(OpCodes\.)Ldarga, p_t_\d+\);
\1Ldc_I4, 42\);
\1Constrained, gp_T_\d+\);
\1Callvirt, m_M_\d+\);
Does.Match($"""
{loadTargetOfCallIlRegex}
(?<prefix>\s+il_call_\d+\.Emit\(OpCodes\.)Ldc_I4, 42\);
\k<prefix>Constrained, gp_T_\d+\);
\k<prefix>Callvirt, m_M_\d+\);
"""));
}

Expand Down
2 changes: 0 additions & 2 deletions Cecilifier.Core/AST/SyntaxWalkerBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -713,8 +713,6 @@ private void HandlePotentialDelegateInvocationOn(SimpleNameSyntax node, ITypeSym
? $"{localDelegateDeclaration}.Methods.Single(m => m.Name == \"Invoke\")"
: ((IMethodSymbol) typeSymbol.GetMembers("Invoke").SingleOrDefault()).MethodResolverExpression(Context);

//TODO: Find all call sites that adds a Call/Callvirt instruction and make sure
// they call X().
OnLastInstructionLoadingTargetOfInvocation();
Context.EmitCilInstruction(ilVar, OpCodes.Callvirt, resolvedMethod);
}
Expand Down

0 comments on commit 21790e9

Please sign in to comment.