Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OHI tests for ref readonly #17547

Merged
merged 7 commits into from
Mar 8, 2017
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions src/Compilers/CSharp/Portable/CSharpResources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 5 additions & 5 deletions src/Compilers/CSharp/Portable/CSharpResources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,9 @@
<data name="IDS_SK_EXTERNALIAS" xml:space="preserve">
<value>extern alias</value>
</data>
<data name="IDS_SK_CONSTRUCTOR" xml:space="preserve">
<value>constructor</value>
</data>
<data name="IDS_FOREACHLOCAL" xml:space="preserve">
<value>foreach iteration variable</value>
</data>
Expand Down Expand Up @@ -1817,8 +1820,8 @@ If such a class is used as a base class and if the deriving class defines a dest
<data name="ERR_OutAttrOnRefParam" xml:space="preserve">
<value>Cannot specify only Out attribute on a ref parameter. Use both In and Out attributes, or neither.</value>
</data>
<data name="ERR_OverloadRefOut" xml:space="preserve">
<value>'{0}' cannot define overloaded methods that differ only on ref and out</value>
<data name="ERR_OverloadRefKind" xml:space="preserve">
<value>'{0}' cannot define an overloaded {1} that differs only on parameter modifiers '{2}' and '{3}'</value>
</data>
<data name="ERR_LiteralDoubleCast" xml:space="preserve">
<value>Literal of type double cannot be implicitly converted to type '{1}'; use an '{0}' suffix to create a literal of this type</value>
Expand Down Expand Up @@ -3731,9 +3734,6 @@ You should consider suppressing the warning only if you're sure that you don't w
<data name="WRN_IsDynamicIsConfusing_Title" xml:space="preserve">
<value>Using 'is' to test compatibility with 'dynamic' is essentially identical to testing compatibility with 'Object'</value>
</data>
<data name="ERR_OverloadRefOutCtor" xml:space="preserve">
<value>Cannot define overloaded constructor '{0}' because it differs from another constructor only on ref and out</value>
</data>
<data name="ERR_YieldNotAllowedInScript" xml:space="preserve">
<value>Cannot use 'yield' in top-level script code</value>
</data>
Expand Down
4 changes: 2 additions & 2 deletions src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,7 @@ internal enum ErrorCode
WRN_EqualityOpWithoutEquals = 660,
WRN_EqualityOpWithoutGetHashCode = 661,
ERR_OutAttrOnRefParam = 662,
ERR_OverloadRefOut = 663,
ERR_OverloadRefKind = 663,
ERR_LiteralDoubleCast = 664,
WRN_IncorrectBooleanAssg = 665,
ERR_ProtectedInStruct = 666,
Expand Down Expand Up @@ -584,7 +584,7 @@ internal enum ErrorCode
ERR_ExpressionTreeContainsBadCoalesce = 845,
ERR_ArrayInitializerExpected = 846,
ERR_ArrayInitializerIncorrectLength = 847,
ERR_OverloadRefOutCtor = 851,
// ERR_OverloadRefOutCtor = 851, Replaced By ERR_OverloadRefKind
ERR_ExpressionTreeContainsNamedArgument = 853,
ERR_ExpressionTreeContainsOptionalArgument = 854,
ERR_ExpressionTreeContainsIndexedProperty = 855,
Expand Down
4 changes: 3 additions & 1 deletion src/Compilers/CSharp/Portable/Errors/MessageID.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ internal enum MessageID
{
None = 0,
MessageBase = 1200,

IDS_SK_METHOD = MessageBase + 2000,
IDS_SK_TYPE = MessageBase + 2001,
IDS_SK_NAMESPACE = MessageBase + 2002,
Expand All @@ -23,6 +24,8 @@ internal enum MessageID
IDS_SK_ALIAS = MessageBase + 2010,
//IDS_SK_EXTERNALIAS = MessageBase + 2011,
IDS_SK_LABEL = MessageBase + 2012,
IDS_SK_CONSTRUCTOR = MessageBase + 2013,

IDS_NULL = MessageBase + 10001,
//IDS_RELATEDERROR = MessageBase + 10002,
//IDS_RELATEDWARNING = MessageBase + 10003,
Expand Down Expand Up @@ -129,7 +132,6 @@ internal enum MessageID
IDS_ThrowExpression = MessageBase + 12717,

IDS_FeatureReadonlyReferences = MessageBase + 12718,

}

// Message IDs may refer to strings that need to be localized.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1538,23 +1538,29 @@ private void ReportMethodSignatureCollision(DiagnosticBag diagnostics, SourceMet
return;
}

if (DifferByOutOrRef(method1, method2))
{
// '{0}' cannot define overloaded methods that differ only on ref and out
ErrorCode errorCode = method1.MethodKind == MethodKind.Constructor ?
ErrorCode.ERR_OverloadRefOutCtor :
ErrorCode.ERR_OverloadRefOut;
diagnostics.Add(errorCode, method1.Locations[0], this);
}
else
Debug.Assert(method1.ParameterCount == method2.ParameterCount);

for (int i = 0; i < method1.ParameterCount; i++)
{
// Special case: if there are two destructors, use the destructor syntax instead of "Finalize"
var methodName = (method1.MethodKind == MethodKind.Destructor && method2.MethodKind == MethodKind.Destructor) ?
"~" + this.Name :
method1.Name;
// Type '{1}' already defines a member called '{0}' with the same parameter types
diagnostics.Add(ErrorCode.ERR_MemberAlreadyExists, method1.Locations[0], methodName, this);
var refKind1 = method1.Parameters[i].RefKind;
var refKind2 = method2.Parameters[i].RefKind;

if (refKind1 != refKind2)
{
// '{0}' cannot define an overloaded {1} that differs only on parameter modifiers '{2}' and '{3}'
var methodKind = method1.MethodKind == MethodKind.Constructor ? MessageID.IDS_SK_CONSTRUCTOR : MessageID.IDS_SK_METHOD;
diagnostics.Add(ErrorCode.ERR_OverloadRefKind, method1.Locations[0], this, methodKind.Localize(), refKind1.ToDisplayString(), refKind2.ToDisplayString());

return;
}
}

// Special case: if there are two destructors, use the destructor syntax instead of "Finalize"
var methodName = (method1.MethodKind == MethodKind.Destructor && method2.MethodKind == MethodKind.Destructor) ?
"~" + this.Name :
method1.Name;
// Type '{1}' already defines a member called '{0}' with the same parameter types
diagnostics.Add(ErrorCode.ERR_MemberAlreadyExists, method1.Locations[0], methodName, this);
}

private void CheckIndexerNameConflicts(DiagnosticBag diagnostics, Dictionary<string, ImmutableArray<Symbol>> membersByName)
Expand Down Expand Up @@ -2436,23 +2442,7 @@ private static ImmutableArray<Symbol> Remove(ImmutableArray<Symbol> symbols, Sym
}
return builder.ToImmutableAndFree();
}

private static bool DifferByOutOrRef(SourceMethodSymbol m1, SourceMethodSymbol m2)
{
var pl1 = m1.Parameters;
var pl2 = m2.Parameters;
int n = pl1.Length;
for (int i = 0; i < n; i++)
{
if (pl1[i].RefKind != pl2[i].RefKind)
{
return true;
}
}

return false;
}


/// <summary>
/// Report an error if a member (other than a method) exists with the same name
/// as the property accessor, or if a method exists with the same name and signature.
Expand Down
4 changes: 2 additions & 2 deletions src/Compilers/CSharp/Test/Emit/CodeGen/SwitchTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4955,7 +4955,7 @@ internal enum ErrorCode
WRN_EqualityOpWithoutEquals = 660,
WRN_EqualityOpWithoutGetHashCode = 661,
ERR_OutAttrOnRefParam = 662,
ERR_OverloadRefOut = 663,
ERR_OverloadRefKind = 663,
ERR_LiteralDoubleCast = 664,
WRN_IncorrectBooleanAssg = 665,
ERR_ProtectedInStruct = 666,
Expand Down Expand Up @@ -5084,7 +5084,7 @@ internal enum ErrorCode
ERR_ExpressionTreeContainsBadCoalesce = 845,
ERR_ArrayInitializerExpected = 846,
ERR_ArrayInitializerIncorrectLength = 847,
ERR_OverloadRefOutCtor = 851,
// ERR_OverloadRefOutCtor = 851, Replaced By ERR_OverloadRefKind
ERR_ExpressionTreeContainsNamedArgument = 853,
ERR_ExpressionTreeContainsOptionalArgument = 854,
ERR_ExpressionTreeContainsIndexedProperty = 855,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1321,5 +1321,39 @@ public static void Main(string[] args)
// since the runtime can distinguish signatures with different modopts.
verifier.VerifyDiagnostics();
}

[Fact]
[CompilerTrait(CompilerFeature.ReadonlyReferences)]
public void OverloadsWithDifferentParameterModifiers_Ref_RefReadOnly()
{
var text = @"
abstract class TestClass
{
public virtual void Method(ref int x) { }
public virtual void Method(ref readonly int x) { }
}";
Copy link
Member

@cston cston Mar 7, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider removing abstract and virtual so it's clear the overload error does not depend on virtual methods. Same comment for test below. #Resolved


var comp = CreateCompilationWithMscorlib(text).VerifyDiagnostics(
// (5,25): error CS0663: 'TestClass' cannot define an overloaded method that differs only on parameter modifiers 'ref readonly' and 'ref'
// public virtual void Method(ref readonly int x) { }
Diagnostic(ErrorCode.ERR_OverloadRefKind, "Method").WithArguments("TestClass", "method", "ref readonly", "ref").WithLocation(5, 25));
}

[Fact]
[CompilerTrait(CompilerFeature.ReadonlyReferences)]
public void OverloadsWithDifferentParameterModifiers_Out_RefReadOnly()
{
var text = @"
abstract class TestClass
{
public virtual void Method(out int x) { x = 0; }
public virtual void Method(ref readonly int x) { }
}";

var comp = CreateCompilationWithMscorlib(text).VerifyDiagnostics(
// (5,25): error CS0663: 'TestClass' cannot define an overloaded method that differs only on parameter modifiers 'ref readonly' and 'out'
// public virtual void Method(ref readonly int x) { }
Diagnostic(ErrorCode.ERR_OverloadRefKind, "Method").WithArguments("TestClass", "method", "ref readonly", "out").WithLocation(5, 25));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5453,8 +5453,9 @@ class Derived2 : Base2
}";

CreateCompilationWithMscorlib(text).VerifyDiagnostics(
// (14,26): error CS0663: 'Derived2' cannot define overloaded methods that differ only on ref and out
Diagnostic(ErrorCode.ERR_OverloadRefOut, "Method").WithArguments("Derived2"));
// (14,26): error CS0663: 'Derived2' cannot define an overloaded method that differs only on parameter modifiers 'ref' and 'out'
// public override void Method(int x, ref int y, out Exception z) { z = null; }
Diagnostic(ErrorCode.ERR_OverloadRefKind, "Method").WithArguments("Derived2", "method", "ref", "out").WithLocation(14, 26));
}

[Fact]
Expand Down
Loading