diff --git a/docs/release-notes/.FSharp.Core/11.0.100.md b/docs/release-notes/.FSharp.Core/11.0.100.md index ae2672e2c9c..9a89e373ae1 100644 --- a/docs/release-notes/.FSharp.Core/11.0.100.md +++ b/docs/release-notes/.FSharp.Core/11.0.100.md @@ -1,6 +1,7 @@ ### Fixed * Mirror compiler-semantic attributes (e.g. `[]`, `[]`) in `.fsi` signature files to match `.fs` implementations. ([Issue #19560](https://github.com/dotnet/fsharp/issues/19560), [PR #19880](https://github.com/dotnet/fsharp/pull/19880)) +* Fix `Array2D` AOT compatibility: `create`, `init` and `rebase` no longer emit `IL3050`; `map`, `mapi` and `copy` no longer emit it on `net10.0`; the `*Based` operations now warn at the call site before the runtime failure they already had. ([Language Suggestion #1454](https://github.com/fsharp/fslang-suggestions/issues/1454), [PR #20338](https://github.com/dotnet/fsharp/pull/20338)) * Fix `Array.exists2` documentation examples to use equal-length arrays; the previous examples would throw `ArgumentException` at runtime instead of returning the documented `false`/`true` values. ([PR #19672](https://github.com/dotnet/fsharp/pull/19672)) * Move `Async.StartChild` to the "Starting Async Computations" docs category alongside `Async.StartChildAsTask`. ([Issue #19667](https://github.com/dotnet/fsharp/issues/19667)) * Add `InlineIfLambda` to `Array.init` ([PR #19869](https://github.com/dotnet/fsharp/pull/19869)) diff --git a/src/FSharp.Core/array2.fs b/src/FSharp.Core/array2.fs index ce4ccc3b9aa..cecf917437a 100644 --- a/src/FSharp.Core/array2.fs +++ b/src/FSharp.Core/array2.fs @@ -6,6 +6,7 @@ open System open Microsoft.FSharp.Core open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators open Microsoft.FSharp.Core.Operators.Checked +open System.Diagnostics.CodeAnalysis #nowarn "3218" // mismatch of parameter name where 'count1' --> 'length1' would shadow function in module of same name @@ -13,6 +14,10 @@ open Microsoft.FSharp.Core.Operators.Checked [] module Array2D = + [] + let private nonZeroBasedRequiresDynamicCode = + "Arrays with a non-zero lower bound cannot be created in an AOT-compiled application. Use Array2D.zeroCreate, Array2D.create or Array2D.init instead." + let inline checkNonNull argName arg = if isNull arg then nullArg argName @@ -48,37 +53,62 @@ module Array2D = if length2 < 0 then invalidArgInputMustBeNonNegative "length2" length2 (# "newarr.multi 2 !0" type ('T) length1 length2 : 'T[,] #) - [] - let zeroCreateBased (base1:int) (base2:int) (length1:int) (length2:int) = + // map, mapi and copy must stay on this unannotated path; the public based entry points + // carry RequiresDynamicCode instead. + let private zeroCreateBasedAux (base1:int) (base2:int) (length1:int) (length2:int) : 'T[,] = if base1 = 0 && base2 = 0 then zeroCreate length1 length2 else +#if NET9_0_OR_GREATER + // Unlike Array.CreateInstance, this overload carries no RequiresDynamicCode. + (Array.CreateInstanceFromArrayType(typeof<'T[,]>, [|length1;length2|], [|base1;base2|]) :?> 'T[,]) +#else (Array.CreateInstance(typeof<'T>, [|length1;length2|], [|base1;base2|]) :?> 'T[,]) +#endif + let private initBasedAux base1 base2 length1 length2 initializer : 'T[,] = + let array = zeroCreateBasedAux base1 base2 length1 length2 + let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(initializer) + for i = base1 to base1 + length1 - 1 do + for j = base2 to base2 + length2 - 1 do + array.[i, j] <- f.Invoke(i, j) + array + + [] + [] + let zeroCreateBased (base1:int) (base2:int) (length1:int) (length2:int) : 'T[,] = + zeroCreateBasedAux base1 base2 length1 length2 + + [] [] let createBased base1 base2 length1 length2 (initial:'T) = - let array = (zeroCreateBased base1 base2 length1 length2 : 'T[,]) + let array = (zeroCreateBasedAux base1 base2 length1 length2 : 'T[,]) for i = base1 to base1 + length1 - 1 do for j = base2 to base2 + length2 - 1 do array.[i, j] <- initial array + [] [] - let initBased base1 base2 length1 length2 initializer = - let array = (zeroCreateBased base1 base2 length1 length2 : 'T[,]) - let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(initializer) - for i = base1 to base1 + length1 - 1 do - for j = base2 to base2 + length2 - 1 do - array.[i, j] <- f.Invoke(i, j) - array + let initBased base1 base2 length1 length2 initializer : 'T[,] = + initBasedAux base1 base2 length1 length2 initializer [] let create length1 length2 (value:'T) = - createBased 0 0 length1 length2 value + let array = zeroCreate length1 length2 + for i = 0 to length1 - 1 do + for j = 0 to length2 - 1 do + array.[i, j] <- value + array [] let init length1 length2 initializer = - initBased 0 0 length1 length2 initializer + let array = zeroCreate length1 length2 + let f = OptimizedClosures.FSharpFunc<_, _, _>.Adapt(initializer) + for i = 0 to length1 - 1 do + for j = 0 to length2 - 1 do + array.[i, j] <- f.Invoke(i, j) + array [] let iter action array = @@ -106,18 +136,18 @@ module Array2D = [] let map mapping array = checkNonNull "array" array - initBased (base1 array) (base2 array) (length1 array) (length2 array) (fun i j -> mapping array.[i,j]) + initBasedAux (base1 array) (base2 array) (length1 array) (length2 array) (fun i j -> mapping array.[i,j]) [] let mapi mapping array = checkNonNull "array" array let f = OptimizedClosures.FSharpFunc<_, _, _, _>.Adapt(mapping) - initBased (base1 array) (base2 array) (length1 array) (length2 array) (fun i j -> f.Invoke(i, j, array.[i,j])) + initBasedAux (base1 array) (base2 array) (length1 array) (length2 array) (fun i j -> f.Invoke(i, j, array.[i,j])) [] let copy array = checkNonNull "array" array - initBased (base1 array) (base2 array) (length1 array) (length2 array) (fun i j -> array.[i,j]) + initBasedAux (base1 array) (base2 array) (length1 array) (length2 array) (fun i j -> array.[i,j]) [] let rebase array = diff --git a/src/FSharp.Core/prim-types.fs b/src/FSharp.Core/prim-types.fs index c282ffe7b84..11e3ff1cb6a 100644 --- a/src/FSharp.Core/prim-types.fs +++ b/src/FSharp.Core/prim-types.fs @@ -450,6 +450,24 @@ namespace System.Diagnostics.CodeAnalysis #endif +#if !NET7_0_OR_GREATER +namespace System.Diagnostics.CodeAnalysis + + open System + open Microsoft.FSharp.Core + + /// + /// Indicates that the specified member requires the ability to generate new code at runtime. + /// + [] + type internal RequiresDynamicCodeAttribute (message: string) = + inherit Attribute () + + member _.Message = message + +#endif + namespace Microsoft.FSharp.Core open System open System.Collections diff --git a/src/FSharp.Core/prim-types.fsi b/src/FSharp.Core/prim-types.fsi index da067b4275a..201013fb97f 100644 --- a/src/FSharp.Core/prim-types.fsi +++ b/src/FSharp.Core/prim-types.fsi @@ -1062,6 +1062,24 @@ namespace System.Diagnostics.CodeAnalysis #endif +#if !NET7_0_OR_GREATER +namespace System.Diagnostics.CodeAnalysis + + open System + open Microsoft.FSharp.Core + + /// + /// Indicates that the specified member requires the ability to generate new code at runtime. + /// + [] + type internal RequiresDynamicCodeAttribute = + inherit Attribute + new: string -> RequiresDynamicCodeAttribute + member Message: string + +#endif + namespace Microsoft.FSharp.Core open System diff --git a/tests/AheadOfTime/NativeAOT/Array2DProgram.fs b/tests/AheadOfTime/NativeAOT/Array2DProgram.fs new file mode 100644 index 00000000000..e148c85c103 --- /dev/null +++ b/tests/AheadOfTime/NativeAOT/Array2DProgram.fs @@ -0,0 +1,56 @@ +module Array2DProgram + +open System + +let private check name (actual: int) (expected: int) = + if actual <> expected then + Console.WriteLine $"FAILED {name}: expected {expected} but got {actual}" + +// Consume every grid, so ILC cannot drop the allocations this test exists to exercise. +let private sum (grid: int[,]) = + let total = ref 0 + grid |> Array2D.iteri (fun _ _ v -> total.Value <- total.Value + v) + total.Value + +[] +let private createBasedThrows rows cols = + try + Array2D.createBased 1 2 rows cols 7 |> ignore + 0 + with :? PlatformNotSupportedException -> + 1 + +let run (argv: string[]) = + // Derive the dimensions from argv, so ILC cannot constant-fold the allocations away. + // The expected values below assume check.ps1 runs the app with no arguments. + let rows = 3 + argv.Length + let cols = 4 + argv.Length + + let table = Array2D.init rows cols (fun i j -> (i + 1) * (j + 1)) + check "init.rows" (Array2D.length1 table) 3 + check "init.cols" (Array2D.length2 table) 4 + check "init" (sum table) 60 + + let board = Array2D.create rows cols 2 + check "create" (sum board) 24 + + Array2D.blit table 0 0 board 1 1 2 2 + check "blit" (sum board) 25 + check "blit.cell" board.[2, 2] 4 + + let rebased = Array2D.rebase table + check "rebase" (sum rebased) 60 + check "rebase.base" (Array2D.base1 rebased + Array2D.base2 rebased) 0 + + let doubled = Array2D.map (fun v -> v * 2) table + check "map" (sum doubled) 120 + + let skewed = Array2D.mapi (fun i j v -> v + i - j) table + check "mapi" (sum skewed) 54 + + let copied = Array2D.copy table + check "copy" (sum copied) 60 + check "copy.distinct" (if Object.ReferenceEquals(copied, table) then 1 else 0) 0 + + check "createBased.throws" (createBasedThrows rows cols) 1 diff --git a/tests/AheadOfTime/NativeAOT/NativeAOT_Test.fsproj b/tests/AheadOfTime/NativeAOT/NativeAOT_Test.fsproj index 18451f28110..514972a780a 100644 --- a/tests/AheadOfTime/NativeAOT/NativeAOT_Test.fsproj +++ b/tests/AheadOfTime/NativeAOT/NativeAOT_Test.fsproj @@ -2,7 +2,7 @@ Exe - net10.0 + $(FSharpCoreShippedNetTargetFramework) preview true @@ -24,6 +24,7 @@ + diff --git a/tests/AheadOfTime/NativeAOT/Program.fs b/tests/AheadOfTime/NativeAOT/Program.fs index dce1bbaf53e..40ec41ba92c 100644 --- a/tests/AheadOfTime/NativeAOT/Program.fs +++ b/tests/AheadOfTime/NativeAOT/Program.fs @@ -27,8 +27,9 @@ let runChecks () = // check ($"value = %A{x}", "value = 42") [] -let main _ = +let main argv = runChecks () + Array2DProgram.run argv // Success sentinel; a failed check above printed a "FAILED" line first, so the output won't be just this. Console.WriteLine "Finished" 0 diff --git a/tests/AheadOfTime/NativeAOT/check.ps1 b/tests/AheadOfTime/NativeAOT/check.ps1 index c31773529dd..32d6fe532d8 100644 --- a/tests/AheadOfTime/NativeAOT/check.ps1 +++ b/tests/AheadOfTime/NativeAOT/check.ps1 @@ -9,42 +9,41 @@ $ErrorActionPreference = "Stop" $root = "NativeAOT_Test" -$tfm = "net10.0" $cwd = Get-Location Set-Location $PSScriptRoot -dotnet publish -restore -c release -f:$tfm "$root.fsproj" -bl:"$PSScriptRoot/../../../artifacts/log/Release/AheadOfTime/NativeAOT/$root.binlog" +dotnet publish -restore -c release "$root.fsproj" -bl:"$PSScriptRoot/../../../artifacts/log/Release/AheadOfTime/NativeAOT/$root.binlog" if (-not ($LASTEXITCODE -eq 0)) { Set-Location $cwd Write-Error "NativeAOT publish failed with exit code $LASTEXITCODE" -ErrorAction Stop } -# Prove this is a genuine net10 dogfood: a net10.0 consumer must resolve the locally-packed -# FSharp.Core's lib/net10.0 asset, not the netstandard2.1 fallback. Assert on the *selected* -# compile/runtime asset under "targets" (the "libraries" manifest lists every lib folder, so a -# plain substring search would false-pass even when ns2.1 was chosen). Without this the test would -# still succeed on the ns2.1 asset and the net10 target framework would go unexercised. +# Read the frameworks from the project; passing -f above would override TargetFramework globally. +$props = dotnet msbuild "$root.fsproj" -getProperty:TargetFramework -getProperty:FSharpCoreShippedNetTargetFramework -nologo | ConvertFrom-Json +$tfm = $props.Properties.TargetFramework +$coreAsset = "lib/$($props.Properties.FSharpCoreShippedNetTargetFramework)/FSharp.Core.dll" + +# Assert on the selected compile/runtime asset, not the "libraries" manifest, which lists every +# lib folder and would false-pass on the netstandard2.1 fallback. $assets = Join-Path $PSScriptRoot "obj/project.assets.json" $assetsJson = Get-Content $assets -Raw | ConvertFrom-Json -$net10Selected = $false +$netAssetSelected = $false foreach ($target in $assetsJson.targets.PSObject.Properties) { foreach ($package in $target.Value.PSObject.Properties) { if ($package.Name -like "FSharp.Core/*") { $compileKeys = if ($package.Value.compile) { @($package.Value.compile.PSObject.Properties.Name) } else { @() } $runtimeKeys = if ($package.Value.runtime) { @($package.Value.runtime.PSObject.Properties.Name) } else { @() } - # FSharp.Core packs only lib/{tfm} (no ref/, no runtimes/), so compile and runtime resolve - # from the same folder; require both to be net10 - anything else means a fallback was chosen. - if (($compileKeys -contains "lib/net10.0/FSharp.Core.dll") -and - ($runtimeKeys -contains "lib/net10.0/FSharp.Core.dll")) { - $net10Selected = $true + # FSharp.Core packs only lib/{tfm}, so both must resolve there; anything else is a fallback. + if (($compileKeys -contains $coreAsset) -and ($runtimeKeys -contains $coreAsset)) { + $netAssetSelected = $true } } } } -if (-not $net10Selected) { +if (-not $netAssetSelected) { Set-Location $cwd - Write-Error "The net10.0 consumer did not resolve the lib/net10.0 FSharp.Core asset (it fell back to a lower target framework). The net10 FSharp.Core target framework is not being dogfooded. See $assets." -ErrorAction Stop + Write-Error "The $tfm consumer did not resolve the $coreAsset FSharp.Core asset (it fell back to a lower target framework). The shipped net FSharp.Core target framework is not being dogfooded. See $assets." -ErrorAction Stop } $exe = Join-Path $PSScriptRoot "bin/release/$tfm/win-x64/publish/$root.exe" @@ -58,7 +57,7 @@ if (-not ($exitCode -eq 0)) { } if ($output.Trim() -ne "Finished") { - Write-Error "NativeAOT interpolation checks failed.`nOutput:`n$output" -ErrorAction Stop + Write-Error "NativeAOT behavior checks failed.`nOutput:`n$output" -ErrorAction Stop } -Write-Host "NativeAOT interpolated-string test passed." +Write-Host "NativeAOT test passed." diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/CodeGenRenamings01.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/CodeGenRenamings01.fs index 48f8e611537..ce8c07a2856 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/CodeGenRenamings01.fs +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/CodeGenRenamings01.fs @@ -37,3 +37,6 @@ Array3D.get array3D 0 0 0 |> Array3D.set array3D 0 0 0 // Array4D Renamings (Array4D.length1 array4D, Array4D.length2 array4D, Array4D.length3 array4D, Array4D.length4 array4D) |> ignore Array4D.get array4D 0 0 0 0 |> Array4D.set array4D 0 0 0 0 + +// Array2D.init renaming, appended here rather than above to limit IL baseline churn. +Array2D.init 2 2 (fun i j -> i + j) |> ignore diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/CodeGenRenamings01.fs.RealInternalSignatureOff.OptimizeOff.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/CodeGenRenamings01.fs.RealInternalSignatureOff.OptimizeOff.il.bsl index 2cce273bc65..983254a8a28 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/CodeGenRenamings01.fs.RealInternalSignatureOff.OptimizeOff.il.bsl +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/CodeGenRenamings01.fs.RealInternalSignatureOff.OptimizeOff.il.bsl @@ -190,6 +190,42 @@ } + .class auto ansi serializable sealed nested assembly beforefieldinit 'Pipe #8 input at line 42@42' + extends class [FSharp.Core]Microsoft.FSharp.Core.OptimizedClosures/FSharpFunc`3 + { + .field static assembly initonly class assembly/'Pipe #8 input at line 42@42' @_instance + .method assembly specialname rtspecialname instance void .ctor() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.OptimizedClosures/FSharpFunc`3::.ctor() + IL_0006: ret + } + + .method public strict virtual instance int32 Invoke(int32 i, int32 j) cil managed + { + + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: ldarg.2 + IL_0002: add + IL_0003: ret + } + + .method private specialname rtspecialname static void .cctor() cil managed + { + + .maxstack 10 + IL_0000: newobj instance void assembly/'Pipe #8 input at line 42@42'::.ctor() + IL_0005: stsfld class assembly/'Pipe #8 input at line 42@42' assembly/'Pipe #8 input at line 42@42'::@_instance + IL_000a: ret + } + + } + .method public specialname static class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 get_alist() cil managed { @@ -397,7 +433,9 @@ int32 V_20, class [runtime]System.Tuple`4 V_21, class [runtime]System.Tuple`4 V_22, - int32 V_23) + int32 V_23, + int32[0...,0...] V_24, + int32[0...,0...] V_25) IL_0000: ldc.i4.0 IL_0001: conv.i8 IL_0002: stloc.s V_12 @@ -669,7 +707,16 @@ int32, !!0) IL_0254: nop - IL_0255: ret + IL_0255: ldc.i4.2 + IL_0256: ldc.i4.2 + IL_0257: ldsfld class assembly/'Pipe #8 input at line 42@42' assembly/'Pipe #8 input at line 42@42'::@_instance + IL_025c: call !!0[0...,0...] [FSharp.Core]Microsoft.FSharp.Collections.Array2DModule::Initialize(int32, + int32, + class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) + IL_0261: stloc.s V_24 + IL_0263: ldloc.s V_24 + IL_0265: stloc.s V_25 + IL_0267: ret } } @@ -678,4 +725,3 @@ - diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/CodeGenRenamings01.fs.RealInternalSignatureOff.OptimizeOn.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/CodeGenRenamings01.fs.RealInternalSignatureOff.OptimizeOn.il.bsl index deb49d2adb1..2970de55a39 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/CodeGenRenamings01.fs.RealInternalSignatureOff.OptimizeOn.il.bsl +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/CodeGenRenamings01.fs.RealInternalSignatureOff.OptimizeOn.il.bsl @@ -5,11 +5,6 @@ .assembly extern runtime { } .assembly extern FSharp.Core { } -.assembly extern netstandard -{ - .publickeytoken = (CC 7B 13 FF CD 2D DD 51 ) - .ver 2:1:0:0 -} .assembly assembly { .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, @@ -195,6 +190,42 @@ } + .class auto ansi serializable sealed nested assembly beforefieldinit clo@42 + extends class [FSharp.Core]Microsoft.FSharp.Core.OptimizedClosures/FSharpFunc`3 + { + .field static assembly initonly class assembly/clo@42 @_instance + .method assembly specialname rtspecialname instance void .ctor() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.OptimizedClosures/FSharpFunc`3::.ctor() + IL_0006: ret + } + + .method public strict virtual instance int32 Invoke(int32 i, int32 j) cil managed + { + + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: ldarg.2 + IL_0002: add + IL_0003: ret + } + + .method private specialname rtspecialname static void .cctor() cil managed + { + + .maxstack 10 + IL_0000: newobj instance void assembly/clo@42::.ctor() + IL_0005: stsfld class assembly/clo@42 assembly/clo@42::@_instance + IL_000a: ret + } + + } + .method public specialname static class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 get_alist() cil managed { @@ -371,6 +402,14 @@ IL_0005: ret } + .method assembly specialname static int32[0...,0...] get_arg@1() cil managed + { + + .maxstack 8 + IL_0000: ldsfld int32[0...,0...] ''.$assembly::arg@1 + IL_0005: ret + } + .property class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 alist() { @@ -486,6 +525,11 @@ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 09 00 00 00 00 00 ) .get int32 assembly::'get_arg_3@38-1'() } + .property int32[0...,0...] arg@1() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 09 00 00 00 00 00 ) + .get int32[0...,0...] assembly::get_arg@1() + } } .class private abstract auto ansi sealed ''.$assembly @@ -535,6 +579,8 @@ .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) .field static assembly int32 'arg_3@38-1' .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly int32[0...,0...] arg@1 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) .field static assembly int32 init@ .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) @@ -634,156 +680,159 @@ !1) IL_00a0: stelem class [runtime]System.Tuple`2 IL_00a5: stsfld class [runtime]System.Tuple`2[] ''.$assembly::array1@10 - IL_00aa: ldc.i4.0 - IL_00ab: ldc.i4.0 - IL_00ac: ldc.i4.2 - IL_00ad: ldc.i4.2 - IL_00ae: ldc.i4.0 - IL_00af: call !!0[0...,0...] [FSharp.Core]Microsoft.FSharp.Collections.Array2DModule::CreateBased(int32, - int32, - int32, - int32, - !!0) - IL_00b4: stsfld int32[0...,0...] ''.$assembly::a3@11 + IL_00aa: ldc.i4.2 + IL_00ab: ldc.i4.2 + IL_00ac: ldc.i4.0 + IL_00ad: call !!0[0...,0...] [FSharp.Core]Microsoft.FSharp.Collections.Array2DModule::Create(int32, + int32, + !!0) + IL_00b2: stsfld int32[0...,0...] ''.$assembly::a3@11 + IL_00b7: ldc.i4.3 + IL_00b8: ldc.i4.3 IL_00b9: ldc.i4.3 - IL_00ba: ldc.i4.3 - IL_00bb: ldc.i4.3 - IL_00bc: ldc.i4.0 - IL_00bd: call !!0[0...,0...,0...] [FSharp.Core]Microsoft.FSharp.Collections.Array3DModule::Create(int32, + IL_00ba: ldc.i4.0 + IL_00bb: call !!0[0...,0...,0...] [FSharp.Core]Microsoft.FSharp.Collections.Array3DModule::Create(int32, int32, int32, !!0) - IL_00c2: stsfld int32[0...,0...,0...] ''.$assembly::array3D@12 + IL_00c0: stsfld int32[0...,0...,0...] ''.$assembly::array3D@12 + IL_00c5: ldc.i4.4 + IL_00c6: ldc.i4.4 IL_00c7: ldc.i4.4 IL_00c8: ldc.i4.4 - IL_00c9: ldc.i4.4 - IL_00ca: ldc.i4.4 - IL_00cb: ldc.i4.0 - IL_00cc: call !!0[0...,0...,0...,0...] [FSharp.Core]Microsoft.FSharp.Collections.Array4DModule::Create(int32, + IL_00c9: ldc.i4.0 + IL_00ca: call !!0[0...,0...,0...,0...] [FSharp.Core]Microsoft.FSharp.Collections.Array4DModule::Create(int32, int32, int32, int32, !!0) - IL_00d1: stsfld int32[0...,0...,0...,0...] ''.$assembly::array4D@13 - IL_00d6: call int32[] assembly::get_array() - IL_00db: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 [FSharp.Core]Microsoft.FSharp.Collections.ListModule::OfArray(!!0[]) - IL_00e0: pop - IL_00e1: call class [runtime]System.Collections.Generic.IEnumerable`1 assembly::get_aseq() - IL_00e6: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToList(class [runtime]System.Collections.Generic.IEnumerable`1) - IL_00eb: pop - IL_00ec: call class [runtime]System.Tuple`2[] assembly::get_array1() - IL_00f1: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpMap`2 [FSharp.Core]Microsoft.FSharp.Collections.MapModule::OfArray(class [runtime]System.Tuple`2[]) - IL_00f6: pop - IL_00f7: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> assembly::get_list1() - IL_00fc: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpMap`2 [FSharp.Core]Microsoft.FSharp.Collections.MapModule::OfList(class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1>) - IL_0101: pop - IL_0102: call class [runtime]System.Collections.Generic.IEnumerable`1> assembly::get_seq1() - IL_0107: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpMap`2 [FSharp.Core]Microsoft.FSharp.Collections.MapModule::OfSeq(class [runtime]System.Collections.Generic.IEnumerable`1>) - IL_010c: pop - IL_010d: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 assembly::get_alist() - IL_0112: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.ArrayModule::OfList(class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) - IL_0117: stsfld int32[] ''.$assembly::a1@25 - IL_011c: call class [runtime]System.Collections.Generic.IEnumerable`1 assembly::get_aseq() - IL_0121: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.ArrayModule::OfSeq(class [runtime]System.Collections.Generic.IEnumerable`1) - IL_0126: stsfld int32[] ''.$assembly::a2@26 - IL_012b: call int32[] assembly::get_a2() - IL_0130: ldc.i4.0 - IL_0131: call int32[] assembly::get_a1() - IL_0136: ldc.i4.0 - IL_0137: ldelem.i4 - IL_0138: stelem.i4 - IL_0139: call int32[0...,0...] assembly::get_a3() - IL_013e: ldc.i4.s 0 - IL_0140: call instance int32 [runtime]System.Array::GetLength(int32) - IL_0145: stsfld int32 ''.$assembly::arg_0@30 - IL_014a: call int32[0...,0...] assembly::get_a3() - IL_014f: ldc.i4.s 1 - IL_0151: call instance int32 [runtime]System.Array::GetLength(int32) - IL_0156: stsfld int32 ''.$assembly::arg_1@30 - IL_015b: call int32[0...,0...] assembly::get_a3() - IL_0160: ldc.i4.0 - IL_0161: callvirt instance int32 [netstandard]System.Array::GetLowerBound(int32) - IL_0166: stsfld int32 ''.$assembly::arg_2@30 - IL_016b: call int32[0...,0...] assembly::get_a3() - IL_0170: ldc.i4.1 - IL_0171: callvirt instance int32 [netstandard]System.Array::GetLowerBound(int32) - IL_0176: stsfld int32 ''.$assembly::arg_3@30 - IL_017b: call int32[0...,0...] assembly::get_a3() - IL_0180: ldc.i4.0 - IL_0181: ldc.i4.0 - IL_0182: call int32[0...,0...] assembly::get_a3() - IL_0187: ldc.i4.0 - IL_0188: ldc.i4.0 - IL_0189: call instance int32 int32[0...,0...]::Get(int32, + IL_00cf: stsfld int32[0...,0...,0...,0...] ''.$assembly::array4D@13 + IL_00d4: call int32[] assembly::get_array() + IL_00d9: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 [FSharp.Core]Microsoft.FSharp.Collections.ListModule::OfArray(!!0[]) + IL_00de: pop + IL_00df: call class [runtime]System.Collections.Generic.IEnumerable`1 assembly::get_aseq() + IL_00e4: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToList(class [runtime]System.Collections.Generic.IEnumerable`1) + IL_00e9: pop + IL_00ea: call class [runtime]System.Tuple`2[] assembly::get_array1() + IL_00ef: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpMap`2 [FSharp.Core]Microsoft.FSharp.Collections.MapModule::OfArray(class [runtime]System.Tuple`2[]) + IL_00f4: pop + IL_00f5: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> assembly::get_list1() + IL_00fa: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpMap`2 [FSharp.Core]Microsoft.FSharp.Collections.MapModule::OfList(class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1>) + IL_00ff: pop + IL_0100: call class [runtime]System.Collections.Generic.IEnumerable`1> assembly::get_seq1() + IL_0105: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpMap`2 [FSharp.Core]Microsoft.FSharp.Collections.MapModule::OfSeq(class [runtime]System.Collections.Generic.IEnumerable`1>) + IL_010a: pop + IL_010b: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 assembly::get_alist() + IL_0110: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.ArrayModule::OfList(class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) + IL_0115: stsfld int32[] ''.$assembly::a1@25 + IL_011a: call class [runtime]System.Collections.Generic.IEnumerable`1 assembly::get_aseq() + IL_011f: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.ArrayModule::OfSeq(class [runtime]System.Collections.Generic.IEnumerable`1) + IL_0124: stsfld int32[] ''.$assembly::a2@26 + IL_0129: call int32[] assembly::get_a2() + IL_012e: ldc.i4.0 + IL_012f: call int32[] assembly::get_a1() + IL_0134: ldc.i4.0 + IL_0135: ldelem.i4 + IL_0136: stelem.i4 + IL_0137: call int32[0...,0...] assembly::get_a3() + IL_013c: ldc.i4.s 0 + IL_013e: call instance int32 [runtime]System.Array::GetLength(int32) + IL_0143: stsfld int32 ''.$assembly::arg_0@30 + IL_0148: call int32[0...,0...] assembly::get_a3() + IL_014d: ldc.i4.s 1 + IL_014f: call instance int32 [runtime]System.Array::GetLength(int32) + IL_0154: stsfld int32 ''.$assembly::arg_1@30 + IL_0159: call int32[0...,0...] assembly::get_a3() + IL_015e: ldc.i4.0 + IL_015f: callvirt instance int32 [runtime]System.Array::GetLowerBound(int32) + IL_0164: stsfld int32 ''.$assembly::arg_2@30 + IL_0169: call int32[0...,0...] assembly::get_a3() + IL_016e: ldc.i4.1 + IL_016f: callvirt instance int32 [runtime]System.Array::GetLowerBound(int32) + IL_0174: stsfld int32 ''.$assembly::arg_3@30 + IL_0179: call int32[0...,0...] assembly::get_a3() + IL_017e: ldc.i4.0 + IL_017f: ldc.i4.0 + IL_0180: call int32[0...,0...] assembly::get_a3() + IL_0185: ldc.i4.0 + IL_0186: ldc.i4.0 + IL_0187: call instance int32 int32[0...,0...]::Get(int32, int32) - IL_018e: call instance void int32[0...,0...]::Set(int32, + IL_018c: call instance void int32[0...,0...]::Set(int32, int32, int32) - IL_0193: call int32[0...,0...,0...] assembly::get_array3D() - IL_0198: ldc.i4.s 0 - IL_019a: call instance int32 [runtime]System.Array::GetLength(int32) - IL_019f: stsfld int32 ''.$assembly::'arg_0@34-1' - IL_01a4: call int32[0...,0...,0...] assembly::get_array3D() - IL_01a9: ldc.i4.s 1 - IL_01ab: call instance int32 [runtime]System.Array::GetLength(int32) - IL_01b0: stsfld int32 ''.$assembly::'arg_1@34-1' - IL_01b5: call int32[0...,0...,0...] assembly::get_array3D() - IL_01ba: ldc.i4.s 2 - IL_01bc: call instance int32 [runtime]System.Array::GetLength(int32) - IL_01c1: stsfld int32 ''.$assembly::'arg_2@34-1' - IL_01c6: call int32[0...,0...,0...] assembly::get_array3D() + IL_0191: call int32[0...,0...,0...] assembly::get_array3D() + IL_0196: ldc.i4.s 0 + IL_0198: call instance int32 [runtime]System.Array::GetLength(int32) + IL_019d: stsfld int32 ''.$assembly::'arg_0@34-1' + IL_01a2: call int32[0...,0...,0...] assembly::get_array3D() + IL_01a7: ldc.i4.s 1 + IL_01a9: call instance int32 [runtime]System.Array::GetLength(int32) + IL_01ae: stsfld int32 ''.$assembly::'arg_1@34-1' + IL_01b3: call int32[0...,0...,0...] assembly::get_array3D() + IL_01b8: ldc.i4.s 2 + IL_01ba: call instance int32 [runtime]System.Array::GetLength(int32) + IL_01bf: stsfld int32 ''.$assembly::'arg_2@34-1' + IL_01c4: call int32[0...,0...,0...] assembly::get_array3D() + IL_01c9: ldc.i4.0 + IL_01ca: ldc.i4.0 IL_01cb: ldc.i4.0 - IL_01cc: ldc.i4.0 - IL_01cd: ldc.i4.0 - IL_01ce: call int32[0...,0...,0...] assembly::get_array3D() + IL_01cc: call int32[0...,0...,0...] assembly::get_array3D() + IL_01d1: ldc.i4.0 + IL_01d2: ldc.i4.0 IL_01d3: ldc.i4.0 - IL_01d4: ldc.i4.0 - IL_01d5: ldc.i4.0 - IL_01d6: call instance int32 int32[0...,0...,0...]::Get(int32, + IL_01d4: call instance int32 int32[0...,0...,0...]::Get(int32, int32, int32) - IL_01db: call instance void int32[0...,0...,0...]::Set(int32, + IL_01d9: call instance void int32[0...,0...,0...]::Set(int32, int32, int32, int32) - IL_01e0: call int32[0...,0...,0...,0...] assembly::get_array4D() - IL_01e5: ldc.i4.s 0 - IL_01e7: call instance int32 [runtime]System.Array::GetLength(int32) - IL_01ec: stsfld int32 ''.$assembly::'arg_0@38-2' - IL_01f1: call int32[0...,0...,0...,0...] assembly::get_array4D() - IL_01f6: ldc.i4.s 1 - IL_01f8: call instance int32 [runtime]System.Array::GetLength(int32) - IL_01fd: stsfld int32 ''.$assembly::'arg_1@38-2' - IL_0202: call int32[0...,0...,0...,0...] assembly::get_array4D() - IL_0207: ldc.i4.s 2 - IL_0209: call instance int32 [runtime]System.Array::GetLength(int32) - IL_020e: stsfld int32 ''.$assembly::'arg_2@38-2' - IL_0213: call int32[0...,0...,0...,0...] assembly::get_array4D() - IL_0218: ldc.i4.s 3 - IL_021a: call instance int32 [runtime]System.Array::GetLength(int32) - IL_021f: stsfld int32 ''.$assembly::'arg_3@38-1' - IL_0224: call int32[0...,0...,0...,0...] assembly::get_array4D() + IL_01de: call int32[0...,0...,0...,0...] assembly::get_array4D() + IL_01e3: ldc.i4.s 0 + IL_01e5: call instance int32 [runtime]System.Array::GetLength(int32) + IL_01ea: stsfld int32 ''.$assembly::'arg_0@38-2' + IL_01ef: call int32[0...,0...,0...,0...] assembly::get_array4D() + IL_01f4: ldc.i4.s 1 + IL_01f6: call instance int32 [runtime]System.Array::GetLength(int32) + IL_01fb: stsfld int32 ''.$assembly::'arg_1@38-2' + IL_0200: call int32[0...,0...,0...,0...] assembly::get_array4D() + IL_0205: ldc.i4.s 2 + IL_0207: call instance int32 [runtime]System.Array::GetLength(int32) + IL_020c: stsfld int32 ''.$assembly::'arg_2@38-2' + IL_0211: call int32[0...,0...,0...,0...] assembly::get_array4D() + IL_0216: ldc.i4.s 3 + IL_0218: call instance int32 [runtime]System.Array::GetLength(int32) + IL_021d: stsfld int32 ''.$assembly::'arg_3@38-1' + IL_0222: call int32[0...,0...,0...,0...] assembly::get_array4D() + IL_0227: ldc.i4.0 + IL_0228: ldc.i4.0 IL_0229: ldc.i4.0 IL_022a: ldc.i4.0 - IL_022b: ldc.i4.0 - IL_022c: ldc.i4.0 - IL_022d: call int32[0...,0...,0...,0...] assembly::get_array4D() + IL_022b: call int32[0...,0...,0...,0...] assembly::get_array4D() + IL_0230: ldc.i4.0 + IL_0231: ldc.i4.0 IL_0232: ldc.i4.0 IL_0233: ldc.i4.0 - IL_0234: ldc.i4.0 - IL_0235: ldc.i4.0 - IL_0236: call instance int32 int32[0...,0...,0...,0...]::Get(int32, + IL_0234: call instance int32 int32[0...,0...,0...,0...]::Get(int32, int32, int32, int32) - IL_023b: call void [FSharp.Core]Microsoft.FSharp.Collections.Array4DModule::Set(!!0[0...,0...,0...,0...], + IL_0239: call void [FSharp.Core]Microsoft.FSharp.Collections.Array4DModule::Set(!!0[0...,0...,0...,0...], int32, int32, int32, int32, !!0) - IL_0240: nop - IL_0241: ret + IL_023e: nop + IL_023f: ldc.i4.2 + IL_0240: ldc.i4.2 + IL_0241: ldsfld class assembly/clo@42 assembly/clo@42::@_instance + IL_0246: call !!0[0...,0...] [FSharp.Core]Microsoft.FSharp.Collections.Array2DModule::Initialize(int32, + int32, + class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) + IL_024b: stsfld int32[0...,0...] ''.$assembly::arg@1 + IL_0250: ret } } @@ -792,4 +841,3 @@ - diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/CodeGenRenamings01.fs.RealInternalSignatureOn.OptimizeOff.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/CodeGenRenamings01.fs.RealInternalSignatureOn.OptimizeOff.il.bsl index b8e51a0b509..dbbc0980da4 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/CodeGenRenamings01.fs.RealInternalSignatureOn.OptimizeOff.il.bsl +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/CodeGenRenamings01.fs.RealInternalSignatureOn.OptimizeOff.il.bsl @@ -190,6 +190,42 @@ } + .class auto ansi serializable sealed nested assembly beforefieldinit 'Pipe #8 input at line 42@42' + extends class [FSharp.Core]Microsoft.FSharp.Core.OptimizedClosures/FSharpFunc`3 + { + .field static assembly initonly class assembly/'Pipe #8 input at line 42@42' @_instance + .method assembly specialname rtspecialname instance void .ctor() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.OptimizedClosures/FSharpFunc`3::.ctor() + IL_0006: ret + } + + .method public strict virtual instance int32 Invoke(int32 i, int32 j) cil managed + { + + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: ldarg.2 + IL_0002: add + IL_0003: ret + } + + .method private specialname rtspecialname static void .cctor() cil managed + { + + .maxstack 10 + IL_0000: newobj instance void assembly/'Pipe #8 input at line 42@42'::.ctor() + IL_0005: stsfld class assembly/'Pipe #8 input at line 42@42' assembly/'Pipe #8 input at line 42@42'::@_instance + IL_000a: ret + } + + } + .field static assembly class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 alist@5 .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) .field static assembly int32[] array@6 @@ -327,7 +363,9 @@ int32 V_9, class [runtime]System.Tuple`4 V_10, class [runtime]System.Tuple`4 V_11, - int32 V_12) + int32 V_12, + int32[0...,0...] V_13, + int32[0...,0...] V_14) IL_0000: ldc.i4.0 IL_0001: conv.i8 IL_0002: stloc.1 @@ -577,7 +615,16 @@ int32, !!0) IL_022d: nop - IL_022e: ret + IL_022e: ldc.i4.2 + IL_022f: ldc.i4.2 + IL_0230: ldsfld class assembly/'Pipe #8 input at line 42@42' assembly/'Pipe #8 input at line 42@42'::@_instance + IL_0235: call !!0[0...,0...] [FSharp.Core]Microsoft.FSharp.Collections.Array2DModule::Initialize(int32, + int32, + class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) + IL_023a: stloc.s V_13 + IL_023c: ldloc.s V_13 + IL_023e: stloc.s V_14 + IL_0240: ret } .property class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 @@ -664,4 +711,3 @@ - diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/CodeGenRenamings01.fs.RealInternalSignatureOn.OptimizeOn.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/CodeGenRenamings01.fs.RealInternalSignatureOn.OptimizeOn.il.bsl index c8843431ed9..f5e8ec4b9a0 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/CodeGenRenamings01.fs.RealInternalSignatureOn.OptimizeOn.il.bsl +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/CodeGenRenamings01.fs.RealInternalSignatureOn.OptimizeOn.il.bsl @@ -5,11 +5,6 @@ .assembly extern runtime { } .assembly extern FSharp.Core { } -.assembly extern netstandard -{ - .publickeytoken = (CC 7B 13 FF CD 2D DD 51 ) - .ver 2:1:0:0 -} .assembly assembly { .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, @@ -195,6 +190,42 @@ } + .class auto ansi serializable sealed nested assembly beforefieldinit clo@42 + extends class [FSharp.Core]Microsoft.FSharp.Core.OptimizedClosures/FSharpFunc`3 + { + .field static assembly initonly class assembly/clo@42 @_instance + .method assembly specialname rtspecialname instance void .ctor() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.OptimizedClosures/FSharpFunc`3::.ctor() + IL_0006: ret + } + + .method public strict virtual instance int32 Invoke(int32 i, int32 j) cil managed + { + + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: ldarg.2 + IL_0002: add + IL_0003: ret + } + + .method private specialname rtspecialname static void .cctor() cil managed + { + + .maxstack 10 + IL_0000: newobj instance void assembly/clo@42::.ctor() + IL_0005: stsfld class assembly/clo@42 assembly/clo@42::@_instance + IL_000a: ret + } + + } + .field static assembly class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 alist@5 .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) .field static assembly int32[] array@6 @@ -239,6 +270,8 @@ .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) .field static assembly int32 'arg_3@38-1' .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly int32[0...,0...] arg@1 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) .method public specialname static class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 get_alist() cil managed { @@ -415,6 +448,14 @@ IL_0005: ret } + .method assembly specialname static int32[0...,0...] get_arg@1() cil managed + { + + .maxstack 8 + IL_0000: ldsfld int32[0...,0...] assembly::arg@1 + IL_0005: ret + } + .method private specialname rtspecialname static void .cctor() cil managed { @@ -520,156 +561,159 @@ !1) IL_00a0: stelem class [runtime]System.Tuple`2 IL_00a5: stsfld class [runtime]System.Tuple`2[] assembly::array1@10 - IL_00aa: ldc.i4.0 - IL_00ab: ldc.i4.0 - IL_00ac: ldc.i4.2 - IL_00ad: ldc.i4.2 - IL_00ae: ldc.i4.0 - IL_00af: call !!0[0...,0...] [FSharp.Core]Microsoft.FSharp.Collections.Array2DModule::CreateBased(int32, - int32, - int32, - int32, - !!0) - IL_00b4: stsfld int32[0...,0...] assembly::a3@11 + IL_00aa: ldc.i4.2 + IL_00ab: ldc.i4.2 + IL_00ac: ldc.i4.0 + IL_00ad: call !!0[0...,0...] [FSharp.Core]Microsoft.FSharp.Collections.Array2DModule::Create(int32, + int32, + !!0) + IL_00b2: stsfld int32[0...,0...] assembly::a3@11 + IL_00b7: ldc.i4.3 + IL_00b8: ldc.i4.3 IL_00b9: ldc.i4.3 - IL_00ba: ldc.i4.3 - IL_00bb: ldc.i4.3 - IL_00bc: ldc.i4.0 - IL_00bd: call !!0[0...,0...,0...] [FSharp.Core]Microsoft.FSharp.Collections.Array3DModule::Create(int32, + IL_00ba: ldc.i4.0 + IL_00bb: call !!0[0...,0...,0...] [FSharp.Core]Microsoft.FSharp.Collections.Array3DModule::Create(int32, int32, int32, !!0) - IL_00c2: stsfld int32[0...,0...,0...] assembly::array3D@12 + IL_00c0: stsfld int32[0...,0...,0...] assembly::array3D@12 + IL_00c5: ldc.i4.4 + IL_00c6: ldc.i4.4 IL_00c7: ldc.i4.4 IL_00c8: ldc.i4.4 - IL_00c9: ldc.i4.4 - IL_00ca: ldc.i4.4 - IL_00cb: ldc.i4.0 - IL_00cc: call !!0[0...,0...,0...,0...] [FSharp.Core]Microsoft.FSharp.Collections.Array4DModule::Create(int32, + IL_00c9: ldc.i4.0 + IL_00ca: call !!0[0...,0...,0...,0...] [FSharp.Core]Microsoft.FSharp.Collections.Array4DModule::Create(int32, int32, int32, int32, !!0) - IL_00d1: stsfld int32[0...,0...,0...,0...] assembly::array4D@13 - IL_00d6: call int32[] assembly::get_array() - IL_00db: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 [FSharp.Core]Microsoft.FSharp.Collections.ListModule::OfArray(!!0[]) - IL_00e0: pop - IL_00e1: call class [runtime]System.Collections.Generic.IEnumerable`1 assembly::get_aseq() - IL_00e6: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToList(class [runtime]System.Collections.Generic.IEnumerable`1) - IL_00eb: pop - IL_00ec: call class [runtime]System.Tuple`2[] assembly::get_array1() - IL_00f1: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpMap`2 [FSharp.Core]Microsoft.FSharp.Collections.MapModule::OfArray(class [runtime]System.Tuple`2[]) - IL_00f6: pop - IL_00f7: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> assembly::get_list1() - IL_00fc: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpMap`2 [FSharp.Core]Microsoft.FSharp.Collections.MapModule::OfList(class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1>) - IL_0101: pop - IL_0102: call class [runtime]System.Collections.Generic.IEnumerable`1> assembly::get_seq1() - IL_0107: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpMap`2 [FSharp.Core]Microsoft.FSharp.Collections.MapModule::OfSeq(class [runtime]System.Collections.Generic.IEnumerable`1>) - IL_010c: pop - IL_010d: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 assembly::get_alist() - IL_0112: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.ArrayModule::OfList(class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) - IL_0117: stsfld int32[] assembly::a1@25 - IL_011c: call class [runtime]System.Collections.Generic.IEnumerable`1 assembly::get_aseq() - IL_0121: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.ArrayModule::OfSeq(class [runtime]System.Collections.Generic.IEnumerable`1) - IL_0126: stsfld int32[] assembly::a2@26 - IL_012b: call int32[] assembly::get_a2() - IL_0130: ldc.i4.0 - IL_0131: call int32[] assembly::get_a1() - IL_0136: ldc.i4.0 - IL_0137: ldelem.i4 - IL_0138: stelem.i4 - IL_0139: call int32[0...,0...] assembly::get_a3() - IL_013e: ldc.i4.s 0 - IL_0140: call instance int32 [runtime]System.Array::GetLength(int32) - IL_0145: stsfld int32 assembly::arg_0@30 - IL_014a: call int32[0...,0...] assembly::get_a3() - IL_014f: ldc.i4.s 1 - IL_0151: call instance int32 [runtime]System.Array::GetLength(int32) - IL_0156: stsfld int32 assembly::arg_1@30 - IL_015b: call int32[0...,0...] assembly::get_a3() - IL_0160: ldc.i4.0 - IL_0161: callvirt instance int32 [netstandard]System.Array::GetLowerBound(int32) - IL_0166: stsfld int32 assembly::arg_2@30 - IL_016b: call int32[0...,0...] assembly::get_a3() - IL_0170: ldc.i4.1 - IL_0171: callvirt instance int32 [netstandard]System.Array::GetLowerBound(int32) - IL_0176: stsfld int32 assembly::arg_3@30 - IL_017b: call int32[0...,0...] assembly::get_a3() - IL_0180: ldc.i4.0 - IL_0181: ldc.i4.0 - IL_0182: call int32[0...,0...] assembly::get_a3() - IL_0187: ldc.i4.0 - IL_0188: ldc.i4.0 - IL_0189: call instance int32 int32[0...,0...]::Get(int32, + IL_00cf: stsfld int32[0...,0...,0...,0...] assembly::array4D@13 + IL_00d4: call int32[] assembly::get_array() + IL_00d9: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 [FSharp.Core]Microsoft.FSharp.Collections.ListModule::OfArray(!!0[]) + IL_00de: pop + IL_00df: call class [runtime]System.Collections.Generic.IEnumerable`1 assembly::get_aseq() + IL_00e4: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToList(class [runtime]System.Collections.Generic.IEnumerable`1) + IL_00e9: pop + IL_00ea: call class [runtime]System.Tuple`2[] assembly::get_array1() + IL_00ef: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpMap`2 [FSharp.Core]Microsoft.FSharp.Collections.MapModule::OfArray(class [runtime]System.Tuple`2[]) + IL_00f4: pop + IL_00f5: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1> assembly::get_list1() + IL_00fa: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpMap`2 [FSharp.Core]Microsoft.FSharp.Collections.MapModule::OfList(class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1>) + IL_00ff: pop + IL_0100: call class [runtime]System.Collections.Generic.IEnumerable`1> assembly::get_seq1() + IL_0105: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpMap`2 [FSharp.Core]Microsoft.FSharp.Collections.MapModule::OfSeq(class [runtime]System.Collections.Generic.IEnumerable`1>) + IL_010a: pop + IL_010b: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 assembly::get_alist() + IL_0110: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.ArrayModule::OfList(class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) + IL_0115: stsfld int32[] assembly::a1@25 + IL_011a: call class [runtime]System.Collections.Generic.IEnumerable`1 assembly::get_aseq() + IL_011f: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.ArrayModule::OfSeq(class [runtime]System.Collections.Generic.IEnumerable`1) + IL_0124: stsfld int32[] assembly::a2@26 + IL_0129: call int32[] assembly::get_a2() + IL_012e: ldc.i4.0 + IL_012f: call int32[] assembly::get_a1() + IL_0134: ldc.i4.0 + IL_0135: ldelem.i4 + IL_0136: stelem.i4 + IL_0137: call int32[0...,0...] assembly::get_a3() + IL_013c: ldc.i4.s 0 + IL_013e: call instance int32 [runtime]System.Array::GetLength(int32) + IL_0143: stsfld int32 assembly::arg_0@30 + IL_0148: call int32[0...,0...] assembly::get_a3() + IL_014d: ldc.i4.s 1 + IL_014f: call instance int32 [runtime]System.Array::GetLength(int32) + IL_0154: stsfld int32 assembly::arg_1@30 + IL_0159: call int32[0...,0...] assembly::get_a3() + IL_015e: ldc.i4.0 + IL_015f: callvirt instance int32 [runtime]System.Array::GetLowerBound(int32) + IL_0164: stsfld int32 assembly::arg_2@30 + IL_0169: call int32[0...,0...] assembly::get_a3() + IL_016e: ldc.i4.1 + IL_016f: callvirt instance int32 [runtime]System.Array::GetLowerBound(int32) + IL_0174: stsfld int32 assembly::arg_3@30 + IL_0179: call int32[0...,0...] assembly::get_a3() + IL_017e: ldc.i4.0 + IL_017f: ldc.i4.0 + IL_0180: call int32[0...,0...] assembly::get_a3() + IL_0185: ldc.i4.0 + IL_0186: ldc.i4.0 + IL_0187: call instance int32 int32[0...,0...]::Get(int32, int32) - IL_018e: call instance void int32[0...,0...]::Set(int32, + IL_018c: call instance void int32[0...,0...]::Set(int32, int32, int32) - IL_0193: call int32[0...,0...,0...] assembly::get_array3D() - IL_0198: ldc.i4.s 0 - IL_019a: call instance int32 [runtime]System.Array::GetLength(int32) - IL_019f: stsfld int32 assembly::'arg_0@34-1' - IL_01a4: call int32[0...,0...,0...] assembly::get_array3D() - IL_01a9: ldc.i4.s 1 - IL_01ab: call instance int32 [runtime]System.Array::GetLength(int32) - IL_01b0: stsfld int32 assembly::'arg_1@34-1' - IL_01b5: call int32[0...,0...,0...] assembly::get_array3D() - IL_01ba: ldc.i4.s 2 - IL_01bc: call instance int32 [runtime]System.Array::GetLength(int32) - IL_01c1: stsfld int32 assembly::'arg_2@34-1' - IL_01c6: call int32[0...,0...,0...] assembly::get_array3D() + IL_0191: call int32[0...,0...,0...] assembly::get_array3D() + IL_0196: ldc.i4.s 0 + IL_0198: call instance int32 [runtime]System.Array::GetLength(int32) + IL_019d: stsfld int32 assembly::'arg_0@34-1' + IL_01a2: call int32[0...,0...,0...] assembly::get_array3D() + IL_01a7: ldc.i4.s 1 + IL_01a9: call instance int32 [runtime]System.Array::GetLength(int32) + IL_01ae: stsfld int32 assembly::'arg_1@34-1' + IL_01b3: call int32[0...,0...,0...] assembly::get_array3D() + IL_01b8: ldc.i4.s 2 + IL_01ba: call instance int32 [runtime]System.Array::GetLength(int32) + IL_01bf: stsfld int32 assembly::'arg_2@34-1' + IL_01c4: call int32[0...,0...,0...] assembly::get_array3D() + IL_01c9: ldc.i4.0 + IL_01ca: ldc.i4.0 IL_01cb: ldc.i4.0 - IL_01cc: ldc.i4.0 - IL_01cd: ldc.i4.0 - IL_01ce: call int32[0...,0...,0...] assembly::get_array3D() + IL_01cc: call int32[0...,0...,0...] assembly::get_array3D() + IL_01d1: ldc.i4.0 + IL_01d2: ldc.i4.0 IL_01d3: ldc.i4.0 - IL_01d4: ldc.i4.0 - IL_01d5: ldc.i4.0 - IL_01d6: call instance int32 int32[0...,0...,0...]::Get(int32, + IL_01d4: call instance int32 int32[0...,0...,0...]::Get(int32, int32, int32) - IL_01db: call instance void int32[0...,0...,0...]::Set(int32, + IL_01d9: call instance void int32[0...,0...,0...]::Set(int32, int32, int32, int32) - IL_01e0: call int32[0...,0...,0...,0...] assembly::get_array4D() - IL_01e5: ldc.i4.s 0 - IL_01e7: call instance int32 [runtime]System.Array::GetLength(int32) - IL_01ec: stsfld int32 assembly::'arg_0@38-2' - IL_01f1: call int32[0...,0...,0...,0...] assembly::get_array4D() - IL_01f6: ldc.i4.s 1 - IL_01f8: call instance int32 [runtime]System.Array::GetLength(int32) - IL_01fd: stsfld int32 assembly::'arg_1@38-2' - IL_0202: call int32[0...,0...,0...,0...] assembly::get_array4D() - IL_0207: ldc.i4.s 2 - IL_0209: call instance int32 [runtime]System.Array::GetLength(int32) - IL_020e: stsfld int32 assembly::'arg_2@38-2' - IL_0213: call int32[0...,0...,0...,0...] assembly::get_array4D() - IL_0218: ldc.i4.s 3 - IL_021a: call instance int32 [runtime]System.Array::GetLength(int32) - IL_021f: stsfld int32 assembly::'arg_3@38-1' - IL_0224: call int32[0...,0...,0...,0...] assembly::get_array4D() + IL_01de: call int32[0...,0...,0...,0...] assembly::get_array4D() + IL_01e3: ldc.i4.s 0 + IL_01e5: call instance int32 [runtime]System.Array::GetLength(int32) + IL_01ea: stsfld int32 assembly::'arg_0@38-2' + IL_01ef: call int32[0...,0...,0...,0...] assembly::get_array4D() + IL_01f4: ldc.i4.s 1 + IL_01f6: call instance int32 [runtime]System.Array::GetLength(int32) + IL_01fb: stsfld int32 assembly::'arg_1@38-2' + IL_0200: call int32[0...,0...,0...,0...] assembly::get_array4D() + IL_0205: ldc.i4.s 2 + IL_0207: call instance int32 [runtime]System.Array::GetLength(int32) + IL_020c: stsfld int32 assembly::'arg_2@38-2' + IL_0211: call int32[0...,0...,0...,0...] assembly::get_array4D() + IL_0216: ldc.i4.s 3 + IL_0218: call instance int32 [runtime]System.Array::GetLength(int32) + IL_021d: stsfld int32 assembly::'arg_3@38-1' + IL_0222: call int32[0...,0...,0...,0...] assembly::get_array4D() + IL_0227: ldc.i4.0 + IL_0228: ldc.i4.0 IL_0229: ldc.i4.0 IL_022a: ldc.i4.0 - IL_022b: ldc.i4.0 - IL_022c: ldc.i4.0 - IL_022d: call int32[0...,0...,0...,0...] assembly::get_array4D() + IL_022b: call int32[0...,0...,0...,0...] assembly::get_array4D() + IL_0230: ldc.i4.0 + IL_0231: ldc.i4.0 IL_0232: ldc.i4.0 IL_0233: ldc.i4.0 - IL_0234: ldc.i4.0 - IL_0235: ldc.i4.0 - IL_0236: call instance int32 int32[0...,0...,0...,0...]::Get(int32, + IL_0234: call instance int32 int32[0...,0...,0...,0...]::Get(int32, int32, int32, int32) - IL_023b: call void [FSharp.Core]Microsoft.FSharp.Collections.Array4DModule::Set(!!0[0...,0...,0...,0...], + IL_0239: call void [FSharp.Core]Microsoft.FSharp.Collections.Array4DModule::Set(!!0[0...,0...,0...,0...], int32, int32, int32, int32, !!0) - IL_0240: nop - IL_0241: ret + IL_023e: nop + IL_023f: ldc.i4.2 + IL_0240: ldc.i4.2 + IL_0241: ldsfld class assembly/clo@42 assembly/clo@42::@_instance + IL_0246: call !!0[0...,0...] [FSharp.Core]Microsoft.FSharp.Collections.Array2DModule::Initialize(int32, + int32, + class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) + IL_024b: stsfld int32[0...,0...] assembly::arg@1 + IL_0250: ret } .property class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 @@ -787,6 +831,11 @@ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 09 00 00 00 00 00 ) .get int32 assembly::'get_arg_3@38-1'() } + .property int32[0...,0...] arg@1() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 09 00 00 00 00 00 ) + .get int32[0...,0...] assembly::get_arg@1() + } } .class private abstract auto ansi sealed ''.$assembly @@ -811,4 +860,3 @@ - diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/Misc.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/Misc.fs index 6e0cdd780d6..e8fa23072fb 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/Misc.fs +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/Misc.fs @@ -37,6 +37,7 @@ module Misc = let ``CodeGenRenamings01_fs`` compilation = compilation |> getCompilation + |> withFSharpCoreShippedNet |> asExe |> verifyCompilation diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/Array2Module.fs b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/Array2Module.fs index 3cbf586831a..31ebeeaf190 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/Array2Module.fs +++ b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/Array2Module.fs @@ -187,8 +187,9 @@ type Array2Module() = [] member this.Copy() = // integer array - let intArr = Array2D.init 2 3 (fun i j -> i*100 + j) + let intArr = Array2D.initBased 3 7 2 3 (fun i j -> i*100 + j) let resultInt = Array2D.copy intArr + if obj.ReferenceEquals(intArr, resultInt) then Assert.Fail() if resultInt <> intArr then Assert.Fail() @@ -197,6 +198,12 @@ type Array2Module() = let resultStr = Array2D.copy strArr if resultStr <> strArr then Assert.Fail() + // copy must return obj[,], not preserve the source's runtime string[,] type. + let covariantSource = Array2D.create 1 1 "value" |> box |> unbox + let covariantCopy = Array2D.copy covariantSource + covariantCopy.[0, 0] <- box 42 + Assert.Equal(box 42, covariantCopy.[0, 0]) + // empty array let eptArr = Array2D.create 0 0 1 let resultEpt = Array2D.copy eptArr @@ -225,6 +232,11 @@ type Array2Module() = let eptArr = Array2D.create 0 0 1 let resultEpt = Array2D.create 0 0 1 if resultEpt <> eptArr then Assert.Fail() + shouldBeEmpty resultEpt + + // invalid arguments + CheckThrowsArgumentException (fun () -> Array2D.create -1 2 0 |> ignore) + CheckThrowsArgumentException (fun () -> Array2D.create 1 -2 0 |> ignore) () @@ -284,6 +296,14 @@ type Array2Module() = // string array let strArr = Array2D.init 2 3 (fun i j -> i.ToString() + "-" + j.ToString()) if strArr.[1,1] <> "1-1" then Assert.Fail() + + // empty array + let eptArr = Array2D.init 0 0 (fun i j -> i + j) + shouldBeEmpty eptArr + + // invalid arguments + CheckThrowsArgumentException (fun () -> Array2D.init -1 2 (fun i j -> i + j) |> ignore) + CheckThrowsArgumentException (fun () -> Array2D.init 1 -2 (fun i j -> i + j) |> ignore) () [] @@ -409,10 +429,10 @@ type Array2Module() = [] member this.Map() = // integer array - let intArr = Array2D.init 2 3 (fun i j -> i*100 + j) + let intArr = Array2D.initBased 3 7 2 3 (fun i j -> i*100 + j) let funInt x = x.ToString() let resultInt = Array2D.map funInt intArr - if resultInt <> (Array2D.init 2 3 (fun i j -> (i*100 + j).ToString())) then Assert.Fail() + if resultInt <> (Array2D.initBased 3 7 2 3 (fun i j -> (i*100 + j).ToString())) then Assert.Fail() // string array @@ -435,10 +455,10 @@ type Array2Module() = [] member this.Mapi() = // integer array - let intArr = Array2D.init 2 3 (fun i j -> i*100 + j) - let funInt x y z = x+y+z - let resultInt = Array2D.mapi funInt intArr - if resultInt <> (Array2D.init 2 3 (fun i j -> i*100 + j + i + j)) then Assert.Fail() + let intArr = Array2D.initBased 3 7 2 3 (fun i j -> i*100 + j) + let funIntToStr x y z = sprintf "%d,%d:%d" x y z + let resultInt = Array2D.mapi funIntToStr intArr + if resultInt <> (Array2D.initBased 3 7 2 3 (fun i j -> sprintf "%d,%d:%d" i j (i*100 + j))) then Assert.Fail() // string array @@ -449,8 +469,8 @@ type Array2Module() = // empty array let eptArr = Array2D.create 0 0 1 - let resultEpt = Array2D.mapi funInt eptArr - if resultEpt <> Array2D.create 0 0 1 then Assert.Fail() + let resultEpt = Array2D.mapi funIntToStr eptArr + if resultEpt <> Array2D.create 0 0 "" then Assert.Fail() // null array let nullArr = null:string[,] @@ -767,3 +787,21 @@ type Array2Module() = [| 5.; 100.; 7.; 8. |]; [| 9.; 100.; 11.; 12. |] |]) + +#if NET9_0_OR_GREATER + // Only a Windows-only NativeAOT leg would otherwise catch a change to either direction. + [] + [] + [] + [] + [] + [] + [] + [] + [] + [] + member this.RequiresDynamicCodeIsOnBasedApisOnly(name: string, expected: bool) = + let m = typeof.Assembly.GetType("Microsoft.FSharp.Collections.Array2DModule").GetMethod(name) + Assert.NotNull m + Assert.Equal(expected, m.IsDefined(typeof, false)) +#endif