Fix #4153: Keep foreach when a named argument reads the loop variable
Once a named argument is hoisted, the call becomes a CallWithNamedArgs block, and inlining moves the Current getter into the block's first argument store. The foreach detection could not move it back out: CanInlineIntoSlot refused the block, and for an instance call the store of the 'this' argument in front counted as a write the getter cannot be moved past. That store only writes the block's own variable, so the getter is checked against the stored value instead, the same way CanExtendNamedArgument allows inlining into that position.
This commit is contained in:
1 parent
3e462ad472
commit
3b5201cabc
4 files changed
+66
No files matched your search
@@ -932,6 +932,12 @@ namespace ICSharpCode.Decompiler.Tests
|
||||
await RunForLibrary(cscOptions: cscOptions);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Issue4153([ValueSource(nameof(roslynOnlyWithNet40Options))] CompilerOptions cscOptions)
|
||||
{
|
||||
await RunForLibrary(cscOptions: cscOptions);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task AssemblyCustomAttributes([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
|
||||
{
|
||||
internal class Issue4153
|
||||
{
|
||||
private static int G(int i)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
|
||||
private static int M(int x, int y)
|
||||
{
|
||||
return x + y;
|
||||
}
|
||||
|
||||
private int N(int x, int y)
|
||||
{
|
||||
return x - y;
|
||||
}
|
||||
|
||||
public static int DictionaryEntries(Dictionary<int, int> d)
|
||||
{
|
||||
int num = 0;
|
||||
foreach (KeyValuePair<int, int> item in d)
|
||||
{
|
||||
num += M(y: G(item.Key), x: G(2));
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
public static int ListOfPairs(List<KeyValuePair<int, int>> list)
|
||||
{
|
||||
int num = 0;
|
||||
foreach (KeyValuePair<int, int> item in list)
|
||||
{
|
||||
num += M(y: G(item.Key), x: G(2));
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
public int InstanceCall(Dictionary<int, int> d)
|
||||
{
|
||||
int num = 0;
|
||||
foreach (KeyValuePair<int, int> item in d)
|
||||
{
|
||||
num += N(y: G(item.Key), x: G(2));
|
||||
}
|
||||
return num;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user