|
// 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 class HideByNameTests : CSharpTestBase
{
#region Methods
[WorkItem(545796, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545796")]
[Fact]
public void MethodOverloadResolutionHidesByNameStatic()
{
var il = @"
.class public auto ansi A
extends [mscorlib]System.Object
{
.method public specialname rtspecialname
instance void .ctor() cil managed
{
ldarg.0
call instance void [mscorlib]System.Object::.ctor()
ret
}
.method public static string Goo(string x) cil managed
{
ldarg.0
ret
}
} // end of class A
.class public auto ansi B
extends A
{
.method public specialname rtspecialname
instance void .ctor() cil managed
{
ldarg.0
call instance void A::.ctor()
ret
}
.method public static void Goo(int32 x) cil managed
{
ret
}
} // end of class B";
var csharp = @"
class Program
{
static void Main()
{
B.Goo("""");
}
}";
CreateCompilationWithILAndMscorlib40(csharp, il).VerifyDiagnostics(
// (6,15): error CS1503: Argument 1: cannot convert from 'string' to 'int'
// B.Goo("");
Diagnostic(ErrorCode.ERR_BadArgType, @"""""").WithArguments("1", "string", "int"));
}
[ClrOnlyFact(ClrOnlyReason.Ilasm)]
public void MethodOverloadResolutionHidesByNameInstance()
{
var il = @"
.class public auto ansi A
extends [mscorlib]System.Object
{
.method public specialname rtspecialname
instance void .ctor() cil managed
{
ldarg.0
call instance void [mscorlib]System.Object::.ctor()
ret
}
.method public instance string Goo(string x) cil managed
{
ldarg.0
ret
}
} // end of class A
.class public auto ansi B
extends A
{
.method public specialname rtspecialname
instance void .ctor() cil managed
{
ldarg.0
call instance void A::.ctor()
ret
}
.method public instance void Goo(int32 x) cil managed
{
ret
}
} // end of class B";
var csharp = @"
class Program
{
static void Main()
{
new B().Goo("""");
}
}";
CreateCompilationWithILAndMscorlib40(csharp, il).VerifyDiagnostics(
// (6,21): error CS1503: Argument 1: cannot convert from 'string' to 'int'
// new B().Goo("");
Diagnostic(ErrorCode.ERR_BadArgType, @"""""").WithArguments("1", "string", "int"));
}
[Fact]
public void MethodOverloadResolutionHidesByNameOverride()
{
var il = @"
.class public auto ansi A
extends [mscorlib]System.Object
{
.method public specialname rtspecialname
instance void .ctor() cil managed
{
ldarg.0
call instance void [mscorlib]System.Object::.ctor()
ret
}
.method public hidebysig newslot virtual
instance void M(int32 x) cil managed
{
ret
}
} // end of class A
.class public auto ansi B
extends A
{
.method public specialname rtspecialname
instance void .ctor() cil managed
{
ldarg.0
call instance void A::.ctor()
ret
}
.method public virtual instance void
M(int32 x) cil managed
{
ret
}
} // end of class B";
var csharp = @"
public class C : B
{
public override void M(int i)
{
}
}
class Program
{
static void Main()
{
new B().M(1);
new C().M(2);
}
}";
var comp = CreateCompilationWithILAndMscorlib40(csharp, il);
CompileAndVerify(comp).VerifyIL("Program.Main", @"
{
// Code size 23 (0x17)
.maxstack 2
IL_0000: newobj ""B..ctor()""
IL_0005: ldc.i4.1
IL_0006: callvirt ""void B.M(int)""
IL_000b: newobj ""C..ctor()""
IL_0010: ldc.i4.2
IL_0011: callvirt ""void B.M(int)""
IL_0016: ret
}");
}
[ClrOnlyFact(ClrOnlyReason.Ilasm)]
public void MethodOverloadResolutionHidesByNameParams()
{
var il = @"
.class public auto ansi A
extends [mscorlib]System.Object
{
.method public specialname rtspecialname
instance void .ctor() cil managed
{
ldarg.0
call instance void [mscorlib]System.Object::.ctor()
ret
}
// params
.method public hidebysig newslot virtual
instance void M(int32[] a) cil managed
{
.param [1]
.custom instance void [mscorlib]System.ParamArrayAttribute::.ctor() = {}
ret
}
} // end of class A
.class public auto ansi B
extends A
{
.method public specialname rtspecialname
instance void .ctor() cil managed
{
ldarg.0
call instance void A::.ctor()
ret
}
// Not params
.method public virtual instance void
M(int32[] a) cil managed
{
ret
}
} // end of class B";
var csharp = @"
class Program
{
static void Main()
{
new B().M(1, 2); // This would work if B.M was not hide-by-name (since A.M is params)
}
}";
CreateCompilationWithILAndMscorlib40(csharp, il).VerifyDiagnostics(
// (6,9): error CS1501: No overload for method 'M' takes 2 arguments
// new B().M(1, 2); // This would work if B.M was not hide-by-name (since A.M is params)
Diagnostic(ErrorCode.ERR_BadArgCount, "M").WithArguments("M", "2"));
}
[Fact]
public void MethodOverridingHidesByName()
{
var il = @"
.class public auto ansi A
extends [mscorlib]System.Object
{
.method public specialname rtspecialname
instance void .ctor() cil managed
{
ldarg.0
call instance void [mscorlib]System.Object::.ctor()
ret
}
.method public hidebysig newslot virtual
instance void M(int32 a) cil managed
{
ret
}
} // end of class A
.class public auto ansi B
extends A
{
.method public specialname rtspecialname
instance void .ctor() cil managed
{
ldarg.0
call instance void A::.ctor()
ret
}
.method public newslot virtual
instance void M(int64 a) cil managed
{
ret
}
} // end of class B";
var csharp = @"
public class C : B
{
public override void M(int a) { }
}";
// NOTE: unlike overload resolution, override resolution does not respect hide-by-name.
CreateCompilationWithILAndMscorlib40(csharp, il).VerifyDiagnostics();
}
[Fact]
public void MethodInterfaceImplementationHidesByName()
{
var il = @"
.class public auto ansi A
extends [mscorlib]System.Object
{
.method public specialname rtspecialname
instance void .ctor() cil managed
{
ldarg.0
call instance void [mscorlib]System.Object::.ctor()
ret
}
.method public hidebysig newslot virtual
instance void M(int32 a) cil managed
{
ret
}
} // end of class A
.class public auto ansi B
extends A
{
.method public specialname rtspecialname
instance void .ctor() cil managed
{
ldarg.0
call instance void A::.ctor()
ret
}
.method public newslot virtual
instance void M(int64 a) cil managed
{
ret
}
} // end of class B";
var csharp = @"
interface I
{
void M(int a);
}
public class C : B, I
{
}";
// NOTE: unlike overload resolution, implicit interface implementation resolution does not respect hide-by-name.
CreateCompilationWithILAndMscorlib40(csharp, il).VerifyDiagnostics();
}
#endregion Methods
#region Indexers
[ClrOnlyFact(ClrOnlyReason.Ilasm)]
public void IndexerOverloadResolutionHidesByNameInstance()
{
var il = @"
.class public auto ansi beforefieldinit A
extends [mscorlib]System.Object
{
.custom instance void [mscorlib]System.Reflection.DefaultMemberAttribute::.ctor(string)
= {string('Item')}
.method public hidebysig newslot specialname virtual
instance int32 get_Item(int32 x) cil managed
{
ldc.i4.0
ret
}
.property instance int32 Item(int32)
{
.get instance int32 A::get_Item(int32)
}
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
ldarg.0
call instance void [mscorlib]System.Object::.ctor()
ret
}
} // end of class A
.class public auto ansi B
extends A
{
.custom instance void [mscorlib]System.Reflection.DefaultMemberAttribute::.ctor(string)
= {string('Item')}
.method public newslot specialname virtual
instance int32 get_Item(string x) cil managed
{
ldc.i4.0
ret
}
.property instance int32 Item(string)
{
.get instance int32 B::get_Item(string)
}
.method public specialname rtspecialname
instance void .ctor() cil managed
{
ldarg.0
call instance void A::.ctor()
ret
}
} // end of class B";
var csharp = @"
class Program
{
static void Main()
{
int x = new B()[0];
}
}";
CreateCompilationWithILAndMscorlib40(csharp, il).VerifyDiagnostics(
// (6,25): error CS1503: Argument 1: cannot convert from 'int' to 'string'
// int x = new B()[0];
Diagnostic(ErrorCode.ERR_BadArgType, "0").WithArguments("1", "int", "string"));
}
[ClrOnlyFact(ClrOnlyReason.Ilasm)]
public void IndexerOverloadResolutionHidesByNameOverride()
{
var il = @"
.class public auto ansi beforefieldinit A
extends [mscorlib]System.Object
{
.custom instance void [mscorlib]System.Reflection.DefaultMemberAttribute::.ctor(string)
= {string('Item')}
.method public hidebysig newslot specialname virtual
instance void set_Item(int32 x, int32 'value') cil managed
{
ret
}
.property instance int32 Item(int32)
{
.set instance void A::set_Item(int32, int32)
}
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
ldarg.0
call instance void [mscorlib]System.Object::.ctor()
ret
}
} // end of class A
.class public auto ansi B
extends A
{
.custom instance void [mscorlib]System.Reflection.DefaultMemberAttribute::.ctor(string)
= {string('Item')}
.method public specialname virtual
instance void set_Item(int32 x, int32 'value') cil managed
{
ret
}
.property instance int32 Item(int32)
{
.set instance void B::set_Item(int32, int32)
}
.method public specialname rtspecialname
instance void .ctor() cil managed
{
ldarg.0
call instance void A::.ctor()
ret
}
} // end of class B";
var csharp = @"
public class C : B
{
public override int this[int x] { set { } }
}
class Program
{
static void Main()
{
new B()[1] = 2;
new C()[2] = 1;
}
}";
var comp = CreateCompilationWithILAndMscorlib40(csharp, il);
CompileAndVerify(comp).VerifyIL("Program.Main", @"
{
// Code size 25 (0x19)
.maxstack 3
IL_0000: newobj ""B..ctor()""
IL_0005: ldc.i4.1
IL_0006: ldc.i4.2
IL_0007: callvirt ""void B.this[int].set""
IL_000c: newobj ""C..ctor()""
IL_0011: ldc.i4.2
IL_0012: ldc.i4.1
IL_0013: callvirt ""void B.this[int].set""
IL_0018: ret
}");
}
[ClrOnlyFact(ClrOnlyReason.Ilasm)]
public void IndexerOverloadResolutionHidesByNameParams()
{
var il = @"
.class public auto ansi beforefieldinit A
extends [mscorlib]System.Object
{
.custom instance void [mscorlib]System.Reflection.DefaultMemberAttribute::.ctor(string)
= {string('Item')}
.method public hidebysig newslot specialname virtual
instance int32 get_Item(int32[] x) cil managed
{
.param [1]
.custom instance void [mscorlib]System.ParamArrayAttribute::.ctor() = {}
ldc.i4.0
ret
}
.property instance int32 Item(int32[])
{
.get instance int32 A::get_Item(int32[])
}
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
ldarg.0
call instance void [mscorlib]System.Object::.ctor()
ret
}
} // end of class A
.class public auto ansi B
extends A
{
.custom instance void [mscorlib]System.Reflection.DefaultMemberAttribute::.ctor(string)
= {string('Item')}
.method public specialname virtual
instance int32 get_Item(int32[] x) cil managed
{
ldc.i4.0
ret
}
.property instance int32 Item(int32[])
{
.get instance int32 B::get_Item(int32[])
}
.method public specialname rtspecialname
instance void .ctor() cil managed
{
ldarg.0
call instance void A::.ctor()
ret
}
} // end of class B";
var csharp = @"
class Program
{
static void Main()
{
int x = new B()[1, 2]; // This would work if B.Item was not hide-by-name (since A.Item is params)
}
}";
CreateCompilationWithILAndMscorlib40(csharp, il).VerifyDiagnostics(
// (6,17): error CS1501: No overload for method 'this' takes 2 arguments
// int x = new B()[1, 2]; // This would work if B.Item was not hide-by-name (since A.Item is params)
Diagnostic(ErrorCode.ERR_BadArgCount, "new B()[1, 2]").WithArguments("this", "2"));
}
[ClrOnlyFact(ClrOnlyReason.Ilasm)]
public void IndexerOverridingHidesByName()
{
var il = @"
.class public auto ansi beforefieldinit A
extends [mscorlib]System.Object
{
.custom instance void [mscorlib]System.Reflection.DefaultMemberAttribute::.ctor(string)
= {string('Item')}
.method public hidebysig newslot specialname virtual
instance void set_Item(int32 x, int32 'value') cil managed
{
ret
}
.property instance int32 Item(int32)
{
.set instance void A::set_Item(int32, int32)
}
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
ldarg.0
call instance void [mscorlib]System.Object::.ctor()
ret
}
} // end of class A
.class public auto ansi B
extends A
{
.custom instance void [mscorlib]System.Reflection.DefaultMemberAttribute::.ctor(string)
= {string('Item')}
.method public newslot specialname virtual
instance void set_Item(int64 x, int32 'value') cil managed
{
ret
}
.property instance int32 Item(int64)
{
.set instance void B::set_Item(int64, int32)
}
.method public specialname rtspecialname
instance void .ctor() cil managed
{
ldarg.0
call instance void A::.ctor()
ret
}
} // end of class B";
var csharp = @"
public class C : B
{
public override int this[int x] { set { } }
}";
// NOTE: unlike overload resolution, override resolution does not respect hide-by-name.
CreateCompilationWithILAndMscorlib40(csharp, il).VerifyDiagnostics();
}
[ClrOnlyFact(ClrOnlyReason.Ilasm)]
public void IndexerInterfaceImplementationHidesByName()
{
var il = @"
.class public auto ansi beforefieldinit A
extends [mscorlib]System.Object
{
.custom instance void [mscorlib]System.Reflection.DefaultMemberAttribute::.ctor(string)
= {string('Item')}
.method public hidebysig newslot specialname virtual
instance void set_Item(int32 x, int32 'value') cil managed
{
ret
}
.property instance int32 Item(int32)
{
.set instance void A::set_Item(int32, int32)
}
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
ldarg.0
call instance void [mscorlib]System.Object::.ctor()
ret
}
} // end of class A
.class public auto ansi B
extends A
{
.custom instance void [mscorlib]System.Reflection.DefaultMemberAttribute::.ctor(string)
= {string('Item')}
.method public newslot specialname virtual
instance void set_Item(int64 x, int32 'value') cil managed
{
ret
}
.property instance int32 Item(int64)
{
.set instance void B::set_Item(int64, int32)
}
.method public specialname rtspecialname
instance void .ctor() cil managed
{
ldarg.0
call instance void A::.ctor()
ret
}
} // end of class B";
var csharp = @"
interface I
{
int this[int x] { set; }
}
public class C : B, I
{
}";
// NOTE: unlike overload resolution, implicit interface implementation resolution does not respect hide-by-name.
CreateCompilationWithILAndMscorlib40(csharp, il).VerifyDiagnostics();
}
#endregion Indexers
[Fact, WorkItem(897971, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/897971")]
public void LocalHideFieldByName()
{
CreateCompilation(@"
using System;
public class M
{
int x;
void P1(int[] xs)
{
for (int i = 0; i < xs.Length; i++)
{
int x = xs[i];
Console.WriteLine(x);
}
for (int i = 0; i < xs.Length; i++)
{
x = xs[i];
Console.WriteLine(x);
}
x = xs.Length;
}
}
").VerifyDiagnostics();
CreateCompilation(@"
using System;
public class M
{
int x;
public virtual void P2(int[] xs)
{
for (int i = 0; i < xs.Length; i++)
{
for (int j = 0; j < xs.Length; j++)
{
int x = xs[j];
Console.WriteLine(x);
}
x = xs.Length;
}
}
}
").VerifyDiagnostics();
CreateCompilation(@"
using System;
public class M
{
int x;
void P1(int[] xs)
{
for (int i = 0; i < xs.Length; i++)
{
int x = xs[i];
Console.WriteLine(x);
}
for (int i = 0; i < xs.Length; i++)
{
x = xs[i];
Console.WriteLine(x);
}
this.x = xs.Length;
}
public virtual void P2(int[] xs)
{
for (int i = 0; i < xs.Length; i++)
{
for (int j = 0; j < xs.Length; j++)
{
int x = xs[j];
Console.WriteLine(x);
}
this.x = xs.Length;
}
}
}
").VerifyDiagnostics();
}
}
}
|