/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/CSharp/Test/Semantic/Semantics/SemanticAnalyzerTests.cs
1 541 строка
78 KB
AlekseyTs
Emit 'Extension' attribute on a type with an extension declaration. (#77573)
13 мар 2025, 22:27
Не верифицирован
13 мар 2025, 22:27
caef526
Код
Авторство
О чём код?
// 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.Symbols; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.Text; using Roslyn.Test.Utilities; using Xunit; namespace Microsoft.CodeAnalysis.CSharp.UnitTests { public partial class SemanticAnalyzerTests : CompilingTestBase { [Fact] public void TestMethodGroupConversionError() { string source = @" using System; using System.Linq.Expressions; class C { static void Main() { Action a = Main; Expression<Action> e = Main; } } "; CreateCompilationWithMscorlib40AndSystemCore(source) .VerifyDiagnostics( // (9,32): error CS0428: Cannot convert method group 'Main' to non-delegate type 'System.Linq.Expressions.Expression<System.Action>'. Did you intend to invoke the method? // Expression<Action> e = Main; Diagnostic(ErrorCode.ERR_MethGrpToNonDel, "Main").WithArguments("Main", "System.Linq.Expressions.Expression<System.Action>") ); } [Fact, WorkItem(546737, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546737")] public void TestBug16693() { // We should treat I.Equals as hiding object.Equals, as noted in section 7.4.1 // of the specification. (That is, for the purposes of determining hiding, // object is considered to be a base type of the interface type.) string source = @" public interface I { bool Equals { get; } } class C { bool M(I i) { return i.Equals; } } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics(); } [Fact, WorkItem(546716, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546716")] public void TestBug16639() { // The bug here was that the warning was reported for the first case -- the conversion // to D -- but not for the second case -- the use of the anonymous function as the ctor argument. string source = @" class Program { delegate void D(); class C {} static void Main() { var o1 = (D)(delegate{ var s = default(C).ToString();}); var o2 = new D(delegate{ var s = default(C).ToString();}); } } "; CreateCompilation(source, parseOptions: TestOptions.Regular7_3).VerifyDiagnostics( // (8,40): warning CS1720: Expression will always cause a System.NullReferenceException because the default value of 'Program.C' is null // var o1 = (D)(delegate{ var s = default(C).ToString();}); Diagnostic(ErrorCode.WRN_DotOnDefault, "default(C).ToString").WithArguments("Program.C"), // (9,42): warning CS1720: Expression will always cause a System.NullReferenceException because the default value of 'Program.C' is null // var o2 = new D(delegate{ var s = default(C).ToString();}); Diagnostic(ErrorCode.WRN_DotOnDefault, "default(C).ToString").WithArguments("Program.C")); CreateCompilation(source).VerifyDiagnostics(); } [Fact] public void TestParenthesisErrors() { string source = @" namespace N { class D { public static int x; } } class C { static int x; void M() { int y = (N).D.x; int z = (N.D).x; } } "; CreateCompilation(source).VerifyDiagnostics( // (8,18): error CS0118: 'N' is a namespace but is used like a variable // int y = (N).D.x; Diagnostic(ErrorCode.ERR_BadSKknown, "N").WithArguments("N", "namespace", "variable").WithLocation(8, 18), // (9,18): error CS0119: 'D' is a type, which is not valid in the given context // int z = (N.D).x; Diagnostic(ErrorCode.ERR_BadSKunknown, "N.D").WithArguments("N.D", "type").WithLocation(9, 18), // (5,16): warning CS0169: The field 'C.x' is never used // static int x; Diagnostic(ErrorCode.WRN_UnreferencedField, "x").WithArguments("C.x").WithLocation(5, 16), // (2,43): warning CS0649: Field 'D.x' is never assigned to, and will always have its default value 0 // namespace N { class D { public static int x; } } Diagnostic(ErrorCode.WRN_UnassignedInternalField, "x").WithArguments("N.D.x", "0").WithLocation(2, 43)); } [Fact] public void TestConstantFoldingErrors() { // UNDONE: integer overflows in checked contexts are not detected yet. string source = @" class C { void M() { int a = 10 / 0; double y = 10.0 % (-0.0); // not an error, makes an infinity decimal z = 10m % 0m; } } "; CreateCompilation(source).VerifyDiagnostics( // (6,17): error CS0020: Division by constant zero // int a = 10 / 0; Diagnostic(ErrorCode.ERR_IntDivByZero, "10 / 0").WithLocation(6, 17), // (8,21): error CS0020: Division by constant zero // decimal z = 10m % 0m; Diagnostic(ErrorCode.ERR_IntDivByZero, "10m % 0m").WithLocation(8, 21), // (7,16): warning CS0219: The variable 'y' is assigned but its value is never used // double y = 10.0 % (-0.0); // not an error, makes an infinity Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "y").WithArguments("y").WithLocation(7, 16)); } [Fact] public void TestStatementBindingErrors() { string source = @" class C { void M() { x; } } "; CreateCompilation(source).VerifyDiagnostics( // (6,9): error CS0103: The name 'x' does not exist in the current context // x; Diagnostic(ErrorCode.ERR_NameNotInContext, "x").WithArguments("x").WithLocation(6, 9), // (6,9): error CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement // x; Diagnostic(ErrorCode.ERR_IllegalStatement, "x").WithLocation(6, 9)); } [Fact] public void TestLocalDeclarationErrors() { // In the native compiler we report both that Dx[] is an illegal array and that // it is an illegal type for a local or type argument. This seems unnecessary // and redundant. In Roslyn I've eliminated the second error. string source = @" class C { class G<T> {} void M() { D1 x1; D2[] x2; G<D3> x3; G<D4[]> x4; } } static class D1 { } static class D2 { } static class D3 { } static class D4 { } "; CreateCompilation(source).VerifyDiagnostics( // (7,9): error CS0723: Cannot declare a variable of static type 'D1' // D1 x1; Diagnostic(ErrorCode.ERR_VarDeclIsStaticClass, "D1").WithArguments("D1").WithLocation(7, 9), // (8,9): error CS0719: 'D2': array elements cannot be of static type // D2[] x2; Diagnostic(ErrorCode.ERR_ArrayOfStaticClass, "D2").WithArguments("D2").WithLocation(8, 9), // (9,11): error CS0718: 'D3': static types cannot be used as type arguments // G<D3> x3; Diagnostic(ErrorCode.ERR_GenericArgIsStaticClass, "D3").WithArguments("D3").WithLocation(9, 11), // (10,11): error CS0719: 'D4': array elements cannot be of static type // G<D4[]> x4; Diagnostic(ErrorCode.ERR_ArrayOfStaticClass, "D4").WithArguments("D4").WithLocation(10, 11), // (7,12): warning CS0168: The variable 'x1' is declared but never used // D1 x1; Diagnostic(ErrorCode.WRN_UnreferencedVar, "x1").WithArguments("x1").WithLocation(7, 12), // (8,14): warning CS0168: The variable 'x2' is declared but never used // D2[] x2; Diagnostic(ErrorCode.WRN_UnreferencedVar, "x2").WithArguments("x2").WithLocation(8, 14), // (9,15): warning CS0168: The variable 'x3' is declared but never used // G<D3> x3; Diagnostic(ErrorCode.WRN_UnreferencedVar, "x3").WithArguments("x3").WithLocation(9, 15), // (10,17): warning CS0168: The variable 'x4' is declared but never used // G<D4[]> x4; Diagnostic(ErrorCode.WRN_UnreferencedVar, "x4").WithArguments("x4").WithLocation(10, 17)); } [Fact] public void TestOverloadResolutionErrors() { string source = @" using System; using System.Collections; // Some types that illustrate transitivity violations in convertibility, // that then create interesting cases for overload resolution. //class T1 { public static implicit operator T2(T1 t1) { return null; } } //class T2 { public static implicit operator T3(T2 t2) { return null; } } //class T3 { public static implicit operator T1(T3 t3) { return null; } } //class T4 { public static implicit operator T1(T4 t4) { return null; } // public static implicit operator T2(T4 t4) { return null; } // public static implicit operator T3(T4 t4) { return null; } } //class T5 { public static implicit operator T1(T5 t5) { return null; } // public static implicit operator T2(T5 t5) { return null; } // public static implicit operator T3(T5 t5) { return null; } } class P // : IEnumerable { // private void CallFinalize() // { // this.Finalize(); // // error CS0245: Destructors and object.Finalize cannot be called directly. Consider // // calling IDisposable.Dispose if available. // base.Finalize(); // // error CS0250: Do not directly call your base type Finalize method. It is called // // automatically from your destructor. // } public void GenericConstrained<T>(T t) where T : class { } public void Generic<T>(){} public void NotGeneric(){} public void NoParameter(){} public void OneParameter(int parameter){} public void RefParameter(ref int parameter) {} public void TwoParameters(int p1, int p2){} public void TwoRefParameters(ref int p1, ref int p2, int p3) {} public void ThreeRefParameters(ref int p1, ref int p2, ref int p3) {} public void Add(int x) {} public void Add(ref string x) {} public IEnumerator GetEnumerator() { return null; } public static void StaticMethod() {} // Both of these are valid candidates for 'best'. We should // report an ambiguity error. public void Ambiguous(string x, object y) {} public void Ambiguous(object x, string y) {} // // All of these are applicable but each is worse than another, // // thanks to transitivity. Again, an ambiguity error. // public void W1(T1 t1){} // public void W1(T2 t2){} // public void W1(T3 t3){} // // // Here the first three are all worse than something // // and the last two are both valid candidates for 'best'. // // We should report the ambiguity on the last two, not on // // the first three. // public void W2(T1 t1){} // public void W2(T2 t2){} // public void W2(T3 t3){} // public void W2(T4 t4){} // public void W2(T5 t5){} } class Q {} static class Extensions1 { public static P Select(this P p, Func<P, P> projection) { return null; } } static class Extensions2 { public static P Select(this P p, Func<P, P> projection) { return null; } public static object Select(this Q q, object projection) { return null; } public static void PExt(this P p) {} } class C { void InstanceMethod(){} // How many different ways can method member lookup / overload resolution fail? static void M() { P p = new P(); Q q = new Q(); p.Ambiguous(null, null); // error CS0121: The call is ambiguous between the following // methods or properties: 'P.Ambiguous(object, string)' and // 'P.Ambiguous(string, object)' // p.W1(null); // // error CS0121: The call is ambiguous between the following // // methods or properties: 'P.W1(T1)' and 'P.W1(T2)' // p.W2(null); // // error CS0121: The call is ambiguous between the following // // methods or properties: 'P.W2(T4)' and 'P.W2(T5)' // var r1 = from x in p select x; // // error CS1940: Multiple implementations of the query pattern were found for source // // type 'P'. Ambiguous call to 'Select'. // var r2 = p.Select(x=>x); // // error CS0121: The call is ambiguous between the following methods or properties: // // 'Extensions1.Select(P, System.Func<P,P>)' and 'Extensions2.Select(P, System.Func<P,P>)' p.Blah(); // error CS1061: 'P' does not contain a definition for 'Blah' and no extension method // 'Blah' accepting a first argument of type 'P' could be found (are you missing a using // directive or an assembly reference?) p.Generic(); // error CS0411: The type arguments for method 'P.Generic<T>()' cannot be inferred // from the usage. Try specifying the type arguments explicitly. p.Generic<int, int>(); // error CS0305: Using the generic method 'P.Generic<T>()' requires 1 type arguments p.NotGeneric<int, int>(); // error CS0308: The non-generic method 'P.NotGeneric()' cannot be used with type arguments // Func<int, int> f = null; // f(frob : null); // f.Invoke(frob : null); // // error CS1746: The delegate 'Func' does not have a parameter named 'frob' // // bad argument arity sometimes takes precedence over missing name, sometimes does not! p.NoParameter(frob: null); // error CS1501: No overload for method 'NoParameter' takes 1 arguments // p.OneParameter(frob : null); // // error CS1739: The best overload for 'OneParameter' does not have a parameter named // // 'frob' // p.TwoParameters(frob : null); // // error CS1739: The best overload for 'TwoParameters' does not have a parameter // // named 'frob' // p.TwoParameters(p1 : 1, 0); // // error CS1738: Named argument specifications must appear after all fixed arguments // // have been specified // dynamic d = null; // q.Select(d); // // error CS1973: 'Q' has no applicable method named 'Select' but // // appears to have an extension method by that name. Extension methods // // cannot be dynamically dispatched. Consider casting the dynamic arguments // // or calling the extension method without the extension method syntax. // var r3 = from x in d select x; // // error CS1979: Query expressions over source type 'dynamic' or // // with a join sequence of type 'dynamic' are not allowed // Func<int, int> f = p.NotGeneric; // // error CS0123: No overload for 'NotGeneric' matches delegate 'System.Func<int,int>' // f(123, 456); // // error CS1593: Delegate 'Func' does not take 2 arguments // new P(123); // // error CS1729: 'P' does not contain a constructor that takes 1 arguments p.NoParameter(123, 456); // error CS1501: No overload for method 'NoParameter' takes 2 arguments // f(123.456); // // error CS1594: Delegate 'System.Func<int,int>' has some invalid arguments // // error CS1503: Argument 1: cannot convert from 'double' to 'int' p.OneParameter(123.456); // error CS1502: The best overloaded method match for 'P.OneParameter(int)' has some invalid arguments // error CS1503: Argument 1: cannot convert from 'double' to 'int' // p.Select(123.456); // // error CS1928: 'P' does not contain a definition for 'Select' // // and the best extension method overload 'Extensions1.Select(P, // // System.Func<P,P>)' has some invalid arguments // // error CS1503: Argument 2: cannot convert from 'double' to 'System.Func<P,P>' // new P() { 123.456 }; // // error CS1950: The best overloaded Add method 'P.Add(int)' for // // the collection initializer has some invalid arguments // // error CS1503: Argument 1: cannot convert from 'double' to 'int' p.TwoRefParameters(1234, 4567, 1234.4567); // error CS1502: The best overloaded method match for 'P.TwoRefParameters(ref int, ref int, int)' has some invalid arguments // error CS1620: Argument 1 must be passed with the 'ref' keyword // error CS1620: Argument 2 must be passed with the 'ref' keyword // error CS1503: Argument 3: cannot convert from 'double' to 'int' p.ThreeRefParameters(null, p.ToString, 12345.67); // error CS1502: The best overloaded method match for 'P.ThreeRefParameters(ref int, ref int, ref int)' has some invalid arguments // error CS1503: Argument 1: cannot convert from '<null>' to 'ref int' // error CS1503: Argument 2: cannot convert from 'method group' to 'ref int' // error CS1620: Argument 3 must be passed with the 'ref' keyword p.RefParameter(456); // error CS1502: The best overloaded method match for 'P.RefParameter(ref int)' has some invalid arguments // error CS1620: Argument 1 must be passed with the 'ref' keyword int local = 456; p.OneParameter(out local); // error CS1502: The best overloaded method match for 'P.OneParameter(int)' has some invalid arguments // error CS1615: Argument 1 should not be passed with the 'out' keyword p.RefParameter(out local); // error CS1502: The best overloaded method match for 'P.RefParameter(ref int)' has some invalid arguments // error CS1620: Argument 1 must be passed with the 'ref' keyword // q.PExt(); // // error CS1928: 'Q' does not contain a definition for 'PExt' and // // the best extension method overload 'Extensions2.PExt(P)' has some // // invalid arguments // // error CS1929: Instance argument: cannot convert from 'Q' to 'P' // new P() { ""hello"" }; // // error CS1954: The best overloaded method match 'P.Add(ref // // string)' for the collection initializer element cannot be used. // // Collection initializer 'Add' methods cannot have ref or out parameters. // p.GenericConstrained(123); // // error CS0452: The type 'int' must be a reference type in order // // to use it as parameter 'T' in the generic type or method // // 'P.GenericConstrained<T>(T)' p.StaticMethod(); // error CS0176: Member 'P.StaticMethod()' cannot be accessed // with an instance reference; qualify it with a type name instead P.NoParameter(); // error CS0120: An object reference is required for the // non-static field, method, or property 'P.NoParameter()' InstanceMethod(); // Verify that use of 'implicit this' is not legal in a static method. // error CS0120: An object reference is required for the // non-static field, method, or property 'C.InstanceMethod()' } }"; CreateCompilationWithMscorlib40(source).VerifyDiagnostics( // (69,28): error CS1110: Cannot define a new extension because the compiler required type 'System.Runtime.CompilerServices.ExtensionAttribute' cannot be found. Are you missing a reference to System.Core.dll? // public static P Select(this P p, Func<P, P> projection) Diagnostic(ErrorCode.ERR_ExtensionAttrNotFound, "this").WithArguments("System.Runtime.CompilerServices.ExtensionAttribute").WithLocation(69, 28), // (84,29): error CS1110: Cannot define a new extension because the compiler required type 'System.Runtime.CompilerServices.ExtensionAttribute' cannot be found. Are you missing a reference to System.Core.dll? // public static void PExt(this P p) {} Diagnostic(ErrorCode.ERR_ExtensionAttrNotFound, "this").WithArguments("System.Runtime.CompilerServices.ExtensionAttribute").WithLocation(84, 29), // (80,33): error CS1110: Cannot define a new extension because the compiler required type 'System.Runtime.CompilerServices.ExtensionAttribute' cannot be found. Are you missing a reference to System.Core.dll? // public static object Select(this Q q, object projection) Diagnostic(ErrorCode.ERR_ExtensionAttrNotFound, "this").WithArguments("System.Runtime.CompilerServices.ExtensionAttribute").WithLocation(80, 33), // (76,28): error CS1110: Cannot define a new extension because the compiler required type 'System.Runtime.CompilerServices.ExtensionAttribute' cannot be found. Are you missing a reference to System.Core.dll? // public static P Select(this P p, Func<P, P> projection) Diagnostic(ErrorCode.ERR_ExtensionAttrNotFound, "this").WithArguments("System.Runtime.CompilerServices.ExtensionAttribute").WithLocation(76, 28), // (95,11): error CS0121: The call is ambiguous between the following methods or properties: 'P.Ambiguous(string, object)' and 'P.Ambiguous(object, string)' // p.Ambiguous(null, null); Diagnostic(ErrorCode.ERR_AmbigCall, "Ambiguous").WithArguments("P.Ambiguous(string, object)", "P.Ambiguous(object, string)").WithLocation(95, 11), // (113,11): error CS1061: 'P' does not contain a definition for 'Blah' and no extension method 'Blah' accepting a first argument of type 'P' could be found (are you missing a using directive or an assembly reference?) // p.Blah(); Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "Blah").WithArguments("P", "Blah").WithLocation(113, 11), // (118,11): error CS0411: The type arguments for method 'P.Generic<T>()' cannot be inferred from the usage. Try specifying the type arguments explicitly. // p.Generic(); Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "Generic").WithArguments("P.Generic<T>()").WithLocation(118, 11), // (122,11): error CS0305: Using the generic method 'P.Generic<T>()' requires 1 type arguments // p.Generic<int, int>(); Diagnostic(ErrorCode.ERR_BadArity, "Generic<int, int>").WithArguments("P.Generic<T>()", "method", "1").WithLocation(122, 11), // (125,11): error CS0308: The non-generic method 'P.NotGeneric()' cannot be used with type arguments // p.NotGeneric<int, int>(); Diagnostic(ErrorCode.ERR_HasNoTypeVars, "NotGeneric<int, int>").WithArguments("P.NotGeneric()", "method").WithLocation(125, 11), // (134,23): error CS1739: The best overload for 'NoParameter' does not have a parameter named 'frob' // p.NoParameter(frob: null); Diagnostic(ErrorCode.ERR_BadNamedArgument, "frob").WithArguments("NoParameter", "frob").WithLocation(134, 23), // (160,11): error CS1501: No overload for method 'NoParameter' takes 2 arguments // p.NoParameter(123, 456); Diagnostic(ErrorCode.ERR_BadArgCount, "NoParameter").WithArguments("NoParameter", "2").WithLocation(160, 11), // (165,24): error CS1503: Argument 1: cannot convert from 'double' to 'int' // p.OneParameter(123.456); Diagnostic(ErrorCode.ERR_BadArgType, "123.456").WithArguments("1", "double", "int").WithLocation(165, 24), // (178,28): error CS1620: Argument 1 must be passed with the 'ref' keyword // p.TwoRefParameters(1234, 4567, 1234.4567); Diagnostic(ErrorCode.ERR_BadArgRef, "1234").WithArguments("1", "ref").WithLocation(178, 28), // (178,34): error CS1620: Argument 2 must be passed with the 'ref' keyword // p.TwoRefParameters(1234, 4567, 1234.4567); Diagnostic(ErrorCode.ERR_BadArgRef, "4567").WithArguments("2", "ref").WithLocation(178, 34), // (178,40): error CS1503: Argument 3: cannot convert from 'double' to 'int' // p.TwoRefParameters(1234, 4567, 1234.4567); Diagnostic(ErrorCode.ERR_BadArgType, "1234.4567").WithArguments("3", "double", "int").WithLocation(178, 40), // (184,30): error CS1503: Argument 1: cannot convert from '<null>' to 'ref int' // p.ThreeRefParameters(null, p.ToString, 12345.67); Diagnostic(ErrorCode.ERR_BadArgType, "null").WithArguments("1", "<null>", "ref int").WithLocation(184, 30), // (184,36): error CS1503: Argument 2: cannot convert from 'method group' to 'ref int' // p.ThreeRefParameters(null, p.ToString, 12345.67); Diagnostic(ErrorCode.ERR_BadArgType, "p.ToString").WithArguments("2", "method group", "ref int").WithLocation(184, 36), // (184,48): error CS1620: Argument 3 must be passed with the 'ref' keyword // p.ThreeRefParameters(null, p.ToString, 12345.67); Diagnostic(ErrorCode.ERR_BadArgRef, "12345.67").WithArguments("3", "ref").WithLocation(184, 48), // (190,24): error CS1620: Argument 1 must be passed with the 'ref' keyword // p.RefParameter(456); Diagnostic(ErrorCode.ERR_BadArgRef, "456").WithArguments("1", "ref").WithLocation(190, 24), // (195,28): error CS1615: Argument 1 may not be passed with the 'out' keyword // p.OneParameter(out local); Diagnostic(ErrorCode.ERR_BadArgExtraRef, "local").WithArguments("1", "out").WithLocation(195, 28), // (199,28): error CS1620: Argument 1 must be passed with the 'ref' keyword // p.RefParameter(out local); Diagnostic(ErrorCode.ERR_BadArgRef, "local").WithArguments("1", "ref").WithLocation(199, 28), // (216,9): error CS0176: Member 'P.StaticMethod()' cannot be accessed with an instance reference; qualify it with a type name instead // p.StaticMethod(); Diagnostic(ErrorCode.ERR_ObjectProhibited, "p.StaticMethod").WithArguments("P.StaticMethod()").WithLocation(216, 9), // (219,9): error CS0120: An object reference is required for the non-static field, method, or property 'P.NoParameter()' // P.NoParameter(); Diagnostic(ErrorCode.ERR_ObjectRequired, "P.NoParameter").WithArguments("P.NoParameter()").WithLocation(219, 9), // (223,9): error CS0120: An object reference is required for the non-static field, method, or property 'C.InstanceMethod()' // InstanceMethod(); // Verify that use of 'implicit this' is not legal in a static method. Diagnostic(ErrorCode.ERR_ObjectRequired, "InstanceMethod").WithArguments("C.InstanceMethod()").WithLocation(223, 9) ); } [WorkItem(538651, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538651")] [Fact] public void TestMemberResolutionWithHiding() { string source = @" class A { public static void P() { } public static void Q() { } public void R() { } public void S() { } public static int T { get; set; } public static int U { get; set; } public int V { get; set; } public int W { get; set; } } class B : A { // Hiding a member (no new keyword) // generates a warning only. public static int P { get; set; } // CS0108 public int Q { get; set; } // CS0108 public static int R { get; set; } // CS0108 public int S { get; set; } // CS0108 public static void T() { } // CS0108 public void U() { } // CS0108 public static void V() { } // CS0108 public void W() { } // CS0108 } class C { static void F(int i) { } static void M(B b) { // Methods. B.P(); B.Q(); b.R(); b.S(); B.T(); b.U(); B.V(); b.W(); // Property get. F(B.P); F(b.Q); F(B.R); F(b.S); F(B.T); // CS1503 F(B.U); // CS1503 F(b.V); // CS1503 F(b.W); // CS1503 // Property set. B.P = 0; b.Q = 0; B.R = 0; b.S = 0; B.T = 0; // CS1656 B.U = 0; // CS1656 b.V = 0; // CS1656 b.W = 0; // CS1656 } }"; CreateCompilation(source).VerifyDiagnostics( // (18,16): warning CS0108: 'B.Q' hides inherited member 'A.Q()'. Use the new keyword if hiding was intended. // public int Q { get; set; } // CS0108 Diagnostic(ErrorCode.WRN_NewRequired, "Q").WithArguments("B.Q", "A.Q()").WithLocation(18, 16), // (19,23): warning CS0108: 'B.R' hides inherited member 'A.R()'. Use the new keyword if hiding was intended. // public static int R { get; set; } // CS0108 Diagnostic(ErrorCode.WRN_NewRequired, "R").WithArguments("B.R", "A.R()").WithLocation(19, 23), // (20,16): warning CS0108: 'B.S' hides inherited member 'A.S()'. Use the new keyword if hiding was intended. // public int S { get; set; } // CS0108 Diagnostic(ErrorCode.WRN_NewRequired, "S").WithArguments("B.S", "A.S()").WithLocation(20, 16), // (21,24): warning CS0108: 'B.T()' hides inherited member 'A.T'. Use the new keyword if hiding was intended. // public static void T() { } // CS0108 Diagnostic(ErrorCode.WRN_NewRequired, "T").WithArguments("B.T()", "A.T").WithLocation(21, 24), // (22,17): warning CS0108: 'B.U()' hides inherited member 'A.U'. Use the new keyword if hiding was intended. // public void U() { } // CS0108 Diagnostic(ErrorCode.WRN_NewRequired, "U").WithArguments("B.U()", "A.U").WithLocation(22, 17), // (23,24): warning CS0108: 'B.V()' hides inherited member 'A.V'. Use the new keyword if hiding was intended. // public static void V() { } // CS0108 Diagnostic(ErrorCode.WRN_NewRequired, "V").WithArguments("B.V()", "A.V").WithLocation(23, 24), // (24,17): warning CS0108: 'B.W()' hides inherited member 'A.W'. Use the new keyword if hiding was intended. // public void W() { } // CS0108 Diagnostic(ErrorCode.WRN_NewRequired, "W").WithArguments("B.W()", "A.W").WithLocation(24, 17), // (17,23): warning CS0108: 'B.P' hides inherited member 'A.P()'. Use the new keyword if hiding was intended. // public static int P { get; set; } // CS0108 Diagnostic(ErrorCode.WRN_NewRequired, "P").WithArguments("B.P", "A.P()").WithLocation(17, 23), // (45,11): error CS1503: Argument 1: cannot convert from 'method group' to 'int' // F(B.T); // CS1503 Diagnostic(ErrorCode.ERR_BadArgType, "B.T").WithArguments("1", "method group", "int").WithLocation(45, 11), // (46,11): error CS1503: Argument 1: cannot convert from 'method group' to 'int' // F(B.U); // CS1503 Diagnostic(ErrorCode.ERR_BadArgType, "B.U").WithArguments("1", "method group", "int").WithLocation(46, 11), // (47,11): error CS1503: Argument 1: cannot convert from 'method group' to 'int' // F(b.V); // CS1503 Diagnostic(ErrorCode.ERR_BadArgType, "b.V").WithArguments("1", "method group", "int").WithLocation(47, 11), // (48,11): error CS1503: Argument 1: cannot convert from 'method group' to 'int' // F(b.W); // CS1503 Diagnostic(ErrorCode.ERR_BadArgType, "b.W").WithArguments("1", "method group", "int").WithLocation(48, 11), // (54,9): error CS1656: Cannot assign to 'T' because it is a 'method group' // B.T = 0; // CS1656 Diagnostic(ErrorCode.ERR_AssgReadonlyLocalCause, "B.T").WithArguments("T", "method group").WithLocation(54, 9), // (55,9): error CS1656: Cannot assign to 'U' because it is a 'method group' // B.U = 0; // CS1656 Diagnostic(ErrorCode.ERR_AssgReadonlyLocalCause, "B.U").WithArguments("U", "method group").WithLocation(55, 9), // (56,9): error CS1656: Cannot assign to 'V' because it is a 'method group' // b.V = 0; // CS1656 Diagnostic(ErrorCode.ERR_AssgReadonlyLocalCause, "b.V").WithArguments("V", "method group").WithLocation(56, 9), // (57,9): error CS1656: Cannot assign to 'W' because it is a 'method group' // b.W = 0; // CS1656 Diagnostic(ErrorCode.ERR_AssgReadonlyLocalCause, "b.W").WithArguments("W", "method group").WithLocation(57, 9)); } [Fact] public void TestAssignmentErrors01() { string source = @" namespace N { struct Q<T,U> {} } struct S { public int z; } class C { static readonly S static_readonly; S GetS(N.Q<string, double>?[][,][,,] q, int? x) { } readonly int instance_readonly; void M() { const int x = 123; null = 123; M = 123; x = 123; N = 123; C = 123; static_readonly.z = 123; GetS(null, null).z = 123; //object o = null; // UNDONE: ((S)o).x = 123; // UNDONE: event // UNDONE: lambdas and anonymous methods // UNDONE: read-only property instance_readonly = 123; // UNDONE: read-only indexer // UNDONE: s.property = 123, s[x] = 123 where s is a struct type and s is not a writable variable // UNDONE: Inaccessible property // UNDONE: base.property where property setter is abstract // UNDONE: range variables // UNDONE: fixed, using and foreach locals int m1 = M(); int m2 = null; long l1 = 0; int m3 = l1; int m4 = M; this = null; } } "; CreateCompilation(source).VerifyDiagnostics( // (7,7): error CS0161: 'C.GetS(Q<string, double>?[][*,*][*,*,*], int?)': not all code paths return a value // S GetS(N.Q<string, double>?[][,][,,] q, int? x) { } Diagnostic(ErrorCode.ERR_ReturnExpected, "GetS").WithArguments("C.GetS(N.Q<string, double>?[][*,*][*,*,*], int?)").WithLocation(7, 7), // (12,9): error CS0131: The left-hand side of an assignment must be a variable, property or indexer // null = 123; Diagnostic(ErrorCode.ERR_AssgLvalueExpected, "null").WithLocation(12, 9), // (13,9): error CS1656: Cannot assign to 'M' because it is a 'method group' // M = 123; Diagnostic(ErrorCode.ERR_AssgReadonlyLocalCause, "M").WithArguments("M", "method group").WithLocation(13, 9), // (14,9): error CS0131: The left-hand side of an assignment must be a variable, property or indexer // x = 123; Diagnostic(ErrorCode.ERR_AssgLvalueExpected, "x").WithLocation(14, 9), // (15,9): error CS0118: 'N' is a namespace but is used like a variable // N = 123; Diagnostic(ErrorCode.ERR_BadSKknown, "N").WithArguments("N", "namespace", "variable").WithLocation(15, 9), // (16,9): error CS0118: 'C' is a type but is used like a variable // C = 123; Diagnostic(ErrorCode.ERR_BadSKknown, "C").WithArguments("C", "type", "variable").WithLocation(16, 9), // (17,9): error CS1650: Fields of static readonly field 'C.static_readonly' cannot be assigned to (except in a static constructor or a variable initializer) // static_readonly.z = 123; Diagnostic(ErrorCode.ERR_AssgReadonlyStatic2, "static_readonly.z").WithArguments("C.static_readonly").WithLocation(17, 9), // (18,9): error CS1612: Cannot modify the return value of 'C.GetS(Q<string, double>?[][*,*][*,*,*], int?)' because it is not a variable // GetS(null, null).z = 123; Diagnostic(ErrorCode.ERR_ReturnNotLValue, "GetS(null, null)").WithArguments("C.GetS(N.Q<string, double>?[][*,*][*,*,*], int?)").WithLocation(18, 9), // (24,9): error CS0191: A readonly field cannot be assigned to (except in the constructor of the class in which the field is defined or a variable initializer)) // instance_readonly = 123; Diagnostic(ErrorCode.ERR_AssgReadonly, "instance_readonly").WithLocation(24, 9), // (31,18): error CS0029: Cannot implicitly convert type 'void' to 'int' // int m1 = M(); Diagnostic(ErrorCode.ERR_NoImplicitConv, "M()").WithArguments("void", "int").WithLocation(31, 18), // (32,18): error CS0037: Cannot convert null to 'int' because it is a non-nullable value type // int m2 = null; Diagnostic(ErrorCode.ERR_ValueCantBeNull, "null").WithArguments("int").WithLocation(32, 18), // (34,18): error CS0266: Cannot implicitly convert type 'long' to 'int'. An explicit conversion exists (are you missing a cast?) // int m3 = l1; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "l1").WithArguments("long", "int").WithLocation(34, 18), // (35,18): error CS0428: Cannot convert method group 'M' to non-delegate type 'int'. Did you intend to invoke the method? // int m4 = M; Diagnostic(ErrorCode.ERR_MethGrpToNonDel, "M").WithArguments("M", "int").WithLocation(35, 18), // (36,9): error CS1604: Cannot assign to 'this' because it is read-only // this = null; Diagnostic(ErrorCode.ERR_AssgReadonlyLocal, "this").WithArguments("this").WithLocation(36, 9) ); } [Fact] public void TestAssignmentErrors02() { string source = @"struct S { public int Field; } class C { S Property { get; set; } S Get() { return new S(); } void M() { Property.Field = 0; Get().Field = 1; } } "; CreateCompilation(source).VerifyDiagnostics( // (8,9): error CS1612: Cannot modify the return value of 'C.Property' because it is not a variable // Property.Field = 0; Diagnostic(ErrorCode.ERR_ReturnNotLValue, "Property").WithArguments("C.Property").WithLocation(8, 9), // (9,9): error CS1612: Cannot modify the return value of 'C.Get()' because it is not a variable // Get().Field = 1; Diagnostic(ErrorCode.ERR_ReturnNotLValue, "Get()").WithArguments("C.Get()").WithLocation(9, 9)); } [Fact] public void TestRefErrors() { string source = @" class C { struct S { public int z; } void N1(ref int x) {} void N2(ref int x) {} void N3(ref int x) {} void N4(ref int x) {} void N5(ref int x) {} void N6(ref int x) {} static readonly int static_readonly; static S GetS() { return new S(); } void M() { int y = 456; const int x = 123; // Here we have a case that is different than the native compiler. In the native compiler we give the // 'ref or out must be variable' error and then go on to do overload resolution. Overload resolution // then *fails* because we have not represented the argument as 'ref to constant int'. We've represented // it as a constant int, and we then give an incorrect 'bad first argument' and an incorrect 'missing ref' // error. Both seem wrong. The first argument is of the right type, it just isn't a variable, and the // ref isn't missing. The right thing to do is what Roslyn does: state that the expression is // bad, but continue with the type analysis regardless. N1(ref 123); N1(ref x); // Notice that the native compiler *does* do precisely that for this case. Here overload resolution // succeeds: N2(ref y + y); N3(ref null); N4(ref M); N5(ref C); N6(ref y); // No error // UNDONE N(ref static_readonly); // UNDONE N(ref GetS().z); // UNDONE: event, property, indexer, lambda, anonymous method, using, fixed, foreach, lock, inaccessible field, range variables } } "; CreateCompilation(source).VerifyDiagnostics( // (27,24): error CS1510: A ref or out argument must be an assignable variable // N1(ref 123); Diagnostic(ErrorCode.ERR_RefLvalueExpected, "123").WithLocation(27, 24), // (28,24): error CS1510: A ref or out argument must be an assignable variable // N1(ref x); Diagnostic(ErrorCode.ERR_RefLvalueExpected, "x").WithLocation(28, 24), // (33,24): error CS1510: A ref or out argument must be an assignable variable // N2(ref y + y); Diagnostic(ErrorCode.ERR_RefLvalueExpected, "y + y").WithLocation(33, 24), // (35,24): error CS1510: A ref or out argument must be an assignable variable // N3(ref null); Diagnostic(ErrorCode.ERR_RefLvalueExpected, "null").WithLocation(35, 24), // (36,24): error CS1657: Cannot pass 'M' as a ref or out argument because it is a 'method group' // N4(ref M); Diagnostic(ErrorCode.ERR_RefReadonlyLocalCause, "M").WithArguments("M", "method group").WithLocation(36, 24), // (37,24): error CS0118: 'C' is a type but is used like a variable // N5(ref C); Diagnostic(ErrorCode.ERR_BadSKknown, "C").WithArguments("C", "type", "variable").WithLocation(37, 24), // (12,33): warning CS0169: The field 'C.static_readonly' is never used // static readonly int static_readonly; Diagnostic(ErrorCode.WRN_UnreferencedField, "static_readonly").WithArguments("C.static_readonly").WithLocation(12, 33), // (4,35): warning CS0649: Field 'C.S.z' is never assigned to, and will always have its default value 0 // struct S { public int z; } Diagnostic(ErrorCode.WRN_UnassignedInternalField, "z").WithArguments("C.S.z", "0").WithLocation(4, 35)); } [Fact] public void TestStaticErrors() { string source = @" class C { int instanceField; static void M() { int x = instanceField; x = this.instanceField; } } "; CreateCompilation(source).VerifyDiagnostics( // (7,17): error CS0120: An object reference is required for the non-static field, method, or property 'C.instanceField' // int x = instanceField; Diagnostic(ErrorCode.ERR_ObjectRequired, "instanceField").WithArguments("C.instanceField").WithLocation(7, 17), // (8,13): error CS0026: Keyword 'this' is not valid in a static property, static method, or static field initializer // x = this.instanceField; Diagnostic(ErrorCode.ERR_ThisInStaticMeth, "this").WithLocation(8, 13), // (4,9): warning CS0649: Field 'C.instanceField' is never assigned to, and will always have its default value 0 // int instanceField; Diagnostic(ErrorCode.WRN_UnassignedInternalField, "instanceField").WithArguments("C.instanceField", "0").WithLocation(4, 9)); } [Fact] public void TestAssignmentWarnings() { var source = @" class C { // UNDONE: Test warning: IDisp loc = whatever; using(loc) { loc = somethingelse; } struct S { public int z; } static int y; S s1; S s2; void M(int q) { int x = 123; x = x; y = y; s1.z = s1.z; s2.z = s2.z; s1.z = s2.z; q = q; } } "; CreateCompilation(source).VerifyDiagnostics( // (12,9): warning CS1717: Assignment made to same variable; did you mean to assign something else? // x = x; Diagnostic(ErrorCode.WRN_AssignmentToSelf, "x = x"), // (13,9): warning CS1717: Assignment made to same variable; did you mean to assign something else? // y = y; Diagnostic(ErrorCode.WRN_AssignmentToSelf, "y = y"), // (14,9): warning CS1717: Assignment made to same variable; did you mean to assign something else? // s1.z = s1.z; Diagnostic(ErrorCode.WRN_AssignmentToSelf, "s1.z = s1.z"), // (15,9): warning CS1717: Assignment made to same variable; did you mean to assign something else? // s2.z = s2.z; Diagnostic(ErrorCode.WRN_AssignmentToSelf, "s2.z = s2.z"), // (17,9): warning CS1717: Assignment made to same variable; did you mean to assign something else? // q = q; Diagnostic(ErrorCode.WRN_AssignmentToSelf, "q = q")); } [Fact, WorkItem(672714, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/672714")] public void TestAssignmentWarnings_Dynamic() { string source = @" class Program { void goo(dynamic d) { d = (int)d; } }"; CreateCompilation(source).VerifyDiagnostics(); } [Fact] public void TestDuplicateLocalDeclaration() { string source = @" class C { void M() { string q = ""hello""; int i; int j; long k, i; } } static class D { } "; CreateCompilation(source).VerifyDiagnostics( // (9,17): error CS0128: A local variable named 'i' is already defined in this scope // long k, i; Diagnostic(ErrorCode.ERR_LocalDuplicate, "i").WithArguments("i").WithLocation(9, 17), // (6,16): warning CS0219: The variable 'q' is assigned but its value is never used // string q = "hello"; Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "q").WithArguments("q").WithLocation(6, 16), // (7,13): warning CS0168: The variable 'i' is declared but never used // int i; Diagnostic(ErrorCode.WRN_UnreferencedVar, "i").WithArguments("i").WithLocation(7, 13), // (8,13): warning CS0168: The variable 'j' is declared but never used // int j; Diagnostic(ErrorCode.WRN_UnreferencedVar, "j").WithArguments("j").WithLocation(8, 13), // (9,14): warning CS0168: The variable 'k' is declared but never used // long k, i; Diagnostic(ErrorCode.WRN_UnreferencedVar, "k").WithArguments("k").WithLocation(9, 14), // (9,17): warning CS0168: The variable 'i' is declared but never used // long k, i; Diagnostic(ErrorCode.WRN_UnreferencedVar, "i").WithArguments("i").WithLocation(9, 17)); } [Fact] public void TestEnumZeroArg() { string source = @"enum E { Zero, One } enum F { Zero, One } class C { const int One = 1; const object Null = null; static void M(E e) { // Zeros M(false); // error M((char)(One - 1)); // error M((sbyte)(One - 1)); M((byte)(One - 1)); M((short)(One - 1)); M((ushort)(One - 1)); M((int)(One - 1)); M((uint)(One - 1)); M((long)(One - 1)); M((ulong)(One - 1)); M((decimal)(One - 1)); M((float)(One - 1)); M((double)(One - 1)); M((E)(One - 1)); M((F)(One - 1)); // error M(Null); // error M(null); // error M(0); M(E.Zero); M(F.Zero); // error // Ones M(true); // error M((char)One); // error M((sbyte)One); // error M((byte)One); // error M((short)One); // error M((ushort)One); // error M((int)One); // error M((uint)One); // error M((long)One); // error M((ulong)One); // error M((decimal)One); // error M((float)One); // error M((double)One); // error M((E)One); M((F)One); // error M(new object()); // error M(1); // error M(E.One); M(F.One); // error } } "; CreateCompilation(source).VerifyDiagnostics( // (10,11): error CS1503: Argument 1: cannot convert from 'bool' to 'E' // M(false); // error Diagnostic(ErrorCode.ERR_BadArgType, "false").WithArguments("1", "bool", "E").WithLocation(10, 11), // (11,11): error CS1503: Argument 1: cannot convert from 'char' to 'E' // M((char)(One - 1)); // error Diagnostic(ErrorCode.ERR_BadArgType, "(char)(One - 1)").WithArguments("1", "char", "E").WithLocation(11, 11), // (24,11): error CS1503: Argument 1: cannot convert from 'F' to 'E' // M((F)(One - 1)); // error Diagnostic(ErrorCode.ERR_BadArgType, "(F)(One - 1)").WithArguments("1", "F", "E").WithLocation(24, 11), // (25,11): error CS1503: Argument 1: cannot convert from 'object' to 'E' // M(Null); // error Diagnostic(ErrorCode.ERR_BadArgType, "Null").WithArguments("1", "object", "E").WithLocation(25, 11), // (26,11): error CS1503: Argument 1: cannot convert from '<null>' to 'E' // M(null); // error Diagnostic(ErrorCode.ERR_BadArgType, "null").WithArguments("1", "<null>", "E").WithLocation(26, 11), // (29,11): error CS1503: Argument 1: cannot convert from 'F' to 'E' // M(F.Zero); // error Diagnostic(ErrorCode.ERR_BadArgType, "F.Zero").WithArguments("1", "F", "E").WithLocation(29, 11), // (31,11): error CS1503: Argument 1: cannot convert from 'bool' to 'E' // M(true); // error Diagnostic(ErrorCode.ERR_BadArgType, "true").WithArguments("1", "bool", "E").WithLocation(31, 11), // (32,11): error CS1503: Argument 1: cannot convert from 'char' to 'E' // M((char)One); // error Diagnostic(ErrorCode.ERR_BadArgType, "(char)One").WithArguments("1", "char", "E").WithLocation(32, 11), // (33,11): error CS1503: Argument 1: cannot convert from 'sbyte' to 'E' // M((sbyte)One); // error Diagnostic(ErrorCode.ERR_BadArgType, "(sbyte)One").WithArguments("1", "sbyte", "E").WithLocation(33, 11), // (34,11): error CS1503: Argument 1: cannot convert from 'byte' to 'E' // M((byte)One); // error Diagnostic(ErrorCode.ERR_BadArgType, "(byte)One").WithArguments("1", "byte", "E").WithLocation(34, 11), // (35,11): error CS1503: Argument 1: cannot convert from 'short' to 'E' // M((short)One); // error Diagnostic(ErrorCode.ERR_BadArgType, "(short)One").WithArguments("1", "short", "E").WithLocation(35, 11), // (36,11): error CS1503: Argument 1: cannot convert from 'ushort' to 'E' // M((ushort)One); // error Diagnostic(ErrorCode.ERR_BadArgType, "(ushort)One").WithArguments("1", "ushort", "E").WithLocation(36, 11), // (37,11): error CS1503: Argument 1: cannot convert from 'int' to 'E' // M((int)One); // error Diagnostic(ErrorCode.ERR_BadArgType, "(int)One").WithArguments("1", "int", "E").WithLocation(37, 11), // (38,11): error CS1503: Argument 1: cannot convert from 'uint' to 'E' // M((uint)One); // error Diagnostic(ErrorCode.ERR_BadArgType, "(uint)One").WithArguments("1", "uint", "E").WithLocation(38, 11), // (39,11): error CS1503: Argument 1: cannot convert from 'long' to 'E' // M((long)One); // error Diagnostic(ErrorCode.ERR_BadArgType, "(long)One").WithArguments("1", "long", "E").WithLocation(39, 11), // (40,11): error CS1503: Argument 1: cannot convert from 'ulong' to 'E' // M((ulong)One); // error Diagnostic(ErrorCode.ERR_BadArgType, "(ulong)One").WithArguments("1", "ulong", "E").WithLocation(40, 11), // (41,11): error CS1503: Argument 1: cannot convert from 'decimal' to 'E' // M((decimal)One); // error Diagnostic(ErrorCode.ERR_BadArgType, "(decimal)One").WithArguments("1", "decimal", "E").WithLocation(41, 11), // (42,11): error CS1503: Argument 1: cannot convert from 'float' to 'E' // M((float)One); // error Diagnostic(ErrorCode.ERR_BadArgType, "(float)One").WithArguments("1", "float", "E").WithLocation(42, 11), // (43,11): error CS1503: Argument 1: cannot convert from 'double' to 'E' // M((double)One); // error Diagnostic(ErrorCode.ERR_BadArgType, "(double)One").WithArguments("1", "double", "E").WithLocation(43, 11), // (45,11): error CS1503: Argument 1: cannot convert from 'F' to 'E' // M((F)One); // error Diagnostic(ErrorCode.ERR_BadArgType, "(F)One").WithArguments("1", "F", "E").WithLocation(45, 11), // (46,11): error CS1503: Argument 1: cannot convert from 'object' to 'E' // M(new object()); // error Diagnostic(ErrorCode.ERR_BadArgType, "new object()").WithArguments("1", "object", "E").WithLocation(46, 11), // (47,11): error CS1503: Argument 1: cannot convert from 'int' to 'E' // M(1); // error Diagnostic(ErrorCode.ERR_BadArgType, "1").WithArguments("1", "int", "E").WithLocation(47, 11), // (49,11): error CS1503: Argument 1: cannot convert from 'F' to 'E' // M(F.One); // error Diagnostic(ErrorCode.ERR_BadArgType, "F.One").WithArguments("1", "F", "E").WithLocation(49, 11)); } [Fact] public void TestEnumZeroAssign() { string source = @"enum E { Zero, One } enum F { Zero, One } class C { const int One = 1; const object Null = null; static void M() { E e; // Zeros e = false; // error e = (char)(One - 1); // error e = (sbyte)(One - 1); e = (byte)(One - 1); e = (short)(One - 1); e = (ushort)(One - 1); e = (int)(One - 1); e = (uint)(One - 1); e = (long)(One - 1); e = (ulong)(One - 1); e = (decimal)(One - 1); e = (float)(One - 1); e = (double)(One - 1); e = (E)(One - 1); e = (F)(One - 1); // error e = Null; // error e = null; // error e = 0; e = E.Zero; e = F.Zero; // error // Ones e = true; // error e = (char)One; // error e = (sbyte)One; // error e = (byte)One; // error e = (short)One; // error e = (ushort)One; // error e = (int)One; // error e = (uint)One; // error e = (long)One; // error e = (ulong)One; // error e = (decimal)One; // error e = (float)One; // error e = (double)One; // error e = (E)One; e = (F)One; // error e = new object(); // error e = 1; // error e = E.One; e = F.One; // error } } "; CreateCompilation(source).VerifyDiagnostics( // (11,13): error CS0029: Cannot implicitly convert type 'bool' to 'E' // e = false; // error Diagnostic(ErrorCode.ERR_NoImplicitConv, "false").WithArguments("bool", "E").WithLocation(11, 13), // (12,13): error CS0266: Cannot implicitly convert type 'char' to 'E'. An explicit conversion exists (are you missing a cast?) // e = (char)(One - 1); // error Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "(char)(One - 1)").WithArguments("char", "E").WithLocation(12, 13), // (25,13): error CS0266: Cannot implicitly convert type 'F' to 'E'. An explicit conversion exists (are you missing a cast?) // e = (F)(One - 1); // error Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "(F)(One - 1)").WithArguments("F", "E").WithLocation(25, 13), // (26,13): error CS0266: Cannot implicitly convert type 'object' to 'E'. An explicit conversion exists (are you missing a cast?) // e = Null; // error Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "Null").WithArguments("object", "E").WithLocation(26, 13), // (27,13): error CS0037: Cannot convert null to 'E' because it is a non-nullable value type // e = null; // error Diagnostic(ErrorCode.ERR_ValueCantBeNull, "null").WithArguments("E").WithLocation(27, 13), // (30,13): error CS0266: Cannot implicitly convert type 'F' to 'E'. An explicit conversion exists (are you missing a cast?) // e = F.Zero; // error Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "F.Zero").WithArguments("F", "E").WithLocation(30, 13), // (32,13): error CS0029: Cannot implicitly convert type 'bool' to 'E' // e = true; // error Diagnostic(ErrorCode.ERR_NoImplicitConv, "true").WithArguments("bool", "E").WithLocation(32, 13), // (33,13): error CS0266: Cannot implicitly convert type 'char' to 'E'. An explicit conversion exists (are you missing a cast?) // e = (char)One; // error Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "(char)One").WithArguments("char", "E").WithLocation(33, 13), // (34,13): error CS0266: Cannot implicitly convert type 'sbyte' to 'E'. An explicit conversion exists (are you missing a cast?) // e = (sbyte)One; // error Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "(sbyte)One").WithArguments("sbyte", "E").WithLocation(34, 13), // (35,13): error CS0266: Cannot implicitly convert type 'byte' to 'E'. An explicit conversion exists (are you missing a cast?) // e = (byte)One; // error Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "(byte)One").WithArguments("byte", "E").WithLocation(35, 13), // (36,13): error CS0266: Cannot implicitly convert type 'short' to 'E'. An explicit conversion exists (are you missing a cast?) // e = (short)One; // error Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "(short)One").WithArguments("short", "E").WithLocation(36, 13), // (37,13): error CS0266: Cannot implicitly convert type 'ushort' to 'E'. An explicit conversion exists (are you missing a cast?) // e = (ushort)One; // error Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "(ushort)One").WithArguments("ushort", "E").WithLocation(37, 13), // (38,13): error CS0266: Cannot implicitly convert type 'int' to 'E'. An explicit conversion exists (are you missing a cast?) // e = (int)One; // error Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "(int)One").WithArguments("int", "E").WithLocation(38, 13), // (39,13): error CS0266: Cannot implicitly convert type 'uint' to 'E'. An explicit conversion exists (are you missing a cast?) // e = (uint)One; // error Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "(uint)One").WithArguments("uint", "E").WithLocation(39, 13), // (40,13): error CS0266: Cannot implicitly convert type 'long' to 'E'. An explicit conversion exists (are you missing a cast?) // e = (long)One; // error Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "(long)One").WithArguments("long", "E").WithLocation(40, 13), // (41,13): error CS0266: Cannot implicitly convert type 'ulong' to 'E'. An explicit conversion exists (are you missing a cast?) // e = (ulong)One; // error Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "(ulong)One").WithArguments("ulong", "E").WithLocation(41, 13), // (42,13): error CS0266: Cannot implicitly convert type 'decimal' to 'E'. An explicit conversion exists (are you missing a cast?) // e = (decimal)One; // error Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "(decimal)One").WithArguments("decimal", "E").WithLocation(42, 13), // (43,13): error CS0266: Cannot implicitly convert type 'float' to 'E'. An explicit conversion exists (are you missing a cast?) // e = (float)One; // error Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "(float)One").WithArguments("float", "E").WithLocation(43, 13), // (44,13): error CS0266: Cannot implicitly convert type 'double' to 'E'. An explicit conversion exists (are you missing a cast?) // e = (double)One; // error Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "(double)One").WithArguments("double", "E").WithLocation(44, 13), // (46,13): error CS0266: Cannot implicitly convert type 'F' to 'E'. An explicit conversion exists (are you missing a cast?) // e = (F)One; // error Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "(F)One").WithArguments("F", "E").WithLocation(46, 13), // (47,13): error CS0266: Cannot implicitly convert type 'object' to 'E'. An explicit conversion exists (are you missing a cast?) // e = new object(); // error Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "new object()").WithArguments("object", "E").WithLocation(47, 13), // (48,13): error CS0266: Cannot implicitly convert type 'int' to 'E'. An explicit conversion exists (are you missing a cast?) // e = 1; // error Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "1").WithArguments("int", "E").WithLocation(48, 13), // (50,13): error CS0266: Cannot implicitly convert type 'F' to 'E'. An explicit conversion exists (are you missing a cast?) // e = F.One; // error Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "F.One").WithArguments("F", "E").WithLocation(50, 13)); } [Fact] public void TestControlFlowErrors() { string source = @" class C { bool N() { return false; } void M() { if (N()) break; } } "; CreateCompilation(source).VerifyDiagnostics( // (8,13): error CS0139: No enclosing loop out of which to break or continue // break; Diagnostic(ErrorCode.ERR_NoBreakOrCont, "break;").WithLocation(8, 13)); } [Fact] public void TestControlFlowWarnings() { var source = @" class C { void M() { bool b; if (b = false) System.Console.WriteLine(); } } "; CreateCompilation(source).VerifyDiagnostics( // (7,13): warning CS0665: Assignment in conditional expression is always constant; did you mean to use == instead of = ? // if (b = false) Diagnostic(ErrorCode.WRN_IncorrectBooleanAssg, "b = false"), // (6,14): warning CS0219: The variable 'b' is assigned but its value is never used // bool b; Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "b").WithArguments("b")); } [Fact] public void TestArrayCreationErrors() { string source = @" class C { int P { set { } } void M() { int x = 3; int[] intArray1 = new int[2] { 1, 2, 3 }; // count mismatch int[,] intArray2 = new int[,] { 4, 5, 6 }; // missing initializer int[,] intArray3 = new int[,] { { 7, 8 }, { 9 } }; // inconsistent size // UNDONE: Negative constants are not represented correctly yet; // UNDONE: This is treated as unary minus applied to positive two! // int[] intArray4 = new int[-2]; // negative size int[] intArray5 = new int[x] { 10, 11, 12 }; // non-constant size with initializer int[] intArray6 = new int[2] { { 13, 14 }, { 15, 16 } }; // unexpected initializer // TODO int[] intArray7 = new int[] { null }; // bad conversion int[] intArray8 = new int[System]; // expected value, not namespace int[] intArray9 = new int[] { System.Int64 }; // expected value, not type int intArray10 = { 17, 18, 19 }; // int is not an array type // TODO int[] intArray11 = new int[1.23]; // size must be integral int[] intArray11 = new int[] { P }; // write-only property } } "; CreateCompilation(source).VerifyDiagnostics( // (8,38): error CS0847: An array initializer of length '2' is expected // int[] intArray1 = new int[2] { 1, 2, 3 }; // count mismatch Diagnostic(ErrorCode.ERR_ArrayInitializerIncorrectLength, "{ 1, 2, 3 }").WithArguments("2").WithLocation(8, 38), // (9,41): error CS0846: A nested array initializer is expected // int[,] intArray2 = new int[,] { 4, 5, 6 }; // missing initializer Diagnostic(ErrorCode.ERR_ArrayInitializerExpected, "4").WithLocation(9, 41), // (9,44): error CS0846: A nested array initializer is expected // int[,] intArray2 = new int[,] { 4, 5, 6 }; // missing initializer Diagnostic(ErrorCode.ERR_ArrayInitializerExpected, "5").WithLocation(9, 44), // (9,47): error CS0846: A nested array initializer is expected // int[,] intArray2 = new int[,] { 4, 5, 6 }; // missing initializer Diagnostic(ErrorCode.ERR_ArrayInitializerExpected, "6").WithLocation(9, 47), // (10,51): error CS0847: An array initializer of length '2' is expected // int[,] intArray3 = new int[,] { { 7, 8 }, { 9 } }; // inconsistent size Diagnostic(ErrorCode.ERR_ArrayInitializerIncorrectLength, "{ 9 }").WithArguments("2").WithLocation(10, 51), // (14,35): error CS0150: A constant value is expected // int[] intArray5 = new int[x] { 10, 11, 12 }; // non-constant size with initializer Diagnostic(ErrorCode.ERR_ConstantExpected, "x").WithLocation(14, 35), // (15,40): error CS0623: Array initializers can only be used in a variable or field initializer. Try using a new expression instead. // int[] intArray6 = new int[2] { { 13, 14 }, { 15, 16 } }; // unexpected initializer Diagnostic(ErrorCode.ERR_ArrayInitInBadPlace, "{ 13, 14 }").WithLocation(15, 40), // (15,52): error CS0623: Array initializers can only be used in a variable or field initializer. Try using a new expression instead. // int[] intArray6 = new int[2] { { 13, 14 }, { 15, 16 } }; // unexpected initializer Diagnostic(ErrorCode.ERR_ArrayInitInBadPlace, "{ 15, 16 }").WithLocation(15, 52), // (17,35): error CS0118: 'System' is a namespace but is used like a variable // int[] intArray8 = new int[System]; // expected value, not namespace Diagnostic(ErrorCode.ERR_BadSKknown, "System").WithArguments("System", "namespace", "variable").WithLocation(17, 35), // (18,39): error CS0119: 'long' is a type, which is not valid in the given context // int[] intArray9 = new int[] { System.Int64 }; // expected value, not type Diagnostic(ErrorCode.ERR_BadSKunknown, "System.Int64").WithArguments("long", "type").WithLocation(18, 39), // (19,26): error CS0622: Can only use array initializer expressions to assign to array types. Try using a new expression instead. // int intArray10 = { 17, 18, 19 }; // int is not an array type Diagnostic(ErrorCode.ERR_ArrayInitToNonArrayType, "{ 17, 18, 19 }").WithLocation(19, 26), // (21,40): error CS0154: The property or indexer 'C.P' cannot be used in this context because it lacks the get accessor // int[] intArray11 = new int[] { P }; // write-only property Diagnostic(ErrorCode.ERR_PropertyLacksGet, "P").WithArguments("C.P").WithLocation(21, 40)); } [Fact] public void TestObjectCreationOfImportedTypeWithNoArguments() { var block = ParseAndBindMethodBody(@" using System.Collections; class C { void M() { ArrayList t = new ArrayList(); } } "); Assert.NotNull(block); Assert.Equal(1, block.Statements.Length); Assert.NotNull(block.Statements[0]); Assert.Equal(BoundKind.LocalDeclaration, block.Statements[0].Kind); var decl = (BoundLocalDeclaration)block.Statements[0]; Assert.NotNull(decl.InitializerOpt); Assert.Equal(BoundKind.ObjectCreationExpression, decl.InitializerOpt.Kind); var call = (BoundObjectCreationExpression)decl.InitializerOpt; Assert.Equal(".ctor", call.Constructor.Name); Assert.Equal(0, call.Constructor.Parameters.Length); Assert.Equal(0, call.Arguments.Length); Assert.Equal("ArrayList", call.Constructor.ContainingSymbol.Name); } [Fact] public void TestObjectCreationOfImportedTypeWithSingleArgument() { var block = ParseAndBindMethodBody(@" using System.Collections; class C { void M() { ArrayList t = new ArrayList(2); } } "); Assert.NotNull(block); Assert.Equal(1, block.Statements.Length); Assert.NotNull(block.Statements[0]); Assert.Equal(BoundKind.LocalDeclaration, block.Statements[0].Kind); var decl = (BoundLocalDeclaration)block.Statements[0]; Assert.NotNull(decl.InitializerOpt); Assert.Equal(BoundKind.ObjectCreationExpression, decl.InitializerOpt.Kind); var call = (BoundObjectCreationExpression)decl.InitializerOpt; Assert.Equal(".ctor", call.Constructor.Name); Assert.Equal("ArrayList", call.Constructor.ContainingSymbol.Name); Assert.Equal(1, call.Constructor.Parameters.Length); Assert.Equal(1, call.Arguments.Length); } [Fact] public void TestObjectCreationOfImportedTypeWithSingleNamedArgument() { var block = ParseAndBindMethodBody(@" using System.Collections; class C { void M() { ArrayList t = new ArrayList(capacity: 2); } } "); Assert.NotNull(block); Assert.Equal(1, block.Statements.Length); Assert.NotNull(block.Statements[0]); Assert.Equal(BoundKind.LocalDeclaration, block.Statements[0].Kind); var decl = (BoundLocalDeclaration)block.Statements[0]; Assert.NotNull(decl.InitializerOpt); Assert.Equal(BoundKind.ObjectCreationExpression, decl.InitializerOpt.Kind); var call = (BoundObjectCreationExpression)decl.InitializerOpt; Assert.Equal(".ctor", call.Constructor.Name); Assert.Equal("ArrayList", call.Constructor.ContainingSymbol.Name); Assert.Equal(1, call.Constructor.Parameters.Length); Assert.Equal("capacity", call.Constructor.Parameters[0].Name); Assert.Equal(1, call.Arguments.Length); Assert.Equal(1, call.ArgumentNamesOpt.Length); Assert.Equal("capacity", call.ArgumentNamesOpt[0]); } [Fact] public void TestObjectCreationOfDeclaredTypeWithNoArguments() { var block = ParseAndBindMethodBody(@" class T { public T() { } public T(int a) { } public T(int a, string b) {} public T(string a) { } } class C { void M() { T t = new T(); } } "); Assert.NotNull(block); Assert.Equal(1, block.Statements.Length); Assert.NotNull(block.Statements[0]); Assert.Equal(BoundKind.LocalDeclaration, block.Statements[0].Kind); var decl = (BoundLocalDeclaration)block.Statements[0]; Assert.NotNull(decl.InitializerOpt); Assert.Equal(BoundKind.ObjectCreationExpression, decl.InitializerOpt.Kind); var call = (BoundObjectCreationExpression)decl.InitializerOpt; Assert.Equal(".ctor", call.Constructor.Name); Assert.Equal(0, call.Constructor.Parameters.Length); Assert.Equal(0, call.Arguments.Length); Assert.Equal("T", call.Constructor.ContainingSymbol.Name); } [Fact] public void TestObjectCreationOfDeclaredTypeWithSingleIntArgument() { var block = ParseAndBindMethodBody(@" class T { public T() { } public T(int a) { } public T(int a, string b) {} public T(string a) { } } class C { void M() { T t = new T(1); } } "); Assert.NotNull(block); Assert.Equal(1, block.Statements.Length); Assert.NotNull(block.Statements[0]); Assert.Equal(BoundKind.LocalDeclaration, block.Statements[0].Kind); var decl = (BoundLocalDeclaration)block.Statements[0]; Assert.NotNull(decl.InitializerOpt); Assert.Equal(BoundKind.ObjectCreationExpression, decl.InitializerOpt.Kind); var call = (BoundObjectCreationExpression)decl.InitializerOpt; Assert.Equal(".ctor", call.Constructor.Name); Assert.Equal(1, call.Arguments.Length); Assert.Equal(1, call.Constructor.Parameters.Length); Assert.Equal("a", call.Constructor.Parameters[0].Name); Assert.Equal("Int32", call.Constructor.Parameters[0].TypeWithAnnotations.Type.Name); } [Fact] public void TestObjectCreationOfDeclaredTypeWithSingleStringArgument() { var block = ParseAndBindMethodBody(@" class T { public T() { } public T(int a) { } public T(int a, string b) {} public T(string a) { } } class C { void M() { T t = new T(""x""); } } "); Assert.NotNull(block); Assert.Equal(1, block.Statements.Length); Assert.NotNull(block.Statements[0]); Assert.Equal(BoundKind.LocalDeclaration, block.Statements[0].Kind); var decl = (BoundLocalDeclaration)block.Statements[0]; Assert.NotNull(decl.InitializerOpt); Assert.Equal(BoundKind.ObjectCreationExpression, decl.InitializerOpt.Kind); var call = (BoundObjectCreationExpression)decl.InitializerOpt; Assert.Equal(".ctor", call.Constructor.Name); Assert.Equal(1, call.Arguments.Length); Assert.Equal(1, call.Constructor.Parameters.Length); Assert.Equal("a", call.Constructor.Parameters[0].Name); Assert.Equal("String", call.Constructor.Parameters[0].TypeWithAnnotations.Type.Name); } [Fact] public void TestObjectCreationOfDeclaredTypeWithSingleNamedIntArgument() { var block = ParseAndBindMethodBody(@" class T { public T() { } public T(int a) { } public T(int a, string b) {} public T(string a) { } } class C { void M() { T t = new T(a: 1); } } "); Assert.NotNull(block); Assert.Equal(1, block.Statements.Length); Assert.NotNull(block.Statements[0]); Assert.Equal(BoundKind.LocalDeclaration, block.Statements[0].Kind); var decl = (BoundLocalDeclaration)block.Statements[0]; Assert.NotNull(decl.InitializerOpt); Assert.Equal(BoundKind.ObjectCreationExpression, decl.InitializerOpt.Kind); var newExpr = (BoundObjectCreationExpression)decl.InitializerOpt; Assert.Equal(".ctor", newExpr.Constructor.Name); Assert.Equal(1, newExpr.Arguments.Length); Assert.Equal(1, newExpr.Constructor.Parameters.Length); Assert.Equal("a", newExpr.Constructor.Parameters[0].Name); Assert.Equal("Int32", newExpr.Constructor.Parameters[0].TypeWithAnnotations.Type.Name); } } }