diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index be221bed765f8..474fcd46b608b 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -6996,6 +6996,12 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ The 'scoped' modifier of parameter '{0}' doesn't match partial definition. + + The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. + + + The '{0}' modifier cannot immediately follow the 'scoped' modifier. + A fixed field must not be a ref field. diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index 5153ca9d395e1..b5c4b2797ac51 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -2448,6 +2448,9 @@ internal enum ErrorCode ERR_ExtensionParameterInStaticContext = 9347, ERR_CompilationUnitUnexpected = 9348, + ERR_ScopedAfterInOutRefReadonly = 9349, + ERR_InvalidModifierAfterScoped = 9350, + // Note: you will need to do the following after adding errors: // 1) Update ErrorFacts.IsBuildOnlyDiagnostic (src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs) // 2) Add message to CSharpResources.resx diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs index a99746c3a5f12..4f95bb82a4bd3 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs @@ -2555,6 +2555,8 @@ or ErrorCode.ERR_EqualityOperatorInPatternNotSupported or ErrorCode.ERR_InequalityOperatorInPatternNotSupported or ErrorCode.ERR_DesignatorBeforePropertyPattern or ErrorCode.ERR_CompilationUnitUnexpected + or ErrorCode.ERR_ScopedAfterInOutRefReadonly + or ErrorCode.ERR_InvalidModifierAfterScoped => false, }; #pragma warning restore CS8524 // The switch expression does not handle some values of its input type (it is not exhaustive) involving an unnamed enum value. diff --git a/src/Compilers/CSharp/Portable/Errors/MessageID.cs b/src/Compilers/CSharp/Portable/Errors/MessageID.cs index 5933baf7c5b04..463f90286d2d8 100644 --- a/src/Compilers/CSharp/Portable/Errors/MessageID.cs +++ b/src/Compilers/CSharp/Portable/Errors/MessageID.cs @@ -487,7 +487,7 @@ internal static LanguageVersion RequiredVersion(this MessageID feature) // C# preview features. //return LanguageVersion.Preview; - // C# 13.0 features. + // C# 14.0 features. case MessageID.IDS_FeatureFieldKeyword: case MessageID.IDS_FeatureFirstClassSpan: case MessageID.IDS_FeatureUnboundGenericTypesInNameof: diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs index 7d9e2b418d691..f34e2393b13d4 100644 --- a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs +++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs @@ -4834,7 +4834,9 @@ private bool IsPossibleParameter() return this.IsTrueIdentifier(); default: - return IsParameterModifierExcludingScoped(this.CurrentToken) || IsPossibleScopedKeyword(isFunctionPointerParameter: false) || IsPredefinedType(this.CurrentToken.Kind); + return IsParameterModifierExcludingScoped(this.CurrentToken) || + IsDefiniteScopedModifier(isFunctionPointerParameter: false, isLambdaParameter: false) || + IsPredefinedType(this.CurrentToken.Kind); } } @@ -4961,32 +4963,50 @@ private static bool IsParameterModifierExcludingScoped(SyntaxToken token) private void ParseParameterModifiers(SyntaxListBuilder modifiers, bool isFunctionPointerParameter, bool isLambdaParameter) { - bool tryScoped = true; + Debug.Assert(!(isFunctionPointerParameter && isLambdaParameter), "Can't be parsing parameters for both a function pointer and a lambda at the same time"); - while (IsParameterModifierExcludingScoped(this.CurrentToken)) + var seenScoped = false; + while (true) { - if (this.CurrentToken.Kind is SyntaxKind.RefKeyword or SyntaxKind.OutKeyword or SyntaxKind.InKeyword or SyntaxKind.ReadOnlyKeyword) + // Normal keyword-modifier (in/out/ref/readonly/params/this). Always safe to consume. + if (IsParameterModifierExcludingScoped(this.CurrentToken)) { - tryScoped = false; + modifiers.Add(this.EatToken()); + continue; } - modifiers.Add(this.EatToken()); - } - - if (tryScoped) - { - SyntaxToken scopedKeyword = ParsePossibleScopedKeyword(isFunctionPointerParameter, isLambdaParameter); - - if (scopedKeyword != null) + // 'scoped' modifier. May be ambiguous with a type/identifier. And has changed parsing rules between + // C#13/14 inside a lambda parameter list. + if (this.IsDefiniteScopedModifier(isFunctionPointerParameter, isLambdaParameter)) { - modifiers.Add(scopedKeyword); - - // Look if ref/out/in/readonly are next - while (this.CurrentToken.Kind is SyntaxKind.RefKeyword or SyntaxKind.OutKeyword or SyntaxKind.InKeyword or SyntaxKind.ReadOnlyKeyword) + // First scoped-modifier is always considered the modifier. + if (!seenScoped) { - modifiers.Add(this.EatToken()); + seenScoped = true; + modifiers.Add(this.EatContextualToken(SyntaxKind.ScopedKeyword)); + continue; + } + else + { + // If we've already seen `scoped` then we may have a situation like `scoped scoped`. This could + // be duplicated modifier, or it could be that the second `scoped` is actually the identifier of + // a parameter. + // + // Places where it is an identifier are: + // + // `(scoped scoped) =>` + // `(scoped scoped, ...) =>` + // `(scoped scoped = ...) =>` + if (this.PeekToken(1).Kind is not (SyntaxKind.CloseParenToken or SyntaxKind.CommaToken or SyntaxKind.EqualsToken)) + { + modifiers.Add(this.EatContextualToken(SyntaxKind.ScopedKeyword)); + continue; + } } } + + // Not a modifier. We're done. + return; } } @@ -8464,7 +8484,7 @@ private bool IsPossibleLocalDeclarationStatement(bool isGlobalScriptLevel) return true; } - if (IsPossibleScopedKeyword(isFunctionPointerParameter: false)) + if (IsDefiniteScopedModifier(isFunctionPointerParameter: false, isLambdaParameter: false)) { return true; } @@ -8482,12 +8502,6 @@ private bool IsPossibleLocalDeclarationStatement(bool isGlobalScriptLevel) return IsPossibleFirstTypedIdentifierInLocalDeclarationStatement(isGlobalScriptLevel); } - private bool IsPossibleScopedKeyword(bool isFunctionPointerParameter) - { - using var _ = this.GetDisposableResetPoint(resetOnDispose: true); - return ParsePossibleScopedKeyword(isFunctionPointerParameter, isLambdaParameter: false) != null; - } - private bool IsPossibleFirstTypedIdentifierInLocalDeclarationStatement(bool isGlobalScriptLevel) { bool? typedIdentifier = IsPossibleTypedIdentifierStart(this.CurrentToken, this.PeekToken(1), allowThisKeyword: false); @@ -8623,7 +8637,7 @@ private bool IsPossibleTopLevelUsingLocalDeclarationStatement() // Skip 'using' keyword EatToken(); - if (IsPossibleScopedKeyword(isFunctionPointerParameter: false)) + if (IsDefiniteScopedModifier(isFunctionPointerParameter: false, isLambdaParameter: false)) { return true; } @@ -10518,41 +10532,34 @@ private StatementSyntax ParseLocalDeclarationStatement(SyntaxList{0} není platný název parametru z {1}. + + The '{0}' modifier cannot immediately follow the 'scoped' modifier. + The '{0}' modifier cannot immediately follow the 'scoped' modifier. + + The modifier '{0}' is not valid for this item in C# {1}. Please use language version '{2}' or greater. Modifikátor {0} není platný pro tuto položku v jazyce C# {1}. Použijte prosím verzi jazyka {2} nebo vyšší. @@ -2357,6 +2362,11 @@ Cílový modul runtime nepodporuje rozšiřitelné konvence volání ani konvence volání výchozí pro prostředí modulu runtime. + + The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. + The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. + + The 'scoped' modifier cannot be used with discard. Modifikátor scoped nejde použít s proměnnou typu discard. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index cc832bbc9e59a..0f45cb89e4f4e 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -1457,6 +1457,11 @@ "{0}" ist kein gültiger Parametername von "{1}". + + The '{0}' modifier cannot immediately follow the 'scoped' modifier. + The '{0}' modifier cannot immediately follow the 'scoped' modifier. + + The modifier '{0}' is not valid for this item in C# {1}. Please use language version '{2}' or greater. Der Modifizierer "{0}" ist für dieses Element in C# {1} ungültig. Verwenden Sie Sprachversion {2} oder höher. @@ -2357,6 +2362,11 @@ Die Zielruntime unterstützt keine erweiterbaren Aufrufkonventionen oder Standardaufrufkonventionen der Runtime-Umgebung. + + The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. + The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. + + The 'scoped' modifier cannot be used with discard. Der Modifizierer „scoped“ kann nicht mit „discard“ verwendet werden. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index 63c1713972390..adb65da6e83cb 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -1457,6 +1457,11 @@ "{0}" no es un nombre de parámetro válido para "{1}". + + The '{0}' modifier cannot immediately follow the 'scoped' modifier. + The '{0}' modifier cannot immediately follow the 'scoped' modifier. + + The modifier '{0}' is not valid for this item in C# {1}. Please use language version '{2}' or greater. El modificador "{0}" no es válido para este elemento en C# {1}. Use la versión de lenguaje "{2}" o una posterior. @@ -2357,6 +2362,11 @@ El entorno de ejecución de destino no admite convenciones de llamada predeterminadas de entorno en tiempo de ejecución o extensible. + + The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. + The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. + + The 'scoped' modifier cannot be used with discard. El modificador “scoped” no se puede usar con discard. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index 2514cadd8555e..1c4a282cd3f72 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -1457,6 +1457,11 @@ « {0} » n’est pas un nom de paramètre valide de « {1} ». + + The '{0}' modifier cannot immediately follow the 'scoped' modifier. + The '{0}' modifier cannot immediately follow the 'scoped' modifier. + + The modifier '{0}' is not valid for this item in C# {1}. Please use language version '{2}' or greater. Le modificateur '{0}' est non valide pour cet élément en C# {1}. Utilisez la version de langage '{2}' ou une version ultérieure. @@ -2357,6 +2362,11 @@ Le runtime cible ne prend pas en charge les conventions d'appel par défaut des environnements extensibles ou d'exécution. + + The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. + The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. + + The 'scoped' modifier cannot be used with discard. Le modificateur « Scoped » ne peut pas être utilisé avec discard. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index 8e9ff5da71416..0ac3d14141c60 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -1457,6 +1457,11 @@ '{0}' non è un nome di parametro valido da '{1}'. + + The '{0}' modifier cannot immediately follow the 'scoped' modifier. + The '{0}' modifier cannot immediately follow the 'scoped' modifier. + + The modifier '{0}' is not valid for this item in C# {1}. Please use language version '{2}' or greater. Il modificatore '{0}' non è valido per questo elemento in C# {1}. Usare la versione '{2}' o versioni successive del linguaggio. @@ -2357,6 +2362,11 @@ Il runtime di destinazione non supporta convenzioni di chiamata predefinite estendibili o dell'ambiente di runtime. + + The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. + The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. + + The 'scoped' modifier cannot be used with discard. Non è possibile usare il modificatore 'scoped' con discard. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index f85cba504ee36..f2d549781dd8b 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -1457,6 +1457,11 @@ '{0}' は、'{1}' からの有効なパラメーター名ではありません。 + + The '{0}' modifier cannot immediately follow the 'scoped' modifier. + The '{0}' modifier cannot immediately follow the 'scoped' modifier. + + The modifier '{0}' is not valid for this item in C# {1}. Please use language version '{2}' or greater. C# {1} では、修飾子 '{0}' はこの項目に対して有効ではありません。'{2}' 以上の言語バージョンをご使用ください。 @@ -2357,6 +2362,11 @@ ターゲット ランタイムは、拡張可能またはランタイム環境の既定の呼び出し規則をサポートしていません。 + + The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. + The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. + + The 'scoped' modifier cannot be used with discard. 'scoped' 修飾子を discard と共に使用することはできません。 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index 8284244bdb176..393077dfb3858 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -1457,6 +1457,11 @@ '{0}'은(는) '{1}'의 유효한 매개 변수 이름이 아닙니다. + + The '{0}' modifier cannot immediately follow the 'scoped' modifier. + The '{0}' modifier cannot immediately follow the 'scoped' modifier. + + The modifier '{0}' is not valid for this item in C# {1}. Please use language version '{2}' or greater. C# {1}의 이 항목에는 '{0}' 한정자가 유효하지 않습니다. 언어 버전 '{2}' 이상을 사용하세요. @@ -2357,6 +2362,11 @@ 대상 런타임에서 확장 가능 또는 런타임 환경 기본 호출 규칙을 지원하지 않습니다. + + The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. + The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. + + The 'scoped' modifier cannot be used with discard. 'scoped' 한정자는 무시 항목과 함께 사용할 수 없습니다. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index da459cc5b6389..a6a2606633b22 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -1457,6 +1457,11 @@ „{0}” nie jest prawidłową nazwą parametru z elementu „{1}”. + + The '{0}' modifier cannot immediately follow the 'scoped' modifier. + The '{0}' modifier cannot immediately follow the 'scoped' modifier. + + The modifier '{0}' is not valid for this item in C# {1}. Please use language version '{2}' or greater. Modyfikator „{0}” nie jest prawidłowy dla tego elementu w języku C# {1}. Użyj wersji języka „{2}” lub nowszej. @@ -2357,6 +2362,11 @@ Docelowe środowisko uruchomieniowe nie obsługuje rozszerzalnych ani domyślnych dla środowiska uruchomieniowego konwencji wywoływania. + + The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. + The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. + + The 'scoped' modifier cannot be used with discard. Modyfikator „scoped” nie może być używany z odrzuceniem. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index 90d782b7048e8..290835e6d52db 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -1457,6 +1457,11 @@ '{0}' não é um nome de parâmetro válido de '{1}'. + + The '{0}' modifier cannot immediately follow the 'scoped' modifier. + The '{0}' modifier cannot immediately follow the 'scoped' modifier. + + The modifier '{0}' is not valid for this item in C# {1}. Please use language version '{2}' or greater. O modificador '{0}' não é válido para este item no C# {1}. Use a versão de linguagem '{2}' ou superior. @@ -2357,6 +2362,11 @@ O runtime de destino não dá suporte a convenções de chamada padrão extensíveis ou de ambiente de runtime. + + The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. + The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. + + The 'scoped' modifier cannot be used with discard. O modificador 'scoped' não pode ser usado com descarte. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index 92e130f888c1a..dffd2877c6817 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -1457,6 +1457,11 @@ "{0}" не является допустимым именем параметра из "{1}". + + The '{0}' modifier cannot immediately follow the 'scoped' modifier. + The '{0}' modifier cannot immediately follow the 'scoped' modifier. + + The modifier '{0}' is not valid for this item in C# {1}. Please use language version '{2}' or greater. Модификатор "{0}" недопустим для этого элемента в C# {1}. Используйте версию языка "{2}" или более позднюю. @@ -2357,6 +2362,11 @@ Целевая среда выполнения не поддерживает расширяемые или принадлежащие среде выполнения соглашения о вызовах по умолчанию. + + The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. + The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. + + The 'scoped' modifier cannot be used with discard. Модификатор "scoped" нельзя использовать с отменой. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index 493f7e2a553b5..f6dfc9ffae25d 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -1457,6 +1457,11 @@ '{0}', '{1}' kaynağından geçerli bir parametre adı değil. + + The '{0}' modifier cannot immediately follow the 'scoped' modifier. + The '{0}' modifier cannot immediately follow the 'scoped' modifier. + + The modifier '{0}' is not valid for this item in C# {1}. Please use language version '{2}' or greater. '{0}' değiştiricisi bu öğe için C# {1} sürümünde geçerli değil. Lütfen '{2}' veya daha yüksek bir dil sürümü kullanın. @@ -2357,6 +2362,11 @@ Hedef çalışma zamanı, genişletilebilir veya çalışma zamanı ortamı varsayılanı çağırma kurallarını desteklemiyor. + + The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. + The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. + + The 'scoped' modifier cannot be used with discard. 'scoped' değiştiricisi atma ile kullanılamaz. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index 9cb1579f6b145..e30d5f8dbc583 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -1457,6 +1457,11 @@ “{0}”不是来自“{1}”的有效参数名称。 + + The '{0}' modifier cannot immediately follow the 'scoped' modifier. + The '{0}' modifier cannot immediately follow the 'scoped' modifier. + + The modifier '{0}' is not valid for this item in C# {1}. Please use language version '{2}' or greater. 在 C# {1} 中,修饰符 "{0}" 对此项无效。请使用语言版本 "{2}" 或更高版本。 @@ -2357,6 +2362,11 @@ 目标运行时不支持可扩展或运行时环境默认调用约定。 + + The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. + The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. + + The 'scoped' modifier cannot be used with discard. "scoped" 修饰符不能与 discard 一起使用。 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index e10aaee051992..f7c0dadf22036 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -1457,6 +1457,11 @@ '{0}' 不是來自 '{1}' 的有效參數名稱。 + + The '{0}' modifier cannot immediately follow the 'scoped' modifier. + The '{0}' modifier cannot immediately follow the 'scoped' modifier. + + The modifier '{0}' is not valid for this item in C# {1}. Please use language version '{2}' or greater. 修飾元 '{0}' 在 C# {1} 中對此項目無效。請使用 '{2}' 或更高的語言版本。 @@ -2357,6 +2362,11 @@ 目標執行階段不支援可延伸或執行階段環境的預設呼叫慣例。 + + The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. + The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. + + The 'scoped' modifier cannot be used with discard. 'scoped' 修飾元不能與捨棄一起使用。 diff --git a/src/Compilers/CSharp/Test/Emit3/RefReadonlyParameterTests.cs b/src/Compilers/CSharp/Test/Emit3/RefReadonlyParameterTests.cs index e2865a72d1f5a..596e23a96d890 100644 --- a/src/Compilers/CSharp/Test/Emit3/RefReadonlyParameterTests.cs +++ b/src/Compilers/CSharp/Test/Emit3/RefReadonlyParameterTests.cs @@ -2146,15 +2146,9 @@ static class C """; var expectedDiagnostics = new[] { - // (3,30): error CS0246: The type or namespace name 'scoped' could not be found (are you missing a using directive or an assembly reference?) + // (3,30): error CS9347: The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. // public static void M(ref scoped readonly int p) => throw null; - Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "scoped").WithArguments("scoped").WithLocation(3, 30), - // (3,37): error CS1001: Identifier expected - // public static void M(ref scoped readonly int p) => throw null; - Diagnostic(ErrorCode.ERR_IdentifierExpected, "readonly").WithLocation(3, 37), - // (3,37): error CS1003: Syntax error, ',' expected - // public static void M(ref scoped readonly int p) => throw null; - Diagnostic(ErrorCode.ERR_SyntaxError, "readonly").WithArguments(",").WithLocation(3, 37), + Diagnostic(ErrorCode.ERR_ScopedAfterInOutRefReadonly, "scoped").WithLocation(3, 30), // (3,37): error CS9190: 'readonly' modifier must be specified after 'ref'. // public static void M(ref scoped readonly int p) => throw null; Diagnostic(ErrorCode.ERR_RefReadOnlyWrongOrdering, "readonly").WithLocation(3, 37) @@ -2178,16 +2172,7 @@ static class C { // (3,26): error CS9190: 'readonly' modifier must be specified after 'ref'. // public static void M(readonly scoped ref int p) => throw null; - Diagnostic(ErrorCode.ERR_RefReadOnlyWrongOrdering, "readonly").WithLocation(3, 26), - // (3,35): error CS0246: The type or namespace name 'scoped' could not be found (are you missing a using directive or an assembly reference?) - // public static void M(readonly scoped ref int p) => throw null; - Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "scoped").WithArguments("scoped").WithLocation(3, 35), - // (3,42): error CS1001: Identifier expected - // public static void M(readonly scoped ref int p) => throw null; - Diagnostic(ErrorCode.ERR_IdentifierExpected, "ref").WithLocation(3, 42), - // (3,42): error CS1003: Syntax error, ',' expected - // public static void M(readonly scoped ref int p) => throw null; - Diagnostic(ErrorCode.ERR_SyntaxError, "ref").WithArguments(",").WithLocation(3, 42) + Diagnostic(ErrorCode.ERR_RefReadOnlyWrongOrdering, "readonly").WithLocation(3, 26) }; CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics(expectedDiagnostics); @@ -2206,15 +2191,12 @@ static class C """; var expectedDiagnostics = new[] { - // (3,26): error CS0246: The type or namespace name 'scoped' could not be found (are you missing a using directive or an assembly reference?) - // public static void M(scoped readonly int p) => throw null; - Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "scoped").WithArguments("scoped").WithLocation(3, 26), - // (3,33): error CS1001: Identifier expected + // (3,26): error CS9048: The 'scoped' modifier can be used for refs and ref struct values only. // public static void M(scoped readonly int p) => throw null; - Diagnostic(ErrorCode.ERR_IdentifierExpected, "readonly").WithLocation(3, 33), - // (3,33): error CS1003: Syntax error, ',' expected + Diagnostic(ErrorCode.ERR_ScopedRefAndRefStructOnly, "scoped readonly int p").WithLocation(3, 26), + // (3,33): error CS9348: The 'readonly' modifier cannot immediately follow the 'scoped' modifier. // public static void M(scoped readonly int p) => throw null; - Diagnostic(ErrorCode.ERR_SyntaxError, "readonly").WithArguments(",").WithLocation(3, 33), + Diagnostic(ErrorCode.ERR_InvalidModifierAfterScoped, "readonly").WithArguments("readonly").WithLocation(3, 33), // (3,33): error CS9190: 'readonly' modifier must be specified after 'ref'. // public static void M(scoped readonly int p) => throw null; Diagnostic(ErrorCode.ERR_RefReadOnlyWrongOrdering, "readonly").WithLocation(3, 33) diff --git a/src/Compilers/CSharp/Test/Emit3/Semantics/ParamsCollectionTests.cs b/src/Compilers/CSharp/Test/Emit3/Semantics/ParamsCollectionTests.cs index 608dbdaf139d6..c94363eb2106e 100644 --- a/src/Compilers/CSharp/Test/Emit3/Semantics/ParamsCollectionTests.cs +++ b/src/Compilers/CSharp/Test/Emit3/Semantics/ParamsCollectionTests.cs @@ -17035,5 +17035,54 @@ .locals init (<>y__InlineArray4 V_0) } "); } + + [Fact] + public void ScopedParams() + { + var source = """ + using System.Collections; + using System.Collections.Generic; + ref struct S : IEnumerable + { + public void Add(int i) { } + + public IEnumerator GetEnumerator() => throw null; + IEnumerator IEnumerable.GetEnumerator() => throw null; + } + static class C + { + public static void M(scoped params S x) + { + } + } + """; + CreateCompilation(source, targetFramework: TargetFramework.Net90).VerifyDiagnostics( + // (12,33): error CS9348: The 'params' modifier cannot immediately follow the 'scoped' modifier. + // public static void M(scoped params S x) + Diagnostic(ErrorCode.ERR_InvalidModifierAfterScoped, "params").WithArguments("params").WithLocation(12, 33)); + } + + [Fact] + public void ParamsScoped() + { + var source = """ + using System.Collections; + using System.Collections.Generic; + ref struct S : IEnumerable + { + public void Add(int i) { } + + public IEnumerator GetEnumerator() => throw null; + IEnumerator IEnumerable.GetEnumerator() => throw null; + } + static class C + { + public static void M(params scoped S x) + { + } + } + """; + CreateCompilation(source, targetFramework: TargetFramework.Net90).VerifyDiagnostics(); + } } } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/LambdaTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/LambdaTests.cs index d0f01f619f6d7..da22a01223836 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/LambdaTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/LambdaTests.cs @@ -9396,5 +9396,73 @@ class ClassWithIntProperty : IWithIntProperty x.IntProperty "); } + + [Fact] + public void TestMultipleScopedModifiers() + { + CreateCompilation(""" + using System; + var v = (scoped scoped Span s) => { }; + """, + targetFramework: TargetFramework.Net90).VerifyDiagnostics( + // (2,17): error CS1107: A parameter can only have one 'scoped' modifier + // var v = (scoped scoped Span s) => { }; + Diagnostic(ErrorCode.ERR_DupParamMod, "scoped").WithArguments("scoped").WithLocation(2, 17)); + } + + [Fact] + public void TestMultipleRefModifiers() + { + CreateCompilation(""" + using System; + var v = (ref ref Span s) => { }; + """, + targetFramework: TargetFramework.Net90).VerifyDiagnostics( + // (2,14): error CS1107: A parameter can only have one 'ref' modifier + // var v = (ref ref Span s) => { }; + Diagnostic(ErrorCode.ERR_DupParamMod, "ref").WithArguments("ref").WithLocation(2, 14)); + } + + [Fact] + public void TestMultipleOutModifiers() + { + CreateCompilation(""" + using System; + var v = (out out Span s) => { s = default; }; + """, + targetFramework: TargetFramework.Net90).VerifyDiagnostics( + // (2,14): error CS1107: A parameter can only have one 'out' modifier + // var v = (out out Span s) => { s = default; }; + Diagnostic(ErrorCode.ERR_DupParamMod, "out").WithArguments("out").WithLocation(2, 14)); + } + + [Fact] + public void TestMultipleInModifiers() + { + CreateCompilation(""" + using System; + var v = (in in Span s) => { }; + """, + targetFramework: TargetFramework.Net90).VerifyDiagnostics( + // (2,13): error CS1107: A parameter can only have one 'in' modifier + // var v = (in in Span s) => { }; + Diagnostic(ErrorCode.ERR_DupParamMod, "in").WithArguments("in").WithLocation(2, 13)); + } + + [Fact] + public void TestMultipleReadonlyModifiers() + { + CreateCompilation(""" + using System; + var v = (readonly readonly Span s) => { }; + """, + targetFramework: TargetFramework.Net90).VerifyDiagnostics( + // (2,10): error CS9190: 'readonly' modifier must be specified after 'ref'. + // var v = (readonly readonly Span s) => { }; + Diagnostic(ErrorCode.ERR_RefReadOnlyWrongOrdering, "readonly").WithLocation(2, 10), + // (2,19): error CS9190: 'readonly' modifier must be specified after 'ref'. + // var v = (readonly readonly Span s) => { }; + Diagnostic(ErrorCode.ERR_RefReadOnlyWrongOrdering, "readonly").WithLocation(2, 19)); + } } } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs index 4aea9bf02a2d8..725a1e993872e 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs @@ -11327,24 +11327,15 @@ static void Main() }"; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular13); comp.VerifyEmitDiagnostics( - // (6,18): error CS8917: The delegate type could not be inferred. + // (6,26): error CS1107: A parameter can only have one 'scoped' modifier // var f1 = (scoped scoped R r) => { }; - Diagnostic(ErrorCode.ERR_CannotInferDelegateType, "(scoped scoped R r) => { }").WithLocation(6, 18), - // (6,26): error CS0246: The type or namespace name 'scoped' could not be found (are you missing a using directive or an assembly reference?) - // var f1 = (scoped scoped R r) => { }; - Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "scoped").WithArguments("scoped").WithLocation(6, 26), - // (6,35): error CS1003: Syntax error, ',' expected - // var f1 = (scoped scoped R r) => { }; - Diagnostic(ErrorCode.ERR_SyntaxError, "r").WithArguments(",").WithLocation(6, 35), - // (6,35): error CS0748: Inconsistent lambda parameter usage; parameter types must be all explicit or all implicit - // var f1 = (scoped scoped R r) => { }; - Diagnostic(ErrorCode.ERR_InconsistentLambdaParameterUsage, "r").WithLocation(6, 35), - // (7,23): error CS0246: The type or namespace name 'scoped' could not be found (are you missing a using directive or an assembly reference?) + Diagnostic(ErrorCode.ERR_DupParamMod, "scoped").WithArguments("scoped").WithLocation(6, 26), + // (7,23): error CS9347: The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. // var f2 = (ref scoped scoped R r) => { }; - Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "scoped").WithArguments("scoped").WithLocation(7, 23), - // (7,37): error CS1003: Syntax error, ',' expected + Diagnostic(ErrorCode.ERR_ScopedAfterInOutRefReadonly, "scoped").WithLocation(7, 23), + // (7,30): error CS1107: A parameter can only have one 'scoped' modifier // var f2 = (ref scoped scoped R r) => { }; - Diagnostic(ErrorCode.ERR_SyntaxError, "R").WithArguments(",").WithLocation(7, 37), + Diagnostic(ErrorCode.ERR_DupParamMod, "scoped").WithArguments("scoped").WithLocation(7, 30), // (8,19): error CS0246: The type or namespace name 'scoped' could not be found (are you missing a using directive or an assembly reference?) // var f3 = (scoped scoped ref R r) => { }; Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "scoped").WithArguments("scoped").WithLocation(8, 19), @@ -11371,33 +11362,18 @@ static void Main() """; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular14); comp.VerifyEmitDiagnostics( - // (6,18): error CS8917: The delegate type could not be inferred. - // var f1 = (scoped scoped R r) => { }; - Diagnostic(ErrorCode.ERR_CannotInferDelegateType, "(scoped scoped R r) => { }").WithLocation(6, 18), - // (6,26): error CS0246: The type or namespace name 'scoped' could not be found (are you missing a using directive or an assembly reference?) - // var f1 = (scoped scoped R r) => { }; - Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "scoped").WithArguments("scoped").WithLocation(6, 26), - // (6,35): error CS1003: Syntax error, ',' expected + // (6,26): error CS1107: A parameter can only have one 'scoped' modifier // var f1 = (scoped scoped R r) => { }; - Diagnostic(ErrorCode.ERR_SyntaxError, "r").WithArguments(",").WithLocation(6, 35), - // (6,35): error CS0748: Inconsistent lambda parameter usage; parameter types must be all explicit or all implicit - // var f1 = (scoped scoped R r) => { }; - Diagnostic(ErrorCode.ERR_InconsistentLambdaParameterUsage, "r").WithLocation(6, 35), - // (7,23): error CS0246: The type or namespace name 'scoped' could not be found (are you missing a using directive or an assembly reference?) + Diagnostic(ErrorCode.ERR_DupParamMod, "scoped").WithArguments("scoped").WithLocation(6, 26), + // (7,23): error CS9347: The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. // var f2 = (ref scoped scoped R r) => { }; - Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "scoped").WithArguments("scoped").WithLocation(7, 23), - // (7,37): error CS1003: Syntax error, ',' expected + Diagnostic(ErrorCode.ERR_ScopedAfterInOutRefReadonly, "scoped").WithLocation(7, 23), + // (7,30): error CS1107: A parameter can only have one 'scoped' modifier // var f2 = (ref scoped scoped R r) => { }; - Diagnostic(ErrorCode.ERR_SyntaxError, "R").WithArguments(",").WithLocation(7, 37), - // (8,26): error CS0246: The type or namespace name 'scoped' could not be found (are you missing a using directive or an assembly reference?) - // var f3 = (scoped scoped ref R r) => { }; - Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "scoped").WithArguments("scoped").WithLocation(8, 26), - // (8,33): error CS1001: Identifier expected + Diagnostic(ErrorCode.ERR_DupParamMod, "scoped").WithArguments("scoped").WithLocation(7, 30), + // (8,26): error CS1107: A parameter can only have one 'scoped' modifier // var f3 = (scoped scoped ref R r) => { }; - Diagnostic(ErrorCode.ERR_IdentifierExpected, "ref").WithLocation(8, 33), - // (8,33): error CS1003: Syntax error, ',' expected - // var f3 = (scoped scoped ref R r) => { }; - Diagnostic(ErrorCode.ERR_SyntaxError, "ref").WithArguments(",").WithLocation(8, 33)); + Diagnostic(ErrorCode.ERR_DupParamMod, "scoped").WithArguments("scoped").WithLocation(8, 26)); } [Fact] @@ -11652,23 +11628,13 @@ static void F3(this scoped ref T t) where T : struct { } }"; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (6,23): error CS0246: The type or namespace name 'scoped' could not be found (are you missing a using directive or an assembly reference?) + // (6,30): error CS9348: The 'this' modifier cannot immediately follow the 'scoped' modifier. // static void F2(scoped this R r) { } - Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "scoped").WithArguments("scoped").WithLocation(6, 23), - // (6,30): error CS1001: Identifier expected - // static void F2(scoped this R r) { } - Diagnostic(ErrorCode.ERR_IdentifierExpected, "this").WithLocation(6, 30), - // (6,30): error CS1003: Syntax error, ',' expected - // static void F2(scoped this R r) { } - Diagnostic(ErrorCode.ERR_SyntaxError, "this").WithArguments(",").WithLocation(6, 30), - // (6,30): error CS1100: Method 'F2' has a parameter modifier 'this' which is not on the first parameter - // static void F2(scoped this R r) { } - Diagnostic(ErrorCode.ERR_BadThisParam, "this").WithArguments("F2").WithLocation(6, 30) - ); + Diagnostic(ErrorCode.ERR_InvalidModifierAfterScoped, "this").WithArguments("this").WithLocation(6, 30)); VerifyParameterSymbol(comp.GetMember("Extensions.F0").Parameters[0], "R r", RefKind.None, ScopedKind.None); VerifyParameterSymbol(comp.GetMember("Extensions.F1").Parameters[0], "scoped R r", RefKind.None, ScopedKind.ScopedValue); - VerifyParameterSymbol(comp.GetMember("Extensions.F2").Parameters[0], "scoped", RefKind.None, ScopedKind.None); + VerifyParameterSymbol(comp.GetMember("Extensions.F2").Parameters[0], "scoped R r", RefKind.None, ScopedKind.ScopedValue); VerifyParameterSymbol(comp.GetMember("Extensions.F3").Parameters[0], "scoped ref T t", RefKind.Ref, ScopedKind.ScopedRef); } @@ -11789,10 +11755,9 @@ scoped readonly ref struct C { } // (2,12): error CS1031: Type expected // scoped ref struct B { } Diagnostic(ErrorCode.ERR_TypeExpected, "struct").WithLocation(2, 12), - // (3,8): error CS1585: Member modifier 'readonly' must precede the member type and name + // (3,1): error CS0116: A namespace cannot directly contain members such as fields, methods or statements // scoped readonly ref struct C { } - Diagnostic(ErrorCode.ERR_BadModifierLocation, "readonly").WithArguments("readonly").WithLocation(3, 8) - ); + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "scoped").WithLocation(3, 1)); } [Fact] @@ -11817,9 +11782,9 @@ public void TypeScopeModifier_02_CSharp10() // (1,15): error CS0548: '.A': property or indexer must have at least one accessor // scoped record A { } Diagnostic(ErrorCode.ERR_PropertyWithNoAccessors, "A").WithArguments(".A").WithLocation(1, 15), - // (2,8): error CS1585: Member modifier 'readonly' must precede the member type and name + // (2,1): error CS0116: A namespace cannot directly contain members such as fields, methods or statements // scoped readonly record struct B; - Diagnostic(ErrorCode.ERR_BadModifierLocation, "readonly").WithArguments("readonly").WithLocation(2, 8), + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "scoped").WithLocation(2, 1), // (3,1): error CS8803: Top-level statements must precede namespace and type declarations. // readonly scoped record struct C(); Diagnostic(ErrorCode.ERR_TopLevelStatementAfterNamespaceOrType, "readonly scoped record ").WithLocation(3, 1), @@ -11837,8 +11802,7 @@ public void TypeScopeModifier_02_CSharp10() Diagnostic(ErrorCode.ERR_SemicolonExpected, "struct").WithLocation(3, 24), // (3,32): error CS8936: Feature 'primary constructors' is not available in C# 10.0. Please use language version 12.0 or greater. // readonly scoped record struct C(); - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion10, "()").WithArguments("primary constructors", "12.0").WithLocation(3, 32) - ); + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion10, "()").WithArguments("primary constructors", "12.0").WithLocation(3, 32)); } [Fact] @@ -11863,9 +11827,9 @@ public void TypeScopeModifier_02_CSharp11() // (1,15): error CS0548: '.A': property or indexer must have at least one accessor // scoped record A { } Diagnostic(ErrorCode.ERR_PropertyWithNoAccessors, "A").WithArguments(".A").WithLocation(1, 15), - // (2,8): error CS1585: Member modifier 'readonly' must precede the member type and name + // (2,1): error CS0116: A namespace cannot directly contain members such as fields, methods or statements // scoped readonly record struct B; - Diagnostic(ErrorCode.ERR_BadModifierLocation, "readonly").WithArguments("readonly").WithLocation(2, 8), + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "scoped").WithLocation(2, 1), // (3,1): error CS8803: Top-level statements must precede namespace and type declarations. // readonly scoped record struct C(); Diagnostic(ErrorCode.ERR_TopLevelStatementAfterNamespaceOrType, "readonly scoped record ").WithLocation(3, 1), @@ -11883,8 +11847,7 @@ public void TypeScopeModifier_02_CSharp11() Diagnostic(ErrorCode.ERR_SemicolonExpected, "struct").WithLocation(3, 24), // (3,32): error CS9058: Feature 'primary constructors' is not available in C# 11.0. Please use language version 12.0 or greater. // readonly scoped record struct C(); - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion11, "()").WithArguments("primary constructors", "12.0").WithLocation(3, 32) - ); + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion11, "()").WithArguments("primary constructors", "12.0").WithLocation(3, 32)); } [Fact] @@ -21963,13 +21926,12 @@ public void RefScoped() // (3,18): error CS1002: ; expected // ref scoped R field; Diagnostic(ErrorCode.ERR_SemicolonExpected, "field").WithLocation(3, 18), - // (3,23): error CS1519: Invalid token ';' in class, record, struct, or interface member declaration + // (3,23): error CS1519: Invalid token ';' in a member declaration // ref scoped R field; Diagnostic(ErrorCode.ERR_InvalidMemberDecl, ";").WithArguments(";").WithLocation(3, 23), - // (3,23): error CS1519: Invalid token ';' in class, record, struct, or interface member declaration + // (3,23): error CS1519: Invalid token ';' in a member declaration // ref scoped R field; - Diagnostic(ErrorCode.ERR_InvalidMemberDecl, ";").WithArguments(";").WithLocation(3, 23) - ); + Diagnostic(ErrorCode.ERR_InvalidMemberDecl, ";").WithArguments(";").WithLocation(3, 23)); source = @"ref struct R @@ -22009,19 +21971,9 @@ void M(ref scoped R parameter) }"; comp = CreateCompilation(source); comp.VerifyDiagnostics( - // (3,16): error CS0246: The type or namespace name 'scoped' could not be found (are you missing a using directive or an assembly reference?) - // void M(ref scoped R parameter) - Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "scoped").WithArguments("scoped").WithLocation(3, 16), - // (3,25): error CS1003: Syntax error, ',' expected + // (3,16): error CS9347: The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. // void M(ref scoped R parameter) - Diagnostic(ErrorCode.ERR_SyntaxError, "parameter").WithArguments(",").WithLocation(3, 25), - // (3,25): error CS0246: The type or namespace name 'parameter' could not be found (are you missing a using directive or an assembly reference?) - // void M(ref scoped R parameter) - Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "parameter").WithArguments("parameter").WithLocation(3, 25), - // (3,34): error CS1001: Identifier expected - // void M(ref scoped R parameter) - Diagnostic(ErrorCode.ERR_IdentifierExpected, ")").WithLocation(3, 34) - ); + Diagnostic(ErrorCode.ERR_ScopedAfterInOutRefReadonly, "scoped").WithLocation(3, 16)); source = @"ref struct R @@ -22032,19 +21984,9 @@ void M(in scoped R parameter) }"; comp = CreateCompilation(source); comp.VerifyDiagnostics( - // (3,15): error CS0246: The type or namespace name 'scoped' could not be found (are you missing a using directive or an assembly reference?) - // void M(in scoped R parameter) - Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "scoped").WithArguments("scoped").WithLocation(3, 15), - // (3,24): error CS1003: Syntax error, ',' expected - // void M(in scoped R parameter) - Diagnostic(ErrorCode.ERR_SyntaxError, "parameter").WithArguments(",").WithLocation(3, 24), - // (3,24): error CS0246: The type or namespace name 'parameter' could not be found (are you missing a using directive or an assembly reference?) + // (3,15): error CS9347: The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. // void M(in scoped R parameter) - Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "parameter").WithArguments("parameter").WithLocation(3, 24), - // (3,33): error CS1001: Identifier expected - // void M(in scoped R parameter) - Diagnostic(ErrorCode.ERR_IdentifierExpected, ")").WithLocation(3, 33) - ); + Diagnostic(ErrorCode.ERR_ScopedAfterInOutRefReadonly, "scoped").WithLocation(3, 15)); source = @"ref struct R @@ -22055,22 +21997,9 @@ void M(out scoped R parameter) }"; comp = CreateCompilation(source); comp.VerifyDiagnostics( - // (3,10): error CS0177: The out parameter 'R' must be assigned to before control leaves the current method - // void M(out scoped R parameter) - Diagnostic(ErrorCode.ERR_ParamUnassigned, "M").WithArguments("R").WithLocation(3, 10), - // (3,16): error CS0246: The type or namespace name 'scoped' could not be found (are you missing a using directive or an assembly reference?) - // void M(out scoped R parameter) - Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "scoped").WithArguments("scoped").WithLocation(3, 16), - // (3,25): error CS1003: Syntax error, ',' expected - // void M(out scoped R parameter) - Diagnostic(ErrorCode.ERR_SyntaxError, "parameter").WithArguments(",").WithLocation(3, 25), - // (3,25): error CS0246: The type or namespace name 'parameter' could not be found (are you missing a using directive or an assembly reference?) + // (3,16): error CS9347: The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. // void M(out scoped R parameter) - Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "parameter").WithArguments("parameter").WithLocation(3, 25), - // (3,34): error CS1001: Identifier expected - // void M(out scoped R parameter) - Diagnostic(ErrorCode.ERR_IdentifierExpected, ")").WithLocation(3, 34) - ); + Diagnostic(ErrorCode.ERR_ScopedAfterInOutRefReadonly, "scoped").WithLocation(3, 16)); source = @"ref struct R @@ -22081,13 +22010,12 @@ void M(ref scoped scoped R parameter) }"; comp = CreateCompilation(source); comp.VerifyDiagnostics( - // (3,16): error CS0246: The type or namespace name 'scoped' could not be found (are you missing a using directive or an assembly reference?) + // (3,16): error CS9347: The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. // void M(ref scoped scoped R parameter) - Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "scoped").WithArguments("scoped").WithLocation(3, 16), - // (3,30): error CS1003: Syntax error, ',' expected + Diagnostic(ErrorCode.ERR_ScopedAfterInOutRefReadonly, "scoped").WithLocation(3, 16), + // (3,23): error CS1107: A parameter can only have one 'scoped' modifier // void M(ref scoped scoped R parameter) - Diagnostic(ErrorCode.ERR_SyntaxError, "R").WithArguments(",").WithLocation(3, 30) - ); + Diagnostic(ErrorCode.ERR_DupParamMod, "scoped").WithArguments("scoped").WithLocation(3, 23)); source = @"ref struct R @@ -22190,19 +22118,9 @@ ref struct R { } "; comp = CreateCompilation(source); comp.VerifyDiagnostics( - // (2,21): error CS0246: The type or namespace name 'scoped' could not be found (are you missing a using directive or an assembly reference?) - // delegate void M(ref scoped R parameter); - Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "scoped").WithArguments("scoped").WithLocation(2, 21), - // (2,30): error CS1003: Syntax error, ',' expected - // delegate void M(ref scoped R parameter); - Diagnostic(ErrorCode.ERR_SyntaxError, "parameter").WithArguments(",").WithLocation(2, 30), - // (2,30): error CS0246: The type or namespace name 'parameter' could not be found (are you missing a using directive or an assembly reference?) + // (2,21): error CS9347: The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. // delegate void M(ref scoped R parameter); - Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "parameter").WithArguments("parameter").WithLocation(2, 30), - // (2,39): error CS1001: Identifier expected - // delegate void M(ref scoped R parameter); - Diagnostic(ErrorCode.ERR_IdentifierExpected, ")").WithLocation(2, 39) - ); + Diagnostic(ErrorCode.ERR_ScopedAfterInOutRefReadonly, "scoped").WithLocation(2, 21)); source = @" ref struct R @@ -22218,15 +22136,9 @@ void M() // (6,9): error CS8183: Cannot infer the type of implicitly-typed discard. // _ = void (ref scoped R parameter) => throw null; Diagnostic(ErrorCode.ERR_DiscardTypeInferenceFailed, "_").WithLocation(6, 9), - // (6,23): error CS0246: The type or namespace name 'scoped' could not be found (are you missing a using directive or an assembly reference?) - // _ = void (ref scoped R parameter) => throw null; - Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "scoped").WithArguments("scoped").WithLocation(6, 23), - // (6,32): error CS1003: Syntax error, ',' expected - // _ = void (ref scoped R parameter) => throw null; - Diagnostic(ErrorCode.ERR_SyntaxError, "parameter").WithArguments(",").WithLocation(6, 32), - // (6,32): error CS0748: Inconsistent lambda parameter usage; parameter types must be all explicit or all implicit + // (6,23): error CS9347: The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. // _ = void (ref scoped R parameter) => throw null; - Diagnostic(ErrorCode.ERR_InconsistentLambdaParameterUsage, "parameter").WithLocation(6, 32)); + Diagnostic(ErrorCode.ERR_ScopedAfterInOutRefReadonly, "scoped").WithLocation(6, 23)); } [Theory, WorkItem(62931, "https://github.com/dotnet/roslyn/issues/62931")] diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/DeclarationParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/DeclarationParsingTests.cs index d3c7a7e5fec53..60f2cd992fabb 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/DeclarationParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/DeclarationParsingTests.cs @@ -19237,5 +19237,126 @@ struct C { } EOF(); } + + [Fact] + public void ScopedInParameter1() + { + var text = """ + static class C + { + public static void M(scoped in this int x) { } + } + """; + CreateCompilation(text).VerifyDiagnostics(); + + var tree = UsingTree(text); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PublicKeyword); + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.IdentifierToken, "M"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.ScopedKeyword); + N(SyntaxKind.InKeyword); + N(SyntaxKind.ThisKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.IdentifierToken, "x"); + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void ScopedInParameter2() + { + var text = """ + static class C + { + public static void M(this in scoped int x) { } + } + """; + CreateCompilation(text).VerifyDiagnostics( + // (3,34): error CS9349: The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. + // public static void M(this in scoped int x) { } + Diagnostic(ErrorCode.ERR_ScopedAfterInOutRefReadonly, "scoped").WithLocation(3, 34)); + + var tree = UsingTree(text); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PublicKeyword); + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.IdentifierToken, "M"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.ThisKeyword); + N(SyntaxKind.InKeyword); + N(SyntaxKind.ScopedKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.IdentifierToken, "x"); + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } } } diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/DeclarationScopeParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/DeclarationScopeParsingTests.cs index 2af1953c35c0b..36c71ce0adb25 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/DeclarationScopeParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/DeclarationScopeParsingTests.cs @@ -2,7 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Linq; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; +using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; using Xunit; using Xunit.Abstractions; @@ -133,32 +135,49 @@ public void Method_02(LanguageVersion langVersion) EOF(); } + private static DiagnosticDescription[] FilterLanguageVersionChecks(LanguageVersion langVersion, params DiagnosticDescription[] expectedDiagnostics) + { + if (langVersion > LanguageVersion.CSharp10) + expectedDiagnostics = [.. expectedDiagnostics.Where(d => d.Code is not (int)ErrorCode.ERR_FeatureNotAvailableInVersion10)]; + + // Can add further filtering here if needed in future. + + return expectedDiagnostics; + } + [Theory] [InlineData(LanguageVersion.CSharp10)] [InlineData(LanguageVersion.CSharp11)] public void Method_03(LanguageVersion langVersion) { string source = "void F(ref scoped int b, in scoped int c, out scoped int d) { }"; - UsingDeclaration(source, TestOptions.Regular.WithLanguageVersion(langVersion), - // (1,19): error CS1001: Identifier expected - // void F(ref scoped int b, in scoped int c, out scoped int d) { } - Diagnostic(ErrorCode.ERR_IdentifierExpected, "int").WithLocation(1, 19), - // (1,19): error CS1003: Syntax error, ',' expected - // void F(ref scoped int b, in scoped int c, out scoped int d) { } - Diagnostic(ErrorCode.ERR_SyntaxError, "int").WithArguments(",").WithLocation(1, 19), - // (1,36): error CS1001: Identifier expected - // void F(ref scoped int b, in scoped int c, out scoped int d) { } - Diagnostic(ErrorCode.ERR_IdentifierExpected, "int").WithLocation(1, 36), - // (1,36): error CS1003: Syntax error, ',' expected - // void F(ref scoped int b, in scoped int c, out scoped int d) { } - Diagnostic(ErrorCode.ERR_SyntaxError, "int").WithArguments(",").WithLocation(1, 36), - // (1,54): error CS1001: Identifier expected - // void F(ref scoped int b, in scoped int c, out scoped int d) { } - Diagnostic(ErrorCode.ERR_IdentifierExpected, "int").WithLocation(1, 54), - // (1,54): error CS1003: Syntax error, ',' expected - // void F(ref scoped int b, in scoped int c, out scoped int d) { } - Diagnostic(ErrorCode.ERR_SyntaxError, "int").WithArguments(",").WithLocation(1, 54) - ); + UsingDeclaration(source, TestOptions.Regular.WithLanguageVersion(langVersion)); + CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(langVersion)).VerifyDiagnostics( + FilterLanguageVersionChecks(langVersion, + // (1,6): error CS0177: The out parameter 'd' must be assigned to before control leaves the current method + // void F(ref scoped int b, in scoped int c, out scoped int d) { } + Diagnostic(ErrorCode.ERR_ParamUnassigned, "F").WithArguments("d").WithLocation(1, 6), + // (1,6): warning CS8321: The local function 'F' is declared but never used + // void F(ref scoped int b, in scoped int c, out scoped int d) { } + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "F").WithArguments("F").WithLocation(1, 6), + // (1,12): error CS8936: Feature 'ref fields' is not available in C# 10.0. Please use language version 11.0 or greater. + // void F(ref scoped int b, in scoped int c, out scoped int d) { } + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion10, "scoped").WithArguments("ref fields", "11.0").WithLocation(1, 12), + // (1,12): error CS9347: The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. + // void F(ref scoped int b, in scoped int c, out scoped int d) { } + Diagnostic(ErrorCode.ERR_ScopedAfterInOutRefReadonly, "scoped").WithLocation(1, 12), + // (1,29): error CS8936: Feature 'ref fields' is not available in C# 10.0. Please use language version 11.0 or greater. + // void F(ref scoped int b, in scoped int c, out scoped int d) { } + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion10, "scoped").WithArguments("ref fields", "11.0").WithLocation(1, 29), + // (1,29): error CS9347: The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. + // void F(ref scoped int b, in scoped int c, out scoped int d) { } + Diagnostic(ErrorCode.ERR_ScopedAfterInOutRefReadonly, "scoped").WithLocation(1, 29), + // (1,47): error CS8936: Feature 'ref fields' is not available in C# 10.0. Please use language version 11.0 or greater. + // void F(ref scoped int b, in scoped int c, out scoped int d) { } + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion10, "scoped").WithArguments("ref fields", "11.0").WithLocation(1, 47), + // (1,47): error CS9347: The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. + // void F(ref scoped int b, in scoped int c, out scoped int d) { } + Diagnostic(ErrorCode.ERR_ScopedAfterInOutRefReadonly, "scoped").WithLocation(1, 47))); N(SyntaxKind.MethodDeclaration); { @@ -173,15 +192,7 @@ public void Method_03(LanguageVersion langVersion) N(SyntaxKind.Parameter); { N(SyntaxKind.RefKeyword); - N(SyntaxKind.IdentifierName); - { - N(SyntaxKind.IdentifierToken, "scoped"); - } - M(SyntaxKind.IdentifierToken); - } - M(SyntaxKind.CommaToken); - N(SyntaxKind.Parameter); - { + N(SyntaxKind.ScopedKeyword); N(SyntaxKind.PredefinedType); { N(SyntaxKind.IntKeyword); @@ -192,15 +203,7 @@ public void Method_03(LanguageVersion langVersion) N(SyntaxKind.Parameter); { N(SyntaxKind.InKeyword); - N(SyntaxKind.IdentifierName); - { - N(SyntaxKind.IdentifierToken, "scoped"); - } - M(SyntaxKind.IdentifierToken); - } - M(SyntaxKind.CommaToken); - N(SyntaxKind.Parameter); - { + N(SyntaxKind.ScopedKeyword); N(SyntaxKind.PredefinedType); { N(SyntaxKind.IntKeyword); @@ -211,15 +214,7 @@ public void Method_03(LanguageVersion langVersion) N(SyntaxKind.Parameter); { N(SyntaxKind.OutKeyword); - N(SyntaxKind.IdentifierName); - { - N(SyntaxKind.IdentifierToken, "scoped"); - } - M(SyntaxKind.IdentifierToken); - } - M(SyntaxKind.CommaToken); - N(SyntaxKind.Parameter); - { + N(SyntaxKind.ScopedKeyword); N(SyntaxKind.PredefinedType); { N(SyntaxKind.IntKeyword); @@ -564,11 +559,20 @@ public void Method_07() public void Method_08() { string source = "void F(ref scoped scoped R r) { }"; - UsingDeclaration(source, TestOptions.Regular11, - // (1,26): error CS1003: Syntax error, ',' expected + UsingDeclaration(source, TestOptions.Regular11); + CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics( + // (1,6): warning CS8321: The local function 'F' is declared but never used // void F(ref scoped scoped R r) { } - Diagnostic(ErrorCode.ERR_SyntaxError, "R").WithArguments(",").WithLocation(1, 26) - ); + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "F").WithArguments("F").WithLocation(1, 6), + // (1,12): error CS9347: The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. + // void F(ref scoped scoped R r) { } + Diagnostic(ErrorCode.ERR_ScopedAfterInOutRefReadonly, "scoped").WithLocation(1, 12), + // (1,19): error CS1107: A parameter can only have one 'scoped' modifier + // void F(ref scoped scoped R r) { } + Diagnostic(ErrorCode.ERR_DupParamMod, "scoped").WithArguments("scoped").WithLocation(1, 19), + // (1,26): error CS0246: The type or namespace name 'R' could not be found (are you missing a using directive or an assembly reference?) + // void F(ref scoped scoped R r) { } + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "R").WithArguments("R").WithLocation(1, 26)); N(SyntaxKind.MethodDeclaration); { @@ -583,15 +587,8 @@ public void Method_08() N(SyntaxKind.Parameter); { N(SyntaxKind.RefKeyword); - N(SyntaxKind.IdentifierName); - { - N(SyntaxKind.IdentifierToken, "scoped"); - } - N(SyntaxKind.IdentifierToken, "scoped"); - } - M(SyntaxKind.CommaToken); - N(SyntaxKind.Parameter); - { + N(SyntaxKind.ScopedKeyword); + N(SyntaxKind.ScopedKeyword); N(SyntaxKind.IdentifierName); { N(SyntaxKind.IdentifierToken, "R"); @@ -615,14 +612,36 @@ public void Method_08() public void Method_09(LanguageVersion langVersion) { string source = "void F(scoped scoped x, ref scoped y, ref scoped scoped z, scoped ref scoped w) { }"; - UsingDeclaration(source, TestOptions.Regular.WithLanguageVersion(langVersion), - // (1,57): error CS1003: Syntax error, ',' expected - // void F(scoped scoped x, ref scoped y, ref scoped scoped z, scoped ref scoped w) { } - Diagnostic(ErrorCode.ERR_SyntaxError, "z").WithArguments(",").WithLocation(1, 57), - // (1,58): error CS1001: Identifier expected - // void F(scoped scoped x, ref scoped y, ref scoped scoped z, scoped ref scoped w) { } - Diagnostic(ErrorCode.ERR_IdentifierExpected, ",").WithLocation(1, 58) - ); + UsingDeclaration(source, TestOptions.Regular.WithLanguageVersion(langVersion)); + CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(langVersion)).VerifyDiagnostics( + FilterLanguageVersionChecks(langVersion, + // (1,6): warning CS8321: The local function 'F' is declared but never used + // void F(scoped scoped x, ref scoped y, ref scoped scoped z, scoped ref scoped w) { } + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "F").WithArguments("F").WithLocation(1, 6), + // (1,8): error CS8936: Feature 'ref fields' is not available in C# 10.0. Please use language version 11.0 or greater. + // void F(scoped scoped x, ref scoped y, ref scoped scoped z, scoped ref scoped w) { } + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion10, "scoped").WithArguments("ref fields", "11.0").WithLocation(1, 8), + // (1,15): error CS0246: The type or namespace name 'scoped' could not be found (are you missing a using directive or an assembly reference?) + // void F(scoped scoped x, ref scoped y, ref scoped scoped z, scoped ref scoped w) { } + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "scoped").WithArguments("scoped").WithLocation(1, 15), + // (1,29): error CS0246: The type or namespace name 'scoped' could not be found (are you missing a using directive or an assembly reference?) + // void F(scoped scoped x, ref scoped y, ref scoped scoped z, scoped ref scoped w) { } + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "scoped").WithArguments("scoped").WithLocation(1, 29), + // (1,43): error CS8936: Feature 'ref fields' is not available in C# 10.0. Please use language version 11.0 or greater. + // void F(scoped scoped x, ref scoped y, ref scoped scoped z, scoped ref scoped w) { } + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion10, "scoped").WithArguments("ref fields", "11.0").WithLocation(1, 43), + // (1,43): error CS9347: The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. + // void F(scoped scoped x, ref scoped y, ref scoped scoped z, scoped ref scoped w) { } + Diagnostic(ErrorCode.ERR_ScopedAfterInOutRefReadonly, "scoped").WithLocation(1, 43), + // (1,50): error CS0246: The type or namespace name 'scoped' could not be found (are you missing a using directive or an assembly reference?) + // void F(scoped scoped x, ref scoped y, ref scoped scoped z, scoped ref scoped w) { } + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "scoped").WithArguments("scoped").WithLocation(1, 50), + // (1,60): error CS8936: Feature 'ref fields' is not available in C# 10.0. Please use language version 11.0 or greater. + // void F(scoped scoped x, ref scoped y, ref scoped scoped z, scoped ref scoped w) { } + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion10, "scoped").WithArguments("ref fields", "11.0").WithLocation(1, 60), + // (1,71): error CS0246: The type or namespace name 'scoped' could not be found (are you missing a using directive or an assembly reference?) + // void F(scoped scoped x, ref scoped y, ref scoped scoped z, scoped ref scoped w) { } + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "scoped").WithArguments("scoped").WithLocation(1, 71))); N(SyntaxKind.MethodDeclaration); { @@ -657,20 +676,12 @@ public void Method_09(LanguageVersion langVersion) N(SyntaxKind.Parameter); { N(SyntaxKind.RefKeyword); + N(SyntaxKind.ScopedKeyword); N(SyntaxKind.IdentifierName); { N(SyntaxKind.IdentifierToken, "scoped"); } - N(SyntaxKind.IdentifierToken, "scoped"); - } - M(SyntaxKind.CommaToken); - N(SyntaxKind.Parameter); - { - N(SyntaxKind.IdentifierName); - { - N(SyntaxKind.IdentifierToken, "z"); - } - M(SyntaxKind.IdentifierToken); + N(SyntaxKind.IdentifierToken, "z"); } N(SyntaxKind.CommaToken); N(SyntaxKind.Parameter); @@ -763,14 +774,24 @@ public void Method_10(LanguageVersion langVersion) public void Method_11(LanguageVersion langVersion) { string source = "void F(scoped readonly int a) { }"; - UsingDeclaration(source, TestOptions.Regular.WithLanguageVersion(langVersion), - // (1,15): error CS1001: Identifier expected - // void F(scoped readonly int a) { } - Diagnostic(ErrorCode.ERR_IdentifierExpected, "readonly").WithLocation(1, 15), - // (1,15): error CS1003: Syntax error, ',' expected - // void F(scoped readonly int a) { } - Diagnostic(ErrorCode.ERR_SyntaxError, "readonly").WithArguments(",").WithLocation(1, 15) - ); + UsingDeclaration(source, TestOptions.Regular.WithLanguageVersion(langVersion)); + CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(langVersion)).VerifyDiagnostics( + FilterLanguageVersionChecks(langVersion, + // (1,6): warning CS8321: The local function 'F' is declared but never used + // void F(scoped readonly int a) { } + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "F").WithArguments("F").WithLocation(1, 6), + // (1,8): error CS8936: Feature 'ref fields' is not available in C# 10.0. Please use language version 11.0 or greater. + // void F(scoped readonly int a) { } + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion10, "scoped").WithArguments("ref fields", "11.0").WithLocation(1, 8), + // (1,8): error CS9048: The 'scoped' modifier can be used for refs and ref struct values only. + // void F(scoped readonly int a) { } + Diagnostic(ErrorCode.ERR_ScopedRefAndRefStructOnly, "scoped readonly int a").WithLocation(1, 8), + // (1,15): error CS9348: The 'readonly' modifier cannot immediately follow the 'scoped' modifier. + // void F(scoped readonly int a) { } + Diagnostic(ErrorCode.ERR_InvalidModifierAfterScoped, "readonly").WithArguments("readonly").WithLocation(1, 15), + // (1,15): error CS9190: 'readonly' modifier must be specified after 'ref'. + // void F(scoped readonly int a) { } + Diagnostic(ErrorCode.ERR_RefReadOnlyWrongOrdering, "readonly").WithLocation(1, 15))); N(SyntaxKind.MethodDeclaration); { @@ -784,15 +805,7 @@ public void Method_11(LanguageVersion langVersion) N(SyntaxKind.OpenParenToken); N(SyntaxKind.Parameter); { - N(SyntaxKind.IdentifierName); - { - N(SyntaxKind.IdentifierToken, "scoped"); - } - M(SyntaxKind.IdentifierToken); - } - M(SyntaxKind.CommaToken); - N(SyntaxKind.Parameter); - { + N(SyntaxKind.ScopedKeyword); N(SyntaxKind.ReadOnlyKeyword); N(SyntaxKind.PredefinedType); { @@ -857,14 +870,24 @@ public void Method_12(LanguageVersion langVersion) public void Method_13(LanguageVersion langVersion) { string source = "void F(out scoped ref int a) { }"; - UsingDeclaration(source, TestOptions.Regular.WithLanguageVersion(langVersion), - // (1,19): error CS1001: Identifier expected - // void F(out scoped ref int a) { } - Diagnostic(ErrorCode.ERR_IdentifierExpected, "ref").WithLocation(1, 19), - // (1,19): error CS1003: Syntax error, ',' expected - // void F(out scoped ref int a) { } - Diagnostic(ErrorCode.ERR_SyntaxError, "ref").WithArguments(",").WithLocation(1, 19) - ); + UsingDeclaration(source, TestOptions.Regular.WithLanguageVersion(langVersion)); + CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(langVersion)).VerifyDiagnostics( + FilterLanguageVersionChecks(langVersion, + // (1,6): error CS0177: The out parameter 'a' must be assigned to before control leaves the current method + // void F(out scoped ref int a) { } + Diagnostic(ErrorCode.ERR_ParamUnassigned, "F").WithArguments("a").WithLocation(1, 6), + // (1,6): warning CS8321: The local function 'F' is declared but never used + // void F(out scoped ref int a) { } + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "F").WithArguments("F").WithLocation(1, 6), + // (1,12): error CS8936: Feature 'ref fields' is not available in C# 10.0. Please use language version 11.0 or greater. + // void F(out scoped ref int a) { } + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion10, "scoped").WithArguments("ref fields", "11.0").WithLocation(1, 12), + // (1,12): error CS9347: The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. + // void F(out scoped ref int a) { } + Diagnostic(ErrorCode.ERR_ScopedAfterInOutRefReadonly, "scoped").WithLocation(1, 12), + // (1,19): error CS8328: The parameter modifier 'ref' cannot be used with 'out' + // void F(out scoped ref int a) { } + Diagnostic(ErrorCode.ERR_BadParameterModifiers, "ref").WithArguments("ref", "out").WithLocation(1, 19))); N(SyntaxKind.MethodDeclaration); { @@ -879,15 +902,7 @@ public void Method_13(LanguageVersion langVersion) N(SyntaxKind.Parameter); { N(SyntaxKind.OutKeyword); - N(SyntaxKind.IdentifierName); - { - N(SyntaxKind.IdentifierToken, "scoped"); - } - M(SyntaxKind.IdentifierToken); - } - M(SyntaxKind.CommaToken); - N(SyntaxKind.Parameter); - { + N(SyntaxKind.ScopedKeyword); N(SyntaxKind.RefKeyword); N(SyntaxKind.PredefinedType); { @@ -1020,30 +1035,41 @@ public void Lambda_02(LanguageVersion langVersion) public void Lambda_03_Ref(LanguageVersion langVersion) { string source = "(ref scoped int a) => null"; - UsingExpression(source, TestOptions.Regular.WithLanguageVersion(langVersion), - // (1,1): error CS1073: Unexpected token 'int' - // (ref scoped int a) => null - Diagnostic(ErrorCode.ERR_UnexpectedToken, "(ref scoped ").WithArguments("int").WithLocation(1, 1), - // (1,2): error CS1525: Invalid expression term 'ref' - // (ref scoped int a) => null - Diagnostic(ErrorCode.ERR_InvalidExprTerm, "ref scoped").WithArguments("ref").WithLocation(1, 2), - // (1,13): error CS1026: ) expected - // (ref scoped int a) => null - Diagnostic(ErrorCode.ERR_CloseParenExpected, "int").WithLocation(1, 13) - ); + UsingExpression(source, TestOptions.Regular.WithLanguageVersion(langVersion)); + CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(langVersion)).VerifyDiagnostics( + FilterLanguageVersionChecks(langVersion, + // (1,6): error CS8936: Feature 'ref fields' is not available in C# 10.0. Please use language version 11.0 or greater. + // (ref scoped int a) => null + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion10, "scoped").WithArguments("ref fields", "11.0").WithLocation(1, 6), + // (1,6): error CS9347: The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. + // (ref scoped int a) => null + Diagnostic(ErrorCode.ERR_ScopedAfterInOutRefReadonly, "scoped").WithLocation(1, 6), + // (1,27): error CS1002: ; expected + // (ref scoped int a) => null + Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(1, 27))); - N(SyntaxKind.ParenthesizedExpression); + N(SyntaxKind.ParenthesizedLambdaExpression); { - N(SyntaxKind.OpenParenToken); - N(SyntaxKind.RefExpression); + N(SyntaxKind.ParameterList); { - N(SyntaxKind.RefKeyword); - N(SyntaxKind.IdentifierName); + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); { - N(SyntaxKind.IdentifierToken, "scoped"); + N(SyntaxKind.RefKeyword); + N(SyntaxKind.ScopedKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.IdentifierToken, "a"); } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.NullLiteralExpression); + { + N(SyntaxKind.NullKeyword); } - M(SyntaxKind.CloseParenToken); } EOF(); } @@ -1054,26 +1080,41 @@ public void Lambda_03_Ref(LanguageVersion langVersion) public void Lambda_03_In(LanguageVersion langVersion) { string source = "(in scoped int a) => null"; - UsingExpression(source, TestOptions.Regular.WithLanguageVersion(langVersion), - // (1,1): error CS1073: Unexpected token 'in' - // (in scoped int a) => null - Diagnostic(ErrorCode.ERR_UnexpectedToken, "(").WithArguments("in").WithLocation(1, 1), - // (1,2): error CS1525: Invalid expression term 'in' - // (in scoped int a) => null - Diagnostic(ErrorCode.ERR_InvalidExprTerm, "in").WithArguments("in").WithLocation(1, 2), - // (1,2): error CS1026: ) expected - // (in scoped int a) => null - Diagnostic(ErrorCode.ERR_CloseParenExpected, "in").WithLocation(1, 2) - ); + UsingExpression(source, TestOptions.Regular.WithLanguageVersion(langVersion)); + CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(langVersion)).VerifyDiagnostics( + FilterLanguageVersionChecks(langVersion, + // (1,5): error CS8936: Feature 'ref fields' is not available in C# 10.0. Please use language version 11.0 or greater. + // (in scoped int a) => null + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion10, "scoped").WithArguments("ref fields", "11.0").WithLocation(1, 5), + // (1,5): error CS9347: The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. + // (in scoped int a) => null + Diagnostic(ErrorCode.ERR_ScopedAfterInOutRefReadonly, "scoped").WithLocation(1, 5), + // (1,26): error CS1002: ; expected + // (in scoped int a) => null + Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(1, 26))); - N(SyntaxKind.ParenthesizedExpression); + N(SyntaxKind.ParenthesizedLambdaExpression); { - N(SyntaxKind.OpenParenToken); - M(SyntaxKind.IdentifierName); + N(SyntaxKind.ParameterList); { - M(SyntaxKind.IdentifierToken); + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.InKeyword); + N(SyntaxKind.ScopedKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.IdentifierToken, "a"); + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.NullLiteralExpression); + { + N(SyntaxKind.NullKeyword); } - M(SyntaxKind.CloseParenToken); } EOF(); } @@ -1084,26 +1125,44 @@ public void Lambda_03_In(LanguageVersion langVersion) public void Lambda_03_Out(LanguageVersion langVersion) { string source = "(out scoped int a) => null"; - UsingExpression(source, TestOptions.Regular.WithLanguageVersion(langVersion), - // (1,1): error CS1073: Unexpected token 'out' - // (out scoped int a) => null - Diagnostic(ErrorCode.ERR_UnexpectedToken, "(").WithArguments("out").WithLocation(1, 1), - // (1,2): error CS1525: Invalid expression term 'out' - // (out scoped int a) => null - Diagnostic(ErrorCode.ERR_InvalidExprTerm, "out").WithArguments("out").WithLocation(1, 2), - // (1,2): error CS1026: ) expected - // (out scoped int a) => null - Diagnostic(ErrorCode.ERR_CloseParenExpected, "out").WithLocation(1, 2) - ); + UsingExpression(source, TestOptions.Regular.WithLanguageVersion(langVersion)); + CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(langVersion)).VerifyDiagnostics( + FilterLanguageVersionChecks(langVersion, + // (1,6): error CS8936: Feature 'ref fields' is not available in C# 10.0. Please use language version 11.0 or greater. + // (out scoped int a) => null + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion10, "scoped").WithArguments("ref fields", "11.0").WithLocation(1, 6), + // (1,6): error CS9347: The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. + // (out scoped int a) => null + Diagnostic(ErrorCode.ERR_ScopedAfterInOutRefReadonly, "scoped").WithLocation(1, 6), + // (1,23): error CS0177: The out parameter 'a' must be assigned to before control leaves the current method + // (out scoped int a) => null + Diagnostic(ErrorCode.ERR_ParamUnassigned, "null").WithArguments("a").WithLocation(1, 23), + // (1,27): error CS1002: ; expected + // (out scoped int a) => null + Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(1, 27))); - N(SyntaxKind.ParenthesizedExpression); + N(SyntaxKind.ParenthesizedLambdaExpression); { - N(SyntaxKind.OpenParenToken); - M(SyntaxKind.IdentifierName); + N(SyntaxKind.ParameterList); { - M(SyntaxKind.IdentifierToken); + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.OutKeyword); + N(SyntaxKind.ScopedKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.IdentifierToken, "a"); + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.NullLiteralExpression); + { + N(SyntaxKind.NullKeyword); } - M(SyntaxKind.CloseParenToken); } EOF(); } @@ -1181,10 +1240,20 @@ public void Lambda_05() public void Lambda_06() { string source = "(ref scoped scoped R r) => { }"; - UsingExpression(source, TestOptions.Regular11, - // (1,20): error CS1003: Syntax error, ',' expected + UsingExpression(source, TestOptions.Regular11); + CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics( + // (1,6): error CS9347: The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. + // (ref scoped scoped R r) => { } + Diagnostic(ErrorCode.ERR_ScopedAfterInOutRefReadonly, "scoped").WithLocation(1, 6), + // (1,13): error CS1107: A parameter can only have one 'scoped' modifier // (ref scoped scoped R r) => { } - Diagnostic(ErrorCode.ERR_SyntaxError, "R").WithArguments(",").WithLocation(1, 20)); + Diagnostic(ErrorCode.ERR_DupParamMod, "scoped").WithArguments("scoped").WithLocation(1, 13), + // (1,20): error CS0246: The type or namespace name 'R' could not be found (are you missing a using directive or an assembly reference?) + // (ref scoped scoped R r) => { } + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "R").WithArguments("R").WithLocation(1, 20), + // (1,31): error CS1002: ; expected + // (ref scoped scoped R r) => { } + Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(1, 31)); N(SyntaxKind.ParenthesizedLambdaExpression); { @@ -1194,15 +1263,8 @@ public void Lambda_06() N(SyntaxKind.Parameter); { N(SyntaxKind.RefKeyword); - N(SyntaxKind.IdentifierName); - { - N(SyntaxKind.IdentifierToken, "scoped"); - } - N(SyntaxKind.IdentifierToken, "scoped"); - } - M(SyntaxKind.CommaToken); - N(SyntaxKind.Parameter); - { + N(SyntaxKind.ScopedKeyword); + N(SyntaxKind.ScopedKeyword); N(SyntaxKind.IdentifierName); { N(SyntaxKind.IdentifierToken, "R"); @@ -1321,14 +1383,20 @@ public void Lambda_08(LanguageVersion langVersion) public void Params_01() { string source = "void F(scoped params object[] args);"; - UsingDeclaration(source, TestOptions.Regular11, - // (1,15): error CS1001: Identifier expected + UsingDeclaration(source, TestOptions.Regular11); + CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics( + // (1,6): error CS8112: Local function 'F(params scoped object[])' must declare a body because it is not marked 'static extern'. // void F(scoped params object[] args); - Diagnostic(ErrorCode.ERR_IdentifierExpected, "params").WithLocation(1, 15), - // (1,15): error CS1003: Syntax error, ',' expected + Diagnostic(ErrorCode.ERR_LocalFunctionMissingBody, "F").WithArguments("F(params scoped object[])").WithLocation(1, 6), + // (1,6): warning CS8321: The local function 'F' is declared but never used // void F(scoped params object[] args); - Diagnostic(ErrorCode.ERR_SyntaxError, "params").WithArguments(",").WithLocation(1, 15) - ); + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "F").WithArguments("F").WithLocation(1, 6), + // (1,8): error CS9048: The 'scoped' modifier can be used for refs and ref struct values only. + // void F(scoped params object[] args); + Diagnostic(ErrorCode.ERR_ScopedRefAndRefStructOnly, "scoped params object[] args").WithLocation(1, 8), + // (1,15): error CS9348: The 'params' modifier cannot immediately follow the 'scoped' modifier. + // void F(scoped params object[] args); + Diagnostic(ErrorCode.ERR_InvalidModifierAfterScoped, "params").WithArguments("params").WithLocation(1, 15)); N(SyntaxKind.MethodDeclaration); { @@ -1342,15 +1410,7 @@ public void Params_01() N(SyntaxKind.OpenParenToken); N(SyntaxKind.Parameter); { - N(SyntaxKind.IdentifierName); - { - N(SyntaxKind.IdentifierToken, "scoped"); - } - M(SyntaxKind.IdentifierToken); - } - M(SyntaxKind.CommaToken); - N(SyntaxKind.Parameter); - { + N(SyntaxKind.ScopedKeyword); N(SyntaxKind.ParamsKeyword); N(SyntaxKind.ArrayType); { @@ -9616,11 +9676,29 @@ public void FunctionPointer_01(LanguageVersion langVersion) public void FunctionPointer_02(LanguageVersion langVersion) { string source = @"delegate* f;"; - UsingStatement(source, TestOptions.Regular.WithLanguageVersion(langVersion), - // (1,32): error CS1003: Syntax error, ',' expected + UsingStatement(source, TestOptions.Regular.WithLanguageVersion(langVersion)); + CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(langVersion)).VerifyDiagnostics( + // (1,1): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context // delegate* f; - Diagnostic(ErrorCode.ERR_SyntaxError, "R").WithArguments(",").WithLocation(1, 32) - ); + Diagnostic(ErrorCode.ERR_UnsafeNeeded, "delegate*").WithLocation(1, 1), + // (1,11): error CS8755: 'scoped' cannot be used as a modifier on a function pointer parameter. + // delegate* f; + Diagnostic(ErrorCode.ERR_BadFuncPointerParamModifier, "scoped").WithArguments("scoped").WithLocation(1, 11), + // (1,18): error CS0246: The type or namespace name 'R' could not be found (are you missing a using directive or an assembly reference?) + // delegate* f; + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "R").WithArguments("R").WithLocation(1, 18), + // (1,25): error CS8755: 'scoped' cannot be used as a modifier on a function pointer parameter. + // delegate* f; + Diagnostic(ErrorCode.ERR_BadFuncPointerParamModifier, "scoped").WithArguments("scoped").WithLocation(1, 25), + // (1,32): error CS0246: The type or namespace name 'R' could not be found (are you missing a using directive or an assembly reference?) + // delegate* f; + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "R").WithArguments("R").WithLocation(1, 32), + // (1,35): error CS8755: 'scoped' cannot be used as a modifier on a function pointer parameter. + // delegate* f; + Diagnostic(ErrorCode.ERR_BadFuncPointerParamModifier, "scoped").WithArguments("scoped").WithLocation(1, 35), + // (1,57): warning CS0168: The variable 'f' is declared but never used + // delegate* f; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "f").WithArguments("f").WithLocation(1, 57)); N(SyntaxKind.LocalDeclarationStatement); { @@ -9645,9 +9723,10 @@ public void FunctionPointer_02(LanguageVersion langVersion) N(SyntaxKind.FunctionPointerParameter); { N(SyntaxKind.RefKeyword); + N(SyntaxKind.ScopedKeyword); N(SyntaxKind.IdentifierName); { - N(SyntaxKind.IdentifierToken, "scoped"); + N(SyntaxKind.IdentifierToken, "R"); } } N(SyntaxKind.CommaToken); @@ -11218,9 +11297,9 @@ public void Type_02() readonly scoped record struct C(); "; UsingTree(source, TestOptions.Regular11, - // (2,8): error CS1585: Member modifier 'readonly' must precede the member type and name + // (2,1): error CS0116: A namespace cannot directly contain members such as fields, methods or statements // scoped readonly record struct B; - Diagnostic(ErrorCode.ERR_BadModifierLocation, "readonly").WithArguments("readonly").WithLocation(2, 8), + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "scoped").WithLocation(2, 1), // (3,1): error CS8803: Top-level statements must precede namespace and type declarations. // readonly scoped record struct C(); Diagnostic(ErrorCode.ERR_TopLevelStatementAfterNamespaceOrType, "readonly scoped record ").WithLocation(3, 1), @@ -11229,8 +11308,7 @@ public void Type_02() Diagnostic(ErrorCode.ERR_BadMemberFlag, "readonly").WithArguments("readonly").WithLocation(3, 1), // (3,24): error CS1002: ; expected // readonly scoped record struct C(); - Diagnostic(ErrorCode.ERR_SemicolonExpected, "struct").WithLocation(3, 24) - ); + Diagnostic(ErrorCode.ERR_SemicolonExpected, "struct").WithLocation(3, 24)); N(SyntaxKind.CompilationUnit); { @@ -11250,10 +11328,7 @@ public void Type_02() } N(SyntaxKind.IncompleteMember); { - N(SyntaxKind.IdentifierName); - { - N(SyntaxKind.IdentifierToken, "scoped"); - } + N(SyntaxKind.ScopedKeyword); } N(SyntaxKind.RecordStructDeclaration); { diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/LambdaParameterParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/LambdaParameterParsingTests.cs index 310422247bdb6..2061d999dc23f 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/LambdaParameterParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/LambdaParameterParsingTests.cs @@ -5759,7 +5759,7 @@ public void ScopedAsParameterName_05() } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/63469")] - public void ScopedAsParameterName_06_CSharp13() + public void ScopedAsParameterName_06_CSharp13_A() { string source = "(scoped scoped) => { }"; UsingExpression(source, TestOptions.Regular13); @@ -5790,7 +5790,86 @@ public void ScopedAsParameterName_06_CSharp13() } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/63469")] - public void ScopedAsParameterName_06_Preview() + public void ScopedAsParameterName_06_CSharp13_B() + { + string source = "(scoped scoped, int i) => { }"; + UsingExpression(source, TestOptions.Regular13); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "scoped"); + } + N(SyntaxKind.IdentifierToken, "scoped"); + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.IdentifierToken, "i"); + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/63469")] + public void ScopedAsParameterName_06_CSharp13_C() + { + string source = "(scoped scoped = default) => { }"; + UsingExpression(source, TestOptions.Regular13); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "scoped"); + } + N(SyntaxKind.IdentifierToken, "scoped"); + N(SyntaxKind.EqualsValueClause); + { + N(SyntaxKind.EqualsToken); + N(SyntaxKind.DefaultLiteralExpression); + { + N(SyntaxKind.DefaultKeyword); + } + } + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/63469")] + public void ScopedAsParameterName_06_Preview_A() { string source = "(scoped scoped) => { }"; UsingExpression(source, TestOptions.RegularPreview); @@ -5817,6 +5896,79 @@ public void ScopedAsParameterName_06_Preview() EOF(); } + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/63469")] + public void ScopedAsParameterName_06_Preview_B() + { + string source = "(scoped scoped, int i) => { }"; + UsingExpression(source, TestOptions.RegularPreview); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.ScopedKeyword); + N(SyntaxKind.IdentifierToken, "scoped"); + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.IdentifierToken, "i"); + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/63469")] + public void ScopedAsParameterName_06_Preview_C() + { + string source = "(scoped scoped = default) => { }"; + UsingExpression(source, TestOptions.RegularPreview); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.ScopedKeyword); + N(SyntaxKind.IdentifierToken, "scoped"); + N(SyntaxKind.EqualsValueClause); + { + N(SyntaxKind.EqualsToken); + N(SyntaxKind.DefaultLiteralExpression); + { + N(SyntaxKind.DefaultKeyword); + } + } + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + EOF(); + } + [Fact] public void MissingParameterName_01() { @@ -6893,5 +7045,168 @@ public void TestParenthesizedLambdaRecovery3() } EOF(); } + + [Theory] + [InlineData(LanguageVersion.CSharp13)] + [InlineData(LanguageVersion.CSharp14)] + public void TestTripleScoped_LocalFunction(LanguageVersion version) + { + UsingTree(""" + void Goo(scoped scoped scoped) { } + """, TestOptions.Regular.WithLanguageVersion(version)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalFunctionStatement); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.IdentifierToken, "Goo"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.ScopedKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "scoped"); + } + N(SyntaxKind.IdentifierToken, "scoped"); + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void TestTripleScoped_Lambda_CSharp13() + { + // In c# 13 this is one scoped modifier on the 'scoped' type on the 'scoped' identifier. + UsingTree(""" + var v = (scoped scoped scoped) => { }; + """, TestOptions.Regular13); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "var"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "v"); + N(SyntaxKind.EqualsValueClause); + { + N(SyntaxKind.EqualsToken); + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.ScopedKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "scoped"); + } + N(SyntaxKind.IdentifierToken, "scoped"); + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void TestTripleScoped_Lambda_CSharp14() + { + // In c# 14 this is two scoped modifiers on the 'scoped' identifier. + UsingTree(""" + var v = (scoped scoped scoped) => { }; + """, TestOptions.Regular14); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "var"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "v"); + N(SyntaxKind.EqualsValueClause); + { + N(SyntaxKind.EqualsToken); + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.ScopedKeyword); + N(SyntaxKind.ScopedKeyword); + N(SyntaxKind.IdentifierToken, "scoped"); + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } } } diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/RefReadonlyTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/RefReadonlyTests.cs index 6979c47d06efe..075291bf0a1f8 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/RefReadonlyTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/RefReadonlyTests.cs @@ -4,11 +4,12 @@ #nullable disable -using Xunit; +using System.Collections.Generic; using System.Linq; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; +using Xunit; using Xunit.Abstractions; namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Parsing @@ -931,25 +932,30 @@ void verifyNodes() public void RefReadonlyWithScoped_02() { var source = "void M(ref scoped readonly int p);"; - var expectedDiagnostics = new[] - { - // (1,19): error CS1001: Identifier expected - // void M(ref scoped readonly int p); - Diagnostic(ErrorCode.ERR_IdentifierExpected, "readonly").WithLocation(1, 19), - // (1,19): error CS1003: Syntax error, ',' expected - // void M(ref scoped readonly int p); - Diagnostic(ErrorCode.ERR_SyntaxError, "readonly").WithArguments(",").WithLocation(1, 19) - }; - UsingDeclaration(source, TestOptions.Regular11, expectedDiagnostics); + UsingDeclaration(source, TestOptions.Regular11); verifyNodes(); - UsingDeclaration(source, TestOptions.Regular12, expectedDiagnostics); + UsingDeclaration(source, TestOptions.Regular12); verifyNodes(); - UsingDeclaration(source, TestOptions.RegularPreview, expectedDiagnostics); + UsingDeclaration(source, TestOptions.RegularPreview); verifyNodes(); + CreateCompilation(source).VerifyDiagnostics( + // (1,6): error CS8112: Local function 'M(scoped ref int)' must declare a body because it is not marked 'static extern'. + // void M(ref scoped readonly int p); + Diagnostic(ErrorCode.ERR_LocalFunctionMissingBody, "M").WithArguments("M(scoped ref int)").WithLocation(1, 6), + // (1,6): warning CS8321: The local function 'M' is declared but never used + // void M(ref scoped readonly int p); + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "M").WithArguments("M").WithLocation(1, 6), + // (1,12): error CS9347: The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier. + // void M(ref scoped readonly int p); + Diagnostic(ErrorCode.ERR_ScopedAfterInOutRefReadonly, "scoped").WithLocation(1, 12), + // (1,19): error CS9190: 'readonly' modifier must be specified after 'ref'. + // void M(ref scoped readonly int p); + Diagnostic(ErrorCode.ERR_RefReadOnlyWrongOrdering, "readonly").WithLocation(1, 19)); + void verifyNodes() { N(SyntaxKind.MethodDeclaration); @@ -965,15 +971,7 @@ void verifyNodes() N(SyntaxKind.Parameter); { N(SyntaxKind.RefKeyword); - N(SyntaxKind.IdentifierName); - { - N(SyntaxKind.IdentifierToken, "scoped"); - } - M(SyntaxKind.IdentifierToken); - } - M(SyntaxKind.CommaToken); - N(SyntaxKind.Parameter); - { + N(SyntaxKind.ScopedKeyword); N(SyntaxKind.ReadOnlyKeyword); N(SyntaxKind.PredefinedType); { @@ -993,25 +991,27 @@ void verifyNodes() public void RefReadonlyWithScoped_03() { var source = "void M(readonly scoped ref int p);"; - var expectedDiagnostics = new[] - { - // (1,24): error CS1001: Identifier expected - // void M(readonly scoped ref int p); - Diagnostic(ErrorCode.ERR_IdentifierExpected, "ref").WithLocation(1, 24), - // (1,24): error CS1003: Syntax error, ',' expected - // void M(readonly scoped ref int p); - Diagnostic(ErrorCode.ERR_SyntaxError, "ref").WithArguments(",").WithLocation(1, 24) - }; - UsingDeclaration(source, TestOptions.Regular11, expectedDiagnostics); + UsingDeclaration(source, TestOptions.Regular11); verifyNodes(); - UsingDeclaration(source, TestOptions.Regular12, expectedDiagnostics); + UsingDeclaration(source, TestOptions.Regular12); verifyNodes(); - UsingDeclaration(source, TestOptions.RegularPreview, expectedDiagnostics); + UsingDeclaration(source, TestOptions.RegularPreview); verifyNodes(); + CreateCompilation(source).VerifyDiagnostics( + // (1,6): error CS8112: Local function 'M(scoped ref int)' must declare a body because it is not marked 'static extern'. + // void M(readonly scoped ref int p); + Diagnostic(ErrorCode.ERR_LocalFunctionMissingBody, "M").WithArguments("M(scoped ref int)").WithLocation(1, 6), + // (1,6): warning CS8321: The local function 'M' is declared but never used + // void M(readonly scoped ref int p); + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "M").WithArguments("M").WithLocation(1, 6), + // (1,8): error CS9190: 'readonly' modifier must be specified after 'ref'. + // void M(readonly scoped ref int p); + Diagnostic(ErrorCode.ERR_RefReadOnlyWrongOrdering, "readonly").WithLocation(1, 8)); + void verifyNodes() { N(SyntaxKind.MethodDeclaration); @@ -1027,15 +1027,7 @@ void verifyNodes() N(SyntaxKind.Parameter); { N(SyntaxKind.ReadOnlyKeyword); - N(SyntaxKind.IdentifierName); - { - N(SyntaxKind.IdentifierToken, "scoped"); - } - M(SyntaxKind.IdentifierToken); - } - M(SyntaxKind.CommaToken); - N(SyntaxKind.Parameter); - { + N(SyntaxKind.ScopedKeyword); N(SyntaxKind.RefKeyword); N(SyntaxKind.PredefinedType); { @@ -1055,25 +1047,33 @@ void verifyNodes() public void ReadonlyWithScoped() { var source = "void M(scoped readonly int p);"; - var expectedDiagnostics = new[] - { - // (1,15): error CS1001: Identifier expected - // void M(scoped readonly int p); - Diagnostic(ErrorCode.ERR_IdentifierExpected, "readonly").WithLocation(1, 15), - // (1,15): error CS1003: Syntax error, ',' expected - // void M(scoped readonly int p); - Diagnostic(ErrorCode.ERR_SyntaxError, "readonly").WithArguments(",").WithLocation(1, 15) - }; - UsingDeclaration(source, TestOptions.Regular11, expectedDiagnostics); + UsingDeclaration(source, TestOptions.Regular11); verifyNodes(); - UsingDeclaration(source, TestOptions.Regular12, expectedDiagnostics); + UsingDeclaration(source, TestOptions.Regular12); verifyNodes(); - UsingDeclaration(source, TestOptions.RegularPreview, expectedDiagnostics); + UsingDeclaration(source, TestOptions.RegularPreview); verifyNodes(); + CreateCompilation(source).VerifyDiagnostics( + // (1,6): error CS8112: Local function 'M(scoped int)' must declare a body because it is not marked 'static extern'. + // void M(scoped readonly int p); + Diagnostic(ErrorCode.ERR_LocalFunctionMissingBody, "M").WithArguments("M(scoped int)").WithLocation(1, 6), + // (1,6): warning CS8321: The local function 'M' is declared but never used + // void M(scoped readonly int p); + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "M").WithArguments("M").WithLocation(1, 6), + // (1,8): error CS9048: The 'scoped' modifier can be used for refs and ref struct values only. + // void M(scoped readonly int p); + Diagnostic(ErrorCode.ERR_ScopedRefAndRefStructOnly, "scoped readonly int p").WithLocation(1, 8), + // (1,15): error CS9348: The 'readonly' modifier cannot immediately follow the 'scoped' modifier. + // void M(scoped readonly int p); + Diagnostic(ErrorCode.ERR_InvalidModifierAfterScoped, "readonly").WithArguments("readonly").WithLocation(1, 15), + // (1,15): error CS9190: 'readonly' modifier must be specified after 'ref'. + // void M(scoped readonly int p); + Diagnostic(ErrorCode.ERR_RefReadOnlyWrongOrdering, "readonly").WithLocation(1, 15)); + void verifyNodes() { N(SyntaxKind.MethodDeclaration); @@ -1088,15 +1088,7 @@ void verifyNodes() N(SyntaxKind.OpenParenToken); N(SyntaxKind.Parameter); { - N(SyntaxKind.IdentifierName); - { - N(SyntaxKind.IdentifierToken, "scoped"); - } - M(SyntaxKind.IdentifierToken); - } - M(SyntaxKind.CommaToken); - N(SyntaxKind.Parameter); - { + N(SyntaxKind.ScopedKeyword); N(SyntaxKind.ReadOnlyKeyword); N(SyntaxKind.PredefinedType); { @@ -1116,25 +1108,30 @@ void verifyNodes() public void ReadonlyWithScoped_02() { var source = "void M(scoped readonly ref int p);"; - var expectedDiagnostics = new[] - { - // (1,15): error CS1001: Identifier expected - // void M(scoped readonly ref int p); - Diagnostic(ErrorCode.ERR_IdentifierExpected, "readonly").WithLocation(1, 15), - // (1,15): error CS1003: Syntax error, ',' expected - // void M(scoped readonly ref int p); - Diagnostic(ErrorCode.ERR_SyntaxError, "readonly").WithArguments(",").WithLocation(1, 15) - }; - UsingDeclaration(source, TestOptions.Regular11, expectedDiagnostics); + UsingDeclaration(source, TestOptions.Regular11); verifyNodes(); - UsingDeclaration(source, TestOptions.Regular12, expectedDiagnostics); + UsingDeclaration(source, TestOptions.Regular12); verifyNodes(); - UsingDeclaration(source, TestOptions.RegularPreview, expectedDiagnostics); + UsingDeclaration(source, TestOptions.RegularPreview); verifyNodes(); + CreateCompilation(source).VerifyDiagnostics( + // (1,6): error CS8112: Local function 'M(scoped ref int)' must declare a body because it is not marked 'static extern'. + // void M(scoped readonly ref int p); + Diagnostic(ErrorCode.ERR_LocalFunctionMissingBody, "M").WithArguments("M(scoped ref int)").WithLocation(1, 6), + // (1,6): warning CS8321: The local function 'M' is declared but never used + // void M(scoped readonly ref int p); + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "M").WithArguments("M").WithLocation(1, 6), + // (1,15): error CS9348: The 'readonly' modifier cannot immediately follow the 'scoped' modifier. + // void M(scoped readonly ref int p); + Diagnostic(ErrorCode.ERR_InvalidModifierAfterScoped, "readonly").WithArguments("readonly").WithLocation(1, 15), + // (1,15): error CS9190: 'readonly' modifier must be specified after 'ref'. + // void M(scoped readonly ref int p); + Diagnostic(ErrorCode.ERR_RefReadOnlyWrongOrdering, "readonly").WithLocation(1, 15)); + void verifyNodes() { N(SyntaxKind.MethodDeclaration); @@ -1149,15 +1146,7 @@ void verifyNodes() N(SyntaxKind.OpenParenToken); N(SyntaxKind.Parameter); { - N(SyntaxKind.IdentifierName); - { - N(SyntaxKind.IdentifierToken, "scoped"); - } - M(SyntaxKind.IdentifierToken); - } - M(SyntaxKind.CommaToken); - N(SyntaxKind.Parameter); - { + N(SyntaxKind.ScopedKeyword); N(SyntaxKind.ReadOnlyKeyword); N(SyntaxKind.RefKeyword); N(SyntaxKind.PredefinedType); @@ -1370,6 +1359,262 @@ public void ArgumentModifier_RefReadonly( EOF(); } + [Fact] + public void ScopedThis() + { + var source = """ + ref struct S { } + static class C + { + public static void M(scoped this S x) + { + } + } + """; + UsingTree(source); + CreateCompilation(source).VerifyDiagnostics( + // (4,33): error CS9348: The 'this' modifier cannot immediately follow the 'scoped' modifier. + // public static void M(scoped this S x) + Diagnostic(ErrorCode.ERR_InvalidModifierAfterScoped, "this").WithArguments("this").WithLocation(4, 33)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.StructDeclaration); + { + N(SyntaxKind.RefKeyword); + N(SyntaxKind.StructKeyword); + N(SyntaxKind.IdentifierToken, "S"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PublicKeyword); + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.IdentifierToken, "M"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.ScopedKeyword); + N(SyntaxKind.ThisKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "S"); + } + N(SyntaxKind.IdentifierToken, "x"); + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void ThisScoped() + { + var source = """ + ref struct S { } + + static class C + { + public static void M(this scoped S x) + { + } + } + """; + UsingTree(source); + CreateCompilation(source).VerifyDiagnostics(); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.StructDeclaration); + { + N(SyntaxKind.RefKeyword); + N(SyntaxKind.StructKeyword); + N(SyntaxKind.IdentifierToken, "S"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PublicKeyword); + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.IdentifierToken, "M"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.ThisKeyword); + N(SyntaxKind.ScopedKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "S"); + } + N(SyntaxKind.IdentifierToken, "x"); + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void ScopedParams() + { + var source = """ + static class C + { + public static void M(scoped params S x) + { + } + } + """; + UsingTree(source); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PublicKeyword); + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.IdentifierToken, "M"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.ScopedKeyword); + N(SyntaxKind.ParamsKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "S"); + } + N(SyntaxKind.IdentifierToken, "x"); + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void ParamsScoped() + { + var source = """ + static class C + { + public static void M(params scoped S x) + { + } + } + """; + UsingTree(source); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PublicKeyword); + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.IdentifierToken, "M"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.ParamsKeyword); + N(SyntaxKind.ScopedKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "S"); + } + N(SyntaxKind.IdentifierToken, "x"); + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + [Theory, CombinatorialData] public void ArgumentModifier_ReadonlyRef( [CombinatorialValues(LanguageVersion.CSharp11, LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion) diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/TopLevelStatementsParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/TopLevelStatementsParsingTests.cs index 24430e3e15adb..aedda8d3b2ba6 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/TopLevelStatementsParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/TopLevelStatementsParsingTests.cs @@ -3066,10 +3066,9 @@ scoped readonly ref struct C { } // (3,12): error CS1031: Type expected // scoped ref struct B { } Diagnostic(ErrorCode.ERR_TypeExpected, "struct").WithLocation(3, 12), - // (4,8): error CS1585: Member modifier 'readonly' must precede the member type and name + // (4,1): error CS0116: A namespace cannot directly contain members such as fields, methods or statements // scoped readonly ref struct C { } - Diagnostic(ErrorCode.ERR_BadModifierLocation, "readonly").WithArguments("readonly").WithLocation(4, 8) - ); + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "scoped").WithLocation(4, 1)); N(SyntaxKind.CompilationUnit); { @@ -3119,10 +3118,7 @@ scoped readonly ref struct C { } } N(SyntaxKind.IncompleteMember); { - N(SyntaxKind.IdentifierName); - { - N(SyntaxKind.IdentifierToken, "scoped"); - } + N(SyntaxKind.ScopedKeyword); } N(SyntaxKind.StructDeclaration); {