diff --git a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md
index dd63aa988bd..8a54e13855f 100644
--- a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md
+++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md
@@ -96,6 +96,7 @@
 * Debug: rework for expressions stepping ([PR #19894](https://github.com/dotnet/fsharp/pull/19894))
 * Debug: rework conditional erasure, fix stepping over literals ([PR #19897](https://github.com/dotnet/fsharp/pull/19897))
 * Debug: fix if and match condition sequence points ([PR #19932](https://github.com/dotnet/fsharp/pull/19932))
+* Support common types of `NotNullIfNotNullAttribute` usage. If a method parameter is marked with `NotNullIfNotNullAttribute`, the compiler will now honor this attribute and mark the return type as non-null. ([PR #19977](https://github.com/dotnet/fsharp/pull/19977))
 
 ### Changed
 
diff --git a/docs/release-notes/.Language/preview.md b/docs/release-notes/.Language/preview.md
index 90c1aa2faa6..cb9d639c163 100644
--- a/docs/release-notes/.Language/preview.md
+++ b/docs/release-notes/.Language/preview.md
@@ -3,6 +3,7 @@
 * Warn (FS3884) when a function or delegate value is used as an interpolated string argument, since it will be formatted via `ToString` rather than being applied. ([PR #19289](https://github.com/dotnet/fsharp/pull/19289))
 * Added `MethodOverloadsCache` language feature (preview) that caches overload resolution results for repeated method calls, significantly improving compilation performance. ([PR #19072](https://github.com/dotnet/fsharp/pull/19072))
 * Added `ErrorOnMissingSignatureAttribute` preview language feature: makes FS3888 (compiler-semantic attribute on the `.fs` but not on the `.fsi`) an error instead of a warning. ([Issue #19560](https://github.com/dotnet/fsharp/issues/19560), [PR #19880](https://github.com/dotnet/fsharp/pull/19880))
+* Support common types of `NotNullIfNotNullAttribute` usage. If a method parameter is marked with `NotNullIfNotNullAttribute`, the compiler will now honor this attribute and mark the return type as non-null. ([PR #19977](https://github.com/dotnet/fsharp/pull/19977))
 
 ### Fixed
 
diff --git a/src/Compiler/AbstractIL/il.fs b/src/Compiler/AbstractIL/il.fs
index 629a3d260bb..b0a900b4550 100644
--- a/src/Compiler/AbstractIL/il.fs
+++ b/src/Compiler/AbstractIL/il.fs
@@ -1257,6 +1257,7 @@ type WellKnownILAttributes =
     | RequiredMemberAttribute = (1u <<< 22)
     | NullableContextAttribute = (1u <<< 23)
     | AttributeUsageAttribute = (1u <<< 24)
+    | NotNullIfNotNullAttribute = (1u <<< 25)
     | NotComputed = (1u <<< 31)
 
 type internal ILAttributesStoredRepr =
diff --git a/src/Compiler/AbstractIL/il.fsi b/src/Compiler/AbstractIL/il.fsi
index dc22d5bc803..1f6296bf1be 100644
--- a/src/Compiler/AbstractIL/il.fsi
+++ b/src/Compiler/AbstractIL/il.fsi
@@ -907,6 +907,7 @@ type WellKnownILAttributes =
     | RequiredMemberAttribute = (1u <<< 22)
     | NullableContextAttribute = (1u <<< 23)
     | AttributeUsageAttribute = (1u <<< 24)
+    | NotNullIfNotNullAttribute = (1u <<< 25)
     | NotComputed = (1u <<< 31)
 
 /// Represents the efficiency-oriented storage of ILAttributes in another item.
diff --git a/src/Compiler/Checking/Expressions/CheckExpressions.fs b/src/Compiler/Checking/Expressions/CheckExpressions.fs
index 070ce6b3e8e..a0c84439716 100644
--- a/src/Compiler/Checking/Expressions/CheckExpressions.fs
+++ b/src/Compiler/Checking/Expressions/CheckExpressions.fs
@@ -3330,6 +3330,46 @@ let GetMethodArgs arg =
 
     unnamedCallerArgs, namedCallerArgs
 
+let NotNullIfNotNullParamNames g (minfo: MethInfo) =
+    match minfo with
+    | ILMeth(ilMethInfo = ilminfo) when ilminfo.RawMetadata.Return.CustomAttrsStored.HasWellKnownAttribute (g, WellKnownILAttributes.NotNullIfNotNullAttribute) ->
+        ilminfo.RawMetadata.Return.CustomAttrs.AsArray()
+        |> Array.toList
+        |> List.choose (fun attr ->
+            if classifyILAttrib attr &&& WellKnownILAttributes.NotNullIfNotNullAttribute <> WellKnownILAttributes.None then
+                match decodeILAttribData attr with
+                | [ ILAttribElem.String (Some paramName) ], _ -> Some paramName
+                | _ -> None
+            else
+                None)
+    | FSMeth(valRef = vref) ->
+        match vref.ValReprInfo with
+        | Some (ValReprInfo(result = retInfo)) when ArgReprInfoHasWellKnownAttribute g WellKnownValAttributes.NotNullIfNotNullAttribute retInfo ->
+            retInfo.Attribs.AsList()
+            |> List.choose (fun attrib ->
+                if classifyValAttrib g attrib &&& WellKnownValAttributes.NotNullIfNotNullAttribute <> WellKnownValAttributes.None then
+                    match attrib with
+                    | Attrib(unnamedArgs = [ AttribStringArg paramName ]) -> Some paramName
+                    | _ -> None
+                else
+                    None)
+        | _ -> []
+    | _ -> []
+
+// Resolve the caller argument bound to 'paramName' and return the type of its type-checked expression.
+let TryGetCallerArgType g (minfo: MethInfo) (callerArgs: CallerArgs<_>) paramName =
+    // First try to find a named argument with the given name
+    callerArgs.Named
+    |> List.tryPick (List.tryPick (fun (CallerNamedArg(id, arg)) -> if id.idText = paramName then Some arg else None))
+    |> Option.orElseWith (fun () ->
+        // If there is no matching named argument, find the argument in the same position as the parameter with the given name
+        minfo.GetParamNames()
+        |> Seq.concat
+        |> Seq.tryFindIndex (fun nm -> match nm with Some nm -> nm = paramName | _ -> false)
+        |> Option.bind (fun idx -> Seq.concat callerArgs.Unnamed |> Seq.tryItem idx)
+    )
+    |> Option.map (fun arg -> tyOfExpr g arg.Expr)
+
 //-------------------------------------------------------------------------
 // Helpers dealing with sequence expressions
 //-------------------------------------------------------------------------
@@ -10270,12 +10310,26 @@ and TcMethodApplication_UniqueOverloadInference
 
     let arityFilteredCandidates = candidateMethsAndProps
 
-    let makeOneCalledMeth (minfo, pinfoOpt, usesParamArrayConversion) =
+    let makeOneCalledMeth (minfo: MethInfo, pinfoOpt, usesParamArrayConversion) =
         let minst = FreshenMethInfo mItem minfo
         let callerTyArgs =
             match tyArgsOpt with
             | Some tyargs -> minfo.AdjustUserTypeInstForFSharpStyleIndexedExtensionMembers tyargs
             | None -> minst
+
+        // If the return value is [<NotNullIfNotNull>], give the return a fresh nullness inference variable here so that
+        // unique-overload inference does not prematurely commit the result to the declared (nullable) nullness. The real
+        // nullness is resolved post argument type-checking (see below), once the argument types are known.
+        let minfo =
+            if not minfo.IsConstructor && g.checkNullness && g.langVersion.SupportsFeature LanguageFeature.NotNullIfNotNull then
+                match NotNullIfNotNullParamNames g minfo with
+                | [ _ ] ->
+                    let retTy = minfo.GetFSharpReturnType(cenv.amap, mMethExpr, callerTyArgs)
+                    MethInfoWithModifiedReturnType(minfo, replaceNullnessOfTy (NewNullnessVar()) retTy)
+                | _ -> minfo
+            else
+                minfo
+    
         CalledMeth<SynExpr>(cenv.infoReader, Some(env.NameEnv), isCheckingAttributeCall, FreshenMethInfo, mMethExpr, ad, minfo, minst, callerTyArgs, pinfoOpt, callerObjArgTys, callerArgs, usesParamArrayConversion, true, objTyOpt, staticTyOpt)
 
     let preArgumentTypeCheckingCalledMethGroup =
@@ -10505,6 +10559,27 @@ and TcMethodApplication
                     match tyArgsOpt with
                     | Some tyargs -> minfo.AdjustUserTypeInstForFSharpStyleIndexedExtensionMembers tyargs
                     | None -> minst
+
+                let minfo =
+                    if not minfo.IsConstructor && g.checkNullness && g.langVersion.SupportsFeature LanguageFeature.NotNullIfNotNull then
+                        // 'minfo' may already carry a placeholder return nullness from unique-overload inference (phase 1);
+                        // strip it back to the base method before applying the real (argument-derived) nullness.
+                        let baseMinfo = match minfo with MethInfoWithModifiedReturnType(inner, _) -> inner | _ -> minfo
+                        match NotNullIfNotNullParamNames g baseMinfo with
+                        | [ paramName ] ->
+                            match TryGetCallerArgType g baseMinfo callerArgs paramName with
+                            | Some callerArgTy ->
+                                let retTy = baseMinfo.GetFSharpReturnType(cenv.amap, mMethExpr, callerTyArgs)
+                                let argNullness =
+                                    match GetTyparTyIfSupportsNull g callerArgTy with
+                                    | ValueSome _ -> g.knownWithNull
+                                    | ValueNone -> nullnessOfTy g callerArgTy
+                                MethInfoWithModifiedReturnType(baseMinfo, replaceNullnessOfTy argNullness retTy)
+                            | None -> baseMinfo
+                        | _ -> baseMinfo
+                    else
+                        minfo
+
                 CalledMeth<Expr>(cenv.infoReader, Some(env.NameEnv), isCheckingAttributeCall, FreshenMethInfo, mMethExpr, ad, minfo, minst, callerTyArgs, pinfoOpt, callerObjArgTys, callerArgs, usesParamArrayConversion, true, objTyOpt, staticTyOpt))
 
         // Commit unassociated constraints prior to member overload resolution where there is ambiguity
diff --git a/src/Compiler/Checking/MethodCalls.fs b/src/Compiler/Checking/MethodCalls.fs
index a9c394ee4e9..9fdf22a3a1a 100644
--- a/src/Compiler/Checking/MethodCalls.fs
+++ b/src/Compiler/Checking/MethodCalls.fs
@@ -1250,6 +1250,14 @@ let rec BuildMethodCall tcVal g amap isMutable m isProp minfo valUseFlags minst
             let expr = mkCoerceExpr (expr, retTy, m, exprTy)
             expr, retTy
 
+        | MethInfoWithModifiedReturnType((FSMeth(_, _, vref, _) as innerMeth), retTy) ->
+            // Build the inner call directly, without re-invoking TakeObjAddrForMethodCall.
+            let vExpr, vExprTy = tcVal vref valUseFlags (innerMeth.DeclaringTypeInst @ minst) m
+            let expr, exprTy = BuildFSharpMethodApp g m vref vExpr vExprTy allArgs
+
+            let expr = mkCoerceExpr (expr, retTy, m, exprTy)
+            expr, retTy
+
         | MethInfoWithModifiedReturnType _ ->
             failwith "MethInfoWithModifiedReturnType: unexpected inner method kind"
 
diff --git a/src/Compiler/Checking/NicePrint.fs b/src/Compiler/Checking/NicePrint.fs
index de8daffa7c5..6bbf4e09644 100644
--- a/src/Compiler/Checking/NicePrint.fs
+++ b/src/Compiler/Checking/NicePrint.fs
@@ -1723,7 +1723,7 @@ module InfoMemberPrinting =
 
         let layout,paramLayouts =
             match denv.showCsharpCodeAnalysisAttributes, minfo with
-            | true, ILMeth(_g,mi,_e) -> 
+            | true, (ILMeth(_, mi, _) | MethInfoWithModifiedReturnType(ILMeth(_, mi, _), _)) ->
                 let methodLayout = 
                     // Render Method attributes and [return:..] attributes on separate lines above (@@) the method definition
                     PrintTypes.layoutCsharpCodeAnalysisIlAttributes denv (minfo.GetCustomAttrs()) (squareAngleL >> (@@)) layout
diff --git a/src/Compiler/DependencyManager/AssemblyResolveHandler.fs b/src/Compiler/DependencyManager/AssemblyResolveHandler.fs
index 6daf749f87f..d59b65d835e 100644
--- a/src/Compiler/DependencyManager/AssemblyResolveHandler.fs
+++ b/src/Compiler/DependencyManager/AssemblyResolveHandler.fs
@@ -54,7 +54,7 @@ type AssemblyResolveHandlerCoreclr(assemblyProbingPaths: AssemblyResolutionProbe
 
             let assemblyPathOpt =
                 assemblyPaths
-                |> Seq.tryFind (fun path -> Path.GetFileNameWithoutExtension(path) = simpleName)
+                |> Seq.tryFind (fun path -> String.Equals(Path.GetFileNameWithoutExtension(path), simpleName))
 
             match assemblyPathOpt with
             | Some path -> loadAssembly path
@@ -84,7 +84,7 @@ type AssemblyResolveHandlerDeskTop(assemblyProbingPaths: AssemblyResolutionProbe
 
             let assemblyPathOpt =
                 assemblyPaths
-                |> Seq.tryFind (fun path -> Path.GetFileNameWithoutExtension(path) = simpleName)
+                |> Seq.tryFind (fun path -> String.Equals(Path.GetFileNameWithoutExtension(path), simpleName))
 
             match assemblyPathOpt with
             | Some path -> Assembly.LoadFrom path
diff --git a/src/Compiler/FSComp.txt b/src/Compiler/FSComp.txt
index dc27f32bae9..c35c5ca3dd6 100644
--- a/src/Compiler/FSComp.txt
+++ b/src/Compiler/FSComp.txt
@@ -1821,3 +1821,4 @@ featurePreprocessorElif,"#elif preprocessor directive"
 3888,implAttributeMissingFromSignature,"The attribute '%s' is present on '%s' in the implementation but not in the signature, which takes precedence for tooling and consumers. Add the attribute to the signature, to ensure the attribute is not ignored by the compiler."
 featureExceptionFieldSerializationSupport,"emit GetObjectData and field-restoring deserialization constructor for exception types"
 featureErrorOnMissingSignatureAttribute,"error (rather than warning) when an enforced compiler-semantic attribute is present in the .fs but missing from the .fsi"
+featureNotNullIfNotNull,"honor the 'NotNullIfNotNull' attribute on a method's return value"
diff --git a/src/Compiler/Facilities/LanguageFeatures.fs b/src/Compiler/Facilities/LanguageFeatures.fs
index da4ef690311..3312cb9a146 100644
--- a/src/Compiler/Facilities/LanguageFeatures.fs
+++ b/src/Compiler/Facilities/LanguageFeatures.fs
@@ -110,6 +110,7 @@ type LanguageFeature =
     | PreprocessorElif
     | ExceptionFieldSerializationSupport
     | ErrorOnMissingSignatureAttribute
+    | NotNullIfNotNull
 
 /// LanguageVersion management
 type LanguageVersion(versionText, ?disabledFeaturesArray: LanguageFeature array) =
@@ -254,6 +255,7 @@ type LanguageVersion(versionText, ?disabledFeaturesArray: LanguageFeature array)
                 LanguageFeature.WarnWhenFunctionValueUsedAsInterpolatedStringArg, languageVersion110
                 LanguageFeature.PreprocessorElif, languageVersion110
                 LanguageFeature.ExceptionFieldSerializationSupport, languageVersion110
+                LanguageFeature.NotNullIfNotNull, languageVersion110
 
                 // Difference between languageVersion110 and preview - 11.0 gets turned on automatically by picking a preview .NET 11 SDK
                 // previewVersion is only when "preview" is specified explicitly in project files  and users also need a preview SDK
@@ -459,6 +461,7 @@ type LanguageVersion(versionText, ?disabledFeaturesArray: LanguageFeature array)
         | LanguageFeature.PreprocessorElif -> FSComp.SR.featurePreprocessorElif ()
         | LanguageFeature.ExceptionFieldSerializationSupport -> FSComp.SR.featureExceptionFieldSerializationSupport ()
         | LanguageFeature.ErrorOnMissingSignatureAttribute -> FSComp.SR.featureErrorOnMissingSignatureAttribute ()
+        | LanguageFeature.NotNullIfNotNull -> FSComp.SR.featureNotNullIfNotNull ()
 
     /// Get a version string associated with the given feature.
     static member GetFeatureVersionString feature =
diff --git a/src/Compiler/Facilities/LanguageFeatures.fsi b/src/Compiler/Facilities/LanguageFeatures.fsi
index 5ba352191af..1be8275de35 100644
--- a/src/Compiler/Facilities/LanguageFeatures.fsi
+++ b/src/Compiler/Facilities/LanguageFeatures.fsi
@@ -101,6 +101,7 @@ type LanguageFeature =
     | PreprocessorElif
     | ExceptionFieldSerializationSupport
     | ErrorOnMissingSignatureAttribute
+    | NotNullIfNotNull
 
 /// LanguageVersion management
 type LanguageVersion =
diff --git a/src/Compiler/TypedTree/TypedTreeOps.Attributes.fs b/src/Compiler/TypedTree/TypedTreeOps.Attributes.fs
index d011c2d231f..21e3bda323c 100644
--- a/src/Compiler/TypedTree/TypedTreeOps.Attributes.fs
+++ b/src/Compiler/TypedTree/TypedTreeOps.Attributes.fs
@@ -183,6 +183,7 @@ module internal ILExtensions =
                     WellKnownILAttributes.SetsRequiredMembersAttribute
                 | "System.ObsoleteAttribute" -> WellKnownILAttributes.ObsoleteAttribute
                 | "System.Diagnostics.CodeAnalysis.ExperimentalAttribute" -> WellKnownILAttributes.ExperimentalAttribute
+                | "System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute" -> WellKnownILAttributes.NotNullIfNotNullAttribute
                 | "System.AttributeUsageAttribute" -> WellKnownILAttributes.AttributeUsageAttribute
                 | _ -> WellKnownILAttributes.None
 
@@ -592,6 +593,11 @@ module internal AttributeHelpers =
                 | "ConditionalAttribute" -> WellKnownValAttributes.ConditionalAttribute
                 | _ -> WellKnownValAttributes.None
 
+            | [| "System"; "Diagnostics"; "CodeAnalysis"; name |] ->
+                match name with
+                | "NotNullIfNotNullAttribute" -> WellKnownValAttributes.NotNullIfNotNullAttribute
+                | _ -> WellKnownValAttributes.None
+
             | [| "System"; name |] ->
                 match name with
                 | "ThreadStaticAttribute" -> WellKnownValAttributes.ThreadStaticAttribute
diff --git a/src/Compiler/TypedTree/WellKnownAttribs.fs b/src/Compiler/TypedTree/WellKnownAttribs.fs
index fac3508a56e..748f525b89c 100644
--- a/src/Compiler/TypedTree/WellKnownAttribs.fs
+++ b/src/Compiler/TypedTree/WellKnownAttribs.fs
@@ -116,6 +116,7 @@ type internal WellKnownValAttributes =
     | NoEagerConstraintApplicationAttribute = (1uL <<< 38)
     | ValueAsStaticPropertyAttribute = (1uL <<< 39)
     | TailCallAttribute = (1uL <<< 40)
+    | NotNullIfNotNullAttribute = (1uL <<< 41)
     | NotComputed = (1uL <<< 63)
 
 module internal Flags =
diff --git a/src/Compiler/TypedTree/WellKnownAttribs.fsi b/src/Compiler/TypedTree/WellKnownAttribs.fsi
index da7a7b67f33..4939f94aaa8 100644
--- a/src/Compiler/TypedTree/WellKnownAttribs.fsi
+++ b/src/Compiler/TypedTree/WellKnownAttribs.fsi
@@ -114,6 +114,7 @@ type internal WellKnownValAttributes =
     | NoEagerConstraintApplicationAttribute = (1uL <<< 38)
     | ValueAsStaticPropertyAttribute = (1uL <<< 39)
     | TailCallAttribute = (1uL <<< 40)
+    | NotNullIfNotNullAttribute = (1uL <<< 41)
     | NotComputed = (1uL <<< 63)
 
 module internal Flags =
diff --git a/src/Compiler/Utilities/range.fs b/src/Compiler/Utilities/range.fs
index 3a22199c32f..2a05fa74c75 100755
--- a/src/Compiler/Utilities/range.fs
+++ b/src/Compiler/Utilities/range.fs
@@ -334,7 +334,7 @@ type Range(code1: int64, code2: int64) =
     member m.FileName = fileOfFileIndex m.FileIndex
 
     member internal m.ShortFileName =
-        Path.GetFileName(fileOfFileIndex m.FileIndex) |> nonNull
+        Path.GetFileName(fileOfFileIndex m.FileIndex) |> Unchecked.nonNull
 
     member m.ApplyLineDirectives() =
         match LineDirectives.store.TryFind m.FileIndex with
diff --git a/src/Compiler/xlf/FSComp.txt.cs.xlf b/src/Compiler/xlf/FSComp.txt.cs.xlf
index 84e5e3cc50c..32eb6598139 100644
--- a/src/Compiler/xlf/FSComp.txt.cs.xlf
+++ b/src/Compiler/xlf/FSComp.txt.cs.xlf
@@ -527,6 +527,11 @@
         <target state="translated">neproměnné vzory napravo od vzorů typu „jako“</target>
         <note />
       </trans-unit>
+      <trans-unit id="featureNotNullIfNotNull">
+        <source>honor the 'NotNullIfNotNull' attribute on a method's return value</source>
+        <target state="new">honor the 'NotNullIfNotNull' attribute on a method's return value</target>
+        <note />
+      </trans-unit>
       <trans-unit id="featureNullableOptionalInterop">
         <source>nullable optional interop</source>
         <target state="translated">nepovinný zprostředkovatel komunikace s možnou hodnotou null</target>
diff --git a/src/Compiler/xlf/FSComp.txt.de.xlf b/src/Compiler/xlf/FSComp.txt.de.xlf
index d6edecb4def..35dac025ce1 100644
--- a/src/Compiler/xlf/FSComp.txt.de.xlf
+++ b/src/Compiler/xlf/FSComp.txt.de.xlf
@@ -527,6 +527,11 @@
         <target state="translated">Nicht-Variablenmuster rechts neben as-Mustern</target>
         <note />
       </trans-unit>
+      <trans-unit id="featureNotNullIfNotNull">
+        <source>honor the 'NotNullIfNotNull' attribute on a method's return value</source>
+        <target state="new">honor the 'NotNullIfNotNull' attribute on a method's return value</target>
+        <note />
+      </trans-unit>
       <trans-unit id="featureNullableOptionalInterop">
         <source>nullable optional interop</source>
         <target state="translated">Interop, NULL-Werte zulassend, optional</target>
diff --git a/src/Compiler/xlf/FSComp.txt.es.xlf b/src/Compiler/xlf/FSComp.txt.es.xlf
index 46573e801f1..281f8dd69bc 100644
--- a/src/Compiler/xlf/FSComp.txt.es.xlf
+++ b/src/Compiler/xlf/FSComp.txt.es.xlf
@@ -527,6 +527,11 @@
         <target state="translated">patrones no variables a la derecha de los patrones "as"</target>
         <note />
       </trans-unit>
+      <trans-unit id="featureNotNullIfNotNull">
+        <source>honor the 'NotNullIfNotNull' attribute on a method's return value</source>
+        <target state="new">honor the 'NotNullIfNotNull' attribute on a method's return value</target>
+        <note />
+      </trans-unit>
       <trans-unit id="featureNullableOptionalInterop">
         <source>nullable optional interop</source>
         <target state="translated">interoperabilidad opcional que admite valores NULL</target>
diff --git a/src/Compiler/xlf/FSComp.txt.fr.xlf b/src/Compiler/xlf/FSComp.txt.fr.xlf
index 1acfc469b5b..0cd33a35441 100644
--- a/src/Compiler/xlf/FSComp.txt.fr.xlf
+++ b/src/Compiler/xlf/FSComp.txt.fr.xlf
@@ -527,6 +527,11 @@
         <target state="translated">modèles non variables à droite de modèles « as »</target>
         <note />
       </trans-unit>
+      <trans-unit id="featureNotNullIfNotNull">
+        <source>honor the 'NotNullIfNotNull' attribute on a method's return value</source>
+        <target state="new">honor the 'NotNullIfNotNull' attribute on a method's return value</target>
+        <note />
+      </trans-unit>
       <trans-unit id="featureNullableOptionalInterop">
         <source>nullable optional interop</source>
         <target state="translated">interopérabilité facultative pouvant accepter une valeur null</target>
diff --git a/src/Compiler/xlf/FSComp.txt.it.xlf b/src/Compiler/xlf/FSComp.txt.it.xlf
index deaca46fad0..f27b686b2e0 100644
--- a/src/Compiler/xlf/FSComp.txt.it.xlf
+++ b/src/Compiler/xlf/FSComp.txt.it.xlf
@@ -527,6 +527,11 @@
         <target state="translated">modelli non variabili a destra dei modelli 'as'</target>
         <note />
       </trans-unit>
+      <trans-unit id="featureNotNullIfNotNull">
+        <source>honor the 'NotNullIfNotNull' attribute on a method's return value</source>
+        <target state="new">honor the 'NotNullIfNotNull' attribute on a method's return value</target>
+        <note />
+      </trans-unit>
       <trans-unit id="featureNullableOptionalInterop">
         <source>nullable optional interop</source>
         <target state="translated">Interop facoltativo nullable</target>
diff --git a/src/Compiler/xlf/FSComp.txt.ja.xlf b/src/Compiler/xlf/FSComp.txt.ja.xlf
index 10029fab134..7977bede1f8 100644
--- a/src/Compiler/xlf/FSComp.txt.ja.xlf
+++ b/src/Compiler/xlf/FSComp.txt.ja.xlf
@@ -527,6 +527,11 @@
         <target state="translated">'as' パターンの右側の非変数パターン</target>
         <note />
       </trans-unit>
+      <trans-unit id="featureNotNullIfNotNull">
+        <source>honor the 'NotNullIfNotNull' attribute on a method's return value</source>
+        <target state="new">honor the 'NotNullIfNotNull' attribute on a method's return value</target>
+        <note />
+      </trans-unit>
       <trans-unit id="featureNullableOptionalInterop">
         <source>nullable optional interop</source>
         <target state="translated">Null 許容のオプションの相互運用</target>
diff --git a/src/Compiler/xlf/FSComp.txt.ko.xlf b/src/Compiler/xlf/FSComp.txt.ko.xlf
index 1d7a19af957..cfe29218dae 100644
--- a/src/Compiler/xlf/FSComp.txt.ko.xlf
+++ b/src/Compiler/xlf/FSComp.txt.ko.xlf
@@ -527,6 +527,11 @@
         <target state="translated">'as' 패턴의 오른쪽에 있는 변수가 아닌 패턴</target>
         <note />
       </trans-unit>
+      <trans-unit id="featureNotNullIfNotNull">
+        <source>honor the 'NotNullIfNotNull' attribute on a method's return value</source>
+        <target state="new">honor the 'NotNullIfNotNull' attribute on a method's return value</target>
+        <note />
+      </trans-unit>
       <trans-unit id="featureNullableOptionalInterop">
         <source>nullable optional interop</source>
         <target state="translated">nullable 선택적 interop</target>
diff --git a/src/Compiler/xlf/FSComp.txt.pl.xlf b/src/Compiler/xlf/FSComp.txt.pl.xlf
index 170e6e37718..e28c23a1c59 100644
--- a/src/Compiler/xlf/FSComp.txt.pl.xlf
+++ b/src/Compiler/xlf/FSComp.txt.pl.xlf
@@ -527,6 +527,11 @@
         <target state="translated">stałe wzorce po prawej stronie wzorców typu „as”</target>
         <note />
       </trans-unit>
+      <trans-unit id="featureNotNullIfNotNull">
+        <source>honor the 'NotNullIfNotNull' attribute on a method's return value</source>
+        <target state="new">honor the 'NotNullIfNotNull' attribute on a method's return value</target>
+        <note />
+      </trans-unit>
       <trans-unit id="featureNullableOptionalInterop">
         <source>nullable optional interop</source>
         <target state="translated">opcjonalna międzyoperacyjność dopuszczająca wartość null</target>
diff --git a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf
index 87ef255a7e8..67cf82ad478 100644
--- a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf
+++ b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf
@@ -527,6 +527,11 @@
         <target state="translated">padrões não-variáveis à direita dos padrões 'as'.</target>
         <note />
       </trans-unit>
+      <trans-unit id="featureNotNullIfNotNull">
+        <source>honor the 'NotNullIfNotNull' attribute on a method's return value</source>
+        <target state="new">honor the 'NotNullIfNotNull' attribute on a method's return value</target>
+        <note />
+      </trans-unit>
       <trans-unit id="featureNullableOptionalInterop">
         <source>nullable optional interop</source>
         <target state="translated">interoperabilidade opcional anulável</target>
diff --git a/src/Compiler/xlf/FSComp.txt.ru.xlf b/src/Compiler/xlf/FSComp.txt.ru.xlf
index 57f29e98517..3bd062a0e57 100644
--- a/src/Compiler/xlf/FSComp.txt.ru.xlf
+++ b/src/Compiler/xlf/FSComp.txt.ru.xlf
@@ -527,6 +527,11 @@
         <target state="translated">шаблоны без переменных справа от шаблонов "as"</target>
         <note />
       </trans-unit>
+      <trans-unit id="featureNotNullIfNotNull">
+        <source>honor the 'NotNullIfNotNull' attribute on a method's return value</source>
+        <target state="new">honor the 'NotNullIfNotNull' attribute on a method's return value</target>
+        <note />
+      </trans-unit>
       <trans-unit id="featureNullableOptionalInterop">
         <source>nullable optional interop</source>
         <target state="translated">необязательное взаимодействие, допускающее значение NULL</target>
diff --git a/src/Compiler/xlf/FSComp.txt.tr.xlf b/src/Compiler/xlf/FSComp.txt.tr.xlf
index 08753e47a27..cee8392e86f 100644
--- a/src/Compiler/xlf/FSComp.txt.tr.xlf
+++ b/src/Compiler/xlf/FSComp.txt.tr.xlf
@@ -527,6 +527,11 @@
         <target state="translated">'as' desenlerinin sağındaki değişken olmayan desenler</target>
         <note />
       </trans-unit>
+      <trans-unit id="featureNotNullIfNotNull">
+        <source>honor the 'NotNullIfNotNull' attribute on a method's return value</source>
+        <target state="new">honor the 'NotNullIfNotNull' attribute on a method's return value</target>
+        <note />
+      </trans-unit>
       <trans-unit id="featureNullableOptionalInterop">
         <source>nullable optional interop</source>
         <target state="translated">null atanabilir isteğe bağlı birlikte çalışma</target>
diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf
index e117ab0ec5d..f14491cfce7 100644
--- a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf
+++ b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf
@@ -527,6 +527,11 @@
         <target state="translated">"as" 模式右侧的非变量模式</target>
         <note />
       </trans-unit>
+      <trans-unit id="featureNotNullIfNotNull">
+        <source>honor the 'NotNullIfNotNull' attribute on a method's return value</source>
+        <target state="new">honor the 'NotNullIfNotNull' attribute on a method's return value</target>
+        <note />
+      </trans-unit>
       <trans-unit id="featureNullableOptionalInterop">
         <source>nullable optional interop</source>
         <target state="translated">可以为 null 的可选互操作</target>
diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf
index 31c5596a098..dcc74bd974c 100644
--- a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf
+++ b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf
@@ -527,6 +527,11 @@
         <target state="translated">'as' 模式右邊的非變數模式</target>
         <note />
       </trans-unit>
+      <trans-unit id="featureNotNullIfNotNull">
+        <source>honor the 'NotNullIfNotNull' attribute on a method's return value</source>
+        <target state="new">honor the 'NotNullIfNotNull' attribute on a method's return value</target>
+        <note />
+      </trans-unit>
       <trans-unit id="featureNullableOptionalInterop">
         <source>nullable optional interop</source>
         <target state="translated">可為 Null 的選擇性 Interop</target>
diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
index 3fc031a525f..f2c74fefd3d 100644
--- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
+++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
@@ -372,6 +372,7 @@
     <Compile Include="Language\BooleanReturningAndReturnTypeDirectedPartialActivePatternTests.fs" />
     <Compile Include="Language\Nullness\NullableLibraryConstructsTests.fs" />
     <Compile Include="Language\Nullness\NullableCsharpImportTests.fs" />
+    <Compile Include="Language\Nullness\NotNullIfNotNullTests.fs" />
     <Compile Include="Language\Nullness\NullableRegressionTests.fs" />
     <Compile Include="Language\Nullness\NullableReferenceTypesTests.fs" />
     <Compile Include="Language\Nullness\EventNullnessTests.fs" />
diff --git a/tests/FSharp.Compiler.ComponentTests/Language/Nullness/NotNullIfNotNullTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/Nullness/NotNullIfNotNullTests.fs
new file mode 100644
index 00000000000..b0ed9b6308d
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/Language/Nullness/NotNullIfNotNullTests.fs
@@ -0,0 +1,400 @@
+module Language.NotNullIfNotNull
+
+open FSharp.Test
+open FSharp.Test.Compiler
+
+let withStrictNullness cu =
+    cu
+    |> withLangVersionPreview
+    |> withCheckNulls
+    |> withWarnOn 3261
+    |> withOptions ["--warnaserror+"]
+
+let typeCheckWithStrictNullness cu =
+    cu
+    |> withStrictNullness
+    |> typecheck
+
+let csNotNullLib =
+    CSharp """
+#nullable enable
+using System.Diagnostics.CodeAnalysis;
+namespace NotNullLib {
+    public class C {
+        [return: NotNullIfNotNull("input")]
+        public static string? Echo(string? input) => input;
+
+        // The result is non-null when the SECOND parameter is non-null.
+        [return: NotNullIfNotNull("second")]
+        public static string? DependsOnSecond(string? first, string? second) => second;
+    }
+
+    public static class Extensions {
+        // Degenerate case: the return depends on the 'this' parameter of a C#-style extension method.
+        // When called instance-style the receiver is an object argument, not an unnamed caller argument.
+        [return: NotNullIfNotNull("self")]
+        public static string? PreferSelf(this string? self, string? other) => self ?? other;
+    }
+
+    public static class Variadic {
+        // The result depends on an optional parameter ('b') that is not in the first position.
+        [return: NotNullIfNotNull("b")]
+        public static string? PickB(string? a = null, string? b = null) => b ?? a;
+
+        // The result depends on the first parameter, which precedes a params array.
+        [return: NotNullIfNotNull("first")]
+        public static string? JoinRest(string? first, params string?[] rest) => first;
+    }
+}""" |> withName "csNotNullLib"
+
+let private nullableExpected = "was expected but this expression is nullable"
+
+[<FactForNETCOREAPP>]
+let ``BCL Path.GetExtension - non-null input yields non-null result`` () =
+    FSharp """module MyLibrary
+open System.IO
+
+let nonNull : string = "file.txt"
+let ext : string = Path.GetExtension(nonNull)
+"""
+    |> asLibrary
+    |> typeCheckWithStrictNullness
+    |> shouldSucceed
+
+[<FactForNETCOREAPP>]
+let ``BCL Path.GetExtension - nullable input yields nullable result`` () =
+    FSharp """module MyLibrary
+open System.IO
+
+let maybeNull : string | null = "file.txt"
+let ext : string = Path.GetExtension(maybeNull)
+"""
+    |> asLibrary
+    |> typeCheckWithStrictNullness
+    |> shouldFail
+    |> withDiagnosticMessageMatches nullableExpected
+
+[<FactForNETCOREAPP>]
+let ``Multiple NotNullIfNotNull attributes are not supported - Delegate.Combine stays nullable`` () =
+    // Delegate.Combine carries two [return: NotNullIfNotNull] attributes. We cannot currently represent nullness linking
+    // to multiple types (logical OR), so the declared nullable return type is kept even though an argument is non-null.
+    FSharp """module MyLibrary
+open System
+
+let d1 : Delegate = Action(fun () -> ()) :> Delegate
+let dMaybe : Delegate | null = null
+
+let combined : Delegate = Delegate.Combine(d1, dMaybe)
+"""
+    |> asLibrary
+    |> typeCheckWithStrictNullness
+    |> shouldFail
+    |> withDiagnosticMessageMatches nullableExpected
+
+[<FactForNETCOREAPP>]
+let ``Csharp NotNullIfNotNull - non-null propagation works positionally`` () =
+    FSharp """module MyLibrary
+open NotNullLib
+
+let notNull : string = "x"
+let maybeNull : string | null = "y"
+
+// Single referenced parameter, passed positionally
+let r1 : string = C.Echo(notNull)
+
+// Referenced parameter is the second one; nullable first, non-null second -> non-null.
+// Arguments are positional (no named arguments), so this proves the parameter is identified by name.
+let r2 : string = C.DependsOnSecond(maybeNull, notNull)
+"""
+    |> asLibrary
+    |> withReferences [csNotNullLib]
+    |> withStrictNullness
+    |> compile
+    |> shouldSucceed
+
+[<FactForNETCOREAPP>]
+let ``Csharp NotNullIfNotNull - non-null propagation works with named arguments`` () =
+    FSharp """module MyLibrary
+open NotNullLib
+
+let notNull : string = "x"
+let maybeNull : string | null = "y"
+
+let r : string = C.DependsOnSecond(second = notNull, first = maybeNull)
+"""
+    |> asLibrary
+    |> withReferences [csNotNullLib]
+    |> withStrictNullness
+    |> compile
+    |> shouldSucceed
+
+[<FactForNETCOREAPP>]
+let ``Csharp NotNullIfNotNull - Echo stays nullable for nullable input`` () =
+    FSharp """module MyLibrary
+open NotNullLib
+
+let maybeNull : string | null = "y"
+let r : string = C.Echo(maybeNull)
+"""
+    |> asLibrary
+    |> withReferences [csNotNullLib]
+    |> withStrictNullness
+    |> compile
+    |> shouldFail
+    |> withDiagnosticMessageMatches nullableExpected
+
+[<FactForNETCOREAPP>]
+let ``Csharp NotNullIfNotNull - depends on second parameter, not the first`` () =
+    FSharp """module MyLibrary
+open NotNullLib
+
+let notNull : string = "x"
+let maybeNull : string | null = "y"
+
+// Non-null first but nullable referenced (second) parameter -> result stays nullable
+let r : string = C.DependsOnSecond(notNull, maybeNull)
+"""
+    |> asLibrary
+    |> withReferences [csNotNullLib]
+    |> withStrictNullness
+    |> compile
+    |> shouldFail
+    |> withDiagnosticMessageMatches nullableExpected
+
+[<FactForNETCOREAPP>]
+let ``Csharp NotNullIfNotNull - extension this-parameter must be identified, not the explicit argument`` () =
+    FSharp """module MyLibrary
+open NotNullLib
+
+let notNull : string = "x"
+let maybeNull : string | null = "y"
+
+// Result depends on 'self' (the receiver), which is nullable -> result must stay nullable and warn.
+let r : string = maybeNull.PreferSelf(notNull)
+"""
+    |> asLibrary
+    |> withReferences [csNotNullLib]
+    |> withStrictNullness
+    |> compile
+    |> shouldFail
+    |> withDiagnosticMessageMatches nullableExpected
+
+[<FactForNETCOREAPP>]
+let ``Csharp NotNullIfNotNull - optional parameter referenced positionally`` () =
+    FSharp """module MyLibrary
+open NotNullLib
+
+let notNull : string = "x"
+let maybeNull : string | null = "y"
+
+// 'b' is the referenced (second, optional) parameter, passed positionally and non-null -> result non-null.
+let r : string = Variadic.PickB(maybeNull, notNull)
+"""
+    |> asLibrary
+    |> withReferences [csNotNullLib]
+    |> withStrictNullness
+    |> compile
+    |> shouldSucceed
+
+[<FactForNETCOREAPP>]
+let ``Csharp NotNullIfNotNull - optional parameter referenced by name`` () =
+    FSharp """module MyLibrary
+open NotNullLib
+
+let notNull : string = "x"
+
+// Only the referenced optional parameter is supplied, by name and non-null -> result non-null.
+let r : string = Variadic.PickB(b = notNull)
+"""
+    |> asLibrary
+    |> withReferences [csNotNullLib]
+    |> withStrictNullness
+    |> compile
+    |> shouldSucceed
+
+[<FactForNETCOREAPP>]
+let ``Csharp NotNullIfNotNull - optional parameter omitted stays nullable`` () =
+    FSharp """module MyLibrary
+open NotNullLib
+
+let notNull : string = "x"
+
+// The referenced optional parameter 'b' is omitted (defaults to null) -> result stays nullable.
+let r : string = Variadic.PickB(notNull)
+"""
+    |> asLibrary
+    |> withReferences [csNotNullLib]
+    |> withStrictNullness
+    |> compile
+    |> shouldFail
+    |> withDiagnosticMessageMatches nullableExpected
+
+[<FactForNETCOREAPP>]
+let ``Csharp NotNullIfNotNull - parameter before params array, non-null propagation`` () =
+    FSharp """module MyLibrary
+open NotNullLib
+
+let notNull : string = "x"
+let maybeNull : string | null = "y"
+
+// Referenced parameter 'first' precedes the params array; non-null first -> result non-null.
+let r : string = Variadic.JoinRest(notNull, maybeNull, maybeNull)
+"""
+    |> asLibrary
+    |> withReferences [csNotNullLib]
+    |> withStrictNullness
+    |> compile
+    |> shouldSucceed
+
+[<FactForNETCOREAPP>]
+let ``Csharp NotNullIfNotNull - parameter before params array, stays nullable`` () =
+    FSharp """module MyLibrary
+open NotNullLib
+
+let notNull : string = "x"
+let maybeNull : string | null = "y"
+
+// Referenced parameter 'first' is nullable -> result stays nullable regardless of params args.
+let r : string = Variadic.JoinRest(maybeNull, notNull, notNull)
+"""
+    |> asLibrary
+    |> withReferences [csNotNullLib]
+    |> withStrictNullness
+    |> compile
+    |> shouldFail
+    |> withDiagnosticMessageMatches nullableExpected
+
+[<FactForNETCOREAPP>]
+let ``Csharp NotNullIfNotNull - unannotated parameter with non-null return annotation fails`` () =
+    FSharp """module MyLibrary
+open NotNullLib
+
+let f x : string = C.Echo(x)
+let _ : string = f null
+"""
+    |> asLibrary
+    |> withReferences [csNotNullLib]
+    |> withStrictNullness
+    |> compile
+    |> shouldFail
+    |> withDiagnosticMessageMatches "Nullness warning: The type 'string' does not support 'null'."
+
+[<FactForNETCOREAPP>]
+let ``Local F# method with NotNullIfNotNull - non-null propagation`` () =
+    FSharp """module MyLibrary
+open System.Diagnostics.CodeAnalysis
+
+type C =
+    [<return: NotNullIfNotNull("x")>]
+    static member Echo(x: string | null) : string | null = x
+
+let notNull : string = "a"
+let ok : string = C.Echo(notNull)
+"""
+    |> asLibrary
+    |> typeCheckWithStrictNullness
+    |> shouldSucceed
+
+[<FactForNETCOREAPP>]
+let ``Local F# method with NotNullIfNotNull - stays nullable for nullable input`` () =
+    FSharp """module MyLibrary
+open System.Diagnostics.CodeAnalysis
+
+type C =
+    [<return: NotNullIfNotNull("x")>]
+    static member Echo(x: string | null) : string | null = x
+
+let maybeNull : string | null = "a"
+let bad : string = C.Echo(maybeNull)
+"""
+    |> asLibrary
+    |> typeCheckWithStrictNullness
+    |> shouldFail
+    |> withDiagnosticMessageMatches nullableExpected
+
+[<FactForNETCOREAPP>]
+let ``Referenced F# method with NotNullIfNotNull - non-null propagation`` () =
+    let fsharpLib =
+        FSharp """module NotNullFSharpLib
+open System.Diagnostics.CodeAnalysis
+
+type C =
+    [<return: NotNullIfNotNull("x")>]
+    static member Echo(x: string | null) : string | null = x
+"""
+        |> withCheckNulls
+        |> withName "NotNullFSharpLib"
+
+    FSharp """module MyLibrary
+open NotNullFSharpLib
+
+let notNull : string = "a"
+let ok : string = C.Echo(notNull)
+"""
+    |> asLibrary
+    |> withReferences [fsharpLib]
+    |> withStrictNullness
+    |> compile
+    |> shouldSucceed
+
+[<FactForNETCOREAPP>]
+let ``Referenced F# method with NotNullIfNotNull - stays nullable for nullable input`` () =
+    let fsharpLib =
+        FSharp """module NotNullFSharpLib
+open System.Diagnostics.CodeAnalysis
+
+type C =
+    [<return: NotNullIfNotNull("x")>]
+    static member Echo(x: string | null) : string | null = x
+"""
+        |> withCheckNulls
+        |> withName "NotNullFSharpLib"
+
+    FSharp """module MyLibrary
+open NotNullFSharpLib
+
+let maybeNull : string | null = "a"
+let bad : string = C.Echo(maybeNull)
+"""
+    |> asLibrary
+    |> withReferences [fsharpLib]
+    |> withStrictNullness
+    |> compile
+    |> shouldFail
+    |> withDiagnosticMessageMatches nullableExpected
+
+[<FactForNETCOREAPP>]
+let ``BCL Path.GetExtension - null literal input yields nullable result`` () =
+    FSharp """module MyLibrary
+open System.IO
+
+let ext : string = Path.GetExtension(null)
+"""
+    |> asLibrary
+    |> typeCheckWithStrictNullness
+    |> shouldFail
+    |> withDiagnosticMessageMatches nullableExpected
+
+[<FactForNETCOREAPP>]
+let ``BCL Path.GetExtension - null-bound variable input yields nullable result`` () =
+    FSharp """module MyLibrary
+open System.IO
+
+let maybeNull = null
+let ext : string = Path.GetExtension(maybeNull)
+"""
+    |> asLibrary
+    |> typeCheckWithStrictNullness
+    |> shouldFail
+    |> withDiagnosticMessageMatches nullableExpected
+
+[<FactForNETCOREAPP>]
+let ``BCL Path.GetExtension - explicit non-null parameter annotation yields non-null result`` () =
+    FSharp """module MyLibrary
+open System.IO
+
+let f (x: string) : string = Path.GetExtension x
+"""
+    |> asLibrary
+    |> typeCheckWithStrictNullness
+    |> shouldSucceed
\ No newline at end of file
diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.bsl b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.bsl
index 4034ba8064d..8067be778fc 100644
--- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.bsl
+++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.bsl
@@ -1833,6 +1833,7 @@ FSharp.Compiler.AbstractIL.IL+WellKnownILAttributes: WellKnownILAttributes IsUnm
 FSharp.Compiler.AbstractIL.IL+WellKnownILAttributes: WellKnownILAttributes NoEagerConstraintApplicationAttribute
 FSharp.Compiler.AbstractIL.IL+WellKnownILAttributes: WellKnownILAttributes None
 FSharp.Compiler.AbstractIL.IL+WellKnownILAttributes: WellKnownILAttributes NotComputed
+FSharp.Compiler.AbstractIL.IL+WellKnownILAttributes: WellKnownILAttributes NotNullIfNotNullAttribute
 FSharp.Compiler.AbstractIL.IL+WellKnownILAttributes: WellKnownILAttributes NullableAttribute
 FSharp.Compiler.AbstractIL.IL+WellKnownILAttributes: WellKnownILAttributes NullableContextAttribute
 FSharp.Compiler.AbstractIL.IL+WellKnownILAttributes: WellKnownILAttributes ObsoleteAttribute
