提交 2803523c 编写于 作者: J Julien Couvreur 提交者: GitHub

Assigning tuple should not be considered use of variable (#15026)

上级 47409fb4
...@@ -613,6 +613,8 @@ internal static bool WriteConsideredUse(TypeSymbol type, BoundExpression value) ...@@ -613,6 +613,8 @@ internal static bool WriteConsideredUse(TypeSymbol type, BoundExpression value)
case BoundKind.ObjectCreationExpression: case BoundKind.ObjectCreationExpression:
var init = (BoundObjectCreationExpression)value; var init = (BoundObjectCreationExpression)value;
return !init.Constructor.IsImplicitlyDeclared || init.InitializerExpressionOpt != null; return !init.Constructor.IsImplicitlyDeclared || init.InitializerExpressionOpt != null;
case BoundKind.ConvertedTupleLiteral:
return false;
default: default:
return true; return true;
} }
......
...@@ -2733,7 +2733,10 @@ static void Main() ...@@ -2733,7 +2733,10 @@ static void Main()
Diagnostic(ErrorCode.ERR_PredefinedValueTupleTypeNotFound, "(int, string)").WithArguments("System.ValueTuple`2").WithLocation(6, 9), Diagnostic(ErrorCode.ERR_PredefinedValueTupleTypeNotFound, "(int, string)").WithArguments("System.ValueTuple`2").WithLocation(6, 9),
// (6,27): error CS8179: Predefined type 'System.ValueTuple`2' is not defined or imported // (6,27): error CS8179: Predefined type 'System.ValueTuple`2' is not defined or imported
// (int, string) x = (1, "hello"); // (int, string) x = (1, "hello");
Diagnostic(ErrorCode.ERR_PredefinedValueTupleTypeNotFound, @"(1, ""hello"")").WithArguments("System.ValueTuple`2").WithLocation(6, 27) Diagnostic(ErrorCode.ERR_PredefinedValueTupleTypeNotFound, @"(1, ""hello"")").WithArguments("System.ValueTuple`2").WithLocation(6, 27),
// (6,23): warning CS0219: The variable 'x' is assigned but its value is never used
// (int, string) x = (1, "hello");
Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "x").WithArguments("x").WithLocation(6, 23)
); );
} }
...@@ -2756,10 +2759,13 @@ static void Main() ...@@ -2756,10 +2759,13 @@ static void Main()
"; ";
var comp = CreateCompilationWithMscorlib(source, assemblyName: "comp"); var comp = CreateCompilationWithMscorlib(source, assemblyName: "comp");
comp.VerifyEmitDiagnostics( comp.VerifyEmitDiagnostics(
// (11,20): warning CS0219: The variable 'x' is assigned but its value is never used
// (int, int) x = (1, 2);
Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "x").WithArguments("x").WithLocation(11, 20),
// (11,24): error CS8128: Member '.ctor' was not found on type 'ValueTuple<T1, T2>' from assembly 'comp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. // (11,24): error CS8128: Member '.ctor' was not found on type 'ValueTuple<T1, T2>' from assembly 'comp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
// (int, int) x = (1, 2); // (int, int) x = (1, 2);
Diagnostic(ErrorCode.ERR_PredefinedTypeMemberNotFoundInAssembly, "(1, 2)").WithArguments(".ctor", "System.ValueTuple<T1, T2>", "comp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(11, 24) Diagnostic(ErrorCode.ERR_PredefinedTypeMemberNotFoundInAssembly, "(1, 2)").WithArguments(".ctor", "System.ValueTuple<T1, T2>", "comp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(11, 24)
); );
} }
[Fact] [Fact]
...@@ -3443,6 +3449,7 @@ class C ...@@ -3443,6 +3449,7 @@ class C
static void Main() static void Main()
{ {
var x = (a: PrintAndReturn(1), b: 2, c: 3, d: PrintAndReturn(4), e: 5, f: 6, g: PrintAndReturn(7), h: PrintAndReturn(""Alice""), i: 2, j: 3, k: 4, l: 5, m: 6, n: PrintAndReturn(7), o: PrintAndReturn(""Bob""), p: 2, q: PrintAndReturn(3)); var x = (a: PrintAndReturn(1), b: 2, c: 3, d: PrintAndReturn(4), e: 5, f: 6, g: PrintAndReturn(7), h: PrintAndReturn(""Alice""), i: 2, j: 3, k: 4, l: 5, m: 6, n: PrintAndReturn(7), o: PrintAndReturn(""Bob""), p: 2, q: PrintAndReturn(3));
x.ToString();
} }
static T PrintAndReturn<T>(T i) static T PrintAndReturn<T>(T i)
...@@ -5493,7 +5500,10 @@ static void Main() ...@@ -5493,7 +5500,10 @@ static void Main()
Diagnostic(ErrorCode.ERR_NoImplicitConvCast, @"((long, string))(1, ""hello"")").WithArguments("(long, string)", "(short, string)").WithLocation(10, 30), Diagnostic(ErrorCode.ERR_NoImplicitConvCast, @"((long, string))(1, ""hello"")").WithArguments("(long, string)", "(short, string)").WithLocation(10, 30),
// (13,34): error CS0266: Cannot implicitly convert type '(long c, string d)' to '(short a, string b)'. An explicit conversion exists (are you missing a cast?) // (13,34): error CS0266: Cannot implicitly convert type '(long c, string d)' to '(short a, string b)'. An explicit conversion exists (are you missing a cast?)
// (short a, string b) x3 = ((long c, string d))(1, "hello"); // (short a, string b) x3 = ((long c, string d))(1, "hello");
Diagnostic(ErrorCode.ERR_NoImplicitConvCast, @"((long c, string d))(1, ""hello"")").WithArguments("(long c, string d)", "(short a, string b)").WithLocation(13, 34) Diagnostic(ErrorCode.ERR_NoImplicitConvCast, @"((long c, string d))(1, ""hello"")").WithArguments("(long c, string d)", "(short a, string b)").WithLocation(13, 34),
// (7,25): warning CS0219: The variable 'x1' is assigned but its value is never used
// (short, string) x1 = (1, "hello");
Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "x1").WithArguments("x1").WithLocation(7, 25)
); );
} }
...@@ -16272,7 +16282,13 @@ public void M() ...@@ -16272,7 +16282,13 @@ public void M()
Diagnostic(ErrorCode.WRN_TupleLiteralNameMismatch, "b: 2").WithArguments("b", "(int a, int)").WithLocation(6, 31), Diagnostic(ErrorCode.WRN_TupleLiteralNameMismatch, "b: 2").WithArguments("b", "(int a, int)").WithLocation(6, 31),
// (7,34): warning CS8123: The tuple element name 'b' is ignored because a different name is specified by the target type '(int a, string)'. // (7,34): warning CS8123: The tuple element name 'b' is ignored because a different name is specified by the target type '(int a, string)'.
// (int a, string) x2 = (1, b: null); // (int a, string) x2 = (1, b: null);
Diagnostic(ErrorCode.WRN_TupleLiteralNameMismatch, "b: null").WithArguments("b", "(int a, string)").WithLocation(7, 34) Diagnostic(ErrorCode.WRN_TupleLiteralNameMismatch, "b: null").WithArguments("b", "(int a, string)").WithLocation(7, 34),
// (6,22): warning CS0219: The variable 'x1' is assigned but its value is never used
// (int a, int) x1 = (1, b: 2);
Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "x1").WithArguments("x1").WithLocation(6, 22),
// (7,25): warning CS0219: The variable 'x2' is assigned but its value is never used
// (int a, string) x2 = (1, b: null);
Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "x2").WithArguments("x2").WithLocation(7, 25)
); );
} }
...@@ -18567,6 +18583,7 @@ void M() ...@@ -18567,6 +18583,7 @@ void M()
var x10 = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10); var x10 = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
D.M2((1, 2)); D.M2((1, 2));
D.M3((1, null)); D.M3((1, null));
System.Console.Write($""{x1} {x2} {x9} {x10}"");
} }
} }
"; ";
...@@ -18615,6 +18632,7 @@ public class C ...@@ -18615,6 +18632,7 @@ public class C
void M() void M()
{ {
var x9 = (1, 2, 3, 4, 5, 6, 7, 8, 9); var x9 = (1, 2, 3, 4, 5, 6, 7, 8, 9);
System.Console.Write(x9);
} }
} }
namespace System namespace System
...@@ -20011,5 +20029,113 @@ public void M() ...@@ -20011,5 +20029,113 @@ public void M()
// no assertion // no assertion
} }
[Fact]
public void UnusedTuple()
{
string source = @"
public class C
{
void M(int x)
{
// Warnings
int[] array = new int[] { 42 };
unsafe
{
fixed (int* p = &array[0])
{
(int*, int*) t1 = (p, p); // converted tuple literal with a pointer type
(string, int*) t2 = (null, p); // implicit tuple literal conversion on a converted tuple literal with a pointer type
(string, (int*, int*)) t3 = (null, (p, p));
}
}
(int, int) t4 = default((int, int));
(int, int) t5 = (1, 2);
(string, string) t6 = (null, null);
(string, string) t7 = (""hello"", ""world"");
(S, (S, S)) t8 = (new S(), (new S(), new S()));
(int, int) t9 = ((C, int))(new C(), 2); // implicit tuple conversion with a user conversion on an element
(int, int) t10 = (new C(), 2); // implicit tuple literal conversion with a user conversion on an element
(int, int) t11 = ((int, int))(((C, int))(new C(), 2)); // explicit tuple conversion with a user conversion on an element
(C, C) t12 = (new C(), new C());
(C, (C, C)) t13 = (new C(), (new C(), new C()));
(S, (S, S)) t14 = (new S(), (new S() { /* object initializer */ }, new S()));
// No warnings
(C, int) tuple = (new C(), 2);
(int, int) t20 = ((C, int))tuple;
(int, int) t21 = tuple;
(int, int) t22 = ((int, int))tuple;
C c1 = (1, 2);
(int, int) intTuple = (1, 2);
C c2 = intTuple;
int i1 = 1;
int i2 = i1;
}
public static implicit operator int(C c)
{
return 0;
}
public static implicit operator C((int, int) t)
{
return new C();
}
}
public struct S { }
";
var comp = CreateCompilationWithMscorlib45AndCSruntime(source, additionalRefs: s_valueTupleRefs, options: TestOptions.UnsafeDebugDll);
comp.VerifyDiagnostics(
// (13,30): warning CS0219: The variable 't1' is assigned but its value is never used
// (int*, int*) t1 = (p, p); // converted tuple literal with a pointer type
Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "t1").WithArguments("t1").WithLocation(13, 30),
// (14,32): warning CS0219: The variable 't2' is assigned but its value is never used
// (string, int*) t2 = (null, p); // implicit tuple literal conversion on a converted tuple literal with a pointer type
Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "t2").WithArguments("t2").WithLocation(14, 32),
// (15,40): warning CS0219: The variable 't3' is assigned but its value is never used
// (string, (int*, int*)) t3 = (null, (p, p));
Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "t3").WithArguments("t3").WithLocation(15, 40),
// (19,20): warning CS0219: The variable 't4' is assigned but its value is never used
// (int, int) t4 = default((int, int));
Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "t4").WithArguments("t4").WithLocation(19, 20),
// (20,20): warning CS0219: The variable 't5' is assigned but its value is never used
// (int, int) t5 = (1, 2);
Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "t5").WithArguments("t5").WithLocation(20, 20),
// (22,26): warning CS0219: The variable 't6' is assigned but its value is never used
// (string, string) t6 = (null, null);
Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "t6").WithArguments("t6").WithLocation(22, 26),
// (23,26): warning CS0219: The variable 't7' is assigned but its value is never used
// (string, string) t7 = ("hello", "world");
Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "t7").WithArguments("t7").WithLocation(23, 26),
// (24,21): warning CS0219: The variable 't8' is assigned but its value is never used
// (S, (S, S)) t8 = (new S(), (new S(), new S()));
Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "t8").WithArguments("t8").WithLocation(24, 21),
// (26,20): warning CS0219: The variable 't9' is assigned but its value is never used
// (int, int) t9 = ((C, int))(new C(), 2); // implicit tuple conversion with a user conversion on an element
Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "t9").WithArguments("t9").WithLocation(26, 20),
// (27,20): warning CS0219: The variable 't10' is assigned but its value is never used
// (int, int) t10 = (new C(), 2); // implicit tuple literal conversion with a user conversion on an element
Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "t10").WithArguments("t10").WithLocation(27, 20),
// (28,20): warning CS0219: The variable 't11' is assigned but its value is never used
// (int, int) t11 = ((int, int))(((C, int))(new C(), 2)); // explicit tuple conversion with a user conversion on an element
Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "t11").WithArguments("t11").WithLocation(28, 20),
// (30,16): warning CS0219: The variable 't12' is assigned but its value is never used
// (C, C) t12 = (new C(), new C());
Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "t12").WithArguments("t12").WithLocation(30, 16),
// (31,21): warning CS0219: The variable 't13' is assigned but its value is never used
// (C, (C, C)) t13 = (new C(), (new C(), new C()));
Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "t13").WithArguments("t13").WithLocation(31, 21),
// (32,21): warning CS0219: The variable 't14' is assigned but its value is never used
// (S, (S, S)) t14 = (new S(), (new S() { /* object initializer */ }, new S()));
Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "t14").WithArguments("t14").WithLocation(32, 21)
);
}
} }
} }
\ No newline at end of file
...@@ -2358,6 +2358,7 @@ static void Main() ...@@ -2358,6 +2358,7 @@ static void Main()
{ {
var x1 = (1, 2); var x1 = (1, 2);
var (x2, x3) = (1, 2); var (x2, x3) = (1, 2);
System.Console.Write($""{x1} {x2} {x3}"");
} }
} }
"; ";
......
...@@ -17823,6 +17823,58 @@ val: -2 ...@@ -17823,6 +17823,58 @@ val: -2
]]>) ]]>)
End Sub End Sub
<Fact>
Public Sub UnusedTuple()
Dim comp = CreateCompilationWithMscorlibAndVBRuntime(
<compilation>
<file name="a.vb"><![CDATA[
Imports System
Class C
Sub M()
' Warnings
Dim x2 As Integer
Const x3 As Integer = 1
Const x4 As String = "hello"
Dim x5 As (Integer, Integer)
Dim x6 As (String, String)
' No warnings
Dim y10 As Integer = 1
Dim y11 As String = "hello"
Dim y12 As (Integer, Integer) = (1, 2)
Dim y13 As (String, String) = ("hello", "world")
Dim tuple As (String, String) = ("hello", "world")
Dim y14 As (String, String) = tuple
End Sub
End Class
]]></file>
</compilation>, additionalRefs:=s_valueTupleRefs)
comp.AssertTheseDiagnostics(
<errors>
BC42024: Unused local variable: 'x2'.
Dim x2 As Integer
~~
BC42099: Unused local constant: 'x3'.
Const x3 As Integer = 1
~~
BC42099: Unused local constant: 'x4'.
Const x4 As String = "hello"
~~
BC42024: Unused local variable: 'x5'.
Dim x5 As (Integer, Integer)
~~
BC42024: Unused local variable: 'x6'.
Dim x6 As (String, String)
~~
</errors>)
End Sub
End Class End Class
End Namespace End Namespace
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册