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

Disallow expression variables in query clauses. (#16081)

Fixes #15910
Also fixes a sequence point issue with the let expression. Specifically, the source range for the query lambda included more than the expression of the let, but included the entire query clause. It now includes only the expression, like other query clauses.
上级 5bb984ba
......@@ -582,7 +582,7 @@ private void ReduceLet(LetClauseSyntax let, QueryTranslationState state, Diagnos
// The bound block represents a closure scope for transparent identifiers captured in the let clause.
// Such closures shall be associated with the lambda body expression.
return lambdaBodyBinder.CreateBlockFromExpression(let.Expression, lambdaBodyBinder.GetDeclaredLocalsForScope(let.Expression), RefKind.None, construction, null, d);
return lambdaBodyBinder.CreateLambdaBlockForQueryClause(let.Expression, construction, d);
};
var lambda = MakeQueryUnboundLambda(state.RangeVariableMap(), ImmutableArray.Create(x), let.Expression, bodyFactory);
......@@ -594,6 +594,17 @@ private void ReduceLet(LetClauseSyntax let, QueryTranslationState state, Diagnos
state.fromExpression = MakeQueryClause(let, invocation, y, invocation);
}
private BoundBlock CreateLambdaBlockForQueryClause(ExpressionSyntax expression, BoundExpression result, DiagnosticBag diagnostics)
{
var locals = this.GetDeclaredLocalsForScope(expression);
if (locals.Any())
{
diagnostics.Add(ErrorCode.ERR_ExpressionVariableInQueryClause, locals[0].Locations[0]);
}
return this.CreateBlockFromExpression(expression, locals, RefKind.None, result, expression, diagnostics);
}
private BoundQueryClause MakeQueryClause(
CSharpSyntaxNode syntax,
BoundExpression expression,
......@@ -648,7 +659,10 @@ private UnboundLambda MakeQueryUnboundLambda(RangeVariableMap qvm, ImmutableArra
{
return MakeQueryUnboundLambda(expression, new QueryUnboundLambdaState(this, qvm, parameters, (LambdaSymbol lambdaSymbol, Binder lambdaBodyBinder, DiagnosticBag diagnostics) =>
{
return lambdaBodyBinder.BindLambdaExpressionAsBlock(expression, diagnostics);
lambdaBodyBinder = lambdaBodyBinder.GetBinder(expression);
Debug.Assert(lambdaSymbol != null);
BoundExpression boundExpression = lambdaBodyBinder.BindValue(expression, diagnostics, BindValueKind.RValue);
return lambdaBodyBinder.CreateLambdaBlockForQueryClause(expression, boundExpression, diagnostics);
}));
}
......@@ -658,13 +672,12 @@ private UnboundLambda MakeQueryUnboundLambdaWithCast(RangeVariableMap qvm, Range
{
lambdaBodyBinder = lambdaBodyBinder.GetBinder(expression);
Debug.Assert(lambdaBodyBinder != null);
BoundExpression boundExpression = lambdaBodyBinder.BindValue(expression, diagnostics, BindValueKind.RValue);
// We transform the expression from "expr" to "expr.Cast<castTypeOpt>()".
boundExpression = lambdaBodyBinder.MakeQueryInvocation(expression, boundExpression, "Cast", castTypeSyntax, castType, diagnostics);
return lambdaBodyBinder.CreateBlockFromExpression(expression, lambdaBodyBinder.GetDeclaredLocalsForScope(expression), RefKind.None, boundExpression, expression, diagnostics);
return lambdaBodyBinder.CreateLambdaBlockForQueryClause(expression, boundExpression, diagnostics);
}));
}
......
......@@ -4228,6 +4228,15 @@ internal class CSharpResources {
}
}
/// <summary>
/// Looks up a localized string similar to Out variable and pattern variable declarations are not allowed within a query clause..
/// </summary>
internal static string ERR_ExpressionVariableInQueryClause {
get {
return ResourceManager.GetString("ERR_ExpressionVariableInQueryClause", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Cannot define a new extension method because the compiler required type &apos;{0}&apos; cannot be found. Are you missing a reference to System.Core.dll?.
/// </summary>
......@@ -10413,7 +10422,7 @@ internal class CSharpResources {
}
/// <summary>
/// Looks up a localized string similar to &lt;throw&gt;.
/// Looks up a localized string similar to &lt;throw expression&gt;.
/// </summary>
internal static string IDS_ThrowExpression {
get {
......
......@@ -4969,6 +4969,9 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<data name="ERR_ExpressionVariableInConstructorOrFieldInitializer" xml:space="preserve">
<value>Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers.</value>
</data>
<data name="ERR_ExpressionVariableInQueryClause" xml:space="preserve">
<value>Out variable and pattern variable declarations are not allowed within a query clause.</value>
</data>
<data name="ERR_SemiOrLBraceOrArrowExpected" xml:space="preserve">
<value>{ or ; or =&gt; expected</value>
</data>
......
......@@ -1443,8 +1443,12 @@ internal enum ErrorCode
ERR_ImplicitlyTypedOutVariableUsedInTheSameArgumentList = 8196,
ERR_TypeInferenceFailedForImplicitlyTypedOutVariable = 8197,
ERR_ExpressionTreeContainsOutVariable = 8198,
#endregion diagnostics for out var
#region more stragglers for C# 7
ERR_VarInvocationLvalueReserved = 8199,
ERR_ExpressionVariableInConstructorOrFieldInitializer = 8200,
#endregion diagnostics for out var
ERR_ExpressionVariableInQueryClause = 8201,
#endregion more stragglers for C# 7
}
}
......@@ -655,7 +655,7 @@ public void M()
<forward declaringType=""C"" methodName=""M"" />
</customDebugInfo>
<sequencePoints>
<entry offset=""0x0"" startLine=""10"" startColumn=""17"" endLine=""10"" endColumn=""30"" />
<entry offset=""0x0"" startLine=""10"" startColumn=""25"" endLine=""10"" endColumn=""30"" />
</sequencePoints>
</method>
<method containingType=""C+&lt;&gt;c"" name=""&lt;M&gt;b__0_1"" parameterNames=""&lt;&gt;h__TransparentIdentifier0"">
......
......@@ -837,20 +837,57 @@ static bool Print(object x)
}
";
var compilation = CreateCompilationWithMscorlib45(source, new[] { SystemCoreRef }, options: TestOptions.DebugExe);
CompileAndVerify(compilation, expectedOutput:
@"1
3
5
2
4
6
7
8
10
9
11
12
");
compilation.VerifyDiagnostics(
// (14,47): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// from x2 in new[] { 2 is var y2 && Print(y2) ? 1 : 0}
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y2").WithLocation(14, 47),
// (16,36): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// on 4 is var y4 && Print(y4) ? 1 : 0
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y4").WithLocation(16, 36),
// (17,43): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// equals 5 is var y5 && Print(y5) ? 1 : 0
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y5").WithLocation(17, 43),
// (18,34): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// where 6 is var y6 && Print(y6)
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y6").WithLocation(18, 34),
// (19,36): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// orderby 7 is var y7 && Print(y7),
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y7").WithLocation(19, 36),
// (20,36): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// 8 is var y8 && Print(y8)
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y8").WithLocation(20, 36),
// (22,32): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// by 10 is var y10 && Print(y10)
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y10").WithLocation(22, 32),
// (21,34): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// group 9 is var y9 && Print(y9)
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y9").WithLocation(21, 34),
// (24,39): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// let x11 = 11 is var y11 && Print(y11)
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y11").WithLocation(24, 39),
// (25,36): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// select 12 is var y12 && Print(y12);
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "y12").WithLocation(25, 36)
);
// Because expression variables are not permitted in query clauses (https://github.com/dotnet/roslyn/issues/15910)
// this program cannot be run. However, once we allow that (https://github.com/dotnet/roslyn/issues/15619)
// the program wil be capable of being run. In that case the following (commented code) would test for the expected output.
// CompileAndVerify(compilation, expectedOutput:
//@"1
//3
//5
//2
//4
//6
//7
//8
//10
//9
//11
//12
//");
var tree = compilation.SyntaxTrees.Single();
var model = compilation.GetSemanticModel(tree);
......
......@@ -2241,5 +2241,229 @@ public static Test Select<T>(System.Func<int, T> selector)
CompileAndVerify(compilation, expectedOutput: "Select");
}
[WorkItem(15910, "https://github.com/dotnet/roslyn/issues/15910")]
[Fact]
public void ExpressionVariablesInQueryClause_01()
{
var csSource = @"
using System.Linq;
class Program
{
public static void Main(string[] args)
{
var a = new[] { 1, 2, 3, 4 };
var za = from x in M(a, out var q1) select x; // ok
var zc = from x in a from y in M(a, out var z) select x; // error 1
var zd = from x in a from int y in M(a, out var z) select x; // error 2
var ze = from x in a from y in M(a, out var z) where true select x; // error 3
var zf = from x in a from int y in M(a, out var z) where true select x; // error 4
var zg = from x in a let y = M(a, out var z) select x; // error 5
var zh = from x in a where M(x, out var z) == 1 select x; // error 6
var zi = from x in a join y in M(a, out var q2) on x equals y select x; // ok
var zj = from x in a join y in a on M(x, out var z) equals y select x; // error 7
var zk = from x in a join y in a on x equals M(y, out var z) select x; // error 8
var zl = from x in a orderby M(x, out var z) select x; // error 9
var zm = from x in a orderby x, M(x, out var z) select x; // error 10
var zn = from x in a group M(x, out var z) by x; // error 11
var zo = from x in a group x by M(x, out var z); // error 12
}
public static T M<T>(T x, out T z) => z = x;
}";
CreateCompilationWithMscorlibAndSystemCore(csSource).VerifyDiagnostics(
// (10,53): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// var zc = from x in a from y in M(a, out var z) select x; // error 1
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(10, 53),
// (11,57): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// var zd = from x in a from int y in M(a, out var z) select x; // error 2
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(11, 57),
// (12,53): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// var ze = from x in a from y in M(a, out var z) where true select x; // error 3
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(12, 53),
// (13,57): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// var zf = from x in a from int y in M(a, out var z) where true select x; // error 4
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(13, 57),
// (14,51): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// var zg = from x in a let y = M(a, out var z) select x; // error 5
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(14, 51),
// (15,49): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// var zh = from x in a where M(x, out var z) == 1 select x; // error 6
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(15, 49),
// (17,58): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// var zj = from x in a join y in a on M(x, out var z) equals y select x; // error 7
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(17, 58),
// (18,67): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// var zk = from x in a join y in a on x equals M(y, out var z) select x; // error 8
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(18, 67),
// (19,51): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// var zl = from x in a orderby M(x, out var z) select x; // error 9
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(19, 51),
// (20,54): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// var zm = from x in a orderby x, M(x, out var z) select x; // error 10
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(20, 54),
// (21,49): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// var zn = from x in a group M(x, out var z) by x; // error 11
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(21, 49),
// (22,54): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// var zo = from x in a group x by M(x, out var z); // error 12
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(22, 54)
);
}
[WorkItem(15910, "https://github.com/dotnet/roslyn/issues/15910")]
[Fact]
public void ExpressionVariablesInQueryClause_02()
{
var csSource = @"
using System.Linq;
class Program
{
public static void Main(string[] args)
{
var a = new[] { 1, 2, 3, 4 };
var za = from x in M(a, a is var q1) select x; // ok
var zc = from x in a from y in M(a, a is var z) select x; // error 1
var zd = from x in a from int y in M(a, a is var z) select x; // error 2
var ze = from x in a from y in M(a, a is var z) where true select x; // error 3
var zf = from x in a from int y in M(a, a is var z) where true select x; // error 4
var zg = from x in a let y = M(a, a is var z) select x; // error 5
var zh = from x in a where M(x, x is var z) == 1 select x; // error 6
var zi = from x in a join y in M(a, a is var q2) on x equals y select x; // ok
var zj = from x in a join y in a on M(x, x is var z) equals y select x; // error 7
var zk = from x in a join y in a on x equals M(y, y is var z) select x; // error 8
var zl = from x in a orderby M(x, x is var z) select x; // error 9
var zm = from x in a orderby x, M(x, x is var z) select x; // error 10
var zn = from x in a group M(x, x is var z) by x; // error 11
var zo = from x in a group x by M(x, x is var z); // error 12
}
public static T M<T>(T x, bool b) => x;
}";
CreateCompilationWithMscorlibAndSystemCore(csSource).VerifyDiagnostics(
// (10,54): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// var zc = from x in a from y in M(a, a is var z) select x; // error 1
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(10, 54),
// (11,58): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// var zd = from x in a from int y in M(a, a is var z) select x; // error 2
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(11, 58),
// (12,54): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// var ze = from x in a from y in M(a, a is var z) where true select x; // error 3
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(12, 54),
// (13,58): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// var zf = from x in a from int y in M(a, a is var z) where true select x; // error 4
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(13, 58),
// (14,52): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// var zg = from x in a let y = M(a, a is var z) select x; // error 5
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(14, 52),
// (15,50): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// var zh = from x in a where M(x, x is var z) == 1 select x; // error 6
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(15, 50),
// (17,59): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// var zj = from x in a join y in a on M(x, x is var z) equals y select x; // error 7
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(17, 59),
// (18,68): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// var zk = from x in a join y in a on x equals M(y, y is var z) select x; // error 8
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(18, 68),
// (19,52): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// var zl = from x in a orderby M(x, x is var z) select x; // error 9
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(19, 52),
// (20,55): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// var zm = from x in a orderby x, M(x, x is var z) select x; // error 10
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(20, 55),
// (21,50): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// var zn = from x in a group M(x, x is var z) by x; // error 11
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(21, 50),
// (22,55): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// var zo = from x in a group x by M(x, x is var z); // error 12
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(22, 55)
);
}
[WorkItem(15910, "https://github.com/dotnet/roslyn/issues/15910")]
[Fact]
public void ExpressionVariablesInQueryClause_03()
{
var csSource = @"
using System.Linq;
class Program
{
public static void Main(string[] args)
{
var a = new[] { (1, 2), (3, 4) };
var za = from x in M(a, (int qa, int wa) = a[0]) select x; // scoping ok
var zc = from x in a from y in M(a, (int z, int w) = x) select x; // error 1
var zd = from x in a from int y in M(a, (int z, int w) = x) select x; // error 2
var ze = from x in a from y in M(a, (int z, int w) = x) where true select x; // error 3
var zf = from x in a from int y in M(a, (int z, int w) = x) where true select x; // error 4
var zg = from x in a let y = M(x, (int z, int w) = x) select x; // error 5
var zh = from x in a where M(x, (int z, int w) = x).Item1 == 1 select x; // error 6
var zi = from x in a join y in M(a, (int qi, int wi) = a[0]) on x equals y select x; // scoping ok
var zj = from x in a join y in a on M(x, (int z, int w) = x) equals y select x; // error 7
var zk = from x in a join y in a on x equals M(y, (int z, int w) = y) select x; // error 8
var zl = from x in a orderby M(x, (int z, int w) = x) select x; // error 9
var zm = from x in a orderby x, M(x, (int z, int w) = x) select x; // error 10
var zn = from x in a group M(x, (int z, int w) = x) by x; // error 11
var zo = from x in a group x by M(x, (int z, int w) = x); // error 12
}
public static T M<T>(T x, (int, int) z) => x;
}
namespace System
{
public struct ValueTuple<T1, T2>
{
public T1 Item1;
public T2 Item2;
public ValueTuple(T1 item1, T2 item2)
{
this.Item1 = item1;
this.Item2 = item2;
}
}
}
";
CreateCompilationWithMscorlibAndSystemCore(csSource)
.GetDiagnostics()
.Where(d => d.Code != (int)ErrorCode.ERR_DeclarationExpressionNotPermitted)
.Verify(
// (10,50): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// var zc = from x in a from y in M(a, (int z, int w) = x) select x; // error 1
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(10, 50),
// (11,54): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// var zd = from x in a from int y in M(a, (int z, int w) = x) select x; // error 2
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(11, 54),
// (12,50): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// var ze = from x in a from y in M(a, (int z, int w) = x) where true select x; // error 3
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(12, 50),
// (13,54): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// var zf = from x in a from int y in M(a, (int z, int w) = x) where true select x; // error 4
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(13, 54),
// (14,48): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// var zg = from x in a let y = M(x, (int z, int w) = x) select x; // error 5
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(14, 48),
// (15,46): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// var zh = from x in a where M(x, (int z, int w) = x).Item1 == 1 select x; // error 6
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(15, 46),
// (17,55): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// var zj = from x in a join y in a on M(x, (int z, int w) = x) equals y select x; // error 7
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(17, 55),
// (18,64): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// var zk = from x in a join y in a on x equals M(y, (int z, int w) = y) select x; // error 8
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(18, 64),
// (19,48): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// var zl = from x in a orderby M(x, (int z, int w) = x) select x; // error 9
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(19, 48),
// (20,51): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// var zm = from x in a orderby x, M(x, (int z, int w) = x) select x; // error 10
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(20, 51),
// (21,46): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// var zn = from x in a group M(x, (int z, int w) = x) by x; // error 11
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(21, 46),
// (22,51): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause.
// var zo = from x in a group x by M(x, (int z, int w) = x); // error 12
Diagnostic(ErrorCode.ERR_ExpressionVariableInQueryClause, "z").WithLocation(22, 51)
);
}
}
}
......@@ -4,6 +4,7 @@
using Xunit;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Roslyn.Test.Utilities;
using System.Linq;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics
{
......@@ -998,5 +999,107 @@ static void RefParam(ref dynamic p)
expectedOutput: "frog",
additionalRefs: new[] { SystemCoreRef, CSharpRef }).VerifyDiagnostics();
}
[Fact]
public void RefQueryClause()
{
// a "ref" may not precede the expression of a query clause...
// simply because the grammar doesn't permit it. Here we check
// that the situation is diagnosed, either syntactically or semantically.
// The precise diagnostics are not important for the purposes of this test.
var text = @"
class C
{
static void Main(string[] args)
{
var a = new[] { 1, 2, 3, 4 };
bool b = true;
int i = 0;
{ var za = from x in a select ref x; } // error 1
{ var zc = from x in a from y in ref a select x; } // error2
{ var zd = from x in a from int y in ref a select x; } // error 3
{ var ze = from x in a from y in ref a where true select x; } // error 4
{ var zf = from x in a from int y in ref a where true select x; } // error 5
{ var zg = from x in a let y = ref a select x; } // error 6
{ var zh = from x in a where ref b select x; } // error 7
{ var zi = from x in a join y in ref a on x equals y select x; } // error 8 (not lambda case)
{ var zj = from x in a join y in a on ref i equals y select x; } // error 9
{ var zk = from x in a join y in a on x equals ref i select x; } // error 10
{ var zl = from x in a orderby ref i select x; } // error 11
{ var zm = from x in a orderby x, ref i select x; } // error 12
{ var zn = from x in a group ref i by x; } // error 13
{ var zo = from x in a group x by ref i; } // error 14
}
public static T M<T>(T x, out T z) => z = x;
public C Select(RefFunc<C, C> c1) => this;
public C SelectMany(RefFunc<C, C> c1, RefFunc<C, C, C> c2) => this;
public C Cast<T>() => this;
}
public delegate ref TR RefFunc<T1, TR>(T1 t1);
public delegate ref TR RefFunc<T1, T2, TR>(T1 t1, T2 t2);
";
CreateCompilationWithMscorlibAndSystemCore(text)
.GetDiagnostics()
// It turns out each of them is diagnosed with ErrorCode.ERR_InvalidExprTerm in the midst
// of a flurry of other syntax errors.
.Where(d => d.Code == (int)ErrorCode.ERR_InvalidExprTerm)
.Verify(
// (9,39): error CS1525: Invalid expression term 'ref'
// { var za = from x in a select ref x; } // error 1
Diagnostic(ErrorCode.ERR_InvalidExprTerm, "ref").WithArguments("ref").WithLocation(9, 39),
// (10,42): error CS1525: Invalid expression term 'ref'
// { var zc = from x in a from y in ref a select x; } // error2
Diagnostic(ErrorCode.ERR_InvalidExprTerm, "ref").WithArguments("ref").WithLocation(10, 42),
// (11,46): error CS1525: Invalid expression term 'ref'
// { var zd = from x in a from int y in ref a select x; } // error 3
Diagnostic(ErrorCode.ERR_InvalidExprTerm, "ref").WithArguments("ref").WithLocation(11, 46),
// (12,42): error CS1525: Invalid expression term 'ref'
// { var ze = from x in a from y in ref a where true select x; } // error 4
Diagnostic(ErrorCode.ERR_InvalidExprTerm, "ref").WithArguments("ref").WithLocation(12, 42),
// (13,46): error CS1525: Invalid expression term 'ref'
// { var zf = from x in a from int y in ref a where true select x; } // error 5
Diagnostic(ErrorCode.ERR_InvalidExprTerm, "ref").WithArguments("ref").WithLocation(13, 46),
// (14,40): error CS1525: Invalid expression term 'ref'
// { var zg = from x in a let y = ref a select x; } // error 6
Diagnostic(ErrorCode.ERR_InvalidExprTerm, "ref").WithArguments("ref").WithLocation(14, 40),
// (15,38): error CS1525: Invalid expression term 'ref'
// { var zh = from x in a where ref b select x; } // error 7
Diagnostic(ErrorCode.ERR_InvalidExprTerm, "ref").WithArguments("ref").WithLocation(15, 38),
// (16,42): error CS1525: Invalid expression term 'ref'
// { var zi = from x in a join y in ref a on x equals y select x; } // error 8 (not lambda case)
Diagnostic(ErrorCode.ERR_InvalidExprTerm, "ref").WithArguments("ref").WithLocation(16, 42),
// (16,42): error CS1525: Invalid expression term 'ref'
// { var zi = from x in a join y in ref a on x equals y select x; } // error 8 (not lambda case)
Diagnostic(ErrorCode.ERR_InvalidExprTerm, "ref").WithArguments("ref").WithLocation(16, 42),
// (16,42): error CS1525: Invalid expression term 'ref'
// { var zi = from x in a join y in ref a on x equals y select x; } // error 8 (not lambda case)
Diagnostic(ErrorCode.ERR_InvalidExprTerm, "ref").WithArguments("ref").WithLocation(16, 42),
// (17,47): error CS1525: Invalid expression term 'ref'
// { var zj = from x in a join y in a on ref i equals y select x; } // error 9
Diagnostic(ErrorCode.ERR_InvalidExprTerm, "ref").WithArguments("ref").WithLocation(17, 47),
// (17,47): error CS1525: Invalid expression term 'ref'
// { var zj = from x in a join y in a on ref i equals y select x; } // error 9
Diagnostic(ErrorCode.ERR_InvalidExprTerm, "ref").WithArguments("ref").WithLocation(17, 47),
// (18,56): error CS1525: Invalid expression term 'ref'
// { var zk = from x in a join y in a on x equals ref i select x; } // error 10
Diagnostic(ErrorCode.ERR_InvalidExprTerm, "ref").WithArguments("ref").WithLocation(18, 56),
// (19,40): error CS1525: Invalid expression term 'ref'
// { var zl = from x in a orderby ref i select x; } // error 11
Diagnostic(ErrorCode.ERR_InvalidExprTerm, "ref").WithArguments("ref").WithLocation(19, 40),
// (20,43): error CS1525: Invalid expression term 'ref'
// { var zm = from x in a orderby x, ref i select x; } // error 12
Diagnostic(ErrorCode.ERR_InvalidExprTerm, "ref").WithArguments("ref").WithLocation(20, 43),
// (21,38): error CS1525: Invalid expression term 'ref'
// { var zn = from x in a group ref i by x; } // error 13
Diagnostic(ErrorCode.ERR_InvalidExprTerm, "ref").WithArguments("ref").WithLocation(21, 38),
// (21,38): error CS1525: Invalid expression term 'ref'
// { var zn = from x in a group ref i by x; } // error 13
Diagnostic(ErrorCode.ERR_InvalidExprTerm, "ref").WithArguments("ref").WithLocation(21, 38),
// (22,43): error CS1525: Invalid expression term 'ref'
// { var zo = from x in a group x by ref i; } // error 14
Diagnostic(ErrorCode.ERR_InvalidExprTerm, "ref").WithArguments("ref").WithLocation(22, 43)
);
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册