提交 e773aec9 编写于 作者: J Julien 提交者: GitHub

Disallow d-declaration as embedded statement and adding other tests (#13379)

上级 4fe9116e
......@@ -554,7 +554,7 @@ internal void ReportDiagnosticsIfObsolete(DiagnosticBag diagnostics, Conversion
///
/// NOTE: The return value reflects obsolete-ness, not whether or not the diagnostic was reported.
/// </returns>
private static ThreeState ReportDiagnosticsIfObsoleteInternal(DiagnosticBag diagnostics, Symbol symbol, SyntaxNodeOrToken node, Symbol containingMember, BinderFlags location)
internal static ThreeState ReportDiagnosticsIfObsoleteInternal(DiagnosticBag diagnostics, Symbol symbol, SyntaxNodeOrToken node, Symbol containingMember, BinderFlags location)
{
Debug.Assert(diagnostics != null);
......
......@@ -62,7 +62,7 @@ internal partial class Binder
if (source.Kind == BoundKind.TupleLiteral)
{
var sourceTuple = (BoundTupleLiteral)source;
TupleTypeSymbol.ReportNamesMismatchesIfAny(destination.TupleElementNames, sourceTuple, diagnostics);
TupleTypeSymbol.ReportNamesMismatchesIfAny(destination, sourceTuple, diagnostics);
source = new BoundConvertedTupleLiteral(
sourceTuple.Syntax,
sourceTuple.Type,
......@@ -355,7 +355,7 @@ private BoundExpression CreateTupleLiteralConversion(SyntaxNode syntax, BoundTup
var destTupleType = (TupleTypeSymbol)targetType;
// do not lose the original element names in the literal if different from names in the target
TupleTypeSymbol.ReportNamesMismatchesIfAny(targetType.TupleElementNames, sourceTuple, diagnostics);
TupleTypeSymbol.ReportNamesMismatchesIfAny(targetType, sourceTuple, diagnostics);
// Come back to this, what about locations? (https://github.com/dotnet/roslyn/issues/11013)
targetType = destTupleType.WithElementNames(sourceTuple.ArgumentNamesOpt);
......
......@@ -1693,10 +1693,10 @@ private BoundExpression BindCastCore(ExpressionSyntax node, BoundExpression oper
}
private void GenerateExplicitConversionErrors(
DiagnosticBag diagnostics,
SyntaxNode syntax,
Conversion conversion,
BoundExpression operand,
DiagnosticBag diagnostics,
SyntaxNode syntax,
Conversion conversion,
BoundExpression operand,
TypeSymbol targetType)
{
// Make sure that errors within the unbound lambda don't get lost.
......@@ -1787,7 +1787,7 @@ private BoundExpression BindCastCore(ExpressionSyntax node, BoundExpression oper
DiagnosticBag diagnostics,
ImmutableArray<BoundExpression> tupleArguments,
ImmutableArray<TypeSymbol> targetElementTypes)
{
{
var argLength = tupleArguments.Length;
// report all leaf elements of the tuple literal that failed to convert
......
......@@ -13355,7 +13355,7 @@ internal class CSharpResources {
}
/// <summary>
/// Looks up a localized string similar to The tuple element name &apos;{0}&apos; is ignored because a different name is specified by the assignment target..
/// Looks up a localized string similar to The tuple element name &apos;{0}&apos; is ignored because a different name is specified by the target type &apos;{1}&apos;..
/// </summary>
internal static string WRN_TupleLiteralNameMismatch {
get {
......
......@@ -4906,7 +4906,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<value>The type must be 'var'.</value>
</data>
<data name="WRN_TupleLiteralNameMismatch" xml:space="preserve">
<value>The tuple element name '{0}' is ignored because a different name is specified by the assignment target.</value>
<value>The tuple element name '{0}' is ignored because a different name is specified by the target type '{1}'.</value>
</data>
<data name="WRN_TupleLiteralNameMismatch_Title" xml:space="preserve">
<value>The tuple element name is ignored because a different name is specified by the assignment target.</value>
......
......@@ -7425,6 +7425,7 @@ private StatementSyntax ParseEmbeddedStatement(bool complexCheck)
case SyntaxKind.LabeledStatement:
case SyntaxKind.LocalDeclarationStatement:
case SyntaxKind.LocalFunctionStatement:
case SyntaxKind.DeconstructionDeclarationStatement:
statement = this.AddError(statement, ErrorCode.ERR_BadEmbeddedStmt);
break;
}
......
......@@ -335,7 +335,7 @@ private static NamedTypeSymbol GetTupleUnderlyingType(ImmutableArray<TypeSymbol>
if ((object)diagnostics != null && (object)syntax != null)
{
Binder.ReportUseSiteDiagnostics(firstTupleType, diagnostics, syntax);
ReportUseSiteAndObsoleteDiagnostics(syntax, diagnostics, firstTupleType);
}
currentSymbol = firstTupleType.Construct(ImmutableArray.Create(elementTypes, (chainLength - 1) * (RestPosition - 1), remainder));
......@@ -347,7 +347,7 @@ private static NamedTypeSymbol GetTupleUnderlyingType(ImmutableArray<TypeSymbol>
if ((object)diagnostics != null && (object)syntax != null)
{
Binder.ReportUseSiteDiagnostics(chainedTupleType, diagnostics, syntax);
ReportUseSiteAndObsoleteDiagnostics(syntax, diagnostics, chainedTupleType);
}
do
......@@ -363,6 +363,12 @@ private static NamedTypeSymbol GetTupleUnderlyingType(ImmutableArray<TypeSymbol>
return currentSymbol;
}
private static void ReportUseSiteAndObsoleteDiagnostics(CSharpSyntaxNode syntax, DiagnosticBag diagnostics, NamedTypeSymbol firstTupleType)
{
Binder.ReportUseSiteDiagnostics(firstTupleType, diagnostics, syntax);
Binder.ReportDiagnosticsIfObsoleteInternal(diagnostics, firstTupleType, syntax, firstTupleType.ContainingType, BinderFlags.None);
}
/// <summary>
/// For tuples with no natural type, we still need to verify that an underlying type of proper arity exists, and report if otherwise.
/// </summary>
......@@ -374,16 +380,16 @@ internal static void VerifyTupleTypePresent(int cardinality, CSharpSyntaxNode sy
int chainLength = NumberOfValueTuples(cardinality, out remainder);
NamedTypeSymbol firstTupleType = compilation.GetWellKnownType(GetTupleType(remainder));
Binder.ReportUseSiteDiagnostics(firstTupleType, diagnostics, syntax);
ReportUseSiteAndObsoleteDiagnostics(syntax, diagnostics, firstTupleType);
if (chainLength > 1)
{
NamedTypeSymbol chainedTupleType = compilation.GetWellKnownType(GetTupleType(RestPosition));
Binder.ReportUseSiteDiagnostics(chainedTupleType, diagnostics, syntax);
ReportUseSiteAndObsoleteDiagnostics(syntax, diagnostics, chainedTupleType);
}
}
internal static void ReportNamesMismatchesIfAny(ImmutableArray<string> destinationNames, BoundTupleLiteral literal, DiagnosticBag diagnostics)
internal static void ReportNamesMismatchesIfAny(TypeSymbol destination, BoundTupleLiteral literal, DiagnosticBag diagnostics)
{
var sourceNames = literal.ArgumentNamesOpt;
if (sourceNames.IsDefault)
......@@ -391,6 +397,7 @@ internal static void ReportNamesMismatchesIfAny(ImmutableArray<string> destinati
return;
}
ImmutableArray<string> destinationNames = destination.TupleElementNames;
int sourceLength = sourceNames.Length;
bool allMissing = destinationNames.IsDefault;
Debug.Assert(allMissing || destinationNames.Length == sourceLength);
......@@ -400,7 +407,7 @@ internal static void ReportNamesMismatchesIfAny(ImmutableArray<string> destinati
var sourceName = sourceNames[i];
if (sourceName != null && (allMissing || string.CompareOrdinal(destinationNames[i], sourceName) != 0))
{
diagnostics.Add(ErrorCode.WRN_TupleLiteralNameMismatch, literal.Arguments[i].Syntax.Parent.Location, sourceName);
diagnostics.Add(ErrorCode.WRN_TupleLiteralNameMismatch, literal.Arguments[i].Syntax.Parent.Location, sourceName, destination);
}
}
}
......
......@@ -845,36 +845,36 @@ static void Main()
var comp = CompileAndVerify(source, expectedOutput: "9 10", additionalRefs: new[] { ValueTupleRef, SystemRuntimeFacadeRef });
comp.VerifyDiagnostics(
// (9,43): warning CS8123: The tuple element name 'a' is ignored because a different name is specified by the assignment target.
// (9,43): warning CS8123: The tuple element name 'a' is ignored because a different name is specified by the target type '(long, long, long, long, long, long, long, long, long, int)'.
// (x, x, x, x, x, x, x, x, x, y) = (a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10);
Diagnostic(ErrorCode.WRN_TupleLiteralNameMismatch, "a: 1").WithArguments("a").WithLocation(9, 43),
// (9,49): warning CS8123: The tuple element name 'b' is ignored because a different name is specified by the assignment target.
Diagnostic(ErrorCode.WRN_TupleLiteralNameMismatch, "a: 1").WithArguments("a", "(long, long, long, long, long, long, long, long, long, int)").WithLocation(9, 43),
// (9,49): warning CS8123: The tuple element name 'b' is ignored because a different name is specified by the target type '(long, long, long, long, long, long, long, long, long, int)'.
// (x, x, x, x, x, x, x, x, x, y) = (a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10);
Diagnostic(ErrorCode.WRN_TupleLiteralNameMismatch, "b: 2").WithArguments("b").WithLocation(9, 49),
// (9,55): warning CS8123: The tuple element name 'c' is ignored because a different name is specified by the assignment target.
Diagnostic(ErrorCode.WRN_TupleLiteralNameMismatch, "b: 2").WithArguments("b", "(long, long, long, long, long, long, long, long, long, int)").WithLocation(9, 49),
// (9,55): warning CS8123: The tuple element name 'c' is ignored because a different name is specified by the target type '(long, long, long, long, long, long, long, long, long, int)'.
// (x, x, x, x, x, x, x, x, x, y) = (a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10);
Diagnostic(ErrorCode.WRN_TupleLiteralNameMismatch, "c: 3").WithArguments("c").WithLocation(9, 55),
// (9,61): warning CS8123: The tuple element name 'd' is ignored because a different name is specified by the assignment target.
Diagnostic(ErrorCode.WRN_TupleLiteralNameMismatch, "c: 3").WithArguments("c", "(long, long, long, long, long, long, long, long, long, int)").WithLocation(9, 55),
// (9,61): warning CS8123: The tuple element name 'd' is ignored because a different name is specified by the target type '(long, long, long, long, long, long, long, long, long, int)'.
// (x, x, x, x, x, x, x, x, x, y) = (a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10);
Diagnostic(ErrorCode.WRN_TupleLiteralNameMismatch, "d: 4").WithArguments("d").WithLocation(9, 61),
// (9,67): warning CS8123: The tuple element name 'e' is ignored because a different name is specified by the assignment target.
Diagnostic(ErrorCode.WRN_TupleLiteralNameMismatch, "d: 4").WithArguments("d", "(long, long, long, long, long, long, long, long, long, int)").WithLocation(9, 61),
// (9,67): warning CS8123: The tuple element name 'e' is ignored because a different name is specified by the target type '(long, long, long, long, long, long, long, long, long, int)'.
// (x, x, x, x, x, x, x, x, x, y) = (a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10);
Diagnostic(ErrorCode.WRN_TupleLiteralNameMismatch, "e: 5").WithArguments("e").WithLocation(9, 67),
// (9,73): warning CS8123: The tuple element name 'f' is ignored because a different name is specified by the assignment target.
Diagnostic(ErrorCode.WRN_TupleLiteralNameMismatch, "e: 5").WithArguments("e", "(long, long, long, long, long, long, long, long, long, int)").WithLocation(9, 67),
// (9,73): warning CS8123: The tuple element name 'f' is ignored because a different name is specified by the target type '(long, long, long, long, long, long, long, long, long, int)'.
// (x, x, x, x, x, x, x, x, x, y) = (a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10);
Diagnostic(ErrorCode.WRN_TupleLiteralNameMismatch, "f: 6").WithArguments("f").WithLocation(9, 73),
// (9,79): warning CS8123: The tuple element name 'g' is ignored because a different name is specified by the assignment target.
Diagnostic(ErrorCode.WRN_TupleLiteralNameMismatch, "f: 6").WithArguments("f", "(long, long, long, long, long, long, long, long, long, int)").WithLocation(9, 73),
// (9,79): warning CS8123: The tuple element name 'g' is ignored because a different name is specified by the target type '(long, long, long, long, long, long, long, long, long, int)'.
// (x, x, x, x, x, x, x, x, x, y) = (a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10);
Diagnostic(ErrorCode.WRN_TupleLiteralNameMismatch, "g: 7").WithArguments("g").WithLocation(9, 79),
// (9,85): warning CS8123: The tuple element name 'h' is ignored because a different name is specified by the assignment target.
Diagnostic(ErrorCode.WRN_TupleLiteralNameMismatch, "g: 7").WithArguments("g", "(long, long, long, long, long, long, long, long, long, int)").WithLocation(9, 79),
// (9,85): warning CS8123: The tuple element name 'h' is ignored because a different name is specified by the target type '(long, long, long, long, long, long, long, long, long, int)'.
// (x, x, x, x, x, x, x, x, x, y) = (a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10);
Diagnostic(ErrorCode.WRN_TupleLiteralNameMismatch, "h: 8").WithArguments("h").WithLocation(9, 85),
// (9,91): warning CS8123: The tuple element name 'i' is ignored because a different name is specified by the assignment target.
Diagnostic(ErrorCode.WRN_TupleLiteralNameMismatch, "h: 8").WithArguments("h", "(long, long, long, long, long, long, long, long, long, int)").WithLocation(9, 85),
// (9,91): warning CS8123: The tuple element name 'i' is ignored because a different name is specified by the target type '(long, long, long, long, long, long, long, long, long, int)'.
// (x, x, x, x, x, x, x, x, x, y) = (a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10);
Diagnostic(ErrorCode.WRN_TupleLiteralNameMismatch, "i: 9").WithArguments("i").WithLocation(9, 91),
// (9,97): warning CS8123: The tuple element name 'j' is ignored because a different name is specified by the assignment target.
Diagnostic(ErrorCode.WRN_TupleLiteralNameMismatch, "i: 9").WithArguments("i", "(long, long, long, long, long, long, long, long, long, int)").WithLocation(9, 91),
// (9,97): warning CS8123: The tuple element name 'j' is ignored because a different name is specified by the target type '(long, long, long, long, long, long, long, long, long, int)'.
// (x, x, x, x, x, x, x, x, x, y) = (a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10);
Diagnostic(ErrorCode.WRN_TupleLiteralNameMismatch, "j: 10").WithArguments("j").WithLocation(9, 97)
Diagnostic(ErrorCode.WRN_TupleLiteralNameMismatch, "j: 10").WithArguments("j", "(long, long, long, long, long, long, long, long, long, int)").WithLocation(9, 97)
);
}
......
......@@ -762,6 +762,30 @@ static void Main()
);
}
[Fact]
public void NotAssignable()
{
string source = @"
class C
{
static void Main()
{
(1, P) = (1, 2);
}
static int P { get { return 1; } }
}
";
var comp = CreateCompilationWithMscorlib(source, references: s_valueTupleRefs);
comp.VerifyDiagnostics(
// (6,10): error CS0131: The left-hand side of an assignment must be a variable, property or indexer
// (1, P) = (1, 2);
Diagnostic(ErrorCode.ERR_AssgLvalueExpected, "1").WithLocation(6, 10),
// (6,13): error CS0200: Property or indexer 'C.P' cannot be assigned to -- it is read only
// (1, P) = (1, 2);
Diagnostic(ErrorCode.ERR_AssgReadonlyProp, "P").WithArguments("C.P").WithLocation(6, 13)
);
}
[Fact]
public void TupleWithUseSiteError()
{
......@@ -2332,5 +2356,26 @@ static void Test(int arg1, (byte, byte) arg2)
);
// no crash
}
[Fact]
public void DeclarationCannotBeEmbedded()
{
var source = @"
class C1
{
void M()
{
if (true)
var (x, y) = (1, 2);
}
}
";
var comp = CreateCompilationWithMscorlib(source, references: s_valueTupleRefs);
comp.VerifyDiagnostics(
// (7,13): error CS1023: Embedded statement cannot be a declaration or labeled statement
// var (x, y) = (1, 2);
Diagnostic(ErrorCode.ERR_BadEmbeddedStmt, "var (x, y) = (1, 2);").WithLocation(7, 13)
);
}
}
}
......@@ -8136,6 +8136,9 @@ static bool TakeOutParam(object y, out object x)
var compilation = CreateCompilationWithMscorlib45(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef },
options: TestOptions.DebugExe, parseOptions: TestOptions.Regular);
compilation.VerifyDiagnostics(
// (11,13): error CS1023: Embedded statement cannot be a declaration or labeled statement
// var (d, dd) = (TakeOutParam(true, out var x1), x1);
Diagnostic(ErrorCode.ERR_BadEmbeddedStmt, "var (d, dd) = (TakeOutParam(true, out var x1), x1);").WithLocation(11, 13),
// (13,9): error CS0103: The name 'x1' does not exist in the current context
// x1++;
Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(13, 9)
......
......@@ -7961,6 +7961,9 @@ void Test1()
var compilation = CreateCompilationWithMscorlib45(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef },
options: TestOptions.DebugExe, parseOptions: TestOptions.Regular);
compilation.VerifyDiagnostics(
// (11,13): error CS1023: Embedded statement cannot be a declaration or labeled statement
// var (d, dd) = ((true is var x1), x1);
Diagnostic(ErrorCode.ERR_BadEmbeddedStmt, "var (d, dd) = ((true is var x1), x1);").WithLocation(11, 13),
// (13,9): error CS0103: The name 'x1' does not exist in the current context
// x1++;
Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(13, 9)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册