Skip to content

Fix nullable Event<'Delegate, 'Args> for INotifyPropertyChanged implementations #18576

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

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 14 additions & 5 deletions src/FSharp.Core/event.fs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@
type Event<'Delegate, 'Args
when 'Delegate: delegate<'Args, unit> and 'Delegate :> System.Delegate and 'Delegate: not struct>() =

let mutable multicast: 'Delegate = Unchecked.defaultof<_>
let mutable multicast: 'Delegate | null = Unchecked.defaultof<_>

static let mi, argTypes =
let instanceBindingFlags =
Expand Down Expand Up @@ -149,12 +149,18 @@
Atomic.setWith (fun value -> System.Delegate.Combine(value, d) :?> 'Delegate) &multicast

member e.RemoveHandler(d) =
Atomic.setWith (fun value -> System.Delegate.Remove(value, d) :?> 'Delegate) &multicast
Atomic.setWith (fun value ->
match System.Delegate.Remove(value, d) with
| null -> null
| result -> result :?> 'Delegate) &multicast

Check failure on line 155 in src/FSharp.Core/event.fs

View check run for this annotation

Azure Pipelines / fsharp-ci (Build Linux)

src/FSharp.Core/event.fs#L155

src/FSharp.Core/event.fs(155,35): error FS3060: (NETCORE_ENGINEERING_TELEMETRY=Build) This type test or downcast will erase the provided type ''Delegate | null' to the type ''Delegate'

Check failure on line 155 in src/FSharp.Core/event.fs

View check run for this annotation

Azure Pipelines / fsharp-ci (Build Linux)

src/FSharp.Core/event.fs#L155

src/FSharp.Core/event.fs(155,35): error FS3060: (NETCORE_ENGINEERING_TELEMETRY=Build) This type test or downcast will erase the provided type ''Delegate | null' to the type ''Delegate'

Check failure on line 155 in src/FSharp.Core/event.fs

View check run for this annotation

Azure Pipelines / fsharp-ci (Build MacOS)

src/FSharp.Core/event.fs#L155

src/FSharp.Core/event.fs(155,35): error FS3060: (NETCORE_ENGINEERING_TELEMETRY=Build) This type test or downcast will erase the provided type ''Delegate | null' to the type ''Delegate'

Check failure on line 155 in src/FSharp.Core/event.fs

View check run for this annotation

Azure Pipelines / fsharp-ci (Build MacOS)

src/FSharp.Core/event.fs#L155

src/FSharp.Core/event.fs(155,35): error FS3060: (NETCORE_ENGINEERING_TELEMETRY=Build) This type test or downcast will erase the provided type ''Delegate | null' to the type ''Delegate'

Check failure on line 155 in src/FSharp.Core/event.fs

View check run for this annotation

Azure Pipelines / fsharp-ci

src/FSharp.Core/event.fs#L155

src/FSharp.Core/event.fs(155,35): error FS3060: (NETCORE_ENGINEERING_TELEMETRY=Build) This type test or downcast will erase the provided type ''Delegate | null' to the type ''Delegate'

Check failure on line 155 in src/FSharp.Core/event.fs

View check run for this annotation

Azure Pipelines / fsharp-ci

src/FSharp.Core/event.fs#L155

src/FSharp.Core/event.fs(155,35): error FS3060: (NETCORE_ENGINEERING_TELEMETRY=Build) This type test or downcast will erase the provided type ''Delegate | null' to the type ''Delegate'
interface System.IObservable<'Args> with
member e.Subscribe(observer) =
let obj = new EventDelegee<'Args>(observer)

let h = Delegate.CreateDelegate(typeof<'Delegate>, obj, invokeInfo) :?> 'Delegate
let h =
match Delegate.CreateDelegate(typeof<'Delegate>, obj, invokeInfo) with
| null -> null
| result -> result :?> 'Delegate

Check failure on line 163 in src/FSharp.Core/event.fs

View check run for this annotation

Azure Pipelines / fsharp-ci (Build Linux)

src/FSharp.Core/event.fs#L163

src/FSharp.Core/event.fs(163,35): error FS3060: (NETCORE_ENGINEERING_TELEMETRY=Build) This type test or downcast will erase the provided type ''Delegate | null' to the type ''Delegate'

Check failure on line 163 in src/FSharp.Core/event.fs

View check run for this annotation

Azure Pipelines / fsharp-ci (Build Linux)

src/FSharp.Core/event.fs#L163

src/FSharp.Core/event.fs(163,35): error FS3060: (NETCORE_ENGINEERING_TELEMETRY=Build) This type test or downcast will erase the provided type ''Delegate | null' to the type ''Delegate'

Check failure on line 163 in src/FSharp.Core/event.fs

View check run for this annotation

Azure Pipelines / fsharp-ci (Build MacOS)

src/FSharp.Core/event.fs#L163

src/FSharp.Core/event.fs(163,35): error FS3060: (NETCORE_ENGINEERING_TELEMETRY=Build) This type test or downcast will erase the provided type ''Delegate | null' to the type ''Delegate'

Check failure on line 163 in src/FSharp.Core/event.fs

View check run for this annotation

Azure Pipelines / fsharp-ci (Build MacOS)

src/FSharp.Core/event.fs#L163

src/FSharp.Core/event.fs(163,35): error FS3060: (NETCORE_ENGINEERING_TELEMETRY=Build) This type test or downcast will erase the provided type ''Delegate | null' to the type ''Delegate'

Check failure on line 163 in src/FSharp.Core/event.fs

View check run for this annotation

Azure Pipelines / fsharp-ci

src/FSharp.Core/event.fs#L163

src/FSharp.Core/event.fs(163,35): error FS3060: (NETCORE_ENGINEERING_TELEMETRY=Build) This type test or downcast will erase the provided type ''Delegate | null' to the type ''Delegate'

(e :?> IDelegateEvent<'Delegate>).AddHandler(h)

Expand All @@ -166,7 +172,7 @@

[<CompiledName("FSharpEvent`1")>]
type Event<'T> =
val mutable multicast: Handler<'T>
val mutable multicast: Handler<'T> | null
new() = { multicast = null }

member x.Trigger(arg: 'T) =
Expand All @@ -183,7 +189,10 @@
Atomic.setWith (fun value -> System.Delegate.Combine(value, d) :?> Handler<'T>) &x.multicast

member e.RemoveHandler(d) =
Atomic.setWith (fun value -> System.Delegate.Remove(value, d) :?> Handler<'T>) &x.multicast
Atomic.setWith (fun value ->
match System.Delegate.Remove(value, d) with
| null -> null
| result -> result :?> Handler<'T>) &x.multicast
interface System.IObservable<'T> with
member e.Subscribe(observer) =
let h = new Handler<_>(fun sender args -> observer.OnNext(args))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace Nullness

open System.ComponentModel

type XViewModel() =
let propertyChanged = Event<PropertyChangedEventHandler, PropertyChangedEventArgs>()

interface INotifyPropertyChanged with
[<CLIEvent>]
member this.PropertyChanged = propertyChanged.Publish
Original file line number Diff line number Diff line change
Expand Up @@ -1540,4 +1540,21 @@ let main _ =
|> compile
//|> verifyIL ["abc"]
|> run
|> verifyOutputContains [|"Test true;,1 true,2 true,3 true,4 true,5 true,6 false,7 true,8 false,9 false,10 false,11 false,12 true"|]
|> verifyOutputContains [|"Test true;,1 true,2 true,3 true,4 true,5 true,6 false,7 true,8 false,9 false,10 false,11 false,12 true"|]

[<Fact>]
let ``INotifyPropertyChanged with Event using PropertyChangedEventHandler`` () =
FSharp """namespace Nullness

open System.ComponentModel

type XViewModel() =
let propertyChanged = Event<PropertyChangedEventHandler, PropertyChangedEventArgs>()

interface INotifyPropertyChanged with
[<CLIEvent>]
member this.PropertyChanged = propertyChanged.Publish
"""
|> asLibrary
|> typeCheckWithStrictNullness
|> shouldSucceed
Loading