diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs index aa382d6a986bd..eca9f3309e292 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs @@ -6046,7 +6046,7 @@ private BoundExpression BindLeftIdentifierOfPotentialColorColorMemberAccess(Iden { var typeDiagnostics = BindingDiagnosticBag.Create(diagnostics); var boundType = BindNamespaceOrType(left, typeDiagnostics); - if (TypeSymbol.Equals(boundType.Type, leftType, TypeCompareKind.ConsiderEverything2)) + if (TypeSymbol.Equals(boundType.Type, leftType, TypeCompareKind.AllIgnoreOptions)) { // NOTE: ReplaceTypeOrValueReceiver will call CheckValue explicitly. boundValue = BindToNaturalType(boundValue, valueDiagnostics); diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/ColorColorTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/ColorColorTests.cs index 4cb4007004d61..2493a9866c4cb 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/ColorColorTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/ColorColorTests.cs @@ -2182,5 +2182,151 @@ class C2 Diagnostic(ErrorCode.ERR_MethDelegateMismatch, "new System.Action(C2.ReferenceEquals)").WithArguments("ReferenceEquals", "System.Action").WithLocation(9, 13) ); } + + [WorkItem(61171, "https://github.com/dotnet/roslyn/issues/61171")] + [Theory] + [InlineData(null)] + [InlineData("class")] + [InlineData("struct")] + [InlineData("unmanaged")] + [InlineData("notnull")] + public void WorkItem61171_Constraints(string constraint) + { + string constraintLine = $"where TValue : {constraint}"; + if (string.IsNullOrEmpty(constraint)) + { + constraintLine = ""; + } + + string source = $@" +#nullable enable + +namespace DataStructures.Trees; + +public sealed class Tree<TValue> + {constraintLine} +{{ + public abstract class Node + {{ + public abstract NodeType NodeType {{ get; }} + }} + + public sealed class ParentNode : Node + {{ + public override NodeType NodeType => Tree<TValue>.NodeType.Parent; + }} + + public sealed class LeafNode : Node + {{ + public override Tree<TValue>.NodeType NodeType => NodeType.Leaf; + }} + + public enum NodeType + {{ + Parent, + Leaf, + }} +}} +"; + + var compilation = CreateCompilation(source); + + compilation.VerifyDiagnostics(); + } + + [WorkItem(61171, "https://github.com/dotnet/roslyn/issues/61171")] + [Theory] + [InlineData("dynamic", "object")] + [InlineData("(int a, int b)", "(int, int)")] + public void WorkItem61171_DynamicObjectTuple(string inheritedArgument, string propertyArgument) + { + string source = $@" +public class Tree<TValue> +{{ + public enum NodeType + {{ + Parent, + Leaf, + }} +}} + +public class Tree1 : Tree<{inheritedArgument}> +{{ +}} + +public class Tree2 : Tree1 +{{ + public sealed class LeafNode + {{ + public Tree<{propertyArgument}>.NodeType NodeType => NodeType.Leaf; + }} +}} +"; + + var compilation = CreateCompilation(source); + + compilation.VerifyDiagnostics(); + } + + [WorkItem(61171, "https://github.com/dotnet/roslyn/issues/61171")] + [Fact] + public void WorkItem61171_ModoptObject() + { + string genericTreeDefinitionSource = @" +public class Tree2 : Tree1 +{ + public sealed class LeafNode + { + public Tree<dynamic>.NodeType NodeType => NodeType.Leaf; + } +} +"; + + string implementingTreeWithModoptObjectILSource = @" +.class public auto ansi beforefieldinit Tree`1<class TValue> + extends [mscorlib]System.Object +{ + // Nested Types + .class nested public auto ansi sealed NodeType<class TValue> + extends [mscorlib]System.Enum + { + // Fields + .field public specialname rtspecialname int32 value__ + .field public static literal valuetype Tree`1/NodeType<!TValue> Parent = int32(0) + .field public static literal valuetype Tree`1/NodeType<!TValue> Leaf = int32(1) + + } // end of class NodeType + + + // Methods + .method public hidebysig specialname rtspecialname + instance void .ctor () cil managed + { + ldarg.0 + call instance void [mscorlib]System.Object::.ctor() + ret + } // end of method Tree`1::.ctor + +} // end of class Tree`1 + +.class public auto ansi beforefieldinit Tree1 + extends class Tree`1<object modopt(object)> +{ + // Methods + .method public hidebysig specialname rtspecialname + instance void .ctor () cil managed + { + ldarg.0 + call instance void class Tree`1<object>::.ctor() + ret + } // end of method Tree1::.ctor + +} // end of class Tree1 +"; + + var compilation = CreateCompilationWithIL(genericTreeDefinitionSource, implementingTreeWithModoptObjectILSource); + + compilation.VerifyDiagnostics(); + } } }