-
Notifications
You must be signed in to change notification settings - Fork 823
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
base: main
Are you sure you want to change the base?
Conversation
Co-authored-by: T-Gro <[email protected]>
src/FSharp.Core/event.fs
Outdated
@@ -146,10 +146,10 @@ type Event<'Delegate, 'Args | |||
"<published event>" | |||
interface IEvent<'Delegate, 'Args> with | |||
member e.AddHandler(d) = | |||
Atomic.setWith (fun value -> System.Delegate.Combine(value, d) :?> 'Delegate) &multicast | |||
Atomic.setWith (fun value -> System.Delegate.Combine(value, d) :?> ('Delegate | null)) &multicast |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot :
It does not make sense casting to nullable types.
Cast just to 'Delegate , without the | null
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 0e34deb - removed the nullable union type from the cast
@T-Gro Unfortunately I hit an unexpected error while processing your comment. I've automatically reported this to GitHub. You can ask me to try again later by mentioning me in a new comment. If you want to contact GitHub about this error, please mention the following identifier so they can better serve you: Sorry for the inconvenience! |
src/FSharp.Core/event.fs
Outdated
@@ -180,10 +180,10 @@ type Event<'T> = | |||
"<published event>" | |||
interface IEvent<'T> with | |||
member e.AddHandler(d) = | |||
Atomic.setWith (fun value -> System.Delegate.Combine(value, d) :?> Handler<'T>) &x.multicast | |||
Atomic.setWith (fun value -> System.Delegate.Combine(value, d) :?> Handler<'T> | null) &x.multicast |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot :
It does not make sense casting to nullable types.
Cast just to Handler<'T> , without the | null .
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 0e34deb - removed the nullable union type from the cast
@T-Gro Unfortunately I hit an unexpected error while processing your comment. I've automatically reported this to GitHub. You can ask me to try again later by mentioning me in a new comment. If you want to contact GitHub about this error, please mention the following identifier so they can better serve you: Sorry for the inconvenience! |
src/FSharp.Core/event.fs
Outdated
|
||
member e.RemoveHandler(d) = | ||
Atomic.setWith (fun value -> System.Delegate.Remove(value, d) :?> Handler<'T>) &x.multicast | ||
Atomic.setWith (fun value -> System.Delegate.Remove(value, d) :?> Handler<'T> | null) &x.multicast |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot :
It does not make sense casting to nullable types.
Cast just to Handler<'T> , without the | null .
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 0e34deb - removed the nullable union type from the cast
@T-Gro Unfortunately I hit an unexpected error while processing your comment. I've automatically reported this to GitHub. You can ask me to try again later by mentioning me in a new comment. If you want to contact GitHub about this error, please mention the following identifier so they can better serve you: Sorry for the inconvenience! |
@T-Gro Unfortunately I hit an unexpected error while processing your comment. I've automatically reported this to GitHub. You can ask me to try again later by mentioning me in a new comment. If you want to contact GitHub about this error, please mention the following identifier so they can better serve you: Sorry for the inconvenience! |
Have a look at all unresolved comments and process them. |
Co-authored-by: T-Gro <[email protected]>
I've addressed all the unresolved comments by removing the unnecessary nullable union types from the casts in commit 0e34deb. Warning Firewall rules blocked me from connecting to one or more addressesI tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
❗ Release notes requiredCaution No release notes found for the changed paths (see table below). Please make sure to add an entry with an informative description of the change as well as link to this pull request, issue and language suggestion if applicable. Release notes for this repository are based on Keep A Changelog format. The following format is recommended for this repository:
If you believe that release notes are not necessary for this PR, please add NO_RELEASE_NOTES label to the pull request. You can open this PR in browser to add release notes: open in github.dev
|
Co-authored-by: T-Gro <[email protected]>
src/FSharp.Core/event.fs
Outdated
@@ -149,12 +149,12 @@ type Event<'Delegate, 'Args | |||
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 -> System.Delegate.Remove(value, d) :?> ('Delegate | null)) &multicast |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
System.Delegate.Remove
can introduce null.
match on it.
If it returns null, set null.
Else, cast the result to `Delegate
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Implemented in 638df49 using pattern matching for System.Delegate.Remove to explicitly handle null values
src/FSharp.Core/event.fs
Outdated
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 = Delegate.CreateDelegate(typeof<'Delegate>, obj, invokeInfo) :?> ('Delegate | null) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
System.Delegate.CreateDelegatecan introduce null.
match on it.
If it returns null, set null.
Else, cast the result to `Delegate
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Implemented in 638df49 using pattern matching for Delegate.CreateDelegate to explicitly handle null values
Co-authored-by: T-Gro <[email protected]>
Issue
When implementing
INotifyPropertyChanged
interface using the standard F# pattern withEvent<PropertyChangedEventHandler, PropertyChangedEventArgs>()
, a nullness warning is produced:This happens in nullable-aware contexts (using
--checknulls
andlangversion:preview
).Root Cause
In a nullness-aware context, .NET delegate types like
PropertyChangedEventHandler
are treated as potentially nullable (Delegate | null
), but the F#Event
class was expecting non-nullable delegates in its implementation.Fix
Updated the
multicast
field inEvent
classes to be explicitly marked as nullable:Fixed the delegate handling in
AddHandler
andRemoveHandler
to correctly handle nullable delegates:Made similar changes to the
Event<'T>
class.Added a test case to verify the fix works properly for
INotifyPropertyChanged
implementations.These changes ensure that F# code can cleanly implement standard .NET interfaces with events when nullability checks are enabled.
Fixes #18361.
Warning
Firewall rules blocked me from connecting to one or more addresses
I tried to connect to the following addresses, but was blocked by firewall rules:
cdn.fwupd.org
/usr/bin/fwupdmgr refresh
(dns block)dc.services.visualstudio.com
/home/REDACTED/work/fsharp/fsharp/.dotnet/dotnet msbuild /m /nologo /clp:Summary /v:minimal /nr:true /warnaserror /p:TreatWarningsAsErrors=true /p:ContinuousIntegrationBuild=false /home/REDACTED/work/fsharp/fsharp/artifacts/toolset/restore.proj /t:__WriteToolsetLocation /clp:ErrorsOnly;NoSummary /p:__ToolsetLocationOutputFile=/home/REDACTED/work/fsharp/fsharp/artifacts/toolset/9.0.0-beta.25266.2.txt
(dns block)pkgs.dev.azure.com
/home/REDACTED/work/fsharp/fsharp/.dotnet/dotnet msbuild /m /nologo /clp:Summary /v:minimal /nr:true /warnaserror /p:TreatWarningsAsErrors=true /p:ContinuousIntegrationBuild=false /home/REDACTED/work/fsharp/fsharp/artifacts/toolset/restore.proj /t:__WriteToolsetLocation /clp:ErrorsOnly;NoSummary /p:__ToolsetLocationOutputFile=/home/REDACTED/work/fsharp/fsharp/artifacts/toolset/9.0.0-beta.25266.2.txt
(dns block)If you need me to access, download, or install something from one of these locations, you can either:
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.