diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionsBase.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionsBase.cs index 28c1c79ac1461..0a1d248cbe2cd 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionsBase.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionsBase.cs @@ -669,7 +669,7 @@ private Conversion ClassifyStandardImplicitConversion(BoundExpression sourceExpr Conversion conversion = ClassifyImplicitBuiltInConversionFromExpression(sourceExpression, source, destination, ref useSiteInfo); if (conversion.Exists && !conversion.IsInterpolatedStringHandler && - !conversion.IsCollectionExpression) + !isImplicitCollectionExpressionConversion(conversion)) { Debug.Assert(IsStandardImplicitConversionFromExpression(conversion.Kind)); return conversion; @@ -681,6 +681,16 @@ private Conversion ClassifyStandardImplicitConversion(BoundExpression sourceExpr } return Conversion.NoConversion; + + static bool isImplicitCollectionExpressionConversion(Conversion conversion) + { + return conversion switch + { + { Kind: ConversionKind.CollectionExpression } => true, + { Kind: ConversionKind.ImplicitNullable, UnderlyingConversions: [{ Kind: ConversionKind.CollectionExpression }] } => true, + _ => false, + }; + } } private Conversion ClassifyStandardImplicitConversion(TypeSymbol source, TypeSymbol destination, ref CompoundUseSiteInfo useSiteInfo) diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs index 7306ecda575a2..e6e2eee6c8652 100644 --- a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs @@ -39168,5 +39168,127 @@ static void Test(MyCollection a) Diagnostic(ErrorCode.ERR_CollectionBuilderAttributeMethodNotFound, "[1]").WithArguments("Create", "long", "MyCollection").WithLocation(5, 14) ); } + + [WorkItem("https://github.com/dotnet/roslyn/issues/74185")] + [Fact] + public void UserDefinedConversion_Nullable_01() + { + var source = """ + using System.Collections; + using System.Collections.Generic; + using System.Collections.Immutable; + + public class Class1 + { + public Container CreateDiagnostic() + { + return [new object()]; + } + } + + public class Container : IEnumerable + { + public Container() { } + + public IEnumerator GetEnumerator() => null; + + IEnumerator IEnumerable.GetEnumerator() => null; + + public static implicit operator Container(in ImmutableArray? items) => default; + } + """; + var comp = CreateCompilation(source, targetFramework: TargetFramework.Net80); + comp.VerifyEmitDiagnostics( + // (9,16): error CS1061: 'Container' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'Container' could be found (are you missing a using directive or an assembly reference?) + // return [new object()]; + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[new object()]").WithArguments("Container", "Add").WithLocation(9, 16)); + } + + [WorkItem("https://github.com/dotnet/roslyn/issues/74185")] + [Theory] + [InlineData("ImmutableArray")] + [InlineData("ImmutableArray?")] + public void UserDefinedConversion_Nullable_02(string sourceParameterType) + { + var source = $$""" + using System.Collections.Immutable; + + class Program + { + static void Main() + { + Container x = [new object()]; + } + } + + public class Container + { + public static implicit operator Container({{sourceParameterType}} items) => default; + } + """; + var comp = CreateCompilation(source, targetFramework: TargetFramework.Net80); + comp.VerifyEmitDiagnostics( + // (7,31): error CS9174: Cannot initialize type 'Container' with a collection expression because the type is not constructible. + // Container x = [new object()]; + Diagnostic(ErrorCode.ERR_CollectionExpressionTargetTypeNotConstructible, "[new object()]").WithArguments("Container").WithLocation(7, 31)); + } + + [WorkItem("https://github.com/dotnet/roslyn/issues/74185")] + [Theory] + [InlineData("ImmutableArray")] + [InlineData("ImmutableArray?")] + public void UserDefinedConversion_Nullable_03(string sourceParameterType) + { + var source = $$""" + using System.Collections.Immutable; + + class Program + { + static void Main() + { + var x = (Container)[new object()]; + } + } + + public class Container + { + public static implicit operator Container({{sourceParameterType}} items) => default; + } + """; + var comp = CreateCompilation(source, targetFramework: TargetFramework.Net80); + comp.VerifyEmitDiagnostics( + // (7,36): error CS9174: Cannot initialize type 'Container' with a collection expression because the type is not constructible. + // var x = (Container)[new object()]; + Diagnostic(ErrorCode.ERR_CollectionExpressionTargetTypeNotConstructible, "[new object()]").WithArguments("Container").WithLocation(7, 36)); + } + + [WorkItem("https://github.com/dotnet/roslyn/issues/74185")] + [Theory] + [InlineData("ImmutableArray")] + [InlineData("ImmutableArray?")] + public void UserDefinedConversion_Nullable_04(string sourceParameterType) + { + var source = $$""" + using System.Collections.Immutable; + + class Program + { + static void Main() + { + (Container, int) x = ([1, 2], 3); + } + } + + public class Container + { + public static implicit operator Container({{sourceParameterType}} items) => default; + } + """; + var comp = CreateCompilation(source, targetFramework: TargetFramework.Net80); + comp.VerifyEmitDiagnostics( + // (7,36): error CS9174: Cannot initialize type 'Container' with a collection expression because the type is not constructible. + // (Container, int) x = ([1, 2], 3); + Diagnostic(ErrorCode.ERR_CollectionExpressionTargetTypeNotConstructible, "[1, 2]").WithArguments("Container").WithLocation(7, 36)); + } } }