Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disallow inline array operations in expression trees. #68222

Merged
merged 1 commit into from
May 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/Compilers/CSharp/Portable/CSharpResources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -7532,4 +7532,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<data name="ERR_InvalidInlineArrayFields" xml:space="preserve">
<value>Inline array struct must declare one and only one instance field which must not be a ref field.</value>
</data>
<data name="ERR_ExpressionTreeContainsInlineArrayOperation" xml:space="preserve">
<value>An expression tree may not contain an inline array access or conversion</value>
</data>
</root>
1 change: 1 addition & 0 deletions src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2198,6 +2198,7 @@ internal enum ErrorCode
ERR_InvalidInlineArrayLength = 9504,
ERR_InvalidInlineArrayLayout = 9505,
ERR_InvalidInlineArrayFields = 9506,
ERR_ExpressionTreeContainsInlineArrayOperation = 9507,

#endregion

Expand Down
1 change: 1 addition & 0 deletions src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down Expand Up @@ -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)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2717,7 +2717,7 @@ internal ImmutableArray<Diagnostic> 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);
}
Expand Down
5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -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()
{
Expand Down Expand Up @@ -4241,6 +4263,36 @@ public ref struct Buffer10
);
}

[Fact]
public void ElementAccess_ExpressionTree_01()
{
var src = @"
using System.Linq.Expressions;

class Program
{
static Expression<System.Func<int>> M1(Buffer10<int> x) =>
() => x[0];

static Expression<System.Action> M2(Buffer10<int> 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)
);
}
Copy link
Member

@jcouv jcouv May 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we testing the conversion case? "An expression tree may not contain an inline array [...] conversion"
Never mind, I'd missed the test for that (at the bottom of the file) #Closed


[ConditionalFact(typeof(MonoOrCoreClrOnly))]
public void ElementAccess_Await_14_GenericMethod()
{
Expand Down Expand Up @@ -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<System.Func<int>> M1(Buffer10<int> x) =>
() => ((System.Span<int>)x).Length;

static Expression<System.Func<int>> M2(Buffer10<int> x) =>
() => ((System.ReadOnlySpan<int>)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<int>)x).Length;
Diagnostic(ErrorCode.ERR_ExpressionTreeContainsInlineArrayOperation, "(System.Span<int>)x").WithLocation(7, 16),
// (10,16): error CS9507: An expression tree may not contain an inline array access or conversion
// () => ((System.ReadOnlySpan<int>)x).Length;
Diagnostic(ErrorCode.ERR_ExpressionTreeContainsInlineArrayOperation, "(System.ReadOnlySpan<int>)x").WithLocation(10, 16)
);
}

[ConditionalFact(typeof(MonoOrCoreClrOnly))]
public void Conversion_NotFromType_01()
{
Expand Down