From f02a7ee7d834245acb80602be6f9eeb3f2d702a5 Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Wed, 17 May 2023 06:43:08 -0700 Subject: [PATCH] Disallow inline array operations in expression trees. --- .../CSharp/Portable/CSharpResources.resx | 3 + .../CSharp/Portable/Errors/ErrorCode.cs | 1 + .../CSharp/Portable/Errors/ErrorFacts.cs | 1 + .../DiagnosticsPass_ExpressionTrees.cs | 14 +++- .../Symbols/Source/SourceAssemblySymbol.cs | 2 +- .../Portable/xlf/CSharpResources.cs.xlf | 5 ++ .../Portable/xlf/CSharpResources.de.xlf | 5 ++ .../Portable/xlf/CSharpResources.es.xlf | 5 ++ .../Portable/xlf/CSharpResources.fr.xlf | 5 ++ .../Portable/xlf/CSharpResources.it.xlf | 5 ++ .../Portable/xlf/CSharpResources.ja.xlf | 5 ++ .../Portable/xlf/CSharpResources.ko.xlf | 5 ++ .../Portable/xlf/CSharpResources.pl.xlf | 5 ++ .../Portable/xlf/CSharpResources.pt-BR.xlf | 5 ++ .../Portable/xlf/CSharpResources.ru.xlf | 5 ++ .../Portable/xlf/CSharpResources.tr.xlf | 5 ++ .../Portable/xlf/CSharpResources.zh-Hans.xlf | 5 ++ .../Portable/xlf/CSharpResources.zh-Hant.xlf | 5 ++ .../Semantic/Semantics/InlineArrayTests.cs | 79 +++++++++++++++++++ 19 files changed, 162 insertions(+), 3 deletions(-) diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 69032041086bf..b24d1a5ed7c93 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -7532,4 +7532,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Inline array struct must declare one and only one instance field which must not be a ref field. + + An expression tree may not contain an inline array access or conversion + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index 5b54a6e69324c..e237f7223abe5 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -2198,6 +2198,7 @@ internal enum ErrorCode ERR_InvalidInlineArrayLength = 9504, ERR_InvalidInlineArrayLayout = 9505, ERR_InvalidInlineArrayFields = 9506, + ERR_ExpressionTreeContainsInlineArrayOperation = 9507, #endregion diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs index 0fe84317fa20e..d7cf23b1efa30 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs @@ -2317,6 +2317,7 @@ internal static bool IsBuildOnlyDiagnostic(ErrorCode code) case ErrorCode.ERR_InvalidInlineArrayLength: case ErrorCode.ERR_InvalidInlineArrayLayout: case ErrorCode.ERR_InvalidInlineArrayFields: + case ErrorCode.ERR_ExpressionTreeContainsInlineArrayOperation: return false; default: // NOTE: All error codes must be explicitly handled in this switch statement diff --git a/src/Compilers/CSharp/Portable/Lowering/DiagnosticsPass_ExpressionTrees.cs b/src/Compilers/CSharp/Portable/Lowering/DiagnosticsPass_ExpressionTrees.cs index f051867117c70..d6f7378f1e4fc 100644 --- a/src/Compilers/CSharp/Portable/Lowering/DiagnosticsPass_ExpressionTrees.cs +++ b/src/Compilers/CSharp/Portable/Lowering/DiagnosticsPass_ExpressionTrees.cs @@ -110,7 +110,11 @@ public override BoundNode VisitImplicitIndexerAccess(BoundImplicitIndexerAccess public override BoundNode VisitInlineArrayAccess(BoundInlineArrayAccess node) { - // PROTOTYPE(InlineArrays): Disallow. + if (_inExpressionLambda) + { + Error(ErrorCode.ERR_ExpressionTreeContainsInlineArrayOperation, node); + } + return base.VisitInlineArrayAccess(node); } @@ -793,7 +797,13 @@ public override BoundNode VisitConversion(BoundConversion node) } break; - // PROTOTYPE(InlineArrays): Disallow in expression trees + case ConversionKind.InlineArray: + if (_inExpressionLambda) + { + Error(ErrorCode.ERR_ExpressionTreeContainsInlineArrayOperation, node); + } + break; + case ConversionKind.InterpolatedStringHandler: if (_inExpressionLambda) { diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceAssemblySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceAssemblySymbol.cs index 6ff5a76982f46..eb79bae7a05ef 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceAssemblySymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceAssemblySymbol.cs @@ -2717,7 +2717,7 @@ internal ImmutableArray GetUnusedFieldWarnings(CancellationToken can } var containingType = field.ContainingType as SourceNamedTypeSymbol; - if ((object)containingType != null && !containingType.HasStructLayoutAttribute) // PROTOTYPE(InlineArrays): && !containingType.HasInlineArrayAttribute(out _) + if ((object)containingType != null && !containingType.HasStructLayoutAttribute && !containingType.HasInlineArrayAttribute(out _)) { diagnostics.Add(ErrorCode.WRN_UnreferencedFieldAssg, field.GetFirstLocationOrNone(), field); } diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index 8378dca6e36fb..5606caa47cbe6 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -577,6 +577,11 @@ Strom výrazů nesmí obsahovat výraz indexu od-do (^). + + An expression tree may not contain an inline array access or conversion + An expression tree may not contain an inline array access or conversion + + An expression tree may not contain an interpolated string handler conversion. Strom výrazů nesmí obsahovat převod obslužné rutiny interpolovaného řetězce. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index 089e7c3abbf76..6ab8108f23bbd 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -577,6 +577,11 @@ Eine Ausdrucksbaumstruktur darf keinen vom Ende ausgehenden Indexausdruck ("^") enthalten. + + An expression tree may not contain an inline array access or conversion + An expression tree may not contain an inline array access or conversion + + An expression tree may not contain an interpolated string handler conversion. Eine Ausdrucksbaumstruktur darf keine Handler-Konvertierung einer interpolierten Zeichenfolge enthalten. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index 96b134057652b..bc09e0a1ac806 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -577,6 +577,11 @@ Un árbol de expresión no puede contener una expresión de índice del otro extremo ("^"). + + An expression tree may not contain an inline array access or conversion + An expression tree may not contain an inline array access or conversion + + An expression tree may not contain an interpolated string handler conversion. Un árbol de (la) expresión no puede contener una conversión de controlador de cadena interpolada. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index f8fb33c7404bd..55bbdafba8abd 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -577,6 +577,11 @@ Une arborescence de l'expression ne peut pas contenir d'expression d'index partant de la fin ('^'). + + An expression tree may not contain an inline array access or conversion + An expression tree may not contain an inline array access or conversion + + An expression tree may not contain an interpolated string handler conversion. Une arborescence de l’expression ne peut pas contenir une conversion de gestionnaire de chaîne interpolée. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index 6f49692384a1b..8937f3b2f657b 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -577,6 +577,11 @@ Un albero delle espressioni non può contenere un'espressione di indice from end ('^'). + + An expression tree may not contain an inline array access or conversion + An expression tree may not contain an inline array access or conversion + + An expression tree may not contain an interpolated string handler conversion. Un albero delle espressioni non può contenere una conversione del gestore di stringhe interpolate. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index ad40cb93a35d6..e85db899ab44c 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -577,6 +577,11 @@ 式ツリーに、from-end インデックス ('^') 式を含めることはできません。 + + An expression tree may not contain an inline array access or conversion + An expression tree may not contain an inline array access or conversion + + An expression tree may not contain an interpolated string handler conversion. 式ツリーには、補間された文字列ハンドラー変換を含めることはできません。 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index e7ade9967973a..e22b86a9aade7 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -577,6 +577,11 @@ 식 트리에는 내림차순 인덱스('^') 식을 포함할 수 없습니다. + + An expression tree may not contain an inline array access or conversion + An expression tree may not contain an inline array access or conversion + + An expression tree may not contain an interpolated string handler conversion. 식 트리에는 보간된 문자열 처리기 변환이 포함될 수 없습니다. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index e721fab8dee5f..27f1a6be32109 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -577,6 +577,11 @@ Drzewo wyrażeń nie może zawierać wyrażenia „od końca indeksu” („^”). + + An expression tree may not contain an inline array access or conversion + An expression tree may not contain an inline array access or conversion + + An expression tree may not contain an interpolated string handler conversion. Drzewo wyrażenia nie może zawierać konwersji procedury obsługi ciągu interpolowanego. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index 44740dfeb9a88..253149dbbe2b3 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -577,6 +577,11 @@ Uma árvore de expressão não pode conter uma expressão de índice de front-end ('^'). + + An expression tree may not contain an inline array access or conversion + An expression tree may not contain an inline array access or conversion + + An expression tree may not contain an interpolated string handler conversion. Uma árvore de expressão pode não conter uma conversão de manipulador de cadeia de caracteres interpolada. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index 430a9b0ca0edb..35a4c95b3481e 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -577,6 +577,11 @@ Дерево выражений не может содержать выражение индекса, отсчитываемого с конца ("^"). + + An expression tree may not contain an inline array access or conversion + An expression tree may not contain an inline array access or conversion + + An expression tree may not contain an interpolated string handler conversion. Дерево выражения не может содержать преобразование обработчика интерполированных строк. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index e59518c7abb98..7fd5d6979cc54 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -577,6 +577,11 @@ İfade ağacı, sondan dizin ('^') ifadesi içeremez. + + An expression tree may not contain an inline array access or conversion + An expression tree may not contain an inline array access or conversion + + An expression tree may not contain an interpolated string handler conversion. Bir ifade ağacı, düz metin arasına kod eklenmiş dize işleyicisi dönüşümü içeremez. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index 16647981c77de..f6e9249e066c5 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -577,6 +577,11 @@ 表达式树不能包含 from-end 索引("^")表达式。 + + An expression tree may not contain an inline array access or conversion + An expression tree may not contain an inline array access or conversion + + An expression tree may not contain an interpolated string handler conversion. 表达式树可能不包含内插字符串处理程序转换。 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index 5ed66f498845c..50a1cf1260d2a 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -577,6 +577,11 @@ 運算式樹狀架構不可包含 from-end index ('^') 運算式。 + + An expression tree may not contain an inline array access or conversion + An expression tree may not contain an inline array access or conversion + + An expression tree may not contain an interpolated string handler conversion. 運算式樹狀架構不可包含差補字串處理常式轉換。 diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/InlineArrayTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/InlineArrayTests.cs index c8f11c7652098..694ba1130b6a3 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/InlineArrayTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/InlineArrayTests.cs @@ -1851,6 +1851,28 @@ struct Buffer Assert.Equal(0, length); } + [ConditionalFact(typeof(MonoOrCoreClrOnly))] + public void InlineArrayType_42() + { + var src = @" +var b = new Buffer(); +System.Console.WriteLine(b[0]); + +[System.Runtime.CompilerServices.InlineArray(10)] +public struct Buffer +{ + private int _element0 = 111; + + public Buffer() + { + } +} +"; + var comp = CreateCompilation(src + InlineArrayAttributeDefinition, targetFramework: TargetFramework.NetCoreApp); + // No warning CS0414: The field 'Buffer._element0' is assigned but its value is never used + CompileAndVerify(comp, expectedOutput: "111", verify: Verification.Fails).VerifyDiagnostics(); + } + [ConditionalFact(typeof(MonoOrCoreClrOnly))] public void ElementAccess_Variable_01() { @@ -4241,6 +4263,36 @@ public ref struct Buffer10 ); } + [Fact] + public void ElementAccess_ExpressionTree_01() + { + var src = @" +using System.Linq.Expressions; + +class Program +{ + static Expression> M1(Buffer10 x) => + () => x[0]; + + static Expression M2(Buffer10 x) => + () => x[0] = 111; +} +" + Buffer10Definition; + + var comp = CreateCompilation(src, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseDll); + comp.VerifyDiagnostics( + // (7,15): error CS9507: An expression tree may not contain an inline array access or conversion + // () => x[0]; + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsInlineArrayOperation, "x[0]").WithLocation(7, 15), + // (10,15): error CS0832: An expression tree may not contain an assignment operator + // () => x[0] = 111; + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsAssignment, "x[0] = 111").WithLocation(10, 15), + // (10,15): error CS9507: An expression tree may not contain an inline array access or conversion + // () => x[0] = 111; + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsInlineArrayOperation, "x[0]").WithLocation(10, 15) + ); + } + [ConditionalFact(typeof(MonoOrCoreClrOnly))] public void ElementAccess_Await_14_GenericMethod() { @@ -12477,6 +12529,33 @@ .locals init (int V_0, "); } + [Fact] + public void Conversion_ExpressionTree_01() + { + var src = @" +using System.Linq.Expressions; + +class Program +{ + static Expression> M1(Buffer10 x) => + () => ((System.Span)x).Length; + + static Expression> M2(Buffer10 x) => + () => ((System.ReadOnlySpan)x).Length; +} +" + Buffer10Definition; + + var comp = CreateCompilation(src, targetFramework: TargetFramework.NetCoreApp, options: TestOptions.ReleaseDll); + comp.VerifyDiagnostics( + // (7,16): error CS9507: An expression tree may not contain an inline array access or conversion + // () => ((System.Span)x).Length; + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsInlineArrayOperation, "(System.Span)x").WithLocation(7, 16), + // (10,16): error CS9507: An expression tree may not contain an inline array access or conversion + // () => ((System.ReadOnlySpan)x).Length; + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsInlineArrayOperation, "(System.ReadOnlySpan)x").WithLocation(10, 16) + ); + } + [ConditionalFact(typeof(MonoOrCoreClrOnly))] public void Conversion_NotFromType_01() {