diff --git a/docs/features/async-streams.md b/docs/features/async-streams.md index 3ee08b33dc8b5..ee113bd616faf 100644 --- a/docs/features/async-streams.md +++ b/docs/features/async-streams.md @@ -58,6 +58,10 @@ async IAsyncEnumerable GetValuesFromServer() **open issue**: Design async LINQ +### Detailed design for `await using` statement + +An asynchronous `using` is lowered just like a regular `using`, except that `Dispose()` is replaced with `await DisposeAsync()`. + ### Detailed design for `await foreach` statement An `await foreach` is lowered just like a regular `foreach`, except that: diff --git a/src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs b/src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs index cf9af34e6ac09..348b2c1023e68 100644 --- a/src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs +++ b/src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs @@ -1033,10 +1033,7 @@ private MethodSymbol PerformForEachPatternOverloadResolution(TypeSymbol patternT } overloadResolutionResult.Free(); - if (arguments.Arguments.Count == 0) - { - arguments.Free(); - } + arguments.Free(); typeArguments.Free(); return result; diff --git a/src/Compilers/CSharp/Portable/Binder/UsingStatementBinder.cs b/src/Compilers/CSharp/Portable/Binder/UsingStatementBinder.cs index 4c36ff8cb10ba..aab2c8eb1bc99 100644 --- a/src/Compilers/CSharp/Portable/Binder/UsingStatementBinder.cs +++ b/src/Compilers/CSharp/Portable/Binder/UsingStatementBinder.cs @@ -64,35 +64,21 @@ internal override BoundStatement BindUsingStatementParts(DiagnosticBag diagnosti bool hasAwait = _syntax.AwaitKeyword.Kind() != default; Debug.Assert((expressionSyntax == null) ^ (declarationSyntax == null)); // Can't have both or neither. + TypeSymbol disposableInterface = getDisposableInterface(hasAwait); - TypeSymbol iDisposable = hasAwait - ? this.Compilation.GetWellKnownType(WellKnownType.System_IAsyncDisposable) - : this.Compilation.GetSpecialType(SpecialType.System_IDisposable); - - Debug.Assert((object)iDisposable != null); - bool hasErrors = ReportUseSiteDiagnostics(iDisposable, diagnostics, hasAwait ? _syntax.AwaitKeyword : _syntax.UsingKeyword); + Debug.Assert((object)disposableInterface != null); + bool hasErrors = ReportUseSiteDiagnostics(disposableInterface, diagnostics, hasAwait ? _syntax.AwaitKeyword : _syntax.UsingKeyword); Conversion iDisposableConversion = Conversion.NoConversion; BoundMultipleLocalDeclarations declarationsOpt = null; BoundExpression expressionOpt = null; AwaitableInfo awaitOpt = null; + TypeSymbol declarationTypeOpt = null; + if (expressionSyntax != null) { expressionOpt = this.BindTargetExpression(diagnostics, originalBinder); - - HashSet useSiteDiagnostics = null; - iDisposableConversion = originalBinder.Conversions.ClassifyImplicitConversionFromExpression(expressionOpt, iDisposable, ref useSiteDiagnostics); - diagnostics.Add(expressionSyntax, useSiteDiagnostics); - - if (!iDisposableConversion.IsImplicit) - { - TypeSymbol expressionType = expressionOpt.Type; - if ((object)expressionType == null || !expressionType.IsErrorType()) - { - Error(diagnostics, hasAwait ? ErrorCode.ERR_NoConvToIAsyncDisp : ErrorCode.ERR_NoConvToIDisp, expressionSyntax, expressionOpt.Display); - } - hasErrors = true; - } + hasErrors |= !initConversion(fromExpression: true); } else { @@ -100,30 +86,16 @@ internal override BoundStatement BindUsingStatementParts(DiagnosticBag diagnosti originalBinder.BindForOrUsingOrFixedDeclarations(declarationSyntax, LocalDeclarationKind.UsingVariable, diagnostics, out declarations); Debug.Assert(!declarations.IsEmpty); - declarationsOpt = new BoundMultipleLocalDeclarations(declarationSyntax, declarations); + declarationTypeOpt = declarations[0].DeclaredType.Type; - TypeSymbol declType = declarations[0].DeclaredType.Type; - - if (declType.IsDynamic()) + if (declarationTypeOpt.IsDynamic()) { iDisposableConversion = Conversion.ImplicitDynamic; } else { - HashSet useSiteDiagnostics = null; - iDisposableConversion = originalBinder.Conversions.ClassifyImplicitConversionFromType(declType, iDisposable, ref useSiteDiagnostics); - diagnostics.Add(declarationSyntax, useSiteDiagnostics); - - if (!iDisposableConversion.IsImplicit) - { - if (!declType.IsErrorType()) - { - Error(diagnostics, hasAwait ? ErrorCode.ERR_NoConvToIAsyncDisp : ErrorCode.ERR_NoConvToIDisp, declarationSyntax, declType); - } - - hasErrors = true; - } + hasErrors |= !initConversion(fromExpression: false); } } @@ -149,6 +121,52 @@ internal override BoundStatement BindUsingStatementParts(DiagnosticBag diagnosti boundBody, awaitOpt, hasErrors); + + bool initConversion(bool fromExpression) + { + HashSet useSiteDiagnostics = null; + + iDisposableConversion = classifyConversion(fromExpression, disposableInterface, ref useSiteDiagnostics); + + diagnostics.Add(fromExpression ? (CSharpSyntaxNode)expressionSyntax : declarationSyntax, useSiteDiagnostics); + + if (iDisposableConversion.IsImplicit) + { + return true; + } + + TypeSymbol type = fromExpression ? expressionOpt.Type : declarationTypeOpt; + if (type is null || !type.IsErrorType()) + { + // Retry with a different assumption about whether the `using` is async + TypeSymbol alternateInterface = getDisposableInterface(!hasAwait); + HashSet ignored = null; + Conversion alternateConversion = classifyConversion(fromExpression, alternateInterface, ref ignored); + + bool wrongAsync = alternateConversion.IsImplicit; + ErrorCode errorCode = wrongAsync + ? (hasAwait ? ErrorCode.ERR_NoConvToIAsyncDispWrongAsync : ErrorCode.ERR_NoConvToIDispWrongAsync) + : (hasAwait ? ErrorCode.ERR_NoConvToIAsyncDisp : ErrorCode.ERR_NoConvToIDisp); + + Error(diagnostics, errorCode, (CSharpSyntaxNode)declarationSyntax ?? expressionSyntax, declarationTypeOpt ?? expressionOpt.Display); + } + + return false; + } + + Conversion classifyConversion(bool fromExpression, TypeSymbol targetInterface, ref HashSet diag) + { + return fromExpression? + originalBinder.Conversions.ClassifyImplicitConversionFromExpression(expressionOpt, targetInterface, ref diag) : + originalBinder.Conversions.ClassifyImplicitConversionFromType(declarationTypeOpt, targetInterface, ref diag); + } + + TypeSymbol getDisposableInterface(bool isAsync) + { + return isAsync + ? this.Compilation.GetWellKnownType(WellKnownType.System_IAsyncDisposable) + : this.Compilation.GetSpecialType(SpecialType.System_IDisposable); + } } internal override ImmutableArray GetDeclaredLocalsForScope(SyntaxNode scopeDesignator) diff --git a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs index 8bbea1e9fa336..5f4563f3e6979 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs +++ b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs @@ -10,7 +10,6 @@ namespace Microsoft.CodeAnalysis.CSharp { using System; - using System.Reflection; /// @@ -20,7 +19,7 @@ namespace Microsoft.CodeAnalysis.CSharp { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class CSharpResources { @@ -40,7 +39,7 @@ internal CSharpResources() { internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.CodeAnalysis.CSharp.CSharpResources", typeof(CSharpResources).GetTypeInfo().Assembly); + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.CodeAnalysis.CSharp.CSharpResources", typeof(CSharpResources).Assembly); resourceMan = temp; } return resourceMan; @@ -845,7 +844,7 @@ internal static string ERR_AutoPropsInRoStruct { } /// - /// Looks up a localized string similar to Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. + /// Looks up a localized string similar to Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. /// internal static string ERR_AwaitForEachMissingMember { get { @@ -854,7 +853,7 @@ internal static string ERR_AwaitForEachMissingMember { } /// - /// Looks up a localized string similar to Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'?. + /// Looks up a localized string similar to Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'?. /// internal static string ERR_AwaitForEachMissingMemberWrongAsync { get { @@ -1619,7 +1618,7 @@ internal static string ERR_BadForeachDecl { } /// - /// Looks up a localized string similar to Async foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property. + /// Looks up a localized string similar to Asynchronous foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property. /// internal static string ERR_BadGetAsyncEnumerator { get { @@ -4976,7 +4975,7 @@ internal static string ERR_ForEachMissingMember { } /// - /// Looks up a localized string similar to foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach'?. + /// Looks up a localized string similar to foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach' rather than 'foreach'?. /// internal static string ERR_ForEachMissingMemberWrongAsync { get { @@ -6731,7 +6730,7 @@ internal static string ERR_MultipleEntryPoints { } /// - /// Looks up a localized string similar to Async foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation. + /// Looks up a localized string similar to Asynchronous foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation. /// internal static string ERR_MultipleIAsyncEnumOfT { get { @@ -7117,6 +7116,15 @@ internal static string ERR_NoConvToIAsyncDisp { } } + /// + /// Looks up a localized string similar to '{0}': type used in an async using statement must be implicitly convertible to 'System.IAsyncDisposable'. Did you mean 'using' rather than 'await using'?. + /// + internal static string ERR_NoConvToIAsyncDispWrongAsync { + get { + return ResourceManager.GetString("ERR_NoConvToIAsyncDispWrongAsync", resourceCulture); + } + } + /// /// Looks up a localized string similar to '{0}': type used in a using statement must be implicitly convertible to 'System.IDisposable'. /// @@ -7126,6 +7134,15 @@ internal static string ERR_NoConvToIDisp { } } + /// + /// Looks up a localized string similar to '{0}': type used in a using statement must be implicitly convertible to 'System.IDisposable'. Did you mean 'await using' rather than 'using'?. + /// + internal static string ERR_NoConvToIDispWrongAsync { + get { + return ResourceManager.GetString("ERR_NoConvToIDispWrongAsync", resourceCulture); + } + } + /// /// Looks up a localized string similar to There is no argument given that corresponds to the required formal parameter '{0}' of '{1}'. /// diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 226c7ce46201d..339320c39390f 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -907,7 +907,7 @@ foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNext' method and public 'Current' property - Async foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property + Asynchronous foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property Only 65534 locals, including those generated by the compiler, are allowed @@ -2633,13 +2633,13 @@ A catch() block after a catch (System.Exception e) block can catch non-CLS excep foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' - foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach'? + foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach' rather than 'foreach'? - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? Invalid type for parameter {0} in XML comment cref attribute: '{1}' @@ -2828,7 +2828,7 @@ A catch() block after a catch (System.Exception e) block can catch non-CLS excep foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation - Async foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation + Asynchronous foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation A fixed size buffer field must have the array size specifier after the field name @@ -2959,9 +2959,15 @@ A catch() block after a catch (System.Exception e) block can catch non-CLS excep '{0}': type used in a using statement must be implicitly convertible to 'System.IDisposable' + + '{0}': type used in a using statement must be implicitly convertible to 'System.IDisposable'. Did you mean 'await using' rather than 'using'? + '{0}': type used in an async using statement must be implicitly convertible to 'System.IAsyncDisposable' + + '{0}': type used in an async using statement must be implicitly convertible to 'System.IAsyncDisposable'. Did you mean 'using' rather than 'await using'? + Parameter {0} must be declared with the '{1}' keyword diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index 274f681d72dc3..55f1f82c99538 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -1592,6 +1592,8 @@ internal enum ErrorCode ERR_ForEachMissingMemberWrongAsync = 8414, ERR_AwaitForEachMissingMemberWrongAsync = 8415, ERR_BadDynamicAwaitForEach = 8416, + ERR_NoConvToIAsyncDispWrongAsync = 8417, + ERR_NoConvToIDispWrongAsync = 8418, WRN_ConvertingNullableToNonNullable = 8600, WRN_NullReferenceAssignment = 8601, diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index 5006fc4daf299..2605040599b67 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -23,13 +23,13 @@ - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? @@ -78,8 +78,8 @@ - foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach'? - foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach'? + foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach' rather than 'foreach'? + foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach' rather than 'foreach'? @@ -112,6 +112,16 @@ The 'new()' constraint cannot be used with the 'unmanaged' constraint + + '{0}': type used in an async using statement must be implicitly convertible to 'System.IAsyncDisposable'. Did you mean 'using' rather than 'await using'? + '{0}': type used in an async using statement must be implicitly convertible to 'System.IAsyncDisposable'. Did you mean 'using' rather than 'await using'? + + + + '{0}': type used in a using statement must be implicitly convertible to 'System.IDisposable'. Did you mean 'await using' rather than 'using'? + '{0}': type used in a using statement must be implicitly convertible to 'System.IDisposable'. Did you mean 'await using' rather than 'using'? + + Expected enable or disable Expected enable or disable @@ -9214,13 +9224,13 @@ Pokud chcete odstranit toto varování, můžete místo toho použít /reference - Async foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property - Async foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property + Asynchronous foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property + Asynchronous foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property - Async foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation - Async foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation + Asynchronous foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation + Asynchronous foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index 9099769cb3456..2e477a60b1e99 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -23,13 +23,13 @@ - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? @@ -78,8 +78,8 @@ - foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach'? - foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach'? + foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach' rather than 'foreach'? + foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach' rather than 'foreach'? @@ -112,6 +112,16 @@ The 'new()' constraint cannot be used with the 'unmanaged' constraint + + '{0}': type used in an async using statement must be implicitly convertible to 'System.IAsyncDisposable'. Did you mean 'using' rather than 'await using'? + '{0}': type used in an async using statement must be implicitly convertible to 'System.IAsyncDisposable'. Did you mean 'using' rather than 'await using'? + + + + '{0}': type used in a using statement must be implicitly convertible to 'System.IDisposable'. Did you mean 'await using' rather than 'using'? + '{0}': type used in a using statement must be implicitly convertible to 'System.IDisposable'. Did you mean 'await using' rather than 'using'? + + Expected enable or disable Expected enable or disable @@ -9227,13 +9237,13 @@ Um die Warnung zu beheben, können Sie stattdessen /reference verwenden (Einbett - Async foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property - Async foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property + Asynchronous foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property + Asynchronous foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property - Async foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation - Async foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation + Asynchronous foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation + Asynchronous foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index 6a9f6fa6af82a..17201e1983248 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -23,13 +23,13 @@ - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? @@ -78,8 +78,8 @@ - foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach'? - foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach'? + foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach' rather than 'foreach'? + foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach' rather than 'foreach'? @@ -112,6 +112,16 @@ The 'new()' constraint cannot be used with the 'unmanaged' constraint + + '{0}': type used in an async using statement must be implicitly convertible to 'System.IAsyncDisposable'. Did you mean 'using' rather than 'await using'? + '{0}': type used in an async using statement must be implicitly convertible to 'System.IAsyncDisposable'. Did you mean 'using' rather than 'await using'? + + + + '{0}': type used in a using statement must be implicitly convertible to 'System.IDisposable'. Did you mean 'await using' rather than 'using'? + '{0}': type used in a using statement must be implicitly convertible to 'System.IDisposable'. Did you mean 'await using' rather than 'using'? + + Expected enable or disable Expected enable or disable @@ -9201,13 +9211,13 @@ Para eliminar la advertencia puede usar /reference (establezca la propiedad Embe - Async foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property - Async foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property + Asynchronous foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property + Asynchronous foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property - Async foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation - Async foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation + Asynchronous foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation + Asynchronous foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index b39ce306aebfc..76eeb27a227e0 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -23,13 +23,13 @@ - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? @@ -78,8 +78,8 @@ - foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach'? - foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach'? + foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach' rather than 'foreach'? + foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach' rather than 'foreach'? @@ -112,6 +112,16 @@ The 'new()' constraint cannot be used with the 'unmanaged' constraint + + '{0}': type used in an async using statement must be implicitly convertible to 'System.IAsyncDisposable'. Did you mean 'using' rather than 'await using'? + '{0}': type used in an async using statement must be implicitly convertible to 'System.IAsyncDisposable'. Did you mean 'using' rather than 'await using'? + + + + '{0}': type used in a using statement must be implicitly convertible to 'System.IDisposable'. Did you mean 'await using' rather than 'using'? + '{0}': type used in a using statement must be implicitly convertible to 'System.IDisposable'. Did you mean 'await using' rather than 'using'? + + Expected enable or disable Expected enable or disable @@ -9202,13 +9212,13 @@ Pour supprimer l'avertissement, vous pouvez utiliser la commande /reference (dé - Async foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property - Async foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property + Asynchronous foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property + Asynchronous foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property - Async foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation - Async foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation + Asynchronous foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation + Asynchronous foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index b8e466c065aa9..8d5bc57003923 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -23,13 +23,13 @@ - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? @@ -78,8 +78,8 @@ - foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach'? - foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach'? + foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach' rather than 'foreach'? + foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach' rather than 'foreach'? @@ -112,6 +112,16 @@ The 'new()' constraint cannot be used with the 'unmanaged' constraint + + '{0}': type used in an async using statement must be implicitly convertible to 'System.IAsyncDisposable'. Did you mean 'using' rather than 'await using'? + '{0}': type used in an async using statement must be implicitly convertible to 'System.IAsyncDisposable'. Did you mean 'using' rather than 'await using'? + + + + '{0}': type used in a using statement must be implicitly convertible to 'System.IDisposable'. Did you mean 'await using' rather than 'using'? + '{0}': type used in a using statement must be implicitly convertible to 'System.IDisposable'. Did you mean 'await using' rather than 'using'? + + Expected enable or disable Expected enable or disable @@ -9203,13 +9213,13 @@ Per rimuovere l'avviso, è invece possibile usare /reference (impostare la propr - Async foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property - Async foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property + Asynchronous foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property + Asynchronous foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property - Async foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation - Async foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation + Asynchronous foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation + Asynchronous foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index 0f1dad78ff915..3a5acdb049b17 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -23,13 +23,13 @@ - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? @@ -78,8 +78,8 @@ - foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach'? - foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach'? + foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach' rather than 'foreach'? + foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach' rather than 'foreach'? @@ -112,6 +112,16 @@ The 'new()' constraint cannot be used with the 'unmanaged' constraint + + '{0}': type used in an async using statement must be implicitly convertible to 'System.IAsyncDisposable'. Did you mean 'using' rather than 'await using'? + '{0}': type used in an async using statement must be implicitly convertible to 'System.IAsyncDisposable'. Did you mean 'using' rather than 'await using'? + + + + '{0}': type used in a using statement must be implicitly convertible to 'System.IDisposable'. Did you mean 'await using' rather than 'using'? + '{0}': type used in a using statement must be implicitly convertible to 'System.IDisposable'. Did you mean 'await using' rather than 'using'? + + Expected enable or disable Expected enable or disable @@ -9227,13 +9237,13 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ - Async foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property - Async foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property + Asynchronous foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property + Asynchronous foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property - Async foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation - Async foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation + Asynchronous foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation + Asynchronous foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index d3bb10beadb4a..20d9442eb1467 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -23,13 +23,13 @@ - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? @@ -78,8 +78,8 @@ - foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach'? - foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach'? + foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach' rather than 'foreach'? + foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach' rather than 'foreach'? @@ -112,6 +112,16 @@ The 'new()' constraint cannot be used with the 'unmanaged' constraint + + '{0}': type used in an async using statement must be implicitly convertible to 'System.IAsyncDisposable'. Did you mean 'using' rather than 'await using'? + '{0}': type used in an async using statement must be implicitly convertible to 'System.IAsyncDisposable'. Did you mean 'using' rather than 'await using'? + + + + '{0}': type used in a using statement must be implicitly convertible to 'System.IDisposable'. Did you mean 'await using' rather than 'using'? + '{0}': type used in a using statement must be implicitly convertible to 'System.IDisposable'. Did you mean 'await using' rather than 'using'? + + Expected enable or disable Expected enable or disable @@ -9227,13 +9237,13 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ - Async foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property - Async foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property + Asynchronous foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property + Asynchronous foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property - Async foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation - Async foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation + Asynchronous foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation + Asynchronous foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 4e8f0cb57c7da..4ece8f73e92f4 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -23,13 +23,13 @@ - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? @@ -78,8 +78,8 @@ - foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach'? - foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach'? + foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach' rather than 'foreach'? + foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach' rather than 'foreach'? @@ -112,6 +112,16 @@ The 'new()' constraint cannot be used with the 'unmanaged' constraint + + '{0}': type used in an async using statement must be implicitly convertible to 'System.IAsyncDisposable'. Did you mean 'using' rather than 'await using'? + '{0}': type used in an async using statement must be implicitly convertible to 'System.IAsyncDisposable'. Did you mean 'using' rather than 'await using'? + + + + '{0}': type used in a using statement must be implicitly convertible to 'System.IDisposable'. Did you mean 'await using' rather than 'using'? + '{0}': type used in a using statement must be implicitly convertible to 'System.IDisposable'. Did you mean 'await using' rather than 'using'? + + Expected enable or disable Expected enable or disable @@ -9206,13 +9216,13 @@ Aby usunąć ostrzeżenie, możesz zamiast tego użyć opcji /reference (ustaw w - Async foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property - Async foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property + Asynchronous foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property + Asynchronous foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property - Async foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation - Async foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation + Asynchronous foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation + Asynchronous foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index f359298c23b5d..929b19b9142f1 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -23,13 +23,13 @@ - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? @@ -78,8 +78,8 @@ - foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach'? - foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach'? + foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach' rather than 'foreach'? + foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach' rather than 'foreach'? @@ -112,6 +112,16 @@ The 'new()' constraint cannot be used with the 'unmanaged' constraint + + '{0}': type used in an async using statement must be implicitly convertible to 'System.IAsyncDisposable'. Did you mean 'using' rather than 'await using'? + '{0}': type used in an async using statement must be implicitly convertible to 'System.IAsyncDisposable'. Did you mean 'using' rather than 'await using'? + + + + '{0}': type used in a using statement must be implicitly convertible to 'System.IDisposable'. Did you mean 'await using' rather than 'using'? + '{0}': type used in a using statement must be implicitly convertible to 'System.IDisposable'. Did you mean 'await using' rather than 'using'? + + Expected enable or disable Expected enable or disable @@ -9207,13 +9217,13 @@ Para incorporar informações de tipo de interoperabilidade para os dois assembl - Async foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property - Async foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property + Asynchronous foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property + Asynchronous foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property - Async foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation - Async foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation + Asynchronous foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation + Asynchronous foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index 1f9c5d8bb2367..3131e671ed5ce 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -23,13 +23,13 @@ - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? @@ -78,8 +78,8 @@ - foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach'? - foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach'? + foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach' rather than 'foreach'? + foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach' rather than 'foreach'? @@ -112,6 +112,16 @@ The 'new()' constraint cannot be used with the 'unmanaged' constraint + + '{0}': type used in an async using statement must be implicitly convertible to 'System.IAsyncDisposable'. Did you mean 'using' rather than 'await using'? + '{0}': type used in an async using statement must be implicitly convertible to 'System.IAsyncDisposable'. Did you mean 'using' rather than 'await using'? + + + + '{0}': type used in a using statement must be implicitly convertible to 'System.IDisposable'. Did you mean 'await using' rather than 'using'? + '{0}': type used in a using statement must be implicitly convertible to 'System.IDisposable'. Did you mean 'await using' rather than 'using'? + + Expected enable or disable Expected enable or disable @@ -9209,13 +9219,13 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ - Async foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property - Async foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property + Asynchronous foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property + Asynchronous foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property - Async foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation - Async foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation + Asynchronous foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation + Asynchronous foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index f4ce33fd42507..35b7df1794bfa 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -23,13 +23,13 @@ - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? @@ -78,8 +78,8 @@ - foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach'? - foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach'? + foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach' rather than 'foreach'? + foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach' rather than 'foreach'? @@ -112,6 +112,16 @@ The 'new()' constraint cannot be used with the 'unmanaged' constraint + + '{0}': type used in an async using statement must be implicitly convertible to 'System.IAsyncDisposable'. Did you mean 'using' rather than 'await using'? + '{0}': type used in an async using statement must be implicitly convertible to 'System.IAsyncDisposable'. Did you mean 'using' rather than 'await using'? + + + + '{0}': type used in a using statement must be implicitly convertible to 'System.IDisposable'. Did you mean 'await using' rather than 'using'? + '{0}': type used in a using statement must be implicitly convertible to 'System.IDisposable'. Did you mean 'await using' rather than 'using'? + + Expected enable or disable Expected enable or disable @@ -9215,13 +9225,13 @@ Uyarıyı kaldırmak için, /reference kullanabilirsiniz (Birlikte Çalışma T - Async foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property - Async foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property + Asynchronous foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property + Asynchronous foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property - Async foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation - Async foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation + Asynchronous foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation + Asynchronous foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index edf298d6ba8f7..3210e370e7eaa 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -23,13 +23,13 @@ - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? @@ -78,8 +78,8 @@ - foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach'? - foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach'? + foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach' rather than 'foreach'? + foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach' rather than 'foreach'? @@ -112,6 +112,16 @@ The 'new()' constraint cannot be used with the 'unmanaged' constraint + + '{0}': type used in an async using statement must be implicitly convertible to 'System.IAsyncDisposable'. Did you mean 'using' rather than 'await using'? + '{0}': type used in an async using statement must be implicitly convertible to 'System.IAsyncDisposable'. Did you mean 'using' rather than 'await using'? + + + + '{0}': type used in a using statement must be implicitly convertible to 'System.IDisposable'. Did you mean 'await using' rather than 'using'? + '{0}': type used in a using statement must be implicitly convertible to 'System.IDisposable'. Did you mean 'await using' rather than 'using'? + + Expected enable or disable Expected enable or disable @@ -9227,13 +9237,13 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ - Async foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property - Async foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property + Asynchronous foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property + Asynchronous foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property - Async foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation - Async foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation + Asynchronous foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation + Asynchronous foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index 51d33850990f6..46b613200da94 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -23,13 +23,13 @@ - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}' - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? - Async foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? + Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'? @@ -78,8 +78,8 @@ - foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach'? - foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach'? + foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach' rather than 'foreach'? + foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach' rather than 'foreach'? @@ -112,6 +112,16 @@ The 'new()' constraint cannot be used with the 'unmanaged' constraint + + '{0}': type used in an async using statement must be implicitly convertible to 'System.IAsyncDisposable'. Did you mean 'using' rather than 'await using'? + '{0}': type used in an async using statement must be implicitly convertible to 'System.IAsyncDisposable'. Did you mean 'using' rather than 'await using'? + + + + '{0}': type used in a using statement must be implicitly convertible to 'System.IDisposable'. Did you mean 'await using' rather than 'using'? + '{0}': type used in a using statement must be implicitly convertible to 'System.IDisposable'. Did you mean 'await using' rather than 'using'? + + Expected enable or disable Expected enable or disable @@ -9227,13 +9237,13 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ - Async foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property - Async foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property + Asynchronous foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property + Asynchronous foreach requires that the return type '{0}' of '{1}' must have a suitable public 'MoveNextAsync' method and public 'Current' property - Async foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation - Async foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation + Asynchronous foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation + Asynchronous foreach statement cannot operate on variables of type '{0}' because it implements multiple instantiations of '{1}'; try casting to a specific interface instantiation diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncIteratorTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncIteratorTests.cs index af896e6e8f8ca..0e16f1039f70d 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncIteratorTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncIteratorTests.cs @@ -405,6 +405,29 @@ public static async System.Collections.Generic.IAsyncEnumerable M() }); } + [Fact] + public void ReturnIAsyncEnumerator() + { + string source = @" +public class C +{ + public static async System.Collections.Generic.IAsyncEnumerator M() + { + await System.Threading.Tasks.Task.CompletedTask; + yield return 4; + } +}"; + var comp = CreateCompilationWithTasksExtensions(new[] { source, s_common }); + comp.VerifyDiagnostics( + // (4,74): error CS1983: The return type of an async method must be void, Task, Task, a task-like type, or IAsyncEnumerable + // public static async System.Collections.Generic.IAsyncEnumerator M() + Diagnostic(ErrorCode.ERR_BadAsyncReturn, "M").WithLocation(4, 74), + // (4,74): error CS1624: The body of 'C.M()' cannot be an iterator block because 'IAsyncEnumerator' is not an iterator interface type + // public static async System.Collections.Generic.IAsyncEnumerator M() + Diagnostic(ErrorCode.ERR_BadIteratorReturn, "M").WithArguments("C.M()", "System.Collections.Generic.IAsyncEnumerator").WithLocation(4, 74) + ); + } + [Fact] public void MissingTypeAndMembers_ManualResetValueTaskSourceLogic() { diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAwaitForeachTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAwaitForeachTests.cs index fb5c446e56bb3..b2b3a9e668da4 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAwaitForeachTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAwaitForeachTests.cs @@ -12,29 +12,6 @@ namespace Microsoft.CodeAnalysis.CSharp.UnitTests.CodeGen [CompilerTrait(CompilerFeature.AsyncStreams)] public class CodeGenAwaitForeachTests : EmitMetadataTestBase { - private static readonly string s_interfaces = @" -namespace System.Collections.Generic -{ - public interface IAsyncEnumerable - { - IAsyncEnumerator GetAsyncEnumerator(); - } - - public interface IAsyncEnumerator : System.IAsyncDisposable - { - System.Threading.Tasks.ValueTask MoveNextAsync(); - T Current { get; } - } -} -namespace System -{ - public interface IAsyncDisposable - { - System.Threading.Tasks.ValueTask DisposeAsync(); - } -} -"; - [Fact] public void TestWithCSharp7_3() { @@ -51,7 +28,7 @@ public static async System.Threading.Tasks.Task Main() IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator() => throw null; }"; - var comp = CreateCompilationWithTasksExtensions(new[] { source, s_interfaces }, parseOptions: TestOptions.Regular7_3); + var comp = CreateCompilationWithTasksExtensions(new[] { source, s_IAsyncEnumerable }, parseOptions: TestOptions.Regular7_3); comp.VerifyDiagnostics( // (7,9): error CS8370: Feature 'async streams' is not available in C# 7.3. Please use language version 8.0 or greater. // await foreach (int i in new C()) @@ -70,7 +47,7 @@ IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator() => throw null; }"; - var lib = CreateCompilationWithTasksExtensions(new[] { lib_cs, s_interfaces }); + var lib = CreateCompilationWithTasksExtensions(new[] { lib_cs, s_IAsyncEnumerable }); lib.VerifyDiagnostics(); string source = @" @@ -91,6 +68,28 @@ public static async System.Threading.Tasks.Task Main() ); } + [ConditionalFact(typeof(WindowsDesktopOnly))] + public void TestWithIAsyncEnumerator() + { + string source = @" +using System.Collections.Generic; +using System.Threading.Tasks; +public class C +{ + async Task M(IAsyncEnumerator enumerator) + { + await foreach (int i in enumerator) { } + } +} +"; + var comp_checked = CreateCompilationWithTasksExtensions(new[] { source, s_IAsyncEnumerable }); + comp_checked.VerifyDiagnostics( + // (8,33): error CS8411: Async foreach statement cannot operate on variables of type 'IAsyncEnumerator' because 'IAsyncEnumerator' does not contain a public instance definition for 'GetAsyncEnumerator' + // await foreach (int i in enumerator) { } + Diagnostic(ErrorCode.ERR_AwaitForEachMissingMember, "enumerator").WithArguments("System.Collections.Generic.IAsyncEnumerator", "GetAsyncEnumerator").WithLocation(8, 33) + ); + } + [ConditionalFact(typeof(WindowsDesktopOnly))] public void TestWithUIntToIntConversion() { @@ -134,11 +133,11 @@ public async ValueTask DisposeAsync() } } "; - var comp_checked = CreateCompilationWithTasksExtensions(new[] { source.Replace("REPLACE", "checked"), s_interfaces }, options: TestOptions.DebugExe); + var comp_checked = CreateCompilationWithTasksExtensions(new[] { source.Replace("REPLACE", "checked"), s_IAsyncEnumerable }, options: TestOptions.DebugExe); comp_checked.VerifyDiagnostics(); CompileAndVerify(comp_checked, expectedOutput: "overflow"); - var comp_unchecked = CreateCompilationWithTasksExtensions(new[] { source.Replace("REPLACE", "unchecked"), s_interfaces }, options: TestOptions.DebugExe); + var comp_unchecked = CreateCompilationWithTasksExtensions(new[] { source.Replace("REPLACE", "unchecked"), s_IAsyncEnumerable }, options: TestOptions.DebugExe); comp_unchecked.VerifyDiagnostics(); CompileAndVerify(comp_unchecked, expectedOutput: "0xFFFFFFFF"); } @@ -161,7 +160,7 @@ IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator() IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator() => throw null; }"; - var comp = CreateCompilationWithTasksExtensions(new[] { source, s_interfaces }); + var comp = CreateCompilationWithTasksExtensions(new[] { source, s_IAsyncEnumerable }); comp.VerifyDiagnostics( // (7,33): error CS8413: Async foreach statement cannot operate on variables of type 'C' because it implements multiple instantiations of 'IAsyncEnumerable'; try casting to a specific interface instantiation // await foreach (int i in new C()) @@ -671,7 +670,7 @@ public int Current } } }"; - var comp = CreateCompilationWithTasksExtensions(source + s_interfaces); + var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable); comp.VerifyDiagnostics( // (6,15): error CS0030: Cannot convert type 'int' to 'string' // await foreach (string i in new C()) @@ -781,7 +780,7 @@ class Element private Element(int value) { i = value; } public override string ToString() => i.ToString(); }"; - var comp = CreateCompilationWithTasksExtensions(new[] { source, s_interfaces }, options: TestOptions.DebugExe); + var comp = CreateCompilationWithTasksExtensions(new[] { source, s_IAsyncEnumerable }, options: TestOptions.DebugExe); comp.VerifyDiagnostics( ); CompileAndVerify(comp, @@ -826,7 +825,7 @@ public async ValueTask DisposeAsync() } } }"; - var comp = CreateCompilationWithTasksExtensions(new[] { source, s_interfaces }, options: TestOptions.DebugExe); + var comp = CreateCompilationWithTasksExtensions(new[] { source, s_IAsyncEnumerable }, options: TestOptions.DebugExe); comp.VerifyDiagnostics(); CompileAndVerify(comp, expectedOutput: "Got(1) Got(2) Captured(1)", verify: Verification.Skipped); } @@ -883,7 +882,7 @@ public async ValueTask DisposeAsync() } } }"; - var comp = CreateCompilationWithTasksExtensions(new[] { source, s_interfaces }, options: TestOptions.DebugExe); + var comp = CreateCompilationWithTasksExtensions(new[] { source, s_IAsyncEnumerable }, options: TestOptions.DebugExe); comp.VerifyDiagnostics(); CompileAndVerify(comp, expectedOutput: "NextAsync(1) Current(1) Got(1) NextAsync(2) Current(2) Got(2) NextAsync(3) Current(3) Got(3) NextAsync(4) Dispose(4)", verify: Verification.Skipped); @@ -924,7 +923,7 @@ public ValueTask DisposeAsync() => throw null; } }"; - var comp = CreateCompilationWithTasksExtensions(new[] { source, s_interfaces }, options: TestOptions.DebugExe); + var comp = CreateCompilationWithTasksExtensions(new[] { source, s_IAsyncEnumerable }, options: TestOptions.DebugExe); comp.VerifyDiagnostics(); CompileAndVerify(comp, expectedOutput: "exception", verify: Verification.Skipped); } @@ -967,7 +966,7 @@ public async ValueTask DisposeAsync() } } }"; - var comp = CreateCompilationWithTasksExtensions(new[] { source, s_interfaces }, options: TestOptions.DebugExe); + var comp = CreateCompilationWithTasksExtensions(new[] { source, s_IAsyncEnumerable }, options: TestOptions.DebugExe); comp.VerifyDiagnostics(); CompileAndVerify(comp, expectedOutput: "dispose exception", verify: Verification.Skipped); } @@ -1014,7 +1013,7 @@ public async ValueTask DisposeAsync() } } }"; - var comp = CreateCompilationWithTasksExtensions(new[] { source, s_interfaces }, options: TestOptions.DebugExe); + var comp = CreateCompilationWithTasksExtensions(new[] { source, s_IAsyncEnumerable }, options: TestOptions.DebugExe); comp.VerifyDiagnostics(); CompileAndVerify(comp, expectedOutput: "wait dispose exception", verify: Verification.Skipped); } @@ -1057,7 +1056,7 @@ public ValueTask DisposeAsync() => throw new System.ArgumentException(""exception""); } }"; - var comp = CreateCompilationWithTasksExtensions(new[] { source, s_interfaces }, options: TestOptions.DebugExe); + var comp = CreateCompilationWithTasksExtensions(new[] { source, s_IAsyncEnumerable }, options: TestOptions.DebugExe); comp.VerifyDiagnostics(); CompileAndVerify(comp, expectedOutput: "wait exception", verify: Verification.Skipped); } @@ -1075,7 +1074,7 @@ public static async System.Threading.Tasks.Task Main() } } }"; - var comp = CreateCompilationWithTasksExtensions(new[] { source, s_interfaces }); + var comp = CreateCompilationWithTasksExtensions(new[] { source, s_IAsyncEnumerable }); comp.VerifyDiagnostics( // (6,33): error CS8416: Cannot use a collection of dynamic type in an asynchronous foreach // await foreach (var i in (dynamic)new C()) @@ -1374,7 +1373,7 @@ public sealed class Enumerator }"; var comp = CreateCompilationWithMscorlib46(source); comp.VerifyDiagnostics( - // (6,27): error CS8414: foreach statement cannot operate on variables of type 'C' because 'C' does not contain a public instance definition for 'GetEnumerator'. Did you mean 'await foreach'? + // (6,27): error CS8414: foreach statement cannot operate on variables of type 'C' because 'C' does not contain a public instance definition for 'GetEnumerator'. Did you mean 'await foreach' rather than 'foreach'? // foreach (var i in new C()) Diagnostic(ErrorCode.ERR_ForEachMissingMemberWrongAsync, "new C()").WithArguments("C", "GetEnumerator").WithLocation(6, 27) ); @@ -1394,7 +1393,7 @@ void M(IAsyncEnumerable collection) } } }"; - var comp = CreateCompilationWithTasksExtensions(source + s_interfaces); + var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable); comp.VerifyDiagnostics( // (7,27): error CS8414: foreach statement cannot operate on variables of type 'IAsyncEnumerable' because 'IAsyncEnumerable' does not contain a public instance definition for 'GetEnumerator'. Did you mean 'await foreach'? // foreach (var i in collection) @@ -1416,7 +1415,7 @@ void M(IEnumerable collection) } } }"; - var comp = CreateCompilationWithTasksExtensions(source + s_interfaces); + var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable); comp.VerifyDiagnostics( // (7,33): error CS8415: Async foreach statement cannot operate on variables of type 'IEnumerable' because 'IEnumerable' does not contain a public instance definition for 'GetAsyncEnumerator'. Did you mean 'foreach' rather than 'await foreach'? // await foreach (var i in collection) @@ -1448,7 +1447,7 @@ public System.Threading.Tasks.Task MoveNextAsync() public int Current { get => throw null; } } }"; - var comp = CreateCompilationWithTasksExtensions(source + s_interfaces); + var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable); comp.VerifyDiagnostics( // (6,27): error CS8414: foreach statement cannot operate on variables of type 'C' because 'C' does not contain a public instance definition for 'GetEnumerator'. Did you mean 'await foreach'? // foreach (var i in new C()) @@ -1477,7 +1476,7 @@ public bool MoveNext() => throw null; } }"; - var comp = CreateCompilationWithTasksExtensions(source + s_interfaces); + var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable); comp.VerifyDiagnostics( // (6,33): error CS8415: Async foreach statement cannot operate on variables of type 'C' because 'C' does not contain a public instance definition for 'GetAsyncEnumerator'. Did you mean 'foreach' rather than 'await foreach'? // await foreach (var i in new C()) @@ -1513,7 +1512,7 @@ public int Current } } }"; - var comp = CreateCompilationWithTasksExtensions(source + s_interfaces); + var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable); comp.VerifyDiagnostics(); var tree = comp.SyntaxTrees.Single(); @@ -1556,7 +1555,7 @@ public System.Threading.Tasks.Task MoveNextAsync() public int Current { get => throw null; } } }"; - var comp = CreateCompilationWithTasksExtensions(source + s_interfaces); + var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable); comp.VerifyDiagnostics( // (6,32): error CS8177: Async methods cannot have by-reference locals // await foreach (ref var i in new C()) @@ -1587,7 +1586,7 @@ public sealed class Enumerator public int* Current { get => throw null; } } }"; - var comp = CreateCompilationWithTasksExtensions(source + s_interfaces, options: TestOptions.UnsafeDebugDll); + var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable, options: TestOptions.UnsafeDebugDll); comp.VerifyDiagnostics( // (6,9): error CS4004: Cannot await in an unsafe context // await foreach (var i in new C()) @@ -1623,7 +1622,7 @@ public System.Threading.Tasks.Task MoveNextAsync() public int Current { get => throw null; } } }"; - var comp = CreateCompilationWithTasksExtensions(source + s_interfaces); + var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable); comp.VerifyDiagnostics( // (6,33): error CS8411: Async foreach statement cannot operate on variables of type 'D' because 'D' does not contain a public definition for 'GetAsyncEnumerator' // await foreach (var i in new D()) @@ -1660,7 +1659,7 @@ private System.Threading.Tasks.Task MoveNextAsync() public int Current { get => throw null; } } }"; - var comp = CreateCompilationWithTasksExtensions(source + s_interfaces); + var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable); comp.VerifyDiagnostics( // (6,33): error CS0122: 'D.Enumerator.MoveNextAsync()' is inaccessible due to its protection level // await foreach (var i in new D()) @@ -1697,7 +1696,7 @@ public sealed class Enumerator private int Current { get => throw null; } } }"; - var comp = CreateCompilationWithTasksExtensions(source + s_interfaces); + var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable); comp.VerifyDiagnostics( // (6,33): error CS0122: 'D.Enumerator.Current' is inaccessible due to its protection level // await foreach (var i in new D()) { } @@ -1734,7 +1733,7 @@ public sealed class Enumerator public int Current { private get => throw null; set => throw null; } } }"; - var comp = CreateCompilationWithTasksExtensions(source + s_interfaces); + var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable); comp.VerifyDiagnostics( // (6,33): error CS8412: Async foreach requires that the return type 'D.Enumerator' of 'D.GetAsyncEnumerator()' must have a suitable public MoveNextAsync method and public Current property // await foreach (var i in new D()) { } @@ -1789,7 +1788,7 @@ public S(int i) public override string ToString() => i.ToString(); } "; - var comp = CreateCompilationWithTasksExtensions(source + s_interfaces, options: TestOptions.DebugExe); + var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable, options: TestOptions.DebugExe); comp.VerifyDiagnostics(); CompileAndVerify(comp, expectedOutput: "1 2 Done"); } @@ -1841,7 +1840,7 @@ public override string ToString() => i.ToString(); } "; - var comp = CreateCompilationWithTasksExtensions(new[] { source, s_interfaces }, options: TestOptions.DebugExe); + var comp = CreateCompilationWithTasksExtensions(new[] { source, s_IAsyncEnumerable }, options: TestOptions.DebugExe); comp.VerifyDiagnostics(); CompileAndVerify(comp, expectedOutput: "1 2 3 Done", verify: Verification.Fails); } @@ -1868,7 +1867,7 @@ public System.Threading.Tasks.Task MoveNextAsync() public int Current { get => throw null; } } }"; - var comp = CreateCompilationWithTasksExtensions(new[] { source, s_interfaces }); + var comp = CreateCompilationWithTasksExtensions(new[] { source, s_IAsyncEnumerable }); comp.VerifyDiagnostics( // (8,13): error CS1656: Cannot assign to 'i' because it is a 'foreach iteration variable' // i = 1; @@ -1923,7 +1922,7 @@ public async ValueTask DisposeAsync() } } }"; - var comp = CreateCompilationWithTasksExtensions(source + s_interfaces, options: TestOptions.DebugExe); + var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable, options: TestOptions.DebugExe); comp.VerifyDiagnostics(); CompileAndVerify(comp, expectedOutput: "NextAsync(0) Current(0) Got(1) NextAsync(1) Current(1) Got(2) NextAsync(2) Current(2) Got(3) NextAsync(3) Current(3) Got(4) NextAsync(4) Done", @@ -1975,7 +1974,7 @@ public async ValueTask DisposeAsync() } } }"; - var comp = CreateCompilationWithTasksExtensions(source + s_interfaces, options: TestOptions.DebugExe); + var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable, options: TestOptions.DebugExe); comp.VerifyDiagnostics(); CompileAndVerify(comp, expectedOutput: "NextAsync(0) Current(1) Got(1) NextAsync(1) Current(2) Got(2) NextAsync(2) Current(3) Got(3) NextAsync(3) Done", verify: Verification.Skipped); @@ -2037,7 +2036,7 @@ public async ValueTask DisposeAsync() } } }"; - var comp = CreateCompilationWithTasksExtensions(source + s_interfaces, options: TestOptions.DebugExe); + var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable, options: TestOptions.DebugExe); comp.VerifyDiagnostics(); var tree = comp.SyntaxTrees.Single(); @@ -2101,7 +2100,7 @@ public async ValueTask DisposeAsync() } } }"; - var comp = CreateCompilationWithTasksExtensions(source + s_interfaces, options: TestOptions.DebugExe); + var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable, options: TestOptions.DebugExe); comp.VerifyDiagnostics(); var tree = comp.SyntaxTrees.Single(); @@ -2352,7 +2351,7 @@ .locals init (int V_0, IL_01d4: nop IL_01d5: ret } -", sequencePoints: "C+
d__0.MoveNext", source: source + s_interfaces); +", sequencePoints: "C+
d__0.MoveNext", source: source + s_IAsyncEnumerable); } [ConditionalFact(typeof(WindowsDesktopOnly))] @@ -2399,7 +2398,7 @@ public async ValueTask DisposeAsync() } } }"; - var comp = CreateCompilationWithTasksExtensions(source + s_interfaces, options: TestOptions.DebugExe); + var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable, options: TestOptions.DebugExe); comp.VerifyDiagnostics(); var tree = comp.SyntaxTrees.Single(); @@ -2443,7 +2442,7 @@ async Task M() } } }"; - var lib = CreateCompilationWithTasksExtensions(enumerator + s_interfaces); + var lib = CreateCompilationWithTasksExtensions(enumerator + s_IAsyncEnumerable); lib.VerifyDiagnostics(); var comp = CreateCompilationWithTasksExtensions(source, references: new[] { lib.EmitToImageReference() }); @@ -2482,7 +2481,7 @@ IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator() throw null; } }"; - var comp = CreateCompilationWithTasksExtensions(source + s_interfaces); + var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable); comp.VerifyDiagnostics( // (7,33): error CS8413: Async foreach statement cannot operate on variables of type 'C' because it implements multiple instantiations of 'IAsyncEnumerable'; try casting to a specific interface instantiation // await foreach (var i in new C()) @@ -2512,7 +2511,7 @@ async Task M() IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator() => throw null; }"; - var comp = CreateCompilationWithTasksExtensions(source + s_interfaces); + var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable); comp.VerifyDiagnostics( // (13,33): error CS8413: Async foreach statement cannot operate on variables of type 'C' because it implements multiple instantiations of 'IAsyncEnumerable'; try casting to a specific interface instantiation // await foreach (var i in new C()) @@ -2565,7 +2564,7 @@ public async ValueTask DisposeAsync() } } }"; - var comp = CreateCompilationWithTasksExtensions(source + s_interfaces, options: TestOptions.DebugExe); + var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable, options: TestOptions.DebugExe); comp.VerifyDiagnostics(); CompileAndVerify(comp, expectedOutput: "NextAsync(0) Current(1) Got(1) NextAsync(1) Current(2) Got(2) NextAsync(2) Current(3) Got(3) NextAsync(3) Dispose(4)", verify: Verification.Skipped); @@ -2638,7 +2637,7 @@ public ValueTask DisposeAsync() } } }"; - var comp = CreateCompilationWithTasksExtensions(source + s_interfaces, options: TestOptions.DebugExe); + var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable, options: TestOptions.DebugExe); comp.VerifyDiagnostics(); CompileAndVerify(comp, expectedOutput: "NextAsync(2) Current(3) Got(3) NextAsync(3) Dispose(4) Done", verify: Verification.Skipped); @@ -2692,7 +2691,7 @@ public async ValueTask DisposeAsync() } } }"; - var comp = CreateCompilationWithTasksExtensions(source + s_interfaces, options: TestOptions.DebugExe); + var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable, options: TestOptions.DebugExe); comp.VerifyDiagnostics(); CompileAndVerify(comp, @@ -2749,7 +2748,7 @@ public async ValueTask DisposeAsync() } } }"; - var comp = CreateCompilationWithTasksExtensions(source + s_interfaces, options: TestOptions.DebugExe); + var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable, options: TestOptions.DebugExe); comp.VerifyDiagnostics(); CompileAndVerify(comp, @@ -2805,7 +2804,7 @@ public async ValueTask DisposeAsync() } } }"; - var comp = CreateCompilationWithTasksExtensions(source + s_interfaces, options: TestOptions.DebugExe); + var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable, options: TestOptions.DebugExe); comp.VerifyDiagnostics(); CompileAndVerify(comp, @@ -2824,7 +2823,7 @@ async System.Threading.Tasks.Task M(System.Collections.Generic.IAsyncEnumerable< await foreach (var item in collection) { } } }"; - var comp = CreateCompilationWithTasksExtensions(source + s_interfaces); + var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable); comp.VerifyDiagnostics(); var tree = comp.SyntaxTrees.Single(); @@ -2854,7 +2853,7 @@ IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator() throw null; } }"; - var comp = CreateCompilationWithTasksExtensions(source + s_interfaces); + var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable); comp.VerifyDiagnostics( // (8,33): error CS0186: Use of null is not valid in this context // await foreach (var i in null) @@ -2897,7 +2896,7 @@ internal struct AsyncEnumerator : IAsyncEnumerator public ValueTask DisposeAsync() => throw new System.Exception(); } }"; - var comp = CreateCompilationWithTasksExtensions(source + s_interfaces, options: TestOptions.DebugExe); + var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable, options: TestOptions.DebugExe); comp.VerifyDiagnostics(); CompileAndVerify(comp, expectedOutput: "Success", verify: Verification.Skipped); } @@ -2957,7 +2956,7 @@ public async ValueTask DisposeAsync() } } }"; - var comp = CreateCompilationWithTasksExtensions(source + s_interfaces, options: TestOptions.DebugExe); + var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable, options: TestOptions.DebugExe); comp.VerifyDiagnostics(); CompileAndVerify(comp, expectedOutput: "Try NextAsync(0) Current(1) Got(1) NextAsync(1) Current(2) Got(2) NextAsync(2) Current(3) Got(3) NextAsync(3) Dispose(4) Done", verify: Verification.Skipped); } @@ -2987,7 +2986,7 @@ IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator() throw null; } }"; - var comp = CreateCompilationWithTasksExtensions(source + s_interfaces); + var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable); comp.VerifyDiagnostics( // (13,13): error CS0157: Control cannot leave the body of a finally clause // await foreach (var i in new C()) @@ -3049,7 +3048,7 @@ class Element private Element(int value) { i = value; } public override string ToString() => i.ToString(); }"; - var comp = CreateCompilationWithTasksExtensions(source + s_interfaces, options: TestOptions.DebugExe); + var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable, options: TestOptions.DebugExe); comp.VerifyDiagnostics(); CompileAndVerify(comp, expectedOutput: "NextAsync(0) Current(1) Convert(1) Got(1) NextAsync(1) Current(2) Convert(2) Got(2) NextAsync(2) Dispose(3) Done", verify: Verification.Skipped); @@ -3122,7 +3121,7 @@ public async ValueTask DisposeAsync() } } }"; - var comp = CreateCompilationWithTasksExtensions(source + s_interfaces, options: TestOptions.DebugExe); + var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable, options: TestOptions.DebugExe); comp.VerifyDiagnostics(); CompileAndVerify(comp, expectedOutput: "NextAsync(0) Current(1) Got(1) NextAsync(1) Current(2) Got(2) NextAsync(2) Dispose(3)", verify: Verification.Skipped); @@ -3178,7 +3177,7 @@ IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator() throw new System.Exception(); } }"; - var comp = CreateCompilationWithTasksExtensions(source + s_interfaces, options: TestOptions.DebugExe); + var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable, options: TestOptions.DebugExe); comp.VerifyDiagnostics(); CompileAndVerify(comp, expectedOutput: "Success", verify: Verification.Skipped); } @@ -3232,7 +3231,7 @@ public static class Extensions { public static void Deconstruct(this int i, out string x1, out int x2) { Write($""Deconstruct({i}) ""); x1 = i.ToString(); x2 = -i; } }"; - var comp = CreateCompilationWithTasksExtensions(source + s_interfaces, options: TestOptions.DebugExe); + var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable, options: TestOptions.DebugExe); comp.VerifyDiagnostics(); CompileAndVerify(comp, expectedOutput: "NextAsync(0) Current(1) Deconstruct(1) Got(1,-1) NextAsync(1) Current(2) Deconstruct(2) Got(2,-2) NextAsync(2) Dispose(3) Done", verify: Verification.Skipped); @@ -3279,7 +3278,7 @@ public static class Extensions { public static void Deconstruct(this int i, out int x1, out int x2) { x1 = i; x2 = -i; } }"; - var comp = CreateCompilationWithTasksExtensions(source + s_interfaces); + var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable); comp.VerifyDiagnostics( // (7,9): error CS4033: The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task'. // await foreach (var (i, j) in new C()) @@ -3332,7 +3331,7 @@ public async ValueTask DisposeAsync() } } }"; - var comp = CreateCompilationWithTasksExtensions(source + s_interfaces, options: TestOptions.DebugExe); + var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable, options: TestOptions.DebugExe); comp.VerifyDiagnostics(); CompileAndVerify(comp, expectedOutput: "NextAsync(0) Current(1) Got(1,-1) NextAsync(1) Current(2) Got(2,-2) NextAsync(2) Dispose(3) Done", verify: Verification.Skipped); @@ -3411,7 +3410,7 @@ public static class Extensions { public static void Deconstruct(this int i, out int x1, out int x2) { x1 = i; x2 = -i; } }"; - var comp = CreateCompilationWithTasksExtensions(source + s_interfaces, options: TestOptions.DebugExe); + var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable, options: TestOptions.DebugExe); comp.VerifyDiagnostics(); CompileAndVerify(comp, expectedOutput: "NextAsync(0) Current(1) Got(1,-1) NextAsync(1) Current(2) Got(2,-2) NextAsync(2) Dispose(3) Done", verify: Verification.Skipped); @@ -3446,7 +3445,7 @@ public sealed class AsyncEnumerator : System.IAsyncDisposable public ValueTask DisposeAsync() => throw null; } }"; - var comp = CreateCompilationWithTasksExtensions(source + s_interfaces, options: TestOptions.DebugExe); + var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable, options: TestOptions.DebugExe); comp.VerifyDiagnostics( // (7,15): warning CS0612: 'C.GetAsyncEnumerator()' is obsolete // await foreach (var i in new C()) @@ -3477,7 +3476,7 @@ async System.Threading.Tasks.Task M() } public IAsyncEnumerator GetAsyncEnumerator() => throw null; }"; - var comp = CreateCompilationWithTasksExtensions(source + s_interfaces); + var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable); comp.VerifyDiagnostics( // (8,33): error CS0165: Use of unassigned local variable 'c' // await foreach (var i in c) @@ -3503,7 +3502,7 @@ public IAsyncEnumerator GetAsyncEnumerator() throw null; } }"; - var comp = CreateCompilationWithTasksExtensions(source + s_interfaces); + var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable); comp.VerifyDiagnostics( // (7,27): error CS8414: foreach statement cannot operate on variables of type 'C' because 'C' does not contain a public instance definition for 'GetEnumerator'. Did you mean 'await foreach'? // foreach (var i in new C()) @@ -3558,7 +3557,7 @@ static async System.Threading.Tasks.Task Main() } } }"; - var comp = CreateCompilationWithTasksExtensions(source + s_interfaces, options: TestOptions.DebugExe); + var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable, options: TestOptions.DebugExe); comp.VerifyDiagnostics(); CompileAndVerify(comp, expectedOutput: "NextAsync(0) Current(1) Got NextAsync(1) Current(2) Got NextAsync(2) Current(3) Got NextAsync(3) Dispose(4)", verify: Verification.Skipped); @@ -3639,7 +3638,7 @@ static async System.Threading.Tasks.Task Main() } } }"; - var comp = CreateCompilationWithTasksExtensions(source + s_interfaces, options: TestOptions.DebugExe); + var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable, options: TestOptions.DebugExe); comp.VerifyDiagnostics(); var verifier = CompileAndVerify(comp, expectedOutput: "NextAsync(0) Current(1) Got NextAsync(1) Current(2) Got NextAsync(2) Current(3) Got NextAsync(3)", verify: Verification.Skipped); diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAwaitUsingTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAwaitUsingTests.cs index e5ca2e8ba01d9..ab75f742dd21c 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAwaitUsingTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAwaitUsingTests.cs @@ -765,6 +765,56 @@ public void Dispose() public void TestIAsyncDisposableInRegularUsing() { string source = @" +class C : System.IAsyncDisposable +{ + public static int Main() + { + using (var x = new C()) + { + return 1; + } + } + public System.Threading.Tasks.ValueTask DisposeAsync() + => throw null; +} +"; + var comp = CreateCompilationWithTasksExtensions(new[] { source, s_interfaces }); + comp.VerifyDiagnostics( + // (6,16): error CS8418: 'C': type used in a using statement must be implicitly convertible to 'System.IDisposable'. Did you mean 'await using' rather than 'using'? + // using (var x = new C()) + Diagnostic(ErrorCode.ERR_NoConvToIDispWrongAsync, "var x = new C()").WithArguments("C").WithLocation(6, 16) + ); + } + + [Fact] + public void TestIAsyncDisposableInRegularUsing_Expression() + { + string source = @" +class C : System.IAsyncDisposable +{ + public static int Main() + { + using (new C()) + { + return 1; + } + } + public System.Threading.Tasks.ValueTask DisposeAsync() + => throw null; +} +"; + var comp = CreateCompilationWithTasksExtensions(new[] { source, s_interfaces }); + comp.VerifyDiagnostics( + // (6,16): error CS8418: 'C': type used in a using statement must be implicitly convertible to 'System.IDisposable'. Did you mean 'await using'? + // using (new C()) + Diagnostic(ErrorCode.ERR_NoConvToIDispWrongAsync, "new C()").WithArguments("C").WithLocation(6, 16) + ); + } + + [Fact] + public void TestIAsyncDisposableInRegularUsing_WithDispose() + { + string source = @" class C : System.IAsyncDisposable, System.IDisposable { public static int Main() @@ -791,6 +841,56 @@ public void Dispose() CompileAndVerify(comp, expectedOutput: "body Dispose"); } + [ConditionalFact(typeof(WindowsDesktopOnly))] + public void TestIDisposableInAwaitUsing() + { + string source = @" +class C : System.IDisposable +{ + async System.Threading.Tasks.Task M() + { + await using (var x = new C()) + { + return 1; + } + } + public void Dispose() + => throw null; +} +"; + var comp = CreateCompilationWithTasksExtensions(new[] { source, s_interfaces }); + comp.VerifyDiagnostics( + // (6,22): error CS8417: 'C': type used in an async using statement must be implicitly convertible to 'System.IAsyncDisposable'. Did you mean 'using' rather than 'await using'? + // await using (var x = new C()) + Diagnostic(ErrorCode.ERR_NoConvToIAsyncDispWrongAsync, "var x = new C()").WithArguments("C").WithLocation(6, 22) + ); + } + + [Fact] + public void TestIDisposableInAwaitUsing_Expression() + { + string source = @" +class C : System.IDisposable +{ + async System.Threading.Tasks.Task M() + { + await using (new C()) + { + return 1; + } + } + public void Dispose() + => throw null; +} +"; + var comp = CreateCompilationWithTasksExtensions(new[] { source, s_interfaces }); + comp.VerifyDiagnostics( + // (6,22): error CS8417: 'C': type used in an async using statement must be implicitly convertible to 'System.IAsyncDisposable'. Did you mean 'using' rather than 'await using'? + // await using (new C()) + Diagnostic(ErrorCode.ERR_NoConvToIAsyncDispWrongAsync, "new C()").WithArguments("C").WithLocation(6, 22) + ); + } + [ConditionalFact(typeof(WindowsDesktopOnly))] public void TestWithDynamicDeclaration() { diff --git a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IAwaitExpression.cs b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IAwaitExpression.cs index 39b452fc00b82..f8cb828875a01 100644 --- a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IAwaitExpression.cs +++ b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IAwaitExpression.cs @@ -224,6 +224,61 @@ static void M(Task t) VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, useLatestFrameworkReferences: true); } + [CompilerTrait(CompilerFeature.IOperation, CompilerFeature.Dataflow, CompilerFeature.AsyncStreams)] + [Fact] + public void AwaitFlow_AsyncIterator() + { + string source = @" +using System.Threading.Tasks; + +class C +{ + static async System.Collections.Generic.IAsyncEnumerable M() + /**/{ + await M2(); + yield return 42; + }/**/ + + static Task M2() => null; +} +"; + var expectedDiagnostics = new[] { + // file.cs(24,32): error CS0234: The type or namespace name 'ValueTask<>' does not exist in the namespace 'System.Threading.Tasks' (are you missing an assembly reference?) + // System.Threading.Tasks.ValueTask MoveNextAsync(); + Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInNS, "ValueTask").WithArguments("ValueTask<>", "System.Threading.Tasks").WithLocation(24, 32), + // file.cs(32,32): error CS0234: The type or namespace name 'ValueTask' does not exist in the namespace 'System.Threading.Tasks' (are you missing an assembly reference?) + // System.Threading.Tasks.ValueTask DisposeAsync(); + Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInNS, "ValueTask").WithArguments("ValueTask", "System.Threading.Tasks").WithLocation(32, 32) + }; + + string expectedFlowGraph = @" +Block[B0] - Entry + Statements (0) + Next (Regular) Block[B1] +Block[B1] - Block + Predecessors: [B0] + Statements (2) + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'await M2();') + Expression: + IAwaitOperation (OperationKind.Await, Type: System.Void) (Syntax: 'await M2()') + Expression: + IInvocationOperation (System.Threading.Tasks.Task C.M2()) (OperationKind.Invocation, Type: System.Threading.Tasks.Task) (Syntax: 'M2()') + Instance Receiver: + null + Arguments(0) + + IReturnOperation (OperationKind.YieldReturn, Type: null) (Syntax: 'yield return 42;') + ReturnedValue: + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 42) (Syntax: '42') + + Next (Regular) Block[B2] +Block[B2] - Exit + Predecessors: [B1] + Statements (0) +"; + VerifyFlowGraphAndDiagnosticsForTest(source + s_IAsyncEnumerable, expectedFlowGraph, expectedDiagnostics); + } + [CompilerTrait(CompilerFeature.IOperation, CompilerFeature.Dataflow)] [Fact] public void AwaitFlow_01() diff --git a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IForEachLoopStatement.cs b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IForEachLoopStatement.cs index 882c9175a004b..2090fc6ae66d7 100644 --- a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IForEachLoopStatement.cs +++ b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IForEachLoopStatement.cs @@ -3789,5 +3789,243 @@ void M(bool result, object a, object b) "; VerifyFlowGraphAndDiagnosticsForTest(source, expectedFlowGraph, expectedDiagnostics); } + + [Fact, CompilerTrait(CompilerFeature.IOperation, CompilerFeature.AsyncStreams)] + public void IForEachLoopStatement_SimpleAwaitForEachLoop() + { + string source = @" +class Program +{ + static async System.Threading.Tasks.Task Main(System.Collections.Generic.IAsyncEnumerable pets) + { + /**/await foreach (string value in pets) + { + System.Console.WriteLine(value); + }/**/ + } +} +"; + // https://github.com/dotnet/roslyn/issues/30362 how do we flag `await`? + string expectedOperationTree = @" +IForEachLoopOperation (LoopKind.ForEach, Continue Label Id: 0, Exit Label Id: 1) (OperationKind.Loop, Type: null, IsInvalid) (Syntax: 'await forea ... }') + Locals: Local_1: System.String value + LoopControlVariable: + IVariableDeclaratorOperation (Symbol: System.String value) (OperationKind.VariableDeclarator, Type: null) (Syntax: 'string') + Initializer: + null + Collection: + IParameterReferenceOperation: pets (OperationKind.ParameterReference, Type: System.Collections.Generic.IAsyncEnumerable, IsInvalid) (Syntax: 'pets') + Body: + IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ ... }') + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'System.Cons ... ine(value);') + Expression: + IInvocationOperation (void System.Console.WriteLine(System.String value)) (OperationKind.Invocation, Type: System.Void) (Syntax: 'System.Cons ... Line(value)') + Instance Receiver: + null + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: null) (Syntax: 'value') + ILocalReferenceOperation: value (OperationKind.LocalReference, Type: System.String) (Syntax: 'value') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + NextVariables(0) +"; + VerifyOperationTreeForTest(source + s_IAsyncEnumerable, expectedOperationTree); + } + + [CompilerTrait(CompilerFeature.IOperation, CompilerFeature.Dataflow, CompilerFeature.AsyncStreams)] + [Fact] + public void ForEachAwaitFlow_SimpleAwaitForEachLoop() + { + string source = @" +using System.Runtime.CompilerServices; +using System.Threading.Tasks; +using System; +class Program +{ + static async Task Main(System.Collections.Generic.IAsyncEnumerable pets) + /**/{ + await foreach (string value in pets) + { + System.Console.WriteLine(value); + } + }/**/ +}"; + + var expectedDiagnostics = DiagnosticDescription.None; + + // https://github.com/dotnet/roslyn/issues/30362 should signal `await`. + // https://github.com/dotnet/roslyn/issues/30362 missing await on `MoveNextAsync()` and `DisposeAsync()` calls + // https://github.com/dotnet/roslyn/issues/30362 showing `Dispose()` instead of `DisposeAsync()` + string expectedFlowGraph = @" +Block[B0] - Entry + Statements (0) + Next (Regular) Block[B1] + Entering: {R1} + +.locals {R1} +{ + CaptureIds: [0] + Block[B1] - Block + Predecessors: [B0] + Statements (1) + IFlowCaptureOperation: 0 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'pets') + Value: + IInvocationOperation (virtual System.Collections.Generic.IAsyncEnumerator System.Collections.Generic.IAsyncEnumerable.GetAsyncEnumerator()) (OperationKind.Invocation, Type: System.Collections.Generic.IAsyncEnumerator, IsImplicit) (Syntax: 'pets') + Instance Receiver: + IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Collections.Generic.IAsyncEnumerable, IsImplicit) (Syntax: 'pets') + Conversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + (Identity) + Operand: + IParameterReferenceOperation: pets (OperationKind.ParameterReference, Type: System.Collections.Generic.IAsyncEnumerable) (Syntax: 'pets') + Arguments(0) + + Next (Regular) Block[B2] + Entering: {R2} {R3} + + .try {R2, R3} + { + Block[B2] - Block + Predecessors: [B1] [B3] + Statements (0) + Jump if False (Regular) to Block[B7] + IInvocationOperation (virtual System.Threading.Tasks.ValueTask System.Collections.Generic.IAsyncEnumerator.MoveNextAsync()) (OperationKind.Invocation, Type: System.Threading.Tasks.ValueTask, IsImplicit) (Syntax: 'pets') + Instance Receiver: + IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.Collections.Generic.IAsyncEnumerator, IsImplicit) (Syntax: 'pets') + Arguments(0) + Finalizing: {R5} + Leaving: {R3} {R2} {R1} + + Next (Regular) Block[B3] + Entering: {R4} + + .locals {R4} + { + Locals: [System.String value] + Block[B3] - Block + Predecessors: [B2] + Statements (2) + ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: null, IsImplicit) (Syntax: 'string') + Left: + ILocalReferenceOperation: value (IsDeclaration: True) (OperationKind.LocalReference, Type: System.String, IsImplicit) (Syntax: 'string') + Right: + IPropertyReferenceOperation: System.String System.Collections.Generic.IAsyncEnumerator.Current { get; } (OperationKind.PropertyReference, Type: System.String, IsImplicit) (Syntax: 'string') + Instance Receiver: + IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.Collections.Generic.IAsyncEnumerator, IsImplicit) (Syntax: 'pets') + + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'System.Cons ... ine(value);') + Expression: + IInvocationOperation (void System.Console.WriteLine(System.String value)) (OperationKind.Invocation, Type: System.Void) (Syntax: 'System.Cons ... Line(value)') + Instance Receiver: + null + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: null) (Syntax: 'value') + ILocalReferenceOperation: value (OperationKind.LocalReference, Type: System.String) (Syntax: 'value') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + + Next (Regular) Block[B2] + Leaving: {R4} + } + } + .finally {R5} + { + CaptureIds: [1] + Block[B4] - Block + Predecessors (0) + Statements (1) + IFlowCaptureOperation: 1 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'pets') + Value: + IConversionOperation (TryCast: True, Unchecked) (OperationKind.Conversion, Type: System.IDisposable, IsImplicit) (Syntax: 'pets') + Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null) + (ExplicitReference) + Operand: + IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.Collections.Generic.IAsyncEnumerator, IsImplicit) (Syntax: 'pets') + + Jump if True (Regular) to Block[B6] + IIsNullOperation (OperationKind.IsNull, Type: System.Boolean, IsImplicit) (Syntax: 'pets') + Operand: + IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.IDisposable, IsImplicit) (Syntax: 'pets') + + Next (Regular) Block[B5] + Block[B5] - Block + Predecessors: [B4] + Statements (1) + IInvocationOperation (virtual void System.IDisposable.Dispose()) (OperationKind.Invocation, Type: System.Void, IsImplicit) (Syntax: 'pets') + Instance Receiver: + IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.IDisposable, IsImplicit) (Syntax: 'pets') + Arguments(0) + + Next (Regular) Block[B6] + Block[B6] - Block + Predecessors: [B4] [B5] + Statements (0) + Next (StructuredExceptionHandling) Block[null] + } +} + +Block[B7] - Exit + Predecessors: [B2] + Statements (0) +"; + VerifyFlowGraphAndDiagnosticsForTest(source + s_IAsyncEnumerable + s_ValueTask, expectedFlowGraph, expectedDiagnostics); + } + + private static string s_ValueTask = @" +namespace System.Threading.Tasks +{ + [AsyncMethodBuilder(typeof(ValueTaskMethodBuilder))] + public struct ValueTask + { + public Awaiter GetAwaiter() => null; + public class Awaiter : INotifyCompletion + { + public void OnCompleted(Action a) { } + public bool IsCompleted => true; + public void GetResult() { } + } + } + [AsyncMethodBuilder(typeof(ValueTaskMethodBuilder<>))] + public struct ValueTask + { + public Awaiter GetAwaiter() => null; + public class Awaiter : INotifyCompletion + { + public void OnCompleted(Action a) { } + public bool IsCompleted => true; + public T GetResult() => default(T); + } + } +} +namespace System.Runtime.CompilerServices +{ + class AsyncMethodBuilderAttribute : Attribute + { + public AsyncMethodBuilderAttribute(Type t) { } + } +} +class ValueTaskMethodBuilder +{ + public static ValueTaskMethodBuilder Create() => null; + internal ValueTaskMethodBuilder(ValueTask task) { } + public void SetStateMachine(IAsyncStateMachine stateMachine) { } + public void Start(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine { } + public void SetException(Exception e) { } + public void SetResult() { } + public void AwaitOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : INotifyCompletion where TStateMachine : IAsyncStateMachine { } + public void AwaitUnsafeOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : ICriticalNotifyCompletion where TStateMachine : IAsyncStateMachine { } + public ValueTask Task => default(ValueTask); +} +class ValueTaskMethodBuilder +{ + public static ValueTaskMethodBuilder Create() => null; + internal ValueTaskMethodBuilder(ValueTask task) { } + public void SetStateMachine(IAsyncStateMachine stateMachine) { } + public void Start(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine { } + public void SetException(Exception e) { } + public void SetResult(T t) { } + public void AwaitOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : INotifyCompletion where TStateMachine : IAsyncStateMachine { } + public void AwaitUnsafeOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : ICriticalNotifyCompletion where TStateMachine : IAsyncStateMachine { } + public ValueTask Task => default(ValueTask); +}"; } } diff --git a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IUsingStatement.cs b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IUsingStatement.cs index 7fd6ded2f2aa9..ad5adf3f3406d 100644 --- a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IUsingStatement.cs +++ b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IUsingStatement.cs @@ -68,6 +68,167 @@ public static void M1() VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } + [CompilerTrait(CompilerFeature.IOperation, CompilerFeature.AsyncStreams)] + [Fact] + public void IUsingAwaitStatement_SimpleAwaitUsing() + { + string source = @" +using System; +using System.Runtime.CompilerServices; +using System.Threading.Tasks; + +class C +{ + public static async Task M1(IAsyncDisposable disposable) + { + /**/await using (var c = disposable) + { + Console.WriteLine(c.ToString()); + }/**/ + } +} +"; + // https://github.com/dotnet/roslyn/issues/30362 should show `await` + string expectedOperationTree = @" +IUsingOperation (OperationKind.Using, Type: null) (Syntax: 'await using ... }') + Locals: Local_1: System.IAsyncDisposable c + Resources: + IVariableDeclarationGroupOperation (1 declarations) (OperationKind.VariableDeclarationGroup, Type: null, IsImplicit) (Syntax: 'var c = disposable') + IVariableDeclarationOperation (1 declarators) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'var c = disposable') + Declarators: + IVariableDeclaratorOperation (Symbol: System.IAsyncDisposable c) (OperationKind.VariableDeclarator, Type: null) (Syntax: 'c = disposable') + Initializer: + IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null) (Syntax: '= disposable') + IParameterReferenceOperation: disposable (OperationKind.ParameterReference, Type: System.IAsyncDisposable) (Syntax: 'disposable') + Initializer: + null + Body: + IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ ... }') + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'Console.Wri ... oString());') + Expression: + IInvocationOperation (void System.Console.WriteLine(System.String value)) (OperationKind.Invocation, Type: System.Void) (Syntax: 'Console.Wri ... ToString())') + Instance Receiver: + null + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: null) (Syntax: 'c.ToString()') + IInvocationOperation (virtual System.String System.Object.ToString()) (OperationKind.Invocation, Type: System.String) (Syntax: 'c.ToString()') + Instance Receiver: + ILocalReferenceOperation: c (OperationKind.LocalReference, Type: System.IAsyncDisposable) (Syntax: 'c') + Arguments(0) + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) +"; + + var expectedDiagnostics = DiagnosticDescription.None; + VerifyOperationTreeAndDiagnosticsForTest(source + s_IAsyncEnumerable + s_ValueTask, expectedOperationTree, expectedDiagnostics); + } + + [CompilerTrait(CompilerFeature.IOperation, CompilerFeature.Dataflow, CompilerFeature.AsyncStreams)] + [Fact] + public void UsingFlow_SimpleAwaitUsing() + { + string source = @" +using System; +using System.Runtime.CompilerServices; +using System.Threading.Tasks; + +class C +{ + public static async Task M1(IAsyncDisposable disposable) + /**/{ + await using (var c = disposable) + { + Console.WriteLine(c.ToString()); + } + }/**/ +} +"; + + // https://github.com/dotnet/roslyn/issues/30362 should be `await DisposeAsync()` + string expectedGraph = @" +Block[B0] - Entry + Statements (0) + Next (Regular) Block[B1] + Entering: {R1} + +.locals {R1} +{ + Locals: [System.IAsyncDisposable c] + Block[B1] - Block + Predecessors: [B0] + Statements (1) + ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.IAsyncDisposable, IsImplicit) (Syntax: 'c = disposable') + Left: + ILocalReferenceOperation: c (IsDeclaration: True) (OperationKind.LocalReference, Type: System.IAsyncDisposable, IsImplicit) (Syntax: 'c = disposable') + Right: + IParameterReferenceOperation: disposable (OperationKind.ParameterReference, Type: System.IAsyncDisposable) (Syntax: 'disposable') + + Next (Regular) Block[B2] + Entering: {R2} {R3} + + .try {R2, R3} + { + Block[B2] - Block + Predecessors: [B1] + Statements (1) + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'Console.Wri ... oString());') + Expression: + IInvocationOperation (void System.Console.WriteLine(System.String value)) (OperationKind.Invocation, Type: System.Void) (Syntax: 'Console.Wri ... ToString())') + Instance Receiver: + null + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: null) (Syntax: 'c.ToString()') + IInvocationOperation (virtual System.String System.Object.ToString()) (OperationKind.Invocation, Type: System.String) (Syntax: 'c.ToString()') + Instance Receiver: + ILocalReferenceOperation: c (OperationKind.LocalReference, Type: System.IAsyncDisposable) (Syntax: 'c') + Arguments(0) + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + + Next (Regular) Block[B6] + Finalizing: {R4} + Leaving: {R3} {R2} {R1} + } + .finally {R4} + { + Block[B3] - Block + Predecessors (0) + Statements (0) + Jump if True (Regular) to Block[B5] + IIsNullOperation (OperationKind.IsNull, Type: System.Boolean, IsImplicit) (Syntax: 'c = disposable') + Operand: + ILocalReferenceOperation: c (OperationKind.LocalReference, Type: System.IAsyncDisposable, IsImplicit) (Syntax: 'c = disposable') + + Next (Regular) Block[B4] + Block[B4] - Block + Predecessors: [B3] + Statements (1) + IInvocationOperation (virtual void System.IDisposable.Dispose()) (OperationKind.Invocation, Type: System.Void, IsImplicit) (Syntax: 'c = disposable') + Instance Receiver: + IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.IDisposable, IsImplicit) (Syntax: 'c = disposable') + Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null) + (ExplicitReference) + Operand: + ILocalReferenceOperation: c (OperationKind.LocalReference, Type: System.IAsyncDisposable, IsImplicit) (Syntax: 'c = disposable') + Arguments(0) + + Next (Regular) Block[B5] + Block[B5] - Block + Predecessors: [B3] [B4] + Statements (0) + Next (StructuredExceptionHandling) Block[null] + } +} + +Block[B6] - Exit + Predecessors: [B2] + Statements (0) +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyFlowGraphAndDiagnosticsForTest(source + s_IAsyncEnumerable + s_ValueTask, expectedGraph, expectedDiagnostics); + } + [CompilerTrait(CompilerFeature.IOperation)] [Fact] public void IUsingStatement_MultipleNewVariable() diff --git a/src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs b/src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs index b1c35c4e70c27..40958cc511e81 100644 --- a/src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs +++ b/src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs @@ -1706,5 +1706,28 @@ protected static CSharpCompilation CreateCompilationWithIndexAndRangeAndSpan(CSh parseOptions: parseOptions); } #endregion + + protected static readonly string s_IAsyncEnumerable = @" +namespace System.Collections.Generic +{ + public interface IAsyncEnumerable + { + IAsyncEnumerator GetAsyncEnumerator(); + } + + public interface IAsyncEnumerator : System.IAsyncDisposable + { + System.Threading.Tasks.ValueTask MoveNextAsync(); + T Current { get; } + } +} +namespace System +{ + public interface IAsyncDisposable + { + System.Threading.Tasks.ValueTask DisposeAsync(); + } +} +"; } }