Skip to content

Commit

Permalink
VBOverloadResolutionPriority: break attribute binding cycles, clone a…
Browse files Browse the repository at this point in the history
… bunch of C# tests (#76008)
  • Loading branch information
AlekseyTs authored Nov 23, 2024
1 parent 38cda8a commit 9e8ad61
Show file tree
Hide file tree
Showing 4 changed files with 1,700 additions and 1 deletion.
91 changes: 91 additions & 0 deletions src/Compilers/CSharp/Test/Emit3/OverloadResolutionPriorityTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -992,9 +992,14 @@ static void Main()
var attrs = ctors.SelectAsArray(ctor => ctor.GetAttributes());

Assert.Empty(attrs[0]);
Assert.Equal(1, ((MethodSymbol)ctors[1]).OverloadResolutionPriority);
AssertEx.Equal("System.Runtime.CompilerServices.OverloadResolutionPriorityAttribute..ctor(System.Int32 priority)",
attrs[1].Single().AttributeConstructor.ToTestDisplayString());

var m = ((CSharpCompilation)verifier.Compilation).GetTypeByMetadataName("System.Runtime.CompilerServices.C")!.GetMembers("M").OfType<MethodSymbol>().First();
Assert.Equal(1, m.OverloadResolutionPriority);
AssertEx.Equal("System.Runtime.CompilerServices.OverloadResolutionPriorityAttribute..ctor(System.Int32 priority)", m.GetAttributes().First().AttributeConstructor.ToTestDisplayString());

verifier.VerifyIL("System.Runtime.CompilerServices.C.Main()", """
{
// Code size 7 (0x7)
Expand Down Expand Up @@ -1059,6 +1064,92 @@ public OtherAttribute() {}
CompileAndVerify(source).VerifyDiagnostics();
}

[Fact]
[WorkItem("https://github.com/dotnet/roslyn/issues/75985")]
public void CycleOnOverloadResolutionPriorityConstructor_07()
{
var source = """
using System.Runtime.CompilerServices;
namespace System
{
public class ObsoleteAttribute : Attribute
{
public ObsoleteAttribute(string x){}
[OverloadResolutionPriority(1)]
public ObsoleteAttribute(string x, bool y = false){}
}
}
#pragma warning disable CS0436 // The type 'ObsoleteAttribute' in '' conflicts with the imported type 'ObsoleteAttribute'
[System.Obsolete("Test")]
public class C {}
public class D
{
public C x;
}
""";

var verifier = CompileAndVerify([source, OverloadResolutionPriorityAttributeDefinition],
symbolValidator: (m) =>
{
AssertEx.Equal("System.ObsoleteAttribute..ctor(System.String x)",
m.ContainingAssembly.GetTypeByMetadataName("C")!.GetAttributes().Single().AttributeConstructor.ToTestDisplayString());
});
verifier.VerifyDiagnostics(
// (22,12): warning CS0618: 'C' is obsolete: 'Test'
// public C x;
Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "C").WithArguments("C", "Test").WithLocation(22, 12)
);
}

[Fact]
[WorkItem("https://github.com/dotnet/roslyn/issues/75985")]
public void CycleOnOverloadResolutionPriorityConstructor_08()
{
var source = """
using System.Runtime.CompilerServices;
namespace System
{
public class ObsoleteAttribute : Attribute
{
public ObsoleteAttribute(string x){}
[OverloadResolutionPriority(1)]
public ObsoleteAttribute(string x, bool y = true){}
}
}
#pragma warning disable CS0436 // The type 'ObsoleteAttribute' in '' conflicts with the imported type 'ObsoleteAttribute'
[System.Obsolete("Test")]
public class C {}
public class D
{
public C x;
}
""";

var verifier = CompileAndVerify([source, OverloadResolutionPriorityAttributeDefinition],
symbolValidator: (m) =>
{
AssertEx.Equal("System.ObsoleteAttribute..ctor(System.String x)",
m.ContainingAssembly.GetTypeByMetadataName("C")!.GetAttributes().Single().AttributeConstructor.ToTestDisplayString());
});
verifier.VerifyDiagnostics(
// (22,12): warning CS0618: 'C' is obsolete: 'Test'
// public C x;
Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "C").WithArguments("C", "Test").WithLocation(22, 12)
);
}

[Theory, CombinatorialData]
public void OverloadResolutionAppliedToIndexers(bool useMetadataReference, bool i1First)
{
Expand Down
11 changes: 11 additions & 0 deletions src/Compilers/VisualBasic/Portable/Semantics/OverloadResolution.vb
Original file line number Diff line number Diff line change
Expand Up @@ -966,6 +966,17 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Dim someCandidatesHaveOverloadResolutionPriority As Boolean = False
Dim respectOverloadResolutionPriority As Boolean = InternalSyntax.Parser.CheckFeatureAvailability(binder.Compilation.LanguageVersion, InternalSyntax.Feature.OverloadResolutionPriority)

If respectOverloadResolutionPriority AndAlso binder.IsEarlyAttributeBinder Then
Dim possiblyConstructor = TryCast(binder.ContainingMember, MethodSymbol)
If possiblyConstructor IsNot Nothing AndAlso
possiblyConstructor.MethodKind = MethodKind.Constructor AndAlso
possiblyConstructor.ContainingType.Name = AttributeDescription.OverloadResolutionPriorityAttribute.Name AndAlso
possiblyConstructor.ContainingType.IsCompilerServicesTopLevelType() Then
' Avoid possible cycle during attribute binding
respectOverloadResolutionPriority = False
End If
End If

' First collect instance methods.
If instanceCandidates.Count > 0 Then

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1538,7 +1538,7 @@ lReportErrorOnTwoTokens:
End If

Dim attrdata = arguments.Binder.GetAttribute(arguments.AttributeSyntax, arguments.AttributeType, hasAnyDiagnostics)
If Not attrdata.HasErrors Then
If Not attrdata.HasErrors AndAlso attrdata.IsTargetAttribute(AttributeDescription.OverloadResolutionPriorityAttribute) Then
Dim priority As Integer = attrdata.GetConstructorArgument(Of Integer)(0, SpecialType.System_Int32)
arguments.GetOrCreateData(Of MethodEarlyWellKnownAttributeData)().OverloadResolutionPriority = priority
Return If(Not hasAnyDiagnostics, attrdata, Nothing)
Expand Down
Loading

0 comments on commit 9e8ad61

Please sign in to comment.