|
// 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 System.Threading;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Symbols
{
/// <summary>
/// Test interface member hiding.
/// </summary>
public class InterfaceOverriddenOrHiddenMembersTests : CSharpTestBase
{
[WorkItem(581173, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/581173")]
[Fact]
public void Repro581173()
{
var source = @"
interface I3
{
int goo { get; set; }
}
interface I1 : I3 { }
interface I2 : I3
{
new void goo();
}
interface I0 : I1, I2
{
new void goo(int x);
}
";
CreateCompilation(source).VerifyDiagnostics(
// (13,14): warning CS0109: The member 'I0.goo(int)' does not hide an accessible member. The new keyword is not required.
// new void goo(int x);
Diagnostic(ErrorCode.WRN_NewNotRequired, "goo").WithArguments("I0.goo(int)"));
}
/// <summary>
/// For this series of tests, we're going to use a fixed type hierarchy and a single member signature "void M()".
/// We will start with the signature in all interfaces, and then remove it from various subsets.
///
/// ITop
/// / \
/// ILeft IRight
/// \ /
/// IBottom
///
/// All have method.
/// </summary>
[WorkItem(581173, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/581173")]
[Fact]
public void TestDiamond_Method_1()
{
var source = @"
public interface ITop
{
void M();
}
public interface ILeft : ITop
{
void M();
}
public interface IRight : ITop
{
void M();
}
public interface IBottom : ILeft, IRight
{
void M();
}
";
CreateCompilation(source).VerifyDiagnostics(
// (9,10): warning CS0108: 'ILeft.M()' hides inherited member 'ITop.M()'. Use the new keyword if hiding was intended.
// void M();
Diagnostic(ErrorCode.WRN_NewRequired, "M").WithArguments("ILeft.M()", "ITop.M()"),
// (14,10): warning CS0108: 'IRight.M()' hides inherited member 'ITop.M()'. Use the new keyword if hiding was intended.
// void M();
Diagnostic(ErrorCode.WRN_NewRequired, "M").WithArguments("IRight.M()", "ITop.M()"),
// (19,10): warning CS0108: 'IBottom.M()' hides inherited member 'ILeft.M()'. Use the new keyword if hiding was intended.
// void M();
Diagnostic(ErrorCode.WRN_NewRequired, "M").WithArguments("IBottom.M()", "ILeft.M()"));
}
/// <summary>
/// All have method but IRight.
/// </summary>
[WorkItem(581173, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/581173")]
[Fact]
public void TestDiamond_Method_2()
{
var source = @"
public interface ITop
{
void M();
}
public interface ILeft : ITop
{
void M();
}
public interface IRight : ITop
{
// void M();
}
public interface IBottom : ILeft, IRight
{
void M();
}
";
CreateCompilation(source).VerifyDiagnostics(
// (9,10): warning CS0108: 'ILeft.M()' hides inherited member 'ITop.M()'. Use the new keyword if hiding was intended.
// void M();
Diagnostic(ErrorCode.WRN_NewRequired, "M").WithArguments("ILeft.M()", "ITop.M()"),
// (19,10): warning CS0108: 'IBottom.M()' hides inherited member 'ILeft.M()'. Use the new keyword if hiding was intended.
// void M();
Diagnostic(ErrorCode.WRN_NewRequired, "M").WithArguments("IBottom.M()", "ILeft.M()"));
}
/// <summary>
/// All have method but ILeft and IRight.
/// </summary>
[WorkItem(581173, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/581173")]
[Fact]
public void TestDiamond_Method_3()
{
var source = @"
public interface ITop
{
void M();
}
public interface ILeft : ITop
{
// void M();
}
public interface IRight : ITop
{
// void M();
}
public interface IBottom : ILeft, IRight
{
void M();
}
";
CreateCompilation(source).VerifyDiagnostics(
// (19,10): warning CS0108: 'IBottom.M()' hides inherited member 'ITop.M()'. Use the new keyword if hiding was intended.
// void M();
Diagnostic(ErrorCode.WRN_NewRequired, "M").WithArguments("IBottom.M()", "ITop.M()"));
}
/// <summary>
/// All have method but ITop.
/// </summary>
[WorkItem(581173, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/581173")]
[Fact]
public void TestDiamond_Method_4()
{
var source = @"
public interface ITop
{
// void M();
}
public interface ILeft : ITop
{
void M();
}
public interface IRight : ITop
{
void M();
}
public interface IBottom : ILeft, IRight
{
void M();
}
";
// Also hides IRight.M, but not reported.
CreateCompilation(source).VerifyDiagnostics(
// (19,10): warning CS0108: 'IBottom.M()' hides inherited member 'ILeft.M()'. Use the new keyword if hiding was intended.
// void M();
Diagnostic(ErrorCode.WRN_NewRequired, "M").WithArguments("IBottom.M()", "ILeft.M()"));
}
/// <summary>
/// All have method but ITop and IRight.
/// </summary>
[WorkItem(581173, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/581173")]
[Fact]
public void TestDiamond_Method_5()
{
var source = @"
public interface ITop
{
// void M();
}
public interface ILeft : ITop
{
void M();
}
public interface IRight : ITop
{
// void M();
}
public interface IBottom : ILeft, IRight
{
void M();
}
";
CreateCompilation(source).VerifyDiagnostics(
// (19,10): warning CS0108: 'IBottom.M()' hides inherited member 'ILeft.M()'. Use the new keyword if hiding was intended.
// void M();
Diagnostic(ErrorCode.WRN_NewRequired, "M").WithArguments("IBottom.M()", "ILeft.M()"));
}
/// <summary>
/// These tests are the same as the TestDiamond_Method tests except that, instead of removing the method
/// from some interfaces, we'll change its parameter list in those interfaces.
///
/// ITop
/// / \
/// ILeft IRight
/// \ /
/// IBottom
///
/// All have unmodified method.
/// </summary>
[WorkItem(581173, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/581173")]
[Fact]
public void TestDiamond_Overload_1()
{
// Identical to TestDiamond_Method_1, so omitted.
}
/// <summary>
/// All have unmodified method but IRight.
/// </summary>
[WorkItem(581173, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/581173")]
[Fact]
public void TestDiamond_Overload_2()
{
var source = @"
public interface ITop
{
void M();
}
public interface ILeft : ITop
{
void M();
}
public interface IRight : ITop
{
void M(int x);
}
public interface IBottom : ILeft, IRight
{
void M();
}
";
CreateCompilation(source).VerifyDiagnostics(
// (9,10): warning CS0108: 'ILeft.M()' hides inherited member 'ITop.M()'. Use the new keyword if hiding was intended.
// void M();
Diagnostic(ErrorCode.WRN_NewRequired, "M").WithArguments("ILeft.M()", "ITop.M()"),
// (19,10): warning CS0108: 'IBottom.M()' hides inherited member 'ILeft.M()'. Use the new keyword if hiding was intended.
// void M();
Diagnostic(ErrorCode.WRN_NewRequired, "M").WithArguments("IBottom.M()", "ILeft.M()"));
}
/// <summary>
/// All have unmodified method but ILeft and IRight.
/// </summary>
[WorkItem(581173, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/581173")]
[Fact]
public void TestDiamond_Overload_3()
{
var source = @"
public interface ITop
{
void M();
}
public interface ILeft : ITop
{
void M(int x);
}
public interface IRight : ITop
{
void M(int x);
}
public interface IBottom : ILeft, IRight
{
void M();
}
";
CreateCompilation(source).VerifyDiagnostics(
// (19,10): warning CS0108: 'IBottom.M()' hides inherited member 'ITop.M()'. Use the new keyword if hiding was intended.
// void M();
Diagnostic(ErrorCode.WRN_NewRequired, "M").WithArguments("IBottom.M()", "ITop.M()"));
}
/// <summary>
/// All have unmodified method but ITop.
/// </summary>
[WorkItem(581173, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/581173")]
[Fact]
public void TestDiamond_Overload_4()
{
var source = @"
public interface ITop
{
void M(int x);
}
public interface ILeft : ITop
{
void M();
}
public interface IRight : ITop
{
void M();
}
public interface IBottom : ILeft, IRight
{
void M();
}
";
// Also hides IRight.M, but not reported.
CreateCompilation(source).VerifyDiagnostics(
// (19,10): warning CS0108: 'IBottom.M()' hides inherited member 'ILeft.M()'. Use the new keyword if hiding was intended.
// void M();
Diagnostic(ErrorCode.WRN_NewRequired, "M").WithArguments("IBottom.M()", "ILeft.M()"));
}
/// <summary>
/// All have unmodified method but ITop and IRight.
/// Unlike the other TestDiamond_Overload tests, this one reports different diagnostics than its TestDiamond_Method counterpart.
/// </summary>
[WorkItem(581173, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/581173")]
[Fact]
public void TestDiamond_Overload_5()
{
var source = @"
public interface ITop
{
void M(int x);
}
public interface ILeft : ITop
{
void M();
}
public interface IRight : ITop
{
void M(int x);
}
public interface IBottom : ILeft, IRight
{
void M();
}
";
CreateCompilation(source).VerifyDiagnostics(
// (19,10): warning CS0108: 'IBottom.M()' hides inherited member 'ILeft.M()'. Use the new keyword if hiding was intended.
// void M();
Diagnostic(ErrorCode.WRN_NewRequired, "M").WithArguments("IBottom.M()", "ILeft.M()"),
// (14,10): warning CS0108: 'IRight.M(int)' hides inherited member 'ITop.M(int)'. Use the new keyword if hiding was intended.
// void M(int x);
Diagnostic(ErrorCode.WRN_NewRequired, "M").WithArguments("IRight.M(int)", "ITop.M(int)"));
}
/// <summary>
/// These tests are the same as the TestDiamond_Method tests except that, instead of removing the method
/// from some interfaces, we'll change its type parameter list in those interfaces.
///
/// ITop
/// / \
/// ILeft IRight
/// \ /
/// IBottom
///
/// All have unmodified method.
/// </summary>
[WorkItem(581173, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/581173")]
[Fact]
public void TestDiamond_Arity_1()
{
// Identical to TestDiamond_Method_1, so omitted.
}
/// <summary>
/// All have unmodified method but IRight.
/// </summary>
[WorkItem(581173, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/581173")]
[Fact]
public void TestDiamond_Arity_2()
{
var source = @"
public interface ITop
{
void M();
}
public interface ILeft : ITop
{
void M();
}
public interface IRight : ITop
{
void M<T>();
}
public interface IBottom : ILeft, IRight
{
void M();
}
";
CreateCompilation(source).VerifyDiagnostics(
// (9,10): warning CS0108: 'ILeft.M()' hides inherited member 'ITop.M()'. Use the new keyword if hiding was intended.
// void M();
Diagnostic(ErrorCode.WRN_NewRequired, "M").WithArguments("ILeft.M()", "ITop.M()"),
// (19,10): warning CS0108: 'IBottom.M()' hides inherited member 'ILeft.M()'. Use the new keyword if hiding was intended.
// void M();
Diagnostic(ErrorCode.WRN_NewRequired, "M").WithArguments("IBottom.M()", "ILeft.M()"));
}
/// <summary>
/// All have unmodified method but ILeft and IRight.
/// </summary>
[WorkItem(581173, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/581173")]
[Fact]
public void TestDiamond_Arity_3()
{
var source = @"
public interface ITop
{
void M();
}
public interface ILeft : ITop
{
void M<T>();
}
public interface IRight : ITop
{
void M<T>();
}
public interface IBottom : ILeft, IRight
{
void M();
}
";
CreateCompilation(source).VerifyDiagnostics(
// (19,10): warning CS0108: 'IBottom.M()' hides inherited member 'ITop.M()'. Use the new keyword if hiding was intended.
// void M();
Diagnostic(ErrorCode.WRN_NewRequired, "M").WithArguments("IBottom.M()", "ITop.M()"));
}
/// <summary>
/// All have unmodified method but ITop.
/// </summary>
[WorkItem(581173, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/581173")]
[Fact]
public void TestDiamond_Arity_4()
{
var source = @"
public interface ITop
{
void M<T>();
}
public interface ILeft : ITop
{
void M();
}
public interface IRight : ITop
{
void M();
}
public interface IBottom : ILeft, IRight
{
void M();
}
";
// Also hides IRight.M, but not reported.
CreateCompilation(source).VerifyDiagnostics(
// (19,10): warning CS0108: 'IBottom.M()' hides inherited member 'ILeft.M()'. Use the new keyword if hiding was intended.
// void M();
Diagnostic(ErrorCode.WRN_NewRequired, "M").WithArguments("IBottom.M()", "ILeft.M()"));
}
/// <summary>
/// All have unmodified method but ITop and IRight.
/// Unlike the other TestDiamond_Overload tests, this one reports different diagnostics than its TestDiamond_Method counterpart.
/// </summary>
[WorkItem(581173, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/581173")]
[Fact]
public void TestDiamond_Arity_5()
{
var source = @"
public interface ITop
{
void M<T>();
}
public interface ILeft : ITop
{
void M();
}
public interface IRight : ITop
{
void M<T>();
}
public interface IBottom : ILeft, IRight
{
void M();
}
";
CreateCompilation(source).VerifyDiagnostics(
// (19,10): warning CS0108: 'IBottom.M()' hides inherited member 'ILeft.M()'. Use the new keyword if hiding was intended.
// void M();
Diagnostic(ErrorCode.WRN_NewRequired, "M").WithArguments("IBottom.M()", "ILeft.M()"),
// (14,10): warning CS0108: 'IRight.M<T>()' hides inherited member 'ITop.M<T>()'. Use the new keyword if hiding was intended.
// void M<T>();
Diagnostic(ErrorCode.WRN_NewRequired, "M").WithArguments("IRight.M<T>()", "ITop.M<T>()"));
}
/// <summary>
/// These tests are the same as the TestDiamond_Method tests except that, instead of removing the method
/// from some interfaces, we'll change its member kind (to Property) in those interfaces.
///
/// ITop
/// / \
/// ILeft IRight
/// \ /
/// IBottom
///
/// All have unmodified method.
/// </summary>
[WorkItem(581173, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/581173")]
[Fact]
public void TestDiamond_Kind_1()
{
// Identical to TestDiamond_Method_1, so omitted.
}
/// <summary>
/// All have unmodified method but IRight.
/// </summary>
[WorkItem(581173, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/581173")]
[Fact]
public void TestDiamond_Kind_2()
{
var source = @"
public interface ITop
{
void M();
}
public interface ILeft : ITop
{
void M();
}
public interface IRight : ITop
{
int M { get; set; }
}
public interface IBottom : ILeft, IRight
{
void M();
}
";
CreateCompilation(source).VerifyDiagnostics(
// (9,10): warning CS0108: 'ILeft.M()' hides inherited member 'ITop.M()'. Use the new keyword if hiding was intended.
// void M();
Diagnostic(ErrorCode.WRN_NewRequired, "M").WithArguments("ILeft.M()", "ITop.M()"),
// (19,10): warning CS0108: 'IBottom.M()' hides inherited member 'ILeft.M()'. Use the new keyword if hiding was intended.
// void M();
Diagnostic(ErrorCode.WRN_NewRequired, "M").WithArguments("IBottom.M()", "ILeft.M()"),
// (14,9): warning CS0108: 'IRight.M' hides inherited member 'ITop.M()'. Use the new keyword if hiding was intended.
// int M { get; set; }
Diagnostic(ErrorCode.WRN_NewRequired, "M").WithArguments("IRight.M", "ITop.M()"));
}
/// <summary>
/// All have unmodified method but ILeft and IRight.
/// </summary>
[WorkItem(581173, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/581173")]
[Fact]
public void TestDiamond_Kind_3()
{
var source = @"
public interface ITop
{
void M();
}
public interface ILeft : ITop
{
int M { get; set; }
}
public interface IRight : ITop
{
int M { get; set; }
}
public interface IBottom : ILeft, IRight
{
void M();
}
";
CreateCompilation(source).VerifyDiagnostics(
// (19,10): warning CS0108: 'IBottom.M()' hides inherited member 'ILeft.M'. Use the new keyword if hiding was intended.
// void M();
Diagnostic(ErrorCode.WRN_NewRequired, "M").WithArguments("IBottom.M()", "ILeft.M"),
// (9,9): warning CS0108: 'ILeft.M' hides inherited member 'ITop.M()'. Use the new keyword if hiding was intended.
// int M { get; set; }
Diagnostic(ErrorCode.WRN_NewRequired, "M").WithArguments("ILeft.M", "ITop.M()"),
// (14,9): warning CS0108: 'IRight.M' hides inherited member 'ITop.M()'. Use the new keyword if hiding was intended.
// int M { get; set; }
Diagnostic(ErrorCode.WRN_NewRequired, "M").WithArguments("IRight.M", "ITop.M()"));
}
/// <summary>
/// All have unmodified method but ITop.
/// </summary>
[WorkItem(581173, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/581173")]
[Fact]
public void TestDiamond_Kind_4()
{
var source = @"
public interface ITop
{
int M { get; set; }
}
public interface ILeft : ITop
{
void M();
}
public interface IRight : ITop
{
void M();
}
public interface IBottom : ILeft, IRight
{
void M();
}
";
// Also hides IRight.M, but not reported.
CreateCompilation(source).VerifyDiagnostics(
// (14,10): warning CS0108: 'IRight.M()' hides inherited member 'ITop.M'. Use the new keyword if hiding was intended.
// void M();
Diagnostic(ErrorCode.WRN_NewRequired, "M").WithArguments("IRight.M()", "ITop.M"),
// (9,10): warning CS0108: 'ILeft.M()' hides inherited member 'ITop.M'. Use the new keyword if hiding was intended.
// void M();
Diagnostic(ErrorCode.WRN_NewRequired, "M").WithArguments("ILeft.M()", "ITop.M"),
// (19,10): warning CS0108: 'IBottom.M()' hides inherited member 'ILeft.M()'. Use the new keyword if hiding was intended.
// void M();
Diagnostic(ErrorCode.WRN_NewRequired, "M").WithArguments("IBottom.M()", "ILeft.M()"));
}
/// <summary>
/// All have unmodified method but ITop and IRight.
/// Unlike the other TestDiamond_Overload tests, this one reports different diagnostics than its TestDiamond_Method counterpart.
/// </summary>
[WorkItem(581173, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/581173")]
[Fact]
public void TestDiamond_Kind_5()
{
var source = @"
public interface ITop
{
int M { get; set; }
}
public interface ILeft : ITop
{
void M();
}
public interface IRight : ITop
{
int M { get; set; }
}
public interface IBottom : ILeft, IRight
{
void M();
}
";
CreateCompilation(source).VerifyDiagnostics(
// (14,9): warning CS0108: 'IRight.M' hides inherited member 'ITop.M'. Use the new keyword if hiding was intended.
// int M { get; set; }
Diagnostic(ErrorCode.WRN_NewRequired, "M").WithArguments("IRight.M", "ITop.M"),
// (19,10): warning CS0108: 'IBottom.M()' hides inherited member 'ILeft.M()'. Use the new keyword if hiding was intended.
// void M();
Diagnostic(ErrorCode.WRN_NewRequired, "M").WithArguments("IBottom.M()", "ILeft.M()"),
// (9,10): warning CS0108: 'ILeft.M()' hides inherited member 'ITop.M'. Use the new keyword if hiding was intended.
// void M();
Diagnostic(ErrorCode.WRN_NewRequired, "M").WithArguments("ILeft.M()", "ITop.M"));
}
[Fact]
[WorkItem(661370, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/661370")]
public void HideAndOverride()
{
var source = @"
public interface Base
{
void M();
int M { get; set; } // NOTE: illegal, since there's already a method M.
}
public interface Derived1 : Base
{
void M();
}
public interface Derived2 : Base
{
int M { get; set; }
}
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (5,9): error CS0102: The type 'Base' already contains a definition for 'M'
// int M { get; set; } // NOTE: illegal, since there's already a method M.
Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "M").WithArguments("Base", "M"),
// (15,10): warning CS0108: 'Derived2.M' hides inherited member 'Base.M'. Use the new keyword if hiding was intended.
// int M { get; set; }
Diagnostic(ErrorCode.WRN_NewRequired, "M").WithArguments("Derived2.M", "Base.M"),
// (10,11): warning CS0108: 'Derived1.M()' hides inherited member 'Base.M()'. Use the new keyword if hiding was intended.
// void M();
Diagnostic(ErrorCode.WRN_NewRequired, "M").WithArguments("Derived1.M()", "Base.M()"));
var global = comp.GlobalNamespace;
var baseInterface = global.GetMember<NamedTypeSymbol>("Base");
var baseMethod = baseInterface.GetMembers("M").OfType<MethodSymbol>().Single();
var baseProperty = baseInterface.GetMembers("M").OfType<PropertySymbol>().Single();
var derivedInterface1 = global.GetMember<NamedTypeSymbol>("Derived1");
var derivedMethod = derivedInterface1.GetMember<MethodSymbol>("M");
var overriddenOrHidden1 = derivedMethod.OverriddenOrHiddenMembers;
AssertEx.SetEqual(overriddenOrHidden1.HiddenMembers, baseMethod, baseProperty);
var derivedInterface2 = global.GetMember<NamedTypeSymbol>("Derived2");
var derivedProperty = derivedInterface2.GetMember<PropertySymbol>("M");
var overriddenOrHidden2 = derivedProperty.OverriddenOrHiddenMembers;
AssertEx.SetEqual(overriddenOrHidden2.HiddenMembers, baseMethod, baseProperty);
}
[Fact]
[WorkItem(667278, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/667278")]
public void FalseIdentificationOfCircularDependency()
{
var source = @"
public class ITest : ITest.Test{
public interface Test { }
}";
CreateCompilation(source).VerifyDiagnostics();
}
[Fact]
[CompilerTrait(CompilerFeature.ReadOnlyReferences)]
public void HidingMethodWithInParameter()
{
var code = @"
interface A
{
void M(in int x);
}
interface B : A
{
void M(in int x);
}";
var comp = CreateCompilation(code).VerifyDiagnostics(
// (8,10): warning CS0108: 'B.M(in int)' hides inherited member 'A.M(in int)'. Use the new keyword if hiding was intended.
// void M(in int x);
Diagnostic(ErrorCode.WRN_NewRequired, "M").WithArguments("B.M(in int)", "A.M(in int)").WithLocation(8, 10));
var aMethod = comp.GetMember<MethodSymbol>("A.M");
var bMethod = comp.GetMember<MethodSymbol>("B.M");
Assert.Empty(aMethod.OverriddenOrHiddenMembers.OverriddenMembers);
Assert.Empty(aMethod.OverriddenOrHiddenMembers.HiddenMembers);
Assert.Empty(bMethod.OverriddenOrHiddenMembers.OverriddenMembers);
Assert.Equal(aMethod, bMethod.OverriddenOrHiddenMembers.HiddenMembers.Single());
}
[Fact]
[CompilerTrait(CompilerFeature.ReadOnlyReferences)]
public void HidingMethodWithRefReadOnlyReturnType_RefReadOnly_RefReadOnly()
{
var code = @"
interface A
{
ref readonly int M();
}
interface B : A
{
ref readonly int M();
}";
var comp = CreateCompilation(code).VerifyDiagnostics(
// (8,22): warning CS0108: 'B.M()' hides inherited member 'A.M()'. Use the new keyword if hiding was intended.
// ref readonly int M();
Diagnostic(ErrorCode.WRN_NewRequired, "M").WithArguments("B.M()", "A.M()").WithLocation(8, 22));
var aMethod = comp.GetMember<MethodSymbol>("A.M");
var bMethod = comp.GetMember<MethodSymbol>("B.M");
Assert.Empty(aMethod.OverriddenOrHiddenMembers.OverriddenMembers);
Assert.Empty(aMethod.OverriddenOrHiddenMembers.HiddenMembers);
Assert.Empty(bMethod.OverriddenOrHiddenMembers.OverriddenMembers);
Assert.Equal(aMethod, bMethod.OverriddenOrHiddenMembers.HiddenMembers.Single());
}
[Fact]
[CompilerTrait(CompilerFeature.ReadOnlyReferences)]
public void HidingMethodWithRefReadOnlyReturnType_Ref_RefReadOnly()
{
var code = @"
interface A
{
ref int M();
}
interface B : A
{
ref readonly int M();
}";
var comp = CreateCompilation(code).VerifyDiagnostics(
// (8,22): warning CS0108: 'B.M()' hides inherited member 'A.M()'. Use the new keyword if hiding was intended.
// ref readonly int M();
Diagnostic(ErrorCode.WRN_NewRequired, "M").WithArguments("B.M()", "A.M()").WithLocation(8, 22));
var aMethod = comp.GetMember<MethodSymbol>("A.M");
var bMethod = comp.GetMember<MethodSymbol>("B.M");
Assert.Empty(aMethod.OverriddenOrHiddenMembers.OverriddenMembers);
Assert.Empty(aMethod.OverriddenOrHiddenMembers.HiddenMembers);
Assert.Empty(bMethod.OverriddenOrHiddenMembers.OverriddenMembers);
Assert.Equal(aMethod, bMethod.OverriddenOrHiddenMembers.HiddenMembers.Single());
}
[Fact]
[CompilerTrait(CompilerFeature.ReadOnlyReferences)]
public void HidingMethodWithRefReadOnlyReturnType_RefReadOnly_Ref()
{
var code = @"
interface A
{
ref readonly int M();
}
interface B : A
{
ref int M();
}";
var comp = CreateCompilation(code).VerifyDiagnostics(
// (8,13): warning CS0108: 'B.M()' hides inherited member 'A.M()'. Use the new keyword if hiding was intended.
// ref readonly int M();
Diagnostic(ErrorCode.WRN_NewRequired, "M").WithArguments("B.M()", "A.M()").WithLocation(8, 13));
var aMethod = comp.GetMember<MethodSymbol>("A.M");
var bMethod = comp.GetMember<MethodSymbol>("B.M");
Assert.Empty(aMethod.OverriddenOrHiddenMembers.OverriddenMembers);
Assert.Empty(aMethod.OverriddenOrHiddenMembers.HiddenMembers);
Assert.Empty(bMethod.OverriddenOrHiddenMembers.OverriddenMembers);
Assert.Equal(aMethod, bMethod.OverriddenOrHiddenMembers.HiddenMembers.Single());
}
[Fact]
[CompilerTrait(CompilerFeature.ReadOnlyReferences)]
public void HidingPropertyWithRefReadOnlyReturnType_RefReadonly_RefReadonly()
{
var code = @"
interface A
{
ref readonly int Property { get; }
}
interface B : A
{
ref readonly int Property { get; }
}";
var comp = CreateCompilation(code).VerifyDiagnostics(
// (8,22): warning CS0108: 'B.Property' hides inherited member 'A.Property'. Use the new keyword if hiding was intended.
// ref readonly int Property { get; }
Diagnostic(ErrorCode.WRN_NewRequired, "Property").WithArguments("B.Property", "A.Property").WithLocation(8, 22));
var aProperty = comp.GetMember<PropertySymbol>("A.Property");
var bProperty = comp.GetMember<PropertySymbol>("B.Property");
Assert.Empty(aProperty.OverriddenOrHiddenMembers.OverriddenMembers);
Assert.Empty(aProperty.OverriddenOrHiddenMembers.HiddenMembers);
Assert.Empty(bProperty.OverriddenOrHiddenMembers.OverriddenMembers);
Assert.Equal(aProperty, bProperty.OverriddenOrHiddenMembers.HiddenMembers.Single());
}
[Fact]
[CompilerTrait(CompilerFeature.ReadOnlyReferences)]
public void HidingPropertyWithRefReadOnlyReturnType_RefReadonly_Ref()
{
var code = @"
interface A
{
ref readonly int Property { get; }
}
interface B : A
{
ref int Property { get; }
}";
var comp = CreateCompilation(code).VerifyDiagnostics(
// (8,13): warning CS0108: 'B.Property' hides inherited member 'A.Property'. Use the new keyword if hiding was intended.
// ref int Property { get; }
Diagnostic(ErrorCode.WRN_NewRequired, "Property").WithArguments("B.Property", "A.Property").WithLocation(8, 13));
var aProperty = comp.GetMember<PropertySymbol>("A.Property");
var bProperty = comp.GetMember<PropertySymbol>("B.Property");
Assert.Empty(aProperty.OverriddenOrHiddenMembers.OverriddenMembers);
Assert.Empty(aProperty.OverriddenOrHiddenMembers.HiddenMembers);
Assert.Empty(bProperty.OverriddenOrHiddenMembers.OverriddenMembers);
Assert.Equal(aProperty, bProperty.OverriddenOrHiddenMembers.HiddenMembers.Single());
}
[Fact]
[CompilerTrait(CompilerFeature.ReadOnlyReferences)]
public void HidingPropertyWithRefReadOnlyReturnType_Ref_RefReadonly()
{
var code = @"
interface A
{
ref int Property { get; }
}
interface B : A
{
ref readonly int Property { get; }
}";
var comp = CreateCompilation(code).VerifyDiagnostics(
// (8,22): warning CS0108: 'B.Property' hides inherited member 'A.Property'. Use the new keyword if hiding was intended.
// ref readonly int Property { get; }
Diagnostic(ErrorCode.WRN_NewRequired, "Property").WithArguments("B.Property", "A.Property").WithLocation(8, 22));
var aProperty = comp.GetMember<PropertySymbol>("A.Property");
var bProperty = comp.GetMember<PropertySymbol>("B.Property");
Assert.Empty(aProperty.OverriddenOrHiddenMembers.OverriddenMembers);
Assert.Empty(aProperty.OverriddenOrHiddenMembers.HiddenMembers);
Assert.Empty(bProperty.OverriddenOrHiddenMembers.OverriddenMembers);
Assert.Equal(aProperty, bProperty.OverriddenOrHiddenMembers.HiddenMembers.Single());
}
[Fact]
[CompilerTrait(CompilerFeature.ReadOnlyReferences)]
public void HidingMethodWithInParameterAndNewKeyword()
{
var code = @"
interface A
{
void M(in int x);
}
interface B : A
{
new void M(in int x);
}";
var comp = CreateCompilation(code).VerifyDiagnostics();
var aMethod = comp.GetMember<MethodSymbol>("A.M");
var bMethod = comp.GetMember<MethodSymbol>("B.M");
Assert.Empty(aMethod.OverriddenOrHiddenMembers.OverriddenMembers);
Assert.Empty(aMethod.OverriddenOrHiddenMembers.HiddenMembers);
Assert.Empty(bMethod.OverriddenOrHiddenMembers.OverriddenMembers);
Assert.Equal(aMethod, bMethod.OverriddenOrHiddenMembers.HiddenMembers.Single());
}
[Fact]
[CompilerTrait(CompilerFeature.ReadOnlyReferences)]
public void HidingMethodWithRefReadOnlyReturnTypeAndNewKeyword()
{
var code = @"
interface A
{
ref readonly int M();
}
interface B : A
{
new ref readonly int M();
}";
var comp = CreateCompilation(code).VerifyDiagnostics();
var aMethod = comp.GetMember<MethodSymbol>("A.M");
var bMethod = comp.GetMember<MethodSymbol>("B.M");
Assert.Empty(aMethod.OverriddenOrHiddenMembers.OverriddenMembers);
Assert.Empty(aMethod.OverriddenOrHiddenMembers.HiddenMembers);
Assert.Empty(bMethod.OverriddenOrHiddenMembers.OverriddenMembers);
Assert.Equal(aMethod, bMethod.OverriddenOrHiddenMembers.HiddenMembers.Single());
}
[Fact]
[CompilerTrait(CompilerFeature.ReadOnlyReferences)]
public void HidingPropertyWithRefReadOnlyReturnTypeAndNewKeyword()
{
var code = @"
interface A
{
ref readonly int Property { get ; }
}
interface B : A
{
new ref readonly int Property { get; }
}";
var comp = CreateCompilation(code).VerifyDiagnostics();
var aProperty = comp.GetMember<PropertySymbol>("A.Property");
var bProperty = comp.GetMember<PropertySymbol>("B.Property");
Assert.Empty(aProperty.OverriddenOrHiddenMembers.OverriddenMembers);
Assert.Empty(aProperty.OverriddenOrHiddenMembers.HiddenMembers);
Assert.Empty(bProperty.OverriddenOrHiddenMembers.OverriddenMembers);
Assert.Equal(aProperty, bProperty.OverriddenOrHiddenMembers.HiddenMembers.Single());
}
[Fact]
[CompilerTrait(CompilerFeature.ReadOnlyReferences)]
public void ImplementingMethodWithInParameter()
{
var code = @"
interface A
{
void M(in int x);
}
class B : A
{
public void M(in int x) { }
}";
var comp = CreateCompilation(code).VerifyDiagnostics();
}
[Fact]
[CompilerTrait(CompilerFeature.ReadOnlyReferences)]
public void ImplementingMethodWithRefReadOnlyReturnType()
{
var code = @"
interface A
{
ref readonly int M();
}
class B : A
{
protected int x = 0;
public ref readonly int M() { return ref x; }
}";
var comp = CreateCompilation(code).VerifyDiagnostics();
}
[Fact]
[CompilerTrait(CompilerFeature.ReadOnlyReferences)]
public void ImplementingPropertyWithRefReadOnlyReturnType()
{
var code = @"
interface A
{
ref readonly int Property { get; }
}
class B : A
{
protected int x = 0;
public ref readonly int Property { get { return ref x; } }
}";
var comp = CreateCompilation(code).VerifyDiagnostics();
}
[Fact]
[CompilerTrait(CompilerFeature.ReadOnlyReferences)]
public void ImplementingMethodWithDifferentParameterRefness()
{
var code = @"
interface A
{
void M(in int x);
}
class B : A
{
public void M(ref int x) { }
}";
var comp = CreateCompilation(code).VerifyDiagnostics(
// (6,11): error CS0535: 'B' does not implement interface member 'A.M(in int)'
// class B : A
Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "A").WithArguments("B", "A.M(in int)").WithLocation(6, 11));
}
[Fact]
[CompilerTrait(CompilerFeature.ReadOnlyReferences)]
public void ImplementingRefReadOnlyMembersWillOverwriteTheCorrectSlot()
{
var text = @"
interface BaseInterface
{
ref readonly int Method1(in int a);
ref readonly int Property1 { get; }
ref readonly int this[int a] { get; }
}
class DerivedClass : BaseInterface
{
protected int field;
public ref readonly int Method1(in int a) { return ref field; }
public ref readonly int Property1 { get { return ref @field; } }
public ref readonly int this[int a] { get { return ref field; } }
}";
var comp = CreateCompilation(text).VerifyDiagnostics();
}
[Fact]
[CompilerTrait(CompilerFeature.ReadOnlyReferences)]
public void MethodImplementationsShouldPreserveRefKindInParameters()
{
var text = @"
interface BaseInterface
{
void Method1(ref int x);
void Method2(in int x);
}
class ChildClass : BaseInterface
{
public void Method1(in int x) { }
public void Method2(ref int x) { }
}";
var comp = CreateCompilation(text).VerifyDiagnostics(
// (7,20): error CS0535: 'ChildClass' does not implement interface member 'BaseInterface.Method2(in int)'
// class ChildClass : BaseInterface
Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "BaseInterface").WithArguments("ChildClass", "BaseInterface.Method2(in int)").WithLocation(7, 20),
// (7,20): error CS0535: 'ChildClass' does not implement interface member 'BaseInterface.Method1(ref int)'
// class ChildClass : BaseInterface
Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "BaseInterface").WithArguments("ChildClass", "BaseInterface.Method1(ref int)").WithLocation(7, 20));
}
[Fact]
[CompilerTrait(CompilerFeature.ReadOnlyReferences)]
public void MethodImplementationsShouldPreserveReadOnlyRefnessInReturnTypes()
{
var text = @"
interface BaseInterface
{
ref int Method1();
ref readonly int Method2();
}
class ChildClass : BaseInterface
{
protected int x = 0 ;
public ref readonly int Method1() { return ref x; }
public ref int Method2() { return ref x; }
}";
var comp = CreateCompilation(text).VerifyDiagnostics(
// (7,20): error CS8152: 'ChildClass' does not implement interface member 'BaseInterface.Method2()'. 'ChildClass.Method2()' cannot implement 'BaseInterface.Method2()' because it does not have matching return by reference.
// class ChildClass : BaseInterface
Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongRefReturn, "BaseInterface").WithArguments("ChildClass", "BaseInterface.Method2()", "ChildClass.Method2()").WithLocation(7, 20),
// (7,20): error CS8152: 'ChildClass' does not implement interface member 'BaseInterface.Method1()'. 'ChildClass.Method1()' cannot implement 'BaseInterface.Method1()' because it does not have matching return by reference.
// class ChildClass : BaseInterface
Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongRefReturn, "BaseInterface").WithArguments("ChildClass", "BaseInterface.Method1()", "ChildClass.Method1()").WithLocation(7, 20));
}
[Fact]
[CompilerTrait(CompilerFeature.ReadOnlyReferences)]
public void PropertyImplementationsShouldPreserveReadOnlyRefnessInReturnTypes()
{
var code = @"
interface A
{
ref int Property1 { get; }
ref readonly int Property2 { get; }
}
class B : A
{
protected int x = 0;
public ref readonly int Property1 { get { return ref x; } }
public ref int Property2 { get { return ref x; } }
}";
var comp = CreateCompilation(code).VerifyDiagnostics(
// (7,11): error CS8152: 'B' does not implement interface member 'A.Property2'. 'B.Property2' cannot implement 'A.Property2' because it does not have matching return by reference.
// class B : A
Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongRefReturn, "A").WithArguments("B", "A.Property2", "B.Property2").WithLocation(7, 11),
// (7,11): error CS8152: 'B' does not implement interface member 'A.Property1'. 'B.Property1' cannot implement 'A.Property1' because it does not have matching return by reference.
// class B : A
Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongRefReturn, "A").WithArguments("B", "A.Property1", "B.Property1").WithLocation(7, 11));
}
[Fact]
[CompilerTrait(CompilerFeature.ReadOnlyReferences)]
public void IndexerImplementationsShouldPreserveReadOnlyRefnessInReturnTypes_Ref_RefReadOnly()
{
var code = @"
interface A
{
ref int this[int p] { get; }
}
class B : A
{
protected int x = 0;
public ref readonly int this[int p] { get { return ref x; } }
}";
var comp = CreateCompilation(code).VerifyDiagnostics(
// (6,11): error CS8152: 'B' does not implement interface member 'A.this[int]'. 'B.this[int]' cannot implement 'A.this[int]' because it does not have matching return by reference.
// class B : A
Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongRefReturn, "A").WithArguments("B", "A.this[int]", "B.this[int]").WithLocation(6, 11));
}
[Fact]
[CompilerTrait(CompilerFeature.ReadOnlyReferences)]
public void IndexerImplementationsShouldPreserveReadOnlyRefnessInReturnTypes_RefReadOnly_Ref()
{
var code = @"
interface A
{
ref readonly int this[int p] { get; }
}
class B : A
{
protected int x = 0;
public ref int this[int p] { get { return ref x; } }
}";
var comp = CreateCompilation(code).VerifyDiagnostics(
// (6,11): error CS8152: 'B' does not implement interface member 'A.this[int]'. 'B.this[int]' cannot implement 'A.this[int]' because it does not have matching return by reference.
// class B : A
Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongRefReturn, "A").WithArguments("B", "A.this[int]", "B.this[int]").WithLocation(6, 11));
}
[Fact]
[CompilerTrait(CompilerFeature.ReadOnlyReferences)]
public void IndexerImplementationsShouldPreserveReadOnlyRefnessInIndexes_Valid()
{
var code = @"
interface A
{
int this[in int p] { get; }
}
class B : A
{
public int this[in int p] { get { return p; } }
}";
var comp = CreateCompilation(code).VerifyDiagnostics();
}
[Fact]
[CompilerTrait(CompilerFeature.ReadOnlyReferences)]
public void IndexerImplementationsShouldPreserveReadOnlyRefnessInIndexes_Source()
{
var code = @"
interface A
{
int this[in int p] { get; }
}
class B : A
{
public int this[int p] { get { return p; } }
}";
var comp = CreateCompilation(code).VerifyDiagnostics(
// (6,11): error CS0535: 'B' does not implement interface member 'A.this[in int]'
// class B : A
Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "A").WithArguments("B", "A.this[in int]").WithLocation(6, 11));
}
[Fact]
[CompilerTrait(CompilerFeature.ReadOnlyReferences)]
public void IndexerImplementationsShouldPreserveReadOnlyRefnessInIndexes_Destination()
{
var code = @"
interface A
{
int this[int p] { get; }
}
class B : A
{
public int this[in int p] { get { return p; } }
}";
var comp = CreateCompilation(code).VerifyDiagnostics(
// (6,11): error CS0535: 'B' does not implement interface member 'A.this[int]'
// class B : A
Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "A").WithArguments("B", "A.this[int]").WithLocation(6, 11));
}
}
}
|