Skip to content

Commit 00d759a

Browse files
authored
Nullness :: Bugfix for internal error when processing System.Nullable with nesting in C# (#17736)
1 parent c910057 commit 00d759a

File tree

3 files changed

+44
-1
lines changed

3 files changed

+44
-1
lines changed

docs/release-notes/.FSharp.Compiler.Service/9.0.100.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@
1818
* Fix IsUnionCaseTester throwing for non-methods/properties [#17301](https://github.com/dotnet/fsharp/pull/17634)
1919
* Consider `open type` used when the type is an enum and any of the enum cases is used unqualified. ([PR #17628](https://github.com/dotnet/fsharp/pull/17628))
2020
* Guard for possible StackOverflowException when typechecking non recursive modules and namespaces ([PR #17654](https://github.com/dotnet/fsharp/pull/17654))
21+
* Nullable - fix for processing System.Nullable types with nesting ([PR #17736](https://github.com/dotnet/fsharp/pull/17736))
2122
* Fixes for the optimization of simple mappings in array and list comprehensions. ([Issue #17708](https://github.com/dotnet/fsharp/issues/17708), [PR #17711](https://github.com/dotnet/fsharp/pull/17711))
2223

24+
2325
### Added
2426

2527
* Support for nullable reference types ([PR #15181](https://github.com/dotnet/fsharp/pull/15181))

src/Compiler/Checking/import.fs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,12 +273,18 @@ For value types, a value is passed even though it is always 0
273273

274274
member this.Advance() = {Data = this.Data; Idx = this.Idx + 1}
275275

276+
let inline isSystemNullable (tspec:ILTypeSpec) =
277+
match tspec.Name,tspec.Enclosing with
278+
| "Nullable`1",["System"] -> true
279+
| "System.Nullable`1",[] -> true
280+
| _ -> false
281+
276282
let inline evaluateFirstOrderNullnessAndAdvance (ilt:ILType) (flags:NullableFlags) =
277283
match ilt with
278284
| ILType.Value tspec when tspec.GenericArgs.IsEmpty -> KnownWithoutNull, flags
279285
// System.Nullable is special-cased in C# spec for nullness metadata.
280286
// You CAN assign 'null' to it, and when boxed, it CAN be boxed to 'null'.
281-
| ILType.Value tspec when tspec.Name = "Nullable`1" && tspec.Enclosing = ["System"] -> KnownWithoutNull, flags
287+
| ILType.Value tspec when isSystemNullable tspec -> KnownWithoutNull, flags
282288
| ILType.Value _ -> KnownWithoutNull, flags.Advance()
283289
| _ -> flags.GetNullness(), flags.Advance()
284290

tests/FSharp.Compiler.ComponentTests/Language/Nullness/NullableCsharpImportTests.fs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,4 +225,39 @@ let ``Consumption of nullable C# - no generics, just strings in methods and fiel
225225
Error 3261, Line 25, Col 85, Line 25, Col 97, "Nullness warning: The types 'string' and 'string | null' do not have equivalent nullability."
226226
Error 3261, Line 28, Col 99, Line 28, Col 111, "Nullness warning: The types 'string' and 'string | null' do not have equivalent nullability."
227227
Error 3261, Line 30, Col 97, Line 30, Col 109, "Nullness warning: The types 'string' and 'string | null' do not have equivalent nullability."]
228+
229+
230+
[<FactForNETCOREAPP>]
231+
let ``Regression 17701 - Nullable value type with nested generics`` () =
232+
let csharpLib =
233+
CSharp """
234+
using System;
235+
using System.Collections.Immutable;
236+
#nullable enable
237+
namespace Nullables;
238+
public class NullableClass {
239+
public static ImmutableArray<string?>? nullableImmArrayOfStrings;
240+
public static ImmutableArray<string>? nullableImmArrayOfNotNullStrings;
241+
}""" |> withName "csNullableLib"
242+
|> withCSharpLanguageVersionPreview
243+
244+
FSharp """module FSNullable
245+
open Nullables
246+
247+
let nullablestrNoParams = NullableClass.nullableImmArrayOfStrings
248+
let toOption = NullableClass.nullableImmArrayOfStrings |> Option.ofNullable
249+
let firstString = (toOption.Value |> Seq.head)
250+
let lengthOfIt = firstString.Length
251+
252+
let theOtherOne = NullableClass.nullableImmArrayOfNotNullStrings
253+
"""
254+
|> asLibrary
255+
|> withReferences [csharpLib]
256+
|> withStrictNullness
257+
|> withLangVersionPreview
258+
|> compile
259+
|> shouldFail
260+
|> withDiagnostics
261+
[Error 3261, Line 7, Col 18, Line 7, Col 36, "Nullness warning: The types 'string' and 'string | null' do not have compatible nullability."]
262+
228263

0 commit comments

Comments
 (0)