Skip to content

Commit 6bc0abc

Browse files
Fix #2378: DeconstructionTransform produced invalid ILAst with some optimized deconstruction patterns.
1 parent 22c9801 commit 6bc0abc

2 files changed

Lines changed: 39 additions & 0 deletions

File tree

ICSharpCode.Decompiler.Tests/TestCases/Pretty/DeconstructionTests.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,22 @@ public void LocalVariable_NoConversion_Tuple_ReferenceTypes()
219219
Console.WriteLine(value2);
220220
}
221221

222+
public void Issue2378(Tuple<object, object> tuple)
223+
{
224+
var (value, value2) = tuple;
225+
Console.WriteLine(value2);
226+
Console.WriteLine(value);
227+
}
228+
229+
public void Issue2378_IntToLongConversion(Tuple<int, int> tuple)
230+
{
231+
int value;
232+
long value2;
233+
(value, value2) = tuple;
234+
Console.WriteLine(value2);
235+
Console.WriteLine(value);
236+
}
237+
222238
public void LocalVariable_IntToLongConversion_Custom()
223239
{
224240
int value;

ICSharpCode.Decompiler/IL/Transforms/DeconstructionTransform.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,28 @@ bool MatchAssignments(Block block, ref int pos,
378378
previousIndex = index;
379379
}
380380
AddMissingAssignmentsForConversions(int.MaxValue, ref delayedActions);
381+
382+
if (deconstructionResults != null)
383+
{
384+
int i = previousIndex + 1;
385+
while (i < deconstructionResults.Length)
386+
{
387+
var v = deconstructionResults[i];
388+
// this should only happen in release mode, where usually the last deconstruction element
389+
// is not stored to a temporary, if it is used directly (and only once!)
390+
// after the deconstruction.
391+
if (v?.LoadCount == 1)
392+
{
393+
delayedActions += (DeconstructInstruction deconstructInst) => {
394+
var freshVar = context.Function.RegisterVariable(VariableKind.StackSlot, v.Type);
395+
deconstructInst.Assignments.Instructions.Add(new StLoc(freshVar, new LdLoc(v)));
396+
v.LoadInstructions[0].Variable = freshVar;
397+
};
398+
}
399+
i++;
400+
}
401+
}
402+
381403
return startPos != pos;
382404

383405
void AddMissingAssignmentsForConversions(int index, ref Action<DeconstructInstruction> delayedActions)
@@ -397,6 +419,7 @@ void AddMissingAssignmentsForConversions(int index, ref Action<DeconstructInstru
397419
stLoc.Variable = freshVar;
398420
};
399421
}
422+
previousIndex = conversionResultIndex;
400423
conversionStLocIndex++;
401424
}
402425
}

0 commit comments

Comments
 (0)