diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs index c577341e48531..d884574b41d96 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs @@ -3182,21 +3182,13 @@ private BoundExpression BindOutVariableDeclarationArgument( /// /// Reports an error when a bad special by-ref local was found. /// - internal static void CheckRestrictedTypeInAsyncMethod(Symbol containingSymbol, TypeSymbol type, BindingDiagnosticBag diagnostics, SyntaxNode syntax, ErrorCode errorCode = ErrorCode.ERR_BadSpecialByRefLocal) + internal static void CheckRestrictedTypeInAsyncMethod(Symbol containingSymbol, TypeSymbol type, BindingDiagnosticBag diagnostics, SyntaxNode syntax) { - Debug.Assert(errorCode is ErrorCode.ERR_BadSpecialByRefLocal or ErrorCode.ERR_BadSpecialByRefUsing or ErrorCode.ERR_BadSpecialByRefLock); if (containingSymbol.Kind == SymbolKind.Method && ((MethodSymbol)containingSymbol).IsAsync && type.IsRestrictedType()) { - if (errorCode == ErrorCode.ERR_BadSpecialByRefLock) - { - Error(diagnostics, errorCode, syntax); - } - else - { - Error(diagnostics, errorCode, syntax, type); - } + CheckFeatureAvailability(syntax, MessageID.IDS_FeatureRefUnsafeInIteratorAsync, diagnostics); } } diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs index 9a453523f720a..faeeb28982488 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs @@ -1170,15 +1170,9 @@ protected BoundLocalDeclaration BindVariableDeclaration( protected bool CheckRefLocalInAsyncOrIteratorMethod(SyntaxToken identifierToken, BindingDiagnosticBag diagnostics) { - if (IsInAsyncMethod()) - { - Error(diagnostics, ErrorCode.ERR_BadAsyncLocalType, identifierToken); - return true; - } - else if (IsDirectlyInIterator) + if (IsDirectlyInIterator || IsInAsyncMethod()) { - Error(diagnostics, ErrorCode.ERR_BadIteratorLocalType, identifierToken); - return true; + return !CheckFeatureAvailability(identifierToken, MessageID.IDS_FeatureRefUnsafeInIteratorAsync, diagnostics); } return false; diff --git a/src/Compilers/CSharp/Portable/Binder/LockBinder.cs b/src/Compilers/CSharp/Portable/Binder/LockBinder.cs index c29d038662a25..0899da0cfdb69 100644 --- a/src/Compilers/CSharp/Portable/Binder/LockBinder.cs +++ b/src/Compilers/CSharp/Portable/Binder/LockBinder.cs @@ -64,13 +64,6 @@ internal override BoundStatement BindLockStatementParts(BindingDiagnosticBag dia _ = diagnostics.ReportUseSite(lockTypeInfo.EnterScopeMethod, exprSyntax) || diagnostics.ReportUseSite(lockTypeInfo.ScopeType, exprSyntax) || diagnostics.ReportUseSite(lockTypeInfo.ScopeDisposeMethod, exprSyntax); - - CheckRestrictedTypeInAsyncMethod( - originalBinder.ContainingMemberOrLambda, - lockTypeInfo.ScopeType, - diagnostics, - exprSyntax, - errorCode: ErrorCode.ERR_BadSpecialByRefLock); } BoundStatement stmt = originalBinder.BindPossibleEmbeddedStatement(_syntax.Statement, diagnostics); diff --git a/src/Compilers/CSharp/Portable/Binder/UsingStatementBinder.cs b/src/Compilers/CSharp/Portable/Binder/UsingStatementBinder.cs index 522d191faa3db..e35930b124152 100644 --- a/src/Compilers/CSharp/Portable/Binder/UsingStatementBinder.cs +++ b/src/Compilers/CSharp/Portable/Binder/UsingStatementBinder.cs @@ -119,7 +119,7 @@ internal static BoundStatement BindUsingStatementOrDeclarationFromParts(SyntaxNo Debug.Assert(expressionOpt is not null); if (expressionOpt.Type is not null) { - CheckRestrictedTypeInAsyncMethod(originalBinder.ContainingMemberOrLambda, expressionOpt.Type, diagnostics, expressionOpt.Syntax, errorCode: ErrorCode.ERR_BadSpecialByRefUsing); + CheckRestrictedTypeInAsyncMethod(originalBinder.ContainingMemberOrLambda, expressionOpt.Type, diagnostics, expressionOpt.Syntax); } } else diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index bca68783ecce8..546daa5c1d4b1 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -3810,7 +3810,7 @@ Give the compiler some way to differentiate the methods. For example, you can gi __arglist is not allowed in the parameter list of async methods - 'await' cannot be used in an expression containing the type '{0}' + Instance of type '{0}' cannot be preserved across 'await' or 'yield' boundary. Async methods cannot have pointer type parameters @@ -3851,15 +3851,12 @@ Give the compiler some way to differentiate the methods. For example, you can gi The 'async' modifier can only be used in methods that have a body. - - Parameters or locals of type '{0}' cannot be declared in async methods or async lambda expressions. - - - A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. - foreach statement cannot operate on enumerators of type '{0}' in async or iterator methods because '{0}' is a ref struct. + + Parameters of type '{0}' cannot be declared in async methods or async lambda expressions. + Security attribute '{0}' cannot be applied to an Async method. @@ -5290,12 +5287,6 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Cannot use ref local '{0}' inside an anonymous method, lambda expression, or query expression - - Iterators cannot have by-reference locals - - - Async methods cannot have by-reference locals - A reference returned by a call to '{0}' cannot be preserved across 'await' or 'yield' boundary. @@ -7851,9 +7842,6 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ A value of type 'System.Threading.Lock' converted to a different type will use likely unintended monitor-based locking in 'lock' statement. - - A lock statement on a value of type 'System.Threading.Lock' cannot be used in async methods or async lambda expressions. - Lock object @@ -7911,4 +7899,10 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ 'yield return' should not be used in the body of a lock statement + + ref and unsafe in async and iterator methods + + + A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index 08f0c3e6b45cf..b4fb86f47e14b 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -1111,7 +1111,7 @@ internal enum ErrorCode ERR_NonTaskMainCantBeAsync = 4009, ERR_CantConvAsyncAnonFuncReturns = 4010, ERR_BadAwaiterPattern = 4011, - ERR_BadSpecialByRefLocal = 4012, + ERR_BadSpecialByRefParameter = 4012, ERR_SpecialByRefInLambda = 4013, WRN_UnobservedAwaitableExpression = 4014, ERR_SynchronizedAsyncMethod = 4015, @@ -1429,8 +1429,8 @@ internal enum ErrorCode ERR_RefAssignmentMustHaveIdentityConversion = 8173, ERR_ByReferenceVariableMustBeInitialized = 8174, ERR_AnonDelegateCantUseLocal = 8175, - ERR_BadIteratorLocalType = 8176, - ERR_BadAsyncLocalType = 8177, + // ERR_BadIteratorLocalType = 8176, + // ERR_BadAsyncLocalType = 8177, ERR_RefReturningCallAndAwait = 8178, #endregion diagnostics for ref locals and ref returns introduced in C# 7 @@ -2161,7 +2161,7 @@ internal enum ErrorCode ERR_UnscopedRefAttributeUnsupportedMemberTarget = 9101, ERR_UnscopedRefAttributeInterfaceImplementation = 9102, ERR_UnrecognizedRefSafetyRulesAttributeVersion = 9103, - ERR_BadSpecialByRefUsing = 9104, + // ERR_BadSpecialByRefUsing = 9104, ERR_InvalidPrimaryConstructorParameterReference = 9105, ERR_AmbiguousPrimaryConstructorParameterAsColorColorReceiver = 9106, @@ -2286,7 +2286,7 @@ internal enum ErrorCode ERR_CollectionExpressionMissingAdd = 9215, WRN_ConvertingLock = 9216, - ERR_BadSpecialByRefLock = 9217, + ERR_RefLocalAcrossAwait = 9217, ERR_CantInferMethTypeArgs_DynamicArgumentWithParamsCollections = 9218, ERR_ParamsCollectionAmbiguousDynamicArgument = 9219, diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs index 2d0a6c799d702..4722401c000b1 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs @@ -626,6 +626,7 @@ internal static bool IsBuildOnlyDiagnostic(ErrorCode code) case ErrorCode.ERR_InterceptableMethodMustBeOrdinary: case ErrorCode.ERR_PossibleAsyncIteratorWithoutYield: case ErrorCode.ERR_PossibleAsyncIteratorWithoutYieldOrAwait: + case ErrorCode.ERR_RefLocalAcrossAwait: // Update src\EditorFeatures\CSharp\LanguageServer\CSharpLspBuildOnlyDiagnostics.cs // whenever new values are added here. return true; @@ -1537,7 +1538,7 @@ internal static bool IsBuildOnlyDiagnostic(ErrorCode code) case ErrorCode.ERR_NonTaskMainCantBeAsync: case ErrorCode.ERR_CantConvAsyncAnonFuncReturns: case ErrorCode.ERR_BadAwaiterPattern: - case ErrorCode.ERR_BadSpecialByRefLocal: + case ErrorCode.ERR_BadSpecialByRefParameter: case ErrorCode.WRN_UnobservedAwaitableExpression: case ErrorCode.ERR_SynchronizedAsyncMethod: case ErrorCode.ERR_BadAsyncReturnExpression: @@ -1780,8 +1781,6 @@ internal static bool IsBuildOnlyDiagnostic(ErrorCode code) case ErrorCode.ERR_RefAssignmentMustHaveIdentityConversion: case ErrorCode.ERR_ByReferenceVariableMustBeInitialized: case ErrorCode.ERR_AnonDelegateCantUseLocal: - case ErrorCode.ERR_BadIteratorLocalType: - case ErrorCode.ERR_BadAsyncLocalType: case ErrorCode.ERR_PredefinedValueTupleTypeNotFound: case ErrorCode.ERR_SemiOrLBraceOrArrowExpected: case ErrorCode.ERR_NewWithTupleTypeSyntax: @@ -2333,7 +2332,6 @@ internal static bool IsBuildOnlyDiagnostic(ErrorCode code) case ErrorCode.ERR_UnscopedRefAttributeUnsupportedMemberTarget: case ErrorCode.ERR_UnscopedRefAttributeInterfaceImplementation: case ErrorCode.ERR_UnrecognizedRefSafetyRulesAttributeVersion: - case ErrorCode.ERR_BadSpecialByRefUsing: case ErrorCode.ERR_InvalidPrimaryConstructorParameterReference: case ErrorCode.ERR_AmbiguousPrimaryConstructorParameterAsColorColorReceiver: case ErrorCode.WRN_CapturedPrimaryConstructorParameterPassedToBase: @@ -2422,7 +2420,6 @@ internal static bool IsBuildOnlyDiagnostic(ErrorCode code) case ErrorCode.ERR_CollectionExpressionMissingConstructor: case ErrorCode.ERR_CollectionExpressionMissingAdd: case ErrorCode.WRN_ConvertingLock: - case ErrorCode.ERR_BadSpecialByRefLock: case ErrorCode.ERR_CantInferMethTypeArgs_DynamicArgumentWithParamsCollections: case ErrorCode.ERR_ParamsCollectionAmbiguousDynamicArgument: case ErrorCode.WRN_DynamicDispatchToParamsCollectionMethod: diff --git a/src/Compilers/CSharp/Portable/Errors/MessageID.cs b/src/Compilers/CSharp/Portable/Errors/MessageID.cs index 72f876baaa909..eb580e98e2ac6 100644 --- a/src/Compilers/CSharp/Portable/Errors/MessageID.cs +++ b/src/Compilers/CSharp/Portable/Errors/MessageID.cs @@ -282,6 +282,8 @@ internal enum MessageID IDS_FeatureLockObject = MessageBase + 12841, IDS_FeatureParamsCollections = MessageBase + 12842, + + IDS_FeatureRefUnsafeInIteratorAsync = MessageBase + 12843, } // Message IDs may refer to strings that need to be localized. @@ -466,6 +468,7 @@ internal static LanguageVersion RequiredVersion(this MessageID feature) case MessageID.IDS_FeatureImplicitIndexerInitializer: case MessageID.IDS_FeatureLockObject: case MessageID.IDS_FeatureParamsCollections: + case MessageID.IDS_FeatureRefUnsafeInIteratorAsync: return LanguageVersion.Preview; // C# 12.0 features. diff --git a/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/IteratorAndAsyncCaptureWalker.cs b/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/IteratorAndAsyncCaptureWalker.cs index 91d75e4f81586..d8ce97fa4088f 100644 --- a/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/IteratorAndAsyncCaptureWalker.cs +++ b/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/IteratorAndAsyncCaptureWalker.cs @@ -19,7 +19,7 @@ namespace Microsoft.CodeAnalysis.CSharp /// /// /// Data flow analysis is used to calculate the locals. At yield/await we mark all variables as "unassigned". - /// When a read from an unassigned variables is reported we add the variable to the captured set. + /// When a read from an unassigned variable is reported we add the variable to the captured set. /// "this" parameter is captured if a reference to "this", "base" or an instance field is encountered. /// Variables used in finally also need to be captured if there is a yield in the corresponding try block. /// @@ -76,19 +76,33 @@ public static OrderedSet Analyze(CSharpCompilation compilation, MethodSy foreach (var kvp in lazyDisallowedCaptures) { var variable = kvp.Key; - var type = (variable.Kind == SymbolKind.Local) ? ((LocalSymbol)variable).Type : ((ParameterSymbol)variable).Type; - if (variable is SynthesizedLocal local && local.SynthesizedKind == SynthesizedLocalKind.Spill) + if (variable is LocalSymbol local) { - Debug.Assert(local.TypeWithAnnotations.IsRestrictedType()); - diagnostics.Add(ErrorCode.ERR_ByRefTypeAndAwait, local.GetFirstLocation(), local.TypeWithAnnotations); + foreach (var syntax in kvp.Value) + { + if (local.TypeWithAnnotations.IsRestrictedType()) + { + // CS4007: Instance of type '{0}' cannot be preserved across 'await' or 'yield' boundary. + diagnostics.Add(ErrorCode.ERR_ByRefTypeAndAwait, syntax.Location, local.TypeWithAnnotations); + } + else + { + Debug.Assert(local.RefKind != RefKind.None); + // CS9217: A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + diagnostics.Add(ErrorCode.ERR_RefLocalAcrossAwait, syntax.Location); + } + } } else { - foreach (CSharpSyntaxNode syntax in kvp.Value) + var parameter = (ParameterSymbol)variable; + Debug.Assert(parameter.TypeWithAnnotations.IsRestrictedType()); + + foreach (var syntax in kvp.Value) { - // CS4013: Instance of type '{0}' cannot be used inside an anonymous function, query expression, iterator block or async method - diagnostics.Add(ErrorCode.ERR_SpecialByRefInLambda, syntax.Location, type); + // CS4007: Instance of type '{0}' cannot be preserved across 'await' or 'yield' boundary. + diagnostics.Add(ErrorCode.ERR_ByRefTypeAndAwait, syntax.Location, parameter.TypeWithAnnotations); } } } @@ -195,14 +209,23 @@ protected override ImmutableArray Scan(ref bool badRegion) private void CaptureVariable(Symbol variable, SyntaxNode syntax) { var type = (variable.Kind == SymbolKind.Local) ? ((LocalSymbol)variable).Type : ((ParameterSymbol)variable).Type; - if (type.IsRestrictedType()) + if (type.IsRestrictedType() || + (variable is LocalSymbol { RefKind: not RefKind.None } refLocal && !canRefLocalBeHoisted(refLocal))) { (_lazyDisallowedCaptures ??= new MultiDictionary()).Add(variable, syntax); } else { if (_variablesToHoist.Add(variable) && variable is LocalSymbol local && _boundRefLocalInitializers.TryGetValue(local, out var variableInitializer)) - CaptureRefInitializer(variableInitializer, syntax); + CaptureRefInitializer(variableInitializer, local.SynthesizedKind != SynthesizedLocalKind.UserDefined ? variableInitializer.Syntax : syntax); + } + + static bool canRefLocalBeHoisted(LocalSymbol refLocal) + { + return refLocal.SynthesizedKind == SynthesizedLocalKind.Spill || + (refLocal.SynthesizedKind == SynthesizedLocalKind.ForEachArray && + refLocal.Type.HasInlineArrayAttribute(out _) && + refLocal.Type.TryGetInlineArrayElementField() is not null); } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMethodSymbol.cs index a1771beb99a70..8cce2057e5200 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMethodSymbol.cs @@ -72,7 +72,7 @@ internal void ReportAsyncParameterErrors(BindingDiagnosticBag diagnostics, Locat } else if (parameter.Type.IsRestrictedType()) { - diagnostics.Add(ErrorCode.ERR_BadSpecialByRefLocal, getLocation(parameter, location), parameter.Type); + diagnostics.Add(ErrorCode.ERR_BadSpecialByRefParameter, getLocation(parameter, location), parameter.Type); } } diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index 43a0b6a8deff2..fc8ee36929979 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -267,14 +267,14 @@ Člen záznamu {0} musí být čitelná vlastnost instance nebo pole typu {1}, která se bude shodovat s pozičním parametrem {2}. - - A lock statement on a value of type 'System.Threading.Lock' cannot be used in async methods or async lambda expressions. - A lock statement on a value of type 'System.Threading.Lock' cannot be used in async methods or async lambda expressions. + + foreach statement cannot operate on enumerators of type '{0}' in async or iterator methods because '{0}' is a ref struct. + foreach statement cannot operate on enumerators of type '{0}' in async or iterator methods because '{0}' is a ref struct. - - A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. - Prostředek použitého příkazu typu {0} nejde použít v asynchronních metodách ani v asynchronních výrazech lambda. + + Parameters of type '{0}' cannot be declared in async methods or async lambda expressions. + Parameters of type '{0}' cannot be declared in async methods or async lambda expressions. @@ -1712,6 +1712,11 @@ Pole ref lze deklarovat pouze ve struktuře ref. + + A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + + The left-hand side of a ref assignment must be a ref variable. Levá strana přiřazení odkazu musí být parametr Ref. @@ -2347,6 +2352,11 @@ parametry ref readonly + + ref and unsafe in async and iterator methods + ref and unsafe in async and iterator methods + + relaxed shift operator uvolněný operátor směny @@ -10540,8 +10550,8 @@ Poskytněte kompilátoru nějaký způsob, jak metody rozlišit. Můžete např - 'await' cannot be used in an expression containing the type '{0}' - 'Operátor await nejde použít ve výrazu, který obsahuje typ {0}. + Instance of type '{0}' cannot be preserved across 'await' or 'yield' boundary. + 'Operátor await nejde použít ve výrazu, který obsahuje typ {0}. @@ -10609,16 +10619,6 @@ Poskytněte kompilátoru nějaký způsob, jak metody rozlišit. Můžete např Modifikátor async se dá použít jenom v metodách, které mají tělo. - - Parameters or locals of type '{0}' cannot be declared in async methods or async lambda expressions. - Parametry nebo lokální proměnné typu {0} nemůžou být deklarované v asynchronních metodách nebo asynchronních výrazech lambda. - - - - foreach statement cannot operate on enumerators of type '{0}' in async or iterator methods because '{0}' is a ref struct. - Výraz foreach nejde použít na enumerátorech typu {0} v asynchronních metodách nebo metodách iterátoru, protože {0} je struktura REF. - - Security attribute '{0}' cannot be applied to an Async method. Atribut zabezpečení {0} nejde použít pro metodu Async. @@ -11138,7 +11138,7 @@ Potlačení upozornění zvažte jenom v případě, když určitě nechcete če Instance of type '{0}' cannot be used inside a nested function, query expression, iterator block or async method - Instance typu {0} nelze použít uvnitř vnořené funkce, výrazu dotazu, bloku iterátoru nebo asynchronní metody. + Instance of type '{0}' cannot be used inside a nested function, query expression, iterator block or async method @@ -12449,16 +12449,6 @@ Pokud chcete odstranit toto varování, můžete místo toho použít /reference Místní hodnotu odkazu {0} nejde použít uvnitř anonymní metody, výrazu lambda nebo výrazu dotazu. - - Iterators cannot have by-reference locals - Iterátory nemůžou mít lokální proměnné podle odkazu. - - - - Async methods cannot have by-reference locals - Asynchronní metody nemůžou mít lokální proměnné podle odkazu. - - A reference returned by a call to '{0}' cannot be preserved across 'await' or 'yield' boundary. Odkaz vrácený voláním funkce {0} nelze zachovat v rámci hranice await nebo yield. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index 5bf51a1f40385..d91808e6fc8ff 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -267,14 +267,14 @@ Das Datensatzelement "{0}" muss eine lesbare Instanzeigenschaft oder ein Feld vom Typ "{1}" sein, um dem Positionsparameter "{2}" zu entsprechen. - - A lock statement on a value of type 'System.Threading.Lock' cannot be used in async methods or async lambda expressions. - A lock statement on a value of type 'System.Threading.Lock' cannot be used in async methods or async lambda expressions. + + foreach statement cannot operate on enumerators of type '{0}' in async or iterator methods because '{0}' is a ref struct. + foreach statement cannot operate on enumerators of type '{0}' in async or iterator methods because '{0}' is a ref struct. - - A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. - Eine using-Anweisungsressource vom Typ „{0}“ kann nicht in asynchronen Methoden oder asynchronen Lambdaausdrücken verwendet werden. + + Parameters of type '{0}' cannot be declared in async methods or async lambda expressions. + Parameters of type '{0}' cannot be declared in async methods or async lambda expressions. @@ -1712,6 +1712,11 @@ Ein Verweisfeld kann nur in einer Verweisstruktur deklariert werden. + + A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + + The left-hand side of a ref assignment must be a ref variable. Die linke Seite einer Ref-Zuweisung muss eine Ref-Variable sein. @@ -2347,6 +2352,11 @@ ref readonly-Parameter + + ref and unsafe in async and iterator methods + ref and unsafe in async and iterator methods + + relaxed shift operator entspannter Schichtoperator @@ -10540,8 +10550,8 @@ Unterstützen Sie den Compiler bei der Unterscheidung zwischen den Methoden. Daz - 'await' cannot be used in an expression containing the type '{0}' - '"await" kann nicht in einem Ausdruck verwendet werden, der den Typ "{0}" enthält + Instance of type '{0}' cannot be preserved across 'await' or 'yield' boundary. + '"await" kann nicht in einem Ausdruck verwendet werden, der den Typ "{0}" enthält @@ -10609,16 +10619,6 @@ Unterstützen Sie den Compiler bei der Unterscheidung zwischen den Methoden. Daz Der Modifizierer "async" kann nur in Methoden verwendet werden, die über einen Textkörper verfügen. - - Parameters or locals of type '{0}' cannot be declared in async methods or async lambda expressions. - Parameter oder lokale Variablen des Typs "{0}" können nicht in asynchronen Methoden oder in asynchronen Lambdaausdrücken deklariert werden. - - - - foreach statement cannot operate on enumerators of type '{0}' in async or iterator methods because '{0}' is a ref struct. - Die foreach-Anweisung kann nicht für Enumeratoren vom Typ "{0}" in asynchronen oder Iteratormethoden verwendet werden, weil "{0}" eine Referenzstruktur ist. - - Security attribute '{0}' cannot be applied to an Async method. Das Sicherheitsattribut "{0}" kann nicht auf eine Async-Methode angewendet werden. @@ -11138,7 +11138,7 @@ Sie sollten das Unterdrücken der Warnung nur in Betracht ziehen, wenn Sie siche Instance of type '{0}' cannot be used inside a nested function, query expression, iterator block or async method - Eine Instanz des Typs "{0}" kann nicht in einer geschachtelten Funktion, einem Abfrageausdruck, einem Iteratorblock oder einer Async-Methode verwendet werden. + Instance of type '{0}' cannot be used inside a nested function, query expression, iterator block or async method @@ -12449,16 +12449,6 @@ Um die Warnung zu beheben, können Sie stattdessen /reference verwenden (Einbett Der lokale Verweis "{0}" kann nicht in einer anonymen Methode, einem Lambdaausdruck oder einem Abfrageausdruck verwendet werden. - - Iterators cannot have by-reference locals - Iteratoren dürfen keine lokalen by-reference-Elemente aufweisen. - - - - Async methods cannot have by-reference locals - Asynchrone Methoden dürfen keine lokalen by-reference-Elemente aufweisen. - - A reference returned by a call to '{0}' cannot be preserved across 'await' or 'yield' boundary. Ein Verweis, der von einem Aufruf von "{0}" zurückgegeben wird, kann nicht über die Grenzen "await" oder "yield" hinweg beibehalten werden. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index 169002cf621a1..519a716d29c04 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -267,14 +267,14 @@ El miembro de registro '{0}' debe ser una propiedad de instancia legible o un campo de tipo '{1}' para coincidir con el parámetro posicional '{2}'. - - A lock statement on a value of type 'System.Threading.Lock' cannot be used in async methods or async lambda expressions. - A lock statement on a value of type 'System.Threading.Lock' cannot be used in async methods or async lambda expressions. + + foreach statement cannot operate on enumerators of type '{0}' in async or iterator methods because '{0}' is a ref struct. + foreach statement cannot operate on enumerators of type '{0}' in async or iterator methods because '{0}' is a ref struct. - - A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. - Un recurso de instrucción using de tipo '{0}' no se puede usar en métodos asincrónicos ni expresiones lambda asincrónicas. + + Parameters of type '{0}' cannot be declared in async methods or async lambda expressions. + Parameters of type '{0}' cannot be declared in async methods or async lambda expressions. @@ -1712,6 +1712,11 @@ Un campo ref solo se puede declarar en una estructura ref. + + A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + + The left-hand side of a ref assignment must be a ref variable. La parte izquierda de una asignación de referencias debe ser una variable local. @@ -2347,6 +2352,11 @@ parámetros ref readonly + + ref and unsafe in async and iterator methods + ref and unsafe in async and iterator methods + + relaxed shift operator operador de cambios relajado @@ -10540,8 +10550,8 @@ Indique al compilador alguna forma de diferenciar los métodos. Por ejemplo, pue - 'await' cannot be used in an expression containing the type '{0}' - 'await' no se puede usar en una expresión que contenga el tipo '{0}' + Instance of type '{0}' cannot be preserved across 'await' or 'yield' boundary. + 'await' no se puede usar en una expresión que contenga el tipo '{0}' @@ -10609,16 +10619,6 @@ Indique al compilador alguna forma de diferenciar los métodos. Por ejemplo, pue El modificador 'async' solo se puede usar en métodos que tengan un cuerpo. - - Parameters or locals of type '{0}' cannot be declared in async methods or async lambda expressions. - Los parámetros o locales de tipo '{0}' no pueden declararse en expresiones lambda o métodos asincrónicos. - - - - foreach statement cannot operate on enumerators of type '{0}' in async or iterator methods because '{0}' is a ref struct. - La instrucción foreach no puede funcionar en enumeradores de tipo "{0}" en métodos async o iterator porque "{0}" es una estructura ref. - - Security attribute '{0}' cannot be applied to an Async method. El atributo de seguridad '{0}' no se puede aplicar a un método Async. @@ -11138,7 +11138,7 @@ Considere la posibilidad de suprimir la advertencia solo si tiene la seguridad d Instance of type '{0}' cannot be used inside a nested function, query expression, iterator block or async method - La instancia de tipo "{0}" no se puede usar dentro de una función anidada, una expresión de consulta, un bloque iterador ni un método asincrónico. + Instance of type '{0}' cannot be used inside a nested function, query expression, iterator block or async method @@ -12449,16 +12449,6 @@ Para eliminar la advertencia puede usar /reference (establezca la propiedad Embe No se puede usar la variable local de tipo ref '{0}' dentro de un método anónimo, una expresión lambda o una expresión de consulta. - - Iterators cannot have by-reference locals - Los iteradores no pueden tener variables locales por referencia. - - - - Async methods cannot have by-reference locals - Los métodos asincrónicos no pueden tener variables locales por referencia. - - A reference returned by a call to '{0}' cannot be preserved across 'await' or 'yield' boundary. Una referencia devuelta por una llamada a '{0}' no se puede conservar a través del límite "await" o "yield". diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index 127c92447318d..ceb81446301bf 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -267,14 +267,14 @@ Le membre d'enregistrement '{0}' doit être une propriété d'instance our champ lisible de type '{1}' pour correspondre au paramètre positionnel '{2}'. - - A lock statement on a value of type 'System.Threading.Lock' cannot be used in async methods or async lambda expressions. - A lock statement on a value of type 'System.Threading.Lock' cannot be used in async methods or async lambda expressions. + + foreach statement cannot operate on enumerators of type '{0}' in async or iterator methods because '{0}' is a ref struct. + foreach statement cannot operate on enumerators of type '{0}' in async or iterator methods because '{0}' is a ref struct. - - A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. - Une ressource d’instruction d’utilisation de type '{0}' ne peut pas être utilisée dans des méthodes asynchrones ou des expressions lambda asynchrones. + + Parameters of type '{0}' cannot be declared in async methods or async lambda expressions. + Parameters of type '{0}' cannot be declared in async methods or async lambda expressions. @@ -1712,6 +1712,11 @@ Un champ de référence ne peut être déclaré que dans une sructure de référence. + + A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + + The left-hand side of a ref assignment must be a ref variable. Le côté gauche d’une affectation ref doit être une variable ref. @@ -2347,6 +2352,11 @@ paramètres ref readonly + + ref and unsafe in async and iterator methods + ref and unsafe in async and iterator methods + + relaxed shift operator opérateur shift souple @@ -10540,8 +10550,8 @@ Permettez au compilateur de différencier les méthodes. Par exemple, vous pouve - 'await' cannot be used in an expression containing the type '{0}' - 'await' ne peut pas être utilisé dans une expression contenant le type '{0}' + Instance of type '{0}' cannot be preserved across 'await' or 'yield' boundary. + 'await' ne peut pas être utilisé dans une expression contenant le type '{0}' @@ -10609,16 +10619,6 @@ Permettez au compilateur de différencier les méthodes. Par exemple, vous pouve Le modificateur 'async' ne peut être utilisé que dans des méthodes ayant un corps. - - Parameters or locals of type '{0}' cannot be declared in async methods or async lambda expressions. - Les paramètres ou variables locales de type '{0}' ne peuvent pas être déclarés dans des méthodes asynchrones ou des expressions asynchrones lambda. - - - - foreach statement cannot operate on enumerators of type '{0}' in async or iterator methods because '{0}' is a ref struct. - L'instruction foreach ne peut pas fonctionner sur les énumérateurs de type '{0}' dans les méthodes asynchrones ou les méthodes d'itérateurs, car '{0}' est un struct par référence. - - Security attribute '{0}' cannot be applied to an Async method. Impossible d'appliquer l'attribut de sécurité '{0}' à une méthode Async. @@ -11138,7 +11138,7 @@ Supprimez l'avertissement seulement si vous êtes sûr de ne pas vouloir attendr Instance of type '{0}' cannot be used inside a nested function, query expression, iterator block or async method - Impossible d'utiliser une instance de type '{0}' dans une fonction imbriquée, une expression de requête, un bloc itérateur ou une méthode async + Instance of type '{0}' cannot be used inside a nested function, query expression, iterator block or async method @@ -12449,16 +12449,6 @@ Pour supprimer l'avertissement, vous pouvez utiliser la commande /reference (dé Impossible d'utiliser ref local '{0}' dans une méthode anonyme, une expression lambda ou une expression de requête - - Iterators cannot have by-reference locals - Les itérateurs ne peuvent pas avoir de variables locales par référence - - - - Async methods cannot have by-reference locals - Les méthodes async ne peuvent pas avoir de variables locales par référence - - A reference returned by a call to '{0}' cannot be preserved across 'await' or 'yield' boundary. Une référence renvoyée par un appel à '{0}' ne peut pas être conservée à travers la limite 'wait' ou 'yield'. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index af24bf98301b5..f1568d3b31829 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -267,14 +267,14 @@ Il membro di record '{0}' deve essere una proprietà di istanza leggibile o campo di tipo '{1}' per corrispondere al parametro posizionale '{2}'. - - A lock statement on a value of type 'System.Threading.Lock' cannot be used in async methods or async lambda expressions. - A lock statement on a value of type 'System.Threading.Lock' cannot be used in async methods or async lambda expressions. + + foreach statement cannot operate on enumerators of type '{0}' in async or iterator methods because '{0}' is a ref struct. + foreach statement cannot operate on enumerators of type '{0}' in async or iterator methods because '{0}' is a ref struct. - - A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. - Non è possibile usare una risorsa di istruzione using di tipo '{0}' in metodi asincroni o espressioni lambda asincrone. + + Parameters of type '{0}' cannot be declared in async methods or async lambda expressions. + Parameters of type '{0}' cannot be declared in async methods or async lambda expressions. @@ -1712,6 +1712,11 @@ Un campo ref può essere dichiarato solo in uno struct ref. + + A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + + The left-hand side of a ref assignment must be a ref variable. La parte sinistra di un'assegnazione ref deve essere una variabile ref. @@ -2347,6 +2352,11 @@ parametri di sola lettura ref + + ref and unsafe in async and iterator methods + ref and unsafe in async and iterator methods + + relaxed shift operator operatore di spostamento rilassato @@ -10540,8 +10550,8 @@ Impostare il compilatore in modo tale da distinguere i metodi, ad esempio assegn - 'await' cannot be used in an expression containing the type '{0}' - 'non è possibile usare 'await' in un'espressione contenente il tipo '{0}' + Instance of type '{0}' cannot be preserved across 'await' or 'yield' boundary. + 'non è possibile usare 'await' in un'espressione contenente il tipo '{0}' @@ -10609,16 +10619,6 @@ Impostare il compilatore in modo tale da distinguere i metodi, ad esempio assegn Il modificatore 'async' può essere usato solo nei metodi con un corpo. - - Parameters or locals of type '{0}' cannot be declared in async methods or async lambda expressions. - Non è possibile dichiarare parametri o variabili locali di tipo '{0}' in metodi asincroni o espressioni lambda asincrone. - - - - foreach statement cannot operate on enumerators of type '{0}' in async or iterator methods because '{0}' is a ref struct. - L'istruzione foreach non può funzionare con enumeratori di tipo '{0}' in metodi async o iterator perché '{0}' è uno struct ref. - - Security attribute '{0}' cannot be applied to an Async method. Non è possibile applicare l'attributo di sicurezza '{0}' a un metodo Async @@ -11138,7 +11138,7 @@ Come procedura consigliata, è consigliabile attendere sempre la chiamata. Instance of type '{0}' cannot be used inside a nested function, query expression, iterator block or async method - L'istanza di tipo '{0}' non può essere usata all'interno di una funzione annidata, un'espressione di query, un blocco iteratore o un metodo asincrono + Instance of type '{0}' cannot be used inside a nested function, query expression, iterator block or async method @@ -12449,16 +12449,6 @@ Per rimuovere l'avviso, è invece possibile usare /reference (impostare la propr Non è possibile usare la variabile locale ref '{0}' in un metodo anonimo, in un'espressione lambda o in un'espressione di query - - Iterators cannot have by-reference locals - Gli iteratori non possono includere variabili locali per riferimento - - - - Async methods cannot have by-reference locals - I metodi Async non possono includere variabili locali per riferimento - - A reference returned by a call to '{0}' cannot be preserved across 'await' or 'yield' boundary. Non è possibile mantenere un riferimento restituito da una chiamata a '{0}' oltre il limite 'await' o 'yield'. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index 0f77641625862..e98478c3c0f65 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -267,14 +267,14 @@ レコード メンバー '{0}' は、位置指定パラメーター '{2}' に一致させるための型 '{1}' の読み取り可能なインスタンス プロパティまたはフィールドである必要があります。 - - A lock statement on a value of type 'System.Threading.Lock' cannot be used in async methods or async lambda expressions. - A lock statement on a value of type 'System.Threading.Lock' cannot be used in async methods or async lambda expressions. + + foreach statement cannot operate on enumerators of type '{0}' in async or iterator methods because '{0}' is a ref struct. + foreach statement cannot operate on enumerators of type '{0}' in async or iterator methods because '{0}' is a ref struct. - - A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. - 型 '{0}' の using ステートメント リソースは、非同期メソッドまたは非同期ラムダ式では使用できません。 + + Parameters of type '{0}' cannot be declared in async methods or async lambda expressions. + Parameters of type '{0}' cannot be declared in async methods or async lambda expressions. @@ -1712,6 +1712,11 @@ ref フィールドは ref 構造体でのみ宣言できます。 + + A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + + The left-hand side of a ref assignment must be a ref variable. ref 代入の左辺は ref 変数である必要があります。 @@ -2347,6 +2352,11 @@ ref readonly パラメーター + + ref and unsafe in async and iterator methods + ref and unsafe in async and iterator methods + + relaxed shift operator 緩和されたシフト演算子 @@ -10540,8 +10550,8 @@ C# では out と ref を区別しますが、CLR では同じと認識します - 'await' cannot be used in an expression containing the type '{0}' - 'await' は、型 '{0}' を含む式では使用できません + Instance of type '{0}' cannot be preserved across 'await' or 'yield' boundary. + 'await' は、型 '{0}' を含む式では使用できません @@ -10609,16 +10619,6 @@ C# では out と ref を区別しますが、CLR では同じと認識します async' 修飾子は、本体があるメソッドでのみ使用できます。 - - Parameters or locals of type '{0}' cannot be declared in async methods or async lambda expressions. - '{0}' 型のパラメーターまたはローカルは、非同期メソッドまたは非同期ラムダ式で宣言することができません。 - - - - foreach statement cannot operate on enumerators of type '{0}' in async or iterator methods because '{0}' is a ref struct. - '{0}' は ref 構造体であるため、非同期または反復子のメソッド内で型 '{0}' の列挙子に対して foreach ステートメントは機能しません。 - - Security attribute '{0}' cannot be applied to an Async method. セキュリティ属性 '{0}' を非同期メソッドに適用することはできません。 @@ -11138,7 +11138,7 @@ You should consider suppressing the warning only if you're sure that you don't w Instance of type '{0}' cannot be used inside a nested function, query expression, iterator block or async method - 型 '{0}' のインスタンスは、入れ子になった関数、クエリ式、反復子ブロック、または非同期メソッドの中では使用できません + Instance of type '{0}' cannot be used inside a nested function, query expression, iterator block or async method @@ -12449,16 +12449,6 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ 匿名メソッド、ラムダ式、クエリ式内で ref ローカル変数 '{0}' は使用できません - - Iterators cannot have by-reference locals - 反復子は参照渡しのローカル変数を持つことができません - - - - Async methods cannot have by-reference locals - 非同期メソッドは参照渡しのローカル変数を持つことができません - - A reference returned by a call to '{0}' cannot be preserved across 'await' or 'yield' boundary. '{0}' への呼び出しによって返された参照は、'await' または 'yield' 境界を越えて保持することはできません。 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index fd7b9c8c83b4d..7e87768b4bf62 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -267,14 +267,14 @@ 위치 매개 변수 '{0}'과(와) 일치하려면 레코드 멤버 '{1}'이(가) 유형 '{2}'의 읽을 수 있는 인스턴스 속성 또는 필드여야 합니다. - - A lock statement on a value of type 'System.Threading.Lock' cannot be used in async methods or async lambda expressions. - A lock statement on a value of type 'System.Threading.Lock' cannot be used in async methods or async lambda expressions. + + foreach statement cannot operate on enumerators of type '{0}' in async or iterator methods because '{0}' is a ref struct. + foreach statement cannot operate on enumerators of type '{0}' in async or iterator methods because '{0}' is a ref struct. - - A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. - '{0}' 형식의 using 문 리소스는 비동기 메서드 또는 비동기 람다 식에 사용할 수 없습니다. + + Parameters of type '{0}' cannot be declared in async methods or async lambda expressions. + Parameters of type '{0}' cannot be declared in async methods or async lambda expressions. @@ -1712,6 +1712,11 @@ ref 필드는 ref 구조체에서만 선언할 수 있습니다. + + A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + + The left-hand side of a ref assignment must be a ref variable. ref 할당의 왼쪽은 ref 변수여야 합니다. @@ -2347,6 +2352,11 @@ ref readonly 매개 변수 + + ref and unsafe in async and iterator methods + ref and unsafe in async and iterator methods + + relaxed shift operator 완화된 시프트 연산자 @@ -10540,8 +10550,8 @@ C#에서는 out과 ref를 구분하지만 CLR에서는 동일한 것으로 간 - 'await' cannot be used in an expression containing the type '{0}' - 'await'는 '{0}' 형식이 포함된 식에 사용할 수 없습니다. + Instance of type '{0}' cannot be preserved across 'await' or 'yield' boundary. + 'await'는 '{0}' 형식이 포함된 식에 사용할 수 없습니다. @@ -10609,16 +10619,6 @@ C#에서는 out과 ref를 구분하지만 CLR에서는 동일한 것으로 간 async' 한정자는 본문이 있는 메서드에서만 사용할 수 있습니다. - - Parameters or locals of type '{0}' cannot be declared in async methods or async lambda expressions. - '{0}' 형식의 매개 변수 또는 로컬은 비동기 메서드나 비동기 람다 식에서 선언할 수 없습니다. - - - - foreach statement cannot operate on enumerators of type '{0}' in async or iterator methods because '{0}' is a ref struct. - '{0}'은(는) ref struct이므로 비동기 또는 반복기 메서드의 '{0}' 형식 열거자에서 foreach 문을 수행할 수 없습니다. - - Security attribute '{0}' cannot be applied to an Async method. '{0}' 보안 특성은 비동기 메서드에 적용할 수 없습니다. @@ -11138,7 +11138,7 @@ You should consider suppressing the warning only if you're sure that you don't w Instance of type '{0}' cannot be used inside a nested function, query expression, iterator block or async method - '{0}' 형식의 인스턴스는 중첩된 함수, 쿼리 식, 반복기 블록 또는 비동기 메서드 내에서 사용할 수 없습니다. + Instance of type '{0}' cannot be used inside a nested function, query expression, iterator block or async method @@ -12449,16 +12449,6 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ 무명 메서드, 람다 식 또는 쿼리 식에는 참조 로컬 '{0}'을(를) 사용할 수 없습니다. - - Iterators cannot have by-reference locals - 반복기에 by-reference 로컬을 사용할 수 없습니다. - - - - Async methods cannot have by-reference locals - 비동기 메서드에 by-reference 로컬을 사용할 수 없습니다. - - A reference returned by a call to '{0}' cannot be preserved across 'await' or 'yield' boundary. '{0}'에 대한 호출로 반환된 참조는 'await' 또는 'yield' 경계에서 보존할 수 없습니다. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 4092f9b5e67c5..7dcc59fdbd7f6 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -267,14 +267,14 @@ Składowa rekordu "{0}" musi być możliwą do odczytu właściwością wystąpienia typu "{1}", aby dopasować parametr pozycyjny "{2}". - - A lock statement on a value of type 'System.Threading.Lock' cannot be used in async methods or async lambda expressions. - A lock statement on a value of type 'System.Threading.Lock' cannot be used in async methods or async lambda expressions. + + foreach statement cannot operate on enumerators of type '{0}' in async or iterator methods because '{0}' is a ref struct. + foreach statement cannot operate on enumerators of type '{0}' in async or iterator methods because '{0}' is a ref struct. - - A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. - Zasobu instrukcji przy użyciu typu '{0}' nie można używać w metodach asynchronicznych ani asynchronicznych wyrażeniach lambda. + + Parameters of type '{0}' cannot be declared in async methods or async lambda expressions. + Parameters of type '{0}' cannot be declared in async methods or async lambda expressions. @@ -1712,6 +1712,11 @@ Pole referencyjne można zadeklarować tylko w strukturze referencyjnej. + + A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + + The left-hand side of a ref assignment must be a ref variable. Lewa strona przypisania referencyjnego musi być zmienną referencyjną. @@ -2347,6 +2352,11 @@ parametry tylko do odczytu ref + + ref and unsafe in async and iterator methods + ref and unsafe in async and iterator methods + + relaxed shift operator operator swobodnej zmiany @@ -10540,8 +10550,8 @@ Musisz umożliwić kompilatorowi rozróżnienie metod. Możesz na przykład nada - 'await' cannot be used in an expression containing the type '{0}' - 'Operatora „await” nie można użyć w wyrażeniu zawierającym typ „{0}” + Instance of type '{0}' cannot be preserved across 'await' or 'yield' boundary. + 'Operatora „await” nie można użyć w wyrażeniu zawierającym typ „{0}” @@ -10609,16 +10619,6 @@ Musisz umożliwić kompilatorowi rozróżnienie metod. Możesz na przykład nada Modyfikatora „async” można używać tylko w metodach mających treść. - - Parameters or locals of type '{0}' cannot be declared in async methods or async lambda expressions. - Parametrów ani elementów lokalnych typu „{0}” nie można deklarować w metodach asynchronicznych ani wyrażeniach lambda. - - - - foreach statement cannot operate on enumerators of type '{0}' in async or iterator methods because '{0}' is a ref struct. - Instrukcja foreach nie może działać na modułach wyliczających typu „{0}” w metodach asynchronicznych lub iteratora, ponieważ element „{0}” jest strukturą ref. - - Security attribute '{0}' cannot be applied to an Async method. Atrybutu zabezpieczeń „{0}” nie można zastosować dla metody asynchronicznej. @@ -11138,7 +11138,7 @@ Pominięcie ostrzeżenia należy wziąć pod uwagę tylko w sytuacji, gdy na pew Instance of type '{0}' cannot be used inside a nested function, query expression, iterator block or async method - Wystąpienia typu „{0}” nie można użyć wewnątrz funkcji zagnieżdżonej, wyrażenia zapytania, bloku iteratora ani metody asynchronicznej + Instance of type '{0}' cannot be used inside a nested function, query expression, iterator block or async method @@ -12449,16 +12449,6 @@ Aby usunąć ostrzeżenie, możesz zamiast tego użyć opcji /reference (ustaw w Nie można użyć zmiennej lokalnej typu ref „{0}” wewnątrz metody anonimowej, wyrażenia lambda ani wyrażenia zapytania - - Iterators cannot have by-reference locals - Iteratory nie mogą mieć zmiennych lokalnych dostępnych przez odwołanie - - - - Async methods cannot have by-reference locals - Metody asynchroniczne nie mogą mieć zmiennych lokalnych dostępnych przez odwołanie - - A reference returned by a call to '{0}' cannot be preserved across 'await' or 'yield' boundary. Odwołanie zwrócone przez wywołanie „{0}” nie może zostać zachowane w granicach „await” lub „yield”. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index 06cd639492e03..578dd52d42e00 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -267,14 +267,14 @@ O membro do registro '{0}' precisa ser uma propriedade de instância legível ou campo do tipo '{1}' para corresponder ao parâmetro posicional '{2}'. - - A lock statement on a value of type 'System.Threading.Lock' cannot be used in async methods or async lambda expressions. - A lock statement on a value of type 'System.Threading.Lock' cannot be used in async methods or async lambda expressions. + + foreach statement cannot operate on enumerators of type '{0}' in async or iterator methods because '{0}' is a ref struct. + foreach statement cannot operate on enumerators of type '{0}' in async or iterator methods because '{0}' is a ref struct. - - A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. - Um recurso de instrução using do tipo "{0}" não pode ser usado em métodos assíncronos ou expressões lambda assíncronas. + + Parameters of type '{0}' cannot be declared in async methods or async lambda expressions. + Parameters of type '{0}' cannot be declared in async methods or async lambda expressions. @@ -1712,6 +1712,11 @@ Um campo ref só pode ser declarado em uma estrutura ref. + + A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + + The left-hand side of a ref assignment must be a ref variable. O lado esquerdo de uma atribuição ref deve ser uma variável ref. @@ -2347,6 +2352,11 @@ parâmetros ref readonly + + ref and unsafe in async and iterator methods + ref and unsafe in async and iterator methods + + relaxed shift operator operador de deslocamento flexível @@ -10540,8 +10550,8 @@ Forneça ao compilador alguma forma de diferenciar os métodos. Por exemplo, voc - 'await' cannot be used in an expression containing the type '{0}' - 'aguardar' não pode ser usado em uma expressão que contém o tipo '{0}' + Instance of type '{0}' cannot be preserved across 'await' or 'yield' boundary. + 'aguardar' não pode ser usado em uma expressão que contém o tipo '{0}' @@ -10609,16 +10619,6 @@ Forneça ao compilador alguma forma de diferenciar os métodos. Por exemplo, voc O modificador 'async' só pode ser usado em métodos que têm um corpo. - - Parameters or locals of type '{0}' cannot be declared in async methods or async lambda expressions. - Os parâmetros ou locais do tipo '{0}' não podem ser declarados nos métodos async ou expressões async lambda. - - - - foreach statement cannot operate on enumerators of type '{0}' in async or iterator methods because '{0}' is a ref struct. - a instrução foreach não pode operar em enumeradores do tipo '{0}' em métodos assíncronos ou iteradores porque '{0}' é uma struct de referência. - - Security attribute '{0}' cannot be applied to an Async method. Atributo de segurança "{0}" não pode ser aplicado a um método Assíncrono. @@ -11138,7 +11138,7 @@ Você pode suprimir o aviso se tiver certeza de que não vai querer aguardar a c Instance of type '{0}' cannot be used inside a nested function, query expression, iterator block or async method - A instância do tipo '{0}' não pode ser usada dentro de uma função aninhada, expressão de consulta, bloco de iteradores ou método assíncrono + Instance of type '{0}' cannot be used inside a nested function, query expression, iterator block or async method @@ -12449,16 +12449,6 @@ Para incorporar informações de tipo de interoperabilidade para os dois assembl Não é possível usar a referência local '{0}' em um método anônimo, expressão lambda ou expressão de consulta - - Iterators cannot have by-reference locals - Os iteradores não podem ter locais por referência - - - - Async methods cannot have by-reference locals - Os métodos assíncronos não podem ter locais por referência - - A reference returned by a call to '{0}' cannot be preserved across 'await' or 'yield' boundary. Uma referência retornada por uma chamada para '{0}' não pode ser preservada no limite 'await' ou 'yield'. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index 954057392e614..619ac7320a17b 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -267,14 +267,14 @@ Элемент записи "{0}" должен быть доступным для чтения свойством экземпляра или полем типа "{1}", чтобы соответствовать позиционному параметру "{2}". - - A lock statement on a value of type 'System.Threading.Lock' cannot be used in async methods or async lambda expressions. - A lock statement on a value of type 'System.Threading.Lock' cannot be used in async methods or async lambda expressions. + + foreach statement cannot operate on enumerators of type '{0}' in async or iterator methods because '{0}' is a ref struct. + foreach statement cannot operate on enumerators of type '{0}' in async or iterator methods because '{0}' is a ref struct. - - A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. - Ресурс оператора использования типа "{0}" нельзя применять в асинхронных методах или асинхронных лямбда-выражениях. + + Parameters of type '{0}' cannot be declared in async methods or async lambda expressions. + Parameters of type '{0}' cannot be declared in async methods or async lambda expressions. @@ -1712,6 +1712,11 @@ Поле ссылки может быть объявлено только в структуре ссылки. + + A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + + The left-hand side of a ref assignment must be a ref variable. Левая сторона назначения ref должна быть переменной ref. @@ -2347,6 +2352,11 @@ Параметры ref, доступные только для чтения + + ref and unsafe in async and iterator methods + ref and unsafe in async and iterator methods + + relaxed shift operator нестрогий оператор сдвига @@ -10541,8 +10551,8 @@ Give the compiler some way to differentiate the methods. For example, you can gi - 'await' cannot be used in an expression containing the type '{0}' - '"await" нельзя использовать в выражении, содержащем тип "{0}" + Instance of type '{0}' cannot be preserved across 'await' or 'yield' boundary. + '"await" нельзя использовать в выражении, содержащем тип "{0}" @@ -10610,16 +10620,6 @@ Give the compiler some way to differentiate the methods. For example, you can gi Модификатор "async" можно использовать только в методах, имеющих тело. - - Parameters or locals of type '{0}' cannot be declared in async methods or async lambda expressions. - Параметры или локальные переменные типа "{0}" не могут объявляться в асинхронных методах и в асинхронных лямбда-выражениях. - - - - foreach statement cannot operate on enumerators of type '{0}' in async or iterator methods because '{0}' is a ref struct. - Оператор foreach нельзя использовать с перечислителями типа "{0}" в методах с модификатором Async или Iterator, так как "{0}" является ссылочной структурой. - - Security attribute '{0}' cannot be applied to an Async method. Атрибут безопасности "{0}" нельзя применить к асинхронному методу. @@ -11139,7 +11139,7 @@ You should consider suppressing the warning only if you're sure that you don't w Instance of type '{0}' cannot be used inside a nested function, query expression, iterator block or async method - Экземпляр типа "{0}" нельзя использовать внутри вложенной функции, выражения запроса, блока итератора или асинхронного метода. + Instance of type '{0}' cannot be used inside a nested function, query expression, iterator block or async method @@ -12450,16 +12450,6 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Невозможно использовать локальную переменную ref "{0}" внутри анонимного метода, лямбда-выражения или выражения запроса - - Iterators cannot have by-reference locals - Итераторы не могут иметь локальных переменных по ссылке - - - - Async methods cannot have by-reference locals - Асинхронные методы не могут иметь локальных переменных по ссылке - - A reference returned by a call to '{0}' cannot be preserved across 'await' or 'yield' boundary. Ссылка, возвращенная вызовом ' {0} ', не может быть сохранена за границей 'wait' или 'yield'. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index a44ca7bfed87c..981f7741495aa 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -267,14 +267,14 @@ {0} kayıt üyesi, {1} konumsal parametresi ile eşleşmesi için {2} türünde okunabilir bir örnek özelliği veya alan olmalıdır. - - A lock statement on a value of type 'System.Threading.Lock' cannot be used in async methods or async lambda expressions. - A lock statement on a value of type 'System.Threading.Lock' cannot be used in async methods or async lambda expressions. + + foreach statement cannot operate on enumerators of type '{0}' in async or iterator methods because '{0}' is a ref struct. + foreach statement cannot operate on enumerators of type '{0}' in async or iterator methods because '{0}' is a ref struct. - - A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. - '{0}' türündeki bir using deyimi kaynağı, asenkron yöntemlerde veya asenkron lambda ifadelerinde kullanılamaz. + + Parameters of type '{0}' cannot be declared in async methods or async lambda expressions. + Parameters of type '{0}' cannot be declared in async methods or async lambda expressions. @@ -1712,6 +1712,11 @@ Başvuru alanı yalnızca başvuru yapısında bildirilebilir. + + A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + + The left-hand side of a ref assignment must be a ref variable. ref atamasının sol tarafı, ref değişkeni olmalıdır. @@ -2347,6 +2352,11 @@ ref salt okunur parametreleri + + ref and unsafe in async and iterator methods + ref and unsafe in async and iterator methods + + relaxed shift operator esnek kaydırma işleci @@ -10540,8 +10550,8 @@ Derleyiciye yöntemleri ayrıştırma yolu verin. Örneğin, bunlara farklı adl - 'await' cannot be used in an expression containing the type '{0}' - 'await', '{0}' türünü içeren bir ifadede kullanılamaz + Instance of type '{0}' cannot be preserved across 'await' or 'yield' boundary. + 'await', '{0}' türünü içeren bir ifadede kullanılamaz @@ -10609,16 +10619,6 @@ Derleyiciye yöntemleri ayrıştırma yolu verin. Örneğin, bunlara farklı adl Async' değiştiricisi yalnızca gövdesi olan metotlarda kullanılabilir. - - Parameters or locals of type '{0}' cannot be declared in async methods or async lambda expressions. - Zaman uyumsuz yöntemlerde veya zaman uyumsuz lambda ifadelerinde '{0}' türündeki parametreler veya yerel öğeler bildirilemez. - - - - foreach statement cannot operate on enumerators of type '{0}' in async or iterator methods because '{0}' is a ref struct. - '{0}' bir başvuru yapısı olduğundan foreach deyimi, async veya iterator metotlarındaki '{0}' türü numaralandırıcılar üzerinde çalışamaz. - - Security attribute '{0}' cannot be applied to an Async method. '{0}' güvenlik özniteliği bir Async yöntemine uygulanamaz. @@ -11138,7 +11138,7 @@ Yalnızca asenkron çağrının tamamlanmasını beklemek istemediğinizden ve Instance of type '{0}' cannot be used inside a nested function, query expression, iterator block or async method - '{0}' türünün örneği iç içe geçmiş bir işlevde, sorgu ifadesinde, yineleyici bloğunda veya zaman uyumsuz bir metotta kullanılamaz + Instance of type '{0}' cannot be used inside a nested function, query expression, iterator block or async method @@ -12449,16 +12449,6 @@ Uyarıyı kaldırmak için, /reference kullanabilirsiniz (Birlikte Çalışma T '{0}' ref yerel değeri bir anonim metotta, lambda ifadesinde veya sorgu ifadesinde kullanılamaz - - Iterators cannot have by-reference locals - Yineleyiciler başvuruya göre yerel değerlere sahip olamaz - - - - Async methods cannot have by-reference locals - Zaman uyumsuz metotlar başvuruya göre yerel değerlere sahip olamaz - - A reference returned by a call to '{0}' cannot be preserved across 'await' or 'yield' boundary. '{0}' hedefine bir çağrı tarafından döndürülen başvuru, 'await' veya 'yield' sınırında korunamıyor. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index 3c164338d3da3..5aceeb57b426c 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -267,14 +267,14 @@ 记录成员 '{0}' 必须为类型 '{1}' 的可读实例属性或字段,以匹配位置参数 '{2}'。 - - A lock statement on a value of type 'System.Threading.Lock' cannot be used in async methods or async lambda expressions. - A lock statement on a value of type 'System.Threading.Lock' cannot be used in async methods or async lambda expressions. + + foreach statement cannot operate on enumerators of type '{0}' in async or iterator methods because '{0}' is a ref struct. + foreach statement cannot operate on enumerators of type '{0}' in async or iterator methods because '{0}' is a ref struct. - - A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. - 无法在异步方法或异步 lambda 表达式中使用类型为“{0}”的 using 语句资源。 + + Parameters of type '{0}' cannot be declared in async methods or async lambda expressions. + Parameters of type '{0}' cannot be declared in async methods or async lambda expressions. @@ -1712,6 +1712,11 @@ ref 字段只能在 ref 结构中声明。 + + A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + + The left-hand side of a ref assignment must be a ref variable. ref 赋值的左侧必须为 ref 变量。 @@ -2347,6 +2352,11 @@ ref readonly 参数 + + ref and unsafe in async and iterator methods + ref and unsafe in async and iterator methods + + relaxed shift operator 移位运算符 @@ -10540,8 +10550,8 @@ Give the compiler some way to differentiate the methods. For example, you can gi - 'await' cannot be used in an expression containing the type '{0}' - '“等待”不能在包含“{0}”类型的表达式中使用 + Instance of type '{0}' cannot be preserved across 'await' or 'yield' boundary. + '“等待”不能在包含“{0}”类型的表达式中使用 @@ -10609,16 +10619,6 @@ Give the compiler some way to differentiate the methods. For example, you can gi 只能在具有正文的方法中使用 "async" 修饰符。 - - Parameters or locals of type '{0}' cannot be declared in async methods or async lambda expressions. - 不能在异步方法或异步 lambda 表达式中声明类型“{0}”的参数或局部变量。 - - - - foreach statement cannot operate on enumerators of type '{0}' in async or iterator methods because '{0}' is a ref struct. - foreach 语句无法在类型“{0}”的枚举器上使用异步或迭代器方法操作,因为“{0}”是 ref 结构。 - - Security attribute '{0}' cannot be applied to an Async method. 安全特性“{0}”不可应用于异步方法。 @@ -11138,7 +11138,7 @@ You should consider suppressing the warning only if you're sure that you don't w Instance of type '{0}' cannot be used inside a nested function, query expression, iterator block or async method - “{0}”类型的实例不能在嵌套函数、查询表达式、迭代器块或异步方法中使用 + Instance of type '{0}' cannot be used inside a nested function, query expression, iterator block or async method @@ -12449,16 +12449,6 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ 不能在匿名方法、lambda 表达式或查询表达式内使用 ref 局部变量“{0}” - - Iterators cannot have by-reference locals - 迭代器不能有按引用局部变量 - - - - Async methods cannot have by-reference locals - 异步方法不能有按引用局部变量 - - A reference returned by a call to '{0}' cannot be preserved across 'await' or 'yield' boundary. 调用“{0}”所返回的引用不能跨 "await" 或 "yield" 边界保留。 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index 30d0776683b21..3b36564d36e33 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -267,14 +267,14 @@ 記錄成員 '{0}' 必須是類型 '{1}' 的可讀取執行個體屬性或欄位,才能符合位置參數 '{2}'。 - - A lock statement on a value of type 'System.Threading.Lock' cannot be used in async methods or async lambda expressions. - A lock statement on a value of type 'System.Threading.Lock' cannot be used in async methods or async lambda expressions. + + foreach statement cannot operate on enumerators of type '{0}' in async or iterator methods because '{0}' is a ref struct. + foreach statement cannot operate on enumerators of type '{0}' in async or iterator methods because '{0}' is a ref struct. - - A using statement resource of type '{0}' cannot be used in async methods or async lambda expressions. - 類型 '{0}' 的 using 陳述式資源不能用於非同步方法或非同步 Lambda 運算式。 + + Parameters of type '{0}' cannot be declared in async methods or async lambda expressions. + Parameters of type '{0}' cannot be declared in async methods or async lambda expressions. @@ -1712,6 +1712,11 @@ ref 欄位只能在 ref 結構中宣告。 + + A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + + The left-hand side of a ref assignment must be a ref variable. 參考指派的左側必須為 ref 變數。 @@ -2347,6 +2352,11 @@ ref readonly 參數 + + ref and unsafe in async and iterator methods + ref and unsafe in async and iterator methods + + relaxed shift operator 寬鬆移位 (Shift) 運算子 @@ -10540,8 +10550,8 @@ Give the compiler some way to differentiate the methods. For example, you can gi - 'await' cannot be used in an expression containing the type '{0}' - 'await' 不得用於包含類型 '{0}' 的運算式中 + Instance of type '{0}' cannot be preserved across 'await' or 'yield' boundary. + 'await' 不得用於包含類型 '{0}' 的運算式中 @@ -10609,16 +10619,6 @@ Give the compiler some way to differentiate the methods. For example, you can gi async' 修飾元只可用於具有主體的方法。 - - Parameters or locals of type '{0}' cannot be declared in async methods or async lambda expressions. - 類型 '{0}' 的參數或區域變數,不可在非同步方法或非同步 Lambda 運算式中宣告。 - - - - foreach statement cannot operate on enumerators of type '{0}' in async or iterator methods because '{0}' is a ref struct. - foreach 陳述式無法對 async 或 iterator 方法中類型 '{0}' 的列舉值進行操作,因為 '{0}' 為 ref struct。 - - Security attribute '{0}' cannot be applied to an Async method. 安全屬性 '{0}' 無法套用至非同步方法。 @@ -11138,7 +11138,7 @@ You should consider suppressing the warning only if you're sure that you don't w Instance of type '{0}' cannot be used inside a nested function, query expression, iterator block or async method - 類型 '{0}' 的執行個體不可用於巢狀函式、查詢運算式、迭代區塊或非同步方法中 + Instance of type '{0}' cannot be used inside a nested function, query expression, iterator block or async method @@ -12449,16 +12449,6 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ 無法在匿名方法、Lambda 運算式或查詢運算式中使用參考本機 '{0}' - - Iterators cannot have by-reference locals - Iterator 不可有 by-reference local - - - - Async methods cannot have by-reference locals - 非同步方法不可有 by-reference local - - A reference returned by a call to '{0}' cannot be preserved across 'await' or 'yield' boundary. 對 '{0}' 之呼叫所傳回的參考無法在 'await' 或 'yield' 界限間保留。 diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncIteratorTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncIteratorTests.cs index 778817985654a..da3d964d5a24a 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncIteratorTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncIteratorTests.cs @@ -133,7 +133,7 @@ private static void VerifyMissingType(string source, WellKnownType type, params // Instrumentation to investigate CI failure: https://github.com/dotnet/roslyn/issues/34207 private CSharpCompilation CreateCompilationWithAsyncIterator(string source, CSharpCompilationOptions options = null, CSharpParseOptions parseOptions = null) => CreateCompilationWithTasksExtensions(new[] { (CSharpTestSource)CSharpTestBase.Parse(source, filename: "source", parseOptions), CSharpTestBase.Parse(AsyncStreamsTypes, filename: "AsyncStreamsTypes", parseOptions) }, - options: options, parseOptions: parseOptions); + options: options); private CSharpCompilation CreateCompilationWithAsyncIterator(CSharpTestSource source, CSharpCompilationOptions options = null, CSharpParseOptions parseOptions = null) => CreateCompilationWithTasksExtensions(new[] { source, AsyncStreamsTypes }, options: options, parseOptions: parseOptions); @@ -631,15 +631,288 @@ static async System.Threading.Tasks.Task Main() ref struct S { }"; + + var expectedDiagnostics = new[] + { + // source(4,65): error CS0306: The type 'S' may not be used as a type argument + // static async System.Collections.Generic.IAsyncEnumerable M() + Diagnostic(ErrorCode.ERR_BadTypeArgument, "M").WithArguments("S").WithLocation(4, 65) + }; + var comp = CreateCompilationWithAsyncIterator(source, options: TestOptions.DebugExe); + comp.VerifyDiagnostics(expectedDiagnostics); + + comp = CreateCompilationWithAsyncIterator(source, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularNext); + comp.VerifyDiagnostics(expectedDiagnostics); + + comp = CreateCompilationWithAsyncIterator(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular12); comp.VerifyDiagnostics( // source(4,65): error CS0306: The type 'S' may not be used as a type argument // static async System.Collections.Generic.IAsyncEnumerable M() Diagnostic(ErrorCode.ERR_BadTypeArgument, "M").WithArguments("S").WithLocation(4, 65), - // source(11,24): error CS4012: Parameters or locals of type 'S' cannot be declared in async methods or async lambda expressions. + // source(11,24): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // await foreach (var s in M()) - Diagnostic(ErrorCode.ERR_BadSpecialByRefLocal, "var").WithArguments("S").WithLocation(11, 24) - ); + Diagnostic(ErrorCode.ERR_FeatureInPreview, "var").WithArguments("ref and unsafe in async and iterator methods").WithLocation(11, 24)); + } + + [Fact] + public void RefStructElementType_NonGeneric() + { + string source = """ + using System.Threading.Tasks; + + class C + { + public E GetAsyncEnumerator() => new E(); + static async Task Main() + { + await foreach (var s in new C()) + { + System.Console.Write(s.F); + } + } + } + class E + { + bool _done; + public S Current => new S { F = 123 }; + public async Task MoveNextAsync() + { + await Task.Yield(); + return !_done ? (_done = true) : false; + } + } + ref struct S + { + public int F; + } + """; + + var comp = CreateCompilationWithAsyncIterator(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular12); + comp.VerifyDiagnostics( + // source(8,24): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // await foreach (var s in new C()) + Diagnostic(ErrorCode.ERR_FeatureInPreview, "var").WithArguments("ref and unsafe in async and iterator methods").WithLocation(8, 24)); + + comp = CreateCompilationWithAsyncIterator(source, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularNext); + comp.VerifyEmitDiagnostics(); + + comp = CreateCompilationWithAsyncIterator(source, options: TestOptions.DebugExe); + var verifier = CompileAndVerify(comp, expectedOutput: "123", verify: Verification.FailsILVerify); + verifier.VerifyDiagnostics(); + verifier.VerifyIL("C.
d__1.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext", """ + { + // Code size 238 (0xee) + .maxstack 3 + .locals init (int V_0, + S V_1, //s + System.Runtime.CompilerServices.TaskAwaiter V_2, + C.
d__1 V_3, + System.Exception V_4) + IL_0000: ldarg.0 + IL_0001: ldfld "int C.
d__1.<>1__state" + IL_0006: stloc.0 + .try + { + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0012 + IL_000a: br.s IL_000c + IL_000c: ldloc.0 + IL_000d: ldc.i4.1 + IL_000e: beq.s IL_0014 + IL_0010: br.s IL_0016 + IL_0012: br.s IL_0082 + IL_0014: br.s IL_0082 + IL_0016: nop + IL_0017: nop + IL_0018: ldarg.0 + IL_0019: newobj "C..ctor()" + IL_001e: call "E C.GetAsyncEnumerator()" + IL_0023: stfld "E C.
d__1.<>s__1" + IL_0028: br.s IL_0044 + IL_002a: ldarg.0 + IL_002b: ldfld "E C.
d__1.<>s__1" + IL_0030: callvirt "S E.Current.get" + IL_0035: stloc.1 + IL_0036: nop + IL_0037: ldloc.1 + IL_0038: ldfld "int S.F" + IL_003d: call "void System.Console.Write(int)" + IL_0042: nop + IL_0043: nop + IL_0044: ldarg.0 + IL_0045: ldfld "E C.
d__1.<>s__1" + IL_004a: callvirt "System.Threading.Tasks.Task E.MoveNextAsync()" + IL_004f: callvirt "System.Runtime.CompilerServices.TaskAwaiter System.Threading.Tasks.Task.GetAwaiter()" + IL_0054: stloc.2 + IL_0055: ldloca.s V_2 + IL_0057: call "bool System.Runtime.CompilerServices.TaskAwaiter.IsCompleted.get" + IL_005c: brtrue.s IL_009e + IL_005e: ldarg.0 + IL_005f: ldc.i4.0 + IL_0060: dup + IL_0061: stloc.0 + IL_0062: stfld "int C.
d__1.<>1__state" + IL_0067: ldarg.0 + IL_0068: ldloc.2 + IL_0069: stfld "System.Runtime.CompilerServices.TaskAwaiter C.
d__1.<>u__1" + IL_006e: ldarg.0 + IL_006f: stloc.3 + IL_0070: ldarg.0 + IL_0071: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.
d__1.<>t__builder" + IL_0076: ldloca.s V_2 + IL_0078: ldloca.s V_3 + IL_007a: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompleted, C.
d__1>(ref System.Runtime.CompilerServices.TaskAwaiter, ref C.
d__1)" + IL_007f: nop + IL_0080: leave.s IL_00ed + IL_0082: ldarg.0 + IL_0083: ldfld "System.Runtime.CompilerServices.TaskAwaiter C.
d__1.<>u__1" + IL_0088: stloc.2 + IL_0089: ldarg.0 + IL_008a: ldflda "System.Runtime.CompilerServices.TaskAwaiter C.
d__1.<>u__1" + IL_008f: initobj "System.Runtime.CompilerServices.TaskAwaiter" + IL_0095: ldarg.0 + IL_0096: ldc.i4.m1 + IL_0097: dup + IL_0098: stloc.0 + IL_0099: stfld "int C.
d__1.<>1__state" + IL_009e: ldarg.0 + IL_009f: ldloca.s V_2 + IL_00a1: call "bool System.Runtime.CompilerServices.TaskAwaiter.GetResult()" + IL_00a6: stfld "bool C.
d__1.<>s__2" + IL_00ab: ldarg.0 + IL_00ac: ldfld "bool C.
d__1.<>s__2" + IL_00b1: brtrue IL_002a + IL_00b6: ldarg.0 + IL_00b7: ldnull + IL_00b8: stfld "E C.
d__1.<>s__1" + IL_00bd: leave.s IL_00d9 + } + catch System.Exception + { + IL_00bf: stloc.s V_4 + IL_00c1: ldarg.0 + IL_00c2: ldc.i4.s -2 + IL_00c4: stfld "int C.
d__1.<>1__state" + IL_00c9: ldarg.0 + IL_00ca: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.
d__1.<>t__builder" + IL_00cf: ldloc.s V_4 + IL_00d1: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)" + IL_00d6: nop + IL_00d7: leave.s IL_00ed + } + IL_00d9: ldarg.0 + IL_00da: ldc.i4.s -2 + IL_00dc: stfld "int C.
d__1.<>1__state" + IL_00e1: ldarg.0 + IL_00e2: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.
d__1.<>t__builder" + IL_00e7: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetResult()" + IL_00ec: nop + IL_00ed: ret + } + """); + } + + [Fact] + public void RefStructElementType_NonGeneric_AwaitAfter() + { + string source = """ + using System.Threading.Tasks; + + class C + { + public E GetAsyncEnumerator() => new E(); + static async Task Main() + { + await foreach (var s in new C()) + { + System.Console.Write(s.F); + await Task.Yield(); + } + } + } + class E + { + bool _done; + public S Current => new S { F = 123 }; + public async Task MoveNextAsync() + { + await Task.Yield(); + return !_done ? (_done = true) : false; + } + } + ref struct S + { + public int F; + } + """; + + var comp = CreateCompilationWithAsyncIterator(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular12); + comp.VerifyDiagnostics( + // source(8,24): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // await foreach (var s in new C()) + Diagnostic(ErrorCode.ERR_FeatureInPreview, "var").WithArguments("ref and unsafe in async and iterator methods").WithLocation(8, 24)); + + comp = CreateCompilationWithAsyncIterator(source, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularNext); + comp.VerifyEmitDiagnostics(); + + comp = CreateCompilationWithAsyncIterator(source, options: TestOptions.DebugExe); + var verifier = CompileAndVerify(comp, expectedOutput: "123", verify: Verification.FailsILVerify); + verifier.VerifyDiagnostics(); + } + + [Fact] + public void RefStructElementType_NonGeneric_AwaitBefore() + { + string source = """ + using System.Threading.Tasks; + + class C + { + public E GetAsyncEnumerator() => new E(); + static async Task Main() + { + await foreach (var s in new C()) + { + await Task.Yield(); + System.Console.Write(s.F); + } + } + } + class E + { + bool _done; + public S Current => new S { F = 123 }; + public async Task MoveNextAsync() + { + await Task.Yield(); + return !_done ? (_done = true) : false; + } + } + ref struct S + { + public int F; + } + """; + + var comp = CreateCompilationWithAsyncIterator(source, parseOptions: TestOptions.Regular12); + comp.VerifyDiagnostics( + // source(8,24): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // await foreach (var s in new C()) + Diagnostic(ErrorCode.ERR_FeatureInPreview, "var").WithArguments("ref and unsafe in async and iterator methods").WithLocation(8, 24)); + + var expectedDiagnostics = new[] + { + // source(11,34): error CS4007: Instance of type 'S' cannot be preserved across 'await' or 'yield' boundary. + // System.Console.Write(s.F); + Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "s.F").WithArguments("S").WithLocation(11, 34) + }; + + comp = CreateCompilationWithAsyncIterator(source, parseOptions: TestOptions.RegularNext); + comp.VerifyEmitDiagnostics(expectedDiagnostics); + + comp = CreateCompilationWithAsyncIterator(source); + comp.VerifyEmitDiagnostics(expectedDiagnostics); } [Fact] diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncSpillTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncSpillTests.cs index 0a7f649ff7d64..999bf6667331d 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncSpillTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncSpillTests.cs @@ -3789,9 +3789,11 @@ static async Task Main() var comp = CreateCompilationWithMscorlibAndSpan(source, options: options); comp.VerifyDiagnostics(); comp.VerifyEmitDiagnostics( - // (9,66): error CS4007: 'await' cannot be used in an expression containing the type 'System.Span' - // await Async1(F1(), G(F2(), stackalloc int[] { 1, 2, 3 }, await F3())); - Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "await F3()").WithArguments("System.Span").WithLocation(9, 66) + // (8,5): error CS4007: Instance of type 'System.Span' cannot be preserved across 'await' or 'yield' boundary. + // { + Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, @"{ + await Async1(F1(), G(F2(), stackalloc int[] { 1, 2, 3 }, await F3())); + }").WithArguments("System.Span").WithLocation(8, 5) ); } } @@ -3897,16 +3899,16 @@ public ref struct S public bool P2 => true; } "; - CreateCompilation(source, options: TestOptions.DebugDll).VerifyDiagnostics().VerifyEmitDiagnostics( - // (9,17): error CS4013: Instance of type 'S' cannot be used inside a nested function, query expression, iterator block or async method - // Q { F: { P1: true } } when await c => r, // error: cached Q.F is alive - Diagnostic(ErrorCode.ERR_SpecialByRefInLambda, "F").WithArguments("S").WithLocation(9, 17) - ); - CreateCompilation(source, options: TestOptions.ReleaseDll).VerifyDiagnostics().VerifyEmitDiagnostics( - // (9,17): error CS4013: Instance of type 'S' cannot be used inside a nested function, query expression, iterator block or async method + + var expectedDiagnostics = new[] + { + // (9,17): error CS4007: Instance of type 'S' cannot be preserved across 'await' or 'yield' boundary. // Q { F: { P1: true } } when await c => r, // error: cached Q.F is alive - Diagnostic(ErrorCode.ERR_SpecialByRefInLambda, "F").WithArguments("S").WithLocation(9, 17) - ); + Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "F").WithArguments("S").WithLocation(9, 17) + }; + + CreateCompilation(source, options: TestOptions.DebugDll).VerifyDiagnostics().VerifyEmitDiagnostics(expectedDiagnostics); + CreateCompilation(source, options: TestOptions.ReleaseDll).VerifyDiagnostics().VerifyEmitDiagnostics(expectedDiagnostics); } [Fact] diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAwaitForeachTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAwaitForeachTests.cs index bce2519fce4d0..9a099be01840b 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAwaitForeachTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAwaitForeachTests.cs @@ -1695,12 +1695,26 @@ public System.Threading.Tasks.Task MoveNextAsync() => throw null; public int Current { get => throw null; } } -}"; - var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable); +}" + s_IAsyncEnumerable; + + var comp = CreateCompilationWithTasksExtensions(source, parseOptions: TestOptions.Regular12); comp.VerifyDiagnostics( - // (6,32): error CS8177: Async methods cannot have by-reference locals + // (6,32): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // await foreach (ref var i in new C()) - Diagnostic(ErrorCode.ERR_BadAsyncLocalType, "i").WithLocation(6, 32)); + Diagnostic(ErrorCode.ERR_FeatureInPreview, "i").WithArguments("ref and unsafe in async and iterator methods").WithLocation(6, 32)); + + var expectedDiagnostics = new[] + { + // (6,37): error CS1510: A ref or out value must be an assignable variable + // await foreach (ref var i in new C()) + Diagnostic(ErrorCode.ERR_RefLvalueExpected, "new C()").WithLocation(6, 37) + }; + + comp = CreateCompilationWithTasksExtensions(source, parseOptions: TestOptions.RegularNext); + comp.VerifyDiagnostics(expectedDiagnostics); + + comp = CreateCompilationWithTasksExtensions(source); + comp.VerifyDiagnostics(expectedDiagnostics); var tree = comp.SyntaxTrees.Single(); var model = (SyntaxTreeSemanticModel)comp.GetSemanticModel(tree, ignoreAccessibility: false); @@ -1708,6 +1722,119 @@ public System.Threading.Tasks.Task MoveNextAsync() Assert.Equal(default, model.GetForEachStatementInfo(foreachSyntax)); } + [Theory, CombinatorialData] + public void TestWithPattern_Ref_Iterator([CombinatorialValues(" ", "readonly")] string modifier) + { + var source = $$""" + using System; + using System.Collections.Generic; + using System.Threading.Tasks; + + class C + { + static async Task Main() + { + await foreach (int i in F()) + { + Console.Write(i); + } + } + + static async IAsyncEnumerable F() + { + await foreach (ref {{modifier}} var i in new C()) + { + yield return i; + } + } + + public Enumerator GetAsyncEnumerator(System.Threading.CancellationToken token = default) => new(); + + public sealed class Enumerator + { + private readonly int[] _array = [1, 2, 3]; + private int _index = -1; + public Task MoveNextAsync() + { + if (_index < _array.Length) _index++; + return Task.FromResult(_index < _array.Length); + } + public ref int Current => ref _array[_index]; + } + } + """ + AsyncStreamsTypes; + + var comp = CreateCompilationWithTasksExtensions(source, parseOptions: TestOptions.Regular12); + comp.VerifyDiagnostics( + // (17,41): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // await foreach (ref readonly var i in new C()) + Diagnostic(ErrorCode.ERR_FeatureInPreview, "i").WithArguments("ref and unsafe in async and iterator methods").WithLocation(17, 41)); + + var expectedOutput = "123"; + + comp = CreateCompilationWithTasksExtensions(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularNext); + CompileAndVerify(comp, expectedOutput: expectedOutput).VerifyDiagnostics(); + + comp = CreateCompilationWithTasksExtensions(source, options: TestOptions.ReleaseExe); + CompileAndVerify(comp, expectedOutput: expectedOutput).VerifyDiagnostics(); + } + + [Fact] + public void TestWithPattern_Ref_Iterator_Used() + { + var source = """ + using System.Collections.Generic; + using System.Threading.Tasks; + + class C + { + static async IAsyncEnumerable F() + { + await foreach (ref var i in new C()) + { + yield return i; + M(ref i); + } + } + + static void M(ref int i) { } + + public Enumerator GetAsyncEnumerator(System.Threading.CancellationToken token = default) => new(); + + public sealed class Enumerator + { + private readonly int[] _array = [1, 2, 3]; + private int _index = -1; + public Task MoveNextAsync() + { + if (_index < _array.Length) _index++; + return Task.FromResult(_index < _array.Length); + } + public ref int Current => ref _array[_index]; + } + } + """ + AsyncStreamsTypes; + + var comp = CreateCompilationWithTasksExtensions(source, parseOptions: TestOptions.Regular12); + comp.VerifyDiagnostics( + // (8,32): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // await foreach (ref var i in new C()) + Diagnostic(ErrorCode.ERR_FeatureInPreview, "i").WithArguments("ref and unsafe in async and iterator methods").WithLocation(8, 32)); + + var expectedDiagnostics = new[] + { + // (11,19): error CS9217: A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + // M(ref i); + Diagnostic(ErrorCode.ERR_RefLocalAcrossAwait, "i").WithLocation(11, 19) + }; + + comp = CreateCompilationWithTasksExtensions(source, parseOptions: TestOptions.RegularNext); + comp.VerifyEmitDiagnostics(expectedDiagnostics); + + comp = CreateCompilationWithTasksExtensions(source); + comp.VerifyEmitDiagnostics(expectedDiagnostics); + } + [Fact] public void TestWithPattern_PointerType() { @@ -1934,6 +2061,101 @@ public S(int i) CompileAndVerify(comp, expectedOutput: "1 2 Done"); } + [Fact] + public void TestWithPattern_RefStructEnumerator() + { + var source = """ + using System.Threading.Tasks; + public class C + { + public static async Task Main() + { + await foreach (var s in new C()) + { + } + } + public Enumerator GetAsyncEnumerator() => new Enumerator(); + public ref struct Enumerator + { + public int Current => 0; + public Task MoveNextAsync() => throw null; + } + } + """; + + var expectedDiagnostics = new[] + { + // (6,15): error CS8344: foreach statement cannot operate on enumerators of type 'C.Enumerator' in async or iterator methods because 'C.Enumerator' is a ref struct. + // await foreach (var s in new C()) + Diagnostic(ErrorCode.ERR_BadSpecialByRefIterator, "foreach").WithArguments("C.Enumerator").WithLocation(6, 15) + }; + + CreateCompilation(source, parseOptions: TestOptions.Regular12).VerifyDiagnostics(expectedDiagnostics); + CreateCompilation(source, parseOptions: TestOptions.RegularNext).VerifyDiagnostics(expectedDiagnostics); + CreateCompilation(source).VerifyDiagnostics(expectedDiagnostics); + } + + [Fact] + public void TestWithPattern_RefStructCurrent() + { + var source = """ + using System; + using System.Threading.Tasks; + public class C + { + public static async Task Main() + { + await foreach (var s in new C()) + { + Console.Write($"{s.ToString()} "); + } + Console.Write("Done"); + } + public Enumerator GetAsyncEnumerator() => new Enumerator(); + public sealed class Enumerator : IAsyncDisposable + { + int i = 0; + public S Current => new S(i); + public async Task MoveNextAsync() + { + i++; + return await Task.FromResult(i < 3); + } + public async ValueTask DisposeAsync() + { + await Task.Yield(); + } + } + } + public ref struct S + { + int i; + public S(int i) + { + this.i = i; + } + public override string ToString() => i.ToString(); + } + """ + s_IAsyncEnumerable; + + var expectedDiagnostics = new[] + { + // (7,24): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // await foreach (var s in new C()) + Diagnostic(ErrorCode.ERR_FeatureInPreview, "var").WithArguments("ref and unsafe in async and iterator methods").WithLocation(7, 24) + }; + + CreateCompilationWithTasksExtensions(source, parseOptions: TestOptions.Regular12).VerifyDiagnostics(expectedDiagnostics); + + var expectedOutput = "1 2 Done"; + + var comp = CreateCompilationWithTasksExtensions(source, parseOptions: TestOptions.RegularNext, options: TestOptions.ReleaseExe); + CompileAndVerify(comp, expectedOutput: expectedOutput, verify: Verification.FailsILVerify).VerifyDiagnostics(); + + comp = CreateCompilationWithTasksExtensions(source, options: TestOptions.ReleaseExe); + CompileAndVerify(comp, expectedOutput: expectedOutput, verify: Verification.FailsILVerify).VerifyDiagnostics(); + } + [Fact] public void TestWithPattern_RefReturningCurrent() { diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/InlineArrayTests.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/InlineArrayTests.cs index 1963a7532e9f2..3c90e1f58fc4f 100644 --- a/src/Compilers/CSharp/Test/Emit2/Semantics/InlineArrayTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Semantics/InlineArrayTests.cs @@ -4691,9 +4691,12 @@ static async Task FromResult(T r) "; var comp = CreateCompilation(src + Buffer10Definition, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseExe); comp.VerifyEmitDiagnostics( - // (24,22): error CS4007: 'await' cannot be used in an expression containing the type 'System.ReadOnlySpan>' - // [Get01()][await FromResult(Get02(x))]; - Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "await FromResult(Get02(x))").WithArguments("System.ReadOnlySpan>").WithLocation(24, 22) + // (20,12): error CS4007: Instance of type 'System.ReadOnlySpan>' cannot be preserved across 'await' or 'yield' boundary. + // => MemoryMarshal.CreateReadOnlySpan( + Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, @"MemoryMarshal.CreateReadOnlySpan( + ref Unsafe.As>, Buffer10>( + ref Unsafe.AsRef(in GetC(x).F)), + 10)").WithArguments("System.ReadOnlySpan>").WithLocation(20, 12) ); } @@ -4743,9 +4746,12 @@ static async Task FromResult(T r) "; var comp = CreateCompilation(src + Buffer10Definition, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseExe); comp.VerifyEmitDiagnostics( - // (24,13): error CS4007: 'await' cannot be used in an expression containing the type 'System.ReadOnlySpan' - // [await FromResult(Get02(x))]; - Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "await FromResult(Get02(x))").WithArguments("System.ReadOnlySpan").WithLocation(24, 13) + // (20,12): error CS4007: Instance of type 'System.ReadOnlySpan' cannot be preserved across 'await' or 'yield' boundary. + // => MemoryMarshal.CreateReadOnlySpan( + Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, @"MemoryMarshal.CreateReadOnlySpan( + ref Unsafe.As, int>( + ref Unsafe.AsRef(in GetC(x).F[Get01()])), + 10)").WithArguments("System.ReadOnlySpan").WithLocation(20, 12) ); } @@ -20154,30 +20160,45 @@ .locals init (int V_0, CompileAndVerify(comp, expectedOutput: " 0 1 2 3", verify: Verification.Fails).VerifyDiagnostics(); } - [Fact] + [ConditionalFact(typeof(CoreClrOnly))] public void Foreach_InAsync_03() { var src = @" class Program { - static async void Test() + static Buffer4 s_buffer; + + static async System.Threading.Tasks.Task Main() { + s_buffer[1] = 3; + foreach (ref int y in GetBuffer()) { + y *= y; + System.Console.Write(y); } await System.Threading.Tasks.Task.Yield(); + + System.Console.Write(s_buffer[1]); } - static ref Buffer4 GetBuffer() => throw null; + static ref Buffer4 GetBuffer() => ref s_buffer; } -"; - var comp = CreateCompilation(src + Buffer4Definition, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseDll); - comp.VerifyDiagnostics( - // (6,26): error CS8177: Async methods cannot have by-reference locals +" + Buffer4Definition; + + CreateCompilation(src, parseOptions: TestOptions.Regular12, targetFramework: TargetFramework.Net80).VerifyDiagnostics( + // (10,26): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // foreach (ref int y in GetBuffer()) - Diagnostic(ErrorCode.ERR_BadAsyncLocalType, "y").WithLocation(6, 26) - ); + Diagnostic(ErrorCode.ERR_FeatureInPreview, "y").WithArguments("ref and unsafe in async and iterator methods").WithLocation(10, 26)); + + var expectedOutput = "09009"; + + CompileAndVerify(src, parseOptions: TestOptions.RegularNext, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseExe, + expectedOutput: expectedOutput).VerifyDiagnostics(); + + CompileAndVerify(src, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseExe, + expectedOutput: expectedOutput).VerifyDiagnostics(); } [Fact] @@ -20598,30 +20619,48 @@ .locals init (int V_0, CompileAndVerify(comp, expectedOutput: " 0 1 2 3", verify: Verification.Fails).VerifyDiagnostics(); } - [Fact] + [ConditionalFact(typeof(CoreClrOnly))] public void Foreach_InAsync_07() { var src = @" class Program { - static async void Test() + static Buffer4 s_buffer; + + static async System.Threading.Tasks.Task Main() { + s_buffer[1] = 3; + + int i = 0; foreach (ref readonly int y in GetBuffer()) { + System.Console.Write(y); + s_buffer[i++]++; + System.Console.Write(y); + System.Console.Write(' '); } await System.Threading.Tasks.Task.Yield(); + + System.Console.Write(s_buffer[1]); } - static ref readonly Buffer4 GetBuffer() => throw null; + static ref readonly Buffer4 GetBuffer() => ref s_buffer; } -"; - var comp = CreateCompilation(src + Buffer4Definition, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseDll); - comp.VerifyDiagnostics( - // (6,35): error CS8177: Async methods cannot have by-reference locals +" + Buffer4Definition; + + CreateCompilation(src, parseOptions: TestOptions.Regular12, targetFramework: TargetFramework.Net80).VerifyDiagnostics( + // (11,35): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // foreach (ref readonly int y in GetBuffer()) - Diagnostic(ErrorCode.ERR_BadAsyncLocalType, "y").WithLocation(6, 35) - ); + Diagnostic(ErrorCode.ERR_FeatureInPreview, "y").WithArguments("ref and unsafe in async and iterator methods").WithLocation(11, 35)); + + var expectedOutput = "01 34 01 01 4"; + + CompileAndVerify(src, parseOptions: TestOptions.RegularNext, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseExe, + verify: Verification.FailsILVerify, expectedOutput: expectedOutput).VerifyDiagnostics(); + + CompileAndVerify(src, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseExe, + verify: Verification.FailsILVerify, expectedOutput: expectedOutput).VerifyDiagnostics(); } [Fact] @@ -20798,132 +20837,209 @@ .locals init (int V_0, } [ConditionalFact(typeof(CoreClrOnly))] - public void Foreach_InIterator_01() + public void Foreach_InAsync_10() { var src = @" class Program { - static private Buffer4 F = default; - private static int index = 0; + static Buffer4 s_buffer; - static void Main() + static async System.Threading.Tasks.Task Main() { - foreach (var a in Test()) - {} + s_buffer[1] = 3; + + ref Buffer4 buffer = ref GetBuffer(); + foreach (ref int y in buffer) + { + y *= y; + System.Console.Write(y); + } + + await System.Threading.Tasks.Task.Yield(); + + System.Console.Write(s_buffer[1]); } - static System.Collections.Generic.IEnumerable Test() + static ref Buffer4 GetBuffer() => ref s_buffer; +} +" + Buffer4Definition; + + CreateCompilation(src, parseOptions: TestOptions.Regular12, targetFramework: TargetFramework.Net80).VerifyDiagnostics( + // (10,26): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // ref Buffer4 buffer = ref GetBuffer(); + Diagnostic(ErrorCode.ERR_FeatureInPreview, "buffer").WithArguments("ref and unsafe in async and iterator methods").WithLocation(10, 26), + // (11,26): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // foreach (ref int y in buffer) + Diagnostic(ErrorCode.ERR_FeatureInPreview, "y").WithArguments("ref and unsafe in async and iterator methods").WithLocation(11, 26)); + + var expectedOutput = "09009"; + + CompileAndVerify(src, parseOptions: TestOptions.RegularNext, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseExe, + expectedOutput: expectedOutput).VerifyDiagnostics(); + + CompileAndVerify(src, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseExe, + expectedOutput: expectedOutput).VerifyDiagnostics(); + } + + [Fact] + public void Foreach_InAsync_11() + { + var src = @" +class Program +{ + static Buffer4 s_buffer; + + static async System.Threading.Tasks.Task Main() { - yield return -1; + s_buffer[1] = 3; - foreach (var y in GetBuffer()) + foreach (ref int y in GetBuffer()) { - Increment(); - System.Console.Write(' '); + await System.Threading.Tasks.Task.Yield(); + y *= y; System.Console.Write(y); } - yield return -2; - } + await System.Threading.Tasks.Task.Yield(); - static ref Buffer4 GetBuffer() - { - System.Console.Write(-1); - return ref F; + System.Console.Write(s_buffer[1]); } - static void Increment() + static ref Buffer4 GetBuffer() => ref s_buffer; +} +" + Buffer4Definition; + + CreateCompilation(src, parseOptions: TestOptions.Regular12, targetFramework: TargetFramework.Net80).VerifyDiagnostics( + // (10,26): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // foreach (ref int y in GetBuffer()) + Diagnostic(ErrorCode.ERR_FeatureInPreview, "y").WithArguments("ref and unsafe in async and iterator methods").WithLocation(10, 26)); + + var expectedDiagnostics = new[] + { + // (13,13): error CS9217: A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + // y *= y; + Diagnostic(ErrorCode.ERR_RefLocalAcrossAwait, "y").WithLocation(13, 13), + // (13,18): error CS9217: A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + // y *= y; + Diagnostic(ErrorCode.ERR_RefLocalAcrossAwait, "y").WithLocation(13, 18), + // (14,34): error CS9217: A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + // System.Console.Write(y); + Diagnostic(ErrorCode.ERR_RefLocalAcrossAwait, "y").WithLocation(14, 34) + }; + + CreateCompilation(src, parseOptions: TestOptions.RegularNext, targetFramework: TargetFramework.Net80).VerifyEmitDiagnostics(expectedDiagnostics); + + CreateCompilation(src, targetFramework: TargetFramework.Net80).VerifyEmitDiagnostics(expectedDiagnostics); + } + + [Fact] + public void Foreach_InAsync_12() + { + var src = @" +class Program +{ + static Buffer4 s_buffer; + + static async System.Threading.Tasks.Task Main() { - index++; + s_buffer[1] = 3; - if (index < 4) + foreach (ref int y in GetBuffer()) { - F[index] = index; + y *= y; + System.Console.Write(y); + await System.Threading.Tasks.Task.Yield(); } + + await System.Threading.Tasks.Task.Yield(); + + System.Console.Write(s_buffer[1]); } + + static ref Buffer4 GetBuffer() => ref s_buffer; } -"; - var comp = CreateCompilation(src + Buffer4Definition, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseExe); - var verifier = CompileAndVerify(comp, expectedOutput: "-1 0 1 2 3", verify: Verification.Fails).VerifyDiagnostics(); +" + Buffer4Definition; - verifier.VerifyIL("Program.d__3.System.Collections.IEnumerator.MoveNext", -@" + CreateCompilation(src, parseOptions: TestOptions.Regular12, targetFramework: TargetFramework.Net80).VerifyDiagnostics( + // (10,26): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // foreach (ref int y in GetBuffer()) + Diagnostic(ErrorCode.ERR_FeatureInPreview, "y").WithArguments("ref and unsafe in async and iterator methods").WithLocation(10, 26)); + + var expectedDiagnostics = new[] + { + // (10,9): error CS8178: A reference returned by a call to 'Program.GetBuffer()' cannot be preserved across 'await' or 'yield' boundary. + // foreach (ref int y in GetBuffer()) + Diagnostic(ErrorCode.ERR_RefReturningCallAndAwait, @"foreach (ref int y in GetBuffer()) + { + y *= y; + System.Console.Write(y); + await System.Threading.Tasks.Task.Yield(); + }").WithArguments("Program.GetBuffer()").WithLocation(10, 9) + }; + + CreateCompilation(src, parseOptions: TestOptions.RegularNext, targetFramework: TargetFramework.Net80).VerifyEmitDiagnostics(expectedDiagnostics); + + CreateCompilation(src, targetFramework: TargetFramework.Net80).VerifyEmitDiagnostics(expectedDiagnostics); + } + + [Fact] + public void Foreach_InAsync_13() + { + var src = @" +class Program { - // Code size 126 (0x7e) - .maxstack 2 - .locals init (int V_0, - Buffer4& V_1, - int V_2) - IL_0000: ldarg.0 - IL_0001: ldfld ""int Program.d__3.<>1__state"" - IL_0006: stloc.0 - IL_0007: ldloc.0 - IL_0008: switch ( - IL_001b, - IL_0032, - IL_0075) - IL_0019: ldc.i4.0 - IL_001a: ret - IL_001b: ldarg.0 - IL_001c: ldc.i4.m1 - IL_001d: stfld ""int Program.d__3.<>1__state"" - IL_0022: ldarg.0 - IL_0023: ldc.i4.m1 - IL_0024: stfld ""int Program.d__3.<>2__current"" - IL_0029: ldarg.0 - IL_002a: ldc.i4.1 - IL_002b: stfld ""int Program.d__3.<>1__state"" - IL_0030: ldc.i4.1 - IL_0031: ret - IL_0032: ldarg.0 - IL_0033: ldc.i4.m1 - IL_0034: stfld ""int Program.d__3.<>1__state"" - IL_0039: call ""ref Buffer4 Program.GetBuffer()"" - IL_003e: stloc.1 - IL_003f: ldc.i4.0 - IL_0040: stloc.2 - IL_0041: br.s IL_0060 - IL_0043: ldloc.1 - IL_0044: ldloc.2 - IL_0045: call ""ref int .InlineArrayElementRef, int>(ref Buffer4, int)"" - IL_004a: ldind.i4 - IL_004b: call ""void Program.Increment()"" - IL_0050: ldc.i4.s 32 - IL_0052: call ""void System.Console.Write(char)"" - IL_0057: call ""void System.Console.Write(int)"" - IL_005c: ldloc.2 - IL_005d: ldc.i4.1 - IL_005e: add - IL_005f: stloc.2 - IL_0060: ldloc.2 - IL_0061: ldc.i4.4 - IL_0062: blt.s IL_0043 - IL_0064: ldarg.0 - IL_0065: ldc.i4.s -2 - IL_0067: stfld ""int Program.d__3.<>2__current"" - IL_006c: ldarg.0 - IL_006d: ldc.i4.2 - IL_006e: stfld ""int Program.d__3.<>1__state"" - IL_0073: ldc.i4.1 - IL_0074: ret - IL_0075: ldarg.0 - IL_0076: ldc.i4.m1 - IL_0077: stfld ""int Program.d__3.<>1__state"" - IL_007c: ldc.i4.0 - IL_007d: ret + static Buffer4 s_buffer; + + static async System.Threading.Tasks.Task Main() + { + s_buffer[1] = 3; + + ref Buffer4 buffer = ref GetBuffer(); + foreach (ref int y in buffer) + { + y *= y; + System.Console.Write(y); + await System.Threading.Tasks.Task.Yield(); + } + + await System.Threading.Tasks.Task.Yield(); + + System.Console.Write(s_buffer[1]); + } + + static ref Buffer4 GetBuffer() => ref s_buffer; } -"); - comp = CreateCompilation(src + Buffer4Definition, targetFramework: TargetFramework.Net80, options: TestOptions.DebugExe); - CompileAndVerify(comp, expectedOutput: "-1 0 1 2 3", verify: Verification.Fails).VerifyDiagnostics(); +" + Buffer4Definition; + + CreateCompilation(src, parseOptions: TestOptions.Regular12, targetFramework: TargetFramework.Net80).VerifyDiagnostics( + // (10,26): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // ref Buffer4 buffer = ref GetBuffer(); + Diagnostic(ErrorCode.ERR_FeatureInPreview, "buffer").WithArguments("ref and unsafe in async and iterator methods").WithLocation(10, 26), + // (11,26): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // foreach (ref int y in buffer) + Diagnostic(ErrorCode.ERR_FeatureInPreview, "y").WithArguments("ref and unsafe in async and iterator methods").WithLocation(11, 26)); + + var expectedDiagnostics = new[] + { + // (11,31): error CS9217: A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + // foreach (ref int y in buffer) + Diagnostic(ErrorCode.ERR_RefLocalAcrossAwait, "buffer").WithLocation(11, 31) + }; + + CreateCompilation(src, parseOptions: TestOptions.RegularNext, targetFramework: TargetFramework.Net80).VerifyEmitDiagnostics(expectedDiagnostics); + + CreateCompilation(src, targetFramework: TargetFramework.Net80).VerifyEmitDiagnostics(expectedDiagnostics); } - [ConditionalFact(typeof(CoreClrOnly))] - public void Foreach_InIterator_02() + [Fact] + public void Foreach_InAsync_14() { var src = @" +using System.Threading.Tasks; + class C { - public Buffer4 F = default; + public readonly Buffer4 F = default; } class Program @@ -20933,19 +21049,20 @@ class Program static void Main() { - foreach (var a in Test(c)) - {} + Test(c).Wait(); } - static System.Collections.Generic.IEnumerable Test(C x) + static async Task Test(C x) { - foreach (var y in x.F) + ref readonly Buffer4 f = ref x.F; + foreach (var y in f) { Increment(); System.Console.Write(' '); System.Console.Write(y); - yield return -1; + await Task.Yield(); + await Task.Delay(2); } } @@ -20955,146 +21072,266 @@ static void Increment() if (index < 4) { - c.F[index] = index; + System.Runtime.CompilerServices.Unsafe.AsRef(in c.F)[index] = index; } } } -"; - var comp = CreateCompilation(src + Buffer4Definition, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseExe); - var verifier = CompileAndVerify(comp, expectedOutput: " 0 1 2 3", verify: Verification.Fails).VerifyDiagnostics(); +" + Buffer4Definition; - verifier.VerifyIL("Program.d__3.System.Collections.IEnumerator.MoveNext", -@" + CreateCompilation(src, parseOptions: TestOptions.Regular12, targetFramework: TargetFramework.Net80).VerifyDiagnostics( + // (21,35): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // ref readonly Buffer4 f = ref x.F; + Diagnostic(ErrorCode.ERR_FeatureInPreview, "f").WithArguments("ref and unsafe in async and iterator methods").WithLocation(21, 35)); + + var expectedDiagnostics = new[] + { + // (22,27): error CS9217: A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + // foreach (var y in f) + Diagnostic(ErrorCode.ERR_RefLocalAcrossAwait, "f").WithLocation(22, 27) + }; + + CreateCompilation(src, parseOptions: TestOptions.RegularNext, targetFramework: TargetFramework.Net80).VerifyEmitDiagnostics(expectedDiagnostics); + + CreateCompilation(src, targetFramework: TargetFramework.Net80).VerifyEmitDiagnostics(expectedDiagnostics); + } + + [Fact] + public void Foreach_InAsync_15() + { + var src = @" +class Program { - // Code size 151 (0x97) - .maxstack 3 - .locals init (int V_0) - IL_0000: ldarg.0 - IL_0001: ldfld ""int Program.d__3.<>1__state"" - IL_0006: stloc.0 - IL_0007: ldloc.0 - IL_0008: brfalse.s IL_0010 - IL_000a: ldloc.0 - IL_000b: ldc.i4.1 - IL_000c: beq.s IL_0070 - IL_000e: ldc.i4.0 - IL_000f: ret - IL_0010: ldarg.0 - IL_0011: ldc.i4.m1 - IL_0012: stfld ""int Program.d__3.<>1__state"" - IL_0017: ldarg.0 - IL_0018: ldarg.0 - IL_0019: ldfld ""C Program.d__3.x"" - IL_001e: stfld ""C Program.d__3.<>7__wrap2"" - IL_0023: ldarg.0 - IL_0024: ldfld ""C Program.d__3.<>7__wrap2"" - IL_0029: ldfld ""Buffer4 C.F"" - IL_002e: pop - IL_002f: ldarg.0 - IL_0030: ldc.i4.0 - IL_0031: stfld ""int Program.d__3.<>7__wrap1"" - IL_0036: br.s IL_0085 - IL_0038: ldarg.0 - IL_0039: ldfld ""C Program.d__3.<>7__wrap2"" - IL_003e: ldflda ""Buffer4 C.F"" - IL_0043: ldarg.0 - IL_0044: ldfld ""int Program.d__3.<>7__wrap1"" - IL_0049: call ""ref int .InlineArrayElementRef, int>(ref Buffer4, int)"" - IL_004e: ldind.i4 - IL_004f: call ""void Program.Increment()"" - IL_0054: ldc.i4.s 32 - IL_0056: call ""void System.Console.Write(char)"" - IL_005b: call ""void System.Console.Write(int)"" - IL_0060: ldarg.0 - IL_0061: ldc.i4.m1 - IL_0062: stfld ""int Program.d__3.<>2__current"" - IL_0067: ldarg.0 - IL_0068: ldc.i4.1 - IL_0069: stfld ""int Program.d__3.<>1__state"" - IL_006e: ldc.i4.1 - IL_006f: ret - IL_0070: ldarg.0 - IL_0071: ldc.i4.m1 - IL_0072: stfld ""int Program.d__3.<>1__state"" - IL_0077: ldarg.0 - IL_0078: ldarg.0 - IL_0079: ldfld ""int Program.d__3.<>7__wrap1"" - IL_007e: ldc.i4.1 - IL_007f: add - IL_0080: stfld ""int Program.d__3.<>7__wrap1"" - IL_0085: ldarg.0 - IL_0086: ldfld ""int Program.d__3.<>7__wrap1"" - IL_008b: ldc.i4.4 - IL_008c: blt.s IL_0038 - IL_008e: ldarg.0 - IL_008f: ldnull - IL_0090: stfld ""C Program.d__3.<>7__wrap2"" - IL_0095: ldc.i4.0 - IL_0096: ret + static Buffer4 s_buffer; + + static async System.Threading.Tasks.Task Main() + { + foreach (ref readonly int y in GetBuffer()) + { + System.Console.Write(y); + await System.Threading.Tasks.Task.Yield(); + } + + await System.Threading.Tasks.Task.Yield(); + } + + static ref readonly Buffer4 GetBuffer() => ref s_buffer; } -"); - comp = CreateCompilation(src + Buffer4Definition, targetFramework: TargetFramework.Net80, options: TestOptions.DebugExe); - CompileAndVerify(comp, expectedOutput: " 0 1 2 3", verify: Verification.Fails).VerifyDiagnostics(); +" + Buffer4Definition; + + CreateCompilation(src, parseOptions: TestOptions.Regular12, targetFramework: TargetFramework.Net80).VerifyDiagnostics( + // (8,35): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // foreach (ref readonly int y in GetBuffer()) + Diagnostic(ErrorCode.ERR_FeatureInPreview, "y").WithArguments("ref and unsafe in async and iterator methods").WithLocation(8, 35)); + + var expectedDiagnostics = new[] + { + // (8,9): error CS8178: A reference returned by a call to 'Program.GetBuffer()' cannot be preserved across 'await' or 'yield' boundary. + // foreach (ref readonly int y in GetBuffer()) + Diagnostic(ErrorCode.ERR_RefReturningCallAndAwait, @"foreach (ref readonly int y in GetBuffer()) + { + System.Console.Write(y); + await System.Threading.Tasks.Task.Yield(); + }").WithArguments("Program.GetBuffer()").WithLocation(8, 9) + }; + + CreateCompilation(src, parseOptions: TestOptions.RegularNext, targetFramework: TargetFramework.Net80).VerifyEmitDiagnostics(expectedDiagnostics); + + CreateCompilation(src, targetFramework: TargetFramework.Net80).VerifyEmitDiagnostics(expectedDiagnostics); } [Fact] - public void Foreach_InIterator_03() + public void Foreach_InAsync_16() { var src = @" class Program { - static System.Collections.Generic.IEnumerable Test() + static Buffer4 s_buffer; + + static async System.Threading.Tasks.Task Main() { - foreach (ref int y in GetBuffer()) + foreach (ref readonly int y in GetBuffer()) { + await System.Threading.Tasks.Task.Yield(); + System.Console.Write(y); } - yield return -1; + await System.Threading.Tasks.Task.Yield(); } - static ref Buffer4 GetBuffer() => throw null; + static ref readonly Buffer4 GetBuffer() => ref s_buffer; } -"; - var comp = CreateCompilation(src + Buffer4Definition, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseDll); - comp.VerifyDiagnostics( - // (6,26): error CS8176: Iterators cannot have by-reference locals - // foreach (ref int y in GetBuffer()) - Diagnostic(ErrorCode.ERR_BadIteratorLocalType, "y").WithLocation(6, 26) - ); +" + Buffer4Definition; + + CreateCompilation(src, parseOptions: TestOptions.Regular12, targetFramework: TargetFramework.Net80).VerifyDiagnostics( + // (8,35): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // foreach (ref readonly int y in GetBuffer()) + Diagnostic(ErrorCode.ERR_FeatureInPreview, "y").WithArguments("ref and unsafe in async and iterator methods").WithLocation(8, 35)); + + var expectedDiagnostics = new[] + { + // (11,34): error CS9217: A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + // System.Console.Write(y); + Diagnostic(ErrorCode.ERR_RefLocalAcrossAwait, "y").WithLocation(11, 34) + }; + + CreateCompilation(src, parseOptions: TestOptions.RegularNext, targetFramework: TargetFramework.Net80).VerifyEmitDiagnostics(expectedDiagnostics); + + CreateCompilation(src, targetFramework: TargetFramework.Net80).VerifyEmitDiagnostics(expectedDiagnostics); + } + + [ConditionalFact(typeof(CoreClrOnly))] + public void Foreach_InAsync_17() + { + var src = @" +using System.Threading.Tasks; + +class C +{ + public readonly Buffer4 F = default; +} + +class Program +{ + private static C c = new C(); + private static int index = 0; + + static void Main() + { + Test(c).Wait(); + } + + static async Task Test(C x) + { + foreach (ref readonly int y in x.F) + { + Increment(); + System.Console.Write(' '); + System.Console.Write(y); + + await Task.Yield(); + await Task.Delay(2); + } + } + + static void Increment() + { + index++; + + if (index < 4) + { + System.Runtime.CompilerServices.Unsafe.AsRef(in c.F)[index] = index; + } + } +} +" + Buffer4Definition; + var expectedOutput = " 0 1 2 3"; + var comp = CreateCompilation(src, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseExe); + var verifier = CompileAndVerify(comp, expectedOutput: expectedOutput, verify: Verification.Fails).VerifyDiagnostics(); + comp = CreateCompilation(src, targetFramework: TargetFramework.Net80, options: TestOptions.DebugExe); + CompileAndVerify(comp, expectedOutput: expectedOutput, verify: Verification.Fails).VerifyDiagnostics(); } [Fact] - public void Foreach_InIterator_04() + public void Foreach_InAsync_18() { var src = @" +using System.Threading.Tasks; + +class C +{ + public readonly Buffer4 F = default; +} + class Program { - static System.Collections.Generic.IEnumerable Test() + static async Task Test(C x) { - foreach (int y in GetBuffer()) + foreach (ref readonly int y in x.F) { - yield return -1; + await Task.Yield(); + System.Console.Write(y); } } +} +" + Buffer4Definition; - static ref Buffer4 GetBuffer() => throw null; + CreateCompilation(src, targetFramework: TargetFramework.Net80, parseOptions: TestOptions.Regular12).VerifyDiagnostics( + // (13,35): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // foreach (ref readonly int y in x.F) + Diagnostic(ErrorCode.ERR_FeatureInPreview, "y").WithArguments("ref and unsafe in async and iterator methods").WithLocation(13, 35)); + + var expectedDiagnostics = new[] + { + // (16,34): error CS9217: A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + // System.Console.Write(y); + Diagnostic(ErrorCode.ERR_RefLocalAcrossAwait, "y").WithLocation(16, 34) + }; + + CreateCompilation(src, targetFramework: TargetFramework.Net80, parseOptions: TestOptions.RegularNext).VerifyEmitDiagnostics(expectedDiagnostics); + CreateCompilation(src, targetFramework: TargetFramework.Net80).VerifyEmitDiagnostics(expectedDiagnostics); + } + + [Fact] + public void Foreach_InAsync_19() + { + var src = @" +using System.Threading.Tasks; + +class C +{ + public readonly Buffer4 F = default; } -"; - var comp = CreateCompilation(src + Buffer4Definition, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseDll); - comp.VerifyEmitDiagnostics( - // (6,9): error CS8178: A reference returned by a call to 'Program.GetBuffer()' cannot be preserved across 'await' or 'yield' boundary. - // foreach (int y in GetBuffer()) - Diagnostic(ErrorCode.ERR_RefReturningCallAndAwait, - @"foreach (int y in GetBuffer()) +class Program +{ + static async Task Test(C x) + { + ref readonly Buffer4 f = ref x.F; + + foreach (var i in f) System.Console.Write(i); + + foreach (var y in f) { - yield return -1; - }").WithArguments("Program.GetBuffer()").WithLocation(6, 9) - ); + System.Console.Write(y); + await Task.Yield(); + } + + foreach (var j in f) System.Console.Write(j); + + foreach (var z in f) + { + System.Console.Write(z); + await Task.Yield(); + } + } +} +" + Buffer4Definition; + + CreateCompilation(src, parseOptions: TestOptions.Regular12, targetFramework: TargetFramework.Net80).VerifyDiagnostics( + // (13,35): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // ref readonly Buffer4 f = ref x.F; + Diagnostic(ErrorCode.ERR_FeatureInPreview, "f").WithArguments("ref and unsafe in async and iterator methods").WithLocation(13, 35)); + + var expectedDiagnostics = new[] + { + // (17,27): error CS9217: A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + // foreach (var y in f) + Diagnostic(ErrorCode.ERR_RefLocalAcrossAwait, "f").WithLocation(17, 27), + // (23,27): error CS9217: A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + // foreach (var j in f) System.Console.Write(j); + Diagnostic(ErrorCode.ERR_RefLocalAcrossAwait, "f").WithLocation(23, 27), + // (25,27): error CS9217: A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + // foreach (var z in f) + Diagnostic(ErrorCode.ERR_RefLocalAcrossAwait, "f").WithLocation(25, 27) + }; + + CreateCompilation(src, parseOptions: TestOptions.RegularNext, targetFramework: TargetFramework.Net80).VerifyEmitDiagnostics(expectedDiagnostics); + + CreateCompilation(src, targetFramework: TargetFramework.Net80).VerifyEmitDiagnostics(expectedDiagnostics); } [ConditionalFact(typeof(CoreClrOnly))] - public void Foreach_InIterator_05() + public void Foreach_InIterator_01() { var src = @" class Program @@ -21122,7 +21359,7 @@ static System.Collections.Generic.IEnumerable Test() yield return -2; } - static ref readonly Buffer4 GetBuffer() + static ref Buffer4 GetBuffer() { System.Console.Write(-1); return ref F; @@ -21174,14 +21411,14 @@ .locals init (int V_0, IL_0032: ldarg.0 IL_0033: ldc.i4.m1 IL_0034: stfld ""int Program.d__3.<>1__state"" - IL_0039: call ""ref readonly Buffer4 Program.GetBuffer()"" + IL_0039: call ""ref Buffer4 Program.GetBuffer()"" IL_003e: stloc.1 IL_003f: ldc.i4.0 IL_0040: stloc.2 IL_0041: br.s IL_0060 IL_0043: ldloc.1 IL_0044: ldloc.2 - IL_0045: call ""ref readonly int .InlineArrayElementRefReadOnly, int>(in Buffer4, int)"" + IL_0045: call ""ref int .InlineArrayElementRef, int>(ref Buffer4, int)"" IL_004a: ldind.i4 IL_004b: call ""void Program.Increment()"" IL_0050: ldc.i4.s 32 @@ -21214,12 +21451,12 @@ .locals init (int V_0, } [ConditionalFact(typeof(CoreClrOnly))] - public void Foreach_InIterator_06() + public void Foreach_InIterator_02() { var src = @" class C { - public readonly Buffer4 F = default; + public Buffer4 F = default; } class Program @@ -21251,7 +21488,7 @@ static void Increment() if (index < 4) { - System.Runtime.CompilerServices.Unsafe.AsRef(in c.F)[index] = index; + c.F[index] = index; } } } @@ -21295,7 +21532,7 @@ .locals init (int V_0) IL_003e: ldflda ""Buffer4 C.F"" IL_0043: ldarg.0 IL_0044: ldfld ""int Program.d__3.<>7__wrap1"" - IL_0049: call ""ref readonly int .InlineArrayElementRefReadOnly, int>(in Buffer4, int)"" + IL_0049: call ""ref int .InlineArrayElementRef, int>(ref Buffer4, int)"" IL_004e: ldind.i4 IL_004f: call ""void Program.Increment()"" IL_0054: ldc.i4.s 32 @@ -21333,34 +21570,57 @@ .locals init (int V_0) CompileAndVerify(comp, expectedOutput: " 0 1 2 3", verify: Verification.Fails).VerifyDiagnostics(); } - [Fact] - public void Foreach_InIterator_07() + [ConditionalFact(typeof(CoreClrOnly))] + public void Foreach_InIterator_03() { var src = @" class Program { + static Buffer4 s_buffer; + + static void Main() + { + s_buffer[2] = 3; + + foreach (int x in Test()) + { + System.Console.Write(x); + } + } + static System.Collections.Generic.IEnumerable Test() { - foreach (ref readonly int y in GetBuffer()) + foreach (ref int y in GetBuffer()) { + y *= y; + System.Console.Write(y); } yield return -1; + + System.Console.Write(s_buffer[2]); } - static ref readonly Buffer4 GetBuffer() => throw null; + static ref Buffer4 GetBuffer() => ref s_buffer; } -"; - var comp = CreateCompilation(src + Buffer4Definition, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseDll); - comp.VerifyDiagnostics( - // (6,35): error CS8176: Iterators cannot have by-reference locals - // foreach (ref readonly int y in GetBuffer()) - Diagnostic(ErrorCode.ERR_BadIteratorLocalType, "y").WithLocation(6, 35) - ); +" + Buffer4Definition; + + CreateCompilation(src, parseOptions: TestOptions.Regular12, targetFramework: TargetFramework.Net80).VerifyDiagnostics( + // (18,26): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // foreach (ref int y in GetBuffer()) + Diagnostic(ErrorCode.ERR_FeatureInPreview, "y").WithArguments("ref and unsafe in async and iterator methods").WithLocation(18, 26)); + + var expectedOutput = "0090-19"; + + CompileAndVerify(src, parseOptions: TestOptions.RegularNext, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseExe, + expectedOutput: expectedOutput).VerifyDiagnostics(); + + CompileAndVerify(src, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseExe, + expectedOutput: expectedOutput).VerifyDiagnostics(); } [Fact] - public void Foreach_InIterator_08() + public void Foreach_InIterator_04() { var src = @" class Program @@ -21373,7 +21633,7 @@ static System.Collections.Generic.IEnumerable Test() } } - static ref readonly Buffer4 GetBuffer() => throw null; + static ref Buffer4 GetBuffer() => throw null; } "; var comp = CreateCompilation(src + Buffer4Definition, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseDll); @@ -21390,11 +21650,14 @@ static System.Collections.Generic.IEnumerable Test() } [ConditionalFact(typeof(CoreClrOnly))] - public void Foreach_InIterator_09() + public void Foreach_InIterator_05() { var src = @" class Program { + static private Buffer4 F = default; + private static int index = 0; + static void Main() { foreach (var a in Test()) @@ -21403,92 +21666,929 @@ static void Main() static System.Collections.Generic.IEnumerable Test() { + yield return -1; + foreach (var y in GetBuffer()) { + Increment(); System.Console.Write(' '); System.Console.Write(y); - yield return -1; } + + yield return -2; } - static Buffer4 GetBuffer() + static ref readonly Buffer4 GetBuffer() { - Buffer4 x = default; - x[0] = 111; - x[1] = 112; - x[2] = 113; - x[3] = 114; - System.Console.Write(-1); - return x; + return ref F; + } + + static void Increment() + { + index++; + + if (index < 4) + { + F[index] = index; + } } } "; var comp = CreateCompilation(src + Buffer4Definition, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseExe); - var verifier = CompileAndVerify(comp, expectedOutput: "-1 111 112 113 114").VerifyDiagnostics(); + var verifier = CompileAndVerify(comp, expectedOutput: "-1 0 1 2 3", verify: Verification.Fails).VerifyDiagnostics(); - verifier.VerifyIL("Program.d__1.System.Collections.IEnumerator.MoveNext", + verifier.VerifyIL("Program.d__3.System.Collections.IEnumerator.MoveNext", @" { - // Code size 121 (0x79) + // Code size 126 (0x7e) + .maxstack 2 + .locals init (int V_0, + Buffer4& V_1, + int V_2) + IL_0000: ldarg.0 + IL_0001: ldfld ""int Program.d__3.<>1__state"" + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: switch ( + IL_001b, + IL_0032, + IL_0075) + IL_0019: ldc.i4.0 + IL_001a: ret + IL_001b: ldarg.0 + IL_001c: ldc.i4.m1 + IL_001d: stfld ""int Program.d__3.<>1__state"" + IL_0022: ldarg.0 + IL_0023: ldc.i4.m1 + IL_0024: stfld ""int Program.d__3.<>2__current"" + IL_0029: ldarg.0 + IL_002a: ldc.i4.1 + IL_002b: stfld ""int Program.d__3.<>1__state"" + IL_0030: ldc.i4.1 + IL_0031: ret + IL_0032: ldarg.0 + IL_0033: ldc.i4.m1 + IL_0034: stfld ""int Program.d__3.<>1__state"" + IL_0039: call ""ref readonly Buffer4 Program.GetBuffer()"" + IL_003e: stloc.1 + IL_003f: ldc.i4.0 + IL_0040: stloc.2 + IL_0041: br.s IL_0060 + IL_0043: ldloc.1 + IL_0044: ldloc.2 + IL_0045: call ""ref readonly int .InlineArrayElementRefReadOnly, int>(in Buffer4, int)"" + IL_004a: ldind.i4 + IL_004b: call ""void Program.Increment()"" + IL_0050: ldc.i4.s 32 + IL_0052: call ""void System.Console.Write(char)"" + IL_0057: call ""void System.Console.Write(int)"" + IL_005c: ldloc.2 + IL_005d: ldc.i4.1 + IL_005e: add + IL_005f: stloc.2 + IL_0060: ldloc.2 + IL_0061: ldc.i4.4 + IL_0062: blt.s IL_0043 + IL_0064: ldarg.0 + IL_0065: ldc.i4.s -2 + IL_0067: stfld ""int Program.d__3.<>2__current"" + IL_006c: ldarg.0 + IL_006d: ldc.i4.2 + IL_006e: stfld ""int Program.d__3.<>1__state"" + IL_0073: ldc.i4.1 + IL_0074: ret + IL_0075: ldarg.0 + IL_0076: ldc.i4.m1 + IL_0077: stfld ""int Program.d__3.<>1__state"" + IL_007c: ldc.i4.0 + IL_007d: ret +} +"); + comp = CreateCompilation(src + Buffer4Definition, targetFramework: TargetFramework.Net80, options: TestOptions.DebugExe); + CompileAndVerify(comp, expectedOutput: "-1 0 1 2 3", verify: Verification.Fails).VerifyDiagnostics(); + } + + [ConditionalFact(typeof(CoreClrOnly))] + public void Foreach_InIterator_06() + { + var src = @" +class C +{ + public readonly Buffer4 F = default; +} + +class Program +{ + private static C c = new C(); + private static int index = 0; + + static void Main() + { + foreach (var a in Test(c)) + {} + } + + static System.Collections.Generic.IEnumerable Test(C x) + { + foreach (var y in x.F) + { + Increment(); + System.Console.Write(' '); + System.Console.Write(y); + + yield return -1; + } + } + + static void Increment() + { + index++; + + if (index < 4) + { + System.Runtime.CompilerServices.Unsafe.AsRef(in c.F)[index] = index; + } + } +} +"; + var comp = CreateCompilation(src + Buffer4Definition, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseExe); + var verifier = CompileAndVerify(comp, expectedOutput: " 0 1 2 3", verify: Verification.Fails).VerifyDiagnostics(); + + verifier.VerifyIL("Program.d__3.System.Collections.IEnumerator.MoveNext", +@" +{ + // Code size 151 (0x97) .maxstack 3 .locals init (int V_0) IL_0000: ldarg.0 - IL_0001: ldfld ""int Program.d__1.<>1__state"" + IL_0001: ldfld ""int Program.d__3.<>1__state"" IL_0006: stloc.0 IL_0007: ldloc.0 IL_0008: brfalse.s IL_0010 IL_000a: ldloc.0 IL_000b: ldc.i4.1 - IL_000c: beq.s IL_0059 + IL_000c: beq.s IL_0070 IL_000e: ldc.i4.0 IL_000f: ret IL_0010: ldarg.0 IL_0011: ldc.i4.m1 - IL_0012: stfld ""int Program.d__1.<>1__state"" + IL_0012: stfld ""int Program.d__3.<>1__state"" IL_0017: ldarg.0 - IL_0018: call ""Buffer4 Program.GetBuffer()"" - IL_001d: stfld ""Buffer4 Program.d__1.<>7__wrap1"" - IL_0022: ldarg.0 - IL_0023: ldc.i4.0 - IL_0024: stfld ""int Program.d__1.<>7__wrap2"" - IL_0029: br.s IL_006e - IL_002b: ldarg.0 - IL_002c: ldflda ""Buffer4 Program.d__1.<>7__wrap1"" - IL_0031: ldarg.0 - IL_0032: ldfld ""int Program.d__1.<>7__wrap2"" - IL_0037: call ""ref readonly int .InlineArrayElementRefReadOnly, int>(in Buffer4, int)"" - IL_003c: ldind.i4 - IL_003d: ldc.i4.s 32 - IL_003f: call ""void System.Console.Write(char)"" - IL_0044: call ""void System.Console.Write(int)"" - IL_0049: ldarg.0 - IL_004a: ldc.i4.m1 - IL_004b: stfld ""int Program.d__1.<>2__current"" - IL_0050: ldarg.0 - IL_0051: ldc.i4.1 - IL_0052: stfld ""int Program.d__1.<>1__state"" - IL_0057: ldc.i4.1 - IL_0058: ret - IL_0059: ldarg.0 - IL_005a: ldc.i4.m1 - IL_005b: stfld ""int Program.d__1.<>1__state"" + IL_0018: ldarg.0 + IL_0019: ldfld ""C Program.d__3.x"" + IL_001e: stfld ""C Program.d__3.<>7__wrap2"" + IL_0023: ldarg.0 + IL_0024: ldfld ""C Program.d__3.<>7__wrap2"" + IL_0029: ldfld ""Buffer4 C.F"" + IL_002e: pop + IL_002f: ldarg.0 + IL_0030: ldc.i4.0 + IL_0031: stfld ""int Program.d__3.<>7__wrap1"" + IL_0036: br.s IL_0085 + IL_0038: ldarg.0 + IL_0039: ldfld ""C Program.d__3.<>7__wrap2"" + IL_003e: ldflda ""Buffer4 C.F"" + IL_0043: ldarg.0 + IL_0044: ldfld ""int Program.d__3.<>7__wrap1"" + IL_0049: call ""ref readonly int .InlineArrayElementRefReadOnly, int>(in Buffer4, int)"" + IL_004e: ldind.i4 + IL_004f: call ""void Program.Increment()"" + IL_0054: ldc.i4.s 32 + IL_0056: call ""void System.Console.Write(char)"" + IL_005b: call ""void System.Console.Write(int)"" IL_0060: ldarg.0 - IL_0061: ldarg.0 - IL_0062: ldfld ""int Program.d__1.<>7__wrap2"" - IL_0067: ldc.i4.1 - IL_0068: add - IL_0069: stfld ""int Program.d__1.<>7__wrap2"" - IL_006e: ldarg.0 - IL_006f: ldfld ""int Program.d__1.<>7__wrap2"" - IL_0074: ldc.i4.4 - IL_0075: blt.s IL_002b - IL_0077: ldc.i4.0 - IL_0078: ret + IL_0061: ldc.i4.m1 + IL_0062: stfld ""int Program.d__3.<>2__current"" + IL_0067: ldarg.0 + IL_0068: ldc.i4.1 + IL_0069: stfld ""int Program.d__3.<>1__state"" + IL_006e: ldc.i4.1 + IL_006f: ret + IL_0070: ldarg.0 + IL_0071: ldc.i4.m1 + IL_0072: stfld ""int Program.d__3.<>1__state"" + IL_0077: ldarg.0 + IL_0078: ldarg.0 + IL_0079: ldfld ""int Program.d__3.<>7__wrap1"" + IL_007e: ldc.i4.1 + IL_007f: add + IL_0080: stfld ""int Program.d__3.<>7__wrap1"" + IL_0085: ldarg.0 + IL_0086: ldfld ""int Program.d__3.<>7__wrap1"" + IL_008b: ldc.i4.4 + IL_008c: blt.s IL_0038 + IL_008e: ldarg.0 + IL_008f: ldnull + IL_0090: stfld ""C Program.d__3.<>7__wrap2"" + IL_0095: ldc.i4.0 + IL_0096: ret } "); comp = CreateCompilation(src + Buffer4Definition, targetFramework: TargetFramework.Net80, options: TestOptions.DebugExe); - CompileAndVerify(comp, expectedOutput: "-1 111 112 113 114").VerifyDiagnostics(); + CompileAndVerify(comp, expectedOutput: " 0 1 2 3", verify: Verification.Fails).VerifyDiagnostics(); + } + + [ConditionalFact(typeof(CoreClrOnly))] + public void Foreach_InIterator_07() + { + var src = @" +class Program +{ + static Buffer4 s_buffer; + + static void Main() + { + s_buffer[2] = 3; + + foreach (int x in Test()) + { + System.Console.Write(x); + } + } + + static System.Collections.Generic.IEnumerable Test() + { + int i = 0; + foreach (ref readonly int y in GetBuffer()) + { + System.Console.Write(y); + s_buffer[i++]++; + System.Console.Write(y); + System.Console.Write(' '); + } + + yield return -1; + + System.Console.Write(s_buffer[2]); + } + + static ref readonly Buffer4 GetBuffer() => ref s_buffer; +} +" + Buffer4Definition; + + CreateCompilation(src, parseOptions: TestOptions.Regular12, targetFramework: TargetFramework.Net80).VerifyDiagnostics( + // (19,35): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // foreach (ref readonly int y in GetBuffer()) + Diagnostic(ErrorCode.ERR_FeatureInPreview, "y").WithArguments("ref and unsafe in async and iterator methods").WithLocation(19, 35)); + + var expectedOutput = "01 01 34 01 -14"; + + CompileAndVerify(src, parseOptions: TestOptions.RegularNext, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseExe, + verify: Verification.FailsILVerify, expectedOutput: expectedOutput).VerifyDiagnostics(); + + CompileAndVerify(src, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseExe, + verify: Verification.FailsILVerify, expectedOutput: expectedOutput).VerifyDiagnostics(); + } + + [Fact] + public void Foreach_InIterator_08() + { + var src = @" +class Program +{ + static System.Collections.Generic.IEnumerable Test() + { + foreach (int y in GetBuffer()) + { + yield return -1; + } + } + + static ref readonly Buffer4 GetBuffer() => throw null; +} +"; + var comp = CreateCompilation(src + Buffer4Definition, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseDll); + + comp.VerifyEmitDiagnostics( + // (6,9): error CS8178: A reference returned by a call to 'Program.GetBuffer()' cannot be preserved across 'await' or 'yield' boundary. + // foreach (int y in GetBuffer()) + Diagnostic(ErrorCode.ERR_RefReturningCallAndAwait, + @"foreach (int y in GetBuffer()) + { + yield return -1; + }").WithArguments("Program.GetBuffer()").WithLocation(6, 9) + ); + } + + [ConditionalFact(typeof(CoreClrOnly))] + public void Foreach_InIterator_09() + { + var src = @" +class Program +{ + static void Main() + { + foreach (var a in Test()) + {} + } + + static System.Collections.Generic.IEnumerable Test() + { + foreach (var y in GetBuffer()) + { + System.Console.Write(' '); + System.Console.Write(y); + yield return -1; + } + } + + static Buffer4 GetBuffer() + { + Buffer4 x = default; + x[0] = 111; + x[1] = 112; + x[2] = 113; + x[3] = 114; + + System.Console.Write(-1); + return x; + } +} +"; + var comp = CreateCompilation(src + Buffer4Definition, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseExe); + var verifier = CompileAndVerify(comp, expectedOutput: "-1 111 112 113 114").VerifyDiagnostics(); + + verifier.VerifyIL("Program.d__1.System.Collections.IEnumerator.MoveNext", +@" +{ + // Code size 121 (0x79) + .maxstack 3 + .locals init (int V_0) + IL_0000: ldarg.0 + IL_0001: ldfld ""int Program.d__1.<>1__state"" + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0010 + IL_000a: ldloc.0 + IL_000b: ldc.i4.1 + IL_000c: beq.s IL_0059 + IL_000e: ldc.i4.0 + IL_000f: ret + IL_0010: ldarg.0 + IL_0011: ldc.i4.m1 + IL_0012: stfld ""int Program.d__1.<>1__state"" + IL_0017: ldarg.0 + IL_0018: call ""Buffer4 Program.GetBuffer()"" + IL_001d: stfld ""Buffer4 Program.d__1.<>7__wrap1"" + IL_0022: ldarg.0 + IL_0023: ldc.i4.0 + IL_0024: stfld ""int Program.d__1.<>7__wrap2"" + IL_0029: br.s IL_006e + IL_002b: ldarg.0 + IL_002c: ldflda ""Buffer4 Program.d__1.<>7__wrap1"" + IL_0031: ldarg.0 + IL_0032: ldfld ""int Program.d__1.<>7__wrap2"" + IL_0037: call ""ref readonly int .InlineArrayElementRefReadOnly, int>(in Buffer4, int)"" + IL_003c: ldind.i4 + IL_003d: ldc.i4.s 32 + IL_003f: call ""void System.Console.Write(char)"" + IL_0044: call ""void System.Console.Write(int)"" + IL_0049: ldarg.0 + IL_004a: ldc.i4.m1 + IL_004b: stfld ""int Program.d__1.<>2__current"" + IL_0050: ldarg.0 + IL_0051: ldc.i4.1 + IL_0052: stfld ""int Program.d__1.<>1__state"" + IL_0057: ldc.i4.1 + IL_0058: ret + IL_0059: ldarg.0 + IL_005a: ldc.i4.m1 + IL_005b: stfld ""int Program.d__1.<>1__state"" + IL_0060: ldarg.0 + IL_0061: ldarg.0 + IL_0062: ldfld ""int Program.d__1.<>7__wrap2"" + IL_0067: ldc.i4.1 + IL_0068: add + IL_0069: stfld ""int Program.d__1.<>7__wrap2"" + IL_006e: ldarg.0 + IL_006f: ldfld ""int Program.d__1.<>7__wrap2"" + IL_0074: ldc.i4.4 + IL_0075: blt.s IL_002b + IL_0077: ldc.i4.0 + IL_0078: ret +} +"); + comp = CreateCompilation(src + Buffer4Definition, targetFramework: TargetFramework.Net80, options: TestOptions.DebugExe); + CompileAndVerify(comp, expectedOutput: "-1 111 112 113 114").VerifyDiagnostics(); + } + + [ConditionalFact(typeof(CoreClrOnly))] + public void Foreach_InIterator_10() + { + var src = @" +class Program +{ + static Buffer4 s_buffer; + + static void Main() + { + s_buffer[2] = 3; + + foreach (int x in Test()) + { + System.Console.Write(x); + } + } + + static System.Collections.Generic.IEnumerable Test() + { + ref Buffer4 buffer = ref GetBuffer(); + foreach (ref int y in buffer) + { + y *= y; + System.Console.Write(y); + } + + yield return -1; + + System.Console.Write(s_buffer[2]); + } + + static ref Buffer4 GetBuffer() => ref s_buffer; +} +" + Buffer4Definition; + + CreateCompilation(src, parseOptions: TestOptions.Regular12, targetFramework: TargetFramework.Net80).VerifyDiagnostics( + // (18,26): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // ref Buffer4 buffer = ref GetBuffer(); + Diagnostic(ErrorCode.ERR_FeatureInPreview, "buffer").WithArguments("ref and unsafe in async and iterator methods").WithLocation(18, 26), + // (19,26): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // foreach (ref int y in buffer) + Diagnostic(ErrorCode.ERR_FeatureInPreview, "y").WithArguments("ref and unsafe in async and iterator methods").WithLocation(19, 26)); + + var expectedOutput = "0090-19"; + + CompileAndVerify(src, parseOptions: TestOptions.RegularNext, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseExe, + expectedOutput: expectedOutput).VerifyDiagnostics(); + + CompileAndVerify(src, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseExe, + expectedOutput: expectedOutput).VerifyDiagnostics(); + } + + [Fact] + public void Foreach_InIterator_11() + { + var src = @" +class Program +{ + static Buffer4 s_buffer; + + static void Main() + { + s_buffer[2] = 3; + + foreach (int x in Test()) + { + System.Console.Write(x); + } + } + + static System.Collections.Generic.IEnumerable Test() + { + foreach (ref int y in GetBuffer()) + { + yield return 1; + y *= y; + System.Console.Write(y); + } + + yield return -1; + + System.Console.Write(s_buffer[2]); + } + + static ref Buffer4 GetBuffer() => ref s_buffer; +} +" + Buffer4Definition; + + CreateCompilation(src, parseOptions: TestOptions.Regular12, targetFramework: TargetFramework.Net80).VerifyDiagnostics( + // (18,26): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // foreach (ref int y in GetBuffer()) + Diagnostic(ErrorCode.ERR_FeatureInPreview, "y").WithArguments("ref and unsafe in async and iterator methods").WithLocation(18, 26)); + + var expectedDiagnostics = new[] + { + // (21,13): error CS9217: A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + // y *= y; + Diagnostic(ErrorCode.ERR_RefLocalAcrossAwait, "y").WithLocation(21, 13), + // (21,18): error CS9217: A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + // y *= y; + Diagnostic(ErrorCode.ERR_RefLocalAcrossAwait, "y").WithLocation(21, 18), + // (22,34): error CS9217: A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + // System.Console.Write(y); + Diagnostic(ErrorCode.ERR_RefLocalAcrossAwait, "y").WithLocation(22, 34) + }; + + CreateCompilation(src, parseOptions: TestOptions.RegularNext, targetFramework: TargetFramework.Net80).VerifyEmitDiagnostics(expectedDiagnostics); + + CreateCompilation(src, targetFramework: TargetFramework.Net80).VerifyEmitDiagnostics(expectedDiagnostics); + } + + [Fact] + public void Foreach_InIterator_12() + { + var src = @" +class Program +{ + static Buffer4 s_buffer; + + static void Main() + { + s_buffer[2] = 3; + + foreach (int x in Test()) + { + System.Console.Write(x); + } + } + + static System.Collections.Generic.IEnumerable Test() + { + foreach (ref int y in GetBuffer()) + { + y *= y; + System.Console.Write(y); + yield return 1; + } + + yield return -1; + + System.Console.Write(s_buffer[2]); + } + + static ref Buffer4 GetBuffer() => ref s_buffer; +} +" + Buffer4Definition; + + CreateCompilation(src, parseOptions: TestOptions.Regular12, targetFramework: TargetFramework.Net80).VerifyDiagnostics( + // (18,26): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // foreach (ref int y in GetBuffer()) + Diagnostic(ErrorCode.ERR_FeatureInPreview, "y").WithArguments("ref and unsafe in async and iterator methods").WithLocation(18, 26)); + + var expectedDiagnostics = new[] + { + // (18,9): error CS8178: A reference returned by a call to 'Program.GetBuffer()' cannot be preserved across 'await' or 'yield' boundary. + // foreach (ref int y in GetBuffer()) + Diagnostic(ErrorCode.ERR_RefReturningCallAndAwait, @"foreach (ref int y in GetBuffer()) + { + y *= y; + System.Console.Write(y); + yield return 1; + }").WithArguments("Program.GetBuffer()").WithLocation(18, 9) + }; + + CreateCompilation(src, parseOptions: TestOptions.RegularNext, targetFramework: TargetFramework.Net80).VerifyEmitDiagnostics(expectedDiagnostics); + + CreateCompilation(src, targetFramework: TargetFramework.Net80).VerifyEmitDiagnostics(expectedDiagnostics); + } + + [Fact] + public void Foreach_InIterator_13() + { + var src = @" +class Program +{ + static Buffer4 s_buffer; + + static void Main() + { + s_buffer[2] = 3; + + foreach (int x in Test()) + { + System.Console.Write(x); + } + } + + static System.Collections.Generic.IEnumerable Test() + { + ref Buffer4 buffer = ref GetBuffer(); + foreach (ref int y in buffer) + { + y *= y; + System.Console.Write(y); + yield return 1; + } + + yield return -1; + + System.Console.Write(s_buffer[2]); + } + + static ref Buffer4 GetBuffer() => ref s_buffer; +} +" + Buffer4Definition; + + CreateCompilation(src, parseOptions: TestOptions.Regular12, targetFramework: TargetFramework.Net80).VerifyDiagnostics( + // (18,26): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // ref Buffer4 buffer = ref GetBuffer(); + Diagnostic(ErrorCode.ERR_FeatureInPreview, "buffer").WithArguments("ref and unsafe in async and iterator methods").WithLocation(18, 26), + // (19,26): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // foreach (ref int y in buffer) + Diagnostic(ErrorCode.ERR_FeatureInPreview, "y").WithArguments("ref and unsafe in async and iterator methods").WithLocation(19, 26)); + + var expectedDiagnostics = new[] + { + // (19,31): error CS9217: A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + // foreach (ref int y in buffer) + Diagnostic(ErrorCode.ERR_RefLocalAcrossAwait, "buffer").WithLocation(19, 31) + }; + + CreateCompilation(src, parseOptions: TestOptions.RegularNext, targetFramework: TargetFramework.Net80).VerifyEmitDiagnostics(expectedDiagnostics); + + CreateCompilation(src, targetFramework: TargetFramework.Net80).VerifyEmitDiagnostics(expectedDiagnostics); + } + + [Fact] + public void Foreach_InIterator_14() + { + var src = @" +class C +{ + public readonly Buffer4 F = default; +} + +class Program +{ + private static C c = new C(); + private static int index = 0; + + static void Main() + { + foreach (var a in Test(c)) + {} + } + + static System.Collections.Generic.IEnumerable Test(C x) + { + ref readonly Buffer4 f = ref x.F; + foreach (var y in f) + { + Increment(); + System.Console.Write(' '); + System.Console.Write(y); + + yield return -1; + } + } + + static void Increment() + { + index++; + + if (index < 4) + { + System.Runtime.CompilerServices.Unsafe.AsRef(in c.F)[index] = index; + } + } +} +" + Buffer4Definition; + + CreateCompilation(src, parseOptions: TestOptions.Regular12, targetFramework: TargetFramework.Net80).VerifyDiagnostics( + // (20,35): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // ref readonly Buffer4 f = ref x.F; + Diagnostic(ErrorCode.ERR_FeatureInPreview, "f").WithArguments("ref and unsafe in async and iterator methods").WithLocation(20, 35)); + + var expectedDiagnostics = new[] + { + // (21,27): error CS9217: A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + // foreach (var y in f) + Diagnostic(ErrorCode.ERR_RefLocalAcrossAwait, "f").WithLocation(21, 27) + }; + + CreateCompilation(src, parseOptions: TestOptions.RegularNext, targetFramework: TargetFramework.Net80).VerifyEmitDiagnostics(expectedDiagnostics); + + CreateCompilation(src, targetFramework: TargetFramework.Net80).VerifyEmitDiagnostics(expectedDiagnostics); + } + + [Fact] + public void Foreach_InIterator_15() + { + var src = @" +class Program +{ + static Buffer4 s_buffer; + + static System.Collections.Generic.IEnumerable Test() + { + foreach (ref readonly int y in GetBuffer()) + { + System.Console.Write(y); + yield return 1; + } + + yield return -1; + } + + static ref readonly Buffer4 GetBuffer() => ref s_buffer; +} +" + Buffer4Definition; + + CreateCompilation(src, parseOptions: TestOptions.Regular12, targetFramework: TargetFramework.Net80).VerifyDiagnostics( + // (8,35): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // foreach (ref readonly int y in GetBuffer()) + Diagnostic(ErrorCode.ERR_FeatureInPreview, "y").WithArguments("ref and unsafe in async and iterator methods").WithLocation(8, 35)); + + var expectedDiagnostics = new[] + { + // (8,9): error CS8178: A reference returned by a call to 'Program.GetBuffer()' cannot be preserved across 'await' or 'yield' boundary. + // foreach (ref readonly int y in GetBuffer()) + Diagnostic(ErrorCode.ERR_RefReturningCallAndAwait, @"foreach (ref readonly int y in GetBuffer()) + { + System.Console.Write(y); + yield return 1; + }").WithArguments("Program.GetBuffer()").WithLocation(8, 9) + }; + + CreateCompilation(src, parseOptions: TestOptions.RegularNext, targetFramework: TargetFramework.Net80).VerifyEmitDiagnostics(expectedDiagnostics); + + CreateCompilation(src, targetFramework: TargetFramework.Net80).VerifyEmitDiagnostics(expectedDiagnostics); + } + + [Fact] + public void Foreach_InIterator_16() + { + var src = @" +class Program +{ + static Buffer4 s_buffer; + + static System.Collections.Generic.IEnumerable Test() + { + foreach (ref readonly int y in GetBuffer()) + { + yield return 1; + System.Console.Write(y); + } + + yield return -1; + } + + static ref readonly Buffer4 GetBuffer() => ref s_buffer; +} +" + Buffer4Definition; + + CreateCompilation(src, parseOptions: TestOptions.Regular12, targetFramework: TargetFramework.Net80).VerifyDiagnostics( + // (8,35): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // foreach (ref readonly int y in GetBuffer()) + Diagnostic(ErrorCode.ERR_FeatureInPreview, "y").WithArguments("ref and unsafe in async and iterator methods").WithLocation(8, 35)); + + var expectedDiagnostics = new[] + { + // (11,34): error CS9217: A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + // System.Console.Write(y); + Diagnostic(ErrorCode.ERR_RefLocalAcrossAwait, "y").WithLocation(11, 34) + }; + + CreateCompilation(src, parseOptions: TestOptions.RegularNext, targetFramework: TargetFramework.Net80).VerifyEmitDiagnostics(expectedDiagnostics); + + CreateCompilation(src, targetFramework: TargetFramework.Net80).VerifyEmitDiagnostics(expectedDiagnostics); + } + + [ConditionalFact(typeof(CoreClrOnly))] + public void Foreach_InIterator_17() + { + var src = @" +class C +{ + public readonly Buffer4 F = default; +} + +class Program +{ + private static C c = new C(); + private static int index = 0; + + static void Main() + { + foreach (var a in Test(c)) + {} + } + + static System.Collections.Generic.IEnumerable Test(C x) + { + foreach (ref readonly int y in x.F) + { + Increment(); + System.Console.Write(' '); + System.Console.Write(y); + + yield return -1; + } + } + + static void Increment() + { + index++; + + if (index < 4) + { + System.Runtime.CompilerServices.Unsafe.AsRef(in c.F)[index] = index; + } + } +} +" + Buffer4Definition; + var expectedOutput = " 0 1 2 3"; + var comp = CreateCompilation(src, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseExe); + var verifier = CompileAndVerify(comp, expectedOutput: expectedOutput, verify: Verification.Fails).VerifyDiagnostics(); + comp = CreateCompilation(src, targetFramework: TargetFramework.Net80, options: TestOptions.DebugExe); + CompileAndVerify(comp, expectedOutput: expectedOutput, verify: Verification.Fails).VerifyDiagnostics(); + } + + [Fact] + public void Foreach_InIterator_18() + { + var src = @" +class C +{ + public readonly Buffer4 F = default; +} + +class Program +{ + static System.Collections.Generic.IEnumerable Test(C x) + { + foreach (ref readonly int y in x.F) + { + yield return -1; + System.Console.Write(y); + } + } +} +" + Buffer4Definition; + + CreateCompilation(src, targetFramework: TargetFramework.Net80, parseOptions: TestOptions.Regular12).VerifyDiagnostics( + // (11,35): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // foreach (ref readonly int y in x.F) + Diagnostic(ErrorCode.ERR_FeatureInPreview, "y").WithArguments("ref and unsafe in async and iterator methods").WithLocation(11, 35)); + + var expectedDiagnostics = new[] + { + // (14,34): error CS9217: A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + // System.Console.Write(y); + Diagnostic(ErrorCode.ERR_RefLocalAcrossAwait, "y").WithLocation(14, 34) + }; + + CreateCompilation(src, targetFramework: TargetFramework.Net80, parseOptions: TestOptions.RegularNext).VerifyEmitDiagnostics(expectedDiagnostics); + CreateCompilation(src, targetFramework: TargetFramework.Net80).VerifyEmitDiagnostics(expectedDiagnostics); + } + + [Fact] + public void Foreach_InIterator_19() + { + var src = @" +class C +{ + public readonly Buffer4 F = default; +} + +class Program +{ + static System.Collections.Generic.IEnumerable Test(C x) + { + ref readonly Buffer4 f = ref x.F; + + foreach (var i in f) System.Console.Write(i); + + foreach (var y in f) + { + System.Console.Write(y); + yield return -1; + } + + foreach (var j in f) System.Console.Write(j); + + foreach (var z in f) + { + System.Console.Write(z); + yield return -2; + } + } +} +" + Buffer4Definition; + + CreateCompilation(src, parseOptions: TestOptions.Regular12, targetFramework: TargetFramework.Net80).VerifyDiagnostics( + // (11,35): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // ref readonly Buffer4 f = ref x.F; + Diagnostic(ErrorCode.ERR_FeatureInPreview, "f").WithArguments("ref and unsafe in async and iterator methods").WithLocation(11, 35)); + + var expectedDiagnostics = new[] + { + // (15,27): error CS9217: A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + // foreach (var y in f) + Diagnostic(ErrorCode.ERR_RefLocalAcrossAwait, "f").WithLocation(15, 27), + // (21,27): error CS9217: A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + // foreach (var j in f) System.Console.Write(j); + Diagnostic(ErrorCode.ERR_RefLocalAcrossAwait, "f").WithLocation(21, 27), + // (23,27): error CS9217: A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + // foreach (var z in f) + Diagnostic(ErrorCode.ERR_RefLocalAcrossAwait, "f").WithLocation(23, 27) + }; + + CreateCompilation(src, parseOptions: TestOptions.RegularNext, targetFramework: TargetFramework.Net80).VerifyEmitDiagnostics(expectedDiagnostics); + + CreateCompilation(src, targetFramework: TargetFramework.Net80).VerifyEmitDiagnostics(expectedDiagnostics); } [ConditionalFact(typeof(CoreClrOnly))] diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/LockTests.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/LockTests.cs index a28521e1fd683..deb134acef381 100644 --- a/src/Compilers/CSharp/Test/Emit2/Semantics/LockTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Semantics/LockTests.cs @@ -1861,9 +1861,6 @@ public void Await() } """; CreateCompilation([source, LockTypeDefinition]).VerifyDiagnostics( - // (4,7): error CS9217: A lock statement on a value of type 'System.Threading.Lock' cannot be used in async methods or async lambda expressions. - // lock (new Lock()) - Diagnostic(ErrorCode.ERR_BadSpecialByRefLock, "new Lock()").WithLocation(4, 7), // (6,5): error CS1996: Cannot await in the body of a lock statement // await Task.Yield(); Diagnostic(ErrorCode.ERR_BadAwaitInLock, "await Task.Yield()").WithLocation(6, 5)); @@ -1875,19 +1872,137 @@ public void AsyncMethod() var source = """ #pragma warning disable 1998 // async method lacks 'await' operators using System.Threading; + using System.Threading.Tasks; class C { - async void M() + static async Task Main() { - lock (new Lock()) { } + lock (new Lock()) { System.Console.Write("L"); } } } """; - CreateCompilation([source, LockTypeDefinition]).VerifyDiagnostics( - // (8,15): error CS9217: A lock statement on a value of type 'System.Threading.Lock' cannot be used in async methods or async lambda expressions. - // lock (new Lock()) { } - Diagnostic(ErrorCode.ERR_BadSpecialByRefLock, "new Lock()").WithLocation(8, 15)); + var expectedOutput = "ELD"; + var verifier = CompileAndVerify([source, LockTypeDefinition], options: TestOptions.DebugExe, + expectedOutput: expectedOutput, verify: Verification.FailsILVerify); + verifier.VerifyDiagnostics(); + verifier.VerifyIL("C.
d__0.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext", """ + { + // Code size 94 (0x5e) + .maxstack 2 + .locals init (int V_0, + System.Threading.Lock.Scope V_1, + System.Exception V_2) + IL_0000: ldarg.0 + IL_0001: ldfld "int C.
d__0.<>1__state" + IL_0006: stloc.0 + .try + { + IL_0007: nop + IL_0008: newobj "System.Threading.Lock..ctor()" + IL_000d: call "System.Threading.Lock.Scope System.Threading.Lock.EnterScope()" + IL_0012: stloc.1 + .try + { + IL_0013: nop + IL_0014: ldstr "L" + IL_0019: call "void System.Console.Write(string)" + IL_001e: nop + IL_001f: nop + IL_0020: leave.s IL_002f + } + finally + { + IL_0022: ldloc.0 + IL_0023: ldc.i4.0 + IL_0024: bge.s IL_002e + IL_0026: ldloca.s V_1 + IL_0028: call "void System.Threading.Lock.Scope.Dispose()" + IL_002d: nop + IL_002e: endfinally + } + IL_002f: leave.s IL_0049 + } + catch System.Exception + { + IL_0031: stloc.2 + IL_0032: ldarg.0 + IL_0033: ldc.i4.s -2 + IL_0035: stfld "int C.
d__0.<>1__state" + IL_003a: ldarg.0 + IL_003b: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.
d__0.<>t__builder" + IL_0040: ldloc.2 + IL_0041: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)" + IL_0046: nop + IL_0047: leave.s IL_005d + } + IL_0049: ldarg.0 + IL_004a: ldc.i4.s -2 + IL_004c: stfld "int C.
d__0.<>1__state" + IL_0051: ldarg.0 + IL_0052: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.
d__0.<>t__builder" + IL_0057: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetResult()" + IL_005c: nop + IL_005d: ret + } + """); + + verifier = CompileAndVerify([source, LockTypeDefinition], options: TestOptions.ReleaseExe, + expectedOutput: expectedOutput, verify: Verification.FailsILVerify); + verifier.VerifyDiagnostics(); + verifier.VerifyIL("C.
d__0.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext", """ + { + // Code size 87 (0x57) + .maxstack 2 + .locals init (int V_0, + System.Threading.Lock.Scope V_1, + System.Exception V_2) + IL_0000: ldarg.0 + IL_0001: ldfld "int C.
d__0.<>1__state" + IL_0006: stloc.0 + .try + { + IL_0007: newobj "System.Threading.Lock..ctor()" + IL_000c: call "System.Threading.Lock.Scope System.Threading.Lock.EnterScope()" + IL_0011: stloc.1 + .try + { + IL_0012: ldstr "L" + IL_0017: call "void System.Console.Write(string)" + IL_001c: leave.s IL_002a + } + finally + { + IL_001e: ldloc.0 + IL_001f: ldc.i4.0 + IL_0020: bge.s IL_0029 + IL_0022: ldloca.s V_1 + IL_0024: call "void System.Threading.Lock.Scope.Dispose()" + IL_0029: endfinally + } + IL_002a: leave.s IL_0043 + } + catch System.Exception + { + IL_002c: stloc.2 + IL_002d: ldarg.0 + IL_002e: ldc.i4.s -2 + IL_0030: stfld "int C.
d__0.<>1__state" + IL_0035: ldarg.0 + IL_0036: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.
d__0.<>t__builder" + IL_003b: ldloc.2 + IL_003c: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)" + IL_0041: leave.s IL_0056 + } + IL_0043: ldarg.0 + IL_0044: ldc.i4.s -2 + IL_0046: stfld "int C.
d__0.<>1__state" + IL_004b: ldarg.0 + IL_004c: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.
d__0.<>t__builder" + IL_0051: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetResult()" + IL_0056: ret + } + """); } [Fact] @@ -1899,17 +2014,527 @@ public void AsyncMethod_WithAwait() class C { - async void M() + static async Task Main() { await Task.Yield(); - lock (new Lock()) { } + lock (new Lock()) { System.Console.Write("L"); } + await Task.Yield(); } } """; - CreateCompilation([source, LockTypeDefinition]).VerifyDiagnostics( - // (9,15): error CS9217: A lock statement on a value of type 'System.Threading.Lock' cannot be used in async methods or async lambda expressions. - // lock (new Lock()) { } - Diagnostic(ErrorCode.ERR_BadSpecialByRefLock, "new Lock()").WithLocation(9, 15)); + var expectedOutput = "ELD"; + var verifier = CompileAndVerify([source, LockTypeDefinition], options: TestOptions.DebugExe, + expectedOutput: expectedOutput, verify: Verification.FailsILVerify); + verifier.VerifyDiagnostics(); + verifier.VerifyIL("C.
d__0.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext", """ + { + // Code size 311 (0x137) + .maxstack 3 + .locals init (int V_0, + System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter V_1, + System.Runtime.CompilerServices.YieldAwaitable V_2, + C.
d__0 V_3, + System.Threading.Lock.Scope V_4, + System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter V_5, + System.Exception V_6) + IL_0000: ldarg.0 + IL_0001: ldfld "int C.
d__0.<>1__state" + IL_0006: stloc.0 + .try + { + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0012 + IL_000a: br.s IL_000c + IL_000c: ldloc.0 + IL_000d: ldc.i4.1 + IL_000e: beq.s IL_0014 + IL_0010: br.s IL_0019 + IL_0012: br.s IL_0058 + IL_0014: br IL_00e1 + IL_0019: nop + IL_001a: call "System.Runtime.CompilerServices.YieldAwaitable System.Threading.Tasks.Task.Yield()" + IL_001f: stloc.2 + IL_0020: ldloca.s V_2 + IL_0022: call "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter System.Runtime.CompilerServices.YieldAwaitable.GetAwaiter()" + IL_0027: stloc.1 + IL_0028: ldloca.s V_1 + IL_002a: call "bool System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.IsCompleted.get" + IL_002f: brtrue.s IL_0074 + IL_0031: ldarg.0 + IL_0032: ldc.i4.0 + IL_0033: dup + IL_0034: stloc.0 + IL_0035: stfld "int C.
d__0.<>1__state" + IL_003a: ldarg.0 + IL_003b: ldloc.1 + IL_003c: stfld "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter C.
d__0.<>u__1" + IL_0041: ldarg.0 + IL_0042: stloc.3 + IL_0043: ldarg.0 + IL_0044: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.
d__0.<>t__builder" + IL_0049: ldloca.s V_1 + IL_004b: ldloca.s V_3 + IL_004d: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompletedd__0>(ref System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter, ref C.
d__0)" + IL_0052: nop + IL_0053: leave IL_0136 + IL_0058: ldarg.0 + IL_0059: ldfld "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter C.
d__0.<>u__1" + IL_005e: stloc.1 + IL_005f: ldarg.0 + IL_0060: ldflda "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter C.
d__0.<>u__1" + IL_0065: initobj "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter" + IL_006b: ldarg.0 + IL_006c: ldc.i4.m1 + IL_006d: dup + IL_006e: stloc.0 + IL_006f: stfld "int C.
d__0.<>1__state" + IL_0074: ldloca.s V_1 + IL_0076: call "void System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.GetResult()" + IL_007b: nop + IL_007c: newobj "System.Threading.Lock..ctor()" + IL_0081: call "System.Threading.Lock.Scope System.Threading.Lock.EnterScope()" + IL_0086: stloc.s V_4 + .try + { + IL_0088: nop + IL_0089: ldstr "L" + IL_008e: call "void System.Console.Write(string)" + IL_0093: nop + IL_0094: nop + IL_0095: leave.s IL_00a4 + } + finally + { + IL_0097: ldloc.0 + IL_0098: ldc.i4.0 + IL_0099: bge.s IL_00a3 + IL_009b: ldloca.s V_4 + IL_009d: call "void System.Threading.Lock.Scope.Dispose()" + IL_00a2: nop + IL_00a3: endfinally + } + IL_00a4: call "System.Runtime.CompilerServices.YieldAwaitable System.Threading.Tasks.Task.Yield()" + IL_00a9: stloc.2 + IL_00aa: ldloca.s V_2 + IL_00ac: call "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter System.Runtime.CompilerServices.YieldAwaitable.GetAwaiter()" + IL_00b1: stloc.s V_5 + IL_00b3: ldloca.s V_5 + IL_00b5: call "bool System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.IsCompleted.get" + IL_00ba: brtrue.s IL_00fe + IL_00bc: ldarg.0 + IL_00bd: ldc.i4.1 + IL_00be: dup + IL_00bf: stloc.0 + IL_00c0: stfld "int C.
d__0.<>1__state" + IL_00c5: ldarg.0 + IL_00c6: ldloc.s V_5 + IL_00c8: stfld "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter C.
d__0.<>u__1" + IL_00cd: ldarg.0 + IL_00ce: stloc.3 + IL_00cf: ldarg.0 + IL_00d0: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.
d__0.<>t__builder" + IL_00d5: ldloca.s V_5 + IL_00d7: ldloca.s V_3 + IL_00d9: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompletedd__0>(ref System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter, ref C.
d__0)" + IL_00de: nop + IL_00df: leave.s IL_0136 + IL_00e1: ldarg.0 + IL_00e2: ldfld "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter C.
d__0.<>u__1" + IL_00e7: stloc.s V_5 + IL_00e9: ldarg.0 + IL_00ea: ldflda "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter C.
d__0.<>u__1" + IL_00ef: initobj "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter" + IL_00f5: ldarg.0 + IL_00f6: ldc.i4.m1 + IL_00f7: dup + IL_00f8: stloc.0 + IL_00f9: stfld "int C.
d__0.<>1__state" + IL_00fe: ldloca.s V_5 + IL_0100: call "void System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.GetResult()" + IL_0105: nop + IL_0106: leave.s IL_0122 + } + catch System.Exception + { + IL_0108: stloc.s V_6 + IL_010a: ldarg.0 + IL_010b: ldc.i4.s -2 + IL_010d: stfld "int C.
d__0.<>1__state" + IL_0112: ldarg.0 + IL_0113: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.
d__0.<>t__builder" + IL_0118: ldloc.s V_6 + IL_011a: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)" + IL_011f: nop + IL_0120: leave.s IL_0136 + } + IL_0122: ldarg.0 + IL_0123: ldc.i4.s -2 + IL_0125: stfld "int C.
d__0.<>1__state" + IL_012a: ldarg.0 + IL_012b: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.
d__0.<>t__builder" + IL_0130: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetResult()" + IL_0135: nop + IL_0136: ret + } + """); + + verifier = CompileAndVerify([source, LockTypeDefinition], options: TestOptions.ReleaseExe, + expectedOutput: expectedOutput, verify: Verification.FailsILVerify); + verifier.VerifyDiagnostics(); + verifier.VerifyIL("C.
d__0.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext", """ + { + // Code size 282 (0x11a) + .maxstack 3 + .locals init (int V_0, + System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter V_1, + System.Runtime.CompilerServices.YieldAwaitable V_2, + System.Threading.Lock.Scope V_3, + System.Exception V_4) + IL_0000: ldarg.0 + IL_0001: ldfld "int C.
d__0.<>1__state" + IL_0006: stloc.0 + .try + { + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_004b + IL_000a: ldloc.0 + IL_000b: ldc.i4.1 + IL_000c: beq IL_00c8 + IL_0011: call "System.Runtime.CompilerServices.YieldAwaitable System.Threading.Tasks.Task.Yield()" + IL_0016: stloc.2 + IL_0017: ldloca.s V_2 + IL_0019: call "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter System.Runtime.CompilerServices.YieldAwaitable.GetAwaiter()" + IL_001e: stloc.1 + IL_001f: ldloca.s V_1 + IL_0021: call "bool System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.IsCompleted.get" + IL_0026: brtrue.s IL_0067 + IL_0028: ldarg.0 + IL_0029: ldc.i4.0 + IL_002a: dup + IL_002b: stloc.0 + IL_002c: stfld "int C.
d__0.<>1__state" + IL_0031: ldarg.0 + IL_0032: ldloc.1 + IL_0033: stfld "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter C.
d__0.<>u__1" + IL_0038: ldarg.0 + IL_0039: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.
d__0.<>t__builder" + IL_003e: ldloca.s V_1 + IL_0040: ldarg.0 + IL_0041: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompletedd__0>(ref System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter, ref C.
d__0)" + IL_0046: leave IL_0119 + IL_004b: ldarg.0 + IL_004c: ldfld "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter C.
d__0.<>u__1" + IL_0051: stloc.1 + IL_0052: ldarg.0 + IL_0053: ldflda "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter C.
d__0.<>u__1" + IL_0058: initobj "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter" + IL_005e: ldarg.0 + IL_005f: ldc.i4.m1 + IL_0060: dup + IL_0061: stloc.0 + IL_0062: stfld "int C.
d__0.<>1__state" + IL_0067: ldloca.s V_1 + IL_0069: call "void System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.GetResult()" + IL_006e: newobj "System.Threading.Lock..ctor()" + IL_0073: call "System.Threading.Lock.Scope System.Threading.Lock.EnterScope()" + IL_0078: stloc.3 + .try + { + IL_0079: ldstr "L" + IL_007e: call "void System.Console.Write(string)" + IL_0083: leave.s IL_0091 + } + finally + { + IL_0085: ldloc.0 + IL_0086: ldc.i4.0 + IL_0087: bge.s IL_0090 + IL_0089: ldloca.s V_3 + IL_008b: call "void System.Threading.Lock.Scope.Dispose()" + IL_0090: endfinally + } + IL_0091: call "System.Runtime.CompilerServices.YieldAwaitable System.Threading.Tasks.Task.Yield()" + IL_0096: stloc.2 + IL_0097: ldloca.s V_2 + IL_0099: call "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter System.Runtime.CompilerServices.YieldAwaitable.GetAwaiter()" + IL_009e: stloc.1 + IL_009f: ldloca.s V_1 + IL_00a1: call "bool System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.IsCompleted.get" + IL_00a6: brtrue.s IL_00e4 + IL_00a8: ldarg.0 + IL_00a9: ldc.i4.1 + IL_00aa: dup + IL_00ab: stloc.0 + IL_00ac: stfld "int C.
d__0.<>1__state" + IL_00b1: ldarg.0 + IL_00b2: ldloc.1 + IL_00b3: stfld "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter C.
d__0.<>u__1" + IL_00b8: ldarg.0 + IL_00b9: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.
d__0.<>t__builder" + IL_00be: ldloca.s V_1 + IL_00c0: ldarg.0 + IL_00c1: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompletedd__0>(ref System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter, ref C.
d__0)" + IL_00c6: leave.s IL_0119 + IL_00c8: ldarg.0 + IL_00c9: ldfld "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter C.
d__0.<>u__1" + IL_00ce: stloc.1 + IL_00cf: ldarg.0 + IL_00d0: ldflda "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter C.
d__0.<>u__1" + IL_00d5: initobj "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter" + IL_00db: ldarg.0 + IL_00dc: ldc.i4.m1 + IL_00dd: dup + IL_00de: stloc.0 + IL_00df: stfld "int C.
d__0.<>1__state" + IL_00e4: ldloca.s V_1 + IL_00e6: call "void System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.GetResult()" + IL_00eb: leave.s IL_0106 + } + catch System.Exception + { + IL_00ed: stloc.s V_4 + IL_00ef: ldarg.0 + IL_00f0: ldc.i4.s -2 + IL_00f2: stfld "int C.
d__0.<>1__state" + IL_00f7: ldarg.0 + IL_00f8: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.
d__0.<>t__builder" + IL_00fd: ldloc.s V_4 + IL_00ff: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)" + IL_0104: leave.s IL_0119 + } + IL_0106: ldarg.0 + IL_0107: ldc.i4.s -2 + IL_0109: stfld "int C.
d__0.<>1__state" + IL_010e: ldarg.0 + IL_010f: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.
d__0.<>t__builder" + IL_0114: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetResult()" + IL_0119: ret + } + """); + } + + [Fact] + public void AsyncMethod_AwaitResource() + { + var source = """ + #pragma warning disable 1998 // async method lacks 'await' operators + using System.Threading; + using System.Threading.Tasks; + + class C + { + static async Task Main() + { + lock (await GetLock()) { System.Console.Write("L"); } + } + + static async Task GetLock() => new Lock(); + } + """; + var expectedOutput = "ELD"; + var verifier = CompileAndVerify([source, LockTypeDefinition], options: TestOptions.DebugExe, + expectedOutput: expectedOutput, verify: Verification.FailsILVerify); + verifier.VerifyDiagnostics(); + verifier.VerifyIL("C.
d__0.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext", """ + { + // Code size 211 (0xd3) + .maxstack 3 + .locals init (int V_0, + System.Threading.Lock.Scope V_1, + System.Runtime.CompilerServices.TaskAwaiter V_2, + C.
d__0 V_3, + System.Exception V_4) + IL_0000: ldarg.0 + IL_0001: ldfld "int C.
d__0.<>1__state" + IL_0006: stloc.0 + .try + { + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_000c + IL_000a: br.s IL_000e + IL_000c: br.s IL_004a + IL_000e: nop + IL_000f: call "System.Threading.Tasks.Task C.GetLock()" + IL_0014: callvirt "System.Runtime.CompilerServices.TaskAwaiter System.Threading.Tasks.Task.GetAwaiter()" + IL_0019: stloc.2 + IL_001a: ldloca.s V_2 + IL_001c: call "bool System.Runtime.CompilerServices.TaskAwaiter.IsCompleted.get" + IL_0021: brtrue.s IL_0066 + IL_0023: ldarg.0 + IL_0024: ldc.i4.0 + IL_0025: dup + IL_0026: stloc.0 + IL_0027: stfld "int C.
d__0.<>1__state" + IL_002c: ldarg.0 + IL_002d: ldloc.2 + IL_002e: stfld "System.Runtime.CompilerServices.TaskAwaiter C.
d__0.<>u__1" + IL_0033: ldarg.0 + IL_0034: stloc.3 + IL_0035: ldarg.0 + IL_0036: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.
d__0.<>t__builder" + IL_003b: ldloca.s V_2 + IL_003d: ldloca.s V_3 + IL_003f: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompleted, C.
d__0>(ref System.Runtime.CompilerServices.TaskAwaiter, ref C.
d__0)" + IL_0044: nop + IL_0045: leave IL_00d2 + IL_004a: ldarg.0 + IL_004b: ldfld "System.Runtime.CompilerServices.TaskAwaiter C.
d__0.<>u__1" + IL_0050: stloc.2 + IL_0051: ldarg.0 + IL_0052: ldflda "System.Runtime.CompilerServices.TaskAwaiter C.
d__0.<>u__1" + IL_0057: initobj "System.Runtime.CompilerServices.TaskAwaiter" + IL_005d: ldarg.0 + IL_005e: ldc.i4.m1 + IL_005f: dup + IL_0060: stloc.0 + IL_0061: stfld "int C.
d__0.<>1__state" + IL_0066: ldarg.0 + IL_0067: ldloca.s V_2 + IL_0069: call "System.Threading.Lock System.Runtime.CompilerServices.TaskAwaiter.GetResult()" + IL_006e: stfld "System.Threading.Lock C.
d__0.<>s__1" + IL_0073: ldarg.0 + IL_0074: ldfld "System.Threading.Lock C.
d__0.<>s__1" + IL_0079: callvirt "System.Threading.Lock.Scope System.Threading.Lock.EnterScope()" + IL_007e: stloc.1 + IL_007f: ldarg.0 + IL_0080: ldnull + IL_0081: stfld "System.Threading.Lock C.
d__0.<>s__1" + .try + { + IL_0086: nop + IL_0087: ldstr "L" + IL_008c: call "void System.Console.Write(string)" + IL_0091: nop + IL_0092: nop + IL_0093: leave.s IL_00a2 + } + finally + { + IL_0095: ldloc.0 + IL_0096: ldc.i4.0 + IL_0097: bge.s IL_00a1 + IL_0099: ldloca.s V_1 + IL_009b: call "void System.Threading.Lock.Scope.Dispose()" + IL_00a0: nop + IL_00a1: endfinally + } + IL_00a2: leave.s IL_00be + } + catch System.Exception + { + IL_00a4: stloc.s V_4 + IL_00a6: ldarg.0 + IL_00a7: ldc.i4.s -2 + IL_00a9: stfld "int C.
d__0.<>1__state" + IL_00ae: ldarg.0 + IL_00af: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.
d__0.<>t__builder" + IL_00b4: ldloc.s V_4 + IL_00b6: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)" + IL_00bb: nop + IL_00bc: leave.s IL_00d2 + } + IL_00be: ldarg.0 + IL_00bf: ldc.i4.s -2 + IL_00c1: stfld "int C.
d__0.<>1__state" + IL_00c6: ldarg.0 + IL_00c7: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.
d__0.<>t__builder" + IL_00cc: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetResult()" + IL_00d1: nop + IL_00d2: ret + } + """); + + verifier = CompileAndVerify([source, LockTypeDefinition], options: TestOptions.ReleaseExe, + expectedOutput: expectedOutput, verify: Verification.FailsILVerify); + verifier.VerifyDiagnostics(); + verifier.VerifyIL("C.
d__0.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext", """ + { + // Code size 172 (0xac) + .maxstack 3 + .locals init (int V_0, + System.Threading.Lock.Scope V_1, + System.Runtime.CompilerServices.TaskAwaiter V_2, + System.Exception V_3) + IL_0000: ldarg.0 + IL_0001: ldfld "int C.
d__0.<>1__state" + IL_0006: stloc.0 + .try + { + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_003e + IL_000a: call "System.Threading.Tasks.Task C.GetLock()" + IL_000f: callvirt "System.Runtime.CompilerServices.TaskAwaiter System.Threading.Tasks.Task.GetAwaiter()" + IL_0014: stloc.2 + IL_0015: ldloca.s V_2 + IL_0017: call "bool System.Runtime.CompilerServices.TaskAwaiter.IsCompleted.get" + IL_001c: brtrue.s IL_005a + IL_001e: ldarg.0 + IL_001f: ldc.i4.0 + IL_0020: dup + IL_0021: stloc.0 + IL_0022: stfld "int C.
d__0.<>1__state" + IL_0027: ldarg.0 + IL_0028: ldloc.2 + IL_0029: stfld "System.Runtime.CompilerServices.TaskAwaiter C.
d__0.<>u__1" + IL_002e: ldarg.0 + IL_002f: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.
d__0.<>t__builder" + IL_0034: ldloca.s V_2 + IL_0036: ldarg.0 + IL_0037: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompleted, C.
d__0>(ref System.Runtime.CompilerServices.TaskAwaiter, ref C.
d__0)" + IL_003c: leave.s IL_00ab + IL_003e: ldarg.0 + IL_003f: ldfld "System.Runtime.CompilerServices.TaskAwaiter C.
d__0.<>u__1" + IL_0044: stloc.2 + IL_0045: ldarg.0 + IL_0046: ldflda "System.Runtime.CompilerServices.TaskAwaiter C.
d__0.<>u__1" + IL_004b: initobj "System.Runtime.CompilerServices.TaskAwaiter" + IL_0051: ldarg.0 + IL_0052: ldc.i4.m1 + IL_0053: dup + IL_0054: stloc.0 + IL_0055: stfld "int C.
d__0.<>1__state" + IL_005a: ldloca.s V_2 + IL_005c: call "System.Threading.Lock System.Runtime.CompilerServices.TaskAwaiter.GetResult()" + IL_0061: callvirt "System.Threading.Lock.Scope System.Threading.Lock.EnterScope()" + IL_0066: stloc.1 + .try + { + IL_0067: ldstr "L" + IL_006c: call "void System.Console.Write(string)" + IL_0071: leave.s IL_007f + } + finally + { + IL_0073: ldloc.0 + IL_0074: ldc.i4.0 + IL_0075: bge.s IL_007e + IL_0077: ldloca.s V_1 + IL_0079: call "void System.Threading.Lock.Scope.Dispose()" + IL_007e: endfinally + } + IL_007f: leave.s IL_0098 + } + catch System.Exception + { + IL_0081: stloc.3 + IL_0082: ldarg.0 + IL_0083: ldc.i4.s -2 + IL_0085: stfld "int C.
d__0.<>1__state" + IL_008a: ldarg.0 + IL_008b: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.
d__0.<>t__builder" + IL_0090: ldloc.3 + IL_0091: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)" + IL_0096: leave.s IL_00ab + } + IL_0098: ldarg.0 + IL_0099: ldc.i4.s -2 + IL_009b: stfld "int C.
d__0.<>1__state" + IL_00a0: ldarg.0 + IL_00a1: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.
d__0.<>t__builder" + IL_00a6: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetResult()" + IL_00ab: ret + } + """); } [Fact] @@ -1921,15 +2546,132 @@ public void AsyncLocalFunction() async void local() { - lock (new Lock()) { } + lock (new Lock()) { System.Console.Write("L"); } } local(); """; - CreateCompilation([source, LockTypeDefinition]).VerifyDiagnostics( - // (6,11): error CS9217: A lock statement on a value of type 'System.Threading.Lock' cannot be used in async methods or async lambda expressions. - // lock (new Lock()) { } - Diagnostic(ErrorCode.ERR_BadSpecialByRefLock, "new Lock()").WithLocation(6, 11)); + var expectedOutput = "ELD"; + var verifier = CompileAndVerify([source, LockTypeDefinition], options: TestOptions.DebugExe, + expectedOutput: expectedOutput, verify: Verification.FailsILVerify); + verifier.VerifyDiagnostics(); + verifier.VerifyIL("Program.<<
$>g__local|0_0>d.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext", """ + { + // Code size 94 (0x5e) + .maxstack 2 + .locals init (int V_0, + System.Threading.Lock.Scope V_1, + System.Exception V_2) + IL_0000: ldarg.0 + IL_0001: ldfld "int Program.<<
$>g__local|0_0>d.<>1__state" + IL_0006: stloc.0 + .try + { + IL_0007: nop + IL_0008: newobj "System.Threading.Lock..ctor()" + IL_000d: call "System.Threading.Lock.Scope System.Threading.Lock.EnterScope()" + IL_0012: stloc.1 + .try + { + IL_0013: nop + IL_0014: ldstr "L" + IL_0019: call "void System.Console.Write(string)" + IL_001e: nop + IL_001f: nop + IL_0020: leave.s IL_002f + } + finally + { + IL_0022: ldloc.0 + IL_0023: ldc.i4.0 + IL_0024: bge.s IL_002e + IL_0026: ldloca.s V_1 + IL_0028: call "void System.Threading.Lock.Scope.Dispose()" + IL_002d: nop + IL_002e: endfinally + } + IL_002f: leave.s IL_0049 + } + catch System.Exception + { + IL_0031: stloc.2 + IL_0032: ldarg.0 + IL_0033: ldc.i4.s -2 + IL_0035: stfld "int Program.<<
$>g__local|0_0>d.<>1__state" + IL_003a: ldarg.0 + IL_003b: ldflda "System.Runtime.CompilerServices.AsyncVoidMethodBuilder Program.<<
$>g__local|0_0>d.<>t__builder" + IL_0040: ldloc.2 + IL_0041: call "void System.Runtime.CompilerServices.AsyncVoidMethodBuilder.SetException(System.Exception)" + IL_0046: nop + IL_0047: leave.s IL_005d + } + IL_0049: ldarg.0 + IL_004a: ldc.i4.s -2 + IL_004c: stfld "int Program.<<
$>g__local|0_0>d.<>1__state" + IL_0051: ldarg.0 + IL_0052: ldflda "System.Runtime.CompilerServices.AsyncVoidMethodBuilder Program.<<
$>g__local|0_0>d.<>t__builder" + IL_0057: call "void System.Runtime.CompilerServices.AsyncVoidMethodBuilder.SetResult()" + IL_005c: nop + IL_005d: ret + } + """); + + verifier = CompileAndVerify([source, LockTypeDefinition], options: TestOptions.ReleaseExe, + expectedOutput: expectedOutput, verify: Verification.FailsILVerify); + verifier.VerifyDiagnostics(); + verifier.VerifyIL("Program.<<
$>g__local|0_0>d.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext", """ + { + // Code size 87 (0x57) + .maxstack 2 + .locals init (int V_0, + System.Threading.Lock.Scope V_1, + System.Exception V_2) + IL_0000: ldarg.0 + IL_0001: ldfld "int Program.<<
$>g__local|0_0>d.<>1__state" + IL_0006: stloc.0 + .try + { + IL_0007: newobj "System.Threading.Lock..ctor()" + IL_000c: call "System.Threading.Lock.Scope System.Threading.Lock.EnterScope()" + IL_0011: stloc.1 + .try + { + IL_0012: ldstr "L" + IL_0017: call "void System.Console.Write(string)" + IL_001c: leave.s IL_002a + } + finally + { + IL_001e: ldloc.0 + IL_001f: ldc.i4.0 + IL_0020: bge.s IL_0029 + IL_0022: ldloca.s V_1 + IL_0024: call "void System.Threading.Lock.Scope.Dispose()" + IL_0029: endfinally + } + IL_002a: leave.s IL_0043 + } + catch System.Exception + { + IL_002c: stloc.2 + IL_002d: ldarg.0 + IL_002e: ldc.i4.s -2 + IL_0030: stfld "int Program.<<
$>g__local|0_0>d.<>1__state" + IL_0035: ldarg.0 + IL_0036: ldflda "System.Runtime.CompilerServices.AsyncVoidMethodBuilder Program.<<
$>g__local|0_0>d.<>t__builder" + IL_003b: ldloc.2 + IL_003c: call "void System.Runtime.CompilerServices.AsyncVoidMethodBuilder.SetException(System.Exception)" + IL_0041: leave.s IL_0056 + } + IL_0043: ldarg.0 + IL_0044: ldc.i4.s -2 + IL_0046: stfld "int Program.<<
$>g__local|0_0>d.<>1__state" + IL_004b: ldarg.0 + IL_004c: ldflda "System.Runtime.CompilerServices.AsyncVoidMethodBuilder Program.<<
$>g__local|0_0>d.<>t__builder" + IL_0051: call "void System.Runtime.CompilerServices.AsyncVoidMethodBuilder.SetResult()" + IL_0056: ret + } + """); } [Fact] @@ -1939,18 +2681,304 @@ public void AsyncLocalFunction_WithAwait() using System.Threading; using System.Threading.Tasks; - async void local() + async Task local() { await Task.Yield(); - lock (new Lock()) { } + lock (new Lock()) { System.Console.Write("L"); } + await Task.Yield(); } - local(); + await local(); """; - CreateCompilation([source, LockTypeDefinition]).VerifyDiagnostics( - // (7,11): error CS9217: A lock statement on a value of type 'System.Threading.Lock' cannot be used in async methods or async lambda expressions. - // lock (new Lock()) { } - Diagnostic(ErrorCode.ERR_BadSpecialByRefLock, "new Lock()").WithLocation(7, 11)); + var expectedOutput = "ELD"; + var verifier = CompileAndVerify([source, LockTypeDefinition], options: TestOptions.DebugExe, + expectedOutput: expectedOutput, verify: Verification.FailsILVerify); + verifier.VerifyDiagnostics(); + verifier.VerifyIL("Program.<<
$>g__local|0_0>d.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext", """ + { + // Code size 311 (0x137) + .maxstack 3 + .locals init (int V_0, + System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter V_1, + System.Runtime.CompilerServices.YieldAwaitable V_2, + Program.<<
$>g__local|0_0>d V_3, + System.Threading.Lock.Scope V_4, + System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter V_5, + System.Exception V_6) + IL_0000: ldarg.0 + IL_0001: ldfld "int Program.<<
$>g__local|0_0>d.<>1__state" + IL_0006: stloc.0 + .try + { + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0012 + IL_000a: br.s IL_000c + IL_000c: ldloc.0 + IL_000d: ldc.i4.1 + IL_000e: beq.s IL_0014 + IL_0010: br.s IL_0019 + IL_0012: br.s IL_0058 + IL_0014: br IL_00e1 + IL_0019: nop + IL_001a: call "System.Runtime.CompilerServices.YieldAwaitable System.Threading.Tasks.Task.Yield()" + IL_001f: stloc.2 + IL_0020: ldloca.s V_2 + IL_0022: call "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter System.Runtime.CompilerServices.YieldAwaitable.GetAwaiter()" + IL_0027: stloc.1 + IL_0028: ldloca.s V_1 + IL_002a: call "bool System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.IsCompleted.get" + IL_002f: brtrue.s IL_0074 + IL_0031: ldarg.0 + IL_0032: ldc.i4.0 + IL_0033: dup + IL_0034: stloc.0 + IL_0035: stfld "int Program.<<
$>g__local|0_0>d.<>1__state" + IL_003a: ldarg.0 + IL_003b: ldloc.1 + IL_003c: stfld "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Program.<<
$>g__local|0_0>d.<>u__1" + IL_0041: ldarg.0 + IL_0042: stloc.3 + IL_0043: ldarg.0 + IL_0044: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program.<<
$>g__local|0_0>d.<>t__builder" + IL_0049: ldloca.s V_1 + IL_004b: ldloca.s V_3 + IL_004d: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompleted$>g__local|0_0>d>(ref System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter, ref Program.<<
$>g__local|0_0>d)" + IL_0052: nop + IL_0053: leave IL_0136 + IL_0058: ldarg.0 + IL_0059: ldfld "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Program.<<
$>g__local|0_0>d.<>u__1" + IL_005e: stloc.1 + IL_005f: ldarg.0 + IL_0060: ldflda "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Program.<<
$>g__local|0_0>d.<>u__1" + IL_0065: initobj "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter" + IL_006b: ldarg.0 + IL_006c: ldc.i4.m1 + IL_006d: dup + IL_006e: stloc.0 + IL_006f: stfld "int Program.<<
$>g__local|0_0>d.<>1__state" + IL_0074: ldloca.s V_1 + IL_0076: call "void System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.GetResult()" + IL_007b: nop + IL_007c: newobj "System.Threading.Lock..ctor()" + IL_0081: call "System.Threading.Lock.Scope System.Threading.Lock.EnterScope()" + IL_0086: stloc.s V_4 + .try + { + IL_0088: nop + IL_0089: ldstr "L" + IL_008e: call "void System.Console.Write(string)" + IL_0093: nop + IL_0094: nop + IL_0095: leave.s IL_00a4 + } + finally + { + IL_0097: ldloc.0 + IL_0098: ldc.i4.0 + IL_0099: bge.s IL_00a3 + IL_009b: ldloca.s V_4 + IL_009d: call "void System.Threading.Lock.Scope.Dispose()" + IL_00a2: nop + IL_00a3: endfinally + } + IL_00a4: call "System.Runtime.CompilerServices.YieldAwaitable System.Threading.Tasks.Task.Yield()" + IL_00a9: stloc.2 + IL_00aa: ldloca.s V_2 + IL_00ac: call "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter System.Runtime.CompilerServices.YieldAwaitable.GetAwaiter()" + IL_00b1: stloc.s V_5 + IL_00b3: ldloca.s V_5 + IL_00b5: call "bool System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.IsCompleted.get" + IL_00ba: brtrue.s IL_00fe + IL_00bc: ldarg.0 + IL_00bd: ldc.i4.1 + IL_00be: dup + IL_00bf: stloc.0 + IL_00c0: stfld "int Program.<<
$>g__local|0_0>d.<>1__state" + IL_00c5: ldarg.0 + IL_00c6: ldloc.s V_5 + IL_00c8: stfld "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Program.<<
$>g__local|0_0>d.<>u__1" + IL_00cd: ldarg.0 + IL_00ce: stloc.3 + IL_00cf: ldarg.0 + IL_00d0: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program.<<
$>g__local|0_0>d.<>t__builder" + IL_00d5: ldloca.s V_5 + IL_00d7: ldloca.s V_3 + IL_00d9: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompleted$>g__local|0_0>d>(ref System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter, ref Program.<<
$>g__local|0_0>d)" + IL_00de: nop + IL_00df: leave.s IL_0136 + IL_00e1: ldarg.0 + IL_00e2: ldfld "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Program.<<
$>g__local|0_0>d.<>u__1" + IL_00e7: stloc.s V_5 + IL_00e9: ldarg.0 + IL_00ea: ldflda "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Program.<<
$>g__local|0_0>d.<>u__1" + IL_00ef: initobj "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter" + IL_00f5: ldarg.0 + IL_00f6: ldc.i4.m1 + IL_00f7: dup + IL_00f8: stloc.0 + IL_00f9: stfld "int Program.<<
$>g__local|0_0>d.<>1__state" + IL_00fe: ldloca.s V_5 + IL_0100: call "void System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.GetResult()" + IL_0105: nop + IL_0106: leave.s IL_0122 + } + catch System.Exception + { + IL_0108: stloc.s V_6 + IL_010a: ldarg.0 + IL_010b: ldc.i4.s -2 + IL_010d: stfld "int Program.<<
$>g__local|0_0>d.<>1__state" + IL_0112: ldarg.0 + IL_0113: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program.<<
$>g__local|0_0>d.<>t__builder" + IL_0118: ldloc.s V_6 + IL_011a: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)" + IL_011f: nop + IL_0120: leave.s IL_0136 + } + IL_0122: ldarg.0 + IL_0123: ldc.i4.s -2 + IL_0125: stfld "int Program.<<
$>g__local|0_0>d.<>1__state" + IL_012a: ldarg.0 + IL_012b: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program.<<
$>g__local|0_0>d.<>t__builder" + IL_0130: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetResult()" + IL_0135: nop + IL_0136: ret + } + """); + + verifier = CompileAndVerify([source, LockTypeDefinition], options: TestOptions.ReleaseExe, + expectedOutput: expectedOutput, verify: Verification.FailsILVerify); + verifier.VerifyDiagnostics(); + verifier.VerifyIL("Program.<<
$>g__local|0_0>d.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext", """ + { + // Code size 282 (0x11a) + .maxstack 3 + .locals init (int V_0, + System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter V_1, + System.Runtime.CompilerServices.YieldAwaitable V_2, + System.Threading.Lock.Scope V_3, + System.Exception V_4) + IL_0000: ldarg.0 + IL_0001: ldfld "int Program.<<
$>g__local|0_0>d.<>1__state" + IL_0006: stloc.0 + .try + { + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_004b + IL_000a: ldloc.0 + IL_000b: ldc.i4.1 + IL_000c: beq IL_00c8 + IL_0011: call "System.Runtime.CompilerServices.YieldAwaitable System.Threading.Tasks.Task.Yield()" + IL_0016: stloc.2 + IL_0017: ldloca.s V_2 + IL_0019: call "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter System.Runtime.CompilerServices.YieldAwaitable.GetAwaiter()" + IL_001e: stloc.1 + IL_001f: ldloca.s V_1 + IL_0021: call "bool System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.IsCompleted.get" + IL_0026: brtrue.s IL_0067 + IL_0028: ldarg.0 + IL_0029: ldc.i4.0 + IL_002a: dup + IL_002b: stloc.0 + IL_002c: stfld "int Program.<<
$>g__local|0_0>d.<>1__state" + IL_0031: ldarg.0 + IL_0032: ldloc.1 + IL_0033: stfld "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Program.<<
$>g__local|0_0>d.<>u__1" + IL_0038: ldarg.0 + IL_0039: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program.<<
$>g__local|0_0>d.<>t__builder" + IL_003e: ldloca.s V_1 + IL_0040: ldarg.0 + IL_0041: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompleted$>g__local|0_0>d>(ref System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter, ref Program.<<
$>g__local|0_0>d)" + IL_0046: leave IL_0119 + IL_004b: ldarg.0 + IL_004c: ldfld "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Program.<<
$>g__local|0_0>d.<>u__1" + IL_0051: stloc.1 + IL_0052: ldarg.0 + IL_0053: ldflda "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Program.<<
$>g__local|0_0>d.<>u__1" + IL_0058: initobj "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter" + IL_005e: ldarg.0 + IL_005f: ldc.i4.m1 + IL_0060: dup + IL_0061: stloc.0 + IL_0062: stfld "int Program.<<
$>g__local|0_0>d.<>1__state" + IL_0067: ldloca.s V_1 + IL_0069: call "void System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.GetResult()" + IL_006e: newobj "System.Threading.Lock..ctor()" + IL_0073: call "System.Threading.Lock.Scope System.Threading.Lock.EnterScope()" + IL_0078: stloc.3 + .try + { + IL_0079: ldstr "L" + IL_007e: call "void System.Console.Write(string)" + IL_0083: leave.s IL_0091 + } + finally + { + IL_0085: ldloc.0 + IL_0086: ldc.i4.0 + IL_0087: bge.s IL_0090 + IL_0089: ldloca.s V_3 + IL_008b: call "void System.Threading.Lock.Scope.Dispose()" + IL_0090: endfinally + } + IL_0091: call "System.Runtime.CompilerServices.YieldAwaitable System.Threading.Tasks.Task.Yield()" + IL_0096: stloc.2 + IL_0097: ldloca.s V_2 + IL_0099: call "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter System.Runtime.CompilerServices.YieldAwaitable.GetAwaiter()" + IL_009e: stloc.1 + IL_009f: ldloca.s V_1 + IL_00a1: call "bool System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.IsCompleted.get" + IL_00a6: brtrue.s IL_00e4 + IL_00a8: ldarg.0 + IL_00a9: ldc.i4.1 + IL_00aa: dup + IL_00ab: stloc.0 + IL_00ac: stfld "int Program.<<
$>g__local|0_0>d.<>1__state" + IL_00b1: ldarg.0 + IL_00b2: ldloc.1 + IL_00b3: stfld "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Program.<<
$>g__local|0_0>d.<>u__1" + IL_00b8: ldarg.0 + IL_00b9: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program.<<
$>g__local|0_0>d.<>t__builder" + IL_00be: ldloca.s V_1 + IL_00c0: ldarg.0 + IL_00c1: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompleted$>g__local|0_0>d>(ref System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter, ref Program.<<
$>g__local|0_0>d)" + IL_00c6: leave.s IL_0119 + IL_00c8: ldarg.0 + IL_00c9: ldfld "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Program.<<
$>g__local|0_0>d.<>u__1" + IL_00ce: stloc.1 + IL_00cf: ldarg.0 + IL_00d0: ldflda "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Program.<<
$>g__local|0_0>d.<>u__1" + IL_00d5: initobj "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter" + IL_00db: ldarg.0 + IL_00dc: ldc.i4.m1 + IL_00dd: dup + IL_00de: stloc.0 + IL_00df: stfld "int Program.<<
$>g__local|0_0>d.<>1__state" + IL_00e4: ldloca.s V_1 + IL_00e6: call "void System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.GetResult()" + IL_00eb: leave.s IL_0106 + } + catch System.Exception + { + IL_00ed: stloc.s V_4 + IL_00ef: ldarg.0 + IL_00f0: ldc.i4.s -2 + IL_00f2: stfld "int Program.<<
$>g__local|0_0>d.<>1__state" + IL_00f7: ldarg.0 + IL_00f8: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program.<<
$>g__local|0_0>d.<>t__builder" + IL_00fd: ldloc.s V_4 + IL_00ff: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)" + IL_0104: leave.s IL_0119 + } + IL_0106: ldarg.0 + IL_0107: ldc.i4.s -2 + IL_0109: stfld "int Program.<<
$>g__local|0_0>d.<>1__state" + IL_010e: ldarg.0 + IL_010f: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program.<<
$>g__local|0_0>d.<>t__builder" + IL_0114: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetResult()" + IL_0119: ret + } + """); } [Fact] @@ -1962,13 +2990,132 @@ public void AsyncLambda() var lam = async () => { - lock (new Lock()) { } + lock (new Lock()) { System.Console.Write("L"); } }; + + await lam(); """; - CreateCompilation([source, LockTypeDefinition]).VerifyDiagnostics( - // (6,11): error CS9217: A lock statement on a value of type 'System.Threading.Lock' cannot be used in async methods or async lambda expressions. - // lock (new Lock()) { } - Diagnostic(ErrorCode.ERR_BadSpecialByRefLock, "new Lock()").WithLocation(6, 11)); + var expectedOutput = "ELD"; + var verifier = CompileAndVerify([source, LockTypeDefinition], options: TestOptions.DebugExe, + expectedOutput: expectedOutput, verify: Verification.FailsILVerify); + verifier.VerifyDiagnostics(); + verifier.VerifyIL("Program.<>c.<<
$>b__0_0>d.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext", """ + { + // Code size 94 (0x5e) + .maxstack 2 + .locals init (int V_0, + System.Threading.Lock.Scope V_1, + System.Exception V_2) + IL_0000: ldarg.0 + IL_0001: ldfld "int Program.<>c.<<
$>b__0_0>d.<>1__state" + IL_0006: stloc.0 + .try + { + IL_0007: nop + IL_0008: newobj "System.Threading.Lock..ctor()" + IL_000d: call "System.Threading.Lock.Scope System.Threading.Lock.EnterScope()" + IL_0012: stloc.1 + .try + { + IL_0013: nop + IL_0014: ldstr "L" + IL_0019: call "void System.Console.Write(string)" + IL_001e: nop + IL_001f: nop + IL_0020: leave.s IL_002f + } + finally + { + IL_0022: ldloc.0 + IL_0023: ldc.i4.0 + IL_0024: bge.s IL_002e + IL_0026: ldloca.s V_1 + IL_0028: call "void System.Threading.Lock.Scope.Dispose()" + IL_002d: nop + IL_002e: endfinally + } + IL_002f: leave.s IL_0049 + } + catch System.Exception + { + IL_0031: stloc.2 + IL_0032: ldarg.0 + IL_0033: ldc.i4.s -2 + IL_0035: stfld "int Program.<>c.<<
$>b__0_0>d.<>1__state" + IL_003a: ldarg.0 + IL_003b: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program.<>c.<<
$>b__0_0>d.<>t__builder" + IL_0040: ldloc.2 + IL_0041: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)" + IL_0046: nop + IL_0047: leave.s IL_005d + } + IL_0049: ldarg.0 + IL_004a: ldc.i4.s -2 + IL_004c: stfld "int Program.<>c.<<
$>b__0_0>d.<>1__state" + IL_0051: ldarg.0 + IL_0052: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program.<>c.<<
$>b__0_0>d.<>t__builder" + IL_0057: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetResult()" + IL_005c: nop + IL_005d: ret + } + """); + + verifier = CompileAndVerify([source, LockTypeDefinition], options: TestOptions.ReleaseExe, + expectedOutput: expectedOutput, verify: Verification.FailsILVerify); + verifier.VerifyDiagnostics(); + verifier.VerifyIL("Program.<>c.<<
$>b__0_0>d.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext", """ + { + // Code size 87 (0x57) + .maxstack 2 + .locals init (int V_0, + System.Threading.Lock.Scope V_1, + System.Exception V_2) + IL_0000: ldarg.0 + IL_0001: ldfld "int Program.<>c.<<
$>b__0_0>d.<>1__state" + IL_0006: stloc.0 + .try + { + IL_0007: newobj "System.Threading.Lock..ctor()" + IL_000c: call "System.Threading.Lock.Scope System.Threading.Lock.EnterScope()" + IL_0011: stloc.1 + .try + { + IL_0012: ldstr "L" + IL_0017: call "void System.Console.Write(string)" + IL_001c: leave.s IL_002a + } + finally + { + IL_001e: ldloc.0 + IL_001f: ldc.i4.0 + IL_0020: bge.s IL_0029 + IL_0022: ldloca.s V_1 + IL_0024: call "void System.Threading.Lock.Scope.Dispose()" + IL_0029: endfinally + } + IL_002a: leave.s IL_0043 + } + catch System.Exception + { + IL_002c: stloc.2 + IL_002d: ldarg.0 + IL_002e: ldc.i4.s -2 + IL_0030: stfld "int Program.<>c.<<
$>b__0_0>d.<>1__state" + IL_0035: ldarg.0 + IL_0036: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program.<>c.<<
$>b__0_0>d.<>t__builder" + IL_003b: ldloc.2 + IL_003c: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)" + IL_0041: leave.s IL_0056 + } + IL_0043: ldarg.0 + IL_0044: ldc.i4.s -2 + IL_0046: stfld "int Program.<>c.<<
$>b__0_0>d.<>1__state" + IL_004b: ldarg.0 + IL_004c: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program.<>c.<<
$>b__0_0>d.<>t__builder" + IL_0051: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetResult()" + IL_0056: ret + } + """); } [Fact] @@ -1981,13 +3128,301 @@ public void AsyncLambda_WithAwait() var lam = async () => { await Task.Yield(); - lock (new Lock()) { } + lock (new Lock()) { System.Console.Write("L"); } + await Task.Yield(); }; + + await lam(); """; - CreateCompilation([source, LockTypeDefinition]).VerifyDiagnostics( - // (7,11): error CS9217: A lock statement on a value of type 'System.Threading.Lock' cannot be used in async methods or async lambda expressions. - // lock (new Lock()) { } - Diagnostic(ErrorCode.ERR_BadSpecialByRefLock, "new Lock()").WithLocation(7, 11)); + var expectedOutput = "ELD"; + var verifier = CompileAndVerify([source, LockTypeDefinition], options: TestOptions.DebugExe, + expectedOutput: expectedOutput, verify: Verification.FailsILVerify); + verifier.VerifyDiagnostics(); + verifier.VerifyIL("Program.<>c.<<
$>b__0_0>d.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext", """ + { + // Code size 311 (0x137) + .maxstack 3 + .locals init (int V_0, + System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter V_1, + System.Runtime.CompilerServices.YieldAwaitable V_2, + Program.<>c.<<
$>b__0_0>d V_3, + System.Threading.Lock.Scope V_4, + System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter V_5, + System.Exception V_6) + IL_0000: ldarg.0 + IL_0001: ldfld "int Program.<>c.<<
$>b__0_0>d.<>1__state" + IL_0006: stloc.0 + .try + { + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0012 + IL_000a: br.s IL_000c + IL_000c: ldloc.0 + IL_000d: ldc.i4.1 + IL_000e: beq.s IL_0014 + IL_0010: br.s IL_0019 + IL_0012: br.s IL_0058 + IL_0014: br IL_00e1 + IL_0019: nop + IL_001a: call "System.Runtime.CompilerServices.YieldAwaitable System.Threading.Tasks.Task.Yield()" + IL_001f: stloc.2 + IL_0020: ldloca.s V_2 + IL_0022: call "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter System.Runtime.CompilerServices.YieldAwaitable.GetAwaiter()" + IL_0027: stloc.1 + IL_0028: ldloca.s V_1 + IL_002a: call "bool System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.IsCompleted.get" + IL_002f: brtrue.s IL_0074 + IL_0031: ldarg.0 + IL_0032: ldc.i4.0 + IL_0033: dup + IL_0034: stloc.0 + IL_0035: stfld "int Program.<>c.<<
$>b__0_0>d.<>1__state" + IL_003a: ldarg.0 + IL_003b: ldloc.1 + IL_003c: stfld "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Program.<>c.<<
$>b__0_0>d.<>u__1" + IL_0041: ldarg.0 + IL_0042: stloc.3 + IL_0043: ldarg.0 + IL_0044: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program.<>c.<<
$>b__0_0>d.<>t__builder" + IL_0049: ldloca.s V_1 + IL_004b: ldloca.s V_3 + IL_004d: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompletedc.<<
$>b__0_0>d>(ref System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter, ref Program.<>c.<<
$>b__0_0>d)" + IL_0052: nop + IL_0053: leave IL_0136 + IL_0058: ldarg.0 + IL_0059: ldfld "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Program.<>c.<<
$>b__0_0>d.<>u__1" + IL_005e: stloc.1 + IL_005f: ldarg.0 + IL_0060: ldflda "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Program.<>c.<<
$>b__0_0>d.<>u__1" + IL_0065: initobj "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter" + IL_006b: ldarg.0 + IL_006c: ldc.i4.m1 + IL_006d: dup + IL_006e: stloc.0 + IL_006f: stfld "int Program.<>c.<<
$>b__0_0>d.<>1__state" + IL_0074: ldloca.s V_1 + IL_0076: call "void System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.GetResult()" + IL_007b: nop + IL_007c: newobj "System.Threading.Lock..ctor()" + IL_0081: call "System.Threading.Lock.Scope System.Threading.Lock.EnterScope()" + IL_0086: stloc.s V_4 + .try + { + IL_0088: nop + IL_0089: ldstr "L" + IL_008e: call "void System.Console.Write(string)" + IL_0093: nop + IL_0094: nop + IL_0095: leave.s IL_00a4 + } + finally + { + IL_0097: ldloc.0 + IL_0098: ldc.i4.0 + IL_0099: bge.s IL_00a3 + IL_009b: ldloca.s V_4 + IL_009d: call "void System.Threading.Lock.Scope.Dispose()" + IL_00a2: nop + IL_00a3: endfinally + } + IL_00a4: call "System.Runtime.CompilerServices.YieldAwaitable System.Threading.Tasks.Task.Yield()" + IL_00a9: stloc.2 + IL_00aa: ldloca.s V_2 + IL_00ac: call "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter System.Runtime.CompilerServices.YieldAwaitable.GetAwaiter()" + IL_00b1: stloc.s V_5 + IL_00b3: ldloca.s V_5 + IL_00b5: call "bool System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.IsCompleted.get" + IL_00ba: brtrue.s IL_00fe + IL_00bc: ldarg.0 + IL_00bd: ldc.i4.1 + IL_00be: dup + IL_00bf: stloc.0 + IL_00c0: stfld "int Program.<>c.<<
$>b__0_0>d.<>1__state" + IL_00c5: ldarg.0 + IL_00c6: ldloc.s V_5 + IL_00c8: stfld "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Program.<>c.<<
$>b__0_0>d.<>u__1" + IL_00cd: ldarg.0 + IL_00ce: stloc.3 + IL_00cf: ldarg.0 + IL_00d0: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program.<>c.<<
$>b__0_0>d.<>t__builder" + IL_00d5: ldloca.s V_5 + IL_00d7: ldloca.s V_3 + IL_00d9: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompletedc.<<
$>b__0_0>d>(ref System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter, ref Program.<>c.<<
$>b__0_0>d)" + IL_00de: nop + IL_00df: leave.s IL_0136 + IL_00e1: ldarg.0 + IL_00e2: ldfld "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Program.<>c.<<
$>b__0_0>d.<>u__1" + IL_00e7: stloc.s V_5 + IL_00e9: ldarg.0 + IL_00ea: ldflda "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Program.<>c.<<
$>b__0_0>d.<>u__1" + IL_00ef: initobj "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter" + IL_00f5: ldarg.0 + IL_00f6: ldc.i4.m1 + IL_00f7: dup + IL_00f8: stloc.0 + IL_00f9: stfld "int Program.<>c.<<
$>b__0_0>d.<>1__state" + IL_00fe: ldloca.s V_5 + IL_0100: call "void System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.GetResult()" + IL_0105: nop + IL_0106: leave.s IL_0122 + } + catch System.Exception + { + IL_0108: stloc.s V_6 + IL_010a: ldarg.0 + IL_010b: ldc.i4.s -2 + IL_010d: stfld "int Program.<>c.<<
$>b__0_0>d.<>1__state" + IL_0112: ldarg.0 + IL_0113: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program.<>c.<<
$>b__0_0>d.<>t__builder" + IL_0118: ldloc.s V_6 + IL_011a: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)" + IL_011f: nop + IL_0120: leave.s IL_0136 + } + IL_0122: ldarg.0 + IL_0123: ldc.i4.s -2 + IL_0125: stfld "int Program.<>c.<<
$>b__0_0>d.<>1__state" + IL_012a: ldarg.0 + IL_012b: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program.<>c.<<
$>b__0_0>d.<>t__builder" + IL_0130: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetResult()" + IL_0135: nop + IL_0136: ret + } + """); + + verifier = CompileAndVerify([source, LockTypeDefinition], options: TestOptions.ReleaseExe, + expectedOutput: expectedOutput, verify: Verification.FailsILVerify); + verifier.VerifyDiagnostics(); + verifier.VerifyIL("Program.<>c.<<
$>b__0_0>d.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext", """ + { + // Code size 282 (0x11a) + .maxstack 3 + .locals init (int V_0, + System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter V_1, + System.Runtime.CompilerServices.YieldAwaitable V_2, + System.Threading.Lock.Scope V_3, + System.Exception V_4) + IL_0000: ldarg.0 + IL_0001: ldfld "int Program.<>c.<<
$>b__0_0>d.<>1__state" + IL_0006: stloc.0 + .try + { + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_004b + IL_000a: ldloc.0 + IL_000b: ldc.i4.1 + IL_000c: beq IL_00c8 + IL_0011: call "System.Runtime.CompilerServices.YieldAwaitable System.Threading.Tasks.Task.Yield()" + IL_0016: stloc.2 + IL_0017: ldloca.s V_2 + IL_0019: call "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter System.Runtime.CompilerServices.YieldAwaitable.GetAwaiter()" + IL_001e: stloc.1 + IL_001f: ldloca.s V_1 + IL_0021: call "bool System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.IsCompleted.get" + IL_0026: brtrue.s IL_0067 + IL_0028: ldarg.0 + IL_0029: ldc.i4.0 + IL_002a: dup + IL_002b: stloc.0 + IL_002c: stfld "int Program.<>c.<<
$>b__0_0>d.<>1__state" + IL_0031: ldarg.0 + IL_0032: ldloc.1 + IL_0033: stfld "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Program.<>c.<<
$>b__0_0>d.<>u__1" + IL_0038: ldarg.0 + IL_0039: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program.<>c.<<
$>b__0_0>d.<>t__builder" + IL_003e: ldloca.s V_1 + IL_0040: ldarg.0 + IL_0041: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompletedc.<<
$>b__0_0>d>(ref System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter, ref Program.<>c.<<
$>b__0_0>d)" + IL_0046: leave IL_0119 + IL_004b: ldarg.0 + IL_004c: ldfld "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Program.<>c.<<
$>b__0_0>d.<>u__1" + IL_0051: stloc.1 + IL_0052: ldarg.0 + IL_0053: ldflda "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Program.<>c.<<
$>b__0_0>d.<>u__1" + IL_0058: initobj "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter" + IL_005e: ldarg.0 + IL_005f: ldc.i4.m1 + IL_0060: dup + IL_0061: stloc.0 + IL_0062: stfld "int Program.<>c.<<
$>b__0_0>d.<>1__state" + IL_0067: ldloca.s V_1 + IL_0069: call "void System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.GetResult()" + IL_006e: newobj "System.Threading.Lock..ctor()" + IL_0073: call "System.Threading.Lock.Scope System.Threading.Lock.EnterScope()" + IL_0078: stloc.3 + .try + { + IL_0079: ldstr "L" + IL_007e: call "void System.Console.Write(string)" + IL_0083: leave.s IL_0091 + } + finally + { + IL_0085: ldloc.0 + IL_0086: ldc.i4.0 + IL_0087: bge.s IL_0090 + IL_0089: ldloca.s V_3 + IL_008b: call "void System.Threading.Lock.Scope.Dispose()" + IL_0090: endfinally + } + IL_0091: call "System.Runtime.CompilerServices.YieldAwaitable System.Threading.Tasks.Task.Yield()" + IL_0096: stloc.2 + IL_0097: ldloca.s V_2 + IL_0099: call "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter System.Runtime.CompilerServices.YieldAwaitable.GetAwaiter()" + IL_009e: stloc.1 + IL_009f: ldloca.s V_1 + IL_00a1: call "bool System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.IsCompleted.get" + IL_00a6: brtrue.s IL_00e4 + IL_00a8: ldarg.0 + IL_00a9: ldc.i4.1 + IL_00aa: dup + IL_00ab: stloc.0 + IL_00ac: stfld "int Program.<>c.<<
$>b__0_0>d.<>1__state" + IL_00b1: ldarg.0 + IL_00b2: ldloc.1 + IL_00b3: stfld "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Program.<>c.<<
$>b__0_0>d.<>u__1" + IL_00b8: ldarg.0 + IL_00b9: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program.<>c.<<
$>b__0_0>d.<>t__builder" + IL_00be: ldloca.s V_1 + IL_00c0: ldarg.0 + IL_00c1: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompletedc.<<
$>b__0_0>d>(ref System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter, ref Program.<>c.<<
$>b__0_0>d)" + IL_00c6: leave.s IL_0119 + IL_00c8: ldarg.0 + IL_00c9: ldfld "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Program.<>c.<<
$>b__0_0>d.<>u__1" + IL_00ce: stloc.1 + IL_00cf: ldarg.0 + IL_00d0: ldflda "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Program.<>c.<<
$>b__0_0>d.<>u__1" + IL_00d5: initobj "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter" + IL_00db: ldarg.0 + IL_00dc: ldc.i4.m1 + IL_00dd: dup + IL_00de: stloc.0 + IL_00df: stfld "int Program.<>c.<<
$>b__0_0>d.<>1__state" + IL_00e4: ldloca.s V_1 + IL_00e6: call "void System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.GetResult()" + IL_00eb: leave.s IL_0106 + } + catch System.Exception + { + IL_00ed: stloc.s V_4 + IL_00ef: ldarg.0 + IL_00f0: ldc.i4.s -2 + IL_00f2: stfld "int Program.<>c.<<
$>b__0_0>d.<>1__state" + IL_00f7: ldarg.0 + IL_00f8: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program.<>c.<<
$>b__0_0>d.<>t__builder" + IL_00fd: ldloc.s V_4 + IL_00ff: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)" + IL_0104: leave.s IL_0119 + } + IL_0106: ldarg.0 + IL_0107: ldc.i4.s -2 + IL_0109: stfld "int Program.<>c.<<
$>b__0_0>d.<>1__state" + IL_010e: ldarg.0 + IL_010f: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program.<>c.<<
$>b__0_0>d.<>t__builder" + IL_0114: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetResult()" + IL_0119: ret + } + """); } [Fact] @@ -2011,14 +3446,95 @@ IEnumerable M() } """; CreateCompilation([source, LockTypeDefinition]).VerifyEmitDiagnostics( - // (9,15): error CS4013: Instance of type 'Lock.Scope' cannot be used inside a nested function, query expression, iterator block or async method + // (9,15): error CS4007: Instance of type 'System.Threading.Lock.Scope' cannot be preserved across 'await' or 'yield' boundary. // lock (new Lock()) - Diagnostic(ErrorCode.ERR_SpecialByRefInLambda, "new Lock()").WithArguments("System.Threading.Lock.Scope").WithLocation(9, 15), + Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "new Lock()").WithArguments("System.Threading.Lock.Scope").WithLocation(9, 15), // (11,13): warning CS9230: 'yield return' should not be used in the body of a lock statement // yield return 2; Diagnostic(ErrorCode.WRN_BadYieldInLock, "yield").WithLocation(11, 13)); } + [Fact] + public void Yield_Break() + { + var source = """ + #pragma warning disable CS0162 // Unreachable code detected + using System; + using System.Collections.Generic; + using System.Threading; + + static class Program + { + static void Main() + { + foreach (var x in M()) + { + Console.Write(x); + } + } + + static IEnumerable M() + { + yield return 1; + lock (new Lock()) + { + Console.Write("L"); + yield break; + Console.Write("B"); + } + yield return 2; + } + } + """; + var expectedOutput = "1ELD"; + var verifier = CompileAndVerify([source, LockTypeDefinition], options: TestOptions.ReleaseExe, + verify: Verification.FailsILVerify, expectedOutput: expectedOutput); + verifier.VerifyDiagnostics(); + + verifier = CompileAndVerify([source, LockTypeDefinition], options: TestOptions.DebugExe, + verify: Verification.FailsILVerify, expectedOutput: expectedOutput); + verifier.VerifyDiagnostics(); + } + + [Fact] + public void Yield_AroundOnly() + { + var source = """ + using System; + using System.Collections.Generic; + using System.Threading; + + static class Program + { + static void Main() + { + foreach (var x in M()) + { + Console.Write(x); + } + } + + static IEnumerable M() + { + yield return 1; + lock (new Lock()) + { + Console.Write("L"); + } + yield return 2; + } + } + """; + var expectedOutput = "1ELD2"; + var verifier = CompileAndVerify([source, LockTypeDefinition], options: TestOptions.ReleaseExe, + verify: Verification.FailsILVerify, expectedOutput: expectedOutput); + verifier.VerifyDiagnostics(); + + verifier = CompileAndVerify([source, LockTypeDefinition], options: TestOptions.DebugExe, + verify: Verification.FailsILVerify, expectedOutput: expectedOutput); + verifier.VerifyDiagnostics(); + } + [Fact] public void Yield_Async() { @@ -2041,15 +3557,457 @@ async IAsyncEnumerable M() } } """; - CreateCompilationWithTasksExtensions([source, LockTypeDefinition, AsyncStreamsTypes]).VerifyDiagnostics( - // (10,15): error CS9217: A lock statement on a value of type 'System.Threading.Lock' cannot be used in async methods or async lambda expressions. + CreateCompilationWithTasksExtensions([source, LockTypeDefinition, AsyncStreamsTypes]).VerifyEmitDiagnostics( + // (10,15): error CS4007: Instance of type 'System.Threading.Lock.Scope' cannot be preserved across 'await' or 'yield' boundary. // lock (new Lock()) - Diagnostic(ErrorCode.ERR_BadSpecialByRefLock, "new Lock()").WithLocation(10, 15), + Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "new Lock()").WithArguments("System.Threading.Lock.Scope").WithLocation(10, 15), // (12,13): warning CS9230: 'yield return' should not be used in the body of a lock statement // yield return 2; Diagnostic(ErrorCode.WRN_BadYieldInLock, "yield").WithLocation(12, 13)); } + [Fact] + public void Yield_Async_Break() + { + var source = """ + #pragma warning disable CS0162 // Unreachable code detected + using System; + using System.Collections.Generic; + using System.Threading; + using System.Threading.Tasks; + + static class Program + { + static async Task Main() + { + await foreach (var x in M()) + { + Console.Write(x); + } + } + + async static IAsyncEnumerable M() + { + yield return 1; + await Task.Yield(); + lock (new Lock()) + { + Console.Write("L"); + yield break; + Console.Write("B"); + } + await Task.Yield(); + yield return 2; + } + } + """; + var expectedOutput = "1ELD"; + var comp = CreateCompilationWithTasksExtensions([source, LockTypeDefinition, AsyncStreamsTypes], options: TestOptions.ReleaseExe); + var verifier = CompileAndVerify(comp, verify: Verification.FailsILVerify, expectedOutput: expectedOutput); + verifier.VerifyDiagnostics(); + + comp = CreateCompilationWithTasksExtensions([source, LockTypeDefinition, AsyncStreamsTypes], options: TestOptions.DebugExe); + verifier = CompileAndVerify(comp, verify: Verification.FailsILVerify, expectedOutput: expectedOutput); + verifier.VerifyDiagnostics(); + } + + [Fact] + public void Yield_Async_AroundOnly() + { + var source = """ + using System; + using System.Collections.Generic; + using System.Threading; + using System.Threading.Tasks; + + static class Program + { + static async Task Main() + { + await foreach (var x in M()) + { + Console.Write(x); + } + } + + static async IAsyncEnumerable M() + { + yield return 1; + lock (new Lock()) + { + Console.Write("L"); + } + await Task.Yield(); + yield return 2; + } + } + """; + var expectedOutput = "1ELD2"; + var comp = CreateCompilationWithTasksExtensions([source, LockTypeDefinition, AsyncStreamsTypes], options: TestOptions.DebugExe); + var verifier = CompileAndVerify(comp, expectedOutput: expectedOutput, verify: Verification.FailsILVerify); + verifier.VerifyDiagnostics(); + verifier.VerifyIL("Program.d__1.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext", """ + { + // Code size 414 (0x19e) + .maxstack 3 + .locals init (int V_0, + System.Threading.Lock.Scope V_1, + System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter V_2, + System.Runtime.CompilerServices.YieldAwaitable V_3, + Program.d__1 V_4, + System.Exception V_5) + IL_0000: ldarg.0 + IL_0001: ldfld "int Program.d__1.<>1__state" + IL_0006: stloc.0 + .try + { + IL_0007: ldloc.0 + IL_0008: ldc.i4.s -5 + IL_000a: sub + IL_000b: switch ( + IL_002a, + IL_002f, + IL_0031, + IL_0038, + IL_0038, + IL_0033) + IL_0028: br.s IL_0038 + IL_002a: br IL_0125 + IL_002f: br.s IL_0065 + IL_0031: br.s IL_0038 + IL_0033: br IL_00ee + IL_0038: ldarg.0 + IL_0039: ldfld "bool Program.d__1.<>w__disposeMode" + IL_003e: brfalse.s IL_0045 + IL_0040: leave IL_0167 + IL_0045: ldarg.0 + IL_0046: ldc.i4.m1 + IL_0047: dup + IL_0048: stloc.0 + IL_0049: stfld "int Program.d__1.<>1__state" + IL_004e: nop + IL_004f: ldarg.0 + IL_0050: ldc.i4.1 + IL_0051: stfld "int Program.d__1.<>2__current" + IL_0056: ldarg.0 + IL_0057: ldc.i4.s -4 + IL_0059: dup + IL_005a: stloc.0 + IL_005b: stfld "int Program.d__1.<>1__state" + IL_0060: leave IL_0190 + IL_0065: ldarg.0 + IL_0066: ldc.i4.m1 + IL_0067: dup + IL_0068: stloc.0 + IL_0069: stfld "int Program.d__1.<>1__state" + IL_006e: ldarg.0 + IL_006f: ldfld "bool Program.d__1.<>w__disposeMode" + IL_0074: brfalse.s IL_007b + IL_0076: leave IL_0167 + IL_007b: newobj "System.Threading.Lock..ctor()" + IL_0080: call "System.Threading.Lock.Scope System.Threading.Lock.EnterScope()" + IL_0085: stloc.1 + .try + { + IL_0086: nop + IL_0087: ldstr "L" + IL_008c: call "void System.Console.Write(string)" + IL_0091: nop + IL_0092: nop + IL_0093: leave.s IL_00a2 + } + finally + { + IL_0095: ldloc.0 + IL_0096: ldc.i4.m1 + IL_0097: bne.un.s IL_00a1 + IL_0099: ldloca.s V_1 + IL_009b: call "void System.Threading.Lock.Scope.Dispose()" + IL_00a0: nop + IL_00a1: endfinally + } + IL_00a2: ldarg.0 + IL_00a3: ldfld "bool Program.d__1.<>w__disposeMode" + IL_00a8: brfalse.s IL_00af + IL_00aa: leave IL_0167 + IL_00af: call "System.Runtime.CompilerServices.YieldAwaitable System.Threading.Tasks.Task.Yield()" + IL_00b4: stloc.3 + IL_00b5: ldloca.s V_3 + IL_00b7: call "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter System.Runtime.CompilerServices.YieldAwaitable.GetAwaiter()" + IL_00bc: stloc.2 + IL_00bd: ldloca.s V_2 + IL_00bf: call "bool System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.IsCompleted.get" + IL_00c4: brtrue.s IL_010a + IL_00c6: ldarg.0 + IL_00c7: ldc.i4.0 + IL_00c8: dup + IL_00c9: stloc.0 + IL_00ca: stfld "int Program.d__1.<>1__state" + IL_00cf: ldarg.0 + IL_00d0: ldloc.2 + IL_00d1: stfld "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Program.d__1.<>u__1" + IL_00d6: ldarg.0 + IL_00d7: stloc.s V_4 + IL_00d9: ldarg.0 + IL_00da: ldflda "System.Runtime.CompilerServices.AsyncIteratorMethodBuilder Program.d__1.<>t__builder" + IL_00df: ldloca.s V_2 + IL_00e1: ldloca.s V_4 + IL_00e3: call "void System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.AwaitUnsafeOnCompletedd__1>(ref System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter, ref Program.d__1)" + IL_00e8: nop + IL_00e9: leave IL_019d + IL_00ee: ldarg.0 + IL_00ef: ldfld "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Program.d__1.<>u__1" + IL_00f4: stloc.2 + IL_00f5: ldarg.0 + IL_00f6: ldflda "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Program.d__1.<>u__1" + IL_00fb: initobj "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter" + IL_0101: ldarg.0 + IL_0102: ldc.i4.m1 + IL_0103: dup + IL_0104: stloc.0 + IL_0105: stfld "int Program.d__1.<>1__state" + IL_010a: ldloca.s V_2 + IL_010c: call "void System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.GetResult()" + IL_0111: nop + IL_0112: ldarg.0 + IL_0113: ldc.i4.2 + IL_0114: stfld "int Program.d__1.<>2__current" + IL_0119: ldarg.0 + IL_011a: ldc.i4.s -5 + IL_011c: dup + IL_011d: stloc.0 + IL_011e: stfld "int Program.d__1.<>1__state" + IL_0123: leave.s IL_0190 + IL_0125: ldarg.0 + IL_0126: ldc.i4.m1 + IL_0127: dup + IL_0128: stloc.0 + IL_0129: stfld "int Program.d__1.<>1__state" + IL_012e: ldarg.0 + IL_012f: ldfld "bool Program.d__1.<>w__disposeMode" + IL_0134: brfalse.s IL_0138 + IL_0136: leave.s IL_0167 + IL_0138: leave.s IL_0167 + } + catch System.Exception + { + IL_013a: stloc.s V_5 + IL_013c: ldarg.0 + IL_013d: ldc.i4.s -2 + IL_013f: stfld "int Program.d__1.<>1__state" + IL_0144: ldarg.0 + IL_0145: ldc.i4.0 + IL_0146: stfld "int Program.d__1.<>2__current" + IL_014b: ldarg.0 + IL_014c: ldflda "System.Runtime.CompilerServices.AsyncIteratorMethodBuilder Program.d__1.<>t__builder" + IL_0151: call "void System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.Complete()" + IL_0156: nop + IL_0157: ldarg.0 + IL_0158: ldflda "System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore Program.d__1.<>v__promiseOfValueOrEnd" + IL_015d: ldloc.s V_5 + IL_015f: call "void System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore.SetException(System.Exception)" + IL_0164: nop + IL_0165: leave.s IL_019d + } + IL_0167: ldarg.0 + IL_0168: ldc.i4.s -2 + IL_016a: stfld "int Program.d__1.<>1__state" + IL_016f: ldarg.0 + IL_0170: ldc.i4.0 + IL_0171: stfld "int Program.d__1.<>2__current" + IL_0176: ldarg.0 + IL_0177: ldflda "System.Runtime.CompilerServices.AsyncIteratorMethodBuilder Program.d__1.<>t__builder" + IL_017c: call "void System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.Complete()" + IL_0181: nop + IL_0182: ldarg.0 + IL_0183: ldflda "System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore Program.d__1.<>v__promiseOfValueOrEnd" + IL_0188: ldc.i4.0 + IL_0189: call "void System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore.SetResult(bool)" + IL_018e: nop + IL_018f: ret + IL_0190: ldarg.0 + IL_0191: ldflda "System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore Program.d__1.<>v__promiseOfValueOrEnd" + IL_0196: ldc.i4.1 + IL_0197: call "void System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore.SetResult(bool)" + IL_019c: nop + IL_019d: ret + } + """); + + comp = CreateCompilationWithTasksExtensions([source, LockTypeDefinition, AsyncStreamsTypes], options: TestOptions.ReleaseExe); + verifier = CompileAndVerify(comp, expectedOutput: expectedOutput, verify: Verification.FailsILVerify); + verifier.VerifyDiagnostics(); + verifier.VerifyIL("Program.d__1.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext", """ + { + // Code size 383 (0x17f) + .maxstack 3 + .locals init (int V_0, + System.Threading.Lock.Scope V_1, + System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter V_2, + System.Runtime.CompilerServices.YieldAwaitable V_3, + Program.d__1 V_4, + System.Exception V_5) + IL_0000: ldarg.0 + IL_0001: ldfld "int Program.d__1.<>1__state" + IL_0006: stloc.0 + .try + { + IL_0007: ldloc.0 + IL_0008: ldc.i4.s -5 + IL_000a: sub + IL_000b: switch ( + IL_010e, + IL_0054, + IL_0028, + IL_0028, + IL_0028, + IL_00d8) + IL_0028: ldarg.0 + IL_0029: ldfld "bool Program.d__1.<>w__disposeMode" + IL_002e: brfalse.s IL_0035 + IL_0030: leave IL_014b + IL_0035: ldarg.0 + IL_0036: ldc.i4.m1 + IL_0037: dup + IL_0038: stloc.0 + IL_0039: stfld "int Program.d__1.<>1__state" + IL_003e: ldarg.0 + IL_003f: ldc.i4.1 + IL_0040: stfld "int Program.d__1.<>2__current" + IL_0045: ldarg.0 + IL_0046: ldc.i4.s -4 + IL_0048: dup + IL_0049: stloc.0 + IL_004a: stfld "int Program.d__1.<>1__state" + IL_004f: leave IL_0172 + IL_0054: ldarg.0 + IL_0055: ldc.i4.m1 + IL_0056: dup + IL_0057: stloc.0 + IL_0058: stfld "int Program.d__1.<>1__state" + IL_005d: ldarg.0 + IL_005e: ldfld "bool Program.d__1.<>w__disposeMode" + IL_0063: brfalse.s IL_006a + IL_0065: leave IL_014b + IL_006a: newobj "System.Threading.Lock..ctor()" + IL_006f: call "System.Threading.Lock.Scope System.Threading.Lock.EnterScope()" + IL_0074: stloc.1 + .try + { + IL_0075: ldstr "L" + IL_007a: call "void System.Console.Write(string)" + IL_007f: leave.s IL_008d + } + finally + { + IL_0081: ldloc.0 + IL_0082: ldc.i4.m1 + IL_0083: bne.un.s IL_008c + IL_0085: ldloca.s V_1 + IL_0087: call "void System.Threading.Lock.Scope.Dispose()" + IL_008c: endfinally + } + IL_008d: ldarg.0 + IL_008e: ldfld "bool Program.d__1.<>w__disposeMode" + IL_0093: brfalse.s IL_009a + IL_0095: leave IL_014b + IL_009a: call "System.Runtime.CompilerServices.YieldAwaitable System.Threading.Tasks.Task.Yield()" + IL_009f: stloc.3 + IL_00a0: ldloca.s V_3 + IL_00a2: call "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter System.Runtime.CompilerServices.YieldAwaitable.GetAwaiter()" + IL_00a7: stloc.2 + IL_00a8: ldloca.s V_2 + IL_00aa: call "bool System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.IsCompleted.get" + IL_00af: brtrue.s IL_00f4 + IL_00b1: ldarg.0 + IL_00b2: ldc.i4.0 + IL_00b3: dup + IL_00b4: stloc.0 + IL_00b5: stfld "int Program.d__1.<>1__state" + IL_00ba: ldarg.0 + IL_00bb: ldloc.2 + IL_00bc: stfld "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Program.d__1.<>u__1" + IL_00c1: ldarg.0 + IL_00c2: stloc.s V_4 + IL_00c4: ldarg.0 + IL_00c5: ldflda "System.Runtime.CompilerServices.AsyncIteratorMethodBuilder Program.d__1.<>t__builder" + IL_00ca: ldloca.s V_2 + IL_00cc: ldloca.s V_4 + IL_00ce: call "void System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.AwaitUnsafeOnCompletedd__1>(ref System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter, ref Program.d__1)" + IL_00d3: leave IL_017e + IL_00d8: ldarg.0 + IL_00d9: ldfld "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Program.d__1.<>u__1" + IL_00de: stloc.2 + IL_00df: ldarg.0 + IL_00e0: ldflda "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter Program.d__1.<>u__1" + IL_00e5: initobj "System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter" + IL_00eb: ldarg.0 + IL_00ec: ldc.i4.m1 + IL_00ed: dup + IL_00ee: stloc.0 + IL_00ef: stfld "int Program.d__1.<>1__state" + IL_00f4: ldloca.s V_2 + IL_00f6: call "void System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.GetResult()" + IL_00fb: ldarg.0 + IL_00fc: ldc.i4.2 + IL_00fd: stfld "int Program.d__1.<>2__current" + IL_0102: ldarg.0 + IL_0103: ldc.i4.s -5 + IL_0105: dup + IL_0106: stloc.0 + IL_0107: stfld "int Program.d__1.<>1__state" + IL_010c: leave.s IL_0172 + IL_010e: ldarg.0 + IL_010f: ldc.i4.m1 + IL_0110: dup + IL_0111: stloc.0 + IL_0112: stfld "int Program.d__1.<>1__state" + IL_0117: ldarg.0 + IL_0118: ldfld "bool Program.d__1.<>w__disposeMode" + IL_011d: pop + IL_011e: leave.s IL_014b + } + catch System.Exception + { + IL_0120: stloc.s V_5 + IL_0122: ldarg.0 + IL_0123: ldc.i4.s -2 + IL_0125: stfld "int Program.d__1.<>1__state" + IL_012a: ldarg.0 + IL_012b: ldc.i4.0 + IL_012c: stfld "int Program.d__1.<>2__current" + IL_0131: ldarg.0 + IL_0132: ldflda "System.Runtime.CompilerServices.AsyncIteratorMethodBuilder Program.d__1.<>t__builder" + IL_0137: call "void System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.Complete()" + IL_013c: ldarg.0 + IL_013d: ldflda "System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore Program.d__1.<>v__promiseOfValueOrEnd" + IL_0142: ldloc.s V_5 + IL_0144: call "void System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore.SetException(System.Exception)" + IL_0149: leave.s IL_017e + } + IL_014b: ldarg.0 + IL_014c: ldc.i4.s -2 + IL_014e: stfld "int Program.d__1.<>1__state" + IL_0153: ldarg.0 + IL_0154: ldc.i4.0 + IL_0155: stfld "int Program.d__1.<>2__current" + IL_015a: ldarg.0 + IL_015b: ldflda "System.Runtime.CompilerServices.AsyncIteratorMethodBuilder Program.d__1.<>t__builder" + IL_0160: call "void System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.Complete()" + IL_0165: ldarg.0 + IL_0166: ldflda "System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore Program.d__1.<>v__promiseOfValueOrEnd" + IL_016b: ldc.i4.0 + IL_016c: call "void System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore.SetResult(bool)" + IL_0171: ret + IL_0172: ldarg.0 + IL_0173: ldflda "System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore Program.d__1.<>v__promiseOfValueOrEnd" + IL_0178: ldc.i4.1 + IL_0179: call "void System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore.SetResult(bool)" + IL_017e: ret + } + """); + } + [Theory, CombinatorialData] public void CastToObject([CombinatorialValues("object ", "dynamic")] string type) { diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/OutVarTests.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/OutVarTests.cs index 1c2c8c2f59050..213a94c3598ea 100644 --- a/src/Compilers/CSharp/Test/Emit2/Semantics/OutVarTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Semantics/OutVarTests.cs @@ -19581,9 +19581,9 @@ static void Test2(object x, System.ArgIterator y) // (11,25): error CS1601: Cannot make reference to variable of type 'ArgIterator' // static object Test1(out System.ArgIterator x) Diagnostic(ErrorCode.ERR_MethodArgCantBeRefAny, "out System.ArgIterator x").WithArguments("System.ArgIterator").WithLocation(11, 25), - // (8,25): error CS4012: Parameters or locals of type 'ArgIterator' cannot be declared in async methods or async lambda expressions. + // (8,25): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // Test2(Test1(out var x1), x1); - Diagnostic(ErrorCode.ERR_BadSpecialByRefLocal, "var").WithArguments("System.ArgIterator").WithLocation(8, 25), + Diagnostic(ErrorCode.ERR_FeatureInPreview, "var").WithArguments("ref and unsafe in async and iterator methods").WithLocation(8, 25), // (6,16): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread. // async void Test() Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "Test").WithLocation(6, 16) @@ -19630,12 +19630,12 @@ static void Test2(object x, System.ArgIterator y) // (12,25): error CS1601: Cannot make reference to variable of type 'ArgIterator' // static object Test1(out System.ArgIterator x) Diagnostic(ErrorCode.ERR_MethodArgCantBeRefAny, "out System.ArgIterator x").WithArguments("System.ArgIterator").WithLocation(12, 25), - // (8,25): error CS4012: Parameters or locals of type 'ArgIterator' cannot be declared in async methods or async lambda expressions. + // (8,25): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // Test2(Test1(out System.ArgIterator x1), x1); - Diagnostic(ErrorCode.ERR_BadSpecialByRefLocal, "System.ArgIterator").WithArguments("System.ArgIterator").WithLocation(8, 25), - // (9,9): error CS4012: Parameters or locals of type 'ArgIterator' cannot be declared in async methods or async lambda expressions. + Diagnostic(ErrorCode.ERR_FeatureInPreview, "System.ArgIterator").WithArguments("ref and unsafe in async and iterator methods").WithLocation(8, 25), + // (9,9): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // var x = default(System.ArgIterator); - Diagnostic(ErrorCode.ERR_BadSpecialByRefLocal, "var").WithArguments("System.ArgIterator").WithLocation(9, 9), + Diagnostic(ErrorCode.ERR_FeatureInPreview, "var").WithArguments("ref and unsafe in async and iterator methods").WithLocation(9, 9), // (9,13): warning CS0219: The variable 'x' is assigned but its value is never used // var x = default(System.ArgIterator); Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "x").WithArguments("x").WithLocation(9, 13), diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/AwaitExpressionTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/AwaitExpressionTests.cs index 58b403f3ed35f..0cdb4221d7784 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/AwaitExpressionTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/AwaitExpressionTests.cs @@ -241,9 +241,9 @@ static async Task Goo() }"; var comp = CreateCompilationWithMscorlib45(text, options: TestOptions.ReleaseDll); comp.VerifyEmitDiagnostics( - // (8,27): error CS4007: 'await' cannot be used in an expression containing the type 'System.TypedReference' + // (8,27): error CS4007: Instance of type 'System.TypedReference' cannot be preserved across 'await' or 'yield' boundary. // Console.WriteLine(new TypedReference().Equals(await Task.FromResult(0))); - Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "await Task.FromResult(0)").WithArguments("System.TypedReference").WithLocation(8, 55)); + Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "new TypedReference()").WithArguments("System.TypedReference").WithLocation(8, 27)); } [Fact] diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/BindingAsyncTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/BindingAsyncTests.cs index 740346725b17a..8e550a2a565e8 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/BindingAsyncTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/BindingAsyncTests.cs @@ -3218,9 +3218,9 @@ async Task M1(TypedReference tr) } }"; CreateCompilationWithMscorlib45(source).VerifyDiagnostics( - // (7,34): error CS4012: Parameters or locals of type 'System.TypedReference' cannot be declared in async methods or async lambda expressions + // (7,34): error CS4012: Parameters of type 'System.TypedReference' cannot be declared in async methods or async lambda expressions // async Task M1(TypedReference tr) - Diagnostic(ErrorCode.ERR_BadSpecialByRefLocal, "tr").WithArguments("System.TypedReference")); + Diagnostic(ErrorCode.ERR_BadSpecialByRefParameter, "tr").WithArguments("System.TypedReference")); } [Fact] @@ -3238,10 +3238,7 @@ async Task M1() await Task.Factory.StartNew(() => { }); } }"; - CreateCompilationWithMscorlib45(source).VerifyDiagnostics( - // (9,9): error CS4012: Parameters or locals of type 'System.TypedReference' cannot be declared in async methods or async lambda expressions - // TypedReference tr; - Diagnostic(ErrorCode.ERR_BadSpecialByRefLocal, "TypedReference").WithArguments("System.TypedReference"), + CreateCompilationWithMscorlib45(source).VerifyEmitDiagnostics( // (9,24): warning CS0168: The variable 'tr' is declared but never used // TypedReference tr; Diagnostic(ErrorCode.WRN_UnreferencedVar, "tr").WithArguments("tr")); @@ -3257,18 +3254,33 @@ public void BadSpecialByRefVarDeclLocal() class Test { async Task M1(bool truth) + { + var tr = new TypedReference(); // 1 + await Task.Factory.StartNew(() => { }); + } + + async Task M2(bool truth) { var tr = new TypedReference(); await Task.Factory.StartNew(() => { }); + var tr2 = tr; // 2 + } + + async Task M3() + { + var tr = new TypedReference(); + await Task.Factory.StartNew(() => { }); + tr = default; + var tr2 = tr; } }"; - CreateCompilationWithMscorlib45(source).VerifyDiagnostics( - // (9,9): error CS4012: Parameters or locals of type 'TypedReference' cannot be declared in async methods or async lambda expressions. - // var tr = new TypedReference(); - Diagnostic(ErrorCode.ERR_BadSpecialByRefLocal, "var").WithArguments("System.TypedReference").WithLocation(9, 9), + CreateCompilationWithMscorlib45(source).VerifyEmitDiagnostics( // (9,13): warning CS0219: The variable 'tr' is assigned but its value is never used - // var tr = new TypedReference(); - Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "tr").WithArguments("tr").WithLocation(9, 13)); + // var tr = new TypedReference(); // 1 + Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "tr").WithArguments("tr").WithLocation(9, 13), + // (17,19): error CS4007: Instance of type 'System.TypedReference' cannot be preserved across 'await' or 'yield' boundary. + // var tr2 = tr; // 2 + Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "tr").WithArguments("System.TypedReference").WithLocation(17, 19)); } [Fact] @@ -3288,9 +3300,6 @@ unsafe async public static void F() // (8,31): error CS0209: The type of a local declared in a fixed statement must be a pointer type // fixed (TypedReference tr) { } Diagnostic(ErrorCode.ERR_BadFixedInitType, "tr"), - // (8,16): error CS4012: Parameters or locals of type 'System.TypedReference' cannot be declared in async methods or async lambda expressions. - // fixed (TypedReference tr) { } - Diagnostic(ErrorCode.ERR_BadSpecialByRefLocal, "TypedReference").WithArguments("System.TypedReference"), // (8,31): error CS0210: You must provide an initializer in a fixed or using statement declaration // fixed (TypedReference tr) { } Diagnostic(ErrorCode.ERR_FixedMustInit, "tr"), diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/ForEachTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/ForEachTests.cs index bb59d99fef196..fd120694a384c 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/ForEachTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/ForEachTests.cs @@ -3531,10 +3531,7 @@ public async static Task Test() System.Console.Write(x); } } -}").VerifyDiagnostics( - // (20,26): error CS8177: Async methods cannot have by-reference locals - // foreach (ref int x in new E()) - Diagnostic(ErrorCode.ERR_BadAsyncLocalType, "x").WithLocation(20, 26)); +}").VerifyEmitDiagnostics(); } [Fact] @@ -3565,10 +3562,7 @@ public async static Task Test() System.Console.Write(x); } } -}").VerifyDiagnostics( - // (20,35): error CS8177: Async methods cannot have by-reference locals - // foreach (ref readonly int x in new E()) - Diagnostic(ErrorCode.ERR_BadAsyncLocalType, "x").WithLocation(20, 35)); +}").VerifyEmitDiagnostics(); } [Fact] @@ -3597,10 +3591,7 @@ public static IEnumerable Test() yield return x; } } -}").VerifyDiagnostics( - // (18,26): error CS8176: Iterators cannot have by-reference locals - // foreach (ref int x in new E()) - Diagnostic(ErrorCode.ERR_BadIteratorLocalType, "x").WithLocation(18, 26)); +}").VerifyEmitDiagnostics(); } [Fact] @@ -3629,10 +3620,7 @@ public static IEnumerable Test() yield return x; } } -}").VerifyDiagnostics( - // (18,35): error CS8176: Iterators cannot have by-reference locals - // foreach (ref readonly int x in new E()) - Diagnostic(ErrorCode.ERR_BadIteratorLocalType, "x").WithLocation(18, 35)); +}").VerifyEmitDiagnostics(); } [Fact] diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/LambdaTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/LambdaTests.cs index 9b2f16c772425..2b32616b85553 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/LambdaTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/LambdaTests.cs @@ -5981,15 +5981,15 @@ static void Main() }"; var comp = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); comp.VerifyDiagnostics( - // (10,39): error CS4012: Parameters or locals of type 'TypedReference' cannot be declared in async methods or async lambda expressions. + // (10,39): error CS4012: Parameters of type 'TypedReference' cannot be declared in async methods or async lambda expressions. // D1 d1 = async (TypedReference r) => { await Task.Yield(); }; - Diagnostic(ErrorCode.ERR_BadSpecialByRefLocal, "r").WithArguments("System.TypedReference").WithLocation(10, 39), - // (11,46): error CS4012: Parameters or locals of type 'RuntimeArgumentHandle' cannot be declared in async methods or async lambda expressions. + Diagnostic(ErrorCode.ERR_BadSpecialByRefParameter, "r").WithArguments("System.TypedReference").WithLocation(10, 39), + // (11,46): error CS4012: Parameters of type 'RuntimeArgumentHandle' cannot be declared in async methods or async lambda expressions. // D2 d2 = async (RuntimeArgumentHandle h) => { await Task.Yield(); }; - Diagnostic(ErrorCode.ERR_BadSpecialByRefLocal, "h").WithArguments("System.RuntimeArgumentHandle").WithLocation(11, 46), - // (12,36): error CS4012: Parameters or locals of type 'ArgIterator' cannot be declared in async methods or async lambda expressions. + Diagnostic(ErrorCode.ERR_BadSpecialByRefParameter, "h").WithArguments("System.RuntimeArgumentHandle").WithLocation(11, 46), + // (12,36): error CS4012: Parameters of type 'ArgIterator' cannot be declared in async methods or async lambda expressions. // D3 d3 = async (ArgIterator i) => { await Task.Yield(); }; - Diagnostic(ErrorCode.ERR_BadSpecialByRefLocal, "i").WithArguments("System.ArgIterator").WithLocation(12, 36)); + Diagnostic(ErrorCode.ERR_BadSpecialByRefParameter, "i").WithArguments("System.ArgIterator").WithLocation(12, 36)); } [Fact] diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/LocalFunctionTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/LocalFunctionTests.cs index 74f8efa9b607c..d135ca3ae11dd 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/LocalFunctionTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/LocalFunctionTests.cs @@ -3516,7 +3516,7 @@ static void Main() // (10,31): error CS0190: The __arglist construct is valid only within a variable argument method // Console.WriteLine(__arglist); Diagnostic(ErrorCode.ERR_ArgsInvalid, "__arglist").WithLocation(10, 31), - // (18,31): error CS4013: Instance of type 'RuntimeArgumentHandle' cannot be used inside an anonymous function, query expression, iterator block or async method + // (18,31): error CS4013: Instance of type 'RuntimeArgumentHandle' cannot be used inside a nested function, query expression, iterator block or async method // Console.WriteLine(__arglist); Diagnostic(ErrorCode.ERR_SpecialByRefInLambda, "__arglist").WithArguments("System.RuntimeArgumentHandle").WithLocation(18, 31), // (24,20): error CS1669: __arglist is not valid in this context @@ -3528,7 +3528,7 @@ static void Main() // (32,20): error CS1669: __arglist is not valid in this context // void Local(__arglist) Diagnostic(ErrorCode.ERR_IllegalVarArgs, "__arglist").WithLocation(32, 20), - // (34,31): error CS4013: Instance of type 'RuntimeArgumentHandle' cannot be used inside an anonymous function, query expression, iterator block or async method + // (34,31): error CS4013: Instance of type 'RuntimeArgumentHandle' cannot be used inside a nested function, query expression, iterator block or async method // Console.WriteLine(__arglist); Diagnostic(ErrorCode.ERR_SpecialByRefInLambda, "__arglist").WithArguments("System.RuntimeArgumentHandle").WithLocation(34, 31) ); diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/RefEscapingTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/RefEscapingTests.cs index 9167634ab8a04..9059ff517d961 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/RefEscapingTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/RefEscapingTests.cs @@ -4962,9 +4962,10 @@ public static unsafe void Test(TestStruct[] ar) [Theory] [InlineData(LanguageVersion.CSharp10)] [InlineData(LanguageVersion.CSharp11)] + [InlineData(LanguageVersionFacts.CSharpNext)] public void AwaitRefStruct(LanguageVersion languageVersion) { - CreateCompilation(@" + var comp = CreateCompilation(@" using System.Threading.Tasks; ref struct S { } @@ -4984,20 +4985,67 @@ async Task M(Task t) void M(S t, ref S t1) { } -}", parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion), options: TestOptions.ReleaseDll).VerifyDiagnostics( - // (8,26): error CS0306: The type 'S' may not be used as a type argument - // async Task M(Task t) - Diagnostic(ErrorCode.ERR_BadTypeArgument, "t").WithArguments("S").WithLocation(8, 26), - // (12,9): error CS4012: Parameters or locals of type 'S' cannot be declared in async methods or async lambda expressions. - // var a = await t; - Diagnostic(ErrorCode.ERR_BadSpecialByRefLocal, "var").WithArguments("S").WithLocation(12, 9), - // (14,9): error CS4012: Parameters or locals of type 'S' cannot be declared in async methods or async lambda expressions. - // var r = t.Result; - Diagnostic(ErrorCode.ERR_BadSpecialByRefLocal, "var").WithArguments("S").WithLocation(14, 9), - // (15,9): error CS8350: This combination of arguments to 'C.M(S, ref S)' is disallowed because it may expose variables referenced by parameter 't' outside of their declaration scope - // M(await t, ref r); - Diagnostic(ErrorCode.ERR_CallArgMixing, "M(await t, ref r)").WithArguments("C.M(S, ref S)", "t").WithLocation(15, 9) - ); +}", parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion), options: TestOptions.ReleaseDll); + if (languageVersion < LanguageVersionFacts.CSharpNext) + { + comp.VerifyDiagnostics( + // (8,26): error CS0306: The type 'S' may not be used as a type argument + // async Task M(Task t) + Diagnostic(ErrorCode.ERR_BadTypeArgument, "t").WithArguments("S").WithLocation(8, 26), + // (12,9): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // var a = await t; + Diagnostic(ErrorCode.ERR_FeatureInPreview, "var").WithArguments("ref and unsafe in async and iterator methods").WithLocation(12, 9), + // (14,9): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // var r = t.Result; + Diagnostic(ErrorCode.ERR_FeatureInPreview, "var").WithArguments("ref and unsafe in async and iterator methods").WithLocation(14, 9), + // (15,9): error CS8350: This combination of arguments to 'C.M(S, ref S)' is disallowed because it may expose variables referenced by parameter 't' outside of their declaration scope + // M(await t, ref r); + Diagnostic(ErrorCode.ERR_CallArgMixing, "M(await t, ref r)").WithArguments("C.M(S, ref S)", "t").WithLocation(15, 9) + ); + } + else + { + comp.VerifyDiagnostics( + // (8,26): error CS0306: The type 'S' may not be used as a type argument + // async Task M(Task t) + Diagnostic(ErrorCode.ERR_BadTypeArgument, "t").WithArguments("S").WithLocation(8, 26), + // (15,9): error CS8350: This combination of arguments to 'C.M(S, ref S)' is disallowed because it may expose variables referenced by parameter 't' outside of their declaration scope + // M(await t, ref r); + Diagnostic(ErrorCode.ERR_CallArgMixing, "M(await t, ref r)").WithArguments("C.M(S, ref S)", "t").WithLocation(15, 9) + ); + } + } + + [Fact] + public void AsyncLocals_Reassignment() + { + var code = """ + using System.Threading.Tasks; + class C + { + async Task M1() + { + int x = 42; + ref int y = ref x; + y.ToString(); + await Task.Yield(); + y.ToString(); // 1 + } + async Task M2() + { + int x = 42; + ref int y = ref x; + y.ToString(); + await Task.Yield(); + y = ref x; + y.ToString(); + } + } + """; + CreateCompilation(code).VerifyEmitDiagnostics( + // (10,9): error CS9217: A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + // y.ToString(); // 1 + Diagnostic(ErrorCode.ERR_RefLocalAcrossAwait, "y").WithLocation(10, 9)); } [WorkItem(25398, "https://github.com/dotnet/roslyn/issues/25398")] @@ -5338,9 +5386,9 @@ public static IEnumerable Iterator() { } """); compilation.VerifyEmitDiagnostics( - // (20,19): error CS4013: Instance of type 'PooledArrayHandle' cannot be used inside a nested function, query expression, iterator block or async method + // (20,19): error CS4007: Instance of type 'PooledArrayHandle' cannot be preserved across 'await' or 'yield' boundary. // using var handle = RentArray(200, out var array); - Diagnostic(ErrorCode.ERR_SpecialByRefInLambda, "handle = RentArray(200, out var array)").WithArguments("PooledArrayHandle").WithLocation(20, 19)); + Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "handle = RentArray(200, out var array)").WithArguments("PooledArrayHandle").WithLocation(20, 19)); } [Theory(Skip = "https://github.com/dotnet/roslyn/issues/40583")] diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/RefLocalsAndReturnsTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/RefLocalsAndReturnsTests.cs index 825e55fd10807..6ae6534c5b23f 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/RefLocalsAndReturnsTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/RefLocalsAndReturnsTests.cs @@ -1209,10 +1209,7 @@ async Task M() await Task.FromResult(false); } }"); - comp.VerifyDiagnostics( - // (7,26): error CS8177: Async methods cannot have by-reference locals - // ref readonly int x = ref (new int[1])[0]; - Diagnostic(ErrorCode.ERR_BadAsyncLocalType, "x").WithLocation(7, 26)); + comp.VerifyEmitDiagnostics(); } [Fact] @@ -1229,10 +1226,87 @@ IEnumerable M() yield return i; } }"); - comp.VerifyDiagnostics( - // (7,26): error CS8176: Iterators cannot have by-reference locals - // ref readonly int x = ref (new int[1])[0]; - Diagnostic(ErrorCode.ERR_BadIteratorLocalType, "x").WithLocation(7, 26)); + comp.VerifyEmitDiagnostics(); + } + + [Fact] + public void RefReadonlyInIterator_ForEach() + { + var source = """ + using System.Collections.Generic; + class C + { + int[] arr = new int[2]; + IEnumerable M() + { + ref readonly int[] x = ref arr; + + foreach (var i in x) + { + System.Console.Write(i); + yield return 1; + } + + foreach (var j in x) + { + System.Console.Write(j); + yield return 2; + } + } + } + """; + + CreateCompilation(source, parseOptions: TestOptions.Regular12).VerifyDiagnostics( + // (7,28): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // ref readonly int[] x = ref arr; + Diagnostic(ErrorCode.ERR_FeatureInPreview, "x").WithArguments("ref and unsafe in async and iterator methods").WithLocation(7, 28)); + + var expectedDiagnostics = new[] + { + // (15,27): error CS9217: A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + // foreach (var j in x) + Diagnostic(ErrorCode.ERR_RefLocalAcrossAwait, "x").WithLocation(15, 27) + }; + + CreateCompilation(source, parseOptions: TestOptions.RegularNext).VerifyEmitDiagnostics(expectedDiagnostics); + + CreateCompilation(source).VerifyEmitDiagnostics(expectedDiagnostics); + } + + [Fact] + public void RefReadonlyInIterator_ForEach_02() + { + var source = """ + using System.Collections.Generic; + + foreach (var i in new C().M()) System.Console.Write(i); + + class C + { + int[] arr = new[] { 4, 5 }; + public IEnumerable M() + { + ref readonly int[] x = ref arr; + + foreach (var i in x) + { + System.Console.Write(i); + yield return 1; + } + } + } + """; + + CreateCompilation(source, parseOptions: TestOptions.Regular12).VerifyDiagnostics( + // (10,28): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // ref readonly int[] x = ref arr; + Diagnostic(ErrorCode.ERR_FeatureInPreview, "x").WithArguments("ref and unsafe in async and iterator methods").WithLocation(10, 28)); + + var expectedOutput = "4151"; + + CompileAndVerify(source, parseOptions: TestOptions.RegularNext, expectedOutput: expectedOutput).VerifyDiagnostics(); + + CompileAndVerify(source, expectedOutput: expectedOutput).VerifyDiagnostics(); } [Fact] @@ -1247,7 +1321,7 @@ IEnumerable M() switch (this) { default: - ref readonly int x = ref (new int[1])[0]; // 1 + ref readonly int x = ref (new int[1])[0]; yield return 1; yield return x; @@ -1260,10 +1334,10 @@ void local() } } }"); - comp.VerifyDiagnostics( - // (10,34): error CS8176: Iterators cannot have by-reference locals - // ref readonly int x = ref (new int[1])[0]; // 1 - Diagnostic(ErrorCode.ERR_BadIteratorLocalType, "x").WithLocation(10, 34)); + comp.VerifyEmitDiagnostics( + // (12,30): error CS9217: A 'ref' local cannot be preserved across 'await' or 'yield' boundary. + // yield return x; + Diagnostic(ErrorCode.ERR_RefLocalAcrossAwait, "x").WithLocation(12, 30)); } [Fact] @@ -1278,22 +1352,19 @@ IEnumerable M() switch (this) { default: - ref readonly int x; // 1, 2 + ref readonly int x; // 1 yield return 1; - yield return x; // 3 + yield return x; // 2 break; } } }"); comp.VerifyDiagnostics( - // (10,34): error CS8176: Iterators cannot have by-reference locals - // ref readonly int x; // 1, 2 - Diagnostic(ErrorCode.ERR_BadIteratorLocalType, "x").WithLocation(10, 34), // (10,34): error CS8174: A declaration of a by-reference variable must have an initializer - // ref readonly int x; // 1, 2 + // ref readonly int x; // 1 Diagnostic(ErrorCode.ERR_ByReferenceVariableMustBeInitialized, "x").WithLocation(10, 34), // (12,30): error CS0165: Use of unassigned local variable 'x' - // yield return x; // 3 + // yield return x; // 2 Diagnostic(ErrorCode.ERR_UseDefViolation, "x").WithArguments("x").WithLocation(12, 30)); } @@ -1316,9 +1387,9 @@ IEnumerable M() } }"); comp.VerifyDiagnostics( - // (10,43): error CS8176: Iterators cannot have by-reference locals + // (10,49): error CS1510: A ref or out value must be an assignable variable // foreach (ref readonly int x in (new int[1])) - Diagnostic(ErrorCode.ERR_BadIteratorLocalType, "x").WithLocation(10, 43)); + Diagnostic(ErrorCode.ERR_RefLvalueExpected, "new int[1]").WithLocation(10, 49)); } [Fact] @@ -1331,18 +1402,15 @@ class C IEnumerable M() { if (true) - ref int x = ref (new int[1])[0]; // 1, 2 + ref int x = ref (new int[1])[0]; // 1 yield return 1; } }"); comp.VerifyDiagnostics( // (8,13): error CS1023: Embedded statement cannot be a declaration or labeled statement - // ref int x = ref (new int[1])[0]; // 1, 2 - Diagnostic(ErrorCode.ERR_BadEmbeddedStmt, "ref int x = ref (new int[1])[0];").WithLocation(8, 13), - // (8,21): error CS8176: Iterators cannot have by-reference locals - // ref int x = ref (new int[1])[0]; // 1, 2 - Diagnostic(ErrorCode.ERR_BadIteratorLocalType, "x").WithLocation(8, 21)); + // ref int x = ref (new int[1])[0]; // 1 + Diagnostic(ErrorCode.ERR_BadEmbeddedStmt, "ref int x = ref (new int[1])[0];").WithLocation(8, 13)); } [Fact] @@ -1355,18 +1423,15 @@ class C async Task M() { if (true) - ref int x = ref (new int[1])[0]; // 1, 2 + ref int x = ref (new int[1])[0]; // 1 await Task.Yield(); } }"); comp.VerifyDiagnostics( // (8,13): error CS1023: Embedded statement cannot be a declaration or labeled statement - // ref int x = ref (new int[1])[0]; // 1, 2 - Diagnostic(ErrorCode.ERR_BadEmbeddedStmt, "ref int x = ref (new int[1])[0];").WithLocation(8, 13), - // (8,21): error CS8177: Async methods cannot have by-reference locals - // ref int x = ref (new int[1])[0]; // 1, 2 - Diagnostic(ErrorCode.ERR_BadAsyncLocalType, "x").WithLocation(8, 21)); + // ref int x = ref (new int[1])[0]; // 1 + Diagnostic(ErrorCode.ERR_BadEmbeddedStmt, "ref int x = ref (new int[1])[0];").WithLocation(8, 13)); } [Fact] @@ -3088,13 +3153,7 @@ IEnumerable localFunction() } }"; - CreateCompilation(code).VerifyDiagnostics( - // (13,21): error CS8176: Iterators cannot have by-reference locals - // ref int z = ref x; - Diagnostic(ErrorCode.ERR_BadIteratorLocalType, "z").WithLocation(13, 21), - // (8,17): error CS8176: Iterators cannot have by-reference locals - // ref int y = ref x; - Diagnostic(ErrorCode.ERR_BadIteratorLocalType, "y").WithLocation(8, 17)); + CreateCompilation(code).VerifyEmitDiagnostics(); } [Fact, WorkItem(13073, "https://github.com/dotnet/roslyn/issues/13073")] @@ -3115,13 +3174,7 @@ await Task.Run(async () => }); } }"; - CreateCompilationWithMscorlib45(code).VerifyDiagnostics( - // (8,17): error CS8177: Async methods cannot have by-reference locals - // ref int y = ref x; - Diagnostic(ErrorCode.ERR_BadAsyncLocalType, "y").WithLocation(8, 17), - // (11,21): error CS8177: Async methods cannot have by-reference locals - // ref int z = ref x; - Diagnostic(ErrorCode.ERR_BadAsyncLocalType, "z").WithLocation(11, 21)); + CreateCompilationWithMscorlib45(code).VerifyEmitDiagnostics(); } [Fact, WorkItem(13073, "https://github.com/dotnet/roslyn/issues/13073")] @@ -3434,15 +3487,40 @@ static async void Goo() } "; - CreateCompilationWithMscorlib46(text).VerifyDiagnostics( - // (8,17): error CS8177: Async methods cannot have by-reference locals - // ref int i = ref field; - Diagnostic(ErrorCode.ERR_BadAsyncLocalType, "i").WithLocation(8, 17), + CreateCompilationWithMscorlib46(text).VerifyEmitDiagnostics( // (6,23): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread. // static async void Goo() Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "Goo").WithLocation(6, 23)); } + [Fact] + public void RefReturnAcrossAwaitExpression() + { + var code = """ + using System.Threading.Tasks; + + class Program + { + static int field = 1; + + static async Task Main() + { + M1(ref GiveMeRef(), await M2()); + } + + static void M1(ref int i, int j) { } + + static ref int GiveMeRef() => ref field; + + static Task M2() => Task.FromResult(field++); + } + """; + CreateCompilation(code).VerifyEmitDiagnostics( + // (9,16): error CS8178: A reference returned by a call to 'Program.GiveMeRef()' cannot be preserved across 'await' or 'yield' boundary. + // M1(ref GiveMeRef(), await M2()); + Diagnostic(ErrorCode.ERR_RefReturningCallAndAwait, "GiveMeRef()").WithArguments("Program.GiveMeRef()").WithLocation(9, 16)); + } + [Fact] public void BadRefLocalInIteratorMethod() { @@ -3461,10 +3539,7 @@ static IEnumerable ObjEnumerable() } "; - CreateCompilationWithMscorlib46(text).VerifyDiagnostics( - // (10,17): error CS8931: Iterators cannot have by-reference locals - // ref int i = ref field; - Diagnostic(ErrorCode.ERR_BadIteratorLocalType, "i").WithLocation(10, 17)); + CreateCompilationWithMscorlib46(text).VerifyEmitDiagnostics(); } [Fact] diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs index 50c1950d2a1a4..e83c4cbb6776d 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs @@ -7269,15 +7269,15 @@ static void Main() }"; var comp = CreateCompilationWithMscorlib40AndSystemCore(source); comp.VerifyDiagnostics( - // (10,14): error CS4013: Instance of type 'System.RuntimeArgumentHandle' cannot be used inside an anonymous function, query expression, iterator block or async method + // (10,14): error CS4013: Instance of type 'RuntimeArgumentHandle' cannot be used inside a nested function, query expression, iterator block or async method // f = x=>f(__arglist); - Diagnostic(ErrorCode.ERR_SpecialByRefInLambda, "__arglist").WithArguments("System.RuntimeArgumentHandle"), - // (11,29): error CS4013: Instance of type 'System.RuntimeArgumentHandle' cannot be used inside an anonymous function, query expression, iterator block or async method + Diagnostic(ErrorCode.ERR_SpecialByRefInLambda, "__arglist").WithArguments("System.RuntimeArgumentHandle").WithLocation(10, 14), + // (11,29): error CS4013: Instance of type 'RuntimeArgumentHandle' cannot be used inside a nested function, query expression, iterator block or async method // f = delegate { return f(__arglist); }; - Diagnostic(ErrorCode.ERR_SpecialByRefInLambda, "__arglist").WithArguments("System.RuntimeArgumentHandle"), - // (12,44): error CS4013: Instance of type 'System.RuntimeArgumentHandle' cannot be used inside an anonymous function, query expression, iterator block or async method + Diagnostic(ErrorCode.ERR_SpecialByRefInLambda, "__arglist").WithArguments("System.RuntimeArgumentHandle").WithLocation(11, 29), + // (12,44): error CS4013: Instance of type 'RuntimeArgumentHandle' cannot be used inside a nested function, query expression, iterator block or async method // var q = from x in new int[10] select f(__arglist); - Diagnostic(ErrorCode.ERR_SpecialByRefInLambda, "__arglist").WithArguments("System.RuntimeArgumentHandle") + Diagnostic(ErrorCode.ERR_SpecialByRefInLambda, "__arglist").WithArguments("System.RuntimeArgumentHandle").WithLocation(12, 44) ); } @@ -7304,12 +7304,12 @@ static void Main() } }"; CreateCompilationWithMscorlib45(source).VerifyEmitDiagnostics( - // (10,34): error CS4013: Instance of type 'System.RuntimeArgumentHandle' cannot be used inside an anonymous function, query expression, iterator block or async method + // (10,34): error CS4013: Instance of type 'RuntimeArgumentHandle' cannot be used inside a nested function, query expression, iterator block or async method // RuntimeArgumentHandle h2 = h; // Bad use of h - Diagnostic(ErrorCode.ERR_SpecialByRefInLambda, "h").WithArguments("System.RuntimeArgumentHandle"), - // (11,43): error CS4013: Instance of type 'System.RuntimeArgumentHandle' cannot be used inside an anonymous function, query expression, iterator block or async method + Diagnostic(ErrorCode.ERR_SpecialByRefInLambda, "h").WithArguments("System.RuntimeArgumentHandle").WithLocation(10, 34), + // (11,43): error CS4013: Instance of type 'RuntimeArgumentHandle' cannot be used inside a nested function, query expression, iterator block or async method // ArgIterator args1 = new ArgIterator(h); // Bad use of h - Diagnostic(ErrorCode.ERR_SpecialByRefInLambda, "h").WithArguments("System.RuntimeArgumentHandle")); + Diagnostic(ErrorCode.ERR_SpecialByRefInLambda, "h").WithArguments("System.RuntimeArgumentHandle").WithLocation(11, 43)); } [Fact] @@ -7321,9 +7321,9 @@ public void CS4013ERR_SpecialByRefInLambda03() public class C { static void N(RuntimeArgumentHandle x) {} - static IEnumerable M(RuntimeArgumentHandle h1) // Error: hoisted to field + static IEnumerable M(RuntimeArgumentHandle h1) { - N(h1); + N(h1); // Error: hoisted to field yield return 1; RuntimeArgumentHandle h2 = default(RuntimeArgumentHandle); yield return 2; @@ -7339,12 +7339,12 @@ static void Main() CreateCompilation(source).Emit(new System.IO.MemoryStream()).Diagnostics .Verify( - // (7,51): error CS4013: Instance of type 'System.RuntimeArgumentHandle' cannot be used inside an anonymous function, query expression, iterator block or async method - // static IEnumerable M(RuntimeArgumentHandle h1) // Error: hoisted to field - Diagnostic(ErrorCode.ERR_SpecialByRefInLambda, "h1").WithArguments("System.RuntimeArgumentHandle"), - // (13,7): error CS4013: Instance of type 'System.RuntimeArgumentHandle' cannot be used inside an anonymous function, query expression, iterator block or async method + // (9,7): error CS4007: Instance of type 'System.RuntimeArgumentHandle' cannot be preserved across 'await' or 'yield' boundary. + // N(h1); // Error: hoisted to field + Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "h1").WithArguments("System.RuntimeArgumentHandle").WithLocation(9, 7), + // (13,7): error CS4007: Instance of type 'System.RuntimeArgumentHandle' cannot be preserved across 'await' or 'yield' boundary. // N(h2); // Error: hoisted to field - Diagnostic(ErrorCode.ERR_SpecialByRefInLambda, "h2").WithArguments("System.RuntimeArgumentHandle") + Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "h2").WithArguments("System.RuntimeArgumentHandle").WithLocation(13, 7) ); } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/SpanStackSafetyTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/SpanStackSafetyTests.cs index 922ac7985d750..f2d5e86fc2836 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/SpanStackSafetyTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/SpanStackSafetyTests.cs @@ -975,9 +975,9 @@ public static async Task M1(Span arg) CSharpCompilation comp = CreateCompilationWithMscorlibAndSpan(text); comp.VerifyDiagnostics( - // (11,48): error CS4012: Parameters or locals of type 'Span' cannot be declared in async methods or async lambda expressions. + // (11,48): error CS4012: Parameters of type 'Span' cannot be declared in async methods or async lambda expressions. // public static async Task M1(Span arg) - Diagnostic(ErrorCode.ERR_BadSpecialByRefLocal, "arg").WithArguments("System.Span").WithLocation(11, 48) + Diagnostic(ErrorCode.ERR_BadSpecialByRefParameter, "arg").WithArguments("System.Span").WithLocation(11, 48) ); } @@ -996,48 +996,77 @@ static void Main() public static async Task M1() { - Span local1 = default(Span); // 1 - var local2 = default(Span); // 2 + Span local1 = default(Span); + var local2 = default(Span); await Task.Yield(); return 42; } + + public static async Task M2() + { + Span local1 = default(Span); + var local2 = default(Span); + + await Task.Yield(); + return local1.Length; // 1 + } + + public static async Task M3() + { + Span local1 = default(Span); + var local2 = default(Span); + + await Task.Yield(); + return local2.Length; // 2 + } + + public static async Task M4() + { + Span local1 = default(Span); + var local2 = default(Span); + + await Task.Yield(); + return local1.Length + local2.Length; // 3, 4 + } } "; - CSharpCompilation comp = CreateCompilationWithMscorlibAndSpan(text); - - comp.VerifyDiagnostics( - // (13,9): error CS4012: Parameters or locals of type 'Span' cannot be declared in async methods or async lambda expressions. - // Span local1 = default(Span); // 1 - Diagnostic(ErrorCode.ERR_BadSpecialByRefLocal, "Span").WithArguments("System.Span").WithLocation(13, 9), + var expectedDiagnostics = new[] + { // (13,19): warning CS0219: The variable 'local1' is assigned but its value is never used - // Span local1 = default(Span); // 1 + // Span local1 = default(Span); Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "local1").WithArguments("local1").WithLocation(13, 19), - // (14,9): error CS4012: Parameters or locals of type 'Span' cannot be declared in async methods or async lambda expressions. - // var local2 = default(Span); // 2 - Diagnostic(ErrorCode.ERR_BadSpecialByRefLocal, "var").WithArguments("System.Span").WithLocation(14, 9), // (14,13): warning CS0219: The variable 'local2' is assigned but its value is never used - // var local2 = default(Span); // 2 - Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "local2").WithArguments("local2").WithLocation(14, 13) - ); + // var local2 = default(Span); + Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "local2").WithArguments("local2").WithLocation(14, 13), + // (23,13): warning CS0219: The variable 'local2' is assigned but its value is never used + // var local2 = default(Span); + Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "local2").WithArguments("local2").WithLocation(23, 13), + // (26,16): error CS4007: Instance of type 'System.Span' cannot be preserved across 'await' or 'yield' boundary. + // return local1.Length; // 1 + Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "local1").WithArguments("System.Span").WithLocation(26, 16), + // (31,19): warning CS0219: The variable 'local1' is assigned but its value is never used + // Span local1 = default(Span); + Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "local1").WithArguments("local1").WithLocation(31, 19), + // (35,16): error CS4007: Instance of type 'System.Span' cannot be preserved across 'await' or 'yield' boundary. + // return local2.Length; // 2 + Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "local2").WithArguments("System.Span").WithLocation(35, 16), + // (44,16): error CS4007: Instance of type 'System.Span' cannot be preserved across 'await' or 'yield' boundary. + // return local1.Length + local2.Length; // 3, 4 + Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "local1").WithArguments("System.Span").WithLocation(44, 16), + // (44,32): error CS4007: Instance of type 'System.Span' cannot be preserved across 'await' or 'yield' boundary. + // return local1.Length + local2.Length; // 3, 4 + Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "local2").WithArguments("System.Span").WithLocation(44, 32) + }; + + CSharpCompilation comp = CreateCompilationWithMscorlibAndSpan(text); + + comp.VerifyEmitDiagnostics(expectedDiagnostics); comp = CreateCompilationWithMscorlibAndSpan(text, TestOptions.DebugExe); - comp.VerifyDiagnostics( - // (13,9): error CS4012: Parameters or locals of type 'Span' cannot be declared in async methods or async lambda expressions. - // Span local1 = default(Span); // 1 - Diagnostic(ErrorCode.ERR_BadSpecialByRefLocal, "Span").WithArguments("System.Span").WithLocation(13, 9), - // (13,19): warning CS0219: The variable 'local1' is assigned but its value is never used - // Span local1 = default(Span); // 1 - Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "local1").WithArguments("local1").WithLocation(13, 19), - // (14,9): error CS4012: Parameters or locals of type 'Span' cannot be declared in async methods or async lambda expressions. - // var local2 = default(Span); // 2 - Diagnostic(ErrorCode.ERR_BadSpecialByRefLocal, "var").WithArguments("System.Span").WithLocation(14, 9), - // (14,13): warning CS0219: The variable 'local2' is assigned but its value is never used - // var local2 = default(Span); // 2 - Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "local2").WithArguments("local2").WithLocation(14, 13) - ); + comp.VerifyEmitDiagnostics(expectedDiagnostics); } [Fact] @@ -1051,27 +1080,44 @@ public class Program { public static async Task M1() { - M2(out var local1); // 1 - M2(out Span local2); // 2 + M2(out var local1); + M2(out Span local2); await Task.Yield(); return 42; } + public static async Task M3() + { + M2(out var local1); + M2(out Span local2); + + await Task.Yield(); + return local1.Length; // 1 + } + + public static async Task M4() + { + M2(out var local1); + M2(out Span local2); + + await Task.Yield(); + return local2.Length; // 2 + } + static void M2(out Span s) => throw null; } "; CSharpCompilation comp = CreateCompilationWithMscorlibAndSpan(text); - comp.VerifyDiagnostics( - // (9,16): error CS4012: Parameters or locals of type 'Span' cannot be declared in async methods or async lambda expressions. - // M2(out var local1); // 1 - Diagnostic(ErrorCode.ERR_BadSpecialByRefLocal, "var").WithArguments("System.Span").WithLocation(9, 16), - // (10,16): error CS4012: Parameters or locals of type 'Span' cannot be declared in async methods or async lambda expressions. - // M2(out Span local2); // 2 - Diagnostic(ErrorCode.ERR_BadSpecialByRefLocal, "Span").WithArguments("System.Span").WithLocation(10, 16) - ); + comp.VerifyEmitDiagnostics( + // (22,16): error CS4007: Instance of type 'System.Span' cannot be preserved across 'await' or 'yield' boundary. + // return local1.Length; // 1 + Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "local1").WithArguments("System.Span").WithLocation(22, 16), + // (31,16): error CS4007: Instance of type 'System.Span' cannot be preserved across 'await' or 'yield' boundary. + // return local2.Length; // 2 + Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "local2").WithArguments("System.Span").WithLocation(31, 16)); } [Fact, WorkItem(62747, "https://github.com/dotnet/roslyn/issues/62747")] @@ -1086,30 +1132,49 @@ public class Program { public async Task M(IReadOnlyList o) { - foreach (ReadOnlySpan c1 in o) { } // 1 + foreach (ReadOnlySpan c1 in o) { } var enumerator = ((IEnumerable)o).GetEnumerator(); while (enumerator.MoveNext()) { - ReadOnlySpan c2 = (ReadOnlySpan)(string)enumerator.Current; // 2 + ReadOnlySpan c2 = (ReadOnlySpan)(string)enumerator.Current; _ = c2.Length; } await Task.Yield(); return; } + + public async Task M2(IReadOnlyList o) + { + foreach (ReadOnlySpan c1 in o) + { + await Task.Yield(); + _ = c1.Length; // 1 + } + + var enumerator = ((IEnumerable)o).GetEnumerator(); + while (enumerator.MoveNext()) + { + ReadOnlySpan c2 = (ReadOnlySpan)(string)enumerator.Current; + await Task.Yield(); + _ = c2.Length; // 2 + } + + await Task.Yield(); + return; + } } "; var comp = CreateCompilation(src, targetFramework: TargetFramework.Net70); - comp.VerifyDiagnostics( - // (10,18): error CS4012: Parameters or locals of type 'ReadOnlySpan' cannot be declared in async methods or async lambda expressions. - // foreach (ReadOnlySpan c1 in o) { } // 1 - Diagnostic(ErrorCode.ERR_BadSpecialByRefLocal, "ReadOnlySpan").WithArguments("System.ReadOnlySpan").WithLocation(10, 18), - // (15,13): error CS4012: Parameters or locals of type 'ReadOnlySpan' cannot be declared in async methods or async lambda expressions. - // ReadOnlySpan c2 = (ReadOnlySpan)(string)enumerator.Current; // 2 - Diagnostic(ErrorCode.ERR_BadSpecialByRefLocal, "ReadOnlySpan").WithArguments("System.ReadOnlySpan").WithLocation(15, 13) - ); + comp.VerifyEmitDiagnostics( + // (28,17): error CS4007: Instance of type 'System.ReadOnlySpan' cannot be preserved across 'await' or 'yield' boundary. + // _ = c1.Length; // 1 + Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "c1").WithArguments("System.ReadOnlySpan").WithLocation(28, 17), + // (36,17): error CS4007: Instance of type 'System.ReadOnlySpan' cannot be preserved across 'await' or 'yield' boundary. + // _ = c2.Length; // 2 + Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "c2").WithArguments("System.ReadOnlySpan").WithLocation(36, 17)); } [Fact, WorkItem(62747, "https://github.com/dotnet/roslyn/issues/62747")] @@ -1123,38 +1188,40 @@ public class Program { public async Task M() { - (Span s1, Span s2) = new Program(); // 1, 2 - var (s3, s4) = new Program(); // 3, 4 - (var s5, var s6) = new Program(); // 5, 6 + (Span s1, Span s2) = new Program(); + var (s3, s4) = new Program(); + (var s5, var s6) = new Program(); await Task.Yield(); return; } + public async Task M2() + { + (Span s1, Span s2) = new Program(); + var (s3, s4) = new Program(); + (var s5, var s6) = new Program(); + + await Task.Yield(); + + _ = s1.Length + s4.Length + s5.Length; // 1, 2, 3 + return; + } + void Deconstruct(out Span s1, out Span s2) => throw null; } "; var comp = CreateCompilation(src, targetFramework: TargetFramework.Net70); - comp.VerifyDiagnostics( - // (9,10): error CS4012: Parameters or locals of type 'Span' cannot be declared in async methods or async lambda expressions. - // (Span s1, Span s2) = new Program(); // 1, 2 - Diagnostic(ErrorCode.ERR_BadSpecialByRefLocal, "Span").WithArguments("System.Span").WithLocation(9, 10), - // (9,24): error CS4012: Parameters or locals of type 'Span' cannot be declared in async methods or async lambda expressions. - // (Span s1, Span s2) = new Program(); // 1, 2 - Diagnostic(ErrorCode.ERR_BadSpecialByRefLocal, "Span").WithArguments("System.Span").WithLocation(9, 24), - // (10,14): error CS4012: Parameters or locals of type 'Span' cannot be declared in async methods or async lambda expressions. - // var (s3, s4) = new Program(); // 3, 4 - Diagnostic(ErrorCode.ERR_BadSpecialByRefLocal, "s3").WithArguments("System.Span").WithLocation(10, 14), - // (10,18): error CS4012: Parameters or locals of type 'Span' cannot be declared in async methods or async lambda expressions. - // var (s3, s4) = new Program(); // 3, 4 - Diagnostic(ErrorCode.ERR_BadSpecialByRefLocal, "s4").WithArguments("System.Span").WithLocation(10, 18), - // (11,10): error CS4012: Parameters or locals of type 'Span' cannot be declared in async methods or async lambda expressions. - // (var s5, var s6) = new Program(); // 5, 6 - Diagnostic(ErrorCode.ERR_BadSpecialByRefLocal, "var").WithArguments("System.Span").WithLocation(11, 10), - // (11,18): error CS4012: Parameters or locals of type 'Span' cannot be declared in async methods or async lambda expressions. - // (var s5, var s6) = new Program(); // 5, 6 - Diagnostic(ErrorCode.ERR_BadSpecialByRefLocal, "var").WithArguments("System.Span").WithLocation(11, 18) - ); + comp.VerifyEmitDiagnostics( + // (25,13): error CS4007: Instance of type 'System.Span' cannot be preserved across 'await' or 'yield' boundary. + // _ = s1.Length + s4.Length + s5.Length; // 1, 2, 3 + Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "s1").WithArguments("System.Span").WithLocation(25, 13), + // (25,25): error CS4007: Instance of type 'System.Span' cannot be preserved across 'await' or 'yield' boundary. + // _ = s1.Length + s4.Length + s5.Length; // 1, 2, 3 + Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "s4").WithArguments("System.Span").WithLocation(25, 25), + // (25,37): error CS4007: Instance of type 'System.Span' cannot be preserved across 'await' or 'yield' boundary. + // _ = s1.Length + s4.Length + s5.Length; // 1, 2, 3 + Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "s5").WithArguments("System.Span").WithLocation(25, 37)); } [Fact, WorkItem(62747, "https://github.com/dotnet/roslyn/issues/62747")] @@ -1167,11 +1234,26 @@ public class Program { public async Task M() { - using (default(RS)) { } // 1 - using (var s1 = default(RS)) { } // 2 - using (RS s2 = default(RS)) { } // 3 - using RS s3 = default(RS); // 4 - using var s4 = default(RS); // 5 + using (default(RS)) { } + using (var s1 = default(RS)) { } + using (RS s2 = default(RS)) { } + using RS s3 = default(RS); // 1 + using var s4 = default(RS); // 2 + + await Task.Yield(); + return; + } + + public async Task M2() + { + using (default(RS)) { await Task.Yield(); } // 3 + using (var s1 = default(RS)) { await Task.Yield(); } // 4 + using (RS s2 = default(RS)) { await Task.Yield(); } // 5 + { + using RS s3 = default(RS); // 6 + await Task.Yield(); + using var s4 = default(RS); + } await Task.Yield(); return; @@ -1184,23 +1266,25 @@ public void Dispose() { } } "; var comp = CreateCompilation(src, targetFramework: TargetFramework.Net70); - comp.VerifyDiagnostics( - // (8,16): error CS9104: A using statement resource of type 'RS' cannot be used in async methods or async lambda expressions. - // using (default(RS)) { } // 1 - Diagnostic(ErrorCode.ERR_BadSpecialByRefUsing, "default(RS)").WithArguments("RS").WithLocation(8, 16), - // (9,16): error CS4012: Parameters or locals of type 'RS' cannot be declared in async methods or async lambda expressions. - // using (var s1 = default(RS)) { } // 2 - Diagnostic(ErrorCode.ERR_BadSpecialByRefLocal, "var").WithArguments("RS").WithLocation(9, 16), - // (10,16): error CS4012: Parameters or locals of type 'RS' cannot be declared in async methods or async lambda expressions. - // using (RS s2 = default(RS)) { } // 3 - Diagnostic(ErrorCode.ERR_BadSpecialByRefLocal, "RS").WithArguments("RS").WithLocation(10, 16), - // (11,15): error CS4012: Parameters or locals of type 'RS' cannot be declared in async methods or async lambda expressions. - // using RS s3 = default(RS); // 4 - Diagnostic(ErrorCode.ERR_BadSpecialByRefLocal, "RS").WithArguments("RS").WithLocation(11, 15), - // (12,15): error CS4012: Parameters or locals of type 'RS' cannot be declared in async methods or async lambda expressions. - // using var s4 = default(RS); // 5 - Diagnostic(ErrorCode.ERR_BadSpecialByRefLocal, "var").WithArguments("RS").WithLocation(12, 15) - ); + comp.VerifyEmitDiagnostics( + // (11,18): error CS4007: Instance of type 'RS' cannot be preserved across 'await' or 'yield' boundary. + // using RS s3 = default(RS); // 1 + Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "s3 = default(RS)").WithArguments("RS").WithLocation(11, 18), + // (12,19): error CS4007: Instance of type 'RS' cannot be preserved across 'await' or 'yield' boundary. + // using var s4 = default(RS); // 2 + Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "s4 = default(RS)").WithArguments("RS").WithLocation(12, 19), + // (20,16): error CS4007: Instance of type 'RS' cannot be preserved across 'await' or 'yield' boundary. + // using (default(RS)) { await Task.Yield(); } // 3 + Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "default(RS)").WithArguments("RS").WithLocation(20, 16), + // (21,20): error CS4007: Instance of type 'RS' cannot be preserved across 'await' or 'yield' boundary. + // using (var s1 = default(RS)) { await Task.Yield(); } // 4 + Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "s1 = default(RS)").WithArguments("RS").WithLocation(21, 20), + // (22,19): error CS4007: Instance of type 'RS' cannot be preserved across 'await' or 'yield' boundary. + // using (RS s2 = default(RS)) { await Task.Yield(); } // 5 + Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "s2 = default(RS)").WithArguments("RS").WithLocation(22, 19), + // (24,22): error CS4007: Instance of type 'RS' cannot be preserved across 'await' or 'yield' boundary. + // using RS s3 = default(RS); // 6 + Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "s3 = default(RS)").WithArguments("RS").WithLocation(24, 22)); } [Fact] @@ -1214,24 +1298,76 @@ public class Program { public async Task M() { - if (M2() is var s1) { } // 1 - if (M2() is Span s2) { } // 2 + if (M2() is var s1) { } + if (M2() is Span s2) { } + if (M2() is var s3) { await Task.Yield(); } + if (M2() is Span s4) { await Task.Yield(); } await Task.Yield(); return; } + + public async Task M3() + { + if (M2() is var s1) + { + await Task.Yield(); + _ = s1.Length; // 1 + } + if (M2() is Span s2) + { + await Task.Yield(); + _ = s2.Length; // 2 + } + + await Task.Yield(); + return; + } + static Span M2() => throw null; } "; var comp = CreateCompilation(src, targetFramework: TargetFramework.Net70); - comp.VerifyDiagnostics( - // (9,25): error CS4012: Parameters or locals of type 'Span' cannot be declared in async methods or async lambda expressions. - // if (M2() is var s1) { } // 1 - Diagnostic(ErrorCode.ERR_BadSpecialByRefLocal, "s1").WithArguments("System.Span").WithLocation(9, 25), - // (10,21): error CS4012: Parameters or locals of type 'Span' cannot be declared in async methods or async lambda expressions. - // if (M2() is Span s2) { } // 2 - Diagnostic(ErrorCode.ERR_BadSpecialByRefLocal, "Span").WithArguments("System.Span").WithLocation(10, 21) - ); + comp.VerifyEmitDiagnostics( + // (23,17): error CS4007: Instance of type 'System.Span' cannot be preserved across 'await' or 'yield' boundary. + // _ = s1.Length; + Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "s1").WithArguments("System.Span").WithLocation(23, 17), + // (28,17): error CS4007: Instance of type 'System.Span' cannot be preserved across 'await' or 'yield' boundary. + // _ = s2.Length; + Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "s2").WithArguments("System.Span").WithLocation(28, 17)); + } + + [Fact] + public void AsyncLocals_Reassignment() + { + var code = """ + using System; + using System.Threading.Tasks; + class C + { + async Task M1() + { + int x = 42; + Span y = new(ref x); + y.ToString(); + await Task.Yield(); + y.ToString(); // 1 + } + async Task M2() + { + int x = 42; + Span y = new(ref x); + y.ToString(); + await Task.Yield(); + y = new(ref x); + y.ToString(); + } + } + """; + CreateCompilation(code, targetFramework: TargetFramework.Net70).VerifyEmitDiagnostics( + // (11,9): error CS4007: Instance of type 'System.Span' cannot be preserved across 'await' or 'yield' boundary. + // y.ToString(); // 1 + Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "y").WithArguments("System.Span").WithLocation(11, 9)); } [Fact] @@ -1280,19 +1416,18 @@ public static async Task I1() CSharpCompilation comp = CreateCompilationWithMscorlibAndSpan(text); - comp.VerifyEmitDiagnostics( - // (17,39): error CS4007: 'await' cannot be used in an expression containing the type 'System.Span' + var expectedDiagnostics = new[] + { + // (17,19): error CS4007: Instance of type 'System.Span' cannot be preserved across 'await' or 'yield' boundary. // TakesSpan(default(Span), await I1()); - Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "await I1()").WithArguments("System.Span") - ); + Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "default(Span)").WithArguments("System.Span").WithLocation(17, 19) + }; + + comp.VerifyEmitDiagnostics(expectedDiagnostics); comp = CreateCompilationWithMscorlibAndSpan(text, TestOptions.DebugExe); - comp.VerifyEmitDiagnostics( - // (17,39): error CS4007: 'await' cannot be used in an expression containing the type 'System.Span' - // TakesSpan(default(Span), await I1()); - Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "await I1()").WithArguments("System.Span") - ); + comp.VerifyEmitDiagnostics(expectedDiagnostics); } [Fact] @@ -1331,19 +1466,18 @@ public static async Task I1() CSharpCompilation comp = CreateCompilationWithMscorlibAndSpan(text); - comp.VerifyEmitDiagnostics( - // (14,45): error CS4007: 'await' cannot be used in an expression containing the type 'Span' + var expectedDiagnostics = new[] + { + // (14,22): error CS4007: Instance of type 'System.Span' cannot be preserved across 'await' or 'yield' boundary. // TakesSpan(s: default(Span), i: await I1()); - Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "await I1()").WithArguments("System.Span").WithLocation(14, 45) - ); + Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "default(Span)").WithArguments("System.Span").WithLocation(14, 22) + }; + + comp.VerifyEmitDiagnostics(expectedDiagnostics); comp = CreateCompilationWithMscorlibAndSpan(text, TestOptions.DebugExe); - comp.VerifyEmitDiagnostics( - // (14,45): error CS4007: 'await' cannot be used in an expression containing the type 'Span' - // TakesSpan(s: default(Span), i: await I1()); - Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "await I1()").WithArguments("System.Span").WithLocation(14, 45) - ); + comp.VerifyEmitDiagnostics(expectedDiagnostics); } [Fact] diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/StackAllocInitializerTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/StackAllocInitializerTests.cs index d96e6abf25f3b..751ca8595562d 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/StackAllocInitializerTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/StackAllocInitializerTests.cs @@ -757,13 +757,29 @@ async void M() comp.VerifyDiagnostics( // (8,38): error CS0150: A constant value is expected // Span p = stackalloc int[await Task.FromResult(1)] { await Task.FromResult(2) }; - Diagnostic(ErrorCode.ERR_ConstantExpected, "await Task.FromResult(1)").WithLocation(8, 38), - // (8,9): error CS4012: Parameters or locals of type 'Span' cannot be declared in async methods or async lambda expressions. - // Span p = stackalloc int[await Task.FromResult(1)] { await Task.FromResult(2) }; - Diagnostic(ErrorCode.ERR_BadSpecialByRefLocal, "Span").WithArguments("System.Span").WithLocation(8, 9) + Diagnostic(ErrorCode.ERR_ConstantExpected, "await Task.FromResult(1)").WithLocation(8, 38) ); } + [Fact] + public void TestAwait_Span_02() + { + var comp = CreateCompilationWithMscorlibAndSpan(""" + using System; + using System.Threading.Tasks; + class Test + { + static async Task Main() + { + Span p = stackalloc int[1] { await Task.FromResult(2) }; + Console.WriteLine(p[0]); + } + } + """, TestOptions.UnsafeReleaseExe); + + CompileAndVerify(comp, expectedOutput: "2", verify: Verification.Fails).VerifyDiagnostics(); + } + [Fact] public void TestSelfInSize() { diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/TopLevelStatementsTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/TopLevelStatementsTests.cs index 6ab50856c1131..a8723ce4cb72b 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/TopLevelStatementsTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/TopLevelStatementsTests.cs @@ -1113,13 +1113,24 @@ public void LocalDeclarationStatement_18() await System.Threading.Tasks.Task.Yield(); "; + var expectedDiagnostics = new[] + { + // (3,9): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // ref int d = ref c; + Diagnostic(ErrorCode.ERR_FeatureInPreview, "d").WithArguments("ref and unsafe in async and iterator methods").WithLocation(3, 9) + }; + var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.VerifyDiagnostics(expectedDiagnostics); - comp.VerifyDiagnostics( - // (3,9): error CS8177: Async methods cannot have by-reference locals - // ref int d = ref c; - Diagnostic(ErrorCode.ERR_BadAsyncLocalType, "d").WithLocation(3, 9) - ); + comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular12); + comp.VerifyDiagnostics(expectedDiagnostics); + + comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularNext); + comp.VerifyEmitDiagnostics(); + + comp = CreateCompilation(text, options: TestOptions.DebugExe); + comp.VerifyEmitDiagnostics(); } [Fact] diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/UsingStatementTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/UsingStatementTests.cs index 3b9371a1c3769..610897b83d561 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/UsingStatementTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/UsingStatementTests.cs @@ -1127,12 +1127,67 @@ static async Task Main() } } }"; - var compilation = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }).VerifyDiagnostics( - // (16,22): error CS4012: Parameters or locals of type 'S1' cannot be declared in async methods or async lambda expressions. + var compilation = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.ReleaseExe); + CompileAndVerify(compilation, expectedOutput: "Dispose async").VerifyDiagnostics(); + } + + [Fact] + public void UsingPatternAsyncTest_02() + { + var source = """ + using System.Threading.Tasks; + ref struct S1 + { + public ValueTask DisposeAsync() + { + System.Console.WriteLine("Dispose async"); + return new ValueTask(Task.CompletedTask); + } + } + class C2 + { + static async Task Main() + { + await using (S1 c = new S1()) + { + await Task.Yield(); + } + } + } + """; + var compilation = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }); + compilation.VerifyEmitDiagnostics( + // 0.cs(14,25): error CS4007: Instance of type 'S1' cannot be preserved across 'await' or 'yield' boundary. // await using (S1 c = new S1()) - Diagnostic(ErrorCode.ERR_BadSpecialByRefLocal, "S1").WithArguments("S1").WithLocation(16, 22) - ); + Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "c = new S1()").WithArguments("S1").WithLocation(14, 25)); + } + [Fact] + public void UsingPatternAsyncTest_03() + { + var source = """ + using System.Threading.Tasks; + ref struct S1 + { + public S1(int x) { } + public ValueTask DisposeAsync() + { + System.Console.WriteLine("Dispose async"); + return new ValueTask(Task.CompletedTask); + } + } + class C2 + { + static async Task Main() + { + await using (S1 c = new S1(await Task.FromResult(1))) + { + } + } + } + """; + var compilation = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.ReleaseExe); + CompileAndVerify(compilation, expectedOutput: "Dispose async").VerifyDiagnostics(); } [Fact] diff --git a/src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs b/src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs index 1a83fa88bfbd7..a7b6120dc07cc 100644 --- a/src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs +++ b/src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs @@ -2982,6 +2982,7 @@ public void TestIsBuildOnlyDiagnostic() case ErrorCode.ERR_InterceptableMethodMustBeOrdinary: case ErrorCode.ERR_PossibleAsyncIteratorWithoutYield: case ErrorCode.ERR_PossibleAsyncIteratorWithoutYieldOrAwait: + case ErrorCode.ERR_RefLocalAcrossAwait: Assert.True(isBuildOnly, $"Check failed for ErrorCode.{errorCode}"); break; diff --git a/src/Features/CSharp/Portable/Diagnostics/LanguageServer/CSharpLspBuildOnlyDiagnostics.cs b/src/Features/CSharp/Portable/Diagnostics/LanguageServer/CSharpLspBuildOnlyDiagnostics.cs index 8a81b6d09d4b1..6bd117bf73410 100644 --- a/src/Features/CSharp/Portable/Diagnostics/LanguageServer/CSharpLspBuildOnlyDiagnostics.cs +++ b/src/Features/CSharp/Portable/Diagnostics/LanguageServer/CSharpLspBuildOnlyDiagnostics.cs @@ -59,7 +59,8 @@ namespace Microsoft.CodeAnalysis.CSharp.LanguageServer; "CS9178", // ErrorCode.ERR_InterceptorCannotBeGeneric "CS9207", // ErrorCode.ERR_InterceptableMethodMustBeOrdinary "CS8419", // ErrorCode.ERR_PossibleAsyncIteratorWithoutYield - "CS8420" // ErrorCode.ERR_PossibleAsyncIteratorWithoutYieldOrAwait + "CS8420", // ErrorCode.ERR_PossibleAsyncIteratorWithoutYieldOrAwait + "CS9217" // ErrorCode.ERR_RefLocalAcrossAwait )] [Shared] internal sealed class CSharpLspBuildOnlyDiagnostics : ILspBuildOnlyDiagnostics