Skip to content

Commit

Permalink
Merge pull request #7493 from dotnet/fix/enumerable-casts/7357-9.0.1xx
Browse files Browse the repository at this point in the history
[Backport] Fix CA2021 false positive for generic class types
  • Loading branch information
JoeRobich authored Dec 5, 2024
2 parents 3d61c57 + f9a1058 commit 5bfaf6a
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,10 @@ static bool CastWillAlwaysFail(ITypeSymbol castFrom, ITypeSymbol castTo)
return false;
}

// Most checks are better with OriginalDefinition, but keep the ones passed in around.
ITypeSymbol castFromParam = castFrom;
ITypeSymbol castToParam = castTo;

castFrom = castFrom.OriginalDefinition;
castTo = castTo.OriginalDefinition;

Expand Down Expand Up @@ -269,8 +273,8 @@ static bool IsUnconstrainedTypeParameter(ITypeParameterSymbol typeParameterSymbo
return false;

case (TypeKind.Class, TypeKind.Class):
return !castFrom.DerivesFrom(castTo)
&& !castTo.DerivesFrom(castFrom);
return !castFromParam.DerivesFrom(castToParam)
&& !castToParam.DerivesFrom(castFromParam);

case (TypeKind.Interface, TypeKind.Class):
return castTo.IsSealed && !castTo.DerivesFrom(castFrom);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -866,6 +866,50 @@ public sealed record class DataNodeUpdate(DataNode Updated) : NodeUpdate<DataNod
await test.RunAsync();
}

[Fact, WorkItem(7357, "https://github.com/dotnet/roslyn-analyzers/issues/7357")]
public async Task GenericDerivedType()
{
var test = new VerifyCS.Test
{
ReferenceAssemblies = ReferenceAssemblies.Net.Net70,
LanguageVersion = LanguageVersion.CSharp10,
TestCode = @"
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
public static class Program
{
public static void Main()
{
// works as expected
new List<Base>() { new Derived() }.Cast<Derived>().ToList();
// same code but generic, fails
// CastTest\Program.cs(7,1,7,77): warning CA2021: Type 'GenericBase<int>' is incompatible with type 'GenericDerived' and cast attempts will throw InvalidCastException at runtime (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2021)
new List<GenericBase<int>>() { new GenericDerived() }.Cast<GenericDerived>().ToList();
}
}
class Base
{
}
class Derived : Base
{
}
class GenericBase<T>
{
}
class GenericDerived : GenericBase<int>
{
}"
};
await test.RunAsync();
}

[Fact]
public async Task NonGenericCasesVB()
{
Expand Down

0 comments on commit 5bfaf6a

Please sign in to comment.