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

Ensure obsolete diagnostics about required constructor or Add method is suppressible. #72426

Merged
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -1559,7 +1559,7 @@ void validateParamsType(BindingDiagnosticBag diagnostics)
case CollectionExpressionTypeKind.ImplementsIEnumerable:
{
var syntax = ParameterSyntax;
var binder = GetDefaultParameterValueBinder(syntax); // this binder is good for our purpose
var binder = GetDefaultParameterValueBinder(syntax).WithContainingMemberOrLambda(ContainingSymbol); // this binder is good for our purpose

binder.TryGetCollectionIterationType(syntax, Type, out elementTypeWithAnnotations);
elementType = elementTypeWithAnnotations.Type;
Expand Down Expand Up @@ -1618,7 +1618,7 @@ void validateParamsType(BindingDiagnosticBag diagnostics)
case CollectionExpressionTypeKind.CollectionBuilder:
{
var syntax = ParameterSyntax;
var binder = GetDefaultParameterValueBinder(syntax); // this binder is good for our purpose
var binder = GetDefaultParameterValueBinder(syntax).WithContainingMemberOrLambda(ContainingSymbol); // this binder is good for our purpose

binder.TryGetCollectionIterationType(syntax, Type, out elementTypeWithAnnotations);
elementType = elementTypeWithAnnotations.Type;
Expand Down
117 changes: 117 additions & 0 deletions src/Compilers/CSharp/Test/Emit2/Semantics/ParamsCollectionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2158,6 +2158,123 @@ static void Test2()
);
}

[Fact]
public void ImplementsIEnumerableT_22_ObsoleteConstructor()
{
var src = """
using System.Collections;
using System.Collections.Generic;

class MyCollection : IEnumerable<long>
{
[System.Obsolete()]
Copy link
Member

@333fred 333fred Mar 6, 2024

Choose a reason for hiding this comment

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

Is it worth it to add variations for Experimental as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is it worth adding variations for Experimental as well?

I do not think so, they are supposed to be handled uniformly. The only difference is the attribute name.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Context for suppression comes from the binder

public MyCollection(){}
public List<long> Array = new List<long>();
IEnumerator<long> IEnumerable<long>.GetEnumerator() => throw null;
IEnumerator IEnumerable.GetEnumerator() => throw null;

public void Add(long l) => Array.Add(l);
}

class Program
{
static void Main()
{
#line 100
Copy link
Contributor

Choose a reason for hiding this comment

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

Is use of #line relevant to the test?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is use of #line relevant to the test?

I used it intentionally, it is reflected in the line numbers for diagnostics in the base line

Test();
Test(1);
Test(2, 3);
}

static void Test(params MyCollection a)
{
}

[System.Obsolete()]
static void Test2(params MyCollection a)
{
Test2();
Test2(1);
Test2(2, 3);
}
}
""";
var comp = CreateCompilation(src, options: TestOptions.ReleaseExe);

comp.VerifyEmitDiagnostics(
// (100,9): warning CS0612: 'MyCollection.MyCollection()' is obsolete
// Test();
Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "Test()").WithArguments("MyCollection.MyCollection()").WithLocation(100, 9),
// (101,9): warning CS0612: 'MyCollection.MyCollection()' is obsolete
// Test(1);
Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "Test(1)").WithArguments("MyCollection.MyCollection()").WithLocation(101, 9),
// (102,9): warning CS0612: 'MyCollection.MyCollection()' is obsolete
// Test(2, 3);
Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "Test(2, 3)").WithArguments("MyCollection.MyCollection()").WithLocation(102, 9),
// (105,22): warning CS0612: 'MyCollection.MyCollection()' is obsolete
// static void Test(params MyCollection a)
Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "params MyCollection a").WithArguments("MyCollection.MyCollection()").WithLocation(105, 22)
);
}

[Fact]
public void ImplementsIEnumerableT_23_ObsoleteAdd()
{
var src = """
using System.Collections;
using System.Collections.Generic;

class MyCollection : IEnumerable<long>
{
public List<long> Array = new List<long>();
IEnumerator<long> IEnumerable<long>.GetEnumerator() => throw null;
IEnumerator IEnumerable.GetEnumerator() => throw null;

[System.Obsolete()]
public void Add(long l) => Array.Add(l);
}

class Program
{
static void Main()
{
#line 100
Test();
Test(1);
Test(2, 3);
}

static void Test(params MyCollection a)
{
}

[System.Obsolete()]
static void Test2(params MyCollection a)
{
Test2();
Test2(1);
Test2(2, 3);
}
}
""";
var comp = CreateCompilation(src, options: TestOptions.ReleaseExe);

comp.VerifyEmitDiagnostics(
// (101,14): warning CS1064: The best overloaded Add method 'MyCollection.Add(long)' for the collection initializer element is obsolete.
// Test(1);
Diagnostic(ErrorCode.WRN_DeprecatedCollectionInitAdd, "1").WithArguments("MyCollection.Add(long)").WithLocation(101, 14),
// (102,14): warning CS1064: The best overloaded Add method 'MyCollection.Add(long)' for the collection initializer element is obsolete.
// Test(2, 3);
Diagnostic(ErrorCode.WRN_DeprecatedCollectionInitAdd, "2").WithArguments("MyCollection.Add(long)").WithLocation(102, 14),
// (102,17): warning CS1064: The best overloaded Add method 'MyCollection.Add(long)' for the collection initializer element is obsolete.
// Test(2, 3);
Diagnostic(ErrorCode.WRN_DeprecatedCollectionInitAdd, "3").WithArguments("MyCollection.Add(long)").WithLocation(102, 17),
// (105,22): warning CS1064: The best overloaded Add method 'MyCollection.Add(long)' for the collection initializer element is obsolete.
// static void Test(params MyCollection a)
Diagnostic(ErrorCode.WRN_DeprecatedCollectionInitAdd, "params MyCollection a").WithArguments("MyCollection.Add(long)").WithLocation(105, 22)
);
}

[Fact]
public void ImplementsIEnumerable_01()
{
Expand Down