Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
5899b74
feat(FSharp.Core): add pinned FSharpCoreShippedNetTargetFramework kno…
T-Gro Aug 6, 2026
b216325
feat(FSharp.Core): compile net10.0 target
T-Gro Aug 6, 2026
533083c
feat(FSharp.Core): pack lib/net10.0 into the shipped nupkg
T-Gro Aug 6, 2026
bdf1161
test(FSharp.Core): add dedicated net SurfaceArea baseline
T-Gro Aug 6, 2026
2f0adaf
test(FSharp.Core): assembly-level ApiCompat net-vs-ns2.1 identity gate
T-Gro Aug 6, 2026
786897d
build(FSharp.Core): add TFM #if guard audit (the #ifdef-management ask)
T-Gro Aug 6, 2026
8dff8f5
test(FSharp.Core): e2e-1 nupkg-contents + AssemblyVersion-equality ve…
Copilot Aug 6, 2026
2aab488
test(FSharp.Core): e2e-2 net-TFM consumer asset-resolution witness
Copilot Aug 6, 2026
cbd9640
test(FSharp.Core): e2e-5 net-TFM trimming + NativeAOT consumer legs
Copilot Aug 6, 2026
22e8de6
ci(FSharp.Core): wire e2e-1 nupkg verify + e2e-2 resolution witness i…
Copilot Aug 6, 2026
6c1b1bd
docs(release-notes): FSharp.Core net10.0 target framework entry
Copilot Aug 6, 2026
2bb06af
docs(release-notes): fill PR #20224 into FSharp.Core net10.0 entry
Copilot Aug 6, 2026
9c0fc9a
docs(release-notes): point net10.0 entry at PR #20229
Copilot Aug 7, 2026
e4b80c5
Merge remote-tracking branch 'origin/main' into t-gro-fsharpcore-net1…
Copilot Aug 7, 2026
944f220
test(FSharp.Core): refresh net SurfaceArea baselines for Async.RunSyn…
Copilot Aug 7, 2026
efa1b50
refactor(FSharp.Core): trim narration comments in net10.0 TFM scaffol…
Copilot Aug 7, 2026
dc2b916
refactor(tests): tighten e2e-2 consumer comments (NoBloat round 2)
Copilot Aug 7, 2026
17fc005
Compaction round 1: drop dangling plan ref + phase tag
Copilot Aug 7, 2026
f3c4ef3
Compaction round 2: dedup e2e-1 asserts, harden gates, drop dead ns2.…
Copilot Aug 7, 2026
74494f5
ci(FSharp.Core): relocate e2e-2 resolution witness to EndToEndBuildTe…
Copilot Aug 7, 2026
1db6100
harden(net10 pin): clear error on malformed pin TFM + fail-closed e2e…
Copilot Aug 7, 2026
021d62c
fix(FSharp.Core): keep in-repo consumers on netstandard2.1 (net10.0 i…
Copilot Aug 7, 2026
820e491
fix(test): e2e-2 resolves FSharp.Core from the packages root, not a f…
Copilot Aug 7, 2026
2428ddc
fix(test): e2e-2 stages FSharp.Core into a flat local feed for determ…
Copilot Aug 7, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions Directory.Build.targets
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,17 @@
<NoWarn>$(NoWarn);NU1507</NoWarn>
</PropertyGroup>

<!-- FSharp.Core additionally builds $(FSharpCoreShippedNetTargetFramework) for its shipped NuGet package
only. In-repo .NET consumers must keep binding the netstandard2.1 asset they resolved before that
target existed, so the in-box compiler/tools and their IL / surface-area baselines stay unchanged.
.NET Framework consumers resolve netstandard2.0 and are left alone; Proto ships only netstandard2.0.
Any pre-existing explicit SetTargetFramework pin is preserved. -->
<ItemGroup Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp' and '$(Configuration)' != 'Proto'">
<ProjectReference Update="@(ProjectReference)">
<SetTargetFramework Condition="'%(ProjectReference.Filename)' == 'FSharp.Core' and '%(ProjectReference.SetTargetFramework)' == ''">TargetFramework=netstandard2.1</SetTargetFramework>
</ProjectReference>
</ItemGroup>

<!-- Disable R2R when building source-only and not targeting the current SDK bundled TFM. -->
<PropertyGroup>
<PublishReadyToRun Condition="'$(DotNetBuildSourceOnly)' == 'true' and
Expand Down
36 changes: 36 additions & 0 deletions azure-pipelines-PR.yml
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,10 @@ stages:
env:
DOTNET_ROLL_FORWARD_TO_PRERELEASE: 1
displayName: Validate test projects are registered in TestSplit.fsx
- script: ./eng/common/dotnet.sh fsi eng/tests/AuditFSharpCoreTfmGuards.fsx
env:
DOTNET_ROLL_FORWARD_TO_PRERELEASE: 1
displayName: Audit FSharp.Core TFM (#if) guards use the standardized idiom

# Check whether package with current version has been published to nuget.org
# We will try to restore both FSharp.Core and FCS and if restore is _successful_, package version needs to be bumped.
Expand Down Expand Up @@ -186,6 +190,26 @@ stages:
DOTNET_ROLL_FORWARD_TO_PRERELEASE: 1
displayName: Check published package version

# Blocking gate enforcing the "net10.0 == netstandard2.1" public-surface invariant
# (mechanism documented in FSharp.Core.ApiCompat.proj).
- job: FSharpCore_ApiCompat
pool:
name: $(DncEngPublicBuildPool)
demands: ImageOverride -equals $(LinuxMachineQueueName)
steps:
- checkout: self
clean: true
- script: ./eng/common/dotnet.sh
displayName: Install .NET SDK
- script: ./eng/common/dotnet.sh build src/FSharp.Core/FSharp.Core.fsproj -c Release
env:
DOTNET_ROLL_FORWARD_TO_PRERELEASE: 1
displayName: Build FSharp.Core (all shipped TFMs, Release)
- script: ./eng/common/dotnet.sh msbuild tests/FSharp.Core.ApiCompat/FSharp.Core.ApiCompat.proj -t:ValidateFSharpCoreApiIdentity -p:Configuration=Release
env:
DOTNET_ROLL_FORWARD_TO_PRERELEASE: 1
displayName: ApiCompat net-vs-netstandard2.1 identity gate (strict, empty suppressions)


#-------------------------------------------------------------------------------------------------------------------#
# PR builds #
Expand Down Expand Up @@ -564,6 +588,18 @@ stages:
NativeToolsOnMachine: true
- script: .\tests\EndToEndBuildTests\EndToEndBuildTests.cmd -c Release
displayName: End to end build tests
- script: .\eng\common\dotnet.cmd fsi .\tests\FSharp.Core.PackageVerification\VerifyFSharpCorePackage.fsx
displayName: 'e2e-1: verify shipped FSharp.Core nupkg (lib layout, satellites, nuspec group, AssemblyVersion parity)'
- script: .\eng\common\dotnet.cmd fsi .\tests\AheadOfTime\NetTfmResolution\VerifyNetResolution.fsx
displayName: 'e2e-2: net-TFM consumer asset-resolution witness (assets.json + runtime smoke)'
workingDirectory: $(Build.SourcesDirectory)
- task: PublishPipelineArtifact@1
displayName: Publish e2e-2 resolution evidence (project.assets.json)
inputs:
targetPath: '$(Build.SourcesDirectory)/tests/AheadOfTime/NetTfmResolution/obj'
artifactName: 'e2e2 NetTfmResolution obj Attempt $(System.JobAttempt)'
continueOnError: true
condition: always()

# Publish artifacts for regression testing
- task: PublishPipelineArtifact@1
Expand Down
1 change: 1 addition & 0 deletions docs/release-notes/.FSharp.Core/11.0.100.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@

### Added

* Ship `FSharp.Core` with an additional `net10.0` target framework (next to `netstandard2.0` and `netstandard2.1`). The `net`-TFM assembly is public-surface-identical to the `netstandard2.1` one; the target version is a pinned, deliberately advanced knob. ([PR #20229](https://github.com/dotnet/fsharp/pull/20229))
* `Async.RunSynchronouslyImmediate`: runs work on the calling thread until the first asynchronous suspension (as opposed to `RunSynchronously`, which immediately offloads if not on a background and/or threadpool thread). ([Issue #1042](https://github.com/fsharp/fslang-suggestions/issues/1042), [PR #19804](https://github.com/dotnet/fsharp/pull/19804))
20 changes: 20 additions & 0 deletions eng/TargetFrameworks.props
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,26 @@

<!-- Derive major version by stripping 'net' prefix and '.0' suffix (e.g., net10.0 -> 10) -->
<FSharpNetCoreProductMajorVersion>$([System.Text.RegularExpressions.Regex]::Replace('$(FSharpNetCoreProductTargetFramework)', '^net(\d+)\.0$', '$1'))</FSharpNetCoreProductMajorVersion>

<!-- Pinned *shipped* net TFM for the FSharp.Core NuGet package. This LAGS the in-dev product TFM above and
tracks the latest STABLE released .NET. It is bumped deliberately (see docs / RFC and the plan's
"how to bump" checklist), NOT automatically with the product. Overridable via env var / CLI. -->
<FSharpCoreShippedNetTargetFramework Condition="'$(FSharpCoreShippedNetTargetFramework)' == ''">net10.0</FSharpCoreShippedNetTargetFramework>
<FSharpCoreShippedNetMajorVersion>$([System.Text.RegularExpressions.Regex]::Replace('$(FSharpCoreShippedNetTargetFramework)', '^net(\d+)\.0$', '$1'))</FSharpCoreShippedNetMajorVersion>
</PropertyGroup>

<!-- Enforce the pinned-stable invariant: the shipped FSharp.Core net TFM must be STRICTLY LESS than the
in-dev product TFM (so producing F# for net(N+1) still ships FSharp.Core targeting the stable netN).
Scoped to the FSharp.Core build/pack, the only consumer of the pin. -->
<Target Name="_ValidateFSharpCoreShippedNetTfm"
Condition="'$(MSBuildProjectName)' == 'FSharp.Core'"
BeforeTargets="Build;Pack">
<!-- Fail with a clear message if the pin is not a plain net<major>.0 TFM (e.g. a net10.0-windows
override), rather than letting the numeric comparison below throw an opaque Version parse error. -->
<Error Condition="!$([System.Text.RegularExpressions.Regex]::IsMatch('$(FSharpCoreShippedNetTargetFramework)', '^net\d+\.0$'))"
Text="FSharpCoreShippedNetTargetFramework ($(FSharpCoreShippedNetTargetFramework)) must be a plain 'netN.0' target framework (e.g. net10.0)." />
<Error Condition="!$([MSBuild]::VersionLessThan('$(FSharpCoreShippedNetMajorVersion).0', '$(FSharpNetCoreProductMajorVersion).0'))"
Text="FSharpCoreShippedNetTargetFramework ($(FSharpCoreShippedNetTargetFramework)) must be STRICTLY LESS than the in-dev product TFM ($(FSharpNetCoreProductTargetFramework)). Bump the pin only when the product advances." />
</Target>

</Project>
132 changes: 132 additions & 0 deletions eng/tests/AuditFSharpCoreTfmGuards.fsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
// Allow-list audit of the TFM (#if) guards in src/FSharp.Core (the "#ifdef management" gate).
//
// Every TFM-discriminating #if/#elif in src/FSharp.Core/**/*.{fs,fsi} must be allow-listed below by
// (<file>, <normalized guard-expr>). A non-allow-listed guard fails the audit, forcing review. This
// catches the regressions that silently mistarget the shipped net TFM:
// * bare #if NETSTANDARD2_1 -> excludes net, dropping a feature there
// * bare #if !NET -> drops a BCL polyfill on EVERY net (wrong floor)
// Standardized idioms: `#if NETSTANDARD2_1_OR_GREATER || NET` (feature on ns2.1 + all net) and
// `#if !NET5_0_OR_GREATER` / `#if !NET8_0_OR_GREATER` (polyfill below a BCL floor).
//
// Run: dotnet fsi eng/tests/AuditFSharpCoreTfmGuards.fsx [--self-test]
// Uses `git ls-files` + the .NET regex engine (not `git grep -P`, absent on macOS git builds).

open System
open System.Diagnostics
open System.Text.RegularExpressions

let scopeGlobs = [ "src/FSharp.Core/*.fs"; "src/FSharp.Core/*.fsi" ]

// The reviewed, allow-listed TFM guards after standardization. Key = (repo-relative path with '/',
// normalized guard expression). To add an entry: confirm the guard uses the idiom above, then list
// it here with a one-line justification in the PR.
let allowList : Set<string * string> =
set [
// Collection-expression support ([<CollectionBuilder>] + Create(ReadOnlySpan<_>)): present on
// netstandard2.1 and every net TFM.
"src/FSharp.Core/set.fs", "NETSTANDARD2_1_OR_GREATER || NET"
"src/FSharp.Core/set.fsi", "NETSTANDARD2_1_OR_GREATER || NET"
"src/FSharp.Core/prim-types.fs", "NETSTANDARD2_1_OR_GREATER || NET"
"src/FSharp.Core/prim-types.fsi", "NETSTANDARD2_1_OR_GREATER || NET"
// task { use! ... } over IAsyncDisposable (TryFinallyAsync / TaskBuilderBase.Using): ns2.1 + net.
"src/FSharp.Core/tasks.fs", "NETSTANDARD2_1 || NET"
"src/FSharp.Core/tasks.fsi", "NETSTANDARD2_1 || NET"
// BCL polyfills that must be dropped once the BCL provides the type:
// DynamicallyAccessedMembers -> floor at NET5
// CollectionBuilder/ScopedRef -> floor at NET8
"src/FSharp.Core/prim-types.fs", "!NET5_0_OR_GREATER"
"src/FSharp.Core/prim-types.fsi", "!NET5_0_OR_GREATER"
"src/FSharp.Core/prim-types.fs", "!NET8_0_OR_GREATER"
"src/FSharp.Core/prim-types.fsi", "!NET8_0_OR_GREATER"
]

// A guard expression is "TFM-discriminating" if it mentions any of these tokens.
let tfmToken =
Regex(@"NETSTANDARD|NETCOREAPP|NETFRAMEWORK|NET\d|(?:^|[^0-9A-Za-z_])!?NET(?:[^0-9A-Za-z_]|$)",
RegexOptions.Compiled)

let guardLine = Regex(@"^\s*#(?:if|elif)\s+(?<expr>.*\S)\s*$", RegexOptions.Compiled)

let normalize (s: string) = Regex.Replace(s, @"\s+", " ").Trim()

let runGit (args: string) =
let psi = ProcessStartInfo("git", args, RedirectStandardOutput = true, UseShellExecute = false)
use p = Process.Start psi
let out = p.StandardOutput.ReadToEnd()
p.WaitForExit()
if p.ExitCode <> 0 then failwithf "git %s failed (exit %d)" args p.ExitCode
out

let trackedFiles () =
runGit ("ls-files -- " + String.Join(" ", scopeGlobs))
|> fun s -> s.Split([| '\n'; '\r' |], StringSplitOptions.RemoveEmptyEntries)
|> Array.map (fun p -> p.Trim())
|> Array.filter (fun p -> p <> "")

// Returns the TFM guards found in the given lines as (normalizedExpr) values.
let tfmGuardsIn (lines: string[]) =
lines
|> Array.choose (fun ln ->
let m = guardLine.Match ln
if m.Success then
let expr = normalize m.Groups.["expr"].Value
if tfmToken.IsMatch expr then Some expr else None
else None)

let auditRepo () =
let violations =
[ for file in trackedFiles () do
let path = file.Replace('\\', '/')
for expr in tfmGuardsIn (IO.File.ReadAllLines file) do
if not (allowList.Contains(path, expr)) then
yield path, expr ]
if violations.IsEmpty then
printfn "FSharp.Core TFM #if guard audit: OK (%d allow-listed guards)." allowList.Count
0
else
eprintfn "FSharp.Core TFM #if guard audit: FAILED. Non-allow-listed TFM guard(s):"
for (path, expr) in violations do
eprintfn " %s: #if %s" path expr
eprintfn ""
eprintfn "Use the standardized idiom (see eng/tests/AuditFSharpCoreTfmGuards.fsx header):"
eprintfn " * feature on ns2.1 + all net: #if NETSTANDARD2_1_OR_GREATER || NET"
eprintfn " * polyfill below a BCL floor: #if !NET8_0_OR_GREATER (or !NET5_0_OR_GREATER)"
eprintfn "A bare '#if NETSTANDARD2_1' or '#if !NET' is almost always wrong for the shipped net TFM."
eprintfn "If the new guard is a legitimate use of the idiom, add its <file>:<expr> to the allow-list."
1

// Self-test: prove the detector actually bites on the known anti-patterns and passes the good idioms.
let selfTest () =
let mutable ok = true
let check desc (expr: string) shouldBeTfm =
// Drive the REAL extractor (guardLine -> normalize -> tfmToken) via a synthetic #if line, so a
// drift in the #if/#elif line parser cannot silently green this self-test while the audit goes blind.
let detected = tfmGuardsIn [| sprintf "#if %s" expr |] |> Array.isEmpty |> not
if detected <> shouldBeTfm then
ok <- false
eprintfn " self-test FAIL: %s -> detected=%b, expected %b" desc detected shouldBeTfm
// These MUST be recognized as TFM guards (and, not being allow-listed for a fake file, would fail):
check "bare NETSTANDARD2_1" "NETSTANDARD2_1" true
check "bare !NET" "!NET" true
check "NET5_0_OR_GREATER" "NET5_0_OR_GREATER" true
check "NETCOREAPP" "NETCOREAPP" true
check "good idiom || NET" "NETSTANDARD2_1_OR_GREATER || NET" true
// These are NOT TFM guards and must be ignored by the audit:
check "DEBUG" "DEBUG" false
check "FX_NO_SOMETHING" "FX_NO_SOMETHING" false
// The line parser must recognize #elif, not only #if.
if tfmGuardsIn [| "#elif NETSTANDARD2_1_OR_GREATER || NET" |] |> Array.isEmpty then
ok <- false; eprintfn " self-test FAIL: #elif TFM guard not detected"
// Allow-list containment behaves as expected:
if not (allowList.Contains("src/FSharp.Core/tasks.fs", "NETSTANDARD2_1 || NET")) then
ok <- false; eprintfn " self-test FAIL: known-good pair not in allow-list"
if allowList.Contains("src/FSharp.Core/tasks.fs", "NETSTANDARD2_1") then
ok <- false; eprintfn " self-test FAIL: bare NETSTANDARD2_1 unexpectedly allow-listed"
if ok then
printfn "FSharp.Core TFM #if guard audit self-test: OK."; 0
else
eprintfn "FSharp.Core TFM #if guard audit self-test: FAILED."; 1

let args = Environment.GetCommandLineArgs()
let exitCode = if Array.contains "--self-test" args then selfTest () else auditRepo ()
exit exitCode
8 changes: 7 additions & 1 deletion src/FSharp.Core/FSharp.Core.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFrameworks Condition="'$(Configuration)' == 'Proto'">netstandard2.0</TargetFrameworks>
<TargetFrameworks Condition="'$(Configuration)' != 'Proto'">netstandard2.0;netstandard2.1</TargetFrameworks>
<TargetFrameworks Condition="'$(Configuration)' != 'Proto'">netstandard2.0;netstandard2.1;$(FSharpCoreShippedNetTargetFramework)</TargetFrameworks>
<NoWarn>$(NoWarn);75</NoWarn> <!-- InternalCommandLineOption -->
<NoWarn>$(NoWarn);1204</NoWarn> <!-- This construct is for use in the FSharp.Core library and should not be used directly -->
<AllowCrossTargeting>true</AllowCrossTargeting>
Expand Down Expand Up @@ -36,6 +36,12 @@
<Configurations>Debug;Release;Proto</Configurations>
</PropertyGroup>

<!-- Pinned .NET TFM for the shipped FSharp.Core, surfaced to FSharp.Core.nuspec as a $token$
so the package lib/dependency group stay driven by the single knob in eng/TargetFrameworks.props. -->
<ItemGroup Condition="'$(Configuration)' != 'Proto'">
<NuspecProperty Include="FSharpCoreShippedNetTargetFramework=$(FSharpCoreShippedNetTargetFramework)" />
</ItemGroup>

<!-- .FSharp.Core always uses the old style initialization mechanism because of SQL CLR requirements -->
<PropertyGroup Condition="'$(BUILDING_USING_DOTNET)' != 'true' and '$(Configuration)' != 'Proto'">
<OtherFlags>$(OtherFlags) --realsig-</OtherFlags>
Expand Down
7 changes: 7 additions & 0 deletions src/FSharp.Core/FSharp.Core.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<dependencies>
<group targetFramework=".NETStandard2.0" />
<group targetFramework=".NETStandard2.1" />
<group targetFramework="$FSharpCoreShippedNetTargetFramework$" />
</dependencies>
</metadata>
<files>
Expand All @@ -22,5 +23,11 @@

<!-- resources -->
<file src="FSharp.Core\$Configuration$\netstandard2.1\**\FSharp.Core.resources.dll" target="lib\netstandard2.1" />

<file src="FSharp.Core\$Configuration$\$FSharpCoreShippedNetTargetFramework$\FSharp.Core.dll" target="lib\$FSharpCoreShippedNetTargetFramework$" />
<file src="FSharp.Core\$Configuration$\$FSharpCoreShippedNetTargetFramework$\FSharp.Core.xml" target="lib\$FSharpCoreShippedNetTargetFramework$" />

<!-- resources -->
<file src="FSharp.Core\$Configuration$\$FSharpCoreShippedNetTargetFramework$\**\FSharp.Core.resources.dll" target="lib\$FSharpCoreShippedNetTargetFramework$" />
</files>
</package>
12 changes: 6 additions & 6 deletions src/FSharp.Core/Query.fs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ type QueryBuilder() =
member _.Head (source: QuerySource<'T, 'Q>) =
Enumerable.First source.Source

member _.Nth (source: QuerySource<'T, 'Q>, index) =
member _.Nth (source: QuerySource<'T, 'Q>, index: int) =
Enumerable.ElementAt (source.Source, index)

member _.Skip (source: QuerySource<'T, 'Q>, count) : QuerySource<'T, 'Q> =
Expand All @@ -116,7 +116,7 @@ type QueryBuilder() =
member _.SkipWhile (source: QuerySource<'T, 'Q>, predicate) : QuerySource<'T, 'Q> =
QuerySource (Enumerable.SkipWhile (source.Source, Func<_, _>(predicate)))

member _.Take (source: QuerySource<'T, 'Q>, count) : QuerySource<'T, 'Q> =
member _.Take (source: QuerySource<'T, 'Q>, count: int) : QuerySource<'T, 'Q> =
QuerySource (Enumerable.Take (source.Source, count))

member _.TakeWhile (source: QuerySource<'T, 'Q>, predicate) : QuerySource<'T, 'Q> =
Expand Down Expand Up @@ -475,8 +475,8 @@ module Query =
MakeOrCallContainsOrElementAt FQ FE

let MakeElementAt, CallElementAt =
let FQ = methodhandleof (fun (x, y) -> Queryable.ElementAt(x, y))
let FE = methodhandleof (fun (x, y) -> Enumerable.ElementAt(x, y))
let FQ = methodhandleof (fun (x, y) -> Queryable.ElementAt(x, (y: int)))
let FE = methodhandleof (fun (x, y) -> Enumerable.ElementAt(x, (y: int)))
MakeOrCallContainsOrElementAt FQ FE

let MakeOrCallMinByOrMaxBy FQ FE =
Expand Down Expand Up @@ -886,8 +886,8 @@ module Query =

let MakeTake =
MakeSkipOrTake
(methodhandleof (fun (x, y) -> Queryable.Take (x, y)))
(methodhandleof (fun (x, y) -> Enumerable.Take (x, y)))
(methodhandleof (fun (x, y) -> Queryable.Take (x, (y: int))))
(methodhandleof (fun (x, y) -> Enumerable.Take (x, (y: int))))

let MakeSkipWhile =
GenMakeSkipWhileOrTakeWhile
Expand Down
6 changes: 3 additions & 3 deletions src/FSharp.Core/local.fs
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,17 @@ module internal DetailedExceptions =
open Microsoft.FSharp.Core

/// takes an argument, a formatting string, a param array to splice into the formatting string
let inline invalidArgFmt (arg:string) (format:string) paramArray =
let inline invalidArgFmt (arg:string) (format:string) (paramArray: obj[]) =
let msg = String.Format (format, paramArray)
raise (ArgumentException(msg, arg))

/// takes an argument, a formatting string, a param array to splice into the formatting string
let inline invalidArgOutOfRangeFmt (arg:string) (format:string) paramArray =
let inline invalidArgOutOfRangeFmt (arg:string) (format:string) (paramArray: obj[]) =
let msg = String.Format (format, paramArray)
raise (ArgumentOutOfRangeException(arg, msg))

/// takes a formatting string and a param array to splice into the formatting string
let inline invalidOpFmt (format:string) paramArray =
let inline invalidOpFmt (format:string) (paramArray: obj[]) =
let msg = String.Format (format, paramArray)
raise (InvalidOperationException(msg))

Expand Down
Loading
Loading