diff --git a/eng/Versions.props b/eng/Versions.props index 5da6039a57..fb35bebb90 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -70,7 +70,7 @@ - 4.8.0 + 4.9.0-3.final 4.6.0-1.final 4.6.0 4.6.0 diff --git a/src/Roslyn.Diagnostics.Analyzers/Core/AbstractDoNotCopyValue.cs b/src/Roslyn.Diagnostics.Analyzers/Core/AbstractDoNotCopyValue.cs index 2f8f3b346c..d2bbb873d8 100644 --- a/src/Roslyn.Diagnostics.Analyzers/Core/AbstractDoNotCopyValue.cs +++ b/src/Roslyn.Diagnostics.Analyzers/Core/AbstractDoNotCopyValue.cs @@ -10,6 +10,7 @@ using System.Linq; using Analyzer.Utilities; using Analyzer.Utilities.Extensions; +using Analyzer.Utilities.Lightup; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.FlowAnalysis; @@ -1437,6 +1438,9 @@ when SymbolEqualityComparer.Default.Equals(taskType, Cache.ValueTaskT) || Symbol case OperationKind.Throw: return RefKind.None; + case OperationKindEx.CollectionExpression: + return RefKind.None; + default: return RefKind.RefReadOnly; } diff --git a/src/Roslyn.Diagnostics.Analyzers/UnitTests/DoNotCopyValueTests.cs b/src/Roslyn.Diagnostics.Analyzers/UnitTests/DoNotCopyValueTests.cs index 3f1b6fb663..f46b1ccf80 100644 --- a/src/Roslyn.Diagnostics.Analyzers/UnitTests/DoNotCopyValueTests.cs +++ b/src/Roslyn.Diagnostics.Analyzers/UnitTests/DoNotCopyValueTests.cs @@ -1400,5 +1400,123 @@ End Structure // /0/Test0.vb(38,22): warning RS0042: Auto-property 'Private Property Property3 As CannotCopy' cannot have non-copyable type 'CannotCopy' VerifyVB.Diagnostic(AbstractDoNotCopyValue.NoAutoPropertyRule).WithLocation(1).WithArguments("CannotCopy", "Private Property Property3 As CannotCopy")); } + + [Fact] + public async Task AllowCopyFromCollectionExpression() + { + var source = """ + using System; + using System.Collections; + using System.Collections.Generic; + using System.Runtime.CompilerServices; + + [NonCopyable] + [CollectionBuilder(typeof(MyCollection), nameof(Create))] + partial struct MyCollection : IEnumerable + { + public IEnumerator GetEnumerator() => null; + IEnumerator IEnumerable.GetEnumerator() => null; + + public static MyCollection Create(ReadOnlySpan r) => throw null; + } + + class C + { + void M() + { + MyCollection m = [1, 2, 3]; + m = []; + } + } + + internal sealed class NonCopyableAttribute : System.Attribute { } + + namespace System.Runtime.CompilerServices + { + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, Inherited = false)] + internal sealed class CollectionBuilderAttribute : Attribute + { + public CollectionBuilderAttribute(Type builderType, string methodName) + { + BuilderType = builderType; + MethodName = methodName; + } + + public Type BuilderType { get; } + + public string MethodName { get; } + } + } + """; + + await new VerifyCS.Test + { + TestCode = source, + LanguageVersion = Microsoft.CodeAnalysis.CSharp.LanguageVersion.CSharp12, + }.RunAsync(); + } + + [Fact] + public async Task DoNotAllowCopyInCollectionExpressionElement() + { + var source = """ + using System; + using System.Collections; + using System.Collections.Generic; + using System.Runtime.CompilerServices; + + [NonCopyable] + struct S + { + } + + [CollectionBuilder(typeof(MyCollection), nameof(Create))] + partial struct MyCollection : IEnumerable + { + public IEnumerator GetEnumerator() => throw null; + IEnumerator IEnumerable.GetEnumerator() => throw null; + + public static MyCollection Create(ReadOnlySpan r) => throw null; + } + + class C + { + void M() + { + S s = new(); + MyCollection m = [{|#0:s|}, new S()]; + } + } + + internal sealed class NonCopyableAttribute : System.Attribute { } + + namespace System.Runtime.CompilerServices + { + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, Inherited = false)] + internal sealed class CollectionBuilderAttribute : Attribute + { + public CollectionBuilderAttribute(Type builderType, string methodName) + { + BuilderType = builderType; + MethodName = methodName; + } + + public Type BuilderType { get; } + + public string MethodName { get; } + } + } + """; + + await new VerifyCS.Test + { + TestCode = source, + LanguageVersion = Microsoft.CodeAnalysis.CSharp.LanguageVersion.CSharp12, + ExpectedDiagnostics = { + // /0/Test0.cs(25,27): warning RS0042: Unsupported use of non-copyable type 'S' in 'LocalReference' operation + VerifyCS.Diagnostic(AbstractDoNotCopyValue.UnsupportedUseRule).WithLocation(0).WithArguments("S", "LocalReference") + } + }.RunAsync(); + } } } diff --git a/src/Utilities/Compiler/Lightup/OperationKindEx.cs b/src/Utilities/Compiler/Lightup/OperationKindEx.cs index e5df73142f..99f5c0f79b 100644 --- a/src/Utilities/Compiler/Lightup/OperationKindEx.cs +++ b/src/Utilities/Compiler/Lightup/OperationKindEx.cs @@ -12,6 +12,7 @@ internal static class OperationKindEx public const OperationKind ImplicitIndexerReference = (OperationKind)0x7b; public const OperationKind Utf8String = (OperationKind)0x7c; public const OperationKind Attribute = (OperationKind)0x7d; + public const OperationKind CollectionExpression = (OperationKind)0x7f; } }