Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nullable Reference Types #317

Merged
merged 48 commits into from
Oct 19, 2018
Merged

Nullable Reference Types #317

merged 48 commits into from
Oct 19, 2018

Conversation

cartermp
Copy link
Member

@cartermp cartermp commented Jun 27, 2018

This is a draft of F# nullable reference types.

It is based primarily on the C# proposal, with additional considerations for F# based on existing behavior we have.

I expect a lot of things that are written down to change over time (i.e., a good lot of what I've written may not actually work out well, but we'll see 😄 )

@cartermp cartermp changed the title [DRAFT] Nullable Reference Types Nullable Reference Types Jun 29, 2018
RFCs/FS-1060-nullable-reference-types.md Outdated Show resolved Hide resolved
RFCs/FS-1060-nullable-reference-types.md Outdated Show resolved Hide resolved
RFCs/FS-1060-nullable-reference-types.md Outdated Show resolved Hide resolved
RFCs/FS-1060-nullable-reference-types.md Outdated Show resolved Hide resolved
RFCs/FS-1060-nullable-reference-types.md Outdated Show resolved Hide resolved
RFCs/FS-1060-nullable-reference-types.md Show resolved Hide resolved
RFCs/FS-1060-nullable-reference-types.md Outdated Show resolved Hide resolved
RFCs/FS-1060-nullable-reference-types.md Show resolved Hide resolved
RFCs/FS-1060-nullable-reference-types.md Show resolved Hide resolved
RFCs/FS-1060-nullable-reference-types.md Show resolved Hide resolved
@cartermp
Copy link
Member Author

Linking dotnet/fsharp#3108 for posterity

RFCs/FS-1060-nullable-reference-types.md Outdated Show resolved Hide resolved
RFCs/FS-1060-nullable-reference-types.md Outdated Show resolved Hide resolved
RFCs/FS-1060-nullable-reference-types.md Outdated Show resolved Hide resolved
@TIHan
Copy link
Contributor

TIHan commented Sep 26, 2018

Notes

  • Does x :? (string | null) generate a warning because the runtime type information doesn't have nullness
  • information is dropped in F# quotations

Test cases

  • can pass obj to obj | null
  • can pass string to obj | null
  • can't pass obj | null to obj

@dsyme
Copy link
Contributor

dsyme commented Oct 12, 2018

Further notes:

Small interaction with type abbreviations, e.g. can you do

type S = string | null
type S2 = S | null

or

type S = string | null
let f (x: (S | null)) = ...

@dsyme
Copy link
Contributor

dsyme commented Oct 15, 2018

ANother note: the syntax string | null may be tricky to implement. For example,

let f2 (_ : string | null) = 1

is valid code today because it is interpreted as a union pattern match combined with a type-annotated wildcard pattern:

let f2 ((_ : string) | null) = 1

Alternatives that look simpler to implement are

let f (x: string?) = x
let f (x: string or null) = x

and there is also the option of using

let f (x: Nullable<string>) = x

@voronoipotato
Copy link
Contributor

voronoipotato commented Oct 17, 2018

This may be an extremely stupid thing to ask but why can't we treat possible nulls from outside things as Option? Null would be represented as None. This way we avoid the possible Option<Nullable>. If we're going to break things (and we're probably not) we might as well break them to be more consistent.

Edit: also let me know if this isn't the proper place to discuss this.

@davidglassborow
Copy link

@voronoipotato this is covered in the RFC document

@slang25
Copy link
Contributor

slang25 commented Oct 18, 2018

Specifically here

@voronoipotato
Copy link
Contributor

Thank you so much guys.

@auduchinok
Copy link
Contributor

I'd like to bring nullability for tuples into consideration.
When tuples are coming from external non-F# code they can have null as a proper value while F# treats them as non-null values making working with them either more error-prone or not very convenient.

An example method from R# SDK I had to deal with recently:

[CanBeNull]
Tuple<IProject, TargetFrameworkId> GetProjectAndTargetFrameworkIdByOutputAssembly(FileSystemPath assemblyPath);

@cartermp
Copy link
Member Author

@auduchinok For interop, an analogous situation would be like this: https://sharplab.io/#v2:EYLgZgpghgLgrgJwgZwLQDk4BstWFiAJQkiQDsBjCAFQE8AHFAGhhAEssAfAAQAYACbgEYA3AFgAUH0FCAdIThkYbALYRZAYQD2K+hwgIAygYBubKsnETJAbXRaymHHUbIAFDARwIASgC6ktwAzIIATPwa/ADekvxxgiHUcPQEADzCvEwyvAB8APz8ALJuPtGx8RXcAOz8ZNhYVhUAvpJNQA

Which is sort of like this:

[NonNullTypes(true)]
public class C
{
    [return: Nullable(new bool[] {
        true,
        false,
        false
    })]
    public Tuple<string, string> M()
    {
        return null;
    }
}

And we'd respect the nullability of the construct. I doubt we'd emit that because we don't have null as a proper value, but consumption of such a thing is considered in scope.

@dsyme
Copy link
Contributor

dsyme commented Oct 19, 2018

I adjsuted the syntax to string? for now. string | null is very hard to support.

I will pull this and we can continue the discussion

@dsyme dsyme merged commit 6342c9f into fsharp:master Oct 19, 2018
@3xau1o
Copy link

3xau1o commented Apr 15, 2023

@dsyme does the literal types proposal 1195, may allow for string | null where null would be a literal value type? this is the way it works on typescript unions

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants