Fix #4019: Recognize with expressions whose initializer awaits
Roslyn spills the receiver of an initializer assignment that precedes an await into a hoisted temporary, so the clone of a with expression (and the object of an object initializer) reaches the initializer transform through a copy it rejects. Only copies between two hoisted compiler temporaries are inlined: folding copies of hoisted user locals as well would turn a user's local into an initializer.
This commit is contained in:
1 parent
ef47a24511
commit
85285c1cea
4 files changed
+50
-4
No files matched your search
@@ -668,12 +668,17 @@ namespace ICSharpCode.Decompiler.IL.Transforms
|
||||
case OpCode.SwitchInstruction:
|
||||
return true;
|
||||
case OpCode.LdLoc:
|
||||
if (v.StateMachineField == null && ((LdLoc)inlinedExpression).Variable.StateMachineField != null)
|
||||
var copiedVariable = ((LdLoc)inlinedExpression).Variable;
|
||||
if (v.StateMachineField == null && copiedVariable.StateMachineField != null)
|
||||
{
|
||||
// Roslyn likes to put the result of fetching a state machine field into a temporary variable,
|
||||
// so inline more aggressively in such cases.
|
||||
return true;
|
||||
}
|
||||
if (IsHoistedCompilerTemporary(v) && IsHoistedCompilerTemporary(copiedVariable))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (inlinedExpression.ResultType == StackType.Ref)
|
||||
@@ -773,6 +778,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms
|
||||
}
|
||||
}
|
||||
|
||||
static bool IsHoistedCompilerTemporary(ILVariable v)
|
||||
{
|
||||
string name = v.StateMachineField?.Name;
|
||||
return name != null
|
||||
&& (name.StartsWith("<>7__wrap", StringComparison.Ordinal) || name.StartsWith("<>s__", StringComparison.Ordinal));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether 'expressionBeingMoved' can be inlined into 'expr'.
|
||||
/// </summary>
|
||||
|
||||
Reference in new issue
Block a user