Skip to content

Commit 15ac410

Browse files
[main] Source code updates from dotnet/fsharp (#5182)
Co-authored-by: dotnet-maestro[bot] <dotnet-maestro[bot]@users.noreply.github.com>
1 parent 3451f7f commit 15ac410

60 files changed

Lines changed: 595 additions & 354 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/fsharp/.config/service-branch-merge.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,18 @@
1616
"release/dev18.0": {
1717
"MergeToBranch": "main",
1818
"ExtraSwitches": "-QuietComments"
19+
},
20+
"main": {
21+
"MergeToBranch": "feature/net11-scouting",
22+
"ExtraSwitches": "-QuietComments",
23+
"ResetToTargetPaths": [
24+
"global.json",
25+
"eng/Version.Details.xml",
26+
"eng/Version.Details.props",
27+
"eng/Versions.props",
28+
"eng/common/**",
29+
"eng/TargetFrameworks.props"
30+
]
1931
}
2032
}
2133
}

src/fsharp/.github/skills/pr-build-status/scripts/Get-PrBuildIds.ps1

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,12 @@
1919
./Get-PrBuildIds.ps1 -PrNumber 33251 -Repo "dotnet/fsharp"
2020
2121
.OUTPUTS
22-
Array of objects with Pipeline, BuildId, State, and Link properties.
22+
Array of objects with Pipeline, BuildId, State, Detail, and Link properties.
23+
The State represents the worst-case state across all jobs in the build:
24+
- FAILURE if any job failed
25+
- IN_PROGRESS if any job is still running or queued
26+
- SUCCESS if all jobs completed successfully
27+
The Detail field shows the count of jobs in each state.
2328
#>
2429

2530
[CmdletBinding()]
@@ -60,6 +65,30 @@ $builds = $checks | Where-Object { $_.link -match "dev\.azure\.com" } | ForEach-
6065
State = $_.state
6166
Link = $_.link
6267
}
63-
} | Sort-Object -Property Pipeline, BuildId -Unique
68+
} | Group-Object BuildId | ForEach-Object {
69+
$jobs = $_.Group
70+
$states = $jobs | Select-Object -ExpandProperty State -Unique
71+
72+
# Determine overall state (worst case wins)
73+
$overall = if ($states -contains "FAILURE") {
74+
"FAILURE"
75+
}
76+
elseif ($states -contains "IN_PROGRESS" -or $states -contains "QUEUED") {
77+
"IN_PROGRESS"
78+
}
79+
else {
80+
"SUCCESS"
81+
}
82+
83+
$first = $jobs | Select-Object -First 1
84+
85+
[PSCustomObject]@{
86+
Pipeline = $first.Pipeline
87+
BuildId = $first.BuildId
88+
State = $overall
89+
Detail = ($jobs | Group-Object State | ForEach-Object { "$($_.Count) $($_.Name)" }) -join ", "
90+
Link = ($first.Link -replace "\&view=.*", "")
91+
}
92+
}
6493

6594
$builds

src/fsharp/docs/release-notes/.FSharp.Compiler.Service/10.0.300.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
### Fixed
22

3+
* Fix strong name signature size to align with Roslyn for public signing ([Issue #17451](https://github.com/dotnet/fsharp/issues/17451), [PR #19242](https://github.com/dotnet/fsharp/pull/19242))
34
* Nullness: Fix UoM ToString returning `string | null` for value types. ([Issue #17539](https://github.com/dotnet/fsharp/issues/17539), [PR #19262](https://github.com/dotnet/fsharp/pull/19262))
45
* Nullness: Fix pipe operator nullness warning location to point at nullable argument. ([Issue #18013](https://github.com/dotnet/fsharp/issues/18013), [PR #19262](https://github.com/dotnet/fsharp/pull/19262))
56
* Nullness: Fix false positive warning when passing non-null AllowNullLiteral constructor result. ([Issue #18021](https://github.com/dotnet/fsharp/issues/18021), [PR #19262](https://github.com/dotnet/fsharp/pull/19262))

src/fsharp/docs/release-notes/.FSharp.Core/10.0.300.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
### Fixed
22

3+
* Optimize Set.intersect performance symmetry and preserve identity from the first set argument. ([PR #19291](https://github.com/dotnet/fsharp/pull/19291)) (Fixes #19139)
34
* Fix anonymous record field ordering in LINQ expression conversion to produce consistent expression trees regardless of field declaration order. ([Issue #11131](https://github.com/dotnet/fsharp/issues/11131), [Issue #15648](https://github.com/dotnet/fsharp/issues/15648))
45
* Fix array indexing in LINQ expressions to generate proper array index expressions instead of GetArray method calls, enabling LINQ providers like Azure Cosmos DB to translate array access. ([Issue #16918](https://github.com/dotnet/fsharp/issues/16918))
56
* Fix tuple join conditions and groupBy operations to properly compare tuple keys using structural equality. AnonymousObject types now implement Equals and GetHashCode, enabling inline tuple joins like `join b on ((a.Id1, a.Id2) = (b.Id1, b.Id2))` to work correctly. ([Issue #7885](https://github.com/dotnet/fsharp/issues/7885), [Issue #47](https://github.com/dotnet/fsharp/issues/47))
67
* Fix tuple/multi-value projections in queries to use Queryable.Select instead of Enumerable.Select when the source is IQueryable, preserving query composition and enabling async operations like ToListAsync() in Entity Framework Core. ([Issue #3782](https://github.com/dotnet/fsharp/issues/3782), [Issue #15133](https://github.com/dotnet/fsharp/issues/15133))
78
* Fix EvaluateQuotation to handle Sequential expressions, void method calls (unit return), and other patterns that were previously throwing NotSupportedException. Also properly handles unit-returning expressions by using Action delegates instead of Func delegates. ([Issue #19099](https://github.com/dotnet/fsharp/issues/19099))
89
* Fix query conditionals without else branch (if-then only) that were causing type mismatch errors. Now properly extracts element type from IQueryable for creating empty sequences. ([Issue #3445](https://github.com/dotnet/fsharp/issues/3445))
10+
* Ensure culture-independent parsing of .NET-style interpolated string holes. ([Issue #19367](https://github.com/dotnet/fsharp/issues/19367), [PR #19370](https://github.com/dotnet/fsharp/pull/19370))
911

1012
### Added
1113

src/fsharp/docs/release-notes/.VisualStudio/18.vNext.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,5 @@
66
* Improve static compilation of state machines. ([PR #19297](https://github.com/dotnet/fsharp/pull/19297))
77

88
### Changed
9+
10+
* Rename "inline hints" to "inlay hints" in VS options for consistency with industry terminology. ([PR #19318](https://github.com/dotnet/fsharp/pull/19318))

src/fsharp/src/Compiler/AbstractIL/ilsign.fs

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
1+
// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
22

33
module internal FSharp.Compiler.AbstractIL.StrongNameSign
44

@@ -301,19 +301,28 @@ let signStream stream keyBlob =
301301
patchSignature stream peReader signature
302302

303303
let signatureSize (pk: byte array) =
304-
if pk.Length < 25 then
304+
if obj.ReferenceEquals(pk, null) || pk.Length < 16 then
305305
raise (CryptographicException(getResourceString (FSComp.SR.ilSignInvalidPKBlob ())))
306-
307-
let mutable reader = BlobReader pk
308-
reader.ReadBigInteger 12 |> ignore // Skip CLRHeader
309-
reader.ReadBigInteger 8 |> ignore // Skip BlobHeader
310-
let magic = reader.ReadInt32() // Read magic
311-
312-
if not (magic = RSA_PRIV_MAGIC || magic = RSA_PUB_MAGIC) then // RSAPubKey.magic
313-
raise (CryptographicException(getResourceString (FSComp.SR.ilSignInvalidPKBlob ())))
314-
315-
let x = reader.ReadInt32() / 8
316-
x
306+
else
307+
let tryReadBitLen (offset: int) =
308+
if pk.Length >= offset + 12 then
309+
let mutable reader = BlobReader pk
310+
reader._offset <- offset
311+
let magic = reader.ReadInt32()
312+
313+
if magic = RSA_PUB_MAGIC || magic = RSA_PRIV_MAGIC then
314+
let bitLen = reader.ReadInt32()
315+
Some(bitLen / 8)
316+
else
317+
None
318+
else
319+
None
320+
321+
// Try offset 8: RSAPUBKEY header in a raw key blob (no CLR header)
322+
// Try offset 20: RSAPUBKEY header in a CLR key blob (12-byte CLR header + 8-byte BLOBHEADER)
323+
[ 8; 20 ]
324+
|> List.tryPick tryReadBitLen
325+
|> Option.defaultWith (fun () -> raise (CryptographicException(getResourceString (FSComp.SR.ilSignInvalidPKBlob ()))))
317326

318327
// Returns a CLR Format Blob public key
319328
let getPublicKeyForKeyPair keyBlob =

src/fsharp/src/FSharp.Core/printf.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ module internal PrintfImpl =
209209
let parseInterpolatedHoleDotNetFormat typeChar (s: string) (i: byref<int>) =
210210
if typeChar = 'P' then
211211
if i < s.Length && s.[i] = '(' then
212-
let i2 = s.IndexOf(")", i)
212+
let i2 = s.IndexOf(')', i)
213213
if i2 = -1 then
214214
ValueNone
215215
else

src/fsharp/src/FSharp.Core/set.fs

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,24 @@ module internal SetTree =
267267
elif c = 0 then true
268268
else mem comparer k tn.Right
269269

270+
let rec tryGet (comparer: IComparer<'T>) k (t: SetTree<'T>) =
271+
if isEmpty t then
272+
ValueNone
273+
else
274+
let c = comparer.Compare(k, t.Key)
275+
276+
if t.Height = 1 then
277+
if c = 0 then
278+
ValueSome t.Key
279+
else
280+
ValueNone
281+
else
282+
let tn = asNode t
283+
284+
if c < 0 then tryGet comparer k tn.Left
285+
elif c = 0 then ValueSome tn.Key
286+
else tryGet comparer k tn.Right
287+
270288
let rec iter f (t: SetTree<'T>) =
271289
if isEmpty t then
272290
()
@@ -391,6 +409,24 @@ module internal SetTree =
391409

392410
balance comparer (union comparer t2n.Left lo) t2n.Key (union comparer t2n.Right hi)
393411

412+
let rec intersectionAuxFromSmall comparer a (t: SetTree<'T>) acc =
413+
if isEmpty t then
414+
acc
415+
else if t.Height = 1 then
416+
match tryGet comparer t.Key a with
417+
| ValueSome v -> add comparer v acc
418+
| ValueNone -> acc
419+
else
420+
let tn = asNode t
421+
let acc = intersectionAuxFromSmall comparer a tn.Right acc
422+
423+
let acc =
424+
match tryGet comparer tn.Key a with
425+
| ValueSome v -> add comparer v acc
426+
| ValueNone -> acc
427+
428+
intersectionAuxFromSmall comparer a tn.Left acc
429+
394430
let rec intersectionAux comparer b (t: SetTree<'T>) acc =
395431
if isEmpty t then
396432
acc
@@ -412,7 +448,13 @@ module internal SetTree =
412448
intersectionAux comparer b tn.Left acc
413449

414450
let intersection comparer a b =
415-
intersectionAux comparer b a empty
451+
let h1 = height a
452+
let h2 = height b
453+
454+
if h1 <= h2 then
455+
intersectionAux comparer b a empty
456+
else
457+
intersectionAuxFromSmall comparer a b empty
416458

417459
let partition1 comparer f k (acc1, acc2) =
418460
if f k then
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// Copyright (c) Microsoft Corporation. All Rights Reserved.
2+
3+
4+
namespace CompilerOptions.Fsc
5+
6+
open System
7+
open System.IO
8+
open Xunit
9+
open FSharp.Test
10+
open FSharp.Test.Compiler
11+
12+
module publicsign =
13+
14+
/// <summary>
15+
/// Tests that --publicsign with a raw key blob (sha1full.snk) produces a non-empty PublicKeyToken.
16+
/// This test specifically exercises the Offset 8 code path in the compiler's public signing logic,
17+
/// avoiding the KeyPair/Offset 20 path, by using --publicsign --keyfile with a raw SNK file.
18+
/// </summary>
19+
[<Fact>]
20+
let ``--publicsign with raw key blob (sha1full.snk) produces a non-empty PublicKeyToken`` () =
21+
let source =
22+
"""
23+
module TestModule
24+
let x = 42
25+
"""
26+
27+
// Resolve the path to sha1full.snk relative to this source file's directory
28+
// Path: tests/FSharp.Compiler.ComponentTests/CompilerOptions/fsc/misc -> tests/fsharp/core/signedtests/sha1full.snk
29+
let snkPath: string =
30+
Path.Combine(__SOURCE_DIRECTORY__, "..", "..", "..", "..", "fsharp", "core", "signedtests", "sha1full.snk")
31+
32+
// Compile with --publicsign+ and --keyfile to exercise the Offset 8 code path
33+
let result =
34+
source
35+
|> FSharp
36+
|> asLibrary
37+
|> withFileName "PublicSignTest.fs"
38+
|> withOptions ["--publicsign+"; sprintf "--keyfile:%s" snkPath]
39+
|> compile
40+
41+
result |> shouldSucceed |> ignore
42+
43+
// Safely extract the output DLL path using pattern matching
44+
let outputDll: string =
45+
match result.OutputPath with
46+
| Some path -> path
47+
| None -> failwith "Compilation did not produce an output DLL"
48+
49+
// Read the compiled DLL bytes for verification
50+
let dllBytes: byte[] = File.ReadAllBytes(outputDll)
51+
52+
// RSA magic number patterns: RSA1 = 0x52 0x53 0x41 0x31, RSA2 = 0x52 0x53 0x41 0x32
53+
// These indicate that RSA key material was embedded in the assembly
54+
let rsa1Magic: byte[] = [| 0x52uy; 0x53uy; 0x41uy; 0x31uy |]
55+
let rsa2Magic: byte[] = [| 0x52uy; 0x53uy; 0x41uy; 0x32uy |]
56+
57+
/// <summary>
58+
/// Searches for RSA magic bytes in the byte array.
59+
/// Returns true if the magic pattern is found, indicating RSA key material is present.
60+
/// </summary>
61+
let containsRSAMagic (data: byte[]) (magic: byte[]): bool =
62+
if data.Length < magic.Length then
63+
false
64+
else
65+
let mutable found = false
66+
for i in 0 .. (data.Length - magic.Length) do
67+
if not found &&
68+
data.[i] = magic.[0] &&
69+
data.[i + 1] = magic.[1] &&
70+
data.[i + 2] = magic.[2] &&
71+
data.[i + 3] = magic.[3] then
72+
found <- true
73+
found
74+
75+
// Verify that the compiled DLL contains RSA magic bytes, confirming the public key blob was embedded
76+
let hasRSAMagic: bool =
77+
containsRSAMagic dllBytes rsa1Magic || containsRSAMagic dllBytes rsa2Magic
78+
79+
Assert.True(
80+
hasRSAMagic,
81+
"Compiled DLL should contain RSA magic bytes (RSA1 or RSA2) indicating public key blob was embedded by compiler with --publicsign"
82+
)

src/fsharp/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,7 @@
399399
<Compile Include="CompilerOptions\fsc\highentropyva.fs" />
400400
<Compile Include="CompilerOptions\fsc\langversion.fs" />
401401
<Compile Include="CompilerOptions\fsc\misc\misc.fs" />
402+
<Compile Include="CompilerOptions\fsc\misc\PublicSign.fs" />
402403
<Compile Include="CompilerOptions\fsc\misc\utf8output.fs" />
403404
<Compile Include="CompilerOptions\fsc\noframework\noframework.fs" />
404405
<Compile Include="CompilerOptions\fsc\platform\platform.fs" />

0 commit comments

Comments
 (0)