Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Designing Nullable Reference Types in F#


Published on

Together with C#, F# will be incorporating nullability as a concept for .NET reference types. From the F# perspective, this fits with the default non-nullness of other F# types. But compatibility with existing code makes designing this a wild ride!

Published in: Software
  • Be the first to comment

Designing Nullable Reference Types in F#

  1. 1. Designing nullable reference types in F# PHILLIP CARTER - @_CARTERMP NDC LONDON – JANUARY 2019
  2. 2. Overview Contextualizing nullability Design overview Metadata representation Nullability assumptions Adjusting semantics of existing F# code Why do this feature?
  3. 3. Contextualizing nullability WHAT’S ALL THE FUSS ABOUT?
  4. 4. Null itself is perfectly valid It really is! You need to represent ”nothing” in a programming language null accomplishes the task of representing “nothing”
  5. 5. Implicit null is the problem Why no warning?
  6. 6. Mitigations: Options
  7. 7. Mitigations: explicit mutability
  8. 8. Mitigations: non-null type declarations
  9. 9. Problems: AllowNullLiteral attribute I just needed nullability here I got nullability everywhere instead
  10. 10. Problems: CLIMutable Can be made null in an application’s lifetime!
  11. 11. Problems: General .NET interop Null? Null?
  13. 13. Main goals Distinguish between nullable and non-nullable reference types in the F# type system Make nullable reference types less desirable to use than non-nullable reference types Offer helper functionality and patterns for dealing with nulls Offer compiler analysis for unsafe access of nullable reference types
  14. 14. Syntax and basic examples
  15. 15. More syntax and basic examples
  16. 16. Helper functions and patterns
  17. 17. Generic constraints ‘T when ‘T: null ‘T when ‘T: struct ‘T when ‘T: not struct ‘T when ‘T: not null New! Semantics: • Error if the constraint is instantiated with an F# type that has null as a proper value • Warning if constraint is instantiated with a nullable reference type
  18. 18. Pattern matching (majority case) NonNull pattern can be used anywhere, not just at the end ‘null’ pattern MUST be the first for this ‘s’ to be non-null, as per existing rules
  19. 19. Pattern matching (column-based) s1 and s2 are still nullable! Typechecking proceeds before column analysis May need to use NonNull patterns to handle this
  20. 20. F# type relations with nullability Type equivalence (x = y; y <> z) ◦ Nullness ignored, but warning given on mismatch Type subsumption (B a subtype of A) ◦ Nullness ignored, but warning given on mismatch Method overload resolution ◦ Nullness ignored, but warning given on mismatches in arguments and return types Abstract slot inference ◦ Nullness ignored, but warning given on slot mismatches Duplicate method checking ◦ Nullness is completely ignored
  21. 21. Type inference and mixing null/non-null • First element in each collection is a non-null string • Introduction of nullable string introduces type equivalence mismatch • Solution is to add explicit type annotation
  22. 22. Type inference and nullability assertions We cannot associate any arbitrary bool value with nullability. A nullability assertion is needed.
  23. 23. Nullability and obj Nullability is completely ignored for ‘obj’ type The ‘obj’ type is used when type information is thrown out Making this nullable/non-nullable is pointless considering throwing out type information
  24. 24. Null analysis for nullable value types Partial alignment of existing nullable value types is possible ◦ Same syntax may be possible (int?, float?, etc.) ◦ Same or similar rules for type relations and type inference
  26. 26. [<Nullable>] attribute bool[] represents nested types
  27. 27. Attributes to affect compiler analysis [<NotNullWhenTrue>] and [<NotNullWhenFalse>] ◦ Used in bool-returning functions or methods that check for null [<EnsuresNotNull>] ◦ Used on functions or methods that throw an exception when null is encountered [<AssertsTrue>] and [<AssertsFalse>] ◦ Used for asserting nullability, such as in test frameworks, and avoiding warnings
  28. 28. [<NonNullTypes>] attribute Three cases: • NonNullTypes(true) • Nullability is a concept • NonNullTypes(false) • Nullability is not a concept • No attribute at all • Null oblivious semantics
  29. 29. Nullability assumptions EVERYONE LIKES ASSUMPTIONS
  30. 30. Three choices involved Distinguish between nullable and non-nullable reference types Do not distinguish between nullable and non-nullable reference types Null oblivious (i.e., no assumption in either direction)
  31. 31. What is null oblivious for F#? No information about nullability for reference types in a given scope If an oblivious value is given a nullable reference type, it is nullable If an oblivious value is given a non-nullable reference type, it is non-nullable Interesting question: What if ‘s’ is not annotated?
  32. 32. The case for null oblivious Pros: ◦ Less warnings (if you don’t want them) ◦ Makes porting existing code a lot easier ◦ Logically consistent Cons: ◦ Less warnings (if you do want them) ◦ More potential NREs ◦ Entire programs can be oblivious due to type inference
  33. 33. The case for assuming nullability Pros: ◦ More warnings (if you want them) ◦ Less NREs if you account for the warnings ◦ Avoids completely oblivious programs Cons: ◦ More warnings (if you don’t want them) ◦ Not logically consistent – no information means no assumptions, so why make them?
  34. 34. There is no perfect approach Some users may prefer obliviousness Some users may prefer assuming nullability Getting it right will be a challenge Current design is not set in stone (yet!)
  35. 35. Adjusting semantics for existing code DEALING WITH PAST DECISIONS IS HARD
  36. 36. Default Values Attribute implies nullability 'string’ is non-nullable This valid pre-F# 5.0 code now produces a warning
  37. 37. CLIMutable Attribute implies nullability ‘string’ is non-nullable This valid pre-F# 5.0 code now produces a warning
  38. 38. Compiled form of F# options • F# options compile to null for None case • Changing this would be a massive source- breaking change • Ironically, F# options would be interpreted as nullable reference types • No good resolution to this quite yet
  39. 39. Why do this feature? WAXING PHILOSOPHICAL ON NULLS
  40. 40. Make .NET a better place
  41. 41. Learn more