Skip to content

Commit c793bfa

Browse files
committed
iron things out
1 parent 7101e5b commit c793bfa

File tree

8 files changed

+78
-73
lines changed

8 files changed

+78
-73
lines changed

src/Compiler/Driver/CompilerImports.fs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1735,7 +1735,7 @@ and [<Sealed>] TcImports
17351735
m
17361736
) =
17371737

1738-
let startingErrorCount = DiagnosticsThreadStatics.DiagnosticsLogger.ErrorCount
1738+
let startingErrorCount = DiagnosticsAsyncState.DiagnosticsLogger.ErrorCount
17391739

17401740
// Find assembly level TypeProviderAssemblyAttributes. These will point to the assemblies that
17411741
// have class which implement ITypeProvider and which have TypeProviderAttribute on them.
@@ -1936,7 +1936,7 @@ and [<Sealed>] TcImports
19361936
with RecoverableException e ->
19371937
errorRecovery e m
19381938

1939-
if startingErrorCount < DiagnosticsThreadStatics.DiagnosticsLogger.ErrorCount then
1939+
if startingErrorCount < DiagnosticsAsyncState.DiagnosticsLogger.ErrorCount then
19401940
error (Error(FSComp.SR.etOneOrMoreErrorsSeenDuringExtensionTypeSetting (), m))
19411941

19421942
providers
@@ -2238,15 +2238,17 @@ and [<Sealed>] TcImports
22382238
| ParallelReferenceResolution.On -> Async.Parallel
22392239
| ParallelReferenceResolution.Off -> Async.SequentialFailFast
22402240

2241-
let diagnosticsLogger = DiagnosticsThreadStatics.DiagnosticsLogger
2241+
use captureTasks = new CaptureDiagnosticsConcurrently(DiagnosticsAsyncState.DiagnosticsLogger)
2242+
22422243
let! results =
22432244
nms
22442245
|> List.map (fun nm ->
22452246
async {
22462247
try
22472248
return! tcImports.TryRegisterAndPrepareToImportReferencedDll(ctok, nm)
22482249
with e ->
2249-
use _ = UseDiagnosticsLogger diagnosticsLogger
2250+
use _ = UseDiagnosticsLogger captureTasks.LoggerForTask
2251+
22502252
errorR (Error(FSComp.SR.buildProblemReadingAssembly (nm.resolvedPath, e.Message), nm.originalReference.Range))
22512253
return None
22522254
})

src/Compiler/Driver/ParseAndCheckInputs.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1828,7 +1828,7 @@ let CheckMultipleInputsUsingGraphMode
18281828
|> Graph.writeMermaidToFile graphFile)
18291829

18301830
let _ = ctok // TODO Use it
1831-
let diagnosticsLogger = DiagnosticsThreadStatics.DiagnosticsLogger
1831+
let diagnosticsLogger = DiagnosticsAsyncState.DiagnosticsLogger
18321832

18331833
// In the first linear part of parallel checking, we use a 'checkForErrors' that checks either for errors
18341834
// somewhere in the files processed prior to each one, or in the processing of this particular file.

src/Compiler/Facilities/AsyncMemoize.fs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -354,15 +354,15 @@ type internal AsyncMemoize<'TKey, 'TVersion, 'TValue when 'TKey: equality and 'T
354354
log (Restarted, key)
355355
Interlocked.Increment &restarted |> ignore
356356
System.Diagnostics.Trace.TraceInformation $"{name} Restarted {key.Label}"
357-
let currentLogger = DiagnosticsThreadStatics.DiagnosticsLogger
358-
DiagnosticsThreadStatics.DiagnosticsLogger <- cachingLogger
357+
let currentLogger = DiagnosticsAsyncState.DiagnosticsLogger
358+
DiagnosticsAsyncState.DiagnosticsLogger <- cachingLogger
359359

360360
try
361361
let! result = computation
362362
post (key, (JobCompleted(result, cachingLogger.CapturedDiagnostics)))
363363
return ()
364364
finally
365-
DiagnosticsThreadStatics.DiagnosticsLogger <- currentLogger
365+
DiagnosticsAsyncState.DiagnosticsLogger <- currentLogger
366366
with
367367
| TaskCancelled _ ->
368368
Interlocked.Increment &cancel_exception_subsequent |> ignore
@@ -484,7 +484,7 @@ type internal AsyncMemoize<'TKey, 'TVersion, 'TValue when 'TKey: equality and 'T
484484
async {
485485
let! ct = Async.CancellationToken
486486

487-
let callerDiagnosticLogger = DiagnosticsThreadStatics.DiagnosticsLogger
487+
let callerDiagnosticLogger = DiagnosticsAsyncState.DiagnosticsLogger
488488

489489
match!
490490
processRequest post (key, GetOrCompute(computation, ct)) callerDiagnosticLogger
@@ -500,8 +500,8 @@ type internal AsyncMemoize<'TKey, 'TVersion, 'TValue when 'TKey: equality and 'T
500500
Async.StartAsTask(
501501
async {
502502
// TODO: Should unify starting and restarting
503-
let currentLogger = DiagnosticsThreadStatics.DiagnosticsLogger
504-
DiagnosticsThreadStatics.DiagnosticsLogger <- cachingLogger
503+
let currentLogger = DiagnosticsAsyncState.DiagnosticsLogger
504+
DiagnosticsAsyncState.DiagnosticsLogger <- cachingLogger
505505

506506
log (Started, key)
507507

@@ -510,7 +510,7 @@ type internal AsyncMemoize<'TKey, 'TVersion, 'TValue when 'TKey: equality and 'T
510510
post (key, (JobCompleted(result, cachingLogger.CapturedDiagnostics)))
511511
return result
512512
finally
513-
DiagnosticsThreadStatics.DiagnosticsLogger <- currentLogger
513+
DiagnosticsAsyncState.DiagnosticsLogger <- currentLogger
514514
},
515515
cancellationToken = linkedCtSource.Token
516516
)

src/Compiler/Facilities/DiagnosticsLogger.fs

Lines changed: 44 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -401,25 +401,23 @@ type ConcurrentCapturingDiagnosticsLogger(nm, ?eagerFormat) =
401401
errors |> Array.iter diagnosticsLogger.DiagnosticSink
402402

403403
/// Type holds thread-static globals for use by the compiler.
404-
type DiagnosticsThreadStatics =
405-
static let buildPhase = new AsyncLocal<BuildPhase>()
406-
static let diagnosticsLogger = new AsyncLocal<DiagnosticsLogger>()
404+
type DiagnosticsAsyncState =
405+
static let buildPhase = new AsyncLocal<BuildPhase voption>()
406+
static let diagnosticsLogger = new AsyncLocal<DiagnosticsLogger voption>()
407407

408-
static let EnsureCreated (h: AsyncLocal<_>) d =
409-
if box h.Value |> isNull then
410-
h.Value <- d
408+
static let getOrCreate (holder: AsyncLocal<_>) defaultValue =
409+
holder.Value
410+
|> ValueOption.defaultWith (fun () ->
411+
holder.Value <- ValueSome defaultValue
412+
defaultValue)
411413

412414
static member BuildPhase
413-
with get () =
414-
EnsureCreated buildPhase BuildPhase.DefaultPhase
415-
buildPhase.Value
416-
and set v = buildPhase.Value <- v
415+
with get () = getOrCreate buildPhase BuildPhase.DefaultPhase
416+
and set v = buildPhase.Value <- ValueSome v
417417

418418
static member DiagnosticsLogger
419-
with get () =
420-
EnsureCreated diagnosticsLogger AssertFalseDiagnosticsLogger
421-
diagnosticsLogger.Value
422-
and set v = diagnosticsLogger.Value <- v
419+
with get () = getOrCreate diagnosticsLogger AssertFalseDiagnosticsLogger
420+
and set v = diagnosticsLogger.Value <- ValueSome v
423421

424422
[<AutoOpen>]
425423
module DiagnosticsLoggerExtensions =
@@ -461,7 +459,7 @@ module DiagnosticsLoggerExtensions =
461459
| ReportedError _ ->
462460
PreserveStackTrace exn
463461
raise exn
464-
| _ -> x.DiagnosticSink(PhasedDiagnostic.Create(exn, DiagnosticsThreadStatics.BuildPhase), severity)
462+
| _ -> x.DiagnosticSink(PhasedDiagnostic.Create(exn, DiagnosticsAsyncState.BuildPhase), severity)
465463

466464
member x.ErrorR exn =
467465
x.EmitDiagnostic(exn, FSharpDiagnosticSeverity.Error)
@@ -521,45 +519,32 @@ module DiagnosticsLoggerExtensions =
521519

522520
/// NOTE: The change will be undone when the returned "unwind" object disposes
523521
let UseBuildPhase (phase: BuildPhase) =
524-
let oldBuildPhase = DiagnosticsThreadStatics.BuildPhase
525-
DiagnosticsThreadStatics.BuildPhase <- phase
522+
let oldBuildPhase = DiagnosticsAsyncState.BuildPhase
523+
DiagnosticsAsyncState.BuildPhase <- phase
526524

527525
{ new IDisposable with
528526
member x.Dispose() =
529-
DiagnosticsThreadStatics.BuildPhase <- oldBuildPhase
527+
DiagnosticsAsyncState.BuildPhase <- oldBuildPhase
530528
}
531529

532530
/// NOTE: The change will be undone when the returned "unwind" object disposes
533531
let UseTransformedDiagnosticsLogger (transformer: DiagnosticsLogger -> #DiagnosticsLogger) =
534-
let oldLogger = DiagnosticsThreadStatics.DiagnosticsLogger
535-
DiagnosticsThreadStatics.DiagnosticsLogger <- transformer oldLogger
532+
let oldLogger = DiagnosticsAsyncState.DiagnosticsLogger
533+
DiagnosticsAsyncState.DiagnosticsLogger <- transformer oldLogger
536534

537535
{ new IDisposable with
538536
member _.Dispose() =
539-
DiagnosticsThreadStatics.DiagnosticsLogger <- oldLogger
537+
DiagnosticsAsyncState.DiagnosticsLogger <- oldLogger
540538
}
541539

542540
let UseDiagnosticsLogger newLogger =
543541
UseTransformedDiagnosticsLogger(fun _ -> newLogger)
544542

545-
let CaptureDiagnosticsConcurrently () =
546-
let newLogger =
547-
ConcurrentCapturingDiagnosticsLogger("CaptureDiagnosticsConcurrently")
548-
549-
let oldLogger = DiagnosticsThreadStatics.DiagnosticsLogger
550-
DiagnosticsThreadStatics.DiagnosticsLogger <- newLogger
551-
552-
{ new IDisposable with
553-
member _.Dispose() =
554-
newLogger.CommitDelayedDiagnostics oldLogger
555-
DiagnosticsThreadStatics.DiagnosticsLogger <- oldLogger
556-
}
557-
558543
let SetThreadBuildPhaseNoUnwind (phase: BuildPhase) =
559-
DiagnosticsThreadStatics.BuildPhase <- phase
544+
DiagnosticsAsyncState.BuildPhase <- phase
560545

561546
let SetThreadDiagnosticsLoggerNoUnwind diagnosticsLogger =
562-
DiagnosticsThreadStatics.DiagnosticsLogger <- diagnosticsLogger
547+
DiagnosticsAsyncState.DiagnosticsLogger <- diagnosticsLogger
563548

564549
/// This represents the thread-local state established as each task function runs as part of the build.
565550
///
@@ -577,30 +562,43 @@ type CompilationGlobalsScope(diagnosticsLogger: DiagnosticsLogger, buildPhase: B
577562
unwindBP.Dispose()
578563
unwindEL.Dispose()
579564

565+
type CaptureDiagnosticsConcurrently(target) =
566+
let loggers = System.Collections.Concurrent.ConcurrentQueue()
567+
568+
member _.LoggerForTask: DiagnosticsLogger =
569+
let logger = CapturingDiagnosticsLogger("One of parallel computations")
570+
loggers.Enqueue logger
571+
logger
572+
573+
interface IDisposable with
574+
member _.Dispose() =
575+
for logger in loggers do
576+
logger.CommitDelayedDiagnostics target
577+
580578
// Global functions are still used by parser and TAST ops.
581579

582580
/// Raises an exception with error recovery and returns unit.
583581
let errorR exn =
584-
DiagnosticsThreadStatics.DiagnosticsLogger.ErrorR exn
582+
DiagnosticsAsyncState.DiagnosticsLogger.ErrorR exn
585583

586584
/// Raises a warning with error recovery and returns unit.
587585
let warning exn =
588-
DiagnosticsThreadStatics.DiagnosticsLogger.Warning exn
586+
DiagnosticsAsyncState.DiagnosticsLogger.Warning exn
589587

590588
/// Raises a warning with error recovery and returns unit.
591589
let informationalWarning exn =
592-
DiagnosticsThreadStatics.DiagnosticsLogger.InformationalWarning exn
590+
DiagnosticsAsyncState.DiagnosticsLogger.InformationalWarning exn
593591

594592
/// Raises a special exception and returns 'T - can be caught later at an errorRecovery point.
595593
let error exn =
596-
DiagnosticsThreadStatics.DiagnosticsLogger.Error exn
594+
DiagnosticsAsyncState.DiagnosticsLogger.Error exn
597595

598596
/// Simulates an error. For test purposes only.
599597
let simulateError (diagnostic: PhasedDiagnostic) =
600-
DiagnosticsThreadStatics.DiagnosticsLogger.SimulateError diagnostic
598+
DiagnosticsAsyncState.DiagnosticsLogger.SimulateError diagnostic
601599

602600
let diagnosticSink (diagnostic, severity) =
603-
DiagnosticsThreadStatics.DiagnosticsLogger.DiagnosticSink(diagnostic, severity)
601+
DiagnosticsAsyncState.DiagnosticsLogger.DiagnosticSink(diagnostic, severity)
604602

605603
let errorSink diagnostic =
606604
diagnosticSink (diagnostic, FSharpDiagnosticSeverity.Error)
@@ -609,13 +607,13 @@ let warnSink diagnostic =
609607
diagnosticSink (diagnostic, FSharpDiagnosticSeverity.Warning)
610608

611609
let errorRecovery exn m =
612-
DiagnosticsThreadStatics.DiagnosticsLogger.ErrorRecovery exn m
610+
DiagnosticsAsyncState.DiagnosticsLogger.ErrorRecovery exn m
613611

614612
let stopProcessingRecovery exn m =
615-
DiagnosticsThreadStatics.DiagnosticsLogger.StopProcessingRecovery exn m
613+
DiagnosticsAsyncState.DiagnosticsLogger.StopProcessingRecovery exn m
616614

617615
let errorRecoveryNoRange exn =
618-
DiagnosticsThreadStatics.DiagnosticsLogger.ErrorRecoveryNoRange exn
616+
DiagnosticsAsyncState.DiagnosticsLogger.ErrorRecoveryNoRange exn
619617

620618
let deprecatedWithError s m = errorR (Deprecated(s, m))
621619

@@ -634,7 +632,7 @@ let mlCompatError s m =
634632

635633
[<DebuggerStepThrough>]
636634
let suppressErrorReporting f =
637-
let diagnosticsLogger = DiagnosticsThreadStatics.DiagnosticsLogger
635+
let diagnosticsLogger = DiagnosticsAsyncState.DiagnosticsLogger
638636

639637
try
640638
let diagnosticsLogger =

src/Compiler/Facilities/DiagnosticsLogger.fsi

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ type ConcurrentCapturingDiagnosticsLogger =
243243

244244
/// Thread statics for the installed diagnostic logger
245245
[<Class>]
246-
type DiagnosticsThreadStatics =
246+
type DiagnosticsAsyncState =
247247

248248
static member BuildPhase: BuildPhase with get, set
249249

@@ -295,12 +295,17 @@ val UseTransformedDiagnosticsLogger: transformer: (DiagnosticsLogger -> #Diagnos
295295

296296
val UseDiagnosticsLogger: newLogger: DiagnosticsLogger -> IDisposable
297297

298-
val CaptureDiagnosticsConcurrently: unit -> IDisposable
299-
300298
val SetThreadBuildPhaseNoUnwind: phase: BuildPhase -> unit
301299

302300
val SetThreadDiagnosticsLoggerNoUnwind: diagnosticsLogger: DiagnosticsLogger -> unit
303301

302+
type CaptureDiagnosticsConcurrently =
303+
new: target: DiagnosticsLogger -> CaptureDiagnosticsConcurrently
304+
305+
member LoggerForTask: DiagnosticsLogger
306+
307+
interface IDisposable
308+
304309
/// Reports an error diagnostic and continues
305310
val errorR: exn: exn -> unit
306311

tests/FSharp.Compiler.ComponentTests/CompilerService/AsyncMemoize.fs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -441,13 +441,13 @@ let ``Preserve thread static diagnostics`` () =
441441
let job1 (input: string) = async {
442442
let! _ = Async.Sleep (rng.Next(1, 30))
443443
let ex = DummyException("job1 error")
444-
DiagnosticsThreadStatics.DiagnosticsLogger.ErrorR(ex)
444+
DiagnosticsAsyncState.DiagnosticsLogger.ErrorR(ex)
445445
return Ok input
446446
}
447447

448448
let job2 (input: int) = async {
449449

450-
DiagnosticsThreadStatics.DiagnosticsLogger.Warning(DummyException("job2 error 1"))
450+
DiagnosticsAsyncState.DiagnosticsLogger.Warning(DummyException("job2 error 1"))
451451

452452
let! _ = Async.Sleep (rng.Next(1, 30))
453453

@@ -458,7 +458,7 @@ let ``Preserve thread static diagnostics`` () =
458458

459459
let! result = job1Cache.Get(key, job1 "${input}" )
460460

461-
DiagnosticsThreadStatics.DiagnosticsLogger.Warning(DummyException("job2 error 2"))
461+
DiagnosticsAsyncState.DiagnosticsLogger.Warning(DummyException("job2 error 2"))
462462

463463
return input, result
464464

@@ -473,7 +473,7 @@ let ``Preserve thread static diagnostics`` () =
473473

474474
use _ = new CompilationGlobalsScope(diagnosticsLogger, BuildPhase.Optimize)
475475

476-
DiagnosticsThreadStatics.DiagnosticsLogger.Warning(DummyException("task error"))
476+
DiagnosticsAsyncState.DiagnosticsLogger.Warning(DummyException("task error"))
477477

478478

479479
let key = { new ICacheKey<_, _> with
@@ -514,7 +514,7 @@ let ``Preserve thread static diagnostics already completed job`` () =
514514

515515
let job (input: string) = async {
516516
let ex = DummyException($"job {input} error")
517-
DiagnosticsThreadStatics.DiagnosticsLogger.ErrorR(ex)
517+
DiagnosticsAsyncState.DiagnosticsLogger.ErrorR(ex)
518518
return Ok input
519519
}
520520

@@ -548,7 +548,7 @@ let ``We get diagnostics from the job that failed`` () =
548548
let job (input: int) = async {
549549
let ex = DummyException($"job {input} error")
550550
do! Async.Sleep 100
551-
DiagnosticsThreadStatics.DiagnosticsLogger.Error(ex)
551+
DiagnosticsAsyncState.DiagnosticsLogger.Error(ex)
552552
return 5
553553
}
554554

tests/FSharp.Compiler.UnitTests/BuildGraphTests.fs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,14 +231,14 @@ module BuildGraphTests =
231231

232232
let job phase _ = async {
233233
do! random 10 |> Async.Sleep
234-
Assert.Equal(phase, DiagnosticsThreadStatics.BuildPhase)
234+
Assert.Equal(phase, DiagnosticsAsyncState.BuildPhase)
235235
}
236236

237237
let work (phase: BuildPhase) =
238238
async {
239239
use _ = new CompilationGlobalsScope(DiscardErrorsLogger, phase)
240240
let! _ = Seq.init 8 (job phase) |> Async.Parallel
241-
Assert.Equal(phase, DiagnosticsThreadStatics.BuildPhase)
241+
Assert.Equal(phase, DiagnosticsAsyncState.BuildPhase)
242242
}
243243

244244
let phases = [|

tests/FSharp.Compiler.UnitTests/HashIfExpression.fs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ type public HashIfExpression() =
6464
let startPos = Position.Empty
6565
let args = mkLexargs (defines, indentationSyntaxStatus, resourceManager, [], diagnosticsLogger, PathMap.empty, applyLineDirectives)
6666

67-
DiagnosticsThreadStatics.DiagnosticsLogger <- diagnosticsLogger
67+
DiagnosticsAsyncState.DiagnosticsLogger <- diagnosticsLogger
6868

6969
let parser (s : string) =
7070
let lexbuf = LexBuffer<char>.FromChars (true, LanguageVersion.Default, None, s.ToCharArray ())
@@ -77,11 +77,11 @@ type public HashIfExpression() =
7777
errors, warnings, parser
7878

7979
do // Setup
80-
DiagnosticsThreadStatics.BuildPhase <- BuildPhase.Compile
80+
DiagnosticsAsyncState.BuildPhase <- BuildPhase.Compile
8181
interface IDisposable with // Teardown
8282
member _.Dispose() =
83-
DiagnosticsThreadStatics.BuildPhase <- BuildPhase.DefaultPhase
84-
DiagnosticsThreadStatics.DiagnosticsLogger <- DiagnosticsThreadStatics.DiagnosticsLogger
83+
DiagnosticsAsyncState.BuildPhase <- BuildPhase.DefaultPhase
84+
DiagnosticsAsyncState.DiagnosticsLogger <- DiagnosticsAsyncState.DiagnosticsLogger
8585

8686
[<Fact>]
8787
member _.PositiveParserTestCases()=

0 commit comments

Comments
 (0)