Skip to content

Commit 0daa0d6

Browse files
committed
Merge branch 'main' into witnesses
2 parents d845820 + 8f441c4 commit 0daa0d6

File tree

16 files changed

+146
-141
lines changed

16 files changed

+146
-141
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
### Fixed
2+
3+
* 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))

eng/Version.Details.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ This file should be imported by eng/Versions.props
2727
<MicrosoftCodeAnalysisFeaturesPackageVersion>5.0.0-2.25480.7</MicrosoftCodeAnalysisFeaturesPackageVersion>
2828
<MicrosoftVisualStudioLanguageServicesPackageVersion>5.0.0-2.25480.7</MicrosoftVisualStudioLanguageServicesPackageVersion>
2929
<!-- dotnet/arcade dependencies -->
30-
<MicrosoftDotNetArcadeSdkPackageVersion>11.0.0-beta.25575.1</MicrosoftDotNetArcadeSdkPackageVersion>
30+
<MicrosoftDotNetArcadeSdkPackageVersion>11.0.0-beta.25601.2</MicrosoftDotNetArcadeSdkPackageVersion>
3131
<!-- _git/dotnet-optimization dependencies -->
3232
<optimizationlinuxarm64MIBCRuntimePackageVersion>1.0.0-prerelease.25502.1</optimizationlinuxarm64MIBCRuntimePackageVersion>
3333
<optimizationlinuxx64MIBCRuntimePackageVersion>1.0.0-prerelease.25502.1</optimizationlinuxx64MIBCRuntimePackageVersion>

eng/Version.Details.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,9 @@
7676
</Dependency>
7777
</ProductDependencies>
7878
<ToolsetDependencies>
79-
<Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="11.0.0-beta.25575.1">
79+
<Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="11.0.0-beta.25601.2">
8080
<Uri>https://github.com/dotnet/arcade</Uri>
81-
<Sha>e29f11a331730bd4f51024ba83fa067d2ab80ca9</Sha>
81+
<Sha>846929727a388f2b1fd3ccf21f67694f44b91b4d</Sha>
8282
</Dependency>
8383
<Dependency Name="optimization.windows_nt-x64.MIBC.Runtime" Version="1.0.0-prerelease.25502.1">
8484
<Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-optimization</Uri>

global.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
"perl": "5.38.2.2"
2323
},
2424
"msbuild-sdks": {
25-
"Microsoft.DotNet.Arcade.Sdk": "11.0.0-beta.25575.1",
25+
"Microsoft.DotNet.Arcade.Sdk": "11.0.0-beta.25601.2",
2626
"Microsoft.DotNet.Helix.Sdk": "8.0.0-beta.23255.2"
2727
}
2828
}

src/FSharp.Core/prim-types.fs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7299,11 +7299,12 @@ namespace Microsoft.FSharp.Core
72997299
namespace Microsoft.FSharp.Control
73007300

73017301
open System
7302+
open System.Diagnostics.CodeAnalysis
73027303
open Microsoft.FSharp.Core
73037304
open Microsoft.FSharp.Core.Operators
73047305

73057306
module LazyExtensions =
7306-
type Lazy<'T> with
7307+
type Lazy<[<DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)>]'T> with
73077308
[<CompiledName("Create")>] // give the extension member a 'nice', unmangled compiled name, unique within this module
73087309
static member Create(creator : unit -> 'T) : Lazy<'T> =
73097310
let creator = Func<'T>(creator)

src/FSharp.Core/prim-types.fsi

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6144,6 +6144,7 @@ namespace Microsoft.FSharp.Core
61446144

61456145
namespace Microsoft.FSharp.Control
61466146

6147+
open System.Diagnostics.CodeAnalysis
61476148
open Microsoft.FSharp.Core
61486149

61496150
/// <summary>Extensions related to Lazy values.</summary>
@@ -6152,7 +6153,7 @@ namespace Microsoft.FSharp.Control
61526153
[<AutoOpen>]
61536154
module LazyExtensions =
61546155

6155-
type System.Lazy<'T> with
6156+
type System.Lazy<[<DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)>]'T> with
61566157

61576158
/// <summary>Creates a lazy computation that evaluates to the result of the given function when forced.</summary>
61586159
///

tests/AheadOfTime/Trimming/Program.fs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9365,6 +9365,20 @@ module NonStructuralComparisonOverTimeSpanDirect =
93659365
do check "test9407" (NonStructuralComparison.hash 11L) (Operators.hash 11L)
93669366
do check "test9408" (NonStructuralComparison.hash 11UL) (Operators.hash 11UL)
93679367

9368+
let testLazySimple () =
9369+
let f23 () = let z = lazy (12345) in z.Force()
9370+
check "lazy_simple" 12345 (f23())
9371+
9372+
let testSeqWithTryFinally () =
9373+
let result =
9374+
seq {
9375+
try
9376+
yield 1
9377+
yield 2
9378+
with
9379+
| ex -> ()
9380+
} |> Seq.toList
9381+
check "seq_try_with" [1; 2] result
93689382

93699383
[<EntryPoint>]
93709384
let main _ =
@@ -9385,6 +9399,8 @@ let main _ =
93859399
PercentAPublicTests.tests ()
93869400
PercentAInternalTests.tests ()
93879401
ClassWithEvents.testWithEventClass ()
9402+
testLazySimple ()
9403+
testSeqWithTryFinally ()
93889404

93899405
match !failures with
93909406
| [] ->
Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,39 @@
1-
function CheckTrim($root, $tfm, $outputfile, $expected_len) {
1+
function CheckTrim($root, $tfm, $outputfile, $expected_len, $callerLineNumber) {
22
Write-Host "Publish and Execute: ${tfm} - ${root}"
33
Write-Host "Expecting ${expected_len} for ${outputfile}"
44

5+
$errors = @()
6+
$scriptFile = $PSCommandPath
7+
58
$cwd = Get-Location
69
Set-Location (Join-Path $PSScriptRoot "${root}")
710
$build_output = dotnet publish -restore -c release -f:$tfm "${root}.fsproj" -bl:"../../../../artifacts/log/Release/AheadOfTime/Trimming/${root}_${tfm}.binlog"
811
Set-Location ${cwd}
912
if ($LASTEXITCODE -ne 0)
1013
{
11-
Write-Error "Build failed with exit code ${LASTEXITCODE}"
12-
Write-Error "${build_output}" -ErrorAction Stop
14+
$errors += "Build failed with exit code ${LASTEXITCODE}"
15+
Write-Host "##vso[task.logissue type=error;sourcepath=${scriptFile};linenumber=${callerLineNumber}]Build failed for ${root} with exit code ${LASTEXITCODE}"
16+
return $errors
1317
}
1418

1519
$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")
1620

1721
# Checking that the test passed
1822
$output = Get-Content $(Join-Path $PSScriptRoot output.txt)
1923
$expected = "All tests passed"
20-
if ($LASTEXITCODE -ne 0)
24+
if ($process.ExitCode -ne 0)
2125
{
22-
Write-Error "Test failed with exit code ${LASTEXITCODE}" -ErrorAction Stop
26+
$errors += "Test failed with exit code $($process.ExitCode)"
27+
Write-Host "##vso[task.logissue type=error;sourcepath=${scriptFile};linenumber=${callerLineNumber}]Test execution failed for ${root} with exit code $($process.ExitCode)"
2328
}
24-
if ($output -eq $expected)
29+
elseif ($output -ne $expected)
2530
{
26-
Write-Host "Test passed"
31+
$errors += "Test failed with unexpected output: Expected '${expected}', Actual '${output}'"
32+
Write-Host "##vso[task.logissue type=error;sourcepath=${scriptFile};linenumber=${callerLineNumber}]Test failed for ${root} with unexpected output: Expected '${expected}', Actual '${output}'"
2733
}
2834
else
2935
{
30-
Write-Error "Test failed with unexpected output:`nExpected:`n`t${expected}`nActual`n`t${output}" -ErrorAction Stop
36+
Write-Host "Test passed"
3137
}
3238

3339
# 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) {
3945
}
4046
elseif ($file_len -ne $expected_len)
4147
{
42-
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
48+
$errors += "Test failed with unexpected ${tfm} - trimmed ${outputfile} length: Expected ${expected_len} Bytes, Actual ${file_len} Bytes"
49+
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."
4350
}
4451

4552
$fileBeforePublish = Get-Item (Join-Path $PSScriptRoot "${root}\bin\release\${tfm}\win-x64\${outputfile}")
4653
$sizeBeforePublish = $fileBeforePublish.Length
4754
$sizeDiff = $sizeBeforePublish - $file_len
4855
Write-Host "Size of ${tfm} - ${outputfile} before publish: ${sizeBeforePublish} Bytes, which means the diff is ${sizeDiff} Bytes"
56+
57+
return $errors
4958
}
5059

5160
# NOTE: Trimming now errors out on desktop TFMs, as shown below:
5261
# error NETSDK1124: Trimming assemblies requires .NET Core 3.0 or higher.
5362

63+
$allErrors = @()
64+
5465
# Check net9.0 trimmed assemblies
55-
CheckTrim -root "SelfContained_Trimming_Test" -tfm "net9.0" -outputfile "FSharp.Core.dll" -expected_len 300032
66+
$allErrors += CheckTrim -root "SelfContained_Trimming_Test" -tfm "net9.0" -outputfile "FSharp.Core.dll" -expected_len 311296 -callerLineNumber 66
5667

5768
# Check net9.0 trimmed assemblies with static linked FSharpCore
58-
CheckTrim -root "StaticLinkedFSharpCore_Trimming_Test" -tfm "net9.0" -outputfile "StaticLinkedFSharpCore_Trimming_Test.dll" -expected_len 9154048
69+
$allErrors += CheckTrim -root "StaticLinkedFSharpCore_Trimming_Test" -tfm "net9.0" -outputfile "StaticLinkedFSharpCore_Trimming_Test.dll" -expected_len 9169408 -callerLineNumber 69
5970

6071
# Check net9.0 trimmed assemblies with F# metadata resources removed
61-
CheckTrim -root "FSharpMetadataResource_Trimming_Test" -tfm "net9.0" -outputfile "FSharpMetadataResource_Trimming_Test.dll" -expected_len 7607296
72+
$allErrors += CheckTrim -root "FSharpMetadataResource_Trimming_Test" -tfm "net9.0" -outputfile "FSharpMetadataResource_Trimming_Test.dll" -expected_len 7609344 -callerLineNumber 72
73+
74+
# Report all errors and exit with failure if any occurred
75+
if ($allErrors.Count -gt 0) {
76+
Write-Host ""
77+
Write-Host "============================================"
78+
Write-Host "TRIMMING TESTS FAILED"
79+
Write-Host "============================================"
80+
Write-Host "Total errors: $($allErrors.Count)"
81+
foreach ($err in $allErrors) {
82+
Write-Error $err
83+
}
84+
exit 1
85+
}
6286

87+
Write-Host ""
88+
Write-Host "============================================"
89+
Write-Host "ALL TRIMMING TESTS PASSED"
90+
Write-Host "============================================"

tests/FSharp.Test.Utilities/FSharp.Test.Utilities.fsproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,8 @@
102102
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="$(SystemDiagnosticsDiagnosticSourceVersion)" />
103103
</ItemGroup>
104104
<PropertyGroup>
105-
<NoWarn>$(NoWarn);NU1510</NoWarn> <!-- NU1510: Project is explicitly referencing the runtime assembly 'System.Collections.Immutable', however, if we remove it, it tries to find it on the wrong path. Also, local NoWarn does not help - This is just me trying to enforce it -->
105+
<NoWarn>$(NoWarn);NU1510;44</NoWarn> <!-- NU1510: Project is explicitly referencing the runtime assembly 'System.Collections.Immutable', however, if we remove it, it tries to find it on the wrong path. Also, local NoWarn does not help - This is just me trying to enforce it -->
106+
<!-- 44: AssemblyName.CodeBase is deprecated but needed for assembly resolution in VS integration tests -->
106107
</PropertyGroup>
107108
<ItemGroup>
108109
<PackageReference Include="System.Collections.Immutable" Version="$(SystemCollectionsImmutableVersion)" GeneratePathProperty="true" />

tests/FSharp.Test.Utilities/VSInstallDiscovery.fs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,3 +126,55 @@ module VSInstallDiscovery =
126126
| NotFound reason ->
127127
logAction $"Visual Studio installation not found: {reason}"
128128
None
129+
130+
/// Gets the VS installation directory or fails with a detailed error message.
131+
/// This is the recommended method for test scenarios that require VS to be installed.
132+
let getVSInstallDirOrFail () : string =
133+
match tryFindVSInstallation () with
134+
| Found (path, _) -> path
135+
| NotFound reason ->
136+
failwith $"Visual Studio installation not found: {reason}. Ensure VS is installed or environment variables (VSAPPIDDIR, VS*COMNTOOLS) are set."
137+
138+
/// Assembly resolver for Visual Studio test infrastructure.
139+
/// Provides centralized assembly resolution for VS integration tests.
140+
module VSAssemblyResolver =
141+
open System
142+
open System.IO
143+
open System.Reflection
144+
open System.Globalization
145+
146+
/// Adds an assembly resolver that probes Visual Studio installation directories.
147+
/// This should be called early in test initialization to ensure VS assemblies can be loaded.
148+
let addResolver () =
149+
let vsInstallDir = VSInstallDiscovery.getVSInstallDirOrFail ()
150+
151+
let probingPaths =
152+
[|
153+
Path.Combine(vsInstallDir, @"IDE\CommonExtensions\Microsoft\Editor")
154+
Path.Combine(vsInstallDir, @"IDE\PublicAssemblies")
155+
Path.Combine(vsInstallDir, @"IDE\PrivateAssemblies")
156+
Path.Combine(vsInstallDir, @"IDE\CommonExtensions\Microsoft\ManagedLanguages\VBCSharp\LanguageServices")
157+
Path.Combine(vsInstallDir, @"IDE\Extensions\Microsoft\CodeSense\Framework")
158+
Path.Combine(vsInstallDir, @"IDE")
159+
|]
160+
161+
AppDomain.CurrentDomain.add_AssemblyResolve(fun _ args ->
162+
let found () =
163+
probingPaths
164+
|> Seq.tryPick (fun p ->
165+
try
166+
let name = AssemblyName(args.Name)
167+
let codebase = Path.GetFullPath(Path.Combine(p, name.Name) + ".dll")
168+
if File.Exists(codebase) then
169+
name.CodeBase <- codebase
170+
name.CultureInfo <- Unchecked.defaultof<CultureInfo>
171+
name.Version <- Unchecked.defaultof<Version>
172+
Some name
173+
else
174+
None
175+
with _ ->
176+
None)
177+
178+
match found () with
179+
| None -> Unchecked.defaultof<Assembly>
180+
| Some name -> Assembly.Load(name))

0 commit comments

Comments
 (0)