diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/LocalDataFlowPass.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/LocalDataFlowPass.cs index cc88a9c5a2694..c06d004ac2ff9 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/LocalDataFlowPass.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/LocalDataFlowPass.cs @@ -113,12 +113,14 @@ protected virtual bool IsEmptyStructType(TypeSymbol type) return _emptyStructTypeCache.IsEmptyStructType(type); } +#nullable enable /// /// Force a variable to have a slot. Returns -1 if the variable has an empty struct type. /// protected virtual int GetOrCreateSlot(Symbol symbol, int containingSlot = 0, bool forceSlotEvenIfEmpty = false) { Debug.Assert(containingSlot >= 0); + Debug.Assert(symbol != null); if (symbol.Kind == SymbolKind.RangeVariable) return -1; @@ -169,6 +171,7 @@ protected virtual int GetOrCreateSlot(Symbol symbol, int containingSlot = 0, boo return slot; } +#nullable restore private int GetSlotDepth(int slot) { diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs index cd2e671546eb7..415be3b5a8017 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs @@ -715,6 +715,10 @@ int getSlotForFieldOrProperty(Symbol member) if (!isStatic) { + if (MethodThisParameter is null) + { + return -1; + } thisSlot = GetOrCreateSlot(MethodThisParameter); if (thisSlot < 0) { @@ -1268,6 +1272,7 @@ static MethodSymbol getTopLevelMethod(MethodSymbol method) } } +#nullable enable protected override int GetOrCreateSlot(Symbol symbol, int containingSlot = 0, bool forceSlotEvenIfEmpty = false) { @@ -1276,6 +1281,7 @@ protected override int GetOrCreateSlot(Symbol symbol, int containingSlot = 0, bo return base.GetOrCreateSlot(symbol, containingSlot, forceSlotEvenIfEmpty); } +#nullable restore private void VisitAndUnsplitAll(ImmutableArray nodes) where T : BoundNode { diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs index 8215db7fc46e5..3b907d8c476c0 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs @@ -129603,6 +129603,46 @@ public async Task Handle(Request request) ); } + + [Fact] + [WorkItem(44049, "https://github.com/dotnet/roslyn/issues/44049")] + public void MemberNotNull_InstanceMemberOnStaticMethod() + { + var source = +@"using System.Diagnostics.CodeAnalysis; + +class C +{ + public string? field; + + [MemberNotNull(""field"")] + public static void M() + { + } + + public void Test() + { + M(); + field.ToString(); + } +}"; + var comp = CreateCompilation( + new[] + { + source, MemberNotNullAttributeDefinition + }, + options: WithNonNullTypesTrue(), + targetFramework: TargetFramework.NetCoreApp30, + parseOptions: TestOptions.RegularPreview); + comp.VerifyDiagnostics( + // (5,20): warning CS0649: Field 'C.field' is never assigned to, and will always have its default value null + // public string? field; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "field").WithArguments("C.field", "null").WithLocation(5, 20), + // (15,9): warning CS8602: Dereference of a possibly null reference. + // field.ToString(); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "field").WithLocation(15, 9)); + } + [Fact, WorkItem(39417, "https://github.com/dotnet/roslyn/issues/39417")] public void CustomAwaitable_DetectSettingNullableToNonNullableType() {