|
// 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 System.Linq;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests
{
public class BreakingChanges : CSharpTestBase
{
[Fact, WorkItem(527050, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/527050")]
[Trait("Feature", "Directives")]
public void TestCS1024DefineWithUnicodeInMiddle()
{
var test = @"#de\u0066in\U00000065 ABC";
// This is now a negative test, this should not be allowed.
SyntaxFactory.ParseSyntaxTree(test).GetDiagnostics().Verify(Diagnostic(ErrorCode.ERR_PPDirectiveExpected, @"de\u0066in\U00000065"));
}
[Fact, WorkItem(527951, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/527951")]
public void CS0133ERR_NotConstantExpression05()
{
var text = @"
class A
{
public void Do()
{
const object o1 = null;
const string o2 = (string)o1; // Dev10 reports CS0133
}
}
";
var comp = CreateCompilation(text);
comp.VerifyDiagnostics(
// (7,22): warning CS0219: The variable 'o2' is assigned but its value is never used
// const string o2 = (string)o1; // Dev10 reports CS0133
Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "o2").WithArguments("o2")
);
}
[WorkItem(527943, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/527943")]
[Fact]
public void CS0146ERR_CircularBase05()
{
var text = @"
interface IFace<T> { }
class B : IFace<B.C.D>
{
public class C
{
public class D { }
}
}
";
var comp = CreateCompilation(text);
// In Dev10, there was an error - ErrorCode.ERR_CircularBase at (4,7)
Assert.Equal(0, comp.GetDiagnostics().Count());
}
[WorkItem(540371, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540371"), WorkItem(530792, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530792")]
[Fact]
public void CS0507ERR_CantChangeAccessOnOverride_TestSynthesizedSealedAccessorsInDifferentAssembly()
{
var source1 = @"
using System.Collections.Generic;
public class Base<T>
{
public virtual List<T> Property1 { get { return null; } protected internal set { } }
public virtual List<T> Property2 { protected internal get { return null; } set { } }
}";
var compilation1 = CreateCompilation(source1);
var source2 = @"
using System.Collections.Generic;
public class Derived : Base<int>
{
public sealed override List<int> Property1 { get { return null; } }
public sealed override List<int> Property2 { set { } }
}";
var comp = CreateCompilation(source2, new[] { new CSharpCompilationReference(compilation1) });
comp.VerifyDiagnostics();
// This is not a breaking change - but it is a change in behavior from Dev10
// Dev10 used to report following errors -
// Error CS0507: 'Derived.Property1.set': cannot change access modifiers when overriding 'protected' inherited member 'Base<int>.Property1.set'
// Error CS0507: 'Derived.Property2.get': cannot change access modifiers when overriding 'protected' inherited member 'Base<int>.Property2.get'
// Roslyn makes this case work by synthesizing 'protected' accessors for the missing ones
var baseClass = comp.GlobalNamespace.GetMember<NamedTypeSymbol>("Base");
var baseProperty1 = baseClass.GetMember<PropertySymbol>("Property1");
var baseProperty2 = baseClass.GetMember<PropertySymbol>("Property2");
Assert.Equal(Accessibility.Public, baseProperty1.DeclaredAccessibility);
Assert.Equal(Accessibility.Public, baseProperty1.GetMethod.DeclaredAccessibility);
Assert.Equal(Accessibility.ProtectedOrInternal, baseProperty1.SetMethod.DeclaredAccessibility);
Assert.Equal(Accessibility.Public, baseProperty2.DeclaredAccessibility);
Assert.Equal(Accessibility.ProtectedOrInternal, baseProperty2.GetMethod.DeclaredAccessibility);
Assert.Equal(Accessibility.Public, baseProperty2.SetMethod.DeclaredAccessibility);
var derivedClass = comp.GlobalNamespace.GetMember<NamedTypeSymbol>("Derived");
var derivedProperty1 = derivedClass.GetMember<SourcePropertySymbol>("Property1");
var derivedProperty2 = derivedClass.GetMember<SourcePropertySymbol>("Property2");
Assert.Equal(Accessibility.Public, derivedProperty1.DeclaredAccessibility);
Assert.Equal(Accessibility.Public, derivedProperty1.GetMethod.DeclaredAccessibility);
Assert.Null(derivedProperty1.SetMethod);
Assert.Equal(Accessibility.Public, derivedProperty2.DeclaredAccessibility);
Assert.Null(derivedProperty2.GetMethod);
Assert.Equal(Accessibility.Public, derivedProperty2.SetMethod.DeclaredAccessibility);
var derivedProperty1Synthesized = derivedProperty1.SynthesizedSealedAccessorOpt;
var derivedProperty2Synthesized = derivedProperty2.SynthesizedSealedAccessorOpt;
Assert.Equal(MethodKind.PropertySet, derivedProperty1Synthesized.MethodKind);
Assert.Equal(Accessibility.Protected, derivedProperty1Synthesized.DeclaredAccessibility);
Assert.Equal(MethodKind.PropertyGet, derivedProperty2Synthesized.MethodKind);
Assert.Equal(Accessibility.Protected, derivedProperty2Synthesized.DeclaredAccessibility);
}
// Confirm that this error no longer exists
[Fact]
public void CS0609ERR_NameAttributeOnOverride()
{
var text = @"
using System.Runtime.CompilerServices;
public class @idx
{
public virtual int this[int iPropIndex]
{
get { return 0; }
set { }
}
}
public class MonthDays : idx
{
[IndexerName(""MonthInfoIndexer"")]
public override int this[int iPropIndex]
{
get { return 1; }
set { }
}
}
";
var compilation = CreateCompilation(text);
compilation.VerifyDiagnostics();
var indexer = compilation.GlobalNamespace.GetMember<NamedTypeSymbol>("MonthDays").Indexers.Single();
Assert.Equal(Microsoft.CodeAnalysis.WellKnownMemberNames.Indexer, indexer.Name);
Assert.Equal("MonthInfoIndexer", indexer.MetadataName);
}
[WorkItem(527116, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/527116")]
[Fact]
public void RegressWarningInSingleMultiLineMixedXml()
{
var text = @"
/// <summary>
/** This is the summary */
/// </summary>
class Test
{
/** <summary> */
/// This is the summary1
/** </summary> */
public int Field = 0;
/** <summary> */
/// This is the summary2
/// </summary>
string Prop { get; set; }
/// <summary>
/** This is the summary3
* </summary> */
static int Main() { return new Test().Field; }
}
";
var tree = Parse(text, options: TestOptions.RegularWithDocumentationComments);
Assert.NotNull(tree);
Assert.Equal(text, tree.GetCompilationUnitRoot().ToFullString());
// Dev10 allows (no warning)
// Roslyn gives Warning CS1570 - "XML Comment has badly formed XML..."
Assert.Equal(8, tree.GetDiagnostics().Count());
}
[Fact, WorkItem(527093, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/527093")]
public void NoCS1570ForUndefinedXmlNamespace()
{
var text = @"
/// <xml> xmlns:s=""uuid: BDC6E3F0-6DA3-11d1-A2A3 - 00AA00C14882"">
/// <s:inventory>
/// </s:inventory>
/// </xml>
class A { }
";
var tree = Parse(text, options: TestOptions.RegularWithDocumentationComments);
Assert.NotNull(tree);
Assert.Equal(text, tree.GetCompilationUnitRoot().ToFullString());
// Native Warning CS1570 - "XML Comment has badly formed XML..."
// Roslyn no
Assert.Empty(tree.GetDiagnostics());
}
[Fact, WorkItem(541345, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541345")]
public void CS0019_TestNullCoalesceWithNullOperandsErrors()
{
var source = @"
class Program
{
static void Main()
{
// This is acceptable by the native compiler and treated as a non-constant null literal.
// That violates the specification; we now correctly treat this as an error.
object a = null ?? null;
// The null coalescing operator never produces a compile-time constant even when
// the arguments are constants.
const object b = null ?? ""ABC"";
const string c = ""DEF"" ?? null;
const int d = (int?)null ?? 123;
// It is legal, though pointless, to use null literals and constants in coalescing
// expressions, provided you don't try to make the result a constant. These should
// produce no errors:
object z = null ?? ""GHI"";
string y = ""JKL"" ?? null;
int x = (int?)null ?? 456;
}
}
";
CreateCompilation(source).VerifyDiagnostics(
Diagnostic(ErrorCode.ERR_BadBinaryOps, "null ?? null").WithArguments("??", "<null>", "<null>"),
Diagnostic(ErrorCode.ERR_NotConstantExpression, @"null ?? ""ABC""").WithArguments("b"),
Diagnostic(ErrorCode.ERR_NotConstantExpression, @"""DEF"" ?? null").WithArguments("c"),
Diagnostic(ErrorCode.ERR_NotConstantExpression, "(int?)null ?? 123").WithArguments("d"));
}
[Fact, WorkItem(528676, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/528676"), WorkItem(528676, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/528676")]
public // CS0657WRN_AttributeLocationOnBadDeclaration_AfterAttrDeclOrDelegate
void CS1730ERR_CantUseAttributeOnInvaildLocation()
{
var test = @"using System;
[AttributeUsage(AttributeTargets.All)]
public class Goo : Attribute
{
public int Name;
public Goo(int sName) { Name = sName; }
}
public delegate void EventHandler(object sender, EventArgs e);
[assembly: Goo(5)]
public class Test { }
";
// In Dev10, this is a warning CS0657
// Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "assembly").WithArguments("assembly", "type")
SyntaxFactory.ParseSyntaxTree(test).GetDiagnostics().Verify(Diagnostic(ErrorCode.ERR_GlobalAttributesNotFirst, "assembly"));
}
[WorkItem(528711, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/528711")]
[Fact]
public void CS9259_StructLayoutCycle()
{
var text =
@"struct S1<T>
{
S1<S1<T>>.S2 x;
struct S2
{
static T x;
}
}";
var comp = CreateCompilation(text);
comp.VerifyDiagnostics(
// (3,18): warning CS0169: The field 'S1<T>.x' is never used
// S1<S1<T>>.S2 x;
Diagnostic(ErrorCode.WRN_UnreferencedField, "x").WithArguments("S1<T>.x").WithLocation(3, 18),
// (6,18): warning CS0169: The field 'S1<T>.S2.x' is never used
// static T x;
Diagnostic(ErrorCode.WRN_UnreferencedField, "x").WithArguments("S1<T>.S2.x").WithLocation(6, 18)
);
}
[WorkItem(528094, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/528094")]
[Fact]
public void FormattingUnicodeNotPartOfId()
{
string source = @"
// <Area> Lexical - Unicode Characters</Area>
// <Title>
// Compiler considers identifiers, which differ only in formatting-character, as different ones;
// This is not actually correct behavior but for the time being this is what we expect
//</Title>
//<RelatedBugs>DDB:133151</RelatedBugs>
// <Expects Status=Success></Expects>
#define A
using System;
class Program
{
static int Main()
{
int x = 0;
#if A == A\uFFFB
x=1;
#endif
Console.Write(x);
return x;
}
}
";
// Dev10 print '0'
CompileAndVerify(source, expectedOutput: "1");
}
[WorkItem(529000, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529000")]
[Fact]
public void NoCS0121ForSwitchedParamNames_Dev10814222()
{
string source = @"
using System;
// Bug Dev10: 814222 resolved as Won't Fix
class Test
{
static void Main()
{
Console.Write(Bar(x: 1, y: ""T0"")); // Dev10:CS0121
Test01.Main01();
}
public static int Bar(int x, string y, params int[] z) { return 1; }
public static int Bar(string y, int x) { return 0; } // Roslyn pick this one
}
class Test01
{
public static int Bar<T>(int x, T y, params int[] z) { return 1; }
public static int Bar<T>(string y, int x) { return 0; } // Roslyn pick this one
public static int Goo<T>(int x, T y) { return 1; }
public static int Goo<T>(string y, int x) { return 0; } // Roslyn pick this one
public static int AbcDef<T>(int x, T y) { return 0; } // Roslyn pick this one
public static int AbcDef<T>(string y, int x, params int[] z) { return 1; }
public static void Main01()
{
Console.Write(Bar<string>(x: 1, y: ""T1"")); // Dev10:CS0121
Console.Write(Goo<string>(x: 1, y: ""T2"")); // Dev10:CS0121
Console.Write(AbcDef<string>(x: 1, y: ""T3"")); // Dev10:CS0121
}
}
";
CompileAndVerify(source, expectedOutput: "0000");
}
[WorkItem(529001, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529001")]
[WorkItem(529002, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529002")]
[WorkItem(1067, "https://github.com/dotnet/roslyn/issues/1067")]
[Fact]
public void CS0185ERR_LockNeedsReference_RequireRefType()
{
var source = @"
class C
{
void M<T, TClass, TStruct>()
where TClass : class
where TStruct : struct
{
lock (default(object)) ;
lock (default(int)) ; // CS0185
lock (default(T)) {} // new CS0185 - no constraints (Bug#10755)
lock (default(TClass)) {}
lock (default(TStruct)) {} // new CS0185 - constraints to value type (Bug#10756)
lock (null) {} // new CS0185 - null is not an object type
}
}
";
var standardCompilation = CreateCompilation(source);
var strictCompilation = CreateCompilation(source, parseOptions: TestOptions.Regular.WithStrictFeature());
standardCompilation.VerifyDiagnostics(
// (8,32): warning CS0642: Possible mistaken empty statement
// lock (default(object)) ;
Diagnostic(ErrorCode.WRN_PossibleMistakenNullStatement, ";").WithLocation(8, 32),
// (9,29): warning CS0642: Possible mistaken empty statement
// lock (default(int)) ; // CS0185
Diagnostic(ErrorCode.WRN_PossibleMistakenNullStatement, ";").WithLocation(9, 29),
// (9,15): error CS0185: 'int' is not a reference type as required by the lock statement
// lock (default(int)) ; // CS0185
Diagnostic(ErrorCode.ERR_LockNeedsReference, "default(int)").WithArguments("int").WithLocation(9, 15),
// (12,15): error CS0185: 'TStruct' is not a reference type as required by the lock statement
// lock (default(TStruct)) {} // new CS0185 - constraints to value type (Bug#10756)
Diagnostic(ErrorCode.ERR_LockNeedsReference, "default(TStruct)").WithArguments("TStruct").WithLocation(12, 15)
);
strictCompilation.VerifyDiagnostics(
// (8,32): warning CS0642: Possible mistaken empty statement
// lock (default(object)) ;
Diagnostic(ErrorCode.WRN_PossibleMistakenNullStatement, ";").WithLocation(8, 32),
// (9,29): warning CS0642: Possible mistaken empty statement
// lock (default(int)) ; // CS0185
Diagnostic(ErrorCode.WRN_PossibleMistakenNullStatement, ";").WithLocation(9, 29),
// (9,15): error CS0185: 'int' is not a reference type as required by the lock statement
// lock (default(int)) ; // CS0185
Diagnostic(ErrorCode.ERR_LockNeedsReference, "default(int)").WithArguments("int").WithLocation(9, 15),
// (10,15): error CS0185: 'T' is not a reference type as required by the lock statement
// lock (default(T)) {} // new CS0185 - no constraints (Bug#10755)
Diagnostic(ErrorCode.ERR_LockNeedsReference, "default(T)").WithArguments("T").WithLocation(10, 15),
// (12,15): error CS0185: 'TStruct' is not a reference type as required by the lock statement
// lock (default(TStruct)) {} // new CS0185 - constraints to value type (Bug#10756)
Diagnostic(ErrorCode.ERR_LockNeedsReference, "default(TStruct)").WithArguments("TStruct").WithLocation(12, 15),
// (13,15): error CS0185: '<null>' is not a reference type as required by the lock statement
// lock (null) {} // new CS0185 - null is not an object type
Diagnostic(ErrorCode.ERR_LockNeedsReference, "null").WithArguments("<null>").WithLocation(13, 15)
);
}
[WorkItem(528972, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/528972")]
[Fact]
public void CS0121ERR_AmbigCall_Lambda1()
{
var text = @"
using System;
class A
{
static void Main()
{
Goo( delegate () { throw new Exception(); }); // both Dev10 & Roslyn no error
Goo(x: () => { throw new Exception(); }); // Dev10: CS0121, Roslyn: no error
}
public static void Goo(Action x)
{
Console.WriteLine(1);
}
public static void Goo(Func<int> x)
{
Console.WriteLine(2); // Roslyn call this one
}
}
";
// Dev11 FIXED this, no error anymore (So Not breaking Dev11)
// Dev10 reports CS0121 because ExpressionBinder::WhichConversionIsBetter fails to unwrap
// the NamedArgumentSpecification to find the UNBOUNDLAMBDA and, thus, never calls
// WhichLambdaConversionIsBetter.
CreateCompilation(text).VerifyDiagnostics();
}
[Fact, WorkItem(529202, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529202")]
public void NoCS0029_ErrorOnZeroToEnumToTypeConversion()
{
string source = @"
class Program
{
static void Main()
{
S s = 0;
}
}
enum E
{
Zero, One, Two
}
struct S
{
public static implicit operator S(E s)
{
return E.Zero;
}
}";
// Dev10/11: (11,9): error CS0029: Cannot implicitly convert type 'int' to 'S'
CreateCompilation(source).VerifyDiagnostics(
// (6,15): error CS0029: Cannot implicitly convert type 'int' to 'S'
// S s = 0;
Diagnostic(ErrorCode.ERR_NoImplicitConv, "0").WithArguments("int", "S")
);
}
[Fact, WorkItem(529242, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529242")]
public void ThrowOverflowExceptionForUncheckedCheckedLambda()
{
string source = @"
using System;
class Program
{
static void Main()
{
Func<int, int> d = checked(delegate(int i)
{
int max = int.MaxValue;
try
{
int n = max + 1;
}
catch (OverflowException)
{
Console.Write(""OV ""); // Roslyn throw
}
return i;
});
var r = unchecked(d(9));
Console.Write(r);
}
}
";
CompileAndVerify(source, expectedOutput: "OV 9");
}
[WorkItem(529262, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529262")]
[Fact]
public void PartialMethod_ParameterAndTypeParameterNames()
{
var source =
@"using System;
using System.Reflection;
partial class C
{
static partial void M<T, U>(T x, U y);
static partial void M<T1, T2>(T1 y, T2 x)
{
Console.Write(""{0}, {1} | "", x, y);
var m = typeof(C).GetMethod(""M"", BindingFlags.Static | BindingFlags.NonPublic);
var tp = m.GetGenericArguments();
Console.Write(""{0}, {1} | "", tp[0].Name, tp[1].Name);
var p = m.GetParameters();
Console.Write(""{0}, {1}"", p[0].Name, p[1].Name);
}
static void Main()
{
M(x: 1, y: 2);
}
}";
// Dev12 would emit "2, 1 | T1, T2 | x, y".
CompileAndVerify(source, expectedOutput: "2, 1 | T, U | x, y");
}
[Fact, WorkItem(529279, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529279")]
public void NewCS0029_ImplicitlyUnwrapGenericNullable()
{
string source = @"
public class GenC<T, U> where T : struct, U
{
public void Test(T t)
{
/*<bind>*/T? nt = t;/*</bind>*/
U valueUn = nt;
}
}";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (7,21): error CS0029: Cannot implicitly convert type 'T?' to 'U'
// U valueUn = nt;
Diagnostic(ErrorCode.ERR_NoImplicitConv, "nt").WithArguments("T?", "U"));
VerifyOperationTreeForTest<LocalDeclarationStatementSyntax>(comp, @"
IVariableDeclarationGroupOperation (1 declarations) (OperationKind.VariableDeclarationGroup, Type: null) (Syntax: 'T? nt = t;')
IVariableDeclarationOperation (1 declarators) (OperationKind.VariableDeclaration, Type: null) (Syntax: 'T? nt = t')
Declarators:
IVariableDeclaratorOperation (Symbol: T? nt) (OperationKind.VariableDeclarator, Type: null) (Syntax: 'nt = t')
Initializer:
IVariableInitializerOperation (OperationKind.VariableInitializer, Type: null) (Syntax: '= t')
IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: T?, IsImplicit) (Syntax: 't')
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Operand:
IParameterReferenceOperation: t (OperationKind.ParameterReference, Type: T) (Syntax: 't')
Initializer:
null
");
}
[Fact, WorkItem(529280, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529280"), WorkItem(546864, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546864")]
public void ExplicitUDCWithGenericConstraints()
{
// This compiles successfully in Dev10 dues to a bug; a user-defined conversion
// that converts from or to an interface should never be chosen. If you are
// converting from Alpha to Beta via standard conversion, then Beta to Gamma
// via user-defined conversion, then Gamma to Delta via standard conversion, then
// none of Alpha, Beta, Gamma or Delta should be allowed to be interfaces. The
// Dev10 compiler only checks Alpha and Delta, not Beta and Gamma.
//
// Unfortunately, real-world code both in devdiv and in the wild depends on this
// behavior, so we are replicating the bug in Roslyn.
string source = @"using System;
public interface IGoo { void Method(); }
public class CT : IGoo { public void Method() { } }
public class GenC<T> where T : IGoo
{
public T valueT;
public static explicit operator T(GenC<T> val)
{
Console.Write(""ExpConv"");
return val.valueT;
}
}
public class Test
{
public static void Main()
{
var _class = new GenC<IGoo>();
var ret = (CT)_class;
}
}
";
// CompileAndVerify(source, expectedOutput: "ExpConv");
CreateCompilation(source).VerifyDiagnostics();
}
[Fact, WorkItem(529362, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529362")]
public void TestNullCoalescingOverImplicitExplicitUDC()
{
string source = @"using System;
struct GenS<T> where T : struct
{
public static int Flag;
public static explicit operator T?(GenS<T> s)
{
Flag = 3;
return default(T);
}
public static implicit operator T(GenS<T> s)
{
Flag = 2;
return default(T);
}
}
class Program
{
public static void Main()
{
int? int_a1 = 1;
GenS<int>? s28 = new GenS<int>();
// Due to related bug dev10: 742047 is won't fix
// so expects the code will call explicit conversion operator
int? result28 = s28 ?? int_a1;
Console.WriteLine(GenS<int>.Flag);
}
}
";
// Native compiler picks explicit conversion - print 3
CompileAndVerify(source, expectedOutput: "2");
}
[Fact, WorkItem(529362, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529362")]
public void TestNullCoalescingOverImplicitExplicitUDC_2()
{
string source = @"using System;
struct S
{
public static explicit operator int?(S? s)
{
Console.WriteLine(""Explicit"");
return 3;
}
public static implicit operator int(S? s)
{
Console.WriteLine(""Implicit"");
return 2;
}
}
class Program
{
public static void Main()
{
int? nn = -1;
S? s = new S();
int? ret = s ?? nn;
}
}
";
// Native compiler picks explicit conversion
CompileAndVerify(source, expectedOutput: "Implicit");
}
[Fact, WorkItem(529363, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529363")]
public void AssignmentNullCoalescingOperator()
{
string source = @"using System;
class NullCoalescingTest
{
public static void Main()
{
int? a;
int c;
var x = (a = null) ?? (c = 123);
Console.WriteLine(c);
}
}
";
// Native compiler no error (print -123)
CreateCompilation(source).VerifyDiagnostics(
// (10,27): error CS0165: Use of unassigned local variable 'c'
// Console.WriteLine(c);
Diagnostic(ErrorCode.ERR_UseDefViolation, "c").WithArguments("c"),
// (7,14): warning CS0219: The variable 'a' is assigned but its value is never used
// int? a;
Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "a").WithArguments("a"));
}
[Fact, WorkItem(529464, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529464")]
public void MultiDimensionArrayWithDiffTypeIndexDevDiv31328()
{
var text = @"
class A
{
public static void Main()
{
byte[,] arr = new byte[1, 1];
ulong i1 = 0;
int i2 = 1;
arr[i1, i2] = 127; // Dev10 CS0266
}
}
";
// Dev10 Won't fix bug#31328 for md array with different types' index and involving ulong
// CS0266: Cannot implicitly convert type 'ulong' to 'int'. ...
CreateCompilation(text).VerifyDiagnostics();
}
[Fact]
public void PointerArithmetic_SubtractNullLiteral()
{
var text = @"
unsafe class C
{
long M(int* p)
{
return p - null; //Dev10 reports CS0019
}
}
";
// Dev10: the null literal is treated as though it is converted to void*, making the subtraction illegal (ExpressionBinder::GetPtrBinOpSigs).
// Roslyn: the null literal is converted to int*, making the subtraction legal.
CreateCompilation(text, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics();
}
[Fact]
public void CS0181ERR_BadAttributeParamType_Nullable()
{
var text = @"
[Boom]
class Boom : System.Attribute
{
public Boom(int? x = 0) { }
static void Main()
{
typeof(Boom).GetCustomAttributes(true);
}
}
";
// Roslyn: error CS0181: Attribute constructor parameter 'x' has type 'int?', which is not a valid attribute parameter type
// Dev10/11: no error, but throw at runtime - System.Reflection.CustomAttributeFormatException
CreateCompilation(text).VerifyDiagnostics(
Diagnostic(ErrorCode.ERR_BadAttributeParamType, "Boom").WithArguments("x", "int?"));
}
/// <summary>
/// When determining whether the LHS of a null-coalescing operator (??) is non-null, the native compiler strips off casts.
///
/// We have decided not to reproduce this behavior.
/// </summary>
[Fact]
public void CastOnLhsOfConditionalOperator()
{
var text = @"
class C
{
static void Main(string[] args)
{
int i;
int? j = (int?)1 ?? i; //dev10 accepts, since it treats the RHS as unreachable.
int k;
int? l = ((int?)1 ?? j) ?? k; // If the LHS of the LHS is non-null, then the LHS should be non-null, but dev10 only handles casts.
int m;
int? n = ((int?)1).HasValue ? ((int?)1).Value : m; //dev10 does not strip casts in a comparable conditional operator
}
}
";
// Roslyn: error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('object')
// Dev10/11: no error
CreateCompilation(text).VerifyDiagnostics(
// This is new in Roslyn.
// (7,29): error CS0165: Use of unassigned local variable 'i'
// int? j = (int?)1 ?? i; //dev10 accepts, since it treats the RHS as unreachable.
Diagnostic(ErrorCode.ERR_UseDefViolation, "i").WithArguments("i"),
// These match Dev10.
// (10,36): error CS0165: Use of unassigned local variable 'k'
// int? l = ((int?)1 ?? j) ?? k; // If the LHS of the LHS is non-null, then the LHS should be non-null, but dev10 only handles casts.
Diagnostic(ErrorCode.ERR_UseDefViolation, "k").WithArguments("k"),
// (13,57): error CS0165: Use of unassigned local variable 'm'
// int? n = ((int?)1).HasValue ? ((int?)1).Value : m; //dev10 does not strip casts in a comparable conditional operator
Diagnostic(ErrorCode.ERR_UseDefViolation, "m").WithArguments("m"));
}
[WorkItem(529974, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529974")]
[Fact]
public void TestCollisionForLoopControlVariable()
{
var source = @"
namespace Microsoft.Test.XmlGen.Protocols.Saml2
{
using System;
using System.Collections.Generic;
public class ProxyRestriction
{
XmlGenIntegerAttribute count;
private List<XmlGenAttribute> Attributes { get; set; }
public ProxyRestriction()
{
for (int count = 0; count < 10; count++)
{
}
for (int i = 0; i < this.Attributes.Count; i++)
{
XmlGenAttribute attribute = this.Attributes[i];
if (attribute.LocalName == null)
{
if (count is XmlGenIntegerAttribute)
{
count = (XmlGenIntegerAttribute)attribute;
}
else
{
count = new XmlGenIntegerAttribute(attribute);
this.Attributes[i] = count;
}
break;
}
}
if (count == null)
{
this.Attributes.Add(new XmlGenIntegerAttribute(String.Empty, null, String.Empty, -1, false));
}
}
}
internal class XmlGenAttribute
{
public object LocalName { get; internal set; }
}
internal class XmlGenIntegerAttribute : XmlGenAttribute
{
public XmlGenIntegerAttribute(string empty1, object count, string empty2, int v, bool isPresent)
{
}
public XmlGenIntegerAttribute(XmlGenAttribute attribute)
{
}
}
}
public class Program
{
public static void Main() { }
}";
// Dev11 reported no errors for the above repro and allowed the name 'count' to bind to different
// variables within the same declaration space. According to the old spec the error should be reported.
// In Roslyn the single definition rule is relaxed and we do not give an error, but for a different reason.
CreateCompilation(source).VerifyDiagnostics();
}
[Fact, WorkItem(530301, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530301")]
public void NoMore_CS0458WRN_AlwaysNull02()
{
CreateCompilation(
@"
public class Test
{
const bool ct = true;
public static int Main()
{
var a = (true & null) ?? null; // CS0458
if (((null & true) == null)) // CS0458
return 0;
var b = !(null | false); // CS0458
if ((false | null) != null) // CS0458
return 1;
const bool cf = false;
var d = ct & null ^ null; // CS0458 - Roslyn Warn this ONLY
d ^= !(null | cf); // CS0458
return -1;
}
}
")
// We decided to not report WRN_AlwaysNull in some cases.
.VerifyDiagnostics(
// Diagnostic(ErrorCode.WRN_AlwaysNull, "true & null").WithArguments("bool?"),
// Diagnostic(ErrorCode.WRN_AlwaysNull, "null & true").WithArguments("bool?"),
// Diagnostic(ErrorCode.WRN_AlwaysNull, "null | false").WithArguments("bool?"),
// Diagnostic(ErrorCode.WRN_AlwaysNull, "false | null").WithArguments("bool?"),
Diagnostic(ErrorCode.WRN_AlwaysNull, "ct & null ^ null").WithArguments("bool?") //,
// Diagnostic(ErrorCode.WRN_AlwaysNull, "null | cf").WithArguments("bool?")
);
}
[WorkItem(530403, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530403")]
[Fact]
public void CS0135_local_param_cannot_be_declared()
{
// Dev11 missed this error. The issue is that an a is a field of c, and then it is a local in parts of d.
// by then referring to the field without the this keyword, it should be flagged as declaring a competing variable (as it is confusing).
var text = @"
using System;
public class @c
{
int a = 0;
void d(bool b) {
if(b)
{
int a = 1;
Console.WriteLine(a);
}
else
{
a = 2;
}
a = 3;
Console.WriteLine(a);
}
}
";
var comp = CreateCompilation(text);
// In Roslyn the single definition rule is relaxed and we do not give an error.
comp.VerifyDiagnostics();
}
[ConditionalFact(typeof(WindowsDesktopOnly), Reason = "https://github.com/dotnet/roslyn/issues/30160")]
[WorkItem(530518, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530518")]
public void ExpressionTreeExplicitOpVsConvert()
{
var text = @"
using System;
using System.Linq;
using System.Linq.Expressions;
class Test
{
public static explicit operator int(Test x) { return 1; }
static void Main()
{
Expression<Func<Test, long?>> testExpr1 = x => (long?)x;
Console.WriteLine(testExpr1);
Expression<Func<Test, decimal?>> testExpr2 = x => (decimal?)x;
Console.WriteLine(testExpr2);
}
}
";
// Native Compiler: x => Convert(Convert(op_Explicit(x)))
CompileAndVerify(text, expectedOutput:
@"x => Convert(Convert(Convert(x)))
x => Convert(Convert(Convert(x)))
");
}
[WorkItem(530531, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530531")]
[ConditionalFact(typeof(WindowsDesktopOnly), Reason = "https://github.com/dotnet/roslyn/issues/30160")]
public void ExpressionTreeNoCovertForIdentityConversion()
{
var source = @"
using System;
using System.Linq;
using System.Linq.Expressions;
class Test
{
static void Main()
{
Expression<Func<Guid, bool>> e = (x) => x != null;
Console.WriteLine(e);
Console.WriteLine(e.Compile()(default(Guid)));
}
}
";
// Native compiler: x => (Convert(x) != Convert(null))
CompileAndVerify(source, expectedOutput:
@"x => (Convert(x) != null)
True
");
}
[Fact, WorkItem(530548, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530548")]
public void CS0219WRN_UnreferencedVarAssg_RHSMidRefType()
{
string source = @"
public interface Base { }
public struct Derived : Base { }
public class Test
{
public static void Main()
{
var b1 = new Derived(); // Both Warning CS0219
var b2 = (Base)new Derived(); // Both NO Warn (reference type)
var b3 = (Derived)((Base)new Derived()); // Roslyn Warning CS0219
}
}
";
// Native compiler no error (print -123)
CreateCompilation(source).VerifyDiagnostics(
// (8,13): warning CS0219: The variable 'b1' is assigned but its value is never used
// var b1 = new Derived(); // Both Warning CS0219
Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "b1").WithArguments("b1"),
// (10,13): warning CS0219: The variable 'b3' is assigned but its value is never used
// var b3 = (Derived)((Base)new Derived()); // Roslyn Warning CS0219
Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "b3").WithArguments("b3"));
}
[Fact, WorkItem(530556, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530556")]
public void NoCS0591ERR_InvalidAttributeArgument()
{
string source = @"
using System;
[AttributeUsage(AttributeTargets.All + 0xFFFFFF)]
class MyAtt : Attribute { }
[AttributeUsage((AttributeTargets)0xffff)]
class MyAtt1 : Attribute { }
public class Test {}
";
// Native compiler error CS0591: Invalid value for argument to 'AttributeUsage' attribute
CreateCompilation(source).VerifyDiagnostics();
}
[Fact, WorkItem(530586, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530586")]
public void ThrowOnceInIteratorFinallyBlock()
{
string source = @"
//<Title> Finally block runs twice in iterator</Title>
//<RelatedBug>Dev10:473561-->8444?</RelatedBug>
using System;
using System.Collections;
class Program
{
public static void Main()
{
var demo = new test();
try
{
foreach (var x in demo.Goo()) { }
}
catch (Exception)
{
Console.Write(""EX "");
}
Console.WriteLine(demo.count);
}
class test
{
public int count = 0;
public IEnumerable Goo()
{
try
{
yield return null;
try
{
yield break;
}
catch
{ }
}
finally
{
Console.Write(""++ "");
++count;
throw new Exception();
}
}
}
}
";
// Native print "++ ++ EX 2"
var verifier = CompileAndVerify(source, expectedOutput: " ++ EX 1");
// must not load "<>4__this"
verifier.VerifyIL("Program.test.<Goo>d__1.System.Collections.IEnumerator.MoveNext()", @"
{
// Code size 101 (0x65)
.maxstack 2
.locals init (bool V_0,
int V_1)
.try
{
IL_0000: ldarg.0
IL_0001: ldfld ""int Program.test.<Goo>d__1.<>1__state""
IL_0006: stloc.1
IL_0007: ldloc.1
IL_0008: brfalse.s IL_0012
IL_000a: ldloc.1
IL_000b: ldc.i4.1
IL_000c: beq.s IL_0033
IL_000e: ldc.i4.0
IL_000f: stloc.0
IL_0010: leave.s IL_0063
IL_0012: ldarg.0
IL_0013: ldc.i4.m1
IL_0014: stfld ""int Program.test.<Goo>d__1.<>1__state""
IL_0019: ldarg.0
IL_001a: ldc.i4.s -3
IL_001c: stfld ""int Program.test.<Goo>d__1.<>1__state""
IL_0021: ldarg.0
IL_0022: ldnull
IL_0023: stfld ""object Program.test.<Goo>d__1.<>2__current""
IL_0028: ldarg.0
IL_0029: ldc.i4.1
IL_002a: stfld ""int Program.test.<Goo>d__1.<>1__state""
IL_002f: ldc.i4.1
IL_0030: stloc.0
IL_0031: leave.s IL_0063
IL_0033: ldarg.0
IL_0034: ldc.i4.s -3
IL_0036: stfld ""int Program.test.<Goo>d__1.<>1__state""
.try
{
IL_003b: ldc.i4.0
IL_003c: stloc.0
IL_003d: leave.s IL_004a
}
catch object
{
IL_003f: pop
IL_0040: leave.s IL_0042
}
IL_0042: ldarg.0
IL_0043: call ""void Program.test.<Goo>d__1.<>m__Finally1()""
IL_0048: br.s IL_0052
IL_004a: ldarg.0
IL_004b: call ""void Program.test.<Goo>d__1.<>m__Finally1()""
IL_0050: leave.s IL_0063
IL_0052: leave.s IL_005b
}
fault
{
IL_0054: ldarg.0
IL_0055: call ""void Program.test.<Goo>d__1.Dispose()""
IL_005a: endfinally
}
IL_005b: ldarg.0
IL_005c: call ""void Program.test.<Goo>d__1.Dispose()""
IL_0061: ldc.i4.1
IL_0062: stloc.0
IL_0063: ldloc.0
IL_0064: ret
}
");
// must load "<>4__this"
verifier.VerifyIL("Program.test.<Goo>d__1.<>m__Finally1()", @"
{
// Code size 42 (0x2a)
.maxstack 3
IL_0000: ldarg.0
IL_0001: ldc.i4.m1
IL_0002: stfld ""int Program.test.<Goo>d__1.<>1__state""
IL_0007: ldarg.0
IL_0008: ldfld ""Program.test Program.test.<Goo>d__1.<>4__this""
IL_000d: ldstr ""++ ""
IL_0012: call ""void System.Console.Write(string)""
IL_0017: dup
IL_0018: ldfld ""int Program.test.count""
IL_001d: ldc.i4.1
IL_001e: add
IL_001f: stfld ""int Program.test.count""
IL_0024: newobj ""System.Exception..ctor()""
IL_0029: throw
}
");
}
[Fact, WorkItem(530587, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530587")]
public void NoFormatCharInIDEqual()
{
string source = @"
#define A
using System;
class Program
{
static int Main()
{
int x = 0;
#if A == A\uFFFB
x=1;
#endif
Console.Write(x);
return x;
}
}
";
CompileAndVerify(source, expectedOutput: "1"); // Native print 0
}
[Fact, WorkItem(530614, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530614")]
public void CS1718WRN_ComparisonToSelf_Roslyn()
{
string source = @"
enum @esbyte : sbyte { e0, e1 };
public class z_1495j12
{
public static void Main()
{
if (esbyte.e0 == esbyte.e0)
{
System.Console.WriteLine(""T"");
}
}}
";
// Native compiler no warn
CreateCompilation(source).VerifyDiagnostics(
// (7,5): warning CS1718: Comparison made to same variable; did you mean to compare something else?
Diagnostic(ErrorCode.WRN_ComparisonToSelf, "esbyte.e0 == esbyte.e0"));
}
[Fact, WorkItem(530629, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530629")]
public void CS0414WRN_UnreferencedFieldAssg_Roslyn()
{
string source = @"
namespace VS7_336319
{
public sealed class PredefinedTypes
{
public class Kind { public static int Decimal; }
}
public class ExpressionBinder
{
private static PredefinedTypes PredefinedTypes = null;
private void Goo()
{
if (0 == (int)PredefinedTypes.Kind.Decimal) { }
}
}
}
";
// Native compiler no warn
CreateCompilation(source).VerifyDiagnostics(
// (10,40): warning CS0414: The field 'VS7_336319.ExpressionBinder.PredefinedTypes' is assigned but its value is never used
// private static PredefinedTypes PredefinedTypes = null;
Diagnostic(ErrorCode.WRN_UnreferencedFieldAssg, "PredefinedTypes").WithArguments("VS7_336319.ExpressionBinder.PredefinedTypes"));
}
[WorkItem(530666, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530666")]
[ConditionalFact(typeof(WindowsDesktopOnly), Reason = "https://github.com/dotnet/roslyn/issues/30160")]
public void ExpressionTreeWithNullableUDCandOperator()
{
string source = @"
using System;
using System.Linq.Expressions;
struct B
{
public static implicit operator int?(B x)
{
return 1;
}
public static int operator +(B x, int y)
{
return 2 + y;
}
static int Main()
{
Expression<Func<B, int?>> f = x => x + x;
var ret = f.Compile()(new B());
Console.WriteLine(ret);
return ret.Value - 3;
}
}
";
// Native compiler throw
CompileAndVerify(source, expectedOutput: "3");
}
[Fact, WorkItem(530696, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530696")]
public void CS0121Err_AmbiguousMethodCall()
{
string source = @"
class G<T> { }
class C
{
static void M(params double[] x)
{
System.Console.WriteLine(1);
}
static void M(params G<int>[] x)
{
System.Console.WriteLine(2);
}
static void Main()
{
M();
}
}
";
CreateCompilation(source).VerifyDiagnostics(
// (15,13): error CS0121: The call is ambiguous between the following methods or properties: 'C.M(params double[])' and 'C.M(params G<int>[])'
// M();
Diagnostic(ErrorCode.ERR_AmbigCall, "M").WithArguments("C.M(params double[])", "C.M(params G<int>[])"));
}
[Fact, WorkItem(530653, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530653")]
public void RepeatedObsoleteWarnings()
{
// <quote source="Srivatsn's comments from bug 16642">
// Inside a method body if you access a static field twice thus:
//
// var x = ObsoleteType.field1;
// var y = ObsoleteType.field1;
//
// then the native compiler reports ObsoleteType as obsolete only once. This is because the native compiler caches
// the lookup of type names for certain cases and doesn't report errors on the second lookup as that just comes
// from the cache. Note how I said caches sometimes. If you simply say -
//
// var x= new ObsoleteType();
// var y = new ObsoleteType();
//
// Then the native compiler reports the error twice. I don't think we should replicate this in Roslyn. Note however
// that this is a breaking change because if the first line had been #pragma disabled, then the code would compile
// without warnings in Dev11 but we will report warnings. I think it's a corner enough scenario and the native
// behavior is quirky enough to warrant a break.
// </quote>
CompileAndVerify(@"
using System;
[Obsolete]
public class ObsoleteType
{
public static readonly int field = 0;
}
public class Program
{
public static void Main()
{
#pragma warning disable 0612
var x = ObsoleteType.field;
#pragma warning restore 0612
var y = ObsoleteType.field; // In Dev11, this line doesn't produce a warning.
}
}").VerifyDiagnostics(
// (15,17): warning CS0612: 'ObsoleteType' is obsolete
// var y = ObsoleteType.field;
Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "ObsoleteType").WithArguments("ObsoleteType"));
}
[Fact, WorkItem(530303, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530303")]
public void TestReferenceResolution()
{
var cs1Compilation = CreateCSharpCompilation("CS1",
@"public class CS1 {}",
compilationOptions: TestOptions.ReleaseDll);
var cs1Verifier = CompileAndVerify(cs1Compilation);
cs1Verifier.VerifyDiagnostics();
var cs2Compilation = CreateCSharpCompilation("CS2",
@"public class CS2<T> {}",
compilationOptions: TestOptions.ReleaseDll,
referencedCompilations: new Compilation[] { cs1Compilation });
var cs2Verifier = CompileAndVerify(cs2Compilation);
cs2Verifier.VerifyDiagnostics();
var cs3Compilation = CreateCSharpCompilation("CS3",
@"public class CS3 : CS2<CS1> {}",
compilationOptions: TestOptions.ReleaseDll,
referencedCompilations: new Compilation[] { cs1Compilation, cs2Compilation });
var cs3Verifier = CompileAndVerify(cs3Compilation);
cs3Verifier.VerifyDiagnostics();
var cs4Compilation = CreateCSharpCompilation("CS4",
@"public class Program
{
static void Main()
{
System.Console.WriteLine(typeof(CS3));
}
}",
compilationOptions: TestOptions.ReleaseExe,
referencedCompilations: new Compilation[] { cs2Compilation, cs3Compilation });
cs4Compilation.VerifyDiagnostics();
}
[Fact, WorkItem(531014, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531014")]
public void TestVariableAndTypeNameClashes()
{
CompileAndVerify(@"
using System;
public class Class1
{
internal class A4 { internal class B { } internal static string F() { return ""A4""; } }
internal class A5 { internal class B { } internal static string F() { return ""A5""; } }
internal class A6 { internal class B { } internal static string F() { return ""A6""; } }
internal delegate void D(); // Check the weird E.M cases.
internal class Outer2
{
internal static void F(A4 A4)
{
A5 A5; const A6 A6 = null;
Console.WriteLine(typeof(A4.B));
Console.WriteLine(typeof(A5.B));
Console.WriteLine(typeof(A6.B));
Console.WriteLine(A4.F());
Console.WriteLine(A5.F());
Console.WriteLine(A6.F());
Console.WriteLine(default(A4) == null);
Console.WriteLine(default(A5) == null);
Console.WriteLine(default(A6) == null);
}
}
}").VerifyDiagnostics(
// Breaking Change: See bug 17395. Dev11 had a bug because of which it didn't report the below warnings.
// (13,16): warning CS0168: The variable 'A5' is declared but never used
// A5 A5; const A6 A6 = null;
Diagnostic(ErrorCode.WRN_UnreferencedVar, "A5").WithArguments("A5"),
// (13,29): warning CS0219: The variable 'A6' is assigned but its value is never used
// A5 A5; const A6 A6 = null;
Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "A6").WithArguments("A6"));
}
[WorkItem(530584, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530584")]
[Fact]
public void NotRuntimeAmbiguousBecauseOfReturnTypes()
{
var source = @"
using System;
class Base<T, S>
{
public virtual int Goo(ref S x) { return 0; }
public virtual string Goo(out T x)
{
x = default(T); return ""Base.Out"";
}
}
class Derived : Base<int, int>
{
public override string Goo(out int x)
{
x = 0; return ""Derived.Out"";
}
static void Main()
{
int x;
Console.WriteLine(new Derived().Goo(out x));
}
}
";
// BREAK: Dev11 reports WRN_MultipleRuntimeOverrideMatches, but there
// is no runtime ambiguity because the return types differ.
CompileAndVerify(source, expectedOutput: "Derived.Out");
}
[WorkItem(695311, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/695311")]
[Fact]
public void NestedCollectionInitializerOnGenericProperty()
{
var libSource = @"
using System.Collections;
public interface IAdd
{
void Add(object o);
}
public struct S : IEnumerable, IAdd
{
private ArrayList list;
public void Add(object o)
{
list = list ?? new ArrayList();
list.Add(o);
}
public IEnumerator GetEnumerator()
{
return (list ?? new ArrayList()).GetEnumerator();
}
}
public class C : IEnumerable, IAdd
{
private readonly ArrayList list = new ArrayList();
public void Add(object o)
{
list.Add(o);
}
public IEnumerator GetEnumerator()
{
return list.GetEnumerator();
}
}
public class Wrapper<T> : IEnumerable where T : IEnumerable, new()
{
public Wrapper()
{
this.Item = new T();
}
public T Item { get; private set; }
public IEnumerator GetEnumerator()
{
return Item.GetEnumerator();
}
}
public static class Util
{
public static int Count(IEnumerable i)
{
int count = 0;
foreach (var v in i) count++;
return count;
}
}
";
var libRef = CreateCompilation(libSource, assemblyName: "lib").EmitToImageReference();
{
var source = @"
using System;
using System.Collections;
class Test
{
static void Main()
{
Console.Write(Util.Count(Goo<S>()));
Console.Write(Util.Count(Goo<C>()));
}
static Wrapper<T> Goo<T>() where T : IEnumerable, IAdd, new()
{
return new Wrapper<T> { Item = { 1, 2, 3} };
}
}
";
// As in dev11.
var comp = CreateCompilation(source, new[] { libRef }, TestOptions.ReleaseExe);
CompileAndVerify(comp, expectedOutput: "03");
}
{
var source = @"
using System;
using System.Collections;
class Test
{
static void Main()
{
Console.Write(Util.Count(Goo<C>()));
}
static Wrapper<T> Goo<T>() where T : class, IEnumerable, IAdd, new()
{
return new Wrapper<T> { Item = { 1, 2, 3} };
}
}
";
// As in dev11.
// NOTE: The spec will likely be updated to make this illegal.
var comp = CreateCompilation(source, new[] { libRef }, TestOptions.ReleaseExe);
var verifier = CompileAndVerify(comp, expectedOutput: "3");
verifier.VerifyIL("Test.Goo<T>()", @"
{
// Code size 72 (0x48)
.maxstack 3
IL_0000: newobj ""Wrapper<T>..ctor()""
IL_0005: dup
IL_0006: callvirt ""T Wrapper<T>.Item.get""
IL_000b: box ""T""
IL_0010: ldc.i4.1
IL_0011: box ""int""
IL_0016: callvirt ""void IAdd.Add(object)""
IL_001b: dup
IL_001c: callvirt ""T Wrapper<T>.Item.get""
IL_0021: box ""T""
IL_0026: ldc.i4.2
IL_0027: box ""int""
IL_002c: callvirt ""void IAdd.Add(object)""
IL_0031: dup
IL_0032: callvirt ""T Wrapper<T>.Item.get""
IL_0037: box ""T""
IL_003c: ldc.i4.3
IL_003d: box ""int""
IL_0042: callvirt ""void IAdd.Add(object)""
IL_0047: ret
}
");
}
{
var source = @"
using System;
using System.Collections;
class Test
{
static void Main()
{
Console.Write(Util.Count(Goo<S>()));
}
static Wrapper<T> Goo<T>() where T : struct, IEnumerable, IAdd
{
return new Wrapper<T> { Item = { 1, 2, 3} };
}
}
";
// BREAK: dev11 compiles and prints "0"
var comp = CreateCompilation(source, new[] { libRef }, TestOptions.ReleaseExe);
comp.VerifyDiagnostics(
// (15,33): error CS1918: Members of property 'Wrapper<T>.Item' of type 'T' cannot be assigned with an object initializer because it is of a value type
// return new Wrapper<T> { Item = { 1, 2, 3} };
Diagnostic(ErrorCode.ERR_ValueTypePropertyInObjectInitializer, "Item").WithArguments("Wrapper<T>.Item", "T"));
}
}
[Fact, WorkItem(770424, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/770424"), WorkItem(1079034, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1079034")]
public void UserDefinedShortCircuitingOperators()
{
var source = @"
public class Base
{
public static bool operator true(Base x)
{
System.Console.Write(""Base.op_True"");
return x != null;
}
public static bool operator false(Base x)
{
System.Console.Write(""Base.op_False"");
return x == null;
}
}
public class Derived : Base
{
public static Derived operator&(Derived x, Derived y)
{
return x;
}
public static Derived operator|(Derived x, Derived y)
{
return y;
}
static void Main()
{
Derived d = new Derived();
var b = (d && d) || d;
}
}
";
CompileAndVerify(source, expectedOutput: "Base.op_FalseBase.op_True");
}
}
}
|