Skip to content

Commit b64ea2b

Browse files
authored
Consolidate .Using and |null in builders (dotnet#18292)
1 parent ad29712 commit b64ea2b

File tree

17 files changed

+47
-20
lines changed

17 files changed

+47
-20
lines changed

.fantomasignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ src/Compiler/Checking/TypeHierarchy.fs
4141
src/Compiler/Checking/TypeRelations.fs
4242

4343
# nullness-related problems
44+
src/Compiler/Utilities/lib.fsi
45+
src/Compiler/Utilities/Cancellable.fsi
46+
src/FSharp.Core/tasks.fsi
47+
src/FSharp.Core/tasks.fs
48+
src/FSharp.Core/resumable.fs
4449
src/Compiler/DependencyManager/DependencyProvider.fs
4550
src/FSharp.Core/fslib-extra-pervasives.fs
4651
src/FSharp.Core/fslib-extra-pervasives.fsi

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
* FSharpCheckFileResults.ProjectContext.ProjectOptions will not be available when using the experimental Transparent Compiler feature. ([PR #18205](https://github.com/dotnet/fsharp/pull/18205))
2121
* Update `Obsolete` attribute checking to account for `DiagnosticId` and `UrlFormat` properties. ([PR #18224](https://github.com/dotnet/fsharp/pull/18224))
2222
* Remove `Cancellable.UsingToken` from tests ([PR #18276](https://github.com/dotnet/fsharp/pull/18276))
23+
* Added nullability annotations to `.Using` builder method for `async`, `task` and compiler-internal builders ([PR #18292](https://github.com/dotnet/fsharp/pull/18292))
2324

2425
### Breaking Changes
2526
* Struct unions with overlapping fields now generate mappings needed for reading via reflection ([Issue #18121](https://github.com/dotnet/fsharp/issues/17797), [PR #18274](https://github.com/dotnet/fsharp/pull/17877))
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
### Fixed
22

33
### Added
4+
* Added nullability annotations to `.Using` builder method for `async` and `task` builders ([PR #18292](https://github.com/dotnet/fsharp/pull/18292))
45

56
### Changed
67

78
### Breaking Changes
8-
* Struct unions with overlapping fields now generate mappings needed for reading via reflection ([Issue #18121](https://github.com/dotnet/fsharp/issues/17797), [PR #18274](https://github.com/dotnet/fsharp/pull/17877)). Previous versions of FSharp.Core returned incomplete mapping between fields and cases, these older fslib versions will now report an exception.
9+
* Struct unions with overlapping fields now generate mappings needed for reading via reflection ([Issue #18121](https://github.com/dotnet/fsharp/issues/17797), [PR #18274](https://github.com/dotnet/fsharp/pull/18274)). Previous versions of FSharp.Core returned incomplete mapping between fields and cases, these older fslib versions will now report an exception.

src/Compiler/Utilities/Activity.fs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,18 +89,18 @@ module internal Activity =
8989

9090
let private activitySource = new ActivitySource(ActivityNames.FscSourceName)
9191

92-
let start (name: string) (tags: (string * string) seq) : IDisposable =
92+
let start (name: string) (tags: (string * string) seq) : IDisposable MaybeNull =
9393
let activity = activitySource.CreateActivity(name, ActivityKind.Internal)
9494

9595
match activity with
96-
| null -> !!activity //TODO change retTy to |null after PR #18262 is merged!!
96+
| null -> activity
9797
| activity ->
9898
for key, value in tags do
9999
activity.AddTag(key, value) |> ignore
100100

101101
activity.Start()
102102

103-
let startNoTags (name: string) : IDisposable = !! (activitySource.StartActivity name) //TODO change retTy to |null after PR #18262 is merged!!
103+
let startNoTags (name: string) : IDisposable MaybeNull = activitySource.StartActivity name
104104

105105
let addEvent name =
106106
match Activity.Current with
@@ -122,7 +122,7 @@ module internal Activity =
122122

123123
let private profiledSource = new ActivitySource(ActivityNames.ProfiledSourceName)
124124

125-
let startAndMeasureEnvironmentStats (name: string) : IDisposable = !!(profiledSource.StartActivity(name)) //TODO change retTy to |null after PR #18262 is merged!!
125+
let startAndMeasureEnvironmentStats (name: string) : IDisposable MaybeNull = profiledSource.StartActivity(name)
126126

127127
type private GCStats = int[]
128128

src/Compiler/Utilities/Activity.fsi

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
namespace FSharp.Compiler.Diagnostics
33

44
open System
5+
open Internal.Utilities.Library
56

67
/// For activities following the dotnet distributed tracing concept
78
/// https://learn.microsoft.com/dotnet/core/diagnostics/distributed-tracing-concepts?source=recommendations
@@ -39,14 +40,14 @@ module internal Activity =
3940
module Events =
4041
val cacheHit: string
4142

42-
val startNoTags: name: string -> IDisposable
43+
val startNoTags: name: string -> IDisposable MaybeNull
4344

44-
val start: name: string -> tags: (string * string) seq -> IDisposable
45+
val start: name: string -> tags: (string * string) seq -> IDisposable MaybeNull
4546

4647
val addEvent: name: string -> unit
4748

4849
module Profiling =
49-
val startAndMeasureEnvironmentStats: name: string -> IDisposable
50+
val startAndMeasureEnvironmentStats: name: string -> IDisposable MaybeNull
5051
val addConsoleListener: unit -> IDisposable
5152

5253
module CsvExport =

src/Compiler/Utilities/Cancellable.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ type CancellableBuilder() =
162162
| Choice2Of2 err -> Cancellable.run ct (handler err)
163163
| ValueOrCancelled.Cancelled err1 -> ValueOrCancelled.Cancelled err1)
164164

165-
member inline _.Using(resource, [<InlineIfLambda>] comp) =
165+
member inline _.Using(resource: _ MaybeNull, [<InlineIfLambda>] comp) =
166166
Cancellable(fun ct ->
167167
#if !FSHARPCORE_USE_PACKAGE
168168
__debugPoint ""

src/Compiler/Utilities/Cancellable.fsi

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,12 @@ type internal CancellableBuilder =
7171
comp: Cancellable<'T> * [<InlineIfLambda>] handler: (exn -> Cancellable<'T>) -> Cancellable<'T>
7272

7373
member inline Using:
74-
resource: 'Resource * [<InlineIfLambda>] comp: ('Resource -> Cancellable<'T>) -> Cancellable<'T>
74+
resource: 'Resource MaybeNull * [<InlineIfLambda>] comp: ('Resource MaybeNull -> Cancellable<'T>) -> Cancellable<'T>
7575
when 'Resource :> IDisposable
76+
and 'Resource:not struct
77+
#if !(NO_CHECKNULLS || BUILDING_WITH_LKG)
78+
and 'Resource:not null
79+
#endif
7680

7781
member inline Zero: unit -> Cancellable<unit>
7882

src/Compiler/Utilities/lib.fs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,10 @@ type DisposablesTracker() =
403403
let items = Stack<IDisposable>()
404404

405405
/// Register some items to dispose
406-
member _.Register i = items.Push i
406+
member _.Register (i:#IDisposable MaybeNull) =
407+
match box i with
408+
| null -> ()
409+
| _ -> items.Push (!!i)
407410

408411
interface IDisposable with
409412

src/Compiler/Utilities/lib.fsi

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,12 @@ type DisposablesTracker =
263263
new: unit -> DisposablesTracker
264264

265265
/// Register some items to dispose
266-
member Register: i: System.IDisposable -> unit
266+
member Register: i:'a MaybeNull -> unit
267+
when 'a:>System.IDisposable
268+
#if !(NO_CHECKNULLS || BUILDING_WITH_LKG)
269+
and 'a:not null
270+
#endif
271+
and 'a:not struct
267272

268273
interface System.IDisposable
269274

src/FSharp.Core/async.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -753,7 +753,7 @@ module AsyncPrimitives =
753753
/// - Cancellation check after 'entering' the implied try/finally and before running the body (see CreateTryFinallyAsync)
754754
/// - Hijack check after 'entering' the implied try/finally and before running the body (see CreateTryFinallyAsync)
755755
/// - Run 'disposeFunction' with exception protection (see CreateTryFinallyAsync)
756-
let CreateUsingAsync (resource: 'T :> IDisposable) (computation: 'T -> Async<'a>) : Async<'a> =
756+
let CreateUsingAsync (resource: 'T :> IDisposable | null) (computation: 'T -> Async<'a>) : Async<'a> =
757757
let disposeFunction () =
758758
Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicFunctions.Dispose resource
759759

src/FSharp.Core/async.fsi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1325,7 +1325,7 @@ namespace Microsoft.FSharp.Control
13251325
/// <returns>An asynchronous computation that binds and eventually disposes <c>resource</c>.</returns>
13261326
///
13271327
/// <example-tbd></example-tbd>
1328-
member Using: resource:'T * binder:('T -> Async<'U>) -> Async<'U> when 'T :> System.IDisposable
1328+
member Using: resource:'T * binder:('T -> Async<'U>) -> Async<'U> when 'T :> System.IDisposable|null
13291329

13301330
/// <summary>Creates an asynchronous computation that runs <c>computation</c>, and when
13311331
/// <c>computation</c> generates a result <c>T</c>, runs <c>binder res</c>.</summary>

src/FSharp.Core/prim-types.fs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -739,8 +739,11 @@ namespace Microsoft.FSharp.Core
739739
let inline TypeTestFast<'T>(source: objnull) =
740740
//assert not(TypeInfo<'T>.TypeInfo = TypeNullnessSemantics_NullTrueValue)
741741
notnullPrim(isinstPrim<'T>(source))
742-
742+
#if !BUILDING_WITH_LKG && !NO_NULLCHECKING_LIB_SUPPORT
743+
let Dispose<'T when 'T :> IDisposable >(resource:'T|null) =
744+
#else
743745
let Dispose<'T when 'T :> IDisposable >(resource:'T) =
746+
#endif
744747
match box resource with
745748
| null -> ()
746749
| _ -> resource.Dispose()

src/FSharp.Core/prim-types.fsi

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1796,7 +1796,11 @@ namespace Microsoft.FSharp.Core
17961796

17971797
/// <summary>A compiler intrinsic for the efficient compilation of sequence expressions</summary>
17981798
[<CompilerMessage("This function is for use by compiled F# code and should not be used directly", 1204, IsHidden=true)>]
1799+
#if !BUILDING_WITH_LKG && !NO_NULLCHECKING_LIB_SUPPORT
1800+
val Dispose<'T when 'T :> System.IDisposable> : resource: 'T|null -> unit
1801+
#else
17991802
val Dispose<'T when 'T :> System.IDisposable> : resource: 'T -> unit
1803+
#endif
18001804

18011805
/// <summary>A compiler intrinsic for checking initialization soundness of recursive bindings</summary>
18021806
[<CompilerMessage("This function is for use by compiled F# code and should not be used directly", 1204, IsHidden=true)>]

src/FSharp.Core/resumable.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,7 @@ module ResumableCode =
399399
(
400400
resource: 'Resource,
401401
body: 'Resource -> ResumableCode<'Data, 'T>
402-
) : ResumableCode<'Data, 'T> when 'Resource :> IDisposable =
402+
) : ResumableCode<'Data, 'T> when 'Resource :> IDisposable|null =
403403
// A using statement is just a try/finally with the finally block disposing if non-null.
404404
TryFinally(
405405
ResumableCode<'Data, 'T>(fun sm -> (body resource).Invoke(&sm)),

src/FSharp.Core/resumable.fsi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ module ResumableCode =
9090
val inline TryWith: body: ResumableCode<'Data, 'T> * catch: (exn -> ResumableCode<'Data, 'T>) -> ResumableCode<'Data, 'T>
9191

9292
/// Specifies resumable code which executes with 'use' semantics
93-
val inline Using: resource: 'Resource * body: ('Resource -> ResumableCode<'Data, 'T>) -> ResumableCode<'Data, 'T> when 'Resource :> IDisposable
93+
val inline Using: resource: 'Resource * body: ('Resource -> ResumableCode<'Data, 'T>) -> ResumableCode<'Data, 'T> when 'Resource :> IDisposable|null
9494

9595
/// Specifies resumable code which executes a loop
9696
val inline While: [<InlineIfLambda>] condition: (unit -> bool) * body: ResumableCode<'Data, unit> -> ResumableCode<'Data, unit>

src/FSharp.Core/tasks.fs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ type TaskBuilderBase() =
138138
false)
139139
)
140140

141-
member inline this.Using<'Resource, 'TOverall, 'T when 'Resource :> IAsyncDisposable>
141+
member inline this.Using<'Resource, 'TOverall, 'T when 'Resource :> IAsyncDisposable|null>
142142
(
143143
resource: 'Resource,
144144
body: 'Resource -> TaskCode<'TOverall, 'T>
@@ -382,7 +382,7 @@ module LowPriority =
382382

383383
this.Bind(task, this.Return)
384384

385-
member inline _.Using<'Resource, 'TOverall, 'T when 'Resource :> IDisposable>
385+
member inline _.Using<'Resource, 'TOverall, 'T when 'Resource :> IDisposable|null>
386386
(
387387
resource: 'Resource,
388388
body: 'Resource -> TaskCode<'TOverall, 'T>

src/FSharp.Core/tasks.fsi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ module LowPriority =
237237
/// </summary>
238238
member inline Using:
239239
resource: 'Resource * body: ('Resource -> TaskCode<'TOverall, 'T>) -> TaskCode<'TOverall, 'T>
240-
when 'Resource :> IDisposable
240+
when 'Resource :> IDisposable|null
241241

242242
/// <summary>
243243
/// Contains medium-priority overloads for the `task` computation expression builder.

0 commit comments

Comments
 (0)