提交 a6b51b2f 编写于 作者: N Neal Gafter 提交者: GitHub

Merge pull request #12941 from gafter/master-12900

Report errors for new features unsupported in expression trees.
......@@ -4111,6 +4111,15 @@ internal class CSharpResources {
}
}
/// <summary>
/// Looks up a localized string similar to An expression tree may not contain an &apos;is&apos; pattern-matching operator..
/// </summary>
internal static string ERR_ExpressionTreeContainsIsMatch {
get {
return ResourceManager.GetString("ERR_ExpressionTreeContainsIsMatch", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to An expression tree may not contain a reference to a local function.
/// </summary>
......@@ -4147,6 +4156,15 @@ internal class CSharpResources {
}
}
/// <summary>
/// Looks up a localized string similar to An expression tree may not contain an out argument variable declaration..
/// </summary>
internal static string ERR_ExpressionTreeContainsOutVariable {
get {
return ResourceManager.GetString("ERR_ExpressionTreeContainsOutVariable", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to An expression tree may not contain an unsafe pointer operation.
/// </summary>
......@@ -4156,6 +4174,24 @@ internal class CSharpResources {
}
}
/// <summary>
/// Looks up a localized string similar to An expression tree may not contain a tuple conversion..
/// </summary>
internal static string ERR_ExpressionTreeContainsTupleConversion {
get {
return ResourceManager.GetString("ERR_ExpressionTreeContainsTupleConversion", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to An expression tree may not contain a tuple literal..
/// </summary>
internal static string ERR_ExpressionTreeContainsTupleLiteral {
get {
return ResourceManager.GetString("ERR_ExpressionTreeContainsTupleLiteral", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Cannot convert lambda to an expression tree whose type argument &apos;{0}&apos; is not a delegate type.
/// </summary>
......@@ -9593,15 +9629,6 @@ internal class CSharpResources {
}
}
/// <summary>
/// Looks up a localized string similar to declaration expression.
/// </summary>
internal static string IDS_FeatureDeclarationExpression {
get {
return ResourceManager.GetString("IDS_FeatureDeclarationExpression", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to default operator.
/// </summary>
......
......@@ -4152,9 +4152,6 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<data name="IDS_Text" xml:space="preserve">
<value>&lt;text&gt;</value>
</data>
<data name="IDS_FeatureDeclarationExpression" xml:space="preserve">
<value>declaration expression</value>
</data>
<data name="IDS_FeatureNullPropagatingOperator" xml:space="preserve">
<value>null propagating operator</value>
</data>
......@@ -4935,6 +4932,18 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<data name="ERR_DeconstructCouldNotInferMergedType" xml:space="preserve">
<value>The type information on the left-hand-side '{0}' and right-hand-side '{1}' of the deconstruction was insufficient to infer a merged type.</value>
</data>
<data name="ERR_ExpressionTreeContainsOutVariable" xml:space="preserve">
<value>An expression tree may not contain an out argument variable declaration.</value>
</data>
<data name="ERR_ExpressionTreeContainsIsMatch" xml:space="preserve">
<value>An expression tree may not contain an 'is' pattern-matching operator.</value>
</data>
<data name="ERR_ExpressionTreeContainsTupleLiteral" xml:space="preserve">
<value>An expression tree may not contain a tuple literal.</value>
</data>
<data name="ERR_ExpressionTreeContainsTupleConversion" xml:space="preserve">
<value>An expression tree may not contain a tuple conversion.</value>
</data>
<data name="ERR_SourceLinkRequiresPortablePdb" xml:space="preserve">
<value>/sourcelink switch is only supported when emitting Portable PDB (/debug:portable or /debug:embedded must be specified).</value>
</data>
......
......@@ -1353,10 +1353,9 @@ internal enum ErrorCode
ERR_PatternValueExpected = 8119,
ERR_PatternIsSubsumed = 8120,
ERR_PatternWrongType = 8121,
ERR_ExpressionTreeContainsIsMatch = 8122,
#endregion diagnostics for pattern-matching introduced in C# 7
// Available = 8122
#region tuple diagnostics introduced in C# 7
WRN_TupleLiteralNameMismatch = 8123,
ERR_TupleTooFewElements = 8124,
......@@ -1378,9 +1377,10 @@ internal enum ErrorCode
ERR_DuplicateInterfaceWithTupleNamesInBaseList = 8140,
ERR_ImplBadTupleNames = 8141,
ERR_PartialMethodInconsistentTupleNames = 8142,
#endregion tuple diagnostics introduced in C# 7
ERR_ExpressionTreeContainsTupleLiteral = 8143,
ERR_ExpressionTreeContainsTupleConversion = 8144,
// Available = 8143, 8144
#endregion tuple diagnostics introduced in C# 7
#region diagnostics for ref locals and ref returns introduced in C# 7
ERR_AutoPropertyCannotBeRefReturning = 8145,
......@@ -1424,6 +1424,7 @@ internal enum ErrorCode
#region diagnostics for out var
ERR_ImplicitlyTypedOutVariableUsedInTheSameArgumentList = 8196,
ERR_TypeInferenceFailedForImplicitlyTypedOutVariable = 8197,
ERR_ExpressionTreeContainsOutVariable = 8198,
#endregion diagnostics for out var
}
}
......@@ -283,6 +283,17 @@ public override BoundNode VisitCall(BoundCall node)
return base.VisitCall(node);
}
/// <summary>
/// Called when a local represents an out variable declaration. Its syntax is of type DeclarationExpressionSyntax.
/// </summary>
private void CheckOutDeclaration(BoundLocal local, Symbol method)
{
if (_inExpressionLambda)
{
Error(ErrorCode.ERR_ExpressionTreeContainsOutVariable, local);
}
}
public override BoundNode VisitCollectionElementInitializer(BoundCollectionElementInitializer node)
{
if (_inExpressionLambda && node.AddMethod.IsStatic)
......@@ -513,6 +524,16 @@ public override BoundNode VisitConversion(BoundConversion node)
}
break;
case ConversionKind.ExplicitTuple:
case ConversionKind.ExplicitTupleLiteral:
case ConversionKind.ImplicitTuple:
case ConversionKind.ImplicitTupleLiteral:
if (_inExpressionLambda)
{
Error(ErrorCode.ERR_ExpressionTreeContainsTupleConversion, node);
}
break;
default:
break;
}
......@@ -631,5 +652,35 @@ public override BoundNode VisitDynamicObjectCreationExpression(BoundDynamicObjec
return base.VisitDynamicObjectCreationExpression(node);
}
public override BoundNode VisitIsPatternExpression(BoundIsPatternExpression node)
{
if (_inExpressionLambda)
{
Error(ErrorCode.ERR_ExpressionTreeContainsIsMatch, node);
}
return base.VisitIsPatternExpression(node);
}
public override BoundNode VisitConvertedTupleLiteral(BoundConvertedTupleLiteral node)
{
if (_inExpressionLambda)
{
Error(ErrorCode.ERR_ExpressionTreeContainsTupleLiteral, node);
}
return base.VisitConvertedTupleLiteral(node);
}
public override BoundNode VisitTupleLiteral(BoundTupleLiteral node)
{
if (_inExpressionLambda)
{
Error(ErrorCode.ERR_ExpressionTreeContainsTupleLiteral, node);
}
return base.VisitTupleLiteral(node);
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Immutable;
using System.Diagnostics;
using Microsoft.CodeAnalysis.CSharp.Symbols;
......@@ -19,9 +20,22 @@ private void CheckArguments(ImmutableArray<RefKind> argumentRefKindsOpt, Immutab
Debug.Assert(arguments.Length == argumentRefKindsOpt.Length);
for (int i = 0; i < arguments.Length; i++)
{
if (argumentRefKindsOpt[i] != RefKind.None && arguments[i].Kind == BoundKind.FieldAccess)
if (argumentRefKindsOpt[i] != RefKind.None)
{
CheckFieldAddress((BoundFieldAccess)arguments[i], method);
var argument = arguments[i];
switch (argument.Kind)
{
case BoundKind.FieldAccess:
CheckFieldAddress((BoundFieldAccess)argument, method);
break;
case BoundKind.Local:
var local = (BoundLocal)argument;
if (local.Syntax.Kind() == SyntaxKind.DeclarationExpression)
{
CheckOutDeclaration(local, method);
}
break;
}
}
}
}
......
......@@ -23050,6 +23050,88 @@ static void Main()
);
}
[WorkItem(12900, "https://github.com/dotnet/roslyn/issues/12900")]
[Fact]
public void CSharp7FeaturesInExprTrees()
{
var source = @"
using System;
//using System.Collections;
using System.Linq.Expressions;
class C
{
static void Main()
{
// out variable declarations
Expression<Func<bool>> e1 = () => TryGetThree(out int x) && x == 3; // ERROR 1
// pattern matching
object o = 3;
Expression<Func<bool>> e2 = () => o is int y && y == 3; // ERROR 2
// direct tuple creation could be OK, as it is just a constructor invocation,
// not for long tuples the generated code is more complex, and we would
// prefer custom expression trees to express the semantics.
Expression<Func<object>> e3 = () => (1, o); // ERROR 3: tuple literal
Expression<Func<(int, int)>> e4 = () => (1, 2); // ERROR 4: tuple literal
// tuple conversions
(byte, byte) t1 = (1, 2);
Expression<Func<(byte a, byte b)>> e5 = () => t1; // OK, identity conversion
Expression<Func<(int, int)>> e6 = () => t1; // ERROR 5: tuple conversion
Expression<Func<int>> e7 = () => TakeRef(ref GetRefThree()); // ERROR 6: calling ref-returning method
}
static bool TryGetThree(out int three)
{
three = 3;
return true;
}
static int three = 3;
static ref int GetRefThree()
{
return ref three;
}
static int TakeRef(ref int x)
{
Console.WriteLine(""wow"");
return x;
}
}
namespace System
{
struct ValueTuple<T1, T2>
{
public T1 Item1;
public T2 Item2;
public ValueTuple(T1 item1, T2 item2) { Item1 = item1; Item2 = item2; }
}
}";
var compilation = CreateCompilationWithMscorlibAndSystemCore(source, options: TestOptions.DebugExe);
compilation.VerifyDiagnostics(
// (10,59): error CS8198: An expression tree may not contain an out argument variable declaration.
// Expression<Func<bool>> e1 = () => TryGetThree(out int x) && x == 3; // ERROR 1
Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOutVariable, "int x").WithLocation(10, 59),
// (14,43): error CS8122: An expression tree may not contain an 'is' pattern-matching operator.
// Expression<Func<bool>> e2 = () => o is int y && y == 3; // ERROR 2
Diagnostic(ErrorCode.ERR_ExpressionTreeContainsIsMatch, "o is int y").WithLocation(14, 43),
// (19,45): error CS8143: An expression tree may not contain a tuple literal.
// Expression<Func<object>> e3 = () => (1, o); // ERROR 3: tuple literal
Diagnostic(ErrorCode.ERR_ExpressionTreeContainsTupleLiteral, "(1, o)").WithLocation(19, 45),
// (20,49): error CS8143: An expression tree may not contain a tuple literal.
// Expression<Func<(int, int)>> e4 = () => (1, 2); // ERROR 4: tuple literal
Diagnostic(ErrorCode.ERR_ExpressionTreeContainsTupleLiteral, "(1, 2)").WithLocation(20, 49),
// (25,49): error CS8144: An expression tree may not contain a tuple conversion.
// Expression<Func<(int, int)>> e6 = () => t1; // ERROR 5: tuple conversion
Diagnostic(ErrorCode.ERR_ExpressionTreeContainsTupleConversion, "t1").WithLocation(25, 49),
// (27,54): error CS8156: An expression tree lambda may not contain a call to a method, property, or indexer that returns by reference
// Expression<Func<int>> e7 = () => TakeRef(ref GetRefThree()); // ERROR 6: calling ref-returning method
Diagnostic(ErrorCode.ERR_RefReturningCallInExpressionTree, "GetRefThree()").WithLocation(27, 54)
);
}
[Fact]
public void DictionaryInitializerInCS5()
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册