diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/AsyncAwaitPatterns.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/AsyncAwaitPatterns.cs index 858f8e6..4157def 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/AsyncAwaitPatterns.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/AsyncAwaitPatterns.cs @@ -16,9 +16,9 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -// Await shapes that still decompile to code that does not compile are tracked as #4017 (type -// parameter with an interface constraint), #4018 (static dynamic call) and #4019 (with -// expression); they are absent here because they have no correct output to pin yet. +// An await shape that still decompiles to code that does not compile is tracked as #4017 (type +// parameter with an interface constraint); it is absent here because it has no correct output to +// pin yet. #pragma warning disable 1998 using System; diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.cs index 1fb9ea4..204b5f0 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.cs @@ -22,6 +22,9 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Threading; +#if ROSLYN2 +using System.Threading.Tasks; +#endif namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.InitializerTests { @@ -1233,6 +1236,23 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.InitializerTests Property = 42 }; } + +#if ROSLYN2 + public static async Task ObjectInitializerWithAwait(Task task) + { + return new C { + Z = await task + }; + } + + public static async Task ObjectInitializerWithAwaitAfterConstant(Task task) + { + return new C { + Z = 42, + Y = await task + }; + } +#endif #endregion #region Collection initializer diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Records.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Records.cs index 1e078e5..6a50b38 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Records.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Records.cs @@ -3,6 +3,7 @@ using System; using System.Runtime.InteropServices; using System.Text; #endif +using System.Threading.Tasks; namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { @@ -129,6 +130,19 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty } }; } + public async Task WithAwait(PrimaryCtor input) + { + return input with { + A = await Task.FromResult(42) + }; + } + public async Task WithAwaitAfterConstant(Fields input) + { + return input with { + A = 42, + B = await Task.FromResult(3.141) + }; + } } public abstract record WithNestedRecords diff --git a/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs b/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs index 6c0c98c..87b1481 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs @@ -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)); + } + /// /// Gets whether 'expressionBeingMoved' can be inlined into 'expr'. ///