|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable disable
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests
{
[CompilerTrait(CompilerFeature.LocalFunctions)]
public class LocalFunctions : FlowTestBase
{
[Fact]
[WorkItem(17829, "https://github.com/dotnet/roslyn/issues/17829")]
public void UncalledLambdaInLocalFunction()
{
var comp = CreateCompilation(@"
using System;
class C
{
void M()
{
void L()
{
Action a = () =>
{
int x;
x++;
};
}
}
}");
comp.VerifyDiagnostics(
// (12,17): error CS0165: Use of unassigned local variable 'x'
// x++;
Diagnostic(ErrorCode.ERR_UseDefViolation, "x").WithArguments("x").WithLocation(12, 17),
// (7,14): warning CS8321: The local function 'L' is declared but never used
// void L()
Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "L").WithArguments("L").WithLocation(7, 14));
}
[Fact]
[WorkItem(17829, "https://github.com/dotnet/roslyn/issues/17829")]
public void LambdaInNestedUncalledLocalFunctions()
{
var comp = CreateCompilation(@"
using System;
class C
{
void M()
{
void L1()
{
void L2()
{
Action a = () =>
{
int x;
x++;
};
}
L2();
}
}
}");
comp.VerifyDiagnostics(
// (14,21): error CS0165: Use of unassigned local variable 'x'
// x++;
Diagnostic(ErrorCode.ERR_UseDefViolation, "x").WithArguments("x").WithLocation(14, 21),
// (7,14): warning CS8321: The local function 'L1' is declared but never used
// void L1()
Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "L1").WithArguments("L1").WithLocation(7, 14));
}
[Fact]
[WorkItem(17829, "https://github.com/dotnet/roslyn/issues/17829")]
public void CapturedInLambdaInUncalledLocalFunction()
{
var comp = CreateCompilation(@"
using System;
class C
{
void M()
{
void L()
{
int x;
Action f = () => x++;
}
}
}");
comp.VerifyDiagnostics(
// (10,30): error CS0165: Use of unassigned local variable 'x'
// Action f = () => x++;
Diagnostic(ErrorCode.ERR_UseDefViolation, "x").WithArguments("x").WithLocation(10, 30),
// (7,14): warning CS8321: The local function 'L' is declared but never used
// void L()
Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "L").WithArguments("L").WithLocation(7, 14));
}
[Fact]
[WorkItem(17829, "https://github.com/dotnet/roslyn/issues/17829")]
public void CapturedInNestedUncalledLocalFunctions()
{
var comp = CreateCompilation(@"
class C
{
void M()
{
void L1()
{
int x;
void L2() => x++;
}
}
}");
comp.VerifyDiagnostics(
// (9,18): warning CS8321: The local function 'L2' is declared but never used
// void L2() => x++;
Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "L2").WithArguments("L2").WithLocation(9, 18),
// (6,14): warning CS8321: The local function 'L1' is declared but never used
// void L1()
Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "L1").WithArguments("L1").WithLocation(6, 14));
}
[Fact]
public void ConstUnassigned()
{
var comp = CreateCompilation(@"
class C
{
void M()
{
L();
int L()
{
int y = x + 1;
const int x = 0;
return y;
}
}
}");
comp.VerifyDiagnostics(
// (9,21): error CS0841: Cannot use local variable 'x' before it is declared
// int y = x + 1;
Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "x").WithArguments("x").WithLocation(9, 21));
}
[Fact]
public void ConstUnassigned2()
{
var comp = CreateCompilation(@"
class C
{
void M()
{
L();
int L() => x;
const int x = 0;
}
}");
comp.VerifyDiagnostics(
// (7,20): error CS0841: Cannot use local variable 'x' before it is declared
// int L() => x;
Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "x").WithArguments("x").WithLocation(7, 20));
}
[Fact]
public void ConstUnassigned3()
{
var comp = CreateCompilation(@"
class C
{
void M()
{
L();
const int x;
int L() => x;
}
}");
comp.VerifyDiagnostics(
// (7,19): error CS0145: A const field requires a value to be provided
// const int x;
Diagnostic(ErrorCode.ERR_ConstValueRequired, "x").WithLocation(7, 19));
}
[Fact]
[WorkItem(14243, "https://github.com/dotnet/roslyn/issues/14243")]
public void AssignInsideCallToLocalFunc()
{
var comp = CreateCompilation(@"
class C
{
public void M()
{
int x;
int Local(int p1) => x++;
Local(x = 0);
int z;
int Local2(int p1, int p2) => z++;
Local2(z = 0, z++);
}
public void M2()
{
int x;
int Local(int p1) => x++;
int Local2(int p1) => Local(p1);
int Local3(int p1) => x + Local2(p1);
Local3(x = 0);
}
}");
comp.VerifyDiagnostics();
}
[Fact]
[WorkItem(14046, "https://github.com/dotnet/roslyn/issues/14046")]
public void UnreachableAfterThrow()
{
var comp = CreateCompilation(@"
class C
{
public void M3()
{
int x, y;
void Local()
{
throw null;
x = 5; // unreachable code
System.Console.WriteLine(y);
}
Local();
System.Console.WriteLine(x);
System.Console.WriteLine(y);
}
}");
comp.VerifyDiagnostics(
// (10,7): warning CS0162: Unreachable code detected
// x = 5; // unreachable code
Diagnostic(ErrorCode.WRN_UnreachableCode, "x").WithLocation(10, 7));
}
[Fact]
[WorkItem(13739, "https://github.com/dotnet/roslyn/issues/13739")]
public void UnreachableRecursion()
{
var comp = CreateCompilation(@"
class C
{
public void M()
{
int x, y;
void Local()
{
Local();
x = 0;
}
Local();
x++;
y++;
}
}");
comp.VerifyDiagnostics();
}
[Fact]
public void ReadBeforeUnreachable()
{
var comp = CreateCompilation(@"
class C
{
public void M()
{
int x;
void Local()
{
x++;
Local();
}
Local();
x++;
}
}");
comp.VerifyDiagnostics(
// (12,9): error CS0165: Use of unassigned local variable 'x'
// Local();
Diagnostic(ErrorCode.ERR_UseDefViolation, "Local()").WithArguments("x").WithLocation(12, 9));
}
[Fact]
[WorkItem(13739, "https://github.com/dotnet/roslyn/issues/13739")]
public void MutualRecursiveUnreachable()
{
var comp = CreateCompilation(@"
class C
{
public static void M()
{
int x, y, z;
void L1()
{
L2();
x++; // Unreachable
}
void L2()
{
L1();
y++; // Unreachable
}
L1();
// Unreachable code, so everything should be definitely assigned
x++;
y++;
z++;
}
}");
comp.VerifyDiagnostics();
}
[Fact]
[WorkItem(13739, "https://github.com/dotnet/roslyn/issues/13739")]
public void AssignedInDeadBranch()
{
var comp = CreateCompilation(@"
using System;
class Program
{
public static void Main(string[] args)
{
int u;
M();
https://github.com/dotnet/roslyn/issues/13739
Console.WriteLine(u); // error: use of unassigned local variable 'u'
return;
void M()
{
goto La;
Lb: return;
La: u = 3;
goto Lb;
}
}
}");
comp.VerifyDiagnostics(
// (10,5): warning CS0164: This label has not been referenced
// https://github.com/dotnet/roslyn/issues/13739
Diagnostic(ErrorCode.WRN_UnreferencedLabel, "https").WithLocation(10, 5));
}
[Fact]
public void InvalidBranchOutOfLocalFunc()
{
var comp = CreateCompilation(@"
class C
{
public static void M()
{
label1:
L();
L2();
L3();
void L()
{
goto label1;
}
void L2()
{
break;
}
void L3()
{
continue;
}
}
}");
comp.VerifyDiagnostics(
// (19,13): error CS0139: No enclosing loop out of which to break or continue
// break;
Diagnostic(ErrorCode.ERR_NoBreakOrCont, "break;").WithLocation(19, 13),
// (24,13): error CS0139: No enclosing loop out of which to break or continue
// continue;
Diagnostic(ErrorCode.ERR_NoBreakOrCont, "continue;").WithLocation(24, 13),
// (14,13): error CS0159: No such label 'label1' within the scope of the goto statement
// goto label1;
Diagnostic(ErrorCode.ERR_LabelNotFound, "goto").WithArguments("label1").WithLocation(14, 13));
}
[Fact]
[WorkItem(13762, "https://github.com/dotnet/roslyn/issues/13762")]
public void AssignsInAsync()
{
var comp = CreateCompilationWithMscorlib46(@"
using System.Threading.Tasks;
class C
{
public static void M2()
{
int a=0, x, y, z;
L1();
a++;
x++;
y++;
z++;
async void L1()
{
x = 0;
await Task.Delay(0);
y = 0;
}
}
}");
comp.VerifyDiagnostics(
// (11,9): error CS0165: Use of unassigned local variable 'x'
// x++;
Diagnostic(ErrorCode.ERR_UseDefViolation, "x").WithArguments("x").WithLocation(11, 9),
// (12,9): error CS0165: Use of unassigned local variable 'y'
// y++;
Diagnostic(ErrorCode.ERR_UseDefViolation, "y").WithArguments("y").WithLocation(12, 9),
// (13,9): error CS0165: Use of unassigned local variable 'z'
// z++;
Diagnostic(ErrorCode.ERR_UseDefViolation, "z").WithArguments("z").WithLocation(13, 9));
}
[Fact]
[WorkItem(13762, "https://github.com/dotnet/roslyn/issues/13762")]
public void AssignsInIterator()
{
var comp = CreateCompilationWithMscorlib46(@"
using System.Collections.Generic;
class C
{
public static void M2()
{
int a=0, w, x, y, z;
L1();
a++;
w++;
x++;
y++;
z++;
IEnumerable<bool> L1()
{
w = 0;
yield return false;
x = 0;
yield break;
y = 0;
}
}
}");
comp.VerifyDiagnostics(
// (24,13): warning CS0162: Unreachable code detected
// y = 0;
Diagnostic(ErrorCode.WRN_UnreachableCode, "y").WithLocation(24, 13),
// (13,9): error CS0165: Use of unassigned local variable 'w'
// w++;
Diagnostic(ErrorCode.ERR_UseDefViolation, "w").WithArguments("w").WithLocation(13, 9),
// (14,9): error CS0165: Use of unassigned local variable 'x'
// x++;
Diagnostic(ErrorCode.ERR_UseDefViolation, "x").WithArguments("x").WithLocation(14, 9),
// (15,9): error CS0165: Use of unassigned local variable 'y'
// y++;
Diagnostic(ErrorCode.ERR_UseDefViolation, "y").WithArguments("y").WithLocation(15, 9),
// (16,9): error CS0165: Use of unassigned local variable 'z'
// z++;
Diagnostic(ErrorCode.ERR_UseDefViolation, "z").WithArguments("z").WithLocation(16, 9));
}
[Fact]
public void SimpleForwardCall()
{
var comp = CreateCompilation(@"
class C
{
public static void Main()
{
var x = Local();
int Local() => 2;
}
}");
comp.VerifyDiagnostics();
}
[Fact]
public void DefinedWhenCalled()
{
var comp = CreateCompilation(@"
class C
{
public static void Main()
{
int x;
bool Local() => x == 0;
x = 0;
Local();
}
}");
comp.VerifyDiagnostics();
}
[Fact]
public void NotDefinedWhenCalled()
{
var comp = CreateCompilation(@"
class C
{
public static void Main()
{
int x;
bool Local() => x == 0;
Local();
}
}");
comp.VerifyDiagnostics(
// (8,9): error CS0165: Use of unassigned local variable 'x'
// Local();
Diagnostic(ErrorCode.ERR_UseDefViolation, "Local()").WithArguments("x").WithLocation(8, 9)
);
}
[Fact]
public void ChainedDef()
{
var comp = CreateCompilation(@"
class C
{
public static void Main()
{
int x;
bool Local2() => Local1();
bool Local1() => x == 0;
Local2();
}
}");
comp.VerifyDiagnostics(
// (9,9): error CS0165: Use of unassigned local variable 'x'
// Local2();
Diagnostic(ErrorCode.ERR_UseDefViolation, "Local2()").WithArguments("x").WithLocation(9, 9)
);
}
[Fact]
public void SetInLocalFunc()
{
var comp = CreateCompilation(@"
class C
{
public static void Main()
{
int x;
void L1()
{
x = 0;
}
bool L2() => x == 0;
L1();
L2();
}
}
");
comp.VerifyDiagnostics();
}
[Fact]
public void SetInLocalFuncMutual()
{
var comp = CreateCompilation(@"
class C
{
public static void Main()
{
int x;
bool L1()
{
L2();
return x == 0;
}
void L2()
{
x = 0;
L1();
}
L1();
}
}
");
comp.VerifyDiagnostics();
}
[Fact]
public void LongWriteChain()
{
var comp = CreateCompilation(@"
class C
{
public void M()
{
int x;
bool L1()
{
L2();
return x == 0;
}
bool L2()
{
L3();
return x == 0;
}
bool L3()
{
L4();
return x == 0;
}
void L4()
{
x = 0;
}
L1();
}
}");
comp.VerifyDiagnostics();
}
[Fact]
public void ConvertBeforeDefined()
{
var comp = CreateCompilation(@"
class C
{
public static void Main()
{
int x;
bool L1() => x == 0;
System.Func<bool> f = L1;
x = 0;
f();
}
}");
comp.VerifyDiagnostics(
// (8,31): error CS0165: Use of unassigned local variable 'x'
// System.Func<bool> f = L1;
Diagnostic(ErrorCode.ERR_UseDefViolation, "L1").WithArguments("x").WithLocation(8, 31));
}
[Fact]
public void NestedCapture()
{
var comp = CreateCompilation(@"
class C
{
public static void Main()
{
void Local1()
{
int x;
bool Local2() => x == 0;
Local2();
}
Local1();
}
}");
comp.VerifyDiagnostics(
// (10,13): error CS0165: Use of unassigned local variable 'x'
// Local2();
Diagnostic(ErrorCode.ERR_UseDefViolation, "Local2()").WithArguments("x").WithLocation(10, 13));
}
[Fact]
public void UnusedLocalFunc()
{
var comp = CreateCompilation(@"
class C
{
public static void Main()
{
int x;
bool Local() => x == 0;
}
}");
comp.VerifyDiagnostics(
// (7,14): warning CS8321: The local function 'Local' is declared but never used
// bool Local() => x == 0;
Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "Local").WithArguments("Local").WithLocation(7, 14));
}
[Fact]
public void UnassignedInStruct()
{
var source = @"
struct S
{
int _x;
public S(int x)
{
var s = this;
void Local()
{
s._x = _x;
}
Local();
}
}";
var comp = CreateCompilation(source, parseOptions: TestOptions.Regular10);
comp.VerifyDiagnostics(
// (10,20): error CS1673: Anonymous methods, lambda expressions, query expressions, and local functions inside structs cannot access instance members of 'this'. Consider copying 'this' to a local variable outside the anonymous method, lambda expression, query expression, or local function and using the local instead.
// s._x = _x;
Diagnostic(ErrorCode.ERR_ThisStructNotInAnonMeth, "_x").WithLocation(10, 20),
// (7,17): error CS0188: The 'this' object cannot be used before all of its fields have been assigned. Consider updating to language version '11.0' to auto-default the unassigned fields.
// var s = this;
Diagnostic(ErrorCode.ERR_UseDefViolationThisUnsupportedVersion, "this").WithArguments("11.0").WithLocation(7, 17),
// (12,9): error CS9015: Use of possibly unassigned field '_x'. Consider updating to language version '11.0' to auto-default the field.
// Local();
Diagnostic(ErrorCode.ERR_UseDefViolationFieldUnsupportedVersion, "Local()").WithArguments("_x", "11.0").WithLocation(12, 9),
// (5,12): error CS0171: Field 'S._x' must be fully assigned before control is returned to the caller. Consider updating to language version '11.0' to auto-default the field.
// public S(int x)
Diagnostic(ErrorCode.ERR_UnassignedThisUnsupportedVersion, "S").WithArguments("S._x", "11.0").WithLocation(5, 12)
);
comp = CreateCompilation(source, parseOptions: TestOptions.Regular11);
comp.VerifyDiagnostics(
// (10,20): error CS1673: Anonymous methods, lambda expressions, query expressions, and local functions inside structs cannot access instance members of 'this'. Consider copying 'this' to a local variable outside the anonymous method, lambda expression, query expression, or local function and using the local instead.
// s._x = _x;
Diagnostic(ErrorCode.ERR_ThisStructNotInAnonMeth, "_x").WithLocation(10, 20));
}
[Fact]
public void AssignWithStruct()
{
var comp = CreateCompilation(@"
struct S
{
public int x;
public int y;
}
class C
{
public void M1()
{
S s1;
Local();
S s2 = s1; // unassigned
void Local()
{
s1.x = 0;
}
s1.y = 0;
}
public void M2()
{
S s1;
Local();
S s2 = s1; // success
void Local()
{
s1.x = 0;
s1.y = 0;
}
}
public void M3()
{
S s1;
S s2 = s1; // unassigned
Local();
void Local()
{
s1.x = 0;
s1.y = 0;
}
}
void M4()
{
S s1;
Local();
void Local()
{
s1.x = 0;
s1.x += s1.y;
}
}
}");
comp.VerifyDiagnostics(
// (14,16): error CS0165: Use of unassigned local variable 's1'
// S s2 = s1; // unassigned
Diagnostic(ErrorCode.ERR_UseDefViolation, "s1").WithArguments("s1").WithLocation(14, 16),
// (37,16): error CS0165: Use of unassigned local variable 's1'
// S s2 = s1; // unassigned
Diagnostic(ErrorCode.ERR_UseDefViolation, "s1").WithArguments("s1").WithLocation(37, 16),
// (48,9): error CS0170: Use of possibly unassigned field 'y'
// Local();
Diagnostic(ErrorCode.ERR_UseDefViolationField, "Local()").WithArguments("y").WithLocation(48, 9));
}
[Fact]
public void NestedStructProperty()
{
var comp = CreateCompilation(@"
struct A
{
public int x;
public int y { get; set; }
}
struct B
{
public A a;
public int z;
}
class C
{
void AssignInLocalFunc()
{
A a1;
Local1(); // unassigned
A a2 = a1;
void Local1()
{
a1.x = 0;
a1.y = 0;
}
B b1;
Local2();
B b2 = b1;
void Local2()
{
b1.a.x = 0;
b1.a.y = 0;
b1.z = 0;
}
}
void SkipNestedField()
{
B b1;
Local();
B b2 = b1; // unassigned
void Local()
{
b1.a.x = 0;
b1.z = 0;
}
}
void SkipNestedStruct()
{
B b1;
Local();
B b2 = b1; // unassigned
void Local()
{
b1.z = 0;
}
}
void SkipField()
{
B b1;
Local();
B b2 = b1; // unassigned
void Local()
{
b1.a.x = 0;
b1.a.y = 0;
}
}
}");
comp.VerifyDiagnostics(
// (19,9): error CS8079: Use of possibly unassigned auto-implemented property 'y'
// Local1(); // unassigned
Diagnostic(ErrorCode.ERR_UseDefViolationProperty, "Local1()").WithArguments("y").WithLocation(19, 9),
// (28,9): error CS8079: Use of possibly unassigned auto-implemented property 'y'
// Local2();
Diagnostic(ErrorCode.ERR_UseDefViolationProperty, "Local2()").WithArguments("y").WithLocation(28, 9),
// (41,16): error CS0165: Use of unassigned local variable 'b1'
// B b2 = b1; // unassigned
Diagnostic(ErrorCode.ERR_UseDefViolation, "b1").WithArguments("b1").WithLocation(41, 16),
// (52,16): error CS0165: Use of unassigned local variable 'b1'
// B b2 = b1; // unassigned
Diagnostic(ErrorCode.ERR_UseDefViolation, "b1").WithArguments("b1").WithLocation(52, 16),
// (61,9): error CS8079: Use of possibly unassigned auto-implemented property 'y'
// Local();
Diagnostic(ErrorCode.ERR_UseDefViolationProperty, "Local()").WithArguments("y").WithLocation(61, 9),
// (62,16): error CS0165: Use of unassigned local variable 'b1'
// B b2 = b1; // unassigned
Diagnostic(ErrorCode.ERR_UseDefViolation, "b1").WithArguments("b1").WithLocation(62, 16));
}
[Fact]
public void WriteAndReadInLocalFunc()
{
var comp = CreateCompilation(@"
class C
{
public void M()
{
int x;
bool b;
Local();
void Local()
{
x = x + 1;
x = 0;
}
b = x == 0;
}
}");
comp.VerifyDiagnostics(
// (8,9): error CS0165: Use of unassigned local variable 'x'
// Local();
Diagnostic(ErrorCode.ERR_UseDefViolation, "Local()").WithArguments("x").WithLocation(8, 9));
}
[Fact]
public void EventReadAndWrite()
{
var comp = CreateCompilation(@"
using System;
struct S
{
public int x;
public event EventHandler Event;
public void Fire() => Event(null, EventArgs.Empty);
}
class C
{
void PartialAssign()
{
S s1;
Local1();
S s2 = s1;
void Local1()
{
s1.x = 0;
}
}
void FullAssign()
{
S s1;
Local1();
S s2 = s1;
void Local1()
{
s1 = new S();
s1.x = 0;
s1.Event += Handler1;
s1.Fire();
void Handler1(object sender, EventArgs args)
{
s1.x++;
}
}
S s3;
void Local2()
{
s3.x = 0;
s3.Event += Handler2;
void Handler2(object sender, EventArgs args)
{
s1.x++;
s3.x++;
}
}
S s4 = s3;
Local2();
}
}");
comp.VerifyDiagnostics(
// (18,16): error CS0165: Use of unassigned local variable 's1'
// S s2 = s1;
Diagnostic(ErrorCode.ERR_UseDefViolation, "s1").WithArguments("s1").WithLocation(18, 16),
// (54,16): error CS0165: Use of unassigned local variable 's3'
// S s4 = s3;
Diagnostic(ErrorCode.ERR_UseDefViolation, "s3").WithArguments("s3").WithLocation(54, 16),
// (55,9): error CS0170: Use of possibly unassigned field 'Event'
// Local2();
Diagnostic(ErrorCode.ERR_UseDefViolationField, "Local2()").WithArguments("Event").WithLocation(55, 9));
}
[Fact]
public void CaptureForeachVar()
{
var comp = CreateCompilation(@"
class C
{
void M()
{
var items = new[] { 0, 1, 2, 3};
foreach (var i in items)
{
void Local()
{
i = 4;
}
Local();
}
}
}");
comp.VerifyDiagnostics(
// (11,17): error CS1656: Cannot assign to 'i' because it is a 'foreach iteration variable'
// i = 4;
Diagnostic(ErrorCode.ERR_AssgReadonlyLocalCause, "i").WithArguments("i", "foreach iteration variable").WithLocation(11, 17));
}
[Fact]
public void CapturePattern()
{
var comp = CreateCompilation(@"
class C
{
void M()
{
object o = 2;
if (o is int x1 && Local(x1) == 0)
{
}
if (o is int x2 || Local(x2) == 0)
{
}
if (!(o is int x3))
{
void Local2()
{
x3++;
}
Local2();
}
int Local(int i) => i;
}
}");
comp.VerifyDiagnostics(
// (11,34): error CS0165: Use of unassigned local variable 'x2'
// if (o is int x2 || Local(x2) == 0)
Diagnostic(ErrorCode.ERR_UseDefViolation, "x2").WithArguments("x2").WithLocation(11, 34),
// (21,13): error CS0165: Use of unassigned local variable 'x3'
// Local2();
Diagnostic(ErrorCode.ERR_UseDefViolation, "Local2()").WithArguments("x3").WithLocation(21, 13));
}
[Fact]
public void NotAssignedControlFlow()
{
var comp = CreateCompilation(@"
class C
{
void FullyAssigned()
{
int x;
int y = 0;
void Local()
{
if (y == 0)
x = 0;
else
Local2();
}
void Local2()
{
x = 0;
}
Local();
y = x;
}
void PartiallyAssigned()
{
int x;
int y = 0;
void Local()
{
if (y == 0)
x = 0;
else
Local2();
}
void Local2()
{
//x = 0;
}
Local();
y = x; // unassigned
}
}");
comp.VerifyDiagnostics(
// (38,13): error CS0165: Use of unassigned local variable 'x'
// y = x; // unassigned
Diagnostic(ErrorCode.ERR_UseDefViolation, "x").WithArguments("x").WithLocation(38, 13));
}
[Fact]
public void UseConsts()
{
var comp = CreateCompilation(@"
struct S
{
public const int z = 0;
}
class C
{
const int x = 0;
void M()
{
const int y = 0;
Local();
int Local()
{
const int a = 1;
return a + x + y + S.z;
}
}
}");
comp.VerifyDiagnostics();
}
[Fact]
public void NotAssignedAtAllReturns()
{
var comp = CreateCompilation(@"
class C
{
void M()
{
int x;
void L1()
{
if ("""".Length == 1)
{
x = 1;
}
else
{
return;
}
}
L1();
var z = x;
}
}");
comp.VerifyDiagnostics(
// (19,17): error CS0165: Use of unassigned local variable 'x'
// var z = x;
Diagnostic(ErrorCode.ERR_UseDefViolation, "x").WithArguments("x").WithLocation(19, 17));
}
[Fact]
public void NotAssignedAtThrow()
{
var comp = CreateCompilation(@"
class C
{
void M()
{
int x1, x2;
void L1()
{
if ("""".Length == 1)
x1 = x2 = 0;
else
throw new System.Exception();
}
try
{
L1();
var y = x1;
}
catch
{
var z = x1;
}
var zz = x2;
}
}");
comp.VerifyDiagnostics(
// (21,21): error CS0165: Use of unassigned local variable 'x1'
// var z = x1;
Diagnostic(ErrorCode.ERR_UseDefViolation, "x1").WithArguments("x1").WithLocation(21, 21),
// (23,18): error CS0165: Use of unassigned local variable 'x2'
// var zz = x2;
Diagnostic(ErrorCode.ERR_UseDefViolation, "x2").WithArguments("x2").WithLocation(23, 18));
}
[Fact]
public void DeadCode()
{
var comp = CreateCompilation(@"
class C
{
void M()
{
int x;
goto live;
void L1() => x = 0;
live:
L1();
var z = x;
}
void M2()
{
int x;
goto live;
void L1()
{
if ("""".Length == 1)
x = 0;
else
return;
}
live:
L1();
var z = x;
}
}");
comp.VerifyDiagnostics(
// (26,17): error CS0165: Use of unassigned local variable 'x'
// var z = x;
Diagnostic(ErrorCode.ERR_UseDefViolation, "x").WithArguments("x").WithLocation(26, 17));
}
[Fact]
public void LocalFunctionFromOtherSwitch()
{
var comp = CreateCompilation(@"
class C
{
void M()
{
int x;
int y;
switch("""".Length)
{
case 0:
void L1()
{
y = 0;
L2();
}
break;
case 1:
L1();
y = x;
break;
case 2:
void L2()
{
x = y;
}
break;
}
}
}");
comp.VerifyDiagnostics();
}
[Fact]
[WorkItem(15298, "https://github.com/dotnet/roslyn/issues/15298")]
public void UnassignedUndefinedVariable()
{
var comp = CreateCompilation(@"
class C
{
void M()
{
{
Goo();
int x = 0;
void Goo() => x++;
}
{
System.Action a = Goo;
int x = 0;
void Goo() => x++;
}
}
}");
comp.VerifyDiagnostics(
// (7,13): error CS0165: Use of unassigned local variable 'x'
// Goo();
Diagnostic(ErrorCode.ERR_UseDefViolation, "Goo()").WithArguments("x").WithLocation(7, 13),
// (12,31): error CS0165: Use of unassigned local variable 'x'
// System.Action a = Goo;
Diagnostic(ErrorCode.ERR_UseDefViolation, "Goo").WithArguments("x").WithLocation(12, 31));
}
[Fact]
[WorkItem(15322, "https://github.com/dotnet/roslyn/issues/15322")]
public void UseBeforeDeclarationInSwitch()
{
var comp = CreateCompilation(@"
class Program
{
static void Main(object[] args)
{
switch(args[0])
{
case string x:
Goo();
break;
case int x:
void Goo() => System.Console.WriteLine(x);
break;
}
}
}");
comp.VerifyDiagnostics(
// (9,17): error CS0165: Use of unassigned local variable 'x'
// Goo();
Diagnostic(ErrorCode.ERR_UseDefViolation, "Goo()").WithArguments("x").WithLocation(9, 17));
}
[Fact]
[WorkItem(14097, "https://github.com/dotnet/roslyn/issues/14097")]
public void PiecewiseStructAssign()
{
var comp = CreateCompilation(@"
struct S { public int X, Y; }
class C
{
public static void Main()
{
S s;
s.X = 5;
void Local()
{
s.Y = 10;
System.Console.WriteLine(s);
}
Local();
}
}");
comp.VerifyDiagnostics();
}
[Fact]
[WorkItem(14097, "https://github.com/dotnet/roslyn/issues/14097")]
public void PiecewiseStructAssign2()
{
var comp = CreateCompilation(@"
struct S
{
public int X;
public int Y { get; set; }
public S(int x, int y)
{
this.X = x;
this.Y = y;
Local(this);
void Local(S s)
{
s.X++;
s.Y++;
}
}
}");
comp.VerifyDiagnostics();
}
[Fact]
[WorkItem(14097, "https://github.com/dotnet/roslyn/issues/14097")]
public void PiecewiseStructAssign3()
{
var comp = CreateCompilation(@"
struct S { }
struct S2
{
public int x;
public S s;
}
class C
{
public void M()
{
S2 s2;
void Local1()
{
s2.x = 0;
S2 s4 = s2;
}
Local1();
S2 s3 = s2;
}
public void M2()
{
S2 s3;
void Local2()
{
s3.s = new S();
S2 s4 = s3;
}
Local2();
}
public void M3()
{
S2 s5;
void Local3()
{
s5.s = new S();
}
Local3();
S2 s6 = s5;
}
}");
comp.VerifyDiagnostics(
// (30,9): error CS0170: Use of possibly unassigned field 'x'
// Local2();
Diagnostic(ErrorCode.ERR_UseDefViolationField, "Local2()").WithArguments("x").WithLocation(30, 9),
// (41,17): error CS0165: Use of unassigned local variable 's5'
// S2 s6 = s5;
Diagnostic(ErrorCode.ERR_UseDefViolation, "s5").WithArguments("s5").WithLocation(41, 17));
}
[Fact]
[WorkItem(14097, "https://github.com/dotnet/roslyn/issues/14097")]
public void PiecewiseStructAssignmentInConstructor()
{
var comp = CreateCompilation(@"
struct S
{
public int _x;
public int _y;
public S(int x, int y)
{
_y = 0;
void Local()
{
_x = 0;
S s2 = this;
}
Local();
}
}");
// Note that definite assignment is still validated in this
// compilation
comp.VerifyDiagnostics(
// (12,13): error CS1673: Anonymous methods, lambda expressions, query expressions, and local functions inside structs cannot access instance members of 'this'. Consider copying 'this' to a local variable outside the anonymous method, lambda expression, query expression, or local function and using the local instead.
// _x = 0;
Diagnostic(ErrorCode.ERR_ThisStructNotInAnonMeth, "_x").WithLocation(12, 13),
// (13,20): error CS1673: Anonymous methods, lambda expressions, query expressions, and local functions inside structs cannot access instance members of 'this'. Consider copying 'this' to a local variable outside the anonymous method, lambda expression, query expression, or local function and using the local instead.
// S s2 = this;
Diagnostic(ErrorCode.ERR_ThisStructNotInAnonMeth, "this").WithLocation(13, 20));
}
[Fact]
[WorkItem(14097, "https://github.com/dotnet/roslyn/issues/14097")]
public void PiecewiseStructAssignmentInConstructor2()
{
var source = @"
struct S
{
public int _x;
public int _y;
public S(int x, int y)
{
_y = 0;
void Local()
{
S s2 = this;
}
Local();
_x = 0;
}
}";
var comp = CreateCompilation(source, parseOptions: TestOptions.Regular10);
comp.VerifyDiagnostics(
// (12,20): error CS1673: Anonymous methods, lambda expressions, query expressions, and local functions inside structs cannot access instance members of 'this'. Consider copying 'this' to a local variable outside the anonymous method, lambda expression, query expression, or local function and using the local instead.
// S s2 = this;
Diagnostic(ErrorCode.ERR_ThisStructNotInAnonMeth, "this").WithLocation(12, 20),
// (14,9): error CS9015: Use of possibly unassigned field '_x'. Consider updating to language version '11.0' to auto-default the field.
// Local();
Diagnostic(ErrorCode.ERR_UseDefViolationFieldUnsupportedVersion, "Local()").WithArguments("_x", "11.0").WithLocation(14, 9)
);
comp = CreateCompilation(source, parseOptions: TestOptions.Regular11);
comp.VerifyDiagnostics(
// (12,20): error CS1673: Anonymous methods, lambda expressions, query expressions, and local functions inside structs cannot access instance members of 'this'. Consider copying 'this' to a local variable outside the anonymous method, lambda expression, query expression, or local function and using the local instead.
// S s2 = this;
Diagnostic(ErrorCode.ERR_ThisStructNotInAnonMeth, "this").WithLocation(12, 20));
}
[Fact]
[WorkItem(18813, "https://github.com/dotnet/roslyn/issues/18813")]
public void LocalIEnumerableFunctionWithOutParameter1()
{
var comp = CreateCompilation(@"
class @c
{
static void Main(string[] args)
{
System.Collections.Generic.IEnumerable<string> getGoo(int count, out bool output)
{
output = true;
yield return ""goo"";
}
getGoo(1, out bool myBool);
}
}");
comp.VerifyDiagnostics(
// (6,83): error CS1623: Iterators cannot have ref, in or out parameters
// System.Collections.Generic.IEnumerable<string> getGoo(int count, out bool goobar)
Diagnostic(ErrorCode.ERR_BadIteratorArgType, "output"),
// (6,56): error CS0177: The out parameter 'goobar' must be assigned to before control leaves the current method
// System.Collections.Generic.IEnumerable<string> getGoo(int count, out bool goobar)
Diagnostic(ErrorCode.ERR_ParamUnassigned, "getGoo").WithArguments("output").WithLocation(6, 56));
}
[Fact]
[WorkItem(18813, "https://github.com/dotnet/roslyn/issues/18813")]
public void LocalIEnumerableFunctionWithOutParameter2()
{
var comp = CreateCompilation(@"
class @c
{
static void Main(string[] args)
{
System.Collections.Generic.IEnumerable<string> getGoo(int count, out bool output)
{
output = false;
for (int i = 0; i < count; i++)
{
foreach (var val in getGoo(3, out var bar))
yield return ""goo"";
}
yield return ""goo"";
}
getGoo(1, out bool myBool);
}
}");
comp.VerifyDiagnostics(
// (6,83): error CS1623: Iterators cannot have ref, in or out parameters
// System.Collections.Generic.IEnumerable<string> getGoo(int count, out bool goobar)
Diagnostic(ErrorCode.ERR_BadIteratorArgType, "output"),
// (6,56): error CS0177: The out parameter 'goobar' must be assigned to before control leaves the current method
// System.Collections.Generic.IEnumerable<string> getGoo(int count, out bool goobar)
Diagnostic(ErrorCode.ERR_ParamUnassigned, "getGoo").WithArguments("output").WithLocation(6, 56));
}
[Fact]
[WorkItem(41631, "https://github.com/dotnet/roslyn/issues/41631")]
public void UseOfCapturedVariableAssignedByOutParameter()
{
CreateCompilation(@"
public class C
{
void M()
{
string s0;
local1(out s0); // 1
void local1(out string s1)
{
s0.ToString();
s1 = ""hello"";
}
}
}").VerifyDiagnostics(
// (7,9): error CS0165: Use of unassigned local variable 's0'
// local1(out s0);
Diagnostic(ErrorCode.ERR_UseDefViolation, "local1(out s0)").WithArguments("s0").WithLocation(7, 9));
}
[Fact]
public void OutParameterIsAssignedByLocalFunction()
{
CreateCompilation(@"
public class C
{
void M()
{
string s0;
local1(out s0);
s0.ToString();
void local1(out string s1)
{
s1 = ""hello"";
}
}
}").VerifyDiagnostics();
}
[Fact]
public void UseOfCapturedVariableAssignedInArgument()
{
CreateCompilation(@"
public class C
{
void M()
{
string s0;
local1(s0 = ""hello"", out s0);
void local1(string s1, out string s2)
{
s0.ToString();
s2 = ""bye"";
}
}
}").VerifyDiagnostics();
}
}
}
|