From 500e713bd1696cc6e2608fc23d16a6346bf7f5c4 Mon Sep 17 00:00:00 2001 From: Jan Jones Date: Thu, 3 Oct 2024 11:21:36 +0200 Subject: [PATCH 1/5] Fix assignment analysis of ref fields --- .../Portable/FlowAnalysis/AbstractFlowPass.cs | 16 +- .../FlowAnalysis/DataFlowsOutWalker.cs | 4 +- .../FlowAnalysis/DefiniteAssignment.cs | 66 +-- .../Portable/FlowAnalysis/ReadWriteWalker.cs | 8 +- .../Symbols/Source/SourceAssemblySymbol.cs | 5 +- .../Emit3/FlowAnalysis/RegionAnalysisTests.cs | 3 + .../Test/Emit3/Semantics/InlineArrayTests.cs | 14 +- .../Test/Semantic/Semantics/RefFieldTests.cs | 515 ++++++++++++++++-- 8 files changed, 535 insertions(+), 96 deletions(-) diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/AbstractFlowPass.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/AbstractFlowPass.cs index cdb93dcbf2bf5..9688c7c4084c5 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/AbstractFlowPass.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/AbstractFlowPass.cs @@ -1545,10 +1545,20 @@ private void VisitArgumentsAfterCall(ImmutableArray arguments, for (int i = 0; i < arguments.Length; i++) { RefKind refKind = GetRefKind(refKindsOpt, i); - // passing as a byref argument is also a potential write - if (refKind != RefKind.None) + switch (refKind) { - WriteArgument(arguments[i], refKind, method); + case RefKind.None: + case RefKind.In: + case RefKind.RefReadOnlyParameter: + case RefKindExtensions.StrictIn: + break; + case RefKind.Ref: + case RefKind.Out: + // passing as a byref argument is also a potential write + WriteArgument(arguments[i], refKind, method); + break; + default: + throw ExceptionUtilities.UnexpectedValue(refKind); } } } diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/DataFlowsOutWalker.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/DataFlowsOutWalker.cs index be797584c8936..9bbb8f5efa013 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/DataFlowsOutWalker.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/DataFlowsOutWalker.cs @@ -88,7 +88,7 @@ protected override void EnterRegion() base.EnterRegion(); } - protected override void NoteWrite(Symbol variable, BoundExpression value, bool read) + protected override void NoteWrite(Symbol variable, BoundExpression value, bool read, bool isRef) { // any reachable assignment to a ref or out parameter can be visible to the caller in the face of exceptions. if (this.State.Reachable && IsInside) @@ -107,7 +107,7 @@ protected override void NoteWrite(Symbol variable, BoundExpression value, bool r #endif } - base.NoteWrite(variable, value, read); + base.NoteWrite(variable, value, read: read, isRef: isRef); } #if DEBUG diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/DefiniteAssignment.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/DefiniteAssignment.cs index e009b16967e55..3845873d8fada 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/DefiniteAssignment.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/DefiniteAssignment.cs @@ -346,7 +346,7 @@ protected override ImmutableArray Scan(ref bool badRegion) // All primary constructor parameters are definitely assigned outside of the primary constructor foreach (var parameter in primaryConstructor.Parameters) { - NoteWrite(parameter, value: null, read: true); + NoteWrite(parameter, value: null, read: true, isRef: false); } CurrentSymbol = save; @@ -846,7 +846,7 @@ private void NoteRead(BoundNode fieldOrEventAccess) } } - protected virtual void NoteWrite(Symbol variable, BoundExpression value, bool read) + protected virtual void NoteWrite(Symbol variable, BoundExpression value, bool read, bool isRef) { if ((object)variable != null) { @@ -854,7 +854,9 @@ protected virtual void NoteWrite(Symbol variable, BoundExpression value, bool re if ((object)_sourceAssembly != null && variable.Kind == SymbolKind.Field) { var field = (FieldSymbol)variable.OriginalDefinition; - _sourceAssembly.NoteFieldAccess(field, read: read && WriteConsideredUse(field.Type, value), write: true); + _sourceAssembly.NoteFieldAccess(field, + read: read && WriteConsideredUse(field.Type, value), + write: field.RefKind == RefKind.None || isRef); } var local = variable as LocalSymbol; @@ -949,7 +951,7 @@ internal static bool WriteConsideredUse(TypeSymbol type, BoundExpression value) } } - private void NoteWrite(BoundExpression n, BoundExpression value, bool read) + private void NoteWrite(BoundExpression n, BoundExpression value, bool read, bool isRef) { while (n != null) { @@ -961,7 +963,9 @@ private void NoteWrite(BoundExpression n, BoundExpression value, bool read) if ((object)_sourceAssembly != null) { var field = fieldAccess.FieldSymbol.OriginalDefinition; - _sourceAssembly.NoteFieldAccess(field, read: value == null || WriteConsideredUse(fieldAccess.FieldSymbol.Type, value), write: true); + _sourceAssembly.NoteFieldAccess(field, + read: value == null || WriteConsideredUse(fieldAccess.FieldSymbol.Type, value), + write: field.RefKind == RefKind.None || isRef); } if (MayRequireTracking(fieldAccess.ReceiverOpt, fieldAccess.FieldSymbol)) @@ -1001,19 +1005,19 @@ private void NoteWrite(BoundExpression n, BoundExpression value, bool read) } case BoundKind.ThisReference: - NoteWrite(MethodThisParameter, value, read); + NoteWrite(MethodThisParameter, value, read: read, isRef: isRef); return; case BoundKind.Local: - NoteWrite(((BoundLocal)n).LocalSymbol, value, read); + NoteWrite(((BoundLocal)n).LocalSymbol, value, read: read, isRef: isRef); return; case BoundKind.Parameter: - NoteWrite(((BoundParameter)n).ParameterSymbol, value, read); + NoteWrite(((BoundParameter)n).ParameterSymbol, value, read: read, isRef: isRef); return; case BoundKind.RangeVariable: - NoteWrite(((BoundRangeVariable)n).Value, value, read); + NoteWrite(((BoundRangeVariable)n).Value, value, read: read, isRef: isRef); return; case BoundKind.InlineArrayAccess: @@ -1542,7 +1546,7 @@ protected virtual void AssignImpl(BoundNode node, BoundExpression value, bool is SetSlotState(slot, assigned: written || !this.State.Reachable); } - if (written) NoteWrite(pattern.VariableAccess, value, read); + if (written) NoteWrite(pattern.VariableAccess, value, read: read, isRef: isRef); break; } @@ -1553,7 +1557,7 @@ protected virtual void AssignImpl(BoundNode node, BoundExpression value, bool is LocalSymbol symbol = local.LocalSymbol; int slot = GetOrCreateSlot(symbol); SetSlotState(slot, assigned: written || !this.State.Reachable); - if (written) NoteWrite(symbol, value, read); + if (written) NoteWrite(symbol, value, read: read, isRef: isRef); break; } @@ -1570,7 +1574,7 @@ protected virtual void AssignImpl(BoundNode node, BoundExpression value, bool is { int slot = MakeSlot(local); SetSlotState(slot, written); - if (written) NoteWrite(local, value, read); + if (written) NoteWrite(local, value, read: read, isRef: isRef); } break; } @@ -1580,7 +1584,7 @@ protected virtual void AssignImpl(BoundNode node, BoundExpression value, bool is var elementAccess = (BoundInlineArrayAccess)node; if (written) { - NoteWrite(elementAccess.Expression, value: null, read); + NoteWrite(elementAccess.Expression, value: null, read: read, isRef: isRef); } if (elementAccess.Expression.Type.HasInlineArrayAttribute(out int length) && @@ -1618,7 +1622,19 @@ protected virtual void AssignImpl(BoundNode node, BoundExpression value, bool is int slot = MakeSlot(paramExpr); SetSlotState(slot, written); - if (written) NoteWrite(paramExpr, value, read); + if (written) NoteWrite(paramExpr, value, read: read, isRef: isRef); + break; + } + + case BoundKind.ObjectInitializerMember: + { + var member = (BoundObjectInitializerMember)node; + if (_sourceAssembly is not null && member.MemberSymbol is FieldSymbol field) + { + _sourceAssembly.NoteFieldAccess(field.OriginalDefinition, + read: false, + write: field.RefKind == RefKind.None || isRef); + } break; } @@ -1630,7 +1646,7 @@ protected virtual void AssignImpl(BoundNode node, BoundExpression value, bool is var expression = (BoundExpression)node; int slot = MakeSlot(expression); SetSlotState(slot, written); - if (written) NoteWrite(expression, value, read); + if (written) NoteWrite(expression, value, read: read, isRef: isRef); break; } @@ -1864,7 +1880,7 @@ protected override void EnterParameter(ParameterSymbol parameter) { // this code has no effect except in region analysis APIs such as DataFlowsOut where we unassign things if (slot > 0) SetSlotState(slot, true); - NoteWrite(parameter, value: null, read: true); + NoteWrite(parameter, value: null, read: true, isRef: false); } if (parameter is SourceComplexParameterSymbolBase { ContainingSymbol: LocalFunctionSymbol or LambdaSymbol } sourceComplexParam) @@ -2748,20 +2764,8 @@ public override void VisitForEachIterationVariables(BoundForEachStatement node) int slot = GetOrCreateSlot(iterationVariable); if (slot > 0) SetSlotAssigned(slot); // NOTE: do not report unused iteration variables. They are always considered used. - NoteWrite(iterationVariable, null, read: true); - } - } - - public override BoundNode VisitObjectInitializerMember(BoundObjectInitializerMember node) - { - var result = base.VisitObjectInitializerMember(node); - - if ((object)_sourceAssembly != null && node.MemberSymbol != null && node.MemberSymbol.Kind == SymbolKind.Field) - { - _sourceAssembly.NoteFieldAccess((FieldSymbol)node.MemberSymbol.OriginalDefinition, read: false, write: true); + NoteWrite(iterationVariable, null, read: true, isRef: false); } - - return result; } public override BoundNode VisitDynamicObjectInitializerMember(BoundDynamicObjectInitializerMember node) @@ -2790,7 +2794,7 @@ protected override void AfterVisitInlineArrayAccess(BoundInlineArrayAccess node) if (node.GetItemOrSliceHelper == WellKnownMember.System_Span_T__Slice_Int_Int) { // exposing ref is a potential write - NoteWrite(node.Expression, value: null, read: false); + NoteWrite(node.Expression, value: null, read: false, isRef: false); } } @@ -2800,7 +2804,7 @@ protected override void AfterVisitConversion(BoundConversion node) node.Type.OriginalDefinition.Equals(compilation.GetWellKnownType(WellKnownType.System_Span_T), TypeCompareKind.AllIgnoreOptions)) { // exposing ref is a potential write - NoteWrite(node.Operand, value: null, read: false); + NoteWrite(node.Operand, value: null, read: false, isRef: false); } } diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/ReadWriteWalker.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/ReadWriteWalker.cs index c5a3ed6f8ab2f..427d6080634fa 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/ReadWriteWalker.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/ReadWriteWalker.cs @@ -129,11 +129,11 @@ protected override void NoteRead(Symbol variable, ParameterSymbol rangeVariableU base.NoteRead(variable, rangeVariableUnderlyingParameter); } - protected override void NoteWrite(Symbol variable, BoundExpression value, bool read) + protected override void NoteWrite(Symbol variable, BoundExpression value, bool read, bool isRef) { if ((object)variable == null) return; (IsInside ? _writtenInside : _writtenOutside).Add(variable); - base.NoteWrite(variable, value, read); + base.NoteWrite(variable, value, read: read, isRef: isRef); } protected override void CheckAssigned(BoundExpression expr, FieldSymbol fieldSymbol, SyntaxNode node) @@ -233,7 +233,7 @@ protected override void AssignImpl(BoundNode node, BoundExpression value, bool i switch (node.Kind) { case BoundKind.RangeVariable: - if (written) NoteWrite(((BoundRangeVariable)node).RangeVariableSymbol, value, read); + if (written) NoteWrite(((BoundRangeVariable)node).RangeVariableSymbol, value, read: read, isRef: isRef); break; case BoundKind.QueryClause: @@ -242,7 +242,7 @@ protected override void AssignImpl(BoundNode node, BoundExpression value, bool i var symbol = ((BoundQueryClause)node).DefinedSymbol; if ((object)symbol != null) { - if (written) NoteWrite(symbol, value, read); + if (written) NoteWrite(symbol, value, read: read, isRef: isRef); } } break; diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceAssemblySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceAssemblySymbol.cs index c0bbc5a77fbae..f3cee9252c70f 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceAssemblySymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceAssemblySymbol.cs @@ -2742,7 +2742,7 @@ internal ImmutableArray GetUnusedFieldWarnings(CancellationToken can } else { - diagnostics.Add(ErrorCode.WRN_UnassignedInternalField, field.GetFirstLocationOrNone(), field, DefaultValue(field.Type)); + diagnostics.Add(ErrorCode.WRN_UnassignedInternalField, field.GetFirstLocationOrNone(), field, DefaultValue(field.Type, isRef: field.RefKind != RefKind.None)); } } @@ -2773,9 +2773,10 @@ internal ImmutableArray GetUnusedFieldWarnings(CancellationToken can return _unusedFieldWarnings; } - private static string DefaultValue(TypeSymbol type) + private static string DefaultValue(TypeSymbol type, bool isRef) { // TODO: localize these strings + if (isRef) return "(null reference)"; if (type.IsReferenceType) return "null"; switch (type.SpecialType) { diff --git a/src/Compilers/CSharp/Test/Emit3/FlowAnalysis/RegionAnalysisTests.cs b/src/Compilers/CSharp/Test/Emit3/FlowAnalysis/RegionAnalysisTests.cs index 3c381b5eef66e..a99164d488376 100644 --- a/src/Compilers/CSharp/Test/Emit3/FlowAnalysis/RegionAnalysisTests.cs +++ b/src/Compilers/CSharp/Test/Emit3/FlowAnalysis/RegionAnalysisTests.cs @@ -14109,6 +14109,9 @@ ref struct RS """, targetFramework: TargetFramework.NetCoreApp); comp.VerifyEmitDiagnostics( + // (3,13): warning CS0649: Field 'RS.ri' is never assigned to, and will always have its default value (null reference) + // ref int ri; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "ri").WithArguments("RS.ri", "(null reference)").WithLocation(3, 13), // (4,20): warning CS9201: Ref field 'ri' should be ref-assigned before use. // public RS() => ri = 0; Diagnostic(ErrorCode.WRN_UseDefViolationRefField, "ri").WithArguments("ri").WithLocation(4, 20)); diff --git a/src/Compilers/CSharp/Test/Emit3/Semantics/InlineArrayTests.cs b/src/Compilers/CSharp/Test/Emit3/Semantics/InlineArrayTests.cs index 745c0e4d1c167..18754727921a9 100644 --- a/src/Compilers/CSharp/Test/Emit3/Semantics/InlineArrayTests.cs +++ b/src/Compilers/CSharp/Test/Emit3/Semantics/InlineArrayTests.cs @@ -4676,7 +4676,10 @@ static async Task FromResult(T r) } "; var comp = CreateCompilation(src + Buffer10Definition, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseExe); - var verifier = CompileAndVerify(comp, expectedOutput: "111", verify: Verification.Fails).VerifyDiagnostics(); + var verifier = CompileAndVerify(comp, expectedOutput: "111", verify: Verification.Fails).VerifyDiagnostics( + // (6,45): warning CS0649: Field 'C.F' is never assigned to, and will always have its default value + // public readonly Buffer10> F; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("C.F", "").WithLocation(6, 45)); verifier.VerifyIL("Program.d__1.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext", @" @@ -4832,6 +4835,9 @@ static async Task FromResult(T r) "; var comp = CreateCompilation(src + Buffer10Definition, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseExe); comp.VerifyEmitDiagnostics( + // (8,45): warning CS0649: Field 'C.F' is never assigned to, and will always have its default value + // public readonly Buffer10> F; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("C.F", "").WithLocation(8, 45), // (20,12): error CS4007: Instance of type 'System.ReadOnlySpan>' cannot be preserved across 'await' or 'yield' boundary. // => MemoryMarshal.CreateReadOnlySpan( Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, @"MemoryMarshal.CreateReadOnlySpan( @@ -4887,6 +4893,9 @@ static async Task FromResult(T r) "; var comp = CreateCompilation(src + Buffer10Definition, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseExe); comp.VerifyEmitDiagnostics( + // (8,45): warning CS0649: Field 'C.F' is never assigned to, and will always have its default value + // public readonly Buffer10> F; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("C.F", "").WithLocation(8, 45), // (20,12): error CS4007: Instance of type 'System.ReadOnlySpan' cannot be preserved across 'await' or 'yield' boundary. // => MemoryMarshal.CreateReadOnlySpan( Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, @"MemoryMarshal.CreateReadOnlySpan( @@ -4940,6 +4949,9 @@ static async Task FromResult(T r) "; var comp = CreateCompilation(src + Buffer10Definition, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseExe); comp.VerifyEmitDiagnostics( + // (8,45): warning CS0649: Field 'C.F' is never assigned to, and will always have its default value + // public readonly Buffer10> F; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("C.F", "").WithLocation(8, 45), // (20,12): error CS8178: A reference returned by a call to 'Program.GetItem(ReadOnlySpan>, int)' cannot be preserved across 'await' or 'yield' boundary. // => GetItem(MemoryMarshal.CreateReadOnlySpan(ref Unsafe.As>, Buffer10>(ref Unsafe.AsRef(in GetC(x).F)),10), Get01())[await FromResult(Get02(x))]; Diagnostic(ErrorCode.ERR_RefReturningCallAndAwait, "GetItem(MemoryMarshal.CreateReadOnlySpan(ref Unsafe.As>, Buffer10>(ref Unsafe.AsRef(in GetC(x).F)),10), Get01())").WithArguments("Program.GetItem(System.ReadOnlySpan>, int)").WithLocation(20, 12) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs index 524e3e7ab5cb4..c5a060efd7d2f 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs @@ -1798,9 +1798,9 @@ public R() """; var comp = CreateCompilation(source, options: TestOptions.ReleaseExe, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics( - // (7,29): warning CS0649: Field 'R.field' is never assigned to, and will always have its default value 0 + // (7,29): warning CS0649: Field 'R.field' is never assigned to, and will always have its default value (null reference) // public readonly ref int field; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "field").WithArguments("R.field", "0").WithLocation(7, 29) + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "field").WithArguments("R.field", "(null reference)").WithLocation(7, 29) ); var verifier = CompileAndVerify(comp, verify: Verification.Skipped, expectedOutput: IncludeExpectedOutput("explicit ctor")); @@ -5213,7 +5213,10 @@ class Program }"; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); comp.VerifyEmitDiagnostics( - // (4,25): warning CS9201: 'ref' field '_t' should be ref-assigned before use. + // (3,19): warning CS0649: Field 'R._t' is never assigned to, and will always have its default value (null reference) + // private ref T _t; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "_t").WithArguments("R._t", "(null reference)").WithLocation(3, 19), + // (4,25): warning CS9201: Ref field '_t' should be ref-assigned before use. // public R(ref T t) { _t = t; } Diagnostic(ErrorCode.WRN_UseDefViolationRefField, "_t").WithArguments("_t").WithLocation(4, 25)); } @@ -5461,11 +5464,282 @@ public S(ref T t) }"; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); comp.VerifyEmitDiagnostics( - // (6,9): warning CS9201: 'ref' field 'F' should be ref-assigned before use. + // (3,18): warning CS0649: Field 'S.F' is never assigned to, and will always have its default value (null reference) + // public ref T F; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("S.F", "(null reference)").WithLocation(3, 18), + // (6,9): warning CS9201: Ref field 'F' should be ref-assigned before use. // F = t; Diagnostic(ErrorCode.WRN_UseDefViolationRefField, "F").WithArguments("F").WithLocation(6, 9)); } + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75315")] + public void DefiniteAssignment_RefField_Unassigned_InAtCallSite() + { + var comp = CreateCompilation(""" + ref struct R + { + public ref int F; + + static void M(in int x) { } + + static void Test(R r) + { + M(in r.F); + } + } + """, + targetFramework: TargetFramework.NetCoreApp); + comp.VerifyDiagnostics( + // (3,20): warning CS0649: Field 'R.F' is never assigned to, and will always have its default value (null reference) + // public ref int F; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "(null reference)").WithLocation(3, 20)); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75315")] + public void DefiniteAssignment_RefField_RefAssigned_InAtCallSite() + { + var comp = CreateCompilation(""" + ref struct R + { + public ref int F; + + static void M(in int x) { } + + static void Test(scoped R r, ref int x) + { + r.F = ref x; + M(in r.F); + } + } + """, + targetFramework: TargetFramework.NetCoreApp); + comp.VerifyDiagnostics(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75315")] + public void DefiniteAssignment_RefField_RefAssignedInObjectInitializer_InAtCallSite() + { + var comp = CreateCompilation(""" + ref struct R + { + public ref int F; + + static void M(in int x) { } + + static void Test(ref int x) + { + var r = new R { F = ref x }; + M(in r.F); + } + } + """, + targetFramework: TargetFramework.NetCoreApp); + comp.VerifyDiagnostics(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75315")] + public void DefiniteAssignment_RefField_Assigned_InAtCallSite() + { + var comp = CreateCompilation(""" + ref struct R + { + public ref int F; + + static void M(in int x) { } + + static void Test(R r, int x) + { + r.F = x; + M(in r.F); + } + } + """, + targetFramework: TargetFramework.NetCoreApp); + comp.VerifyDiagnostics( + // (3,20): warning CS0649: Field 'R.F' is never assigned to, and will always have its default value (null reference) + // public ref int F; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "(null reference)").WithLocation(3, 20)); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75315")] + public void DefiniteAssignment_RefField_AssignedInObjectInitializer_InAtCallSite() + { + var comp = CreateCompilation(""" + ref struct R + { + public ref int F; + + static void M(in int x) { } + + static void Test(int x) + { + var r = new R { F = x }; + M(in r.F); + } + } + """, + targetFramework: TargetFramework.NetCoreApp); + comp.VerifyDiagnostics( + // (3,20): warning CS0649: Field 'R.F' is never assigned to, and will always have its default value (null reference) + // public ref int F; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "(null reference)").WithLocation(3, 20)); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75315")] + public void DefiniteAssignment_ValueField_Unassigned_InAtCallSite() + { + var comp = CreateCompilation(""" + ref struct R + { + public int F; + + static void M(in int x) { } + + static void Test(R r) + { + M(in r.F); + } + } + """, + targetFramework: TargetFramework.NetCoreApp); + comp.VerifyDiagnostics( + // (3,16): warning CS0649: Field 'R.F' is never assigned to, and will always have its default value 0 + // public int F; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "0").WithLocation(3, 16)); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75315")] + public void DefiniteAssignment_RefField_Unassigned_PlainAtCallSite() + { + var comp = CreateCompilation(""" + ref struct R + { + public ref int F; + + static void M(in int x) { } + + static void Test(R r) + { + M(r.F); + } + } + """, + targetFramework: TargetFramework.NetCoreApp); + comp.VerifyDiagnostics( + // (3,20): warning CS0649: Field 'R.F' is never assigned to, and will always have its default value (null reference) + // public ref int F; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "(null reference)").WithLocation(3, 20)); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75315")] + public void DefiniteAssignment_ValueField_Unassigned_PlainAtCallSite() + { + var comp = CreateCompilation(""" + ref struct R + { + public int F; + + static void M(in int x) { } + + static void Test(R r) + { + M(r.F); + } + } + """, + targetFramework: TargetFramework.NetCoreApp); + comp.VerifyDiagnostics( + // (3,16): warning CS0649: Field 'R.F' is never assigned to, and will always have its default value 0 + // public int F; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "0").WithLocation(3, 16)); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75315")] + public void DefiniteAssignment_RefField_Unassigned_RefAtCallSite() + { + var comp = CreateCompilation(""" + ref struct R + { + public ref int F; + + static void M(ref int x) { } + + static void Test(R r) + { + M(ref r.F); + } + } + """, + targetFramework: TargetFramework.NetCoreApp); + comp.VerifyDiagnostics( + // (3,20): warning CS0649: Field 'R.F' is never assigned to, and will always have its default value (null reference) + // public ref int F; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "(null reference)").WithLocation(3, 20)); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75315")] + public void DefiniteAssignment_ValueField_Unassigned_RefAtCallSite() + { + var comp = CreateCompilation(""" + ref struct R + { + public int F; + + static void M(ref int x) { } + + static void Test(R r) + { + M(ref r.F); + } + } + """, + targetFramework: TargetFramework.NetCoreApp); + comp.VerifyDiagnostics(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75315")] + public void DefiniteAssignment_RefField_Unassigned_OutAtCallSite() + { + var comp = CreateCompilation(""" + ref struct R + { + public ref int F; + + static void M(out int x) => throw null; + + static void Test(R r) + { + M(out r.F); + } + } + """, + targetFramework: TargetFramework.NetCoreApp); + comp.VerifyDiagnostics( + // (3,20): warning CS0649: Field 'R.F' is never assigned to, and will always have its default value (null reference) + // public ref int F; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "(null reference)").WithLocation(3, 20)); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75315")] + public void DefiniteAssignment_ValueField_Unassigned_OutAtCallSite() + { + var comp = CreateCompilation(""" + ref struct R + { + public int F; + + static void M(out int x) => throw null; + + static void Test(R r) + { + M(out r.F); + } + } + """, + targetFramework: TargetFramework.NetCoreApp); + comp.VerifyDiagnostics(); + } + [Fact] public void AssignLocal() { @@ -5571,7 +5845,10 @@ object P }"; var comp = CreateCompilation(new[] { source, IsExternalInitTypeDefinition }, targetFramework: TargetFramework.Net70); comp.VerifyEmitDiagnostics( - // 0.cs(7,9): warning CS9201: 'ref' field 'F' should be ref-assigned before use. + // 0.cs(3,18): warning CS0649: Field 'S.F' is never assigned to, and will always have its default value (null reference) + // public ref T F; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("S.F", "(null reference)").WithLocation(3, 18), + // 0.cs(7,9): warning CS9201: Ref field 'F' should be ref-assigned before use. // F = tValue; Diagnostic(ErrorCode.WRN_UseDefViolationRefField, "F").WithArguments("F").WithLocation(7, 9)); } @@ -5606,10 +5883,13 @@ object P }"; var comp = CreateCompilation(new[] { source, IsExternalInitTypeDefinition }, targetFramework: TargetFramework.Net70); comp.VerifyEmitDiagnostics( + // (3,27): warning CS0649: Field 'S.F' is never assigned to, and will always have its default value (null reference) + // public ref readonly T F; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("S.F", "(null reference)").WithLocation(3, 27), // (7,9): error CS8331: Cannot assign to field 'F' or use it as the right hand side of a ref assignment because it is a readonly variable // F = tValue; // 1 Diagnostic(ErrorCode.ERR_AssignReadonlyNotField, "F").WithArguments("field", "F").WithLocation(7, 9), - // (7,9): warning CS9201: 'ref' field 'F' should be ref-assigned before use. + // (7,9): warning CS9201: Ref field 'F' should be ref-assigned before use. // F = tValue; // 1 Diagnostic(ErrorCode.WRN_UseDefViolationRefField, "F").WithArguments("F").WithLocation(7, 9), // (8,9): error CS8331: Cannot assign to field 'F' or use it as the right hand side of a ref assignment because it is a readonly variable @@ -5662,7 +5942,10 @@ object P }"; var comp = CreateCompilation(new[] { source, IsExternalInitTypeDefinition }, targetFramework: TargetFramework.Net70); comp.VerifyEmitDiagnostics( - // 0.cs(7,9): warning CS9201: 'ref' field 'F' should be ref-assigned before use. + // 0.cs(3,27): warning CS0649: Field 'S.F' is never assigned to, and will always have its default value (null reference) + // public readonly ref T F; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("S.F", "(null reference)").WithLocation(3, 27), + // 0.cs(7,9): warning CS9201: Ref field 'F' should be ref-assigned before use. // F = tValue; Diagnostic(ErrorCode.WRN_UseDefViolationRefField, "F").WithArguments("F").WithLocation(7, 9)); } @@ -5697,10 +5980,13 @@ object P }"; var comp = CreateCompilation(new[] { source, IsExternalInitTypeDefinition }, targetFramework: TargetFramework.Net70); comp.VerifyEmitDiagnostics( + // (3,36): warning CS0649: Field 'S.F' is never assigned to, and will always have its default value (null reference) + // public readonly ref readonly T F; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("S.F", "(null reference)").WithLocation(3, 36), // (7,9): error CS8331: Cannot assign to field 'F' or use it as the right hand side of a ref assignment because it is a readonly variable // F = tValue; // 1 Diagnostic(ErrorCode.ERR_AssignReadonlyNotField, "F").WithArguments("field", "F").WithLocation(7, 9), - // (7,9): warning CS9201: 'ref' field 'F' should be ref-assigned before use. + // (7,9): warning CS9201: Ref field 'F' should be ref-assigned before use. // F = tValue; // 1 Diagnostic(ErrorCode.WRN_UseDefViolationRefField, "F").WithArguments("F").WithLocation(7, 9), // (8,9): error CS8331: Cannot assign to field 'F' or use it as the right hand side of a ref assignment because it is a readonly variable @@ -7207,6 +7493,18 @@ class Program }"; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); comp.VerifyEmitDiagnostics( + // (3,18): warning CS0649: Field 'S.Ref' is never assigned to, and will always have its default value (null reference) + // public ref T Ref; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "Ref").WithArguments("S.Ref", "(null reference)").WithLocation(3, 18), + // (4,27): warning CS0649: Field 'S.RefReadonly' is never assigned to, and will always have its default value (null reference) + // public ref readonly T RefReadonly; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "RefReadonly").WithArguments("S.RefReadonly", "(null reference)").WithLocation(4, 27), + // (5,27): warning CS0649: Field 'S.ReadonlyRef' is never assigned to, and will always have its default value (null reference) + // public readonly ref T ReadonlyRef; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "ReadonlyRef").WithArguments("S.ReadonlyRef", "(null reference)").WithLocation(5, 27), + // (6,36): warning CS0649: Field 'S.ReadonlyRefReadonly' is never assigned to, and will always have its default value (null reference) + // public readonly ref readonly T ReadonlyRefReadonly; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "ReadonlyRefReadonly").WithArguments("S.ReadonlyRefReadonly", "(null reference)").WithLocation(6, 36), // (12,73): error CS8329: Cannot use field 'RefReadonly' as a ref or out value because it is a readonly variable // static void FromValueRefReadonly(S s) { ref T t = ref s.RefReadonly; } // 1 Diagnostic(ErrorCode.ERR_RefReadonlyNotField, "s.RefReadonly").WithArguments("field", "RefReadonly").WithLocation(12, 73), @@ -7268,7 +7566,19 @@ class Program static void FromInReadonlyRefReadonly(in S s) { ref readonly T t = ref s.ReadonlyRefReadonly; } }"; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); - comp.VerifyEmitDiagnostics(); + comp.VerifyEmitDiagnostics( + // (3,18): warning CS0649: Field 'S.Ref' is never assigned to, and will always have its default value (null reference) + // public ref T Ref; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "Ref").WithArguments("S.Ref", "(null reference)").WithLocation(3, 18), + // (4,27): warning CS0649: Field 'S.RefReadonly' is never assigned to, and will always have its default value (null reference) + // public ref readonly T RefReadonly; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "RefReadonly").WithArguments("S.RefReadonly", "(null reference)").WithLocation(4, 27), + // (5,27): warning CS0649: Field 'S.ReadonlyRef' is never assigned to, and will always have its default value (null reference) + // public readonly ref T ReadonlyRef; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "ReadonlyRef").WithArguments("S.ReadonlyRef", "(null reference)").WithLocation(5, 27), + // (6,36): warning CS0649: Field 'S.ReadonlyRefReadonly' is never assigned to, and will always have its default value (null reference) + // public readonly ref readonly T ReadonlyRefReadonly; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "ReadonlyRefReadonly").WithArguments("S.ReadonlyRefReadonly", "(null reference)").WithLocation(6, 36)); } [Fact] @@ -7327,7 +7637,10 @@ class Program static ref readonly T F10(in S s) => ref s.F; }"; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); - comp.VerifyEmitDiagnostics(); + comp.VerifyEmitDiagnostics( + // (3,18): warning CS0649: Field 'S.F' is never assigned to, and will always have its default value (null reference) + // public ref T F; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("S.F", "(null reference)").WithLocation(3, 18)); } [Fact] @@ -7353,6 +7666,9 @@ class Program }"; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); comp.VerifyEmitDiagnostics( + // (3,27): warning CS0649: Field 'S.F' is never assigned to, and will always have its default value (null reference) + // public ref readonly T F; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("S.F", "(null reference)").WithLocation(3, 27), // (4,30): error CS8333: Cannot return field 'F' by writable reference because it is a readonly variable // public ref T F1() => ref F; Diagnostic(ErrorCode.ERR_RefReturnReadonlyNotField, "F").WithArguments("field", "F").WithLocation(4, 30), @@ -7392,7 +7708,10 @@ class Program static ref readonly T F10(in S s) => ref s.F; }"; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); - comp.VerifyEmitDiagnostics(); + comp.VerifyEmitDiagnostics( + // (3,27): warning CS0649: Field 'S.F' is never assigned to, and will always have its default value (null reference) + // public readonly ref T F; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("S.F", "(null reference)").WithLocation(3, 27)); } [Fact] @@ -7418,6 +7737,9 @@ class Program }"; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); comp.VerifyEmitDiagnostics( + // (3,36): warning CS0649: Field 'S.F' is never assigned to, and will always have its default value (null reference) + // public readonly ref readonly T F; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("S.F", "(null reference)").WithLocation(3, 36), // (4,30): error CS8333: Cannot return field 'F' by writable reference because it is a readonly variable // public ref T F1() => ref F; Diagnostic(ErrorCode.ERR_RefReturnReadonlyNotField, "F").WithArguments("field", "F").WithLocation(4, 30), @@ -7688,7 +8010,10 @@ static void M4(in T t) { } static void FromIn4B(in S s) { M4(s.F); } }"; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); - comp.VerifyEmitDiagnostics(); + comp.VerifyEmitDiagnostics( + // (3,18): warning CS0649: Field 'S.F' is never assigned to, and will always have its default value (null reference) + // public ref T F; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("S.F", "(null reference)").WithLocation(3, 18)); } [Fact] @@ -7733,6 +8058,9 @@ static void M4(in T t) { } }"; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); comp.VerifyEmitDiagnostics( + // (3,27): warning CS0649: Field 'S.F' is never assigned to, and will always have its default value (null reference) + // public ref readonly T F; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("S.F", "(null reference)").WithLocation(3, 27), // (14,49): error CS8329: Cannot use field 'F' as a ref or out value because it is a readonly variable // static void FromValue2(S s) { M2(ref s.F); } // 1 Diagnostic(ErrorCode.ERR_RefReadonlyNotField, "s.F").WithArguments("field", "F").WithLocation(14, 49), @@ -7800,7 +8128,10 @@ static void M4(in T t) { } static void FromIn4B(in S s) { M4(s.F); } }"; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); - comp.VerifyEmitDiagnostics(); + comp.VerifyEmitDiagnostics( + // (3,27): warning CS0649: Field 'S.F' is never assigned to, and will always have its default value (null reference) + // public readonly ref T F; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("S.F", "(null reference)").WithLocation(3, 27)); } [Fact] @@ -7845,6 +8176,9 @@ static void M4(in T t) { } }"; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); comp.VerifyEmitDiagnostics( + // (3,36): warning CS0649: Field 'S.F' is never assigned to, and will always have its default value (null reference) + // public readonly ref readonly T F; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("S.F", "(null reference)").WithLocation(3, 36), // (14,49): error CS8329: Cannot use field 'F' as a ref or out value because it is a readonly variable // static void FromValue2(S s) { M2(ref s.F); } // 1 Diagnostic(ErrorCode.ERR_RefReadonlyNotField, "s.F").WithArguments("field", "F").WithLocation(14, 49), @@ -9601,7 +9935,10 @@ public R(){} Diagnostic(ErrorCode.ERR_RefProperty, "c.N").WithLocation(12, 12), // (14,12): error CS0206: A non ref-returning property or indexer may not be used as an out or ref value // _ = M2(out c[0]); //CS0206 - Diagnostic(ErrorCode.ERR_RefProperty, "c[0]").WithLocation(14, 12) + Diagnostic(ErrorCode.ERR_RefProperty, "c[0]").WithLocation(14, 12), + // (28,21): warning CS0649: Field 'R.n' is never assigned to, and will always have its default value (null reference) + // private ref int n; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "n").WithArguments("R.n", "(null reference)").WithLocation(28, 21) ); } @@ -9819,9 +10156,9 @@ public static void M() where T : unmanaged { } // (10,36): warning CS0649: Field 'StructWithIndirectRefField.Field' is never assigned to, and will always have its default value // public StructWithRefField Field; Diagnostic(ErrorCode.WRN_UnassignedInternalField, "Field").WithArguments("StructWithIndirectRefField.Field", "").WithLocation(10, 36), - // (14,18): warning CS0649: Field 'StructWithRefField.RefField' is never assigned to, and will always have its default value + // (14,18): warning CS0649: Field 'StructWithRefField.RefField' is never assigned to, and will always have its default value (null reference) // public ref T RefField; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "RefField").WithArguments("StructWithRefField.RefField", "").WithLocation(14, 18) + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "RefField").WithArguments("StructWithRefField.RefField", "(null reference)").WithLocation(14, 18) ); Assert.True(comp.GetTypeByMetadataName("StructWithIndirectRefField").IsManagedTypeNoUseSiteDiagnostics); @@ -18266,7 +18603,10 @@ public void ReturnRefField() public ref readonly T GetRefReadonly() => ref F; }"; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); - comp.VerifyDiagnostics(); + comp.VerifyDiagnostics( + // (3,18): warning CS0649: Field 'R.F' is never assigned to, and will always have its default value (null reference) + // public ref T F; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "(null reference)").WithLocation(3, 18)); } [Fact] @@ -18282,6 +18622,9 @@ public void ReturnRefReadonlyField() }"; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics( + // (3,27): warning CS0649: Field 'R.F' is never assigned to, and will always have its default value (null reference) + // public ref readonly T F; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "(null reference)").WithLocation(3, 27), // (5,34): error CS8333: Cannot return field 'F' by writable reference because it is a readonly variable // public ref T GetRef() => ref F; // 1 Diagnostic(ErrorCode.ERR_RefReturnReadonlyNotField, "F").WithArguments("field", "F").WithLocation(5, 34)); @@ -29883,6 +30226,9 @@ ref struct RS expectedOutput: "1"); verifier.VerifyDiagnostics( + // (14,13): warning CS0649: Field 'RS.ri' is never assigned to, and will always have its default value (null reference) + // ref int ri; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "ri").WithArguments("RS.ri", "(null reference)").WithLocation(14, 13), // (15,20): warning CS9201: Ref field 'ri' should be ref-assigned before use. // public RS() => ri = 0; Diagnostic(ErrorCode.WRN_UseDefViolationRefField, "ri").WithArguments("ri").WithLocation(15, 20)); @@ -29934,9 +30280,9 @@ public RS() expectedOutput: "1"); verifier.VerifyDiagnostics( - // (14,13): warning CS0649: Field 'RS.ri' is never assigned to, and will always have its default value 0 + // (14,13): warning CS0649: Field 'RS.ri' is never assigned to, and will always have its default value (null reference) // ref int ri; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "ri").WithArguments("RS.ri", "0").WithLocation(14, 13), + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "ri").WithArguments("RS.ri", "(null reference)").WithLocation(14, 13), // (15,12): warning CS9022: Control is returned to caller before field 'RS.ri' is explicitly assigned, causing a preceding implicit assignment of 'default'. // public RS() Diagnostic(ErrorCode.WRN_UnassignedThisSupportedVersion, "RS").WithArguments("RS.ri").WithLocation(15, 12), @@ -30002,6 +30348,9 @@ public RS(bool ignored) expectedOutput: "12"); verifier.VerifyDiagnostics( + // (17,13): warning CS0649: Field 'RS.ri' is never assigned to, and will always have its default value (null reference) + // ref int ri; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "ri").WithArguments("RS.ri", "(null reference)").WithLocation(17, 13), // (20,29): warning CS9201: Ref field 'ri' should be ref-assigned before use. // ref int local = ref ri; // 1 Diagnostic(ErrorCode.WRN_UseDefViolationRefField, "ri").WithArguments("ri").WithLocation(20, 29), @@ -30077,6 +30426,9 @@ ref struct RS targetFramework: TargetFramework.NetCoreApp); comp.VerifyDiagnostics( + // (3,22): warning CS0649: Field 'RS.ri' is never assigned to, and will always have its default value (null reference) + // ref readonly int ri; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "ri").WithArguments("RS.ri", "(null reference)").WithLocation(3, 22), // (4,20): error CS8331: Cannot assign to field 'ri' or use it as the right hand side of a ref assignment because it is a readonly variable // public RS() => ri = 0; Diagnostic(ErrorCode.ERR_AssignReadonlyNotField, "ri").WithArguments("field", "ri").WithLocation(4, 20), @@ -30106,7 +30458,10 @@ static void Test1() verify: Verification.Skipped, targetFramework: TargetFramework.NetCoreApp); - verifier.VerifyDiagnostics(); + verifier.VerifyDiagnostics( + // (3,20): warning CS0649: Field 'S.F1' is never assigned to, and will always have its default value (null reference) + // public ref int F1; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F1").WithArguments("S.F1", "(null reference)").WithLocation(3, 20)); verifier.VerifyIL("S.Test1", @" @@ -30145,6 +30500,9 @@ static void Test1() targetFramework: TargetFramework.NetCoreApp); comp.VerifyDiagnostics( + // (3,29): warning CS0649: Field 'S.F1' is never assigned to, and will always have its default value (null reference) + // public ref readonly int F1; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F1").WithArguments("S.F1", "(null reference)").WithLocation(3, 29), // (11,15): error CS8329: Cannot use field 'F1' as a ref or out value because it is a readonly variable // M(ref GetS().F1); Diagnostic(ErrorCode.ERR_RefReadonlyNotField, "GetS().F1").WithArguments("field", "F1").WithLocation(11, 15) @@ -30174,7 +30532,10 @@ static void Test1() verify: Verification.Skipped, targetFramework: TargetFramework.NetCoreApp); - verifier.VerifyDiagnostics(); + verifier.VerifyDiagnostics( + // (3,29): warning CS0649: Field 'S.F1' is never assigned to, and will always have its default value (null reference) + // public ref readonly int F1; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F1").WithArguments("S.F1", "(null reference)").WithLocation(3, 29)); verifier.VerifyIL("S.Test1", """ { @@ -30212,6 +30573,9 @@ static void Test1() targetFramework: TargetFramework.NetCoreApp); comp.VerifyDiagnostics( + // (3,29): warning CS0649: Field 'S.F1' is never assigned to, and will always have its default value (null reference) + // public ref readonly int F1; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F1").WithArguments("S.F1", "(null reference)").WithLocation(3, 29), // (11,15): error CS8329: Cannot use field 'F1' as a ref or out value because it is a readonly variable // M(ref GetS().F1); Diagnostic(ErrorCode.ERR_RefReadonlyNotField, "GetS().F1").WithArguments("field", "F1").WithLocation(11, 15) @@ -30241,7 +30605,10 @@ static void Test1() verify: Verification.Skipped, targetFramework: TargetFramework.NetCoreApp); - verifier.VerifyDiagnostics(); + verifier.VerifyDiagnostics( + // (3,29): warning CS0649: Field 'S.F1' is never assigned to, and will always have its default value (null reference) + // public ref readonly int F1; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F1").WithArguments("S.F1", "(null reference)").WithLocation(3, 29)); verifier.VerifyIL("S.Test1", """ { @@ -30320,7 +30687,10 @@ static void Test1() verify: Verification.Skipped, targetFramework: TargetFramework.NetCoreApp); - verifier.VerifyDiagnostics(); + verifier.VerifyDiagnostics( + // (3,29): warning CS0649: Field 'S.F1' is never assigned to, and will always have its default value (null reference) + // public readonly ref int F1; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F1").WithArguments("S.F1", "(null reference)").WithLocation(3, 29)); verifier.VerifyIL("S.Test1", @" @@ -30359,7 +30729,10 @@ static void Test1() verify: Verification.Skipped, targetFramework: TargetFramework.NetCoreApp); - verifier.VerifyDiagnostics(); + verifier.VerifyDiagnostics( + // (3,29): warning CS0649: Field 'S.F1' is never assigned to, and will always have its default value (null reference) + // public readonly ref int F1; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F1").WithArguments("S.F1", "(null reference)").WithLocation(3, 29)); verifier.VerifyIL("S.Test1", @" @@ -30400,7 +30773,10 @@ static void Test1() verify: Verification.Skipped, targetFramework: TargetFramework.NetCoreApp); - verifier.VerifyDiagnostics(); + verifier.VerifyDiagnostics( + // (3,29): warning CS0649: Field 'S.F1' is never assigned to, and will always have its default value (null reference) + // public readonly ref int F1; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F1").WithArguments("S.F1", "(null reference)").WithLocation(3, 29)); verifier.VerifyIL("S.Test1", """ { @@ -30439,6 +30815,9 @@ static void Test1() targetFramework: TargetFramework.NetCoreApp); verifier.VerifyDiagnostics( + // (3,29): warning CS0649: Field 'S.F1' is never assigned to, and will always have its default value (null reference) + // public readonly ref int F1; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F1").WithArguments("S.F1", "(null reference)").WithLocation(3, 29), // (11,15): warning CS9191: The 'ref' modifier for argument 1 corresponding to 'in' parameter is equivalent to 'in'. Consider using 'in' instead. // M(ref GetS().F1); Diagnostic(ErrorCode.WRN_BadArgRef, "GetS().F1").WithArguments("1").WithLocation(11, 15) @@ -30483,7 +30862,10 @@ static void Test1() verify: Verification.Skipped, targetFramework: TargetFramework.NetCoreApp); - verifier.VerifyDiagnostics(); + verifier.VerifyDiagnostics( + // (3,29): warning CS0649: Field 'S.F1' is never assigned to, and will always have its default value (null reference) + // public readonly ref int F1; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F1").WithArguments("S.F1", "(null reference)").WithLocation(3, 29)); verifier.VerifyIL("S.Test1", """ { @@ -30560,7 +30942,10 @@ static void Test() } """, targetFramework: TargetFramework.NetCoreApp); - comp.VerifyDiagnostics(); + comp.VerifyDiagnostics( + // (3,20): warning CS0649: Field 'R.F' is never assigned to, and will always have its default value (null reference) + // public ref int F; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "(null reference)").WithLocation(3, 20)); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75082")] @@ -30582,7 +30967,10 @@ static void Test() } """, targetFramework: TargetFramework.NetCoreApp); - comp.VerifyDiagnostics(); + comp.VerifyDiagnostics( + // (3,20): warning CS0649: Field 'R.F' is never assigned to, and will always have its default value (null reference) + // public ref int F; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "(null reference)").WithLocation(3, 20)); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75082")] @@ -30606,7 +30994,10 @@ static void Test() } """, targetFramework: TargetFramework.NetCoreApp); - comp.VerifyDiagnostics(); + comp.VerifyDiagnostics( + // (3,20): warning CS0649: Field 'R.F' is never assigned to, and will always have its default value (null reference) + // public ref int F; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "(null reference)").WithLocation(3, 20)); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75082")] @@ -30628,15 +31019,16 @@ static void Test() } """, targetFramework: TargetFramework.NetCoreApp); - comp.VerifyDiagnostics(); + comp.VerifyDiagnostics( + // (3,20): warning CS0649: Field 'R.F' is never assigned to, and will always have its default value (null reference) + // public ref int F; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "(null reference)").WithLocation(3, 20)); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75082")] public void ThroughValue_ValueOfRef_ToRefReadonly() { var comp = CreateCompilation(""" - #pragma warning disable CS0649 // Field 'R.F' is never assigned to, and will always have its default value 0 - ref struct R { public ref int F; @@ -30653,17 +31045,18 @@ static void Test() """, targetFramework: TargetFramework.NetCoreApp); comp.VerifyDiagnostics( - // (13,11): warning CS9192: Argument 1 should be passed with 'ref' or 'in' keyword + // (3,20): warning CS0649: Field 'R.F' is never assigned to, and will always have its default value (null reference) + // public ref int F; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "(null reference)").WithLocation(3, 20), + // (11,11): warning CS9192: Argument 1 should be passed with 'ref' or 'in' keyword // M(GetValue().F); - Diagnostic(ErrorCode.WRN_ArgExpectedRefOrIn, "GetValue().F").WithArguments("1").WithLocation(13, 11)); + Diagnostic(ErrorCode.WRN_ArgExpectedRefOrIn, "GetValue().F").WithArguments("1").WithLocation(11, 11)); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75082")] public void ThroughValue_ValueOfRef_ToIn() { var comp = CreateCompilation(""" - #pragma warning disable CS0649 // Field 'R.F' is never assigned to, and will always have its default value 0 - ref struct R { public ref int F; @@ -30679,15 +31072,16 @@ static void Test() } """, targetFramework: TargetFramework.NetCoreApp); - comp.VerifyDiagnostics(); + comp.VerifyDiagnostics( + // (3,20): warning CS0649: Field 'R.F' is never assigned to, and will always have its default value (null reference) + // public ref int F; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "(null reference)").WithLocation(3, 20)); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75082")] public void ThroughValue_ValueOfRef_ToRef() { var comp = CreateCompilation(""" - #pragma warning disable CS0649 // Field 'R.F' is never assigned to, and will always have its default value 0 - ref struct R { public ref int F; @@ -30704,9 +31098,12 @@ static void Test() """, targetFramework: TargetFramework.NetCoreApp); comp.VerifyDiagnostics( - // (13,11): error CS1620: Argument 1 must be passed with the 'ref' keyword + // (3,20): warning CS0649: Field 'R.F' is never assigned to, and will always have its default value (null reference) + // public ref int F; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "(null reference)").WithLocation(3, 20), + // (11,11): error CS1620: Argument 1 must be passed with the 'ref' keyword // M(GetValue().F); - Diagnostic(ErrorCode.ERR_BadArgRef, "GetValue().F").WithArguments("1", "ref").WithLocation(13, 11)); + Diagnostic(ErrorCode.ERR_BadArgRef, "GetValue().F").WithArguments("1", "ref").WithLocation(11, 11)); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75082")] @@ -30729,6 +31126,9 @@ static void Test() """, targetFramework: TargetFramework.NetCoreApp); comp.VerifyDiagnostics( + // (3,29): warning CS0649: Field 'R.F' is never assigned to, and will always have its default value (null reference) + // public ref readonly int F; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "(null reference)").WithLocation(3, 29), // (11,15): error CS8329: Cannot use field 'F' as a ref or out value because it is a readonly variable // M(ref GetValue().F); Diagnostic(ErrorCode.ERR_RefReadonlyNotField, "GetValue().F").WithArguments("field", "F").WithLocation(11, 15)); @@ -30753,7 +31153,10 @@ static void Test() } """, targetFramework: TargetFramework.NetCoreApp); - comp.VerifyDiagnostics(); + comp.VerifyDiagnostics( + // (3,29): warning CS0649: Field 'R.F' is never assigned to, and will always have its default value (null reference) + // public ref readonly int F; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "(null reference)").WithLocation(3, 29)); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75082")] @@ -30776,6 +31179,9 @@ static void Test() """, targetFramework: TargetFramework.NetCoreApp); comp.VerifyDiagnostics( + // (3,29): warning CS0649: Field 'R.F' is never assigned to, and will always have its default value (null reference) + // public ref readonly int F; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "(null reference)").WithLocation(3, 29), // (11,15): error CS8329: Cannot use field 'F' as a ref or out value because it is a readonly variable // M(out GetValue().F); Diagnostic(ErrorCode.ERR_RefReadonlyNotField, "GetValue().F").WithArguments("field", "F").WithLocation(11, 15)); @@ -30785,8 +31191,6 @@ static void Test() public void ThroughValue_ValueOfRefReadonly_ToRefReadonly() { var comp = CreateCompilation(""" - #pragma warning disable CS0649 // Field 'R.F' is never assigned to, and will always have its default value 0 - ref struct R { public ref readonly int F; @@ -30803,17 +31207,18 @@ static void Test() """, targetFramework: TargetFramework.NetCoreApp); comp.VerifyDiagnostics( - // (13,11): warning CS9195: Argument 1 should be passed with the 'in' keyword + // (3,29): warning CS0649: Field 'R.F' is never assigned to, and will always have its default value (null reference) + // public ref readonly int F; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "(null reference)").WithLocation(3, 29), + // (11,11): warning CS9195: Argument 1 should be passed with the 'in' keyword // M(GetValue().F); - Diagnostic(ErrorCode.WRN_ArgExpectedIn, "GetValue().F").WithArguments("1").WithLocation(13, 11)); + Diagnostic(ErrorCode.WRN_ArgExpectedIn, "GetValue().F").WithArguments("1").WithLocation(11, 11)); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75082")] public void ThroughValue_ValueOfRefReadonly_ToIn() { var comp = CreateCompilation(""" - #pragma warning disable CS0649 // Field 'R.F' is never assigned to, and will always have its default value 0 - ref struct R { public ref readonly int F; @@ -30829,15 +31234,16 @@ static void Test() } """, targetFramework: TargetFramework.NetCoreApp); - comp.VerifyDiagnostics(); + comp.VerifyDiagnostics( + // (3,29): warning CS0649: Field 'R.F' is never assigned to, and will always have its default value (null reference) + // public ref readonly int F; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "(null reference)").WithLocation(3, 29)); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75082")] public void ThroughValue_ValueOfRefReadonly_ToRef() { var comp = CreateCompilation(""" - #pragma warning disable CS0649 // Field 'R.F' is never assigned to, and will always have its default value 0 - ref struct R { public ref readonly int F; @@ -30854,9 +31260,12 @@ static void Test() """, targetFramework: TargetFramework.NetCoreApp); comp.VerifyDiagnostics( - // (13,11): error CS1620: Argument 1 must be passed with the 'ref' keyword + // (3,29): warning CS0649: Field 'R.F' is never assigned to, and will always have its default value (null reference) + // public ref readonly int F; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "(null reference)").WithLocation(3, 29), + // (11,11): error CS1620: Argument 1 must be passed with the 'ref' keyword // M(GetValue().F); - Diagnostic(ErrorCode.ERR_BadArgRef, "GetValue().F").WithArguments("1", "ref").WithLocation(13, 11)); + Diagnostic(ErrorCode.ERR_BadArgRef, "GetValue().F").WithArguments("1", "ref").WithLocation(11, 11)); } } } From 253e28e7fe2c7a45b05dd3fb02956e260c027be9 Mon Sep 17 00:00:00 2001 From: Jan Jones Date: Fri, 4 Oct 2024 14:26:11 +0200 Subject: [PATCH 2/5] Avoid propagating ref assignment --- .../FlowAnalysis/DefiniteAssignment.cs | 1 + .../Test/Semantic/Semantics/RefFieldTests.cs | 67 +++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/DefiniteAssignment.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/DefiniteAssignment.cs index 3845873d8fada..870542cac711d 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/DefiniteAssignment.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/DefiniteAssignment.cs @@ -971,6 +971,7 @@ private void NoteWrite(BoundExpression n, BoundExpression value, bool read, bool if (MayRequireTracking(fieldAccess.ReceiverOpt, fieldAccess.FieldSymbol)) { n = fieldAccess.ReceiverOpt; + isRef = false; if (n.Kind == BoundKind.Local) { _usedVariables.Add(((BoundLocal)n).LocalSymbol); diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs index c5a060efd7d2f..b1a211d38dc44 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs @@ -5561,6 +5561,73 @@ static void Test(R r, int x) Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "(null reference)").WithLocation(3, 20)); } + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75315")] + public void DefiniteAssignment_RefField_Assigned_Nested() + { + var comp = CreateCompilation(""" + ref struct R1 + { + public ref R2 F; + } + + ref struct R2 + { + public ref int F; + } + + class C + { + static void Test(R1 r, int x) + { + r.F.F = x; + } + } + """, + targetFramework: TargetFramework.NetCoreApp); + comp.VerifyDiagnostics( + // (3,12): error CS9050: A ref field cannot refer to a ref struct. + // public ref R2 F; + Diagnostic(ErrorCode.ERR_RefFieldCannotReferToRefStruct, "ref R2").WithLocation(3, 12), + // (3,19): warning CS0649: Field 'R1.F' is never assigned to, and will always have its default value (null reference) + // public ref R2 F; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R1.F", "(null reference)").WithLocation(3, 19), + // (8,20): warning CS0649: Field 'R2.F' is never assigned to, and will always have its default value (null reference) + // public ref int F; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R2.F", "(null reference)").WithLocation(8, 20)); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75315")] + public void DefiniteAssignment_RefField_RefAssigned_Nested() + { + var comp = CreateCompilation(""" + ref struct R1 + { + public ref R2 F; + } + + ref struct R2 + { + public ref int F; + } + + class C + { + static void Test(scoped R1 r, ref int x) + { + r.F.F = ref x; + } + } + """, + targetFramework: TargetFramework.NetCoreApp); + comp.VerifyDiagnostics( + // (3,12): error CS9050: A ref field cannot refer to a ref struct. + // public ref R2 F; + Diagnostic(ErrorCode.ERR_RefFieldCannotReferToRefStruct, "ref R2").WithLocation(3, 12), + // (3,19): warning CS0649: Field 'R1.F' is never assigned to, and will always have its default value (null reference) + // public ref R2 F; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R1.F", "(null reference)").WithLocation(3, 19)); + } + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75315")] public void DefiniteAssignment_RefField_AssignedInObjectInitializer_InAtCallSite() { From d7591954c5a2627973e0e53796e9d4b0cc98f76e Mon Sep 17 00:00:00 2001 From: Jan Jones Date: Fri, 4 Oct 2024 14:37:42 +0200 Subject: [PATCH 3/5] Set `isRef` to more future-proof values in more places --- .../CSharp/Portable/FlowAnalysis/DefiniteAssignment.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/DefiniteAssignment.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/DefiniteAssignment.cs index 870542cac711d..82eb7be04404c 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/DefiniteAssignment.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/DefiniteAssignment.cs @@ -346,7 +346,7 @@ protected override ImmutableArray Scan(ref bool badRegion) // All primary constructor parameters are definitely assigned outside of the primary constructor foreach (var parameter in primaryConstructor.Parameters) { - NoteWrite(parameter, value: null, read: true, isRef: false); + NoteWrite(parameter, value: null, read: true, isRef: parameter.RefKind != RefKind.None); } CurrentSymbol = save; @@ -1881,7 +1881,7 @@ protected override void EnterParameter(ParameterSymbol parameter) { // this code has no effect except in region analysis APIs such as DataFlowsOut where we unassign things if (slot > 0) SetSlotState(slot, true); - NoteWrite(parameter, value: null, read: true, isRef: false); + NoteWrite(parameter, value: null, read: true, isRef: parameter.RefKind != RefKind.None); } if (parameter is SourceComplexParameterSymbolBase { ContainingSymbol: LocalFunctionSymbol or LambdaSymbol } sourceComplexParam) @@ -2765,7 +2765,7 @@ public override void VisitForEachIterationVariables(BoundForEachStatement node) int slot = GetOrCreateSlot(iterationVariable); if (slot > 0) SetSlotAssigned(slot); // NOTE: do not report unused iteration variables. They are always considered used. - NoteWrite(iterationVariable, null, read: true, isRef: false); + NoteWrite(iterationVariable, null, read: true, isRef: iterationVariable.RefKind != RefKind.None); } } From 3005947e0a5538374d80709b1152a89ee11a3ae7 Mon Sep 17 00:00:00 2001 From: Jan Jones Date: Tue, 8 Oct 2024 13:37:10 +0200 Subject: [PATCH 4/5] Use separate warning --- .../CSharp/Warnversion Warning Waves.md | 8 + .../CSharp/Portable/CSharpResources.resx | 6 + .../CSharp/Portable/Errors/ErrorCode.cs | 1 + .../CSharp/Portable/Errors/ErrorFacts.cs | 5 + .../Generated/ErrorFacts.Generated.cs | 1 + .../Symbols/Source/SourceAssemblySymbol.cs | 9 +- .../Portable/xlf/CSharpResources.cs.xlf | 10 + .../Portable/xlf/CSharpResources.de.xlf | 10 + .../Portable/xlf/CSharpResources.es.xlf | 10 + .../Portable/xlf/CSharpResources.fr.xlf | 10 + .../Portable/xlf/CSharpResources.it.xlf | 10 + .../Portable/xlf/CSharpResources.ja.xlf | 10 + .../Portable/xlf/CSharpResources.ko.xlf | 10 + .../Portable/xlf/CSharpResources.pl.xlf | 10 + .../Portable/xlf/CSharpResources.pt-BR.xlf | 10 + .../Portable/xlf/CSharpResources.ru.xlf | 10 + .../Portable/xlf/CSharpResources.tr.xlf | 10 + .../Portable/xlf/CSharpResources.zh-Hans.xlf | 10 + .../Portable/xlf/CSharpResources.zh-Hant.xlf | 10 + .../Emit3/FlowAnalysis/RegionAnalysisTests.cs | 4 +- .../Semantics/PrimaryConstructorTests.cs | 2 +- .../Test/Semantic/Semantics/RefFieldTests.cs | 284 ++++++++++-------- .../Symbol/Symbols/RequiredMembersTests.cs | 2 +- .../Test/Syntax/Diagnostics/DiagnosticTest.cs | 4 + 24 files changed, 318 insertions(+), 138 deletions(-) diff --git a/docs/compilers/CSharp/Warnversion Warning Waves.md b/docs/compilers/CSharp/Warnversion Warning Waves.md index 65d25e8b1b528..19be76b7d8ef2 100644 --- a/docs/compilers/CSharp/Warnversion Warning Waves.md +++ b/docs/compilers/CSharp/Warnversion Warning Waves.md @@ -13,6 +13,14 @@ In a typical project, this setting is controlled by the `AnalysisLevel` property which determines the `WarningLevel` property (passed to the `Csc` task). For more information on `AnalysisLevel`, see https://devblogs.microsoft.com/dotnet/automatically-find-latent-bugs-in-your-code-with-net-5/ +## Warning level 10 + +The compiler shipped with .NET 10 (the C# 14 compiler) contains the following warnings which are reported only under `/warn:10` or higher. + +| Warning ID | Description | +|------------|-------------| +| CS9265 | [Field is never ref-assigned to, and will always have its default value (null reference)](https://github.com/dotnet/roslyn/issues/75315) | + ## Warning level 8 The compiler shipped with .NET 8 (the C# 12 compiler) contains the following warnings which are reported only under `/warn:8` or higher. diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 4210d8664c209..351d867389303 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -1916,6 +1916,12 @@ If such a class is used as a base class and if the deriving class defines a dest Field is never assigned to, and will always have its default value + + Field '{0}' is never ref-assigned to, and will always have its default value (null reference) + + + Field is never ref-assigned to, and will always have its default value (null reference) + Bad array declarator: To declare a managed array the rank specifier precedes the variable's identifier. To declare a fixed size buffer field, use the fixed keyword before the field type. diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index 7c07bb82d271e..ddf9033bcbfb5 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -2346,6 +2346,7 @@ internal enum ErrorCode ERR_PartialPropertyDuplicateInitializer = 9263, WRN_UninitializedNonNullableBackingField = 9264, + WRN_UnassignedInternalRefField = 9265, // Note: you will need to do the following after adding errors: // 1) Update ErrorFacts.IsBuildOnlyDiagnostic (src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs) diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs index 4c8a7e03fa39c..36c061058fae1 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs @@ -210,6 +210,10 @@ internal static int GetWarningLevel(ErrorCode code) // docs/compilers/CSharp/Warnversion Warning Waves.md switch (code) { + case ErrorCode.WRN_UnassignedInternalRefField: + // Warning level 10 is exclusively for warnings introduced in the compiler + // shipped with dotnet 10 (C# 14) and that can be reported for pre-existing code. + return 10; case ErrorCode.WRN_AddressOfInAsync: case ErrorCode.WRN_ByValArraySizeConstRequired: // Warning level 8 is exclusively for warnings introduced in the compiler @@ -2460,6 +2464,7 @@ or ErrorCode.ERR_CannotApplyOverloadResolutionPriorityToOverride or ErrorCode.ERR_CannotApplyOverloadResolutionPriorityToMember or ErrorCode.ERR_PartialPropertyDuplicateInitializer or ErrorCode.WRN_UninitializedNonNullableBackingField + or ErrorCode.WRN_UnassignedInternalRefField => false, }; #pragma warning restore CS8524 // The switch expression does not handle some values of its input type (it is not exhaustive) involving an unnamed enum value. diff --git a/src/Compilers/CSharp/Portable/Generated/ErrorFacts.Generated.cs b/src/Compilers/CSharp/Portable/Generated/ErrorFacts.Generated.cs index 1d3dab8bda75f..c339c5db75597 100644 --- a/src/Compilers/CSharp/Portable/Generated/ErrorFacts.Generated.cs +++ b/src/Compilers/CSharp/Portable/Generated/ErrorFacts.Generated.cs @@ -341,6 +341,7 @@ public static bool IsWarning(ErrorCode code) case ErrorCode.WRN_PartialPropertySignatureDifference: case ErrorCode.WRN_FieldIsAmbiguous: case ErrorCode.WRN_UninitializedNonNullableBackingField: + case ErrorCode.WRN_UnassignedInternalRefField: return true; default: return false; diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceAssemblySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceAssemblySymbol.cs index f3cee9252c70f..916a8a348eac2 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceAssemblySymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceAssemblySymbol.cs @@ -2740,9 +2740,13 @@ internal ImmutableArray GetUnusedFieldWarnings(CancellationToken can { diagnostics.Add(ErrorCode.WRN_UnreferencedField, field.GetFirstLocationOrNone(), field); } + else if (field.RefKind != RefKind.None) + { + diagnostics.Add(ErrorCode.WRN_UnassignedInternalRefField, field.GetFirstLocationOrNone(), field); + } else { - diagnostics.Add(ErrorCode.WRN_UnassignedInternalField, field.GetFirstLocationOrNone(), field, DefaultValue(field.Type, isRef: field.RefKind != RefKind.None)); + diagnostics.Add(ErrorCode.WRN_UnassignedInternalField, field.GetFirstLocationOrNone(), field, DefaultValue(field.Type)); } } @@ -2773,10 +2777,9 @@ internal ImmutableArray GetUnusedFieldWarnings(CancellationToken can return _unusedFieldWarnings; } - private static string DefaultValue(TypeSymbol type, bool isRef) + private static string DefaultValue(TypeSymbol type) { // TODO: localize these strings - if (isRef) return "(null reference)"; if (type.IsReferenceType) return "null"; switch (type.SpecialType) { diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index 88e737c1beb27..8da755efedfc7 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -5218,6 +5218,16 @@ Parametr typu má stejný typ jako parametr typu z vnější metody. + + Field '{0}' is never ref-assigned to, and will always have its default value (null reference) + Field '{0}' is never ref-assigned to, and will always have its default value (null reference) + + + + Field is never ref-assigned to, and will always have its default value (null reference) + Field is never ref-assigned to, and will always have its default value (null reference) + + Control is returned to caller before auto-implemented property '{0}' is explicitly assigned, causing a preceding implicit assignment of 'default'. Volajícímu se vrátí ovládací prvek před explicitním přiřazením automaticky implementované vlastnosti {0}, což způsobí předchozí implicitní přiřazení default. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index 7791b4941b495..70c26711d6329 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -5218,6 +5218,16 @@ Der Typparameter und der Typparameter der äußeren Methode weisen denselben Typ auf. + + Field '{0}' is never ref-assigned to, and will always have its default value (null reference) + Field '{0}' is never ref-assigned to, and will always have its default value (null reference) + + + + Field is never ref-assigned to, and will always have its default value (null reference) + Field is never ref-assigned to, and will always have its default value (null reference) + + Control is returned to caller before auto-implemented property '{0}' is explicitly assigned, causing a preceding implicit assignment of 'default'. Das Steuerelement wird an den Aufrufer zurückgegeben, bevor die automatisch implementierte Eigenschaft "{0}" explizit zugewiesen wird. Dies führt zu einer vorherigen impliziten Zuweisung von "default". diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index 49dc784c465a9..645883895770e 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -5218,6 +5218,16 @@ El parámetro de tipo tiene el mismo tipo que el parámetro de tipo del método externo. + + Field '{0}' is never ref-assigned to, and will always have its default value (null reference) + Field '{0}' is never ref-assigned to, and will always have its default value (null reference) + + + + Field is never ref-assigned to, and will always have its default value (null reference) + Field is never ref-assigned to, and will always have its default value (null reference) + + Control is returned to caller before auto-implemented property '{0}' is explicitly assigned, causing a preceding implicit assignment of 'default'. El control se devuelve al autor de la llamada antes de que la propiedad implementada automáticamente '{0}' se asigne explícitamente, lo que provoca una asignación implícita anterior de 'default'. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index ebc8306793f12..3b841bfa25369 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -5218,6 +5218,16 @@ Le paramètre de type a le même type que le paramètre de type de la méthode externe. + + Field '{0}' is never ref-assigned to, and will always have its default value (null reference) + Field '{0}' is never ref-assigned to, and will always have its default value (null reference) + + + + Field is never ref-assigned to, and will always have its default value (null reference) + Field is never ref-assigned to, and will always have its default value (null reference) + + Control is returned to caller before auto-implemented property '{0}' is explicitly assigned, causing a preceding implicit assignment of 'default'. Le contrôle est retourné à l’appelant avant que la propriété implémentée automatiquement '{0}' soit explicitement affectée, ce qui provoque une attribution implicite précédente de 'default'. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index 268e0502cd458..460061a51f157 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -5218,6 +5218,16 @@ target:module Compila un modulo che può essere aggiunto ad altro Il tipo del parametro di tipo è lo stesso del parametro di tipo del metodo esterno. + + Field '{0}' is never ref-assigned to, and will always have its default value (null reference) + Field '{0}' is never ref-assigned to, and will always have its default value (null reference) + + + + Field is never ref-assigned to, and will always have its default value (null reference) + Field is never ref-assigned to, and will always have its default value (null reference) + + Control is returned to caller before auto-implemented property '{0}' is explicitly assigned, causing a preceding implicit assignment of 'default'. Il controllo viene restituito al chiamante prima che la proprietà implementata automaticamente '{0}' sia assegnata in modo esplicito, determinando un'assegnazione implicita precedente di 'default'. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index 7ac7b47912be2..7e8b8fb563ebf 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -5218,6 +5218,16 @@ 型パラメーターの型は、外のメソッドからの型パラメーターと同じ型です。 + + Field '{0}' is never ref-assigned to, and will always have its default value (null reference) + Field '{0}' is never ref-assigned to, and will always have its default value (null reference) + + + + Field is never ref-assigned to, and will always have its default value (null reference) + Field is never ref-assigned to, and will always have its default value (null reference) + + Control is returned to caller before auto-implemented property '{0}' is explicitly assigned, causing a preceding implicit assignment of 'default'. フィールド '{0}' が明示的に割り当てられる前に自動実装プロパティが呼び出し元に返され、先行する暗黙的な代入が 'default' になります。 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index 1c3127f912223..a0238290697ac 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -5218,6 +5218,16 @@ 형식 매개 변수가 외부 메서드의 형식 매개 변수와 형식이 같습니다. + + Field '{0}' is never ref-assigned to, and will always have its default value (null reference) + Field '{0}' is never ref-assigned to, and will always have its default value (null reference) + + + + Field is never ref-assigned to, and will always have its default value (null reference) + Field is never ref-assigned to, and will always have its default value (null reference) + + Control is returned to caller before auto-implemented property '{0}' is explicitly assigned, causing a preceding implicit assignment of 'default'. 자동 구현 속성 '{0}'이(가) 명시적으로 할당되기 전에 제어가 호출자에게 반환되어 'default'의 선행 암시적 할당이 발생합니다. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 4a0500365e1e0..6722677775ae8 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -5218,6 +5218,16 @@ Parametr typu ma ten sam typ co parametr typu z metody zewnętrznej. + + Field '{0}' is never ref-assigned to, and will always have its default value (null reference) + Field '{0}' is never ref-assigned to, and will always have its default value (null reference) + + + + Field is never ref-assigned to, and will always have its default value (null reference) + Field is never ref-assigned to, and will always have its default value (null reference) + + Control is returned to caller before auto-implemented property '{0}' is explicitly assigned, causing a preceding implicit assignment of 'default'. Kontrolka jest zwracana do obiektu wywołującego przed jawnym przypisaniem właściwości „{0}”, co powoduje wcześniejsze niejawne przypisanie wartości „default”. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index 2c3070ffc18a6..f445eed9fbd82 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -5218,6 +5218,16 @@ O parâmetro de tipo tem o mesmo tipo que o parâmetro de tipo do método externo. + + Field '{0}' is never ref-assigned to, and will always have its default value (null reference) + Field '{0}' is never ref-assigned to, and will always have its default value (null reference) + + + + Field is never ref-assigned to, and will always have its default value (null reference) + Field is never ref-assigned to, and will always have its default value (null reference) + + Control is returned to caller before auto-implemented property '{0}' is explicitly assigned, causing a preceding implicit assignment of 'default'. O controle é devolvido ao chamador antes que a propriedade auto-implementada seja '{0}' explicitamente atribuída, causando uma atribuição implícita anterior de 'default'. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index 5ad07dbfa5172..71b229fe58f9b 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -5219,6 +5219,16 @@ Параметр типа имеет то же имя, что и параметр типа во внешнем методе. + + Field '{0}' is never ref-assigned to, and will always have its default value (null reference) + Field '{0}' is never ref-assigned to, and will always have its default value (null reference) + + + + Field is never ref-assigned to, and will always have its default value (null reference) + Field is never ref-assigned to, and will always have its default value (null reference) + + Control is returned to caller before auto-implemented property '{0}' is explicitly assigned, causing a preceding implicit assignment of 'default'. Контроль возвращается вызывающему элементу до явного назначения автоматически реализуемого свойства "{0}", что приводит к предшествующему неявному назначению "default" diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index f6b9d136c9e3c..565e34cb8ecbc 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -5218,6 +5218,16 @@ Tür parametresi dış metottaki tür parametresi ile aynı türe sahip + + Field '{0}' is never ref-assigned to, and will always have its default value (null reference) + Field '{0}' is never ref-assigned to, and will always have its default value (null reference) + + + + Field is never ref-assigned to, and will always have its default value (null reference) + Field is never ref-assigned to, and will always have its default value (null reference) + + Control is returned to caller before auto-implemented property '{0}' is explicitly assigned, causing a preceding implicit assignment of 'default'. Denetim, otomatik uygulanan '{0}' özelliği açıkça atanmadan önce çağırana döndürülür ve bu da 'default' öğesinin önceki örtük ataması ile sonuçlanır. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index 430ad886cfb0a..17d1e6454862e 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -5218,6 +5218,16 @@ 类型参数与外部方法中的类型参数有相同的类型。 + + Field '{0}' is never ref-assigned to, and will always have its default value (null reference) + Field '{0}' is never ref-assigned to, and will always have its default value (null reference) + + + + Field is never ref-assigned to, and will always have its default value (null reference) + Field is never ref-assigned to, and will always have its default value (null reference) + + Control is returned to caller before auto-implemented property '{0}' is explicitly assigned, causing a preceding implicit assignment of 'default'. 在显式分配自动实现的属性'{0}'之前,将向调用方返回控件,从而导致前面隐式分配了“default”。 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index 6d362a02305c7..1c593dcfbf532 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -5218,6 +5218,16 @@ strument:TestCoverage 產生檢測要收集 類型參數與外部方法的類型參數,類型相同。 + + Field '{0}' is never ref-assigned to, and will always have its default value (null reference) + Field '{0}' is never ref-assigned to, and will always have its default value (null reference) + + + + Field is never ref-assigned to, and will always have its default value (null reference) + Field is never ref-assigned to, and will always have its default value (null reference) + + Control is returned to caller before auto-implemented property '{0}' is explicitly assigned, causing a preceding implicit assignment of 'default'. 在明確指派自動實作屬性 '{0}' 之前會先將控制項傳回呼叫者,導致先前隱含的指派為 'default'。 diff --git a/src/Compilers/CSharp/Test/Emit3/FlowAnalysis/RegionAnalysisTests.cs b/src/Compilers/CSharp/Test/Emit3/FlowAnalysis/RegionAnalysisTests.cs index a99164d488376..d911a0f876095 100644 --- a/src/Compilers/CSharp/Test/Emit3/FlowAnalysis/RegionAnalysisTests.cs +++ b/src/Compilers/CSharp/Test/Emit3/FlowAnalysis/RegionAnalysisTests.cs @@ -14109,9 +14109,9 @@ ref struct RS """, targetFramework: TargetFramework.NetCoreApp); comp.VerifyEmitDiagnostics( - // (3,13): warning CS0649: Field 'RS.ri' is never assigned to, and will always have its default value (null reference) + // (3,13): warning CS9265: Field 'RS.ri' is never ref-assigned to, and will always have its default value (null reference) // ref int ri; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "ri").WithArguments("RS.ri", "(null reference)").WithLocation(3, 13), + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "ri").WithArguments("RS.ri").WithLocation(3, 13), // (4,20): warning CS9201: Ref field 'ri' should be ref-assigned before use. // public RS() => ri = 0; Diagnostic(ErrorCode.WRN_UseDefViolationRefField, "ri").WithArguments("ri").WithLocation(4, 20)); diff --git a/src/Compilers/CSharp/Test/Emit3/Semantics/PrimaryConstructorTests.cs b/src/Compilers/CSharp/Test/Emit3/Semantics/PrimaryConstructorTests.cs index b35dc0ce5acde..64063d8c36f34 100644 --- a/src/Compilers/CSharp/Test/Emit3/Semantics/PrimaryConstructorTests.cs +++ b/src/Compilers/CSharp/Test/Emit3/Semantics/PrimaryConstructorTests.cs @@ -20114,7 +20114,7 @@ public void IllegalCapturingDueToRefness_01(string keyword, string tag, TestFlag [Fact] public void IllegalCapturingDueToRefness_02() { - var source = @"#pragma warning disable CS0649 // Field 'R1.F1' is never assigned to, and will always have its default value 0 + var source = @"#pragma warning disable CS0649, CS9265 // Field 'R1.F1' is never assigned to, and will always have its default value 0 ref struct R1 { public int F1; diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs index b1a211d38dc44..e1b2e1cceaae0 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs @@ -1798,9 +1798,9 @@ public R() """; var comp = CreateCompilation(source, options: TestOptions.ReleaseExe, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics( - // (7,29): warning CS0649: Field 'R.field' is never assigned to, and will always have its default value (null reference) + // (7,29): warning CS9265: Field 'R.field' is never ref-assigned to, and will always have its default value (null reference) // public readonly ref int field; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "field").WithArguments("R.field", "(null reference)").WithLocation(7, 29) + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "field").WithArguments("R.field").WithLocation(7, 29) ); var verifier = CompileAndVerify(comp, verify: Verification.Skipped, expectedOutput: IncludeExpectedOutput("explicit ctor")); @@ -2279,7 +2279,7 @@ public void RequiredField_01(LanguageVersion languageVersion) { var source = """ #pragma warning disable 169 - #pragma warning disable 649 + #pragma warning disable 9265 ref struct R { public required ref T F1; @@ -5213,9 +5213,9 @@ class Program }"; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); comp.VerifyEmitDiagnostics( - // (3,19): warning CS0649: Field 'R._t' is never assigned to, and will always have its default value (null reference) + // (3,19): warning CS9265: Field 'R._t' is never ref-assigned to, and will always have its default value (null reference) // private ref T _t; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "_t").WithArguments("R._t", "(null reference)").WithLocation(3, 19), + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "_t").WithArguments("R._t").WithLocation(3, 19), // (4,25): warning CS9201: Ref field '_t' should be ref-assigned before use. // public R(ref T t) { _t = t; } Diagnostic(ErrorCode.WRN_UseDefViolationRefField, "_t").WithArguments("_t").WithLocation(4, 25)); @@ -5464,14 +5464,36 @@ public S(ref T t) }"; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); comp.VerifyEmitDiagnostics( - // (3,18): warning CS0649: Field 'S.F' is never assigned to, and will always have its default value (null reference) + // (3,18): warning CS9265: Field 'S.F' is never ref-assigned to, and will always have its default value (null reference) // public ref T F; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("S.F", "(null reference)").WithLocation(3, 18), + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F").WithArguments("S.F").WithLocation(3, 18), // (6,9): warning CS9201: Ref field 'F' should be ref-assigned before use. // F = t; Diagnostic(ErrorCode.WRN_UseDefViolationRefField, "F").WithArguments("F").WithLocation(6, 9)); } + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75315")] + public void DefiniteAssignment_WarningWave() + { + var source = """ + ref struct R + { + public ref int F; + } + """; + CreateCompilation(source, options: TestOptions.ReleaseDll.WithWarningLevel(9), targetFramework: TargetFramework.Net70).VerifyDiagnostics(); + + var expectedDiagnostics = new[] + { + // (3,20): warning CS9265: Field 'R.F' is never ref-assigned to, and will always have its default value (null reference) + // public ref int F; + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F").WithArguments("R.F").WithLocation(3, 20) + }; + + CreateCompilation(source, options: TestOptions.ReleaseDll.WithWarningLevel(10), targetFramework: TargetFramework.Net70).VerifyDiagnostics(expectedDiagnostics); + CreateCompilation(source, targetFramework: TargetFramework.Net70).VerifyDiagnostics(expectedDiagnostics); + } + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75315")] public void DefiniteAssignment_RefField_Unassigned_InAtCallSite() { @@ -5490,9 +5512,9 @@ static void Test(R r) """, targetFramework: TargetFramework.NetCoreApp); comp.VerifyDiagnostics( - // (3,20): warning CS0649: Field 'R.F' is never assigned to, and will always have its default value (null reference) + // (3,20): warning CS9265: Field 'R.F' is never ref-assigned to, and will always have its default value (null reference) // public ref int F; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "(null reference)").WithLocation(3, 20)); + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F").WithArguments("R.F").WithLocation(3, 20)); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75315")] @@ -5556,9 +5578,9 @@ static void Test(R r, int x) """, targetFramework: TargetFramework.NetCoreApp); comp.VerifyDiagnostics( - // (3,20): warning CS0649: Field 'R.F' is never assigned to, and will always have its default value (null reference) + // (3,20): warning CS9265: Field 'R.F' is never ref-assigned to, and will always have its default value (null reference) // public ref int F; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "(null reference)").WithLocation(3, 20)); + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F").WithArguments("R.F").WithLocation(3, 20)); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75315")] @@ -5588,12 +5610,12 @@ static void Test(R1 r, int x) // (3,12): error CS9050: A ref field cannot refer to a ref struct. // public ref R2 F; Diagnostic(ErrorCode.ERR_RefFieldCannotReferToRefStruct, "ref R2").WithLocation(3, 12), - // (3,19): warning CS0649: Field 'R1.F' is never assigned to, and will always have its default value (null reference) + // (3,19): warning CS9265: Field 'R1.F' is never ref-assigned to, and will always have its default value (null reference) // public ref R2 F; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R1.F", "(null reference)").WithLocation(3, 19), - // (8,20): warning CS0649: Field 'R2.F' is never assigned to, and will always have its default value (null reference) + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F").WithArguments("R1.F").WithLocation(3, 19), + // (8,20): warning CS9265: Field 'R2.F' is never ref-assigned to, and will always have its default value (null reference) // public ref int F; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R2.F", "(null reference)").WithLocation(8, 20)); + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F").WithArguments("R2.F").WithLocation(8, 20)); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75315")] @@ -5623,9 +5645,9 @@ static void Test(scoped R1 r, ref int x) // (3,12): error CS9050: A ref field cannot refer to a ref struct. // public ref R2 F; Diagnostic(ErrorCode.ERR_RefFieldCannotReferToRefStruct, "ref R2").WithLocation(3, 12), - // (3,19): warning CS0649: Field 'R1.F' is never assigned to, and will always have its default value (null reference) + // (3,19): warning CS9265: Field 'R1.F' is never ref-assigned to, and will always have its default value (null reference) // public ref R2 F; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R1.F", "(null reference)").WithLocation(3, 19)); + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F").WithArguments("R1.F").WithLocation(3, 19)); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75315")] @@ -5647,9 +5669,9 @@ static void Test(int x) """, targetFramework: TargetFramework.NetCoreApp); comp.VerifyDiagnostics( - // (3,20): warning CS0649: Field 'R.F' is never assigned to, and will always have its default value (null reference) + // (3,20): warning CS9265: Field 'R.F' is never ref-assigned to, and will always have its default value (null reference) // public ref int F; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "(null reference)").WithLocation(3, 20)); + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F").WithArguments("R.F").WithLocation(3, 20)); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75315")] @@ -5693,9 +5715,9 @@ static void Test(R r) """, targetFramework: TargetFramework.NetCoreApp); comp.VerifyDiagnostics( - // (3,20): warning CS0649: Field 'R.F' is never assigned to, and will always have its default value (null reference) + // (3,20): warning CS9265: Field 'R.F' is never ref-assigned to, and will always have its default value (null reference) // public ref int F; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "(null reference)").WithLocation(3, 20)); + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F").WithArguments("R.F").WithLocation(3, 20)); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75315")] @@ -5739,9 +5761,9 @@ static void Test(R r) """, targetFramework: TargetFramework.NetCoreApp); comp.VerifyDiagnostics( - // (3,20): warning CS0649: Field 'R.F' is never assigned to, and will always have its default value (null reference) + // (3,20): warning CS9265: Field 'R.F' is never ref-assigned to, and will always have its default value (null reference) // public ref int F; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "(null reference)").WithLocation(3, 20)); + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F").WithArguments("R.F").WithLocation(3, 20)); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75315")] @@ -5782,9 +5804,9 @@ static void Test(R r) """, targetFramework: TargetFramework.NetCoreApp); comp.VerifyDiagnostics( - // (3,20): warning CS0649: Field 'R.F' is never assigned to, and will always have its default value (null reference) + // (3,20): warning CS9265: Field 'R.F' is never ref-assigned to, and will always have its default value (null reference) // public ref int F; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "(null reference)").WithLocation(3, 20)); + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F").WithArguments("R.F").WithLocation(3, 20)); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75315")] @@ -5912,9 +5934,9 @@ object P }"; var comp = CreateCompilation(new[] { source, IsExternalInitTypeDefinition }, targetFramework: TargetFramework.Net70); comp.VerifyEmitDiagnostics( - // 0.cs(3,18): warning CS0649: Field 'S.F' is never assigned to, and will always have its default value (null reference) + // 0.cs(3,18): warning CS9265: Field 'S.F' is never ref-assigned to, and will always have its default value (null reference) // public ref T F; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("S.F", "(null reference)").WithLocation(3, 18), + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F").WithArguments("S.F").WithLocation(3, 18), // 0.cs(7,9): warning CS9201: Ref field 'F' should be ref-assigned before use. // F = tValue; Diagnostic(ErrorCode.WRN_UseDefViolationRefField, "F").WithArguments("F").WithLocation(7, 9)); @@ -5950,9 +5972,9 @@ object P }"; var comp = CreateCompilation(new[] { source, IsExternalInitTypeDefinition }, targetFramework: TargetFramework.Net70); comp.VerifyEmitDiagnostics( - // (3,27): warning CS0649: Field 'S.F' is never assigned to, and will always have its default value (null reference) + // (3,27): warning CS9265: Field 'S.F' is never ref-assigned to, and will always have its default value (null reference) // public ref readonly T F; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("S.F", "(null reference)").WithLocation(3, 27), + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F").WithArguments("S.F").WithLocation(3, 27), // (7,9): error CS8331: Cannot assign to field 'F' or use it as the right hand side of a ref assignment because it is a readonly variable // F = tValue; // 1 Diagnostic(ErrorCode.ERR_AssignReadonlyNotField, "F").WithArguments("field", "F").WithLocation(7, 9), @@ -6009,9 +6031,9 @@ object P }"; var comp = CreateCompilation(new[] { source, IsExternalInitTypeDefinition }, targetFramework: TargetFramework.Net70); comp.VerifyEmitDiagnostics( - // 0.cs(3,27): warning CS0649: Field 'S.F' is never assigned to, and will always have its default value (null reference) + // 0.cs(3,27): warning CS9265: Field 'S.F' is never ref-assigned to, and will always have its default value (null reference) // public readonly ref T F; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("S.F", "(null reference)").WithLocation(3, 27), + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F").WithArguments("S.F").WithLocation(3, 27), // 0.cs(7,9): warning CS9201: Ref field 'F' should be ref-assigned before use. // F = tValue; Diagnostic(ErrorCode.WRN_UseDefViolationRefField, "F").WithArguments("F").WithLocation(7, 9)); @@ -6047,9 +6069,9 @@ object P }"; var comp = CreateCompilation(new[] { source, IsExternalInitTypeDefinition }, targetFramework: TargetFramework.Net70); comp.VerifyEmitDiagnostics( - // (3,36): warning CS0649: Field 'S.F' is never assigned to, and will always have its default value (null reference) + // (3,36): warning CS9265: Field 'S.F' is never ref-assigned to, and will always have its default value (null reference) // public readonly ref readonly T F; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("S.F", "(null reference)").WithLocation(3, 36), + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F").WithArguments("S.F").WithLocation(3, 36), // (7,9): error CS8331: Cannot assign to field 'F' or use it as the right hand side of a ref assignment because it is a readonly variable // F = tValue; // 1 Diagnostic(ErrorCode.ERR_AssignReadonlyNotField, "F").WithArguments("field", "F").WithLocation(7, 9), @@ -7489,7 +7511,7 @@ class Program public void AssignOutParameterFrom_RefField() { var source = -@"#pragma warning disable 649 +@"#pragma warning disable 9265 ref struct S { public ref T Ref; @@ -7560,18 +7582,18 @@ class Program }"; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); comp.VerifyEmitDiagnostics( - // (3,18): warning CS0649: Field 'S.Ref' is never assigned to, and will always have its default value (null reference) + // (3,18): warning CS9265: Field 'S.Ref' is never ref-assigned to, and will always have its default value (null reference) // public ref T Ref; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "Ref").WithArguments("S.Ref", "(null reference)").WithLocation(3, 18), - // (4,27): warning CS0649: Field 'S.RefReadonly' is never assigned to, and will always have its default value (null reference) + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "Ref").WithArguments("S.Ref").WithLocation(3, 18), + // (4,27): warning CS9265: Field 'S.RefReadonly' is never ref-assigned to, and will always have its default value (null reference) // public ref readonly T RefReadonly; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "RefReadonly").WithArguments("S.RefReadonly", "(null reference)").WithLocation(4, 27), - // (5,27): warning CS0649: Field 'S.ReadonlyRef' is never assigned to, and will always have its default value (null reference) + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "RefReadonly").WithArguments("S.RefReadonly").WithLocation(4, 27), + // (5,27): warning CS9265: Field 'S.ReadonlyRef' is never ref-assigned to, and will always have its default value (null reference) // public readonly ref T ReadonlyRef; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "ReadonlyRef").WithArguments("S.ReadonlyRef", "(null reference)").WithLocation(5, 27), - // (6,36): warning CS0649: Field 'S.ReadonlyRefReadonly' is never assigned to, and will always have its default value (null reference) + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "ReadonlyRef").WithArguments("S.ReadonlyRef").WithLocation(5, 27), + // (6,36): warning CS9265: Field 'S.ReadonlyRefReadonly' is never ref-assigned to, and will always have its default value (null reference) // public readonly ref readonly T ReadonlyRefReadonly; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "ReadonlyRefReadonly").WithArguments("S.ReadonlyRefReadonly", "(null reference)").WithLocation(6, 36), + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "ReadonlyRefReadonly").WithArguments("S.ReadonlyRefReadonly").WithLocation(6, 36), // (12,73): error CS8329: Cannot use field 'RefReadonly' as a ref or out value because it is a readonly variable // static void FromValueRefReadonly(S s) { ref T t = ref s.RefReadonly; } // 1 Diagnostic(ErrorCode.ERR_RefReadonlyNotField, "s.RefReadonly").WithArguments("field", "RefReadonly").WithLocation(12, 73), @@ -7634,18 +7656,18 @@ class Program }"; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); comp.VerifyEmitDiagnostics( - // (3,18): warning CS0649: Field 'S.Ref' is never assigned to, and will always have its default value (null reference) + // (3,18): warning CS9265: Field 'S.Ref' is never ref-assigned to, and will always have its default value (null reference) // public ref T Ref; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "Ref").WithArguments("S.Ref", "(null reference)").WithLocation(3, 18), - // (4,27): warning CS0649: Field 'S.RefReadonly' is never assigned to, and will always have its default value (null reference) + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "Ref").WithArguments("S.Ref").WithLocation(3, 18), + // (4,27): warning CS9265: Field 'S.RefReadonly' is never ref-assigned to, and will always have its default value (null reference) // public ref readonly T RefReadonly; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "RefReadonly").WithArguments("S.RefReadonly", "(null reference)").WithLocation(4, 27), - // (5,27): warning CS0649: Field 'S.ReadonlyRef' is never assigned to, and will always have its default value (null reference) + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "RefReadonly").WithArguments("S.RefReadonly").WithLocation(4, 27), + // (5,27): warning CS9265: Field 'S.ReadonlyRef' is never ref-assigned to, and will always have its default value (null reference) // public readonly ref T ReadonlyRef; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "ReadonlyRef").WithArguments("S.ReadonlyRef", "(null reference)").WithLocation(5, 27), - // (6,36): warning CS0649: Field 'S.ReadonlyRefReadonly' is never assigned to, and will always have its default value (null reference) + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "ReadonlyRef").WithArguments("S.ReadonlyRef").WithLocation(5, 27), + // (6,36): warning CS9265: Field 'S.ReadonlyRefReadonly' is never ref-assigned to, and will always have its default value (null reference) // public readonly ref readonly T ReadonlyRefReadonly; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "ReadonlyRefReadonly").WithArguments("S.ReadonlyRefReadonly", "(null reference)").WithLocation(6, 36)); + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "ReadonlyRefReadonly").WithArguments("S.ReadonlyRefReadonly").WithLocation(6, 36)); } [Fact] @@ -7705,9 +7727,9 @@ class Program }"; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); comp.VerifyEmitDiagnostics( - // (3,18): warning CS0649: Field 'S.F' is never assigned to, and will always have its default value (null reference) + // (3,18): warning CS9265: Field 'S.F' is never ref-assigned to, and will always have its default value (null reference) // public ref T F; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("S.F", "(null reference)").WithLocation(3, 18)); + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F").WithArguments("S.F").WithLocation(3, 18)); } [Fact] @@ -7733,9 +7755,9 @@ class Program }"; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); comp.VerifyEmitDiagnostics( - // (3,27): warning CS0649: Field 'S.F' is never assigned to, and will always have its default value (null reference) + // (3,27): warning CS9265: Field 'S.F' is never ref-assigned to, and will always have its default value (null reference) // public ref readonly T F; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("S.F", "(null reference)").WithLocation(3, 27), + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F").WithArguments("S.F").WithLocation(3, 27), // (4,30): error CS8333: Cannot return field 'F' by writable reference because it is a readonly variable // public ref T F1() => ref F; Diagnostic(ErrorCode.ERR_RefReturnReadonlyNotField, "F").WithArguments("field", "F").WithLocation(4, 30), @@ -7776,9 +7798,9 @@ class Program }"; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); comp.VerifyEmitDiagnostics( - // (3,27): warning CS0649: Field 'S.F' is never assigned to, and will always have its default value (null reference) + // (3,27): warning CS9265: Field 'S.F' is never ref-assigned to, and will always have its default value (null reference) // public readonly ref T F; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("S.F", "(null reference)").WithLocation(3, 27)); + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F").WithArguments("S.F").WithLocation(3, 27)); } [Fact] @@ -7804,9 +7826,9 @@ class Program }"; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); comp.VerifyEmitDiagnostics( - // (3,36): warning CS0649: Field 'S.F' is never assigned to, and will always have its default value (null reference) + // (3,36): warning CS9265: Field 'S.F' is never ref-assigned to, and will always have its default value (null reference) // public readonly ref readonly T F; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("S.F", "(null reference)").WithLocation(3, 36), + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F").WithArguments("S.F").WithLocation(3, 36), // (4,30): error CS8333: Cannot return field 'F' by writable reference because it is a readonly variable // public ref T F1() => ref F; Diagnostic(ErrorCode.ERR_RefReturnReadonlyNotField, "F").WithArguments("field", "F").WithLocation(4, 30), @@ -8078,9 +8100,9 @@ static void M4(in T t) { } }"; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); comp.VerifyEmitDiagnostics( - // (3,18): warning CS0649: Field 'S.F' is never assigned to, and will always have its default value (null reference) + // (3,18): warning CS9265: Field 'S.F' is never ref-assigned to, and will always have its default value (null reference) // public ref T F; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("S.F", "(null reference)").WithLocation(3, 18)); + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F").WithArguments("S.F").WithLocation(3, 18)); } [Fact] @@ -8125,9 +8147,9 @@ static void M4(in T t) { } }"; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); comp.VerifyEmitDiagnostics( - // (3,27): warning CS0649: Field 'S.F' is never assigned to, and will always have its default value (null reference) + // (3,27): warning CS9265: Field 'S.F' is never ref-assigned to, and will always have its default value (null reference) // public ref readonly T F; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("S.F", "(null reference)").WithLocation(3, 27), + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F").WithArguments("S.F").WithLocation(3, 27), // (14,49): error CS8329: Cannot use field 'F' as a ref or out value because it is a readonly variable // static void FromValue2(S s) { M2(ref s.F); } // 1 Diagnostic(ErrorCode.ERR_RefReadonlyNotField, "s.F").WithArguments("field", "F").WithLocation(14, 49), @@ -8196,9 +8218,9 @@ static void M4(in T t) { } }"; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); comp.VerifyEmitDiagnostics( - // (3,27): warning CS0649: Field 'S.F' is never assigned to, and will always have its default value (null reference) + // (3,27): warning CS9265: Field 'S.F' is never ref-assigned to, and will always have its default value (null reference) // public readonly ref T F; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("S.F", "(null reference)").WithLocation(3, 27)); + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F").WithArguments("S.F").WithLocation(3, 27)); } [Fact] @@ -8243,9 +8265,9 @@ static void M4(in T t) { } }"; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); comp.VerifyEmitDiagnostics( - // (3,36): warning CS0649: Field 'S.F' is never assigned to, and will always have its default value (null reference) + // (3,36): warning CS9265: Field 'S.F' is never ref-assigned to, and will always have its default value (null reference) // public readonly ref readonly T F; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("S.F", "(null reference)").WithLocation(3, 36), + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F").WithArguments("S.F").WithLocation(3, 36), // (14,49): error CS8329: Cannot use field 'F' as a ref or out value because it is a readonly variable // static void FromValue2(S s) { M2(ref s.F); } // 1 Diagnostic(ErrorCode.ERR_RefReadonlyNotField, "s.F").WithArguments("field", "F").WithLocation(14, 49), @@ -8276,7 +8298,7 @@ static void M4(in T t) { } public void RefParameter_ReadonlyRefReadonly_PEVerifyCompat() { var source = -@"#pragma warning disable 649 +@"#pragma warning disable 9265 ref struct S { public readonly ref readonly T F; @@ -10003,9 +10025,9 @@ public R(){} // (14,12): error CS0206: A non ref-returning property or indexer may not be used as an out or ref value // _ = M2(out c[0]); //CS0206 Diagnostic(ErrorCode.ERR_RefProperty, "c[0]").WithLocation(14, 12), - // (28,21): warning CS0649: Field 'R.n' is never assigned to, and will always have its default value (null reference) + // (28,21): warning CS9265: Field 'R.n' is never ref-assigned to, and will always have its default value (null reference) // private ref int n; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "n").WithArguments("R.n", "(null reference)").WithLocation(28, 21) + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "n").WithArguments("R.n").WithLocation(28, 21) ); } @@ -10223,9 +10245,9 @@ public static void M() where T : unmanaged { } // (10,36): warning CS0649: Field 'StructWithIndirectRefField.Field' is never assigned to, and will always have its default value // public StructWithRefField Field; Diagnostic(ErrorCode.WRN_UnassignedInternalField, "Field").WithArguments("StructWithIndirectRefField.Field", "").WithLocation(10, 36), - // (14,18): warning CS0649: Field 'StructWithRefField.RefField' is never assigned to, and will always have its default value (null reference) + // (14,18): warning CS9265: Field 'StructWithRefField.RefField' is never ref-assigned to, and will always have its default value (null reference) // public ref T RefField; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "RefField").WithArguments("StructWithRefField.RefField", "(null reference)").WithLocation(14, 18) + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "RefField").WithArguments("StructWithRefField.RefField").WithLocation(14, 18) ); Assert.True(comp.GetTypeByMetadataName("StructWithIndirectRefField").IsManagedTypeNoUseSiteDiagnostics); @@ -18671,9 +18693,9 @@ public void ReturnRefField() }"; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics( - // (3,18): warning CS0649: Field 'R.F' is never assigned to, and will always have its default value (null reference) + // (3,18): warning CS9265: Field 'R.F' is never ref-assigned to, and will always have its default value (null reference) // public ref T F; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "(null reference)").WithLocation(3, 18)); + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F").WithArguments("R.F").WithLocation(3, 18)); } [Fact] @@ -18689,9 +18711,9 @@ public void ReturnRefReadonlyField() }"; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics( - // (3,27): warning CS0649: Field 'R.F' is never assigned to, and will always have its default value (null reference) + // (3,27): warning CS9265: Field 'R.F' is never ref-assigned to, and will always have its default value (null reference) // public ref readonly T F; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "(null reference)").WithLocation(3, 27), + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F").WithArguments("R.F").WithLocation(3, 27), // (5,34): error CS8333: Cannot return field 'F' by writable reference because it is a readonly variable // public ref T GetRef() => ref F; // 1 Diagnostic(ErrorCode.ERR_RefReturnReadonlyNotField, "F").WithArguments("field", "F").WithLocation(5, 34)); @@ -30293,9 +30315,9 @@ ref struct RS expectedOutput: "1"); verifier.VerifyDiagnostics( - // (14,13): warning CS0649: Field 'RS.ri' is never assigned to, and will always have its default value (null reference) + // (14,13): warning CS9265: Field 'RS.ri' is never ref-assigned to, and will always have its default value (null reference) // ref int ri; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "ri").WithArguments("RS.ri", "(null reference)").WithLocation(14, 13), + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "ri").WithArguments("RS.ri").WithLocation(14, 13), // (15,20): warning CS9201: Ref field 'ri' should be ref-assigned before use. // public RS() => ri = 0; Diagnostic(ErrorCode.WRN_UseDefViolationRefField, "ri").WithArguments("ri").WithLocation(15, 20)); @@ -30347,9 +30369,9 @@ public RS() expectedOutput: "1"); verifier.VerifyDiagnostics( - // (14,13): warning CS0649: Field 'RS.ri' is never assigned to, and will always have its default value (null reference) + // (14,13): warning CS9265: Field 'RS.ri' is never ref-assigned to, and will always have its default value (null reference) // ref int ri; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "ri").WithArguments("RS.ri", "(null reference)").WithLocation(14, 13), + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "ri").WithArguments("RS.ri").WithLocation(14, 13), // (15,12): warning CS9022: Control is returned to caller before field 'RS.ri' is explicitly assigned, causing a preceding implicit assignment of 'default'. // public RS() Diagnostic(ErrorCode.WRN_UnassignedThisSupportedVersion, "RS").WithArguments("RS.ri").WithLocation(15, 12), @@ -30415,9 +30437,9 @@ public RS(bool ignored) expectedOutput: "12"); verifier.VerifyDiagnostics( - // (17,13): warning CS0649: Field 'RS.ri' is never assigned to, and will always have its default value (null reference) + // (17,13): warning CS9265: Field 'RS.ri' is never ref-assigned to, and will always have its default value (null reference) // ref int ri; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "ri").WithArguments("RS.ri", "(null reference)").WithLocation(17, 13), + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "ri").WithArguments("RS.ri").WithLocation(17, 13), // (20,29): warning CS9201: Ref field 'ri' should be ref-assigned before use. // ref int local = ref ri; // 1 Diagnostic(ErrorCode.WRN_UseDefViolationRefField, "ri").WithArguments("ri").WithLocation(20, 29), @@ -30493,9 +30515,9 @@ ref struct RS targetFramework: TargetFramework.NetCoreApp); comp.VerifyDiagnostics( - // (3,22): warning CS0649: Field 'RS.ri' is never assigned to, and will always have its default value (null reference) + // (3,22): warning CS9265: Field 'RS.ri' is never ref-assigned to, and will always have its default value (null reference) // ref readonly int ri; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "ri").WithArguments("RS.ri", "(null reference)").WithLocation(3, 22), + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "ri").WithArguments("RS.ri").WithLocation(3, 22), // (4,20): error CS8331: Cannot assign to field 'ri' or use it as the right hand side of a ref assignment because it is a readonly variable // public RS() => ri = 0; Diagnostic(ErrorCode.ERR_AssignReadonlyNotField, "ri").WithArguments("field", "ri").WithLocation(4, 20), @@ -30526,9 +30548,9 @@ static void Test1() targetFramework: TargetFramework.NetCoreApp); verifier.VerifyDiagnostics( - // (3,20): warning CS0649: Field 'S.F1' is never assigned to, and will always have its default value (null reference) + // (3,20): warning CS9265: Field 'S.F1' is never ref-assigned to, and will always have its default value (null reference) // public ref int F1; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F1").WithArguments("S.F1", "(null reference)").WithLocation(3, 20)); + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F1").WithArguments("S.F1").WithLocation(3, 20)); verifier.VerifyIL("S.Test1", @" @@ -30567,9 +30589,9 @@ static void Test1() targetFramework: TargetFramework.NetCoreApp); comp.VerifyDiagnostics( - // (3,29): warning CS0649: Field 'S.F1' is never assigned to, and will always have its default value (null reference) + // (3,29): warning CS9265: Field 'S.F1' is never ref-assigned to, and will always have its default value (null reference) // public ref readonly int F1; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F1").WithArguments("S.F1", "(null reference)").WithLocation(3, 29), + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F1").WithArguments("S.F1").WithLocation(3, 29), // (11,15): error CS8329: Cannot use field 'F1' as a ref or out value because it is a readonly variable // M(ref GetS().F1); Diagnostic(ErrorCode.ERR_RefReadonlyNotField, "GetS().F1").WithArguments("field", "F1").WithLocation(11, 15) @@ -30600,9 +30622,9 @@ static void Test1() targetFramework: TargetFramework.NetCoreApp); verifier.VerifyDiagnostics( - // (3,29): warning CS0649: Field 'S.F1' is never assigned to, and will always have its default value (null reference) + // (3,29): warning CS9265: Field 'S.F1' is never ref-assigned to, and will always have its default value (null reference) // public ref readonly int F1; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F1").WithArguments("S.F1", "(null reference)").WithLocation(3, 29)); + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F1").WithArguments("S.F1").WithLocation(3, 29)); verifier.VerifyIL("S.Test1", """ { @@ -30640,9 +30662,9 @@ static void Test1() targetFramework: TargetFramework.NetCoreApp); comp.VerifyDiagnostics( - // (3,29): warning CS0649: Field 'S.F1' is never assigned to, and will always have its default value (null reference) + // (3,29): warning CS9265: Field 'S.F1' is never ref-assigned to, and will always have its default value (null reference) // public ref readonly int F1; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F1").WithArguments("S.F1", "(null reference)").WithLocation(3, 29), + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F1").WithArguments("S.F1").WithLocation(3, 29), // (11,15): error CS8329: Cannot use field 'F1' as a ref or out value because it is a readonly variable // M(ref GetS().F1); Diagnostic(ErrorCode.ERR_RefReadonlyNotField, "GetS().F1").WithArguments("field", "F1").WithLocation(11, 15) @@ -30673,9 +30695,9 @@ static void Test1() targetFramework: TargetFramework.NetCoreApp); verifier.VerifyDiagnostics( - // (3,29): warning CS0649: Field 'S.F1' is never assigned to, and will always have its default value (null reference) + // (3,29): warning CS9265: Field 'S.F1' is never ref-assigned to, and will always have its default value (null reference) // public ref readonly int F1; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F1").WithArguments("S.F1", "(null reference)").WithLocation(3, 29)); + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F1").WithArguments("S.F1").WithLocation(3, 29)); verifier.VerifyIL("S.Test1", """ { @@ -30696,7 +30718,7 @@ .locals init (S V_0) public void RefField_AsRefArgument_06() { var verifier = CompileAndVerify(""" - #pragma warning disable CS0649 // Field 'S.F1' is never assigned to, and will always have its default value 0 + #pragma warning disable CS9265 // Field 'S.F1' is never ref-assigned to, and will always have its default value (null reference) ref struct S { @@ -30755,9 +30777,9 @@ static void Test1() targetFramework: TargetFramework.NetCoreApp); verifier.VerifyDiagnostics( - // (3,29): warning CS0649: Field 'S.F1' is never assigned to, and will always have its default value (null reference) + // (3,29): warning CS9265: Field 'S.F1' is never ref-assigned to, and will always have its default value (null reference) // public readonly ref int F1; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F1").WithArguments("S.F1", "(null reference)").WithLocation(3, 29)); + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F1").WithArguments("S.F1").WithLocation(3, 29)); verifier.VerifyIL("S.Test1", @" @@ -30797,9 +30819,9 @@ static void Test1() targetFramework: TargetFramework.NetCoreApp); verifier.VerifyDiagnostics( - // (3,29): warning CS0649: Field 'S.F1' is never assigned to, and will always have its default value (null reference) + // (3,29): warning CS9265: Field 'S.F1' is never ref-assigned to, and will always have its default value (null reference) // public readonly ref int F1; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F1").WithArguments("S.F1", "(null reference)").WithLocation(3, 29)); + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F1").WithArguments("S.F1").WithLocation(3, 29)); verifier.VerifyIL("S.Test1", @" @@ -30841,9 +30863,9 @@ static void Test1() targetFramework: TargetFramework.NetCoreApp); verifier.VerifyDiagnostics( - // (3,29): warning CS0649: Field 'S.F1' is never assigned to, and will always have its default value (null reference) + // (3,29): warning CS9265: Field 'S.F1' is never ref-assigned to, and will always have its default value (null reference) // public readonly ref int F1; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F1").WithArguments("S.F1", "(null reference)").WithLocation(3, 29)); + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F1").WithArguments("S.F1").WithLocation(3, 29)); verifier.VerifyIL("S.Test1", """ { @@ -30882,9 +30904,9 @@ static void Test1() targetFramework: TargetFramework.NetCoreApp); verifier.VerifyDiagnostics( - // (3,29): warning CS0649: Field 'S.F1' is never assigned to, and will always have its default value (null reference) + // (3,29): warning CS9265: Field 'S.F1' is never ref-assigned to, and will always have its default value (null reference) // public readonly ref int F1; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F1").WithArguments("S.F1", "(null reference)").WithLocation(3, 29), + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F1").WithArguments("S.F1").WithLocation(3, 29), // (11,15): warning CS9191: The 'ref' modifier for argument 1 corresponding to 'in' parameter is equivalent to 'in'. Consider using 'in' instead. // M(ref GetS().F1); Diagnostic(ErrorCode.WRN_BadArgRef, "GetS().F1").WithArguments("1").WithLocation(11, 15) @@ -30930,9 +30952,9 @@ static void Test1() targetFramework: TargetFramework.NetCoreApp); verifier.VerifyDiagnostics( - // (3,29): warning CS0649: Field 'S.F1' is never assigned to, and will always have its default value (null reference) + // (3,29): warning CS9265: Field 'S.F1' is never ref-assigned to, and will always have its default value (null reference) // public readonly ref int F1; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F1").WithArguments("S.F1", "(null reference)").WithLocation(3, 29)); + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F1").WithArguments("S.F1").WithLocation(3, 29)); verifier.VerifyIL("S.Test1", """ { @@ -30953,7 +30975,7 @@ .locals init (S V_0) public void RefField_AsRefArgument_12() { var verifier = CompileAndVerify(""" - #pragma warning disable CS0649 // Field 'S.F1' is never assigned to, and will always have its default value 0 + #pragma warning disable CS9265 // Field 'S.F1' is never ref-assigned to, and will always have its default value (null reference) ref struct S { @@ -31010,9 +31032,9 @@ static void Test() """, targetFramework: TargetFramework.NetCoreApp); comp.VerifyDiagnostics( - // (3,20): warning CS0649: Field 'R.F' is never assigned to, and will always have its default value (null reference) + // (3,20): warning CS9265: Field 'R.F' is never ref-assigned to, and will always have its default value (null reference) // public ref int F; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "(null reference)").WithLocation(3, 20)); + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F").WithArguments("R.F").WithLocation(3, 20)); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75082")] @@ -31035,9 +31057,9 @@ static void Test() """, targetFramework: TargetFramework.NetCoreApp); comp.VerifyDiagnostics( - // (3,20): warning CS0649: Field 'R.F' is never assigned to, and will always have its default value (null reference) + // (3,20): warning CS9265: Field 'R.F' is never ref-assigned to, and will always have its default value (null reference) // public ref int F; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "(null reference)").WithLocation(3, 20)); + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F").WithArguments("R.F").WithLocation(3, 20)); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75082")] @@ -31062,9 +31084,9 @@ static void Test() """, targetFramework: TargetFramework.NetCoreApp); comp.VerifyDiagnostics( - // (3,20): warning CS0649: Field 'R.F' is never assigned to, and will always have its default value (null reference) + // (3,20): warning CS9265: Field 'R.F' is never ref-assigned to, and will always have its default value (null reference) // public ref int F; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "(null reference)").WithLocation(3, 20)); + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F").WithArguments("R.F").WithLocation(3, 20)); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75082")] @@ -31087,9 +31109,9 @@ static void Test() """, targetFramework: TargetFramework.NetCoreApp); comp.VerifyDiagnostics( - // (3,20): warning CS0649: Field 'R.F' is never assigned to, and will always have its default value (null reference) + // (3,20): warning CS9265: Field 'R.F' is never ref-assigned to, and will always have its default value (null reference) // public ref int F; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "(null reference)").WithLocation(3, 20)); + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F").WithArguments("R.F").WithLocation(3, 20)); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75082")] @@ -31112,9 +31134,9 @@ static void Test() """, targetFramework: TargetFramework.NetCoreApp); comp.VerifyDiagnostics( - // (3,20): warning CS0649: Field 'R.F' is never assigned to, and will always have its default value (null reference) + // (3,20): warning CS9265: Field 'R.F' is never ref-assigned to, and will always have its default value (null reference) // public ref int F; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "(null reference)").WithLocation(3, 20), + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F").WithArguments("R.F").WithLocation(3, 20), // (11,11): warning CS9192: Argument 1 should be passed with 'ref' or 'in' keyword // M(GetValue().F); Diagnostic(ErrorCode.WRN_ArgExpectedRefOrIn, "GetValue().F").WithArguments("1").WithLocation(11, 11)); @@ -31140,9 +31162,9 @@ static void Test() """, targetFramework: TargetFramework.NetCoreApp); comp.VerifyDiagnostics( - // (3,20): warning CS0649: Field 'R.F' is never assigned to, and will always have its default value (null reference) + // (3,20): warning CS9265: Field 'R.F' is never ref-assigned to, and will always have its default value (null reference) // public ref int F; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "(null reference)").WithLocation(3, 20)); + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F").WithArguments("R.F").WithLocation(3, 20)); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75082")] @@ -31165,9 +31187,9 @@ static void Test() """, targetFramework: TargetFramework.NetCoreApp); comp.VerifyDiagnostics( - // (3,20): warning CS0649: Field 'R.F' is never assigned to, and will always have its default value (null reference) + // (3,20): warning CS9265: Field 'R.F' is never ref-assigned to, and will always have its default value (null reference) // public ref int F; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "(null reference)").WithLocation(3, 20), + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F").WithArguments("R.F").WithLocation(3, 20), // (11,11): error CS1620: Argument 1 must be passed with the 'ref' keyword // M(GetValue().F); Diagnostic(ErrorCode.ERR_BadArgRef, "GetValue().F").WithArguments("1", "ref").WithLocation(11, 11)); @@ -31193,9 +31215,9 @@ static void Test() """, targetFramework: TargetFramework.NetCoreApp); comp.VerifyDiagnostics( - // (3,29): warning CS0649: Field 'R.F' is never assigned to, and will always have its default value (null reference) + // (3,29): warning CS9265: Field 'R.F' is never ref-assigned to, and will always have its default value (null reference) // public ref readonly int F; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "(null reference)").WithLocation(3, 29), + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F").WithArguments("R.F").WithLocation(3, 29), // (11,15): error CS8329: Cannot use field 'F' as a ref or out value because it is a readonly variable // M(ref GetValue().F); Diagnostic(ErrorCode.ERR_RefReadonlyNotField, "GetValue().F").WithArguments("field", "F").WithLocation(11, 15)); @@ -31221,9 +31243,9 @@ static void Test() """, targetFramework: TargetFramework.NetCoreApp); comp.VerifyDiagnostics( - // (3,29): warning CS0649: Field 'R.F' is never assigned to, and will always have its default value (null reference) + // (3,29): warning CS9265: Field 'R.F' is never ref-assigned to, and will always have its default value (null reference) // public ref readonly int F; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "(null reference)").WithLocation(3, 29)); + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F").WithArguments("R.F").WithLocation(3, 29)); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75082")] @@ -31246,9 +31268,9 @@ static void Test() """, targetFramework: TargetFramework.NetCoreApp); comp.VerifyDiagnostics( - // (3,29): warning CS0649: Field 'R.F' is never assigned to, and will always have its default value (null reference) + // (3,29): warning CS9265: Field 'R.F' is never ref-assigned to, and will always have its default value (null reference) // public ref readonly int F; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "(null reference)").WithLocation(3, 29), + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F").WithArguments("R.F").WithLocation(3, 29), // (11,15): error CS8329: Cannot use field 'F' as a ref or out value because it is a readonly variable // M(out GetValue().F); Diagnostic(ErrorCode.ERR_RefReadonlyNotField, "GetValue().F").WithArguments("field", "F").WithLocation(11, 15)); @@ -31274,9 +31296,9 @@ static void Test() """, targetFramework: TargetFramework.NetCoreApp); comp.VerifyDiagnostics( - // (3,29): warning CS0649: Field 'R.F' is never assigned to, and will always have its default value (null reference) + // (3,29): warning CS9265: Field 'R.F' is never ref-assigned to, and will always have its default value (null reference) // public ref readonly int F; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "(null reference)").WithLocation(3, 29), + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F").WithArguments("R.F").WithLocation(3, 29), // (11,11): warning CS9195: Argument 1 should be passed with the 'in' keyword // M(GetValue().F); Diagnostic(ErrorCode.WRN_ArgExpectedIn, "GetValue().F").WithArguments("1").WithLocation(11, 11)); @@ -31302,9 +31324,9 @@ static void Test() """, targetFramework: TargetFramework.NetCoreApp); comp.VerifyDiagnostics( - // (3,29): warning CS0649: Field 'R.F' is never assigned to, and will always have its default value (null reference) + // (3,29): warning CS9265: Field 'R.F' is never ref-assigned to, and will always have its default value (null reference) // public ref readonly int F; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "(null reference)").WithLocation(3, 29)); + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F").WithArguments("R.F").WithLocation(3, 29)); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75082")] @@ -31327,9 +31349,9 @@ static void Test() """, targetFramework: TargetFramework.NetCoreApp); comp.VerifyDiagnostics( - // (3,29): warning CS0649: Field 'R.F' is never assigned to, and will always have its default value (null reference) + // (3,29): warning CS9265: Field 'R.F' is never ref-assigned to, and will always have its default value (null reference) // public ref readonly int F; - Diagnostic(ErrorCode.WRN_UnassignedInternalField, "F").WithArguments("R.F", "(null reference)").WithLocation(3, 29), + Diagnostic(ErrorCode.WRN_UnassignedInternalRefField, "F").WithArguments("R.F").WithLocation(3, 29), // (11,11): error CS1620: Argument 1 must be passed with the 'ref' keyword // M(GetValue().F); Diagnostic(ErrorCode.ERR_BadArgRef, "GetValue().F").WithArguments("1", "ref").WithLocation(11, 11)); diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/RequiredMembersTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/RequiredMembersTests.cs index c70afdb79199a..63df7b20d52b8 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/RequiredMembersTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/RequiredMembersTests.cs @@ -1364,7 +1364,7 @@ class C public void RefFields() { var source = """ - #pragma warning disable 649 + #pragma warning disable 9265 internal ref struct R1 { internal required ref T F1; diff --git a/src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs b/src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs index 47c197cb03303..4bd091c5823dc 100644 --- a/src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs +++ b/src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs @@ -471,6 +471,10 @@ public void WarningLevel_2() // These are the warnings introduced with the warning "wave" shipped with dotnet 8 and C# 12. Assert.Equal(8, ErrorFacts.GetWarningLevel(errorCode)); break; + case ErrorCode.WRN_UnassignedInternalRefField: + // These are the warnings introduced with the warning "wave" shipped with dotnet 10 and C# 14. + Assert.Equal(10, ErrorFacts.GetWarningLevel(errorCode)); + break; default: // If a new warning is added, this test will fail // and whoever is adding the new warning will have to update it with the expected error level. From db62221844eadd5e8102bb9356d5b1fc3326e037 Mon Sep 17 00:00:00 2001 From: Jan Jones Date: Thu, 10 Oct 2024 11:24:05 +0200 Subject: [PATCH 5/5] Document `isRef` parameter --- .../CSharp/Portable/FlowAnalysis/DefiniteAssignment.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/DefiniteAssignment.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/DefiniteAssignment.cs index 82eb7be04404c..568b2c4d01aa6 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/DefiniteAssignment.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/DefiniteAssignment.cs @@ -951,6 +951,9 @@ internal static bool WriteConsideredUse(TypeSymbol type, BoundExpression value) } } + /// + /// Whether this write represents a ref-assignment. + /// private void NoteWrite(BoundExpression n, BoundExpression value, bool read, bool isRef) { while (n != null)