diff --git a/docs/release-notes/.FSharp.Core/10.0.200.md b/docs/release-notes/.FSharp.Core/10.0.200.md new file mode 100644 index 00000000000..ceba7553639 --- /dev/null +++ b/docs/release-notes/.FSharp.Core/10.0.200.md @@ -0,0 +1,3 @@ +### Fixed + +* Fix IL2091 trimming warning in `LazyExtensions.Create` by adding `DynamicallyAccessedMembers` attribute to the generic type parameter. ([Issue #17356](https://github.com/dotnet/fsharp/issues/17356), [PR #18302](https://github.com/dotnet/fsharp/pull/18302)) diff --git a/src/FSharp.Core/prim-types.fs b/src/FSharp.Core/prim-types.fs index a885a666498..1f9fb73203e 100644 --- a/src/FSharp.Core/prim-types.fs +++ b/src/FSharp.Core/prim-types.fs @@ -7299,11 +7299,12 @@ namespace Microsoft.FSharp.Core namespace Microsoft.FSharp.Control open System + open System.Diagnostics.CodeAnalysis open Microsoft.FSharp.Core open Microsoft.FSharp.Core.Operators module LazyExtensions = - type Lazy<'T> with + type Lazy<[]'T> with [] // give the extension member a 'nice', unmangled compiled name, unique within this module static member Create(creator : unit -> 'T) : Lazy<'T> = let creator = Func<'T>(creator) diff --git a/src/FSharp.Core/prim-types.fsi b/src/FSharp.Core/prim-types.fsi index d29c4067c36..19acb8468c9 100644 --- a/src/FSharp.Core/prim-types.fsi +++ b/src/FSharp.Core/prim-types.fsi @@ -6144,6 +6144,7 @@ namespace Microsoft.FSharp.Core namespace Microsoft.FSharp.Control + open System.Diagnostics.CodeAnalysis open Microsoft.FSharp.Core /// Extensions related to Lazy values. @@ -6152,7 +6153,7 @@ namespace Microsoft.FSharp.Control [] module LazyExtensions = - type System.Lazy<'T> with + type System.Lazy<[]'T> with /// Creates a lazy computation that evaluates to the result of the given function when forced. /// diff --git a/tests/AheadOfTime/Trimming/Program.fs b/tests/AheadOfTime/Trimming/Program.fs index fbdda4cfdd4..f67c31a0013 100644 --- a/tests/AheadOfTime/Trimming/Program.fs +++ b/tests/AheadOfTime/Trimming/Program.fs @@ -9365,6 +9365,20 @@ module NonStructuralComparisonOverTimeSpanDirect = do check "test9407" (NonStructuralComparison.hash 11L) (Operators.hash 11L) do check "test9408" (NonStructuralComparison.hash 11UL) (Operators.hash 11UL) +let testLazySimple () = + let f23 () = let z = lazy (12345) in z.Force() + check "lazy_simple" 12345 (f23()) + +let testSeqWithTryFinally () = + let result = + seq { + try + yield 1 + yield 2 + with + | ex -> () + } |> Seq.toList + check "seq_try_with" [1; 2] result [] let main _ = @@ -9385,6 +9399,8 @@ let main _ = PercentAPublicTests.tests () PercentAInternalTests.tests () ClassWithEvents.testWithEventClass () + testLazySimple () + testSeqWithTryFinally () match !failures with | [] -> diff --git a/tests/AheadOfTime/Trimming/check.ps1 b/tests/AheadOfTime/Trimming/check.ps1 index 79b57bb15f8..ec64b57863f 100644 --- a/tests/AheadOfTime/Trimming/check.ps1 +++ b/tests/AheadOfTime/Trimming/check.ps1 @@ -1,15 +1,19 @@ -function CheckTrim($root, $tfm, $outputfile, $expected_len) { +function CheckTrim($root, $tfm, $outputfile, $expected_len, $callerLineNumber) { Write-Host "Publish and Execute: ${tfm} - ${root}" Write-Host "Expecting ${expected_len} for ${outputfile}" + $errors = @() + $scriptFile = $PSCommandPath + $cwd = Get-Location Set-Location (Join-Path $PSScriptRoot "${root}") $build_output = dotnet publish -restore -c release -f:$tfm "${root}.fsproj" -bl:"../../../../artifacts/log/Release/AheadOfTime/Trimming/${root}_${tfm}.binlog" Set-Location ${cwd} if ($LASTEXITCODE -ne 0) { - Write-Error "Build failed with exit code ${LASTEXITCODE}" - Write-Error "${build_output}" -ErrorAction Stop + $errors += "Build failed with exit code ${LASTEXITCODE}" + Write-Host "##vso[task.logissue type=error;sourcepath=${scriptFile};linenumber=${callerLineNumber}]Build failed for ${root} with exit code ${LASTEXITCODE}" + return $errors } $process = Start-Process -FilePath $(Join-Path $PSScriptRoot "${root}\bin\release\${tfm}\win-x64\publish\${root}.exe") -Wait -NoNewWindow -PassThru -RedirectStandardOutput $(Join-Path $PSScriptRoot "output.txt") @@ -17,17 +21,19 @@ function CheckTrim($root, $tfm, $outputfile, $expected_len) { # Checking that the test passed $output = Get-Content $(Join-Path $PSScriptRoot output.txt) $expected = "All tests passed" - if ($LASTEXITCODE -ne 0) + if ($process.ExitCode -ne 0) { - Write-Error "Test failed with exit code ${LASTEXITCODE}" -ErrorAction Stop + $errors += "Test failed with exit code $($process.ExitCode)" + Write-Host "##vso[task.logissue type=error;sourcepath=${scriptFile};linenumber=${callerLineNumber}]Test execution failed for ${root} with exit code $($process.ExitCode)" } - if ($output -eq $expected) + elseif ($output -ne $expected) { - Write-Host "Test passed" + $errors += "Test failed with unexpected output: Expected '${expected}', Actual '${output}'" + Write-Host "##vso[task.logissue type=error;sourcepath=${scriptFile};linenumber=${callerLineNumber}]Test failed for ${root} with unexpected output: Expected '${expected}', Actual '${output}'" } else { - Write-Error "Test failed with unexpected output:`nExpected:`n`t${expected}`nActual`n`t${output}" -ErrorAction Stop + Write-Host "Test passed" } # Checking that the trimmed outputfile binary is of expected size (needs adjustments if test is updated). @@ -39,24 +45,46 @@ function CheckTrim($root, $tfm, $outputfile, $expected_len) { } elseif ($file_len -ne $expected_len) { - Write-Error "Test failed with unexpected ${tfm} - trimmed ${outputfile} length:`nExpected:`n`t${expected_len} Bytes`nActual:`n`t${file_len} Bytes`nEither codegen or trimming logic have changed. Please investigate and update expected dll size or report an issue." -ErrorAction Stop + $errors += "Test failed with unexpected ${tfm} - trimmed ${outputfile} length: Expected ${expected_len} Bytes, Actual ${file_len} Bytes" + Write-Host "##vso[task.logissue type=error;sourcepath=${scriptFile};linenumber=${callerLineNumber}]Trimmed ${outputfile} size mismatch for ${root}: Expected ${expected_len} Bytes, Actual ${file_len} Bytes. Either codegen or trimming logic have changed. Please investigate and update expected dll size or report an issue." } $fileBeforePublish = Get-Item (Join-Path $PSScriptRoot "${root}\bin\release\${tfm}\win-x64\${outputfile}") $sizeBeforePublish = $fileBeforePublish.Length $sizeDiff = $sizeBeforePublish - $file_len Write-Host "Size of ${tfm} - ${outputfile} before publish: ${sizeBeforePublish} Bytes, which means the diff is ${sizeDiff} Bytes" + + return $errors } # NOTE: Trimming now errors out on desktop TFMs, as shown below: # error NETSDK1124: Trimming assemblies requires .NET Core 3.0 or higher. +$allErrors = @() + # Check net9.0 trimmed assemblies -CheckTrim -root "SelfContained_Trimming_Test" -tfm "net9.0" -outputfile "FSharp.Core.dll" -expected_len 300032 +$allErrors += CheckTrim -root "SelfContained_Trimming_Test" -tfm "net9.0" -outputfile "FSharp.Core.dll" -expected_len 311296 -callerLineNumber 66 # Check net9.0 trimmed assemblies with static linked FSharpCore -CheckTrim -root "StaticLinkedFSharpCore_Trimming_Test" -tfm "net9.0" -outputfile "StaticLinkedFSharpCore_Trimming_Test.dll" -expected_len 9154048 +$allErrors += CheckTrim -root "StaticLinkedFSharpCore_Trimming_Test" -tfm "net9.0" -outputfile "StaticLinkedFSharpCore_Trimming_Test.dll" -expected_len 9169408 -callerLineNumber 69 # Check net9.0 trimmed assemblies with F# metadata resources removed -CheckTrim -root "FSharpMetadataResource_Trimming_Test" -tfm "net9.0" -outputfile "FSharpMetadataResource_Trimming_Test.dll" -expected_len 7607296 +$allErrors += CheckTrim -root "FSharpMetadataResource_Trimming_Test" -tfm "net9.0" -outputfile "FSharpMetadataResource_Trimming_Test.dll" -expected_len 7609344 -callerLineNumber 72 + +# Report all errors and exit with failure if any occurred +if ($allErrors.Count -gt 0) { + Write-Host "" + Write-Host "============================================" + Write-Host "TRIMMING TESTS FAILED" + Write-Host "============================================" + Write-Host "Total errors: $($allErrors.Count)" + foreach ($err in $allErrors) { + Write-Error $err + } + exit 1 +} +Write-Host "" +Write-Host "============================================" +Write-Host "ALL TRIMMING TESTS PASSED" +Write-Host "============================================"