From 7192705edeb685a7594d5f6114c63f2596fadf1c Mon Sep 17 00:00:00 2001 From: Nat Elkins Date: Wed, 8 Jul 2026 13:27:03 -0400 Subject: [PATCH 01/33] Avoid leaking a MeterListener per Cache in DEBUG builds (#19995) * Avoid leaking a MeterListener per Cache in DEBUG builds In DEBUG builds, every Cache instance created a CacheMetrics.CacheMetricsListener, which starts a System.Diagnostics.Metrics.MeterListener registered in the process-global metrics registry. These were never disposed, so they accumulated for the lifetime of the process. Because every cache hit/miss/add publishes a measurement to all registered listeners, the per-operation cost grew linearly with the number of leaked listeners, so workloads that create many caches (for example repeated ParseAndCheckProject / per-file checks) slowed down steadily. Track the per-cache totals used by DebugDisplay directly, incrementing a small Stats object alongside the existing global Meter counters, instead of via a per-cache MeterListener. No listener is created, so nothing leaks, and DebugDisplay still works. The now-unused CacheMetrics.Hit/Miss/Add/Update/Eviction/EvictionFail helpers are replaced by a single recordMetric helper. * Address review: drop per-cache CacheMetricsListener and cacheId tag - Remove the CacheMetrics.CacheMetricsListener type. Its only per-cache use was the #if DEBUG debugListener each Cache created and never disposed, which was the leak this PR set out to fix. (majocha) - Drop the per-instance cacheId tag (and nextCacheId). Measurements now carry only the cache name, shrinking the payload published to any connected exporter and removing the per-instance filtering that was cacheId's only purpose. (majocha) - DebugDisplay and the cache tests read the existing name-aggregated stats via CacheMetrics.getTotalsByName / getRatioByName, populated by the single process-wide ListenToAll listener. No per-cache listener is created and no per-operation cost is added in any configuration, so there is no DEBUG-only overhead left to gate behind a separate directive. (T-Gro) - Overload-cache tests enable ListenToAll and snapshot totals before/after to stay scoped to their own compilation; FSharpChecker .CreateOverloadCacheMetricsListener is removed. * Update public SurfaceArea baseline after removing CacheMetricsListener CacheMetricsListener was a public type, so dropping it changes the recorded public surface. Remove its 10 entries from FSharp.Compiler.Service.SurfaceArea.netstandard20.bsl; the SurfaceArea test now passes. Also note the single-listener assumption the cache metric tests rely on. * Apply fantomas formatting to Caches.fs * Document why OverloadCacheTests is not parallelizable (global cache metrics state) --------- Co-authored-by: Tomas Grosup --- .../.FSharp.Compiler.Service/11.0.100.md | 1 + src/Compiler/Service/service.fs | 3 - src/Compiler/Service/service.fsi | 3 - src/Compiler/Utilities/Caches.fs | 66 +++---------------- src/Compiler/Utilities/Caches.fsi | 25 +++---- .../CompilerService/Caches.fs | 53 ++++++++------- ...iler.Service.SurfaceArea.netstandard20.bsl | 10 --- .../OverloadCacheTests.fs | 36 ++++++---- 8 files changed, 74 insertions(+), 123 deletions(-) diff --git a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md index 47210a580fd..f2e8661b650 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md +++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md @@ -1,5 +1,6 @@ ### Fixed +* Stop leaking a `System.Diagnostics.Metrics.MeterListener` per `Cache` in DEBUG builds. Each cache created a `CacheMetrics.CacheMetricsListener` (which starts a `MeterListener` registered in the process-global metrics registry) and never disposed it, so listeners accumulated for the lifetime of the process. Because every cache hit/miss/add published to all registered listeners, the per-operation cost grew linearly with the number of leaked listeners, so repeated checks (and Debug FCS test runs) slowed down over time. The per-cache `CacheMetricsListener` and the per-instance `cacheId` tag are removed; `DebugDisplay` and tests now read the existing name-aggregated stats populated by the single `ListenToAll` listener, so no per-cache listener is created and no per-operation cost is added. ([PR #19995](https://github.com/dotnet/fsharp/pull/19995)) * Fix state machine lowering dropping the side-effectful receiver of an unused unit-typed member access (e.g. inside `task { (effectful()).UnitProp }`). ([Issue #13099](https://github.com/dotnet/fsharp/issues/13099), [PR #19885](https://github.com/dotnet/fsharp/pull/19885)) * `--deterministic` Release builds now produce byte-identical `FSharp.Compiler.Service.dll` under `--parallelcompilation+` and `--parallelcompilation-`, so it is restored to the determinism gate (now also checked sequential-vs-parallel). Code generation runs the same deferred per-file drain in both modes, with type/member/field emit-order keys and generated names derived from the file being emitted rather than thread-scheduling order. ([Issue #19928](https://github.com/dotnet/fsharp/issues/19928), [PR #19929](https://github.com/dotnet/fsharp/pull/19929)) * Fix `[]` silently producing duplicate IL entries (FS0192/FS2014) when applied to a multi-value let-binding (e.g. `let a, b = 1, 2`); now emits FS0755 at type-check time. ([Issue #6131](https://github.com/dotnet/fsharp/issues/6131), [PR #19924](https://github.com/dotnet/fsharp/pull/19924)) diff --git a/src/Compiler/Service/service.fs b/src/Compiler/Service/service.fs index c0dd6e21d09..3584ca61e49 100644 --- a/src/Compiler/Service/service.fs +++ b/src/Compiler/Service/service.fs @@ -623,9 +623,6 @@ type FSharpChecker static member Instance = globalInstance.Force() - static member internal CreateOverloadCacheMetricsListener() = - new CacheMetrics.CacheMetricsListener("overloadResolutionCache") - member internal _.FrameworkImportsCache = backgroundCompiler.FrameworkImportsCache /// Tokenize a single line, returning token information and a tokenization state represented by an integer diff --git a/src/Compiler/Service/service.fsi b/src/Compiler/Service/service.fsi index ae2b253c676..1584e19562b 100644 --- a/src/Compiler/Service/service.fsi +++ b/src/Compiler/Service/service.fsi @@ -506,9 +506,6 @@ type public FSharpChecker = [] static member Instance: FSharpChecker - /// Creates a listener for overload resolution cache metrics, aggregating across all compilations. - static member internal CreateOverloadCacheMetricsListener: unit -> CacheMetrics.CacheMetricsListener - member internal FrameworkImportsCache: FrameworkImportsCache member internal ReferenceResolver: LegacyReferenceResolver diff --git a/src/Compiler/Utilities/Caches.fs b/src/Compiler/Utilities/Caches.fs index fb024844e09..d8c143cebc6 100644 --- a/src/Compiler/Utilities/Caches.fs +++ b/src/Compiler/Utilities/Caches.fs @@ -22,14 +22,12 @@ module CacheMetrics = let creations = Meter.CreateCounter("creations", "count") let disposals = Meter.CreateCounter("disposals", "count") - let mutable private nextCacheId = 0 - let mkTags (name: string) = - let cacheId = Interlocked.Increment &nextCacheId // Avoid TagList(ReadOnlySpan<...>) to support net472 runtime + // Only the cache name is tagged: a per-instance id would be published on every measurement, + // inflating the tag payload sent to any connected exporter for no in-process benefit. let mutable tags = TagList() tags.Add("name", box name) - tags.Add("cacheId", box cacheId) tags let Add (tags: inref) = adds.Add(1L, &tags) @@ -78,6 +76,10 @@ module CacheMetrics = let getStatsByName name = statsByName.GetOrAdd(name, fun _ -> Stats()) + let getTotalsByName name = (getStatsByName name).GetTotals() + + let getRatioByName name = (getStatsByName name).Ratio + let ListenToAll () = let listener = new MeterListener() @@ -123,50 +125,6 @@ module CacheMetrics = Console.WriteLine(StatsToString()) } - [] - type CacheMetricsListener(cacheTags: TagList, ?nameOnlyFilter: string) = - - let stats = Stats() - let listener = new MeterListener() - - do - for instrument in allCounters do - listener.EnableMeasurementEvents instrument - - listener.SetMeasurementEventCallback(fun instrument v tags _ -> - let shouldIncrement = - match nameOnlyFilter with - | Some filterName -> - match tags[0].Value with - | :? string as name when name = filterName -> true - | _ -> false - | None -> tags[0] = cacheTags[0] && tags[1] = cacheTags[1] - - if shouldIncrement then - stats.Incr instrument.Name v) - - listener.Start() - - /// Creates a listener that aggregates metrics across all cache instances with the given name. - new(cacheName: string) = new CacheMetricsListener(TagList(), nameOnlyFilter = cacheName) - - interface IDisposable with - member _.Dispose() = listener.Dispose() - - /// Gets the current totals for each metric type. - member _.GetTotals() = stats.GetTotals() - - /// Gets the current hit ratio (hits / (hits + misses)). - member _.Ratio = stats.Ratio - - /// Gets the total number of cache hits. - member _.Hits = stats.GetTotals().[hits.Name] - - /// Gets the total number of cache misses. - member _.Misses = stats.GetTotals().[misses.Name] - - override _.ToString() = stats.ToString() - [] type EvictionMode = | NoEviction @@ -361,10 +319,6 @@ type Cache<'Key, 'Value when 'Key: not null> internal (options: CacheOptions<'Ke post, dispose -#if DEBUG - let debugListener = new CacheMetrics.CacheMetricsListener(tags) -#endif - do CacheMetrics.Created &tags member val Evicted = evicted.Publish @@ -430,9 +384,6 @@ type Cache<'Key, 'Value when 'Key: not null> internal (options: CacheOptions<'Ke CacheMetrics.Update &tags post (EvictionQueueMessage.Update result) - member _.CreateMetricsListener() = - new CacheMetrics.CacheMetricsListener(tags) - member _.Dispose() = if Interlocked.Exchange(&disposed, 1) = 0 then disposeEvictionProcessor () @@ -447,5 +398,8 @@ type Cache<'Key, 'Value when 'Key: not null> internal (options: CacheOptions<'Ke override this.Finalize() = this.Dispose() #if DEBUG - member _.DebugDisplay() = debugListener.ToString() + // Shows the totals aggregated for this cache's name. Populated only while a metrics listener + // (CacheMetrics.ListenToAll, e.g. under --times or the editor's metrics view) is running. + member _.DebugDisplay() = + (CacheMetrics.getStatsByName name).ToString() #endif diff --git a/src/Compiler/Utilities/Caches.fsi b/src/Compiler/Utilities/Caches.fsi index 3e1c98e9bb1..e0bff618fcb 100644 --- a/src/Compiler/Utilities/Caches.fsi +++ b/src/Compiler/Utilities/Caches.fsi @@ -8,25 +8,18 @@ module CacheMetrics = /// Global telemetry Meter for all caches. Exposed for testing purposes. /// Set FSHARP_OTEL_EXPORT environment variable to enable OpenTelemetry export to external collectors in tests. val Meter: Meter + + /// Current metric totals aggregated across all cache instances with the given name. + /// Totals only accumulate while a listener from ListenToAll is running. + val internal getTotalsByName: name: string -> Map + + /// Current hit ratio (hits / (hits + misses)) aggregated across all cache instances with the given name. + val internal getRatioByName: name: string -> float + val internal ListenToAll: unit -> IDisposable val internal StatsToString: unit -> string val internal CaptureStatsAndWriteToConsole: unit -> IDisposable - /// A listener that captures cache metrics, matching by cache name or exact cache tags. - [] - type CacheMetricsListener = - /// Creates a listener that aggregates metrics across all cache instances with the given name. - new: cacheName: string -> CacheMetricsListener - /// Gets the current totals for each metric type. - member GetTotals: unit -> Map - /// Gets the current hit ratio (hits / (hits + misses)). - member Ratio: float - /// Gets the total number of cache hits. - member Hits: int64 - /// Gets the total number of cache misses. - member Misses: int64 - interface IDisposable - [] type internal EvictionMode = /// Do not evict items, cache is effectively a ConcurrentDictionary. @@ -74,5 +67,3 @@ type internal Cache<'Key, 'Value when 'Key: not null> = member Evicted: IEvent /// For testing only. member EvictionFailed: IEvent - /// For testing only. Creates a local telemetry listener for this cache instance. - member CreateMetricsListener: unit -> CacheMetrics.CacheMetricsListener diff --git a/tests/FSharp.Compiler.ComponentTests/CompilerService/Caches.fs b/tests/FSharp.Compiler.ComponentTests/CompilerService/Caches.fs index b7aac72a93b..c00f1af81ba 100644 --- a/tests/FSharp.Compiler.ComponentTests/CompilerService/Caches.fs +++ b/tests/FSharp.Compiler.ComponentTests/CompilerService/Caches.fs @@ -16,6 +16,12 @@ let shouldNeverTimeout = 200_000 let defaultStructural() = CacheOptions.getDefault HashIdentity.Structural +// Metrics assertions below read absolute per-name totals via CacheMetrics.getTotalsByName. Those totals +// are aggregated process-globally while a CacheMetrics.ListenToAll() listener is running. This works +// because each test uses a unique cache name and this module is the only ListenToAll caller in the +// assembly, so nothing else increments those names. A second concurrently-active listener would +// double-count every measurement, so keep it that way. + [] let ``Create and dispose many`` () = let caches = @@ -28,8 +34,8 @@ let ``Create and dispose many`` () = [] let ``Basic add and retrieve`` () = let name = "Basic_add_and_retrieve" + use _ = CacheMetrics.ListenToAll() use cache = new Cache(defaultStructural(), name = name) - use metricsListener = cache.CreateMetricsListener() cache.TryAdd("key1", 1) |> shouldBeTrue cache.TryAdd("key2", 2) |> shouldBeTrue @@ -45,14 +51,14 @@ let ``Basic add and retrieve`` () = cache.TryGetValue("key3", &value) |> shouldBeFalse // Metrics assertions - let totals = metricsListener.GetTotals() + let totals = CacheMetrics.getTotalsByName name totals.["adds"] |> shouldEqual 2L [] let ``Eviction of least recently used`` () = let name = "Eviction_of_least_recently_used" + use _ = CacheMetrics.ListenToAll() use cache = new Cache({ defaultStructural() with TotalCapacity = 2; HeadroomPercentage = 0 }, name = name) - use metricsListener = cache.CreateMetricsListener() cache.TryAdd("key1", 1) |> shouldBeTrue cache.TryAdd("key2", 2) |> shouldBeTrue @@ -76,7 +82,7 @@ let ``Eviction of least recently used`` () = value |> shouldEqual 3 // Metrics assertions - let totals = metricsListener.GetTotals() + let totals = CacheMetrics.getTotalsByName name totals.["adds"] |> shouldEqual 3L [] @@ -85,14 +91,14 @@ let ``Stress test evictions`` () = let iterations = 10_000 let name = "Stress test evictions" + use _ = CacheMetrics.ListenToAll() use cache = new Cache({ defaultStructural() with TotalCapacity = cacheSize; HeadroomPercentage = 0 }, name = name) - use metricsListener = cache.CreateMetricsListener() let evictionsCompleted = new TaskCompletionSource() let expectedEvictions = iterations - cacheSize cache.Evicted.Add <| fun () -> - if metricsListener.GetTotals().["evictions"] = expectedEvictions then + if (CacheMetrics.getTotalsByName name).["evictions"] = expectedEvictions then evictionsCompleted.SetResult() cache.EvictionFailed.Add <| fun _ -> @@ -114,13 +120,14 @@ let ``Stress test evictions`` () = value |> shouldEqual iterations // Metrics assertions - let totals = metricsListener.GetTotals() + let totals = CacheMetrics.getTotalsByName name totals.["adds"] |> shouldEqual (int64 iterations) [] let ``Metrics can be retrieved`` () = - use cache = new Cache({ defaultStructural() with TotalCapacity = 2; HeadroomPercentage = 0 }, name = "test_metrics") - use metricsListener = cache.CreateMetricsListener() + let name = "test_metrics" + use _ = CacheMetrics.ListenToAll() + use cache = new Cache({ defaultStructural() with TotalCapacity = 2; HeadroomPercentage = 0 }, name = name) cache.TryAdd("key1", 1) |> shouldBeTrue cache.TryAdd("key2", 2) |> shouldBeTrue @@ -135,17 +142,17 @@ let ``Metrics can be retrieved`` () = cache.TryAdd("key3", 3) |> shouldBeTrue evictionCompleted.Task.Wait shouldNeverTimeout |> shouldBeTrue - let totals = metricsListener.GetTotals() + let totals = CacheMetrics.getTotalsByName name - metricsListener.Ratio |> shouldEqual 1.0 + CacheMetrics.getRatioByName name |> shouldEqual 1.0 totals.["evictions"] |> shouldEqual 1L totals.["adds"] |> shouldEqual 3L [] let ``GetOrAdd basic usage`` () = let cacheName = "GetOrAdd_basic_usage" + use _ = CacheMetrics.ListenToAll() use cache = new Cache(defaultStructural(), name = cacheName) - use metricsListener = cache.CreateMetricsListener() let mutable factoryCalls = 0 let factory k = factoryCalls <- factoryCalls + 1; String.length k let v1 = cache.GetOrAdd("abc", factory) @@ -157,17 +164,17 @@ let ``GetOrAdd basic usage`` () = v3 |> shouldEqual 4 factoryCalls |> shouldEqual 2 // Metrics assertions - let totals = metricsListener.GetTotals() + let totals = CacheMetrics.getTotalsByName cacheName totals.["hits"] |> shouldEqual 1L totals.["misses"] |> shouldEqual 2L - metricsListener.Ratio |> shouldEqual (1.0/3.0) + CacheMetrics.getRatioByName cacheName |> shouldEqual (1.0/3.0) totals.["adds"] |> shouldEqual 2L [] let ``AddOrUpdate basic usage`` () = let cacheName = "AddOrUpdate_basic_usage" + use _ = CacheMetrics.ListenToAll() use cache = new Cache(defaultStructural(), name = cacheName) - use metricsListener = cache.CreateMetricsListener() cache.AddOrUpdate("x", 1) let mutable value = 0 cache.TryGetValue("x", &value) |> shouldBeTrue @@ -179,10 +186,10 @@ let ``AddOrUpdate basic usage`` () = cache.TryGetValue("y", &value) |> shouldBeTrue value |> shouldEqual 99 // Metrics assertions - let totals = metricsListener.GetTotals() + let totals = CacheMetrics.getTotalsByName cacheName totals.["hits"] |> shouldEqual 3L // 3 cache hits totals.["misses"] |> shouldEqual 0L // 0 cache misses - metricsListener.Ratio |> shouldEqual 1.0 + CacheMetrics.getRatioByName cacheName |> shouldEqual 1.0 totals.["adds"] |> shouldEqual 2L // "x" and "y" added totals.["updates"] |> shouldEqual 1L // "x" updated @@ -191,8 +198,8 @@ type BoxedKey = BoxedKey of int * int [] let ``GetOrAdd with reference identity`` () = let cacheName = "GetOrAdd_with_Reference" + use _ = CacheMetrics.ListenToAll() use cache = new Cache(CacheOptions.getReferenceIdentity(), cacheName) - use metricsListener = cache.CreateMetricsListener() let t1 = BoxedKey (1, 2) let t2 = BoxedKey (1, 2) let t3 = BoxedKey (1, 2) @@ -219,17 +226,17 @@ let ``GetOrAdd with reference identity`` () = v1'' |> shouldEqual v1' v2'' |> shouldEqual v2' // Metrics assertions - let totals = metricsListener.GetTotals() + let totals = CacheMetrics.getTotalsByName cacheName totals.["hits"] |> shouldEqual 4L totals.["misses"] |> shouldEqual 3L - metricsListener.Ratio |> shouldEqual (4.0 / 7.0) + CacheMetrics.getRatioByName cacheName |> shouldEqual (4.0 / 7.0) totals.["adds"] |> shouldEqual 2L [] let ``AddOrUpdate with reference identity`` () = let cacheName = "AddOrUpdate_with_Reference" + use _ = CacheMetrics.ListenToAll() use cache = new Cache(CacheOptions.getReferenceIdentity(), name = cacheName) - use metricsListener = cache.CreateMetricsListener() let t1 = box (3, 4) let t2 = box (3, 4) cache.AddOrUpdate(t1, 7) @@ -248,9 +255,9 @@ let ``AddOrUpdate with reference identity`` () = cache.TryGetValue(t1, &value1Updated) |> shouldBeTrue value1Updated |> shouldEqual 9 // Metrics assertions - let totals = metricsListener.GetTotals() + let totals = CacheMetrics.getTotalsByName cacheName totals.["hits"] |> shouldEqual 3L // 3 cache hits totals.["misses"] |> shouldEqual 0L // 0 cache misses - metricsListener.Ratio |> shouldEqual 1.0 + CacheMetrics.getRatioByName cacheName |> shouldEqual 1.0 totals.["adds"] |> shouldEqual 2L // t1 and t2 added totals.["updates"] |> shouldEqual 1L // t1 updated once diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.bsl b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.bsl index 0a8b95305b6..0c81c8df894 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.bsl +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.bsl @@ -2035,16 +2035,6 @@ FSharp.Compiler.AbstractIL.ILBinaryReader: FSharp.Compiler.AbstractIL.ILBinaryRe FSharp.Compiler.AbstractIL.ILBinaryReader: FSharp.Compiler.AbstractIL.ILBinaryReader+MetadataOnlyFlag FSharp.Compiler.AbstractIL.ILBinaryReader: FSharp.Compiler.AbstractIL.ILBinaryReader+ReduceMemoryFlag FSharp.Compiler.AbstractIL.ILBinaryReader: FSharp.Compiler.AbstractIL.ILBinaryReader+Shim -FSharp.Compiler.Caches.CacheMetrics+CacheMetricsListener: Double Ratio -FSharp.Compiler.Caches.CacheMetrics+CacheMetricsListener: Double get_Ratio() -FSharp.Compiler.Caches.CacheMetrics+CacheMetricsListener: Int64 Hits -FSharp.Compiler.Caches.CacheMetrics+CacheMetricsListener: Int64 Misses -FSharp.Compiler.Caches.CacheMetrics+CacheMetricsListener: Int64 get_Hits() -FSharp.Compiler.Caches.CacheMetrics+CacheMetricsListener: Int64 get_Misses() -FSharp.Compiler.Caches.CacheMetrics+CacheMetricsListener: Microsoft.FSharp.Collections.FSharpMap`2[System.String,System.Int64] GetTotals() -FSharp.Compiler.Caches.CacheMetrics+CacheMetricsListener: System.String ToString() -FSharp.Compiler.Caches.CacheMetrics+CacheMetricsListener: Void .ctor(System.String) -FSharp.Compiler.Caches.CacheMetrics: FSharp.Compiler.Caches.CacheMetrics+CacheMetricsListener FSharp.Compiler.Caches.CacheMetrics: System.Diagnostics.Metrics.Meter Meter FSharp.Compiler.Caches.CacheMetrics: System.Diagnostics.Metrics.Meter get_Meter() FSharp.Compiler.Cancellable: Boolean HasCancellationToken diff --git a/tests/FSharp.Compiler.Service.Tests/OverloadCacheTests.fs b/tests/FSharp.Compiler.Service.Tests/OverloadCacheTests.fs index cf6032afb3a..4abe9d9c46a 100644 --- a/tests/FSharp.Compiler.Service.Tests/OverloadCacheTests.fs +++ b/tests/FSharp.Compiler.Service.Tests/OverloadCacheTests.fs @@ -1,5 +1,10 @@ // Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. +// These tests are serialized (NotThreadSafeResourceCollection) because they read process-global state: +// the shared language-service `checker`, and the process-global cache metrics that +// `CacheMetrics.ListenToAll` aggregates by name (see the `use _ = CacheMetrics.ListenToAll()` in each +// test). Running them in parallel with each other, or alongside anything else that drives caches while +// a listener is attached, would let counts from unrelated work bleed into the before/after deltas. [] module FSharp.Compiler.Service.Tests.OverloadCacheTests @@ -54,23 +59,31 @@ let generateRepetitiveOverloadCalls (callCount: int) = [] let ``Overload cache hit rate exceeds 70 percent for repetitive int-int calls`` () = - use listener = FSharpChecker.CreateOverloadCacheMetricsListener() + use _ = CacheMetrics.ListenToAll() checker.ClearLanguageServiceRootCachesAndCollectAndFinalizeAllTransients() - + + // Measure only this compilation's activity: the per-name totals are process-global, so snapshot + // before/after and diff rather than reading absolute counts. + let before = CacheMetrics.getTotalsByName "overloadResolutionCache" + let callCount = 150 let source = generateRepetitiveOverloadCalls callCount checkSourceHasNoErrors source |> ignore - - let hits = listener.Hits - let misses = listener.Misses + + let after = CacheMetrics.getTotalsByName "overloadResolutionCache" + let hits = after.["hits"] - before.["hits"] + let misses = after.["misses"] - before.["misses"] Assert.True(hits + misses > 0L, "Expected cache activity but got no hits or misses - is the cache enabled?") - Assert.True(listener.Ratio > 0.70, sprintf "Expected hit ratio > 70%%, but got %.2f%%" (listener.Ratio * 100.0)) + let ratio = float hits / float (hits + misses) + Assert.True(ratio > 0.70, sprintf "Expected hit ratio > 70%%, but got %.2f%%" (ratio * 100.0)) [] let ``Overload cache returns correct resolution`` () = - use listener = FSharpChecker.CreateOverloadCacheMetricsListener() + use _ = CacheMetrics.ListenToAll() checker.ClearLanguageServiceRootCachesAndCollectAndFinalizeAllTransients() - + + let before = CacheMetrics.getTotalsByName "overloadResolutionCache" + let source = """ type Overloaded = static member Process(x: int) = "int" @@ -91,7 +104,9 @@ let f2 = Overloaded.Process(2.0) """ checkSourceHasNoErrors source |> ignore - Assert.True(listener.Hits > 0L, "Expected cache hits for repeated overload calls") + + let after = CacheMetrics.getTotalsByName "overloadResolutionCache" + Assert.True(after.["hits"] - before.["hits"] > 0L, "Expected cache hits for repeated overload calls") let overloadCorrectnessTestCases () : obj[] seq = seq { @@ -273,9 +288,8 @@ let ``Overload resolution correctness`` (_scenario: string, source: string) = [] let ``Overload cache benefits from rigid generic type parameters`` () = - use listener = FSharpChecker.CreateOverloadCacheMetricsListener() checker.ClearLanguageServiceRootCachesAndCollectAndFinalizeAllTransients() - + let source = """ type Assert = static member Equal(expected: int, actual: int) = expected = actual From 3ebcc7466ad7c1038ca640df01a3bc43de63c5da Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Thu, 9 Jul 2026 10:17:36 +0200 Subject: [PATCH 02/33] Bump FCSMinorVersion to 13 (keep main above 10.0.4xx servicing 43.12.400) (#20045) --- eng/Versions.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/Versions.props b/eng/Versions.props index b224ff9b8c4..60486fabcaa 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -38,7 +38,7 @@ 43 - 12 + 13 $(FSBuildVersion) $(FSRevisionVersion) $(FCSMajorVersion).$(FCSMinorVersion).$(FCSBuildVersion) From 87ad51b0ce068c736f71b178b7b0f28a0b285d66 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Thu, 9 Jul 2026 13:28:46 +0200 Subject: [PATCH 03/33] Update dependencies from https://github.com/dotnet/msbuild build 20260708.3 (#20048) On relative base path root Microsoft.Build , Microsoft.Build.Framework , Microsoft.Build.Tasks.Core , Microsoft.Build.Utilities.Core From Version 18.10.0-preview-26357-08 -> To Version 18.10.0-preview-26358-03 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.props | 8 ++++---- eng/Version.Details.xml | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/eng/Version.Details.props b/eng/Version.Details.props index 96a9b125d5c..b413006403e 100644 --- a/eng/Version.Details.props +++ b/eng/Version.Details.props @@ -8,10 +8,10 @@ This file should be imported by eng/Versions.props 10.0.0-beta.26324.4 - 18.10.0-preview-26357-08 - 18.10.0-preview-26357-08 - 18.10.0-preview-26357-08 - 18.10.0-preview-26357-08 + 18.10.0-preview-26358-03 + 18.10.0-preview-26358-03 + 18.10.0-preview-26358-03 + 18.10.0-preview-26358-03 1.0.0-prerelease.26318.1 1.0.0-prerelease.26318.1 diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index dbe95ffcb65..2e8683b7ba5 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -2,21 +2,21 @@ - + https://github.com/dotnet/msbuild - 746aeb090c9e2bcedc398751370da862014ebf7a + 98935500d8efcb66c1f32927cb2976ea067172d2 - + https://github.com/dotnet/msbuild - 746aeb090c9e2bcedc398751370da862014ebf7a + 98935500d8efcb66c1f32927cb2976ea067172d2 - + https://github.com/dotnet/msbuild - 746aeb090c9e2bcedc398751370da862014ebf7a + 98935500d8efcb66c1f32927cb2976ea067172d2 - + https://github.com/dotnet/msbuild - 746aeb090c9e2bcedc398751370da862014ebf7a + 98935500d8efcb66c1f32927cb2976ea067172d2 https://github.com/dotnet/roslyn From d11945a90d1a5180c706fb93036c2c80103dacb5 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Thu, 9 Jul 2026 13:28:50 +0200 Subject: [PATCH 04/33] Update dependencies from https://github.com/dotnet/roslyn build 20260708.9 (#20049) On relative base path root Microsoft.CodeAnalysis , Microsoft.CodeAnalysis.Compilers , Microsoft.CodeAnalysis.CSharp , Microsoft.CodeAnalysis.EditorFeatures , Microsoft.CodeAnalysis.EditorFeatures.Text , Microsoft.CodeAnalysis.ExternalAccess.FSharp , Microsoft.CodeAnalysis.Features , Microsoft.VisualStudio.LanguageServices From Version 5.10.0-1.26357.6 -> To Version 5.10.0-1.26358.9 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.props | 16 ++++++++-------- eng/Version.Details.xml | 32 ++++++++++++++++---------------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/eng/Version.Details.props b/eng/Version.Details.props index b413006403e..b6eb37c7f68 100644 --- a/eng/Version.Details.props +++ b/eng/Version.Details.props @@ -19,14 +19,14 @@ This file should be imported by eng/Versions.props 1.0.0-prerelease.26318.1 1.0.0-prerelease.26318.1 - 5.10.0-1.26357.6 - 5.10.0-1.26357.6 - 5.10.0-1.26357.6 - 5.10.0-1.26357.6 - 5.10.0-1.26357.6 - 5.10.0-1.26357.6 - 5.10.0-1.26357.6 - 5.10.0-1.26357.6 + 5.10.0-1.26358.9 + 5.10.0-1.26358.9 + 5.10.0-1.26358.9 + 5.10.0-1.26358.9 + 5.10.0-1.26358.9 + 5.10.0-1.26358.9 + 5.10.0-1.26358.9 + 5.10.0-1.26358.9 10.0.2 10.0.2 diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 2e8683b7ba5..0d0852f8158 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -18,37 +18,37 @@ https://github.com/dotnet/msbuild 98935500d8efcb66c1f32927cb2976ea067172d2 - + https://github.com/dotnet/roslyn - 97ee762dcf4f7135ff591ebf24b6f1dab3fe0632 + 35967bab3447f7edd6162baee7048f801f18fffe - + https://github.com/dotnet/roslyn - 97ee762dcf4f7135ff591ebf24b6f1dab3fe0632 + 35967bab3447f7edd6162baee7048f801f18fffe - + https://github.com/dotnet/roslyn - 97ee762dcf4f7135ff591ebf24b6f1dab3fe0632 + 35967bab3447f7edd6162baee7048f801f18fffe - + https://github.com/dotnet/roslyn - 97ee762dcf4f7135ff591ebf24b6f1dab3fe0632 + 35967bab3447f7edd6162baee7048f801f18fffe - + https://github.com/dotnet/roslyn - 97ee762dcf4f7135ff591ebf24b6f1dab3fe0632 + 35967bab3447f7edd6162baee7048f801f18fffe - + https://github.com/dotnet/roslyn - 97ee762dcf4f7135ff591ebf24b6f1dab3fe0632 + 35967bab3447f7edd6162baee7048f801f18fffe - + https://github.com/dotnet/roslyn - 97ee762dcf4f7135ff591ebf24b6f1dab3fe0632 + 35967bab3447f7edd6162baee7048f801f18fffe - + https://github.com/dotnet/roslyn - 97ee762dcf4f7135ff591ebf24b6f1dab3fe0632 + 35967bab3447f7edd6162baee7048f801f18fffe From 60d315a3636901380ea9efc125d8b84865d43f3c Mon Sep 17 00:00:00 2001 From: Nat Elkins Date: Thu, 9 Jul 2026 10:09:12 -0400 Subject: [PATCH 05/33] Add ResetCompilerGeneratedNameState to compiler-generated name generators (#20017) Compiler-generated occurrence names (name@line-N) are allocated from process-wide counters on CompilerGlobalState that accumulate across compilations. When a warm checker re-emits the same project in-process, an unchanged closure therefore gets a different occurrence suffix than the previous emit, so consumers that align generated names across compilations (Edit-and-Continue delta emission, dotnet/fsharp#19941) cannot match them. Add an internal ResetCompilerGeneratedNameState to NiceNameGenerator (clears the per-(name, file) occurrence counters), StableNiceNameGenerator (clears the cached stable names and the inner counters), and an aggregate on CompilerGlobalState that resets all three generators, restoring the fresh-process name layout. Callers must ensure no compilation is concurrently generating names. No in-tree caller yet; the consumer is the hot reload emit path in dotnet/fsharp#19941. Covered by unit tests proving drift without reset, exact replay after reset, and that the stable-name cache itself is cleared. --- .../.FSharp.Compiler.Service/11.0.100.md | 1 + src/Compiler/TypedTree/CompilerGlobalState.fs | 20 ++++ .../TypedTree/CompilerGlobalState.fsi | 15 +++ .../CompilerGlobalStateTests.fs | 96 +++++++++++++++++++ .../FSharp.Compiler.Service.Tests.fsproj | 1 + 5 files changed, 133 insertions(+) create mode 100644 tests/FSharp.Compiler.Service.Tests/CompilerGlobalStateTests.fs diff --git a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md index f2e8661b650..b49aa2d0835 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md +++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md @@ -139,6 +139,7 @@ * Debug: fix if and match condition sequence points ([PR #19932](https://github.com/dotnet/fsharp/pull/19932)) * Checker: recover on checking language version ([PR ##19970](https://github.com/dotnet/fsharp/pull/19970)) * Implied argument names for function-to-delegate coercions now fall back to the delegate's `Invoke` parameter names when the function has no recoverable names (e.g. a partial application like `System.Func((+) 1)`), instead of synthetic `delegateArg0`, `delegateArg1`, … names. ([PR #20001](https://github.com/dotnet/fsharp/pull/20001)) +* Add internal `ResetCompilerGeneratedNameState` to `CompilerGlobalState` name generators so warm-checker re-compilation can produce fresh-process-identical generated names. ([PR #20017](https://github.com/dotnet/fsharp/pull/20017)) ### Improved diff --git a/src/Compiler/TypedTree/CompilerGlobalState.fs b/src/Compiler/TypedTree/CompilerGlobalState.fs index dfc8bb0abbe..1f46a53ad6c 100644 --- a/src/Compiler/TypedTree/CompilerGlobalState.fs +++ b/src/Compiler/TypedTree/CompilerGlobalState.fs @@ -45,6 +45,11 @@ type NiceNameGenerator() = let count = incrementBucket basicName scopeFileIndex mkName basicName m count + /// Reset the per-(basicName, file) occurrence counters so a subsequent codegen run assigns the + /// same compiler-generated occurrence names a fresh process would. Callers must ensure no + /// concurrent codegen is using this generator when resetting. + member _.ResetCompilerGeneratedNameState() = basicNameCounts.Clear() + /// Generates compiler-generated names marked up with a source code location, but if given the same unique value then /// return precisely the same name. Each name generated also includes the StartLine number of the range passed in /// at the point of first generation. @@ -61,6 +66,12 @@ type StableNiceNameGenerator() = let key = basicName, uniq niceNames.GetOrAddLazy(key, fun (basicName, _) -> innerGenerator.FreshCompilerGeneratedNameOfBasicName(basicName, m)) + /// Reset the stable-name cache and inner occurrence counters, so both the cached stable names and + /// the underlying occurrence counters are cleared. See NiceNameGenerator.ResetCompilerGeneratedNameState. + member _.ResetCompilerGeneratedNameState() = + niceNames.Clear() + innerGenerator.ResetCompilerGeneratedNameState() + [] type PerFileNamingScope internal (nng: NiceNameGenerator, fileIndex: int) = @@ -86,6 +97,15 @@ type internal CompilerGlobalState () = member _.NewFileScope (fileRange: range) = PerFileNamingScope(globalNng, fileRange.FileIndex) + /// Reset all compiler-generated-name occurrence counters on this state, so successive in-process + /// codegen runs over the same source produce identical generated names (a fresh-process layout). + /// Callers must ensure no compilation is concurrently generating names (quiescence). Needed by + /// Edit-and-Continue style scenarios that re-emit from a warm checker. + member _.ResetCompilerGeneratedNameState() = + globalNng.ResetCompilerGeneratedNameState() + globalStableNameGenerator.ResetCompilerGeneratedNameState() + ilxgenGlobalNng.ResetCompilerGeneratedNameState() + /// Unique name generator for stamps attached to lambdas and object expressions type Unique = int64 diff --git a/src/Compiler/TypedTree/CompilerGlobalState.fsi b/src/Compiler/TypedTree/CompilerGlobalState.fsi index cf357d066be..5768089a668 100644 --- a/src/Compiler/TypedTree/CompilerGlobalState.fsi +++ b/src/Compiler/TypedTree/CompilerGlobalState.fsi @@ -18,6 +18,11 @@ type NiceNameGenerator = new: unit -> NiceNameGenerator member FreshCompilerGeneratedName: name: string * m: range -> string + /// Reset the per-(basicName, file) occurrence counters so a subsequent codegen run assigns the + /// same compiler-generated occurrence names a fresh process would. Callers must ensure no + /// concurrent codegen is using this generator when resetting. + member ResetCompilerGeneratedNameState: unit -> unit + /// Generates compiler-generated names marked up with a source code location, but if given the same unique value then /// return precisely the same name. Each name generated also includes the StartLine number of the range passed in /// at the point of first generation. @@ -29,6 +34,10 @@ type StableNiceNameGenerator = new: unit -> StableNiceNameGenerator member GetUniqueCompilerGeneratedName: name: string * m: range * uniq: int64 -> string + /// Reset the stable-name cache and inner occurrence counters, so both the cached stable names and + /// the underlying occurrence counters are cleared. See NiceNameGenerator.ResetCompilerGeneratedNameState. + member ResetCompilerGeneratedNameState: unit -> unit + /// A compiler-generated-name allocation scope bound to a single ImplFile being optimized. /// Instances can only be obtained from CompilerGlobalState.NewFileScope so a call site can't /// accidentally bucket names by the wrong (e.g. inlined-source) file and reintroduce the @@ -58,6 +67,12 @@ type internal CompilerGlobalState = /// under parallel optimization. See https://github.com/dotnet/fsharp/issues/19732. member NewFileScope: fileRange: range -> PerFileNamingScope + /// Reset all compiler-generated-name occurrence counters on this state, so successive in-process + /// codegen runs over the same source produce identical generated names (a fresh-process layout). + /// Callers must ensure no compilation is concurrently generating names (quiescence). Needed by + /// Edit-and-Continue style scenarios that re-emit from a warm checker. + member ResetCompilerGeneratedNameState: unit -> unit + type Unique = int64 /// Concurrency-safe diff --git a/tests/FSharp.Compiler.Service.Tests/CompilerGlobalStateTests.fs b/tests/FSharp.Compiler.Service.Tests/CompilerGlobalStateTests.fs new file mode 100644 index 00000000000..888e79ac50e --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/CompilerGlobalStateTests.fs @@ -0,0 +1,96 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +module FSharp.Compiler.Service.Tests.CompilerGlobalStateTests + +open FSharp.Compiler.CompilerGlobalState +open FSharp.Compiler.Text.Range +open FSharp.Test.Assert +open Xunit + +[] +let ``NiceNameGenerator drifts across calls and ResetCompilerGeneratedNameState restores a fresh-process layout`` () = + let nng = NiceNameGenerator() + let r = rangeN "niceNameGenerator.fs" 10 + + // First batch: occurrence counters start from zero, so names drift f@10, f@10-1, f@10-2. + let batch1 = [ for _ in 1 .. 3 -> nng.FreshCompilerGeneratedName("f", r) ] + batch1 |> shouldEqual [ "f@10"; "f@10-1"; "f@10-2" ] + + // Without a reset, further calls keep drifting from where the counters left off. + let keepsDriftingWithoutReset = [ for _ in 1 .. 2 -> nng.FreshCompilerGeneratedName("f", r) ] + keepsDriftingWithoutReset |> shouldEqual [ "f@10-3"; "f@10-4" ] + + // Resetting clears the occurrence counters, so a subsequent run reproduces the very first batch. + nng.ResetCompilerGeneratedNameState() + let batch2 = [ for _ in 1 .. 3 -> nng.FreshCompilerGeneratedName("f", r) ] + batch2 |> shouldEqual batch1 + +[] +let ``StableNiceNameGenerator caches by uniq and ResetCompilerGeneratedNameState clears both the cache and the counters`` () = + let gen = StableNiceNameGenerator() + let r = rangeN "stableNiceNameGenerator.fs" 20 + + // First occurrence of "h" for uniq 1. + let first = gen.GetUniqueCompilerGeneratedName("h", r, 1L) + first |> shouldEqual "h@20" + + // A different uniq for the same basic name advances the shared occurrence counter. + let second = gen.GetUniqueCompilerGeneratedName("h", r, 2L) + second |> shouldEqual "h@20-1" + + // Re-querying uniq 1 must return the cached name, not a recomputed (drifted) one, even though + // the shared occurrence counter for "h" has since advanced to produce `second`. + let cachedAgain = gen.GetUniqueCompilerGeneratedName("h", r, 1L) + cachedAgain |> shouldEqual first + + gen.ResetCompilerGeneratedNameState() + + // Replaying the exact same sequence of calls after a reset reproduces the exact same names + // ("h@20" then "h@20-1"), because both the stable-name cache and the shared occurrence + // counter were cleared: a fresh call for uniq 1 is once again the first-ever occurrence. + let afterResetForUniq1 = gen.GetUniqueCompilerGeneratedName("h", r, 1L) + afterResetForUniq1 |> shouldEqual first + + let afterResetForUniq2 = gen.GetUniqueCompilerGeneratedName("h", r, 2L) + afterResetForUniq2 |> shouldEqual second + + // The cache is fully functional again after reset: re-querying uniq 1 still returns the + // cached (post-reset) name rather than drifting further. + let cachedAgainAfterReset = gen.GetUniqueCompilerGeneratedName("h", r, 1L) + cachedAgainAfterReset |> shouldEqual afterResetForUniq1 + + // Prove the stable-name CACHE itself was cleared, not just the inner counters: after another + // reset, the same (name, uniq) key queried with a DIFFERENT range must be recomputed from the + // new range ("h@99"). A stale cache entry would instead return the pre-reset "h@20". + gen.ResetCompilerGeneratedNameState() + let differentRange = rangeN "stableNiceNameGenerator.fs" 99 + let recomputedForUniq1 = gen.GetUniqueCompilerGeneratedName("h", differentRange, 1L) + recomputedForUniq1 |> shouldEqual "h@99" + +[] +let ``CompilerGlobalState.ResetCompilerGeneratedNameState resets all three generators together`` () = + let state = CompilerGlobalState() + let r = rangeN "compilerGlobalState.fs" 30 + + let niceName1 = state.NiceNameGenerator.FreshCompilerGeneratedName("f", r) + let ilxName1 = state.IlxGenNiceNameGenerator.FreshCompilerGeneratedName("g", r) + let stableName1 = state.StableNameGenerator.GetUniqueCompilerGeneratedName("h", r, 1L) + + // Drift each generator away from its first-occurrence name before resetting. + state.NiceNameGenerator.FreshCompilerGeneratedName("f", r) |> ignore + state.IlxGenNiceNameGenerator.FreshCompilerGeneratedName("g", r) |> ignore + state.StableNameGenerator.GetUniqueCompilerGeneratedName("h", r, 2L) |> ignore + + state.ResetCompilerGeneratedNameState() + + let niceName2 = state.NiceNameGenerator.FreshCompilerGeneratedName("f", r) + let ilxName2 = state.IlxGenNiceNameGenerator.FreshCompilerGeneratedName("g", r) + // Replaying the same first call (uniq 1) after the aggregate reset reproduces the original + // stable name, confirming the reset reached the StableNameGenerator too. (StableNiceNameGenerator's + // own tests separately confirm that the reset actually clears its cache, rather than merely + // resetting the shared occurrence counter.) + let stableName2 = state.StableNameGenerator.GetUniqueCompilerGeneratedName("h", r, 1L) + + niceName2 |> shouldEqual niceName1 + ilxName2 |> shouldEqual ilxName1 + stableName2 |> shouldEqual stableName1 diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj index d29c8693d18..6193e4f73a4 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj @@ -53,6 +53,7 @@ + From 5928e91b5f701586690562ce10bd639357fff50b Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Fri, 10 Jul 2026 10:55:22 +0200 Subject: [PATCH 06/33] Update dependencies from https://github.com/dotnet/msbuild build 20260709.10 (#20051) On relative base path root Microsoft.Build , Microsoft.Build.Framework , Microsoft.Build.Tasks.Core , Microsoft.Build.Utilities.Core From Version 18.10.0-preview-26358-03 -> To Version 18.10.0-1.26359.10 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.props | 8 ++++---- eng/Version.Details.xml | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/eng/Version.Details.props b/eng/Version.Details.props index b6eb37c7f68..fb64aafcc65 100644 --- a/eng/Version.Details.props +++ b/eng/Version.Details.props @@ -8,10 +8,10 @@ This file should be imported by eng/Versions.props 10.0.0-beta.26324.4 - 18.10.0-preview-26358-03 - 18.10.0-preview-26358-03 - 18.10.0-preview-26358-03 - 18.10.0-preview-26358-03 + 18.10.0-1.26359.10 + 18.10.0-1.26359.10 + 18.10.0-1.26359.10 + 18.10.0-1.26359.10 1.0.0-prerelease.26318.1 1.0.0-prerelease.26318.1 diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 0d0852f8158..e446d5e3f40 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -2,21 +2,21 @@ - + https://github.com/dotnet/msbuild - 98935500d8efcb66c1f32927cb2976ea067172d2 + ad7e074ca3a93f4af30405c4cd24db04151d7ce8 - + https://github.com/dotnet/msbuild - 98935500d8efcb66c1f32927cb2976ea067172d2 + ad7e074ca3a93f4af30405c4cd24db04151d7ce8 - + https://github.com/dotnet/msbuild - 98935500d8efcb66c1f32927cb2976ea067172d2 + ad7e074ca3a93f4af30405c4cd24db04151d7ce8 - + https://github.com/dotnet/msbuild - 98935500d8efcb66c1f32927cb2976ea067172d2 + ad7e074ca3a93f4af30405c4cd24db04151d7ce8 https://github.com/dotnet/roslyn From 4eefd058a51a889e1c51d9952ffbe7d31a12ec16 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 21 Jul 2026 10:18:12 +0200 Subject: [PATCH 07/33] [main] Update dependencies from dotnet/msbuild (#20055) * Update dependencies from https://github.com/dotnet/msbuild build 20260710.4 On relative base path root Microsoft.Build , Microsoft.Build.Framework , Microsoft.Build.Tasks.Core , Microsoft.Build.Utilities.Core From Version 18.10.0-1.26359.10 -> To Version 18.10.0-1.26360.4 * Update dependencies from https://github.com/dotnet/msbuild build 20260713.4 On relative base path root Microsoft.Build , Microsoft.Build.Framework , Microsoft.Build.Tasks.Core , Microsoft.Build.Utilities.Core From Version 18.10.0-1.26359.10 -> To Version 18.10.0-1.26363.4 * Update dependencies from https://github.com/dotnet/msbuild build 20260714.11 On relative base path root Microsoft.Build , Microsoft.Build.Framework , Microsoft.Build.Tasks.Core , Microsoft.Build.Utilities.Core From Version 18.10.0-1.26359.10 -> To Version 18.10.0-1.26364.11 * Update dependencies from https://github.com/dotnet/msbuild build 20260715.6 On relative base path root Microsoft.Build , Microsoft.Build.Framework , Microsoft.Build.Tasks.Core , Microsoft.Build.Utilities.Core From Version 18.10.0-1.26359.10 -> To Version 18.10.0-1.26365.6 * Update dependencies from https://github.com/dotnet/msbuild build 20260716.8 On relative base path root Microsoft.Build , Microsoft.Build.Framework , Microsoft.Build.Tasks.Core , Microsoft.Build.Utilities.Core From Version 18.10.0-1.26359.10 -> To Version 18.10.0-1.26366.8 * Update dependencies from https://github.com/dotnet/msbuild build 20260717.5 On relative base path root Microsoft.Build , Microsoft.Build.Framework , Microsoft.Build.Tasks.Core , Microsoft.Build.Utilities.Core From Version 18.10.0-1.26359.10 -> To Version 18.10.0-1.26367.5 * Update dependencies from https://github.com/dotnet/msbuild build 20260719.1 On relative base path root Microsoft.Build , Microsoft.Build.Framework , Microsoft.Build.Tasks.Core , Microsoft.Build.Utilities.Core From Version 18.10.0-1.26359.10 -> To Version 18.10.0-1.26369.1 * Update dependencies from https://github.com/dotnet/msbuild build 20260720.18 On relative base path root Microsoft.Build , Microsoft.Build.Framework , Microsoft.Build.Tasks.Core , Microsoft.Build.Utilities.Core From Version 18.10.0-1.26359.10 -> To Version 18.10.0-1.26370.18 --------- Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.props | 8 ++++---- eng/Version.Details.xml | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/eng/Version.Details.props b/eng/Version.Details.props index fb64aafcc65..fd2e2f089be 100644 --- a/eng/Version.Details.props +++ b/eng/Version.Details.props @@ -8,10 +8,10 @@ This file should be imported by eng/Versions.props 10.0.0-beta.26324.4 - 18.10.0-1.26359.10 - 18.10.0-1.26359.10 - 18.10.0-1.26359.10 - 18.10.0-1.26359.10 + 18.10.0-1.26370.18 + 18.10.0-1.26370.18 + 18.10.0-1.26370.18 + 18.10.0-1.26370.18 1.0.0-prerelease.26318.1 1.0.0-prerelease.26318.1 diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index e446d5e3f40..1555816a57a 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -2,21 +2,21 @@ - + https://github.com/dotnet/msbuild - ad7e074ca3a93f4af30405c4cd24db04151d7ce8 + eae54023463db15e9a9081f35a959c9162797643 - + https://github.com/dotnet/msbuild - ad7e074ca3a93f4af30405c4cd24db04151d7ce8 + eae54023463db15e9a9081f35a959c9162797643 - + https://github.com/dotnet/msbuild - ad7e074ca3a93f4af30405c4cd24db04151d7ce8 + eae54023463db15e9a9081f35a959c9162797643 - + https://github.com/dotnet/msbuild - ad7e074ca3a93f4af30405c4cd24db04151d7ce8 + eae54023463db15e9a9081f35a959c9162797643 https://github.com/dotnet/roslyn From 2cd254e2af7419a03dd278cc314afe029cf2c810 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 21 Jul 2026 10:18:23 +0200 Subject: [PATCH 08/33] [main] Update dependencies from dotnet/roslyn (#20052) * Update dependencies from https://github.com/dotnet/roslyn build 20260709.4 On relative base path root Microsoft.CodeAnalysis , Microsoft.CodeAnalysis.Compilers , Microsoft.CodeAnalysis.CSharp , Microsoft.CodeAnalysis.EditorFeatures , Microsoft.CodeAnalysis.EditorFeatures.Text , Microsoft.CodeAnalysis.ExternalAccess.FSharp , Microsoft.CodeAnalysis.Features , Microsoft.VisualStudio.LanguageServices From Version 5.10.0-1.26358.9 -> To Version 5.10.0-1.26359.4 * Fix NU1605 package downgrades from Roslyn 5.10.0-1.26359.4 bump The new Roslyn build adds a net472 dependency on Microsoft.VisualStudio.SDK 18.9.496-Preview and bumps its runtime deps to 10.0.8, causing package downgrade errors: - System.Collections.Immutable / System.Reflection.Metadata / System.Composition now required >= 10.0.8 (were pinned to 10.0.2) - VS interops (OLE/Shell/TextManager.Interop) required >= 18.9.438 - Microsoft.VisualStudio.Threading required >= 18.7.19 The three interop packages are decoupled from the shared shell package version since the VS SDK pins them newer than the other shell packages. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix MSB3277 assembly conflicts from new Roslyn VS SDK 18.9 deps The new Roslyn Microsoft.CodeAnalysis.ExternalAccess.FSharp (net472) now depends on Microsoft.VisualStudio.SDK 18.9.496 and its coherent 18.9.x VS package set, pulling newer transitive assemblies than fsharp's 18.0.x Shell packages. This caused MSB3277 (assembly version conflicts) across the vsintegration projects for: - System.Diagnostics.DiagnosticSource (10.0.2 vs 10.0.8) - Microsoft.VisualStudio.Validation (17.13 vs 18.7.1) - StreamJsonRpc (2.23 vs 2.26.5) - Microsoft.ServiceHub.Framework (4.9 vs 4.10.128) - Microsoft.VisualStudio.RpcContracts (17.15.25 vs 18.9.453) Bump DiagnosticSource to 10.0.8 (coherent with the other runtime deps) and pin the four remaining transitive packages to the exact versions Roslyn pulls, so all vsintegration projects resolve them coherently. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix runtime VS assembly load failures in legacy VS unit tests The Roslyn 5.10.0-1.26359.4 bump pulls Microsoft.VisualStudio.SDK 18.9.496 which transitively upgrades the editor assemblies (Microsoft.VisualStudio.Text.*, .Editor) to 18.9.123 and Shell.15.0 to 18.9.x. Two runtime-only breaks remained after the earlier NU1605/MSB3277 build-time fixes, both surfacing as a ReflectionTypeLoadException in the VsMocks MEF catalog that failed all ~1959 legacy VS unit tests: 1. Microsoft.VisualStudio.Platform.VSEditor is not pulled transitively, so it stayed pinned at 18.0.404-preview and its implementation types no longer bind against the newer Text.Internal 18.9.123 interfaces. Pin VSEditor to 18.9.123 to match. 2. Shell.15.0 18.9.x references Microsoft.VisualStudio.SolutionPersistence at runtime without declaring it as a NuGet dependency; deploy it next to the VS unit-test host (scoped to test projects to keep it out of the VSIX). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix flaky AOT CI build: pass -ci to disable UpdateXlfOnBuild The Build_And_Test_AOT_Windows job runs '.\Build.cmd -pack' without -ci, so ContinuousIntegrationBuild is not set. Arcade then enables UpdateXlfOnBuild, which flakily fails with 'MSB4057: The target UpdateXlf does not exist' on FSharp.Core (the classic_metadata leg failed while the identical compressed_metadata leg passed). Every other CI job builds via CIBuildNoPublish.cmd/cibuild.sh, which pass -ci. Add -ci here for consistency so ContinuousIntegrationBuild=true and UpdateXlfOnBuild stays disabled. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Update dependencies from https://github.com/dotnet/roslyn build 20260709.5 On relative base path root Microsoft.CodeAnalysis , Microsoft.CodeAnalysis.Compilers , Microsoft.CodeAnalysis.CSharp , Microsoft.CodeAnalysis.EditorFeatures , Microsoft.CodeAnalysis.EditorFeatures.Text , Microsoft.CodeAnalysis.ExternalAccess.FSharp , Microsoft.CodeAnalysis.Features , Microsoft.VisualStudio.LanguageServices From Version 5.10.0-1.26358.9 -> To Version 5.10.0-1.26359.5 * Update dependencies from https://github.com/dotnet/roslyn build 20260713.9 On relative base path root Microsoft.CodeAnalysis , Microsoft.CodeAnalysis.Compilers , Microsoft.CodeAnalysis.CSharp , Microsoft.CodeAnalysis.EditorFeatures , Microsoft.CodeAnalysis.EditorFeatures.Text , Microsoft.CodeAnalysis.ExternalAccess.FSharp , Microsoft.CodeAnalysis.Features , Microsoft.VisualStudio.LanguageServices From Version 5.10.0-1.26358.9 -> To Version 5.10.0-1.26363.9 * Update dependencies from https://github.com/dotnet/roslyn build 20260714.9 On relative base path root Microsoft.CodeAnalysis , Microsoft.CodeAnalysis.Compilers , Microsoft.CodeAnalysis.CSharp , Microsoft.CodeAnalysis.EditorFeatures , Microsoft.CodeAnalysis.EditorFeatures.Text , Microsoft.CodeAnalysis.ExternalAccess.FSharp , Microsoft.CodeAnalysis.Features , Microsoft.VisualStudio.LanguageServices From Version 5.10.0-1.26358.9 -> To Version 5.10.0-1.26364.9 * Update dependencies from https://github.com/dotnet/roslyn build 20260715.2 On relative base path root Microsoft.CodeAnalysis , Microsoft.CodeAnalysis.Compilers , Microsoft.CodeAnalysis.CSharp , Microsoft.CodeAnalysis.EditorFeatures , Microsoft.CodeAnalysis.EditorFeatures.Text , Microsoft.CodeAnalysis.ExternalAccess.FSharp , Microsoft.CodeAnalysis.Features , Microsoft.VisualStudio.LanguageServices From Version 5.10.0-1.26358.9 -> To Version 5.10.0-1.26365.2 * Update dependencies from https://github.com/dotnet/roslyn build 20260715.3 On relative base path root Microsoft.CodeAnalysis , Microsoft.CodeAnalysis.Compilers , Microsoft.CodeAnalysis.CSharp , Microsoft.CodeAnalysis.EditorFeatures , Microsoft.CodeAnalysis.EditorFeatures.Text , Microsoft.CodeAnalysis.ExternalAccess.FSharp , Microsoft.CodeAnalysis.Features , Microsoft.VisualStudio.LanguageServices From Version 5.10.0-1.26358.9 -> To Version 5.10.0-1.26365.3 --------- Co-authored-by: dotnet-maestro[bot] Co-authored-by: Copilot Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- azure-pipelines-PR.yml | 2 +- eng/Version.Details.props | 24 ++++++------- eng/Version.Details.xml | 40 ++++++++++----------- eng/Versions.props | 30 +++++++++++++--- vsintegration/Directory.Build.targets | 5 +++ vsintegration/tests/Directory.Build.targets | 7 ++++ 6 files changed, 70 insertions(+), 38 deletions(-) diff --git a/azure-pipelines-PR.yml b/azure-pipelines-PR.yml index 827b97f33ac..8647164d91a 100644 --- a/azure-pipelines-PR.yml +++ b/azure-pipelines-PR.yml @@ -774,7 +774,7 @@ stages: workingDirectory: $(Build.SourcesDirectory) installationPath: $(Build.SourcesDirectory)/.dotnet - script: .\eng\common\dotnet.cmd - - script: .\Build.cmd $(_kind) -pack -c $(_BuildConfig) + - script: .\Build.cmd $(_kind) -ci -pack -c $(_BuildConfig) env: NativeToolsOnMachine: true displayName: Initial build and prepare packages. diff --git a/eng/Version.Details.props b/eng/Version.Details.props index fd2e2f089be..8af19d96d15 100644 --- a/eng/Version.Details.props +++ b/eng/Version.Details.props @@ -19,19 +19,19 @@ This file should be imported by eng/Versions.props 1.0.0-prerelease.26318.1 1.0.0-prerelease.26318.1 - 5.10.0-1.26358.9 - 5.10.0-1.26358.9 - 5.10.0-1.26358.9 - 5.10.0-1.26358.9 - 5.10.0-1.26358.9 - 5.10.0-1.26358.9 - 5.10.0-1.26358.9 - 5.10.0-1.26358.9 + 5.10.0-1.26365.3 + 5.10.0-1.26365.3 + 5.10.0-1.26365.3 + 5.10.0-1.26365.3 + 5.10.0-1.26365.3 + 5.10.0-1.26365.3 + 5.10.0-1.26365.3 + 5.10.0-1.26365.3 - 10.0.2 - 10.0.2 - 10.0.2 - 10.0.2 + 10.0.8 + 10.0.8 + 10.0.8 + 10.0.8 10.0.8 diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 1555816a57a..61d4682124e 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -18,58 +18,58 @@ https://github.com/dotnet/msbuild eae54023463db15e9a9081f35a959c9162797643 - + https://github.com/dotnet/roslyn - 35967bab3447f7edd6162baee7048f801f18fffe + 3d32d464e2949f054086fbb5346e4beea0c6df56 - + https://github.com/dotnet/roslyn - 35967bab3447f7edd6162baee7048f801f18fffe + 3d32d464e2949f054086fbb5346e4beea0c6df56 - + https://github.com/dotnet/roslyn - 35967bab3447f7edd6162baee7048f801f18fffe + 3d32d464e2949f054086fbb5346e4beea0c6df56 - + https://github.com/dotnet/roslyn - 35967bab3447f7edd6162baee7048f801f18fffe + 3d32d464e2949f054086fbb5346e4beea0c6df56 - + https://github.com/dotnet/roslyn - 35967bab3447f7edd6162baee7048f801f18fffe + 3d32d464e2949f054086fbb5346e4beea0c6df56 - + https://github.com/dotnet/roslyn - 35967bab3447f7edd6162baee7048f801f18fffe + 3d32d464e2949f054086fbb5346e4beea0c6df56 - + https://github.com/dotnet/roslyn - 35967bab3447f7edd6162baee7048f801f18fffe + 3d32d464e2949f054086fbb5346e4beea0c6df56 - + https://github.com/dotnet/roslyn - 35967bab3447f7edd6162baee7048f801f18fffe + 3d32d464e2949f054086fbb5346e4beea0c6df56 - + https://github.com/dotnet/runtime - + https://github.com/dotnet/runtime - + https://github.com/dotnet/runtime - + https://github.com/dotnet/runtime diff --git a/eng/Versions.props b/eng/Versions.props index 60486fabcaa..8f756067e4d 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -103,16 +103,17 @@ 18.0.2188-preview.1 18.0.1237-pre 18.0.2077-preview.1 - 18.0.5 + 18.7.19 2.0.28 $(MicrosoftVisualStudioShellPackagesVersion) $(VisualStudioShellProjectsPackages) - $(MicrosoftVisualStudioShellPackagesVersion) - $(MicrosoftVisualStudioShellPackagesVersion) - $(MicrosoftVisualStudioShellPackagesVersion) + + 18.9.438 + 18.9.438 + 18.9.438 $(MicrosoftVisualStudioShellPackagesVersion) $(MicrosoftVisualStudioShellPackagesVersion) $(MicrosoftVisualStudioShellPackagesVersion) @@ -127,7 +128,12 @@ $(VisualStudioEditorPackagesVersion) $(VisualStudioEditorPackagesVersion) $(VisualStudioEditorPackagesVersion) - $(VisualStudioEditorPackagesVersion) + + 18.9.123 $(VisualStudioEditorPackagesVersion) 17.14.0 0.1.800-beta @@ -136,6 +142,20 @@ $(MicrosoftVisualStudioThreadingPackagesVersion) + + 18.7.1 + 18.9.453 + 4.10.128 + 2.26.5 + + + 1.0.52 + $(VisualStudioProjectSystemPackagesVersion) 2.3.6152103 diff --git a/vsintegration/Directory.Build.targets b/vsintegration/Directory.Build.targets index 6d09285feca..16099d6637c 100644 --- a/vsintegration/Directory.Build.targets +++ b/vsintegration/Directory.Build.targets @@ -14,6 +14,11 @@ + + + + + diff --git a/vsintegration/tests/Directory.Build.targets b/vsintegration/tests/Directory.Build.targets index 14437118703..2bbbb8d4d4c 100644 --- a/vsintegration/tests/Directory.Build.targets +++ b/vsintegration/tests/Directory.Build.targets @@ -1,3 +1,10 @@ + + + + + From 9fc230a93756076a174e164d8094d3953d95a8c3 Mon Sep 17 00:00:00 2001 From: dotnet bot Date: Tue, 21 Jul 2026 01:18:51 -0700 Subject: [PATCH 09/33] Localized file check-in by OneLocBuild Task: Build definition ID 499: Build ID 3013177 (#20023) Co-authored-by: Copilot --- src/Compiler/xlf/FSStrings.cs.xlf | 2 +- src/Compiler/xlf/FSStrings.de.xlf | 2 +- src/Compiler/xlf/FSStrings.es.xlf | 2 +- src/Compiler/xlf/FSStrings.fr.xlf | 2 +- src/Compiler/xlf/FSStrings.it.xlf | 2 +- src/Compiler/xlf/FSStrings.ja.xlf | 2 +- src/Compiler/xlf/FSStrings.ko.xlf | 2 +- src/Compiler/xlf/FSStrings.pl.xlf | 2 +- src/Compiler/xlf/FSStrings.pt-BR.xlf | 2 +- src/Compiler/xlf/FSStrings.ru.xlf | 2 +- src/Compiler/xlf/FSStrings.tr.xlf | 2 +- src/Compiler/xlf/FSStrings.zh-Hans.xlf | 2 +- src/Compiler/xlf/FSStrings.zh-Hant.xlf | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/Compiler/xlf/FSStrings.cs.xlf b/src/Compiler/xlf/FSStrings.cs.xlf index 86f2f70699a..2a344c5d674 100644 --- a/src/Compiler/xlf/FSStrings.cs.xlf +++ b/src/Compiler/xlf/FSStrings.cs.xlf @@ -1,4 +1,4 @@ - + diff --git a/src/Compiler/xlf/FSStrings.de.xlf b/src/Compiler/xlf/FSStrings.de.xlf index 12e8860ae56..eb13919bfaf 100644 --- a/src/Compiler/xlf/FSStrings.de.xlf +++ b/src/Compiler/xlf/FSStrings.de.xlf @@ -1,4 +1,4 @@ - + diff --git a/src/Compiler/xlf/FSStrings.es.xlf b/src/Compiler/xlf/FSStrings.es.xlf index 317e1230228..1fc832b7e27 100644 --- a/src/Compiler/xlf/FSStrings.es.xlf +++ b/src/Compiler/xlf/FSStrings.es.xlf @@ -1,4 +1,4 @@ - + diff --git a/src/Compiler/xlf/FSStrings.fr.xlf b/src/Compiler/xlf/FSStrings.fr.xlf index c35bfe5ed08..b539a265b93 100644 --- a/src/Compiler/xlf/FSStrings.fr.xlf +++ b/src/Compiler/xlf/FSStrings.fr.xlf @@ -1,4 +1,4 @@ - + diff --git a/src/Compiler/xlf/FSStrings.it.xlf b/src/Compiler/xlf/FSStrings.it.xlf index fcbe444c44e..acd4ffcfe20 100644 --- a/src/Compiler/xlf/FSStrings.it.xlf +++ b/src/Compiler/xlf/FSStrings.it.xlf @@ -1,4 +1,4 @@ - + diff --git a/src/Compiler/xlf/FSStrings.ja.xlf b/src/Compiler/xlf/FSStrings.ja.xlf index 75b5d835d55..2d199d7f94e 100644 --- a/src/Compiler/xlf/FSStrings.ja.xlf +++ b/src/Compiler/xlf/FSStrings.ja.xlf @@ -1,4 +1,4 @@ - + diff --git a/src/Compiler/xlf/FSStrings.ko.xlf b/src/Compiler/xlf/FSStrings.ko.xlf index b495c3a27c8..2611ca958be 100644 --- a/src/Compiler/xlf/FSStrings.ko.xlf +++ b/src/Compiler/xlf/FSStrings.ko.xlf @@ -1,4 +1,4 @@ - + diff --git a/src/Compiler/xlf/FSStrings.pl.xlf b/src/Compiler/xlf/FSStrings.pl.xlf index 7d5af0e89d1..27c6d4455ce 100644 --- a/src/Compiler/xlf/FSStrings.pl.xlf +++ b/src/Compiler/xlf/FSStrings.pl.xlf @@ -1,4 +1,4 @@ - + diff --git a/src/Compiler/xlf/FSStrings.pt-BR.xlf b/src/Compiler/xlf/FSStrings.pt-BR.xlf index 47f6b1d5cda..df00934621b 100644 --- a/src/Compiler/xlf/FSStrings.pt-BR.xlf +++ b/src/Compiler/xlf/FSStrings.pt-BR.xlf @@ -1,4 +1,4 @@ - + diff --git a/src/Compiler/xlf/FSStrings.ru.xlf b/src/Compiler/xlf/FSStrings.ru.xlf index d420b749357..a0958ee1efc 100644 --- a/src/Compiler/xlf/FSStrings.ru.xlf +++ b/src/Compiler/xlf/FSStrings.ru.xlf @@ -1,4 +1,4 @@ - + diff --git a/src/Compiler/xlf/FSStrings.tr.xlf b/src/Compiler/xlf/FSStrings.tr.xlf index 43123521b37..509eb6d5ac6 100644 --- a/src/Compiler/xlf/FSStrings.tr.xlf +++ b/src/Compiler/xlf/FSStrings.tr.xlf @@ -1,4 +1,4 @@ - + diff --git a/src/Compiler/xlf/FSStrings.zh-Hans.xlf b/src/Compiler/xlf/FSStrings.zh-Hans.xlf index 637d8d2b7a9..7a3c8482ebc 100644 --- a/src/Compiler/xlf/FSStrings.zh-Hans.xlf +++ b/src/Compiler/xlf/FSStrings.zh-Hans.xlf @@ -1,4 +1,4 @@ - + diff --git a/src/Compiler/xlf/FSStrings.zh-Hant.xlf b/src/Compiler/xlf/FSStrings.zh-Hant.xlf index f4452359da8..e671202ffb2 100644 --- a/src/Compiler/xlf/FSStrings.zh-Hant.xlf +++ b/src/Compiler/xlf/FSStrings.zh-Hant.xlf @@ -1,4 +1,4 @@ - + From e729d97d8bbe1712be6a7b1223d40b421ba0fa56 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed, 22 Jul 2026 18:05:13 +0200 Subject: [PATCH 10/33] [main] Update dependencies from dotnet/arcade (#20054) * Update dependencies from https://github.com/dotnet/arcade build 20260708.3 On relative base path root Microsoft.DotNet.Arcade.Sdk From Version 10.0.0-beta.26324.4 -> To Version 10.0.0-beta.26358.3 * Update dependencies from https://github.com/dotnet/arcade build 20260716.3 On relative base path root Microsoft.DotNet.Arcade.Sdk From Version 10.0.0-beta.26324.4 -> To Version 10.0.0-beta.26366.3 * Update dependencies from https://github.com/dotnet/arcade build 20260717.6 On relative base path root Microsoft.DotNet.Arcade.Sdk From Version 10.0.0-beta.26324.4 -> To Version 10.0.0-beta.26367.6 * Re-run CI (flaky infrastructure failures unrelated to Arcade bump) The two failing jobs on this darc dependency PR were flaky/infra failures, not caused by the Arcade SDK version bump: - WindowsCompressedMetadata transparent_compiler_release: FSharp.Compiler.Service.Tests host hang hitting the 5m hangdump timeout (createdump MiniDumpWriteDump failure). - IcedTasks_Test_Debug Regression Test: net9.0-only 'Entry point was not found' in the third-party FSharp.Control.TaskSeq DisposeAsync path (passed on net8.0/net10.0). Both signatures recur on unrelated PRs (e.g. IcedTasks on #19941). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Update dependencies from https://github.com/dotnet/arcade build 20260721.2 On relative base path root Microsoft.DotNet.Arcade.Sdk From Version 10.0.0-beta.26324.4 -> To Version 10.0.0-beta.26371.2 --------- Co-authored-by: dotnet-maestro[bot] Co-authored-by: T-Gro <15220165+T-Gro@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- eng/Version.Details.props | 2 +- eng/Version.Details.xml | 4 ++-- eng/common/core-templates/job/onelocbuild.yml | 20 ++++++++++++++++++- .../job/publish-build-assets.yml | 3 --- .../core-templates/post-build/post-build.yml | 2 -- eng/common/dotnet.ps1 | 1 + eng/common/tools.ps1 | 2 +- eng/common/tools.sh | 2 +- global.json | 2 +- 9 files changed, 26 insertions(+), 12 deletions(-) diff --git a/eng/Version.Details.props b/eng/Version.Details.props index 8af19d96d15..43bc8e6d8e0 100644 --- a/eng/Version.Details.props +++ b/eng/Version.Details.props @@ -6,7 +6,7 @@ This file should be imported by eng/Versions.props - 10.0.0-beta.26324.4 + 10.0.0-beta.26371.2 18.10.0-1.26370.18 18.10.0-1.26370.18 diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 61d4682124e..b00667f5028 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -82,9 +82,9 @@ - + https://github.com/dotnet/arcade - 1373629deb1e04f3e8e66fb68bb48ae36479c5ef + c38c50f518aac7fac47ca488c42c7176d40e695c https://dev.azure.com/dnceng/internal/_git/dotnet-optimization diff --git a/eng/common/core-templates/job/onelocbuild.yml b/eng/common/core-templates/job/onelocbuild.yml index eefed3b667a..12d7e55a94b 100644 --- a/eng/common/core-templates/job/onelocbuild.yml +++ b/eng/common/core-templates/job/onelocbuild.yml @@ -8,6 +8,12 @@ parameters: CeapexPat: $(dn-bot-ceapex-package-r) # PAT for the loc AzDO instance https://dev.azure.com/ceapex GithubPat: $(BotAccount-dotnet-bot-repo-PAT) + # Service connection for WIF-based Entra authentication to ceapex feeds (replaces CeapexPat). + # When set, dnceng/internal builds acquire a federated Entra token instead of using a PAT. + # All other projects (e.g. DevDiv, public), where this dnceng-scoped service connection does not + # exist, and any pipeline that sets this to '' fall back to PAT-based auth via the CeapexPat parameter. + CeapexServiceConnection: 'dnceng-onelocbuild-ceapex' + SourcesDirectory: $(System.DefaultWorkingDirectory) CreatePr: true AutoCompletePr: false @@ -73,6 +79,15 @@ jobs: displayName: Generate LocProject.json condition: ${{ parameters.condition }} + # Acquire an Entra token for ceapex feed access via WIF (dnceng/internal only). + # All other projects use PAT-based auth, since the ceapex service connection is scoped to dnceng/internal. + - ${{ if and(ne(parameters.CeapexServiceConnection, ''), eq(variables['System.TeamProject'], 'internal')) }}: + - template: /eng/common/templates/steps/get-federated-access-token.yml + parameters: + federatedServiceConnection: ${{ parameters.CeapexServiceConnection }} + outputVariableName: 'CeapexEntraToken' + condition: ${{ parameters.condition }} + - task: OneLocBuild@2 displayName: OneLocBuild env: @@ -88,7 +103,10 @@ jobs: isUseLfLineEndingsSelected: ${{ parameters.UseLfLineEndings }} isShouldReusePrSelected: ${{ parameters.ReusePr }} packageSourceAuth: patAuth - patVariable: ${{ parameters.CeapexPat }} + ${{ if and(ne(parameters.CeapexServiceConnection, ''), eq(variables['System.TeamProject'], 'internal')) }}: + patVariable: $(CeapexEntraToken) + ${{ if or(eq(parameters.CeapexServiceConnection, ''), ne(variables['System.TeamProject'], 'internal')) }}: + patVariable: ${{ parameters.CeapexPat }} ${{ if eq(parameters.RepoType, 'gitHub') }}: repoType: ${{ parameters.RepoType }} gitHubPatVariable: "${{ parameters.GithubPat }}" diff --git a/eng/common/core-templates/job/publish-build-assets.yml b/eng/common/core-templates/job/publish-build-assets.yml index 06f2eed0323..53af522d6d4 100644 --- a/eng/common/core-templates/job/publish-build-assets.yml +++ b/eng/common/core-templates/job/publish-build-assets.yml @@ -122,9 +122,6 @@ jobs: # Populate internal runtime variables. - template: /eng/common/templates/steps/enable-internal-sources.yml - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - parameters: - legacyCredential: $(dn-bot-dnceng-artifact-feeds-rw) - template: /eng/common/templates/steps/enable-internal-runtimes.yml diff --git a/eng/common/core-templates/post-build/post-build.yml b/eng/common/core-templates/post-build/post-build.yml index 905a6315e2d..135fc9a5051 100644 --- a/eng/common/core-templates/post-build/post-build.yml +++ b/eng/common/core-templates/post-build/post-build.yml @@ -352,8 +352,6 @@ stages: # Populate internal runtime variables. - template: /eng/common/templates/steps/enable-internal-sources.yml - parameters: - legacyCredential: $(dn-bot-dnceng-artifact-feeds-rw) - template: /eng/common/templates/steps/enable-internal-runtimes.yml diff --git a/eng/common/dotnet.ps1 b/eng/common/dotnet.ps1 index 45e5676c9eb..ce4ea40730a 100755 --- a/eng/common/dotnet.ps1 +++ b/eng/common/dotnet.ps1 @@ -8,4 +8,5 @@ $dotnetRoot = InitializeDotNetCli -install:$true if ($args.count -gt 0) { $env:DOTNET_NOLOGO=1 & "$dotnetRoot\dotnet.exe" $args + ExitWithExitCode $LASTEXITCODE } diff --git a/eng/common/tools.ps1 b/eng/common/tools.ps1 index 977a2d4b103..c6a1d6eaec4 100644 --- a/eng/common/tools.ps1 +++ b/eng/common/tools.ps1 @@ -732,7 +732,7 @@ function InitializeToolset() { '' | Set-Content $proj - MSBuild-Core $proj $bl /t:__WriteToolsetLocation /clp:ErrorsOnly`;NoSummary /p:__ToolsetLocationOutputFile=$toolsetLocationFile + MSBuild-Core $proj $bl /t:__WriteToolsetLocation /clp:ErrorsOnly`;NoSummary /p:__ToolsetLocationOutputFile=$toolsetLocationFile /p:RestoreIgnoreFailedSources=true $path = Get-Content $toolsetLocationFile -Encoding UTF8 -TotalCount 1 if (!(Test-Path $path)) { diff --git a/eng/common/tools.sh b/eng/common/tools.sh index 1b296f646c2..62aeb73fe51 100755 --- a/eng/common/tools.sh +++ b/eng/common/tools.sh @@ -430,7 +430,7 @@ function InitializeToolset { fi echo '' > "$proj" - MSBuild-Core "$proj" $bl /t:__WriteToolsetLocation /clp:ErrorsOnly\;NoSummary /p:__ToolsetLocationOutputFile="$toolset_location_file" + MSBuild-Core "$proj" $bl /t:__WriteToolsetLocation /clp:ErrorsOnly\;NoSummary /p:__ToolsetLocationOutputFile="$toolset_location_file" /p:RestoreIgnoreFailedSources=true local toolset_build_proj=`cat "$toolset_location_file"` diff --git a/global.json b/global.json index 7d1a9d739bc..88decf7c2a9 100644 --- a/global.json +++ b/global.json @@ -22,7 +22,7 @@ "xcopy-msbuild": "18.0.0" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.26324.4", + "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.26371.2", "Microsoft.DotNet.Helix.Sdk": "8.0.0-beta.23255.2" } } From 69fca7f6e1412e3272a3a4224608cbae4ad165f4 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Wed, 22 Jul 2026 19:15:58 +0200 Subject: [PATCH 11/33] Tests/source context: support multiple carets (#20077) --- .../FSharp.Compiler.Service.Tests/Checker.fs | 148 +++++++++++++----- .../CheckerExtensionsTests.fs | 12 ++ .../FSharp.Compiler.Service.Tests.fsproj | 1 + 3 files changed, 121 insertions(+), 40 deletions(-) create mode 100644 tests/FSharp.Compiler.Service.Tests/CheckerExtensionsTests.fs diff --git a/tests/FSharp.Compiler.Service.Tests/Checker.fs b/tests/FSharp.Compiler.Service.Tests/Checker.fs index ca583beb25c..95ef268e80a 100644 --- a/tests/FSharp.Compiler.Service.Tests/Checker.fs +++ b/tests/FSharp.Compiler.Service.Tests/Checker.fs @@ -1,11 +1,13 @@ namespace FSharp.Compiler.Service.Tests open System +open System.Text.RegularExpressions open FSharp.Compiler.CodeAnalysis open FSharp.Compiler.EditorServices open FSharp.Compiler.Text open FSharp.Compiler.Text.Range open FSharp.Compiler.Tokenization +open FSharp.Test.Assert type SourceContext = { Source: string @@ -32,83 +34,149 @@ type CodeCompletionContext = [] module SourceContext = - let private markers = ["{caret}"; "{selstart}"; "{selend}"] + type private Marker = + { Text: string + Position: pos } + + type private SourceMarkers = + { Caret: Marker option + SelectionStart: Marker option + SelectionEnd: Marker option + Id: int option } + + let private markers = ["caret"; "selstart"; "selend"] let getLines (source: string) = source.Split([|"\r\n"; "\n"|], StringSplitOptions.None) - let rec private extractMarkersOnLine markersAcc (line, lineText: string) = + let private stripMarkers (markedSource: string) = + let names = String.concat "|" markers + Regex.Replace(markedSource, $@"\{{({names})\d*\}}", "") + + let rec private extractMarkersOnLine (markersAcc: (int option * Marker) list) (line, lineText: string) = let markersOnLine = markers |> List.choose (fun (marker: string) -> - match lineText.IndexOf(marker) with - | -1 -> None - | column -> Some(marker, column) + let regexMatch = Regex.Match(lineText, $@"\{{{marker}(\d*)\}}") + if regexMatch.Success then Some(marker, regexMatch) else None ) if markersOnLine.IsEmpty then markersAcc else - let marker, column = List.minBy snd markersOnLine + let marker, regexMatch = markersOnLine |> List.minBy (fun (_, m) -> m.Index) - let markerPos = - let column = - match marker with - | "{caret}" -> column - 1 - | _ -> column + let column = + match marker with + | "caret" -> regexMatch.Index - 1 + | _ -> regexMatch.Index - Position.mkPos (line + 1) column + let markerPos = Position.mkPos (line + 1) column - if markersAcc |> List.map fst |> List.contains marker then - failwith $"Duplicate marker: {marker}" + let id = + match regexMatch.Groups.[1].Value with + | "" -> None + | value -> Some(int value) - let markersAcc = (marker, markerPos) :: markersAcc - let lineText = lineText.Replace(marker, "") + if markersAcc |> List.exists (fun (markerId, m) -> m.Text = marker && markerId = id) then + failwith $"Duplicate marker: {regexMatch.Value}" + + let markersAcc = (id, { Text = marker; Position = markerPos }) :: markersAcc + let lineText = lineText.Replace(regexMatch.Value, "") extractMarkersOnLine markersAcc (line, lineText) - let fromMarkedSource (markedSource: string) : SourceContext = - let markerPositions = + let private extractSourceMarkers (markedSource: string) : string * SourceMarkers list = + let sourceMarkers = getLines markedSource |> Seq.indexed |> Seq.fold extractMarkersOnLine [] + |> List.groupBy fst + |> List.map (fun (id, group) -> + let markers = group |> List.map snd + let tryFind text = markers |> List.tryFind (fun m -> m.Text = text) - let source = - markerPositions - |> List.map fst - |> List.fold (fun (source: string) marker -> source.Replace(marker, "")) markedSource + { Id = id + Caret = tryFind "caret" + SelectionStart = tryFind "selstart" + SelectionEnd = tryFind "selend" }) - let markerPositions = markerPositions |> dict + stripMarkers markedSource, sourceMarkers - let tryGetPos marker = - match markerPositions.TryGetValue(marker) with - | true, pos -> Some pos - | _ -> None + let private toSourceContext (source: string) (sourceMarkers: SourceMarkers) : SourceContext = + let reportError message = + let prefix = + match sourceMarkers with + | { Id = Some id } -> $"{id}: " + | _ -> "" + + failwith (prefix + message) let caretPos, selectedRange = - match tryGetPos "{caret}", tryGetPos "{selstart}", tryGetPos "{selend}" with - | Some caretPos, None, None -> - caretPos, None + match sourceMarkers.Caret, sourceMarkers.SelectionStart, sourceMarkers.SelectionEnd with + | Some caret, None, None -> + caret.Position, None - | Some caretPos, Some startPos, Some endPos -> - let selectedRange = mkRange "Test.fsx" startPos endPos - caretPos, Some selectedRange + | Some caret, Some selStart, Some selEnd -> + let selectedRange = mkRange "Test.fsx" selStart.Position selEnd.Position + caret.Position, Some selectedRange - | None, Some startPos, Some endPos -> - let selectedRange = mkRange "Test.fsx" startPos endPos - let caretPos = Position.mkPos endPos.Line (endPos.Column - 1) + | None, Some selStart, Some selEnd -> + let selectedRange = mkRange "Test.fsx" selStart.Position selEnd.Position + let caretPos = Position.mkPos selEnd.Position.Line (selEnd.Position.Column - 1) caretPos, Some selectedRange - | _, None, Some _ -> failwith "Missing selected range start" - | _, Some _, None -> failwith "Missing selected range end" - - | None, None, None -> failwith "Missing caret marker" + | _, None, Some _ -> reportError "Missing selected range start" + | _, Some _, None -> reportError "Missing selected range end" + | None, None, None -> reportError "Missing caret marker" let lines = getLines source let lineText = Array.get lines (caretPos.Line - 1) { Source = source; CaretPos = caretPos; LineText = lineText; SelectedRange = selectedRange } + let fromMarkedSource (markedSource: string) : SourceContext = + let source, sourceMarkers = extractSourceMarkers markedSource + let sourceMarkers = sourceMarkers |> List.exactlyOne + sourceMarkers.Id |> shouldBe None + + toSourceContext source sourceMarkers + + let fromOrderedMarkedSource (orderedMarkedSource: string) : SourceContext list = + let source, sourceMarkers = extractSourceMarkers orderedMarkedSource + sourceMarkers |> List.iter (fun markers -> markers.Id.IsSome |> shouldBeTrue) + + sourceMarkers + |> List.sortBy _.Id + |> List.map (toSourceContext source) + + let toMarkedSource (context: SourceContext) : string = + let skipCaretMarker = + match context.SelectedRange with + | Some range -> context.CaretPos.Line = range.End.Line && context.CaretPos.Column = range.End.Column - 1 + | None -> false + + let insertions = + [ if not skipCaretMarker then + context.CaretPos.Line, context.CaretPos.Column + 1, "{caret}" + + match context.SelectedRange with + | Some range -> + range.Start.Line, range.Start.Column, "{selstart}" + range.End.Line, range.End.Column, "{selend}" + | None -> () ] + + let lines = getLines context.Source + + for line, column, marker in insertions |> List.sortByDescending (fun (line, column, _) -> line, column) do + lines[line - 1] <- lines[line - 1].Insert(column, marker) + + String.concat "\n" lines + + let extractOrderedMarkedSources (markedSource: string) : string list = + fromOrderedMarkedSource markedSource + |> List.map toMarkedSource + [] module CheckResultsExtensions = diff --git a/tests/FSharp.Compiler.Service.Tests/CheckerExtensionsTests.fs b/tests/FSharp.Compiler.Service.Tests/CheckerExtensionsTests.fs new file mode 100644 index 00000000000..3c7ac11454a --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/CheckerExtensionsTests.fs @@ -0,0 +1,12 @@ +module FSharp.Compiler.Service.Tests.CheckerExtensionsTests + +open Xunit +open FSharp.Test.Assert + +[] +let ``Extract ordered marked sources`` () = + let markedSources = SourceContext.extractOrderedMarkedSources "let a{caret1}, b{caret2} = 1, 2" + + markedSources + |> shouldBe [ "let a{caret}, b = 1, 2" + "let a, b{caret} = 1, 2" ] diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj index 6193e4f73a4..0a831038313 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj @@ -26,6 +26,7 @@ + From 2f07589d742861372eecce48d06ab70e841f8408 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Thu, 23 Jul 2026 15:37:26 +0200 Subject: [PATCH 12/33] Move VS language-service logic tests to FSharp.Compiler.Service.Tests (#20033) * Move VS language-service logic tests to FSharp.Compiler.Service.Tests Port completion, quick info, parameter info, go-to-definition, and diagnostics coverage from the Windows-only VS Salsa suite to the cross-platform FSharp.Compiler.Service.Tests. The legacy suite keeps only the tests that genuinely exercise Visual Studio integration. --- .../FSharp.Compiler.Service.Tests/Checker.fs | 50 +- tests/FSharp.Compiler.Service.Tests/Common.fs | 30 +- .../CompletionTests.Accessibility.fs | 233 + .../Completion/CompletionTests.Attributes.fs | 229 + .../Completion/CompletionTests.ByrefSpans.fs | 17 + .../Completion/CompletionTests.Classes.fs | 256 + .../CompletionTests.ComputationExpressions.fs | 559 ++ .../CompletionTests.Conditionals.fs | 79 + .../Completion/CompletionTests.Constraints.fs | 89 + .../CompletionTests.DiscriminatedUnions.fs | 185 + .../Completion/CompletionTests.Enums.fs | 174 + .../Completion/CompletionTests.Events.fs | 48 + .../Completion/CompletionTests.Exceptions.fs | 69 + .../Completion/CompletionTests.Functions.fs | 200 + .../Completion/CompletionTests.Generics.fs | 174 + .../CompletionTests.IndexingSlicing.fs | 189 + .../Completion/CompletionTests.Interfaces.fs | 30 + .../Completion/CompletionTests.Lambdas.fs | 88 + .../Completion/CompletionTests.LetBindings.fs | 114 + .../Completion/CompletionTests.Literals.fs | 43 + .../Completion/CompletionTests.Members.fs | 361 + .../Completion/CompletionTests.Modules.fs | 102 + .../Completion/CompletionTests.Mutability.fs | 61 + .../CompletionTests.MutuallyRecursive.fs | 25 + .../Completion/CompletionTests.Namespaces.fs | 99 + .../CompletionTests.ObjectExpressions.fs | 27 + .../CompletionTests.ObjectInitializers.fs | 148 + .../CompletionTests.OpenDirectives.fs | 304 + .../Completion/CompletionTests.Operators.fs | 59 + .../CompletionTests.PatternMatching.fs | 281 + .../CompletionTests.PrintfFormat.fs | 70 + .../Completion/CompletionTests.Properties.fs | 337 + .../Completion/CompletionTests.Queries.fs | 362 + .../Completion/CompletionTests.Quotations.fs | 50 + .../Completion/CompletionTests.Records.fs | 409 + .../Completion/CompletionTests.Recursion.fs | 16 + .../CompletionTests.SeqListArrayExprs.fs | 137 + .../Completion/CompletionTests.Tuples.fs | 74 + .../CompletionTests.TypeAbbreviations.fs | 190 + .../CompletionTests.TypeAnnotations.fs | 194 + .../CompletionTests.TypeExtensions.fs | 58 + .../CompletionTests.TypeProviders.fs | 135 + .../CompletionTests.UnitsOfMeasure.fs | 90 + .../CompletionTests.fs | 20 - .../EditorServiceAsserts.fs | 530 ++ .../EditorTests.fs | 9 - .../ErrorList/ErrorListTests.fs | 483 ++ .../ErrorList/ScriptDiagnosticsTests.fs | 356 + .../FSharp.Compiler.Service.Tests.fsproj | 103 +- .../GotoDefinitionTests.ActivePatterns.fs | 24 + .../GotoDefinitionTests.Classes.fs | 33 + ...GotoDefinitionTests.DiscriminatedUnions.fs | 57 + .../GotoDefinitionTests.IdentifierIsland.fs | 24 + .../GotoDefinitionTests.LetBindings.fs | 82 + .../GotoDefinitionTests.Members.fs | 191 + .../GotoDefinitionTests.Misc.fs | 108 + .../GotoDefinitionTests.Modules.fs | 46 + .../GotoDefinitionTests.Operators.fs | 39 + .../GotoDefinitionTests.PatternMatching.fs | 115 + .../GotoDefinitionTests.Records.fs | 28 + .../GotoDefinitionTests.TypeAnnotations.fs | 131 + .../GotoDefinitionTests.TypeProviders.fs | 59 + .../ParameterInfoTests.Attributes.fs | 33 + .../ParameterInfoTests.ByrefSpans.fs | 27 + .../ParameterInfoTests.Classes.fs | 52 + ...rameterInfoTests.ComputationExpressions.fs | 20 + .../ParameterInfoTests.DiscriminatedUnions.fs | 24 + .../ParameterInfoTests.Events.fs | 15 + .../ParameterInfoTests.Exceptions.fs | 14 + .../ParameterInfoTests.Functions.fs | 32 + .../ParameterInfoTests.Generics.fs | 106 + .../ParameterInfoTests.IndexingSlicing.fs | 33 + .../ParameterInfoTests.Interfaces.fs | 12 + .../ParameterInfoTests.Lambdas.fs | 15 + .../ParameterInfoTests.LetBindings.fs | 11 + .../ParameterInfoTests.Members.fs | 144 + .../ParameterInfoTests.Modules.fs | 23 + .../ParameterInfoTests.Namespaces.fs | 11 + .../ParameterInfoTests.ObjectExpressions.fs | 7 + .../ParameterInfoTests.OpenDirectives.fs | 25 + .../ParameterInfoTests.Operators.fs | 23 + .../ParameterInfoTests.PatternMatching.fs | 53 + .../ParameterInfoTests.Properties.fs | 45 + .../ParameterInfoTests.Queries.fs | 85 + .../ParameterInfoTests.Records.fs | 28 + .../ParameterInfoTests.SeqListArrayExprs.fs | 36 + ...ParameterInfoTests.StringsInterpolation.fs | 17 + .../ParameterInfoTests.Tuples.fs | 145 + .../ParameterInfoTests.TypeAnnotations.fs | 53 + .../ParameterInfoTests.TypeExtensions.fs | 33 + .../ParameterInfoTests.TypeProviders.fs | 154 + .../QuickParseTests.fs | 125 + .../ScriptOptionsTests.fs | 50 + .../TokenizerTests.fs | 171 + .../Tooltip/TooltipTests.ActivePatterns.fs | 64 + .../Tooltip/TooltipTests.Attributes.fs | 74 + .../Tooltip/TooltipTests.Classes.fs | 234 + .../TooltipTests.ComputationExpressions.fs | 228 + .../Tooltip/TooltipTests.Declarations.fs | 166 + .../TooltipTests.DiscriminatedUnions.fs | 171 + .../Tooltip/TooltipTests.Expressions.fs | 237 + .../Tooltip/TooltipTests.Generics.fs | 73 + .../Tooltip/TooltipTests.Members.fs | 137 + .../Tooltip/TooltipTests.Modules.fs | 96 + .../Tooltip/TooltipTests.Properties.fs | 54 + .../Tooltip/TooltipTests.Queries.fs | 245 + .../Tooltip/TooltipTests.Records.fs | 94 + .../Tooltip/TooltipTests.TypeProviders.fs | 203 + .../Tooltip/TooltipTests.Types.fs | 464 ++ .../TooltipTests.fs | 15 - .../TypeChecker/Obsolete.fs | 1 - .../TypeChecker/TypeCheckerRecoveryTests.fs | 353 +- .../Tests.LanguageService.Completion.fs | 7027 +---------------- .../Tests.LanguageService.ErrorList.fs | 751 -- .../Tests.LanguageService.ErrorRecovery.fs | 214 +- .../Tests.LanguageService.General.fs | 228 - .../Tests.LanguageService.GotoDefinition.fs | 942 +-- .../Tests.LanguageService.ParameterInfo.fs | 1677 ---- .../Tests.LanguageService.QuickInfo.fs | 2745 +------ .../Tests.LanguageService.QuickParse.fs | 171 +- .../Tests.LanguageService.Script.fs | 1123 --- 121 files changed, 13443 insertions(+), 14849 deletions(-) create mode 100644 tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Accessibility.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Attributes.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.ByrefSpans.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Classes.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.ComputationExpressions.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Conditionals.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Constraints.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.DiscriminatedUnions.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Enums.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Events.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Exceptions.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Functions.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Generics.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.IndexingSlicing.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Interfaces.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Lambdas.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.LetBindings.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Literals.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Members.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Modules.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Mutability.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.MutuallyRecursive.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Namespaces.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.ObjectExpressions.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.ObjectInitializers.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.OpenDirectives.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Operators.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.PatternMatching.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.PrintfFormat.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Properties.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Queries.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Quotations.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Records.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Recursion.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.SeqListArrayExprs.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Tuples.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.TypeAbbreviations.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.TypeAnnotations.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.TypeExtensions.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.TypeProviders.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.UnitsOfMeasure.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/EditorServiceAsserts.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/ErrorList/ErrorListTests.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/ErrorList/ScriptDiagnosticsTests.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.ActivePatterns.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.Classes.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.DiscriminatedUnions.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.IdentifierIsland.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.LetBindings.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.Members.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.Misc.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.Modules.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.Operators.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.PatternMatching.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.Records.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.TypeAnnotations.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.TypeProviders.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Attributes.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.ByrefSpans.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Classes.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.ComputationExpressions.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.DiscriminatedUnions.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Events.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Exceptions.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Functions.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Generics.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.IndexingSlicing.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Interfaces.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Lambdas.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.LetBindings.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Members.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Modules.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Namespaces.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.ObjectExpressions.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.OpenDirectives.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Operators.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.PatternMatching.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Properties.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Queries.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Records.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.SeqListArrayExprs.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.StringsInterpolation.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Tuples.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.TypeAnnotations.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.TypeExtensions.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.TypeProviders.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.ActivePatterns.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Attributes.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Classes.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.ComputationExpressions.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Declarations.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.DiscriminatedUnions.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Expressions.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Generics.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Members.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Modules.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Properties.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Queries.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Records.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.TypeProviders.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Types.fs diff --git a/tests/FSharp.Compiler.Service.Tests/Checker.fs b/tests/FSharp.Compiler.Service.Tests/Checker.fs index 95ef268e80a..dc86d85c1ad 100644 --- a/tests/FSharp.Compiler.Service.Tests/Checker.fs +++ b/tests/FSharp.Compiler.Service.Tests/Checker.fs @@ -3,11 +3,14 @@ namespace FSharp.Compiler.Service.Tests open System open System.Text.RegularExpressions open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.Diagnostics open FSharp.Compiler.EditorServices open FSharp.Compiler.Text open FSharp.Compiler.Text.Range open FSharp.Compiler.Tokenization open FSharp.Test.Assert +open FSharp.Test.Compiler.Assertions.TextBasedDiagnosticAsserts +open Xunit type SourceContext = { Source: string @@ -193,6 +196,9 @@ module CheckResultsExtensions = member this.GetTooltip(context: ResolveContext, width) = this.GetToolTip(context.Pos.Line, context.Pos.Column, context.LineText, context.Names, FSharpTokenTag.Identifier, width) + member this.GetDeclarationLocation(context: ResolveContext) = + this.GetDeclarationLocation(context.Pos.Line, context.Pos.Column, context.LineText, context.Names) + member this.GetCodeCompletionSuggestions(context: CodeCompletionContext, parseResults: FSharpParseFileResults, options: FSharpCodeCompletionOptions) = this.GetDeclarationListInfo(Some parseResults, context.Pos.Line, context.LineText, context.PartialIdentifier, options = options) @@ -241,6 +247,11 @@ module Checker = let getCompletionInfo markedSource = getCompletionInfoWithOptions FSharpCodeCompletionOptions.Default markedSource + let getCompletionInfoOfSignatureFile markedSource = + let context = getCompletionContext markedSource + let parseResults, checkResults = getParseAndCheckResultsOfSignatureFile context.Source + checkResults.GetCodeCompletionSuggestions(context, parseResults, FSharpCodeCompletionOptions.Default) + let getSymbolUses (markedSource: string) = let context, checkResults = getCheckedResolveContext markedSource checkResults.GetSymbolUses(context) @@ -249,10 +260,14 @@ module Checker = let symbolUses = getSymbolUses markedSource symbolUses |> List.exactlyOne + let getDeclarationLocation (markedSource: string) = + let context, checkResults = getCheckedResolveContext markedSource + checkResults.GetDeclarationLocation(context) + let getTooltipWithOptions (options: string array) (markedSource: string) = let context = getResolveContext markedSource let _, checkResults = getParseAndCheckResultsWithOptions options context.Source - checkResults.GetToolTip(context.Pos.Line, context.Pos.Column, context.LineText, context.Names, FSharpTokenTag.Identifier) + checkResults.GetTooltip(context) let getTooltip (markedSource: string) = getTooltipWithOptions [||] markedSource @@ -260,3 +275,36 @@ module Checker = let getMethodOverloads names (markedSource: string) = let context, checkResults = getCheckedResolveContext markedSource checkResults.GetMethodOverloads(context, names) + +/// Shared assertion helpers reused by the completion, editor, tooltip and type-checker-recovery +/// test files. Defined here (an early-compiled file) so every consuming file sees a single +/// definition instead of redefining its own copy. +[] +module AssertHelpers = + let assertItemsWithNames contains names (completionInfo: DeclarationListInfo) = + let itemNames = + completionInfo.Items + |> Array.map _.NameInCode + |> Array.map normalizeNewLines + |> set + + for name in names do + let name = normalizeNewLines name + Set.contains name itemNames |> shouldEqual contains + + let assertHasItemWithNames names (completionInfo: DeclarationListInfo) = + assertItemsWithNames true names completionInfo + + let assertHasNoItemsWithNames names (completionInfo: DeclarationListInfo) = + assertItemsWithNames false names completionInfo + + let assertAndExtractTooltip (ToolTipText(items)) = + Assert.Equal(1, items.Length) + match items[0] with + | ToolTipElement.Group [ singleElement ] -> + let toolTipText = + singleElement.MainDescription + |> taggedTextToString + toolTipText, singleElement.XmlDoc, singleElement.Remarks |> Option.map taggedTextToString + | _ -> failwith $"Expected group, got {items[0]}" + diff --git a/tests/FSharp.Compiler.Service.Tests/Common.fs b/tests/FSharp.Compiler.Service.Tests/Common.fs index 7fad5ff15c5..a7ca1d2c4f4 100644 --- a/tests/FSharp.Compiler.Service.Tests/Common.fs +++ b/tests/FSharp.Compiler.Service.Tests/Common.fs @@ -7,6 +7,7 @@ open System.IO open System.Collections.Generic open System.Threading.Tasks open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.Diagnostics open FSharp.Compiler.IO open FSharp.Compiler.Symbols open FSharp.Compiler.Syntax @@ -363,6 +364,12 @@ let getParseResultsOfSignatureFile (source: string) = let getParseAndCheckResults (source: string) = parseAndCheckScript("Test.fsx", source) +/// Reference/#load script tests must not share the checker's filename-keyed script-closure +/// cache: a shared "Test.fsx" lets one test's closure (its resolved/failed #r references and +/// their diagnostics) leak into the next. Give each such test a unique script identity. +let getParseAndCheckResultsUniqueName (source: string) = + parseAndCheckScript(Guid.NewGuid().ToString("N") + ".fsx", source) + let getParseAndCheckResultsWithOptions options source = parseAndCheckScriptWithOptions ("Test.fsx", source, options) @@ -376,15 +383,22 @@ let getParseAndCheckResults80 (source: string) = parseAndCheckScript80("Test.fsx", source) -let inline dumpDiagnostics (results: FSharpCheckFileResults) = +let normalizeDiagnosticMessage (d: FSharpDiagnostic) = + d.Message.Split('\n') + |> Array.map _.Trim() + |> Array.filter (fun s -> s.Length > 0) + |> String.concat " " + +let formatDiagnostic (d: FSharpDiagnostic) = + sprintf "%s: %s" (d.Range.ToString()) (normalizeDiagnosticMessage d) + +let dumpDiagnostics (results: FSharpCheckFileResults) = + results.Diagnostics |> Array.map formatDiagnostic |> List.ofArray + +let dumpDiagnosticsOfSeverity (severity: FSharpDiagnosticSeverity) (results: FSharpCheckFileResults) = results.Diagnostics - |> Array.map (fun e -> - let message = - e.Message.Split('\n') - |> Array.map _.Trim() - |> Array.filter (fun s -> s.Length > 0) - |> String.concat " " - sprintf "%s: %s" (e.Range.ToString()) message) + |> Array.filter (fun d -> d.Severity = severity) + |> Array.map formatDiagnostic |> List.ofArray let inline dumpDiagnosticNumbers (results: FSharpCheckFileResults) = diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Accessibility.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Accessibility.fs new file mode 100644 index 00000000000..66d7a6ae6b4 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Accessibility.fs @@ -0,0 +1,233 @@ +module FSharp.Compiler.Service.Tests.CompletionAccessibilityTests + +open Xunit + +[] +let ``PrivateVisible`` () = + let info = + Checker.getCompletionInfo + """ +module CodeAccessibility + +module Module1 = + let private fieldPrivate = 1 + let private MethodPrivate x = + x+1 + type private TypePrivate() = + member this.mem = 1 + let a = (*Marker1*) {caret}""" + + assertHasItemWithNames [ "fieldPrivate"; "MethodPrivate"; "TypePrivate" ] info + +[] +let ``InternalVisible`` () = + let info = + Checker.getCompletionInfo + """ +module CodeAccessibility + +module Module1 = + let internal fieldInternal = 1 + let internal MethodInternal x = + x+1 + type internal TypeInternal() = + member this.mem = 1 + let a = (*Marker1*) {caret}""" + + assertHasItemWithNames [ "fieldInternal"; "MethodInternal"; "TypeInternal" ] info + +let private widgetInheritanceSource = + """ +open System +//define the base class +type Widget() = + let mutable state = 0 + member internal x.MethodInternal() = state + member public x.MethodPublic(n) = state <- state + n + member private x.MethodPrivate() = (state <> 0) + [] + val mutable internal fieldInternal:int + [] + val mutable public fieldPublic:int + [] + val mutable private fieldPrivate:int +//define the divided class which inherent "Widget" +type Divided() = + inherit Widget() + member x.myPrint() = + base.{caret} +Console.ReadKey(true)""" + +[] +let ``InheritedClass.BaseClassPrivateMethod.Negative`` () = + let info = Checker.getCompletionInfo widgetInheritanceSource + assertHasNoItemsWithNames [ "MethodPrivate"; "fieldPrivate" ] info + +[] +let ``InheritedClass.BaseClassPublicMethodAndProperty`` () = + let info = Checker.getCompletionInfo widgetInheritanceSource + assertHasItemWithNames [ "MethodPublic"; "fieldPublic" ] info + +[] +let ``Visibility.InternalNestedClass.Negative`` () = + let info = Checker.getCompletionInfo "System.Console.{caret}" + + assertHasNoItemsWithNames [ "ControlCDelegateData" ] info + +[] +let ``Visibility.PrivateIdentifierInDiffModule.Negative`` () = + let info = + Checker.getCompletionInfo + """ +module Module1 = + let private fieldPrivate = 1 + let private MethodPrivate x = + x+1 + type private TypePrivate()= + member this.mem = 1 +module Module2 = + Module1.{caret}""" + + Assert.Equal(0, info.Items.Length) + +[] +let ``Visibility.PrivateIdentifierInDiffClass.Negative`` () = + let info = + Checker.getCompletionInfo + """ +open System +module Module1 = + type Type1()= + [] + val mutable private fieldPrivate:int + member private x.MethodPrivate() = 1 + type Type2()= + let M1= + let type1 = new Type1() + type1.{caret}""" + + assertHasNoItemsWithNames [ "fieldPrivate"; "MethodPrivate" ] info + +[] +[] + val mutable private PrivateField:int + static member private PrivateMethod() = 1 + member this.Field1 with get () = this.{caret} + member x.MethodTest() = Type1(*MarkerMethodInType*) + let type1 = new Type1() """, + "PrivateField")>] +[] + val mutable private PrivateField:int + static member private PrivateMethod() = 1 + member this.Field1 with get () = this(*MarkerFieldInType*) + member x.MethodTest() = Type1.{caret} + let type1 = new Type1() """, + "PrivateMethod")>] +let ``Visibility.PrivateMemberInSameClass`` (markedSource: string) (expected: string) = + let info = Checker.getCompletionInfo markedSource + + assertHasItemWithNames [ expected ] info + +[] +let ``Visibility.InternalMethods.DefInSameAssembly`` () = + let info = + Checker.getCompletionInfo + """ +module CodeAccessibility +open System +module Module1 = +type Type1()= + [] + val mutable internal fieldInternal:int + member internal x.MethodInternal (x:int) = x+2 +let type1 = new Type1() +type1.{caret}""" + + assertHasItemWithNames [ "fieldInternal"; "MethodInternal" ] info + +[] +[] +[] +let ``ObjInstance.InheritedClass.MethodsWithDiffAccessibility`` (markedSource: string) = + let info = Checker.getCompletionInfo markedSource + assertHasItemWithNames [ "baseField"; "derivedField" ] info + assertHasNoItemsWithNames [ "baseFieldPrivate"; "derivedFieldPrivate" ] info + +[] +[] +[] +let ``Visibility.InheritedClass.MethodsWithDiffAccessibility`` (markedSource: string) = + let info = Checker.getCompletionInfo markedSource + assertHasItemWithNames [ "baseField"; "derivedField"; "derivedFieldPrivate" ] info + assertHasNoItemsWithNames [ "baseFieldPrivate" ] info + +[] +let ``Visibility.InheritedClass.MethodsWithSameNameMethod`` () = + let info = + Checker.getCompletionInfo + """type MyClass = + val foo : int + new (foo) = { foo = foo } +type MyClass2 = + inherit MyClass + val foo : int + new (foo) = { + inherit MyClass(foo) + foo = foo + } +let x = new MyClass2(0) +(*marker*)x.{caret}foo""" + + assertHasItemWithNames [ "foo" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Attributes.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Attributes.fs new file mode 100644 index 00000000000..73bb17aa242 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Attributes.fs @@ -0,0 +1,229 @@ +module FSharp.Compiler.Service.Tests.CompletionAttributesTests + +open Xunit + +[] +[] +[] +[] +[] +[] +[] +[] +let ``Attribute.WhenAttachedTo.Bug70080`` (noneTargetSource: string) = + for prefix in [ ""; "type:"; "module:" ] do + noneTargetSource.Replace("[ Checker.getCompletionInfo + |> assertHasItemWithNames [ "AttributeUsage" ] + +[] +let ``ObsoleteAndOCamlCompatDontAppear`` () = + let info = + Checker.getCompletionInfo + """open System +type X = + static member private Private() = () + [] + static member Obsolete() = () + [] + static member CompilerMessageTest() = () +X.{caret}""" + + assertHasNoItemsWithNames [ "Obsolete"; "CompilerMessageTest" ] info + +[] +let ``Attributes.CanSeeOpenNamespaces.Bug268290.Case1`` () = + let info = + Checker.getCompletionInfo + """ + module Foo + open System + [<{caret} + """ + + assertHasItemWithNames [ "AttributeUsage" ] info + +[] +let ``LongIdent.AsAttribute`` () = + let info = + Checker.getCompletionInfo + """ + [] + type TestAttribute() = + member x.print() = "print" """ + + assertHasItemWithNames [ "ObsoleteAttribute" ] info + +[] +let ``NotShowAttribute`` () = + let info1 = + Checker.getCompletionInfo + """ + open System + [] + type testclass() = + member x.Name() = "test" + [] + type testattribute() = + member x.Empty = 0 + """ + + Assert.Equal(0, info1.Items.Length) + + let info2 = + Checker.getCompletionInfo + """ + open System + [] + type testclass() = + member x.Name() = "test" + [] + type testattribute() = + member x.Empty = 0 + """ + + Assert.Equal(0, info2.Items.Length) + +[] +[] +[] +let ``Regression2296.DirectResultsOfMethodCall`` (shouldContain: bool) (names: string) = + let info = + Checker.getCompletionInfo + """ + module BasicTest + // regression test of bug 2296: No completion lists on the direct results of a method call + // This is a function that has a custom attribute on the return type. + let foo(a) : [] int + = a + 5 + // The rest of the code is a mere verification that the compiler thru reflection + let executingAssembly = System.Reflection.Assembly.GetExecutingAssembly() + let programType = executingAssembly.GetType("Program") + let message = programType.GetMethod("foo").{caret} + """ + + let expected = names.Split(';') |> List.ofArray + + assertItemsWithNames shouldContain expected info + +[] +[] +[] +let ``Regression2296.Identifier.String.Reflection01`` (shouldContain: bool) (names: string) = + let info = + Checker.getCompletionInfo + """ + module BasicTest + // regression test of bug 2296: No completion lists on the direct results of a method call + // This is a function that has a custom attribute on the return type. + let foo(a) : [] int + = a + 5 + // The rest of the code is a mere verification that the compiler thru reflection + let executingAssembly = System.Reflection.Assembly.GetExecutingAssembly() + let programType = executingAssembly.GetType("Program") + let message = programType.GetMethod("foo")(*Marker1*) + let x = "" + let _ = x.Contains("a").{caret}""" + + let expected = names.Split(';') |> List.ofArray + + assertItemsWithNames shouldContain expected info + +[] +[] +[] +let ``Regression2296.Identifier.String.Reflection02`` (shouldContain: bool) (names: string) = + let info = + Checker.getCompletionInfo + """ + module BasicTest + // regression test of bug 2296: No completion lists on the direct results of a method call + // This is a function that has a custom attribute on the return type. + let foo(a) : [] int + = a + 5 + // The rest of the code is a mere verification that the compiler thru reflection + let executingAssembly = System.Reflection.Assembly.GetExecutingAssembly() + let programType = executingAssembly.GetType("Program") + let message = programType.GetMethod("foo")(*Marker1*) + let x = "" + let _ = x.Contains("a")(*Marker2*) + let _ = x.CompareTo("a").{caret}""" + + let expected = names.Split(';') |> List.ofArray + + assertItemsWithNames shouldContain expected info + +[] +[] +[] +let ``Regression2296.System.StaticMethod.Reflection`` (shouldContain: bool) (names: string) = + let info = + Checker.getCompletionInfo + """ + module BasicTest + // regression test of bug 2296: No completion lists on the direct results of a method call + // This is a function that has a custom attribute on the return type. + let foo(a) : [] int + = a + 5 + // The rest of the code is a mere verification that the compiler thru reflection + let executingAssembly = System.Reflection.Assembly.GetExecutingAssembly() + let programType = executingAssembly.GetType("Program") + let message = programType.GetMethod("foo")(*Marker1*) + let x = "" + let _ = x.Contains("a")(*Marker2*) + let _ = x.CompareTo("a")(*Marker3*) + open System.IO + let GetFileSize (filePath: string) = File.GetAttributes(filePath).{caret}""" + + let expected = names.Split(';') |> List.ofArray + + assertItemsWithNames shouldContain expected info + +[] +let ``LongIdent.PInvoke.AsAttribute`` () = + let info = + Checker.getCompletionInfo + """ + open System.IO + open System.Runtime.InteropServices + + module mymodule = + type SomeAttrib() = + inherit System.Attribute() + type myclass() = + member x.name() = "test case" + module mymodule2 = + [] + extern bool CopyFile_Attrib([] char [] lpExistingFileName, char []lpNewFileName, [] bool & bFailIfExists); + + let result5 = CopyFile_Arrays(tempFile1.ToCharArray(), tempFile2.ToCharArray(), false) + printfn "WithAttribute %A" result5""" + + assertHasItemWithNames [ "SomeAttrib" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.ByrefSpans.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.ByrefSpans.fs new file mode 100644 index 00000000000..43e34524a48 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.ByrefSpans.fs @@ -0,0 +1,17 @@ +module FSharp.Compiler.Service.Tests.CompletionByrefSpansTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``CLIEventsWithByRefArgs`` () = + let info = + Checker.getCompletionInfo + """type MyDelegate = delegate of obj * string byref -> unit +type mytype() = [] member this.myEvent = (new DelegateEvent()).Publish +let t = mytype() +t.{caret}""" + + assertHasItemWithNames [ "add_myEvent"; "remove_myEvent" ] info + assertHasNoItemsWithNames [ "myEvent" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Classes.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Classes.fs new file mode 100644 index 00000000000..f576c7339e8 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Classes.fs @@ -0,0 +1,256 @@ +module FSharp.Compiler.Service.Tests.CompletionClassesTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``AutoCompletion.BeforeThis`` () = + let plain = + Checker.getCompletionInfo + """type A() = + member _.X = () + member this.{caret}""" + + let privateMember = + Checker.getCompletionInfo + """type A() = + member _.X = () + member private this.{caret}""" + + let publicMember = + Checker.getCompletionInfo + """type A() = + member _.X = () + member public this.{caret}""" + + let internalMember = + Checker.getCompletionInfo + """type A() = + member _.X = () + member internal this.{caret}""" + + Assert.Equal(0, plain.Items.Length) + Assert.Equal(0, privateMember.Items.Length) + Assert.Equal(0, publicMember.Items.Length) + Assert.Equal(0, internalMember.Items.Length) + +[] +let ``Completion.DetectInvalidCompletionContext`` () = + let dotOnly = + Checker.getCompletionInfo + """type X = + inherit System {caret}.""" + + let dotCollections = + Checker.getCompletionInfo + """type X = + inherit System {caret}.Collections""" + + Assert.Equal(0, dotOnly.Items.Length) + Assert.Equal(0, dotCollections.Items.Length) + +[] +let ``Completion.LongIdentifiers`` () = + let trailingSpaces = + Checker.getCompletionInfo + """type X = + inherit System. {caret}""" + + let nextLineComment = + Checker.getCompletionInfo + """type X = + inherit System. + {caret}""" + + let leadingDotNextLine = + Checker.getCompletionInfo + """type X = + inherit System + .{caret}""" + + let moduleCandidates = + Checker.getCompletionInfo + """module Mod = + let x = 1 +module Mod2 = + let x = 1 +type X = + inherit Mod{caret}""" + + let partialSystem = + Checker.getCompletionInfo + """type X = + inherit Sys{caret}""" + + let partialCollection = + Checker.getCompletionInfo + """type X = + inherit System.Col{caret}lection""" + + let dotSpaceCollections = + Checker.getCompletionInfo + """type X = + inherit System. {caret} Collections""" + + let dotSpaceArrayList = + Checker.getCompletionInfo + """type X = + inherit System. {caret} Collections.ArrayList()""" + + assertHasItemWithNames [ "IDisposable"; "Array" ] trailingSpaces + assertHasItemWithNames [ "IDisposable"; "Array" ] nextLineComment + assertHasItemWithNames [ "IDisposable"; "Array" ] leadingDotNextLine + assertHasItemWithNames [ "Mod"; "Mod2" ] moduleCandidates + assertHasItemWithNames [ "System"; "obj" ] partialSystem + assertHasItemWithNames [ "Collections"; "IDisposable" ] partialCollection + assertHasItemWithNames [ "Collections"; "IDisposable" ] dotSpaceCollections + assertHasItemWithNames [ "Collections"; "IDisposable" ] dotSpaceArrayList + +[] +let ``AfterConstructor.5039_1`` () = + let info = + Checker.getCompletionInfo + """let someCall(x) = null +let xe = someCall(System.IO.StringReader().{caret}""" + + assertHasItemWithNames [ "ReadBlock" ] info + assertHasNoItemsWithNames [ "LastIndexOfAny" ] info + +[] +let ``AfterConstructor.5039_1.CoffeeBreak`` () = + let info = + Checker.getCompletionInfo + """let someCall(x) = null +let xe = someCall(System.IO.StringReader().{caret}""" + + assertHasItemWithNames [ "ReadBlock" ] info + assertHasNoItemsWithNames [ "LastIndexOfAny" ] info + +[] +let ``AfterConstructor.5039_2`` () = + let info = Checker.getCompletionInfo "System.Random().{caret}" + + assertHasItemWithNames [ "NextDouble" ] info + +[] +let ``AfterConstructor.5039_4`` () = + let info = Checker.getCompletionInfo "System.Collections.Generic.List().{caret}" + + assertHasItemWithNames [ "BinarySearch" ] info + +[] +let ``NameSpace.AsConstructor`` () = + let info = Checker.getCompletionInfo "new System.DateTime({caret})" + + assertHasItemWithNames [ "System"; "Array2D" ] info + assertHasNoItemsWithNames [ "DaysInMonth"; "AddDays" ] info + +[] +let ``Bug243082.DotAfterNewBreaksCompletion`` () = + let info = + Checker.getCompletionInfo + """module A = + type B() = class end +let s = 1 +s.{caret} +let z = new A.""" + + assertHasItemWithNames [ "CompareTo"; "ToString" ] info + +let bug2884Cases: obj[] seq = + [ + [| box "type T1(aaa1) =\n do ({caret}"; box [ "aaa1" ] |] + [| box "type T1(aaa1) =\n do ({caret}\nlet a = 0"; box [ "aaa1" ] |] + [| box "type T1(aaa1) =\n member x.Foo(aaa2) = \n do ({caret}\n member x.Bar = 0"; box [ "aaa1"; "aaa2" ] |] + [| box "type T1(aaa1) =\n member x.Foo(aaa2) = \n let dt = new System.DateTime({caret}"; box [ "aaa1"; "aaa2" ] |] + ] + +[] +let ``Parameter.Bug2884`` (source: string) (expected: string list) = + assertHasItemWithNames expected (Checker.getCompletionInfo source) + +[] +let ``CaseInsensitive`` () = + let info = + Checker.getCompletionInfo + """ + type Test() = + member this.Xyzzy = () + member this.xYzzy = () + member this.xyZzy = () + member this.xyzZy = () + member this.xyzzY = () + let t = new Test() + t.XYZ{caret} + """ + + assertHasItemWithNames [ "Xyzzy"; "xYzzy"; "xyZzy"; "xyzZy"; "xyzzY" ] info + +[] +let ``ObjInstance.InheritedClass.MethodsDefInBase`` () = + let info = + Checker.getCompletionInfo + """ + type Pet() = + member x.Name() = "pet" + member x.Speak() = "this is a pet" + type Dog() = + inherit Pet() + member x.dog() = "this is a dog" + let dog = new Dog() + dog.{caret}""" + + assertHasItemWithNames [ "Name"; "dog" ] info + +[] +[] // Class.Self.Bug1544 +[] // MemberSelf +[] // Identifier.AsClassName.InInitial +let ``Identifier.DeclarationPositionDotIsEmpty`` (caseId: int) = + let source = + match caseId with + | 153 + | 441 -> + """ + type Foo() = + member this.{caret}""" + | _ -> + """ + type f1.{caret} = + val field: int""" + + let info = Checker.getCompletionInfo source + + Assert.Equal(0, info.Items.Length) + +[] +let ``SelfParameter.InDoKeywordScope`` () = + let info = + Checker.getCompletionInfo + """ + type foo() as this = + do + this.{caret}""" + + assertHasItemWithNames [ "ToString" ] info + +[] +let ``SelfParameter.InDoKeywordScope.Negative`` () = + let info = + Checker.getCompletionInfo + """ + type foo() as this = + do + this.{caret}""" + + assertHasNoItemsWithNames [ "Value"; "Contents" ] info + +[] +let ``AutoComplete.Bug72596_A`` () = + let info = + Checker.getCompletionInfo + """type ClassType() = + let foo = fo{caret}""" + + assertHasNoItemsWithNames [ "foo" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.ComputationExpressions.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.ComputationExpressions.fs new file mode 100644 index 00000000000..bf7d3b31ea8 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.ComputationExpressions.fs @@ -0,0 +1,559 @@ +module FSharp.Compiler.Service.Tests.CompletionComputationExpressionsTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``AsyncExpression.CtrlSpaceSmokeTest3d`` () = + let info = + Checker.getCompletionInfo + """ + module BasicTest + let x = async { for xxxxxx in [1;2;3] do xxx{caret} }""" + + assertHasItemWithNames [ "xxxxxx" ] info + +[] +let ``SequenceExpressions.SequenceExprWithWhileLoopSystematic`` () = + let prefix = "\nmodule Test\nlet abbbbc = [| 1 |]\nlet aaaaaa = 0\n" + + let suffixes = + [ "" + " }" + " } \nlet nextDefinition () = 1\n" + " \nlet nextDefinition () = 1\n" + " \ntype NextDefinition() = member x.P = 1\n" ] + + let lines = + [ "BL1", "let f() = seq { while abb(*C*)", [ "(*C*)", false, [ "abbbbc" ] ] + "BL2", "let f() = seq { while abbbbc(*D1*)", [ "(*D1*)", true, [ "Length" ] ] + "BL3", "let f() = seq { while abbbbc(*D1*) do (*C*)", [ "(*D1*)", true, [ "Length" ]; "(*C*)", false, [ "abbbbc" ] ] + "BL4", "let f() = seq { while abbbbc(*D1*) do abb(*C*)", [ "(*D1*)", true, [ "Length" ]; "(*C*)", false, [ "abbbbc" ] ] + "BL5", "let f() = seq { while abbbbc(*D1*) do abbbbc(*D2*)", [ "(*D1*)", true, [ "Length" ]; "(*D2*)", true, [ "Length" ] ] + "BL6", "let f() = seq { while abbbbc(*D1*) do abbbbc.[(*C*)", [ "(*D1*)", true, [ "Length" ]; "(*C*)", false, [ "abbbbc"; "aaaaaa" ] ] + "BL7", "let f() = seq { while abbbbc(*D1*) do abbbbc.[aaa(*C*)", [ "(*D1*)", true, [ "Length" ]; "(*C*)", false, [ "aaaaaa" ] ] + "BL7a", "let f() = seq { while abbbbc(*D1*) do abbbbc.[aaa(*C*)]", [ "(*D1*)", true, [ "Length" ]; "(*C*)", false, [ "aaaaaa" ] ] + "BL7b", "let f() = seq { while abbbbc(*D1*) do abbbbc.[aaa(*C*)] <- ", [ "(*D1*)", true, [ "Length" ]; "(*C*)", false, [ "aaaaaa" ] ] + "BL7c", "let f() = seq { while abbbbc(*D1*) do abbbbc.[aaa(*C*)] <- 1", [ "(*D1*)", true, [ "Length" ]; "(*C*)", false, [ "aaaaaa" ] ] + "BL7d", "let f() = seq { while abbbbc(*D1*) do abbbbc.[ (*C*) ] <- 1", [ "(*D1*)", true, [ "Length" ]; "(*C*)", false, [ "aaaaaa" ] ] + "BL8", "let f() = seq { while abbbbc(*D1*) do abbbbc.[aaaaaa]", [ "(*D1*)", true, [ "Length" ] ] + "BL9", "let f() = seq { while abbbbc(*D1*) do abbbbc.[aaaaaa] <- (*C*)", [ "(*D1*)", true, [ "Length" ]; "(*C*)", false, [ "abbbbc"; "aaaaaa" ] ] + "BL10", "let f() = seq { while abbbbc(*D1*) do abbbbc.[aaaaaa] <- aaa(*C*)", [ "(*D1*)", true, [ "Length" ]; "(*C*)", false, [ "aaaaaa" ] ] ] + + for suffix in suffixes do + for (lineName, lineText, checks) in lines do + for (marker, dot, expected) in checks do + let replacement = if dot then ".{caret}" else "{caret}" + let markedSource = prefix + lineText.Replace(marker, replacement) + suffix + let info = Checker.getCompletionInfo markedSource + let itemNames = info.Items |> Array.map (fun i -> i.NameInCode) + + for name in expected do + if not (Array.contains name itemNames) then + failwithf + "suffix=%A line=%s marker=%s: expected %s but got [%s]" + suffix + lineName + marker + name + (String.concat ", " itemNames) + +[] +let ``ComputationExpression.LetBang`` () = + let info = + Checker.getCompletionInfo + """let http(url:string) = + async { + let rnd = new System.Random() + let! rsp = rnd.{caret}N""" + + assertHasItemWithNames [ "Next" ] info + +[] +let ``CompletionInDifferentEnvs3`` () = + let info = + Checker.getCompletionInfo + """let mb1 = new MailboxProcessor>(fun inbox -> async { let! msg = inbox.Receive() + do {caret}""" + + assertHasItemWithNames [ "msg" ] info + +[] +let ``CompletionInDifferentEnvs4`` () = + let info1 = + Checker.getCompletionInfo + """async { + let! x = i + ({caret} +}""" + + assertHasItemWithNames [ "x" ] info1 + + let info2 = + Checker.getCompletionInfo + """let q = + let a = 20 + let b = (fun i -> i) 40 + (({caret}""" + + assertHasItemWithNames [ "b" ] info2 + assertHasNoItemsWithNames [ "i" ] info2 + +[] +let ``CompletionForAndBang_BaseLine0`` () = + let info = + Checker.getCompletionInfo + """type Builder() = + member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a + member x.Return(a: 'T) = a +let builder = Builder() +builder { + let! xxx3 = 2 + return x{caret} +}""" + + assertHasItemWithNames [ "xxx3" ] info + +[] +let ``CompletionForAndBang_BaseLine1`` () = + let info = + Checker.getCompletionInfo + """type Builder() = + member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a + member x.Return(a: 'T) = a +let builder = Builder() +let xxx1 = 1 +builder { + let xxx2 = 1 + let! xxx3 = 1 + return (1 + x{caret}) +}""" + + assertHasItemWithNames [ "xxx1"; "xxx2"; "xxx3" ] info + +[] +let ``CompletionForAndBang_BaseLine2`` () = + let info = + Checker.getCompletionInfo + """type Builder() = + member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a + member x.Return(a: 'T) = a +let builder = Builder() +let yyy1 = 1 +builder { + let yyy2 = 1 + let! yyy3 = 1 + return (1 + y{caret})""" + + assertHasItemWithNames [ "yyy1"; "yyy2"; "yyy3" ] info + +[] +let ``CompletionForAndBang_BaseLine3`` () = + let info = + Checker.getCompletionInfo + """type Builder() = + member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a + member x.Return(a: 'T) = a +let builder = Builder() +let zzz1 = 1 +builder { + let zzz2 = 1 + let! zzz3 = 1 + return (1 + z{caret}""" + + assertHasItemWithNames [ "zzz1"; "zzz2"; "zzz3" ] info + +[] +let ``CompletionForAndBang_BaseLine4`` () = + let info = + Checker.getCompletionInfo + """type Builder() = + member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a + member x.Return(a: 'T) = a +let builder = Builder() +let zzz1 = 1 +builder { + let! zzz3 = 1 + return (1 + z{caret}""" + + assertHasItemWithNames [ "zzz1"; "zzz3" ] info + +[] +let ``CompletionForAndBang_Test_MergeSources_Bind_Return0`` () = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| "/langversion:preview" |] + FSharpCodeCompletionOptions.Default + """type Builder() = + member x.MergeSources(a: 'T1, b: 'T2) = (a, b) + member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a + member x.Return(a: 'T) = a +let builder = Builder() +builder { + let! xxx3 = 2 + and! xxx4 = 2 + return x{caret} +}""" + + assertHasItemWithNames [ "xxx3"; "xxx4" ] info + +[] +let ``CompletionForAndBang_Test_MergeSources_Bind_Return1`` () = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| "/langversion:preview" |] + FSharpCodeCompletionOptions.Default + """type Builder() = + member x.MergeSources(a: 'T1, b: 'T2) = (a, b) + member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a + member x.Return(a: 'T) = a +let builder = Builder() +let xxx1 = 1 +builder { + let xxx2 = 1 + let! xxx3 = 1 + and! xxx4 = 1 + return (1 + x{caret}) +}""" + + assertHasItemWithNames [ "xxx1"; "xxx2"; "xxx3"; "xxx4" ] info + +[] +let ``CompletionForAndBang_Test_MergeSources_Bind_Return2`` () = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| "/langversion:preview" |] + FSharpCodeCompletionOptions.Default + """type Builder() = + member x.MergeSources(a: 'T1, b: 'T2) = (a, b) + member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a + member x.Return(a: 'T) = a +let builder = Builder() +let yyy1 = 1 +builder { + let yyy2 = 1 + let! yyy3 = 1 + and! yyy4 = 1 + return (1 + y{caret})""" + + assertHasItemWithNames [ "yyy1"; "yyy2"; "yyy3"; "yyy4" ] info + +[] +[ 'T2) = f a + member x.Return(a: 'T) = a +let builder = Builder() +let zzz1 = 1 +builder { + let zzz2 = 1 + let! zzz3 = 1 + and! zzz4 = 1 + return (1 + z{caret}""", + "zzz1 zzz2 zzz3 zzz4")>] +[ 'T2) = f a + member x.Return(a: 'T) = a +let builder = Builder() +let zzz1 = 1 +builder { + let! zzz3 = 1 + and! zzz4 = 1 + return (1 + z{caret}""", + "zzz1 zzz3 zzz4")>] +let ``CompletionForAndBang_Test_MergeSources_Bind_Return3and4`` (markedSource: string) (expectedNames: string) = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| "/langversion:preview" |] + FSharpCodeCompletionOptions.Default + markedSource + + assertHasItemWithNames (expectedNames.Split(' ') |> List.ofArray) info + +[] +let ``CompletionForAndBang_Test_Bind2Return0`` () = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| "/langversion:preview" |] + FSharpCodeCompletionOptions.Default + """type Builder() = + member x.Bind2Return(a: 'T1, b: 'T2, f: ('T1 * 'T2) -> 'T3) = f (a, b) +let builder = Builder() +builder { + let! xxx3 = 2 + and! xxx4 = 2 + return x{caret} +}""" + + assertHasItemWithNames [ "xxx3"; "xxx4" ] info + +[] +let ``CompletionForAndBang_Test_Bind2Return1`` () = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| "/langversion:preview" |] + FSharpCodeCompletionOptions.Default + """type Builder() = + member x.Bind2Return(a: 'T1, b: 'T2, f: ('T1 * 'T2) -> 'T3) = f (a, b) +let builder = Builder() +let xxx1 = 1 +builder { + let xxx2 = 1 + let! xxx3 = 1 + and! xxx4 = 1 + return (1 + x{caret}) +}""" + + assertHasItemWithNames [ "xxx1"; "xxx2"; "xxx3"; "xxx4" ] info + +[] +let ``CompletionForAndBang_Test_Bind2Return2`` () = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| "/langversion:preview" |] + FSharpCodeCompletionOptions.Default + """type Builder() = + member x.Bind2Return(a: 'T1, b: 'T2, f: ('T1 * 'T2) -> 'T3) = f (a, b) +let builder = Builder() +let yyy1 = 1 +builder { + let yyy2 = 1 + let! yyy3 = 1 + and! yyy4 = 1 + return (1 + y{caret})""" + + assertHasItemWithNames [ "yyy1"; "yyy2"; "yyy3"; "yyy4" ] info + +[] +[ 'T3) = f (a, b) +let builder = Builder() +let zzz1 = 1 +builder { + let zzz2 = 1 + let! zzz3 = 1 + and! zzz4 = 1 + return (1 + z{caret}""", + "zzz1 zzz2 zzz3 zzz4")>] +[ 'T3) = f (a, b) +let builder = Builder() +let zzz1 = 1 +builder { + let! zzz3 = 1 + and! zzz4 = 1 + return (1 + z{caret}""", + "zzz1 zzz3 zzz4")>] +let ``CompletionForAndBang_Test_Bind2Return3and4`` (markedSource: string) (expectedNames: string) = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| "/langversion:preview" |] + FSharpCodeCompletionOptions.Default + markedSource + + assertHasItemWithNames (expectedNames.Split(' ') |> List.ofArray) info + +[] +let ``Expressions.Computation`` () = + let info = + Checker.getCompletionInfo + """type FooBuilder() = + member x.Return(a) = new System.Random() +let foo = FooBuilder() +(foo { return 0 }).{caret}""" + + assertHasItemWithNames [ "Next" ] info + assertHasNoItemsWithNames [ "GetEnumerator" ] info + +[] +let ``ComputationExpressionLet`` () = + let info = + Checker.getCompletionInfo + """let http(url:string) = + async { + let rnd = new System.Random() + let rsp = rnd.{caret}N""" + + assertHasItemWithNames [ "Next" ] info + +[] +let ``InAsyncAndUseBlock`` () = + let info = + Checker.getCompletionInfo + """ + open System.Text.RegularExpressions + open System.IO + let collectLinksAsync (url:string) : Async = + async { do printfn "requesting %s" url + let! html = + async { use reader = new System.IO.StreamReader(new System.IO.FileStream("", FileMode.CreateNew)) + do printfn "reading %s" url + return {caret}reader.ReadToEnd() } //<---- reader + let links = "a" + return links } + """ + + assertHasItemWithNames [ "reader" ] info + +[] +let ``ComputationExpression.WithClosingBrace`` () = + let info = + Checker.getCompletionInfo + """ + module BasicTest + // regression test for bug 3879: intellisense glitch for computation expression + // intellisense does not work in computation expression without the closing brace + type System.Net.WebRequest with + member x.AsyncGetResponse() = Async.BuildPrimitive(x.BeginGetResponse, x.EndGetResponse) + member x.GetResponseAsync() = x.AsyncGetResponse() + let http(url:string) = + async {let req = System.Net.WebRequest.Create("http://www.yahoo.com") + let! rsp = req.{caret}} """ + + assertHasItemWithNames [ "AsyncGetResponse"; "GetResponseAsync"; "ToString" ] info + +[] +let ``ComputationExpression.WithoutClosingBrace`` () = + let info = + Checker.getCompletionInfo + """ + module BasicTest + // regression test for bug 3879: intellisense glitch for computation expression + // intellisense does not work in computation expression without the closing brace + type System.Net.WebRequest with + member x.AsyncGetResponse() = Async.BuildPrimitive(x.BeginGetResponse, x.EndGetResponse) + member x.GetResponseAsync() = x.AsyncGetResponse() + let http(url:string) = + async { let req = System.Net.WebRequest.Create("http://www.yahoo.com") + let! rsp = req.{caret}""" + + assertHasItemWithNames [ "AsyncGetResponse"; "GetResponseAsync"; "ToString" ] info + +[] +let ``AutoComplete.Bug69654_1`` () = + let info1 = + Checker.getCompletionInfo + """let s = async { + let! xxx = async { return 0 } + xxx.Comp{caret}areTo |> ignore // the dot works + xxx |> ignore // no xxx + do xxx |> ignore // no xxx + return xxx // no xxx + }""" + + assertHasItemWithNames [ "CompareTo" ] info1 + + let info2 = + Checker.getCompletionInfo + """let s = async { + let! xxx = async { return 0 } + x{caret}xx.CompareTo |> ignore // the dot works + xxx |> ignore // no xxx + do xxx |> ignore // no xxx + return xxx // no xxx + }""" + + assertHasItemWithNames [ "xxx" ] info2 + + let info3 = + Checker.getCompletionInfo + """let s = async { + let! xxx = async { return 0 } + xxx.CompareTo |> ignore // the dot works + x{caret}xx |> ignore // no xxx + do xxx |> ignore // no xxx + return xxx // no xxx + }""" + + assertHasItemWithNames [ "xxx" ] info3 + + let info4 = + Checker.getCompletionInfo + """let s = async { + let! xxx = async { return 0 } + xxx.CompareTo |> ignore // the dot works + xxx |> ignore // no xxx + do xx{caret}x |> ignore // no xxx + return xxx // no xxx + }""" + + assertHasItemWithNames [ "xxx" ] info4 + + let info5 = + Checker.getCompletionInfo + """let s = async { + let! xxx = async { return 0 } + xxx.CompareTo |> ignore // the dot works + xxx |> ignore // no xxx + do xxx |> ignore // no xxx + return xx{caret}x // no xxx + }""" + + assertHasItemWithNames [ "xxx" ] info5 + +[] +let ``AutoComplete.Bug69654_2`` () = + let info1 = + Checker.getCompletionInfo + """let s = async { + use xxx = null + xxx.Disp{caret}ose() // the dot works + xxx |> ignore // no xxx + do xxx |> ignore // no xxx + return xxx // no xxx + }""" + + assertHasItemWithNames [ "Dispose" ] info1 + + let info2 = + Checker.getCompletionInfo + """let s = async { + use xxx = null + x{caret}xx.Dispose() // the dot works + xxx |> ignore // no xxx + do xxx |> ignore // no xxx + return xxx // no xxx + }""" + + assertHasItemWithNames [ "xxx" ] info2 + + let info3 = + Checker.getCompletionInfo + """let s = async { + use xxx = null + xxx.Dispose() // the dot works + x{caret}xx |> ignore // no xxx + do xxx |> ignore // no xxx + return xxx // no xxx + }""" + + assertHasItemWithNames [ "xxx" ] info3 + + let info4 = + Checker.getCompletionInfo + """let s = async { + use xxx = null + xxx.Dispose() // the dot works + xxx |> ignore // no xxx + do xx{caret}x |> ignore // no xxx + return xxx // no xxx + }""" + + assertHasItemWithNames [ "xxx" ] info4 + + let info5 = + Checker.getCompletionInfo + """let s = async { + use xxx = null + xxx.Dispose() // the dot works + xxx |> ignore // no xxx + do xxx |> ignore // no xxx + return xx{caret}x // no xxx + }""" + + assertHasItemWithNames [ "xxx" ] info5 + +[] +let ``EnsureThatUnhandledExceptionsCauseAnAssert`` () = () diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Conditionals.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Conditionals.fs new file mode 100644 index 00000000000..b0faf6e55b7 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Conditionals.fs @@ -0,0 +1,79 @@ +module FSharp.Compiler.Service.Tests.CompletionConditionalsTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``ValueDeclarationHidden.Bug4405`` () = + let info = + Checker.getCompletionInfo + """do + let a = "string" + let a = if true then 0 else a.{caret}""" + + assertHasItemWithNames [ "IndexOf"; "Substring" ] info + +[] +let ``Parameter.DirectAfterDefined.Bug2884`` () = + let info = + Checker.getCompletionInfo + """if true then + let aaa1 = 0 + ({caret}""" + + assertHasItemWithNames [ "aaa1" ] info + +[] +let ``COMPILED.DefineNotPropagatedToIncrementalBuilder`` () = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| "--define:COMPILED" |] + FSharpCodeCompletionOptions.Default + """module File1 = +#if COMPILED + let x = 0 +#else + let y = 1 +#endif + +module File2 = + File1.{caret}""" + + assertHasItemWithNames [ "x" ] info + assertHasNoItemsWithNames [ "y" ] info + Assert.Equal(1, info.Items.Length) + +[] +let ``Keywords.If`` () = + let info = + Checker.getCompletionInfo + """ + if.{caret} true then + () """ + + Assert.Equal(0, info.Items.Length) + +[] +let ``NotShowPInvokeSignature`` () = + let info = + Checker.getCompletionInfo + """let x = "System.Console" +#if RELEASE +System.Console.{caret} +#endif +()""" + + Assert.Equal(0, info.Items.Length) + +[] +let ``Regression4405.Identifier.ReBound`` () = + let info = + Checker.getCompletionInfo + """ + let f x = + let varA = "string" + let varA = if x then varA.{caret} else 2 + varA""" + + assertHasItemWithNames [ "Chars"; "StartsWith" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Constraints.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Constraints.fs new file mode 100644 index 00000000000..9dd4005c8ac --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Constraints.fs @@ -0,0 +1,89 @@ +module FSharp.Compiler.Service.Tests.CompletionConstraintsTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``AutoCompletion.OnTypeConstraintError`` () = + let info = + Checker.getCompletionInfo + """type Foo = Foo + with + member _.Bar = 1 + member _.PublicMethodForIntellisense() = 2 + member internal _.InternalMethod() = 3 + member private _.PrivateProperty = 4 + +let u: Unit = + [ Foo ] + |> List.map (fun abcd -> abcd.{caret})""" + + assertHasItemWithNames [ "Bar"; "Equals"; "GetHashCode"; "GetType"; "InternalMethod"; "PublicMethodForIntellisense"; "ToString" ] info + +[] +let ``ConstrainedTypes`` () = + let info1 = + Checker.getCompletionInfo + """ + type Pet() = + member x.Name() = "pet" + member x.Speak() = "this is a pet" + type Dog() = + inherit Pet() + member x.dog() = "this is a dog" + let dog = new Dog() + let pet = dog :> Pet + pet.{caret} + let dctest = pet :?> Dog + dctest(*Mdowncast*) + let f (x : bigint) = x(*Mconstrainedtoint*) + """ + + assertHasItemWithNames [ "Name"; "Speak" ] info1 + + let info2 = + Checker.getCompletionInfo + """ + type Pet() = + member x.Name() = "pet" + member x.Speak() = "this is a pet" + type Dog() = + inherit Pet() + member x.dog() = "this is a dog" + let dog = new Dog() + let pet = dog :> Pet + pet(*Mupcast*) + let dctest = pet :?> Dog + dctest.{caret} + let f (x : bigint) = x(*Mconstrainedtoint*) + """ + + assertHasItemWithNames [ "dog"; "Name" ] info2 + + let info3 = + Checker.getCompletionInfo + """ + type Pet() = + member x.Name() = "pet" + member x.Speak() = "this is a pet" + type Dog() = + inherit Pet() + member x.dog() = "this is a dog" + let dog = new Dog() + let pet = dog :> Pet + pet(*Mupcast*) + let dctest = pet :?> Dog + dctest(*Mdowncast*) + let f (x : bigint) = x.{caret} + """ + + assertHasItemWithNames [ "ToString" ] info3 + +[] +let ``Identifier.EqualityConstraint.Bug65730`` () = + let info = + Checker.getCompletionInfo + """let g3<'a when 'a : equality> (x:'a) = x.{caret}""" + + assertHasItemWithNames [ "Equals"; "GetHashCode" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.DiscriminatedUnions.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.DiscriminatedUnions.fs new file mode 100644 index 00000000000..e540564a36a --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.DiscriminatedUnions.fs @@ -0,0 +1,185 @@ +module FSharp.Compiler.Service.Tests.CompletionDiscriminatedUnionsTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``AutoCompletion.ObjectMethods`` () = + let source (tail: string) = + sprintf + """type DU1 = DU_1 +[] +type DU2 = DU_2 +[] +type DU3 = + | DU_3 + with member this.Equals(b : string) = 1 +[] +type DU4 = + | DU_4 + with member this.GetHashCode(b : string) = 1 +module Extensions = + type System.Object with + member this.ExtensionPropObj = 42 + member this.ExtensionMethodObj () = 42 +open Extensions +%s""" + tail + + let cases = + [ "obj().{caret}", [ "Equals"; "ExtensionPropObj"; "ExtensionMethodObj" ], [] + "System.Object.{caret}", [ "Equals"; "ReferenceEquals" ], [] + "System.String.{caret}", [ "Equals" ], [] + "DU_1.{caret}", [ "Equals"; "GetHashCode"; "ExtensionMethodObj"; "ExtensionPropObj" ], [] + "DU_2.{caret}", [ "ExtensionPropObj"; "ExtensionMethodObj" ], [ "Equals"; "GetHashCode" ] + "DU_3.{caret}", [ "ExtensionPropObj"; "ExtensionMethodObj"; "Equals" ], [ "GetHashCode" ] + "DU_4.{caret}", [ "ExtensionPropObj"; "ExtensionMethodObj"; "GetHashCode" ], [ "Equals" ] ] + + for tail, expected, notExpected in cases do + let info = Checker.getCompletionInfo (source tail) + assertHasItemWithNames expected info + + if not (List.isEmpty notExpected) then + assertHasNoItemsWithNames notExpected info + +[] +let ``SimpleTypes.DisUnion`` () = + let info = + Checker.getCompletionInfo + """ + type Route = int + type Make = string + type Model = string + type Transport = + | Car of Make * Model + | Bicycle + | Bus of Route + let typediscriminatedunion = Car("BMW","360") + typediscriminatedunion.{caret}""" + + assertHasItemWithNames [ "GetType"; "ToString" ] info + +[] +let ``VariableIdentifier.MethodsInheritFromBase`` () = + let info = + Checker.getCompletionInfo + """ + namespace MyNamespace1 + module MyModule = + type DuType = + | Tag of int + let f (DuType(*Maftervariable1*).Tag(x)) = 10 + type Pet() = + member x.Name = "pet" + member x.Speak() = "this is a pet" + type Dog() = + inherit Pet() + do base.{caret}GetType() + let dog = new Dog()""" + + assertHasItemWithNames [ "Name"; "Speak" ] info + +[] +[ = [1; 2; 3] + let f (x:MyNamespace1.MyModule.{caret}) = 10 + let y = int System.IO(*Maftervariable5*)""", + "DuType")>] +[ = [1; 2; 3] + let f (x:MyNamespace1.MyModule(*Maftervariable4*)) = 10 + let y = int System.IO.{caret}""", + "BinaryReader;Stream;Directory")>] +let ``VariableIdentifier.DefInDiffNamespace`` (markedSource: string) (names: string) = + let info = Checker.getCompletionInfo markedSource + + assertHasItemWithNames (names.Split(';') |> List.ofArray) info + +[] +[] 'a> = 10""", + "Dog;DuType")>] +[] 'a> = 10""", + "Tag")>] +let ``LongIdent.AsTypeParameter.DefInDiffNamespace`` (markedSource: string) (names: string) = + let info = Checker.getCompletionInfo markedSource + + assertHasItemWithNames (names.Split(';') |> List.ofArray) info + +[] +let ``Identifier.InDiscUnion.WithoutDef`` () = + let info = + Checker.getCompletionInfo + """ + type DUTag = + |Tag.{caret} of int""" + + Assert.Equal(0, info.Items.Length) + +[] +let ``VariableIdentifier.AsParameter`` () = + let info = + Checker.getCompletionInfo + """ + module MyModule = + type DuType = + | Tag of int + let f (DuType.{caret}Tag(x)) = 10 """ + + assertHasItemWithNames [ "Tag" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Enums.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Enums.fs new file mode 100644 index 00000000000..6c68f7ebd26 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Enums.fs @@ -0,0 +1,174 @@ +module FSharp.Compiler.Service.Tests.CompletionEnumsTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``OfSeveralModuleMembers`` () = + let completeAt (expr: string) = + Checker.getCompletionInfo ( + sprintf + """module Module = + let Constant = 5 + type Class = class + end + type Record = {AString:string} + exception OutOfRange of string + type Enum = Red = 0 | White = 1 | Blue = 2 + type DiscriminatedUnion = A | B | C + type TupleType = int * int + type FunctionType = unit->unit + let (~+) x = -x + type Interface = + abstract MyMethod : unit->unit + type Struct = struct + end + let Function x = 0 + let FunctionValue = fun x -> 0 + let Tuple = (0,2) + module Submodule = + let a = 0 + type ValueType = int +module AbbreviationModule = + type StructAbbreviation = Module.Struct + type InterfaceAbbreviation = Module.Interface + type DiscriminatedUnionAbbreviation = Module.DiscriminatedUnion + type RecordAbbreviation = Module.Record + type EnumAbbreviation = Module.Enum + type TupleTypeAbbreviation = Module.TupleType +let y = %s +let f x = 0""" + expr) + + let moduleMembers = completeAt "Module.{caret}" + + assertHasItemWithNames + [ "Constant"; "Class"; "Record"; "OutOfRange"; "Enum"; "DiscriminatedUnion"; "TupleType" + "FunctionType"; "Interface"; "Struct"; "Function"; "FunctionValue"; "Tuple"; "Submodule"; "ValueType" ] + moduleMembers + + for name, glyph in + [ "A", FSharpGlyph.EnumMember + "B", FSharpGlyph.EnumMember + "C", FSharpGlyph.EnumMember + "Enum", FSharpGlyph.Enum + "DiscriminatedUnion", FSharpGlyph.Union + "Interface", FSharpGlyph.Interface + "Struct", FSharpGlyph.Struct + "ValueType", FSharpGlyph.Struct + "Class", FSharpGlyph.Class + "Record", FSharpGlyph.Type + "TupleType", FSharpGlyph.Class + "FunctionType", FSharpGlyph.Delegate + "Submodule", FSharpGlyph.Module + "OutOfRange", FSharpGlyph.Exception + "Function", FSharpGlyph.Method + "FunctionValue", FSharpGlyph.Method + "Constant", FSharpGlyph.Variable + "Tuple", FSharpGlyph.Variable ] do + assertItemGlyph name glyph moduleMembers + + let abbreviationMembers = completeAt "AbbreviationModule.{caret}" + + assertHasItemWithNames + [ "StructAbbreviation"; "InterfaceAbbreviation"; "DiscriminatedUnionAbbreviation" + "RecordAbbreviation"; "EnumAbbreviation"; "TupleTypeAbbreviation" ] + abbreviationMembers + + for name, glyph in + [ "EnumAbbreviation", FSharpGlyph.Enum + "InterfaceAbbreviation", FSharpGlyph.Interface + "StructAbbreviation", FSharpGlyph.Struct + "RecordAbbreviation", FSharpGlyph.Type + "DiscriminatedUnionAbbreviation", FSharpGlyph.Union + "TupleTypeAbbreviation", FSharpGlyph.Class ] do + assertItemGlyph name glyph abbreviationMembers + +[] +let ``EnumValue.Bug2449`` () = + let info = + Checker.getCompletionInfo + """type E = | A = 1 | B = 2 +let e = E.A +e.{caret}""" + + assertHasNoItemsWithNames [ "value__" ] info + +[] +let ``EnumValue.Bug4044`` () = + let info = + Checker.getCompletionInfo + """open System.IO +let GetFileSize filePath = File.GetAttributes(filePath).{caret}""" + + assertHasNoItemsWithNames [ "value__" ] info + +[] +let ``SimpleTypes.Enum`` () = + let info = + Checker.getCompletionInfo + """ + type weekday = + | Monday = 1 + | Tuesday = 2 + | Wednesday = 3 + | Thursday = 4 + | Friday = 5 + let typeenum = weekday.Friday + typeenum.{caret}""" + + assertHasItemWithNames [ "GetType"; "ToString" ] info + +[] +[ "move left" + | NS(*Mpatternmatch2*) -> "move right" """, + "Direction;ToString")>] +[ "move left" + | NS.{caret} -> "move right" """, + "longident")>] +let ``LongIdent.PatternMatch.DefFromDiffNamespace`` (markedSource: string) (names: string) = + let info = Checker.getCompletionInfo markedSource + + assertHasItemWithNames (names.Split(';') |> List.ofArray) info + +[] +let ``ReOpenNameSpace.EnumTypes`` () = + let info = + Checker.getCompletionInfo + """ + // F# declared enum types: + namespace A + module Test = + type A = | Foo = 0 + namespace B + open A + open A + Test.A.{caret} + """ + + assertHasItemWithNames [ "Foo" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Events.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Events.fs new file mode 100644 index 00000000000..becc3a2cb3a --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Events.fs @@ -0,0 +1,48 @@ +module FSharp.Compiler.Service.Tests.CompletionEventsTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``CLIEvents.DefinedInAssemblies.Bug787438`` () = + let info = + Checker.getCompletionInfo + """let mb = new MailboxProcessor(fun _ -> ()) +mb.{caret}""" + + assertHasItemWithNames [ "Error" ] info + assertHasNoItemsWithNames [ "add_Error"; "remove_Error" ] info + +[] +let ``Event.NonStandard.PrefixMethods`` () = + let info = + Checker.getCompletionInfo + """System.AppDomain.CurrentDomain.{caret}""" + + assertHasItemWithNames [ "add_AssemblyResolve"; "remove_AssemblyResolve"; "add_ReflectionOnlyAssemblyResolve"; "remove_ReflectionOnlyAssemblyResolve"; "add_ResourceResolve"; "remove_ResourceResolve"; "add_TypeResolve"; "remove_TypeResolve" ] info + +[] +let ``Event.NonStandard.VerifyLegitimateNameShowUp`` () = + let info = + Checker.getCompletionInfo + """System.AppDomain.CurrentDomain.{caret}""" + + assertHasItemWithNames [ "AssemblyResolve"; "ReflectionOnlyAssemblyResolve"; "ResourceResolve"; "TypeResolve" ] info + +[] +let ``ReOpenNameSpace.StaticProperties`` () = + let info = + Checker.getCompletionInfo + """ + // Static properties & events + namespace A + type TestType = + static member Prop = 0 + static member Event = (new Event()).Publish + namespace B + open A + open A + TestType.{caret}""" + + assertHasItemWithNames [ "Prop"; "Event" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Exceptions.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Exceptions.fs new file mode 100644 index 00000000000..9e702dcbfc0 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Exceptions.fs @@ -0,0 +1,69 @@ +module FSharp.Compiler.Service.Tests.CompletionExceptionsTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``IncompleteStatement.Try_B`` () = + let info = + Checker.getCompletionInfo + """let x = "1" +try (x).{caret} finally ()""" + + assertHasItemWithNames [ "Contains" ] info + +[] +let ``IncompleteStatement.Try_C`` () = + let info = + Checker.getCompletionInfo + """let x = "1" +try (x).{caret} with e -> () """ + + assertHasItemWithNames [ "Contains" ] info + +[] +let ``Duplicates.Bug4103b`` () = + let source marker = + sprintf + """namespace A +module Test = + let foo n = n + 1 + let (|Pat|) x = x + 1 + exception Failed + type Del = delegate of int -> int + type A = | Foo + type B = | Bar = 0 +type TestType = + static member Prop = 0 + static member Event = (new Event<_>()).Publish +namespace B +open A +open A +%s""" + marker + + for marker, shortName, fullName in + [ "Test.", "foo", "foo" + "Test.", "Pat", "Pat" + "Test.", "Failed", "exception Failed" + "Test.", "Del", "type Del" + "Test.", "Foo", "Test.A.Foo" + "Test.B.", "Bar", "Test.B.Bar" + "TestType.", "Prop", "TestType.Prop" + "TestType.", "Event", "TestType.Event" ] do + let info = Checker.getCompletionInfo (source (marker + "{caret}")) + + assertItemDescriptionContainsExactlyOnce shortName fullName info + +[] +let ``NoDupException.Postive`` () = + let info = Checker.getCompletionInfo """let x = Match{caret}""" + + assertHasItemWithNames [ "MatchFailureException" ] info + +[] +let ``DotNetException.Negative`` () = + let info = Checker.getCompletionInfo """let x = Match{caret}""" + + assertHasNoItemsWithNames [ "MatchFailure" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Functions.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Functions.fs new file mode 100644 index 00000000000..32d20a5c257 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Functions.fs @@ -0,0 +1,200 @@ +module FSharp.Compiler.Service.Tests.CompletionFunctionsTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``DotAfterApplication1`` () = + let info = + Checker.getCompletionInfo + """let g a = new System.Random() +(g []).{caret}""" + + assertHasItemWithNames [ "Next" ] info + +[] +let ``DotAfterApplication2`` () = + let info = + Checker.getCompletionInfo + """let g a = new System.Random() +g [].{caret}""" + + assertHasItemWithNames [ "Head" ] info + +[] +let ``CurriedArguments.Regression1`` () = + let info = + Checker.getCompletionInfo + """let f{caret}ffff x y = 1 +let ggggg = 1 +let test1 = fffff "a" ggggg +let test2 = fffff 1 ggggg +let test3 = fffff ggggg ggggg""" + + assertHasItemWithNames [ "fffff" ] info + +[] +[] +[] +[] +[] +[] +let ``CurriedArguments.Regression`` (markedSource: string) (expected: string) = + let info = Checker.getCompletionInfo markedSource + + assertHasItemWithNames [ expected ] info + +[] +let ``StringFunctions`` () = + let info = + Checker.getCompletionInfo + """let y = String.{caret} +let f x = 0""" + + assertHasItemWithNames [ "collect"; "concat"; "exists" ] info + + for item in info.Items do + Assert.Equal(FSharpGlyph.Method, item.Glyph) + +[] +let ``NotShowInfo.FunctionParameter.Bug3602`` () = + let info = + Checker.getCompletionInfo + """let foo s.{caret} = s + "Hello world" + ()""" + + Assert.Equal(0, info.Items.Length) + +[] +let ``IncompleteIfClause.Bug4594`` () = + let info = + Checker.getCompletionInfo + """let Bar(xyz) = + let hello = + if x{caret}""" + + assertHasItemWithNames [ "xyz" ] info + +[] +let ``ListFunctions`` () = + let info = + Checker.getCompletionInfo + """let y = List.{caret} +let f x = 0""" + + assertHasItemWithNames [ "map"; "filter"; "fold" ] info + + for item in info.Items do + match item.NameInCode, item.Glyph with + | "Cons", FSharpGlyph.Method -> () + | "Empty", FSharpGlyph.Property -> () + | "empty", _ -> () + | _, FSharpGlyph.Method -> () + | name, glyph -> Assert.Fail(sprintf "Unexpected item %s with glyph %A" name glyph) + +[] +let ``Expression.Function`` () = + let info = + Checker.getCompletionInfo + """ + let func(mm) = 100 + func(x + y).{caret} + """ + + assertHasItemWithNames [ "CompareTo"; "ToString" ] info + +[] +[] +[] +let ``RedefinedIdentifier.DiffScope.InScope`` (item: string) (shouldBePresent: bool) = + let info = + Checker.getCompletionInfo + """ + let identifierBothScope = "" + let functionScope () = + let identifierBothScope = System.DateTime.Now + identifierBothScope.{caret} + identifierBothScope(*MarkerShowLastOneWhenOutscoped*)""" + + if shouldBePresent then + assertHasItemWithNames [ item ] info + else + assertHasNoItemsWithNames [ item ] info + +[] +let ``RedefinedIdentifier.DiffScope.OutScope.Positive`` () = + let info = + Checker.getCompletionInfo + """ + let identifierBothScope = "" + let functionScope () = + let identifierBothScope = System.DateTime.Now + identifierBothScope(*MarkerShowLastOneWhenInScope*) + identifierBothScope.{caret}""" + + assertHasItemWithNames [ "Chars" ] info + +[] +let ``Identifier.AsFunctionName.InInitial`` () = + let info = + Checker.getCompletionInfo + """let f2.{caret} x = x+1 """ + + Assert.Equal(0, info.Items.Length) + +[] +let ``Identifier.AsParameter.InInitial`` () = + let info = + Checker.getCompletionInfo + """ let f3 x.{caret} = x+1""" + + Assert.Equal(0, info.Items.Length) + +[] +let ``Basic.Completion.UnfinishedLet`` () = + let info = + Checker.getCompletionInfo + """ + let g(x) = x+1 + let f() = + let r = g(4).{caret} """ + + assertHasItemWithNames [ "CompareTo" ] info + +[] +let ``AutoComplete.Bug65730`` () = + let info = + Checker.getCompletionInfo + """let f x y = x.{caret}Equals(y)""" + + assertHasItemWithNames [ "Equals" ] info + +[] +let ``AutoComplete.Bug72596_B`` () = + let info = + Checker.getCompletionInfo + """let f() = + let foo = fo{caret}""" + + assertHasNoItemsWithNames [ "foo" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Generics.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Generics.fs new file mode 100644 index 00000000000..100036cdd22 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Generics.fs @@ -0,0 +1,174 @@ +module FSharp.Compiler.Service.Tests.CompletionGenericsTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``AfterConstructor.5039_3`` () = + let info = + Checker.getCompletionInfo + """ +System.Collections.Generic.List().{caret}""" + + assertHasItemWithNames [ "BinarySearch" ] info + +let private genericsPreamble = """ +type GT<'a> = + static member P = 12 + static member Q = 13 +type GT2 = + static member R = 12 + static member S = 13 +type D = | DD +let td = typeof +let f i = typeof +""" + +let genericsMemberCases: obj[] seq = + [ [| box "let _ = typeof.{caret}"; box [ "Assembly"; "AssemblyQualifiedName" ] |] + [| box "let _ = GT2.{caret}"; box [ "R"; "S" ] |] + [| box "let _ = GT.{caret}"; box [ "P"; "Q" ] |] ] + +[] +let ``Generics member completion`` (completionLine: string) (expected: string list) = + assertHasItemWithNames expected (Checker.getCompletionInfo (genericsPreamble + "\n" + completionLine)) + +[] +let ``GenericType.Self.Bug69673_1.01`` () = + let info = + Checker.getCompletionInfo + """ +type Base(o:obj) = class end +type Foo() as this = + inherit Base(th{caret}is) // this + let o = this // this ok + do this.Bar() // this ok, dotting ok + member this.Bar() = ()""" + + assertHasItemWithNames [ "this" ] info + +[] +[] +[] +let ``GenericType.Self.Bug69673_1.CtrlSpaceForThis`` (markedSource: string) = + let info = Checker.getCompletionInfo markedSource + assertHasItemWithNames [ "this" ] info + +[] +let ``GenericType.Self.Bug69673_1.04`` () = + let info = + Checker.getCompletionInfo + """ +type Base(o:obj) = class end +type Foo() as this = + inherit Base(this) // this + let o = this // this ok + do this.{caret}Bar() // this ok, dotting ok + member this.Bar() = ()""" + + assertHasItemWithNames [ "Bar" ] info + +[] +let ``GenericType.Self.Bug69673_2.1`` () = + let info = + Checker.getCompletionInfo + """ +type Base(o:obj) = class end +type Food() as this = + class + inherit Base(th{caret}is) // this + do + this |> ignore // this (only repros with explicit class/end) + end""" + + assertHasItemWithNames [ "this" ] info + +[] +let ``GenericType.Self.Bug69673_2.2`` () = + let info = + Checker.getCompletionInfo + """ +type Base(o:obj) = class end +type Food() as this = + class + inherit Base(this) // this + do + th{caret}is |> ignore // this (only repros with explicit class/end) + end""" + + assertHasItemWithNames [ "this" ] info + +[] +let ``AfterTypeParameter`` () = + let info1 = + Checker.getCompletionInfo + """ + + type Type1 = Tag of string.{caret} + + let f x:int -> string(*MarkerParamFunction*) + + let Type2<'a(*MarkerGenericParam*)> = 1 + + let type1 = typeof + """ + + Assert.Equal(0, info1.Items.Length) + + let info2 = + Checker.getCompletionInfo + """ + + type Type1 = Tag of string(*MarkerDUTypeParam*) + + let f x:int -> string.{caret} + + let Type2<'a(*MarkerGenericParam*)> = 1 + + let type1 = typeof + """ + + Assert.Equal(0, info2.Items.Length) + + let info3 = + Checker.getCompletionInfo + """ + + type Type1 = Tag of string(*MarkerDUTypeParam*) + + let f x:int -> string(*MarkerParamFunction*) + + let Type2<'a.{caret}> = 1 + + let type1 = typeof + """ + + Assert.Equal(0, info3.Items.Length) + + let info4 = + Checker.getCompletionInfo + """ + + type Type1 = Tag of string(*MarkerDUTypeParam*) + + let f x:int -> string(*MarkerParamFunction*) + + let Type2<'a(*MarkerGenericParam*)> = 1 + + let type1 = typeof + """ + + Assert.Equal(0, info4.Items.Length) diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.IndexingSlicing.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.IndexingSlicing.fs new file mode 100644 index 00000000000..f98464b92f1 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.IndexingSlicing.fs @@ -0,0 +1,189 @@ +module FSharp.Compiler.Service.Tests.CompletionIndexingSlicingTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +let ``AdjacentToDot.Positive`` (op: string) = + let info = Checker.getCompletionInfo (markAtEndOfMarker ("System.Console" + op) "System.Console.") + assertHasItemWithNames [ "BackgroundColor" ] info + +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +let ``AdjacentToDot.Negative`` (op: string) = + let info = Checker.getCompletionInfo ("System.Console" + op + "{caret}") + assertHasItemWithNames [ "abs" ] info + assertHasNoItemsWithNames [ "BackgroundColor" ] info + +[] +let ``DotOff.Parenthesized.Expr`` () = + let info = + Checker.getCompletionInfo + """let string_of_int (x:int) = x.ToString() +let strs = Array.init 10 string_of_int +let x = (strs.[1]).{caret}""" + + assertHasItemWithNames [ "Substring"; "GetHashCode" ] info + +[] +let ``DotOff.ArrayIndexerNotation`` () = + let info = + Checker.getCompletionInfo + """let string_of_int (x:int) = x.ToString() +let strs = Array.init 10 string_of_int +let test1 = strs.[1].{caret}""" + + assertHasItemWithNames [ "Substring"; "GetHashCode" ] info + +[] +[] +[] +[] +let ``DotOff.ArraySliceNotation`` (source: string) = + let info = Checker.getCompletionInfo source + + assertHasItemWithNames [ "Length" ] info + +[] +let ``DotOff.DictionaryIndexer`` () = + let info = + Checker.getCompletionInfo + """let dict = new System.Collections.Generic.Dictionary() +let test5 = dict.[1].{caret}""" + + assertHasItemWithNames [ "Length" ] info + +[] +let ``Identifier.FuzzyDefined.Bug67133`` () = + let info = + Checker.getCompletionInfo + """let gDateTime (arr: System.DateTime[]) = + arr.[0].{caret}""" + + assertHasItemWithNames [ "AddDays" ] info + +[] +let ``Identifier.FuzzyDefined.Bug67133.Negative`` () = + let info = + Checker.getCompletionInfo + """let gDateTime (arr: DateTime[]) = + arr.[0].{caret}""" + + Assert.Equal(0, info.Items.Length) + +[] +let ``Type.Indexers.Bug4898_1`` () = + let info = + Checker.getCompletionInfo + """type Foo(len) = + member this.Value = [1 .. len] +type Bar = + static member ParamProp with get len = new Foo(len) +let n = Bar.ParamProp.{caret}""" + + assertHasItemWithNames [ "ToString" ] info + assertHasNoItemsWithNames [ "Value" ] info + +[] +let ``Type.Indexers.Bug4898_2`` () = + let info = + Checker.getCompletionInfo + """type mytype() = + let instanceArray2 = [|[| "A"; "B" |]; [| "A"; "B" |] |] + let instanceArray = [| "A"; "B" |] + member x.InstanceIndexer + with get(idx) = instanceArray.[idx] + member x.InstanceIndexer2 + with get(idx1,idx2) = instanceArray2.[idx1].[idx2] +let a = mytype() +a.InstanceIndexer2.{caret}""" + + assertHasItemWithNames [ "ToString" ] info + assertHasNoItemsWithNames [ "Chars" ] info + +[] +let ``Expression.ListItem`` () = + let info = + Checker.getCompletionInfo + """ + let a = [1;2;3] + a.[1].{caret} + """ + + assertHasItemWithNames [ "CompareTo"; "ToString" ] info + +[] +let ``Expression.2DArray`` () = + let info = + Checker.getCompletionInfo + """ + let (a2: int[,]) = Array2.zero_create 10 10 + a2.[1,2].{caret} + """ + + assertHasItemWithNames [ "ToString" ] info + +[] +[] +[] +let ``Expression.ArrayItem`` (names: string, shouldContain: bool) = + let info = + Checker.getCompletionInfo + """ + //regression test for bug 1001 + let str1 = Array.init 10 string + str1.[1].{caret}""" + + let names = names.Split(';') |> List.ofArray + + assertItemsWithNames shouldContain names info + +[] +let ``Identifier.In#Statement`` () = + let info = + Checker.getCompletionInfo + """ + # 29 "original-test-file.fs" + let argv = System.Environment.GetCommandLineArgs() + let SetCulture() = + if argv.{caret}Length > 2 && argv.[1] = "--culture" then + let cultureString = argv.[2] + """ + + assertHasItemWithNames [ "Length"; "Clone"; "ToString" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Interfaces.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Interfaces.fs new file mode 100644 index 00000000000..62034bf6cd4 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Interfaces.fs @@ -0,0 +1,30 @@ +module FSharp.Compiler.Service.Tests.CompletionInterfacesTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``Completion.DetectInterfaces`` () = + let info1 = + Checker.getCompletionInfo + """type X = interface + inherit {caret}""" + + assertHasItemWithNames [ "seq" ] info1 + + let info2 = + Checker.getCompletionInfo + """[] +type X = + inherit {caret}""" + + assertHasItemWithNames [ "seq" ] info2 + + let info3 = + Checker.getCompletionInfo + """[] +type X = interface + inherit {caret}""" + + assertHasItemWithNames [ "seq" ] info3 diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Lambdas.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Lambdas.fs new file mode 100644 index 00000000000..0a0d3a9a3be --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Lambdas.fs @@ -0,0 +1,88 @@ +module FSharp.Compiler.Service.Tests.CompletionLambdasTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``DotCompletionInBrokenLambda`` () = + let info = + Checker.getCompletionInfo + """1 |> id (fun x .{caret}> x)""" + + Assert.Equal(0, info.Items.Length) + +[] +[ id (fun) +let x = 1 +x.{caret}""")>] // error prepended: 1 |> id (fun) +[ id (fun)""")>] // error appended: 1 |> id (fun) +[ id (fun x > x) +let x = 1 +x.{caret}""")>] // error prepended: 1 |> id (fun x > x) +[ id (fun x > x)""")>] // error appended: 1 |> id (fun x > x) +[ id (fun x > ) +let x = 1 +x.{caret}""")>] // error prepended: 1 |> id (fun x > ) +[ id (fun x > )""")>] // error appended: 1 |> id (fun x > ) +[ id (fun x -> ) +let x = 1 +x.{caret}""")>] // error prepended: 1 |> id (fun x -> ) +[ id (fun x -> )""")>] // error appended: 1 |> id (fun x -> ) +let ``DotCompletionWithBrokenLambda`` (markedSource: string) = + let info = Checker.getCompletionInfo markedSource + + assertHasItemWithNames [ "CompareTo" ] info + assertHasNoItemsWithNames [ "Array" ] info + +[] +let ``LambdaExpression.WithoutClosing.Bug1346c`` () = + let info = + Checker.getCompletionInfo + """let p4 = + let isPalindrome x = + let chars = (string_of_int x).ToCharArray() + let len = chars.{caret} + chars + |> Array.mapi (fun i c -> )""" + + assertHasItemWithNames [ "Length" ] info + +[] +let ``Identifier.InLambdaExpression`` () = + let info = + Checker.getCompletionInfo + """let funcLambdaExp = fun (x:int)-> x.{caret}""" + + assertHasItemWithNames [ "ToString"; "Equals" ] info + +[] +let ``Identifier.AsFunctionName.UsingFunKeyword`` () = + let info = + Checker.getCompletionInfo + """fun f4.{caret} x -> x+1""" + + Assert.Equal(0, info.Items.Length) + +[] +let ``AutoComplete.Bug69654_0`` () = + let info = + Checker.getCompletionInfo + """ +let q = + let a = 42 + let b = (fun i -> i) 43 + // i shows up in Ctrl-space list here, b does not + ({caret}) // but in the parens, things are correct again +""" + + assertHasItemWithNames [ "b" ] info + assertHasNoItemsWithNames [ "i" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.LetBindings.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.LetBindings.fs new file mode 100644 index 00000000000..501ae5315df --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.LetBindings.fs @@ -0,0 +1,114 @@ +module FSharp.Compiler.Service.Tests.CompletionLetBindingsTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``CtrlSpaceCompletion.Bug130670.Case2`` () = + let info = + Checker.getCompletionInfo + """ +let x = 42 +let r = x + 1 {caret}""" + + assertHasItemWithNames [ "AbstractClassAttribute" ] info + assertHasNoItemsWithNames [ "CompareTo" ] info + +[] +let ``InComment`` () = + let info = Checker.getCompletionInfo """ let s = "System.C{caret}" """ + + Assert.Equal(0, info.Items.Length) + +[] +let ``TopLevelIdentifier.AfterPartialToken1`` () = + let info = + Checker.getCompletionInfo + """let foobaz = 1 +(*marker*)fo{caret}""" + + assertHasItemWithNames [ "System"; "Array2D"; "foobaz" ] info + assertHasNoItemsWithNames [ "Int32" ] info + +[] +let ``TopLevelIdentifier.AfterPartialToken2`` () = + let info = + Checker.getCompletionInfo + """let foobaz = 1 +{caret}fo""" + + assertHasItemWithNames [ "System"; "Array2D"; "foobaz" ] info + +[] +let ``NonDotCompletion`` () = + let info = Checker.getCompletionInfo "let x = S{caret}" + + assertHasItemWithNames [ "Some" ] info + +[] +[] +[] +[] +[] +let ``Residues`` (source: string) = + let info = Checker.getCompletionInfo source + + assertHasItemWithNames [ "CompareTo" ] info + assertHasNoItemsWithNames [ "CLIEventAttribute"; "Checked"; "Choice" ] info + +[] +let ``CompletionInDifferentEnvs2`` () = + let info = + Checker.getCompletionInfo + """let aaa = 1 +let aab = 2 +(aa{caret} +let aac = 3""" + + assertHasItemWithNames [ "aaa"; "aab" ] info + assertHasNoItemsWithNames [ "aac" ] info + +[] +let ``Selection`` () = + let info = + Checker.getCompletionInfo + """ +let preSelectedItem = 1 +let r = (*MarkerPreSelectedItem*)pre{caret}""" + + assertHasItemWithNames [ "preSelectedItem" ] info + +[] +let ``CompListInDiffFileTypes`` () = + let sigInfo = + Checker.getCompletionInfoOfSignatureFile + """ +val x:int = 1 +x.{caret}""" + + Assert.Equal(0, sigInfo.Items.Length) + + let info = + Checker.getCompletionInfo + """ +let i = 1 +i.{caret}""" + + assertHasItemWithNames [ "CompareTo"; "Equals" ] info + +[] +let ``Keywords.Let`` () = + let info = Checker.getCompletionInfo "let.{caret} a = 1" + + Assert.Equal(0, info.Items.Length) + +[] +let ``Expression.InString`` () = + let info = Checker.getCompletionInfo """let x = "System.Console.{caret}" """ + + Assert.Equal(0, info.Items.Length) diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Literals.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Literals.fs new file mode 100644 index 00000000000..a224ef10cab --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Literals.fs @@ -0,0 +1,43 @@ +module FSharp.Compiler.Service.Tests.CompletionLiteralsTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``Literal.809979`` () = + let info = + Checker.getCompletionInfo """let value=uint64.{caret}""" + + assertHasNoItemsWithNames [ "Parse" ] info + +[] +let ``CharLiteral`` () = + let info = + Checker.getCompletionInfo + """let x = "foo" +let x' = "bar" +x'.{caret}""" + + assertHasItemWithNames [ "CompareTo"; "GetHashCode" ] info + +[] +let ``Literal.Float`` () = + let info = + Checker.getCompletionInfo """let myfloat = (42.0).{caret}""" + + assertHasItemWithNames [ "GetType"; "ToString" ] info + +[] +let ``Literal.String`` () = + let info = + Checker.getCompletionInfo """let name = "foo".{caret}""" + + assertHasItemWithNames [ "Chars"; "Clone" ] info + +[] +let ``Literal.Int`` () = + let info = + Checker.getCompletionInfo """let typeint = (10).{caret}""" + + assertHasItemWithNames [ "GetType"; "ToString" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Members.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Members.fs new file mode 100644 index 00000000000..93e7dfb6900 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Members.fs @@ -0,0 +1,361 @@ +module FSharp.Compiler.Service.Tests.CompletionMembersTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +let globalMemberCases: obj[] seq = + [ [| "Basic"; "\nlet x = 1\nx.{caret}" |] + [| "EndingWithTick"; "\nlet x' = 1\nx'.{caret}" |] + [| "PartialMember2"; "\nlet x = 1\nx.{caret}CompareT" |] + [| "ContainingTick"; "\nlet x'y = 1\nx'y.{caret}" |] + [| "PartialMember1"; "\nlet x = 1\nx.CompareT{caret}" |] ] + +[] +let ``GlobalMember completion lists CompareTo and GetHashCode`` (caseName: string) (source: string) = + assertHasItemWithNames [ "CompareTo"; "GetHashCode" ] (Checker.getCompletionInfo source) + +[] +[] +[")>] +[] +[] +[] +[] +let ``AdjacentToDot positive`` (source: string) = + let info = Checker.getCompletionInfo source + + assertHasItemWithNames [ "BackgroundColor" ] info + +[] +[] +[{caret}")>] +[] +[] +[] +[] +[] +let ``AdjacentToDot negative`` (source: string) = + let info = Checker.getCompletionInfo source + + assertHasItemWithNames [ "abs" ] info + assertHasNoItemsWithNames [ "BackgroundColor" ] info + +[] +let ``CtrlSpaceCompletion.Bug130670.Case1`` () = + let info = Checker.getCompletionInfo "let i = async.Return(4){caret}" + + assertHasItemWithNames [ "AbstractClassAttribute" ] info + assertHasNoItemsWithNames [ "GetType" ] info + +[] +let ``InString`` () = + let info = Checker.getCompletionInfo " // System.C{caret} " + + Assert.Equal(0, info.Items.Length) + +[] +let ``EmptyFile.Dot.Bug1115`` () = + let info = Checker.getCompletionInfo ".{caret}" + + Assert.Equal(0, info.Items.Length) + +[] +let ``Project.FsFileWithBuildAction`` () = + let info = + Checker.getCompletionInfo + """ +let i = 4 +let r = i.{caret}ToString() +let x = File1.bob""" + + assertHasItemWithNames [ "CompareTo" ] info + +[] +let ``DotOff.String`` () = + let info = + Checker.getCompletionInfo + """ +"x".{caret} (*marker*) +""" + + assertHasItemWithNames [ "Substring"; "GetHashCode" ] info + +[] +let ``Bug243082.DotAfterNewBreaksCompletion2`` () = + let info = + Checker.getCompletionInfo + """ +let s = 1 +s.{caret} +new System.""" + + assertHasItemWithNames [ "CompareTo"; "ToString" ] info + +[] +let ``NotShowInfo.LetBinding.Bug3602`` () = + let info = + Checker.getCompletionInfo + """ +let s.{caret} = "Hello world" + ()""" + + Assert.Equal(0, info.Items.Length) + +[] +let ``HandleInlineComments1`` () = + let info = + Checker.getCompletionInfo "let rrr = System (* boo! *) .{caret} Int32 . MaxValue" + + assertHasItemWithNames [ "Int32" ] info + assertHasNoItemsWithNames [ "abs" ] info + +[] +let ``HandleInlineComments2`` () = + let info = + Checker.getCompletionInfo "let rrr = System (* boo! *) . Int32 .{caret} MaxValue" + + assertHasItemWithNames [ "MaxValue" ] info + assertHasNoItemsWithNames [ "abs" ] info + +[] +let ``Expression.MultiLine.Bug66705`` () = + let info = + Checker.getCompletionInfo + """ +let x = 4 +let y = x.GetType() + .{caret}ToString()""" + + assertHasItemWithNames [ "ToString" ] info + +[] +[] +[] +[] +[] +let ``IncompleteStatement`` (source: string) = + let info = Checker.getCompletionInfo source + + assertHasItemWithNames [ "Contains" ] info + +[] +let ``WithNonExistentDll`` () = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| @"-r:..\bar\nonexistent.dll" |] + FSharpCodeCompletionOptions.Default + "(*marker*) {caret} " + + assertHasItemWithNames [ "System"; "Array2D" ] info + assertHasNoItemsWithNames [ "Int32" ] info + +[] +let ``FlagsAndSettings.Bug1969`` () = + let info = + Checker.getCompletionInfo + """ +let y = System.Deployment.Application.{caret} +()""" + + Assert.Equal(0, info.Items.Length) + +[] +let ``OfSystemWindows`` () = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| "-r:System.Windows.Forms.dll" |] + FSharpCodeCompletionOptions.Default + "let y=new System.Windows.{caret}" + + Assert.Equal(3, info.Items.Length) + +[] +let ``Editor.WithoutContext.Bug986`` () = + let info = Checker.getCompletionInfo "{caret}" + + assertHasNoItemsWithNames [ "IChapteredRowset"; "ICorRuntimeHost" ] info + +[] +let ``LetBind.TopLevel.Bug1650`` () = + let info = Checker.getCompletionInfo "let x = {caret}" + + assertHasItemWithNames [ "System" ] info + +[] +let ``PrimTypeAndFunc`` () = + let info1 = + Checker.getCompletionInfo + """ +System.Int32.{caret} +int. """ + + assertHasItemWithNames [ "MinValue" ] info1 + + let info2 = + Checker.getCompletionInfo + """ +System.Int32. +int.{caret} """ + + assertHasNoItemsWithNames [ "MinValue" ] info2 + +[] +let ``ThirdLevelOfDotting`` () = + let info = Checker.getCompletionInfo "let x = System.Console.Wr{caret}" + + assertHasItemWithNames [ "BackgroundColor"; "CancelKeyPress" ] info + + for item in info.Items do + match item.NameInCode with + | "BackgroundColor" -> Assert.Equal(CompletionItemKind.Property, item.Kind) + | "CancelKeyPress" -> Assert.Equal(CompletionItemKind.Event, item.Kind) + | _ -> () + +[] +let ``Expression.WithoutPreDefinedMethods`` () = + let info = + Checker.getCompletionInfo + """ + let x = F{caret}""" + + assertHasNoItemsWithNames [ "FSharpDelegateEvent"; "PrivateMethod"; "PrivateType" ] info + +[] +let ``CaseInsensitive.MapMethod`` () = + let info = + Checker.getCompletionInfo + """ + List.MaP{caret} + """ + + assertHasItemWithNames [ "map" ] info + +[] +let ``SimpleTypes.SystemTime`` () = + let info = + Checker.getCompletionInfo + """ + let typestruct = System.DateTime.Now + typestruct.{caret}""" + + assertHasItemWithNames [ "AddDays"; "Date" ] info + +[] +[] +[] +[] +[] +let ``MacroDirectives`` (source: string) = + let info = Checker.getCompletionInfo source + + Assert.Equal(0, info.Items.Length) + +[] +let ``Identifier.This`` () = + let info = + Checker.getCompletionInfo + """ + type Type1 = + member this.{caret}.Foo () = 3""" + + Assert.Equal(0, info.Items.Length) + +[] +let ``Regression4702.SystemWord`` () = + let info = Checker.getCompletionInfo "System.{caret}" + + assertHasItemWithNames [ "Console"; "Byte"; "ArgumentException" ] info + +[] +let ``ExpressionDotting.Regression.Bug3709`` () = + let info = + Checker.getCompletionInfo + """ + let foo = "" + let foo = foo.E{caret}n "a" """ + + assertHasItemWithNames [ "EndsWith" ] info + +[] +let ``ExpressionDotting.Regression.Bug187799.Test2`` () = + let info = + Checker.getCompletionInfo + """ + type T() = + member _.M() = [|1..2|] + type R = { P : T } + // dotting through an F# record field + let r = { P = T() } + r.P.M().{caret} """ + + assertHasItemWithNames [ "Clone" ] info + +[] +let ``ExpressionDotting.Regression.Bug187799.Test3`` () = + let info = + Checker.getCompletionInfo + """ + type R = { P : System.Reflection.InterfaceMapping } + // Dotting through an F# record field and an IL record field + // Note that InterfaceMapping is a rare example of a public .NET instance field in mscorlib + let r = { P = Unchecked.defaultof } + r.P.{caret}""" + + assertHasItemWithNames [ "InterfaceMethods" ] info + +[] +let ``ExpressionDotting.Regression.Bug187799.Test4`` () = + let info = + Checker.getCompletionInfo + """ + type R = { P : System.Reflection.InterfaceMapping } + // Dotting through an F# record field and an IL record field + // Note that InterfaceMapping is a rare example of a public .NET instance field in mscorlib + let f() = { P = Unchecked.defaultof } + f().P.{caret}""" + + assertHasItemWithNames [ "InterfaceMethods" ] info + +[] +let ``ExpressionDotting.Regression.Bug187799.Test5`` () = + let info = + Checker.getCompletionInfo + """ + type R = { P : System.Reflection.InterfaceMapping } + // Note that InterfaceMapping is a rare example of a public .NET instance field in mscorlib + let f() = { P = Unchecked.defaultof } + f().P.InterfaceMethods.{caret}""" + + assertHasItemWithNames [ "GetEnumerator" ] info + +[] +[] +[] +let ``ExpressionDotting.Regression.Bug187799.Test6`` (markedSource: string, expected: string) = + let info = Checker.getCompletionInfo markedSource + assertHasItemWithNames [ expected ] info + +[] +let ``Fsx.Bug2530FsiObject`` () = + let info = Checker.getCompletionInfo "fsi.{caret}" + + assertHasItemWithNames [ "CommandLineArgs" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Modules.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Modules.fs new file mode 100644 index 00000000000..d949c13606e --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Modules.fs @@ -0,0 +1,102 @@ +module FSharp.Compiler.Service.Tests.CompletionModulesTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``String.BeforeIncompleteModuleDefinition.Bug2385`` () = + let info = + Checker.getCompletionInfo + """let s = "hello".{caret} +module Timer =""" + + assertHasItemWithNames [ "Substring"; "GetHashCode" ] info + +[] +let ``Identifier.DefineByVal.InFsiFile.Bug882304_1`` () = + let info = + Checker.getCompletionInfoOfSignatureFile + """module BasicTest +val z:int = 1 +z.{caret}""" + + assertHasNoItemsWithNames [ "Equals" ] info + +[] +let ``ShowSetAsModuleAndType`` () = + let info = Checker.getCompletionInfo "let s = Set{caret}" + + let tip = flattenItemDescription (findCompletionItem "Set" info).Description + Assert.Contains("module Set", tip) + Assert.Contains("type Set", tip) + +[] +let ``Expression.WithPreDefinedMethods`` () = + let info = + Checker.getCompletionInfo + """ + module Module1 = + let private PrivateField = 1 + let private PrivateMethod x = + x+1 + type private PrivateType() = + member this.mem = 1 + let a = {caret} + + let b = 23 + """ + + assertHasItemWithNames [ "PrivateField"; "PrivateMethod"; "PrivateType" ] info + +[] +let ``Identifier.AsModule`` () = + let info = Checker.getCompletionInfo "module Module1.{caret}" + + Assert.Equal(0, info.Items.Length) + +[] +let ``TypeAbbreviation.Positive`` () = + let info = + Checker.getCompletionInfo + """ + module BasicTest + + Microsoft.FSharp.Core.{caret}""" + + assertHasItemWithNames [ "int16"; "int32"; "int64" ] info + +[] +let ``TypeAbbreviation.Negative`` () = + let info = + Checker.getCompletionInfo + """ + module BasicTest + + Microsoft.FSharp.Core.{caret}""" + + assertHasNoItemsWithNames [ "Int16"; "Int32"; "Int64" ] info + +[] +let ``Verify no completion on dot after module definition`` () = + let info = + Checker.getCompletionInfo + """ + module BasicTest.{caret} + + let foo x = x + let bar = 1""" + + Assert.Equal(0, info.Items.Length) + +[] +let ``Verify no completion after module definition`` () = + let info = + Checker.getCompletionInfo + """ + module BasicTest {caret} + + let foo x = x + let bar = 1""" + + Assert.Equal(0, info.Items.Length) diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Mutability.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Mutability.fs new file mode 100644 index 00000000000..0582e8a578b --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Mutability.fs @@ -0,0 +1,61 @@ +module FSharp.Compiler.Service.Tests.CompletionMutabilityTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``AdjacentToDot_20`` () = + let info = Checker.getCompletionInfo "System.Console.{caret}()<-" + + assertHasItemWithNames [ "BackgroundColor" ] info + +[] +let ``AdjacentToDot_20_Negative`` () = + let info = Checker.getCompletionInfo "System.Console.()<-{caret}" + + assertHasItemWithNames [ "abs" ] info + assertHasNoItemsWithNames [ "BackgroundColor" ] info + +let private obsoletePreamble = """[] +module ObsoleteTop = + let T = "T" +module Module = + [] + module ObsoleteM = + let A = "A" + [] + module ObsoleteNested = + let C = "C" + [] + type ObsoleteT = + static member B = "B" + let Other = 0 +let mutable level = "" + +""" + +let obsoleteCases: obj[] seq = + [ + [| box "level <- O{caret}"; box [ "None" ]; box [ "ObsoleteTop"; "Chars" ] |] + [| box "level <- Module.{caret}"; box [ "Other" ]; box [ "ObsoleteM"; "ObsoleteT"; "Chars" ] |] + [| box "level <- Module.ObsoleteM.{caret}"; box [ "A" ]; box [ "ObsoleteNested"; "Chars" ] |] + [| box "level <- Module.ObsoleteM.ObsoleteNested.{caret}"; box [ "C" ]; box [ "Chars" ] |] + [| box "level <- Module.ObsoleteT.{caret}"; box [ "B" ]; box [ "Chars" ] |] + ] + +[] +let ``Obsolete.completion`` (completionLine: string) (included: string list) (excluded: string list) = + let info = Checker.getCompletionInfo (obsoletePreamble + completionLine) + assertHasItemWithNames included info + assertHasNoItemsWithNames excluded info + +[] +let ``Identifier.InClass.WithoutDef`` () = + let info = + Checker.getCompletionInfo + """ + type Type2 = + val mutable x.{caret} : string""" + + Assert.Equal(0, info.Items.Length) diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.MutuallyRecursive.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.MutuallyRecursive.fs new file mode 100644 index 00000000000..cdf9ef3ba73 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.MutuallyRecursive.fs @@ -0,0 +1,25 @@ +module FSharp.Compiler.Service.Tests.CompletionMutuallyRecursiveTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``ProtectedMembers.SelfOrDerivedClass`` () = + let info1 = + Checker.getCompletionInfo + """type T() = + inherit exn() + member this.Run(x : T) = x.{caret}""" + + assertHasItemWithNames [ "Message"; "HResult" ] info1 + + let info2 = + Checker.getCompletionInfo + """type T() = + inherit exn() + member this.Run(x : Z) = x.{caret} +and Z() = + inherit T()""" + + assertHasItemWithNames [ "Message"; "HResult" ] info2 diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Namespaces.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Namespaces.fs new file mode 100644 index 00000000000..23da9f8e443 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Namespaces.fs @@ -0,0 +1,99 @@ +module FSharp.Compiler.Service.Tests.CompletionNamespacesTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``List.AfterAddLinqNamespace.Bug3754`` () = + let info = + Checker.getCompletionInfo + """open System.Xml.Linq +List.{caret}""" + + assertHasItemWithNames [ "map"; "filter" ] info + +[] +let ``Global`` () = + let info = Checker.getCompletionInfo "global.{caret}" + + assertHasItemWithNames [ "System"; "Microsoft" ] info + +[] +let ``Identifier.NonDottedNamespace.Bug1347`` () = + let info = + Checker.getCompletionInfo + """open System +let x = Mic{caret} +let p7 = + let sieve limit = + let isPrime = Array.create (limit+1) true + for n in""" + + assertHasItemWithNames [ "Microsoft" ] info + +[] +let ``OpenNamespaceOrModule.CompletionOnlyContainsNamespaceOrModule.Case2`` () = + let info = Checker.getCompletionInfo "open Microsoft.FSharp.Collections.Array.{caret}" + + assertHasItemWithNames [ "Parallel" ] info + assertHasNoItemsWithNames [ "map" ] info + +[] +let ``AtNamespaceDot`` () = + let info = Checker.getCompletionInfo "let y=new System.{caret}String()" + + assertHasItemWithNames [ "String"; "Console" ] info + +[] +let ``SystemNamespace`` () = + let info = Checker.getCompletionInfo "let y = System.{caret}" + + assertHasItemWithNames [ "Action"; "Collections" ] info + + assertItemGlyph "Action" FSharpGlyph.Delegate info + assertItemGlyph "Collections" FSharpGlyph.NameSpace info + +[] +let ``WithoutOpenNamespace`` () = + let info = + Checker.getCompletionInfo + """ +module CodeAccessibility +let x = S{caret}""" + + assertHasNoItemsWithNames [ "Single" ] info + +[] +let ``Namespace.System`` () = + let info = + Checker.getCompletionInfo + """ +// Test '.' after System +open System.{caret} +let str = "a string" +// Test '.' after str +let _ = str(*usage*)""" + + assertHasItemWithNames [ "IO"; "Collections" ] info + +[] +let ``Identifier.AsNamespace`` () = + let info = Checker.getCompletionInfo "namespace Namespace1.{caret}" + + Assert.Equal(0, info.Items.Length) + +[] +let ``ReopenNamespace.Module`` () = + let info = + Checker.getCompletionInfo + """ +namespace A +module Test = + let foo n = n + 1 +namespace B +open A +open A +Test.{caret}""" + + assertHasItemWithNames [ "foo" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.ObjectExpressions.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.ObjectExpressions.fs new file mode 100644 index 00000000000..2594cc909ed --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.ObjectExpressions.fs @@ -0,0 +1,27 @@ +module FSharp.Compiler.Service.Tests.CompletionObjectExpressionsTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``ObjInstance.AnonymousClass.MethodsDefInInterface`` () = + let info = + Checker.getCompletionInfo + """ + type IFoo = + abstract DoStuff : unit -> string + abstract DoStuff2 : int * int -> string -> string + // Implement an interface in a class (This is kind of lame if you don't want to actually declare a class) + type Foo() = + interface IFoo with + member this.DoStuff () = "Return a string" + member this.DoStuff2 (x, y) z = sprintf "Arguments were (%d, %d) %s" x y z + // instanceOfIFoo is an instance of an anonymous class which implements IFoo + let instanceOfIFoo = { + new IFoo with + member this.DoStuff () = "Implement IFoo" + member this.DoStuff2 (x, y) z = sprintf "Arguments were (%d, %d) %s" x y z + }.{caret}""" + + assertHasItemWithNames [ "DoStuff"; "DoStuff2" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.ObjectInitializers.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.ObjectInitializers.fs new file mode 100644 index 00000000000..b8fd3c661d9 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.ObjectInitializers.fs @@ -0,0 +1,148 @@ +module FSharp.Compiler.Service.Tests.CompletionObjectInitializersTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +let private propPlain = """ +type A() = + member val SettableProperty = 1 with get,set + member val AnotherSettableProperty = 1 with get,set + member val NonSettableProperty = 1 +""" + +let private propGeneric = """ +type A<'a>() = + member val SettableProperty = 1 with get,set + member val AnotherSettableProperty = 1 with get,set + member val NonSettableProperty = 1 +""" + +let private propModule = """ +module M = + type A() = + member val SettableProperty = 1 with get,set + member val AnotherSettableProperty = 1 with get,set + member val NonSettableProperty = 1 +""" + +let private propModuleGeneric = """ +module M = + type A<'a, 'b>() = + member val SettableProperty = 1 with get,set + member val AnotherSettableProperty = 1 with get,set + member val NonSettableProperty = 1 +""" + +let propertyCases: obj[] seq = + [ + [| box (propPlain + "A((**){caret})"); box [ "SettableProperty"; "AnotherSettableProperty" ]; box [ "NonSettableProperty" ] |] + [| box (propPlain + "A(S{caret} = 1)"); box [ "SettableProperty" ]; box [ "NonSettableProperty" ] |] + [| box (propPlain + "A(S = 1{caret})"); box ([]: string list); box [ "SettableProperty"; "NonSettableProperty" ] |] + [| box (propPlain + "A(S = 1,{caret})"); box [ "AnotherSettableProperty" ]; box [ "NonSettableProperty" ] |] + [| box (propPlain + "new A((**){caret})"); box [ "SettableProperty"; "AnotherSettableProperty" ]; box [ "NonSettableProperty" ] |] + [| box (propPlain + "new A(S{caret} = 1)"); box [ "SettableProperty" ]; box [ "NonSettableProperty" ] |] + [| box (propPlain + "new A(S = 1{caret})"); box ([]: string list); box [ "SettableProperty"; "NonSettableProperty" ] |] + [| box (propPlain + "new A(S = 1,{caret})"); box [ "AnotherSettableProperty" ]; box [ "NonSettableProperty" ] |] + + [| box (propGeneric + "A((**){caret})"); box [ "SettableProperty"; "AnotherSettableProperty" ]; box [ "NonSettableProperty" ] |] + [| box (propGeneric + "A(S{caret} = 1)"); box [ "SettableProperty" ]; box [ "NonSettableProperty" ] |] + [| box (propGeneric + "A(S = 1{caret})"); box ([]: string list); box [ "SettableProperty"; "NonSettableProperty" ] |] + [| box (propGeneric + "A(S = 1,{caret})"); box [ "AnotherSettableProperty" ]; box [ "NonSettableProperty" ] |] + [| box (propGeneric + "new A<_>((**){caret})"); box [ "SettableProperty"; "AnotherSettableProperty" ]; box [ "NonSettableProperty" ] |] + [| box (propGeneric + "new A<_>(S{caret} = 1)"); box [ "SettableProperty" ]; box [ "NonSettableProperty" ] |] + [| box (propGeneric + "new A<_>(S = 1{caret})"); box ([]: string list); box [ "SettableProperty"; "NonSettableProperty" ] |] + [| box (propGeneric + "new A<_>(S = 1,{caret})"); box [ "AnotherSettableProperty" ]; box [ "NonSettableProperty" ] |] + + [| box (propModule + "M.A((**){caret})"); box [ "SettableProperty"; "AnotherSettableProperty" ]; box [ "NonSettableProperty" ] |] + [| box (propModule + "M.A(S{caret} = 1)"); box [ "SettableProperty" ]; box [ "NonSettableProperty" ] |] + [| box (propModule + "M.A(S = 1{caret})"); box ([]: string list); box [ "NonSettableProperty"; "SettableProperty" ] |] + [| box (propModule + "M.A(S = 1,{caret})"); box [ "AnotherSettableProperty" ]; box [ "NonSettableProperty" ] |] + [| box (propModule + "new M.A((**){caret})"); box [ "SettableProperty"; "AnotherSettableProperty" ]; box [ "NonSettableProperty" ] |] + [| box (propModule + "new M.A(S{caret} = 1)"); box [ "SettableProperty" ]; box [ "NonSettableProperty" ] |] + [| box (propModule + "new M.A(S = 1{caret})"); box ([]: string list); box [ "NonSettableProperty"; "SettableProperty" ] |] + + [| box (propModuleGeneric + "M.A((**){caret})"); box [ "SettableProperty"; "AnotherSettableProperty" ]; box [ "NonSettableProperty" ] |] + [| box (propModuleGeneric + "M.A(S{caret} = 1)"); box [ "SettableProperty" ]; box [ "NonSettableProperty" ] |] + [| box (propModuleGeneric + "M.A(S = 1{caret})"); box ([]: string list); box [ "SettableProperty"; "NonSettableProperty" ] |] + [| box (propModuleGeneric + "M.A(S = 1,{caret})"); box [ "AnotherSettableProperty" ]; box [ "NonSettableProperty" ] |] + [| box (propModuleGeneric + "new M.A<_, _>((**){caret})"); box [ "SettableProperty"; "AnotherSettableProperty" ]; box [ "NonSettableProperty" ] |] + [| box (propModuleGeneric + "new M.A<_, _>(S{caret} = 1)"); box [ "SettableProperty" ]; box [ "NonSettableProperty" ] |] + [| box (propModuleGeneric + "new M.A<_, _>(S = 1{caret})"); box ([]: string list); box [ "NonSettableProperty"; "SettableProperty" ] |] + [| box (propModuleGeneric + "new M.A<_, _>(S = 1,{caret})"); box [ "AnotherSettableProperty" ]; box [ "NonSettableProperty" ] |] + ] + +[] +let ``ObjectInitializer.CompletionForProperties`` (source: string) (included: string list) (excluded: string list) = + let info = Checker.getCompletionInfo source + assertHasItemWithNames included info + assertHasNoItemsWithNames excluded info + +let private namedPlain = """ +type A = + static member Run(xyz: int, zyx: string) = 1 +""" + +let private namedGeneric = """ +type A = + static member Run<'T>(xyz: 'T, zyx: string) = 1 +""" + +let namedParamCases: obj[] seq = + [ + [| box (namedPlain + "A.Run({caret})"); box [ "xyz"; "zyx" ] |] + [| box (namedPlain + "A.Run(x{caret} = 1)"); box [ "xyz" ] |] + [| box (namedPlain + "A.Run(x = 1,{caret})"); box [ "xyz"; "zyx" ] |] + + [| box (namedGeneric + "A.Run({caret})"); box [ "xyz"; "zyx" ] |] + [| box (namedGeneric + "A.Run(x{caret} = 1)"); box [ "xyz" ] |] + [| box (namedGeneric + "A.Run(x = 1,{caret})"); box [ "xyz"; "zyx" ] |] + [| box (namedGeneric + "A.Run<_>({caret})"); box [ "xyz"; "zyx" ] |] + [| box (namedGeneric + "A.Run<_>(x{caret} = 1)"); box [ "xyz" ] |] + [| box (namedGeneric + "A.Run<_>(x = 1,{caret})"); box [ "xyz"; "zyx" ] |] + ] + +[] +let ``ObjectInitializer.CompletionForNamedParameters`` (source: string) (expected: string list) = + assertHasItemWithNames expected (Checker.getCompletionInfo source) + +let private settablePlain = """ +type A0() = member val Settable0 = 1 with get,set +type A() = + member val Settable = 1 with get,set + member val NonSettable = 1 + static member Run(): A0 = Unchecked.defaultof<_> + static member Run(a: string): A = Unchecked.defaultof<_> +""" + +let private settableGeneric = """ +type A0() = member val Settable0 = 1 with get,set +type A() = + member val Settable = 1 with get,set + member val NonSettable = 1 + static member Run<'T>(): A0 = Unchecked.defaultof<_> + static member Run(a: int): A = Unchecked.defaultof<_> +""" + +let settableReturnCases: obj[] seq = + [ + [| box (settablePlain + "A.Run({caret})"); box [ "Settable"; "Settable0" ] |] + [| box (settablePlain + "A.Run(S{caret} = 1)"); box [ "Settable"; "Settable0" ] |] + [| box (settablePlain + "A.Run(S = 1,{caret})"); box [ "Settable"; "Settable0" ] |] + [| box (settablePlain + "A.Run(Settable = 1,{caret})"); box [ "Settable0" ] |] + + [| box (settableGeneric + "A.Run({caret})"); box [ "Settable"; "Settable0" ] |] + [| box (settableGeneric + "A.Run(S{caret} = 1)"); box [ "Settable"; "Settable0" ] |] + [| box (settableGeneric + "A.Run(S = 1,{caret})"); box [ "Settable"; "Settable0" ] |] + [| box (settableGeneric + "A.Run(Settable = 1,{caret})"); box [ "Settable0" ] |] + [| box (settableGeneric + "A.Run<_>({caret})"); box [ "Settable"; "Settable0" ] |] + [| box (settableGeneric + "A.Run<_>(S{caret} = 1)"); box [ "Settable"; "Settable0" ] |] + [| box (settableGeneric + "A.Run<_>(S = 1,{caret})"); box [ "Settable"; "Settable0" ] |] + [| box (settableGeneric + "A.Run<_>(Settable = 1,{caret})"); box [ "Settable0" ] |] + ] + +[] +let ``ObjectInitializer.CompletionForSettablePropertiesInReturnValue`` (source: string) (included: string list) = + let info = Checker.getCompletionInfo source + assertHasItemWithNames included info + assertHasNoItemsWithNames [ "NonSettable" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.OpenDirectives.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.OpenDirectives.fs new file mode 100644 index 00000000000..6ed30db0888 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.OpenDirectives.fs @@ -0,0 +1,304 @@ +module FSharp.Compiler.Service.Tests.CompletionOpenDirectivesTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``LambdaOverloads.Completion`` () = + let info = + Checker.getCompletionInfo + """open System.Linq +let _ = [""].Sum(fun x -> x.Len{caret})""" + + assertHasItemWithNames [ "Length" ] info + +[] +let ``Duplicates.Bug4103a`` () = + let info = Checker.getCompletionInfo "open Microsoft.FSharp.Quotations\nExpr.{caret}" + + assertItemDescriptionContainsExactlyOnce "WhileLoop" "WhileLoop" info + +[] +let ``StandardTypes.Bug4403`` () = + let info = + Checker.getCompletionInfo + """open System +let x={caret}""" + + assertHasItemWithNames [ "int8"; "int16"; "int32"; "string"; "SByte"; "Int16"; "Int32"; "String" ] info + +[] +let ``NameSpace.InFsiFile.Bug882304_2`` () = + let info = + Checker.getCompletionInfoOfSignatureFile + """module BasicTest +open System.{caret}""" + + assertHasItemWithNames [ "Action"; "Activator"; "Collections"; "IConvertible" ] info + +[] +let ``Duplicates.Bug4103c`` () = + let info = + Checker.getCompletionInfo + """open System.IO +open System.IO +File.{caret}""" + + let expectedOverloads = + typeof.GetMethods() + |> Array.filter (fun m -> m.Name = "Open") + |> Array.length + + assertItemDescriptionOccurrences expectedOverloads "Open" "File.Open" info + +[] +let ``Duplicates.Bug2094`` () = + let info = + Checker.getCompletionInfo + """open Microsoft.FSharp.Control +let b = MailboxProcessor.{caret}""" + + assertItemDescriptionOccurrences 2 "Start" "Start" info + +[] +let ``Identifier.String.Positive`` () = + let info = + Checker.getCompletionInfo + """ + open System + let str = "a string" + // Test '.' after str + let _ = str.{caret} + """ + + assertHasItemWithNames [ "Chars"; "ToString"; "Length"; "GetHashCode" ] info + +[] +let ``Identifier.String.Negative`` () = + let info = + Checker.getCompletionInfo + """ + open System + let str = "a string" + // Test '.' after str + let _ = str.{caret} + """ + + assertHasNoItemsWithNames [ "Parse"; "op_Addition"; "op_Subtraction" ] info + +[] +let ``ImportStatement.System.ImportDirectly`` () = + let info = + Checker.getCompletionInfo + """ + open System.{caret} + open IO = System(*Mimportstatement2*)""" + + assertHasItemWithNames [ "Collections" ] info + +[] +let ``ImportStatement.System.ImportAsIdentifier`` () = + let info = + Checker.getCompletionInfo + """ + open System(*Mimportstatement1*) + open IO = System.{caret}""" + + assertHasItemWithNames [ "IO" ] info + +[] +let ``ObjInstance.ExtensionMethods.WithoutDef.Negative`` () = + let info = + Checker.getCompletionInfo + """ + open System + let rnd = new System.Random() + rnd.{caret}""" + + assertHasNoItemsWithNames [ "NextDice"; "DiceValue" ] info + +[] +let ``Expression.InComment`` () = + let info = + Checker.getCompletionInfo + """ + //open System + //open IO = System.{caret}""" + + Assert.Equal(0, info.Items.Length) + +[] +let ``ShortFormSeqExpr.Bug229610`` () = + let info = + Checker.getCompletionInfo + """module test + +open System.Text.RegularExpressions + +let getLinks (txt: string) = + [ for m in Regex.Matches(txt, "pattern") -> m.Groups.Item(1).{caret} ]""" + + assertHasItemWithNames [ "Value" ] info + +[] +let ``ReOpenNameSpace.SystemLibrary`` () = + let info = + Checker.getCompletionInfo + """ + module BasicTest + open System.IO + open System.IO + + File.{caret} + """ + + assertHasItemWithNames [ "Open" ] info + +[] +let ``ReOpenNameSpace.MailboxProcessor`` () = + let info = + Checker.getCompletionInfo + """ + module BasicTest + open Microsoft.FSharp.Control + open Microsoft.FSharp.Control + let counter = + MailboxProcessor.{caret}""" + + assertHasItemWithNames [ "Start" ] info + +[] +let ``Seq.NearTheEndOfFile`` () = + let info = + Checker.getCompletionInfo + """ + module BasicTest + open Microsoft.FSharp.Math + + let trianglenumbers = Seq.init_infinite (fun i -> let i = BigInt(i) in i * (i+1I) / 2I) + + (trianglenumbers |> Seq.{caret})""" + + assertHasItemWithNames [ "cache"; "find" ] info + +[] +[] +[")>] +let ``Regression3754.TypeOfListForward`` (shouldContain: bool) (names: string) = + let info = + Checker.getCompletionInfo + """ + module BasicTest + // regression test for bug 3754 + // tupe forwarder bug? intellisense bug? + + open System.IO + open System.Xml + open System.Xml.Linq + let xmlStr = @" Blah Blah " + let xns = XNamespace.op_Implicit "" + let a = xns + "a" + let reader = new StringReader(xmlStr) + let xdoc = XDocument.Load(reader) + let aElements = [for x in xdoc.Root.Elements() do + if x.Name = a then + yield x] + let href = xns + "href" + aElements |> List.{caret}""" + + let expected = names.Split(';') |> List.ofArray + + assertItemsWithNames shouldContain expected info + +[] +let ``NonApplicableExtensionMembersDoNotAppear.Bug40379`` () = + let source (decl: string) = + sprintf + """open System.Xml.Linq +type MyType() = + static member Foo(actual: XElement) = actual.Name + member public this.Bar() = + let actual: %s = failwith "" + actual.{caret}""" + decl + + let info1 = Checker.getCompletionInfo (source "int[]") + assertHasNoItemsWithNames [ "Ancestors"; "AncestorsAndSelf" ] info1 + + let info2 = Checker.getCompletionInfo (source "XNode[]") + assertHasItemWithNames [ "Ancestors" ] info2 + assertHasNoItemsWithNames [ "AncestorsAndSelf" ] info2 + + let info3 = Checker.getCompletionInfo (source "XElement[]") + assertHasItemWithNames [ "Ancestors"; "AncestorsAndSelf" ] info3 + +[] +let ``Verify no completion in hash directives`` () = + let info = + Checker.getCompletionInfo + """ + #r {caret} + + let foo x = x + let bar = 1""" + + Assert.Equal(0, info.Items.Length) + +[] +let ``Fsx.HashLoad.Conditionals`` () = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| "--define:INTERACTIVE" |] + FSharpCodeCompletionOptions.Default + """module InDifferentFS = +#if INTERACTIVE + let x = 1 +#else + let y = 2 +#endif +#if RELEASE + let A = 3 +#else + let B = 4 +#endif + +InDifferentFS.{caret}""" + + assertHasItemWithNames [ "x"; "B" ] info + assertHasNoItemsWithNames [ "y"; "A" ] info + Assert.Equal(2, info.Items.Length) + +[] +let ``Fsx.BugAllowExplicitReferenceToMsCorlib`` () = + let serviceDll = typeof.Assembly.Location + + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| sprintf "-r:%s" serviceDll |] + FSharpCodeCompletionOptions.Default + """#r "mscorlib" +open FSharp.Compiler.Interactive.Shell.Settings +fsi.{caret}""" + + assertHasItemWithNames [ "CommandLineArgs" ] info + +[] +let ``Fsx.HashReferenceAgainstStrongName`` () = + let source = + sprintf + "#reference \"System.Core, Version=%s, Culture=neutral, PublicKeyToken=b77a5c561934e089\"\nopen System.{caret}" + (System.Environment.Version.ToString()) + + let info = Checker.getCompletionInfo source + + assertHasItemWithNames [ "Linq" ] info + +[] +let ``Fsx.ShouldBeAbleToReference30Assemblies.Bug2050`` () = + let info = + Checker.getCompletionInfo + """#r "System.Core.dll" +open System.{caret}""" + + assertHasItemWithNames [ "Linq" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Operators.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Operators.fs new file mode 100644 index 00000000000..396ab1a25ca --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Operators.fs @@ -0,0 +1,59 @@ +module FSharp.Compiler.Service.Tests.CompletionOperatorsTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``AdjacentToDot_01`` () = + let info = Checker.getCompletionInfo "System.Console.{caret}." + + assertHasItemWithNames [ "BackgroundColor" ] info + +[] +let ``RangeOperator.IncorrectUsage`` () = + let info2Dots = Checker.getCompletionInfo "..{caret}" + Assert.Equal(0, info2Dots.Items.Length) + + let info3Dots = Checker.getCompletionInfo "...{caret}" + Assert.Equal(0, info3Dots.Items.Length) + +[] +let ``RangeOperator.CorrectUsage`` () = + let singleLine = Checker.getCompletionInfo "let _ = [1..{caret}]" + assertHasItemWithNames [ "abs" ] singleLine + + let multiLine = + Checker.getCompletionInfo + """[ + 1 + ..{caret} +]""" + + assertHasItemWithNames [ "abs" ] multiLine + +[] +let ``Array.AfterOperator...Bug65732_A`` () = + let info = Checker.getCompletionInfo "let r = [1 .. System.{caret}Int32.MaxValue]" + + assertHasItemWithNames [ "Int32" ] info + assertHasNoItemsWithNames [ "abs" ] info + +[] +[] +[] +[] +[] +[] +let ``Array.AfterOperator...Bug65732_B_C_D`` (source: string) = + let info = Checker.getCompletionInfo source + + assertHasItemWithNames [ "abs" ] info + assertHasNoItemsWithNames [ "CompareTo" ] info + +[] +let ``Dot.AfterOperator.Bug69159`` () = + let info = Checker.getCompletionInfo "let x1 = [|0..1..10|].{caret}" + + assertHasItemWithNames [ "Length" ] info + assertHasNoItemsWithNames [ "abs" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.PatternMatching.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.PatternMatching.fs new file mode 100644 index 00000000000..4aaf1724c5a --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.PatternMatching.fs @@ -0,0 +1,281 @@ +module FSharp.Compiler.Service.Tests.CompletionPatternMatchingTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``TupledArgsInLambda.Completion.Bug312557_2`` () = + let assertOffersTupleArgs (markedSource: string) = + let info = Checker.getCompletionInfo markedSource + assertHasItemWithNames [ "aaa"; "bbb" ] info + + assertOffersTupleArgs + """(1,2) |> (fun (aaa,bbb) -> + printfn "hi" + printfn "%d%d" b{caret} a + printfn "%d%d" a b ) """ + + assertOffersTupleArgs + """(1,2) |> (fun (aaa,bbb) -> + printfn "hi" + printfn "%d%d" b a + printfn "%d%d" a{caret} b ) """ + + assertOffersTupleArgs + """(1,2) |> (fun (aaa,bbb) -> + printfn "hi" + printfn "%d%d" b a{caret} + printfn "%d%d" a b ) """ + + assertOffersTupleArgs + """(1,2) |> (fun (aaa,bbb) -> + printfn "hi" + printfn "%d%d" b a + printfn "%d%d" a b{caret} ) """ + +[] +let ``DotCompletionInPatternsPartOfLambda`` () = + let info = Checker.getCompletionInfo "let _ = fun x .{caret} -> x + 1" + Assert.Equal(0, info.Items.Length) + +[] +let ``DotCompletionInPatterns`` () = + let assertEmpty (markedSource: string) = + let info = Checker.getCompletionInfo markedSource + Assert.Equal(0, info.Items.Length) + + assertEmpty "let (x, y .{caret}) = 1, 2" + assertEmpty "let run (o : obj) = match o with | :? int as i .{caret} -> 1 | _ -> 0" + assertEmpty "let (``x.y``, ``y.z`` .{caret}) = 1, true" + assertEmpty "let ``x`` .{caret} = 1" + +[] +let ``MatchStatement.WhenClause.Bug2519`` () = + let info = + Checker.getCompletionInfo + """type DU = X of int +let timefilter pkt = + match pkt with + | X(hdr) when (*aaa*)hdr.{caret} + | _ -> ()""" + + assertHasItemWithNames [ "CompareTo"; "GetHashCode" ] info + +[] +let ``Bug229433.AfterMismatchedParensCauseWeirdParseTreeAndExceptionDuringTypecheck`` () = + let info = + Checker.getCompletionInfo + """ + type T() = + member this.Bar() = () + member val X = "foo" with get,set + static member Id(x) = x + [1] + |> Seq.iter (fun x -> + let user = x + ["foo"] + |> List.iter (fun m -> + let xyz = new T() + xyz.X <- null + T.Id((*here*)xyz.{caret} // no intellisense here after . + ) + printfn "" + ) """ + + assertHasItemWithNames [ "Bar"; "X" ] info + +[] +let ``Identifer.InMatchStatement.Bug72595`` () = + let info = + Checker.getCompletionInfo + """ + type C() = + let someValue = "abc" + member _.M() = + let x = 1 + match someValue.{caret} with + let x = 1 + match 1 with + | _ -> 2 + type D() = + member x.P = 1 + [] + do() + """ + + assertHasItemWithNames [ "Chars" ] info + +[] +[ Array.mapi (fun i c ->""")>] +[ Array.mapi (fun i c -> +let p5 = 1""")>] +let ``LambdaExpression.WithoutClosing.Bug1346`` (markedSource: string) = + let info = Checker.getCompletionInfo markedSource + assertHasItemWithNames [ "Length" ] info + +[] +let ``IncompleteStatement.Match_A`` () = + let info = + Checker.getCompletionInfo + """let x = "1" +let test2 = match (x).{caret}""" + + assertHasItemWithNames [ "Contains" ] info + +[] +let ``IncompleteStatement.Match_C`` () = + let info = + Checker.getCompletionInfo + """let x = "1" +let test2 = match (x).{caret} +let y = 2""" + + assertHasItemWithNames [ "Contains" ] info + +[] +let ``WithinMatchClause.Bug1603`` () = + let info = + Checker.getCompletionInfo + """let rec f l = + match l with + | [] -> + let xx = System.DateTime.Now + let y = xx.{caret} + | x :: xs -> f xs""" + + assertHasItemWithNames [ "AddMilliseconds" ] info + +[] +let ``MatchStatement.Clause.AfterLetBinds.Bug1603`` () = + let info = + Checker.getCompletionInfo + """let rec f l = + match l with + | [] -> + let xx = System.DateTime.Now + let y = xx + | x :: xs -> f xs.{caret}""" + + assertHasItemWithNames [ "Head"; "Tail" ] info + + let headTail = + info.Items |> Array.filter (fun i -> i.NameInCode = "Head" || i.NameInCode = "Tail") + + if headTail.Length <> 2 then + failwithf + "Expected exactly 2 items named Head/Tail but found %d: [%s]" + headTail.Length + (headTail |> Array.map _.NameInCode |> String.concat ", ") + + for item in headTail do + if item.Glyph <> FSharpGlyph.Property then + failwithf "Item %A has glyph %A but expected Property" item.NameInCode item.Glyph + +[] +let ``BestMatch.Bug4320a`` () = + let info = Checker.getCompletionInfo " let x = System.{caret}" + assertHasItemWithNames [ "GC"; "GCCollectionMode" ] info + assertPrefixIsNotUnique "G" false info + assertPrefixIsUnique "GCC" false info + +[] +let ``BestMatch.Bug4320b`` () = + let info = Checker.getCompletionInfo " let x = List.{caret}" + assertHasItemWithNames [ "empty" ] info + assertPrefixIsNotUnique "e" false info + assertPrefixIsUnique "em" false info + +[] +let ``BestMatch.Bug5131`` () = + let info = Checker.getCompletionInfo "System.Environment.{caret}" + assertHasItemWithNames [ "OSVersion" ] info + assertPrefixIsUnique "o" true info + +[] +let ``Identifier.InMatchStatement`` () = + let info = + Checker.getCompletionInfo + """ +let x = 1 +match x.{caret} with + |1 -> 1*1 + |2 -> 2*2 +""" + + assertHasItemWithNames [ "ToString"; "Equals" ] info + +[] +let ``Identifier.InMatchClause`` () = + let info = + Checker.getCompletionInfo + """ +let rec f l = + match l with + | [] -> + let xx = System.DateTime.Now + let y = xx.{caret} + () + | x :: xs -> f xs +""" + + assertHasItemWithNames [ "Add"; "Date" ] info + +[] +let ``Keywords.Match`` () = + let info = + Checker.getCompletionInfo + """ + match.{caret} a with + | pattern -> exp""" + + Assert.Equal(0, info.Items.Length) + +[] +let ``Identifier.InMatch.UnderScore`` () = + let info = + Checker.getCompletionInfo + """ + let x = 1 + match x with + |1 -> 1*2 + |2 -> 2*2 + |_.{caret} -> 0 """ + + Assert.Equal(0, info.Items.Length) + +[] +let ``Identifier.InFunctionMatch`` () = + let info = + Checker.getCompletionInfo + """ + let f5 = function + | 1.{caret} -> printfn "1" + | 2 -> printfn "2" """ + + Assert.Equal(0, info.Items.Length) + +[] +let ``Expression.InMatchWhenClause`` () = + let info = + Checker.getCompletionInfo + """ + module BasicTest + type DU = X of int + let timefilter pkt = + match pkt with + | X(hdr) when hdr.{caret} -> () + | _ -> () + """ + + assertHasItemWithNames [ "CompareTo"; "ToString" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.PrintfFormat.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.PrintfFormat.fs new file mode 100644 index 00000000000..56ffcebebf1 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.PrintfFormat.fs @@ -0,0 +1,70 @@ +module FSharp.Compiler.Service.Tests.CompletionPrintfFormatTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``TupledArgsInLambda.Completion.Bug312557_1`` () = + let info = + Checker.getCompletionInfo + """[(1,2);(1,2);(1,2)] +|> Seq.iter (fun (xxx,yyy) -> printfn "%d" {caret} + printfn "%d" 1)""" + + assertHasItemWithNames [ "xxx"; "yyy" ] info + +[] +let ``CtrlSpaceInWhiteSpace.Bug133112`` () = + let info = + Checker.getCompletionInfo + """ + type Foo = + static member A = 1 + static member B = 2 + printfn "%d %d" Foo.A {caret} """ + + assertHasItemWithNames [ "AbstractClassAttribute" ] info + assertHasNoItemsWithNames [ "A"; "B" ] info + +[] +let ``BY_DESIGN.ExplicitlyCloseTheParens.Bug73940`` () = + let info = + Checker.getCompletionInfo + """ + let g lam = + lam true |> printfn "%b" + sprintf "%s" + let r = + ["1"] + |> List.map (fun s -> s.{caret} ) // user types close paren here to avoid paren mismatch + |> g // regardless of whatever is down here now, it won't affect the type of 's' above + """ + + assertHasItemWithNames [ "Chars" ] info + +[] +let ``BY_DESIGN.MismatchedParenthesesAreHardToRecoverFromAndHereIsWhy.Bug73940`` () = + let info = + Checker.getCompletionInfo + """ + let g lam = + lam true |> printfn "%b" + sprintf "%s" + let r = + ["1"] + |> List.map (fun s -> s.{caret} // it looks like s is a string here, but it's not! + |> g // parser recovers as though there is a right-paren here + """ + + assertHasItemWithNames [ "CompareTo" ] info + assertHasNoItemsWithNames [ "Chars" ] info + +[] +let ``Identifier.AfterParenthesis.Bug6484_2`` () = + let info = + Checker.getCompletionInfo + """for x = 1 to 10 do + printfn "%s" (x.{caret} """ + + assertHasItemWithNames [ "CompareTo" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Properties.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Properties.fs new file mode 100644 index 00000000000..3bfe01ba304 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Properties.fs @@ -0,0 +1,337 @@ +module FSharp.Compiler.Service.Tests.CompletionPropertiesTests + +open FSharp.Test +open Xunit + +[] +let ``ObsoleteProperties.6377_1`` () = + let info = + Checker.getCompletionInfo + """type StandIn() = + [] + static member val SecurityEnabled = false with get, set + static member GetStandardSandbox() = 0 +StandIn.{caret}""" + + assertHasItemWithNames [ "GetStandardSandbox" ] info + assertHasNoItemsWithNames [ "get_SecurityEnabled"; "set_SecurityEnabled" ] info + +[] +let ``ObsoleteProperties.6377_2`` () = + let info = Checker.getCompletionInfo "System.Threading.Thread.CurrentThread.{caret}" + + assertHasItemWithNames [ "CurrentCulture" ] info + assertHasNoItemsWithNames [ "get_ApartmentState"; "set_ApartmentState" ] info + +[] +let ``Class.Property.Bug69150_A`` () = + let info = + Checker.getCompletionInfo + """type ClassType(x : int) = + member this.Value = x +let z = (new ClassType(23)).{caret}Value""" + + assertHasItemWithNames [ "Value" ] info + assertHasNoItemsWithNames [ "CompareTo" ] info + +[] +let ``Class.Property.Bug69150_B`` () = + let info = + Checker.getCompletionInfo + """type ClassType(x : int) = + member this.Value = x +let z = ClassType(23).{caret}Value""" + + assertHasItemWithNames [ "Value" ] info + assertHasNoItemsWithNames [ "CompareTo" ] info + +[] +let ``Class.Property.Bug69150_C`` () = + let info = + Checker.getCompletionInfo + """type ClassType(x : int) = + member this.Value = x +let f x = new ClassType(x) +let z = f(23).{caret}Value""" + + assertHasItemWithNames [ "Value" ] info + assertHasNoItemsWithNames [ "CompareTo" ] info + +[] +let ``Class.Property.Bug69150_D`` () = + let info = + Checker.getCompletionInfo + """type ClassType(x : int) = + member this.Value = x +let z = ClassType(23).V{caret}alue""" + + assertHasItemWithNames [ "Value" ] info + assertHasNoItemsWithNames [ "VolatileFieldAttribute" ] info + +[] +let ``Class.Property.Bug69150_E`` () = + let info = + Checker.getCompletionInfo + """type ClassType(x : int) = + member this.Value = x +let z = ClassType(23) . {caret} Value""" + + assertHasItemWithNames [ "Value" ] info + assertHasNoItemsWithNames [ "VolatileFieldAttribute" ] info + +[] +let ``AssignmentToProperty.Bug231283`` () = + let info = + Checker.getCompletionInfo + """ + type Foo() = + member val Bar = 0 with get,set + let f = new Foo() + f.Bar <- + let xyz = 42 {caret}(*Mark*) + xyz """ + + assertHasItemWithNames [ "AbstractClassAttribute" ] info + assertHasNoItemsWithNames [ "Bar" ] info + +[] +let ``Bug130733.LongIdSet.CtrlSpace`` () = + let info = + Checker.getCompletionInfo + """ + type C() = + member this.XX with get() = 4 and set(x) = () + let c = C() + c.X{caret} <- 42""" + + assertHasItemWithNames [ "XX" ] info + +[] +let ``Bug130733.LongIdSet.Dot`` () = + let info = + Checker.getCompletionInfo + """ + type C() = + member this.XX with get() = 4 and set(x) = () + let c = C() + c.{caret}X <- 42""" + + assertHasItemWithNames [ "XX" ] info + +[] +let ``Bug130733.ExprDotSet.CtrlSpace`` () = + let info = + Checker.getCompletionInfo + """ + type C() = + member this.XX with get() = 4 and set(x) = () + let f(x) = C() + f(0).X{caret} <- 42""" + + assertHasItemWithNames [ "XX" ] info + +[] +let ``Bug130733.ExprDotSet.Dot`` () = + let info = + Checker.getCompletionInfo + """ + type C() = + member this.XX with get() = 4 and set(x) = () + let f(x) = C() + f(0).{caret}X <- 42""" + + assertHasItemWithNames [ "XX" ] info + +[] +let ``Bug130733.Nested.LongIdSet.CtrlSpace`` () = + let info = + Checker.getCompletionInfo + """ + type C() = + member this.XX with get() = 4 and set(x) = () + member this.CC with get() = C() + let c = C() + c.CC.X{caret} <- 42""" + + assertHasItemWithNames [ "XX" ] info + +[] +let ``Bug130733.Nested.LongIdSet.Dot`` () = + let info = + Checker.getCompletionInfo + """ + type C() = + member this.XX with get() = 4 and set(x) = () + member this.CC with get() = C() + let c = C() + c.CC.{caret}X <- 42""" + + assertHasItemWithNames [ "XX" ] info + +[] +let ``Bug130733.Nested.ExprDotSet.CtrlSpace`` () = + let info = + Checker.getCompletionInfo + """ + type C() = + member this.XX with get() = 4 and set(x) = () + member this.CC with get() = C() + let f(x) = C() + f(0).CC.X{caret} <- 42""" + + assertHasItemWithNames [ "XX" ] info + +[] +let ``Bug130733.Nested.ExprDotSet.Dot`` () = + let info = + Checker.getCompletionInfo + """ + type C() = + member this.XX with get() = 4 and set(x) = () + member this.CC with get() = C() + let f(x) = C() + f(0).CC.{caret}X <- 42""" + + assertHasItemWithNames [ "XX" ] info + +[] +let ``Bug130733.NamedIndexedPropertyGet.Dot`` () = + let info = + Checker.getCompletionInfo + """ + let str = "foo" + str.Chars(3).{caret}""" + + assertHasItemWithNames [ "CompareTo" ] info + +[] +let ``Bug130733.NamedIndexedPropertyGet.CtrlSpace`` () = + let info = + Checker.getCompletionInfo + """ + let str = "foo" + str.Chars(3).Co{caret}""" + + assertHasItemWithNames [ "CompareTo" ] info + +[] +[] +[] +let ``Bug230533.NamedIndexedPropertySet.CtrlSpace`` (source: string) = + let info = Checker.getCompletionInfo source + assertHasItemWithNames [ "MutableInstanceIndexer" ] info + +[] +let ``Bug230533.ExprDotSet.CtrlSpace.Case1`` () = + let info = + Checker.getCompletionInfo + """ + type C() = + member this.XX with get() = 4 and set(x) = () + type D() = + member this.CC = new C() + let f(x) = D() + f(0).CC.{caret} <- 42 """ + + assertHasItemWithNames [ "XX" ] info + +[] +let ``Bug230533.ExprDotSet.CtrlSpace.Case2`` () = + let info = + Checker.getCompletionInfo + """ + type C() = + member this.XX with get() = 4 and set(x) = () + type D() = + member this.CC with get() = new C() and set(x) = () + let f(x) = D() + f(0).CC.{caret} <- 42 """ + + assertHasItemWithNames [ "XX" ] info + +[] +let ``ExpressionDotting.Regression.Bug187799`` () = + let info = + Checker.getCompletionInfo + """ + type T() = + member _.P with get() = new T() + member _.M() = [|1..2|] + let t = new T() + t.P.M().{caret} """ + + assertHasItemWithNames [ "Clone" ] info + +[] +let ``ExpressionDotting.Regression.Bug187799.Test8`` () = + let info = + Checker.getCompletionInfo + """ + type C() = + static member XXX with get() = 4 and set(x) = () + static member CCC with get() = C() + C.XXX.{caret} <- 42""" + + assertHasItemWithNames [ "CompareTo" ] info + +[] +let ``NoInfiniteLoopInProperties`` () = + let info = + Checker.getCompletionInfo + """ + type NodeCollection() = + member _.Add(n: Node) = () + member _.Item with get (index: int) = Node() + and Node() = + member _.Nodes = NodeCollection() + let tn = Node() + tn.Nodes.{caret}""" + + assertHasNoItemsWithNames [ "Nodes" ] info + +[] +let ``Identifier.AsProperty`` () = + let info = + Checker.getCompletionInfo + """ + type Type2 = + member this.Foo.{caret} = 1""" + + Assert.Equal(0, info.Items.Length) + +[] +let ``ExpressionPropertyAssignment.Bug217051`` () = + let info = + Checker.getCompletionInfo + """ + type Foo() = + member val Prop = 0 with get, set + Foo().{caret} <- 4 """ + + assertHasItemWithNames [ "Prop" ] info + +[] +let ``ExpressionProperty.Bug234687`` () = + let info = + Checker.getCompletionInfo + """ + open System.Reflection + let x = obj() + let a = x.GetType().Assembly.{caret} + """ + + assertHasItemWithNames [ "CodeBase" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Queries.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Queries.fs new file mode 100644 index 00000000000..89024fcde35 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Queries.fs @@ -0,0 +1,362 @@ +module FSharp.Compiler.Service.Tests.CompletionQueriesTests + +open Xunit + +[] +let ``Query.CompletionInJoinOn`` () = + let info = + Checker.getCompletionInfo + """ +query { + for a in [1] do + join b in [2] on (a.{caret}) + select (a + b) +}""" + + assertHasItemWithNames [ "GetHashCode"; "CompareTo" ] info + +[] +let ``Query.GroupJoin.CompletionInIncorrectJoinRelations`` () = + let info = + Checker.getCompletionInfo + """ +let t = + query { + for x in [1] do + groupJoin y in [""] on (x.{caret} ?=? y.) into g + select 1 }""" + + assertHasItemWithNames [ "CompareTo" ] info + assertHasNoItemsWithNames [ "abs" ] info + +[] +let ``Query.Join.CompletionInIncorrectJoinRelations`` () = + let info = + Checker.getCompletionInfo + """ +let t = + query { + for x in [1] do + join y in [""] on (x.{caret} ?=? y.) + select 1 }""" + + assertHasItemWithNames [ "CompareTo" ] info + assertHasNoItemsWithNames [ "abs" ] info + +[] +let ``Query.ForKeywordCanCompleteIntoIdentifier`` () = + let info = + Checker.getCompletionInfo + """ +let form = 42 +let t = + query { + for{caret} + }""" + + assertHasItemWithNames [ "form" ] info + +[] +let ``QueryExpression.CtrlSpaceSmokeTest0`` () = + let info = + Checker.getCompletionInfo + """ +module BasicTest +let x = si{caret}""" + + assertHasItemWithNames [ "sin" ] info + +[] +let ``QueryExpression.CtrlSpaceSmokeTest0b`` () = + let info = + Checker.getCompletionInfo + """ +module BasicTest +let x = qu{caret}""" + + assertHasItemWithNames [ "query" ] info + +[] +let ``QueryExpression.CtrlSpaceSmokeTest1`` () = + let info = + Checker.getCompletionInfo + """ +module BasicTest +let x = query { for x in [1;2;3] do sel{caret}""" + + assertHasItemWithNames [ "select" ] info + +[] +let ``QueryExpression.CtrlSpaceSmokeTest1b`` () = + let info = + Checker.getCompletionInfo + """ +module BasicTest +let x = query { for x in [1;2;3] do {caret}""" + + assertHasItemWithNames [ "select" ] info + +[] +let ``QueryExpression.CtrlSpaceSmokeTest2`` () = + let info = + Checker.getCompletionInfo + """ +module BasicTest +let x = query { for x in [1;2;3] do sel{caret} }""" + + assertHasItemWithNames [ "select" ] info + +[] +let ``QueryExpression.CtrlSpaceSmokeTest3`` () = + let info = + Checker.getCompletionInfo + """ +module BasicTest +let x = query { for xxxxxx in [1;2;3] do xxx{caret}""" + + assertHasItemWithNames [ "xxxxxx" ] info + +[] +[] +[] +let ``QueryExpression.CtrlSpaceSmokeTest3b_3c`` (markedSource: string) = + let info = Checker.getCompletionInfo markedSource + + assertHasItemWithNames [ "xxxxxx" ] info + +[] +let ``QueryExpression.CtrlSpaceSystematic1`` () = + let info = + Checker.getCompletionInfo + """ +module BasicTest +let x = query { for x in [1;2;3] do sel{caret}""" + + assertHasItemWithNames [ "select" ] info + +[] +let ``QueryExpressions.QueryAndSequenceExpressionWithForYieldLoopSystematic`` () = + let info = + Checker.getCompletionInfo + """ +module Test +let aaaaaa = [| "1" |] +let v = query { for bbbb in [ aaaaaa ] do yield {caret}""" + + assertHasItemWithNames [ "aaaaaa"; "bbbb" ] info + +[] +let ``QueryAndOtherExpressions.WordByWordSystematicJoinQueryOnSingleLine`` () = + let info = + Checker.getCompletionInfo + """ +module Test +let abbbbc = [| 1 |] +let aaaaaa = 0 +let x = query { for bbbb in abbbbc do join cccc in abbb{caret}""" + + assertHasItemWithNames [ "abbbbc" ] info + +[] +let ``QueryAndOtherExpressions.WordByWordSystematicJoinQueryOnMultipleLine`` () = + let info = + Checker.getCompletionInfo + """ +module Test +let abbbbc = [| 1 |] +let aaaaaa = 0 +let x = query { for bbbb in abbbbc do + join cccc in abbb{caret}""" + + assertHasItemWithNames [ "abbbbc" ] info + +[] +let ``QueryExpression.CtrlSpaceSystematic2`` () = + let info = + Checker.getCompletionInfo + """ +module BasicTest +let x = query { for x in [1;2;3] do {caret}""" + + assertHasItemWithNames [ "select"; "where" ] info + +[] +let ``Query.Auto.InNestedQuery`` () = + let info = + Checker.getCompletionInfo + """ +let tuples = [ (1, 8, 9); (56, 45, 3)] +let numbers = [ 1;2; 8; 9; 15; 23; 3; 42; 4;0; 55;] +let foo = + query { + for n in numbers do + let maxNumber = query {for x in tuples do ma{caret}} + select n }""" + + assertHasItemWithNames [ "maxBy"; "maxByNullable" ] info + +[] +let ``Query.Auto.OffSetFromPreviousLine`` () = + let info = + Checker.getCompletionInfo + """ +let numbers = [ 1;2; 8; 9; 15; 23; 3; 42; 4;0; 55;] +let foo = + query { + for n in numbers do + gro{caret} + }""" + + assertHasItemWithNames [ "groupBy"; "groupJoin"; "groupValBy" ] info + +[] +let ``QueryExpression.DotCompletionSmokeTest1`` () = + let info = + Checker.getCompletionInfo + """ +module Basic +let x2 = query { for x in ["1";"2";"3"] do + select x.{caret}""" + + assertHasItemWithNames [ "Chars"; "Length" ] info + +[] +let ``QueryExpression.DotCompletionSmokeTest2`` () = + let info = + Checker.getCompletionInfo + """ +module BasicTest +let x = query { for x in ["1";"2";"3"] do select x.{caret}""" + + assertHasItemWithNames [ "Chars"; "Length" ] info + +[] +let ``QueryExpression.DotCompletionSmokeTest0`` () = + let info = + Checker.getCompletionInfo + """ +module BasicTest +let x = seq { for x in ["1";"2";"3"] do yield x.{caret} }""" + + assertHasItemWithNames [ "Chars"; "Length" ] info + +[] +let ``QueryExpression.DotCompletionSmokeTest3`` () = + let info = + Checker.getCompletionInfo + """ +module BasicTest +let x = query { for x in ["1";"2";"3"] do select x.{caret} }""" + + assertHasItemWithNames [ "Chars"; "Length" ] info + +[] +let ``QueryExpression.DotCompletionSystematic1`` () = + let info = + Checker.getCompletionInfo + """ +module Simple +let x2 = query { for x in ["1";"2";"3"] do + select x.{caret}""" + + assertHasItemWithNames [ "Chars"; "Length" ] info + +[] +let ``QueryExpression.InsideJoin.Bug204147`` () = + let info = + Checker.getCompletionInfo + """ +module Simple +type T() = + member x.GetCollection() = [1;2;3;4] +let q = + query { + for e in [1..10] do + join b in T().{caret} + select b + }""" + + assertHasItemWithNames [ "GetCollection" ] info + +[] +let ``Query.HasErrors.Bug196230`` () = + let info = + Checker.getCompletionInfo + """ +open DataSource +let products = Products.getProductList() +let sortedProducts = + query { + for p in products do + let x = p.ProductID + "a" + sortBy p.{caret} + select p + }""" + + assertHasItemWithNames [ "ProductID"; "ProductName" ] info + +[] +let ``Query.HasErrors2`` () = + let info = + Checker.getCompletionInfo + """ +open DataSource +let products = Products.getProductList() +let sortedProducts = + query { + for p in products do + orderBy (p.{caret}) + }""" + + assertHasItemWithNames [ "ProductID"; "ProductName" ] info + +[] +let ``Query.ShadowedVariables`` () = + let info = + Checker.getCompletionInfo + """ +open DataSource +let products = Products.getProductList() +let p = 12 +let sortedProducts = + query { + for p in products do + select p.{caret} + }""" + + assertHasItemWithNames [ "Category"; "ProductName" ] info + +[] +let ``Query.InNestedQuery`` () = + let info = + Checker.getCompletionInfo + """ +let tuples = [ (1, 8, 9); (56, 45, 3)] +let numbers = [ 1;2; 8; 9; 15; 23; 3; 42; 4;0; 55;] +let foo = + query { + for n in numbers do + let maxNumber = query {for x in tuples do maxBy x.{caret}} + select (n, query {for y in numbers do minBy y}) }""" + + assertHasItemWithNames [ "Equals"; "GetType" ] info + +[] +let ``Query.NestedExpressionWithinLamda`` () = + let info = + Checker.getCompletionInfo + """ +let numbers = [ 1;2; 8; 9; 15; 23; 3; 42; 4;0; 55;] +let f (x : string) = () +let foo = + query { + for n in numbers do + let x = 42 |> ignore; numbers |> List.iter( fun n -> f ("1" + "1").{caret}) + skipWhile (n < 30) + }""" + + assertHasItemWithNames [ "Chars"; "Length" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Quotations.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Quotations.fs new file mode 100644 index 00000000000..3e6075a60cc --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Quotations.fs @@ -0,0 +1,50 @@ +module FSharp.Compiler.Service.Tests.CompletionQuotationsTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``Regression3225.Identifier.InQuotation`` () = + let info = + Checker.getCompletionInfo + """ + let _ = <@ let x = "foo" + x.{caret} @>""" + + assertHasItemWithNames [ "Chars"; "Length" ] info + +[] +let ``ReOpenNameSpace.FsharpQuotation`` () = + let info = + Checker.getCompletionInfo + """ + module BasicTest + open Microsoft.FSharp.Quotations + open Microsoft.FSharp.Quotations + Expr.{caret} + """ + + assertHasItemWithNames [ "Value" ] info + +[] +[] +[] +let ``Identifier.InActivePattern`` (shouldContain: bool) (names: string) = + let info = + Checker.getCompletionInfo + """ + module BasicTest + // regression test for bug 3223 No intellisense at point + open Microsoft.FSharp.Quotations.Patterns + open Microsoft.FSharp.Quotations.DerivedPatterns + let test1 = <@ 1 + 1 @> + let _ = + match test1 with + | Call(None, methInfo, args) -> + if methInfo.{caret} + """ + + let expected = names.Split(';') |> List.ofArray + + assertItemsWithNames shouldContain expected info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Records.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Records.fs new file mode 100644 index 00000000000..6fac61968a0 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Records.fs @@ -0,0 +1,409 @@ +module FSharp.Compiler.Service.Tests.CompletionRecordsTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``Records.DotCompletion.ConstructingRecords1`` () = + let assertOffers (should: string list) (markedSource: string) = + let info = Checker.getCompletionInfo markedSource + assertHasItemWithNames should info + assertHasNoItemsWithNames [ "abs" ] info + + assertOffers + [ "XX" ] + """type OuterRec = {XX : int; YY : string} +let _ = (* MARKER*) {X{caret}""" + + assertOffers + [ "OuterRec" ] + """type OuterRec = {XX : int; YY : string} +let _ = {XX = 1; (* MARKER*)O{caret}""" + + assertOffers + [ "XX"; "YY" ] + """type OuterRec = {XX : int; YY : string} +let _ = {XX = 1; (* MARKER*)OuterRec.{caret}""" + +[] +let ``Records.DotCompletion.ConstructingRecords2`` () = + let check (should: string list) (shouldNot: string list) (markedSource: string) = + let info = Checker.getCompletionInfo markedSource + assertHasItemWithNames should info + assertHasNoItemsWithNames shouldNot info + + let info1 = + Checker.getCompletionInfo + """module Mod = + type Rec = {XX : int; YY : string} +let _ = (* MARKER*){X{caret} }""" + + assertHasNoItemsWithNames [ "XX" ] info1 + + check + [ "XX"; "YY" ] + [ "System" ] + """module Mod = + type Rec = {XX : int; YY : string} +let _ = {(* MARKER*)Mod.{caret} = 1; O""" + + check + [ "XX"; "YY" ] + [ "System" ] + """module Mod = + type Rec = {XX : int; YY : string} +let _ = {(* MARKER*)Mod.Rec.{caret} """ + + check + [ "Mod" ] + [ "XX"; "abs" ] + """module Mod = + type Rec = {XX : int; YY : string} +let _ = (* MARKER*){Mod.XX = 1; {caret} }""" + +[] +let ``Records.CopyOnUpdate`` () = + let assertFields (markedSource: string) = + let info = Checker.getCompletionInfo markedSource + assertHasItemWithNames [ "a"; "b" ] info + assertHasNoItemsWithNames [ "abs" ] info + + assertFields + """module SomeOtherPath = + type r = { a: int; b : int } +let f1 x = { x with SomeOtherPath.{caret} = 3 }""" + + assertFields + """module SomeOtherPath = + type r = { a: int; b : int } +let f2 x = { x with SomeOtherPath.r.{caret} = 3 }""" + + assertFields + """module SomeOtherPath = + type r = { a: int; b : int } +let f3 (x : SomeOtherPath.r) = { x with {caret}}""" + +[] +let ``Records.CopyOnUpdate.NoFieldsCompletionBeforeWith`` () = + let info = + Checker.getCompletionInfo + """type T = {AAA : int} +let r = {AAA = 5} +let b = {r {caret} with }""" + + assertHasNoItemsWithNames [ "AAA" ] info + +[] +let ``Records.Constructors1`` () = + let assertOffers (markedSource: string) = + let info = Checker.getCompletionInfo markedSource + assertHasItemWithNames [ "field1"; "field2" ] info + assertHasNoItemsWithNames [ "abs" ] info + + assertOffers + """type X = + val field1: int + val field2: string + new() = { f{caret}}""" + + assertOffers + """type X = + val field1: int + val field2: string + new() = { field1; {caret}}""" + + assertOffers + """type X = + val field1: int + val field2: string + new() = { field1 = 5; {caret}}""" + + assertOffers + """type X = + val field1: int + val field2: string + new() = { field1 = 5; f{caret} }""" + +[] +let ``Records.Constructors2.UnderscoresInNames`` () = + let assertOffers (markedSource: string) = + let info = Checker.getCompletionInfo markedSource + assertHasItemWithNames [ "_field1"; "_field2" ] info + assertHasNoItemsWithNames [ "abs" ] info + + assertOffers + """type X = + val _field1: int + val _field2: string + new() = { _{caret}}""" + + assertOffers + """type X = + val _field1: int + val _field2: string + new() = { _field1; {caret}}""" + +[] +let ``Records.NestedRecordPatterns`` () = + let info = Checker.getCompletionInfo "[1..({contents = 5}).{caret}]" + assertHasItemWithNames [ "Value"; "contents" ] info + assertHasNoItemsWithNames [ "CompareTo" ] info + +[] +let ``Records.Separators1`` () = + let assertOffers (markedSource: string) = + let info = Checker.getCompletionInfo markedSource + assertHasItemWithNames [ "abs" ] info + assertHasNoItemsWithNames [ "AAA"; "BBB" ] info + + assertOffers + """type X = { AAA : int; BBB : string} +let r = {AAA = 5 {caret}; }""" + + assertOffers + """type X = { AAA : int; BBB : string} +let r = {AAA = 5 ; } +let b = {r with AAA = 5 {caret}; }""" + +[] +let ``Records.Separators2`` () = + let assertOffers (should: string list) (markedSource: string) = + let info = Checker.getCompletionInfo markedSource + assertHasItemWithNames should info + assertHasNoItemsWithNames [ "abs" ] info + + assertOffers + [ "AAA"; "BBB" ] + """type X = { AAA : int; BBB : string} +let r = + { + AAA = 5; +(*MARKER*) {caret} + }""" + + assertOffers + [ "AAA"; "BBB"; "CCC" ] + """type X = { AAA : int; BBB : string; CCC : int} +let r = + { + AAA = 5; {caret} + CCC = 5 + }""" + +[] +let ``Records.Separators2.OffsideRule`` () = + let info = + Checker.getCompletionInfo + """type X = { AAA : int; BBB : string} +let r = + { + AAA = 5 +(*MARKER*){caret} + }""" + + assertHasItemWithNames [ "AAA"; "BBB" ] info + assertHasNoItemsWithNames [ "abs" ] info + +[] +let ``Records.Inherits`` () = + let info = + Checker.getCompletionInfo + """type A = class end +type B = + inherit A + val f1: int + val f2: int + new() = { inherit A(); {caret}}""" + + assertHasItemWithNames [ "f1"; "f2" ] info + assertHasNoItemsWithNames [ "abs" ] info + +[] +let ``Records.Inherits.AfterInheritNewLine`` () = + let info = + Checker.getCompletionInfo + """type A = class end +type B = + inherit A + val f1: int + val f2: int + new() = { inherit A() + (*M*){caret} + }""" + + assertHasItemWithNames [ "f1"; "f2" ] info + assertHasNoItemsWithNames [ "abs" ] info + +[] +let ``Records.MissingBindings`` () = + let assertOffersR (markedSource: string) = + let info = Checker.getCompletionInfo markedSource + assertHasItemWithNames [ "R" ] info + assertHasNoItemsWithNames [ "abs" ] info + + let assertOffersFields (markedSource: string) = + let info = Checker.getCompletionInfo markedSource + assertHasItemWithNames [ "AAA"; "BBB" ] info + assertHasNoItemsWithNames [ "abs" ] info + + assertOffersR + """type R = {AAA : int; BBB : bool} +let _ = {A = 1; _;{caret} }""" + + assertOffersR + """type R = {AAA : int; BBB : bool} +let _ = {A = 1; _=;{caret} }""" + + assertOffersFields + """type R = {AAA : int; BBB : bool} +let _ = {A = 1; R.{caret} }""" + + assertOffersFields + """type R = {AAA : int; BBB : bool} +let _ = {A = 1; _; R.{caret} }""" + +[] +let ``Records.WRONG.ErrorsInFirstBinding`` () = + let assertNoFields (markedSource: string) = + let info = Checker.getCompletionInfo markedSource + assertHasNoItemsWithNames [ "field1"; "field2" ] info + + assertNoFields + """type X = + val field1: int + val field2: string + new() = { field1 =; {caret}}""" + + assertNoFields + """type X = + val field1: int + val field2: string + new() = { field1 =; f{caret}}""" + +[] +let ``Records.InferByFieldsInPriorMethodArguments`` () = + let assertOffers (markedSource: string) = + let info = Checker.getCompletionInfo markedSource + assertHasItemWithNames [ "Left"; "Top"; "Width"; "Height" ] info + + assertOffers + """type T() = + new (left: float32, top: float32) = T() + new (left: float32, top: float32, width: float32, height: float32) = T() + +type Rect = + { Left: float32 + Top: float32 + Width: float32 + Height: float32 } +let toT(original) = T(original.Left, (* MARKER*)original.{caret})""" + + assertOffers + """type T() = + new (left: float32, top: float32) = T() + new (left: float32, top: float32, width: float32, height: float32) = T() + +type Rect = + { Left: float32 + Top: float32 + Width: float32 + Height: float32 } +let toT(original) = T(original.Left, original.Height, (* MARKER*)original.{caret})""" + + assertOffers + """type T() = + new (left: float32, top: float32) = T() + new (left: float32, top: float32, width: float32, height: float32) = T() + +type Rect = + { Left: float32 + Top: float32 + Width: float32 + Height: float32 } +let toT(original) = T(original.Left, original.Height, original.Width, (* MARKER*)original.{caret})""" + + assertOffers + """type T() = + new (left: float32, top: float32) = T() + new (left: float32, top: float32, width: float32, height: float32) = T() + +type Rect = + { Left: float32 + Top: float32 + Width: float32 + Height: float32 } +let toT(original) = T(original.Left, original.Height, (* MARKER*)original.{caret}, original.Width)""" + +[] +let ``Expression.RecordPattern`` () = + let info = + Checker.getCompletionInfo + """ + type Rec = + { X : int} + member this.Value = 42 + { X = 1 }.{caret} + """ + + assertHasItemWithNames [ "Value"; "ToString" ] info + +[] +let ``SimpleTypes.Record`` () = + let info = + Checker.getCompletionInfo + """ + type Person = { Name: string; DateOfBirth: System.DateTime } + let typrecord = { Name = "Bill"; DateOfBirth = new System.DateTime(1962,09,02) } + typrecord.{caret}""" + + assertHasItemWithNames [ "DateOfBirth"; "Name" ] info + +[] +let ``LongIdent.Record.AsField`` () = + let info = + Checker.getCompletionInfo + """ + module MyModule = + type person = + { name: string; + dateOfBirth: System.DateTime; } + module MyModule2 = + let x = {MyModule.{caret} = 32}""" + + assertHasItemWithNames [ "person" ] info + +[] +let ``Identifier.InRecord.WithoutDef`` () = + let info = Checker.getCompletionInfo """type Rec = { X.{caret} : int }""" + Assert.Equal(0, info.Items.Length) + +[] +let ``Regression1911.Expression.InMatchStatement`` () = + let info = + Checker.getCompletionInfo + """ + type Thingy = { A : bool; B : int } + let test = match (List.head [{A = true; B = 0}; {A = false; B = 1}]).{caret}""" + + assertHasItemWithNames [ "A"; "B" ] info + +[] +let ``AutoComplete.Bug65731_A`` () = + let info = + Checker.getCompletionInfo + """module SomeOtherPath = + type r = { a: int; b : int } +let f1 x = { x with SomeOtherPath.{caret}a = 3 } // a""" + + assertHasItemWithNames [ "a" ] info + +[] +let ``AutoComplete.Bug65731_B`` () = + let info = + Checker.getCompletionInfo + """module SomeOtherPath = + type r = { a: int; b : int } +let f2 x = { x with SomeOtherPath.r.{caret}a = 3 } // a""" + + assertHasItemWithNames [ "a" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Recursion.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Recursion.fs new file mode 100644 index 00000000000..df38f26d2c5 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Recursion.fs @@ -0,0 +1,16 @@ +module FSharp.Compiler.Service.Tests.CompletionRecursionTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``CompletionInDifferentEnvs1`` () = + let info = + Checker.getCompletionInfo + """let f1 num = + let rec completeword d = + d + d +(**)comple{caret}""" + + assertHasItemWithNames [ "completeword" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.SeqListArrayExprs.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.SeqListArrayExprs.fs new file mode 100644 index 00000000000..8e6695e28a5 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.SeqListArrayExprs.fs @@ -0,0 +1,137 @@ +module FSharp.Compiler.Service.Tests.CompletionSeqListArrayExprsTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``Array.Length.InForRange`` () = + let info = + Checker.getCompletionInfo + """ +let a = [|1;2;3|] +for i in 0..a.{caret}""" + + assertHasItemWithNames [ "Length" ] info + +[] +let ``Identifier.Array.AfterassertKeyword`` () = + let info = + Checker.getCompletionInfo + """ +let x = [1;2;3] +assert x.{caret}""" + + assertHasItemWithNames [ "Head" ] info + assertHasNoItemsWithNames [ "Listeners" ] info + +[] +let ``CtrlSpaceCompletion.Bug294974.Case2`` () = + let info = + Checker.getCompletionInfo + """ + let xxx {caret}= [1] + xxx .IsEmpty // Ctrl-J just before the '.' """ + + assertHasItemWithNames [ "AbstractClassAttribute" ] info + assertHasNoItemsWithNames [ "IsEmpty" ] info + +[] +[] +[] +let ``PopupsVersusCtrlSpaceOnDotDot.FirstDot`` (_trigger: string) = + let info = Checker.getCompletionInfo "System.Console.{caret}.BackgroundColor" + + assertHasItemWithNames [ "BackgroundColor" ] info + assertHasNoItemsWithNames [ "abs" ] info + +[] +let ``Identifier.OnWhiteSpace.AtTopLevel`` () = + let info = Checker.getCompletionInfo "(*marker*) {caret} " + + assertHasItemWithNames [ "System"; "Array2D" ] info + assertHasNoItemsWithNames [ "Int32" ] info + +[] +let ``Identifier.AfterDefined.Bug1545`` () = + let info = + Checker.getCompletionInfo + """ +let x = [|"hello"|] +x.{caret}""" + + assertHasItemWithNames [ "Length" ] info + +[] +let ``Residues1`` () = + let info = Checker.getCompletionInfo "System . Int32 . M{caret}" + + assertHasItemWithNames [ "MaxValue"; "MinValue" ] info + assertHasNoItemsWithNames [ "MailboxProcessor"; "Map" ] info + +[] +let ``BY_DESIGN.CommonScenarioThatBegsTheQuestion.Bug73940`` () = + let info = + Checker.getCompletionInfo + """ + let r = + ["1"] + |> List.map (fun s -> s.{caret} // user previous had e.g. '(fun s -> s)' here, but he erased after 's' to end-of-line and hit '.' e.g. to eventually type '.Substring(5))' + |> List.filter (fun s -> s.Length > 5) // parser recover assumes close paren is here, and type inference goes wacky-useless with such a parse + """ + + assertHasNoItemsWithNames [ "Chars" ] info + +[] +let ``Identifier.AfterParenthesis.Bug835276`` () = + let info = + Checker.getCompletionInfo + """ +let f ( s : string ) = + let x = 10 + s.Length + for i in 1..10 do + let ok = 10 + s.Length // dot here did work + let y = 10 +(s.{caret}""" + + assertHasItemWithNames [ "Length" ] info + +[] +let ``Identifier.AfterParenthesis.Bug6484_1`` () = + let info = + Checker.getCompletionInfo + """ +for x in 1..10 do + printfn "%s" (x.{caret} """ + + assertHasItemWithNames [ "CompareTo" ] info + +[] +let ``Array`` () = + let info = Checker.getCompletionInfo "let arr = [| for i in 1..10 -> i |].{caret}" + + assertHasItemWithNames [ "Clone"; "IsFixedSize" ] info + +[] +let ``List`` () = + let info = Checker.getCompletionInfo "let lst = [ for i in 1..10 -> i].{caret}" + + assertHasItemWithNames [ "Head"; "Tail" ] info + +[] +let ``Expression.List`` () = + let info = Checker.getCompletionInfo "[1;2].{caret} " + + assertHasItemWithNames [ "Head"; "Item" ] info + +[] +let ``Array.InitialUsing..`` () = + let info = Checker.getCompletionInfo "let x1 = [| 0.0 .. 0.1 .. 10.0 |].{caret}" + + assertHasItemWithNames [ "Length"; "Clone"; "ToString" ] info + +[] +let ``BadCompletionAfterQuicklyTyping`` () = + let info = Checker.getCompletionInfo "[1].{caret}" + + assertHasItemWithNames [ "Length" ] info + assertHasNoItemsWithNames [ "AbstractClassAttribute" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Tuples.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Tuples.fs new file mode 100644 index 00000000000..86620ee9af6 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.Tuples.fs @@ -0,0 +1,74 @@ +module FSharp.Compiler.Service.Tests.CompletionTuplesTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``NotShowInfo.ClassMemberDeclA.Bug3602`` () = + let info = + Checker.getCompletionInfo + """type Foo() = + member this.Func (x, y) = () + member (*marker*) this.{caret} +()""" + + Assert.Equal(0, info.Items.Length) + +[] +let ``NotShowInfo.ClassMemberDeclB.Bug3602`` () = + let info = + Checker.getCompletionInfo + """type Foo() = + member this.Func (x, y) = () + member this.{caret} +()""" + + Assert.Equal(0, info.Items.Length) + +[] +let ``Expression.InLetScope`` () = + let info = + Checker.getCompletionInfo + """ + module BasicTest + + let p4 = + let isPalindrome x = + let chars = (string x).ToCharArray() + let len = chars.{caret} + chars + |> Array.mapi (fun i c -> (i(*Marker2*), c(*Marker3*))""" + + assertHasItemWithNames [ "IsFixedSize"; "Initialize" ] info + +[] +let ``Expression.InFunScope.FirstParameter`` () = + let info = + Checker.getCompletionInfo + """ + module BasicTest + let p4 = + let isPalindrome x = + let chars = (string x).ToCharArray() + let len = chars(*Marker1*) + chars + |> Array.mapi (fun i c -> (i.{caret}, c(*Marker3*))""" + + assertHasItemWithNames [ "CompareTo" ] info + +[] +let ``Expression.InFunScope.SecParameter`` () = + let info = + Checker.getCompletionInfo + """ + module BasicTest + + let p4 = + let isPalindrome x = + let chars = (string x).ToCharArray() + let len = chars(*Marker1*) + chars + |> Array.mapi (fun i c -> (i(*Marker2*), c.{caret})""" + + assertHasItemWithNames [ "GetType"; "ToString" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.TypeAbbreviations.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.TypeAbbreviations.fs new file mode 100644 index 00000000000..5ea0e9f02e1 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.TypeAbbreviations.fs @@ -0,0 +1,190 @@ +module FSharp.Compiler.Service.Tests.CompletionTypeAbbreviationsTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``Completion.DetectClasses`` () = + let sources = + [ """type X = class + inherit {caret}""" + """[] +type X = + inherit {caret}""" + """[] +type X = class + inherit {caret}""" + """[] +type X() = + inherit {caret}""" ] + + for source in sources do + let info = Checker.getCompletionInfo source + assertHasItemWithNames [ "obj" ] info + +[] +let ``Completion.DetectUnknownCompletionContext`` () = + let info = + Checker.getCompletionInfo + """type X = + inherit {caret}""" + + assertHasItemWithNames [ "obj"; "seq" ] info + +[] +[] + type ObsoleteType() = + member this.TestMethod() = 10 + [] + type CompilerMessageType() = + member this.TestMethod() = 10 + type TestType() = + member this.TestMethod() = 100 + [] + member this.ObsoleteMethod() = 100 + [] + member this.CompilerMessageMethod() = 100 + [] + member this.HiddenMethod() = 10 + [] + member this.VisibleMethod() = 10 + [] + member this.VisibleMethod2() = 10 + namespace NS2 + module m2 = + type x = NS1.MyModule.{caret} + let b = (new NS1.MyModule.TestType())(*MarkerMethod*) + """, + true, "TestType")>] +[] + type ObsoleteType() = + member this.TestMethod() = 10 + [] + type CompilerMessageType() = + member this.TestMethod() = 10 + type TestType() = + member this.TestMethod() = 100 + [] + member this.ObsoleteMethod() = 100 + [] + member this.CompilerMessageMethod() = 100 + [] + member this.HiddenMethod() = 10 + [] + member this.VisibleMethod() = 10 + [] + member this.VisibleMethod2() = 10 + namespace NS2 + module m2 = + type x = NS1.MyModule.{caret} + let b = (new NS1.MyModule.TestType())(*MarkerMethod*) + """, + false, "ObsoleteType;CompilerMessageType")>] +[] + type ObsoleteType() = + member this.TestMethod() = 10 + [] + type CompilerMessageType() = + member this.TestMethod() = 10 + type TestType() = + member this.TestMethod() = 100 + [] + member this.ObsoleteMethod() = 100 + [] + member this.CompilerMessageMethod() = 100 + [] + member this.HiddenMethod() = 10 + [] + member this.VisibleMethod() = 10 + [] + member this.VisibleMethod2() = 10 + namespace NS2 + module m2 = + type x = NS1.MyModule(*MarkerType*) + let b = (new NS1.MyModule.TestType()).{caret} + """, + true, "TestMethod;VisibleMethod;VisibleMethod2")>] +[] + type ObsoleteType() = + member this.TestMethod() = 10 + [] + type CompilerMessageType() = + member this.TestMethod() = 10 + type TestType() = + member this.TestMethod() = 100 + [] + member this.ObsoleteMethod() = 100 + [] + member this.CompilerMessageMethod() = 100 + [] + member this.HiddenMethod() = 10 + [] + member this.VisibleMethod() = 10 + [] + member this.VisibleMethod2() = 10 + namespace NS2 + module m2 = + type x = NS1.MyModule(*MarkerType*) + let b = (new NS1.MyModule.TestType()).{caret} + """, + false, "ObsoleteMethod;CompilerMessageMethod;HiddenMethod")>] +let ``DefInDiffNameSpace`` (markedSource: string) (shouldContain: bool) (names: string) = + let info = Checker.getCompletionInfo markedSource + let expected = names.Split(';') |> List.ofArray + + assertItemsWithNames shouldContain expected info + +[] +let ``Regression1067.InstanceOfGenericType`` () = + let info = + Checker.getCompletionInfo + """ + type GT<'a> = + static member P = 12 + static member Q = 13 + let _ = GT(*Marker1*) + type gt_int = GT + gt_int.{caret} + type D = + class + end + let x = typeof(*Marker3*) + let y = typeof + y(*Marker4*) + """ + + assertHasItemWithNames [ "P"; "Q" ] info + +[] +let ``Regression1067.ClassUsingGenericTypeAsAttribute`` () = + let info = + Checker.getCompletionInfo + """ + type GT<'a> = + static member P = 12 + static member Q = 13 + let _ = GT(*Marker1*) + type gt_int = GT + gt_int(*Marker2*) + type D = + class + end + let x = typeof(*Marker3*) + let y = typeof + y.{caret} + """ + + assertHasItemWithNames [ "Assembly"; "FullName"; "GUID" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.TypeAnnotations.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.TypeAnnotations.fs new file mode 100644 index 00000000000..600aa043991 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.TypeAnnotations.fs @@ -0,0 +1,194 @@ +module FSharp.Compiler.Service.Tests.CompletionTypeAnnotationsTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``Inherit.CompletionInConstructorArguments1`` () = + let info = + Checker.getCompletionInfo + """type A(a : int) = class end +type B() = inherit A(a{caret})""" + + assertHasItemWithNames [ "abs" ] info + +[] +let ``Inherit.CompletionInConstructorArguments2`` () = + let info = + Checker.getCompletionInfo + """type A(a : int) = class end +type B() = inherit A(System.String.{caret})""" + + assertHasItemWithNames [ "Empty" ] info + assertHasNoItemsWithNames [ "Array"; "Collections" ] info + +[] +let ``ProtectedMembers.BaseClass`` () = + let info = + Checker.getCompletionInfo + """type T() = + inherit exn() + member this.Run(x : exn) = x.{caret}""" + + assertHasItemWithNames [ "Message"; "HResult" ] info + +[] +let ``BasicLocalMemberList`` () = + let info = + Checker.getCompletionInfo + """let MyFunction (s:string) = + let y="dog" + y.{caret} + ()""" + + assertHasItemWithNames [ "Substring"; "GetHashCode" ] info + +[] +let ``LocalMemberList.WithPartialMemberEntry1`` () = + let info = + Checker.getCompletionInfo + """let MyFunction (s:string) = + let y="dog" + y.Substri{caret} + ()""" + + assertHasItemWithNames [ "Substring"; "GetHashCode" ] info + +[] +let ``LocalMemberList.WithPartialMemberEntry2`` () = + let info = + Checker.getCompletionInfo + """let MyFunction (s:string) = + let y="dog" + y.{caret}Substri + ()""" + + assertHasItemWithNames [ "Substring"; "GetHashCode" ] info + +[] +let ``MemberInfoCompileErrorsShowInDataTip`` () = + let info = + Checker.getCompletionInfo + """type Foo = + member x.Bar() = 0 +let foovalue:Foo = unbox null +foovalue.B{caret}""" + + assertHasItemWithNames [ "Bar" ] info + +[] +let ``Identifier.Invalid.Bug876b`` () = + let info = + Checker.getCompletionInfo + """let f (x:System.Exception) = x.{caret} + for x = 0 to 0 do () done""" + + assertHasItemWithNames [ "Message"; "StackTrace" ] info + +[] +let ``Identifier.Invalid.Bug876c`` () = + let info = + Checker.getCompletionInfo + """let f (x:System.Exception) = x.{caret} + 12""" + + assertHasItemWithNames [ "Message" ] info + +[] +[] +[] +[] +let ``Identifier.IntBinderDot`` (source: string) = + let info = Checker.getCompletionInfo source + + assertHasItemWithNames [ "ToString"; "Equals" ] info + +[] +[] +[] +[] +let ``Expression.AtomicStringDot`` (source: string) = + let info = Checker.getCompletionInfo source + + assertHasItemWithNames [ "CompareTo"; "ToString" ] info + +[] +let ``Expression.Nested.InLetBind`` () = + let info = + Checker.getCompletionInfo + """ + let f (x : string) = () + // Nested expressions + let x = 42 |> ignore; f ("1" + "1").{caret} + """ + + assertHasItemWithNames [ "Chars"; "Length" ] info + +[] +let ``Expression.Nested.InWhileLoop`` () = + let info = + Checker.getCompletionInfo + """ + let f (x : string) = () + while true do + ignore (f ("1" + "1").{caret}) + """ + + assertHasItemWithNames [ "Chars"; "Length" ] info + +[] +let ``LongIdent.PInvoke.AsReturnType`` () = + let info = + Checker.getCompletionInfo + """ + open System.IO + open System.Runtime.InteropServices + // Get two temp files, write data into one of them + let tempFile1, tempFile2 = Path.GetTempFileName(), Path.GetTempFileName() + let writer = new StreamWriter (tempFile1) + writer.WriteLine("Some Data") + writer.Close() + // Original signature + //[] + //extern bool CopyFile(string lpExistingFileName, string lpNewFileName, bool bFailIfExists); + [] + extern System.{caret} CopyFile_Arrays(char[] lpExistingFileName, char[] lpNewFileName, bool bFailIfExists); + let result = CopyFile_Arrays(tempFile1.ToCharArray(), tempFile2.ToCharArray(), false) + printfn "Array %A" result""" + + assertHasItemWithNames [ "Boolean"; "Int32" ] info + +[] +let ``LongIdent.PInvoke.AsParameterType`` () = + let info = + Checker.getCompletionInfo + """ + open System.IO + open System.Runtime.InteropServices + [] + extern bool CopyFile_ArraySpaces(char [] lpExistingFileName, char []lpNewFileName, System.{caret} bFailIfExists); + let result2 = CopyFile_Arrays(tempFile1.ToCharArray(), tempFile2.ToCharArray(), false) + printfn "Array Space %A" result2""" + + assertHasItemWithNames [ "Boolean"; "Int32" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.TypeExtensions.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.TypeExtensions.fs new file mode 100644 index 00000000000..1417f8df46f --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.TypeExtensions.fs @@ -0,0 +1,58 @@ +module FSharp.Compiler.Service.Tests.CompletionTypeExtensionsTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``ObjectInitializer.CompletionForSettableExtensionProperties`` () = + let info1 = + Checker.getCompletionInfo + """type A() = member this.SetXYZ(v: int) = () +module Ext = type A with member this.XYZ with set(v) = this.SetXYZ(v) +open Ext +A((**){caret})""" + + assertHasItemWithNames [ "XYZ" ] info1 + + let info2 = + Checker.getCompletionInfo + """type A() = member this.SetXYZ(v: int) = () +module Ext = type A with member this.XYZ with set(v) = this.SetXYZ(v) +A((**){caret})""" + + assertHasNoItemsWithNames [ "XYZ" ] info2 + +[] +let ``AfterMethod.Bug2296`` () = + let info = + Checker.getCompletionInfo + """type System.Int32 with + member x.Int32Member() = 0 +"".CompareTo("a").{caret}""" + + assertHasItemWithNames [ "Int32Member" ] info + +[] +let ``AfterMethod.Overloaded.Bug2296`` () = + let info = + Checker.getCompletionInfo + """type System.Boolean with + member x.BooleanMember() = 0 +"".Contains("a").{caret}""" + + assertHasItemWithNames [ "BooleanMember" ] info + +[] +let ``ObjInstance.ExtensionMethods.WithDef.Positive`` () = + let info = + Checker.getCompletionInfo + """ + open System + type System.Random with + member this.NextDice() = true + member this.DiceValue = 6 + let rnd = new System.Random() + rnd.{caret}""" + + assertHasItemWithNames [ "NextDice"; "DiceValue" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.TypeProviders.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.TypeProviders.fs new file mode 100644 index 00000000000..99404c7cbc9 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.TypeProviders.fs @@ -0,0 +1,135 @@ +module FSharp.Compiler.Service.Tests.CompletionTypeProvidersTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``TypeProvider.VisibilityChecksForGeneratedTypes`` () = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| "-r:" + PathRelativeToTestAssembly("DummyProviderForLanguageServiceTesting.dll") |] + FSharpCodeCompletionOptions.Default + """ +type T = GeneratedType.SampleType +let t = T(5) +t.{caret}""" + + assertHasItemWithNames [ "PublicM"; "PublicProp" ] info + assertHasNoItemsWithNames [ "f"; "ProtectedProp"; "PrivateProp"; "ProtectedM"; "PrivateM" ] info + +[] +let ``TypeProvider.EditorHideMethodsAttribute.InstanceMethod.CtrlSpaceCompletionContains`` () = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| "-r:" + PathRelativeToTestAssembly("DummyProviderForLanguageServiceTesting.dll") |] + FSharpCodeCompletionOptions.Default + """ +let t = new N1.T1() +t.I{caret}""" + + assertHasItemWithNames [ "IM1" ] info + +[] +let ``TypeProvider.EditorHideMethodsAttribute.Event.CtrlSpaceCompletionContains`` () = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| "-r:" + PathRelativeToTestAssembly("EditorHideMethodsAttribute.dll") |] + FSharpCodeCompletionOptions.Default + """ +let t = new N.T() +t.Eve{caret}""" + + assertHasItemWithNames [ "Event1" ] info + +[] +let ``TypeProvider.EditorHideMethodsAttribute.Type.CtrlSpaceCompletionContains`` () = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| "-r:" + PathRelativeToTestAssembly("DummyProviderForLanguageServiceTesting.dll") |] + FSharpCodeCompletionOptions.Default + """ +type boo = N1.T] +let ``TypeProvider.EditorHideMethodsAttribute.Type.DoesnotContain`` () = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| "-r:" + PathRelativeToTestAssembly("EditorHideMethodsAttribute.dll") |] + FSharpCodeCompletionOptions.Default + """ +let t = new N.T() +t.{caret}""" + + assertHasNoItemsWithNames [ "Equals"; "GetHashCode" ] info + +[] +let ``TypeProvider.EditorHideMethodsAttribute.Type.Contains`` () = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| "-r:" + PathRelativeToTestAssembly("EditorHideMethodsAttribute.dll") |] + FSharpCodeCompletionOptions.Default + """ +let t = new N.T() +t.{caret}""" + + assertHasItemWithNames [ "Event1" ] info + +[] +let ``TypeProvider.EditorHideMethodsAttribute.InstanceMethod.Contains`` () = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| "-r:" + PathRelativeToTestAssembly("DummyProviderForLanguageServiceTesting.dll") |] + FSharpCodeCompletionOptions.Default + """ +let t = new N1.T1() +t.{caret}""" + + assertHasItemWithNames [ "IM1" ] info + +[] +let ``TypeProvider.TypeContainsNestedType`` () = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| "-r:" + PathRelativeToTestAssembly("DummyProviderForLanguageServiceTesting.dll") |] + FSharpCodeCompletionOptions.Default + """ +type XXX = N1.T1.{caret}""" + + assertHasItemWithNames [ "SomeNestedType" ] info + +[] +let ``TypeProvider.EditorHideMethodsAttribute.Event.Contain`` () = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| "-r:" + PathRelativeToTestAssembly("EditorHideMethodsAttribute.dll") |] + FSharpCodeCompletionOptions.Default + """ +let t = new N.T() +t.Event1.{caret}""" + + assertHasItemWithNames [ "AddHandler"; "RemoveHandler" ] info + +[] +let ``TypeProvider.EditorHideMethodsAttribute.Method.Contain`` () = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| "-r:" + PathRelativeToTestAssembly("EditorHideMethodsAttribute.dll") |] + FSharpCodeCompletionOptions.Default + """ +let t = N.T.M.{caret}()""" + + Assert.Equal(0, info.Items.Length) + +[] +let ``TypeProvider.EditorHideMethodsAttribute.Property.Contain`` () = + let info = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| "-r:" + PathRelativeToTestAssembly("EditorHideMethodsAttribute.dll") |] + FSharpCodeCompletionOptions.Default + """ +let t = N.T.StaticProp.{caret}""" + + assertHasItemWithNames [ "GetType"; "Equals" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.UnitsOfMeasure.fs b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.UnitsOfMeasure.fs new file mode 100644 index 00000000000..24cd49b8049 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Completion/CompletionTests.UnitsOfMeasure.fs @@ -0,0 +1,90 @@ +module FSharp.Compiler.Service.Tests.CompletionUnitsOfMeasureTests + +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open Xunit + +[] +let ``UnitMeasure.Bug78932_1`` () = + let info = + Checker.getCompletionInfo + """ + module M1 = + [] type Kg + + module M2 = + let f = 1 // <- type . between M1 and ' >' => works""" + + assertHasItemWithNames [ "Kg" ] info + +[] +let ``UnitMeasure.Bug78932_2`` () = + let info = + Checker.getCompletionInfo + """ + module M1 = + [] type Kg + + module M2 = + let f = 1 // <- type . between M1 and '>' => no popup intellisense""" + + assertHasItemWithNames [ "Kg" ] info + +[] +let ``UnitMeasure.UnitNames`` () = + let info = + Checker.getCompletionInfo + """Microsoft.FSharp.Data.UnitSystems.SI.UnitNames.{caret}""" + + assertHasItemWithNames + [ "ampere"; "becquerel"; "candela"; "coulomb"; "farad"; "gray"; "henry"; "hertz"; "joule"; "katal"; "kelvin"; "kilogram"; "lumen"; "lux"; "metre"; "mole"; "newton"; "ohm"; "pascal"; "second"; "siemens"; "sievert"; "tesla"; "volt"; "watt"; "weber" ] + info + +[] +let ``UnitMeasure.UnitSymbols`` () = + let info = + Checker.getCompletionInfo + """Microsoft.FSharp.Data.UnitSystems.SI.UnitSymbols.{caret}""" + + assertHasItemWithNames + [ "A"; "Bq"; "C"; "F"; "Gy"; "H"; "Hz"; "J"; "K"; "N"; "Pa"; "S"; "Sv"; "T"; "V"; "W"; "Wb"; "cd"; "kat"; "kg"; "lm"; "lx"; "m"; "mol"; "ohm"; "s" ] + info + +[] +[] 'a> = [1; 2; 3] + let f (x:MyNamespace1.MyModule(*Maftervariable4*)) = 10 + let y = int System.IO(*Maftervariable5*)""")>] +[] 'a> = 10""")>] +let ``UnitMeasure.AsTypeParameter.DefFromDiffNamespace`` (markedSource: string) = + let info = Checker.getCompletionInfo markedSource + + assertHasItemWithNames [ "DuType"; "Pet"; "Dog" ] info diff --git a/tests/FSharp.Compiler.Service.Tests/CompletionTests.fs b/tests/FSharp.Compiler.Service.Tests/CompletionTests.fs index f1dd58b7edd..fb359909d0f 100644 --- a/tests/FSharp.Compiler.Service.Tests/CompletionTests.fs +++ b/tests/FSharp.Compiler.Service.Tests/CompletionTests.fs @@ -6,23 +6,6 @@ open FSharp.Test.Assert open FSharp.Test.Compiler.Assertions.TextBasedDiagnosticAsserts open Xunit -let private assertItemsWithNames contains names (completionInfo: DeclarationListInfo) = - let itemNames = - completionInfo.Items - |> Array.map _.NameInCode - |> Array.map normalizeNewLines - |> set - - for name in names do - let name = normalizeNewLines name - Set.contains name itemNames |> shouldEqual contains - -let assertHasItemWithNames names (completionInfo: DeclarationListInfo) = - assertItemsWithNames true names completionInfo - -let assertHasNoItemsWithNames names (completionInfo: DeclarationListInfo) = - assertItemsWithNames false names completionInfo - [] let ``Expr - After record decl 01`` () = let info = Checker.getCompletionInfo """ @@ -439,9 +422,6 @@ module Options = let assertItemAllowed name source = assertItemWithOptions [allowObsoleteOptions] name source - let assertItemNotAllowed name source = - assertItemWithOptions [disallowObsoleteOptions] name source - [] let ``Prop - Instance 01`` () = assertItem "Prop" """ diff --git a/tests/FSharp.Compiler.Service.Tests/EditorServiceAsserts.fs b/tests/FSharp.Compiler.Service.Tests/EditorServiceAsserts.fs new file mode 100644 index 00000000000..d32b76d097b --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/EditorServiceAsserts.fs @@ -0,0 +1,530 @@ +namespace FSharp.Compiler.Service.Tests + +open System +open System.IO +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.Diagnostics +open FSharp.Compiler.EditorServices +open FSharp.Compiler.IO +open FSharp.Compiler.Symbols +open FSharp.Compiler.Tokenization +open FSharp.Test.Compiler.Assertions.TextBasedDiagnosticAsserts +open TestFramework + +[] +module EditorServiceAsserts = + let private markAtOffset (offsetInMarker: string -> int) (source: string) (marker: string) = + match source.IndexOf(marker, StringComparison.Ordinal) with + | -1 -> failwithf "Marker %A not found in source" marker + | i -> source.Insert(i + offsetInMarker marker, "{caret}") + + let markAtStartOfMarker = markAtOffset (fun _ -> 0) + + let markAtEndOfMarker = markAtOffset (fun marker -> marker.Length) + + let findCompletionItem (name: string) (completionInfo: DeclarationListInfo) = + let norm = normalizeNewLines name + + match completionInfo.Items |> Array.tryFind (fun i -> normalizeNewLines i.NameInCode = norm || i.NameInList = name) with + | Some item -> item + | None -> + let names = completionInfo.Items |> Array.map _.NameInCode |> String.concat ", " + failwithf "Expected a completion item named %A but found none. Items: [%s]" name names + + let assertItemGlyph (name: string) (glyph: FSharpGlyph) (completionInfo: DeclarationListInfo) = + let item = findCompletionItem name completionInfo + + if item.Glyph <> glyph then + failwithf "Item %A has glyph %A but expected %A" name item.Glyph glyph + + let groupMainDescriptions (ToolTipText elements) = + elements + |> List.collect (fun e -> + match e with + | ToolTipElement.Group items -> items |> List.map (fun d -> taggedTextToString d.MainDescription) + | _ -> []) + + let flattenItemDescription (tooltip: ToolTipText) = + groupMainDescriptions tooltip |> String.concat "\n" + + let assertItemDescriptionOccurrences (expected: int) (itemName: string) (token: string) (completionInfo: DeclarationListInfo) = + let item = findCompletionItem itemName completionInfo + let descr = flattenItemDescription item.Description + let occurrences = descr.Split([| token |], StringSplitOptions.None).Length - 1 + + if occurrences <> expected then + failwithf "Item %A: expected %d occurrence(s) of %A but found %d (description: %s)" itemName expected token occurrences descr + + let assertItemDescriptionContainsExactlyOnce itemName token completionInfo = + assertItemDescriptionOccurrences 1 itemName token completionInfo + + let private itemsWithPrefix (prefix: string) (ignoreCase: bool) (completionInfo: DeclarationListInfo) = + let cmp = + if ignoreCase then StringComparison.OrdinalIgnoreCase else StringComparison.Ordinal + + completionInfo.Items + |> Array.map _.NameInCode + |> Array.filter (fun n -> n.StartsWith(prefix, cmp)) + + let private assertPrefixUniqueness (unique: bool) (prefix: string) (ignoreCase: bool) (completionInfo: DeclarationListInfo) = + let matches = itemsWithPrefix prefix ignoreCase completionInfo + let ok = if unique then matches.Length = 1 else matches.Length >= 2 + + if not ok then + let expectation = if unique then "exactly ONE item" else "AT LEAST TWO items" + + failwithf "Expected %s whose NameInCode start(s) with %A (ignoreCase=%b) but found %d: [%s]" + expectation prefix ignoreCase matches.Length (String.concat ", " matches) + + let assertPrefixIsUnique = assertPrefixUniqueness true + + let assertPrefixIsNotUnique = assertPrefixUniqueness false + + let private expectedLineOf (definitionLine: string) (sourceLines: string array) = + match sourceLines |> Array.indexed |> Array.filter (fun (_, l) -> l.Contains definitionLine) with + | [| (i, _) |] -> i + 1 + | [||] -> failwithf "Definition line containing %A was not found in the source" definitionLine + | many -> + failwithf + "Definition line %A is AMBIGUOUS — it matches %d source lines (1-based: %A); use a more specific substring" + definitionLine many.Length (many |> Array.map (fun (i, _) -> i + 1)) + + let private assertLandedOnLine (landedPrefix: string) (definitionLine: string) (sourceLines: string array) (expectedLine: int) result = + match result with + | FindDeclResult.DeclFound range when range.StartLine = expectedLine -> () + | FindDeclResult.DeclFound range -> + let landedText = + if range.StartLine >= 1 && range.StartLine <= sourceLines.Length then + sourceLines.[range.StartLine - 1] + else + "" + + failwithf "%s landed on line %d (%s) but expected line %d (containing %A)" + landedPrefix range.StartLine landedText expectedLine definitionLine + | other -> + failwithf "Expected FindDeclResult.DeclFound on line %d (containing %A) but got %A" + expectedLine definitionLine other + + let assertGoToDefinitionOnLine (definitionLine: string) (markedSource: string) = + let context, checkResults = Checker.getCheckedResolveContext markedSource + let result = + checkResults.GetDeclarationLocation(context) + + let sourceLines = context.Source.Replace("\r\n", "\n").Split('\n') + let expectedLine = expectedLineOf definitionLine sourceLines + assertLandedOnLine "Goto-def" definitionLine sourceLines expectedLine result + + /// Goto-def on a source carrying several ordered carets ({caret1}, {caret2}, ...), + /// pairing each caret (in order) with its expected definition line. + let assertGoToDefinitionOnLines (definitionLines: string list) (orderedMarkedSource: string) = + let markedSources = SourceContext.extractOrderedMarkedSources orderedMarkedSource + if List.length definitionLines <> List.length markedSources then + failwithf "Expected %d definition line(s) but the source has %d caret(s)" + (List.length definitionLines) (List.length markedSources) + List.iter2 assertGoToDefinitionOnLine definitionLines markedSources + + let assertGoToDefinitionFails (markedSource: string) = + match Checker.getDeclarationLocation markedSource with + | FindDeclResult.DeclFound range -> + failwithf "Expected goto-def to fail (not DeclFound), but it found a definition at %A" range + | _ -> () + + let assertGoToDefinitionIsExternal (markedSource: string) = + match Checker.getDeclarationLocation markedSource with + | FindDeclResult.ExternalDecl _ -> () + | other -> + failwithf "Expected FindDeclResult.ExternalDecl (resolved-but-external), but got %A" other + + let assertGoToDefinitionOperatorOnLine (definitionLine: string) (operatorName: string) (markedSource: string) = + let context, checkResults = Checker.getCheckedResolveContext markedSource + let result = + checkResults.GetDeclarationLocation(context.Pos.Line, context.Pos.Column + 1, context.LineText, [ operatorName ]) + + let sourceLines = context.Source.Replace("\r\n", "\n").Split('\n') + let expectedLine = expectedLineOf definitionLine sourceLines + assertLandedOnLine "Operator goto-def" definitionLine sourceLines expectedLine result + + let assertGoToDefinitionToExternalLine (definitionLine: string) (markedSource: string) = + match Checker.getDeclarationLocation markedSource with + | FindDeclResult.DeclFound range when File.Exists range.FileName -> + let landedLines = + File.ReadAllText(range.FileName).Replace("\r\n", "\n").Split('\n') + + let landedText = + if range.StartLine >= 1 && range.StartLine <= landedLines.Length then + landedLines.[range.StartLine - 1] + else + "" + + if not (landedText.Contains definitionLine) then + failwithf "Goto-def landed on %s:%d (%s) but expected a line containing %A" + range.FileName range.StartLine landedText definitionLine + | FindDeclResult.DeclFound _ -> () + | other -> + failwithf "Expected FindDeclResult.DeclFound on a line containing %A but got %A" definitionLine other + + let assertNoDiagnostics (results: FSharpCheckFileResults) = + match dumpDiagnostics results with + | [] -> () + | msgs -> + failwithf "Expected no diagnostics, but got %d:\n%s" msgs.Length (String.concat "\n" msgs) + + let assertDiagnosticCount (expected: int) (results: FSharpCheckFileResults) = + let msgs = dumpDiagnostics results |> List.distinct + if msgs.Length <> expected then + failwithf "Expected %d distinct diagnostic(s), but got %d:\n%s" expected msgs.Length (String.concat "\n" msgs) + + let assertDiagnosticsContain (expected: string) (results: FSharpCheckFileResults) = + let messages = results.Diagnostics |> Array.map normalizeDiagnosticMessage + if not (messages |> Array.exists (fun m -> m.Contains expected)) then + let dump = dumpDiagnostics results + failwithf "Expected a diagnostic message containing %A, but got %d:\n%s" + expected dump.Length (String.concat "\n" dump) + + let assertSingleDiagnosticContainingAll (parts: string list) (results: FSharpCheckFileResults) = + let dump = dumpDiagnostics results |> List.distinct + match dump with + | [ single ] -> + match parts |> List.filter (fun p -> not (single.Contains p)) with + | [] -> () + | missing -> + failwithf "Single diagnostic is missing expected part(s) %A:\n%s" missing single + | _ -> + failwithf "Expected exactly 1 distinct diagnostic, but got %d:\n%s" + dump.Length (String.concat "\n" dump) + + let assertWarningCount (expected: int) (results: FSharpCheckFileResults) = + let warnings = dumpDiagnosticsOfSeverity FSharpDiagnosticSeverity.Warning results |> List.distinct + + if warnings.Length <> expected then + failwithf "Expected %d warning(s), but got %d:\n%s" + expected warnings.Length (String.concat "\n" warnings) + + let checkAsFsFile (source: string) = + let fileName, options = mkTestFileAndOptions [||] + let _, checkResults = parseAndCheckFile fileName source options + checkResults + + let getTooltipWithReferences (name: string) (references: string list) (markedSource: string) = + let context = Checker.getResolveContext markedSource + let fileName = name + ".fsx" + + let args = + [| "--simpleresolution" + "--noframework" + "--debug:full" + "--define:DEBUG" + "--optimize-" + "--out:" + name + ".dll" + "--warn:3" + "--fullpaths" + "--flaterrors" + "--target:library" + yield! references |> List.map (fun r -> "-r:" + r) |] + + let options = + { checker.GetProjectOptionsFromCommandLineArgs(name + ".fsproj", args) with + SourceFiles = [| fileName |] } + + let _, checkResults = parseAndCheckFile fileName context.Source options + checkResults.GetTooltip(context) + + let foldToolTip (ToolTipText items) = + items + |> List.collect (fun item -> + match item with + | ToolTipElement.Group elements -> + elements + |> List.collect (fun e -> + [ taggedTextToString e.MainDescription + match e.XmlDoc with + | FSharpXmlDoc.FromXmlText xmlDoc -> String.concat "\n" xmlDoc.UnprocessedLines + | _ -> "" + match e.Remarks with + | Some r -> taggedTextToString r + | None -> "" ]) + | ToolTipElement.CompositionError err -> [ err ] + | ToolTipElement.None -> []) + |> String.concat "\n" + + type TooltipSource = + | Script + | FsFile + + let foldedTooltip (mode: TooltipSource) (markedSource: string) : string = + match mode with + | Script -> foldToolTip (Checker.getTooltip markedSource) + | FsFile -> + let context = Checker.getResolveContext markedSource + let checkResults = checkAsFsFile context.Source + + checkResults.GetTooltip(context) + |> foldToolTip + + let private tooltipSourceLabel mode = + match mode with + | Script -> "tooltip" + | FsFile -> ".fs-file tooltip" + + let assertFoldedTooltipContains (contains: bool) (label: string) (expected: string) (actual: string) = + if actual.Contains expected <> contains then + let relation = if contains then "to contain" else "NOT to contain" + failwithf "Expected %s %s %A, but the actual tooltip was:\n%s" label relation expected actual + + let private assertTooltip (contains: bool) (mode: TooltipSource) (expected: string) (markedSource: string) = + assertFoldedTooltipContains contains (tooltipSourceLabel mode) expected (foldedTooltip mode markedSource) + + let assertTooltipContains = assertTooltip true Script + + let walk (source: string) (initial: string) (ident: string) (expected: string) = + let baseIndex = source.IndexOf(initial, StringComparison.Ordinal) + + for i in 0 .. ident.Length - 1 do + let marked = source.Insert(baseIndex + initial.Length + i + 1, "{caret}") + assertTooltipContains expected marked + + let assertTooltipDoesNotContain = assertTooltip false Script + + let assertIdentifierInTooltipExactlyOnce (ident: string) (markedSource: string) = + let actual = foldToolTip (Checker.getTooltip markedSource) + + if not (actual.Contains ident) then + failwithf "Expected tooltip to contain %A at least once (non-vacuity), but the actual tooltip was:\n%s" ident actual + + let count = + actual.Split([| '='; '.'; ' '; '\t'; '('; ':'; ')'; '\n'; '\r' |]) + |> Array.filter ((=) ident) + |> Array.length + + if count <> 1 then + failwithf "Expected identifier %A to occur exactly once in the tooltip, but it occurred %d time(s):\n%s" ident count actual + + let assertStringContainsInOrder (parts: string list) (actual: string) = + let mutable fromIndex = 0 + for part in parts do + match actual.IndexOf(part, fromIndex, StringComparison.Ordinal) with + | -1 -> + failwithf "Expected tooltip to contain %A after index %d (in order), but the actual tooltip was:\n%s" + part fromIndex actual + | index -> fromIndex <- index + part.Length + + let assertTooltipContainsInOrder (parts: string list) (markedSource: string) = + let actual = foldToolTip (Checker.getTooltip markedSource) + assertStringContainsInOrder parts actual + + let assertCompletionItemTooltipContainsInOrder (itemName: string) (parts: string list) (markedSource: string) = + let item = findCompletionItem itemName (Checker.getCompletionInfo markedSource) + assertStringContainsInOrder parts (foldToolTip item.Description) + + let assertTooltipContainsInFsFile = assertTooltip true FsFile + + let assertTooltipDoesNotContainInFsFile = assertTooltip false FsFile + + let fsTestLibCode = """namespace FSTestLib + + /// DocComment: This is MyStruct type, represents a struct. + type MyPoint = + struct + val mutable private m_X : float + val mutable private m_Y : float + + new (x, y) = { m_X = x; m_Y = y } + + /// Gets and sets X + member this.X with get () = this.m_X and set x = this.m_X <- x + + /// Gets and sets Y + member this.Y with get () = this.m_Y and set y = this.m_Y <- y + + // Length of given Point + member this.Len = sqrt ( this.X * this.X + this.Y * this.Y ) + + static member (+) (p1 : MyPoint, p2 : MyPoint) = MyPoint(p1.X + p2.X, p1.Y + p2.Y) + + end + + [] + /// DocComment: This is my record type. + type MyEmployee = + { mutable Name : string; + mutable Age : int; + /// DocComment: Indicates whether the employee is full time or not + mutable IsFTE : bool } + + interface System.IComparable with + member this.CompareTo (emp : obj) = + let r = emp :?> MyEmployee + match r.IsFTE && this.IsFTE with + | true -> this.Age - r.Age + | _ -> System.Convert.ToInt32(this.IsFTE) - System.Convert.ToInt32(r.IsFTE) + + override this.ToString() = sprintf "%s is %d." this.Name this.Age + + /// DocComment: Method + static member MakeDummy () = + { Name = System.String.Empty; Age = -1; IsFTE = false } + + // TODO: Normally there's no DotCompletion after "this" here + override this.Equals(ob : obj) = + let r = ob :?> MyEmployee + this.Name = r.Name && this.Age = r.Age && this.IsFTE = r.IsFTE + + /// DocComment: This is my interface type + type IMyInterface = + interface + /// DocComment: abstract method in Interface + abstract Represent : unit -> string + end + + // TODO: add formatable ToString() + /// DocComment: This is my discriminated union type + type MyDistance = + | Kilometers of float + | Miles of float + | NauticalMiles of float + + + /// DocComment: Static Method + static member toMiles x = + Miles( + match x with + | Miles x -> x + | Kilometers x -> x / 1.6 + | NauticalMiles x -> x * 1.15 + ) + + /// DocComment: Property + member this.toNautical = + NauticalMiles( + match this with + | Kilometers x -> x / 1.852 + | Miles x -> x / 1.15 + | NauticalMiles x -> x + ) + + /// DocComment: Method + member this.IncreaseBy dist = + match this with + | Kilometers x -> Kilometers (x + dist) + | Miles x -> Miles (x + dist) + | NauticalMiles x -> NauticalMiles (x + dist) + + /// DocComment: Event + static member Event = + let evnt = new Event() + evnt + + /// DocComment: This is my enum type + type MyColors = + | /// DocComment: Field + Red = 0 + | Green = 1 + | Blue = 2 + + /// DocComment: This is my class type + type MyCar( number: int, color:MyColors) = + /// DocComment: This is static field + static member Owner = "MySelf" + /// DocComment: This is instance field + member this.Number = number + member this.Color = color + /// DocComment: This is static method + static member Run (number:int) = printf "%s" (number.ToString()+"Running") + /// DocComment: This is instance method + member this.Repair (expense:int) = printf "%s" ("Spent " + expense.ToString() + " for repairing. ") + + /// DocComment: This is my delegate type + type ControlEventHandler = delegate of int -> unit""" + + let foldedProjectTooltip (priorFiles: string list) (extraRefs: string list) (markedSource: string) = + let context = Checker.getResolveContext markedSource + let options = createProjectOptions (priorFiles @ [ context.Source ]) [ for r in extraRefs -> "-r:" + r ] + let queriedPath = Array.last options.SourceFiles + let _, checkResults = parseAndCheckFile queriedPath context.Source options + checkResults.GetTooltip(context) |> foldToolTip + + let assertTooltipContainsWithFsTestLib (expected: string) (markedFile2: string) = + foldedProjectTooltip [ fsTestLibCode ] [] markedFile2 + |> assertFoldedTooltipContains true "FSTestLib two-file tooltip" expected + + let assertCompleteIdentifierIslandWithTolerate (tolerate: bool) (expected: string option) (sourceWithCaretMarker: string) = + let n = sourceWithCaretMarker.IndexOf '$' + if n < 0 then failwith "source must contain the '$' caret marker" + let line = sourceWithCaretMarker.Remove(n, 1) + + match QuickParse.GetCompleteIdentifierIsland tolerate line n, expected with + | Some(island, _, _), Some exp -> + if island <> exp then + failwithf "tolerate=%b: GetCompleteIdentifierIsland returned island %A but expected %A (line=%A col=%d)" tolerate island exp line n + | None, None -> () + | Some(island, _, _), None -> + failwithf "tolerate=%b: expected NO island but got %A (line=%A col=%d)" tolerate island line n + | None, Some exp -> + failwithf "tolerate=%b: expected island %A but got None (line=%A col=%d)" tolerate exp line n + + let assertCompleteIdentifierIsland (expected: string option) (sourceWithCaretMarker: string) = + assertCompleteIdentifierIslandWithTolerate true expected sourceWithCaretMarker + assertCompleteIdentifierIslandWithTolerate false expected sourceWithCaretMarker + + let private getMethodGroup (markedSource: string) = + let context, checkResults = Checker.getCheckedResolveContext markedSource + checkResults.GetMethods(context.Pos.Line, context.Pos.Column, context.LineText, Some context.Names) + + let private paramDisplays (m: MethodGroupItem) = + m.Parameters |> Array.map (fun p -> taggedTextToString p.Display) |> Array.toList + + let private describeMethodGroup (mg: MethodGroup) = + if mg.Methods.Length = 0 then + " " + else + mg.Methods + |> Array.mapi (fun i m -> sprintf " [%d] %s" i (String.concat ", " (paramDisplays m))) + |> String.concat "\n" + + let private displaysMatch (expected: string list) (displays: string list) = + expected.Length = displays.Length + && List.forall2 (fun (e: string) (d: string) -> d.Contains e) expected displays + + let assertParameterInfoOverloads (expected: string list list) (markedSource: string) = + let mg = getMethodGroup markedSource + if mg.Methods.Length <> expected.Length then + failwithf "Expected %d overload(s) but got %d:\n%s" expected.Length mg.Methods.Length (describeMethodGroup mg) + for m in mg.Methods do + let displays = paramDisplays m + let matched = expected |> List.exists (fun exp -> displaysMatch exp displays) + if not matched then + failwithf "Overload [%s] matched no expected set %A:\n%s" (String.concat ", " displays) expected (describeMethodGroup mg) + + let assertNoParameterInfo (markedSource: string) = + let mg = getMethodGroup markedSource + if mg.Methods.Length <> 0 then + failwithf "Expected no parameter info but got %d overload(s):\n%s" mg.Methods.Length (describeMethodGroup mg) + + let assertParameterInfoContains (expected: string list) (markedSource: string) = + let mg = getMethodGroup markedSource + let matched = + mg.Methods + |> Array.exists (fun m -> displaysMatch expected (paramDisplays m)) + if not matched then + failwithf "No overload matched expected %A:\n%s" expected (describeMethodGroup mg) + + let assertParameterInfoOverloadIndex (idx: int) (expected: string list) (markedSource: string) = + let mg = getMethodGroup markedSource + if idx < 0 || idx >= mg.Methods.Length then + failwithf "No overload at index %d (have %d):\n%s" idx mg.Methods.Length (describeMethodGroup mg) + let displays = paramDisplays mg.Methods[idx] + if not (displaysMatch expected displays) then + failwithf "Overload [%d] = [%s] did not match expected %A:\n%s" idx (String.concat ", " displays) expected (describeMethodGroup mg) + + let assertHasParameterInfo (markedSource: string) = + let mg = getMethodGroup markedSource + if mg.Methods.Length = 0 then + failwith "Expected a method group with parameter info, but got none" + + let assertFirstReturnTypeText (expected: string) (markedSource: string) = + let mg = getMethodGroup markedSource + if mg.Methods.Length = 0 then + failwithf "Expected a method group, but got none. Looking for return type %A" expected + let actual = taggedTextToString mg.Methods[0].ReturnTypeText + if actual <> expected then + failwithf "Expected first overload return type %A but got %A:\n%s" expected actual (describeMethodGroup mg) diff --git a/tests/FSharp.Compiler.Service.Tests/EditorTests.fs b/tests/FSharp.Compiler.Service.Tests/EditorTests.fs index 47ad18e8633..be06517681c 100644 --- a/tests/FSharp.Compiler.Service.Tests/EditorTests.fs +++ b/tests/FSharp.Compiler.Service.Tests/EditorTests.fs @@ -1991,15 +1991,6 @@ let hasRecordType (recordTypeName: string) (symbolUses: FSharpSymbolUse list) = ) |> fun exists -> Assert.True(exists, $"Record type {recordTypeName} not found.") -let private assertItemsWithNames contains names (completionInfo: DeclarationListInfo) = - let itemNames = completionInfo.Items |> Array.map _.NameInCode |> set - - for name in names do - Assert.True(Set.contains name itemNames = contains) - -let assertHasItemWithNames names (completionInfo: DeclarationListInfo) = - assertItemsWithNames true names completionInfo - [] let ``Record fields are completed via type name usage`` () = let parseResults, checkResults = diff --git a/tests/FSharp.Compiler.Service.Tests/ErrorList/ErrorListTests.fs b/tests/FSharp.Compiler.Service.Tests/ErrorList/ErrorListTests.fs new file mode 100644 index 00000000000..d77e04af881 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ErrorList/ErrorListTests.fs @@ -0,0 +1,483 @@ +module FSharp.Compiler.Service.Tests.ErrorListTests + +open Xunit +open FSharp.Test + +[] +let ``OverloadsAndExtensionMethodsForGenericTypes`` () = + let _, checkResults = getParseAndCheckResults """ +open System.Linq + +type T = + abstract Count : int -> bool + default this.Count(_ : int) = true + + interface System.Collections.Generic.IEnumerable with + member this.GetEnumerator() : System.Collections.Generic.IEnumerator = failwith "not implemented" + interface System.Collections.IEnumerable with + member this.GetEnumerator() : System.Collections.IEnumerator = failwith "not implemented" + +let g (t : T) = t.Count() +""" + assertNoDiagnostics checkResults + +[] +let ``ErrorsInScriptFile`` () = + let _, checkResults = getParseAndCheckResultsUniqueName "#r \"System\"\n#r \"System2\"\n" + assertDiagnosticCount 1 checkResults + assertDiagnosticsContain "Assembly reference 'System2' was not found or is invalid" checkResults + +[] +let ``LineDirective`` () = + let _, checkResults = getParseAndCheckResults """ +# 100 "foo.fs" +let x = y +""" + assertDiagnosticsContain "The value or constructor 'y' is not defined" checkResults + +[] +let ``InvalidConstructorOverload`` () = + let _, checkResults = getParseAndCheckResults """ +type X private() = + new(_ : int) = X() + new(_ : bool) = X() + new(_ : float, _ : int) = X() +X(1.0) +""" + assertSingleDiagnosticContainingAll + [ "No overloads match for method 'X'." + "Available overloads:" + "new: bool -> X" + "new: int -> X" ] + checkResults + +[] +let ``Query.InvalidJoinRelation.GroupJoin`` () = + let _, checkResults = getParseAndCheckResults """ +let x = query { + for x in [1] do + groupJoin y in [2] on ( x < y) into g + select x } +""" + assertDiagnosticsContain "Invalid join relation in 'groupJoin'." checkResults + +[] +[] +[] +let ``Query.NonOpenedNullableModule - nullable operator cannot be resolved`` (source: string) = + let _, checkResults = getParseAndCheckResults source + assertDiagnosticsContain "The operator '?=?' cannot be resolved." checkResults + +[] +let ``Query.InvalidJoinRelation.Join`` () = + let _, checkResults = getParseAndCheckResults """ +let x = + query { + for x in [1] do + join y in [""] on (x > y) + select 1 + } +""" + assertDiagnosticsContain "Invalid join relation in 'join'." checkResults + +let invalidMethodOverloadCases: obj[] seq = + [ + [| box """ +System.Console.WriteLine(null) +""" + box [ "A unique overload for method 'WriteLine' could not be determined" + "Candidates:" + "System.Console.WriteLine(value: obj) : unit" + "System.Console.WriteLine(value: string) : unit" ] |] + [| box """ +type A<'T>() = + member this.Do(a : int, b : 'T) = () + member this.Do(a : int, b : int) = () +type B() = + inherit A() + +let b = B() +b.Do(1, 1) +""" + box [ "A unique overload for method 'Do' could not be determined" + "Candidates:" + "member A.Do: a: int * b: 'T -> unit" + "member A.Do: a: int * b: int -> unit" ] |] + ] + +[] +let ``InvalidMethodOverload`` (source: string) (expectedParts: string list) = + let _, checkResults = getParseAndCheckResults source + assertSingleDiagnosticContainingAll expectedParts checkResults + +[] +let ``NoErrorInErrList`` () = + let _, checkResults = getParseAndCheckResults """ +module NoErrors2 + +module DictionaryExtension = + + type System.Collections.Generic.IDictionary<'k,'v> with + member this.TryLookup(key : 'k) = + let mutable value = Unchecked.defaultof<'v> + if this.TryGetValue(key, &value) then + Some value + else + None + +open DictionaryExtension +""" + assertNoDiagnostics checkResults + +[] +let ``NoLevel4Warning`` () = + let _, checkResults = getParseAndCheckResults """ +namespace testerrorlist +module nolevel4warnings = + let x = System.DateTime.Now - System.DateTime.Now + x.Add(x) |> ignore +""" + assertNoDiagnostics checkResults + +[] +let ``TestWrongKeywordInInterfaceImplementation`` () = + let _, checkResults = getParseAndCheckResults """ +type staticInInterface = + class + interface System.IDisposable with + static member Foo() = () + member x.Dispose() = () + end + end +""" + assertDiagnosticsContain "No static abstract member was found that corresponds to this override" checkResults + +[] +let ``TypeProvider.MultipleErrors`` () = + let _, checkResults = getParseAndCheckResults "type Err = TPErrors.TP<1>" + assertDiagnosticsContain "type provider" checkResults + +[] +let ``Records.ErrorList.IncorrectBindings1`` () = + for code in [ "{_}"; "{_ = }" ] do + let _, checkResults = getParseAndCheckResults code + assertDiagnosticCount 2 checkResults + assertDiagnosticsContain "Field bindings must have the form 'id = expr;'" checkResults + assertDiagnosticsContain "'_' cannot be used as field name" checkResults + +[] +let ``Records.ErrorList.IncorrectBindings2`` () = + let _, checkResults = getParseAndCheckResults "{_ = 1}" + assertDiagnosticCount 1 checkResults + assertDiagnosticsContain "'_' cannot be used as field name" checkResults + +[] +let ``Records.ErrorList.IncorrectBindings3`` () = + let _, checkResults = getParseAndCheckResults "{a = 1; _; _ = 1}" + assertDiagnosticCount 3 checkResults + let messages = dumpDiagnostics checkResults |> List.distinct + Assert.Equal(2, messages |> List.filter (fun m -> m.Contains "'_' cannot be used as field name") |> List.length) + Assert.Equal(1, messages |> List.filter (fun m -> m.Contains "Field bindings must have the form 'id = expr;'") |> List.length) + +[] +let ``TypeProvider.StaticParameters.IncorrectType`` () = + let _, checkResults = getParseAndCheckResults """type foo = N1.T< const 42,2>""" + assertDiagnosticsContain "but here has type" checkResults + +[] +let ``TypeProvider.StaticParameters.Incorrect`` () = + let _, checkResults = getParseAndCheckResults """type foo = N1.T< const " ",2>""" + assertDiagnosticsContain "An error occurred applying the static arguments to a provided type" checkResults + +[] +let ``TypeProvider.StaticParameters.IncorrectNumberOfParameter`` () = + let _, checkResults = getParseAndCheckResults """type foo = N1.T< const "Hello World">""" + assertDiagnosticsContain "requires a value" checkResults + +[] +let ``TypeProvider.ProhibitedMethods`` () = + let _, checkResults = getParseAndCheckResults "let x = BadMethods.Arr.GetFirstElement([||])" + assertDiagnosticsContain "reported an error in the context of provided type" checkResults + +[] +let ``TypeProvider.StaticParameters.ErrorListItem`` () = + let _, checkResults = getParseAndCheckResults """type foo = N1.T< const "Hello World",2>""" + assertDiagnosticCount 1 checkResults + assertDiagnosticsContain "The namespace or module 'N1' is not defined." checkResults + +[] +let ``TypeProvider.StaticParameters.NoErrorListCount`` () = + let _, checkResults = getParseAndCheckResults """type foo = N1.T< const "Hello World",2>""" + assertNoDiagnostics checkResults + +[] +let ``NoError.FlagsAndSettings.TargetOptionsRespected`` () = + let _, checkResults = + getParseAndCheckResultsWithOptions [| "--nowarn:44" |] """ +[] +let fn x = 0 +let y = fn 1 +""" + assertNoDiagnostics checkResults + +[] +let ``UnicodeCharacters`` () = + let _, checkResults = getParseAndCheckResults "namespace 新規baApplication5" + assertDiagnosticsContain "新規" checkResults + +[] +let ``NoWarn.Bug5424`` () = + let _, checkResults = getParseAndCheckResults """ +#nowarn "67" // this type test or downcast will always hold +#nowarn "66" // this upcast is unnecessary - the types are identical +namespace Namespace1 + module Test = + open System + let a = ((5 :> obj) :?> Object) + let b = a :> obj +""" + assertNoDiagnostics checkResults + +[] +let ``FlagsAndSettings.ErrorsInFlagsDisplayed`` () = + let _, checkResults = + getParseAndCheckResultsWithOptions [| "--versionfile:nonexistent" |] """ +let x = 1 +""" + assertDiagnosticsContain "Invalid version file" checkResults + assertDiagnosticsContain "nonexistent" checkResults + +[] +let ``CompilerErrorsInErrList1`` () = + let _, checkResults = getParseAndCheckResults """ +namespace Errorlist +module CompilerError = + + let a = NoVal +""" + assertDiagnosticCount 1 checkResults + assertDiagnosticsContain "The value or constructor 'NoVal' is not defined" checkResults + +[] +let ``CompilerErrorsInErrList6`` () = + let _, checkResults = getParseAndCheckResults """ +type EnumOfBigInt = + | A = 0I + | B = 0I + +type EnumOfNatNum = + | A = 0N + | B = 0N +""" + assertDiagnosticCount 2 checkResults + assertDiagnosticsContain "is not a valid value for an enumeration literal" checkResults + +[] +let ``CompilerErrorsInErrList7`` () = + let _, checkResults = getParseAndCheckResults """ +type EnumType = + | A = 1 + | B = 2 + +type CustomAttrib(a:int, b:string, c:float, d:EnumType) = + inherit System.Attribute() + +let a = 42 +let b = "str" +let c = 3.141 +let d = EnumType.A + +[] +type SomeClass() = + override this.ToString() = "SomeClass" + +[] +let main0 args = () + +let foo = 1 +""" + assertDiagnosticCount 5 checkResults + assertDiagnosticsContain "is not a valid constant expression or custom attribute value" checkResults + +[] +let ``CompilerErrorsInErrList9`` () = + let _, checkResults = getParseAndCheckResults """ +namespace NS + [] + type Lib() = + class + abstract M : int -> int + end + +namespace NS + module M = + type Lib with + override x.M i = i +""" + assertDiagnosticCount 1 checkResults + assertDiagnosticsContain "Method overrides and interface implementations are not permitted here" checkResults + +[] +let ``CompilerErrorsInErrList10`` () = + let _, checkResults = getParseAndCheckResults """ +namespace Errorlist +module CompilerError = + + printfn "%A" System.Windows.Forms.Application.UserAppDataPath +""" + assertDiagnosticCount 1 checkResults + assertDiagnosticsContain "'Forms' is not defined" checkResults + +[] +let ``DoubleClickErrorListItem`` () = + let _, checkResults = getParseAndCheckResults """ +let x = x +""" + assertDiagnosticCount 1 checkResults + assertDiagnosticsContain "The value or constructor 'x' is not defined" checkResults + +[] +let ``FixingCodeAfterBuildRemovesErrors01`` () = + let _, checkResults = getParseAndCheckResults """ +let x = 4 + "x" +""" + assertDiagnosticCount 2 checkResults + assertDiagnosticsContain "does not match the type" checkResults + +[] +let ``FixingCodeAfterBuildRemovesErrors02`` () = + let _, checkResults = getParseAndCheckResults "let x = 4" + assertNoDiagnostics checkResults + +[] +let ``IncompleteExpression`` () = + let checkResults = + checkAsFsFile """module Test + +printfn "%A" + +List.map (fun x -> x + 1) +""" + assertDiagnosticCount 2 checkResults + assertDiagnosticsContain "This expression is a function value, i.e. is missing arguments" checkResults + +[] +let ``IntellisenseRequest`` () = + let _, checkResults = getParseAndCheckResults """ +type Foo() = + member a.B(*Marker*) : int = "1" +""" + assertDiagnosticCount 1 checkResults + assertDiagnosticsContain "This expression was expected to have type 'int' but here has type 'string'" checkResults + +[] +[] +[] +let ``TypeChecking - error count`` (source: string) = + let _, checkResults = getParseAndCheckResults source + assertDiagnosticCount 1 checkResults + +[] +[] +[] +let ``TypeChecking - error message`` (source: string) (expected: string) = + let _, checkResults = getParseAndCheckResults source + assertDiagnosticsContain expected checkResults + +[] +let ``Warning.ConsistentWithLanguageService`` () = + let _, checkResults = getParseAndCheckResults """ +open System +mixin mixin mixin mixin mixin mixin mixin mixin mixin mixin +mixin mixin mixin mixin mixin mixin mixin mixin mixin mixin""" + assertWarningCount 20 checkResults + assertDiagnosticsContain "is reserved for future use by F#" checkResults + +[] +let ``Warning.ConsistentWithLanguageService.Comment`` () = + let _, checkResults = getParseAndCheckResults """ +open System +//mixin mixin mixin mixin mixin mixin mixin mixin mixin mixin +//mixin mixin mixin mixin mixin mixin mixin mixin mixin mixin""" + assertWarningCount 0 checkResults + +[] +let ``Errorlist.WorkwithoutNowarning`` () = + let _, checkResults = getParseAndCheckResults """ +type Fruit (shelfLife : int) as x = + let mutable m_age = (fun () -> x) +#nowarn "47" +""" + assertDiagnosticCount 1 checkResults + +[] +let ``CompilerErrorsInErrList4`` () = + let _, checkResults = getParseAndCheckResults """ +#nowarn "47" + +type Fruit (shelfLife : int) as x = + + let mutable m_age = (fun () -> x) + +#nowarn "25" // FS0025: Incomplete pattern matches on this expression. For example, the value 'C' + +type DU = A | B | C +let f x = function A -> true | B -> false + +let _fsyacc_gotos = [| 0us; 1us; 2us|] +""" + assertNoDiagnostics checkResults diff --git a/tests/FSharp.Compiler.Service.Tests/ErrorList/ScriptDiagnosticsTests.fs b/tests/FSharp.Compiler.Service.Tests/ErrorList/ScriptDiagnosticsTests.fs new file mode 100644 index 00000000000..688d85d09b6 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ErrorList/ScriptDiagnosticsTests.fs @@ -0,0 +1,356 @@ +[] +module FSharp.Compiler.Service.Tests.ScriptDiagnosticsTests + +open System +open System.IO +open Xunit +open FSharp.Test +open FSharp.Compiler.Diagnostics +open FSharp.Compiler.Text + +let private closure (files: (string * string) list) (active: string) : FSharpDiagnostic[] = + let dir = Path.Combine(Path.GetTempPath(), "sdt_" + Guid.NewGuid().ToString("N")) + Directory.CreateDirectory(dir) |> ignore + try + for (name, content) in files do + File.WriteAllText(Path.Combine(dir, name), content) + let activePath = Path.Combine(dir, active) + let source = File.ReadAllText activePath + let options, _ = +#if NETCOREAPP + checker.GetProjectOptionsFromScript(activePath, SourceText.ofString source, assumeDotNetFramework = false, useSdkRefs = true) |> Async.RunImmediate +#else + checker.GetProjectOptionsFromScript(activePath, SourceText.ofString source) |> Async.RunImmediate +#endif + let results = checker.ParseAndCheckProject(options) |> Async.RunImmediate + results.Diagnostics + finally + try Directory.Delete(dir, true) with _ -> () + +let private distinctDiags (diags: FSharpDiagnostic[]) = + diags + |> Array.map (fun d -> formatDiagnostic d, normalizeDiagnosticMessage d) + |> Array.distinctBy fst + +let private closureDump (diags: FSharpDiagnostic[]) = + distinctDiags diags |> Array.map fst |> String.concat "\n" + +let private assertClosureNoDiagnostics (diags: FSharpDiagnostic[]) = + if diags.Length > 0 then + failwithf "Expected no diagnostics, but got %d:\n%s" diags.Length (closureDump diags) + +let private assertClosureContains (text: string) (diags: FSharpDiagnostic[]) = + let errors = diags |> Array.filter (fun d -> d.Severity = FSharpDiagnosticSeverity.Error) + let msgs = distinctDiags errors |> Array.map snd + if not (msgs |> Array.exists (fun m -> m.Contains text)) then + failwithf "Expected an ERROR diagnostic containing %A, but got %d:\n%s" text diags.Length (closureDump diags) + +let private assertClosureContainsAll (parts: string list) (diags: FSharpDiagnostic[]) = + let errors = diags |> Array.filter (fun d -> d.Severity = FSharpDiagnosticSeverity.Error) + let msgs = distinctDiags errors |> Array.map snd + if not (msgs |> Array.exists (fun m -> parts |> List.forall (fun p -> m.Contains p))) then + failwithf "Expected a single ERROR diagnostic containing all of %A, but got %d:\n%s" parts diags.Length (closureDump diags) + +let private assertClosureWarningContains (text: string) (diags: FSharpDiagnostic[]) = + let warnings = diags |> Array.filter (fun d -> d.Severity = FSharpDiagnosticSeverity.Warning) + let msgs = distinctDiags warnings |> Array.map snd + if not (msgs |> Array.exists (fun m -> m.Contains text)) then + failwithf "Expected a WARNING containing %A, but got %d diagnostic(s):\n%s" text diags.Length (closureDump diags) + +let private assertClosureExactlyOneContaining (text: string) (diags: FSharpDiagnostic[]) = + let matching = distinctDiags diags |> Array.filter (fun (_, m) -> m.Contains text) + if matching.Length <> 1 then + failwithf "Expected exactly one diagnostic containing %A, but %d of %d matched:\n%s" + text matching.Length diags.Length (closureDump diags) + +let private fooFs = "namespace Namespace\ntype Foo = \n static member public Property = 0\n" +let private fooFsi = "namespace Namespace\ntype Foo =\n class\n static member Property : int\n end\n" +let private fooFsHidden = "namespace Namespace\ntype Foo = \n static member public HiddenProperty = 0\n static member public Property = 0\n" +let private myNamespaceFs = "namespace MyNamespace\n module MyModule =\n let x = 1\n" + +[] +let ``Squiggles.ShowInFsxFiles`` () = + let _, checkResults = getParseAndCheckResults "open Thing1.Thing2" + assertDiagnosticsContain "The namespace or module 'Thing1' is not defined" checkResults + +[] +let ``Hash.RProperSquiggleForNonExistentFile`` () = + let _, checkResults = getParseAndCheckResultsUniqueName "#r \"NonExistent\" " + assertDiagnosticsContain "'NonExistent' was not found or is invalid" checkResults + +[] +let ``Hash.RDoesNotExist.Bug3325`` () = + let _, checkResults = getParseAndCheckResultsUniqueName "#r \"ThisDLLDoesNotExist\" " + assertDiagnosticsContain "'ThisDLLDoesNotExist' was not found or is invalid" checkResults + +[] +let ``ExactlyOneError.Bug4861`` () = + let _, checkResults = getParseAndCheckResultsUniqueName "//\n#r \"Nonexistent\"\n" + assertDiagnosticCount 1 checkResults + assertDiagnosticsContain "Nonexistent" checkResults + +[] +let ``InvalidHashLoad.ShouldBeASquiggle.Bug3012`` () = + let diags = closure [ "Test.fsx", "\n#load \"Bar.fs\"\n" ] "Test.fsx" + assertClosureContains "Bar.fs" diags + +[] +let ``HashLoad.Added`` () = + let _, checkResults = getParseAndCheckResults "//#load \"File1.fs\"\nopen MyNamespace.MyModule\nprintfn \"%d\" x\n" + assertDiagnosticsContain "MyNamespace" checkResults + +[] +let ``HashR.Removed`` () = + let _, checkResults = getParseAndCheckResultsUniqueName "#r \"System.Transactions.dll\"\nopen System.Transactions\n" + assertNoDiagnostics checkResults + +[] +let ``HashR.AddedIn`` () = + let _, checkResults = getParseAndCheckResults "//#r \"System.Transactions.dll\"\nopen System.Transactions\n" + assertDiagnosticsContain "'Transactions' is not defined" checkResults + +[] +let ``NoError.HashR.DllWithNoPath`` () = + let _, checkResults = getParseAndCheckResultsUniqueName "\n#r \"System.Transactions.dll\"\nopen System.Transactions" + assertNoDiagnostics checkResults + +[] +let ``NoError.HashR.BugDefaultReferenceFileIsAlsoResolved`` () = + let _, checkResults = getParseAndCheckResultsUniqueName "\n#r \"System\"\n" + assertNoDiagnostics checkResults + +[] +let ``NoError.HashR.DoubleReference`` () = + let _, checkResults = getParseAndCheckResultsUniqueName "\n#r \"System\"\n#r \"System\"\n" + assertNoDiagnostics checkResults + +[] +let ``NoError.HashR.ResolveFromGAC`` () = + let _, checkResults = getParseAndCheckResultsUniqueName "\n#r \"CustomMarshalers\"\n" + assertNoDiagnostics checkResults + +[] +let ``NoError.HashR.ResolveFromFullyQualifiedPath`` () = + let path = Path.Combine(System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory(), "System.configuration.dll") + let _, checkResults = getParseAndCheckResultsUniqueName (sprintf "#r @\"%s\"" path) + assertNoDiagnostics checkResults + +[] +let ``NoError.HashR.RelativePath1`` () = () + +[] +let ``NoError.HashR.RelativePath2`` () = () + +[] +let ``NoError.AutomaticImportsForFsxFiles`` () = + let _, checkResults = + getParseAndCheckResults + "\nopen System\nopen System.Xml\nopen System.Drawing\nopen System.Runtime.Remoting\nopen System.Runtime.Serialization.Formatters.Soap\nopen System.Data\nopen System.Drawing\nopen System.Web\nopen System.Web.Services\nopen System.Windows.Forms" + assertNoDiagnostics checkResults + +[] +[] +[] +[] +let ``HashDirectivesAreErrors.InNonScriptFiles`` (directive: string) = + assertDiagnosticsContain "may only be used in F# script files" (checkAsFsFile directive) + +[] +let ``ScriptCanReferenceBinDirectoryOutput.Bug3151`` () = + let _, checkResults = getParseAndCheckResults "#reference @\"bin\\Debug\\testproject.exe\"\n" + assertNoDiagnostics checkResults + +[] +let ``HashReferenceAgainstNonAssemblyExe`` () = + let path = Path.Combine(Environment.GetEnvironmentVariable("windir"), "notepad.exe") + let _, checkResults = getParseAndCheckResults (sprintf "#reference @\"%s\"\n" path) + assertDiagnosticsContain "was not found or is invalid" checkResults + +[] +let ``TypeProvider.UnitsOfMeasure.SmokeTest1`` () = () + +[] +let ``ScriptClosure.TransitiveLoad1`` () = + closure + [ "File1.fs", fooFs + "Script2.fsx", "#load \"File1.fs\"\n" + "Script1.fsx", "#load \"Script2.fsx\"\nNamespace.Foo.Property\n" ] + "Script1.fsx" + |> assertClosureNoDiagnostics + +[] +let ``ScriptClosure.TransitiveLoad2`` () = + closure + [ "File1.fs", fooFs + "Script2.fsx", "#load \"File1.fs\"\n" + "Script1.fsx", "#load \"Script2.fsx\"\nNamespace.Foo.NonExistingProperty\n" ] + "Script1.fsx" + |> assertClosureExactlyOneContaining "NonExistingProperty" + +[] +let ``HashLoad.Removed`` () = + closure + [ "File1.fs", myNamespaceFs + "File2.fsx", "#load \"File1.fs\"\nopen MyNamespace.MyModule\nprintfn \"%d\" x\n" ] + "File2.fsx" + |> assertClosureNoDiagnostics + +[] +let ``NoError.ScriptClosure.TransitiveLoad16`` () = + closure + [ "ThisProject.fsx", "#nowarn \"44\"\n" + "Script1.fsx", "#load \"ThisProject.fsx\"\n[]\nlet fn x = 0\nlet y = fn 1\n" ] + "Script1.fsx" + |> assertClosureExactlyOneContaining "This construct is deprecated. x" + +[] +let ``NoError.HashLoad.Simple`` () = + closure + [ "File1.fs", myNamespaceFs + "File2.fsx", "#load \"File1.fs\"\nopen MyNamespace.MyModule\nprintfn \"%d\" x\n" ] + "File2.fsx" + |> assertClosureNoDiagnostics + +[] +let ``NoWarn.OnLoadedFile.Bug4837`` () = + closure + [ "File1.fs", "module File1Module\nlet x = System.DateTime.Now - System.DateTime.Now\nx.Add(x) |> ignore\n" + "File2.fsx", "#load \"File1.fs\"\n" ] + "File2.fsx" + |> assertClosureNoDiagnostics + +[] +let ``ExactlyOneError.ScriptClosure.TransitiveLoad15`` () = + closure + [ "File2.fs", "namespace Namespace\ntype Type() =\n static member Property = 0\n" + "File1.fs", "#load \"File2.fs\"\nnamespace File2Namespace\n" + "Script1.fsx", "#load \"File1.fs\"\nNamespace.Type.Property\n" ] + "Script1.fsx" + |> assertClosureExactlyOneContaining "Namespace" + +[] +let ``ScriptClosure.TransitiveLoad14`` () = + closure + [ "Script2.fsx", "#load \"Script1.fsx\"\n#r \"NonExisting\"\n" + "Script1.fsx", "#load \"Script2.fsx\"\n#r \"System\"\n" ] + "Script1.fsx" + // Cyclic #load with a resolvable `#r "System"` must not squiggle; only the deliberately + // missing `#r "NonExisting"` may warn (surfaced by the transparent compiler, not the classic one). + |> Array.filter (fun d -> not (d.Message.Contains "NonExisting")) + |> assertClosureNoDiagnostics + +[] +let ``HashLoadedFileWithErrors.Bug3149`` () = + closure + [ "File1.fs", "module File1\nDogChow\n" + "File2.fsx", "#load @\"File1.fs\"\n" ] + "File2.fsx" + |> assertClosureContains "DogChow" + +[] +let ``HashLoadedFileWithWarnings.Bug3149`` () = + closure + [ "File1.fs", "module File1Module\ntype WarningHere<'a> = static member X() = 0\nlet y = WarningHere.X\n" + "File2.fsx", "#load @\"File1.fs\"\n" ] + "File2.fsx" + |> assertClosureWarningContains "WarningHere" + +[] +let ``HashLoadedFileWithErrors.Bug3652`` () = + closure + [ "File1.fs", "module File1\nlet a = 1 + \"\"\nlet c = new obj()\nlet b = c.foo()\n" + "File2.fsx", "#load @\"File1.fs\"\n" ] + "File2.fsx" + |> assertClosureContainsAll [ "'string'"; "'int'" ] + +[] +[] +[] +let ``ScriptClosure.TransitiveLoad3and4`` (caseId: int) = + let member', expected = + match caseId with + | 1123 -> "Property", null + | _ -> "NonExistingProperty", "NonExistingProperty" + let files = + [ "File1.fs", fooFs + "Script2.fsx", "#load \"Script1.fsx\"\n#load \"File1.fs\"\n" + "Script1.fsx", sprintf "#load \"Script2.fsx\"\n#load \"File1.fs\"\nNamespace.Foo.%s\n" member' ] + let diags = closure files "Script1.fsx" + if isNull expected then assertClosureNoDiagnostics diags + else assertClosureExactlyOneContaining expected diags + +[] +[] +[] +let ``ScriptClosure.TransitiveLoad9and5`` (caseId: int) = + let member', expected = + match caseId with + | 1124 -> "Property", null + | _ -> "HiddenProperty", "HiddenProperty" + let files = + [ "File1.fsi", fooFsi + "File1.fs", fooFsHidden + "Script1.fsx", sprintf "#load \"File1.fsi\"\n#load \"File1.fs\"\nNamespace.Foo.%s\n" member' ] + let diags = closure files "Script1.fsx" + if isNull expected then assertClosureNoDiagnostics diags + else assertClosureExactlyOneContaining expected diags + +[] +[] +[] +[] +[] +let ``ScriptClosure.TransitiveLoad10_12_6_8`` (caseId: int) = + let member', expected = + match caseId with + | 1125 | 1127 -> "Property", null + | _ -> "HiddenProperty", "HiddenProperty" + let script1, script2 = + match caseId with + | 1125 | 1141 -> + "#load \"File1.fsi\"\n#load \"File1.fs\"\n", + sprintf "#load \"Script1.fsx\"\nNamespace.Foo.%s\n" member' + | _ -> + "#load \"File1.fs\"\n", + sprintf "#load \"File1.fsi\"\n#load \"Script1.fsx\"\nNamespace.Foo.%s\n" member' + let files = + [ "File1.fsi", fooFsi + "File1.fs", fooFsHidden + "Script1.fsx", script1 + "Script2.fsx", script2 ] + let diags = closure files "Script2.fsx" + if isNull expected then assertClosureNoDiagnostics diags + else assertClosureExactlyOneContaining expected diags + +[] +[] +[] +let ``ScriptClosure.TransitiveLoad11and7`` (caseId: int) = + let member', expected = + match caseId with + | 1126 -> "Property", null + | _ -> "HiddenProperty", "HiddenProperty" + let files = + [ "File1.fsi", fooFsi + "File1.fs", fooFsHidden + "Script1.fsx", "#load \"File1.fsi\"\n" + "Script2.fsx", sprintf "#load \"Script1.fsx\"\n#load \"File1.fs\"\nNamespace.Foo.%s\n" member' ] + let diags = closure files "Script2.fsx" + if isNull expected then assertClosureNoDiagnostics diags + else assertClosureExactlyOneContaining expected diags + +[] +let ``Fsx.SyntheticTokens`` () = + let _, checkResults = getParseAndCheckResultsUniqueName "#r \"\"\n#reference \"\"\n#load \"\"\n#line 52\n#nowarn 72\n" + assertDiagnosticsContain "is not a valid assembly name" checkResults + assertDiagnosticsContain "is not a valid filename" checkResults + let errors = checkResults.Diagnostics |> Array.filter (fun d -> d.Severity = FSharpDiagnosticSeverity.Error) + Assert.Empty(errors) + +[] +[] +[] +[] +let ``Fsx.UnclosedHashReferenceOrLoad`` (source: string) = + let _, checkResults = getParseAndCheckResultsUniqueName source + assertDiagnosticsContain "End of file in string begun" checkResults diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj index 0a831038313..6f4a9c75063 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj @@ -27,7 +27,6 @@ - @@ -56,6 +55,7 @@ + @@ -85,6 +85,107 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.ActivePatterns.fs b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.ActivePatterns.fs new file mode 100644 index 00000000000..44275c744d0 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.ActivePatterns.fs @@ -0,0 +1,24 @@ +module FSharp.Compiler.Service.Tests.GotoDefinitionActivePatternsTests + +open System +open Xunit + +let private overlapSource = + String.concat + "\n" + [ "module Overlap =" + " type Parity = Even | Odd" + " let (|Even{caret1}|Odd|) x = (*loc-59*)" + " if x % 0 = 0" + " then Even{caret2} (*loc-60*)" + " else Odd" + " let foo (x : int) =" + " match x with" + " | Even{caret3} -> 1 (*loc-61*)" + " | Odd -> 0" + " let patval = (|Even{caret4}|Odd|) (*loc-61b*)" ] + +[] +let ``GotoDefinition.Simple.ActivePat`` () = + overlapSource + |> assertGoToDefinitionOnLines (List.replicate 4 "let (|Even|Odd|) x = (*loc-59*)") diff --git a/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.Classes.fs b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.Classes.fs new file mode 100644 index 00000000000..a99805143f9 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.Classes.fs @@ -0,0 +1,33 @@ +module FSharp.Compiler.Service.Tests.GotoDefinitionClassesTests + +open System +open Xunit + +let private classFieldSource = + String.concat + "\n" + [ "let id77 = 0" + "type C =" + " val id77{caret} (*loc-77*) : int" ] + +[] +let ``GotoDefinition.InsideClass.Bug3176`` () = + assertGoToDefinitionOnLine + "val id77 (*loc-77*) : int" + classFieldSource + +let private classSource = + String.concat + "\n" + [ "type Class{caret1} () = (*loc-62*)" + " member c.Method () = () (*loc-63*)" + " static member Foo () = () (*loc-64*)" + "let _ =" + " let c = Class{caret2} () (*loc-65*)" + " c.Method () (*loc-66*)" + " Class.Foo () (*loc-67*)" ] + +[] +let ``GotoDefinition.ObjectOriented.ClassNameDefAndConstructorUse`` () = + classSource + |> assertGoToDefinitionOnLines (List.replicate 2 "type Class () = (*loc-62*)") diff --git a/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.DiscriminatedUnions.fs b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.DiscriminatedUnions.fs new file mode 100644 index 00000000000..e1552b4b17b --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.DiscriminatedUnions.fs @@ -0,0 +1,57 @@ +module FSharp.Compiler.Service.Tests.GotoDefinitionDiscriminatedUnionsTests + +open System +open Xunit + +let private discUnionSource = + """ + type DiscUnion = + | Alpha of string + | Beta of decimal * unit + | Gamma + + let valueX = Beta{caret2}(1.0M, ())(*GotoTypeDef*) + let valueY = valueX{caret1} (*GotoValDef*) + """ + +[] +let ``GotoDefinition.DiscriminatedUnion`` () = + discUnionSource + |> assertGoToDefinitionOnLines + [ "let valueX = Beta(1.0M, ())(*GotoTypeDef*)" + "| Beta of decimal * unit" ] + +let private simpleDatatypeSource = + String.concat + "\n" + [ "type Zero = (*loc-13*)" + "let foo (_ : Zero{caret1}) : 'a = failwith \"hi\" (*loc-14*)" + "type One{caret3} = (*loc-16*)" + " One{caret2} (*loc-15*)" + "let f (x : One{caret5}) = (*loc-17*)" + " One{caret4} (*loc-18*)" + "type Nat{caret6} = (*loc-19*)" + " | Suc of Nat{caret7} (*loc-20*)" + " | Zro (*loc-21*)" + "let rec plus m n = (*loc-23*)" + " match m with (*loc-22*)" + " | Zro{caret8} -> (*loc-24*)" + " n" + " | Suc{caret9} m -> (*loc-25*)" + " Suc (plus m{caret10} n{caret11}) (*loc-26*)" ] + +[] +let ``GotoDefinition.Simple.Datatype`` () = + simpleDatatypeSource + |> assertGoToDefinitionOnLines + [ "type Zero = (*loc-13*)" + "One (*loc-15*)" + "type One = (*loc-16*)" + "One (*loc-15*)" + "type One = (*loc-16*)" + "type Nat = (*loc-19*)" + "type Nat = (*loc-19*)" + "| Zro (*loc-21*)" + "| Suc of Nat (*loc-20*)" + "| Suc m -> (*loc-25*)" + "let rec plus m n = (*loc-23*)" ] diff --git a/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.IdentifierIsland.fs b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.IdentifierIsland.fs new file mode 100644 index 00000000000..c37c769c362 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.IdentifierIsland.fs @@ -0,0 +1,24 @@ +module FSharp.Compiler.Service.Tests.GotoDefinitionIdentifierIslandTests + +open Xunit + +[] +[] +[] +[] +[] +[] +[] +[] +let ``GetCompleteIdTest source-only`` (source: string) (expected: string) = + assertCompleteIdentifierIsland (Option.ofObj expected) source + +[] +let ``GetCompleteIdTest.TrivialEnd`` () = + assertCompleteIdentifierIslandWithTolerate true (Some "ThisIsAnIdentifier") "let ThisIsAnIdentifier$ = ()" + assertCompleteIdentifierIslandWithTolerate false None "let ThisIsAnIdentifier$ = ()" + +[] +let ``GetCompleteIdTest.GetsUpToDot5`` () = + assertCompleteIdentifierIslandWithTolerate true (Some "Test.Moo.Foo.bar") "let ThisIsAnIdentifier = Test.Moo.Foo.bar$" + assertCompleteIdentifierIslandWithTolerate false None "let ThisIsAnIdentifier = Test.Moo.Foo.bar$" diff --git a/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.LetBindings.fs b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.LetBindings.fs new file mode 100644 index 00000000000..3737bf94b43 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.LetBindings.fs @@ -0,0 +1,82 @@ +module FSharp.Compiler.Service.Tests.GotoDefinitionLetBindingsTests + +open System +open Xunit + +[] +let ``PrimitiveType`` () = + let source = + """ + // Can't goto def on an int literal + let bi = 123456I{caret}""" + + assertGoToDefinitionFails source + +[] +let ``GotoDefinition.NoIdentifierAtLocation`` () = + let markedSources = + [ "let x = 1{caret}" + "let x = 1{caret}.2" + "let x = \"12{caret}3\"" ] + + for markedSource in markedSources do + assertGoToDefinitionFails markedSource + +let private trivialLetSource = + String.concat + "\n" + [ "let _ =" + " let x{caret2} = () (*loc-2*)" + " x{caret1} (*loc-1*)" ] + +[] +let ``GotoDefinition.Simple.Binding.TrivialLet`` () = + trivialLetSource + |> assertGoToDefinitionOnLines (List.replicate 2 "let x = () (*loc-2*)") + +let private nestedSameNameSource = + String.concat + "\n" + [ "let _ =" + " let x{caret3} = () (*loc-5*)" + " let x{caret2} = () (*loc-3*)" + " x{caret1} (*loc-4*)" ] + +[] +let ``GotoDefinition.Simple.Binding.NestedLetWithSameName`` () = + nestedSameNameSource + |> assertGoToDefinitionOnLines + [ "let x = () (*loc-3*)" + "let x = () (*loc-3*)" + "let x = () (*loc-5*)" ] + +let private nestedXIsXSource = + String.concat + "\n" + [ "let _ =" + " let x = () (*loc-7*)" + " let x =" + " x{caret} (*loc-6*)" + " ()" ] + +[] +let ``GotoDefinition.Simple.Binding.NestedLetWithXIsX`` () = + assertGoToDefinitionOnLine + "let x = () (*loc-7*)" + nestedXIsXSource + +let private lotsOfFsFuncSource = + String.concat + "\n" + [ "let _ =" + " let f = () (*loc-40*)" + " let f{caret} = (*loc-41*)" + " function f -> (*loc-42*)" + " f (*loc-43*)" + " ()" ] + +[] +let ``GotoDefinition.Simple.Tricky.LotsOfFsFunc`` () = + assertGoToDefinitionOnLine + "let f = (*loc-41*)" + lotsOfFsFuncSource diff --git a/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.Members.fs b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.Members.fs new file mode 100644 index 00000000000..797ed28e807 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.Members.fs @@ -0,0 +1,191 @@ +module FSharp.Compiler.Service.Tests.GotoDefinitionMembersTests + +open System +open Xunit + +[] +let ``GotoDefinition.NoSourceCodeAvailable`` () = + let source = """System.String.Format{caret}("")""" + + assertGoToDefinitionIsExternal source + +let private orPatSource = + String.concat + "\n" + [ "type Nat =" + " | Suc of Nat" + " | Zro" + "let _ =" + " let f x =" + " match x with" + " | Suc x{caret1} (*loc-44*)" + " | x{caret2} (*loc-45*) -> " + " x" + " ()" ] + +[] +let ``GotoDefinition.Simple.Tricky.OrPat`` () = + orPatSource + |> assertGoToDefinitionOnLines (List.replicate 2 "| Suc x (*loc-44*)") + +let private consPatSource = + String.concat + "\n" + [ "let _ =" + " let f xs =" + " match xs with" + " | x :: xs (*loc-54*)" + " when xs <> [] -> (*loc-52*)" + " x{caret1} :: xs{caret2} (*loc-53*)" + " ()" ] + +[] +let ``GotoDefinition.Simple.Tricky.ConsPatWhenClauseInWhenRhs`` () = + consPatSource + |> assertGoToDefinitionOnLines (List.replicate 2 "| x :: xs (*loc-54*)") + +let private inStringSource = + String.concat + "\n" + [ "let _ =" + " let x = 2" + " \"x{caret}(*loc-72*)\"" ] + +[] +let ``GotoDefinition.Simple.Tricky.InStringFails`` () = + assertGoToDefinitionFails inStringSource + +let private inMultiLineStringSource = + String.concat + "\n" + [ "let _ =" + " let x = 2" + " \"this is a string" + " x{caret}(*loc-73*)" + " \"" ] + +[] +let ``GotoDefinition.Simple.Tricky.InMultiLineStringFails`` () = + assertGoToDefinitionFails inMultiLineStringSource + +[] +let ``GotoDefinition.Library.InitialTest`` () = + let source = "let _ = List.map{caret} (*loc-1*)" + + assertGoToDefinitionToExternalLine "map" source + +let private ooClassSource = + String.concat + "\n" + [ "type Class () = (*loc-62*)" + " member c{caret2}.Method{caret1} () = () (*loc-63*)" + " static member Foo{caret3} () = () (*loc-64*)" + "let _ =" + " let c = Class () (*loc-65*)" + " c.Method{caret4} () (*loc-66*)" + " Class.Foo{caret5} () (*loc-67*)" ] + +[] +let ``GotoDefinition.ObjectOriented`` () = + ooClassSource + |> assertGoToDefinitionOnLines + [ "member c.Method () = () (*loc-63*)" + "member c.Method () = () (*loc-63*)" + "static member Foo () = () (*loc-64*)" + "member c.Method () = () (*loc-63*)" + "static member Foo () = () (*loc-64*)" ] + +let private ooClassPrimeSource = + String.concat + "\n" + [ "type Class () = (*loc-62*)" + " member c.Method () = () (*loc-63*)" + " static member Foo () = () (*loc-64*)" + "type Class' () =" + " member c.Method () = c.Method{caret1} () (*loc-68*)" + " member c.Method1 () = c.Method2{caret2} () (*loc-69*)" + " member c.Method2 () = c.Method1 () (*loc-70*)" + " member c.Method3 () =" + " let c = Class ()" + " c{caret3}.Method{caret4} () (*loc-71*)" ] + +[] +let ``GotoDefinition.ObjectOriented.Prime`` () = + ooClassPrimeSource + |> assertGoToDefinitionOnLines + [ "member c.Method () = c.Method () (*loc-68*)" + "member c.Method2 () = c.Method1 () (*loc-70*)" + "let c = Class ()" + "member c.Method () = () (*loc-63*)" ] + +let private overloadedPropertiesSource = + String.concat + "\n" + [ "type D() =" + " member this.Foo (*loc-d1*)" + " with get(i:int) = 1" + " and set (i:int) v = ()" + "" + " member this.Foo (*loc-d3*)" + " with get (s:string) = 1" + " and set (s:string) v = ()" + "" + "D().Foo{caret1} 1 (*loc-u1*)" + "D().Foo{caret2} 1 <- 2 (*loc-u2*)" + "D().Foo{caret3} \"abc\" (*loc-u3*)" + "D().Foo{caret4} \"abc\" <- 2 (*loc-u4*)" ] + +[] +let ``GotoDefinition.OverloadResolutionForProperties`` () = + overloadedPropertiesSource + |> assertGoToDefinitionOnLines + [ "member this.Foo (*loc-d1*)" + "member this.Foo (*loc-d1*)" + "member this.Foo (*loc-d3*)" + "member this.Foo (*loc-d3*)" ] + +let private overloadedMethodsSource = + String.concat + "\n" + [ "[]" + "type Base<'T>() =" + " member this.Method() = () (*loc-d2*)" + " abstract Method : 'T -> unit" + "" + "type Derived() =" + " inherit Base()" + "" + " override this.Method (i:int) = () (*loc-d1*)" + "" + "let d = new Derived()" + "d.Method{caret1} 12 (*loc-u1*)" + "d.Method{caret2}() (*loc-u2*)" ] + +[] +let ``GotoDefinition.OverloadResolutionWithOverrides`` () = + overloadedMethodsSource + |> assertGoToDefinitionOnLines + [ "override this.Method (i:int) = () (*loc-d1*)" + "member this.Method() = () (*loc-d2*)" ] + +let private inheritedMembersSource = + String.concat + "\n" + [ "[]" + "type Foo() =" + " abstract Method : unit -> unit" + " abstract Property : int" + "type Bar() =" + " inherit Foo()" + " override this.Method () = ()" + " override this.Property = 1" + "let b = Bar()" + "b.Method{caret1}(*loc-1*)()" + "b.Property{caret2}(*loc-2*)" ] + +[] +let ``GotoDefinition.InheritedMembers`` () = + inheritedMembersSource + |> assertGoToDefinitionOnLines + [ "override this.Method () = ()" + "override this.Property = 1" ] diff --git a/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.Misc.fs b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.Misc.fs new file mode 100644 index 00000000000..101059a65ee --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.Misc.fs @@ -0,0 +1,108 @@ +module FSharp.Compiler.Service.Tests.GotoDefinitionMiscTests + +open System +open Xunit + +let private nestedLetRecSource = + String.concat + "\n" + [ "let _ =" + " let x = ()" + " let rec x = (*loc-9*)" + " fun y -> (*loc-10*)" + " x{caret} y (*loc-8*)" + " ()" ] + +[] +let ``GotoDefinition.Simple.Binding.NestedLetWithXRec`` () = + assertGoToDefinitionOnLine + "let rec x = (*loc-9*)" + nestedLetRecSource + +let private asPatternSource = + String.concat + "\n" + [ "let _ =" + " let foo = ()" + " let f (_ as foo{caret1}) = (*loc-35*)" + " foo{caret2} (*loc-36*)" + " ()" ] + +[] +let ``GotoDefinition.Simple.Tricky.AsPat`` () = + asPatternSource + |> assertGoToDefinitionOnLines (List.replicate 2 "let f (_ as foo) = (*loc-35*)") + +let private lambdaMultiBindSource = + String.concat + "\n" + [ "let _ =" + " fun x{caret} (*loc-37*)" + " x -> (*loc-38*)" + " x (*loc-39*)" ] + +[] +let ``GotoDefinition.Simple.Tricky.LambdaMultBind1`` () = + assertGoToDefinitionOnLine + "fun x (*loc-37*)" + lambdaMultiBindSource + +let private quotedKeywordSource = + String.concat + "\n" + [ "let _ =" + " let rec ``let{caret}`` = (*loc-74*)" + " function 0 -> 1" + " | n -> n * ``let`` (n - 1) (*loc-75*)" ] + +[] +let ``GotoDefinition.Simple.Tricky.QuotedKeyword`` () = + assertGoToDefinitionOnLine + "let rec ``let`` = (*loc-74*)" + quotedKeywordSource + +let private structConstructorSource = + String.concat + "\n" + [ "" + "[]" + "type Astruct(x:int, y:int) =" + " []" + " val mutable a : int" + " new(a) = Astruct(a, a)" + "type AS = Astruct" + "let a1 = Astruct{caret1}(0)" + "let b1 = Astruct{caret2}(0, 1)" + "let c1 = Astruct{caret3}()" + "let a2 = AS{caret4}(0)" + "let b2 = AS{caret5}(0, 1)" + "let c2 = AS{caret6}()" ] + +[] +let ``GotoDefinition.ObjectOriented.StructConstructor`` () = + structConstructorSource + |> assertGoToDefinitionOnLines + [ "new(a) = Astruct(a, a)" + "type Astruct(x:int, y:int) =" + "type Astruct(x:int, y:int) =" + "new(a) = Astruct(a, a)" + "type Astruct(x:int, y:int) =" + "type Astruct(x:int, y:int) =" ] + +[] +let ``GotoDefinition.Abbreviation.Bug193064`` () = + let source = + """ + type X = int + let f (x:X) = x{caret}(*Marker*) """ + + assertGoToDefinitionOnLine "let f (x:X) = x(*Marker*)" source + +[] +let ``GotoDefinition.UnitOfMeasure.Bug193064`` () = + let source = + """ + open Microsoft.FSharp.Data.UnitSystems.SI + UnitSymbols.A{caret}(*Marker*)""" + + assertGoToDefinitionToExternalLine "type A = ampere" source diff --git a/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.Modules.fs b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.Modules.fs new file mode 100644 index 00000000000..939845a3c5b --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.Modules.fs @@ -0,0 +1,46 @@ +module FSharp.Compiler.Service.Tests.GotoDefinitionModulesTests + +open System +open Xunit + +let private moduleDefSource = + """ + //regression test for bug 2517 + module Foo{caret} (*MarkerModuleDefinition*) = + let x = () + """ + +[] +let ``ModuleDefinition`` () = + assertGoToDefinitionOnLine + "module Foo (*MarkerModuleDefinition*) =" + moduleDefSource + +let private moduleSource = + String.concat + "\n" + [ "module Too{caret1} = (*loc-55*)" + " let foo{caret2} = 0 (*loc-56*)" + "module Bar =" + " open Too{caret5} (*loc-57*)" + "let _ = Too{caret3}.foo{caret4} (*loc-58*)" ] + +[] +let ``GotoDefinition.Simple.Module`` () = + moduleSource + |> assertGoToDefinitionOnLines + [ "module Too = (*loc-55*)" + "let foo = 0 (*loc-56*)" + "module Too = (*loc-55*)" + "let foo = 0 (*loc-56*)" + "module Too = (*loc-55*)" ] + +[] +let ``ModuleName.OnDefinitionSite.Bug2517`` () = + let source = + """ + namespace GotoDefinition + module Foo{caret}(*Mark*) = + let x = ()""" + + assertGoToDefinitionOnLine "module Foo(*Mark*) =" source diff --git a/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.Operators.fs b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.Operators.fs new file mode 100644 index 00000000000..21687aa5959 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.Operators.fs @@ -0,0 +1,39 @@ +module FSharp.Compiler.Service.Tests.GotoDefinitionOperatorsTests + +open Xunit + +[] +let ``Operators.TopLevel`` () = + let source = + """ + let (===) a b = a = b + let _ = 1 ==={caret} 2 + """ + + assertGoToDefinitionOperatorOnLine "let (===) a b = a = b" "===" source + +[] +let ``Operators.Member`` () = + let source = + """ + type U = U + with + static member (+++) (U, U) = U + let _ = U +++{caret} U + """ + + assertGoToDefinitionOperatorOnLine "static member (+++) (U, U) = U" "+++" source + +let private simpleOperatorSource = + String.concat + "\n" + [ "let _ =" + " let (+) x _ = x (*loc-12*)" + " 2 +{caret} 3 (*loc-11*)" ] + +[] +let ``GotoDefinition.Simple.Binding.Operator`` () = + assertGoToDefinitionOperatorOnLine + "let (+) x _ = x (*loc-2*)" + "+" + simpleOperatorSource diff --git a/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.PatternMatching.fs b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.PatternMatching.fs new file mode 100644 index 00000000000..4380418525b --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.PatternMatching.fs @@ -0,0 +1,115 @@ +module FSharp.Compiler.Service.Tests.GotoDefinitionPatternMatchingTests + +open System +open Xunit + +let private nestedLetSource = + String.concat + "\n" + [ "let _ =" + " let x = ()" + " let rec x = (*loc-9*)" + " fun y -> (*loc-10*)" + " x y{caret} (*loc-8*)" + " ()" ] + +[] +let ``GotoDefinition.Simple.Binding.NestedLetWithXRecParam`` () = + assertGoToDefinitionOnLine + "fun y -> (*loc-10*)" + nestedLetSource + +let private lambdaMultiBindSource = + String.concat + "\n" + [ "let _ =" + " fun x (*loc-37*)" + " x{caret1} -> (*loc-38*)" + " x{caret2} (*loc-39*)" ] + +[] +let ``GotoDefinition.Simple.Tricky.LambdaMultBind`` () = + lambdaMultiBindSource + |> assertGoToDefinitionOnLines (List.replicate 2 "x -> (*loc-38*)") + +let private functionPatternSource = + String.concat + "\n" + [ "let _ =" + " let f = () (*loc-40*)" + " let f = (*loc-41*)" + " function f{caret1} -> (*loc-42*)" + " f{caret2} (*loc-43*)" + " ()" ] + +[] +let ``GotoDefinition.Simple.Tricky.LotsOfFsPat`` () = + functionPatternSource + |> assertGoToDefinitionOnLines (List.replicate 2 "function f -> (*loc-42*)") + +let private andPatternSource = + String.concat + "\n" + [ "type Nat = Suc of Nat | Zro" + "let _ =" + " let f x =" + " match x with" + " | Suc y & z -> (*loc-47*)" + " y{caret} (*loc-46*)" + " ()" ] + +[] +let ``GotoDefinition.Simple.Tricky.AndPat`` () = + assertGoToDefinitionOnLine + "| Suc y & z -> (*loc-47*)" + andPatternSource + +let private consPatternSource = + String.concat + "\n" + [ "let _ =" + " let f xs =" + " match xs with" + " | x :: xs -> (*loc-49*)" + " x{caret} (*loc-48*)" + " | _ -> []" + " ()" ] + +[] +let ``GotoDefinition.Simple.Tricky.ConsPat`` () = + assertGoToDefinitionOnLine + "| x :: xs -> (*loc-49*)" + consPatternSource + +let private pairPatternSource = + String.concat + "\n" + [ "let _ =" + " let f x =" + " match x with" + " | (y : int, z) -> (*loc-51*)" + " y{caret} (*loc-50*)" + " ()" ] + +[] +let ``GotoDefinition.Simple.Tricky.PairPat`` () = + assertGoToDefinitionOnLine + "| (y : int, z) -> (*loc-51*)" + pairPatternSource + +let private consWhenSource = + String.concat + "\n" + [ "let _ =" + " let f xs =" + " match xs with" + " | x :: xs (*loc-54*)" + " when xs{caret} <> [] -> (*loc-52*)" + " x :: xs (*loc-53*)" + " ()" ] + +[] +let ``GotoDefinition.Simple.Tricky.ConsPatWhenClauseInWhen`` () = + assertGoToDefinitionOnLine + "| x :: xs (*loc-54*)" + consWhenSource diff --git a/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.Records.fs b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.Records.fs new file mode 100644 index 00000000000..a652be5afd2 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.Records.fs @@ -0,0 +1,28 @@ +module FSharp.Compiler.Service.Tests.GotoDefinitionRecordsTests + +open System +open Xunit + +let private simpleRecordSource = + String.concat + "\n" + [ "type MyRec{caret1} = (*loc-27*)" + " { myX{caret2} : int (*loc-28*)" + " myY{caret3} : int (*loc-29*)" + " }" + "let rDefault =" + " { myX{caret4} = 2 (*loc-30*)" + " myY{caret5} = 3 (*loc-31*)" + " }" + "let _ = { rDefault with myX{caret6} = 7 } (*loc-32*)" ] + +[] +let ``GotoDefinition.Simple.Datatype.Record`` () = + simpleRecordSource + |> assertGoToDefinitionOnLines + [ "type MyRec = (*loc-27*)" + "{ myX : int (*loc-28*)" + "myY : int (*loc-29*)" + "{ myX : int (*loc-28*)" + "myY : int (*loc-29*)" + "{ myX : int (*loc-28*)" ] diff --git a/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.TypeAnnotations.fs b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.TypeAnnotations.fs new file mode 100644 index 00000000000..5fb2617e6eb --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.TypeAnnotations.fs @@ -0,0 +1,131 @@ +module FSharp.Compiler.Service.Tests.GotoDefinitionTypeAnnotationsTests + +open System +open Xunit + +let private bug2516SpacedSource = + """ + //regression test for bug 2516 + type One{caret1} (*Marker1*) = One + let f (x : One{caret2} (*Marker2*)) = 2 + """ + +[] +let ``OnTypeDefinitionAndParameter`` () = + bug2516SpacedSource + |> assertGoToDefinitionOnLines (List.replicate 2 "type One (*Marker1*) = One") + +let private overloadResolutionSource = + String.concat + "\n" + [ "type D() =" + " override this.ToString() (*#3#*) = System.String.Empty" + " member this.ToString(s : string) (*#4#*) = ()" + "" + " member this.Foo() (*#1#*) = ()" + " member this.Foo(x) (*#2#*) = ()" + "" + "let d = new D()" + "d.Foo{caret1}() (*$1$*)" + "d.Foo{caret2}(1) (*$2$*)" + "d.ToString{caret3}() (*$3$*)" + "d.ToString{caret4}(\"aaa\") (*$4$*)" ] + +[] +let ``GotoDefinition.OverloadResolution`` () = + overloadResolutionSource + |> assertGoToDefinitionOnLines + [ "member this.Foo() (*#1#*) = ()" + "member this.Foo(x) (*#2#*) = ()" + "override this.ToString() (*#3#*) = System.String.Empty" + "member this.ToString(s : string) (*#4#*) = ()" ] + +let private overloadStaticsSource = + String.concat + "\n" + [ "type T =" + " static member Foo(i : int) (*#1#*) = ()" + " static member Foo(s : string) (*#2#*) = ()" + "" + "T.Foo{caret1} 1 (*$1$*)" + "T.Foo{caret2} \"abc\" (*$2$*)" ] + +[] +let ``GotoDefinition.OverloadResolutionStatics`` () = + overloadStaticsSource + |> assertGoToDefinitionOnLines + [ "static member Foo(i : int) (*#1#*) = ()" + "static member Foo(s : string) (*#2#*) = ()" ] + +let private constructorsSource = + String.concat + "\n" + [ "type B() (*#1#*) =" + " new(i : int) (*#2#*) = B()" + " new(s : string) (*#3#*) = B()" + "" + "B()" + "B(1)" + "B(\"abc\")" + "" + "new B{caret1}() (*$1b$*)" + "new B{caret2}(1) (*$2b$*)" + "new B{caret3}(\"abc\") (*$3b$*)" + "" + "type D1() =" + " inherit B{caret4}() (*$1c$*)" + "" + "type D2() =" + " inherit B{caret5}(1) (*$2c$*)" + "" + "type D3() =" + " inherit B{caret6}(\"abc\") (*$3c$*)" + "" + "let o1 = { new B{caret7}() (*$1d$*) with" + " override this.ToString() = \"\"" + " }" + "let o2 = { new B{caret8}(1) (*$2d$*) with" + " override this.ToString() = \"\"" + " }" + "let o3 = { new B{caret9}(\"aaa\") (*$3d$*) with" + " override this.ToString() = \"\"" + " }" ] + +[] +let ``GotoDefinition.Constructors`` () = + constructorsSource + |> assertGoToDefinitionOnLines + [ "type B() (*#1#*) =" + "new(i : int) (*#2#*) = B()" + "new(s : string) (*#3#*) = B()" + "type B() (*#1#*) =" + "new(i : int) (*#2#*) = B()" + "new(s : string) (*#3#*) = B()" + "type B() (*#1#*) =" + "new(i : int) (*#2#*) = B()" + "new(s : string) (*#3#*) = B()" ] + +let private simplePolymorphSource = + String.concat + "\n" + [ "let _ =" + " let a = 2" + " let id (x : 'a{caret1}) (*loc-33*)" + " : 'a{caret2} = x (*loc-34*)" + " ()" ] + +[] +let ``GotoDefinition.Simple.Polymorph`` () = + simplePolymorphSource + |> assertGoToDefinitionOnLines (List.replicate 2 "let id (x : 'a) (*loc-33*)") + +let private bug2516ModuleSource = + """ + module GotoDefinition + type One{caret1}(*Mark1*) = One + let f (x : One{caret2}(*Mark2*)) = 2""" + +[] +let ``Identifier.Bug2516`` () = + bug2516ModuleSource + |> assertGoToDefinitionOnLines (List.replicate 2 "type One(*Mark1*) = One") diff --git a/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.TypeProviders.fs b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.TypeProviders.fs new file mode 100644 index 00000000000..c042c6a8f49 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/GotoDefinition/GotoDefinitionTests.TypeProviders.fs @@ -0,0 +1,59 @@ +module FSharp.Compiler.Service.Tests.GotoDefinitionTypeProvidersTests + +open Xunit + +[] +let ``GotoDefinition.TypeProvider.DefinitionLocationAttribute`` () = + let targetLine = "// A0(*ColumnMarker*)1234567890" + assertGoToDefinitionOnLine targetLine + "\nlet a = typeof\n// A0(*ColumnMarker*)1234567890\n// B01234567890\n// C01234567890 " + assertGoToDefinitionOnLine targetLine + "\nlet a = typeof\n// A0(*ColumnMarker*)1234567890\n// B01234567890\n// C01234567890 " + assertGoToDefinitionOnLine targetLine + "\nlet foo = new N.T{caret}(*GotoValDef*)()\n// A0(*ColumnMarker*)1234567890\n// B01234567890\n// C01234567890 " + assertGoToDefinitionOnLine targetLine + "\nlet t = new N.T.M{caret}(*GotoValDef*)()\n// A0(*ColumnMarker*)1234567890\n// B01234567890\n// C01234567890 " + assertGoToDefinitionOnLine targetLine + "\nlet p = N.T.StaticProp{caret}(*GotoValDef*)\n// A0(*ColumnMarker*)1234567890\n// B01234567890\n// C01234567890 " + assertGoToDefinitionOnLine targetLine + "\nlet t = new N.T()\nt.Event1{caret}(*GotoValDef*)\n// A0(*ColumnMarker*)1234567890\n// B01234567890\n// C01234567890 " + +[] +let ``GotoDefinition.ProvidedTypeNoDefinitionLocationAttribute`` () = + let source = "\ntype T = N1.T{caret}<\"\", 1>\n" + assertGoToDefinitionFails source + +[] +let ``GotoDefinition.ProvidedMemberNoDefinitionLocationAttribute`` () = + assertGoToDefinitionFails "\ntype T = N1.T<\"\", 1>\nT.Param1{caret}\n" + assertGoToDefinitionFails "\ntype T = N1.T1\nT.M1{caret}(1)\n" + +[] +let ``GotoDefinition.TypeProvider.DefinitionLocationAttribute.Type.FileDoesnotExist`` () = + let source = "\nlet a = typeof\n// A0(*Marker*)1234567890\n// B01234567890\n// C01234567890 " + assertGoToDefinitionFails source + +[] +let ``GotoDefinition.TypeProvider.DefinitionLocationAttribute.Type.LineDoesnotExist`` () = + let source = "\nlet a = typeof\n// A0(*Marker*)1234567890\n// B01234567890\n// C01234567890 " + assertGoToDefinitionFails source + +[] +let ``GotoDefinition.TypeProvider.DefinitionLocationAttribute.Constructor.FileDoesnotExist`` () = + let source = "\nlet foo = new N.T{caret}(*GotoValDef*)()\n// A0(*Marker*)1234567890\n// B01234567890\n// C01234567890 " + assertGoToDefinitionFails source + +[] +let ``GotoDefinition.TypeProvider.DefinitionLocationAttribute.Method.FileDoesnotExist`` () = + let source = "\nlet t = new N.T.M{caret}(*GotoValDef*)()\n// A0(*Marker*)1234567890\n// B01234567890\n// C01234567890 " + assertGoToDefinitionFails source + +[] +let ``GotoDefinition.TypeProvider.DefinitionLocationAttribute.Property.FileDoesnotExist`` () = + let source = "\nlet p = N.T.StaticProp{caret}(*GotoValDef*)\n// A0(*Marker*)1234567890\n// B01234567890\n// C01234567890 " + assertGoToDefinitionFails source + +[] +let ``GotoDefinition.TypeProvider.DefinitionLocationAttribute.Event.FileDoesnotExist`` () = + let source = "\nlet t = new N.T()\nt.Event1{caret}(*GotoValDef*)\n// A0(*Marker*)1234567890\n// B01234567890\n// C01234567890 " + assertGoToDefinitionFails source diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Attributes.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Attributes.fs new file mode 100644 index 00000000000..1b2e98dfd0a --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Attributes.fs @@ -0,0 +1,33 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoAttributesTests + +open Xunit + +[] +let ``Single.OnAttributes`` () = + assertParameterInfoOverloads [ []; [ "check: bool" ] ] """ +type Emp = + [] + static val mutable private m_ID : int""" + +[] +let ``LocationOfParams.Attributes.Bug230393`` () = + assertHasParameterInfo """ +let paramTest((strA : string),(strB : string)) = + strA + strB +param{caret}Test( + +[] +type RMB""" + +[] +let ``ParameterInfo.ArgumentsWithParamsArrayAttribute`` () = + assertParameterInfoContains [ "format"; "[] args" ] """let _ = System.String.Form{caret}at("",)""" + +[] +let ``Regression.Multi.ExplicitAnnotate.Bug93188`` () = + assertParameterInfoOverloads [ ["int"; "string"] ] """ +type LiveAnimalAttribute(a : int, b: string) = + inherit System.Attribute() + +[] +type Wombat() = class end""" diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.ByrefSpans.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.ByrefSpans.fs new file mode 100644 index 00000000000..b952444ce85 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.ByrefSpans.fs @@ -0,0 +1,27 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoByrefSpansTests + +open Xunit + +[] +let ``Single.DotNet.ParameterByReference`` () = + assertParameterInfoOverloads [ ["s: string"; "result: int byref"]; ["s"; "style"; "provider"; "result"] ] """ +let s = "1" +let _ = System.Int32.TryParse(s,{caret}""" + +[] +let ``Single.Locations.OperatorTrick3`` () = + assertHasParameterInfo """ +open System.Threading +let mutable n = null +let aaa = Interlocked.Excha{caret}nge(&n, new obj())""" + +let multiGenericExchangeCases: obj[] seq = + [ + [| box [ "byref"; "int" ]; box "System.Threading.Interlocked.Excha{caret}nge(123," |] + [| box [ "byref"; "float" ]; box "System.Threading.Interlocked.Excha{caret}nge(12.0," |] + [| box [ "byref"; "obj" ]; box "System.Threading.Interlocked.Excha{caret}nge<_> (obj," |] + ] + +[] +let ``Multi.Generic.Exchange`` (expected: string list) (source: string) = + assertParameterInfoContains expected source diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Classes.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Classes.fs new file mode 100644 index 00000000000..a0e5c77c252 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Classes.fs @@ -0,0 +1,52 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoClassesTests + +open Xunit + +[] +let ``Regression.OnConstructor.881644`` () = + assertParameterInfoContains ["path: string"] "new System.IO.StreamReader({caret}" + +[] +let ``Regression.MethodInfo.WithColon.Bug4518_3`` () = + assertFirstReturnTypeText ": unit" """ +type M() = + member this.f x = () +let m = new M() +m.f({caret}""" + +[] +let ``Single.Constructor1`` () = + assertHasParameterInfo "new System.DateTime({caret}" + +[] +let ``LocationOfParams.InsideAMemberOfAType`` () = + assertHasParameterInfo """ +type Widget(z) = + member x.a = (1 <> System.Int32.Pa{caret}rse("")) """ + +[] +let ``Multi.DotNet.StaticMethod.WithinClassMember`` () = + assertParameterInfoContains ["string"; "System.Globalization.NumberStyles"] """ +type Widget(z) = + member x.a = (1 <> System.Int32.Pa{caret}rse("", + +let widget = Widget(1) +45""" + +[] +let ``Multi.DotNet.Constructor`` () = + assertParameterInfoContains ["int"; "int"; "int"] "let _ = new System.Date{caret}Time(2010,12," + +[] +let ``Regression.OptionalArguments.Bug4042`` () = + assertParameterInfoOverloads [ ["x: int"; "?y int"] ] """ +module ParameterInfo +type TT(x : int, ?y : int) = + let z = y + do printfn "%A" z + member this.Foo(?z : int) = z + +type TT2(x : int, y : int option) = + let z = y + do printfn "%A" z +let tt = TT({caret}""" diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.ComputationExpressions.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.ComputationExpressions.fs new file mode 100644 index 00000000000..bfe63538e96 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.ComputationExpressions.fs @@ -0,0 +1,20 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoComputationExpressionsTests + +open Xunit + +[] +let ``Regression.InsideWorkflow.6437`` () = + assertParameterInfoContains ["count: int"] """ +open System.IO +let computation2 = + async { use file = File.Open("",FileMode.Open) + let! buffer = file.AsyncRead({caret}0) + return 0 }""" + +[] +let ``Regression.ParameterFirstTypeOpenParen.Bug90798`` () = + assertParameterInfoOverloads [ ["'Arg -> Async<'T>"] ] """ +let a = async { + Async.AsBeginEnd({caret} + } +let p = 10""" diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.DiscriminatedUnions.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.DiscriminatedUnions.fs new file mode 100644 index 00000000000..ce393a2b138 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.DiscriminatedUnions.fs @@ -0,0 +1,24 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoDiscriminatedUnionsTests + +open Xunit + +[] +let ``Single.DiscriminatedUnion.Construction`` () = + let du = """ +type MyDU = + | Case1 of int * string + | Case2 of V1 : int * string * V3 : bool + | Case3 of ``Long Name`` : int * Item2 : string + | Case4 of int +""" + assertParameterInfoOverloads [ ["int"; "string"] ] (du + "let x1 = Case1({caret}") + assertParameterInfoOverloads [ ["V1: int"; "string"; "V3: bool"] ] (du + "let x2 = Case2({caret}") + assertParameterInfoOverloads [ ["``Long Name`` : int"; "string"] ] (du + "let x3 = Case3({caret}") + assertParameterInfoOverloads [ ["int"] ] (du + "let x4 = Case4({caret}") + +[] +let ``LocationOfParams.Unions1`` () = + assertHasParameterInfo """ +type MyDU = + | FOO of int * string +let r = F{caret}OO(42,"") """ diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Events.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Events.fs new file mode 100644 index 00000000000..33bdc52c3ca --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Events.fs @@ -0,0 +1,15 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoEventsTests + +open Xunit + +[] +let ``Single.Generics.EventHandler`` () = + assertParameterInfoOverloads [ [""] ] "open System\nnew System.EventHandler( {caret}" + +[] +let ``Single.Generics.EventHandlerEventArgs`` () = + assertParameterInfoOverloads [ [""] ] "open System\nSystem.EventHandler({caret}" + +[] +let ``Single.Generics.EventHandlerEventArgsNew`` () = + assertParameterInfoOverloads [ [""] ] "open System\nnew System.EventHandler ( {caret}" diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Exceptions.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Exceptions.fs new file mode 100644 index 00000000000..f7138f26431 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Exceptions.fs @@ -0,0 +1,14 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoExceptionsTests + +open Xunit + +[] +let ``Single.Exception.Construction`` () = + let exns = """ +exception E1 of int * string +exception E2 of V1 : int * string * V3 : bool +exception E3 of ``Long Name`` : int * Data1 : string +""" + assertParameterInfoOverloads [ ["int"; "string"] ] (exns + "let x1 = E1({caret}") + assertParameterInfoOverloads [ ["V1: int"; "string"; "V3: bool"] ] (exns + "let x2 = E2({caret}") + assertParameterInfoOverloads [ ["``Long Name`` : int"; "string"] ] (exns + "let x3 = E3({caret}") diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Functions.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Functions.fs new file mode 100644 index 00000000000..3c1abfb9432 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Functions.fs @@ -0,0 +1,32 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoFunctionsTests + +open Xunit + +[] +let ``Regression.MethodInfo.WithColon.Bug4518_5`` () = + assertFirstReturnTypeText ": (int -> int) " """ + let f x y = x + y + f({caret}""" + +[] +let ``Single.BasicFSharpFunction`` () = + assertParameterInfoOverloads [["x: 'a"]] """ + let foo(x) = 1 + foo({caret}""" + +[] +let ``Single.Locations.FunctionWithSpace`` () = + assertHasParameterInfo "let a = sin 0{caret}.0" + +[] +let ``LocationOfParams.ThisOnceAssertedToo`` () = + assertNoParameterInfo """ + let readString() = + let x = 42 + while ('"' = '""' then + () + else + let sb = new System.Text.StringBuilder() + while true do + ({caret}) """ + diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Generics.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Generics.fs new file mode 100644 index 00000000000..1dc982aa032 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Generics.fs @@ -0,0 +1,106 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoGenericsTests + +open Xunit + +[] +let ``Single.Generics.Typeof`` () = + assertNoParameterInfo "typeof({caret}" + +[] +let ``Single.Generics.MathAbs`` () = + assertParameterInfoOverloads (List.replicate 7 ["value"]) """ +open System +Math.Abs({caret}""" + +[] +let ``Single.Generics.ExchangeInt`` () = + assertParameterInfoOverloads (List.replicate 7 ["location1"; "value"]) """ +open System.Threading +Interlocked.Exchange({caret}""" + +[] +let ``Single.Generics.Exchange`` () = + assertParameterInfoOverloads (List.replicate 7 ["location1"; "value"]) """ +open System.Threading +Interlocked.Exchange({caret}""" + +[] +let ``Single.Generics.ExchangeUnder`` () = + assertParameterInfoOverloads (List.replicate 7 ["location1"; "value"]) """ +open System.Threading +Interlocked.Exchange<_> ({caret}""" + +[] +let ``Single.Generics.Dictionary`` () = + assertParameterInfoOverloads [ []; ["capacity"]; ["comparer"]; ["capacity"; "comparer"]; ["dictionary"]; ["dictionary"; "comparer"] ] """ +System.Collections.Generic.Dictionary<_, option>({caret}""" + +[] +let ``Single.Generics.List`` () = + assertParameterInfoOverloads [ []; ["capacity"]; ["collection"] ] """ +new System.Collections.Generic.List< _ > ( {caret}""" + +[] +let ``Single.Generics.ListInt`` () = + assertParameterInfoOverloads [ []; ["capacity"]; ["collection"] ] """ +System.Collections.Generic.List({caret}""" + +[] +let ``Single.Locations.GenericCtorWithNamespace`` () = + assertHasParameterInfo "let _ = new System.Collections.Generic.Dictionary<_, _>({caret})" + +[] +let ``Single.Locations.GenericCtor`` () = + assertHasParameterInfo """ +open System.Collections.Generic +let _ = new Dictionary<_, _>({caret})""" + +[] +let ``Single.Locations.Multiline.IdentOnPrevLineWithGenerics`` () = + assertHasParameterInfo """ +open System.Collections.Generic +let d = Dictionar{caret}y<_, option< int >> + ( )""" + +[] +let ``Single.Locations.GenericCtorWithoutNew`` () = + assertHasParameterInfo "let d = System.Collections.Generic.Dictionar{caret}y<_, option< int >> ( )" + +[] +let ``Single.Locations.Multiline.GenericTyargsOnTheSameLine`` () = + assertHasParameterInfo "let dict3 = System.Collections.Generic.Dictionar{caret}y<_, \n option< int>>( )" + +[] +let ``ParameterInfo.LocationOfParams.Bug112340`` () = + assertHasParameterInfo """let a = typeof] +let ``LocationOfParams.Generics1`` () = + assertHasParameterInfo """ + let f<'T,'U>(x:'T, y:'U) = (y,x) + let r = f{caret}(42,"")""" + +[] +let ``LocationOfParams.Generics2`` () = + assertHasParameterInfo """let x = System.Collections.Generic.Dictionar{caret}y(42,null)""" + +[] +let ``LocationOfParams.EvenWhenOverloadResolutionFails.Case2`` () = + assertHasParameterInfo """ + open System.Collections.Generic + open System.Linq + let l = List([||]) + l.Aggregate({caret}) // was once a bug""" + +[] +let ``Multi.Generic.Dictionary`` () = + assertParameterInfoContains ["int"; "System.Collections.Generic.IEqualityComparer"] "System.Collections.Generic.Dictionar{caret}y<_, option>(12," + +[] +let ``Multi.Generic.HashSet`` () = + assertParameterInfoContains ["Seq<'a>"; "System.Collections.Generic.IEqualityComparer<'a>"] "System.Collections.Generic.HashSet({ 1 ..12 },{caret}" + +[] +let ``Multi.Generic.SortedList`` () = + assertParameterInfoContains ["int"; "System.Collections.Generic.IComparer<'TKey>"] "System.Collections.Generic.SortedList<_,option> (12,{caret}" diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.IndexingSlicing.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.IndexingSlicing.fs new file mode 100644 index 00000000000..14ae2220e84 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.IndexingSlicing.fs @@ -0,0 +1,33 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoIndexingSlicingTests + +open Xunit + +[] +let ``Single.DotNet.IndexerParameter`` () = + assertParameterInfoOverloads [ ["index: int"] ] """ +let alist = System.Collections.ArrayList(2) +alist.[{caret}0] |> ignore""" + +[] +let ``LocationOfParams.UnmatchedParens.Bug91609.OtherCases.Open`` () = + assertHasParameterInfo """ +let arr = Array.create 4 1 +arr.[1] <- System.Int32.Parse({caret} +open System""" + +[] +let ``LocationOfParams.UnmatchedParens.Bug91609.OtherCases.Module`` () = + assertHasParameterInfo """ +let arr = Array.create 4 1 +arr.[1] <- System.Int32.Parse({caret} +module Foo = + let x = 42""" + +[] +let ``LocationOfParams.UnmatchedParens.Bug91609.OtherCases.Namespace`` () = + assertHasParameterInfo """ +namespace Foo +module Bar = + let arr = Array.create 4 1 + arr.[1] <- System.Int32.Parse({caret} +namespace Other""" diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Interfaces.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Interfaces.fs new file mode 100644 index 00000000000..c44cd07abce --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Interfaces.fs @@ -0,0 +1,12 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoInterfacesTests + +open Xunit + +[] +let ``Regression.MethodInfo.WithColon.Bug4518_2`` () = + assertFirstReturnTypeText ": int" """ +type IFoo = interface + abstract f : int -> int + end +let i : IFoo = null +i.f({caret}""" diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Lambdas.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Lambdas.fs new file mode 100644 index 00000000000..1caebc2db94 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Lambdas.fs @@ -0,0 +1,15 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoLambdasTests + +open Xunit + +[] +let ``Regression.LocationOfParams.Bug91479`` () = + assertHasParameterInfo "let z = fun x -> x + System.Int16.Parse({caret} " + +[] +let ``Multi.DotNet.StaticMethod.WithinLambda`` () = + assertParameterInfoContains ["string"; "System.Globalization.NumberStyles"] """let z = fun x -> x + System.Int16.Parse("",{caret}""" + +[] +let ``Multi.DotNet.StaticMethod.WithinLambda2`` () = + assertParameterInfoOverloads [ ["fileName: string"] ] "let _ = fun file -> new System.IO.FileInfo({caret}" diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.LetBindings.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.LetBindings.fs new file mode 100644 index 00000000000..581cdb04feb --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.LetBindings.fs @@ -0,0 +1,11 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoLetBindingsTests + +open Xunit + +[] +let ``Single.InString`` () = + assertNoParameterInfo """let s = "System.Console.WriteLine({caret})" """ + +[] +let ``Multi.NoParameterInfo.WithinString`` () = + assertNoParameterInfo """let s = "new System.DateTime(2000,12{caret}" """ diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Members.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Members.fs new file mode 100644 index 00000000000..752c63474dc --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Members.fs @@ -0,0 +1,144 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoMembersTests + +open Xunit + +[] +let ``Regression.MethodInfo.Bug808310`` () = + assertHasParameterInfo "System.Console.WriteLine({caret}" + +[] +let ``Single.DotNet.StaticMethod`` () = + assertParameterInfoOverloads [["objA"; "objB"]] "System.Object.ReferenceEquals({caret}" + +[] +let ``Regression.NoParameterInfo.100I.Bug5038`` () = + assertNoParameterInfo "100I({caret}" + +[] +let ``Single.DotNet.InstanceMethod`` () = + assertParameterInfoOverloads [["startIndex: int"]; ["startIndex: int"; "length: int"]] """ +let s = "Hello" +s.Substring({caret}""" + +[] +let ``Single.DotNet.NoParameters`` () = + assertParameterInfoOverloads [[]] """ +let x = "a" +x.ToUpperInvariant({caret}""" + +[] +let ``Single.DotNet.OnSecondParameter`` () = + assertHasParameterInfo "System.String.Format(\"x\",{caret}" + +[] +let ``Single.Locations.PointOfDefinition`` () = + assertNoParameterInfo """ +type FunkyType = + private new({caret}) = {}""" + +[] +let ``Single.Locations.AfterTypeAnnotation`` () = + assertNoParameterInfo """ +type Emp = + val mutable private m_DoB : System.DateTime + {caret}""" + +[] +let ``Single.Locations.AfterValues`` () = + assertNoParameterInfo "let _ = <@@ let x = 1 in x{caret} @@>" + +[] +let ``Single.Locations.EndOfFile`` () = + assertParameterInfoOverloads [[]] "System.Console.ReadLine({caret}" + +[] +let ``Single.QuotedIdentifier`` () = + assertParameterInfoOverloads [[]; ["maxValue: int"]; ["minValue: int"; "maxValue: int"]] """ +let ``Random Number Generator`` = System.Random() +let ``?Max!Value?`` = 100 +let _ = ``Random Number Generator``.Next({caret}``?Max!Value?``)""" + +[] +let ``Single.Locations.LineWithSpaces`` () = + assertHasParameterInfo """ +let r = + System.Math.Abs({caret}0)""" + +[] +let ``Single.Locations.FullCall`` () = + assertHasParameterInfo "System.Math.Abs({caret}0)" + +[] +let ``Single.Locations.SpacesAfterParen`` () = + assertHasParameterInfo """ +open System +let a = Math.Sign({caret}-10 )""" + +[] +let ``Single.Locations.MethodCallWithoutParens`` () = + assertHasParameterInfo """ +open System +let n = Math.Sin 1{caret}0.0""" + +[] +let ``Single.Locations.Multiline.IdentOnPrevPrevLine`` () = + assertHasParameterInfo """ +open System +do Console.WriteLine + ({caret} + "Multiline")""" + +[] +let ``Single.Locations.Multiline.LongIdentSplit`` () = + assertHasParameterInfo """ +let ll = new System.Collections. + Generic.List< _ > ({caret})""" + +[] +let ``Single.InComment`` () = + assertNoParameterInfo "// System.Console.WriteLine({caret})" + +[] +let ``LocationOfParams.Case1`` () = + assertHasParameterInfo "System.Console.WriteLine({caret}\"hello\")" + +[] +let ``LocationOfParams.Case3`` () = + assertHasParameterInfo """System.Console.WriteLine + ({caret} + "hello {0}" , + "Brian" ) """ + +[] +let ``LocationOfParams.InsideObjectExpression`` () = + assertHasParameterInfo "let _ = { new System.Object({caret}) with member _.GetHashCode() = 2}" + +[] +let ``LocationOfParams.Nested1`` () = + assertHasParameterInfo "System.Console.WriteLine(\"hello {0}\" , sin ({caret}42.0 ) )" + +[] +let ``LocationOfParams.EvenWhenOverloadResolutionFails.Case1`` () = + assertHasParameterInfo "let a = new System.IO.FileStream({caret})" + +[] +let ``Multi.DotNet.InstanceMethod`` () = + assertParameterInfoContains ["startIndex: int"; "length: int"] """ +let s = "Hello" +s.Substring({caret}0,1)""" + +[] +let ``Multi.OverloadMethod.OrderedParameters`` () = + assertParameterInfoContains ["year: int"; "month: int"; "day: int"] "new System.DateTime({caret}2000,12,1)" + +[] +let ``ParameterInfo.Multi.NoParameterInfo.InComments`` () = + assertNoParameterInfo "//let _ = System.Object({caret})" + +[] +let ``Multi.NoParameterInfo.InComments2`` () = + assertNoParameterInfo "(*System.Console.WriteLine({caret}\"Test on Fsharp style comments.\")*)" + +[] +let ``BasicBehavior.DotNet.Static`` () = + assertParameterInfoContains ["string"; "obj array"] "System.String.Format({caret}" diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Modules.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Modules.fs new file mode 100644 index 00000000000..2d0f6c93ba6 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Modules.fs @@ -0,0 +1,23 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoModulesTests + +open Xunit + +[] +let ``Regression.MethodSortedByArgumentCount.Bug4495.Case1`` () = + assertParameterInfoOverloadIndex 0 ["System.Type array"] """ +module ParameterInfo + +let a1 = System.Reflection.Assembly.Load("mscorlib") +let m = a1.GetType("System.Decimal").GetConstructor({caret}null)""" + +[] +let ``Regression.MethodSortedByArgumentCount.Bug4495.Case2`` () = + assertParameterInfoContains + [ "System.Reflection.BindingFlags" + "System.Reflection.Binder" + "System.Type array" + "System.Reflection.ParameterModifier array" ] """ +module ParameterInfo + +let a1 = System.Reflection.Assembly.Load("mscorlib") +let m = a1.GetType("System.Decimal").GetConstructor({caret}null)""" diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Namespaces.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Namespaces.fs new file mode 100644 index 00000000000..85bf267f031 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Namespaces.fs @@ -0,0 +1,11 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoNamespacesTests + +open Xunit + +[] +let ``Single.Locations.WithNamespace`` () = + assertHasParameterInfo "let a = System.Threading.Interlocked.Exchange({caret}" + +[] +let ``ParameterInfo.Locations.WithoutNamespace`` () = + assertHasParameterInfo "open System.Threading\nlet a = Interlocked.Exchange({caret}" diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.ObjectExpressions.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.ObjectExpressions.fs new file mode 100644 index 00000000000..f16503871c9 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.ObjectExpressions.fs @@ -0,0 +1,7 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoObjectExpressionsTests + +open Xunit + +[] +let ``Multi.Constructor.WithinObjectExpression`` () = + assertParameterInfoOverloads [[]] "let _ = { new System.Object({caret}) with member _.GetHashCode() = 2}" diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.OpenDirectives.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.OpenDirectives.fs new file mode 100644 index 00000000000..27c93f782d0 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.OpenDirectives.fs @@ -0,0 +1,25 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoOpenDirectivesTests + +open Xunit + +[] +let ``Single.Constructor2`` () = + assertHasParameterInfo """ +open System +new DateTime({caret}""" + +[] +let ``Regression.NoParameterInfoTriggeredByOpenBrace.Bug3878`` () = + assertParameterInfoContains ["value: string"] """ +module ParameterInfo +let x = 1 + 2 + +let _ = System.Console.WriteLin{caret}e () + +let y = 1""" + +[] +let ``BasicBehavior.WithReference`` () = + assertParameterInfoContains ["System.Type"; "System.Uri []"] """ +open System.ServiceModel +let serviceHost = new ServiceHost({caret})""" diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Operators.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Operators.fs new file mode 100644 index 00000000000..8593314a65d --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Operators.fs @@ -0,0 +1,23 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoOperatorsTests + +open Xunit + +[) operator group; the negative case was editor-layer only")>] +let ``Single.Negative.OperatorTrick1`` () = + assertNoParameterInfo "let fooo = 0\n >({caret} 1 )" + +[] +let ``Single.Negative.OperatorTrick2`` () = + assertNoParameterInfo "let fooo = 0\n <({caret} 1 )" + +[] +let ``LocationOfParams.InfixOperators.Case1`` () = + assertHasParameterInfo """System.Console.Write{caret}Line("" + "")""" + +[] +let ``LocationOfParams.InfixOperators.Case2`` () = + assertHasParameterInfo """System.Console.Write{caret}Line((+)(3)(4))""" + +[] +let ``Regression.ParameterWithOperators.Bug90832`` () = + assertParameterInfoContains ["value: string"] """System.Console.Write{caret}Line("This is a" + " bug.")""" diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.PatternMatching.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.PatternMatching.fs new file mode 100644 index 00000000000..96684a8a41b --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.PatternMatching.fs @@ -0,0 +1,53 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoPatternMatchingTests + +open Xunit + +[] +let ``Single.InMatchClause`` () = + assertParameterInfoOverloads + [ ["format"; "arg0"] + ["format"; "args"] + ["provider"; "format"; "args"] + ["format"; "arg0"; "arg1"] + ["format"; "arg0"; "arg1"; "arg2"] + ["provider"; "format"; "arg0"] + ["provider"; "format"; "arg0"; "arg1"] + ["provider"; "format"; "arg0"; "arg1"; "arg2"] ] """ +let rec f l = + match l with + | [] -> System.String.Format({caret} + | x :: xs -> f xs""" + +[] +let ``LocationOfParams.MatchGuard`` () = + assertHasParameterInfo """match [1] with | [x] when box({caret}x) <> null -> ()""" + +[] +let ``LocationOfParams.ThisOnceAsserted`` () = + assertNoParameterInfo """ +module CSVTypeProvider + +f(fun x -> + match args with + | [| y |] -> + for name, kind in (headerNames, + rowType.AddMember(new ProvidedProperty({caret} + null + | _ -> failwith "unexpected generic params" )""" + +[] +let ``Multi.MethodInMatchCause`` () = + assertParameterInfoContains ["format"; "arg0"] """ +let rec f l = + match l with + | [] -> System.String.For{caret}mat("{0:X2}", + | x :: xs -> f xs""" + +[] +let ``Regression.Multi.IndexerProperty.Bug93945`` () = + assertParameterInfoOverloads [["int"; "int"]] """ +type Year2(year : int) = + member this.Item (month : int, day : int) = month + day + +let O'seven = new Year2(2007) +let randomDay = O'seven.[12,{caret}""" diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Properties.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Properties.fs new file mode 100644 index 00000000000..12ac004a070 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Properties.fs @@ -0,0 +1,45 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoPropertiesTests + +open Xunit + +[] +let ``Regression.MethodInfo.WithColon.Bug4518_1`` () = + assertFirstReturnTypeText ": int" """ +type T() = + member this.X + with set ((a:int), (b:int)) (c:int) = () +((new T()).X({caret}""" + +[] +let ``Single.Locations.AfterProperties`` () = + assertNoParameterInfo "System.DateTime.Today{caret}" + +let private propertyGetterSetterSource = """ +type Widget(z) = + member x.P1 + with get() = System.Int32.Parse("") + and set(z) = System.Int32.Parse("") |> ignore + member x.P2 with get() = System.Int32.Parse("") + member x.P2 with set(z) = System.Int32.Parse("") |> ignore""" + +[] +let ``LocationOfParams.InsidePropertyGettersAndSetters.Case1`` () = + assertHasParameterInfo (markAtEndOfMarker propertyGetterSetterSource "with get() = System.Int32.Pa") + +[] +let ``LocationOfParams.InsidePropertyGettersAndSetters.Case2`` () = + assertHasParameterInfo (markAtEndOfMarker propertyGetterSetterSource "and set(z) = System.Int32.Pa") + +[] +let ``LocationOfParams.InsidePropertyGettersAndSetters.Case3`` () = + assertHasParameterInfo (markAtEndOfMarker propertyGetterSetterSource "P2 with get() = System.Int32.Pa") + +[] +let ``LocationOfParams.InsidePropertyGettersAndSetters.Case4`` () = + assertHasParameterInfo (markAtEndOfMarker propertyGetterSetterSource "P2 with set(z) = System.Int32.Pa") + +[] +let ``Multi.NoParameterInfo.OnProperty`` () = + assertNoParameterInfo """ +let s = "Hello" +let _ = s.Length{caret}""" diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Queries.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Queries.fs new file mode 100644 index 00000000000..20c3ccbaf8c --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Queries.fs @@ -0,0 +1,85 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoQueriesTests + +open Xunit + +[] +let ``LocationOfParams.UnmatchedParensBeforeModuleKeyword.Bug245850.Case2a`` () = + assertHasParameterInfo """ +module Repro = + query { for a in System.Int16.TryParse({caret} +module AA = + let x = 10""" + +[] +let ``Query.InNestedQuery`` () = + assertParameterInfoContains ["obj"] """ +let tuples = [ (1, 8, 9); (56, 45, 3)] +let numbers = [ 1;2; 8; 9; 15; 23; 3; 42; 4;0; 55;] +let tp = (2,3,6) +let foo = + query { + for n in numbers do + yield (n, query {for x in tuples do + let r = x.Equals({caret}tp) + select r }) + }""" + +[] +let ``Query.WithErrors`` () = + assertParameterInfoContains ["obj"] """ +let tuples = [ (1, 8, 9); (56, 45, 3)] +let tp = (2,3,6) +let foo = + query { + for t in tuples do + orderBy (t.Equals({caret}tp)) + }""" + +[] +let ``Query.OperatorWithParentheses`` () = + assertParameterInfoContains [] """ +let categories = ["Beverages"; "Condiments"; "Vegetables";] +let products = [1;2;3] +let q2 = + query { + for c in categories do + groupJoin({caret}for p in products -> c = p) into ps + select (c, ps) + } |> Seq.toArray""" + +[] +let ``Query.OptionalArgumentsInQuery`` () = + assertParameterInfoContains ["x: int"; "?y int"] """ +type TT(x : int, ?y : int) = + let z = y + do printfn "%A" z + member this.Foo(?z : int) = z + +type TT2(x : int, y : int option) = + let z = y + do printfn "%A" z +let numbers = [ 1;2; 8; 9; 15; 23; 3; 42; 4;0; 55;] + +let test3 = + query { + for n in numbers do + let tt = TT({caret} + minBy n + }""" + +[] +let ``Query.OverloadMethod.InQuery`` () = + assertParameterInfoContains ["int"; "int"; "string"; "bool"] """ +let numbers = [ 1;2; 8; 9; 15; 23; 3; 42; 4;0; 55;] + +type Foo() = + member this.A1(x1 : int, x2 : int, ?y : string, ?Z: bool) = () + member this.A1(x1 : int, X2 : string, ?y : int, ?Z: bool) = () + +let test3 = + query { + for n in numbers do + let foo = new Foo() + foo.A1(1,1,{caret} + minBy n + }""" diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Records.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Records.fs new file mode 100644 index 00000000000..87db424e587 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Records.fs @@ -0,0 +1,28 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoRecordsTests + +open Xunit + +[] +let ``Single.RecordAndUnionType`` () = + assertParameterInfoOverloads [ [ "Fruit"; "KeyValuePair" ] ] """ +type Fruit = | Apple | Banana +type KeyValuePair = { Key : int; Value : float } +let print (x : Fruit, kvp : KeyValuePair) = System.Console.WriteLine(x); System.Console.WriteLine(kvp) +pri{caret}nt (Banana, {Key = 0; Value = 0.0})""" + +[] +let ``Multi.Function.WithRecordType`` () = + assertParameterInfoOverloads [ ["int"; "Vector"] ] """ +type Vector = + { X : float; Y : float; Z : float } +let foo(x : int,v : Vector) = () +fo{caret}o(12, { X = 10.0; Y = 20.0; Z = 30.0 })""" + +[] +let ``Multi.NoParameterInfo.OnValues`` () = + assertNoParameterInfo """ +type Foo = class + val private size : int + val private path : string + new (s : int, p : string) = {size = s; path{caret} = p} +end""" diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.SeqListArrayExprs.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.SeqListArrayExprs.fs new file mode 100644 index 00000000000..ec2a091a41f --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.SeqListArrayExprs.fs @@ -0,0 +1,36 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoSeqListArrayExprsTests + +open Xunit + +[] +let ``Single.DotNet.ParameterArray`` () = + assertParameterInfoOverloads + [ ["format"; "args"] + ["format"; "arg0"] + ["provider"; "format"; "args"] + ["format"; "arg0"; "arg1"] + ["format"; "arg0"; "arg1"; "arg2"] ] """ +let x = "a" +System.String.Format("[{0}] for [{1}]", x.ToUpperInvariant(){caret}, x)""" + +[] +let ``ParameterInfo.LocationOfParams.Bug112688`` () = + assertNoParameterInfo """ +let f x y = () +module MailboxProcessorBasicTests = + do f 0 + 0 + {caret}let zz = 42 + for timeout in [0; 10] do + ()""" + +[] +let ``Multi.Function.AsParameter`` () = + assertParameterInfoOverloads [ ["int list"] ] """ +let isLessThanZero x = (x < 0) +let containsNegativeNumbers intList = + let filteredList = List.filter isLessThanZero intList + if List.length filteredList > 0 + then Some(filteredList) + else None +let _ = Option.get(containsNegativeNumber{caret}s [6; 20; 8; 45; 5])""" diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.StringsInterpolation.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.StringsInterpolation.fs new file mode 100644 index 00000000000..35ed13ec949 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.StringsInterpolation.fs @@ -0,0 +1,17 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoStringsInterpolationTests + +open Xunit + +[] +let ``Single.Locations.Multiline.IdentOnPrevLine`` () = + assertHasParameterInfo """ +open System +do Console.WriteLine + ({caret}"Multiline")""" + +[] +let ``LocationOfParams.GenericMethodExplicitTypeArgs()`` () = + assertHasParameterInfo """ +type T<'a> = + static member M(x:int, y:string) = x + y.Length +let x = T.M{caret}(1, "test") """ diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Tuples.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Tuples.fs new file mode 100644 index 00000000000..185d3fc0efc --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.Tuples.fs @@ -0,0 +1,145 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoTuplesTests + +open Xunit + +[] +let ``Regression.MethodInfo.WithColon.Bug4518_4`` () = + assertFirstReturnTypeText ": string" """ + type T() = + member this.Foo(a,b) = "" + let t = new T() + t.Foo({caret}""" + +[] +let ``ParameterInfo.NamesOfParams`` () = + assertParameterInfoOverloads [["a: int"; "b: bool"; "c: int"; "d: int"; "?e int"]] """ +type Foo = + static member F(a:int, b:bool, c:int, d:int, ?e:int) = () +let a = 42 +Foo.F({caret}0,(a=42),d=3,?e=Some 4,c=2)""" + +[] +let ``LocationOfParams.Case2`` () = + assertHasParameterInfo """System.Console.WriteLine({caret}"hello {0}" , "Brian" )""" + +[] +let ``LocationOfParams.Case4`` () = + assertHasParameterInfo """System.Console.WriteLine({caret}"hello {0}" , ("tuples","don't confuse it") )""" + +[] +let ``LocationOfParams.Nested2`` () = + assertHasParameterInfo """System.Console.WriteLine({caret}"hello {0}" , sin 42.0 )""" + +[] +let ``LocationOfParams.BY_DESIGN.WayThatMismatchedParensFailOver.Case1`` () = + assertHasParameterInfo """ + type CC() = + member this.M(a,b,c,d) = a+b+c+d + let c = new CC() + c.M({caret}1,2,3, + c.M(1,2,3,4)""" + +[] +let ``LocationOfParams.BY_DESIGN.WayThatMismatchedParensFailOver.Case2`` () = + assertHasParameterInfo """ + type CC() = + member this.M(a,b,c,d) = a+b+c+d + let c = new CC() + c.M({caret}1,2,3, + c.M(1,2,3,4) + c.M(1,2,3,4) + c.M(1,2,3,4)""" + +[] +let ``LocationOfParams.Tuples.Bug91360.Case1`` () = + assertHasParameterInfo """System.Console.WriteLine({caret} (42,43) ) // oops""" + +[] +let ``LocationOfParams.Tuples.Bug91360.Case2`` () = + assertHasParameterInfo """System.Console.WriteLine({caret}(42,43) ) // oops""" + +[] +let ``LocationOfParams.InheritsClause.Bug192134`` () = + assertHasParameterInfo """ + type B(x : int) = + new(x1:int, x2: int) = new B(10) + type A() = + inherit B({caret}1,2)""" + +[] +let ``ParameterNamesInFunctionsDefinedByLetBindings`` () = + assertParameterInfoOverloads [["n1: int"]] "let foo (n1 : int) (n2 : int) = n1 + n2\nfoo({caret}" + assertParameterInfoOverloads [["n1: int"; "n2: int"]] "let foo (n1 : int, n2 : int) = n1 + n2\nfoo({caret}" + assertParameterInfoOverloads [["'a -> 'b"]] "let foo = List.map\nfoo({caret}" + assertParameterInfoOverloads [["int"]] "let foo x =\n let bar y = x + y\n bar({caret}" + assertParameterInfoOverloads [["int option"]] "let f (Some x) = x + 1\nf({caret}" + +[] +let ``Multi.DotNet.StaticMethod`` () = + assertParameterInfoContains ["format"; "arg0"] """System.Console.WriteLine({caret}"Today is {0:dd MMM yyyy}",System.DateTime.Today)""" + +[] +let ``Multi.Function.InTheClassMember`` () = + assertParameterInfoOverloads [["int"; "int"]] """ + type Foo() = + let foo1(a : int, b:int) = () + + member this.A() = + foo1({caret}1, + member this.A(a : string, b:int) = ()""" + +[] +let ``Multi.ParamAsTupleType`` () = + assertParameterInfoOverloads [["int * int"; "int"]] """ + let tuple((a : int, b : int), c : int) = a * b + c + let result = tuple({caret}(1, 2), 3)""" + +[] +let ``Multi.ParamAsCurryType`` () = + assertParameterInfoOverloads [["x: float"]] """ + let multi (x : float) (y : float) = 0 + let sum(a, b) = a + b + let rtnValue = sum(multi({caret}1.0) 3.0, 5)""" + +[] +let ``Multi.Function.WithOptionType`` () = + assertParameterInfoOverloads [["int option"; "string ref"]] """ + let foo( a : int option, b : string ref) = 0 + let _ = foo({caret}Some(12),""" + +[] +let ``Multi.Function.WithOptionType2`` () = + assertParameterInfoOverloads [["int option"; "float option"]] """ + let multi (x : float) (y : float) = x * y + let sum(a : int, b) = a + b + let options(a1 : int option, b1 : float option) = a1.ToString() + b1.ToString() + let rtnOption = options({caret}Some(sum(1, 3)), Some(multi 3.1 5.0)) """ + +[] +let ``Multi.Function.WithRefType`` () = + assertParameterInfoOverloads [["int ref"; "string ref"]] """ + let foo( a : int ref, b : string ref) = 0 + let _ = foo({caret}ref 12,""" + +[] +let ``Multi.Overload.WithSameParameterCount`` () = + assertParameterInfoOverloads [["int"; "int"; "string"; "bool"]; ["int"; "string"; "int"; "bool"]] """ + type Foo() = + member this.A1(x1 : int, x2 : int, ?y : string, ?Z: bool) = () + member this.A1(x1 : int, X2 : string, ?y : int, ?Z: bool) = () + let foo = new Foo() + foo.A1({caret}1,1,""" + +[] +let ``Multi.NoParameterInfo.OnFunctionDeclaration`` () = + assertNoParameterInfo "let Foo(x : int, {caret}b : string) = ()" + +[] +let ``LocationOfParams.Tuples.Bug123219`` () = + assertHasParameterInfo """ +type Expr = | Num of int +type T<'a>() = + member this.M1(a:int*string, b:'a -> unit) = () +let x = new T() + +x.M1((1,{caret} """ diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.TypeAnnotations.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.TypeAnnotations.fs new file mode 100644 index 00000000000..678d7dc5321 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.TypeAnnotations.fs @@ -0,0 +1,53 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoTypeAnnotationsTests + +open Xunit + +[] +let ``Regression.StaticVsInstance.Bug3626.Case1`` () = + assertParameterInfoOverloads [["staticReturnsInt: int"]] """ +type Foo() = + member this.Bar(instanceReturnsString:int) = "hllo" + static member Bar(staticReturnsInt:int) = 13 +let z = Foo.Bar({caret})""" + +[] +let ``Regression.StaticVsInstance.Bug3626.Case2`` () = + assertParameterInfoOverloads [["instanceReturnsString: int"]] """ +type Foo() = + member this.Bar(instanceReturnsString:int) = "hllo" + static member Bar(staticReturnsInt:int) = 13 +let Hoo = new Foo() +let y = Hoo.Bar({caret}""" + +[] +let ``NoArguments`` () = + assertParameterInfoOverloads [[]] """ +type T = + static member F() = 42 +let r1 = T.F({caret})""" + assertParameterInfoOverloads [[]] """ +type T = + static member G(x:unit) = 42 +let r2 = T.G({caret})""" + assertParameterInfoOverloads [[]] """ +let h((x:unit)) = 42 +let r3 = h({caret})""" + assertParameterInfoOverloads [[]] """ +let g() = 42 +let r4 = g({caret})""" + +[] +let ``Single.DotNet.OneParameter`` () = + assertParameterInfoOverloads [["value: int"]] "System.DateTime.Today.AddYears({caret}" + +[] +let ``Single.DotNet.RefTypeValueType`` () = + assertParameterInfoOverloads [ []; ["name: string"; "salary: float"; "dob: System.DateTime"]; ["name: string"; "dob: System.DateTime"] ] """ +type Emp = + val mutable private m_Name : string + val mutable private m_Salary : float + val mutable private m_DoB : System.DateTime + public new() = { m_Name = System.String.Empty; m_Salary = 0.0; m_DoB = System.DateTime.Today } + public new(name, salary, dob) = { m_Name = name; m_Salary = salary; m_DoB = dob } + public new(name, dob) = new Emp(name, 0.0, dob) +let _ = Emp({caret}""" diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.TypeExtensions.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.TypeExtensions.fs new file mode 100644 index 00000000000..a4f6c35d5a9 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.TypeExtensions.fs @@ -0,0 +1,33 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoTypeExtensionsTests + +open Xunit + +[] +let ``ExtensionMethod.Overloads`` () = + assertParameterInfoOverloads [ ["a: string"]; ["a: int"] ] """ +module MyCode = + type A() = + member this.Method(a:string) = "" +module MyExtension = + type MyCode.A with + member this.Method(a:int) = "" + +open MyCode +open MyExtension +let foo = A() +foo.Method({caret}""" + +[] +let ``ExtensionProperty.Overloads`` () = + assertParameterInfoOverloads [ ["string"]; ["int"] ] """ +module MyCode = + type A() = + member this.Prop with get(a:string) = "" +module MyExtension = + type MyCode.A with + member this.Prop with get(a:int) = "" + +open MyCode +open MyExtension +let foo = A() +foo.Prop({caret}""" diff --git a/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.TypeProviders.fs b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.TypeProviders.fs new file mode 100644 index 00000000000..baa4303941a --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/ParameterInfo/ParameterInfoTests.TypeProviders.fs @@ -0,0 +1,154 @@ +module FSharp.Compiler.Service.Tests.ParameterInfoTypeProvidersTests + +open Xunit + +[] +let ``TypeProvider.StaticMethodWithOneParam`` () = + assertParameterInfoOverloads [["arg1"]] "let foo = N1.T1.M1({caret}" + +[] +let ``TypeProvider.StaticMethodWithMoreParam`` () = + assertParameterInfoOverloads [["arg1"; "arg2"]] "let foo = N1.T1.M2({caret}" + +[] +let ``TypeProvider.StaticMethodColonContent`` () = + assertFirstReturnTypeText ": int" "let foo = N1.T1.M2({caret}" + +[] +let ``TypeProvider.ConstructorWithNoParam`` () = + assertParameterInfoOverloadIndex 0 [] "let foo = new N1.T1({caret}" + +[] +let ``TypeProvider.ConstructorWithOneParam`` () = + assertParameterInfoOverloadIndex 1 ["arg1"] "let foo = new N1.T1({caret}" + +[] +let ``TypeProvider.ConstructorWithMoreParam`` () = + assertParameterInfoOverloadIndex 2 ["arg1"; "arg2"] "let foo = new N1.T1({caret}" + +[] +let ``TypeProvider.Type.WhenOpeningBracket`` () = + assertParameterInfoOverloads [["Param1"; "ParamIgnored"]] "type foo = N1.T<{caret}" + +[] +let ``TypeProvider.Type.AfterCloseBracket`` () = + assertNoParameterInfo "type foo = N1.T< \"Hello\", 2>{caret}" + +[] +let ``TypeProvider.Type.AfterDelimiter`` () = + assertParameterInfoContains ["Param1"; "ParamIgnored"] "type foo = N1.T<\"Hello\",{caret}" + +[] +let ``TypeProvider.Type.ParameterInfoLocation.WithNamespace`` () = + assertHasParameterInfo "type boo = N1.T<{caret}" + +[] +let ``TypeProvider.Type.ParameterInfoLocation.WithOutNamespace`` () = + assertHasParameterInfo "open N1 \ntype boo = T<{caret}" + +[] +let ``TypeProvider.Type.Negative.InString`` () = + assertNoParameterInfo "type boo = \"N1.T<{caret}\"" + +[] +let ``TypeProvider.Type.Negative.InComment`` () = + assertNoParameterInfo "// type boo = N1.T<{caret}" + +[] +let ``LocationOfParams.TypeProviders.Basic`` () = + assertHasParameterInfo """ + type U = N1.T< "fo{caret}o", 42 >""" + +[] +let ``LocationOfParams.TypeProviders.BasicNamed`` () = + assertHasParameterInfo """ + type U = N1.T< "fo{caret}o", ParamIgnored=42 >""" + +[] +let ``LocationOfParams.TypeProviders.Prefix0`` () = + assertHasParameterInfo """ + type U = N1.T< {caret} """ + +[] +let ``LocationOfParams.TypeProviders.Prefix1`` () = + assertHasParameterInfo """ + type U = N1.T< "fo{caret}o", 42 """ + +[] +let ``LocationOfParams.TypeProviders.Prefix1Named`` () = + assertHasParameterInfo """ + type U = N1.T< "fo{caret}o", ParamIgnored=42 """ + +[] +let ``LocationOfParams.TypeProviders.Prefix2`` () = + assertHasParameterInfo """ + type U = N1.T< "fo{caret}o", """ + +[] +let ``LocationOfParams.TypeProviders.Prefix2Named1`` () = + assertHasParameterInfo """ + type U = N1.T< "fo{caret}o", ParamIgnored= """ + +[] +let ``LocationOfParams.TypeProviders.Prefix2Named2`` () = + assertHasParameterInfo """ + type U = N1.T< "fo{caret}o", ParamIgnored """ + +[] +let ``LocationOfParams.TypeProviders.Negative1`` () = + assertNoParameterInfo """ + type D = System.Collections.Generic.Dictionary< in{caret}t, int >""" + +[] +let ``LocationOfParams.TypeProviders.Negative2`` () = + assertNoParameterInfo """ + type D = System.Collections.Generic.List< in{caret}t >""" + +[] +let ``LocationOfParams.TypeProviders.Negative3`` () = + assertNoParameterInfo """ + let i = 42 + let b = i< 4{caret}2""" + +[] +let ``LocationOfParams.TypeProviders.Negative4.Bug181000`` () = + assertNoParameterInfo """ + type U = N1.T< "foo", 42 >{caret} """ + +[] +let ``LocationOfParams.TypeProviders.BasicWithinExpr`` () = + assertNoParameterInfo """ + let f() = + let r = id( N1.T< "fo{caret}o", ParamIgnored=42 > ) + r """ + +[] +let ``LocationOfParams.TypeProviders.BasicWithinExpr.DoesNotInterfereWithOuterFunction`` () = + assertHasParameterInfo """ + let f() = + let r = id( N1.{caret}T< "foo", ParamIgnored=42 > ) + r """ + +[] +let ``LocationOfParams.TypeProviders.Bug199744.ExcessCommasShouldNotAssertAndShouldGiveInfo.Case1`` () = + assertHasParameterInfo """ + type U = N1.T< "fo{caret}o", 42, , >""" + +[] +let ``LocationOfParams.TypeProviders.Bug199744.ExcessCommasShouldNotAssertAndShouldGiveInfo.Case2`` () = + assertHasParameterInfo """ + type U = N1.T< "fo{caret}o", , >""" + +[] +let ``LocationOfParams.TypeProviders.Bug199744.ExcessCommasShouldNotAssertAndShouldGiveInfo.Case3`` () = + assertHasParameterInfo """ + type U = N1.T< ,{caret} >""" + +[] +let ``LocationOfParams.TypeProviders.StaticParametersAtConstructorCallSite`` () = + assertHasParameterInfo """ + let x = new N1.T< "fo{caret}o", 42 >()""" + +[] +let ``TypeProvider.FormatOfNamesOfSystemTypes`` () = + assertParameterInfoOverloads [["Param1: string"; "ParamIgnored: int"]] """type TTT = N1.T< "fo{caret}o", ParamIgnored=42 > """ diff --git a/tests/FSharp.Compiler.Service.Tests/QuickParseTests.fs b/tests/FSharp.Compiler.Service.Tests/QuickParseTests.fs index 6f4dad7a97d..845c08f109e 100644 --- a/tests/FSharp.Compiler.Service.Tests/QuickParseTests.fs +++ b/tests/FSharp.Compiler.Service.Tests/QuickParseTests.fs @@ -128,3 +128,128 @@ let ``GetPartialLongNameEx preserves plain long identifiers`` (lineStr: string, Assert.NotEmpty pln.QualifyingIdents Assert.Equal(lastQualifier, List.last pln.QualifyingIdents) Assert.Equal("", pln.PartialIdent) + +// QuickParse.GetCompleteIdentifierIsland tolerateJustAfter line index -> (identifier, endColumn, isQuoted) option. +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +let ``QuickParse GetCompleteIdentifierIsland`` + (tolerateJustAfter: bool) + (line: string) + (index: int) + (expectedIdent: string) + (expectedEndCol: int) + = + let actual = + match QuickParse.GetCompleteIdentifierIsland tolerateJustAfter line index with + | Some(ident, endCol, _) -> Some(ident, endCol) + | None -> None + + let expected = + if isNull expectedIdent then + None + else + Some(expectedIdent, expectedEndCol) + + Assert.Equal<(string * int) option>(expected, actual) + +[] +let ``QuickParse GetCompleteIdentifierIsland tolerates one char after a quoted identifier (legacy CheckIsland25, not enforced)`` + () + = + let actual = + match QuickParse.GetCompleteIdentifierIsland true "``Space Man``" 11 with + | Some(ident, endCol, _) -> Some(ident, endCol) + | None -> None + + Assert.Equal<(string * int) option>(Some("Man", 11), actual) + +// tuple (QualifyingIdents, PartialIdent, LastDotPos). Encoding for the [] primitives: +// quals: null -> [] (empty list); "" -> [""] (one empty qualifier); else ';'-split into a list. +// lastDot: -1 -> None; else Some lastDot. +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +[] +let ``QuickParse GetPartialLongNameEx`` + (line: string) + (quals: string) + (partialIdent: string) + (lastDot: int) + = + let actual = QuickParse.GetPartialLongNameEx(line, line.Length - 1) + + let expectedQuals = + if isNull quals then [] else quals.Split(';') |> List.ofArray + + let expectedLastDot = if lastDot < 0 then None else Some lastDot + let expected = (expectedQuals, partialIdent, expectedLastDot) + let actualTuple = (actual.QualifyingIdents, actual.PartialIdent, actual.LastDotPos) + Assert.Equal(expected, actualTuple) diff --git a/tests/FSharp.Compiler.Service.Tests/ScriptOptionsTests.fs b/tests/FSharp.Compiler.Service.Tests/ScriptOptionsTests.fs index fd6b868de08..c5c6ba78e9c 100644 --- a/tests/FSharp.Compiler.Service.Tests/ScriptOptionsTests.fs +++ b/tests/FSharp.Compiler.Service.Tests/ScriptOptionsTests.fs @@ -60,3 +60,53 @@ let pi = Math.PI let expectedReferenceText = match [| flag |] |> Array.tryFind(fun f -> f = "--targetprofile:mscorlib") with | Some _ -> "net45" | _ -> "netstandard2.0" let found = options.OtherOptions |> Array.exists (fun s -> s.Contains(expectedReferenceText) && s.Contains("FSharp.Data.dll")) Assert.True(found) + +/// `SourceFiles` is exactly the single script; the fsi default-reference injection for a missing `#load` +/// is a host-layout detail (not product behaviour) and is intentionally not asserted. +/// Desktop-only: it asserts .NET Framework GAC assemblies (`System.Runtime.Remoting`/`System.Transactions`) +/// resolve, which is not possible on a .NET-Core-only host. +#if !NETCOREAPP +[] +let ``Fsx.ScriptClosure.SurfaceOrderOfHashes`` () = + let scriptSource = + String.concat "\n" + [ "#r \"System.Runtime.Remoting\"" + "#r \"System.Transactions\"" + "#load \"Load1.fs\"" + "#load \"Load2.fsx\"" ] + let tempFile = Path.Combine(Path.GetTempPath(), getTemporaryFileName () + ".fsx") + let options, _errors = + checker.GetProjectOptionsFromScript(tempFile, SourceText.ofString scriptSource) + |> Async.RunImmediate + let containsPartial (needle: string) = options.OtherOptions |> Array.exists (fun o -> o.Contains needle) + Assert.True(containsPartial "--noframework", "OtherOptions should contain --noframework") + Assert.True(containsPartial "System.Runtime.Remoting.dll", "OtherOptions should resolve System.Runtime.Remoting.dll") + Assert.True(containsPartial "System.Transactions.dll", "OtherOptions should resolve System.Transactions.dll") + Assert.Equal(1, options.SourceFiles.Length) + Assert.Equal(tempFile, options.SourceFiles.[0]) +#endif + +/// A no-crash test: the invalid meta-command filenames must be processed WITHOUT crashing the script +/// options (a single source file, the `--noframework` closure flag) without throwing — the invalid +/// references surface as non-fatal resolution diagnostics, never an assert. +[] +let ``Fsx.InvalidMetaCommandFilenames`` () = + let scriptSource = + String.concat "\n" + [ "#r @\"\"" + "#load @\"\"" + "#I @\"\"" + "#r @\"*\"" + "#load @\"*\"" + "#I @\"*\"" + "#r @\"?\"" + "#load @\"?\"" + "#I @\"?\"" + "#r @\"C:\\path\\does\\not\\exist.dll\" " ] + let tempFile = Path.Combine(Path.GetTempPath(), getTemporaryFileName () + ".fsx") + let options, _errors = + checker.GetProjectOptionsFromScript(tempFile, SourceText.ofString scriptSource) + |> Async.RunImmediate + Assert.Equal(1, options.SourceFiles.Length) + Assert.Equal(tempFile, options.SourceFiles.[0]) + Assert.Contains("--noframework", options.OtherOptions) diff --git a/tests/FSharp.Compiler.Service.Tests/TokenizerTests.fs b/tests/FSharp.Compiler.Service.Tests/TokenizerTests.fs index 4c1cea62bf6..48dd529b2af 100644 --- a/tests/FSharp.Compiler.Service.Tests/TokenizerTests.fs +++ b/tests/FSharp.Compiler.Service.Tests/TokenizerTests.fs @@ -23,6 +23,17 @@ let tokenizeLines (lines:string[]) = let tokenizer = sourceTok.CreateLineTokenizer(line) yield n, parseLine(line, state, tokenizer) |> List.ofSeq ] +/// Scans every token of a (possibly multi-line) source using a single line tokenizer, +/// threading the lex state across embedded newlines (column index resets at each newline). +let scanTokens (defines: string list) (source: string) = + let sourceTok = FSharpSourceTokenizer(defines, Some "C:\\test.fsx", None, None) + let tokenizer = sourceTok.CreateLineTokenizer(source) + let rec loop (state: FSharpTokenizerLexState) acc = + match tokenizer.ScanToken(state) with + | Some tok, nstate -> loop nstate (tok :: acc) + | None, _ -> List.rev acc + loop FSharpTokenizerLexState.Initial [] + [] let ``Tokenizer test - simple let with string``() = let tokenizedLines = @@ -293,3 +304,163 @@ let ``Tokenizer test - optional parameters with question mark``() = printfn "actual = %A" actual printfn "expected = %A" expected actual |> Assert.shouldBeEqualWith expected (sprintf "actual and expected did not match,actual =\n%A\nexpected=\n%A\n" actual expected) + +[] +let ``Lexer.CommentsLexing.Bug1548``() = + let cm = FSharpTokenColorKind.Comment + let kw = FSharpTokenColorKind.Keyword + + // This specifies the source code to test and a collection of tokens that + // we want to find in the result (note: it doesn't have to contain every token, because + // behavior for some of them is undefined - e.g. "(* "\"*)" - what is token here? + let sources = + [ "// some comment", + [ ((0, 1), cm); ((2, 2), cm); ((3, 6), cm); ((7, 7), cm); ((8, 14), cm) ] + "// (* hello // 12345\nlet", + [ ((6, 10), cm); ((15, 19), cm); ((0, 2), kw) ] // checks 'hello', '12345' and keyword 'let' + "//- test", + [ ((0, 2), cm); ((4, 7), cm) ] // checks whether '//-' isn't treated as an operator + + // same thing for XML comments - these are treated in a different lexer branch + "/// some comment", + [ ((0, 2), cm); ((3, 3), cm); ((4, 7), cm); ((8, 8), cm); ((9, 15), cm) ] + "/// (* hello // 12345\nmember", + [ ((7, 11), cm); ((16, 20), cm); ((0, 5), kw) ] + "///- test", + [ ((0, 3), cm); ((5, 8), cm) ] + + // same thing for "////" - these are treated in a different lexer branch + "//// some comment", + [ ((0, 3), cm); ((4, 4), cm); ((5, 8), cm); ((9, 9), cm); ((10, 16), cm) ] + "//// (* hello // 12345\nlet", + [ ((8, 12), cm); ((17, 21), cm); ((0, 2), kw) ] + "////- test", + [ ((0, 4), cm); ((6, 9), cm) ] + + "(* test 123 (* 456 nested *) comments *)", + [ ((3, 6), cm); ((8, 10), cm); ((15, 17), cm); ((19, 24), cm); ((29, 36), cm) ] // checks 'test', '123', '456', 'nested', 'comments' + "(* \"with 123 \\\" *)\" string *)", + [ ((4, 7), cm); ((9, 11), cm); ((20, 25), cm) ] // checks 'with', '123', 'string' + "(* @\"with 123 \"\" *)\" string *)", + [ ((5, 8), cm); ((10, 12), cm); ((21, 26), cm) ] // checks 'with', '123', 'string' + ] + + for lineText, expected in sources do + // Lex the (possibly multi-line) source and add every lexed token's color to a dictionary + let lexed = System.Collections.Generic.Dictionary() + for tok in scanTokens [ "COMPILED"; "EDITING" ] lineText do + lexed[(tok.LeftColumn, tok.RightColumn)] <- tok.ColorClass + + // Verify that all tokens in the specified list occur in the lexed result with the right color + for pos, clr in expected do + let succ, v = lexed.TryGetValue(pos) + let found = [ for kvp in lexed -> kvp.Key, kvp.Value ] + Assert.True(succ, sprintf "Cannot find token %A at %A in %A\nFound: %A" clr pos lineText found) + Assert.True((clr = v), sprintf "Wrong color of token %A at %A in %A\nFound: %A" clr pos lineText found) + +[] +let ``TokenInfo.TriggerClasses``() = + let punct = FSharpTokenColorKind.Punctuation + let delim = FSharpTokenCharKind.Delimiter + + // Tokenize a minimal source, return the (ColorClass, CharClass, TriggerClass) of the first token + let triggerInfoOf (tokenName: string) (source: string) = + let toks = scanTokens [] source + match toks |> List.tryFind (fun t -> t.TokenName = tokenName) with + | Some t -> (t.ColorClass, t.CharClass, t.FSharpTokenTriggerClass) + | None -> + failwithf "Token %s was not produced by source %A. Tokens: %A" + tokenName source (toks |> List.map (fun t -> t.TokenName)) + + // important - tokens with specific trigger classes used to drive IntelliSense + triggerInfoOf "DOT" "a.b" + |> Assert.shouldBe (punct, delim, FSharpTokenTriggerClass.MemberSelect) // member select for dot completions + triggerInfoOf "LPAREN" "f(x,y)" + |> Assert.shouldBe (punct, delim, FSharpTokenTriggerClass.ParamStart ||| FSharpTokenTriggerClass.MatchBraces) // for parameter info + triggerInfoOf "COMMA" "f(x,y)" + |> Assert.shouldBe (punct, delim, FSharpTokenTriggerClass.ParamNext) + triggerInfoOf "RPAREN" "f(x,y)" + |> Assert.shouldBe (punct, delim, FSharpTokenTriggerClass.ParamEnd ||| FSharpTokenTriggerClass.MatchBraces) + + // matching - other cases where we expect MatchBraces + let matchBracesInfo = (punct, delim, FSharpTokenTriggerClass.MatchBraces) + triggerInfoOf "LQUOTE" "<@ 1 @>" |> Assert.shouldBe matchBracesInfo + triggerInfoOf "LBRACK" "[ 1 ]" |> Assert.shouldBe matchBracesInfo + triggerInfoOf "LBRACE" "{ x = 1 }" |> Assert.shouldBe matchBracesInfo + triggerInfoOf "LBRACK_BAR" "[| 1 |]" |> Assert.shouldBe matchBracesInfo + triggerInfoOf "RQUOTE" "<@ 1 @>" |> Assert.shouldBe matchBracesInfo + triggerInfoOf "RBRACK" "[ 1 ]" |> Assert.shouldBe matchBracesInfo + triggerInfoOf "RBRACE" "{ x = 1 }" |> Assert.shouldBe matchBracesInfo + triggerInfoOf "BAR_RBRACK" "[| 1 |]" |> Assert.shouldBe matchBracesInfo + +// Each case has exactly one brace pair: left brace at the start marker, right brace at the end marker. +[] +let ``MatchingBraces.VerifyMatches``() = + let lines = + [ "" + " let x = (1, 2)//1" + " let y = ( 3 + 1 ) * 2" + " let z =" + " async {" + " return 10" + " }" + " let lst = " + " [// list_start" + " 1;2;3" + " ]//list_end" + " let arr = " + " [|" + " 1" + " 2" + " |]" + " let quote = <@(* S0 *) 1 @>(* E0 *)" + " let quoteWithNestedList = <@(* S1 *) ['x';'y';'z'](* E_L*) @>(* E1 *)" + " [< System.Serializable() >]" + " type T = class end" + " " ] + let source = String.concat "\n" lines + let linesArr = List.toArray lines + let braces = matchBraces ("MatchingBracesVerifyMatches", source) + + // Locate the START of the marker substring (0-based row/col). + let findMarker (marker: string) = + let mutable found = None + let mutable i = 0 + while found.IsNone && i < linesArr.Length do + let idx = linesArr[i].IndexOf(marker, System.StringComparison.Ordinal) + if idx >= 0 then found <- Some(i, idx) + i <- i + 1 + match found with + | Some p -> p + | None -> failwithf "Marker %A not found in source" marker + + let checkBraces startMarker endMarker (expectedSpanLen: int) = + let (startRow, startCol) = findMarker startMarker + let (endRow, endCol) = findMarker endMarker + + // exactly one matching pair has its left brace at the start marker (FCS line is 1-based) + let matching = + braces |> Array.filter (fun (l, _) -> l.StartLine = startRow + 1 && l.StartColumn = startCol) + Assert.Equal(1, matching.Length) + + let (lbrace, rbrace) = matching[0] + // left brace span: single line, starts at the start marker, expectedSpanLen columns wide + Assert.Equal(lbrace.StartLine, lbrace.EndLine) + Assert.Equal(startRow + 1, lbrace.StartLine) + Assert.Equal(startCol, lbrace.StartColumn) + Assert.Equal(startCol + expectedSpanLen, lbrace.EndColumn) + // right brace span: single line, starts at the end marker, expectedSpanLen columns wide + Assert.Equal(rbrace.StartLine, rbrace.EndLine) + Assert.Equal(endRow + 1, rbrace.StartLine) + Assert.Equal(endCol, rbrace.StartColumn) + Assert.Equal(endCol + expectedSpanLen, rbrace.EndColumn) + + checkBraces "(1" ")//1" 1 + checkBraces "( " ") *" 1 + checkBraces "{" "}" 1 + checkBraces "[// list_start" "]//list_end" 1 + checkBraces "[|" "|]" 2 + checkBraces "<@(* S0 *)" "@>(* E0 *)" 2 + checkBraces "<@(* S1 *)" "@>(* E1 *)" 2 + checkBraces "['x'" "](* E_L*)" 1 + checkBraces "[<" ">]" 2 diff --git a/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.ActivePatterns.fs b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.ActivePatterns.fs new file mode 100644 index 00000000000..96fc44ab2a5 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.ActivePatterns.fs @@ -0,0 +1,64 @@ +module FSharp.Compiler.Service.Tests.TooltipActivePatternsTests + +open Xunit + +let private lazyActivePatternSource = + """let (|Lazy|) x = x + match 0 with | Lazy y -> ()""" + +[] +let ``ActivePatterns.Declaration`` () = + assertTooltipContains "int -> Choice" (markAtEndOfMarker "let ( |One|Two| ) x = One(x+1)" "ne|Tw") + +[] +let ``ActivePatterns.Result`` () = + assertTooltipContains "active pattern result One: int -> Choice" (markAtEndOfMarker "let ( |One|Two| ) x = One(x+1)" "= On") + +[] +let ``ActivePatterns.Value`` () = + let source = + """let ( |One|Two| ) x = One(x+1) + let patval = (|One|Two|) // use""" + + assertTooltipContains "int -> Choice" (markAtEndOfMarker source "= (|On") + +[] +let ``Regression.ActivePatterns.Bug4100a`` () = + assertTooltipDoesNotContain "'?" (markAtEndOfMarker lazyActivePatternSource "with | Laz") + assertTooltipContains "Lazy" (markAtEndOfMarker lazyActivePatternSource "with | Laz") + +[] +let ``Regression.ActivePatterns.Bug4100b`` () = + let source = + """let Some (a:int) = a +match None with +| Some _ -> () +| _ -> () + +let (|NSome|) (a:int) = a +let NSome (a:int) = a.ToString() +match 0 with +| NSome _ -> ()""" + + assertTooltipDoesNotContain "int -> int" (markAtEndOfMarker source "| Som") + assertTooltipContains "Option.Some" (markAtEndOfMarker source "| Som") + assertTooltipDoesNotContain "int -> string" (markAtEndOfMarker source "| NSom") + assertTooltipContains "active recognizer NSome" (markAtEndOfMarker source "| NSom") + +[] +let ``Regression.ActivePatterns.Bug4103`` () = + let marked = markAtEndOfMarker lazyActivePatternSource "(|Laz" + assertTooltipDoesNotContain "Control.Lazy" marked + assertTooltipContains "|Lazy|" marked + +[] +let ``Regression.MemberDefinition.DocComments.Bug5856_5`` () = + assertCompletionItemTooltipContainsInOrder + "Pattern" + [ "active recognizer Pattern: int"; "Pattern comment" ] + """module Module = + /// Pattern comment + let (|Pattern|) = 0 + +let x() = + Module.{caret}""" diff --git a/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Attributes.fs b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Attributes.fs new file mode 100644 index 00000000000..bc8ff79b950 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Attributes.fs @@ -0,0 +1,74 @@ +module FSharp.Compiler.Service.Tests.TooltipAttributesTests + +open System +open Xunit + +[] +let ``EnsureNoAssertFromBadParserRangeOnAttribute`` () = + let source = + """ + [] + Types foo = int""" + + Checker.getTooltip (markAtEndOfMarker source "ype") |> ignore + +[] +[] a:")>] +[] a:")>] +let ``ParamsArrayArgument`` (marker: string) (expected: string) = + let source = + """ + type A() = + static member Foo([] a : int[]) = () + let r = A.Foo(42)""" + + assertTooltipContains expected (markAtEndOfMarker source marker) + +[] +let ``IdentifiersInAttributes`` () = + let source = + String.concat + "\n" + [ "[<(*test13*)System.CLSCompliant(true)>]" + "let test13 = 1" + "open System" + "[<(*test14*)CLSCompliant(true)>]" + "let test14 = 1" ] + + walk source "[<(*test13*)" "System" "namespace System" + walk source "[<(*test13*)System." "CLSCompliant" "CLSCompliantAttribute" + walk source "[<(*test14*)" "CLSCompliant" "CLSCompliantAttribute" + +[] +let ``Regression.FieldRepeatedInToolTip.Bug3818`` () = + let source = + """ + [] + type A() = + do ()""" + + assertIdentifierInTooltipExactlyOnce "Inherited" (markAtEndOfMarker source "Inherite") + +[] +let ``Automation.OverRiddenMembers`` () = + let source = + """namespace QuickinfoGeneric + + module FSharpOwnCode = + [] + type TextOutputSink() = + abstract WriteChar : char -> unit + abstract WriteString : string -> unit + default x.WriteString(s) = s |> String.iter x.WriteChar + + type ByteOutputSink() = + inherit TextOutputSink() + default sink.WriteChar(c) = System.Console.Write(c) + override sink.WriteString(s) = System.Console.Write(s) + + let sink = new ByteOutputSink() + sink.WriteChar(*Marker11*)('c') + sink.WriteString(*Marker12*)("Hello World!")""" + + assertTooltipContainsInFsFile "override ByteOutputSink.WriteChar: c: char -> unit" (markAtStartOfMarker source "(*Marker11*)") + assertTooltipContainsInFsFile "override ByteOutputSink.WriteString: s: string -> unit" (markAtStartOfMarker source "(*Marker12*)") diff --git a/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Classes.fs b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Classes.fs new file mode 100644 index 00000000000..5cbb2c5bd3f --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Classes.fs @@ -0,0 +1,234 @@ +module FSharp.Compiler.Service.Tests.TooltipClassesTests + +open System +open System.IO +open Xunit +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open FSharp.Compiler.IO +open FSharp.Compiler.Symbols +open FSharp.Compiler.Tokenization +open TestFramework + +let private assertCrossFileTooltipContains + (expected: string) + (file1Name: string) + (file1Source: string) + (file2RelativePath: string) + (markedFile2: string) + = + let context = Checker.getResolveContext markedFile2 + let root = createTemporaryDirectory () + let projDir = Path.Combine(root.FullName, "proj") + Directory.CreateDirectory(projDir) |> ignore + let file1Path = Path.Combine(projDir, file1Name) + let file2LogicalPath = Path.Combine(projDir, file2RelativePath) + let file2PhysicalPath = Path.GetFullPath file2LogicalPath + Directory.CreateDirectory(Path.GetDirectoryName file2PhysicalPath) |> ignore + FileSystem.OpenFileForWriteShim(file1Path).Write(file1Source) + FileSystem.OpenFileForWriteShim(file2PhysicalPath).Write(context.Source) + + let dllName = Path.Combine(projDir, "CrossFile.dll") + let projName = Path.Combine(projDir, "CrossFile.fsproj") + let args = mkProjectCommandLineArgs(dllName, []) + + let options = + { checker.GetProjectOptionsFromCommandLineArgs(projName, args) with + SourceFiles = [| file1Path; file2LogicalPath |] } + + let _, checkResults = parseAndCheckFile file2LogicalPath context.Source options + + checkResults.GetTooltip(context) + |> foldToolTip + |> assertFoldedTooltipContains true "cross-file tooltip" expected + +let private assertProjectTooltipContains (projectName: string) (expected: string) (markedSource: string) = + foldedProjectTooltip [] [] markedSource + |> assertFoldedTooltipContains true (sprintf "tooltip in project %A" projectName) expected + +[] +let ``QuickInfo.LetBindingsInTypes`` () = + assertTooltipContains + "val fff: n: int -> int" + """type A() = + let ff{caret}f n = n + 1""" + +[] +let ``Basic`` () = + assertTooltipContains + "Bob =" + """type (*bob*)Bob{caret}() = + let x = 1""" + +[] +let ``TauStarter`` () = + assertTooltipContains + "Bob =" + """type (*Scenario01*)Bob() = + let x = 1 +type (*Scenario021*)Bob{caret} = + class + public new() = { } +end +type (*Scenario022*)Alice = + class + public new() = { } +end""" + + assertTooltipContains + "Alice =" + """type (*Scenario01*)Bob() = + let x = 1 +type (*Scenario021*)Bob = + class + public new() = { } +end +type (*Scenario022*)Alice{caret} = + class + public new() = { } +end""" + +[] +let ``MemberIdentifiers`` () = + let source = + String.concat + "\n" + [ "type TestType() =" + " member (*test6*) xx.PPPP = 1" + " member (*test7*) xx.QQQQ(x) = 3.0" + "let test8 = (TestType()).PPPP" ] + + let walk = EditorServiceAsserts.walk source + walk "member (*test6*) " "xx" "TestType" + walk "member (*test6*) xx." "PPPP" "PPPP" + walk "member (*test7*) " "xx" "TestType" + walk "member (*test7*) xx." "QQQQ" "float" + walk "let test8 = (TestType())." "PPPP" "PPPP" + +[] +let ``Regression.StaticVsInstance.Bug3626`` () = + let staticCall = + """type Foo() = + member this.Bar () = "hllo" + static member Bar() = 13 +let z = (*int*) Foo.Ba{caret}r() +let Hoo = new Foo() +let y = (*string*) Hoo.Bar()""" + + assertTooltipContains "Foo.Bar" staticCall + assertTooltipContains "-> int" staticCall + + let instanceCall = + """type Foo() = + member this.Bar () = "hllo" + static member Bar() = 13 +let z = (*int*) Foo.Bar() +let Hoo = new Foo() +let y = (*string*) Hoo.Ba{caret}r()""" + + assertTooltipContains "Foo.Bar" instanceCall + assertTooltipContains "-> string" instanceCall + +[] +let ``Regression.Classes.Bug4066`` () = + let source = "type Foo() as this =\n do this |> ignore\n member this.Bar() = this" + + for marker in [ "as thi"; "do thi"; "member thi"; "Bar() = thi" ] do + let marked = markAtEndOfMarker source marker + assertTooltipContains "val this: Foo" marked + assertTooltipDoesNotContain "ref" marked + +[] +let ``AcrossTwoProjects`` () = + assertProjectTooltipContains + "testproject1" + "Bob1 =" + """type (*bob*)Bob{caret}1() = + let x = 1""" + + assertProjectTooltipContains + "testproject2" + "Bob2 =" + """type (*bob*)Bob{caret}2() = + let x = 1""" + +[] +[] +[] +let ``AcrossMultipleFiles`` (file2RelativePath: string) = + assertCrossFileTooltipContains + "File1.Bob" + "File1.fs" + "type Bob() =\n let x = 1\n" + file2RelativePath + "let bo{caret}b = new File1.Bob()" + +[] +let ``AcrossLinkedFiles`` () = + assertCrossFileTooltipContains + "Link.Bob" + "link.fs" + "type Bob() =\n let x = 1\n" + "File2.fs" + "let bo{caret}b = new Link.Bob()" + +[] +let ``Regression.MemberDefinition.DocComments.Bug5856_9`` () = + assertTooltipContainsInOrder + [ "type Class"; "A comment" ] + """module Module = + /// A comment + type Class = class end +let _ = typeof""" + +[] +let ``Regression.Class.Printing.CSharp.Classes.Only.Bug4592`` () = + assertTooltipContainsInOrder + [ "type Random =" + " new: unit -> unit + 1 overload" + " member Next: unit -> int + 2 overloads" + " member NextBytes: buffer: byte array -> unit" + " member NextDouble: unit -> float" ] + "let _ = typeof" + +#if !NETCOREAPP +let private getWinFormsTooltip (markedSource: string) = + getTooltipWithReferences + "WinFormsTooltip" + [ fsCoreDefaultReference () + sysLib "mscorlib" + sysLib "System" + sysLib "System.Core" + sysLib "System.Drawing" + sysLib "System.Windows.Forms" ] + markedSource + +[] +let ``Regression.CompListItemInfo.Bug5694`` () = + let actual = + getWinFormsTooltip + """type Form2() as self = + inherit System.Windows.Forms.Form() + member _.M() = self.AcceptB{caret}utton""" + |> foldToolTip + + let expected = + "Gets or sets the button on the form that is clicked when the user presses the ENTER key." + + if not (actual.Contains expected) then + failwithf "Expected tooltip to contain %A, but the actual tooltip was:\n%s" expected actual + +[] +let ``Regression.Class.Printing.CSharp.Classes.Bug4624`` () = + assertTooltipContainsInOrder + [ "type CodeConnectAccess =" + " new: allowScheme: string * allowPort: int -> unit" + " member Equals: o: obj -> bool" + " member GetHashCode: unit -> int" + " static member CreateAnySchemeAccess: allowPort: int -> CodeConnectAccess" + " static member CreateOriginSchemeAccess: allowPort: int -> CodeConnectAccess" + " static val AnyScheme: string" + " static val DefaultPort: int" + " ..." ] + "let _ = typeof" +#endif diff --git a/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.ComputationExpressions.fs b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.ComputationExpressions.fs new file mode 100644 index 00000000000..e0a79700f46 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.ComputationExpressions.fs @@ -0,0 +1,228 @@ +module FSharp.Compiler.Service.Tests.TooltipComputationExpressionsTests + +open Xunit + +let private identifierHaveDiffMeaningsSource = """namespace NS + module float(*Marker1_1*) = + + let GenerateTuple = fun x -> let tuple = (x,x.ToString(),(float(*Marker1_2*))x, ( fun y -> (y.ToString(),y+1)) ) + tuple + + let MySeq : seq(*Marker2_1*) = + seq(*Marker2_2*) { + + for i in 1..9 do + + let myTuple = GenerateTuple i + let fieldInt,fieldString,fieldFloat,_ = myTuple + yield fieldFloat + } + + let MySet : Set(*Marker3_1*) = + MySeq + |> Array.ofSeq + |> List.ofArray + |> Set(*Marker3_2*).ofList + + let int(*Marker4_1*) : int(*Marker4_2*) = 1 + + type int(*Marker4_3*)() = + member this.M = 1 + + type T(*Marker5_1*)() = + [] + val mutable T : T + + let T = new T() + let t = T.T.T.T(*Marker5_2*); + + type ValType() = + member this.Value with get(*Marker6_1*) () = 10 + and set(*Marker6_2*) x = x + 1 |> ignore""" + +let private typeAbbreviationsSource = """namespace NS + module TypeAbbreviation = + + type MyInt(*Marker1_1*) = int + + type PairOfFloat(*Marker2_1*) = float * float + + + type AbAttrName(*Marker5_1*) = AbstractClassAttribute + + + type IA(*Marker3_1*) = + abstract AbstractMember : int -> int + + [] + type ClassIA(*Marker3_2*)() = + interface IA with + member this.AbstractMember x = x + 1 + + type GenericClass(*Marker4_1*)<'a when 'a :> IA>() = + static member StaticMember(x:'a) = x.AbstractMember(1) + + + let GenerateTuple = fun ( x : MyInt) -> + let myInt(*Marker1_2*),float1,float2,function1 = (x,(float)x,(float)x, ( fun y -> (y.ToString(),y+1)) ) + myInt,((float1,float2):PairOfFloat),function1 + + let MySeq(*Marker2_2*) = + seq { + + for i in 1..9 do + let myInt,pairofFloat,function1 = GenerateTuple i + + yield pairofFloat + } + + let genericClass(*Marker4_2*) = new GenericClass()""" + +let private whereQuickInfoShouldNotShowUpSource = """namespace Test + + module Helper = + /// Tests if passed System.Numerics.BigInteger(*Marker1*) argument is prime + let IsPrime x = + let mutable i = 2I + let mutable foundFactor = false + while not foundFactor && i < x do + (* + the most naive way to test for number being prime + Works great for small int(*Marker2*) + *) + if x % i = 0I then + foundFactor <- true + i <- i + 1I + not foundFactor + + module App = + open Helper + + let sumOfAllPrimesUnder1Mi = + #if TEST_TWO_MI + seq(*Marker4*) { 1I .. 2000000I } + #else + seq { 1I .. 1000000I(*Marker7*) } + #endif + |> Seq.filter(IsPrime) + // find result after filtering seq(*Marker3*) + |> Seq.sum + + let myString hello = "hello"(*Marker5*) + + myString "myString"(*Marker8*) + |> Seq.filter (fun c -> int c > 75) + |> Seq.item 0 + |> (=) 'e'(*Marker6*) + |> ignore""" + +let private xDelegateSource = """module Test + + open FSTestLib + + open System.Runtime.InteropServices + let ctrlSignal = ref false + [] + extern void SetConsoleCtrlHandler(ControlEventHandler callback,bool add) + let ctrlEventHandlerStatic = new ControlEventHandler(MyCar.Run) + let ctrlEventHandlerInstance = new ControlEventHandler( (new MyCar(10, MyColors.Blue)).Repair ) + + let IsInstanceMethod (controlEventHandler:ControlEventHandler) = + // TC 32 Identifier Delegate Own Code Pattern Match + match controlEventHandler(*Marker1*).Method.IsStatic with + | true -> printf "It's not a instance method. " + | false -> printf " It's a instance method. " + + // TC 33 Event DiscUnion Own Code Quotation + let a = <@ MyDistance.Event(*Marker2*) @> + + let DelegateSeq = + seq { for i in 1..10 do + let newDelegate = new ControlEventHandler(MyCar.Run) + // TC 35 Identifier Delegate Own Code Comp Expression + yield newDelegate(*Marker3*) } + + let StructFieldSeq = + seq { for i in 1..10 do + let a = MyPoint((float)i,2.0) + // TC 36 Field Struct Own Code Comp Expression + yield a.X(*Marker4*) }""" + +let private asyncToolTipsSource = """let a = + async { + let ms = new System.IO.MemoryStream(Array.create 1000 1uy) + let toFill = Array.create 2000 0uy + let! x = ms.AsyncRead(2000) + return x + }""" + +[] +let ``Automation.IdentifierHaveDiffMeanings`` () = + let source = identifierHaveDiffMeaningsSource + assertTooltipContainsInFsFile "module float" (markAtStartOfMarker source "(*Marker1_1*)") + assertTooltipContainsInFsFile "val float: 'T -> float (requires member op_Explicit)" (markAtStartOfMarker source "(*Marker1_2*)") + assertTooltipContainsInFsFile "Full name: Microsoft.FSharp.Core.Operators.float" (markAtStartOfMarker source "(*Marker1_2*)") + assertTooltipContainsInFsFile "type float = System.Double" (markAtStartOfMarker source "(*Marker1_3*)") + assertTooltipContainsInFsFile "Full name: Microsoft.FSharp.Core.float" (markAtStartOfMarker source "(*Marker1_3*)") + assertTooltipContainsInFsFile "type seq<'T> = System.Collections.Generic.IEnumerable<'T>" (markAtStartOfMarker source "(*Marker2_1*)") + assertTooltipContainsInFsFile "Full name: Microsoft.FSharp.Collections.seq<_>" (markAtStartOfMarker source "(*Marker2_1*)") + assertTooltipContainsInFsFile "val seq: 'T seq -> 'T seq" (markAtStartOfMarker source "(*Marker2_2*)") + assertTooltipContainsInFsFile "Full name: Microsoft.FSharp.Core.Operators.seq" (markAtStartOfMarker source "(*Marker2_2*)") + assertTooltipContainsInFsFile "type Set<'T (requires comparison)> =" (markAtStartOfMarker source "(*Marker3_1*)") + assertTooltipContainsInFsFile "Full name: Microsoft.FSharp.Collections.Set" (markAtStartOfMarker source "(*Marker3_1*)") + assertTooltipContainsInFsFile "module Set" (markAtStartOfMarker source "(*Marker3_2*)") + assertTooltipContainsInFsFile "Functional programming operators related to the Set<_> type" (markAtStartOfMarker source "(*Marker3_2*)") + assertTooltipContainsInFsFile "val int: int" (markAtStartOfMarker source "(*Marker4_1*)") + assertTooltipContainsInFsFile "Full name: NS.float.int" (markAtStartOfMarker source "(*Marker4_1*)") + assertTooltipContainsInFsFile "type int = int32" (markAtStartOfMarker source "(*Marker4_2*)") + assertTooltipContainsInFsFile "Full name: Microsoft.FSharp.Core.int" (markAtStartOfMarker source "(*Marker4_2*)") + assertTooltipContainsInFsFile "type int =" (markAtStartOfMarker source "(*Marker4_3*)") + assertTooltipContainsInFsFile "member M: int" (markAtStartOfMarker source "(*Marker4_3*)") + assertTooltipContainsInFsFile "type T =" (markAtStartOfMarker source "(*Marker5_1*)") + assertTooltipContainsInFsFile "new : unit -> T" (markAtStartOfMarker source "(*Marker5_1*)") + assertTooltipContainsInFsFile "val mutable T: T" (markAtStartOfMarker source "(*Marker5_1*)") + assertTooltipContainsInFsFile "T.T: T" (markAtStartOfMarker source "(*Marker5_2*)") + assertTooltipContainsInFsFile "member ValType.Value : int" (markAtStartOfMarker source "(*Marker6_1*)") + assertTooltipContainsInFsFile "member ValType.Value : int with set" (markAtStartOfMarker source "(*Marker6_2*)") + assertTooltipDoesNotContainInFsFile "Microsoft.FSharp.Core.ExtraTopLevelOperators.set" (markAtStartOfMarker source "(*Marker6_2*)") + +[] +let ``Automation.TypeAbbreviations`` () = + let source = typeAbbreviationsSource + assertTooltipContainsInFsFile "type MyInt = int" (markAtStartOfMarker source "(*Marker1_1*)") + assertTooltipContainsInFsFile "val myInt: MyInt" (markAtStartOfMarker source "(*Marker1_2*)") + assertTooltipContainsInFsFile "type PairOfFloat = float * float" (markAtStartOfMarker source "(*Marker2_1*)") + assertTooltipContainsInFsFile "val MySeq: PairOfFloat seq" (markAtStartOfMarker source "(*Marker2_2*)") + assertTooltipContainsInFsFile "type IA =" (markAtStartOfMarker source "(*Marker3_1*)") + assertTooltipContainsInFsFile "type ClassIA =" (markAtStartOfMarker source "(*Marker3_2*)") + assertTooltipContainsInFsFile "type GenericClass<'a (requires 'a :> IA)> =" (markAtStartOfMarker source "(*Marker4_1*)") + assertTooltipContainsInFsFile "val genericClass: GenericClass" (markAtStartOfMarker source "(*Marker4_2*)") + assertTooltipContainsInFsFile "type AbAttrName = AbstractClassAttribute" (markAtStartOfMarker source "(*Marker5_1*)") + assertTooltipContainsInFsFile "type AbAttrName = AbstractClassAttribute" (markAtStartOfMarker source "(*Marker5_2*)") + +[] +let ``Automation.WhereQuickInfoShouldNotShowUp`` () = + let source = whereQuickInfoShouldNotShowUpSource + assertTooltipDoesNotContainInFsFile "BigInteger" (markAtStartOfMarker source "(*Marker1*)") + assertTooltipDoesNotContainInFsFile "int" (markAtStartOfMarker source "(*Marker2*)") + assertTooltipDoesNotContainInFsFile "seq" (markAtStartOfMarker source "(*Marker3*)") + assertTooltipDoesNotContainInFsFile "seq" (markAtStartOfMarker source "(*Marker4*)") + assertTooltipDoesNotContainInFsFile "hello" (markAtStartOfMarker source "(*Marker5*)") + assertTooltipDoesNotContainInFsFile "char" (markAtStartOfMarker source "(*Marker6*)") + assertTooltipDoesNotContainInFsFile "bigint" (markAtStartOfMarker source "(*Marker7*)") + assertTooltipDoesNotContainInFsFile "myString" (markAtStartOfMarker source "(*Marker8*)") + +[] +let ``Automation.XDelegateDUStructfromOwnCode`` () = + let source = xDelegateSource + assertTooltipContainsWithFsTestLib "val controlEventHandler: ControlEventHandler" (markAtStartOfMarker source "(*Marker1*)") + assertTooltipContainsWithFsTestLib "property MyDistance.Event: Event" (markAtStartOfMarker source "(*Marker2*)") + assertTooltipContainsWithFsTestLib "val newDelegate: ControlEventHandler" (markAtStartOfMarker source "(*Marker3*)") + assertTooltipContainsWithFsTestLib "property MyPoint.X: float" (markAtStartOfMarker source "(*Marker4*)") + assertTooltipContainsWithFsTestLib "Gets and sets X" (markAtStartOfMarker source "(*Marker4*)") + +[] +let ``Async.AsyncToolTips`` () = + let source = asyncToolTipsSource + assertTooltipContains "AsyncBuilder" (markAtEndOfMarker source "asy") + assertTooltipDoesNotContain "---" (markAtEndOfMarker source "asy") diff --git a/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Declarations.fs b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Declarations.fs new file mode 100644 index 00000000000..0f49ba8ead2 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Declarations.fs @@ -0,0 +1,166 @@ +module FSharp.Compiler.Service.Tests.TooltipDeclarationsTests + +open System +open Xunit +open FSharp.Test +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open FSharp.Compiler.Symbols +open FSharp.Compiler.Tokenization + +[] +let ``Regression.ImportedEvent.138110`` () = + let source = + """ +open Microsoft.FSharp.Core.CompilerServices +let f (tp:ITypeProvider(*$$$*)) = tp.Invalidate +""" + + assertTooltipContains "Invalidate" (markAtStartOfMarker source "Provider(*$$$*)") + +[] +let ``OrphanFs.BaselineIntellisenseStillWorks`` () = + assertTooltipContains "val astring: string" (markAtEndOfMarker """let astring = "Hello" """ "let astr") + +[] +let ``Global.LongPaths`` () = + let source = + String.concat + "\n" + [ "let test0 = global.System.Console.In" + "let test0b = global.System.Collections.Generic.List()" + "let test0c = global.System.Collections.Generic.KeyNotFoundException()" + "type Test0d = global.System.Collections.Generic.List" + "type Test0e = global.System.Collections.Generic.KeyNotFoundException" ] + + walk source "let test0 = global.System." "Console" "Console =" + walk source "let test0 = global.System.Console." "In" "System.Console.In" + walk source "let test0 = global.System.Console." "In" "TextReader" + walk source "let test0b = global.System." "Collections" "namespace System.Collections" + walk source "let test0b = global.System.Collections." "Generic" "namespace System.Collections.Generic" + walk source "let test0b = global.System.Collections.Generic." "List" "List()" + walk source "let test0c = global.System." "Collections" "namespace System.Collections" + walk source "let test0c = global.System.Collections." "Generic" "namespace System.Collections.Generic" + walk source "let test0c = global.System.Collections.Generic." "KeyNotFoundException" "KeyNotFoundException()" + walk source "type Test0d = global.System." "Collections" "namespace System.Collections" + walk source "type Test0d = global.System.Collections." "Generic" "namespace System.Collections.Generic" + walk source "type Test0d = global.System.Collections.Generic." "List" "Generic.List" + walk source "type Test0e = global.System." "Collections" "namespace System.Collections" + walk source "type Test0e = global.System.Collections." "Generic" "namespace System.Collections.Generic" + walk source "type Test0e = global.System.Collections.Generic." "KeyNotFoundException" "Generic.KeyNotFoundException" + +[] +let ``MethodAndPropTooltip`` () = + let source = + """ +open System +do + Console.Clear() + Console.BackgroundColor |> ignore""" + + assertIdentifierInTooltipExactlyOnce "Clear" (markAtEndOfMarker source "Console.Cle") + assertIdentifierInTooltipExactlyOnce "BackgroundColor" (markAtEndOfMarker source "Console.Back") + +[] +let ``Automation.Regression.AccessibilityOnTypeMembers.Bug4168`` () = + let source = + """module Test +type internal Foo2(*Marker*) () = + member public this.Prop1 = 12 + member internal this.Prop2 = 12 + member private this.Prop3 = 12 + public new(x: int) = new Foo2() + internal new(x: int, y: int) = new Foo2() + private new(x: int, y: int, z: int) = new Foo2()""" + + assertTooltipContains "type internal Foo2" (markAtStartOfMarker source "(*Marker*)") + +[] +let ``Automation.AutoOpenMyNamespace`` () = + let source = + """namespace System.Numerics +type t = BigInteger(*Marker1*)""" + + assertTooltipContainsInFsFile "type BigInteger" (markAtStartOfMarker source "r(*Marker1*)") + +[] +let ``Automation.Regression.TupleException.Bug3723`` () = + let source = + """namespace TestQuickinfo +exception E3(*Marker1*) of int * int +exception E4(*Marker2*) of (int * int) +exception E5(*Marker3*) = E4""" + + assertTooltipContainsInFsFile "exception E3 of int * int" (markAtStartOfMarker source "(*Marker1*)") + assertTooltipContainsInFsFile "Full name: TestQuickinfo.E3" (markAtStartOfMarker source "(*Marker1*)") + assertTooltipContainsInFsFile "exception E4 of (int * int)" (markAtStartOfMarker source "(*Marker2*)") + assertTooltipContainsInFsFile "Full name: TestQuickinfo.E4" (markAtStartOfMarker source "(*Marker2*)") + assertTooltipContainsInFsFile "exception E5 = E4" (markAtStartOfMarker source "(*Marker3*)") + +[] +let ``Automation.Regression.XmlDocComments.Bug3157`` () = + let source = + """namespace TestQuickinfo +module XmlComment = + /// XmlComment J + let func(*Marker*) x = + /// XmlComment K + let rec g x = 1 + g x""" + + let marked = markAtStartOfMarker source "(*Marker*)" + assertTooltipContainsInFsFile "val func: x: 'a -> int" marked + assertTooltipContainsInFsFile "XmlComment J" marked + assertTooltipContainsInFsFile "Full name: TestQuickinfo.XmlComment.func" marked + assertTooltipDoesNotContainInFsFile "XmlComment K" marked + +let private referenceTooltipAtCaret (markedSource: string) = + let context = SourceContext.fromMarkedSource markedSource + let _, checkResults = getParseAndCheckResultsUniqueName context.Source + checkResults.GetToolTip(context.CaretPos.Line, context.CaretPos.Column, context.LineText, ([]: string list), FSharpTokenTag.String) + |> foldToolTip + +let private assertReferenceTooltipContains (expected: string) (markedSource: string) = + referenceTooltipAtCaret markedSource + |> assertFoldedTooltipContains true "#r reference tooltip" expected + +let private assertReferenceTooltipDoesNotContain (notExpected: string) (markedSource: string) = + referenceTooltipAtCaret markedSource + |> assertFoldedTooltipContains false "#r reference tooltip" notExpected + +[] +let ``Fsx.Bug4311HoverOverReferenceInFirstLine`` () = + let source = "#r \"PresentationFramework.dll\"\n\n#r \"PresentationCore.dll\" " + assertReferenceTooltipContains "PresentationFramework.dll" (markAtEndOfMarker source "#r \"PresentationFrame") + assertReferenceTooltipDoesNotContain "multiple results" (markAtEndOfMarker source "#r \"PresentationFrame") + +[] +let ``Fsx.Bug5073`` () = + let source = "#r \"System\" " + assertReferenceTooltipContains @"Reference Assemblies\Microsoft" (markAtEndOfMarker source "#r \"Sys") + assertReferenceTooltipContains ".NETFramework" (markAtEndOfMarker source "#r \"Sys") + +[] +let ``Fsx.HashR_QuickInfo.BugDefaultReferenceFileIsAlsoResolved`` () = + assertReferenceTooltipContains "System.dll" (markAtEndOfMarker "#r \"System\" " "#r \"Syst") + +[] +let ``Fsx.HashR_QuickInfo.DoubleReference`` () = + let source = "#r \"System\" // Mark1\n#r \"System\" // Mark2 " + assertReferenceTooltipContains "System.dll" (markAtStartOfMarker source "tem\" // Mark1") + assertReferenceTooltipContains "System.dll" (markAtStartOfMarker source "tem\" // Mark2") + +[] +let ``Fsx.HashR_QuickInfo.ResolveFromGAC`` () = + let marked = markAtEndOfMarker "#r \"CustomMarshalers\" " "#r \"Custo" + assertReferenceTooltipContains ".NETFramework" marked + assertReferenceTooltipContains "CustomMarshalers.dll" marked + +[] +let ``Fsx.HashR_QuickInfo.ResolveFromFullyQualifiedPath`` () = + let path = System.IO.Path.Combine(System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory(), "System.configuration.dll") + let source = sprintf "#r @\"%s\"" path + let marker = "#r @\"" + path.Substring(0, path.Length / 2) + let marked = markAtEndOfMarker source marker + assertReferenceTooltipContains path marked + assertReferenceTooltipContains (System.Reflection.AssemblyName.GetAssemblyName(path).ToString()) marked diff --git a/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.DiscriminatedUnions.fs b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.DiscriminatedUnions.fs new file mode 100644 index 00000000000..b2a616d5b02 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.DiscriminatedUnions.fs @@ -0,0 +1,171 @@ +module FSharp.Compiler.Service.Tests.TooltipDiscriminatedUnionsTests + +open System +open Xunit +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open FSharp.Compiler.Symbols +open FSharp.Compiler.Tokenization +open TestFramework + +let private assertTooltipContainsWithProvider (expected: string) (markedSource: string) = + Checker.getTooltipWithOptions + [| "-r:" + PathRelativeToTestAssembly("DummyProviderForLanguageServiceTesting.dll") |] + markedSource + |> foldToolTip + |> assertFoldedTooltipContains true "provider tooltip" expected + +let private priorityQueueSource = + """open System +type PriorityQueue(*MarkerType*)<'k,'a> = + | Nil(*MarkerDataConstructor*) + | Branch of 'k * 'a * PriorityQueue<'k,'a> * PriorityQueue<'k,'a> +module PriorityQueue(*MarkerModule*) = + let empty = Nil + let minKeyValue = function + | Nil -> failwith "empty queue" + | Branch(k,a,_,_) -> (k,a) + let minKey pq = fst (minKeyValue pq(*MarkerVal*)) + let singleton(*MarkerLastLine*) k a = Branch(k,a,Nil,Nil)""" + +[] +let ``TypeConstructorQuickInfo`` () = + assertTooltipContainsInOrder + [ "type PriorityQueue<'k,'a> =" + "| Nil" + "| Branch of 'k * 'a * PriorityQueue<'k,'a> * PriorityQueue<'k,'a>" ] + (markAtStartOfMarker priorityQueueSource "(*MarkerType*)") + + assertTooltipContains + "union case PriorityQueue.Nil: PriorityQueue<'k,'a>" + (markAtStartOfMarker priorityQueueSource "(*MarkerDataConstructor*)") + + assertTooltipContainsInOrder + [ "module PriorityQueue"; "from Test" ] + (markAtStartOfMarker priorityQueueSource "(*MarkerModule*)") + + assertTooltipContains "val pq: PriorityQueue<'a,'b>" (markAtStartOfMarker priorityQueueSource "(*MarkerVal*)") + + assertTooltipContains + "val singleton: k: 'a -> a: 'b -> PriorityQueue<'a,'b>" + (markAtStartOfMarker priorityQueueSource "(*MarkerLastLine*)") + +[] +let ``NamedDUFieldQuickInfo`` () = + let source = + """type NamedFieldDU(*MarkerType*) = + | Case1(*MarkerCase1*) of V1 : int * bool * V3 : float + | Case2(*MarkerCase2*) of ``Big Name`` : int * Item2 : bool + | Case3(*MarkerCase3*) of Item : int +exception NamedExn(*MarkerException*) of int * V2 : string * bool * Data9 : float""" + + assertTooltipContainsInOrder + [ "type NamedFieldDU =" + "| Case1 of V1: int * bool * V3: float" + "| Case2 of ``Big Name`` : int * bool" + "| Case3 of int" ] + (markAtStartOfMarker source "(*MarkerType*)") + + assertTooltipContains + "union case NamedFieldDU.Case1: V1: int * bool * V3: float -> NamedFieldDU" + (markAtStartOfMarker source "(*MarkerCase1*)") + + assertTooltipContains + "union case NamedFieldDU.Case2: ``Big Name`` : int * bool -> NamedFieldDU" + (markAtStartOfMarker source "(*MarkerCase2*)") + + assertTooltipContains "union case NamedFieldDU.Case3: int -> NamedFieldDU" (markAtStartOfMarker source "(*MarkerCase3*)") + + assertTooltipContains + "exception NamedExn of int * V2: string * bool * Data9: float" + (markAtStartOfMarker source "(*MarkerException*)") + +[] +let ``Regression.InDeclaration.Bug3176d`` () = + let source = + """type DU<'a> = + | DULabel of 'a""" + + assertTooltipContains "DULabel: 'a -> DU<'a>" (markAtEndOfMarker source "DULab") + +[] +let ``IdentifiersForUnionCases`` () = + let source = + String.concat "\n" [ "type TestType10 = Case1 | Case2 of int"; "let test12 = (Case1,Case2(3))" ] + + walk source "type TestType10 = " "Case1" "union case TestType10.Case1" + walk source "type TestType10 = Case1 | " "Case2" "union case TestType10.Case2" + walk source "let test12 = (" "Case1" "union case TestType10.Case1" + walk source "let test12 = (Case1," "Case2" "union case TestType10.Case2" + +[] +let ``Regression.MemberDefinition.DocComments.Bug5856_3`` () = + assertTooltipContainsInOrder + [ "union case Module.Union.Case: int -> Module.Union"; "Case comment" ] + """module Module = + /// Union comment + type Union = + /// Case comment + | Case of int + +let x() = Module.Ca{caret}se""" + +[] +let ``Regression.MemberDefinition.DocComments.Bug5856_4`` () = + assertTooltipContainsInOrder + [ "type Union ="; "| Case of int"; "Union comment" ] + """module Module = + /// Union comment + type Union = + /// Case comment + | Case of int + +let _ = typeof""" + +[] +let ``XmlDocCommentsForArguments`` () = + let source = + """type bar() = + /// Test for members + /// x1 param! + member this.foo + (x1:int)= + System.Console.WriteLine(x1.ToString()) +type Uni1 = + /// Test for unions + /// str of case1 + | Case1 of str: string + | None +/// Test for exception types +/// value param +exception Ex1 of value: string +// Methods +let f1 = (new bar()).foo(*Marker0*)(x1(*Marker1*) = 10) +let f2 = System.String.Concat(1, arg1(*Marker2*) = "") +//Unions +let f3 = Case1(str(*Marker3*) = "10") +match f3 with +| Case1(str(*Marker4*) = "10") -> () +| _ -> () +//Exceptions +let f4 = Ex1(value(*Marker5*) = "") +try + () +with + Ex1(value(*Marker6*) = v) -> () +//Static parameters of type providers +type provType = N1.T""" + + assertTooltipContains "Test for members" (markAtStartOfMarker source "(*Marker0*)") + assertTooltipContains "x1 param!" (markAtStartOfMarker source "(*Marker1*)") + + assertTooltipContains + "Concatenates the string representations of two specified objects." + (markAtStartOfMarker source "(*Marker2*)") + + assertTooltipContains "str of case1" (markAtStartOfMarker source "(*Marker3*)") + assertTooltipContains "str of case1" (markAtStartOfMarker source "(*Marker4*)") + assertTooltipContains "value param" (markAtStartOfMarker source "(*Marker5*)") + assertTooltipContains "value param" (markAtStartOfMarker source "(*Marker6*)") + assertTooltipContainsWithProvider "Param1 of string" (markAtStartOfMarker source "(*Marker7*)") + assertTooltipContainsWithProvider "Ignored" (markAtStartOfMarker source "(*Marker8*)") diff --git a/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Expressions.fs b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Expressions.fs new file mode 100644 index 00000000000..22bb8d65f95 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Expressions.fs @@ -0,0 +1,237 @@ +module FSharp.Compiler.Service.Tests.TooltipExpressionsTests + +open System +open Xunit +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open FSharp.Compiler.Symbols +open FSharp.Compiler.Tokenization + +let private assertOperatorTooltipContains (expected: string) (operatorName: string) (markedSource: string) = + let context = SourceContext.fromMarkedSource markedSource + let _, checkResults = getParseAndCheckResults context.Source + + checkResults.GetToolTip(context.CaretPos.Line, context.CaretPos.Column + 1, context.LineText, [ operatorName ], FSharpTokenTag.Identifier) + |> foldToolTip + |> assertFoldedTooltipContains true "operator tooltip" expected + +[] +let ``Operators.TopLevel`` () = + assertOperatorTooltipContains + "tooltip for operator" + "===" + "/// tooltip for operator\nlet (===) a b = a + b\nlet _ = \"\" ==={caret} \"\"" + +[] +let ``Operators.Member`` () = + assertOperatorTooltipContains + "tooltip for operator" + "+++" + "type U = U\n with\n /// tooltip for operator\n static member (+++) (U, U) = U\nlet _ = U +++{caret} U" + +[] +let ``QuickInfoForQuotedIdentifiers`` () = + let source = + "/// The fff function\nlet fff x = x\n/// The gg gg function\nlet ``gg gg`` x = x\nlet r = fff 1 + ``gg gg`` 2 // no tip hovering over" + + let identifier = "``gg gg``" + + for i in 1 .. identifier.Length - 1 do + let marker = "+ " + identifier.Substring(0, i) + assertTooltipContains "gg gg" (markAtEndOfMarker source marker) + +[] +let ``QuickInfoSingleCharQuotedIdentifier`` () = + assertTooltipContains "val x: int" "let ``x`` = 10\n``x{caret}``|> printfn \"%A\"" + +[] +let ``IntArrayQuickInfo`` () = + let source = + "let x(*MIntArray1*) : int array = [| 1; 2; 3 |]\nlet y(*MInt[]*) : int [] = [| 1; 2; 3 |]" + + assertTooltipContains "int array" (markAtStartOfMarker source "(*MIntArray1*)") + assertTooltipContains "int array" (markAtStartOfMarker source "(*MInt[]*)") + +[] +let ``LinkNameStringQuickInfo`` () = + assertTooltipDoesNotContain "val" "let y = 1\nlet f x = \"{caret}x\"(*Marker1*)\nlet g z = \"y\"(*Marker2*)" + assertTooltipDoesNotContain "val" "let y = 1\nlet f x = \"x\"(*Marker1*)\nlet g z = \"{caret}y\"(*Marker2*)" + assertTooltipContains "val y: int" "let y{caret} = 1\nlet f x = \"x\"(*Marker1*)\nlet g z = \"y\"(*Marker2*)" + +[] +let ``IdentifierWithTick`` () = + let source = "let x = 1\nlet x' = \"foo\"\nif (*aaa*)x = 1 then (*bbb*)x' else \"\"" + assertTooltipContains "val x: int" (markAtEndOfMarker source "(*aaa*)x") + assertTooltipContains "val x': string" (markAtEndOfMarker source "(*bbb*)x'") + +[] +let ``NegativeTest.CharLiteralNotConfusedWithIdentifierWithTick`` () = + assertTooltipDoesNotContain "val x" (markAtEndOfMarker "let x = 1\nlet y = 'x'" "'x") + assertTooltipContains "val x: int" "let x{caret} = 1\nlet y = 'x'" + +[] +let ``StringLiteralWithIdentifierLookALikes.Bug2360_A`` () = + let source = "let y = 1\nlet f x = \"x\"\nlet g z = \"y\"" + assertTooltipDoesNotContain "val" (markAtEndOfMarker source "f x = \"") + assertTooltipContains "val y: int" (markAtEndOfMarker source "let y") + +[] +let ``Regression.StringLiteralWithIdentifierLookALikes.Bug2360_B`` () = + assertTooltipContains "val y: int" (markAtEndOfMarker "let y = 1" "let y") + +[] +let ``Class.OnlyClassInfo`` () = + let source = "type TT(x : int, ?y : int) =\n class end" + let marked = markAtEndOfMarker source "type T" + assertTooltipContains "type TT" marked + assertTooltipDoesNotContain "---" marked + +[] +let ``Regression.Classes.Bug2362`` () = + let source = "let append mm nn = fun ac -> mm (nn ac)" + assertTooltipContains "mm: ('a -> 'b) -> nn: ('c -> 'a) -> ac: 'c -> 'b" (markAtEndOfMarker source "let appen") + assertTooltipContains "'a -> 'b" (markAtEndOfMarker source "let append m") + assertTooltipContains "'c -> 'a" (markAtEndOfMarker source "let append mm n") + +[] +let ``Regression.NoTooltipForOperators.Bug4567`` () = + assertOperatorTooltipContains + "val (|+|) : a: int -> b: int -> int" + "|+|" + "let ( |+|{caret} ) a b = a + b\nlet n = 1 |+| 2\nlet b = true || false\n()" + + assertOperatorTooltipContains + "val (|+|) : a: int -> b: int -> int" + "|+|" + "let ( |+| ) a b = a + b\nlet n = 1 |+|{caret} 2\nlet b = true || false\n()" + + assertOperatorTooltipContains + "val (||) : e1: bool -> e2: bool -> bool" + "||" + "let ( |+| ) a b = a + b\nlet n = 1 |+| 2\nlet b = true ||{caret} false\n()" + +[] +let ``Regression.Bug1605`` () = + assertTooltipContains + "val string: value: 'T -> string" + (markAtEndOfMarker "let rec f l =\n match l with\n | [] -> string.Format(\n | x::xs -> \"hello\"" "| [] -> str") + +[] +let ``Regression.MemberDefinition.DocComments.Bug5856_6`` () = + let source = + "module Module =\n /// A comment\n exception MyException of int\nlet x() =\n Module.MyExcep{caret}tion |> ignore" + + assertTooltipContainsInOrder [ "exception MyException of int"; "A comment" ] source + + match (Checker.getSymbolUse source).Symbol with + | :? FSharpEntity as ent -> + if ent.XmlDocSig <> "T:Test.Module.MyException" then + failwithf "Unexpected XmlDocSig for own-code MyException: %s" ent.XmlDocSig + + if ent.Assembly.FileName |> Option.isSome then + failwithf "Expected own-code MyException to have no backing assembly file, but got %A" ent.Assembly.FileName + | sym -> failwithf "Expected an entity symbol for MyException, but got %A" sym + +let private accessorsAndMutatorsSource = + """type TestType1(*Marker1*)( x : int , y : int ) = + let mutable x = x + let mutable y = y + member this.X with get () = x + and set x' = x <- x' + member this.Y with set y' = y <- y' + member this.Length with get () = sqrt(float (x * x + y * y)) + member this.Item with get (i : int) = match i with | 0 -> x | 1 -> y | _ -> failwith "Incorrect index" +let point = TestType1(10,10) +point.X <- 3 +point.Y <- 4 +let xx = point.[0] +let yy = point.[1] +let bitArray = new System.Collections.BitArray(*Marker2*)(1) +point.Length |> ignore""" + +[] +let ``Automation.Regression.AccessorsAndMutators.Bug4276`` () = + let m1 = markAtStartOfMarker accessorsAndMutatorsSource "(*Marker1*)" + assertTooltipContains "type TestType1" m1 + assertTooltipContains "member Length: float" m1 + assertTooltipContains "member Item" m1 + assertTooltipContains "member X: int" m1 + assertTooltipContains "member Y: int" m1 + + let m2 = markAtStartOfMarker accessorsAndMutatorsSource "(*Marker2*)" + assertTooltipContains "type BitArray" m2 + assertTooltipContains "member And: value: BitArray -> BitArray" m2 + assertTooltipDoesNotContain "get_Length" m2 + assertTooltipDoesNotContain "set_Length" m2 + +let private tupleRecordClassOwnCodeConsumerSource = + """module Test + +open FSTestLib + +let AbsTuple = + fun x -> + let tuple1 = (x, x.ToString(), (float) x, (fun y -> (y.ToString(), y + 1))) + let tuple2 = (-x, (-x).ToString(), (float) (-x), (fun y -> (y.ToString(), y + 1))) + if x >= 0 then tuple1(*Marker1*) + else tuple2 + +let GenerateMyEmployee name age = + let a = MyEmployee.MakeDummy() + a.Name <- name + a.Age <- age + a.IsFTE <- System.Convert.ToBoolean(System.Random().Next(2)) + match a.IsFTE with + | true -> a + | _ -> MyEmployee(*Marker2*).MakeDummy() + +let myCarQuot = <@ new MyCar(*Marker3*)(19, MyColors.Red) @> + +let MaxTuple x y = + let tuplex = (x, x.ToString()) + let tupley = (y, (y).ToString()) + match x > y with + | true -> tuplex(*Marker4*) + | false -> tupley""" + +[] +let ``Automation.TupleRecordClassfromOwnCode`` () = + assertTooltipContainsWithFsTestLib + "val tuple1: int * string * float * (int -> string * int)" + (markAtStartOfMarker tupleRecordClassOwnCodeConsumerSource "(*Marker1*)") + + let m2 = markAtStartOfMarker tupleRecordClassOwnCodeConsumerSource "(*Marker2*)" + assertTooltipContainsWithFsTestLib "type MyEmployee" m2 + assertTooltipContainsWithFsTestLib "Full name: FSTestLib.MyEmployee" m2 + + let m3 = markAtStartOfMarker tupleRecordClassOwnCodeConsumerSource "(*Marker3*)" + assertTooltipContainsWithFsTestLib "type MyCar" m3 + assertTooltipContainsWithFsTestLib "Full name: FSTestLib.MyCar" m3 + + assertTooltipContainsWithFsTestLib + "val tuplex: 'a * string" + (markAtStartOfMarker tupleRecordClassOwnCodeConsumerSource "(*Marker4*)") + +[] +let ``Fsx.QuickInfo.Bug4979`` () = + assertTooltipContains + "The left or right SHIFT modifier key." + "System.ConsoleModifiers.Sh{caret}ift |> ignore\n(3).ToString().Length |> ignore" + + let tolerantAssemblies = + set + [ "netstandard.dll" + "System.Runtime.dll" + "System.Private.CoreLib.dll" + "System.Console.dll" + "mscorlib.dll" ] + + match (Checker.getSymbolUse "System.ConsoleModifiers.Shift |> ignore\n(3).ToString().Len{caret}gth |> ignore").Symbol with + | :? FSharpMemberOrFunctionOrValue as m -> + if m.XmlDocSig <> "P:System.String.Length" then + failwithf "Unexpected XmlDocSig for String.Length: %s" m.XmlDocSig + + match m.Assembly.FileName |> Option.map System.IO.Path.GetFileName with + | Some basename when tolerantAssemblies.Contains basename -> () + | other -> failwithf "Expected String.Length to be defined in one of %A, but got %A" tolerantAssemblies other + | sym -> failwithf "Expected a member symbol for String.Length, but got %A" sym diff --git a/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Generics.fs b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Generics.fs new file mode 100644 index 00000000000..b78dd00985a --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Generics.fs @@ -0,0 +1,73 @@ +module FSharp.Compiler.Service.Tests.TooltipGenericsTests + +open System +open Xunit +open FSharp.Compiler.Symbols + +[] +let ``Regression.Generic.3773a`` () = + assertTooltipContains "val M2: a: 'a -> obj" (markAtEndOfMarker "let rec M2<'a>(a:'a) = M2(a)" "let rec M") + +[] +let ``Regression.RecursiveDefinition.Generic.3773b`` () = + assertTooltipContains "val M1: a: int -> 'a" (markAtEndOfMarker "let rec M1<'a>(a:'a) = M1(0)" "let rec M") + +[] +let ``FrameworkClass`` () = + let source = "let l = new System.Collections.Generic.List()" + let marked = markAtEndOfMarker source "Generic.List" + assertTooltipContains "member Capacity: int\n" marked + assertTooltipContains "member Clear: unit -> unit\n" marked + assertTooltipDoesNotContain "get_Capacity" marked + assertTooltipDoesNotContain "set_Capacity" marked + assertTooltipDoesNotContain "get_Count" marked + assertTooltipDoesNotContain "set_Count" marked + +[] +let ``FrameworkClassNoMethodImpl`` () = + assertTooltipDoesNotContain + "System.Collections.ICollection.IsSynchronized" + (markAtEndOfMarker "let l = new System.Collections.Generic.LinkedList()" "Generic.LinkedList") + + assertTooltipContains + "LinkedList" + (markAtEndOfMarker "let l = new System.Collections.Generic.LinkedList()" "Generic.LinkedList") + +[] +let ``Regression.ExtensionMethods.DocComments.Bug6028`` () = + let source = + """open System.Linq +let rec query: System.Linq.IQueryable<_> = null +let _ = query.Al{caret}l""" + + assertTooltipContains "IQueryable.All" source + + match (Checker.getSymbolUse source).Symbol with + | :? FSharpMemberOrFunctionOrValue as m -> + if m.XmlDocSig <> "M:System.Linq.Queryable.All``1(System.Linq.IQueryable{``0},System.Linq.Expressions.Expression{System.Func{``0,System.Boolean}})" then + failwithf "Unexpected XmlDocSig for query.All: %s" m.XmlDocSig + + let expectedAssembly = +#if NETCOREAPP + "System.Linq.Queryable.dll" +#else + "System.Core.dll" +#endif + let basename = m.Assembly.FileName |> Option.map System.IO.Path.GetFileName + + if basename <> Some expectedAssembly then + failwithf "Expected query.All to be defined in %s, but got %A" expectedAssembly basename + | sym -> failwithf "Expected a member symbol for query.All, but got %A" sym + +[] +let ``GenericDotNetMethodShowsComment`` () = + let source = "let _ = System.Linq.ParallelEnumerable.ElementA{caret}t" + + match (Checker.getSymbolUse source).Symbol with + | :? FSharpMemberOrFunctionOrValue as m -> + let expected = + "M:System.Linq.ParallelEnumerable.ElementAt``1(System.Linq.ParallelQuery{``0},System.Int32" + + if not (m.XmlDocSig.Contains expected) then + failwithf "Unexpected XmlDocSig for ParallelEnumerable.ElementAt: %s" m.XmlDocSig + | sym -> failwithf "Expected a member symbol for ParallelEnumerable.ElementAt, but got %A" sym diff --git a/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Members.fs b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Members.fs new file mode 100644 index 00000000000..4d52736ead5 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Members.fs @@ -0,0 +1,137 @@ +module FSharp.Compiler.Service.Tests.TooltipMembersTests + +open System +open Xunit +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open FSharp.Compiler.Symbols +open FSharp.Compiler.Tokenization + +[] +let ``Regression.InDeclaration.Bug3176c`` () = + assertTooltipContains + "aaaa" + """type C = + val aa{caret}aa: int""" + +[] +let ``Declaration.CyclicalDeclarationDoesNotCrash`` () = + assertTooltipContains "type A" """type (*1*)A = int * A{caret} """ + +[] +let ``LongPaths`` () = + let source = + String.concat + "\n" + [ "let test0 = System.Console.In" + "let test0b = System.Collections.Generic.List()" + "let test0c = System.Collections.Generic.KeyNotFoundException()" + "type Test0d = System.Collections.Generic.List" + "type Test0e = System.Collections.Generic.KeyNotFoundException" ] + + let walk = EditorServiceAsserts.walk source + + walk "let test0 = " "System" "namespace System" + walk "let test0 = System." "Console" "Console =" + walk "let test0 = System.Console." "In" "System.Console.In" + walk "let test0 = System.Console." "In" "TextReader" + walk "let test0b = " "System" "namespace System" + walk "let test0b = System." "Collections" "namespace System.Collections" + walk "let test0b = System.Collections." "Generic" "namespace System.Collections.Generic" + walk "let test0b = System.Collections.Generic." "List" "List()" + walk "let test0c = " "System" "namespace System" + walk "let test0c = System." "Collections" "namespace System.Collections" + walk "let test0c = System.Collections." "Generic" "namespace System.Collections.Generic" + walk "let test0c = System.Collections.Generic." "KeyNotFoundException" "KeyNotFoundException()" + walk "type Test0d = " "System" "namespace System" + walk "type Test0d = System." "Collections" "namespace System.Collections" + walk "type Test0d = System.Collections." "Generic" "namespace System.Collections.Generic" + walk "type Test0d = System.Collections.Generic." "List" "Generic.List" + walk "type Test0e = " "System" "namespace System" + walk "type Test0e = System." "Collections" "namespace System.Collections" + walk "type Test0e = System.Collections." "Generic" "namespace System.Collections.Generic" + walk "type Test0e = System.Collections.Generic." "KeyNotFoundException" "Generic.KeyNotFoundException" + +[] +let ``AtEndOfLine`` () = + let (ToolTipText elements) = Checker.getTooltip "//{caret}" + + let meaningfulElements = + elements + |> List.filter (function + | ToolTipElement.None -> false + | _ -> true) + + match meaningfulElements with + | [] -> () + | _ -> failwithf "Expected an empty tooltip at the end of a comment line, but got: %A" elements + +#if !NETCOREAPP +let private getTooltipWithoutSystemDrawing (markedSource: string) = + getTooltipWithReferences + "MissingDependencyReferences" + [ fsCoreDefaultReference () + sysLib "mscorlib" + sysLib "System" + sysLib "System.Core" + sysLib "System.Windows.Forms" ] // System.Drawing.dll omitted on purpose (Bug 5409's missing transitive dependency) + markedSource + +[] +let ``MissingDependencyReferences.QuickInfo.Bug5409`` () = + let actual = + getTooltipWithoutSystemDrawing "let myFo{caret}rm = new System.Windows.Forms.Form()" + |> foldToolTip + + if not (actual.Contains "Form") then + failwithf "Expected tooltip to contain %A when System.Drawing is absent, but the actual tooltip was:\n%s" "Form" actual +#endif + +[] +let ``Regression.Bug4642`` () = + assertTooltipContains "int -> char" """ "AA".Ch{caret}ars """ + +[] +let ``Regression.MemberDefinition.DocComments.Bug5856_10`` () = + let source = "let _ = System.String.Form{caret}at" + assertTooltipContains "System.String.Format(" source + + match (Checker.getSymbolUse source).Symbol with + | :? FSharpMemberOrFunctionOrValue as m -> + if m.XmlDocSig <> "M:System.String.Format(System.String,System.Object[])" then + failwithf "Unexpected XmlDocSig for String.Format: %s" m.XmlDocSig + + let expectedAssembly = +#if NETCOREAPP + "System.Runtime.dll" +#else + "mscorlib.dll" +#endif + let basename = m.Assembly.FileName |> Option.map System.IO.Path.GetFileName + + if basename <> Some expectedAssembly then + failwithf "Expected String.Format to be defined in %s, but got %A" expectedAssembly basename + | sym -> failwithf "Expected a member symbol for String.Format, but got %A" sym + +[] +let ``Regression.MemberDefinition.DocComments.Bug5856_13`` () = + assertTooltipContainsInOrder + [ "type KeyCollection<" + "member CopyTo" + """Represents the collection of keys in a . This class cannot be inherited.""" ] + "let _ = typeof.KeyColl{caret}ection>" + +[] +let ``Regression.MemberDefinition.DocComments.Bug5856_14`` () = + assertTooltipContainsInOrder + [ "type ArgumentException" + "member Message" + "The exception that is thrown when one of the arguments provided to a method is not valid." + +[] +let ``Regression.MemberDefinition.DocComments.Bug5856_15`` () = + assertTooltipContainsInOrder + [ "property System.AppDomain.CurrentDomain: System.AppDomain" + """Gets the current application domain for the current .""" ] + "let _ = System.AppDomain.CurrentDom{caret}ain" diff --git a/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Modules.fs b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Modules.fs new file mode 100644 index 00000000000..d5847b9eb08 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Modules.fs @@ -0,0 +1,96 @@ +module FSharp.Compiler.Service.Tests.TooltipModulesTests + +open System +open Xunit +open FSharp.Compiler.EditorServices + +[] +let ``ModuleDefinition.ModuleNoNewLines`` () = + let source = + """module XXX +type t = C3 +module YYY = + type t = C4 +///Doc +module ZZZ = + type t = C5 """ + + assertTooltipContains "module XXX" (markAtEndOfMarker source "XX") + assertTooltipContainsInOrder [ "module YYY"; "from XXX" ] (markAtEndOfMarker source "YY") + assertTooltipContainsInOrder [ "module ZZZ"; "from XXX"; "Doc" ] (markAtEndOfMarker source "ZZ") + +[] +let ``TypeAndModuleReferences`` () = + let source = + String.concat + "\n" + [ "let test1 = List.length" + "let test2 = List.Empty" + "let test3 = (\"1\").Length" + "let test3b = (id \"1\").Length" ] + + walk source "let test1 = " "List" "module List" + walk source "let test1 = List." "length" "length" + walk source "let test2 = " "List" "Collections.List" + walk source "let test2 = List." "Empty" "List.Empty" + walk source "let test3 = (\"1\")." "Length" "String.Length" + walk source "let test3b = (id \"1\")." "Length" "String.Length" + +[] +let ``ModuleNameAndMisc`` () = + let source = + String.concat + "\n" + [ "module (*test3q*)MM3 =" + " let y = 2" + "let test4 = lock" + "let (*test5*) ffff xx = xx + 1" ] + + walk source "module (*test3q*)" "MM3" "module MM3" + walk source "let test4 = " "lock" "lock" + walk source "let (*test5*) " "ffff" "ffff" + +[] +let ``Regression.ModuleAlias.Bug3790a`` () = + let source = + """module ``Some`` = Microsoft.FSharp.Collections.List +module None = Microsoft.FSharp.Collections.List""" + + assertTooltipContains "module List" (markAtEndOfMarker source "module ``So") + assertTooltipContains "module List" (markAtEndOfMarker source "module No") + assertTooltipDoesNotContain "Option" (markAtEndOfMarker source "module ``So") + assertTooltipDoesNotContain "Option" (markAtEndOfMarker source "module No") + +[] +let ``Regression.MemberDefinition.DocComments.Bug5856_2`` () = + assertTooltipContainsInOrder + [ "module Inner"; "from"; "Outer"; "Comment" ] + """module Outer = + /// Comment + module Inner = + let x = 1 + +let _ = Outer.Inn{caret}er.x""" + +[] +let ``Automation.Regression.ModuleIdentifier.Bug2937`` () = + let source = "module XXX{caret}\ntype t = C3" + assertTooltipContains "module XXX" source + + for description in groupMainDescriptions (Checker.getTooltip source) do + if description.Contains "module XXX" && description.Contains "\n" then + failwithf "Expected the module identifier tooltip to be a single line, but it contained a newline:\n%s" description + +[] +let ``Automation.Regression.QuotedIdentifier.Bug3790`` () = + let source = + String.concat + "\n" + [ "module Test" + "module ``Some``(*Marker1*) = Microsoft.FSharp.Collections.List" + "let _ = ``Some``(*Marker2*).append [] []" ] + + assertTooltipContains "module List" (markAtStartOfMarker source "``(*Marker1*)") + assertTooltipDoesNotContain "Option.Some" (markAtStartOfMarker source "``(*Marker1*)") + assertTooltipContains "module List" (markAtStartOfMarker source "``(*Marker2*)") + assertTooltipDoesNotContain "Option.Some" (markAtStartOfMarker source "``(*Marker2*)") diff --git a/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Properties.fs b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Properties.fs new file mode 100644 index 00000000000..48618eedc8e --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Properties.fs @@ -0,0 +1,54 @@ +module FSharp.Compiler.Service.Tests.TooltipPropertiesTests + +open Xunit + +let private propSource = + """namespace CountChocula + type BooBerry() = + let get() = "" + member source.Prop + with get() : int = 0 + and set(value:int) : unit = ()""" + +[] +let ``Regression.AccessorMutator.Bug4903a`` () = + assertTooltipDoesNotContain "string" (markAtEndOfMarker propSource "with g") + assertTooltipContains "int" (markAtEndOfMarker propSource "with g") + +[] +let ``Regression.AccessorMutator.Bug4903d`` () = + assertTooltipDoesNotContain + "string" + """namespace CountChocula + type BooBerry() = + member source.AMetho{caret}d() = () + member source.AProperty + with get() : int = 0 + and set(value:int) : unit = ()""" + +[] +let ``Regression.AccessorMutator.Bug4903b`` () = + assertTooltipDoesNotContain "seq" (markAtEndOfMarker propSource "and s") + assertTooltipContains "int" (markAtEndOfMarker propSource "and s") + +[] +let ``Regression.AccessorMutator.Bug4903c`` () = + assertTooltipContains "string" (markAtEndOfMarker propSource "let g") + +[] +[] +[] +[] +let ``Regression.AccessorMutator.Bug4903efg`` (marker: string) (expected: string) = + assertTooltipContains expected (markAtEndOfMarker propSource marker) + +[] +let ``Regression.MemberDefinition.DocComments.Bug5856_8`` () = + assertTooltipContainsInOrder + [ "property Foo.Property: string"; "A comment" ] + """type Foo = + /// A comment + static member Property + with get() = "" + +let x() = Foo.Prop{caret}erty""" diff --git a/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Queries.fs b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Queries.fs new file mode 100644 index 00000000000..97cbb16c89d --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Queries.fs @@ -0,0 +1,245 @@ +module FSharp.Compiler.Service.Tests.TooltipQueriesTests + +open System +open System.IO +open Xunit +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open FSharp.Compiler.IO +open FSharp.Compiler.Symbols +open FSharp.Compiler.Tokenization +open TestFramework + +let private dataSourceCode = + """namespace DataSource +open System +open System.Xml.Linq + +type Product() = + let mutable id = 0 + let mutable name = "" + let mutable category = "" + let mutable price = 0M + let mutable unitsInStock = 0 + member x.ProductID with get() = id and set(v) = id <- v + member x.ProductName with get() = name and set(v) = name <- v + member x.Category with get() = category and set(v) = category <- v + member x.UnitPrice with get() = price and set(v) = price <- v + member x.UnitsInStock with get() = unitsInStock and set(v) = unitsInStock <- v + +module Products = + let getProductList() = + [ + Product(ProductID = 1, ProductName = "Chai", Category = "Beverages", UnitPrice = 18.0000M, UnitsInStock = 39 ); + Product(ProductID = 2, ProductName = "Chang", Category = "Beverages", UnitPrice = 19.0000M, UnitsInStock = 17 ); + Product(ProductID = 3, ProductName = "Aniseed Syrup", Category = "Condiments", UnitPrice = 10.0000M, UnitsInStock = 13 ); + ] +""" + +let private assertQuickInfoInQuery (expected: string) (markedFile2: string) = + foldedProjectTooltip [ dataSourceCode ] [ sysLib "System.Xml.Linq" ] markedFile2 + |> assertFoldedTooltipContains true "query tooltip" expected + +[] +let ``Regression.ComputationExpressionMemberAppearingInQuickInfo`` () = + let source = + """module Test +let q2 = + query { + for p in [1;2] do + join cccccc in [3;4] on (p = cccccc) + yield ccc{caret}ccc + }""" + + assertTooltipDoesNotContain "Yield" source + assertTooltipContains "val cccccc: int" source + +[] +let ``QueryExpression.QuickInfoSmokeTest1`` () = + let source = """let q = query { for x in ["1"] do selec{caret}t x }""" + assertTooltipContains "custom operation: select" source + assertTooltipContains "custom operation: select ('Result)" source + assertTooltipContains "Calls" source + assertTooltipContains "Linq.QueryBuilder.Select" source + +[] +let ``QueryExpression.QuickInfoSmokeTest2`` () = + let source = """let q = query { for x in ["1"] do joi{caret}n y in ["2"] on (x = y); select (x,y) }""" + assertTooltipContains "custom operation: join" source + assertTooltipContains "join var in collection on (outerKey = innerKey)" source + assertTooltipContains "Calls" source + assertTooltipContains "Linq.QueryBuilder.Join" source + +[] +let ``QueryExpression.QuickInfoSmokeTest3`` () = + let source = """let q = query { for x in ["1"] do groupJoin{caret} y in ["2"] on (x = y) into g; select (x,g) }""" + assertTooltipContains "custom operation: groupJoin" source + assertTooltipContains "groupJoin var in collection on (outerKey = innerKey)" source + assertTooltipContains "Calls" source + assertTooltipContains "Linq.QueryBuilder.GroupJoin" source + +[] +let ``Query.WithError1.Bug196137`` () = + assertQuickInfoInQuery + "Product.ProductName: string" + """open DataSource +let products = Products.getProductList() +let sortedProducts = + query { + for p in products do + let x = p.ProductID + "a" + sortBy p.ProductName{caret} + select p + }""" + +[] +let ``Query.WithError2`` () = + assertQuickInfoInQuery + "custom operation: minBy ('Value)" + """open DataSource +let products = Products.getProductList() +let test = + query { + for p in products do + let x = p.ProductID + "1" + minBy{caret} p.UnitPrice + }""" + +[] +let ``Query.WithinLargeQuery`` () = + let source = + """open DataSource +let products = Products.getProductList() +let numbers = [ 1;2; 8; 9; 15; 23; 3; 42; 4;0; 55;] +let largequery = + query { + for p in products do + sortBy p.ProductName + thenBy p.UnitPrice + thenByDescending p.Category + where (p.UnitsInStock < 100) + where (p.Category = "Condiments") + groupValBy(*Mark1*) p p.Category into g + let maxPrice = query { for x in g do maxBy(*Mark2*) x.UnitPrice } + let mostExpensiveProducts = query { for x in g do where (x.UnitPrice = maxPrice) } + select (g.Key, mostExpensiveProducts, query { + for n in numbers do + where (n%2 = 0) + where(*Mark3*) (n > 2) + where (n < 40) + select n}) + distinct(*Mark4*) + }""" + + let at (mark: string) = source.Replace(mark, "{caret}") + assertQuickInfoInQuery "custom operation: groupValBy ('Value) ('Key)" (at "(*Mark1*)") + assertQuickInfoInQuery "custom operation: maxBy ('Value)" (at "(*Mark2*)") + assertQuickInfoInQuery "custom operation: where (bool)" (at "(*Mark3*)") + assertQuickInfoInQuery "custom operation: distinct" (at "(*Mark4*)") + +[] +let ``Query.ArgumentToQuery.OperatorError`` () = + let source = + """let numbers = [ 1;2; 8; 9; 15; 23; 3; 42; 4;0; 55;] +let foo = + query { + for n in numbers do + orderBy (n.GetType()) + select n }""" + + assertTooltipContains "val n: int" (markAtStartOfMarker source "n.GetType()") + assertTooltipContains "System.Object.GetType() : System.Type" (markAtStartOfMarker source "Type()") + +[] +let ``Query.ArgumentToQuery.InNestedQuery`` () = + let source = + """open DataSource +let products = Products.getProductList() +let test1 = + query { + for p in products do + sortBy p.ProductName + select (p.ProductName, query { for f in products do + groupValBy(*Mark3*) f f.Category into g + let maxPrice = query { for x in g do maxBy x.UnitPrice } + let mostExpensiveProducts = query { for x in g do where(*Mark1*) (x.UnitPrice = maxPrice(*Mark2*)) } + select(*Mark4*) (g.Key, g)}) }""" + + let at (mark: string) = source.Replace(mark, "{caret}") + assertQuickInfoInQuery "custom operation: where (bool)" (at "(*Mark1*)") + assertQuickInfoInQuery "val maxPrice: decimal" (at "(*Mark2*)") + assertQuickInfoInQuery "custom operation: groupValBy ('Value) ('Key)" (at "(*Mark3*)") + assertQuickInfoInQuery "custom operation: select ('Result)" (at "(*Mark4*)") + +[] +let ``Query.ComputationExpression.Method`` () = + let source = + """open System.Collections.Generic +let chars = ["A";"B";"C"] +type WorkflowBuilder() = + let yieldedItems = new List() + member this.Items = yieldedItems |> Array.ofSeq + member this.Yield(item) = yieldedItems.Add(item) + member this.YieldFrom(items : seq) = + items |> Seq.iter (fun item -> yieldedItems.Add(item.ToUpper())) + () + member this.Combine(f, g) = g + member this.Delay (f : unit -> 'a) = + f() + member this.Zero() = () + member this.Return _ = this.Items +let computationExpreQuery = + query { + for char in chars do + let workflow = new WorkflowBuilder() + let result = + workflow { + yield "foo" + yield "bar" + yield! [| "a"; "b"; "c" |] + return () + } + let t = workflow.Combine(*Mark1*)("a","b") + let d = workflow.Zero(*Mark2*)() + where (result |> Array.exists(fun i -> i = char)) + yield char + }""" + + let at (mark: string) = source.Replace(mark, "{caret}") + assertTooltipContains "member WorkflowBuilder.Combine: f: 'b0 * g: 'c1 -> 'c1" (at "(*Mark1*)") + assertTooltipContains "member WorkflowBuilder.Zero: unit -> unit" (at "(*Mark2*)") + +[] +let ``Query.ComputationExpression.CustomOp`` () = + let source = + """open System +open Microsoft.FSharp.Quotations + +type EventBuilder() = + member _.For(ev:IObservable<'T>, loop:('T -> #IObservable<'U>)) : IObservable<'U> = failwith "" + member _.Yield(v:'T) : IObservable<'T> = failwith "" + member _.Quote(v:Quotations.Expr<'T>) : Expr<'T> = v + member _.Run(x:Expr<'T>) = Microsoft.FSharp.Linq.RuntimeHelpers.LeafExpressionConverter.EvaluateQuotation x :?> 'T + + [] + member _.Where (x, [] f) = Observable.filter f x + + [] + member _.Select (x, [] f) = Observable.map f x + + [] + member inline _.ScanSumBy (source, [] f : 'T -> 'U) : IObservable<'U> = Observable.scan (fun a b -> a + f b) LanguagePrimitives.GenericZero<'U> source + +let myquery = EventBuilder() +let f = new Event() +let e1 = + myquery { for x in f.Publish do + myWhere(*Mark1*) (fst x < 100) + scanSumBy(*Mark2*) (snd x) + }""" + + let at (mark: string) = source.Replace(mark, "{caret}") + assertTooltipContains "custom operation: myWhere (bool)" (at "(*Mark1*)") + assertTooltipContains "Calls EventBuilder.Where" (at "(*Mark1*)") + assertTooltipContains "custom operation: scanSumBy ('U)" (at "(*Mark2*)") + assertTooltipContains "Calls EventBuilder.ScanSumBy" (at "(*Mark2*)") diff --git a/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Records.fs b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Records.fs new file mode 100644 index 00000000000..3a12966746e --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Records.fs @@ -0,0 +1,94 @@ +module FSharp.Compiler.Service.Tests.TooltipRecordsTests + +open System +open Xunit +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open FSharp.Compiler.Symbols +open FSharp.Compiler.Tokenization + +let private assertTooltipTrimmedContainsInFsFile (expected: string) (markedSource: string) = + let actual = foldedTooltip FsFile markedSource + let trimmed = actual.Replace("\r", "").Replace("\n", "") + + if not (trimmed.Contains expected) then + failwithf "Expected newline-stripped .fs-file tooltip to contain %A, but the actual tooltip was:\n%s" expected actual + +[] +[] + [] + member x._Print = x.Element.ToString() +let u = { Element = "abc" } +""", + "member _Print", "")>] +[] + member x.Print1 = x.Element.ToString() + member x.Print2 = x.Element.ToString() +let u = { Element = "abc" } +""", + "member Print1", "member Print2")>] +let ``Hidden record members are omitted from the type tooltip`` (source: string) (notExpected: string) (alsoExpected: string) = + let marked = markAtStartOfMarker source "ypeU =" + assertTooltipDoesNotContain notExpected marked + + if alsoExpected <> "" then + assertTooltipContains alsoExpected marked + +[] +let ``TypeRecordQuickInfo`` () = + let source = + """namespace NS + type Re(*MarkerRecord*) = { X : int } """ + + assertTooltipTrimmedContainsInFsFile "type Re = { X: int }" (markAtStartOfMarker source "(*MarkerRecord*)") + +[] +let ``Regression.InDeclaration.Bug3176a`` () = + let source = """type T<'a> = { aaaa : 'a; bbbb : int } """ + assertTooltipContains "aaaa: 'a" (markAtEndOfMarker source "aa") + +[] +let ``IdentifiersForFields`` () = + let source = + String.concat "\n" [ "type TestType9 = { XXX : int }"; "let test11 = { XXX = 1 }" ] + + walk source "type TestType9 = { " "XXX" "XXX: int" + walk source "let test11 = { " "XXX" "XXX" + +[] +let ``ArgumentAndPropertyNames`` () = + let source = + String.concat + "\n" + [ "type R = { mutable AAA : int }" + " static member M() = { AAA = 1 }" + "let test13 = R.M(AAA=3)" + "type R2() = " + " static member M() = System.Reflection.InterfaceMapping()" + "" + "let test14 = R2.M(InterfaceMethods= [| |])" + "" + "let test15 = new System.Reflection.AssemblyName(Name=\"Foo\")" + "let test16 = new System.Reflection.AssemblyName(assemblyName=\"Foo\")" ] + + walk source "let test13 = R.M(" "AAA" "R.AAA: int" + walk source "let test14 = R2.M(" "InterfaceMethods" "field System.Reflection.InterfaceMapping.InterfaceMethods" + walk source "let test15 = new System.Reflection.AssemblyName(" "Name" "property System.Reflection.AssemblyName.Name" + walk source "let test16 = new System.Reflection.AssemblyName(" "assemblyName" "argument assemblyName" + +[] +let ``Regression.MemberDefinition.DocComments.Bug5856_7`` () = + assertTooltipContainsInOrder + [ "Record.field: int"; "A comment" ] + """type Record = { + /// A comment + field : int + } + +let record = {field = 1} +let x() = record.fie{caret}ld""" diff --git a/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.TypeProviders.fs b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.TypeProviders.fs new file mode 100644 index 00000000000..a64704cd2b7 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.TypeProviders.fs @@ -0,0 +1,203 @@ +module FSharp.Compiler.Service.Tests.TooltipTypeProvidersTests + +open Xunit + +[] +let ``TypeProviders.NestedTypesOrder`` () = + assertTooltipContainsInOrder + [ "A"; "X"; "Z" ] + """type t = N1.TypeWithNestedTypes{caret}""" + +[] +let ``TypeProvider.XmlDocAttribute.Type.Comment`` () = + assertTooltipContains + "This is a synthetic type created by me!" + """let a = typeof""" + +[] +let ``TypeProvider.XmlDocAttribute.Type.WithLongComment`` () = + assertTooltipContains + "This is a synthetic type created by me!. Which is used to test the tool tip of the typeprovider type to check if it shows the right message or not." + """let a = typeof""" + +[] +let ``TypeProvider.XmlDocAttribute.Type.WithNullComment`` () = + assertTooltipContains + "type T =\n new: unit -> T\n static member M: unit -> int []\n static member StaticProp: decimal\n member Event1: EventHandler" + """let a = typeof""" + +[] +let ``TypeProvider.XmlDocAttribute.Type.WithEmptyComment`` () = + assertTooltipContains + "type T =\n new : unit -> T\n static member M: unit -> int []\n static member StaticProp: decimal\n member Event1: EventHandler" + """let a = typeof""" + +[] +let ``TypeProvider.XmlDocAttribute.Type.LocalizedComment`` () = + assertTooltipContains + "This is a synthetic type Localized! ኤፍ ሻርፕ" + """let a = typeof""" + +[] +let ``TypeProvider.XmlDocAttribute.Constructor.Comment`` () = + assertTooltipContains + "This is a synthetic .ctor created by me for N.T" + """let foo = new N.T{caret}()""" + +[] +let ``TypeProvider.XmlDocAttribute.Constructor.WithLongComment`` () = + assertTooltipContains + "This is a synthetic .ctor created by me for N.T. Which is used to test the tool tip of the typeprovider Constructor to check if it shows the right message or not." + """let foo = new N.T{caret}()""" + +[] +let ``TypeProvider.XmlDocAttribute.Constructor.WithNullComment`` () = + assertTooltipContains + "N.T() : N.T" + """let foo = new N.T{caret}()""" + +[] +let ``TypeProvider.XmlDocAttribute.Constructor.WithEmptyComment`` () = + assertTooltipContains + "N.T() : N.T" + """let foo = new N.T{caret}()""" + +[] +let ``TypeProvider.XmlDocAttribute.Constructor.LocalizedComment`` () = + assertTooltipContains + "This is a synthetic .ctor Localized! ኤፍ ሻርፕ for N.T" + """let foo = new N.T{caret}()""" + +[] +let ``TypeProvider.XmlDocAttribute.Event.Comment`` () = + assertTooltipContains + "This is a synthetic *event* created by me for N.T" + """let t = new N.T() +t.Event1{caret}""" + +[] +let ``TypeProvider.XmlDocAttribute.Event.LocalizedComment`` () = + assertTooltipContains + "This is a synthetic *event* Localized! ኤፍ ሻርፕ for N.T" + """let t = new N.T() +t.Event1{caret}""" + +[] +let ``TypeProvider.ParamsAttributeTest`` () = + assertTooltipContains + "[] separator" + """let t = "a".Spl{caret}it('c', 'd')""" + +[] +let ``TypeProvider.XmlDocAttribute.Event.WithLongComment`` () = + assertTooltipContains + "This is a synthetic *event* created by me for N.T. Which is used to test the tool tip of the typeprovider Event to check if it shows the right message or not.!" + """let t = new N.T() +t.Event1{caret}""" + +[] +let ``TypeProvider.XmlDocAttribute.Event.WithNullComment`` () = + assertTooltipContains + "member N.T.Event1: IEvent" + """let t = new N.T() +t.Event1{caret}""" + +[] +let ``TypeProvider.XmlDocAttribute.Event.WithEmptyComment`` () = + assertTooltipContains + "member N.T.Event1: IEvent" + """let t = new N.T() +t.Event1{caret}""" + +[] +let ``TypeProvider.XmlDocAttribute.Method.Comment`` () = + assertTooltipContains + "This is a synthetic *method* created by me!!" + """let t = new N.T.M{caret}()""" + +[] +let ``TypeProvider.XmlDocAttribute.Method.LocalizedComment`` () = + assertTooltipContains + "This is a synthetic *method* Localized! ኤፍ ሻርፕ" + """let t = new N.T.M{caret}()""" + +[] +let ``TypeProvider.XmlDocAttribute.Method.WithLongComment`` () = + assertTooltipContains + "This is a synthetic *method* created by me!!. Which is used to test the tool tip of the typeprovider Method to check if it shows the right message or not.!" + """let t = new N.T.M{caret}()""" + +[] +let ``TypeProvider.XmlDocAttribute.Method.WithNullComment`` () = + assertTooltipContains + "N.T.M() : int array" + """let t = new N.T.M{caret}()""" + +[] +let ``TypeProvider.XmlDocAttribute.Method.WithEmptyComment`` () = + assertTooltipContains + "N.T.M() : int array" + """let t = new N.T.M{caret}()""" + +[] +let ``TypeProvider.XmlDocAttribute.Property.Comment`` () = + assertTooltipContains + "This is a synthetic *property* created by me for N.T" + """let p = N.T.StaticProp{caret}""" + +[] +let ``TypeProvider.XmlDocAttribute.Property.LocalizedComment`` () = + assertTooltipContains + "This is a synthetic *property* Localized! ኤፍ ሻርፕ for N.T" + """let p = N.T.StaticProp{caret}""" + +[] +let ``TypeProvider.XmlDocAttribute.Property.WithLongComment`` () = + assertTooltipContains + "This is a synthetic *property* created by me for N.T. Which is used to test the tool tip of the typeprovider Property to check if it shows the right message or not.!" + """let p = N.T.StaticProp{caret}""" + +[] +let ``TypeProvider.XmlDocAttribute.Property.WithNullComment`` () = + assertTooltipContains + "property N.T.StaticProp: decimal" + """let p = N.T.StaticProp{caret}""" + +[] +let ``TypeProvider.XmlDocAttribute.Property.WithEmptyComment`` () = + assertTooltipContains + "property N.T.StaticProp: decimal" + """let p = N.T.StaticProp{caret}""" + +[] +let ``TypeProvider.StaticParameters.Correct`` () = + assertTooltipContains + "type foo = N1.T" + """type foo{caret} = N1.T< const "Hello World",2>""" + +[] +let ``TypeProvider.StaticParameters.Negative.Invalid`` () = + assertTooltipContains + "type foo" + """type foo{caret} = N1.T< const 100,2>""" + +[] +let ``TypeProvider.StaticParameters.XmlComment`` () = + assertTooltipContains + "XMLComment" + """///XMLComment +type foo{caret} = N1.T< const "Hello World",2>""" + +[] +let ``TypeProvider.StaticParameters.QuickInfo.OnTheErasedType`` () = + assertTooltipContains + "type TTT = Samples.FSharp.RegexTypeProvider.RegexTyped<...>\nFull name: File1.TTT" + """type TTT{caret} = Samples.FSharp.RegexTypeProvider.RegexTyped< @"(?^\d{3})-(?\d{3}-\d{7}$)">""" + +[] +let ``TypeProvider.StaticParameters.QuickInfo.OnNestedErasedTypeProperty`` () = + assertTooltipContains + "property Samples.FSharp.RegexTypeProvider.RegexTyped<...>.MatchType.AreaCode: System.Text.RegularExpressions.Group" + """type T = Samples.FSharp.RegexTypeProvider.RegexTyped< @"(?^\d{3})-(?\d{3}-\d{7}$)"> +let reg = T() +let r = reg.Match("425-123-2345").A{caret}reaCode.Value""" diff --git a/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Types.fs b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Types.fs new file mode 100644 index 00000000000..e875a276073 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/Tooltip/TooltipTests.Types.fs @@ -0,0 +1,464 @@ +module FSharp.Compiler.Service.Tests.TooltipTypesTests + +open System +open Xunit +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.EditorServices +open FSharp.Compiler.Symbols +open FSharp.Compiler.Tokenization + +[] +let ``NestedTypesOrder`` () = + assertTooltipContainsInOrder + [ "GetHashCode"; "GetObjectValue" ] + (markAtStartOfMarker "type t = System.Runtime.CompilerServices.RuntimeHelpers(*M*)" "(*M*)") + +[] +let ``QuickInfo.HideBaseClassMembersTP`` () = + assertTooltipContains + "type HiddenBaseMembersTP =\n inherit TPBaseTy" + (markAtStartOfMarker "type foo = HiddenMembersInBaseClass.HiddenBaseMembersTP(*Marker*)" "MembersTP(*Marker*)") + +[] +let ``QuickInfo.OverridenMethods`` () = + let source = + """ +type A() = + abstract member M: unit -> unit + /// 1234 + default this.M() = () + +type AA() = + inherit A() + /// 5678 + override this.M() = () +let x = new AA() +x.M() + +let y = new A() +y.M() +""" + + assertTooltipContains "5678" (markAtEndOfMarker source "x.M") + assertTooltipContains "1234" (markAtEndOfMarker source "y.M") + +[] +let ``QuickInfoForTypesWithHiddenRepresentation`` () = + let signatureListing = + "type Async =\n static member AsBeginEnd: computation: ('Arg -> Async<'T>) -> ('Arg * AsyncCallback * objnull -> IAsyncResult) * (IAsyncResult -> 'T) * (IAsyncResult -> unit)\n static member AwaitEvent: event: IEvent<'Del,'T> * ?cancelAction: (unit -> unit) -> Async<'T> (requires delegate and 'Del :> Delegate and 'Del: not null)\n static member AwaitIAsyncResult: iar: IAsyncResult * ?millisecondsTimeout: int -> Async\n static member AwaitTask: task: Task<'T> -> Async<'T> + 1 overload\n static member AwaitWaitHandle: waitHandle: WaitHandle * ?millisecondsTimeout: int -> Async\n static member CancelDefaultToken: unit -> unit\n static member Catch: computation: Async<'T> -> Async>\n static member Choice: computations: Async<'T option> seq -> Async<'T option>\n static member FromBeginEnd: beginAction: (AsyncCallback * objnull -> IAsyncResult) * endAction: (IAsyncResult -> 'T) * ?cancelAction: (unit -> unit) -> Async<'T> + 3 overloads\n static member FromContinuations: callback: (('T -> unit) * (exn -> unit) * (OperationCanceledException -> unit) -> unit) -> Async<'T>\n ..." + + assertTooltipContainsInOrder + [ signatureListing; "Full name: Microsoft.FSharp.Control.Async" ] + (markAtEndOfMarker "let x = Async.AsBeginEnd\n1" "Asyn") + +[] +let ``GetterSetterInsideInterfaceImpl.ThisOnceAsserted`` () = + assertTooltipContains + "Operators.id" + """ +type IFoo = + abstract member X: int with get,set + +type Bar = + interface IFoo with + member this.X + with get() = 42 // hello + and set(v) = id{caret}() """ + +[] +let ``Regression.FieldRepeatedInToolTip.Bug3538`` () = + assertIdentifierInTooltipExactlyOnce + "Explicit" + """ +open System.Runtime.InteropServices +[] +type A() = + [] + val mutable x : int""" + +[] +let ``Regression.MemberDefinition.DocComments.Bug5856_1`` () = + assertCompletionItemTooltipContainsInOrder + "Overload" + [ "static member MyType.Overload: unit -> int" + "static member MyType.Overload: x: int -> int" + "Hello" ] + """type MyType = + /// Hello + static member Overload() = 0 + /// Hello2 + static member Overload(x:int) = 0 + /// Hello3 + static member NonOverload() = 0 +let x() = MyType.{caret}""" + +[] +let ``Regression.Class.Printing.FSharp.Classes.Bug4624`` () = + let source = + """type F1() = + class + inherit System.Windows.Forms.Form() + abstract AAA : int with get + abstract ZZZ : int with get + abstract AAA : bool with set + val x : F1 + static val x : F1 + static member A() = 12 + member this.B() = 12 + static member C() = 12 + member this.D() = 12 + member this.D with get() = 12 and set(12) = () + member this.D(x:int,y:int) = 12 + member this.D(x:int) = 12 + member this.D x y z = [1;x;y;z] + override this.ToString() = "" + interface System.IDisposable with + override this.Dispose() = () + end + end +type A1 = F1""" + + assertTooltipContainsInOrder + [ "type F1 =" +#if !NETCOREAPP + " inherit Form" +#endif + " interface IDisposable" + " new: unit -> F1" + " val x: F1" + " member B: unit -> int" + " override ToString: unit -> string" + " static member A: unit -> int" + " static member C: unit -> int" + " abstract AAA: int" + " member D: int" + " ..." ] + (markAtEndOfMarker source "type A1 = F1") + +[] +let ``Automation.Regression.BeforeAndAfterIdentifier.Bug4371`` () = + let baseSrc = + """module Test +let f arg1 (arg2, arg3, arg4) arg5 = 42 +let goo a = f 12 a + +type printer = System.Console +let z = printer.BufferWidth""" + + let fSrc = baseSrc.Replace("let goo a = f 12 a", "let goo a = f{caret} 12 a") + assertTooltipContains "Full name: Test.f" fSrc + assertTooltipContains "val f" fSrc + + assertTooltipContains + "property System.Console.BufferWidth: int" + (baseSrc.Replace("let z = printer.BufferWidth", "let z = printer.BufferWidth{caret}")) + + assertTooltipContains + "Full name: Test.printer" + (baseSrc.Replace("let z = printer.BufferWidth", "let z = printer{caret}.BufferWidth")) + +[] +let ``Automation.Regression.ConstructorWithSameNameAsType.Bug2739`` () = + let source = + """namespace AA +module AA = + type AA = | AA(*Marker1*) = 1 + | BB = 2 +type BB = { BB(*Marker2*) : string; }""" + + assertTooltipContainsInFsFile "AA.AA: AA" (markAtStartOfMarker source "(*Marker1*)") + assertTooltipContainsInFsFile "BB.BB: string" (markAtStartOfMarker source "(*Marker2*)") + +[] +let ``Automation.Regression.EventImplementation.Bug5471`` () = + let source = + """namespace regressiontest +open System.ComponentModel + +type CommandReference() = + let evt = Event() + + interface INotifyPropertyChanged with + [] + member x.PropertyChanged(*Marker*) = evt.Publish""" + + let marked = markAtStartOfMarker source "(*Marker*)" + assertTooltipContainsInFsFile "override CommandReference.PropertyChanged: IEvent" marked + assertTooltipContainsInFsFile "regressiontest.CommandReference.PropertyChanged" marked + +[] +let ``Automation.ExtensionMethod`` () = + let source = + """namespace TestQuickinfo + +module BCLExtensions = + type System.Random with + /// BCL class Extension method + member this.NextDice() = this.Next() + 1 + /// new BCL class Extension method with overload + member this.NextDice(a : bool) = this.Next() + 1 + /// existing BCL class Extension method with overload + member this.Next(a : bool) = this.Next() + 1 + /// BCL class Extension property + member this.DiceValue with get() = 6 + + type System.ConsoleKeyInfo with + /// BCL struct extension method + member this.ExtensionMethod() = 100 + /// BCL struct extension property + member this.ExtensionProperty with get() = "Foo" + +module OwnCode = + /// fs class + type FSClass() = + class + /// fs class method original + member this.Method(a:string) = "" + /// fs class property original + member this.Prop with get(a:string) = "" + end + + /// fs struct + type FSStruct(x:int) = + struct + end + +module OwnCodeExtensions = + type OwnCode.FSClass with + /// fs class extension method + member this.ExtensionMethod() = 100 + /// fs class extension property + member this.ExtensionProperty with get() = "Foo" + /// fs class method extension overload + member this.Method(a:int) = "" + /// fs class property extension overload + member this.Prop with get(a:int) = "" + + type OwnCode.FSStruct with + /// fs struct extension method + member this.ExtensionMethod() = 100 + /// fs struct extension property + member this.ExtensionProperty with get() = "Foo" + +module BCLClass = + open BCLExtensions + let rnd = new System.Random() + rnd.DiceValue(*Marker11*) |>ignore + rnd.NextDice(*Marker12*)() |>ignore + rnd.NextDice(*Marker13*)(true) |>ignore + rnd.Next(*Marker14*)(true) |>ignore + +module BCLStruct = + open BCLExtensions + let cki = new System.ConsoleKeyInfo() + cki.ExtensionMethod(*Marker21*) |>ignore + cki.ExtensionProperty(*Marker22*) |>ignore + +module OwnClass = + open OwnCode + open OwnCodeExtensions + let rnd = new FSClass() + rnd.ExtensionMethod(*Marker31*) |>ignore + rnd.ExtensionProperty(*Marker32*) |>ignore + rnd.Method(*Marker33*)("") |>ignore + rnd.Method(*Marker34*)(6) |>ignore + rnd.Prop(*Marker35*)("") |>ignore + rnd.Prop(*Marker36*)(6) |>ignore + +module OwnStruct = + open OwnCode + open OwnCodeExtensions + let cki = new FSStruct(100) + cki.ExtensionMethod(*Marker41*) |>ignore + cki.ExtensionProperty(*Marker42*) |>ignore""" + + let assertAt marker sig' doc = + let marked = markAtStartOfMarker source marker + assertTooltipContainsInFsFile sig' marked + assertTooltipContainsInFsFile doc marked + + assertAt "(*Marker11*)" "property System.Random.DiceValue: int" "BCL class Extension property" + assertAt "(*Marker12*)" "member System.Random.NextDice: unit -> int" "BCL class Extension method" + assertAt "(*Marker13*)" "member System.Random.NextDice: a: bool -> int" "new BCL class Extension method with overload" + assertAt "(*Marker14*)" "member System.Random.Next: a: bool -> int" "existing BCL class Extension method with overload" + assertAt "(*Marker21*)" "member System.ConsoleKeyInfo.ExtensionMethod: unit -> int" "BCL struct extension method" + assertAt "(*Marker22*)" "System.ConsoleKeyInfo.ExtensionProperty: string" "BCL struct extension property" + assertAt "(*Marker31*)" "member FSClass.ExtensionMethod: unit -> int" "fs class extension method" + assertAt "(*Marker32*)" "FSClass.ExtensionProperty: string" "fs class extension property" + assertAt "(*Marker33*)" "member FSClass.Method: a: string -> string" "fs class method original" + assertAt "(*Marker34*)" "member FSClass.Method: a: int -> string" "fs class method extension overload" + assertAt "(*Marker35*)" "property FSClass.Prop: string -> string" "fs class property original" + assertAt "(*Marker36*)" "property FSClass.Prop: int -> string" "fs class property extension overload" + assertAt "(*Marker41*)" "member FSStruct.ExtensionMethod: unit -> int" "fs struct extension method" + assertAt "(*Marker42*)" "FSStruct.ExtensionProperty: string" "fs struct extension property" + +[] +let ``Automation.Regression.GenericFunction.Bug2868`` () = + let marked = + markAtStartOfMarker + """module Test +let F (f :_ -> float<_>) = fun x -> f (x+1.0) +let rec Gen<[] 'u> (f:float<'u> -> float<'u>) = + Gen(*Marker*)(F f)""" + "(*Marker*)" + + assertTooltipContains "val Gen: f: (float -> float) -> 'a" marked + assertTooltipDoesNotContain "Exception" marked + assertTooltipDoesNotContain "thrown" marked + +[] +let ``Automation.Regression.NamesArgument.Bug3818`` () = + assertTooltipContains + "property System.AttributeUsageAttribute.AllowMultiple: bool" + (markAtStartOfMarker + """module m +[] +type T = class + end""" + "(*Marker1*)") + +[] +let ``Automation.OnUnitsOfMeasure`` () = + let source = + """namespace TestQuickinfo + +module TestCase1 = + [] + /// this type represents kilogram in UOM + type kg + let mass(*Marker11*) = 2.0 + +module TestCase2 = + [] + /// use Set as the type name of UoM + type Set + + let v1 = [1.0 .. 2.0 .. 5.0] |> Seq.item 1 + + (if v1 = 3.0 then 0 else 1) |> ignore + + let twoSets = 2.0 + + [1.0] + |> Set.ofList + |> Set(*Marker22*).isEmpty + |> ignore""" + + assertTooltipContainsInFsFile "val mass: float" (markAtStartOfMarker source "(*Marker11*)") + assertTooltipContainsInFsFile "Full name: TestQuickinfo.TestCase1.mass" (markAtStartOfMarker source "(*Marker11*)") + assertTooltipContainsInFsFile "inherits: System.ValueType" (markAtStartOfMarker source "(*Marker11*)") + assertTooltipContainsInFsFile "[]" (markAtStartOfMarker source "(*Marker12*)") + assertTooltipContainsInFsFile "type kg" (markAtStartOfMarker source "(*Marker12*)") + assertTooltipContainsInFsFile "this type represents kilogram in UOM" (markAtStartOfMarker source "(*Marker12*)") + assertTooltipContainsInFsFile "Full name: TestQuickinfo.TestCase1.kg" (markAtStartOfMarker source "(*Marker12*)") + assertTooltipContainsInFsFile "[]" (markAtStartOfMarker source "(*Marker21*)") + assertTooltipContainsInFsFile "type Set" (markAtStartOfMarker source "(*Marker21*)") + assertTooltipContainsInFsFile "use Set as the type name of UoM" (markAtStartOfMarker source "(*Marker21*)") + assertTooltipContainsInFsFile "Full name: TestQuickinfo.TestCase2.Set" (markAtStartOfMarker source "(*Marker21*)") + assertTooltipContainsInFsFile "module Set" (markAtStartOfMarker source "(*Marker22*)") + assertTooltipContainsInFsFile "from Microsoft.FSharp.Collections" (markAtStartOfMarker source "(*Marker22*)") + assertTooltipContainsInFsFile "Functional programming operators related to the Set<_> type." (markAtStartOfMarker source "(*Marker22*)") + +[] +let ``Automation.Setter`` () = + let source = + """type T() = + member this.XX + with set ((a:int), (b:int), (c:int)) = () + +(new T()).XX(*Marker1*) <- (1,2,3) + +type IFoo = interface + abstract foo : int -> int + end +let i : IFoo = Unchecked.defaultof +i.foo(*Marker2*) |> ignore + +type Rec = { bar:int->int->int } +let r = {bar = fun x y -> x + y } + +r.bar(*Marker3*) 1 2 |>ignore + +type M() = + member this.baz x y = x + y +let m = new M() +m.baz(*Marker3*) 1 2 |>ignore + +type T2() = + member this.Foo(a,b) = "" +let t = new T2() +t.Foo(*Marker4*)(1,2) |>ignore + +let foo (x:int) (y:int) : int = 1 +foo(*Marker5*) 2 3 |> ignore""" + + assertTooltipContains "T.XX: int * int * int" (markAtStartOfMarker source "(*Marker1*)") + assertTooltipDoesNotContain "->" (markAtStartOfMarker source "(*Marker1*)") + assertTooltipContains "IFoo.foo: int -> int" (markAtStartOfMarker source "(*Marker2*)") + assertTooltipContains "Rec.bar: int -> int -> int" (markAtStartOfMarker source "(*Marker3*)") + assertTooltipContains "T2.Foo: a: 'a * b: 'b -> string" (markAtStartOfMarker source "(*Marker4*)") + assertTooltipContains "val foo: int -> int -> int" (markAtStartOfMarker source "(*Marker5*)") + +[] +let ``Automation.Regression.TypeInferenceScenarios.Bug2362_3538`` () = + let source = + """module Test.Module1 + +open System +open System.Diagnostics +open System.Runtime.InteropServices + +#nowarn "9" + +let append m(*Marker1*) n(*Marker2*) = fun ac(*Marker3*) -> m (n ac) + +type Foo() as this(*Marker4*) = + do this(*Marker5*) |> ignore + member this.Bar() = + this(*Marker6*) |> ignore + () + +[] +type A = + [] + val mutable x : int + new () = { } + member this.Prop = this.x + +let x = new (*Marker7*)A()""" + + assertTooltipContains "val m: ('a -> 'b)" (markAtStartOfMarker source "(*Marker1*)") + assertTooltipContains "val n: ('c -> 'a)" (markAtStartOfMarker source "(*Marker2*)") + assertTooltipContains "val ac: 'c" (markAtStartOfMarker source "(*Marker3*)") + assertTooltipContains "val this: Foo" (markAtStartOfMarker source "(*Marker4*)") + assertTooltipContains "val this: Foo" (markAtStartOfMarker source "(*Marker5*)") + assertTooltipContains "val this: Foo" (markAtStartOfMarker source "(*Marker6*)") + + let mSrc7 = source.Replace("new (*Marker7*)A()", "new A{caret}()") + assertTooltipContains "type A =" mSrc7 + assertTooltipContains "val mutable x: int" mSrc7 + +[] +let ``Automation.Regression.XmlDocCommentsOnExtensionMembers.Bug138112`` () = + let source = + """module Module1 = + type T() = + /// XmlComment M1 + member this.M1() = () + type T with + /// XmlComment M2 + member this.M2() = () + module public Extension = + type T with + /// XmlComment M3 + member this.M3() = () +open Module1 +open Extension + +let x1 = T().M1(*Marker1*)() +let x2 = T().M2(*Marker2*)() +let x3 = T().M3(*Marker3*)()""" + + assertTooltipContains "XmlComment M1" (markAtStartOfMarker source "(*Marker1*)") + assertTooltipContains "XmlComment M2" (markAtStartOfMarker source "(*Marker2*)") + assertTooltipContains "XmlComment M3" (markAtStartOfMarker source "(*Marker3*)") diff --git a/tests/FSharp.Compiler.Service.Tests/TooltipTests.fs b/tests/FSharp.Compiler.Service.Tests/TooltipTests.fs index 5bee4573952..5c53e7879ee 100644 --- a/tests/FSharp.Compiler.Service.Tests/TooltipTests.fs +++ b/tests/FSharp.Compiler.Service.Tests/TooltipTests.fs @@ -370,21 +370,6 @@ let getCheckResults source options = checkResults -let taggedTextsToString (t: TaggedText array) = - t - |> Array.map (fun taggedText -> taggedText.Text) - |> String.concat "" - -let assertAndExtractTooltip (ToolTipText(items)) = - Assert.Equal(1,items.Length) - match items[0] with - | ToolTipElement.Group [ singleElement ] -> - let toolTipText = - singleElement.MainDescription - |> taggedTextsToString - toolTipText, singleElement.XmlDoc, singleElement.Remarks |> Option.map taggedTextsToString - | _ -> failwith $"Expected group, got {items[0]}" - let assertAndGetSingleToolTipText items = let text,_xml,_remarks = assertAndExtractTooltip items text diff --git a/tests/FSharp.Compiler.Service.Tests/TypeChecker/Obsolete.fs b/tests/FSharp.Compiler.Service.Tests/TypeChecker/Obsolete.fs index 22393f98607..dff8364704f 100644 --- a/tests/FSharp.Compiler.Service.Tests/TypeChecker/Obsolete.fs +++ b/tests/FSharp.Compiler.Service.Tests/TypeChecker/Obsolete.fs @@ -1,7 +1,6 @@ module FSharp.Compiler.Service.Tests.TypeChecker.Obsolete open FSharp.Compiler.Service.Tests -open FSharp.Compiler.Symbols open FSharp.Test.Assert open Xunit diff --git a/tests/FSharp.Compiler.Service.Tests/TypeChecker/TypeCheckerRecoveryTests.fs b/tests/FSharp.Compiler.Service.Tests/TypeChecker/TypeCheckerRecoveryTests.fs index 343009b8db4..03658cd74e6 100644 --- a/tests/FSharp.Compiler.Service.Tests/TypeChecker/TypeCheckerRecoveryTests.fs +++ b/tests/FSharp.Compiler.Service.Tests/TypeChecker/TypeCheckerRecoveryTests.fs @@ -1,7 +1,10 @@ -module FSharp.Compiler.Service.Tests.TypeChecker.TypeCheckerRecoveryTests +module FSharp.Compiler.Service.Tests.TypeChecker.TypeCheckerRecoveryTests open FSharp.Compiler.Service.Tests +open FSharp.Compiler.Symbols open FSharp.Compiler.Text +open FSharp.Compiler.Service.Tests.CompletionTests +open FSharp.Compiler.Service.Tests.TooltipTests open FSharp.Test.Assert open Xunit @@ -27,7 +30,6 @@ do "(3,12--3,13)", 39 ] - [] let ``Tuple 01`` () = let _, checkResults = getParseAndCheckResults """ @@ -44,7 +46,6 @@ Math.Max(a,) assertHasSymbolUsages ["Max"] checkResults - [] let ``Tuple 02`` () = let _, checkResults = getParseAndCheckResults """ @@ -83,112 +84,300 @@ T.M{caret} "" """ module Expressions = + [] + [] + [] + [] + [] + let ``Method type`` (name: string) (source: string) = + assertHasSymbolUsageAtCaret name source + +module Patterns = + [] + [ () + """)>] + [ () + """)>] + [] + [] + [ () + """)>] + [] + [] + let ``Enum - Type`` (source: string) = + assertHasSymbolUsageAtCaret "E" source + +module ErrorRecovery = + + [] + [] + [] + [] + [] + let ``Bug4881 - member completion after dot in elif on broken code`` (source: string) = + let info = Checker.getCompletionInfo source + assertHasItemWithNames ["Split"] info + [] - let ``Method type 01`` () = - assertHasSymbolUsageAtCaret "ToString" """ -if true then - "".ToString{caret} + let ``NotFixing4538_1 - completion offers type after partial 'new MyT'`` () = + let info = Checker.getCompletionInfo """ +type MyType() = + override x.ToString() = "" +let Main() = + let _ = new MyT{caret} + () """ - + assertHasItemWithNames ["MyType"] info + + [] + [] + [] + let ``NotFixing4538_2_3 - completion offers type after partial 'MyT'`` (source: string) = + let info = Checker.getCompletionInfo source + assertHasItemWithNames ["MyType"] info [] - let ``Method type 02`` () = - assertHasSymbolUsageAtCaret "M" """ -type T = - static member M() = "" - -if true then - T.M{caret} + let ``Bug4538_2 - completion offers type after a preceding valid binding`` () = + let info = Checker.getCompletionInfo """ +type MyType() = + override x.ToString() = "" +let Main() = + let x = MyType() + let _ = MyT{caret} """ + assertHasItemWithNames ["MyType"] info [] - let ``Method type 03`` () = - assertHasSymbolUsageAtCaret "M" """ -type T = - static member M(i: int) = "" - static member M(s: string) = "" - -if true then - T.M{caret} + let ``Bug4538_5 - completion offers type after partial 'MyT' in use binding`` () = + let info = Checker.getCompletionInfo """ +type MyType() = + override x.ToString() = "" +let Main() = + use x = null + use _ = MyT{caret} """ + assertHasItemWithNames ["MyType"] info [] - let ``Method type 04`` () = - assertHasSymbolUsageAtCaret "GetHashCode" """ -let o: obj = null -if true then - o.GetHashCode{caret} + let ``5878_1 - member data tip available for Module dot at end of file`` () = + let info = Checker.getCompletionInfo """ +module Module = + /// Union comment + type Union = + /// Case comment + | Case of int +Module.{caret} """ + let caseItem = + info.Items + |> Array.find (fun item -> item.NameInCode = "Case") -module Patterns = - [] - let ``Enum - Type 01`` () = - assertHasSymbolUsageAtCaret "E" """ -type E = - | A = 1 + let description, xmlDoc, _ = assertAndExtractTooltip caseItem.Description -match E.A with -| E{caret}.A -> () -""" + Assert.Contains("union case Module.Union.Case: int -> Module.Union", description) - [] - let ``Enum - Type 02`` () = - assertHasSymbolUsageAtCaret "E" """ -type E = - | A = 1 + match xmlDoc with + | FSharpXmlDoc.FromXmlText t -> + Assert.Contains("Case comment", String.concat "\n" t.UnprocessedLines) + | other -> failwith $"Expected FSharpXmlDoc.FromXmlText, got {other}" -match E.A with -| E{caret} -> () -""" +module ExhaustivelyScrutinize = [] - let ``Enum - Type 03`` () = - assertHasSymbolUsageAtCaret "E" """ -type E = - | A = 1 - -match E.A with -| E{caret} + let ``ThisOnceAsserted - if/elif/else returning malformed tuples`` () = + let _, checkResults = getParseAndCheckResults """ +let F() = + if true then [], + elif true then [],"" + else [],"" """ + dumpDiagnosticNumbers checkResults |> shouldEqual [ + "(4,4--4,8)", 58 + "(3,19--3,20)", 3100 + ] [] - let ``Enum - Type 04`` () = - assertHasSymbolUsageAtCaret "E" """ -type E = - | A = 1 - -match E.A with -| E{caret}. + let ``ThisOnceAssertedToo - interface implementation`` () = + let _, checkResults = getParseAndCheckResults """ +type C() = + member this.F() = () + interface System.IComparable with + member _.CompareTo(v:obj) = 1 """ - - [] - let ``Enum - Type 05`` () = - assertHasSymbolUsageAtCaret "E" """ -type E = - | A = 1 + dumpDiagnosticNumbers checkResults |> shouldEqual [ + "(2,5--2,6)", 343 + ] -match E.A with -| E{caret}. -> () + [] + let ``ThisOnceAssertedThree - property with get and set`` () = + let _, checkResults = getParseAndCheckResults """ +type Foo = + { mutable Data: string } + member x.XmlDocSig + with get() = x.Data + and set(v) = x.Data <- v """ + dumpDiagnosticNumbers checkResults |> shouldEqual [] - [] - let ``Enum - Type 06`` () = - assertHasSymbolUsageAtCaret "E" """ -type E = - | A = 1 - -match E.A with -| E{caret}.B + [] + let ``ThisOnceAssertedFour - unfinished new`` () = + let _, checkResults = getParseAndCheckResults """ +let y=new +let z=4 """ + dumpDiagnosticNumbers checkResults |> shouldEqual [ + "(3,0--3,3)", 10 + ] [] - let ``Enum - Type 07`` () = - assertHasSymbolUsageAtCaret "E" """ -type E = - | A = 1 + let ``ThisOnceAssertedFive - type application with quotation token`` () = + let _, checkResults = getParseAndCheckResults """ +CSV.File<@"File1.txt">.[0]. +""" + dumpDiagnosticNumbers checkResults |> shouldEqual [ + "(2,10--2,21)", 10 + "(2,10--2,21)", 1241 + "(2,21--2,22)", 3156 + "(2,0--2,3)", 39 + ] -match E.A with -| E{caret}. + [] + let ``Bug2277 - open of non-existent namespace`` () = + let _, checkResults = getParseAndCheckResults """ +open Microsoft.FSharp.Plot.Excel +open Microsoft.FSharp.Plot.Interactive +let ps = [| (1.,"c"); (-2.,"p") |] +plot (Bars(ps)) +let xs = [| 1.0 .. 20.0 |] +let ys = [| 2.0 .. 21.0 |] +let pp= plot(Area(xs,ys)) +""" + dumpDiagnosticNumbers checkResults |> shouldEqual [ + "(2,22--2,26)", 39 + "(3,22--3,26)", 39 + "(5,0--5,4)", 39 + "(8,8--8,12)", 39 + ] -() + [] + let ``Bug2283 - missing reference and nested generic classes`` () = + let _, checkResults = getParseAndCheckResultsUniqueName """ +#r "NestedClasses.dll" +//753 atomType -> atomType DOT path typeArgs +let specificIdent (x : RootNamespace.ClassOfT.NestedClassOfU) = x +let x = new RootNamespace.ClassOfT.NestedClassOfU() +if specificIdent x <> x then exit 1 +exit 0 """ +#if NETCOREAPP + dumpDiagnosticNumbers checkResults |> shouldEqual [ + "(4,23--4,36)", 39 + "(5,12--5,25)", 39 + ] +#else + dumpDiagnosticNumbers checkResults + |> List.distinct + |> List.sort + |> shouldEqual [ + "(2,0--2,22)", 84 + "(4,23--4,36)", 39 + "(5,12--5,25)", 39 + ] +#endif diff --git a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.Completion.fs b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.Completion.fs index b2edb2a68c7..c36379acdb4 100644 --- a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.Completion.fs +++ b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.Completion.fs @@ -268,1043 +268,58 @@ type UsingMSBuild() as this = let completions = DotCompletionAtStartOfMarker file marker AssertCompListIsEmpty(completions) - [] - member this.``AutoCompletion.ObjectMethods``() = - let code = - [ - "type DU1 = DU_1" - - "[]" - "type DU2 = DU_2" - - "[]" - "type DU3 =" - " | DU_3" - " with member this.Equals(b : string) = 1" - - "[]" - "type DU4 =" - " | DU_4" - " with member this.GetHashCode(b : string) = 1" - - - "module Extensions =" - " type System.Object with" - " member this.ExtensionPropObj = 42" - " member this.ExtensionMethodObj () = 42" - - "open Extensions" - ] - let (_, _, file) = this.CreateSingleFileProject(code) - let test tail marker expected notExpected = - let code = code @ [tail] - ReplaceFileInMemory file code - MoveCursorToEndOfMarker(file,marker) - - let completions = AutoCompleteAtCursor file - AssertCompListContainsAll(completions, expected) - AssertCompListDoesNotContainAny(completions, notExpected) - - test "obj()." ")." ["Equals"; "ExtensionPropObj"; "ExtensionMethodObj"] [] - test "System.Object." "Object." ["Equals"; "ReferenceEquals"] [] - test "System.String." "String." ["Equals"] [] - test "DU_1." "DU_1." ["Equals"; "GetHashCode"; "ExtensionMethodObj"; "ExtensionPropObj"] [] - test "DU_2." "DU_2." ["ExtensionPropObj"; "ExtensionMethodObj"] ["Equals"; "GetHashCode"] // no equals\gethashcode - test "DU_3." "DU_3." ["ExtensionPropObj"; "ExtensionMethodObj"; "Equals"] ["GetHashCode"] // no gethashcode, has equals defined in DU3 type - test "DU_4." "DU_4." ["ExtensionPropObj"; "ExtensionMethodObj"; "GetHashCode"] ["Equals"] // no equals, has gethashcode defined in DU4 type - [] - member this.``AutoCompletion.BeforeThis``() = - let code = - [ - [ - "type A() =" - " member _.X = ()" - " member this." - ] - [ - "type A() =" - " member _.X = ()" - " member private this." - ] - [ - "type A() =" - " member _.X = ()" - " member public this." - ] - [ - "type A() =" - " member _.X = ()" - " member internal this." - ] - - ] - - for c in code do - AssertCtrlSpaceCompletionListIsEmpty c "this." - AssertAutoCompleteCompletionListIsEmpty c "this." - AssertCtrlSpaceCompletionListIsEmptyNoCoffeeBreak c "this." - AssertAutoCompleteCompletionListIsEmptyNoCoffeeBreak c "this." - [] - member this.``TypeProvider.VisibilityChecksForGeneratedTypes``() = - let extraRefs = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")] - let check = DoWithAutoCompleteUsingExtraRefs extraRefs None true SourceFileKind.FS BackgroundRequestReason.MemberSelect - - let code = - [ - "type T = GeneratedType.SampleType" - - "let t = T(5)" - "t." - - "T." - - - "type T1() = " - " inherit T(5)" - " member this.Foo() = this." - ] - check code "T." <| - fun ci -> - AssertCompListContains(ci, "PublicField") - - check code "t." <| - fun ci -> - AssertCompListContainsAll(ci, ["PublicM"; "PublicProp"]) - AssertCompListDoesNotContainAny(ci, ["f"; "ProtectedProp"; "PrivateProp"; "ProtectedM"; "PrivateM"]) - - check code "= this." <| - fun ci -> - AssertCompListContainsAll(ci, ["PublicM"; "PublicProp"]) - // The F# compiler never even asks to see protected/private provided members - AssertCompListDoesNotContainAny(ci, ["f"; "ProtectedProp"; "ProtectedM"; "PrivateProp"; "PrivateM"]) - [] member public this.``AdjacentToDot_01``() = testAutoCompleteAdjacentToDot ".." - [] member public this.``AdjacentToDot_02``() = testAutoCompleteAdjacentToDot ".<" - [] member public this.``AdjacentToDot_03``() = testAutoCompleteAdjacentToDot ".>" - [] member public this.``AdjacentToDot_04``() = testAutoCompleteAdjacentToDot ".=" - [] member public this.``AdjacentToDot_05``() = testAutoCompleteAdjacentToDot ".!=" - [] member public this.``AdjacentToDot_06``() = testAutoCompleteAdjacentToDot ".$" - [] member public this.``AdjacentToDot_07``() = testAutoCompleteAdjacentToDot ".[]" - [] member public this.``AdjacentToDot_08``() = testAutoCompleteAdjacentToDot ".[]<-" - [] member public this.``AdjacentToDot_09``() = testAutoCompleteAdjacentToDot ".[,]<-" - [] member public this.``AdjacentToDot_10``() = testAutoCompleteAdjacentToDot ".[,,]<-" - [] member public this.``AdjacentToDot_11``() = testAutoCompleteAdjacentToDot ".[,,,]<-" - [] member public this.``AdjacentToDot_12``() = testAutoCompleteAdjacentToDot ".[,,,]" - [] member public this.``AdjacentToDot_13``() = testAutoCompleteAdjacentToDot ".[,,]" - [] member public this.``AdjacentToDot_14``() = testAutoCompleteAdjacentToDot ".[,]" - [] member public this.``AdjacentToDot_15``() = testAutoCompleteAdjacentToDot ".[..]" - [] member public this.``AdjacentToDot_16``() = testAutoCompleteAdjacentToDot ".[..,..]" - [] member public this.``AdjacentToDot_17``() = testAutoCompleteAdjacentToDot ".[..,..,..]" - [] member public this.``AdjacentToDot_18``() = testAutoCompleteAdjacentToDot ".[..,..,..,..]" - [] member public this.``AdjacentToDot_19``() = testAutoCompleteAdjacentToDot ".()" - [] member public this.``AdjacentToDot_20``() = testAutoCompleteAdjacentToDot ".()<-" - [] member public this.``AdjacentToDot_02_Negative``() = testAutoCompleteAdjacentToDotNegative ".<" - [] member public this.``AdjacentToDot_03_Negative``() = testAutoCompleteAdjacentToDotNegative ".>" - [] member public this.``AdjacentToDot_04_Negative``() = testAutoCompleteAdjacentToDotNegative ".=" - [] member public this.``AdjacentToDot_05_Negative``() = testAutoCompleteAdjacentToDotNegative ".!=" - [] member public this.``AdjacentToDot_06_Negative``() = testAutoCompleteAdjacentToDotNegative ".$" - [] member public this.``AdjacentToDot_07_Negative``() = testAutoCompleteAdjacentToDotNegative ".[]" - [] member public this.``AdjacentToDot_08_Negative``() = testAutoCompleteAdjacentToDotNegative ".[]<-" - [] member public this.``AdjacentToDot_09_Negative``() = testAutoCompleteAdjacentToDotNegative ".[,]<-" - [] member public this.``AdjacentToDot_10_Negative``() = testAutoCompleteAdjacentToDotNegative ".[,,]<-" - [] member public this.``AdjacentToDot_11_Negative``() = testAutoCompleteAdjacentToDotNegative ".[,,,]<-" - [] member public this.``AdjacentToDot_12_Negative``() = testAutoCompleteAdjacentToDotNegative ".[,,,]" - [] member public this.``AdjacentToDot_13_Negative``() = testAutoCompleteAdjacentToDotNegative ".[,,]" - [] member public this.``AdjacentToDot_14_Negative``() = testAutoCompleteAdjacentToDotNegative ".[,]" - [] member public this.``AdjacentToDot_15_Negative``() = testAutoCompleteAdjacentToDotNegative ".[..]" - [] member public this.``AdjacentToDot_16_Negative``() = testAutoCompleteAdjacentToDotNegative ".[..,..]" - [] member public this.``AdjacentToDot_17_Negative``() = testAutoCompleteAdjacentToDotNegative ".[..,..,..]" - [] member public this.``AdjacentToDot_18_Negative``() = testAutoCompleteAdjacentToDotNegative ".[..,..,..,..]" - [] member public this.``AdjacentToDot_19_Negative``() = testAutoCompleteAdjacentToDotNegative ".()" - [] member public this.``AdjacentToDot_20_Negative``() = testAutoCompleteAdjacentToDotNegative ".()<-" - [] member public this.``AdjacentToDot_21_Negative``() = testAutoCompleteAdjacentToDotNegative ".+." - - [] - member public this.``LambdaOverloads.Completion``() = - let prologue = "open System.Linq" - let cases = - [ - "[\"\"].Sum(fun x -> (*$*)x.Len )" - "[\"\"].Select(fun x -> (*$*)x.Len )" - "[\"\"].Select(fun x i -> (*$*)x.Len )" - "[\"\"].GroupBy(fun x -> (*$*)x.Len )" - "[\"\"].Join([\"\"], (fun x -> (*$*)x.Len), (fun x -> x.Len), (fun x y -> x.Len+ y.Len))" - "[\"\"].Join([\"\"], (fun x -> x.Len), (fun x -> (*$*)x.Len), (fun x y -> x.Len+ y.Len))" - "[\"\"].Join([\"\"], (fun x -> x.Len), (fun x -> x.Len), (fun x y -> (*$*)x.Len + y.Len))" - "[\"\"].Join([\"\"], (fun x -> x.Len), (fun x -> x.Len), (fun y x -> y.Len + (*$*)x.Len))" - "[\"\"].Where(fun x -> (*$*)x.Len )" - "[\"\"].Where(fun x -> (*$*)x.Len % 3 )" - "[\"\"].Where(fun x -> (*$*)x.Len % 3 = 0)" - "[\"\"].AsQueryable().Select(fun x -> (*$*)x.Len )" - "[\"\"].AsQueryable().Select(fun x i -> (*$*)x.Len )" - "[\"\"].AsQueryable().Where(fun x -> (*$*)x.Len )" - ] - - for case in cases do - let code = [prologue; case] - AssertCtrlSpaceCompleteContains code "(*$*)x.Len" ["Length"] [] - - [] - member public this.``Query.CompletionInJoinOn``() = - let code = - [ - "query {" - " for a in [1] do" - " join b in [2] on (a.)" - " select (a + b)" - "}" - ] - AssertCtrlSpaceCompleteContains code "(a." ["GetHashCode"; "CompareTo"] [] - - - - [] - member public this.``TupledArgsInLambda.Completion.Bug312557_1``() = - let code = - [ - "[(1,2);(1,2);(1,2)]" - "|> Seq.iter (fun (xxx,yyy) -> printfn \"%d\" (*MARKER*)" - " printfn \"%d\" 1)" - ] - AssertCtrlSpaceCompleteContains code "(*MARKER*)" ["xxx"; "yyy"] [] - [] - member public this.``TupledArgsInLambda.Completion.Bug312557_2``() = - let code = - [ - "(1,2) |> (fun (aaa,bbb) ->" - " printfn \"hi\"" - " printfn \"%d%d\" b a" - " printfn \"%d%d\" a b ) " - ] - AssertCtrlSpaceCompleteContains code "\" b" ["aaa"; "bbb"] [] - AssertCtrlSpaceCompleteContains code "\" a" ["aaa"; "bbb"] [] - AssertCtrlSpaceCompleteContains code "b a" ["aaa"; "bbb"] [] - AssertCtrlSpaceCompleteContains code "a b" ["aaa"; "bbb"] [] - [] - member this.``AutoCompletion.OnTypeConstraintError``() = - let code = - [ - "type Foo = Foo" - " with" - " member _.Bar = 1" - " member _.PublicMethodForIntellisense() = 2" - " member internal _.InternalMethod() = 3" - " member private _.PrivateProperty = 4" - "" - "let u: Unit =" - " [ Foo ]" - " |> List.map (fun abcd -> abcd.)" - ] - AssertCtrlSpaceCompleteContains code "abcd." ["Bar"; "Equals"; "GetHashCode"; "GetType"; "InternalMethod"; "PublicMethodForIntellisense"; "ToString"] [] - [] - member public this.``RangeOperator.IncorrectUsage``() = - AssertCtrlSpaceCompletionListIsEmpty [".."] ".." - AssertCtrlSpaceCompletionListIsEmpty ["..."] "..." - [] - member public this.``Inherit.CompletionInConstructorArguments1``() = - let code = - [ - "type A(a : int) = class end" - "type B() = inherit A(a)" - ] - AssertCtrlSpaceCompleteContains code "inherit A(a" ["abs"] [] - [] - member public this.``Inherit.CompletionInConstructorArguments2``() = - let code = - [ - "type A(a : int) = class end" - "type B() = inherit A(System.String.)" - ] - AssertCtrlSpaceCompleteContains code "System.String." ["Empty"] ["Array"; "Collections"] - [] - member public this.``ObjectInitializer.CompletionForProperties``() = - let typeDef1 = - [ - "type A() = " - " member val SettableProperty = 1 with get,set" - " member val AnotherSettableProperty = 1 with get,set" - " member val NonSettableProperty = 1" - ] - AssertCtrlSpaceCompleteContains (typeDef1 @ ["A((**))"]) "A((**)" ["SettableProperty"; "AnotherSettableProperty"] ["NonSettableProperty"] - AssertCtrlSpaceCompleteContains (typeDef1 @ ["A(S = 1)"]) "A(S" ["SettableProperty"] ["NonSettableProperty"] - AssertCtrlSpaceCompleteContains (typeDef1 @ ["A(S = 1)"]) "A(S = 1" [] ["SettableProperty"; "NonSettableProperty"] // neg test - AssertCtrlSpaceCompleteContains (typeDef1 @ ["A(S = 1,)"]) "A(S = 1," ["AnotherSettableProperty"] ["NonSettableProperty"] - AssertCtrlSpaceCompleteContains (typeDef1 @ ["new A((**))"]) "A((**)" ["SettableProperty"; "AnotherSettableProperty"] ["NonSettableProperty"] - AssertCtrlSpaceCompleteContains (typeDef1 @ ["new A(S = 1)"]) "A(S" ["SettableProperty"] ["NonSettableProperty"] - AssertCtrlSpaceCompleteContains (typeDef1 @ ["new A(S = 1)"]) "A(S = 1" [] ["SettableProperty"; "NonSettableProperty"] // neg test - AssertCtrlSpaceCompleteContains (typeDef1 @ ["new A(S = 1,)"]) "A(S = 1," ["AnotherSettableProperty"] ["NonSettableProperty"] - - let typeDef2 = - [ - "type A<'a>() = " - " member val SettableProperty = 1 with get,set" - " member val AnotherSettableProperty = 1 with get,set" - " member val NonSettableProperty = 1" - ] - AssertCtrlSpaceCompleteContains (typeDef2 @ ["A((**))"]) "A((**)" ["SettableProperty"; "AnotherSettableProperty"] ["NonSettableProperty"] - AssertCtrlSpaceCompleteContains (typeDef2 @ ["A(S = 1)"]) "A(S" ["SettableProperty"] ["NonSettableProperty"] - AssertCtrlSpaceCompleteContains (typeDef2 @ ["A(S = 1)"]) "A(S = 1" [] ["SettableProperty"; "NonSettableProperty"] // neg test - AssertCtrlSpaceCompleteContains (typeDef2 @ ["A(S = 1,)"]) "A(S = 1," ["AnotherSettableProperty"] ["NonSettableProperty"] - AssertCtrlSpaceCompleteContains (typeDef2 @ ["new A<_>((**))"]) "A<_>((**)" ["SettableProperty"; "AnotherSettableProperty"] ["NonSettableProperty"] - AssertCtrlSpaceCompleteContains (typeDef2 @ ["new A<_>(S = 1)"]) "A<_>(S" ["SettableProperty"] ["NonSettableProperty"] - AssertCtrlSpaceCompleteContains (typeDef2 @ ["new A<_>(S = 1)"]) "A<_>(S = 1" [] ["SettableProperty"; "NonSettableProperty"] // neg test - AssertCtrlSpaceCompleteContains (typeDef2 @ ["new A<_>(S = 1,)"]) "A<_>(S = 1," ["AnotherSettableProperty"] ["NonSettableProperty"] - - let typeDef3 = - [ - "module M =" - " type A() = " - " member val SettableProperty = 1 with get,set" - " member val AnotherSettableProperty = 1 with get,set" - " member val NonSettableProperty = 1" - ] - AssertCtrlSpaceCompleteContains (typeDef3 @ ["M.A((**))"]) "A((**)" ["SettableProperty"; "AnotherSettableProperty"] ["NonSettableProperty"] - AssertCtrlSpaceCompleteContains (typeDef3 @ ["M.A(S = 1)"]) "A(S" ["SettableProperty"] ["NonSettableProperty"] - AssertCtrlSpaceCompleteContains (typeDef3 @ ["M.A(S = 1)"]) "A(S = 1" [] ["NonSettableProperty"; "SettableProperty"] // neg test - AssertCtrlSpaceCompleteContains (typeDef3 @ ["M.A(S = 1,)"]) "A(S = 1," ["AnotherSettableProperty"] ["NonSettableProperty"] - AssertCtrlSpaceCompleteContains (typeDef3 @ ["new M.A((**))"]) "A((**)" ["SettableProperty"; "AnotherSettableProperty"] ["NonSettableProperty"] - AssertCtrlSpaceCompleteContains (typeDef3 @ ["new M.A(S = 1)"]) "A(S" ["SettableProperty"] ["NonSettableProperty"] - AssertCtrlSpaceCompleteContains (typeDef3 @ ["new M.A(S = 1)"]) "A(S = 1" [] ["NonSettableProperty"; "SettableProperty"] // neg test - - let typeDef4 = - [ - "module M =" - " type A<'a, 'b>() = " - " member val SettableProperty = 1 with get,set" - " member val AnotherSettableProperty = 1 with get,set" - " member val NonSettableProperty = 1" - ] - AssertCtrlSpaceCompleteContains (typeDef4 @ ["M.A((**))"]) "A((**)" ["SettableProperty"; "AnotherSettableProperty"] ["NonSettableProperty"] - AssertCtrlSpaceCompleteContains (typeDef4 @ ["M.A(S = 1)"]) "A(S" ["SettableProperty"] ["NonSettableProperty"] - AssertCtrlSpaceCompleteContains (typeDef4 @ ["M.A(S = 1)"]) "A(S = 1" [] ["SettableProperty"; "NonSettableProperty"] // neg test - AssertCtrlSpaceCompleteContains (typeDef4 @ ["M.A(S = 1,)"]) "A(S = 1," ["AnotherSettableProperty"] ["NonSettableProperty"] - AssertCtrlSpaceCompleteContains (typeDef4 @ ["new M.A<_, _>((**))"]) "A<_, _>((**)" ["SettableProperty"; "AnotherSettableProperty"] ["NonSettableProperty"] - AssertCtrlSpaceCompleteContains (typeDef4 @ ["new M.A<_, _>(S = 1)"]) "A<_, _>(S" ["SettableProperty"] ["NonSettableProperty"] - AssertCtrlSpaceCompleteContains (typeDef4 @ ["new M.A<_, _>(S = 1)"]) "A<_, _>(S = 1" [] ["NonSettableProperty"; "SettableProperty"] - AssertCtrlSpaceCompleteContains (typeDef4 @ ["new M.A<_, _>(S = 1,)"]) "A<_, _>(S = 1," ["AnotherSettableProperty"] ["NonSettableProperty"] - [] - member public this.``ObjectInitializer.CompletionForSettableExtensionProperties``() = - let typeDef = - [ - "type A() = member this.SetXYZ(v: int) = ()" - "module Ext = type A with member this.XYZ with set(v) = this.SetXYZ(v)" - - ] - AssertCtrlSpaceCompleteContains (typeDef @ ["open Ext"; "A((**))"]) "A((**)" ["XYZ"] [] // positive - AssertCtrlSpaceCompleteContains (typeDef @ ["A((**))"]) "A((**)" [] ["XYZ"] // negative - - [] - member public this.``ObjectInitializer.CompletionForNamedParameters``() = - let typeDef1 = - [ - "type A = " - " static member Run(xyz: int, zyx: string) = 1" - ] - AssertCtrlSpaceCompleteContains (typeDef1 @ ["A.Run()"]) ".Run(" ["xyz"; "zyx"] [] - AssertCtrlSpaceCompleteContains (typeDef1 @ ["A.Run(x = 1)"]) ".Run(x" ["xyz"] [] - AssertCtrlSpaceCompleteContains (typeDef1 @ ["A.Run(x = 1,)"]) ".Run(x = 1," ["xyz"; "zyx"] [] - - let typeDef2 = - [ - "type A = " - " static member Run<'T>(xyz: 'T, zyx: string) = 1" - ] - AssertCtrlSpaceCompleteContains (typeDef2 @ ["A.Run()"]) ".Run(" ["xyz"; "zyx"] [] - AssertCtrlSpaceCompleteContains (typeDef2 @ ["A.Run(x = 1)"]) ".Run(x" ["xyz"] [] - AssertCtrlSpaceCompleteContains (typeDef2 @ ["A.Run(x = 1,)"]) ".Run(x = 1," ["xyz"; "zyx"] [] - AssertCtrlSpaceCompleteContains (typeDef2 @ ["A.Run<_>()"]) ".Run<_>(" ["xyz"; "zyx"] [] - AssertCtrlSpaceCompleteContains (typeDef2 @ ["A.Run<_>(x = 1)"]) ".Run<_>(x" ["xyz"] [] - AssertCtrlSpaceCompleteContains (typeDef2 @ ["A.Run<_>(x = 1,)"]) ".Run<_>(x = 1," ["xyz"; "zyx"] [] - [] - member public this.``ObjectInitializer.CompletionForSettablePropertiesInReturnValue``() = - let typeDef1 = - [ - "type A0() = member val Settable0 = 1 with get,set" - "type A() = " - " member val Settable = 1 with get,set" - " member val NonSettable = 1" - " static member Run(): A0 = Unchecked.defaultof<_>" - " static member Run(a: string): A = Unchecked.defaultof<_>" - ] - AssertCtrlSpaceCompleteContains (typeDef1 @ ["A.Run()"]) ".Run(" ["Settable"; "Settable0"] ["NonSettable"] - AssertCtrlSpaceCompleteContains (typeDef1 @ ["A.Run(S = 1)"]) ".Run(S" ["Settable"; "Settable0"] ["NonSettable"] - AssertCtrlSpaceCompleteContains (typeDef1 @ ["A.Run(S = 1,)"]) ".Run(S = 1," ["Settable"; "Settable0"] ["NonSettable"] - AssertCtrlSpaceCompleteContains (typeDef1 @ ["A.Run(Settable = 1,)"]) ".Run(Settable = 1," ["Settable0"] ["NonSettable"] - - let typeDef2 = - [ - "type A0() = member val Settable0 = 1 with get,set" - "type A() = " - " member val Settable = 1 with get,set" - " member val NonSettable = 1" - " static member Run<'T>(): A0 = Unchecked.defaultof<_>" - " static member Run(a: int): A = Unchecked.defaultof<_>" - ] - AssertCtrlSpaceCompleteContains (typeDef2 @ ["A.Run()"]) ".Run(" ["Settable"; "Settable0"] ["NonSettable"] - AssertCtrlSpaceCompleteContains (typeDef2 @ ["A.Run(S = 1)"]) ".Run(S" ["Settable"; "Settable0"] ["NonSettable"] - AssertCtrlSpaceCompleteContains (typeDef2 @ ["A.Run(S = 1,)"]) ".Run(S = 1," ["Settable"; "Settable0"] ["NonSettable"] - AssertCtrlSpaceCompleteContains (typeDef2 @ ["A.Run(Settable = 1,)"]) ".Run(Settable = 1," ["Settable0"] ["NonSettable"] - AssertCtrlSpaceCompleteContains (typeDef2 @ ["A.Run<_>()"]) ".Run<_>(" ["Settable"; "Settable0"] ["NonSettable"] - AssertCtrlSpaceCompleteContains (typeDef2 @ ["A.Run<_>(S = 1)"]) ".Run<_>(S" ["Settable"; "Settable0"] ["NonSettable"] - AssertCtrlSpaceCompleteContains (typeDef2 @ ["A.Run<_>(S = 1,)"]) ".Run<_>(S = 1," ["Settable"; "Settable0"] ["NonSettable"] - AssertCtrlSpaceCompleteContains (typeDef2 @ ["A.Run<_>(Settable = 1,)"]) ".Run<_>(Settable = 1," ["Settable0"] ["NonSettable"] - [] - member public this.``RangeOperator.CorrectUsage``() = - let useCases = - [ - [ - "let _ = [1..]" - ], "1.." - [ - "[" - " 1" - " .." - "]" - ], ".." - ] - for (code, marker) in useCases do - printfn "%A" code - AssertCtrlSpaceCompleteContains code marker ["abs"] [] - printfn "ok" - [] - member public this.``Array.Length.InForRange``() = - AssertAutoCompleteContainsNoCoffeeBreak - [ "let a = [|1;2;3|] -for i in 0..a."] - "0..a." - [ "Length" ] // should contain - [ ] // should not contain - [] - member public this.``ProtectedMembers.BaseClass`` () = - let sourceCode = - [ - "type T() = " - " inherit exn()" - " member this.Run(x : exn) = x." - ] - AssertCtrlSpaceCompleteContains sourceCode "x." ["Message"; "HResult"] [] - [] - member public this.``ProtectedMembers.SelfOrDerivedClass`` () = - let sources = - [ - [ - "type T() = " - " inherit exn()" - " member this.Run(x : T) = x." - ] - [ - "type T() = " - " inherit exn()" - " member this.Run(x : Z) = x." - "and Z() =" - " inherit T()" - ] - ] - for src in sources do - AssertCtrlSpaceCompleteContains src "x." ["Message"; "HResult"] [] - [] - member public this.``Records.DotCompletion.ConstructingRecords1``() = - let prologue = "type OuterRec = {XX : int; YY : string}" - - let useCases = - [ - "let _ = (* MARKER*) {X", "(* MARKER*) {X", ["XX"] - "let _ = {XX = 1; (* MARKER*)O", "(* MARKER*)O", ["OuterRec"] - "let _ = {XX = 1; (* MARKER*)OuterRec.", "(* MARKER*)OuterRec.", ["XX"; "YY"] - ] - () - for (code, marker, should) in useCases do - let code = [prologue; code] - AssertCtrlSpaceCompleteContains code marker should ["abs"] - [] - member public this.``Records.DotCompletion.ConstructingRecords2``() = - let prologue = - [ - "module Mod = " - " type Rec = {XX : int; YY : string}" - ] - let useCases = - [ - "let _ = (* MARKER*){X }", "(* MARKER*){X", [], ["XX"] - "let _ = {(* MARKER*)Mod. = 1; O", "(* MARKER*)Mod.", ["XX"; "YY"], ["System"] - "let _ = {(* MARKER*)Mod.Rec. ", "(* MARKER*)Mod.Rec.", ["XX"; "YY"], ["System"] - "let _ = (* MARKER*){Mod.XX = 1; }", "(* MARKER*){Mod.XX = 1; ", ["Mod"], ["XX"; "abs"] - ] - - for (code, marker, should, shouldnot) in useCases do - let code = prologue @ [code] - AssertCtrlSpaceCompleteContains code marker should shouldnot - [] - member public this.``Records.CopyOnUpdate``() = - let prologue = - [ - "module SomeOtherPath =" - " type r = { a: int; b : int }" - ] - - let useCases = - [ - "let f1 x = { x with SomeOtherPath. = 3 }", "SomeOtherPath." - "let f2 x = { x with SomeOtherPath.r. = 3 }", "SomeOtherPath.r." - "let f3 (x : SomeOtherPath.r) = { x with }", "x with " - ] - for (code, marker) in useCases do - let code = prologue @ [code] - AssertCtrlSpaceCompleteContains code marker ["a"; "b"] ["abs"] - [] - member public this.``Records.CopyOnUpdate.NoFieldsCompletionBeforeWith``() = - let code = - [ - "type T = {AAA : int}" - "let r = {AAA = 5}" - "let b = {r with }" - ] - AssertCtrlSpaceCompleteContains code "{r " [] ["AAA"] - [] - member public this.``Records.Constructors1``() = - let prologue = - [ - "type X =" - " val field1: int" - " val field2: string" - ] - - let useCases = - [ - " new() = { f}", "{ f" - " new() = { field1; }", "field1; " - " new() = { field1 = 5; }", "= 5; " - " new() = { field1 = 5; f }", "5; f" - ] - for (code, marker) in useCases do - let code = prologue @ [code] - AssertCtrlSpaceCompleteContains code marker ["field1"; "field2"] ["abs"] - [] - member public this.``Records.Constructors2.UnderscoresInNames``() = - let prologue = - [ - "type X =" - " val _field1: int" - " val _field2: string" - ] - - let useCases = - [ - " new() = { _}", "{ _" - " new() = { _field1; }", "_field1; " - ] - for (code, marker) in useCases do - let code = prologue @ [code] - AssertCtrlSpaceCompleteContains code marker ["_field1"; "_field2"] ["abs"] - [] - member public this.``Records.NestedRecordPatterns``() = - let code = ["[1..({contents = 5}).]"] - AssertCtrlSpaceCompleteContains code "5})." ["Value"; "contents"] ["CompareTo"] - [] - member public this.``Records.Separators1``() = - let useCases = - [ - [ - "type X = { AAA : int; BBB : string}" - "let r = {AAA = 5 ; }" - ], "AAA = 5 " - [ - "type X = { AAA : int; BBB : string}" - "let r = {AAA = 5 ; }" - "let b = {r with AAA = 5 ; }" - ], "with AAA = 5 " - ] - - for (code, marker) in useCases do - printfn "checking separators" - printfn "%A" code - AssertCtrlSpaceCompleteContains code marker ["abs"] ["AAA"; "BBB"] - [] - member public this.``Records.Separators2``() = - let useCases = - [ - "Offside rule", [ - "type X = { AAA : int; BBB : string}" - "let r =" - " {" - " AAA = 5" - "(*MARKER*) " - " }" - ], "(*MARKER*)", ["AAA"; "BBB"] - - "Semicolumn", [ - "type X = { AAA : int; BBB : string}" - "let r =" - " {" - " AAA = 5;" - "(*MARKER*) " - " }" - ], "(*MARKER*) ", ["AAA"; "BBB"] - "Semicolumn2", [ - "type X = { AAA : int; BBB : string; CCC : int}" - "let r =" - " {" - " AAA = 5; (*M*)" - " CCC = 5" - " }" - ], "(*M*)", ["AAA"; "BBB"; "CCC"] - ] - - for (caption, code, marker, should) in useCases do - printfn "%s" caption - printfn "%A" code - AssertCtrlSpaceCompleteContains code marker should ["abs"] - [] - member public this.``Records.Inherits``() = - let prologue = - [ - "type A = class end" - "type B = " - " inherit A" - " val f1: int" - " val f2: int" - ] - - let useCases = - [ - [" new() = { inherit A(); }"], "inherit A(); ", ["f1"; "f2"] - [ - " new() = { inherit A()" - " (*M*)" - " }"], "(*M*)", ["f1"; "f2"] - ] - for (code, marker, should) in useCases do - let code = prologue @ code - printfn "running:" - printfn "%s" (String.concat "\r\n" code) - AssertCtrlSpaceCompleteContains code marker should ["abs"] - [] - member public this.``Records.MissingBindings``() = - let prologue = - [ - "type R = {AAA : int; BBB : bool}" - ] - let useCases = - [ - ["let _ = {A = 1; _; }"], "; _;", ["R"] // ["AAA"; "BBB"] <- this check should be used after fixing 279738 - ["let _ = {A = 1; _=; }"], " _=;", ["R"] // ["AAA"; "BBB"] <- this check should be used after fixing 279738 - ["let _ = {A = 1; R. }"], "1; R.", ["AAA"; "BBB"] - ["let _ = {A = 1; _; R. }"], "_; R.", ["AAA"; "BBB"] - ] - - for (code, marker, should) in useCases do - let code = prologue @ code - printfn "running:" - printfn "%s" (String.concat "\r\n" code) - AssertCtrlSpaceCompleteContains code marker should ["abs"] - [] - member public this.``Records.WRONG.ErrorsInFirstBinding``() = - // errors in the first binding are critical now - let prologue = - [ - "type X =" - " val field1: int" - " val field2: string" - ] - - let useCases = - [ - " new() = { field1 =; }", "=; " - " new() = { field1 =; f}", "=; f" - ] - for (code, marker) in useCases do - let code = prologue @ [code] - AssertCtrlSpaceCompleteContains code marker [] ["field1"; "field2"] - - [] - member public this.``Records.InferByFieldsInPriorMethodArguments``() = - - let prologue = - [ - "type T() =" - " new (left: float32, top: float32) = T()" - " new (left: float32, top: float32, width: float32, height: float32) = T()" - "" - "type Rect =" - " { Left: float32" - " Top: float32" - " Width: float32" - " Height: float32 }" - ] - - let useCases = - [ - "let toT(original) = T(original.Left, (* MARKER*)original.)", "(* MARKER*)original.", ["Left"; "Top"; "Width"; "Height"] - "let toT(original) = T(original.Left, original.Height, (* MARKER*)original.)", "(* MARKER*)original.", ["Left"; "Top"; "Width"; "Height"] - "let toT(original) = T(original.Left, original.Height, original.Width, (* MARKER*)original.)", "(* MARKER*)original.", ["Left"; "Top"; "Width"; "Height"] - "let toT(original) = T(original.Left, original.Height, (* MARKER*)original., original.Width)", "(* MARKER*)original.", ["Left"; "Top"; "Width"; "Height"] - ] - for (code, marker, should) in useCases do - let code = prologue @ [code] - AssertCtrlSpaceCompleteContains code marker should [] - - [] - member this.``Completion.DetectInterfaces``() = - let shouldBeInterface = - [ - [ - "type X = interface" - " inherit (*M*)" - ] - [ - "[]" - "type X =" - " inherit (*M*)" - ] - [ - "[]" - "type X = interface" - " inherit (*M*)" - ] - ] - for ifs in shouldBeInterface do - AssertCtrlSpaceCompleteContains ifs "(*M*)" ["seq"] [] - - - [] - member this.``Completion.DetectClasses``() = - - let shouldBeClass = - [ - [ - "type X = class" - " inherit (*M*)" - ] - [ - "[]" - "type X =" - " inherit (*M*)" - ] - [ - "[]" - "type X = class" - " inherit (*M*)" - ] - [ - "[]" - "type X() = " - " inherit (*M*)" - ] - ] - for cls in shouldBeClass do - AssertCtrlSpaceCompleteContains cls "(*M*)" ["obj"] [] - - [] - member this.``Completion.DetectUnknownCompletionContext``() = - let content = - [ - "type X = " - " inherit (*M*)" - ] - - AssertCtrlSpaceCompleteContains content "(*M*)" ["obj"; "seq"] [] - - [] - member this.``Completion.DetectInvalidCompletionContext``() = - let shouldBeInvalid = - [ - [ - "type X =" - " inherit System (*M*)." - ] - [ - "type X =" - " inherit System (*M*).Collections" - ] - - ] - - for invalid in shouldBeInvalid do - AssertCtrlSpaceCompletionListIsEmpty invalid "(*M*)" - - [] - member this.``Completion.LongIdentifiers``() = - // System.Diagnostics.Debugger.Launch() |> ignore - AssertCtrlSpaceCompleteContains - [ - "type X = " - " inherit System. " - ] - "System. " - ["IDisposable"; "Array"] - [] - AssertCtrlSpaceCompleteContains - [ - "type X = " - " inherit System." - " (*M*)" - ] - "(*M*)" - ["IDisposable"; "Array"] - [] - AssertCtrlSpaceCompleteContains - [ - "type X = " - " inherit System" - " .(*M*)" - ] - "(*M*)" - ["IDisposable"; "Array"] - [] - - // caret is immediately after marker - AssertCtrlSpaceCompleteContains - [ - "module Mod =" - " let x = 1" - "module Mod2 = " - " let x = 1" - "type X = " - " inherit Mod" - ] - " inherit Mod" - ["Mod"; "Mod2"] - [] - - AssertCtrlSpaceCompleteContains - [ - "type X = " - " inherit Sys" - ] - "Sys" - ["System"; "obj"] - [] - AssertCtrlSpaceCompleteContains - [ - "type X = " - " inherit System.Collection" - ] - "System.Col" - ["Collections"; "IDisposable"] - [] - AssertCtrlSpaceCompleteContains - [ - "type X = " - " inherit System. Collections" - ] - "System. " - ["Collections"; "IDisposable"] - [] - AssertCtrlSpaceCompleteContains - [ - "type X = " - " inherit System. Collections.ArrayList()" - ] - "System. " - ["Collections"; "IDisposable"] - [] - [] - member public this.``Query.GroupJoin.CompletionInIncorrectJoinRelations``() = - let code = - [ - "let t =" - " query {" - " for x in [1] do" - " groupJoin y in [\"\"] on (x. ?=? y.) into g" - " select 1 }" - ] - AssertCtrlSpaceCompleteContains code "(x." ["CompareTo"] ["abs"] - AssertCtrlSpaceCompleteContains code "? y." ["Chars"; "Length"] ["abs"] - [] - member public this.``Query.Join.CompletionInIncorrectJoinRelations``() = - let code = - [ - "let t =" - " query {" - " for x in [1] do" - " join y in [\"\"] on (x. ?=? y.)" - " select 1 }" - ] - AssertCtrlSpaceCompleteContains code "(x." ["CompareTo"] ["abs"] - AssertCtrlSpaceCompleteContains code "? y." ["Chars"; "Length"] ["abs"] - - [] - member public this.``Query.ForKeywordCanCompleteIntoIdentifier``() = - let code = - [ - "let form = 42" - "let t =" - " query {" - " for" - " }" - ] - AssertCtrlSpaceCompleteContains code "for" ["form"] [] // 'for' is a keyword, but should not prevent completion - [] - member public this.``ObjInstance.InheritedClass.MethodsWithDiffAccessibility``() = - AssertAutoCompleteContainsNoCoffeeBreak - [ "type Base = - val mutable baseField : int - val mutable private baseFieldPrivate : int - new () = { baseField = 0; baseFieldPrivate=1 } - -type Derived = - val mutable derivedField : int - val mutable private derivedFieldPrivate : int - inherit Base - new () = { derivedField = 0;derivedFieldPrivate = 0 } - -let derived = Derived() -derived.derivedField"] - "derived." - [ "baseField"; "derivedField" ] // should contain - [ "baseFieldPrivate"; "derivedFieldPrivate" ] // should not contain - [] - member public this.``ObjInstance.InheritedClass.MethodsWithDiffAccessibilityWithSameNameMethod``() = - AssertAutoCompleteContainsNoCoffeeBreak - [ "type Base = - val mutable baseField : int - val mutable private baseFieldPrivate : int - new () = { baseField = 0; baseFieldPrivate=1 } - -type Derived = - val mutable baseField : int - val mutable derivedField : int - val mutable private derivedFieldPrivate : int - inherit Base - new () = { baseField = 0; derivedField = 0; derivedFieldPrivate = 0 } - -let derived = Derived() -derived.derivedField"] - "derived." - [ "baseField"; "derivedField" ] // should contain - [ "baseFieldPrivate"; "derivedFieldPrivate" ] // should not contain - [] - member public this.``Visibility.InheritedClass.MethodsWithDiffAccessibility``() = - AssertAutoCompleteContainsNoCoffeeBreak - [ "type Base = - val mutable baseField : int - val mutable private baseFieldPrivate : int - new () = { baseField = 0; baseFieldPrivate=1 } - -type Derived = - val mutable derivedField : int - val mutable private derivedFieldPrivate : int - inherit Base - new () = { derivedField = 0;derivedFieldPrivate = 0 } - member this.Method() = - (*marker*)this.baseField"] - "(*marker*)this." - [ "baseField"; "derivedField"; "derivedFieldPrivate" ] // should contain - [ "baseFieldPrivate" ] // should not contain - [] - member public this.``Visibility.InheritedClass.MethodsWithDiffAccessibilityWithSameNameMethod``() = - AssertAutoCompleteContainsNoCoffeeBreak - [ "type Base = - val mutable baseField : int - val mutable private baseFieldPrivate : int - new () = { baseField = 0; baseFieldPrivate=1 } - -type Derived = - val mutable baseField : int - val mutable derivedField : int - val mutable private derivedFieldPrivate : int - inherit Base - new () = { baseField = 0; derivedField = 0; derivedFieldPrivate = 0 } - member this.Method() = - (*marker*)this.baseField"] - "(*marker*)this." - [ "baseField"; "derivedField"; "derivedFieldPrivate" ] // should contain - [ "baseFieldPrivate" ] // should not contain - [] - member public this.``Visibility.InheritedClass.MethodsWithSameNameMethod``() = - AssertAutoCompleteContainsNoCoffeeBreak - [ "type MyClass = - val foo : int - new (foo) = { foo = foo } - -type MyClass2 = - inherit MyClass - val foo : int - new (foo) = { - inherit MyClass(foo) - foo = foo - } - -let x = new MyClass2(0) -(*marker*)x.foo"] - "(*marker*)x." - [ "foo" ] // should contain - [ ] // should not contain - [] - member public this.``Identifier.Array.AfterassertKeyword``() = - AssertAutoCompleteContainsNoCoffeeBreak - [ "let x = [1;2;3] " - "assert x." ] - "x." - [ "Head" ] // should contain (from List) - [ "Listeners" ] // should not contain (from System.Diagnostics.Debug) - [] - member public this.``CtrlSpaceCompletion.Bug130670.Case1``() = - AssertCtrlSpaceCompleteContainsNoCoffeeBreak - [ "let i = async.Return(4)" ] - ")" - [ "AbstractClassAttribute" ] // should contain (top-level) - [ "GetType" ] // should not contain (object instance method) - [] - member public this.``CtrlSpaceCompletion.Bug130670.Case2``() = - AssertCtrlSpaceCompleteContainsNoCoffeeBreak - [ """ - let x = 42 - let r = x + 1 """ ] - "1 " - [ "AbstractClassAttribute" ] // should contain (top-level) - [ "CompareTo" ] // should not contain (instance method on int) [] member public this.``CtrlSpaceCompletion.Bug294974.Case1``() = @@ -1317,992 +332,71 @@ let x = new MyClass2(0) [ "xxx" ] // should contain (completions before dot) [ "IsEmpty" ] // should not contain (completions after dot) - [] - member public this.``CtrlSpaceCompletion.Bug294974.Case2``() = - AssertCtrlSpaceCompleteContains - [ """ - let xxx = [1] - xxx .IsEmpty // Ctrl-J just before the '.' """ ] - "xxx " - [ "AbstractClassAttribute" ] // should contain (top-level) - [ "IsEmpty" ] // should not contain (completions after dot) - - [] - member public this.``ObsoleteProperties.6377_1``() = - AssertAutoCompleteContainsNoCoffeeBreak - [ "System.Security.SecurityManager." ] - "SecurityManager." - [ "GetStandardSandbox" ] // should contain - [ "get_SecurityEnabled"; "set_SecurityEnabled" ] // should not contain - - [] - member public this.``ObsoleteProperties.6377_2``() = - AssertAutoCompleteContainsNoCoffeeBreak - [ "System.Threading.Thread.CurrentThread." ] - "CurrentThread." - [ "CurrentCulture" ] // should contain: just make sure something shows - [ "get_ApartmentState"; "set_ApartmentState" ] // should not contain - - [] - member public this.``PopupsVersusCtrlSpaceOnDotDot.FirstDot.Popup``() = - AssertAutoCompleteContainsNoCoffeeBreak - [ "System.Console..BackgroundColor" ] - "System.Console." - [ "BackgroundColor" ] // should contain (from prior System.Console) - [ "abs" ] // should not contain (top-level autocomplete on empty identifier) - [] - member public this.``PopupsVersusCtrlSpaceOnDotDot.FirstDot.CtrlSpace``() = - AssertCtrlSpaceCompleteContainsNoCoffeeBreak - [ "System.Console..BackgroundColor" ] - "System.Console." - [ "BackgroundColor" ] // should contain (from prior System.Console) - [ "abs" ] // should not contain (top-level autocomplete on empty identifier) - [] - member public this.``DotCompletionInPatternsPartOfLambda``() = - let content = ["let _ = fun x . -> x + 1"] - AssertCtrlSpaceCompletionListIsEmpty content "x ." - [] - member public this.``DotCompletionInBrokenLambda``() = - let content = ["1 |> id (fun x .> x)"] - AssertCtrlSpaceCompletionListIsEmpty content "x ." - [] - member public this.``DotCompletionInPatterns``() = - let useCases = - [ - ["let (x, y .) = 1, 2"], "y ." - ["let run (o : obj) = match o with | :? int as i . -> 1 | _ -> 0"], "as i ." - ["let (``x.y``, ``y.z`` .) = 1, true"], "z`` ." - ["let ``x`` . = 1"], "x`` ." - ] - for (source, marker) in useCases do - AssertCtrlSpaceCompletionListIsEmpty source marker - [] - member public this.``DotCompletionWithBrokenLambda``() = - let errors = - [ - "1 |> id (fun)" - "1 |> id (fun x > x)" - "1 |> id (fun x > )" - "1 |> id (fun x -> )" - ] - let testcases = - [ - for error in errors do - let source = - [ - "let x = 1" - "x." - ] - yield (error::source), "x.", ["CompareTo"], ["Array"] - yield (source @ [error]), "x.", ["CompareTo"], ["Array"] - ] - for (source, marker, should, shouldnot) in testcases do - printfn "%A" source - AssertCtrlSpaceCompleteContains source marker should shouldnot - [] - member public this.``AfterConstructor.5039_1``() = - AssertAutoCompleteContainsNoCoffeeBreak - [ "let someCall(x) = null" - "let xe = someCall(System.IO.StringReader()." ] - "StringReader()." - [ "ReadBlock" ] // should contain (StringReader) - [ "LastIndexOfAny" ] // should not contain (String) - [] - member public this.``AfterConstructor.5039_1.CoffeeBreak``() = - AssertAutoCompleteContains - [ "let someCall(x) = null" - "let xe = someCall(System.IO.StringReader()." ] - "StringReader()." - [ "ReadBlock" ] // should contain (StringReader) - [ "LastIndexOfAny" ] // should not contain (String) - [] - member public this.``AfterConstructor.5039_2``() = - AssertAutoCompleteContainsNoCoffeeBreak - [ "System.Random()." ] - "Random()." - [ "NextDouble" ] // should contain - [ ] // should not contain - [] - member public this.``AfterConstructor.5039_3``() = - AssertAutoCompleteContainsNoCoffeeBreak - [ "System.Collections.Generic.List()." ] - "List()." - [ "BinarySearch" ] // should contain - [ ] // should not contain - [] - member public this.``AfterConstructor.5039_4``() = - AssertAutoCompleteContainsNoCoffeeBreak - [ "System.Collections.Generic.List()." ] - "List()." - [ "BinarySearch" ] // should contain - [ ] // should not contain - [] - member public this.``Literal.809979``() = - AssertAutoCompleteContainsNoCoffeeBreak - [ "let value=uint64." ] - "uint64." - [ ] // should contain - [ "Parse" ] // should not contain - [] - member public this.``NameSpace.AsConstructor``() = - AssertCtrlSpaceCompleteContainsNoCoffeeBreak - [ "new System.DateTime()" ] - "System.DateTime(" // move to marker - ["System";"Array2D"] - ["DaysInMonth"; "AddDays" ] // should contain top level info, no static or instance DateTime members! - [] - member public this.``DotAfterApplication1``() = - AssertAutoCompleteContainsNoCoffeeBreak - ["let g a = new System.Random()" - "(g [])."] - "(g [])." - ["Next"] - [ ] - - [] - member public this.``DotAfterApplication2``() = - AssertAutoCompleteContainsNoCoffeeBreak - ["let g a = new System.Random()" - "g []."] - "g []." - ["Head"] - [ ] - - [] - member public this.``Quickinfo.809979``() = - AssertAutoCompleteContainsNoCoffeeBreak - [ "let value=uint64." ] - "uint64." - [ ] // should contain - [ "Parse" ] // should not contain - - /// No intellisense in comments/strings! - [] - member public this.``InString``() = - this.VerifyCtrlSpaceCompListIsEmptyAtEndOfMarker( - fileContents = """ // System.C """ , - marker = "// System.C" ) - [] - member public this.``InComment``() = - this.VerifyCtrlSpaceCompListIsEmptyAtEndOfMarker( - fileContents = """ let s = "System.C" """, - marker = "\"System.C") - - /// Intellisense at the top level (on white space) - [] - member public this.``Identifier.OnWhiteSpace.AtTopLevel``() = - AssertCtrlSpaceCompleteContainsNoCoffeeBreak - ["(*marker*) "] - "(*marker*) " - ["System"; "Array2D"] - ["Int32"] - - /// Intellisense at the top level (after a partial token). All matches should be shown even if there is a unique match - [] - member public this.``TopLevelIdentifier.AfterPartialToken1``() = - AssertCtrlSpaceCompleteContainsNoCoffeeBreak - ["let foobaz = 1" - "(*marker*)fo"] - "(*marker*)fo" - ["System";"Array2D";"foobaz"] - ["Int32"] - - [] - member public this.``TopLevelIdentifier.AfterPartialToken2``() = - AssertCtrlSpaceCompleteContainsNoCoffeeBreak - ["let foobaz = 1" - "(*marker*)fo"] - "(*marker*)" - ["System";"Array2D";"foobaz"] - [] - -(* these issues have not been fixed yet, but when they are, here are some tests - [] - member public this.``AutoComplete.Bug65730``() = - AssertAutoCompleteContains - [ "let f x y = x.Equals(y)" ] - "x." // marker - [ "Equals" ] // should contain - [ ] // should not contain - - [] - member public this.``AutoComplete.Bug65731_A``() = - AssertAutoCompleteContains - [ -@"module SomeOtherPath =" -@" type r = { a: int; b : int }" -@"let f1 x = { x with SomeOtherPath.a = 3 } // a" - ] - "SomeOtherPath." // marker - [ "a" ] // should contain - [ ] // should not contain - - [] - member public this.``AutoComplete.Bug65731_B``() = - AssertAutoCompleteContains - [ -@"module SomeOtherPath =" -@" type r = { a: int; b : int }" -@"let f2 x = { x with SomeOtherPath.r.a = 3 } // a" - ] - "SomeOtherPath.r." // marker - [ "a" ] // should contain - [ ] // should not contain + member this.QueryExpressionFileExamples() = + [ """ + module BasicTest + let x = query { for x in [1;2;3] do (*TYPING*)""" + """ + module BasicTest + let x = query { for x in [1;2;3] do (*TYPING*) }""" + """ + module BasicTest + let x = query { for x in [1;2;3] do + (*TYPING*)""" + """ + module BasicTest + let x = query { for x in [1;2;3] do + if x > 3 then + (*TYPING*)""" + """ + module BasicTest + let x = query { for x in [1;2;3] do + where (x > 3) + (*TYPING*)""" + """ + module BasicTest + let x = query { for x in [1;2;3] do + sortBy x + (*TYPING*)""" + """ + module BasicTest + let x = query { for x in [1;2;3] do + (*TYPING*) + sortBy x """ + """ + module BasicTest + let x = query { for x in [1;2;3] do + let y = x + 1 + (*TYPING*)""" ] - [] - member public this.``AutoComplete.Bug69654_0``() = - let code = [ @" - let q = - let a = 42 - let b = (fun i -> i) 43 - // i shows up in Ctrl-space list here, b does not - ((* *)) // but in the parens, things are correct again - "] - - let solution = CreateSolution(this.VS) - let project = CreateProject(solution,"testproject") - let file = AddFileFromText(project,"File1.fs", code) - let file = OpenFile(project,"File1.fs") - TakeCoffeeBreak(this.VS) - let gpatcc = GlobalParseAndTypeCheckCounter.StartNew(this.VS) - MoveCursorToStartOfMarker(file, "//") - let completions = AutoCompleteAtCursor file - AssertCompListContains(completions, "b") - AssertCompListDoesNotContain(completions, "i") - MoveCursorToStartOfMarker(file, "(* *)") - let completions = AutoCompleteAtCursor file - AssertCompListContains(completions, "b") - AssertCompListDoesNotContain(completions, "i") + member this.WordByWordSystematicTestWithSpecificExpectations(prefix, suffixes, lines, variations, knownFailures:list<_>) = - gpatcc.AssertExactly(0,0) - - [] - member public this.``AutoComplete.Bug69654_1``() = - let code = [ - "let s = async {" - " let! xxx = async { return 0 }" - " xxx.CompareTo |> ignore // the dot works" - " xxx |> ignore // no xxx" - " do xxx |> ignore // no xxx" - " return xxx // no xxx" - " }" ] - let solution = CreateSolution(this.VS) - let project = CreateProject(solution,"testproject") - let file = AddFileFromText(project,"File1.fs", code) - let file = OpenFile(project,"File1.fs") - TakeCoffeeBreak(this.VS) - let gpatcc = GlobalParseAndTypeCheckCounter.StartNew(this.VS) - - MoveCursorToEndOfMarker(file, "xx.Comp") - let completions = AutoCompleteAtCursor file - AssertCompListContains(completions, "CompareTo") - - MoveCursorToStartOfMarker(file, "xx.Comp") - let completions = AutoCompleteAtCursor file - AssertCompListContains(completions, "xxx") - - MoveCursorToStartOfMarker(file, "xx |>") - let completions = AutoCompleteAtCursor file - AssertCompListContains(completions, "xxx") - - MoveCursorToEndOfMarker(file, "do xx") - let completions = AutoCompleteAtCursor file - AssertCompListContains(completions, "xxx") - - MoveCursorToEndOfMarker(file, "return xx") - let completions = AutoCompleteAtCursor file - AssertCompListContains(completions, "xxx") - - gpatcc.AssertExactly(0,0) - - [] - member public this.``AutoComplete.Bug69654_2``() = - let code = [ - "let s = async {" - " use xxx = null" - " xxx.Dispose() // the dot works" - " xxx |> ignore // no xxx" - " do xxx |> ignore // no xxx" - " return xxx // no xxx" - " }" ] - let solution = CreateSolution(this.VS) - let project = CreateProject(solution,"testproject") - let file = AddFileFromText(project,"File1.fs", code) - let file = OpenFile(project,"File1.fs") - TakeCoffeeBreak(this.VS) - let gpatcc = GlobalParseAndTypeCheckCounter.StartNew(this.VS) - - MoveCursorToEndOfMarker(file, "xx.Disp") - let completions = AutoCompleteAtCursor file - AssertCompListContains(completions, "Dispose") - - MoveCursorToStartOfMarker(file, "xx.Disp") - let completions = AutoCompleteAtCursor file - AssertCompListContains(completions, "xxx") - - MoveCursorToStartOfMarker(file, "xx |>") - let completions = AutoCompleteAtCursor file - AssertCompListContains(completions, "xxx") - - MoveCursorToEndOfMarker(file, "do xx") - let completions = AutoCompleteAtCursor file - AssertCompListContains(completions, "xxx") - - MoveCursorToEndOfMarker(file, "return xx") - let completions = AutoCompleteAtCursor file - AssertCompListContains(completions, "xxx") - - gpatcc.AssertExactly(0,0) -*) - - [] - member public this.``List.AfterAddLinqNamespace.Bug3754``() = - let code = - ["open System.Xml.Linq" - "List." ] - let (_, _, file) = this.CreateSingleFileProject(code, references = ["System.Xml"; "System.Xml.Linq"]) - MoveCursorToEndOfMarker(file, "List.") - let completions = AutoCompleteAtCursor file - AssertCompListContainsAll(completions, [ "map"; "filter" ] ) - - [] - member public this.``Global``() = - AssertAutoCompleteContainsNoCoffeeBreak - ["global."] - "global." - ["System"; "Microsoft" ] - [] - - [] - member public this.``Duplicates.Bug4103a``() = - let code = - [ - "open Microsoft.FSharp.Quotations" - "Expr." ] - let (_, _, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file, "Expr.") - let completions = AutoCompleteAtCursor file - - // Get description for Expr.Var - let (CompletionItem(_, _, _, descrFunc, _)) = completions |> Array.find (fun (CompletionItem(name, _, _, _, _)) -> name = "WhileLoop") - let descr = descrFunc() - // Check whether the description contains the name only once - let occurrences = (" " + descr + " ").Split([| "WhileLoop" |], System.StringSplitOptions.None).Length - 1 - // You'll get two occurrences - one for the signature, and one for the doc - AssertEqualWithMessage(2, occurrences, "The entry for 'Expr.Var' is duplicated.") - - /// Testing autocomplete after a dot directly following method call - [] - member public this.``AfterMethod.Bug2296``() = - AssertAutoCompleteContainsNoCoffeeBreak - [ "type System.Int32 with" - " member x.Int32Member() = 0" - "\"\".CompareTo(\"a\")." ] - "(\"a\")." - ["Int32Member" ] - [] - - /// Testing autocomplete after a dot directly following overloaded method call - [] - member public this.``AfterMethod.Overloaded.Bug2296``() = - AssertAutoCompleteContainsNoCoffeeBreak - ["type System.Boolean with" - " member x.BooleanMember() = 0" - "\"\".Contains(\"a\")."] - "(\"a\")." - ["BooleanMember"] - [] - - [] - member public this.``BasicGlobalMemberList``() = - AssertAutoCompleteContainsNoCoffeeBreak - ["let x = 1" - "x."] - "x." - ["CompareTo"; "GetHashCode"] - [] - - [] - member public this.``CharLiteral``() = - AssertAutoCompleteContainsNoCoffeeBreak - ["let x = \"foo\"" - "let x' = \"bar\"" - "x'."] - "x'." - ["CompareTo";"GetHashCode"] - [] - - [] - member public this.``GlobalMember.ListOnIdentifierEndingWithTick``() = - AssertAutoCompleteContainsNoCoffeeBreak - ["let x' = 1" - "x'."] - "x'." - ["CompareTo";"GetHashCode"] - [] - - [] - member public this.``GlobalMember.ListOnIdentifierContainingTick``() = - AssertAutoCompleteContainsNoCoffeeBreak - ["let x'y = 1" - "x'y."] - "x'y." - ["CompareTo";"GetHashCode"] - [] - - [] - member public this.``GlobalMember.ListWithPartialMember1``() = - AssertCtrlSpaceCompleteContainsNoCoffeeBreak - ["let x = 1" - "x.CompareT"] - "x.CompareT" - ["CompareTo";"GetHashCode"] - [] - - [] - member public this.``GlobalMember.ListWithPartialMember2``() = - AssertAutoCompleteContainsNoCoffeeBreak - ["let x = 1" - "x.CompareT"] - "x." - ["CompareTo";"GetHashCode"] - [] - - /// Wrong intellisense for array - [] - member public this.``DotOff.Parenthesized.Expr``() = - AssertAutoCompleteContainsNoCoffeeBreak - ["let string_of_int (x:int) = x.ToString()" - "let strs = Array.init 10 string_of_int" - "let x = (strs.[1])."] - "(strs.[1])." - ["Substring";"GetHashCode"] - [] - - /// Wrong intellisense for array - [] - member public this.``DotOff.ArrayIndexerNotation``() = - AssertAutoCompleteContainsNoCoffeeBreak - ["let string_of_int (x:int) = x.ToString()" - "let strs = Array.init 10 string_of_int" - "let test1 = strs.[1]."] - "strs.[1]." - ["Substring";"GetHashCode"] - [] - - /// Wrong intellisense for array - [] - member public this.``DotOff.ArraySliceNotation1``() = - AssertAutoCompleteContainsNoCoffeeBreak - ["let string_of_int (x:int) = x.ToString()" - "let strs = Array.init 10 string_of_int" - "let test2 = strs.[1..]." - "let test3 = strs.[..1]." - "let test4 = strs.[1..1]."] - "trs.[1..]." - ["Length"] - [] - - [] - member public this.``DotOff.ArraySliceNotation2``() = - AssertAutoCompleteContainsNoCoffeeBreak - ["let string_of_int (x:int) = x.ToString()" - "let strs = Array.init 10 string_of_int" - "let test2 = strs.[1..]." - "let test3 = strs.[..1]." - "let test4 = strs.[1..1]."] - "strs.[..1]." - ["Length"] - [] - - [] - member public this.``DotOff.ArraySliceNotation3``() = - AssertAutoCompleteContainsNoCoffeeBreak - ["let string_of_int (x:int) = x.ToString()" - "let strs = Array.init 10 string_of_int" - "let test2 = strs.[1..]." - "let test3 = strs.[..1]." - "let test4 = strs.[1..1]."] - "strs.[1..1]." - ["Length"] - [] - - [] - member public this.``DotOff.DictionaryIndexer``() = - AssertAutoCompleteContainsNoCoffeeBreak - ["let dict = new System.Collections.Generic.Dictionary()" - "let test5 = dict.[1]."] - "dict.[1]." - ["Length"] - [] - - /// intellisense on DOT - [] - member public this.``EmptyFile.Dot.Bug1115``() = - this.VerifyAutoCompListIsEmptyAtEndOfMarker( - fileContents = "." , - marker = ".") - - [] - member public this.``Identifier.NonDottedNamespace.Bug1347``() = - this.AssertCtrlSpaceCompletionContains( - ["open System" - "open Microsoft.FSharp.Math" - "let x = Mic" - "let p7 =" - " let sieve limit = " - " let isPrime = Array.create (limit+1) true" - " for n in"], - "let x = Mic", - "Microsoft") - - [] - member public this.``MatchStatement.WhenClause.Bug2519``() = - AssertAutoCompleteContainsNoCoffeeBreak - ["type DU = X of int" - "let timefilter pkt =" - " match pkt with" - " | X(hdr) when (*aaa*)hdr." - " | _ -> ()"] - "(*aaa*)hdr." - ["CompareTo";"GetHashCode"] - [] - - [] - member public this.``String.BeforeIncompleteModuleDefinition.Bug2385``() = - AssertAutoCompleteContainsNoCoffeeBreak - ["let s = \"hello\"." - "module Timer ="] - "\"hello\"." - ["Substring";"GetHashCode"] - [] - - [] - member public this.``Project.FsFileWithBuildAction``() = - AssertAutoCompleteContainsNoCoffeeBreak - ["let i = 4" - "let r = i.ToString()" - "let x = File1.bob"] - "i." - ["CompareTo"] - [] - - /// Dotting off a string literal should work. - [] - member public this.``DotOff.String``() = - AssertAutoCompleteContainsNoCoffeeBreak - ["\"x\". (*marker*)" - ""] - "\"x\"." - ["Substring";"GetHashCode"] - [] - - /// FEATURE: Pressing dot (.) after an local variable will produce an Intellisense list of members the user may select. - [] - member public this.``BasicLocalMemberList``() = - AssertAutoCompleteContainsNoCoffeeBreak - ["let MyFunction (s:string) = " - " let y=\"dog\"" - " y." - " ()"] - " y." - ["Substring";"GetHashCode"] - [] - - [] - member public this.``LocalMemberList.WithPartialMemberEntry1``() = - AssertCtrlSpaceCompleteContainsNoCoffeeBreak - ["let MyFunction (s:string) = " - " let y=\"dog\"" - " y.Substri" - " ()"] - " y.Substri" - ["Substring";"GetHashCode"] - [] - - [] - member public this.``LocalMemberList.WithPartialMemberEntry2``() = - AssertAutoCompleteContainsNoCoffeeBreak - ["let MyFunction (s:string) = " - " let y=\"dog\"" - " y.Substri" - " ()"] - " y." - ["Substring";"GetHashCode"] - [] - - [] - member public this.``CurriedArguments.Regression1``() = - AssertCtrlSpaceCompleteContainsNoCoffeeBreak - ["let fffff x y = 1" - "let ggggg = 1" - "let test1 = fffff \"a\" ggggg" - "let test2 = fffff 1 ggggg" - "let test3 = fffff ggggg ggggg"] - "let f" - ["fffff"] - [] - - [] - member public this.``CurriedArguments.Regression2``() = - AssertCtrlSpaceCompleteContainsNoCoffeeBreak - ["let fffff x y = 1" - "let ggggg = 1" - "let test1 = fffff \"a\" ggggg" - "let test2 = fffff 1 ggggg" - "let test3 = fffff ggggg ggggg"] - "let test1 = f" - ["fffff"] - [] - - [] - member public this.``CurriedArguments.Regression3``() = - AssertCtrlSpaceCompleteContainsNoCoffeeBreak - ["let fffff x y = 1" - "let ggggg = 1" - "let test1 = fffff \"a\" ggggg" - "let test2 = fffff 1 ggggg" - "let test3 = fffff ggggg ggggg"] - "let test1 = fffff \"a\" gg" - ["ggggg"] - [] - - [] - member public this.``CurriedArguments.Regression4``() = - AssertCtrlSpaceCompleteContainsNoCoffeeBreak - ["let fffff x y = 1" - "let ggggg = 1" - "let test1 = fffff \"a\" ggggg" - "let test2 = fffff 1 ggggg" - "let test3 = fffff ggggg ggggg"] - "let test2 = fffff 1 gg" - ["ggggg"] - [] - - [] - member public this.``CurriedArguments.Regression5``() = - AssertCtrlSpaceCompleteContainsNoCoffeeBreak - ["let fffff x y = 1" - "let ggggg = 1" - "let test1 = fffff \"a\" ggggg" - "let test2 = fffff 1 ggggg" - "let test3 = fffff ggggg ggggg"] - "let test3 = fffff gg" - ["ggggg"] - [] - - [] - member public this.``CurriedArguments.Regression6``() = - AssertCtrlSpaceCompleteContainsNoCoffeeBreak - ["let fffff x y = 1" - "let ggggg = 1" - "let test1 = fffff \"a\" ggggg" - "let test2 = fffff 1 ggggg" - "let test3 = fffff ggggg ggggg"] - "let test3 = fffff ggggg gg" - ["ggggg"] - [] - - // Test whether standard types appear in the completion list under both F# and .NET name - [] - member public this.``StandardTypes.Bug4403``() = - AssertCtrlSpaceCompleteContainsNoCoffeeBreak - ["open System"; "let x=" ] - "let x=" - ["int8"; "int16"; "int32"; "string"; "SByte"; "Int16"; "Int32"; "String" ] - [ ] - - // Test whether standard types appear in the completion list under both F# and .NET name - [] - member public this.``ValueDeclarationHidden.Bug4405``() = - AssertAutoCompleteContainsNoCoffeeBreak - [ "do " - " let a = \"string\"" - " let a = if true then 0 else a."] - "else a." - ["IndexOf"; "Substring"] - [ ] - - [] - member public this.``StringFunctions``() = - let code = - [ - "let y = String." - "let f x = 0" - ] - let (_, _, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file,"String.") - let completions = time1 AutoCompleteAtCursor file "Time of first autocomplete." - // printf "Completions=%A\n" completions - Assert.True(completions.Length > 0) - for completion in completions do - match completion with - | CompletionItem(_,_,_,_,DeclarationType.Method) -> () - | CompletionItem(name,_,_,_,x) -> failwith (sprintf "Unexpected item %s seen with declaration type %A" name x) - - // FEATURE: Pressing ctrl+space or ctrl+j will give a list of valid completions. - - [] - //Verified at least "Some" is contained in the Ctrl-Space Completion list - member public this.``NonDotCompletion``() = - this.AssertCtrlSpaceCompletionContains( - ["let x = S"], - "x = S", - "Some") - - [] - // This test case checks Pressing ctrl+space on the provided Type instance method shows list of valid completions - member this.``TypeProvider.EditorHideMethodsAttribute.InstanceMethod.CtrlSpaceCompletionContains``() = - this.AssertCtrlSpaceCompletionContains( - fileContents = [""" - let t = new N1.T1() - t.I"""], - marker = "t.I", - expected = "IM1", - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - // This test case checks Pressing ctrl+space on the provided Type Event shows list of valid completions - member this.``TypeProvider.EditorHideMethodsAttribute.Event.CtrlSpaceCompletionContains``() = - this.AssertCtrlSpaceCompletionContains( - fileContents = [""" - let t = new N.T() - t.Eve"""], - marker = "t.Eve", - expected = "Event1", - addtlRefAssy = [PathRelativeToTestAssembly(@"EditorHideMethodsAttribute.dll")]) - - [] - // This test case checks Pressing ctrl+space on the provided Type static parameter and verify "int" is in the list just to make sure bad things don't happen and autocomplete window pops up - member this.``TypeProvider.EditorHideMethodsAttribute.Type.CtrlSpaceCompletionContains``() = - this.AssertCtrlSpaceCompletionContains( - fileContents = [""" - type boo = N1.T] - member public this.``Class.Self.Bug1544``() = - this.VerifyAutoCompListIsEmptyAtEndOfMarker( - fileContents = " - type Foo() = - member this.", - marker = "this.") - - // No completion list at the end of file. - [] - member public this.``Identifier.AfterDefined.Bug1545``() = - this.AutoCompletionListNotEmpty - ["let x = [|\"hello\"|]" - "x."] - "x." - - [] - member public this.``Bug243082.DotAfterNewBreaksCompletion`` () = - this.AutoCompletionListNotEmpty - [ - "module A =" - " type B() = class end" - "let s = 1" - "s." - "let z = new A."] - "s." - - [] - member public this.``Bug243082.DotAfterNewBreaksCompletion2`` () = - this.AutoCompletionListNotEmpty - [ - "let s = 1" - "s." - "new System."] - "s." - - [] - member this.``QueryExpression.CtrlSpaceSmokeTest0``() = - this.VerifyCtrlSpaceListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - let x = si(*Marker*)""" , - marker = "(*Marker*)", - list = ["sin"], - addtlRefAssy=standard40AssemblyRefs ) - - [] - member this.``QueryExpression.CtrlSpaceSmokeTest0b``() = - this.VerifyCtrlSpaceListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - let x = qu(*Marker*)""" , - marker = "(*Marker*)", - list = ["query"], - addtlRefAssy=standard40AssemblyRefs ) - - [] - member this.``QueryExpression.CtrlSpaceSmokeTest1``() = - this.VerifyCtrlSpaceListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - let x = query { for x in [1;2;3] do sel(*Marker*)""" , - marker = "(*Marker*)", - list = ["select"], - addtlRefAssy=standard40AssemblyRefs ) - - [] - member this.``QueryExpression.CtrlSpaceSmokeTest1b``() = - this.VerifyCtrlSpaceListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - let x = query { for x in [1;2;3] do (*Marker*)""" , - marker = "(*Marker*)", - list = ["select"], - addtlRefAssy=standard40AssemblyRefs ) - - - - [] - member this.``QueryExpression.CtrlSpaceSmokeTest2``() = - this.VerifyCtrlSpaceListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - let x = query { for x in [1;2;3] do sel(*Marker*) }""" , - marker = "(*Marker*)", - list = ["select"], - addtlRefAssy=standard40AssemblyRefs ) - - - [] - member this.``QueryExpression.CtrlSpaceSmokeTest3``() = - this.VerifyCtrlSpaceListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - let x = query { for xxxxxx in [1;2;3] do xxx(*Marker*)""" , - marker = "(*Marker*)", - list = ["xxxxxx"], - addtlRefAssy=standard40AssemblyRefs ) - - - [] - member this.``QueryExpression.CtrlSpaceSmokeTest3b``() = - this.VerifyCtrlSpaceListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - let x = seq { for xxxxxx in [1;2;3] do xxx(*Marker*)""" , - marker = "(*Marker*)", - list = ["xxxxxx"], - addtlRefAssy=standard40AssemblyRefs ) - - - - [] - member this.``QueryExpression.CtrlSpaceSmokeTest3c``() = - this.VerifyCtrlSpaceListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - let x = async { for xxxxxx in [1;2;3] do xxx(*Marker*)""" , - marker = "(*Marker*)", - list = ["xxxxxx"], - addtlRefAssy=standard40AssemblyRefs ) - - - [] - member this.``AsyncExpression.CtrlSpaceSmokeTest3d``() = - this.VerifyCtrlSpaceListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - let x = async { for xxxxxx in [1;2;3] do xxx(*Marker*) }""" , - marker = "(*Marker*)", - list = ["xxxxxx"], - addtlRefAssy=standard40AssemblyRefs ) - - - member this.QueryExpressionFileExamples() = - [ """ - module BasicTest - let x = query { for x in [1;2;3] do (*TYPING*)""" - """ - module BasicTest - let x = query { for x in [1;2;3] do (*TYPING*) }""" - """ - module BasicTest - let x = query { for x in [1;2;3] do - (*TYPING*)""" - """ - module BasicTest - let x = query { for x in [1;2;3] do - if x > 3 then - (*TYPING*)""" - """ - module BasicTest - let x = query { for x in [1;2;3] do - where (x > 3) - (*TYPING*)""" - """ - module BasicTest - let x = query { for x in [1;2;3] do - sortBy x - (*TYPING*)""" - """ - module BasicTest - let x = query { for x in [1;2;3] do - (*TYPING*) - sortBy x """ - """ - module BasicTest - let x = query { for x in [1;2;3] do - let y = x + 1 - (*TYPING*)""" ] - - [] - /// This is the case where at (*TYPING*) we first type 1...N-1 characters of the target custom operation and then invoke the completion list, and we check that the completion list contains the custom operation - member this.``QueryExpression.CtrlSpaceSystematic1``() = - let rec strictPrefixes (s:string) = seq { if s.Length > 1 then let s = s.[0..s.Length-2] in yield s; yield! strictPrefixes s} - for customOperation in ["select";"skip";"contains";"groupJoin"] do - printfn " Running systematic tests looking for completion of '%s' at multiple locations" customOperation - for idText in strictPrefixes customOperation do - for i,fileContents in this.QueryExpressionFileExamples() |> List.mapi (fun i x -> (i,x)) do - let fileContents = fileContents.Replace("(*TYPING*)",idText+"(*Marker*)") - try - this.VerifyCtrlSpaceListContainAllAtStartOfMarker( - fileContents = fileContents, - marker = "(*Marker*)", - list = [customOperation], - addtlRefAssy=standard40AssemblyRefs ) - with _ -> - printfn "FAILURE: customOperation = %s, idText = %s, fileContents <<<%s>>>" customOperation idText fileContents - reraise() - - - member this.WordByWordSystematicTestWithSpecificExpectations(prefix, suffixes, lines, variations, knownFailures:list<_>) = - - let knownFailuresDict = set knownFailures - printfn "Building systematic tests, excluding %d known failures" knownFailures.Length - let tests = - [ for (suffixName,suffixText) in suffixes do - for builderName in variations do - for (lineName, line, checks) in lines builderName do - for check in checks do - let expectedToFail = knownFailuresDict.Contains (lineName, suffixName, builderName, check) - if not expectedToFail then yield (lineName, suffixName, suffixText, builderName, line, check, expectedToFail) ] + let knownFailuresDict = set knownFailures + printfn "Building systematic tests, excluding %d known failures" knownFailures.Length + let tests = + [ for (suffixName,suffixText) in suffixes do + for builderName in variations do + for (lineName, line, checks) in lines builderName do + for check in checks do + let expectedToFail = knownFailuresDict.Contains (lineName, suffixName, builderName, check) + if not expectedToFail then yield (lineName, suffixName, suffixText, builderName, line, check, expectedToFail) ] let unexpectedSuccesses = ResizeArray<_>() let successes = ResizeArray<_>() @@ -2353,316 +447,11 @@ let x = new MyClass2(0) if failures.Count <> 0 || unexpectedSuccesses.Count <> 0 then raise <| new Exception("there were unexpected results, see console output for details") - [] - member this.``QueryExpressions.QueryAndSequenceExpressionWithForYieldLoopSystematic``() = - - let prefix = """ -module Test -let aaaaaa = [| "1" |] -""" - let suffixes = - [ "Empty", ""; - "ClosingBrace", " }"; - "ClosingBrace,NextDefinition", " } \nlet nextDefinition () = 1\n"; - "NoClosingBrace,NextDefinition", " \nlet nextDefinition () = 1\n"; - "NoClosingBrace,NextTypeDefinition", " \ntype NextDefinition() = member x.P = 1\n" - ] - let lines b = - [ "AL1", "let v = " + b + " { " , [] - "AL2", "let v = " + b + " { for " , [] - "AL3", "let v = " + b + " { for bbbb " , [QI "for bbbb" "val bbbb"] - "AL4", "let v = " + b + " { for bbbb in (*C*)" , [QI "for bbbb" "val bbbb"; AC "(*C*)" "aaaaaa" ] - "AL5", "let v = " + b + " { for bbbb in [ (*C*) " , [QI "for bbbb" "val bbbb"; AC "(*C*)" "aaaaaa" ] - "AL6", "let v = " + b + " { for bbbb in [ aaa(*C*) " , [QI "for bbbb" "val bbbb"; AC "(*C*)" "aaaaaa" ] - "AL7", "let v = " + b + " { for bbbb in [ aaaaaa(*D1*)" , [QI "for bbbb" "val bbbb"; QI "aaaaaa" "val aaaaaa"; DC "(*D1*)" "Length" ] - "AL8", "let v = " + b + " { for bbbb in [ aaaaaa(*D1*) ] " , [QI "for bbbb" "val bbbb"; QI "aaaaaa" "val aaaaaa"; DC "(*D1*)" "Length" ] - "AL9", "let v = " + b + " { for bbbb in [ aaaaaa(*D1*) ] do (*C*)" , [QI "for bbbb" "val bbbb"; QI "aaaaaa" "val aaaaaa"; AC "(*C*)" (if b = "query" then "select" else "sin"); DC "(*D1*)" "Length" ] - "AL10", "let v = " + b + " { for bbbb in [ aaaaaa(*D1*) ] do yield (*C*) " , [QI "for bbbb" "val bbbb"; QI "aaaaaa" "val aaaaaa"; AC "(*C*)" "aaaaaa"; AC "(*C*)" "bbbb" ; DC "(*D1*)" "Length" ] - "AL11", "let v = " + b + " { for bbbb in [ aaaaaa(*D1*) ] do yield bb(*C*) " , [QI "for bbbb" "val bbbb"; QI "aaaaaa" "val aaaaaa"; AC "(*C*)" "bbbb" ; DC "(*D1*)" "Length" ] - "AL12", "let v = " + b + " { for bbbb in [ aaaaaa(*D1*) ] do yield bbbb(*D2*) " , [QI "for bbbb" "val bbbb"; QI "aaaaaa" "val aaaaaa"; QI "yield bbbb" "val bbbb"; DC "(*D1*)" "Length" ; DC "(*D2*)" "Length" ] - "AL13", "let v = " + b + " { for bbbb in [ aaaaaa(*D1*) ] do yield bbbb(*D2*) + (*C*)" , [QI "for bbbb" "val bbbb"; QI "aaaaaa" "val aaaaaa"; QI "yield bbbb" "val bbbb"; AC "(*C*)" "aaaaaa"; AC "(*C*)" "bbbb" ; DC "(*D1*)" "Length" ; DC "(*D2*)" "Length" ] - "AL14", "let v = " + b + " { for bbbb in [ aaaaaa(*D1*) ] do yield bbbb(*D2*) + bb(*C*)" , [QI "for bbbb" "val bbbb"; QI "aaaaaa" "val aaaaaa"; QI "yield bbbb" "val bbbb"; AC "(*C*)" "bbbb" ; DC "(*D1*)" "Length" ; DC "(*D2*)" "Length" ] - "AL15", "let v = " + b + " { for bbbb in [ aaaaaa(*D1*) ] do yield bbbb(*D2*) + bbbb(*D3*)" , [QI "for bbbb" "val bbbb"; QI "aaaaaa" "val aaaaaa"; QI "yield bbbb" "val bbbb"; QI "+ bbbb" "val bbbb"; DC "(*D3*)" "Length" ] ] - - - let knownFailures = - [ - ("AL3", "NoClosingBrace,NextDefinition", "query", QuickInfoExpected ("for bbbb","val bbbb")) - ("AL3", "NoClosingBrace,NextDefinition", "seq", QuickInfoExpected ("for bbbb","val bbbb")) - ("AL6", "NoClosingBrace,NextDefinition", "query", AutoCompleteExpected ("(*C*)","aaaaaa")) - ("AL6", "NoClosingBrace,NextDefinition", "query", QuickInfoExpected ("for bbbb","val bbbb")) - ("AL6", "NoClosingBrace,NextDefinition", "seq", AutoCompleteExpected ("(*C*)","aaaaaa")) - ("AL6", "NoClosingBrace,NextDefinition", "seq", QuickInfoExpected ("for bbbb","val bbbb")) - ("AL7", "NoClosingBrace,NextDefinition", "query", DotCompleteExpected ("(*D1*)","Length")) - ("AL7", "NoClosingBrace,NextDefinition", "query", QuickInfoExpected ("aaaaaa","val aaaaaa")) - ("AL7", "NoClosingBrace,NextDefinition", "query", QuickInfoExpected ("for bbbb","val bbbb")) - ("AL7", "NoClosingBrace,NextDefinition", "seq", DotCompleteExpected ("(*D1*)","Length")) - ("AL7", "NoClosingBrace,NextDefinition", "seq", QuickInfoExpected ("aaaaaa","val aaaaaa")) - ("AL7", "NoClosingBrace,NextDefinition", "seq", QuickInfoExpected ("for bbbb","val bbbb")) - ("AL10", "ClosingBrace", "query", AutoCompleteExpected ("(*C*)","bbbb")) - ("AL10", "ClosingBrace,NextDefinition", "query", AutoCompleteExpected ("(*C*)","bbbb")) - ("AL10", "Empty", "query", AutoCompleteExpected ("(*C*)","bbbb")) - ("AL10", "Empty", "seq", AutoCompleteExpected ("(*C*)","bbbb")) - ("AL10", "NoClosingBrace,NextDefinition", "query", AutoCompleteExpected ("(*C*)","bbbb")) - ("AL10", "NoClosingBrace,NextDefinition", "seq", AutoCompleteExpected ("(*C*)","bbbb")) - ("AL10", "NoClosingBrace,NextTypeDefinition", "query", AutoCompleteExpected ("(*C*)","bbbb")) - ("AL10", "NoClosingBrace,NextTypeDefinition", "seq", AutoCompleteExpected ("(*C*)","bbbb")) - ] - - this.WordByWordSystematicTestWithSpecificExpectations(prefix, suffixes, lines, ["seq";"query"], knownFailures) - - [] - /// Incrementally enter a seq{ .. while ...} loop and check for availability of intellisense etc. - member this.``SequenceExpressions.SequenceExprWithWhileLoopSystematic``() = - - let prefix = """ -module Test -let abbbbc = [| 1 |] -let aaaaaa = 0 -""" - let suffixes = - [ "Empty", ""; - "ClosingBrace", " }"; - "ClosingBrace,NextDefinition", " } \nlet nextDefinition () = 1\n"; - "NoClosingBrace,NextDefinition", " \nlet nextDefinition () = 1\n"; - "NoClosingBrace,NextTypeDefinition", " \ntype NextDefinition() = member x.P = 1\n" - ] - let lines b = - [ "BL1", "let f() = seq { while abb(*C*)" , [AC "(*C*)" "abbbbc"] - "BL2", "let f() = seq { while abbbbc(*D1*)" , [QI "while abbbbc" "val abbbbc"; DC "(*D1*)" "Length"] - "BL3", "let f() = seq { while abbbbc(*D1*) do (*C*)" , [QI "while abbbbc" "val abbbbc"; DC "(*D1*)" "Length"; AC "(*C*)" "abbbbc"] - "BL4", "let f() = seq { while abbbbc(*D1*) do abb(*C*)" , [QI "while abbbbc" "val abbbbc"; DC "(*D1*)" "Length"; AC "(*C*)" "abbbbc"] - "BL5", "let f() = seq { while abbbbc(*D1*) do abbbbc(*D2*)" , [QI "while abbbbc" "val abbbbc"; DC "(*D1*)" "Length"; QI "do abbbbc" "val abbbbc"; DC "(*D2*)" "Length"; ] - "BL6", "let f() = seq { while abbbbc(*D1*) do abbbbc.[(*C*)" , [QI "while abbbbc" "val abbbbc"; DC "(*D1*)" "Length"; QI "do abbbbc" "val abbbbc"; AC "(*C*)" "abbbbc"; AC "(*C*)" "aaaaaa"; ] - "BL7", "let f() = seq { while abbbbc(*D1*) do abbbbc.[aaa(*C*)" , [QI "while abbbbc" "val abbbbc"; DC "(*D1*)" "Length"; QI "do abbbbc" "val abbbbc"; AC "(*C*)" "aaaaaa"; ] - "BL7a", "let f() = seq { while abbbbc(*D1*) do abbbbc.[aaa(*C*)]" , [QI "while abbbbc" "val abbbbc"; DC "(*D1*)" "Length"; QI "do abbbbc" "val abbbbc"; AC "(*C*)" "aaaaaa"; ] - "BL7b", "let f() = seq { while abbbbc(*D1*) do abbbbc.[aaa(*C*)] <- " , [QI "while abbbbc" "val abbbbc"; DC "(*D1*)" "Length"; QI "do abbbbc" "val abbbbc"; AC "(*C*)" "aaaaaa"; ] - "BL7c", "let f() = seq { while abbbbc(*D1*) do abbbbc.[aaa(*C*)] <- 1" , [QI "while abbbbc" "val abbbbc"; DC "(*D1*)" "Length"; QI "do abbbbc" "val abbbbc"; AC "(*C*)" "aaaaaa"; ] - "BL7d", "let f() = seq { while abbbbc(*D1*) do abbbbc.[ (*C*) ] <- 1" , [QI "while abbbbc" "val abbbbc"; DC "(*D1*)" "Length"; QI "do abbbbc" "val abbbbc"; AC "(*C*)" "aaaaaa"; ] - "BL8", "let f() = seq { while abbbbc(*D1*) do abbbbc.[aaaaaa]" , [QI "while abbbbc" "val abbbbc"; DC "(*D1*)" "Length"; QI "do abbbbc" "val abbbbc"; ] - "BL9", "let f() = seq { while abbbbc(*D1*) do abbbbc.[aaaaaa] <- (*C*)" , [QI "while abbbbc" "val abbbbc"; DC "(*D1*)" "Length"; QI "do abbbbc" "val abbbbc"; AC "(*C*)" "abbbbc"; AC "(*C*)" "aaaaaa"; ] - "BL10", "let f() = seq { while abbbbc(*D1*) do abbbbc.[aaaaaa] <- aaa(*C*)" , [QI "while abbbbc" "val abbbbc"; DC "(*D1*)" "Length"; QI "do abbbbc" "val abbbbc"; AC "(*C*)" "aaaaaa"; ] ] - - let knownFailures = - [ - ] - this.WordByWordSystematicTestWithSpecificExpectations(prefix, suffixes, lines, [""], knownFailures) - [] - /// Incrementally enter query with a 'join' and check for availability of quick info, auto completion and dot completion - member this.``QueryAndOtherExpressions.WordByWordSystematicJoinQueryOnSingleLine``() = - - let prefix = """ -module Test -let abbbbc = [| 1 |] -let aaaaaa = 0 -""" - let suffixes = - [ "Empty", ""; - "ClosingBrace", " }"; - "ClosingBrace,NextDefinition", " } \nlet nextDefinition () = 1\n"; - "NoClosingBrace,NextDefinition", " \nlet nextDefinition () = 1\n"; - "NoClosingBrace,NextTypeDefinition", " \ntype NextDefinition() = member x.P = 1\n" - ] - let lines b = - [ "CL1", "let x = query { for bbbb in abbbbc(*D0*) do join " , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"] - "CL2", "let x = query { for bbbb in abbbbc(*D0*) do join cccc " , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"] - "CL2a", "let x = query { for bbbb in abbbbc(*D0*) do join cccc )" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"] - "CL3", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in " , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"] - "CL3a", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in )" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"] - "CL4", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in abbb(*C*)" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length";QI "join" "join"; AC "(*C*)" "abbbbc"] - "CL4a", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in abbb(*C*) )" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length";QI "join" "join"; AC "(*C*)" "abbbbc"] - "CL5", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in abbbbc(*D1*)" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"] - "CL5a", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in abbbbc(*D1*) )" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"] - "CL6", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in abbbbc(*D1*) on " , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"] - "CL6a", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in abbbbc(*D1*) on )" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"] - "CL6b", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in abbbbc(*D1*) on (bb(*C*)" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; AC "(*C*)" "bbbb"] - "CL7", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in abbbbc(*D1*) on (bbbb" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"] - "CL7a", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in abbbbc(*D1*) on (bbbb )" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"] - "CL8", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in abbbbc(*D1*) on (bbbb = " , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"] - "CL8a", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in abbbbc(*D1*) on (bbbb = )" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"] - "CL8b", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in abbbbc(*D1*) on (bbbb = cc(*C*)" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; AC "(*C*)" "cccc"] - "CL9", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in abbbbc(*D1*) on (bbbb(*D11*) = cccc(*D12*)" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; DC "(*D11*)" "CompareTo"; DC "(*D12*)" "CompareTo"] - "CL10", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in abbbbc(*D1*) on (bbbb(*D11*) = cccc(*D12*))" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; DC "(*D11*)" "CompareTo"; DC "(*D12*)" "CompareTo"] - "CL11", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in abbbbc(*D1*) on (bbbb(*D11*) = cccc(*D12*)); " , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; DC "(*D11*)" "CompareTo"; DC "(*D12*)" "CompareTo"] - "CL12", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in abbbbc(*D1*) on (bbbb(*D11*) = cccc(*D12*)); select" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; DC "(*D11*)" "CompareTo"; DC "(*D12*)" "CompareTo"] - "CL13", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in abbbbc(*D1*) on (bbbb(*D11*) = cccc(*D12*)); select (bb(*C*)" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; DC "(*D11*)" "CompareTo"; DC "(*D12*)" "CompareTo"] - "CL14", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in abbbbc(*D1*) on (bbbb(*D11*) = cccc(*D12*)); select (bbbb(*D2*)" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; DC "(*D2*)" "CompareTo"; DC "(*D11*)" "CompareTo"; DC "(*D12*)" "CompareTo"] - "CL15", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in abbbbc(*D1*) on (bbbb(*D11*) = cccc(*D12*)); select (bbbb(*D2*), " , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; DC "(*D2*)" "CompareTo"; DC "(*D11*)" "CompareTo"; DC "(*D12*)" "CompareTo"] - "CL16", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in abbbbc(*D1*) on (bbbb(*D11*) = cccc(*D12*)); select (bbbb(*D2*), cc(*C*)" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; DC "(*D2*)" "CompareTo"; AC "(*C*)" "cccc"; DC "(*D11*)" "CompareTo"; DC "(*D12*)" "CompareTo"] - "CL17", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in abbbbc(*D1*) on (bbbb(*D11*) = cccc(*D12*)); select (bbbb(*D2*), cccc(*D3*)" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; DC "(*D2*)" "CompareTo"; DC "(*D3*)" "CompareTo"; QI "(bbbb" "val bbbb"; QI ", cccc" "val cccc"; DC "(*D11*)" "CompareTo"; DC "(*D12*)" "CompareTo" ] - "CL18", "let x = query { for bbbb in abbbbc(*D0*) do join cccc in abbbbc(*D1*) on (bbbb(*D11*) = cccc(*D12*)); select (bbbb(*D2*), cccc(*D3*))" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; DC "(*D2*)" "CompareTo"; DC "(*D3*)" "CompareTo"; QI "(bbbb" "val bbbb"; QI ", cccc" "val cccc"; DC "(*D11*)" "CompareTo"; DC "(*D12*)" "CompareTo" ] ] - - let knownFailures = - [ - ] - - this.WordByWordSystematicTestWithSpecificExpectations(prefix, suffixes, lines, [""], knownFailures) - [] - /// This is a sanity check that the multiple-line case is much the same as the single-line case - member this.``QueryAndOtherExpressions.WordByWordSystematicJoinQueryOnMultipleLine``() = - - let prefix = """ -module Test -let abbbbc = [| 1 |] -let aaaaaa = 0 -""" - let suffixes = - [ "Empty", ""; - "ClosingBrace", " }"; - "ClosingBrace,NextDefinition", " } \nlet nextDefinition () = 1\n"; - "NoClosingBrace,NextDefinition", " \nlet nextDefinition () = 1\n"; - "NoClosingBrace,NextTypeDefinition", " \ntype NextDefinition() = member x.P = 1\n" - ] - let lines b = - [ "DL1", """ -let x = query { for bbbb in abbbbc(*D0*) do -join -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"] - "DL2", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"] - - "DL2a", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc ) -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"] - - "DL3", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"] - - "DL3a", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in ) -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"] - - "DL4", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in abbb(*C*) -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length";QI "join" "join"; AC "(*C*)" "abbbbc"] - - "DL4a", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in abbb(*C*) ) -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length";QI "join" "join"; AC "(*C*)" "abbbbc"] - - "DL5", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in abbbbc(*D1*) -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"] - - "DL5a", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in abbbbc(*D1*) ) -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"] - - "DL6", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in abbbbc(*D1*) on -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"] - - "L6a", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in abbbbc(*D1*) on ) -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"] - "L6b", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in abbbbc(*D1*) on (bb(*C*) -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; AC "(*C*)" "bbbb"] - "DL7", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in abbbbc(*D1*) on (bbbb -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"] - "DL7a", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in abbbbc(*D1*) on (bbbb ) -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"] - "DL8", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in abbbbc(*D1*) on (bbbb = -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"] - "DL8a", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in abbbbc(*D1*) on (bbbb = ) -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"] - "DL8b", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in abbbbc(*D1*) on (bbbb = cc(*C*) -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; AC "(*C*)" "cccc"] - "DL9", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in abbbbc(*D1*) on (bbbb(*D11*) = cccc(*D12*) -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; DC "(*D11*)" "CompareTo"; DC "(*D12*)" "CompareTo"] - "DL10", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in abbbbc(*D1*) on (bbbb(*D11*) = cccc(*D12*)) -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; DC "(*D11*)" "CompareTo"; DC "(*D12*)" "CompareTo"] - "DL11", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in abbbbc(*D1*) on (bbbb(*D11*) = cccc(*D12*)); -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; DC "(*D11*)" "CompareTo"; DC "(*D12*)" "CompareTo"] - "DL12", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in abbbbc(*D1*) on (bbbb(*D11*) = cccc(*D12*)); select -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; DC "(*D11*)" "CompareTo"; DC "(*D12*)" "CompareTo"] - "DL13", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in abbbbc(*D1*) on (bbbb(*D11*) = cccc(*D12*)); select (bb(*C*) -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; DC "(*D11*)" "CompareTo"; DC "(*D12*)" "CompareTo"] - "DL14", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in abbbbc(*D1*) on (bbbb(*D11*) = cccc(*D12*)); select (bbbb(*D2*) -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; DC "(*D2*)" "CompareTo"; DC "(*D11*)" "CompareTo"; DC "(*D12*)" "CompareTo"] - "DL15", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in abbbbc(*D1*) on (bbbb(*D11*) = cccc(*D12*)); select (bbbb(*D2*), -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; DC "(*D2*)" "CompareTo"; DC "(*D11*)" "CompareTo"; DC "(*D12*)" "CompareTo"] - "DL16", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in abbbbc(*D1*) on (bbbb(*D11*) = cccc(*D12*)); select (bbbb(*D2*), cc(*C*) -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; DC "(*D2*)" "CompareTo"; AC "(*C*)" "cccc"; DC "(*D11*)" "CompareTo"; DC "(*D12*)" "CompareTo"] - "DL17", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in abbbbc(*D1*) on (bbbb(*D11*) = cccc(*D12*)); select (bbbb(*D2*), cccc(*D3*) -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; DC "(*D2*)" "CompareTo"; DC "(*D3*)" "CompareTo"; QI "(bbbb" "val bbbb"; QI ", cccc" "val cccc"; DC "(*D11*)" "CompareTo"; DC "(*D12*)" "CompareTo" ] - "DL18", """ -let x = query { for bbbb in abbbbc(*D0*) do - join cccc in abbbbc(*D1*) on (bbbb(*D11*) = cccc(*D12*)); select (bbbb(*D2*), cccc(*D3*)) -""" , [QI "for bbbb" "val bbbb"; QI "in abbbbc" "val abbbbc"; DC "(*D0*)" "Length"; QI "join" "join"; DC "(*D1*)" "Length"; DC "(*D2*)" "CompareTo"; DC "(*D3*)" "CompareTo"; QI "(bbbb" "val bbbb"; QI ", cccc" "val cccc"; DC "(*D11*)" "CompareTo"; DC "(*D12*)" "CompareTo" ] ] - - let knownFailures = - - [ - //("DL2", "NoClosingBrace,NextDefinition", "", QuickInfoExpected ("for bbbb","val bbbb")) - //("DL2", "NoClosingBrace,NextDefinition", "", QuickInfoExpected ("in abbbbc","val abbbbc")) - //("DL2", "NoClosingBrace,NextDefinition", "", DotCompleteExpected ("(*D0*)","Length")) - //("DL2", "NoClosingBrace,NextDefinition", "", QuickInfoExpected ("join","join")) - ] - - - this.WordByWordSystematicTestWithSpecificExpectations(prefix, suffixes, lines, [""], knownFailures) - [] - /// This is the case where (*TYPING*) nothing has been typed yet and we invoke the completion list - /// This is a known failure right now for some of the example files above. - member this.``QueryExpression.CtrlSpaceSystematic2``() = - for fileContents in this.QueryExpressionFileExamples() do - - try - this.VerifyCtrlSpaceListContainAllAtStartOfMarker( - fileContents = fileContents, - marker = "(*TYPING*)", - list = customOperations, - addtlRefAssy=standard40AssemblyRefs ) - with _ -> - printfn "FAILURE on systematic test: fileContents = <<<%s>>>" fileContents - reraise() @@ -2675,101 +464,14 @@ let x = query { for bbbb in abbbbc(*D0*) do let completions = time1 CtrlSpaceCompleteAtCursor file "Time of first autocomplete." AssertCompListContainsAll(completions, expected) - [] - member public this.``Parameter.CommonCase.Bug2884``() = - this.AutoCompleteRecoveryTest - ([ - "type T1(aaa1) =" - " do (" ], "do (", [ "aaa1" ]) - [] - member public this.``Parameter.SubsequentLet.Bug2884``() = - this.AutoCompleteRecoveryTest - ([ - "type T1(aaa1) =" - " do (" - "let a = 0" ], "do (", [ "aaa1" ]) - [] - member public this.``Parameter.SubsequentMember.Bug2884``() = - this.AutoCompleteRecoveryTest - ([ - "type T1(aaa1) =" - " member x.Foo(aaa2) = " - " do (" - " member x.Bar = 0" ], "do (", [ "aaa1"; "aaa2" ]) - - [] - member public this.``Parameter.System.DateTime.Bug2884``() = - this.AutoCompleteRecoveryTest - ([ - "type T1(aaa1) =" - " member x.Foo(aaa2) = " - " let dt = new System.DateTime(" ], "Time(", [ "aaa1"; "aaa2" ]) - [] - member public this.``Parameter.DirectAfterDefined.Bug2884``() = - this.AutoCompleteRecoveryTest - ([ - "if true then" - " let aaa1 = 0" - " (" ], "(", [ "aaa1" ]) - [] - member public this.``NotShowInfo.LetBinding.Bug3602``() = - this.VerifyAutoCompListIsEmptyAtEndOfMarker( - fileContents = "let s. = \"Hello world\" - ()", - marker = "let s.") - [] - member public this.``NotShowInfo.FunctionParameter.Bug3602``() = - this.VerifyAutoCompListIsEmptyAtEndOfMarker( - fileContents = "let foo s. = s + \"Hello world\" - ()", - marker = "let foo s.") - - [] - member public this.``NotShowInfo.ClassMemberDeclA.Bug3602``() = - this.TestCompletionNotShowingWhenFastUpdate - [ - "type Foo() =" - " member this.Func (x, y) = ()" - " member (*marker*) this.Prop = 10" - "()" ] - [ - "type Foo() =" - " member this.Func (x, y) = ()" - " member (*marker*) this." - "()" ] - "(*marker*) this." // Another test case for the same thing - this goes through a different code path - [] - member public this.``NotShowInfo.ClassMemberDeclB.Bug3602``() = - this.TestCompletionNotShowingWhenFastUpdate - [ - "type Foo() =" - " member this.Func (x, y) = ()" - " // marker$" // <- trick to move the cursor to the right location before source replacement - "()" ] - [ - "type Foo() =" - " member this.Func (x, y) = ()" - " member this." - "()" ] - "marker$" - [] - member public this.``ComputationExpression.LetBang``() = - AssertAutoCompleteContainsNoCoffeeBreak - ["let http(url:string) = " - " async { " - " let rnd = new System.Random()" - " let! rsp = rnd.N" ] - "rsp = rnd." - ["Next"] - [] (* Tests for autocomplete -------------------------------------------------------------- *) @@ -2792,948 +494,75 @@ let x = query { for bbbb in abbbbc(*D0*) do AssertCompListContainsAll(completions, expected) gpatcc.AssertExactly(0,0) - [] - member public this.``Generics.Typeof``() = - this.TestGenericAutoComplete ("let _ = typeof.", [ "Assembly"; "AssemblyQualifiedName"; (* ... *) ]) - [] - member public this.``Generics.NonGenericTypeMembers``() = - this.TestGenericAutoComplete ("let _ = GT2.", [ "R"; "S" ]) - [] - member public this.``Generics.GenericTypeMembers``() = - this.TestGenericAutoComplete ("let _ = GT.", [ "P"; "Q" ]) - //[] // keep disabled unless trying to prove that UnhandledExceptionHandler is working - member public this.EnsureThatUnhandledExceptionsCauseAnAssert() = - // Do something that causes LanguageService to load - AssertAutoCompleteContains - [ - "type FooBuilder() =" - " member x.Return(a) = new System.Random()" - "let foo = FooBuilder()" - "(foo { return 0 })." ] - "})." // marker - [ "Next" ] // should contain - [ "GetEnumerator" ] // should not contain - // kaboom - let t = new System.Threading.Thread(new System.Threading.ThreadStart(fun () -> failwith "foo")) - t.Start() - System.Threading.Thread.Sleep(1000) - - [] - member public this.``GenericType.Self.Bug69673_1.01``() = - AssertCtrlSpaceCompleteContains - ["type Base(o:obj) = class end" - "type Foo() as this =" - " inherit Base(this) // this" - " let o = this // this ok" - " do this.Bar() // this ok, dotting ok" - " member this.Bar() = ()" ] - "Base(th" - ["this"] - [] - [] - member public this.``GenericType.Self.Bug69673_1.02``() = - AssertCtrlSpaceCompleteContains - ["type Base(o:obj) = class end" - "type Foo() as this =" - " inherit Base(this) // this" - " let o = this // this ok" - " do this.Bar() // this ok, dotting ok" - " member this.Bar() = ()" ] - "o = th" - ["this"] - [] - [] - member public this.``GenericType.Self.Bug69673_1.03``() = - AssertCtrlSpaceCompleteContains - ["type Base(o:obj) = class end" - "type Foo() as this =" - " inherit Base(this) // this" - " let o = this // this ok" - " do this.Bar() // this ok, dotting ok" - " member this.Bar() = ()" ] - "do th" - ["this"] - [] - [] - member public this.``GenericType.Self.Bug69673_1.04``() = - AssertAutoCompleteContains - ["type Base(o:obj) = class end" - "type Foo() as this =" - " inherit Base(this) // this" - " let o = this // this ok" - " do this.Bar() // this ok, dotting ok" - " member this.Bar() = ()" ] - "do this." - ["Bar"] - [] - - [] - member public this.``GenericType.Self.Bug69673_2.1``() = - AssertAutoCompleteContains - ["type Base(o:obj) = class end" - "type Food() as this =" - " class" - " inherit Base(this) // this" - " do" - " this |> ignore // this (only repros with explicit class/end)" - " end" ] - "Base(th" - ["this"] - [] + + - [] - member public this.``GenericType.Self.Bug69673_2.2``() = - AssertAutoCompleteContains - ["type Base(o:obj) = class end" - "type Food() as this =" - " class" - " inherit Base(this) // this" - " do" - " this |> ignore // this (only repros with explicit class/end)" - " end" ] - " th" - ["this"] - [] - [] - member public this.``UnitMeasure.Bug78932_1``() = - AssertAutoCompleteContains - [ @" - module M1 = - [] type Kg - - module M2 = - let f = 1 // <- type . between M1 and ' >' => works" ] - "M1." // marker - [ "Kg" ] // should contain - [ ] // should not contain - [] - member public this.``UnitMeasure.Bug78932_2``() = - // Note: in this case, pressing '.' does not automatically pop up a completion list in VS, but ctrl-space does get the right list - // This is just like how - // let y = true.>"trueSuffix" // no popup on dot, but ctrl-space brings up list with ToString that is legal completion - // works, the issue is ".>" is seen as an operator and not a dot-for-completion. - AssertAutoCompleteContains - [ @" - module M1 = - [] type Kg - - module M2 = - let f = 1 // <- type . between M1 and '>' => no popup intellisense" ] - "M1." // marker - [ "Kg" ] // should contain - [ ] // should not contain - [] - member public this.``Array.AfterOperator...Bug65732_A``() = - AssertAutoCompleteContains - [ "let r = [1 .. System.Int32.MaxValue]" ] - "System." // marker - [ "Int32" ] // should contain - [ "abs" ] // should not contain (from top level) - [] - member public this.``Array.AfterOperator...Bug65732_B``() = - AssertCtrlSpaceCompleteContains - [ "let r = [System.Int32.MaxValue..42]" ] - ".." // marker - [ "abs" ] // should contain (top level) - [ "CompareTo" ] // should not contain (from Int32) - [] - member public this.``Array.AfterOperator...Bug65732_B2``() = - AssertCtrlSpaceCompleteContains - [ "let r = [System.Int32.MaxValue.. 42]" ] - ".." // marker - [ "abs" ] // should contain (top level) - [ "CompareTo" ] // should not contain (from Int32) - [] - member public this.``Array.AfterOperator...Bug65732_B3``() = - AssertCtrlSpaceCompleteContains - [ "let r = [System.Int32.MaxValue .. 42]" ] - ".." // marker - [ "abs" ] // should contain (top level) - [ "CompareTo" ] // should not contain (from Int32) - - [] - member public this.``Array.AfterOperator...Bug65732_C``() = - AssertCtrlSpaceCompleteContains - [ "let r = [System.Int32.MaxValue..]" ] - ".." // marker - [ "abs" ] // should contain (top level) - [ "CompareTo" ] // should not contain (from Int32) - - [] - member public this.``Array.AfterOperator...Bug65732_D``() = - AssertCtrlSpaceCompleteContains - [ "let r = [System.Int32.MaxValue .. ]" ] - ".." // marker - [ "abs" ] // should contain (top level) - [ "CompareTo" ] // should not contain (from Int32) - [] - member public this.``Identifier.FuzzyDefined.Bug67133``() = - AssertAutoCompleteContainsNoCoffeeBreak - [ "let gDateTime (arr: System.DateTime[]) =" - " arr.[0]." ] - "arr.[0]." - ["AddDays"] - [] - - [] - member public this.``Identifier.FuzzyDefined.Bug67133.Negative``() = - let code = [ "let gDateTime (arr: DateTime[]) =" // Note: no 'open System', so DateTime is unknown - " arr.[0]." ] - let (_, _, file) = this.CreateSingleFileProject(code) - TakeCoffeeBreak(this.VS) - let gpatcc = GlobalParseAndTypeCheckCounter.StartNew(this.VS) - MoveCursorToEndOfMarker(file, "arr.[0].") - let completions = AutoCompleteAtCursor file - AssertCompListContainsExactly(completions, []) // we don't want any completions on . when has unknown type due to errors - // (In particular, we don't want the "didn't find any completions, so just show top-level entities like 'abs' here" logic to kick in.) - [] - member public this.``Class.Property.Bug69150_A``() = - AssertCtrlSpaceCompleteContains - [ "type ClassType(x : int) =" - " member this.Value = x" - "let z = (new ClassType(23)).Value" ] - "))." // marker - [ "Value" ] // should contain - [ "CompareTo" ] // should not contain (from Int32) - [] - member public this.``Class.Property.Bug69150_B``() = - AssertCtrlSpaceCompleteContains - [ "type ClassType(x : int) =" - " member this.Value = x" - "let z = ClassType(23).Value" ] - "3)." // marker - [ "Value" ] // should contain - [ "CompareTo" ] // should not contain (from Int32) - [] - member public this.``Class.Property.Bug69150_C``() = - AssertCtrlSpaceCompleteContains - [ "type ClassType(x : int) =" - " member this.Value = x" - "let f x = new ClassType(x)" - "let z = f(23).Value" ] - "3)." // marker - [ "Value" ] // should contain - [ "CompareTo" ] // should not contain (from Int32) - [] - member public this.``Class.Property.Bug69150_D``() = - AssertCtrlSpaceCompleteContains - [ "type ClassType(x : int) =" - " member this.Value = x" - "let z = ClassType(23).Value" ] - "3).V" // marker - [ "Value" ] // should contain - [ "VolatileFieldAttribute" ] // should not contain (from top-level) - [] - member public this.``Class.Property.Bug69150_E``() = - AssertCtrlSpaceCompleteContains - [ "type ClassType(x : int) =" - " member this.Value = x" - "let z = ClassType(23) . Value" ] - "3) . " // marker - [ "Value" ] // should contain - [ "VolatileFieldAttribute" ] // should not contain (from top-level) - [] - member public this.``AssignmentToProperty.Bug231283``() = - AssertCtrlSpaceCompleteContains - [""" - type Foo() = - member val Bar = 0 with get,set - - let f = new Foo() - f.Bar <- - let xyz = 42 (*Mark*) - xyz """] - "42 " - [ "AbstractClassAttribute" ] // top-level completions - [ "Bar" ] // not stuff from the lhs of assignment - [] - member public this.``Dot.AfterOperator.Bug69159``() = - AssertAutoCompleteContains - [ "let x1 = [|0..1..10|]." ] - "]." // marker - [ "Length" ] // should contain (array) - [ "abs" ] // should not contain (top-level) - [] - member public this.``Residues1``() = - AssertCtrlSpaceCompleteContains - [ "System . Int32 . M" ] - "M" // marker - [ "MaxValue"; "MinValue" ] // should contain - [ "MailboxProcessor"; "Map" ] // should not contain (top-level) - [] - member public this.``Residues2``() = - AssertCtrlSpaceCompleteContains - [ "let x = 42" - "x . C" ] - "C" // marker - [ "CompareTo" ] // should contain (Int32) - [ "CLIEventAttribute"; "Checked"; "Choice" ] // should not contain (top-level) - [] - member public this.``Residues3``() = - AssertCtrlSpaceCompleteContains - [ "let x = 42" - "x . " ] - ". " // marker - [ "CompareTo" ] // should contain (Int32) - [ "CLIEventAttribute"; "Checked"; "Choice" ] // should not contain (top-level) - [] - member public this.``Residues4``() = - AssertCtrlSpaceCompleteContains - [ "let x = 42" - "id(x) . C" ] - "C" // marker - [ "CompareTo" ] // should contain (Int32) - [ "CLIEventAttribute"; "Checked"; "Choice" ] // should not contain (top-level) - [] - member public this.``CtrlSpaceInWhiteSpace.Bug133112``() = - AssertCtrlSpaceCompleteContains - [ """ - type Foo = - static member A = 1 - static member B = 2 - - printfn "%d %d" Foo.A """ ] - "Foo.A " // marker - [ "AbstractClassAttribute" ] // should contain (top-level) - [ "A"; "B" ] // should not contain (Foo) - [] - member public this.``Residues5``() = - AssertCtrlSpaceCompleteContains - [ "let x = 42" - "id(x) . " ] - ". " // marker - [ "CompareTo" ] // should contain (Int32) - [ "CLIEventAttribute"; "Checked"; "Choice" ] // should not contain (top-level) - [] - member public this.``CompletionInDifferentEnvs1``() = - AssertCtrlSpaceCompleteContains - ["let f1 num =" - " let rec completeword d =" - " d + d" - "(**)comple"] - "(**)comple" // marker - ["completeword"] // should contain - [""] - [] - member public this.``CompletionInDifferentEnvs2``() = - AssertCtrlSpaceCompleteContains - ["let aaa = 1" - "let aab = 2" - "(aa" - "let aac = 3"] - "(aa" - ["aaa"; "aab"] - ["aac"] - [] - member public this.``CompletionInDifferentEnvs3``() = - AssertCtrlSpaceCompleteContains - ["let mb1 = new MailboxProcessor>(fun inbox -> async { let! msg = inbox.Receive()" - " do "] - "do " - ["msg"] - [] - [] - member public this.``CompletionInDifferentEnvs4``() = - AssertCtrlSpaceCompleteContains - ["async {" - " let! x = i" - " (" - "}"] - "(" - ["x"] - [] - AssertCtrlSpaceCompleteContains - ["let q = " - " let a = 20" - " let b = (fun i -> i) 40" - " (("] - "((" - ["b"] - ["i"] - [] - member public this.``CompletionForAndBang_BaseLine0``() = - AssertCtrlSpaceCompleteContains - ["type Builder() =" - " member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a" - " member x.Return(a: 'T) = a" - "let builder = Builder()" - "builder {" - " let! xxx3 = 2" - " return x" - "}"] - " return x" - ["xxx3"] - [] - [] - member public this.``CompletionForAndBang_BaseLine1``() = - AssertCtrlSpaceCompleteContains - ["type Builder() =" - " member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a" - " member x.Return(a: 'T) = a" - "let builder = Builder()" - "let xxx1 = 1" - "builder {" - " let xxx2 = 1" - " let! xxx3 = 1" - " return (1 + x)" - "}"] - " return (1 + x" - ["xxx1"; "xxx2"; "xxx3"] - [] - [] - member public this.``CompletionForAndBang_BaseLine2``() = - /// Without closing '}' - AssertCtrlSpaceCompleteContains - ["type Builder() =" - " member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a" - " member x.Return(a: 'T) = a" - "let builder = Builder()" - "let yyy1 = 1" - "builder {" - " let yyy2 = 1" - " let! yyy3 = 1" - " return (1 + y)"] - " return (1 + y" - ["yyy1"; "yyy2"; "yyy3"] - [] - [] - member public this.``CompletionForAndBang_BaseLine3``() = - /// Without closing ')' - AssertCtrlSpaceCompleteContains - ["type Builder() =" - " member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a" - " member x.Return(a: 'T) = a" - "let builder = Builder()" - "let zzz1 = 1" - "builder {" - " let zzz2 = 1" - " let! zzz3 = 1" - " return (1 + z" ] - " return (1 + z" - ["zzz1"; "zzz2"; "zzz3"] - [] - [] - member public this.``CompletionForAndBang_BaseLine4``() = - AssertCtrlSpaceCompleteContains - ["type Builder() =" - " member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a" - " member x.Return(a: 'T) = a" - "let builder = Builder()" - "let zzz1 = 1" - "builder {" - " let! zzz3 = 1" - " return (1 + z" ] - " return (1 + z" - ["zzz1"; "zzz3"] - [] - [] - member public this.``CompletionForAndBang_Test_MergeSources_Bind_Return0``() = - AssertCtrlSpaceCompleteContainsWithOtherFlags - "/langversion:preview" - ["type Builder() =" - " member x.MergeSources(a: 'T1, b: 'T2) = (a, b)" - " member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a" - " member x.Return(a: 'T) = a" - "let builder = Builder()" - "builder {" - " let! xxx3 = 2" - " and! xxx4 = 2" - " return x" - "}"] - " return x" - ["xxx3"; "xxx4"] - [] - [] - member public this.``CompletionForAndBang_Test_MergeSources_Bind_Return1``() = - AssertCtrlSpaceCompleteContainsWithOtherFlags - "/langversion:preview" - ["type Builder() =" - " member x.MergeSources(a: 'T1, b: 'T2) = (a, b)" - " member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a" - " member x.Return(a: 'T) = a" - "let builder = Builder()" - "let xxx1 = 1" - "builder {" - " let xxx2 = 1" - " let! xxx3 = 1" - " and! xxx4 = 1" - " return (1 + x)" - "}"] - " return (1 + x" - ["xxx1"; "xxx2"; "xxx3"; "xxx4"] - [] - [] - member public this.``CompletionForAndBang_Test_MergeSources_Bind_Return2``() = - AssertCtrlSpaceCompleteContainsWithOtherFlags - "/langversion:preview" - ["type Builder() =" - " member x.MergeSources(a: 'T1, b: 'T2) = (a, b)" - " member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a" - " member x.Return(a: 'T) = a" - "let builder = Builder()" - "let yyy1 = 1" - "builder {" - " let yyy2 = 1" - " let! yyy3 = 1" - " and! yyy4 = 1" - " return (1 + y)"] - " return (1 + y" - ["yyy1"; "yyy2"; "yyy3"; "yyy4"] - [] - [] - member public this.``CompletionForAndBang_Test_MergeSources_Bind_Return3``() = - AssertCtrlSpaceCompleteContainsWithOtherFlags - "/langversion:preview" - ["type Builder() =" - " member x.MergeSources(a: 'T1, b: 'T2) = (a, b)" - " member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a" - " member x.Return(a: 'T) = a" - "let builder = Builder()" - "let zzz1 = 1" - "builder {" - " let zzz2 = 1" - " let! zzz3 = 1" - " and! zzz4 = 1" - " return (1 + z" ] - " return (1 + z" - ["zzz1"; "zzz2"; "zzz3"; "zzz4"] - [] - [] - member public this.``CompletionForAndBang_Test_MergeSources_Bind_Return4``() = - AssertCtrlSpaceCompleteContainsWithOtherFlags - "/langversion:preview" - ["type Builder() =" - " member x.MergeSources(a: 'T1, b: 'T2) = (a, b)" - " member x.Bind(a: 'T1, f: 'T1 -> 'T2) = f a" - " member x.Return(a: 'T) = a" - "let builder = Builder()" - "let zzz1 = 1" - "builder {" - " let! zzz3 = 1" - " and! zzz4 = 1" - " return (1 + z" ] - " return (1 + z" - ["zzz1"; "zzz3"; "zzz4"] - [] - [] - member public this.``CompletionForAndBang_Test_Bind2Return0``() = - AssertCtrlSpaceCompleteContainsWithOtherFlags - "/langversion:preview" - ["type Builder() =" - " member x.Bind2Return(a: 'T1, b: 'T2, f: ('T1 * 'T2) -> 'T3) = f (a, b)" - "let builder = Builder()" - "builder {" - " let! xxx3 = 2" - " and! xxx4 = 2" - " return x" - "}"] - " return x" - ["xxx3"; "xxx4"] - [] - [] - member public this.``CompletionForAndBang_Test_Bind2Return1``() = - AssertCtrlSpaceCompleteContainsWithOtherFlags - "/langversion:preview" - ["type Builder() =" - " member x.Bind2Return(a: 'T1, b: 'T2, f: ('T1 * 'T2) -> 'T3) = f (a, b)" - "let builder = Builder()" - "let xxx1 = 1" - "builder {" - " let xxx2 = 1" - " let! xxx3 = 1" - " and! xxx4 = 1" - " return (1 + x)" - "}"] - " return (1 + x" - ["xxx1"; "xxx2"; "xxx3"; "xxx4"] - [] - [] - member public this.``CompletionForAndBang_Test_Bind2Return2``() = - AssertCtrlSpaceCompleteContainsWithOtherFlags - "/langversion:preview" - ["type Builder() =" - " member x.Bind2Return(a: 'T1, b: 'T2, f: ('T1 * 'T2) -> 'T3) = f (a, b)" - "let builder = Builder()" - "let yyy1 = 1" - "builder {" - " let yyy2 = 1" - " let! yyy3 = 1" - " and! yyy4 = 1" - " return (1 + y)"] - " return (1 + y" - ["yyy1"; "yyy2"; "yyy3"; "yyy4"] - [] - [] - member public this.``CompletionForAndBang_Test_Bind2Return3``() = - AssertCtrlSpaceCompleteContainsWithOtherFlags - "/langversion:preview" - ["type Builder() =" - " member x.Bind2Return(a: 'T1, b: 'T2, f: ('T1 * 'T2) -> 'T3) = f (a, b)" - "let builder = Builder()" - "let zzz1 = 1" - "builder {" - " let zzz2 = 1" - " let! zzz3 = 1" - " and! zzz4 = 1" - " return (1 + z" ] - " return (1 + z" - ["zzz1"; "zzz2"; "zzz3"; "zzz4"] - [] - [] - member public this.``CompletionForAndBang_Test_Bind2Return4``() = - AssertCtrlSpaceCompleteContainsWithOtherFlags - "/langversion:preview" - ["type Builder() =" - " member x.Bind2Return(a: 'T1, b: 'T2, f: ('T1 * 'T2) -> 'T3) = f (a, b)" - "let builder = Builder()" - "let zzz1 = 1" - "builder {" - " let! zzz3 = 1" - " and! zzz4 = 1" - " return (1 + z" ] - " return (1 + z" - ["zzz1"; "zzz3"; "zzz4"] - [] (**) - [] - member public this.``Bug229433.AfterMismatchedParensCauseWeirdParseTreeAndExceptionDuringTypecheck``() = - AssertAutoCompleteContains [ """ - type T() = - member this.Bar() = () - member val X = "foo" with get,set - static member Id(x) = x - - [1] - |> Seq.iter (fun x -> - let user = x - ["foo"] - |> List.iter (fun m -> - let xyz = new T() - xyz.X <- null - T.Id((*here*)xyz. // no intellisense here after . - ) - printfn "" - ) """ ] - "(*here*)xyz." - [ "Bar"; "X" ] - [] - - [] - member public this.``Bug130733.LongIdSet.CtrlSpace``() = - AssertCtrlSpaceCompleteContains [ """ - type C() = - member this.XX with get() = 4 and set(x) = () - - let c = C() - c.X <- 42""" ] - "c.X" - [ "XX" ] - [] - - [] - member public this.``Bug130733.LongIdSet.Dot``() = - AssertAutoCompleteContains [ """ - type C() = - member this.XX with get() = 4 and set(x) = () - - let c = C() - c.X <- 42""" ] - "c." - [ "XX" ] - [] - [] - member public this.``Bug130733.ExprDotSet.CtrlSpace``() = - AssertCtrlSpaceCompleteContains [ """ - type C() = - member this.XX with get() = 4 and set(x) = () - - let f(x) = C() - f(0).X <- 42""" ] - ").X" - [ "XX" ] - [] - - [] - member public this.``Bug130733.ExprDotSet.Dot``() = - AssertAutoCompleteContains [ """ - type C() = - member this.XX with get() = 4 and set(x) = () - - let f(x) = C() - f(0).X <- 42""" ] - "(0)." - [ "XX" ] - [] - - - [] - member public this.``Bug130733.Nested.LongIdSet.CtrlSpace``() = - AssertCtrlSpaceCompleteContains [ """ - type C() = - member this.XX with get() = 4 and set(x) = () - member this.CC with get() = C() - - let c = C() - c.CC.X <- 42""" ] - "CC.X" - [ "XX" ] - [] - [] - member public this.``Bug130733.Nested.LongIdSet.Dot``() = - AssertAutoCompleteContains [ """ - type C() = - member this.XX with get() = 4 and set(x) = () - member this.CC with get() = C() - - let c = C() - c.CC.X <- 42""" ] - "c.CC." - [ "XX" ] - [] - - [] - member public this.``Bug130733.Nested.ExprDotSet.CtrlSpace``() = - AssertCtrlSpaceCompleteContains [ """ - type C() = - member this.XX with get() = 4 and set(x) = () - member this.CC with get() = C() - - let f(x) = C() - f(0).CC.X <- 42""" ] - "CC.X" - [ "XX" ] - [] - - [] - member public this.``Bug130733.Nested.ExprDotSet.Dot``() = - AssertAutoCompleteContains [ """ - type C() = - member this.XX with get() = 4 and set(x) = () - member this.CC with get() = C() - - let f(x) = C() - f(0).CC.X <- 42""" ] - "(0).CC." - [ "XX" ] - [] - [] - member public this.``Bug130733.NamedIndexedPropertyGet.Dot``() = - AssertAutoCompleteContains [ """ - let str = "foo" - str.Chars(3).""" ] - ")." - [ "CompareTo" ] // char - [] - [] - member public this.``Bug130733.NamedIndexedPropertyGet.CtrlSpace``() = - AssertCtrlSpaceCompleteContains [ """ - let str = "foo" - str.Chars(3).Co""" ] - ").Co" - [ "CompareTo" ] // char - [] - [] - member public this.``Bug230533.NamedIndexedPropertySet.CtrlSpace.Case1``() = - AssertCtrlSpaceCompleteContains [ """ - type Foo() = - member x.MutableInstanceIndexer - with get (i) = 0 - and set (i) (v:string) = () - - let h() = new Foo() - (h()).MutableInstanceIndexer(0) <- "foo" """ ] - ")).Muta" - [ "MutableInstanceIndexer" ] - [] - [] - member public this.``Bug230533.NamedIndexedPropertySet.CtrlSpace.Case2``() = - AssertCtrlSpaceCompleteContains [ """ - type Foo() = - member x.MutableInstanceIndexer - with get (i) = 0 - and set (i) (v:string) = () - type Bar() = - member this.ZZZ = new Foo() - - let g() = new Bar() - (g()).ZZZ.MutableInstanceIndexer(0) <- "blah" """ ] - ")).ZZZ.Muta" - [ "MutableInstanceIndexer" ] - [] - [] - member public this.``Bug230533.ExprDotSet.CtrlSpace.Case1``() = - AssertCtrlSpaceCompleteContains [ """ - type C() = - member this.XX with get() = 4 and set(x) = () - type D() = - member this.CC = new C() - let f(x) = D() - f(0).CC. <- 42 """ ] - "0).CC." - [ "XX" ] - [] - [] - member public this.``Bug230533.ExprDotSet.CtrlSpace.Case2``() = - AssertCtrlSpaceCompleteContains [ """ - type C() = - member this.XX with get() = 4 and set(x) = () - type D() = - member this.CC with get() = new C() and set(x) = () - let f(x) = D() - f(0).CC. <- 42 """ ] - "0).CC." - [ "XX" ] - [] - [] - member public this.``Attribute.WhenAttachedToLet.Bug70080``() = - this.AutoCompleteBug70080Helper @" - open System - [] - member public this.``Attribute.WhenAttachedToType.Bug70080``() = - this.AutoCompleteBug70080Helper(@" - open System - [] - member public this.``Attribute.WhenAttachedToLetInNamespace.Bug70080``() = - this.AutoCompleteBug70080Helper @" - namespace Foo - open System - [] - member public this.``Attribute.WhenAttachedToTypeInNamespace.Bug70080``() = - this.AutoCompleteBug70080Helper(@" - namespace Foo - open System - [] - member public this.``Attribute.WhenAttachedToNothingInNamespace.Bug70080``() = - this.AutoCompleteBug70080Helper(@" - namespace Foo - open System - [] - member public this.``Attribute.WhenAttachedToModuleInNamespace.Bug70080``() = - this.AutoCompleteBug70080Helper(@" - namespace Foo - open System - [] - member public this.``Attribute.WhenAttachedToModule.Bug70080``() = - this.AutoCompleteBug70080Helper(@" - open System - [] - member public this.``Identifer.InMatchStatement.Bug72595``() = - // in this bug, "match blah with let" caused the lexfilter to go awry, which made things hopeless for the parser, yielding no parse tree and thus no intellisense - AssertAutoCompleteContains - [ @" - type C() = - let someValue = ""abc"" - member _.M() = - let x = 1 - match someValue. with - let x = 1 - match 1 with - | _ -> 2 - - type D() = - member x.P = 1 - - [] - do() - " ] - "someValue." // marker - [ "Chars" ] // should contain - [ ] // should not contain - [] - member public this.``HandleInlineComments1``() = - AssertAutoCompleteContains - [ "let rrr = System (* boo! *) . Int32 . MaxValue" ] - ") ." // marker - [ "Int32"] - [ "abs" ] // should not contain (top-level) - [] - member public this.``HandleInlineComments2``() = - AssertAutoCompleteContains - [ "let rrr = System (* boo! *) . Int32 . MaxValue" ] - "2 ." // marker - [ "MaxValue" ] // should contain - [ "abs" ] // should not contain (top-level) [] member public this.``OpenNamespaceOrModule.CompletionOnlyContainsNamespaceOrModule.Case1``() = @@ -3743,209 +572,15 @@ let x = query { for bbbb in abbbbc(*D0*) do [ "Collections" ] // should contain (namespace) [ ] // should not contain - [] - member public this.``OpenNamespaceOrModule.CompletionOnlyContainsNamespaceOrModule.Case2``() = - AssertAutoCompleteContains - [ "open Microsoft.FSharp.Collections.Array." ] - "Array." // marker - [ "Parallel" ] // should contain (module) - [ "map" ] // should not contain (let-bound value) - - [] - member public this.``BY_DESIGN.CommonScenarioThatBegsTheQuestion.Bug73940``() = - AssertAutoCompleteContains - [ @" - let r = - [""1""] - |> List.map (fun s -> s. // user previous had e.g. '(fun s -> s)' here, but he erased after 's' to end-of-line and hit '.' e.g. to eventually type '.Substring(5))' - |> List.filter (fun s -> s.Length > 5) // parser recover assumes close paren is here, and type inference goes wacky-useless with such a parse - "] - "s." // marker - [ ] // should contain (ideally would be string) - [ "Chars" ] // should not contain (documenting the undesirable behavior, that this does not show up) - - [] - member public this.``BY_DESIGN.ExplicitlyCloseTheParens.Bug73940``() = - AssertAutoCompleteContains - [ @" - let g lam = - lam true |> printfn ""%b"" - sprintf ""%s"" - let r = - [""1""] - |> List.map (fun s -> s. ) // user types close paren here to avoid paren mismatch - |> g // regardless of whatever is down here now, it won't affect the type of 's' above - "] - "s." // marker - [ "Chars" ] // should contain (string) - [ ] // should not contain - - [] - member public this.``BY_DESIGN.MismatchedParenthesesAreHardToRecoverFromAndHereIsWhy.Bug73940``() = - AssertAutoCompleteContains - [ @" - let g lam = - lam true |> printfn ""%b"" - sprintf ""%s"" - let r = - [""1""] - |> List.map (fun s -> s. // it looks like s is a string here, but it's not! - |> g // parser recovers as though there is a right-paren here - "] - "s." // marker - [ "CompareTo" ] // should contain (bool) - [ "Chars" ] // should not contain (string) - -(* - [] - member public this.``AutoComplete.Bug72596_A``() = - AssertAutoCompleteContains - [ "type ClassType() =" - " let foo = fo" ] // is not 'let rec', foo should not be in scope yet, but showed up in completions - "= fo" // marker - [ ] // should contain - [ "foo" ] // should not contain - - - [] - member public this.``AutoComplete.Bug72596_B``() = - AssertAutoCompleteContains - [ "let f() =" - " let foo = fo" ] // is not 'let rec', foo should not be in scope yet, but showed up in completions - "= fo" // marker - [ ] // should contain - [ "foo" ] // should not contain -*) - - [] - member public this.``Expression.MultiLine.Bug66705``() = - AssertAutoCompleteContains - [ "let x = 4" - "let y = x.GetType()" - " .ToString()" ] // "fluent" interface spanning multiple lines - " ." // marker - [ "ToString" ] // should contain - [ ] // should not contain - - [] - member public this.``Expressions.Computation``() = - AssertAutoCompleteContains - [ - "type FooBuilder() =" - " member x.Return(a) = new System.Random()" - "let foo = FooBuilder()" - "(foo { return 0 })." ] - "})." // marker - [ "Next" ] // should contain - [ "GetEnumerator" ] // should not contain - [] - member public this.``Identifier.DefineByVal.InFsiFile.Bug882304_1``() = - AutoCompleteInInterfaceFileContains - [ - "module BasicTest" - "val z:int = 1" - "z." - ] - "z." // marker - [ ] // should contain - [ "Equals" ] // should not contain - [] - member public this.``NameSpace.InFsiFile.Bug882304_2``() = - AutoCompleteInInterfaceFileContains - [ - "module BasicTest" - "open System." - ] - "System." // marker - [ "Action"; // Delegate - "Activator"; // Class - "Collections"; // Subnamespace - "IConvertible" // Interface - ] // should contain - [ ] // should not contain - [] - member public this.``CLIEvents.DefinedInAssemblies.Bug787438``() = - AssertAutoCompleteContains - [ "let mb = new MailboxProcessor(fun _ -> ())" - "mb." ] - "mb." // marker - [ "Error" ] // should contain - [ "add_Error"; "remove_Error" ] // should not contain - [] - member public this.CLIEventsWithByRefArgs() = - AssertAutoCompleteContains - [ "type MyDelegate = delegate of obj * string byref -> unit" - "type mytype() = [] member this.myEvent = (new DelegateEvent()).Publish" - "let t = mytype()" - "t." ] - "t." // marker - [ "add_myEvent"; "remove_myEvent" ] // should contain - [ "myEvent" ] // should not contain - [] - member public this.``Identifier.AfterParenthesis.Bug835276``() = - AssertAutoCompleteContains - [ "let f ( s : string ) =" - " let x = 10 + s.Length" - " for i in 1..10 do" - " let ok = 10 + s.Length // dot here did work" - " let y = 10 +(s." ] - "+(s." // marker - [ "Length" ] // should contain - [ ] // should not contain - [] - member public this.``Identifier.AfterParenthesis.Bug6484_1``() = - AssertAutoCompleteContains - [ "for x in 1..10 do" - " printfn \"%s\" (x. " ] - "x." // marker - [ "CompareTo" ] // should contain (a method on the 'int' type) - [ ] // should not contain - [] - member public this.``Identifier.AfterParenthesis.Bug6484_2``() = - AssertAutoCompleteContains - [ "for x = 1 to 10 do" - " printfn \"%s\" (x. " ] - "x." // marker - [ "CompareTo" ] // should contain (a method on the 'int' type) - [ ] // should not contain - [] - member public this.``Type.Indexers.Bug4898_1``() = - AssertAutoCompleteContains - [ - "type Foo(len) =" - " member this.Value = [1 .. len]" - "type Bar =" - " static member ParamProp with get len = new Foo(len)" - "let n = Bar.ParamProp."] - "ar.ParamProp." // marker - [ "ToString" ] // should contain - [ "Value" ] // should not contain - [] - member public this.``Type.Indexers.Bug4898_2``() = - AssertAutoCompleteContains - [ - "type mytype() =" - " let instanceArray2 = [|[| \"A\"; \"B\" |]; [| \"A\"; \"B\" |] |]" - " let instanceArray = [| \"A\"; \"B\" |]" - " member x.InstanceIndexer" - " with get(idx) = instanceArray.[idx]" - " member x.InstanceIndexer2" - " with get(idx1,idx2) = instanceArray2.[idx1].[idx2]" - "let a = mytype()" - "a.InstanceIndexer2."] - - "a.InstanceIndexer2." // marker - [ "ToString" ] // should contain - [ "Chars" ] // should not contain [] member public this.``Expressions.Sequence``() = @@ -3956,171 +591,21 @@ let x = query { for bbbb in abbbbc(*D0*) do [ "GetEnumerator" ] // should contain [ ] // should not contain - [] - member public this.``LambdaExpression.WithoutClosing.Bug1346``() = - AssertAutoCompleteContains - [ - "let p4 = " - " let isPalindrome x = " - " let chars = (string_of_int x).ToCharArray()" - " let len = chars." - " chars " - " |> Array.mapi (fun i c ->" ] - "chars." // marker - [ "Length" ] // should contain - [ ] // should not contain - [] - member public this.``LambdaExpression.WithoutClosing.Bug1346c``() = - AssertAutoCompleteContains - [ - "let p4 = " - " let isPalindrome x = " - " let chars = (string_of_int x).ToCharArray()" - " let len = chars." - " chars " - " |> Array.mapi (fun i c -> )" ] - "chars." // marker - [ "Length" ] // should contain - [ ] // should not contain - - [] - member public this.``LambdaExpression.WithoutClosing.Bug1346b``() = - AssertAutoCompleteContains - [ - "let p4 = " - " let isPalindrome x = " - " let chars = (string_of_int x).ToCharArray()" - " let len = chars." - " chars " - " |> Array.mapi (fun i c ->" - "let p5 = 1" ] - "chars." // marker - [ "Length" ] // should contain - [ ] // should not contain - [] - member public this.``IncompleteStatement.If_A``() = - AssertAutoCompleteContains - [ - "let x = \"1\"" - "let test2 = if (x)." ] - "(x)." // marker - [ "Contains" ] // should contain - [ ] // should not contain - [] - member public this.``IncompleteStatement.If_C``() = - AssertAutoCompleteContains - [ - "let x = \"1\"" - "let test2 = if (x)." - "let y = 2" ] - "(x)." // marker - [ "Contains" ] // should contain - [ ] // should not contain - [] - member public this.``IncompleteStatement.Try_A``() = - AssertAutoCompleteContains - [ - "let x = \"1\"" - "try (x)." ] - "(x)." // marker - [ "Contains" ] // should contain - [ ] // should not contain - [] - member public this.``IncompleteStatement.Try_B``() = - AssertAutoCompleteContains - [ - "let x = \"1\"" - "try (x). finally ()" ] - "(x)." // marker - [ "Contains" ] // should contain - [ ] // should not contain - [] - member public this.``IncompleteStatement.Try_C``() = - AssertAutoCompleteContains - [ - "let x = \"1\"" - "try (x). with e -> () " ] - "(x)." // marker - [ "Contains" ] // should contain - [ ] // should not contain - [] - member public this.``IncompleteStatement.Try_D``() = - AssertAutoCompleteContains - [ - "let x = \"1\"" - "try (x)." - "let y = 2" ] - "(x)." // marker - [ "Contains" ] // should contain - [ ] // should not contain - [] - member public this.``IncompleteStatement.Match_A``() = - AssertAutoCompleteContains - [ - "let x = \"1\"" - "let test2 = match (x)." ] - "(x)." // marker - [ "Contains" ] // should contain - [ ] // should not contain - [] - member public this.``IncompleteStatement.Match_C``() = - AssertAutoCompleteContains - [ - "let x = \"1\"" - "let test2 = match (x)." - "let y = 2"] - "(x)." // marker - [ "Contains" ] // should contain - [ ] // should not contain - [] - member public this.``IncompleteIfClause.Bug4594``() = - AssertCtrlSpaceCompleteContains - [ "let Bar(xyz) ="; - " let hello = "; - " if x" ] - "if x" // move to marker - ["xyz"] [] // should contain 'xyz' - (* Tests for various uses of ObsoleteAttribute ----------------------------------------- *) (* Members marked with obsolete shouldn't be visible, but we should support *) (* dot completions on them *) // Obsolete and CompilerMessage(IsError=true) should not appear. - [] - member public this.``ObsoleteAndOCamlCompatDontAppear``() = - let code= - [ - "open System" - "type X = " - " static member private Private() = ()" - " []" - " static member Obsolete() = ()" - " []" - " static member CompilerMessageTest() = ()" - "X." - ] - let (_, _, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file,"X.") - let completions = time1 AutoCompleteAtCursor file "Time of first autocomplete." - for completion in completions do - match completion with - | CompletionItem("Obsolete" as s,_,_,_,_) - //| ("Private" as s,_,_,_) this isn't supported yet - | CompletionItem("CompilerMessageTest" as s,_,_,_,_)-> failwith (sprintf "Unexpected item %s at top level." s) - | _ -> () - - // Test various configurations of nested obsolete modules & types - // (also test whether we show the right intellisense) member public this.AutoCompleteObsoleteTest testLine appendDot should shouldnot = let code = [ "[]" @@ -4164,50 +649,11 @@ let x = query { for bbbb in abbbbc(*D0*) do // When the module isn't empty, we should show completion for the module // (and not type-inference based completion on strings - therefore test for 'Chars') - [] - member public this.``Obsolete.TopLevelModule``() = - this.AutoCompleteObsoleteTest "level <- O" false [ "None" ] [ "ObsoleteTop"; "Chars" ] - [] - member public this.``Obsolete.NestedTypeOrModule``() = - this.AutoCompleteObsoleteTest "level <- Module" true [ "Other" ] [ "ObsoleteM"; "ObsoleteT"; "Chars" ] - [] - member public this.``Obsolete.CompletionOnObsoleteModule.Bug3992``() = - this.AutoCompleteObsoleteTest "level <- Module.ObsoleteM" true [ "A" ] [ "ObsoleteNested"; "Chars" ] - [] - member public this.``Obsolete.DoubleNested``() = - this.AutoCompleteObsoleteTest "level <- Module.ObsoleteM.ObsoleteNested" true [ "C" ] [ "Chars" ] - [] - member public this.``Obsolete.CompletionOnObsoleteType``() = - this.AutoCompleteObsoleteTest "level <- Module.ObsoleteT" true [ "B" ] [ "Chars" ] - /// BUG: Referencing a nonexistent DLL caused an assert. - [] - member public this.``WithNonExistentDll``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - // in the project system, 'AddAssemblyReference' would throw, so just poke this into the .fsproj file - PlaceIntoProjectFileBeforeImport - (project, @" - - - ") - let file = AddFileFromText(project,"File1.fs", - [ - "(*marker*) " - ]) - let file = OpenFile(project,"File1.fs") - - MoveCursorToEndOfMarker(file,"(*marker*) ") - let completions = CtrlSpaceCompleteAtCursor file - AssertCompListContainsAll(completions,[ - "System"; // .NET namespaces - "Array2D"]) // Types in the F# library - AssertCompListDoesNotContain(completions,"Int32") // Types in the System namespace member internal this.AutoCompleteDuplicatesTest (marker, shortName, fullName:string) = let code = @@ -4242,67 +688,7 @@ let x = query { for bbbb in abbbbc(*D0*) do // This is some tag in the tooltip that also contains the overload name text if descr.Contains("[Signature:") then occurrences - 1 else occurrences - [] - member public this.``Duplicates.Bug4103b``() = - for args in - [ "Test.", "foo", "foo"; - "Test.", "Pat", "Pat"; - "Test.", "Failed", "exception Failed"; - "Test.", "Del", "type Del"; - "Test.", "Foo", "Test.A.Foo" - "Test.B.", "Bar", "Test.B.Bar" - "TestType.", "Prop", "TestType.Prop" - "TestType.", "Event", "TestType.Event" ] do - this.AutoCompleteDuplicatesTest args - - [] - member public this.``Duplicates.Bug4103c``() = - let code = - [ - "open System.IO" - "open System.IO" - "File." ] - let (_, _, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file, "File.") - let completions = AutoCompleteAtCursor file - - // Get description for Expr.Var - let (CompletionItem(_, _, _, descrFunc, _)) = completions |> Array.find (fun (CompletionItem(name, _, _, _, _)) -> name = "Open") - let occurrences = this.CountMethodOccurrences(descrFunc(), "File.Open") - AssertEqualWithMessage(3, occurrences, "Found wrong number of overloads for 'File.Open'.") - [] - member public this.``Duplicates.Bug2094``() = - let code = - [ - "open Microsoft.FSharp.Control" - "let b = MailboxProcessor." ] - let (_, _, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file, "MailboxProcessor.") - let completions = AutoCompleteAtCursor file - - // Get description for Expr.Var - let (CompletionItem(_, _, _, descrFunc, _)) = completions |> Array.find (fun (CompletionItem(name, _, _, _, _)) -> name = "Start") - let occurrences = this.CountMethodOccurrences(descrFunc(), "Start") - AssertEqualWithMessage(2, occurrences, sprintf "Found wrong number of overloads for 'MailboxProcessor.Start'. Found %A." completions) - - [] - member public this.``WithinMatchClause.Bug1603``() = - let code = - [ - "let rec f l =" - " match l with" - " | [] ->" - " let xx = System.DateTime.Now" - " let y = xx." - " | x :: xs -> f xs" - ] - let (_, _, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file,"let y = xx.") - let completions = AutoCompleteAtCursor file - // Should contain something - Assert.NotEqual(0,completions.Length) - Assert.True(completions |> Array.exists (fun (CompletionItem(name,_,_,_,_)) -> name.Contains("AddMilliseconds"))) // FEATURE: Saving file N does not cause files 1 to N-1 to re-typecheck (but does cause files N to to [] @@ -4438,470 +824,30 @@ let x = query { for bbbb in abbbbc(*D0*) do Assert.NotEqual(0, completions.Length, "Expected some items in the list after adding a reference.") *) - /// In this bug, a bogus flag caused the rest of flag parsing to be ignored. - [] - member public this.``FlagsAndSettings.Bug1969``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let file = AddFileFromText(project,"File1.fs", - [ - "let y = System.Deployment.Application." - "()"]) - let file = OpenFile(project, "File1.fs") - MoveCursorToEndOfMarker(file,"System.Deployment.Application.") - let completions = AutoCompleteAtCursor(file) - // printf "Completions=%A\n" completions - Assert.Equal(0, completions.Length) // Expect none here because reference hasn't been added. - // Add an unknown flag followed by the reference to our assembly. - let deploymentAssembly = sprintf @"%s\Microsoft.NET\Framework\v4.0.30319\System.Deployment.dll" (System.Environment.GetEnvironmentVariable("windir")) - SetOtherFlags(project,"--doo-da -r:" + deploymentAssembly) - let completions = AutoCompleteAtCursor(file) - // Now, make sure the reference added after the erroneous reference is still honored. - Assert.NotEqual(0, completions.Length) - ShowErrors(project) - /// In this bug there was an exception if the user pressed dot after a long identifier - /// that was unknown. - [] - member public this.``OfSystemWindows``() = - let code = ["let y=new System.Windows."] - let (_, _, file) = this.CreateSingleFileProject(code, references = ["System.Windows.Forms"]) - MoveCursorToEndOfMarker(file,"System.Windows.") - let completions = AutoCompleteAtCursor(file) - printfn "Completions=%A" completions - Assert.Equal(3, completions.Length) - /// Tests whether we're correctly showing both type and module when they have the same name - [] - member public this.``ShowSetAsModuleAndType``() = - let code = ["let s = Set"] - let (_, _, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file,"= Set") - let completions = CtrlSpaceCompleteAtCursor(file) - let found = completions |> Array.tryFind (fun (CompletionItem(n, _, _, _, _)) -> n = "Set") - match found with - | Some(CompletionItem(_, _, _, f, _)) -> - let tip = f() - AssertContains(tip, "module Set") - AssertContains(tip, "type Set") - | _ -> - Assert.Fail("'Set' not found in the completion list") - - /// FEATURE: The user may type namespace followed by dot and see a completion list containing members of that namespace. - [] - member public this.``AtNamespaceDot``() = - let code = ["let y=new System.String()"] - let (_, _, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file,"System.") - let completions = AutoCompleteAtCursor(file) - Assert.True(completions.Length>0) - - /// FEATURE: The user will see appropriate glyphs in the autocompletion list. - [] - member public this.``OfSeveralModuleMembers``() = - let code = - [ - "module Module =" - " let Constant = 5" - " type Class = class" - " end" - " type Record = {AString:string}" - " exception OutOfRange of string" - " type Enum = Red = 0 | White = 1 | Blue = 2" - " type DiscriminatedUnion = A | B | C" - " type AsmType = (# \"!0[]\" #)" - " type TupleType = int * int" - " type FunctionType = unit->unit" - " let (~+) x = -x" - " type Interface =" - " abstract MyMethod : unit->unit" - " type Struct = struct" - " end" - " let Function x = 0" - " let FunctionValue = fun x -> 0" - " let Tuple = (0,2)" - " module Submodule =" - " let a = 0" - " type ValueType = int" - "module AbbreviationModule =" - " type StructAbbreviation = Module.Struct" - " type InterfaceAbbreviation = Module.Interface" - " type DiscriminatedUnionAbbreviation = Module.DiscriminatedUnion" - " type RecordAbbreviation = Module.Record" - " type EnumAbbreviation = Module.Enum" - " type TupleTypeAbbreviation = Module.TupleType" - " type AsmTypeAbbreviation = Module.AsmType" - "let y = AbbreviationModule." - "let y = Module." - "let f x = 0" - ] - let (_, _, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file," Module.") - let completions = time1 AutoCompleteAtCursor file "Time of first autocomplete." - - Assert.True(completions.Length>0) - for completion in completions do - match completion with - | CompletionItem("A",_,_,_,DeclarationType.EnumMember) -> () - | CompletionItem("B",_,_,_,DeclarationType.EnumMember) -> () - | CompletionItem("C",_,_,_,DeclarationType.EnumMember) -> () - | CompletionItem("Function",_,_,_,_) -> () - | CompletionItem("Enum",_,_,_,DeclarationType.Enum) -> () - | CompletionItem("Constant",_,_,_,_) -> () - | CompletionItem("FunctionValue",_,_,_,DeclarationType.Method) -> () - | CompletionItem("OutOfRange",_,_,_,DeclarationType.Exception) -> () - | CompletionItem("OutOfRangeException",_,_,_,DeclarationType.Class) -> () - | CompletionItem("Interface",_,_,_,DeclarationType.Interface) -> () - | CompletionItem("Struct",_,_,_,DeclarationType.ValueType) -> () - | CompletionItem("Tuple",_,_,_,_) -> () - | CompletionItem("Submodule",_,_,_,DeclarationType.Module) -> () - | CompletionItem("Record",_,_,_,DeclarationType.Class) -> () - | CompletionItem("DiscriminatedUnion",_,_,_,DeclarationType.DiscriminatedUnion) -> () - | CompletionItem("AsmType",_,_,_,DeclarationType.Class) -> () - | CompletionItem("FunctionType",_,_,_,DeclarationType.Class) -> () - | CompletionItem("TupleType",_,_,_,DeclarationType.Class) -> () - | CompletionItem("ValueType",_,_,_,DeclarationType.ValueType) -> () - | CompletionItem("Class",_,_,_,DeclarationType.Class) -> () - | CompletionItem("Int32",_,_,_,DeclarationType.Method) -> () - | CompletionItem("TupleTypeAbbreviation",_,_,_,_) -> () - | CompletionItem(name,_,_,_,x) -> failwith (sprintf "Unexpected module member %s seen with declaration type %A" name x) - - MoveCursorToEndOfMarker(file,"AbbreviationModule.") - let completions = time1 AutoCompleteAtCursor file "Time of second autocomplete." - // printf "Completions=%A\n" completions - Assert.True(completions.Length>0) - for completion in completions do - match completion with - | CompletionItem("Int32",_,_,_,_) - | CompletionItem("Function",_,_,_,_) - | CompletionItem("Enum",_,_,_,_) - | CompletionItem("Constant",_,_,_,_) - | CompletionItem("Function",_,_,_,_) - | CompletionItem("Interface",_,_,_,_) - | CompletionItem("Struct",_,_,_,_) - | CompletionItem("Tuple",_,_,_,_) - | CompletionItem("Record",_,_,_,_) -> () - | CompletionItem("EnumAbbreviation",_,_,_,DeclarationType.Enum) -> () - | CompletionItem("InterfaceAbbreviation",_,_,_,DeclarationType.Interface) -> () - | CompletionItem("StructAbbreviation",_,_,_,DeclarationType.ValueType) -> () - | CompletionItem("DiscriminatedUnion",_,_,_,_) -> () - | CompletionItem("RecordAbbreviation",_,_,_,DeclarationType.Class) -> () - | CompletionItem("DiscriminatedUnionAbbreviation",_,_,_,DeclarationType.DiscriminatedUnion) -> () - | CompletionItem("AsmTypeAbbreviation",_,_,_,DeclarationType.Class) -> () - | CompletionItem("TupleTypeAbbreviation",_,_,_,_) -> () - | CompletionItem(name,_,_,_,x) -> failwith (sprintf "Unexpected union member %s seen with declaration type %A" name x) - - [] - member public this.ListFunctions() = - let code = - [ - "let y = List." - "let f x = 0" - ] - let (_,_, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file,"List.") - let completions = time1 AutoCompleteAtCursor file "Time of first autocomplete." - // printf "Completions=%A\n" completions - Assert.True(completions.Length>0) - for completion in completions do - match completion with - | CompletionItem("Cons",_,_,_,DeclarationType.Method) -> () - | CompletionItem("Equals",_,_,_,DeclarationType.Method) -> () - | CompletionItem("Empty",_,_,_,DeclarationType.Property) -> () - | CompletionItem("empty",_,_,_,_) -> () - | CompletionItem(_,_,_,_,DeclarationType.Method) -> () - | CompletionItem(name,_,_,_,x) -> failwith (sprintf "Unexpected item %s seen with declaration type %A" name x) - - [] - member public this.``SystemNamespace``() = - let code = - [ - "let y = System." - ] - let (_,_, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file,"System.") - let completions = time1 AutoCompleteAtCursor file "Time of first autocomplete." - // printf "Completions=%A\n" completions - Assert.True(completions.Length>0) - - let AssertIsDecl(name,decl,expected) = - if decl<>expected then failwith (sprintf "Expected %A for %s but was %A" expected name decl) - - for completion in completions do - match completion with - | CompletionItem("Action" as name,_,_,_,decl) -> AssertIsDecl(name,decl,DeclarationType.Class) - | CompletionItem("CodeDom" as name,_,_,_,decl) -> AssertIsDecl(name,decl,DeclarationType.Namespace) - | _ -> () // If there is a compile error that prevents a data tip from resolving then show that data tip. - [] - member public this.``MemberInfoCompileErrorsShowInDataTip``() = - let code = - [ - "type Foo = " - " member x.Bar() = 0" - "let foovalue:Foo = unbox null" - "foovalue.B" // make sure this is different from the line 3! - ] - let (_,_, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file,"foovalue.B") - - use scope = AutoCompleteMemberDataTipsThrowsScope(this.VS, "Simulated compiler error") - let completions = time1 CtrlSpaceCompleteAtCursor file "Time of first autocomplete." - Assert.True(completions.Length>0) - for completion in completions do - let (CompletionItem(_,_,_,descfunc,_)) = completion - let desc = descfunc() - printfn "MemberInfoCompileErrorsShowInDataTip: desc = <<<%s>>>" desc - AssertContains(desc,"Simulated compiler error") // Bunch of crud in empty list. This test asserts that unwanted things don't exist at the top level. - [] - member public this.``Editor.WithoutContext.Bug986``() = - let code = ["(*mark*)"] - let (_,_, file) = this.CreateSingleFileProject(code) - - MoveCursorToEndOfMarker(file,"(*mark*)") - let completions = time1 CtrlSpaceCompleteAtCursor file "Time of first autocomplete." - for completion in completions do - match completion with - | CompletionItem("IChapteredRowset" as s,_,_,_,_) - | CompletionItem("ICorRuntimeHost" as s,_,_,_,_) -> failwith (sprintf "Unexpected item %s at top level." s) - | _ -> () - [] - member public this.``LetBind.TopLevel.Bug1650``() = - let code =["let x = "] - let (_,_, file) = this.CreateSingleFileProject(code) - let gpatcc = GlobalParseAndTypeCheckCounter.StartNew(this.VS) - MoveCursorToEndOfMarker(file,"let x = ") - let completions = time1 CtrlSpaceCompleteAtCursor file "Time of first autocomplete." - Assert.True(completions.Length>0) - gpatcc.AssertExactly(0,0) - [] - member public this.``Identifier.Invalid.Bug876b``() = - let code = - [ - "let f (x:System.Windows.Forms.Form) = x." - " for x = 0 to 0 do () done" - ] - let (_,project, file) = this.CreateSingleFileProject(code, references = ["System"; "System.Drawing"; "System.Windows.Forms"]) - - MoveCursorToEndOfMarker(file,"x.") - let completions = time1 AutoCompleteAtCursor file "Time of first autocomplete." - ShowErrors(project) - Assert.True(completions.Length>0) - [] - member public this.``Identifier.Invalid.Bug876c``() = - let code = - [ - "let f (x:System.Windows.Forms.Form) = x." - " 12" - ] - let (_,_, file) = this.CreateSingleFileProject(code, references = ["System"; "System.Drawing"; "System.Windows.Forms"]) - MoveCursorToEndOfMarker(file,"x.") - let completions = time1 AutoCompleteAtCursor file "Time of first autocomplete." - Assert.True(completions.Length>0) - [] - member public this.``EnumValue.Bug2449``() = - let code = - [ - "type E = | A = 1 | B = 2" - "let e = E.A" - "e." - ] - let (_, _, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file,"e.") - let completions = time1 AutoCompleteAtCursor file "Time of first autocomplete." - AssertCompListDoesNotContain(completions, "value__") - [] - member public this.``EnumValue.Bug4044``() = - let code = - [ - "open System.IO" - "let GetFileSize filePath = File.GetAttributes(filePath)." - ] - let (_, _, file) = this.CreateSingleFileProject(code) - let gpatcc = GlobalParseAndTypeCheckCounter.StartNew(this.VS) - MoveCursorToEndOfMarker(file,"filePath).") - let completions = time1 AutoCompleteAtCursor file "Time of first autocomplete." - AssertCompListDoesNotContain(completions, "value__") - gpatcc.AssertExactly(0,0) - /// There was a bug (2584) that IntelliSense should treat 'int' as a type instead of treating it as a function - /// However, this is now deprecated behavior. We want the user to use 'System.Int32' and - /// we generally prefer information from name resolution (also see 4405) - [] - member public this.``PrimTypeAndFunc``() = - let code = - [ - "System.Int32. " - "int. " - ] - let (_, _, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file,"System.Int32.") - let completions = time1 AutoCompleteAtCursor file "Time of first autocomplete." - AssertCompListContains(completions,"MinValue") - - MoveCursorToEndOfMarker(file,"int.") - let completions = time1 AutoCompleteAtCursor file "Time of first autocomplete." - AssertCompListDoesNotContain(completions,"MinValue") - /// This is related to Bug1605--since the file couldn't parse there was no information to provide the autocompletion list. - [] - member public this.``MatchStatement.Clause.AfterLetBinds.Bug1603``() = - let code = - [ - "let rec f l =" - " match l with" - " | [] ->" - " let xx = System.DateTime.Now" - " let y = xx" - " | x :: xs -> f xs." - ] - let (_, _, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file,"xs -> f xs.") - let completions = time1 AutoCompleteAtCursor file "Time of first autocomplete." - // printf "Completions=%A\n" completions - Assert.True(completions.Length>0) - - let mutable count = 0 - - let AssertIsDecl(name,decl,expected) = - if decl<>expected then failwith (sprintf "Expected %A for %s but was %A" expected name decl) - - for completion in completions do - match completion with - | CompletionItem("Head" as name,_,_,_,decl) -> - count<-count + 1 - AssertIsDecl(name,decl,DeclarationType.Property) - | CompletionItem("Tail" as name,_,_,_,decl) -> - count<-count + 1 - AssertIsDecl(name,decl,DeclarationType.Property) - | CompletionItem(name,_,_,_,x) -> () - - Assert.Equal(2,count) // This was a bug in which the third level of dotting was ignored. - [] - member public this.``ThirdLevelOfDotting``() = - let code = - [ - "let x = System.Console.Wr" - ] - let (_, _, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file,"Console.Wr") - let completions = time1 CtrlSpaceCompleteAtCursor file "Time of first autocomplete." - // printf "Completions=%A\n" completions - Assert.True(completions.Length>0) - - let AssertIsDecl(name,decl,expected) = - if decl<>expected then failwith (sprintf "Expected %A for %s but was %A" expected name decl) - - for completion in completions do - match completion with - | CompletionItem("BackgroundColor" as name,_,_,_,decl) -> AssertIsDecl(name,decl,DeclarationType.Property) - | CompletionItem("CancelKeyEvent" as name,_,_,_,decl) -> AssertIsDecl(name,decl,DeclarationType.Event) - | CompletionItem(name,_,_,_,x) -> () // Test completions in an incomplete computation expression (case 1: for "let") - [] - member public this.``ComputationExpressionLet``() = - let code = - [ - "let http(url:string) = " - " async { " - " let rnd = new System.Random()" - " let rsp = rnd.N" ] - let (_, _, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file,"rsp = rnd.") - let completions = time1 AutoCompleteAtCursor file "Time of first autocomplete." - AssertCompListContainsAll(completions, ["Next"]) - [] - member public this.``BestMatch.Bug4320a``() = - let code = [ " let x = System." ] - let (_, _, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file,"System.") - let Match text filterText = CompletionBestMatchAtCursorFor(file, text, filterText) - // (ItemName, isUnique, isPrefix) - // isUnique=true means it will be selected on ctrl-space invocation - // isPrefix=true means it will be selected, instead of just outlined - AssertEqual(Some ("GC", false, true), Match "G" None) - AssertEqual(Some ("GC", false, true), Match "GC" None) - AssertEqual(Some ("GCCollectionMode", true, true), Match "GCC" None) - AssertEqual(Some ("GCCollectionMode", false, false), Match "GCCZ" None) - AssertEqual(Some ("GC", false, true), Match "G" (Some "G")) - AssertEqual(Some ("GC", false, true), Match "GC" (Some "G")) - AssertEqual(Some ("GCCollectionMode", true, true), Match "GCC" (Some "G")) - AssertEqual(Some ("GCCollectionMode", false, false), Match "GCCZ" (Some "G")) - AssertEqual(Some ("GC", false, true), Match "G" (Some "GC")) - AssertEqual(Some ("GC", false, true), Match "GC" (Some "GC")) - AssertEqual(Some ("GCCollectionMode", true, true), Match "GCC" (Some "GC")) - AssertEqual(Some ("GCCollectionMode", false, false), Match "GCCZ" (Some "GC")) - [] - member public this.``BestMatch.Bug4320b``() = - let code = [ " let x = List." ] - let (_, _, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file,"List.") - let Match text = CompletionBestMatchAtCursorFor(file, text, None) - // (ItemName, isUnique, isPrefix) - // isUnique=true means it will be selected on ctrl-space invocation - // isPrefix=true means it will be selected, instead of just outlined - AssertEqual(Some ("empty", false, true), Match "e") - AssertEqual(Some ("empty", true, true), Match "em") - [] - member public this.``BestMatch.Bug5131``() = - let code = [ "System.Environment." ] - let (_, _, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file,"Environment.") - let Match text = CompletionBestMatchAtCursorFor(file, text, None) - // (ItemName, isUnique, isPrefix) - // isUnique=true means it will be selected on ctrl-space invocation - // isPrefix=true means it will be selected, instead of just outlined - AssertEqual(Some ("OSVersion", true, true), Match "o") - [] - member public this.``COMPILED.DefineNotPropagatedToIncrementalBuilder``() = - use _guard = this.UsingNewVS() - - let solution = this.CreateSolution() - let projName = "testproject" - let project = CreateProject(solution,projName) - let dir = ProjectDirectory(project) - let file1 = AddFileFromText(project,"File1.fs", - [ - "module File1" - "#if COMPILED" - "let x = 0" - "#else" - "let y = 1" - "#endif" - ]) - let file2 = AddFileFromText(project,"File2.fs", - [ - "module File2" - "File1." - ]) - - let file = OpenFile(project, "File2.fs") - MoveCursorToEndOfMarker(file, "File1.") - let completionItems = - AutoCompleteAtCursor(file) - |> Array.map (fun (CompletionItem(name, _, _, _, _)) -> name) - Assert.Equal(1, completionItems.Length) - Assert.Equal("x", completionItems.[0]) - [] member public this.``VisualStudio.CloseAndReopenSolution``() = use _guard = this.UsingNewVS() @@ -4928,2703 +874,145 @@ let x = query { for bbbb in abbbbc(*D0*) do MoveCursorToEndOfMarker(file,"x.") let completions = time1 AutoCompleteAtCursor file "Time of first autocomplete." // printf "Completions=%A\n" completions - Assert.True(completions.Length>0) - - [] - member this.``BadCompletionAfterQuicklyTyping.Bug72561``() = - let code = [ " " ] - let (_, _, file) = this.CreateSingleFileProject(code) - - TakeCoffeeBreak(this.VS) - let gpatcc = GlobalParseAndTypeCheckCounter.StartNew(this.VS) - // In this case, we quickly type "." and then get dot-completions - // This simulates the case when the user quickly types "dot" after the file has been TCed before. - ReplaceFileInMemoryWithoutCoffeeBreak file ([ "[1]." ]) - MoveCursorToEndOfMarker(file, ".") - // Note: no TakeCoffeeBreak(this.VS) - let completions = AutoCompleteAtCursor file - AssertCompListContainsExactly(completions, []) // there are no stale results for an expression at this location, so nothing is returned immediately - // second-chance intellisense will kick in: - TakeCoffeeBreak(this.VS) - let completions = AutoCompleteAtCursor file - AssertCompListContainsAll(completions, ["Length"]) - AssertCompListDoesNotContainAny(completions, ["AbstractClassAttribute"]) - gpatcc.AssertExactly(0,0) - - [] - member this.``BadCompletionAfterQuicklyTyping.Bug72561.Noteworthy.NowWorks``() = - let code = [ "123 " ] - let (_, _, file) = this.CreateSingleFileProject(code) - - TakeCoffeeBreak(this.VS) - let gpatcc = GlobalParseAndTypeCheckCounter.StartNew(this.VS) - // In this case, we quickly type "." and then get dot-completions - // This simulates the case when the user quickly types "dot" after the file has been TCed before. - ReplaceFileInMemoryWithoutCoffeeBreak file ([ "[1]." ]) - MoveCursorToEndOfMarker(file, ".") - // Note: no TakeCoffeeBreak(this.VS) - let completions = AutoCompleteAtCursor file - AssertCompListIsEmpty(completions) // empty completion list means second-chance intellisense will kick in - // if we wait... - TakeCoffeeBreak(this.VS) - let completions = AutoCompleteAtCursor file - // ... we get the expected answer - AssertCompListContainsAll(completions, ["Length"]) - AssertCompListDoesNotContainAny(completions, ["AbstractClassAttribute"]) - gpatcc.AssertExactly(0,0) - - [] - member this.``BadCompletionAfterQuicklyTyping.Bug130733.NowWorks``() = - let code = [ "let someCall(x) = null" - "let xe = someCall(System.IO.StringReader() "] - let (_, _, file) = this.CreateSingleFileProject(code) - - TakeCoffeeBreak(this.VS) - let gpatcc = GlobalParseAndTypeCheckCounter.StartNew(this.VS) - // In this case, we quickly type "." and then get dot-completions - // This simulates the case when the user quickly types "dot" after the file has been TCed before. - ReplaceFileInMemoryWithoutCoffeeBreak file [ "let someCall(x) = null" - "let xe = someCall(System.IO.StringReader(). "] - MoveCursorToEndOfMarker(file, "().") - // Note: no TakeCoffeeBreak(this.VS) - let completions = AutoCompleteAtCursor file - AssertCompListContainsAll(completions, ["ReadBlock"]) // text to the left of the dot did not change, so we use stale (correct) result immediately - // if we wait... - TakeCoffeeBreak(this.VS) - let completions = AutoCompleteAtCursor file - // ... we get the expected answer - AssertCompListContainsAll(completions, ["ReadBlock"]) - gpatcc.AssertExactly(0,0) - - -//*********************************************Previous Completion test and helper***** - member private this.VerifyCompListDoesNotContainAnyAtStartOfMarker(fileContents : string, marker : string, list : string list) = - let (solution, project, file) = this.CreateSingleFileProject(fileContents) - MoveCursorToStartOfMarker(file, marker) - let completions = AutoCompleteAtCursor(file) - AssertCompListDoesNotContainAny(completions,list) - - member private this.VerifyCtrlSpaceListDoesNotContainAnyAtStartOfMarker(fileContents : string, marker : string, list : string list) = - let (solution, project, file) = this.CreateSingleFileProject(fileContents) - MoveCursorToStartOfMarker(file, marker) - let completions = CtrlSpaceCompleteAtCursor file - AssertCompListDoesNotContainAny(completions,list) - - member private this.VerifyCompListContainAllAtStartOfMarker(fileContents : string, marker : string, list : string list) = - let (solution, project, file) = this.CreateSingleFileProject(fileContents) - MoveCursorToStartOfMarker(file, marker) - let completions = AutoCompleteAtCursor(file) - AssertCompListContainsAll(completions, list) - - member private this.VerifyCtrlSpaceListContainAllAtStartOfMarker(fileContents : string, marker : string, list : string list, ?coffeeBreak:bool, ?addtlRefAssy:string list) = - let coffeeBreak = defaultArg coffeeBreak false - let (solution, project, file) = this.CreateSingleFileProject(fileContents, ?references = addtlRefAssy) - MoveCursorToStartOfMarker(file, marker) - if coffeeBreak then TakeCoffeeBreak(this.VS) - let completions = CtrlSpaceCompleteAtCursor file - AssertCompListContainsAll(completions, list) - - - member private this.VerifyAutoCompListIsEmptyAtEndOfMarker(fileContents : string, marker : string) = - let (solution, project, file) = this.CreateSingleFileProject(fileContents) - MoveCursorToEndOfMarker(file, marker) - let completions = AutoCompleteAtCursor(file) - AssertEqual(0,completions.Length) - - member private this.VerifyCtrlSpaceCompListIsEmptyAtEndOfMarker(fileContents : string, marker : string) = - let (solution, project, file) = this.CreateSingleFileProject(fileContents) - MoveCursorToEndOfMarker(file, marker) - let completions = CtrlSpaceCompleteAtCursor(file) - AssertEqual(0,completions.Length) - - [] - member this.``Expression.WithoutPreDefinedMethods``() = - this.VerifyCtrlSpaceListDoesNotContainAnyAtStartOfMarker( - fileContents = """ - let x = F(*HERE*)""", - marker = "(*HERE*)", - list = ["FSharpDelegateEvent"; "PrivateMethod"; "PrivateType"]) - - [] - member this.``Expression.WithPreDefinedMethods``() = - this.VerifyCtrlSpaceListContainAllAtStartOfMarker( - fileContents = """ - module Module1 = - let private PrivateField = 1 - let private PrivateMethod x = - x+1 - type private PrivateType() = - member this.mem = 1 - let a = (*Marker1*) - - let b = 23 - """, - marker = "(*Marker1*)", - list = ["PrivateField"; "PrivateMethod"; "PrivateType"]) - - // Regression for bug 2116 -- Consider making selected item in completion list case-insensitive - [] - member this.``CaseInsensitive``() = - this.VerifyCtrlSpaceListContainAllAtStartOfMarker( - fileContents = """ - type Test() = - member this.Xyzzy = () - member this.xYzzy = () - member this.xyZzy = () - member this.xyzZy = () - member this.xyzzY = () - - let t = new Test() - t.XYZ(*Marker1*) - """, - marker = "(*Marker1*)", - list = ["Xyzzy"; "xYzzy"; "xyZzy"; "xyzZy"; "xyzzY"]) - - [] - member this.``Attributes.CanSeeOpenNamespaces.Bug268290.Case1``() = - AssertCtrlSpaceCompleteContains - [""" - module Foo - open System - [< - """] - "[<" - ["AttributeUsage"] - [] - - [] - member this.``Selection``() = - AssertCtrlSpaceCompleteContains - [""" - let preSelectedItem = 1 - let r = (*MarkerPreSelectedItem*)pre - """] - "(*MarkerPreSelectedItem*)pre" - ["preSelectedItem"] - [] - - // Regression test for 1653 -- Both the F# exception and the .NET exception representing it are shown in completion lists - [] - member this.``NoDupException.Postive``() = - this.VerifyCtrlSpaceListContainAllAtStartOfMarker( - fileContents = """ - let x = Match(*MarkerException*)""", - marker = "(*MarkerException*)", - list = ["MatchFailureException"]) - - [] - member this.``DotNetException.Negative``() = - this.VerifyCtrlSpaceListDoesNotContainAnyAtStartOfMarker( - fileContents = """ - let x = Match(*MarkerException*)""", - marker = "(*MarkerException*)", - list = ["MatchFailure"]) - - // Regression for bug 921 -- intellisense case-insensitive? - [] - member this.``CaseInsensitive.MapMethod``() = - this.VerifyCtrlSpaceListContainAllAtStartOfMarker( - fileContents = """ - List.MaP(*MarkerCase*) - """, - marker = "(*MarkerCase*)", - list = ["map"]) - - //Regression for bug 69644 69654 Fsharp: no completion for an identifier when 'use'd inside an 'async' block - [] - member this.``InAsyncAndUseBlock``() = - this.VerifyCompListContainAllAtStartOfMarker( - fileContents = """ - open System.Text.RegularExpressions - open System.IO - - let collectLinksAsync (url:string) : Async = - async { do printfn "requesting %s" url - let! html = - async { use reader = new System.IO.StreamReader(new System.IO.FileStream("", FileMode.CreateNew)) - do printfn "reading %s" url - return (*Marker1*)reader.ReadToEnd() } //<---- reader - let links = "a" - return links } - """, - marker = "(*Marker1*)", - list = ["reader"]) - - [] - member this.``WithoutOpenNamespace``() = - AssertCtrlSpaceCompleteContains - [""" - module CodeAccessibility - - let x = S(*Marker*) - """] - "(*Marker*)" - [] // should - ["Single"] // should not - - [] - member this.``PrivateVisible``() = - AssertCtrlSpaceCompleteContains - [""" - module CodeAccessibility - - module Module1 = - - let private fieldPrivate = 1 - - let private MethodPrivate x = - x+1 - - type private TypePrivate() = - member this.mem = 1 - - let a = (*Marker1*) - """] - "(*Marker1*) " - ["fieldPrivate";"MethodPrivate";"TypePrivate"] - [] - - [] - member this.``InternalVisible``() = - AssertCtrlSpaceCompleteContains - [""" - module CodeAccessibility - - module Module1 = - - let internal fieldInternal = 1 - - let internal MethodInternal x = - x+1 - - type internal TypeInternal() = - member this.mem = 1 - - let a = (*Marker1*) """] - "(*Marker1*) " - ["fieldInternal";"MethodInternal";"TypeInternal"] // should - [] // should not - - [] - // Verify that we display the correct list of Unit of Measure (Names) in the autocomplete window. - // This also ensures that no UoM are accidentally added or removed. - member public this.``UnitMeasure.UnitNames``() = - AssertAutoCompleteContains - [ "Microsoft.FSharp.Data.UnitSystems.SI.UnitNames."] - "UnitNames." - [ "ampere"; "becquerel"; "candela"; "coulomb"; "farad"; "gray"; "henry"; "hertz"; - "joule"; "katal"; "kelvin"; "kilogram"; "lumen"; "lux"; "metre"; "mole"; "newton"; - "ohm"; "pascal"; "second"; "siemens"; "sievert"; "tesla"; "volt"; "watt"; "weber";] // should contain; exact match - [ ] // should not contain - - [] - // Verify that we display the correct list of Unit of Measure (Symbols) in the autocomplete window. - // This also ensures that no UoM are accidentally added or removed. - member public this.``UnitMeasure.UnitSymbols``() = - AssertAutoCompleteContains - [ "Microsoft.FSharp.Data.UnitSystems.SI.UnitSymbols."] - "UnitSymbols." - [ "A"; "Bq"; "C"; "F"; "Gy"; "H"; "Hz"; "J"; "K"; "N"; "Pa"; "S"; "Sv"; "T"; "V"; - "W"; "Wb"; "cd"; "kat"; "kg"; "lm"; "lx"; "m"; "mol"; "ohm"; "s";] // should contain; exact match - [ ] // should not contain - -(*------------------------------------------IDE Query automation start -------------------------------------------------*) - member private this.AssertAutoCompletionInQuery(fileContent : string list, marker:string,contained:string list) = - let file = createFile fileContent SourceFileKind.FS ["System.Xml.Linq"] None - - let gpatcc = GlobalParseAndTypeCheckCounter.StartNew(this.VS) - MoveCursorToEndOfMarker(file, marker) - let completions = CompleteAtCursorForReason(file,BackgroundRequestReason.CompleteWord) - AssertCompListContainsAll(completions, contained) - gpatcc.AssertExactly(0,0) - - [] - // Custom operators appear in Intellisense list after entering a valid query operator - // on the previous line and invoking Intellisense manually - // Including in a nested query - member public this.``Query.Auto.InNestedQuery``() = - this.AssertAutoCompletionInQuery( - fileContent =[""" - let tuples = [ (1, 8, 9); (56, 45, 3)] - let numbers = [ 1;2; 8; 9; 15; 23; 3; 42; 4;0; 55;] - - let foo = - query { - for n in numbers do - let maxNumber = query {for x in tuples do ma} - select n }"""], - marker = "do ma", - contained = [ "maxBy"; "maxByNullable"; ]) - - [] - // Custom operators appear in Intellisense list after entering a valid query operator - // on the previous line and invoking Intellisense manually - // Including in a nested query - member public this.``Query.Auto.OffSetFromPreviousLine``() = - this.AssertAutoCompletionInQuery( - fileContent =[""" - let numbers = [ 1;2; 8; 9; 15; 23; 3; 42; 4;0; 55;] - let foo = - query { - for n in numbers do - gro - }"""], - marker = "gro", - contained = [ "groupBy"; "groupJoin"; "groupValBy";]) - - [] - member this.``Namespace.System``() = - this.VerifyDotCompListContainAllAtEndOfMarker( - fileContents = """ - // Test '.' after System - open System - let str = "a string" - // Test '.' after str - let _ = str(*usage*) - """, - marker = "open System", - list = [ "IO"; "Collections" ]) - - [] - member this.``Identifier.String.Positive``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - open System - let str = "a string" - // Test '.' after str - let _ = str(*usage*) - """, - marker = "(*usage*)", - list = ["Chars"; "ToString"; "Length"; "GetHashCode"]) - - [] - member this.``Identifier.String.Negative``() = - this.VerifyDotCompListDoesNotContainAnyAtStartOfMarker( - fileContents = """ - open System - let str = "a string" - // Test '.' after str - let _ = str(*usage*) - """, - marker = "(*usage*)", - list = ["Parse"; "op_Addition"; "op_Subtraction"]) - - // Verify add_* methods show up for non-standard events. These are events - // where the associated delegate type does not return "void" - [] - member this.``Event.NonStandard.PrefixMethods``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """System.AppDomain.CurrentDomain(*usage*)""", - marker = "(*usage*)", - list = ["add_AssemblyResolve"; "remove_AssemblyResolve"; "add_ReflectionOnlyAssemblyResolve"; "remove_ReflectionOnlyAssemblyResolve"; "add_ResourceResolve"; "remove_ResourceResolve"; "add_TypeResolve"; "remove_TypeResolve"]) - - // Verify the events do show up. An error is generated when they are used asking the user to use add_* and remove_* instead. - // That is, they are legitimate name resolutions but do not pass type checking. - [] - member this.``Event.NonStandard.VerifyLegitimateNameShowUp``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = "System.AppDomain.CurrentDomain(*usage*)", - marker = "(*usage*)", - list = ["AssemblyResolve"; "ReflectionOnlyAssemblyResolve"; "ResourceResolve"; "TypeResolve" ]) - - [] - member this.``Array``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = "let arr = [| for i in 1..10 -> i |](*Mexparray*)", - marker = "(*Mexparray*)", - list = ["Clone"; "IsFixedSize"]) - - [] - member this.``List``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = "let lst = [ for i in 1..10 -> i](*Mexplist*)", - marker = "(*Mexplist*)", - list = ["Head"; "Tail"]) - - [] - member public this.``ExpressionDotting.Regression.Bug187799``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - type T() = - member _.P with get() = new T() - member _.M() = [|1..2|] - let t = new T() - t.P.M()(*marker*) """, - marker = "(*marker*)", - list = ["Clone"]) // should contain method on array (result of M call) - - [] - member public this.``ExpressionDotting.Regression.Bug187799.Test2``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - type T() = - member _.M() = [|1..2|] - - type R = { P : T } - - // dotting through an F# record field - let r = { P = T() } - r.P.M()(*marker*) """, - marker = "(*marker*)", - list = ["Clone"]) // should contain method on array (result of M call) - - [] - member public this.``ExpressionDotting.Regression.Bug187799.Test3``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - type R = { P : System.Reflection.InterfaceMapping } - - // Dotting through an F# record field and an IL record field - // Note that InterfaceMapping is a rare example of a public .NET instance field in mscorlib - let r = { P = Unchecked.defaultof } - r.P(*marker*)""", - marker = "(*marker*)", - list = ["InterfaceMethods"]) - - - - [] - member public this.``ExpressionDotting.Regression.Bug187799.Test4``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - type R = { P : System.Reflection.InterfaceMapping } - - // Dotting through an F# record field and an IL record field - // Note that InterfaceMapping is a rare example of a public .NET instance field in mscorlib - let f() = { P = Unchecked.defaultof } - f().P(*marker*)""", - marker = "(*marker*)", - list = ["InterfaceMethods"]) - - [] - member public this.``ExpressionDotting.Regression.Bug187799.Test5``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - type R = { P : System.Reflection.InterfaceMapping } - - // Note that InterfaceMapping is a rare example of a public .NET instance field in mscorlib - let f() = { P = Unchecked.defaultof } - f().P.InterfaceMethods(*marker*)""", - marker = "(*marker*)", - list = ["GetEnumerator"]) - - [] - member public this.``ExpressionDotting.Regression.Bug187799.Test6``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - type R = { P : System.AppDomain } - - // Test dotting through an F# record field and a .NET event - let f() = { P = null } - f().P.UnhandledException(*marker*)""", - marker = "(*marker*)", - list = ["AddHandler"]) - - [] - member public this.``ExpressionDotting.Regression.Bug187799.Test7``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - type R = { P : System.AppDomain } - - // Test dotting through an F# record field and a .NET event - let f() = { P = null } - f().P.UnhandledException.GetType()(*marker*)""", - marker = "(*marker*)", - list = ["Assembly"]) - - [] - member public this.``ExpressionDotting.Regression.Bug187799.Test8``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - type C() = - static member XXX with get() = 4 and set(x) = () - static member CCC with get() = C() - - C.XXX(*marker*) <- 42""", - marker = "(*marker*)", - list = ["CompareTo"]) - - - [] - member public this.``ExpressionDotting.Regression.Bug187799.Test9``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - type C() = - static member XXX with get() = 4 and set(x) = () - static member CCC with get() = C() - - C.XXX(*marker*) <- 42""", - marker = "(*marker*)", - list = ["CompareTo"]) - - // This test case checks that autocomplete on the provided Type DOES NOT show System.Object members - [] - member this.``TypeProvider.EditorHideMethodsAttribute.Type.DoesnotContain``() = - this.VerifyDotCompListDoesNotContainAnyAtStartOfMarker( - fileContents = """ - let t = new N.T() - t(*Marker*)""", - marker = "(*Marker*)", - list = ["Equals";"GetHashCode"], - addtlRefAssy = [PathRelativeToTestAssembly(@"EditorHideMethodsAttribute.dll")]) - - [] - // This test case checks if autocomplete on the provided Type shows only the Event1 elements - member this.``TypeProvider.EditorHideMethodsAttribute.Type.Contains``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - let t = new N.T() - t(*Marker*)""", - marker = "(*Marker*)", - list = ["Event1"], - addtlRefAssy = [PathRelativeToTestAssembly(@"EditorHideMethodsAttribute.dll")]) - - [] - // This test case checks if autocomplete on the provided Type shows the instance method IM1 - member this.``TypeProvider.EditorHideMethodsAttribute.InstanceMethod.Contains``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - let t = new N1.T1() - t(*Marker*)""", - marker = "(*Marker*)", - list = ["IM1"], - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - // This test case checks that nested types show up only statically and not on instances - member this.``TypeProvider.TypeContainsNestedType``() = - // should have it here - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - type XXX = N1.T1(*Marker*)""", - marker = "(*Marker*)", - list = ["SomeNestedType"], - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - // should _not_ have it here - this.VerifyDotCompListDoesNotContainAnyAtStartOfMarker( - fileContents = """ - let t = new N1.T1() - t(*Marker*)""", - marker = "(*Marker*)", - list = ["SomeNestedType"], - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - // This test case checks if autocomplete on the provided Event shows only the AddHandler/RemoveHandler elements - member this.``TypeProvider.EditorHideMethodsAttribute.Event.Contain``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - let t = new N.T() - t.Event1(*Marker*)""", - marker = "(*Marker*)", - list = ["AddHandler";"RemoveHandler"], - addtlRefAssy = [PathRelativeToTestAssembly(@"EditorHideMethodsAttribute.dll")]) - - [] - // This test case checks if autocomplete on the provided Method shows no elements - // You can see this as a "negative case" (to check that the usage of the attribute on a method is harmless) - member this.``TypeProvider.EditorHideMethodsAttribute.Method.Contain``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """ - let t = N.T.M(*Marker*)()""", - marker = "(*Marker*)", - addtlRefAssy = [PathRelativeToTestAssembly(@"EditorHideMethodsAttribute.dll")]) - - [] - // This test case checks if autocomplete on the provided Property (the type of which is not synthetic) shows the usual elements... like GetType() - // 1. I think it does not make sense to use this attribute on a synthetic property unless it's type is also synthetic (already covered) - // 2. You can see this as a "negative case" (to check that the usage of the attribute is harmless) - member this.``TypeProvider.EditorHideMethodsAttribute.Property.Contain``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - let t = N.T.StaticProp(*Marker*)""", - marker = "(*Marker*)", - list = ["GetType"; "Equals"], // just a couple of System.Object methods: we expect them to be there! - addtlRefAssy = [PathRelativeToTestAssembly(@"EditorHideMethodsAttribute.dll")]) - - [] - member this.CompListInDiffFileTypes() = - let fileContents = """ - val x:int = 1 - x(*MarkerInsideaSignatureFile*) - """ - let (solution, project, openfile) = this.CreateSingleFileProject(fileContents, fileKind = SourceFileKind.FSI) - - let completions = DotCompletionAtStartOfMarker openfile "(*MarkerInsideaSignatureFile*)" - AssertCompListContainsAll(completions, []) // .fsi will not contain completions for this (it doesn't make sense) - - let fileContents = """ - let i = 1 - i(*MarkerInsideSourceFile*) - """ - let (solution, project, file) = this.CreateSingleFileProject(fileContents) - - let completions = DotCompletionAtStartOfMarker file "(*MarkerInsideSourceFile*)" - AssertCompListContainsAll(completions, ["CompareTo"; "Equals"]) - - [] - member this.ConstrainedTypes() = - let fileContents = """ - type Pet() = - member x.Name() = "pet" - member x.Speak() = "this is a pet" - type Dog() = - inherit Pet() - member x.dog() = "this is a dog" - let dog = new Dog() - let pet = dog :> Pet - pet(*Mupcast*) - let dctest = pet :?> Dog - dctest(*Mdowncast*) - let f (x : bigint) = x(*Mconstrainedtoint*) - """ - let references = - [ - "System.Numerics" // code uses bigint - ] - let (solution, project, file) = this.CreateSingleFileProject(fileContents, references = references) - let completions = DotCompletionAtStartOfMarker file "(*Mupcast*)" - AssertCompListContainsAll(completions, ["Name"; "Speak"]) - - let completions = DotCompletionAtStartOfMarker file "(*Mdowncast*)" - AssertCompListContainsAll(completions, ["dog"; "Name"]) - - let completions = DotCompletionAtStartOfMarker file "(*Mconstrainedtoint*)" - AssertCompListContainsAll(completions, ["ToString"]) - - [] - member this.``Literal.Float``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = "let myfloat = (42.0)(*Mconstantfloat*)", - marker = "(*Mconstantfloat*)", - list = ["GetType"; "ToString"]) - - [] - member this.``Literal.String``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """let name = "foo"(*Mconstantstring*)""", - marker = "(*Mconstantstring*)", - list = ["Chars"; "Clone"]) - - [] - member this.``Literal.Int``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = "let typeint = (10)(*Mint*)", - marker = "(*Mint*)", - list = ["GetType";"ToString"]) - - [] - member this.``Identifier.InLambdaExpression``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = "let funcLambdaExp = fun (x:int)-> x(*MarkerinLambdaExp*)", - marker = "(*MarkerinLambdaExp*)", - list = ["ToString"; "Equals"]) - - [] - member this.``Identifier.InClass``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - type ClassLetBindIn(x:int) = - let m_field = x(*MarkerLetBindinClass*) """, - marker = "(*MarkerLetBindinClass*)", - list = ["ToString"; "Equals"]) - - [] - member this.``Identifier.InNestedLetBind``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = " -let funcNestedLetBinding (x:int) = - let funcNested (x:int) = x(*MarkerNestedLetBind*) - () -", - marker = "(*MarkerNestedLetBind*)", - list = ["ToString"; "Equals"]) - - [] - member this.``Identifier.InModule``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = " -module ModuleLetBindIn = - let f (x:int) = x(*MarkerLetBindinModule*) -", - marker = "(*MarkerLetBindinModule*)", - list = ["ToString"; "Equals"]) - - [] - member this.``Identifier.InMatchStatement``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = " -let x = 1 -match x(*MarkerMatchStatement*) with - |1 -> 1*1 - |2 -> 2*2 - -", - marker = "(*MarkerMatchStatement*)", - list = ["ToString"; "Equals"]) - - [] - member this.``Identifier.InMatchClause``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = " -let rec f l = - match l with - | [] -> - let xx = System.DateTime.Now - let y = xx(*MarkerMatchClause*) - () - | x :: xs -> f xs -", - marker = "(*MarkerMatchClause*)", - list = ["Add";"Date"]) - - [] - member this.``Expression.ListItem``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - let a = [1;2;3] - a.[1](*MarkerListItem*) - """, - marker = "(*MarkerListItem*)", - list = ["CompareTo"; "ToString"]) - - [] - member this.``Expression.FunctionParameter``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - let f (x : string) = () - f ("1" + "1")(*MarkerParameter*) - """, - marker = "(*MarkerParameter*)", - list = ["CompareTo"; "ToString"]) - - [] - member this.``Expression.Function``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - let func(mm) = 100 - func(x + y)(*MarkerFunction*) - """, - marker = "(*MarkerFunction*)", - list = ["CompareTo"; "ToString"]) - - [] - member this.``Expression.RecordPattern``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - type Rec = - { X : int} - member this.Value = 42 - { X = 1 }(*MarkerRecordPattern*) - """, - marker = "(*MarkerRecordPattern*)", - list = ["Value"; "ToString"]) - - [] - member this.``Expression.2DArray``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - let (a2: int[,]) = Array2.zero_create 10 10 - a2.[1,2](*Marker2DArray*) - """, - marker = "(*Marker2DArray*)", - list = ["ToString"]) - - [] - member this.``Expression.LetBind``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - let f (x : string) = () - //And in many different contexts where the ??tomic expression??occurs at the end of the expression, e.g. - let x = y in f ("1" + "1")(*MarkerContext1*) - """, - marker = "(*MarkerContext1*)", - list = ["CompareTo";"ToString"]) - - [] - member this.``Expression.WhileLoop``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - let f (x : string) = () - while true do - f ("1" + "1")(*MarkerContext3*) - """, - marker = "(*MarkerContext3*)", - list = ["CompareTo";"ToString"]) - - [] - member this.``Expression.List``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """[1;2](*MarkerList*) """, - marker = "(*MarkerList*)", - list = ["Head"; "Item"]) - - [] - member this.``Expression.Nested.InLetBind``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - let f (x : string) = () - // Nested expressions - let x = 42 |> ignore; f ("1" + "1")(*MarkerNested1*) - """, - marker = "(*MarkerNested1*)", - list = ["Chars";"Length"]) - - [] - member this.``Expression.Nested.InWhileLoop``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - let f (x : string) = () - while true do - ignore (f ("1" + "1")(*MarkerNested2*)) - """, - marker = "(*MarkerNested2*)", - list = ["Chars";"Length"]) - - [] - member this.``Expression.ArrayItem.Positive``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - //regression test for bug 1001 - let str1 = Array.init 10 string - str1.[1](*MarkerArrayIndexer*)""", - marker = "(*MarkerArrayIndexer*)", - list = ["Chars";"Split"]) - - [] - member this.``Expression.ArrayItem.Negative``() = - this.VerifyDotCompListDoesNotContainAnyAtStartOfMarker( - fileContents = """ - //regression test for bug 1001 - let str1 = Array.init 10 string - str1.[1](*MarkerArrayIndexer*)""", - marker = "(*MarkerArrayIndexer*)", - list = ["IsReadOnly";"Rank"]) - - [] - member this.``ObjInstance.InheritedClass.MethodsDefInBase``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - type Pet() = - member x.Name() = "pet" - member x.Speak() = "this is a pet" - type Dog() = - inherit Pet() - member x.dog() = "this is a dog" - let dog = new Dog() - dog(*Mderived*)""", - marker = "(*Mderived*)", - list = ["Name"; "dog"]) - - [] - member this.``ObjInstance.AnonymousClass.MethodsDefInInterface``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - type IFoo = - abstract DoStuff : unit -> string - abstract DoStuff2 : int * int -> string -> string - // Implement an interface in a class (This is kind of lame if you don't want to actually declare a class) - type Foo() = - interface IFoo with - member this.DoStuff () = "Return a string" - member this.DoStuff2 (x, y) z = sprintf "Arguments were (%d, %d) %s" x y z - // instanceOfIFoo is an instance of an anonymous class which implements IFoo - let instanceOfIFoo = { - new IFoo with - member this.DoStuff () = "Implement IFoo" - member this.DoStuff2 (x, y) z = sprintf "Arguments were (%d, %d) %s" x y z - }(*Mexpnewtype*)""", - marker = "(*Mexpnewtype*)", - list = ["DoStuff"; "DoStuff2"]) - - [] - member this.``SimpleTypes.SystemTime``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - let typestruct = System.DateTime.Now - typestruct(*Mstruct*)""", - marker = "(*Mstruct*)", - list = ["AddDays"; "Date"]) - - [] - member this.``SimpleTypes.Record``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - type Person = { Name: string; DateOfBirth: System.DateTime } - let typrecord = { Name = "Bill"; DateOfBirth = new System.DateTime(1962,09,02) } - typrecord(*Mrecord*)""", - marker = "(*Mrecord*)", - list = ["DateOfBirth"; "Name"]) - - [] - member this.``SimpleTypes.Enum``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - type weekday = - | Monday = 1 - | Tuesday = 2 - | Wednesday = 3 - | Thursday = 4 - | Friday = 5 - let typeenum = weekday.Friday - typeenum(*Menum*)""", - marker = "(*Menum*)", - list = ["GetType"; "ToString"]) - - [] - member this.``SimpleTypes.DisUnion``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - type Route = int - type Make = string - type Model = string - type Transport = - | Car of Make * Model - | Bicycle - | Bus of Route - let typediscriminatedunion = Car("BMW","360") - typediscriminatedunion(*Mdiscriminatedunion*)""", - marker = "(*Mdiscriminatedunion*)", - list = ["GetType"; "ToString"]) - - [] - member this.``InheritedClass.BaseClassPrivateMethod.Negative``() = - this.VerifyDotCompListDoesNotContainAnyAtStartOfMarker( - fileContents = """ - open System - //define the base class - type Widget() = - let mutable state = 0 - member internal x.MethodInternal() = state - member public x.MethodPublic(n) = state <- state + n - member private x.MethodPrivate() = (state <> 0) - [] - val mutable internal fieldInternal:int - [] - val mutable public fieldPublic:int - [] - val mutable private fieldPrivate:int - //define the divided class which inherent "Widget" - type Divided() = - inherit Widget() - member x.myPrint() = - base(*MUnShowPrivate*) - Console.ReadKey(true)""" , - marker = "(*MUnShowPrivate*)", - list = ["MethodPrivate";"fieldPrivate"]) - - [] - member this.``InheritedClass.BaseClassPublicMethodAndProperty``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - open System - //define the base class - type Widget() = - let mutable state = 0 - member internal x.MethodInternal() = state - member public x.MethodPublic(n) = state <- state + n - member private x.MethodPrivate() = (state <> 0) - [] - val mutable internal fieldInternal:int - [] - val mutable public fieldPublic:int - [] - val mutable private fieldPrivate:int - //define the divided class which inherent "Widget" - type Divided() = - inherit Widget() - member x.myPrint() = - base(*MShowPublic*) - Console.ReadKey(true)""", - marker = "(*MShowPublic*)", - list = ["MethodPublic";"fieldPublic"]) - - [] - member this.``Visibility.InternalNestedClass.Negative``() = - this.VerifyDotCompListDoesNotContainAnyAtStartOfMarker( - fileContents = """System.Console(*Marker1*)""", - marker = "(*Marker1*)", - list = ["ControlCDelegateData"]) - - [] - member this.``Visibility.PrivateIdentifierInDiffModule.Negative``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """ - module Module1 = - let private fieldPrivate = 1 - let private MethodPrivate x = - x+1 - type private TypePrivate()= - member this.mem = 1 - module Module2 = - Module1(*Marker1*) """, - marker = "(*Marker1*)") - - [] - member this.``Visibility.PrivateIdentifierInDiffClass.Negative``() = - this.VerifyDotCompListDoesNotContainAnyAtStartOfMarker( - fileContents = """ - open System - module Module1 = - type Type1()= - [] - val mutable private fieldPrivate:int - member private x.MethodPrivate() = 1 - type Type2()= - let M1= - let type1 = new Type1() - type1(*MarkerOutType*) """, - marker = "(*MarkerOutType*)", - list = ["fieldPrivate";"MethodPrivate"]) - - [] - member this.``Visibility.PrivateFieldInSameClass``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - open System - - module Module1 = - type Type1()= - [] - val mutable private PrivateField:int - static member private PrivateMethod() = 1 - member this.Field1 with get () = this(*MarkerFieldInType*) - member x.MethodTest() = Type1(*MarkerMethodInType*) - let type1 = new Type1() """, - marker = "(*MarkerFieldInType*)", - list = ["PrivateField"]) - - [] - member this.``Visibility.PrivateMethodInSameClass``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - open System - - module Module1 = - type Type1()= - [] - val mutable private PrivateField:int - static member private PrivateMethod() = 1 - member this.Field1 with get () = this(*MarkerFieldInType*) - member x.MethodTest() = Type1(*MarkerMethodInType*) - let type1 = new Type1() """, - marker = "(*MarkerMethodInType*)", - list = ["PrivateMethod"]) - -// [] - member this.``VariableIdentifier.AsParameter``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module MyModule = - type DuType = - | Tag of int - let f (DuType(*Maftervariable1*).Tag(x)) = 10 """, - marker = "(*Maftervariable1*)", - list = ["Tag"]) - - [] - member this.``VariableIdentifier.InMeasure.DefineInDiffNamespace``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - namespace MyNamespace1 - module MyModule = - type DuType = - | Tag of int - let f (DuType(*Maftervariable1*).Tag(x)) = 10 - type Pet() = - member x.Name = "pet" - member x.Speak() = "this is a pet" - type Dog() = - inherit Pet() - do base(*Maftervariable3*).GetType() - let dog = new Dog() - namespace MyNamespace2 - module MyModule2 = - let typeFunc<[] 'a> = [1; 2; 3] - let f (x:MyNamespace1.MyModule(*Maftervariable4*)) = 10 - let y = int System.IO(*Maftervariable5*)""", - marker = "(*Maftervariable2*)", - list = []) - - [] - member this.``VariableIdentifier.MethodsInheritFromBase``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - namespace MyNamespace1 - module MyModule = - type DuType = - | Tag of int - let f (DuType(*Maftervariable1*).Tag(x)) = 10 - type Pet() = - member x.Name = "pet" - member x.Speak() = "this is a pet" - type Dog() = - inherit Pet() - do base(*Maftervariable3*).GetType() - let dog = new Dog()""", - marker = "(*Maftervariable3*)", - list = ["Name";"Speak"]) - - [] - member this.``VariableIdentifier.AsParameter.DefineInDiffNamespace``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - namespace MyNamespace1 - module MyModule = - type DuType = - | Tag of int - let f (DuType(*Maftervariable1*).Tag(x)) = 10 - type Pet() = - member x.Name = "pet" - member x.Speak() = "this is a pet" - type Dog() = - inherit Pet() - do base(*Maftervariable3*).GetType() - let dog = new Dog() - namespace MyNamespace2 - module MyModule2 = - let typeFunc = [1; 2; 3] - let f (x:MyNamespace1.MyModule(*Maftervariable4*)) = 10 - let y = int System.IO(*Maftervariable5*)""", - marker = "(*Maftervariable4*)", - list = ["DuType"]) - - [] - member this.``VariableIdentifier.SystemNamespace``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - namespace MyNamespace1 - module MyModule = - type DuType = - | Tag of int - let f (DuType(*Maftervariable1*).Tag(x)) = 10 - type Pet() = - member x.Name = "pet" - member x.Speak() = "this is a pet" - type Dog() = - inherit Pet() - do base(*Maftervariable3*).GetType() - let dog = new Dog() - namespace MyNamespace2 - module MyModule2 = - let typeFunc = [1; 2; 3] - let f (x:MyNamespace1.MyModule(*Maftervariable4*)) = 10 - let y = int System.IO(*Maftervariable5*)""", - marker = "(*Maftervariable5*)", - list = ["BinaryReader";"Stream";"Directory"]) - - [] - member this.``LongIdent.AsAttribute``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - [] - type TestAttribute() = - member x.print() = "print" """, - marker = "(*Mattribute*)", - list = ["Obsolete"]) - - [] - member this.``ImportStatement.System.ImportDirectly``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - open System(*Mimportstatement1*) - open IO = System(*Mimportstatement2*)""", - marker = "(*Mimportstatement1*)", - list = ["Collections"]) - - [] - member this.``ImportStatement.System.ImportAsIdentifier``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - open System(*Mimportstatement1*) - open IO = System(*Mimportstatement2*)""", - marker = "(*Mimportstatement2*)", - list = ["IO"]) - - [] - member this.``LongIdent.PatternMatch.AsVariable.DefFromDiffNamespace``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - namespace NS - module longident = - type Direction = - | Left = 1 - | Right = 2 - type MoveCursor() = - member this.Direction = Direction.Left - namespace NS2 - module test = - let cursor = new NS.longident.MoveCursor() - match cursor(*Mpatternmatch1*) with - | NS.longident.Direction.Left -> "move left" - | NS(*Mpatternmatch2*) -> "move right" """, - marker = "(*Mpatternmatch1*)", - list = ["Direction";"ToString"]) - - [] - member this.``LongIdent.PatternMatch.AsConstantValue.DefFromDiffNamespace``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - namespace NS - module longident = - type Direction = - | Left = 1 - | Right = 2 - type MoveCursor() = - member this.Direction = Direction.Left - namespace NS2 - module test = - let cursor = new NS.longident.MoveCursor() - match cursor(*Mpatternmatch1*) with - | NS.longident.Direction.Left -> "move left" - | NS(*Mpatternmatch2*) -> "move right" """, - marker = "(*Mpatternmatch2*)", - list = ["longident"]) - - [] - member this.``LongIdent.PInvoke.AsReturnType``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - open System.IO - open System.Runtime.InteropServices - // Get two temp files, write data into one of them - let tempFile1, tempFile2 = Path.GetTempFileName(), Path.GetTempFileName() - let writer = new StreamWriter (tempFile1) - writer.WriteLine("Some Data") - writer.Close() - // Original signature - //[] - //extern bool CopyFile(string lpExistingFileName, string lpNewFileName, bool bFailIfExists); - [] - extern System(*Mpinvokereturntype*) CopyFile_Arrays(char[] lpExistingFileName, char[] lpNewFileName, bool bFailIfExists); - let result = CopyFile_Arrays(tempFile1.ToCharArray(), tempFile2.ToCharArray(), false) - printfn "Array %A" result""", - marker = "(*Mpinvokereturntype*)", - list = ["Boolean";"Int32"]) - - [] - member this.``LongIdent.PInvoke.AsAttribute``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - open System.IO - open System.Runtime.InteropServices - - module mymodule = - type SomeAttrib() = - inherit System.Attribute() - type myclass() = - member x.name() = "test case" - module mymodule2 = - [] - extern bool CopyFile_Attrib([] char [] lpExistingFileName, char []lpNewFileName, [] bool & bFailIfExists); - - let result5 = CopyFile_Arrays(tempFile1.ToCharArray(), tempFile2.ToCharArray(), false) - printfn "WithAttribute %A" result5""", - marker = "(*Mpinvokeattribute*)", - list = ["SomeAttrib"]) - - [] - member this.``LongIdent.PInvoke.AsParameterType``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - open System.IO - open System.Runtime.InteropServices - [] - extern bool CopyFile_ArraySpaces(char [] lpExistingFileName, char []lpNewFileName, System(*Mpinvokeparametertype*) bFailIfExists); - let result2 = CopyFile_Arrays(tempFile1.ToCharArray(), tempFile2.ToCharArray(), false) - printfn "Array Space %A" result2""", - marker = "(*Mpinvokeparametertype*)", - list = ["Boolean";"Int32"]) - - [] - member this.``LongIdent.Record.AsField``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module MyModule = - type person = - { name: string; - dateOfBirth: System.DateTime; } - module MyModule2 = - let x = {MyModule(*Mrecord*) = 32}""", - marker = "(*Mrecord*)", - list = ["person"]) - - [] - member this.``LongIdent.DiscUnion.AsTypeParameter.DefInDiffNamespace``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - namespace MyNamespace1 - module MyModule = - type DuType = - | Tag of int - type Pet() = - member x.Name = "pet" - member x.Speak() = "this is a pet" - type Dog() = - inherit Pet() - namespace MyNamespace2 - module MyModule2 = - let foo = MyNamespace1.MyModule(*Mtypeparameter1*) - let f (x:int) = MyNamespace1.MyModule.DuType(*Mtypeparameter2*) - let typeFunc<[] 'a> = 10""", - marker = "(*Mtypeparameter1*)", - list = ["Dog";"DuType"]) - - [] - member this.``LongIdent.AnonymousFunction.AsTypeParameter.DefFromDiffNamespace``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - namespace MyNamespace1 - module MyModule = - type DuType = - | Tag of int - type Pet() = - member x.Name = "pet" - member x.Speak() = "this is a pet" - type Dog() = - inherit Pet() - namespace MyNamespace2 - module MyModule2 = - let foo = MyNamespace1.MyModule(*Mtypeparameter1*) - let f (x:int) = MyNamespace1.MyModule.DuType(*Mtypeparameter2*) - let typeFunc<[] 'a> = 10""", - marker = "(*Mtypeparameter2*)", - list = ["Tag"]) - - [] - member this.``LongIdent.UnitMeasure.AsTypeParameter.DefFromDiffNamespace``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - namespace MyNamespace1 - module MyModule = - type DuType = - | Tag of int - type Pet() = - member x.Name = "pet" - member x.Speak() = "this is a pet" - type Dog() = - inherit Pet() - namespace MyNamespace2 - module MyModule2 = - let foo = MyNamespace1.MyModule(*Mtypeparameter1*) - let f (x:int) = MyNamespace1.MyModule.DuType(*Mtypeparameter2*) - let typeFunc<[] 'a> = 10""", - marker = "(*Mtypeparameter3*)", - list = []) - - [] - member this.``RedefinedIdentifier.DiffScope.InScope.Positive``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - let identifierBothScope = "" - let functionScope () = - let identifierBothScope = System.DateTime.Now - identifierBothScope(*MarkerShowLastOneWhenInScope*) - identifierBothScope(*MarkerShowLastOneWhenOutscoped*)""", - marker = "(*MarkerShowLastOneWhenInScope*)", - list = ["DayOfWeek"]) - - [] - member this.``RedefinedIdentifier.DiffScope.InScope.Negative``() = - this.VerifyDotCompListDoesNotContainAnyAtStartOfMarker( - fileContents = """ - let identifierBothScope = "" - let functionScope () = - let identifierBothScope = System.DateTime.Now - identifierBothScope(*MarkerShowLastOneWhenInScope*) - identifierBothScope(*MarkerShowLastOneWhenOutscoped*)""", - marker = "(*MarkerShowLastOneWhenInScope*)", - list = ["Chars"]) - - [] - member this.``RedefinedIdentifier.DiffScope.OutScope.Positive``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - let identifierBothScope = "" - let functionScope () = - let identifierBothScope = System.DateTime.Now - identifierBothScope(*MarkerShowLastOneWhenInScope*) - identifierBothScope(*MarkerShowLastOneWhenOutscoped*)""", - marker = "(*MarkerShowLastOneWhenOutscoped*)", - list = ["Chars"]) - - [] - member this.``ObjInstance.ExtensionMethods.WithoutDef.Negative``() = - this.VerifyDotCompListDoesNotContainAnyAtStartOfMarker( - fileContents = """ - open System - let rnd = new System.Random() - rnd(*MWithoutReference*)""", - marker = "(*MWithoutReference*)", - list = ["NextDice";"DiceValue"]) - - [] - member this.``Class.DefInDiffNameSpace``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - namespace NS1 - module MyModule = - [] - type ObsoleteType() = - member this.TestMethod() = 10 - [] - type CompilerMessageType() = - member this.TestMethod() = 10 - type TestType() = - member this.TestMethod() = 100 - [] - member this.ObsoleteMethod() = 100 - [] - member this.CompilerMessageMethod() = 100 - [] - member this.HiddenMethod() = 10 - [] - member this.VisibleMethod() = 10 - [] - member this.VisibleMethod2() = 10 - namespace NS2 - module m2 = - type x = NS1.MyModule(*MarkerType*) - let b = (new NS1.MyModule.TestType())(*MarkerMethod*) - """, - marker = "(*MarkerType*)" , - list = ["TestType"]) - - [] - member this.``Class.DefInDiffNameSpace.WithAttributes.Negative``() = - this.VerifyDotCompListDoesNotContainAnyAtStartOfMarker( - fileContents = """ - namespace NS1 - module MyModule = - [] - type ObsoleteType() = - member this.TestMethod() = 10 - [] - type CompilerMessageType() = - member this.TestMethod() = 10 - type TestType() = - member this.TestMethod() = 100 - [] - member this.ObsoleteMethod() = 100 - [] - member this.CompilerMessageMethod() = 100 - [] - member this.HiddenMethod() = 10 - [] - member this.VisibleMethod() = 10 - [] - member this.VisibleMethod2() = 10 - namespace NS2 - module m2 = - type x = NS1.MyModule(*MarkerType*) - let b = (new NS1.MyModule.TestType())(*MarkerMethod*) - """, - marker = "(*MarkerType*)", - list = ["ObsoleteType";"CompilerMessageType"]) - - [] - member this.``Method.DefInDiffNameSpace``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - namespace NS1 - module MyModule = - [] - type ObsoleteType() = - member this.TestMethod() = 10 - [] - type CompilerMessageType() = - member this.TestMethod() = 10 - type TestType() = - member this.TestMethod() = 100 - [] - member this.ObsoleteMethod() = 100 - [] - member this.CompilerMessageMethod() = 100 - [] - member this.HiddenMethod() = 10 - [] - member this.VisibleMethod() = 10 - [] - member this.VisibleMethod2() = 10 - - namespace NS2 - module m2 = - type x = NS1.MyModule(*MarkerType*) - let b = (new NS1.MyModule.TestType())(*MarkerMethod*) - """, - marker = "(*MarkerMethod*)", - list = ["TestMethod"; "VisibleMethod";"VisibleMethod2"]) - - [] - member this.``Method.DefInDiffNameSpace.WithAttributes.Negative``() = - this.VerifyDotCompListDoesNotContainAnyAtStartOfMarker( - fileContents = """ - namespace NS1 - module MyModule = - [] - type ObsoleteType() = - member this.TestMethod() = 10 - [] - type CompilerMessageType() = - member this.TestMethod() = 10 - type TestType() = - member this.TestMethod() = 100 - [] - member this.ObsoleteMethod() = 100 - [] - member this.CompilerMessageMethod() = 100 - [] - member this.HiddenMethod() = 10 - [] - member this.VisibleMethod() = 10 - [] - member this.VisibleMethod2() = 10 - namespace NS2 - module m2 = - type x = NS1.MyModule(*MarkerType*) - let b = (new NS1.MyModule.TestType())(*MarkerMethod*)""", - marker = "(*MarkerMethod*)", - list = ["ObsoleteMethod";"CompilerMessageMethod";"HiddenMethod"]) - - [] - member this.``ObjInstance.ExtensionMethods.WithDef.Positive``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - open System - - type System.Random with - member this.NextDice() = true - member this.DiceValue = 6 - - let rnd = new System.Random() - rnd(*MWithReference*)""", - marker = "(*MWithReference*)", - list = ["NextDice";"DiceValue"]) - - [] - member this.``Keywords.If``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """ - if(*MarkerKeywordIf*) true then - () """, - marker ="(*MarkerKeywordIf*)") - - [] - member this.``Keywords.Let``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """let(*MarkerKeywordLet*) a = 1""", - marker = "(*MarkerKeywordLet*)") - - [] - member this.``Keywords.Match``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """ - match(*MarkerKeywordMatch*) a with - | pattern -> exp""", - marker = "(*MarkerKeywordMatch*)") - - [] - member this.``MacroDirectives.nowarn``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """#nowarn(*MarkerPreProcessNowarn*)""", - marker = "(*MarkerPreProcessNowarn*)") - - [] - member this.``MacroDirectives.define``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """#define(*MarkerPreProcessDefine*)""", - marker = "(*MarkerPreProcessDefine*)") - - [] - member this.``MacroDirectives.PreProcessDefine``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """#define Foo(*MarkerPreProcessDefineConst*)""", - marker = "(*MarkerPreProcessDefineConst*)") - - [] - member this.``Identifier.InClass.WithoutDef``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """ - type Type2 = - val mutable x(*MarkerValue*) : string""", - marker = "(*MarkerValue*)") - - [] - member this.``Identifier.InDiscUnion.WithoutDef``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """ - type DUTag = - |Tag(*MarkerDU*) of int""", - marker = "(*MarkerDU*)") - - [] - member this.``Identifier.InRecord.WithoutDef``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """type Rec = { X(*MarkerRec*) : int }""", - marker = "(*MarkerRec*)") - - [] - member this.``Identifier.AsNamespace``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """namespace Namespace1(*MarkerNamespace*)""", - marker = "(*MarkerNamespace*)") - - [] - member this.``Identifier.AsModule``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """module Module1(*MarkerModule*)""", - marker = "(*MarkerModule*)") - - [] - member this.``Identifier.WithoutDef``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """ abcd(*MarkerUndefinedIdentifier*) """, - marker = "(*MarkerUndefinedIdentifier*)") - - [] - member this.``Identifier.InMatch.UnderScore``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """ - let x = 1 - match x with - |1 -> 1*2 - |2 -> 2*2 - |_(*MarkerIdentifierIsUnderScore*) -> 0 """, - marker = "(*MarkerIdentifierIsUnderScore*)") - - [] - member this.MemberSelf() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """ - type Foo() = - member this(*Mmemberself*)""", - marker = "(*Mmemberself*)") - - [] - member this.``Expression.InComment``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """ - //open System - //open IO = System(*Mcomment*)""", - marker = "(*Mcomment*)") - - [] - member this.``Expression.InString``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """let x = "System.Console(*Minstring*)" """, - marker = "(*Minstring*)") - - // Regression test for 1067 -- Completion lists don't work after generic arguments - for generic functions and for static members of generic types - [] - member this.``Regression1067.InstanceOfGenericType``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - type GT<'a> = - static member P = 12 - static member Q = 13 - - let _ = GT(*Marker1*) - type gt_int = GT - gt_int(*Marker2*) - - type D = - class - end - - let x = typeof(*Marker3*) - let y = typeof - y(*Marker4*) - """, - marker = "(*Marker2*)", - list = ["P"; "Q"]) - - [] - member this.``Regression1067.ClassUsingGenericTypeAsAttribute``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - type GT<'a> = - static member P = 12 - static member Q = 13 - - let _ = GT(*Marker1*) - type gt_int = GT - gt_int(*Marker2*) - - type D = - class - end - - let x = typeof(*Marker3*) - let y = typeof - y(*Marker4*) - """, - marker = "(*Marker4*)", - list = ["Assembly"; "FullName"; "GUID"]) - - [] - member this.NoInfiniteLoopInProperties() = - let fileContents = """ - open System.Windows.Forms - - let tn = new TreeNode("") - - tn.Nodes(*Marker1*)""" - let (solution, project, file) = this.CreateSingleFileProject(fileContents, references = ["System.Windows.Forms"]) - - let completions = DotCompletionAtStartOfMarker file "(*Marker1*)" - AssertCompListDoesNotContainAny(completions, ["Nodes"]) - - // Regression for bug 3225 -- Invalid intellisense when inside of a quotation - [] - member this.``Regression3225.Identifier.InQuotation``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - let _ = <@ let x = "foo" - x(*Marker*) @>""", - marker = "(*Marker*)", - list = ["Chars"; "Length"]) - - // Regression for bug 1911 -- No completion list of expr in match statement - [] - member this.``Regression1911.Expression.InMatchStatement``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - type Thingy = { A : bool; B : int } - - let test = match (List.head [{A = true; B = 0}; {A = false; B = 1}])(*Marker*)""", - marker = "(*Marker*)", - list = ["A"; "B"]) - - - // Bug 3627 - Completion lists should be filtered in many contexts - // This blocks six testcases and is slated for Dev11, so these will be disabled for some time. - [] - member this.AfterTypeParameter() = - let fileContents = """ - type Type1 = Tag of string(*MarkerDUTypeParam*) - - let f x:int -> string(*MarkerParamFunction*) - - let Type2<'a(*MarkerGenericParam*)> = 1 - - let type1 = typeof - """ - let (solution, project, file) = this.CreateSingleFileProject(fileContents) - - //Completion list Not comes up after DUType parameter - let completions = DotCompletionAtStartOfMarker file "(*MarkerDUTypeParam*)" - AssertCompListIsEmpty(completions) - - //Completion list Not comes up after function parameter - let completions = DotCompletionAtStartOfMarker file "(*MarkerParamFunction*)" - AssertCompListIsEmpty(completions) - - //Completion list Not comes up after generic parameter - let completions = DotCompletionAtStartOfMarker file "(*MarkerGenericParam*)" - AssertCompListIsEmpty(completions) - - //Completion list Not comes up after parameter in typeof - let completions = DotCompletionAtStartOfMarker file "(*MarkerParamTypeof*)" - AssertCompListIsEmpty(completions) - - [] - member this.``Identifier.AsClassName.InInitial``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """ - type f1(*MarkerType*) = - val field: int""", - marker = "(*MarkerType*)") - - [] - member this.``Identifier.AsFunctionName.InInitial``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """let f2(*MarkerFunctionIdentifier*) x = x+1 """, - marker = "(*MarkerFunctionIdentifier*)") - - [] - member this.``Identifier.AsParameter.InInitial``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """ let f3 x(*MarkerParam*) = x+1""", - marker = "(*MarkerParam*)") - - [] - member this.``Identifier.AsFunctionName.UsingFunKeyword``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """fun f4(*MarkerFunctionDeclaration*) x -> x+1""", - marker = "(*MarkerFunctionDeclaration*)") - - [] - member public this.``Identifier.EqualityConstraint.Bug65730``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """let g3<'a when 'a : equality> (x:'a) = x(*Marker*)""", - marker = "(*Marker*)", - list = ["Equals"; "GetHashCode"]) // equality constraint should make these show up - - [] - member this.``Identifier.InFunctionMatch``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """ - let f5 = function - | 1(*MarkerFunctionMatch*) -> printfn "1" - | 2 -> printfn "2" """, - marker = "(*MarkerFunctionMatch*)") - - [] - member this.``Identifier.This``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """ - type Type1 = - member this(*MarkerMemberThis*).Foo () = 3""", - marker = "(*MarkerMemberThis*)") - - [] - member this.``Identifier.AsProperty``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """ - type Type2 = - member this.Foo(*MarkerMemberThisProperty*) = 1""", - marker = "(*MarkerMemberThisProperty*)") - - [] - member this.``ExpressionPropertyAssignment.Bug217051``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - type Foo() = - member val Prop = 0 with get, set - - Foo()(*Marker*) <- 4 """, - marker = "(*Marker*)", - list = ["Prop"]) - - [] - member this.``ExpressionProperty.Bug234687``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - open System.Reflection - let x = obj() - let a = x.GetType().Assembly(*Marker*) - """, - marker = "(*Marker*)", - list = ["CodeBase"]) // expect instance properties of Assembly, not static Assembly methods - - [] - member this.NotShowAttribute() = - let fileContents = """ - open System - - [] - type testclass() = - member x.Name() = "test" - - [] - type testattribute() = - member x.Empty = 0 - """ - let (solution, project, file) = this.CreateSingleFileProject(fileContents) - - //Completion List----where completion list does not come up - let completions = DotCompletionAtStartOfMarker file "(*Mattribute1*)" - AssertCompListIsEmpty(completions) - - //Completion List----type where completion list does not come up - let completions = DotCompletionAtStartOfMarker file "(*Mattribute2*)" - AssertCompListIsEmpty(completions) - - [] - member this.NotShowPInvokeSignature() = - let fileContents = """ - //open System - //open IO = System(*Mcomment*) - - #if RELEASE - System.Console(*Mdisablecode*) - #endif - - let x = "System.Console(*Minstring*)" - """ - let (solution, project, file) = this.CreateSingleFileProject(fileContents) - - - // description="Completion List----where completion list does not come up - let completions = DotCompletionAtStartOfMarker file "(*Mreturntype*)" - AssertCompListIsEmpty(completions) - - - // description="Completion List----type where completion list does not come up - let completions = DotCompletionAtStartOfMarker file "(*Mfunctionname*)" - AssertCompListIsEmpty(completions) - - - // description="Completion List----type where completion list does not come up - let completions = DotCompletionAtStartOfMarker file "(*Mparametertype*)" - AssertCompListIsEmpty(completions) - - - // description="Completion List----type where completion list does not come up - let completions = DotCompletionAtStartOfMarker file "(*Mparameter*)" - AssertCompListIsEmpty(completions) - - - // description="Completion List----type where completion list does not come up - let completions = DotCompletionAtStartOfMarker file "(*Mparameterlist*)" - AssertCompListIsEmpty(completions) - - [] - member this.``Basic.Completion.UnfinishedLet``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - let g(x) = x+1 - - let f() = - let r = g(4)(*Marker*) """, - marker = "(*Marker*)", - list = ["CompareTo"]) - - [] - member this.``ShortFormSeqExpr.Bug229610``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module test - open System.Text.RegularExpressions - - let limit = 50 - let linkPat = "href=\s*\"[^\"h]*(http://[^&\"]*)\"" - let getLinks (txt:string) = [ for m in Regex.Matches(txt,linkPat) -> m.Groups.Item(1)(*Marker*) ] """, - marker = "(*Marker*)", - list = ["Value"]) + Assert.True(completions.Length>0) - //Regression test for bug 69159 Fsharp: dot completion is mission for an array - [] - member this.``Array.InitialUsing..``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """let x1 = [| 0.0 .. 0.1 .. 10.0 |](*Marker*)""", - marker = "(*Marker*)", - list = ["Length";"Clone";"ToString"]) - - //Regression test for bug 65740 Fsharp: dot completion is mission after a '#' statement - [] - member this.``Identifier.In#Statement``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - # 29 "original-test-file.fs" - let argv = System.Environment.GetCommandLineArgs() - - let SetCulture() = - if argv(*Marker*)Length > 2 && argv.[1] = "--culture" then - let cultureString = argv.[2] - """, - marker = "(*Marker*)", - list = ["Length";"Clone";"ToString"]) - - //This test is about CompletionList which should be moved to completionList, it's too special to refactor. - //Regression test for bug 72595 typing quickly yields wrong intellisense - [] - member this.``BadCompletionAfterQuicklyTyping``() = + [] + member this.``BadCompletionAfterQuicklyTyping.Bug72561``() = let code = [ " " ] let (_, _, file) = this.CreateSingleFileProject(code) - + TakeCoffeeBreak(this.VS) - + let gpatcc = GlobalParseAndTypeCheckCounter.StartNew(this.VS) // In this case, we quickly type "." and then get dot-completions - // For "level <- Module" this shows completions from the "Module" (e.g. "Module.Other") // This simulates the case when the user quickly types "dot" after the file has been TCed before. - ReplaceFileInMemoryWithoutCoffeeBreak file ([ "[1]." ]) MoveCursorToEndOfMarker(file, ".") + // Note: no TakeCoffeeBreak(this.VS) + let completions = AutoCompleteAtCursor file + AssertCompListContainsExactly(completions, []) // there are no stale results for an expression at this location, so nothing is returned immediately + // second-chance intellisense will kick in: TakeCoffeeBreak(this.VS) - let completions = AutoCompleteAtCursor file AssertCompListContainsAll(completions, ["Length"]) AssertCompListDoesNotContainAny(completions, ["AbstractClassAttribute"]) + gpatcc.AssertExactly(0,0) - [] - member this.``SelfParameter.InDoKeywordScope``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - type foo() as this = - do - this(*Marker*)""", - marker = "(*Marker*)", - list = ["ToString"]) - - [] - member this.``SelfParameter.InDoKeywordScope.Negative``() = - this.VerifyDotCompListDoesNotContainAnyAtStartOfMarker( - fileContents = """ - type foo() as this = - do - this(*Marker*)""", - marker = "(*Marker*)", - list = ["Value";"Contents"]) - - [] - member this.``ReOpenNameSpace.StaticProperties``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - // Static properties & events - namespace A - type TestType = - static member Prop = 0 - static member Event = (new Event()).Publish - namespace B - open A - open A - TestType(*Marker1*)""", - marker = "(*Marker1*)", - list = ["Prop";"Event"]) - - [] - member this.``ReOpenNameSpace.EnumTypes``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - // F# declared enum types: - namespace A - module Test = - type A = | Foo = 0 - - namespace B - open A - open A - Test.A(*Marker2*) - """, - marker = "(*Marker2*)", - list = ["Foo"]) - - [] - member this.``ReOpenNameSpace.SystemLibrary``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - open System.IO - open System.IO - - File(*Marker3*) - """, - marker = "(*Marker3*)", - list = ["Open"]) - - [] - member this.``ReOpenNameSpace.FsharpQuotation``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - open Microsoft.FSharp.Quotations - open Microsoft.FSharp.Quotations - Expr(*Marker4*) - """, - marker = "(*Marker4*)", - list = ["Value"]) - - [] - member this.``ReOpenNameSpace.MailboxProcessor``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - open Microsoft.FSharp.Control - open Microsoft.FSharp.Control - let counter = - MailboxProcessor(*Marker6*)""", - marker = "(*Marker6*)", - list = ["Start"]) - - [] - member this.``ReopenNamespace.Module``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - namespace A - module Test = - let foo n = n + 1 - namespace B - open A - open A - Test(*Marker7*)""", - marker = "(*Marker7*)", - list = ["foo"]) - - [] - member this.``Expression.InLetScope``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - - let p4 = - let isPalindrome x = - let chars = (string_of_int x).ToCharArray() - let len = chars(*Marker1*) - chars - |> Array.mapi (fun i c -> (i(*Marker2*), c(*Marker3*))""", - marker = "(*Marker1*)", - list = ["IsFixedSize";"Initialize"]) - - [] - member this.``Expression.InFunScope.FirstParameter``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - let p4 = - let isPalindrome x = - let chars = (string_of_int x).ToCharArray() - let len = chars(*Marker1*) - chars - |> Array.mapi (fun i c -> (i(*Marker2*), c(*Marker3*))""", - marker = "(*Marker2*)", - list = ["CompareTo"]) - - [] - member this.``Expression.InFunScope.SecParameter``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - - let p4 = - let isPalindrome x = - let chars = (string_of_int x).ToCharArray() - let len = chars(*Marker1*) - chars - |> Array.mapi (fun i c -> (i(*Marker2*), c(*Marker3*))""", - marker = "(*Marker3*)", - list = ["GetType";"ToString"]) - - [] - member this.``Expression.InMatchWhenClause``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - type DU = X of int - - let timefilter pkt = - match pkt with - | X(hdr) when hdr(*MarkerMatch*) -> () - | _ -> () - """, - marker = "(*MarkerMatch*)", - list = ["CompareTo";"ToString"]) - - //Regression test for bug 3223 in PS: No intellisense at point - [] - member this.``Identifier.InActivePattern.Positive``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - // regression test for bug 3223 No intellisense at point - - open Microsoft.FSharp.Quotations.Patterns - open Microsoft.FSharp.Quotations.DerivedPatterns - - let test1 = <@ 1 + 1 @> - let _ = - match test1 with - | Call(None, methInfo, args) -> - if methInfo(*Marker*) - """, - marker = "(*Marker*)", - list = ["Attributes";"CallingConvention";"ContainsGenericParameters"]) - - [] - member this.``Identifier.InActivePattern.Negative``() = - this.VerifyDotCompListDoesNotContainAnyAtStartOfMarker( - fileContents = """ - module BasicTest - // regression test for bug 3223 No intellisense at point - - open Microsoft.FSharp.Quotations.Patterns - open Microsoft.FSharp.Quotations.DerivedPatterns - - let test1 = <@ 1 + 1 @> - let _ = - match test1 with - | Call(None, methInfo, args) -> - if methInfo(*Marker*) - """, - marker = "(*Marker*)", - list = ["Head";"ToInt"]) - - //Regression test of bug 2296:No completion lists on the direct results of a method call - [] - member this.``Regression2296.DirectResultsOfMethodCall``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - // regression test of bug 2296: No completion lists on the direct results of a method call - - // This is a function that has a custom attribute on the return type. - let foo(a) : [] int - = a + 5 - - // The rest of the code is a mere verification that the compiler thru reflection - let executingAssembly = System.Reflection.Assembly.GetExecutingAssembly() - let programType = executingAssembly.GetType("Program") - let message = programType.GetMethod("foo")(*Marker1*) - """, - marker = "(*Marker1*)", - list = ["Attributes";"CallingConvention";"IsFamily"]) - - [] - member this.``Regression2296.DirectResultsOfMethodCall.Negative``() = - this.VerifyDotCompListDoesNotContainAnyAtStartOfMarker( - fileContents = """ - module BasicTest - // regression test of bug 2296: No completion lists on the direct results of a method call - - // This is a function that has a custom attribute on the return type. - let foo(a) : [] int - = a + 5 - - // The rest of the code is a mere verification that the compiler thru reflection - let executingAssembly = System.Reflection.Assembly.GetExecutingAssembly() - let programType = executingAssembly.GetType("Program") - let message = programType.GetMethod("foo")(*Marker1*) - """, - marker = "(*Marker1*)", - list = ["value__"]) - - [] - member this.``Regression2296.Identifier.String.Reflection01``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - // regression test of bug 2296: No completion lists on the direct results of a method call - - // This is a function that has a custom attribute on the return type. - let foo(a) : [] int - = a + 5 - - // The rest of the code is a mere verification that the compiler thru reflection - let executingAssembly = System.Reflection.Assembly.GetExecutingAssembly() - - let programType = executingAssembly.GetType("Program") - - let message = programType.GetMethod("foo")(*Marker1*) - - let x = "" - let _ = x.Contains("a")(*Marker2*)""", - marker = "(*Marker2*)", - list = ["CompareTo";"GetType";"ToString"]) - - [] - member this.``Regression2296.Identifier.String.Reflection01.Negative``() = - this.VerifyDotCompListDoesNotContainAnyAtStartOfMarker( - fileContents = """ - module BasicTest - // regression test of bug 2296: No completion lists on the direct results of a method call - - // This is a function that has a custom attribute on the return type. - let foo(a) : [] int - = a + 5 - - // The rest of the code is a mere verification that the compiler thru reflection - let executingAssembly = System.Reflection.Assembly.GetExecutingAssembly() - - let programType = executingAssembly.GetType("Program") - - let message = programType.GetMethod("foo")(*Marker1*) - - let x = "" - let _ = x.Contains("a")(*Marker2*)""", - marker = "(*Marker2*)", - list = ["value__"]) - - [] - member this.``Regression2296.Identifier.String.Reflection02``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - // regression test of bug 2296: No completion lists on the direct results of a method call - - // This is a function that has a custom attribute on the return type. - let foo(a) : [] int - = a + 5 - - // The rest of the code is a mere verification that the compiler thru reflection - let executingAssembly = System.Reflection.Assembly.GetExecutingAssembly() - - let programType = executingAssembly.GetType("Program") - - let message = programType.GetMethod("foo")(*Marker1*) - - let x = "" - let _ = x.Contains("a")(*Marker2*) - let _ = x.CompareTo("a")(*Marker3*)""", - marker = "(*Marker3*)", - list = ["CompareTo";"GetType";"ToString"]) - - [] - member this.``Regression2296.Identifier.String.Reflection02.Negative``() = - this.VerifyDotCompListDoesNotContainAnyAtStartOfMarker( - fileContents = """ - module BasicTest - // regression test of bug 2296: No completion lists on the direct results of a method call - - // This is a function that has a custom attribute on the return type. - let foo(a) : [] int - = a + 5 - - // The rest of the code is a mere verification that the compiler thru reflection - let executingAssembly = System.Reflection.Assembly.GetExecutingAssembly() - let programType = executingAssembly.GetType("Program") - let message = programType.GetMethod("foo")(*Marker1*) - let x = "" - let _ = x.Contains("a")(*Marker2*) - let _ = x.CompareTo("a")(*Marker3*)""", - marker = "(*Marker3*)", - list = ["value__"]) - - [] - member this.``Regression2296.System.StaticMethod.Reflection``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - // regression test of bug 2296: No completion lists on the direct results of a method call - - // This is a function that has a custom attribute on the return type. - let foo(a) : [] int - = a + 5 - - // The rest of the code is a mere verification that the compiler thru reflection - let executingAssembly = System.Reflection.Assembly.GetExecutingAssembly() - let programType = executingAssembly.GetType("Program") - let message = programType.GetMethod("foo")(*Marker1*) - let x = "" - let _ = x.Contains("a")(*Marker2*) - let _ = x.CompareTo("a")(*Marker3*) - - open System.IO - - let GetFileSize filePath = File.GetAttributes(filePath)(*Marker4*)""", - marker = "(*Marker4*)", - list = ["CompareTo";"GetType";"ToString"]) - - [] - member this.``Regression2296.System.StaticMethod.Reflection.Negative``() = - this.VerifyDotCompListDoesNotContainAnyAtStartOfMarker( - fileContents = """ - module BasicTest - // regression test of bug 2296: No completion lists on the direct results of a method call - - // This is a function that has a custom attribute on the return type. - let foo(a) : [] int - = a + 5 - - // The rest of the code is a mere verification that the compiler thru reflection - let executingAssembly = System.Reflection.Assembly.GetExecutingAssembly() - let programType = executingAssembly.GetType("Program") - let message = programType.GetMethod("foo")(*Marker1*) - let x = "" - let _ = x.Contains("a")(*Marker2*) - let _ = x.CompareTo("a")(*Marker3*) - - open System.IO - - let GetFileSize filePath = File.GetAttributes(filePath)(*Marker4*)""", - marker = "(*Marker4*)", - list = ["value__"]) - - [] - member this.``Seq.NearTheEndOfFile``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - open Microsoft.FSharp.Math + [] + member this.``BadCompletionAfterQuicklyTyping.Bug72561.Noteworthy.NowWorks``() = + let code = [ "123 " ] + let (_, _, file) = this.CreateSingleFileProject(code) + + TakeCoffeeBreak(this.VS) + let gpatcc = GlobalParseAndTypeCheckCounter.StartNew(this.VS) + // In this case, we quickly type "." and then get dot-completions + // This simulates the case when the user quickly types "dot" after the file has been TCed before. + ReplaceFileInMemoryWithoutCoffeeBreak file ([ "[1]." ]) + MoveCursorToEndOfMarker(file, ".") + // Note: no TakeCoffeeBreak(this.VS) + let completions = AutoCompleteAtCursor file + AssertCompListIsEmpty(completions) // empty completion list means second-chance intellisense will kick in + // if we wait... + TakeCoffeeBreak(this.VS) + let completions = AutoCompleteAtCursor file + // ... we get the expected answer + AssertCompListContainsAll(completions, ["Length"]) + AssertCompListDoesNotContainAny(completions, ["AbstractClassAttribute"]) + gpatcc.AssertExactly(0,0) - let trianglenumbers = Seq.init_infinite (fun i -> let i = BigInt(i) in i * (i+1I) / 2I) + [] + member this.``BadCompletionAfterQuicklyTyping.Bug130733.NowWorks``() = + let code = [ "let someCall(x) = null" + "let xe = someCall(System.IO.StringReader() "] + let (_, _, file) = this.CreateSingleFileProject(code) + + TakeCoffeeBreak(this.VS) + let gpatcc = GlobalParseAndTypeCheckCounter.StartNew(this.VS) + // In this case, we quickly type "." and then get dot-completions + // This simulates the case when the user quickly types "dot" after the file has been TCed before. + ReplaceFileInMemoryWithoutCoffeeBreak file [ "let someCall(x) = null" + "let xe = someCall(System.IO.StringReader(). "] + MoveCursorToEndOfMarker(file, "().") + // Note: no TakeCoffeeBreak(this.VS) + let completions = AutoCompleteAtCursor file + AssertCompListContainsAll(completions, ["ReadBlock"]) // text to the left of the dot did not change, so we use stale (correct) result immediately + // if we wait... + TakeCoffeeBreak(this.VS) + let completions = AutoCompleteAtCursor file + // ... we get the expected answer + AssertCompListContainsAll(completions, ["ReadBlock"]) + gpatcc.AssertExactly(0,0) - (trianglenumbers |> Seq(*MarkerNearTheEnd*))""", - marker = "(*MarkerNearTheEnd*)", - list = ["cache";"find"]) - //Regression test of bug 3879: intellisense glitch for computation expression - [] - member this.``ComputationExpression.WithClosingBrace``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - // regression test for bug 3879: intellisense glitch for computation expression - // intellisense does not work in computation expression without the closing brace - type System.Net.WebRequest with - - member x.AsyncGetResponse() = Async.BuildPrimitive(x.BeginGetResponse, x.EndGetResponse) - member x.GetResponseAsync() = x.AsyncGetResponse() - - let http(url:string) = - async {let req = System.Net.WebRequest.Create("http://www.yahoo.com") - let! rsp = req(*Marker*)} """, - marker = "(*Marker*)", - list = ["AsyncGetResponse";"GetResponseAsync";"ToString"]) - - [] - member this.``ComputationExpression.WithoutClosingBrace``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - // regression test for bug 3879: intellisense glitch for computation expression - // intellisense does not work in computation expression without the closing brace - type System.Net.WebRequest with +//*********************************************Previous Completion test and helper***** + member private this.VerifyCompListDoesNotContainAnyAtStartOfMarker(fileContents : string, marker : string, list : string list) = + let (solution, project, file) = this.CreateSingleFileProject(fileContents) + MoveCursorToStartOfMarker(file, marker) + let completions = AutoCompleteAtCursor(file) + AssertCompListDoesNotContainAny(completions,list) - member x.AsyncGetResponse() = Async.BuildPrimitive(x.BeginGetResponse, x.EndGetResponse) - member x.GetResponseAsync() = x.AsyncGetResponse() + member private this.VerifyCtrlSpaceListDoesNotContainAnyAtStartOfMarker(fileContents : string, marker : string, list : string list) = + let (solution, project, file) = this.CreateSingleFileProject(fileContents) + MoveCursorToStartOfMarker(file, marker) + let completions = CtrlSpaceCompleteAtCursor file + AssertCompListDoesNotContainAny(completions,list) - let http(url:string) = - async { let req = System.Net.WebRequest.Create("http://www.yahoo.com") - let! rsp = req(*Marker*) """, - marker = "(*Marker*)", - list = ["AsyncGetResponse";"GetResponseAsync";"ToString"]) + member private this.VerifyCompListContainAllAtStartOfMarker(fileContents : string, marker : string, list : string list) = + let (solution, project, file) = this.CreateSingleFileProject(fileContents) + MoveCursorToStartOfMarker(file, marker) + let completions = AutoCompleteAtCursor(file) + AssertCompListContainsAll(completions, list) - //Regression Test of 4405:intellisense has wrong type for identifier, using most recently bound of same name rather than the one in scope? - [] - member this.``Regression4405.Identifier.ReBound``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - let f x = - let varA = "string" - let varA = if x then varA(*MarkerRebound*) else 2 - varA""", - marker = "(*MarkerRebound*)", - list = ["Chars";"StartsWith"]) - - //Regression test for FSharp1.0:4702 - [] - member this.``Regression4702.SystemWord``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = "System(*Marker*)", - marker = "(*Marker*)", - list = ["Console";"Byte";"ArgumentException"]) + member private this.VerifyCtrlSpaceListContainAllAtStartOfMarker(fileContents : string, marker : string, list : string list, ?coffeeBreak:bool, ?addtlRefAssy:string list) = + let coffeeBreak = defaultArg coffeeBreak false + let (solution, project, file) = this.CreateSingleFileProject(fileContents, ?references = addtlRefAssy) + MoveCursorToStartOfMarker(file, marker) + if coffeeBreak then TakeCoffeeBreak(this.VS) + let completions = CtrlSpaceCompleteAtCursor file + AssertCompListContainsAll(completions, list) - [] - member this.``TypeAbbreviation.Positive``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest + + member private this.VerifyAutoCompListIsEmptyAtEndOfMarker(fileContents : string, marker : string) = + let (solution, project, file) = this.CreateSingleFileProject(fileContents) + MoveCursorToEndOfMarker(file, marker) + let completions = AutoCompleteAtCursor(file) + AssertEqual(0,completions.Length) - Microsoft.FSharp.Core(*Marker1*)""", - marker = "(*Marker1*)", - list = ["int16";"int32";"int64"]) + member private this.VerifyCtrlSpaceCompListIsEmptyAtEndOfMarker(fileContents : string, marker : string) = + let (solution, project, file) = this.CreateSingleFileProject(fileContents) + MoveCursorToEndOfMarker(file, marker) + let completions = CtrlSpaceCompleteAtCursor(file) + AssertEqual(0,completions.Length) + + + + // Regression for bug 2116 -- Consider making selected item in completion list case-insensitive + - [] - member this.``TypeAbbreviation.Negative``() = - this.VerifyDotCompListDoesNotContainAnyAtStartOfMarker( - fileContents = """ - module BasicTest - Microsoft.FSharp.Core(*Marker1*)""", - marker = "(*Marker1*)", - list = ["Int16";"Int32";"Int64"]) - //Regression test of bug 3754:tupe forwarder bug? intellisense bug? - [] - member this.``Regression3754.TypeOfListForward.Positive``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - // regression test for bug 3754 - // tupe forwarder bug? intellisense bug? - - open System.IO - open System.Xml - open System.Xml.Linq - let xmlStr = @" Blah Blah " - let xns = XNamespace.op_Implicit "" - let a = xns + "a" - let reader = new StringReader(xmlStr) - let xdoc = XDocument.Load(reader) - let aElements = [for x in xdoc.Root.Elements() do - if x.Name = a then - yield x] - let href = xns + "href" - aElements |> List(*Marker*)""", - marker = "(*Marker*)", - list = ["append";"choose";"isEmpty"]) - [] - member this.``Regression3754.TypeOfListForward.Negative``() = - this.VerifyDotCompListDoesNotContainAnyAtStartOfMarker( - fileContents = """ - module BasicTest - // regression test for bug 3754 - // tupe forwarder bug? intellisense bug? - - open System.IO - open System.Xml - open System.Xml.Linq - let xmlStr = @" Blah Blah " - let xns = XNamespace.op_Implicit "" - let a = xns + "a" - let reader = new StringReader(xmlStr) - let xdoc = XDocument.Load(reader) - let aElements = [for x in xdoc.Root.Elements() do - if x.Name = a then - yield x] - let href = xns + "href" - aElements |> List(*Marker*)""", - marker = "Marker", - list = [""]) +(*------------------------------------------IDE Query automation start -------------------------------------------------*) + member private this.AssertAutoCompletionInQuery(fileContent : string list, marker:string,contained:string list) = + let file = createFile fileContent SourceFileKind.FS ["System.Xml.Linq"] None + + let gpatcc = GlobalParseAndTypeCheckCounter.StartNew(this.VS) + MoveCursorToEndOfMarker(file, marker) + let completions = CompleteAtCursorForReason(file,BackgroundRequestReason.CompleteWord) + AssertCompListContainsAll(completions, contained) + gpatcc.AssertExactly(0,0) - [] - member this.``NonApplicableExtensionMembersDoNotAppear.Bug40379``() = - let code = - [ "open System.Xml.Linq" - "type MyType() =" - " static member Foo(actual:XElement) = actual.Name " - " member public this.Bar1() =" - " let actual1 : int[] = failwith \"\"" - " actual1.(*Marker*)" - " member public this.Bar2() =" - " let actual2 : XNode[] = failwith \"\"" - " actual2.(*Marker*)" - " member public this.Bar3() =" - " let actual3 : XElement[] = failwith \"\"" - " actual3.(*Marker*)" - ] - let (_, _, file) = this.CreateSingleFileProject(code, references = ["System.Xml"; "System.Xml.Linq"]) - MoveCursorToEndOfMarker(file, "actual1.") - let completions = AutoCompleteAtCursor file - AssertCompListDoesNotContainAny(completions, [ "Ancestors"; "AncestorsAndSelf"]) - MoveCursorToEndOfMarker(file, "actual2.") - let completions = AutoCompleteAtCursor file - AssertCompListContains(completions, "Ancestors") - AssertCompListDoesNotContain(completions, "AncestorsAndSelf") - MoveCursorToEndOfMarker(file, "actual3.") - let completions = AutoCompleteAtCursor file - AssertCompListContainsAll(completions, ["Ancestors"; "AncestorsAndSelf"]) - [] - member this.``Visibility.InternalMethods.DefInSameAssembly``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module CodeAccessibility - open System - module Module1 = - - type Type1()= - [] - val mutable internal fieldInternal:int - - member internal x.MethodInternal (x:int) = x+2 - - let type1 = new Type1() - type1(*MarkerSameAssemb*)""", - marker = "(*MarkerSameAssemb*)", - list = ["fieldInternal";"MethodInternal"]) + - [] - member this.``QueryExpression.DotCompletionSmokeTest1``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module Basic - let x2 = query { for x in ["1";"2";"3"] do - select x(*Marker*)""", - marker = "(*Marker*)", - list = ["Chars";"Length"], - addtlRefAssy=standard40AssemblyRefs) - [] - member this.``QueryExpression.DotCompletionSmokeTest2``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - let x = query { for x in ["1";"2";"3"] do select x(*Marker*)""" , - marker = "(*Marker*)", - list = ["Chars"; "Length"], - addtlRefAssy=standard40AssemblyRefs ) - [] - member this.``QueryExpression.DotCompletionSmokeTest0``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - let x = seq { for x in ["1";"2";"3"] do yield x(*Marker*) }""" , - marker = "(*Marker*)", - list = ["Chars";"Length"], - addtlRefAssy=standard40AssemblyRefs ) - [] - member this.``QueryExpression.DotCompletionSmokeTest3``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module BasicTest - let x = query { for x in ["1";"2";"3"] do select x(*Marker*) }""" , - marker = "(*Marker*)", - list = ["Chars";"Length"], - addtlRefAssy=standard40AssemblyRefs ) - [] - member this.``QueryExpression.DotCompletionSystematic1``() = - for customOperation in ["select";"sortBy";"where"] do - let fileContentsList = - [""" - module Simple - let x2 = query { for x in ["1";"2";"3"] do - """+customOperation+""" x(*Marker*)""" - """ - module Simple - let x2 = query { for x in ["1";"2";"3"] do - """+customOperation+""" (x(*Marker*)""" - """ - module Simple - let x2 = query { for x in ["1";"2";"3"] do - """+customOperation+""" (x(*Marker*) }""" - """ - module Simple - let x2 = query { for x in ["1";"2";"3"] do - """+customOperation+""" (x(*Marker*) - select x""" - """ - module Simple - let x2 = query { for x in ["1";"2";"3"] do - """+customOperation+""" x(*Marker*) - select x }""" - """ - module Simple - let x2 = query { for x in ["1";"2";"3"] do - """+customOperation+""" (x(*Marker*))""" - """ - module Simple - let x2 = query { for x in ["1";"2";"3"] do - """+customOperation+""" (x.Length + x(*Marker*)""" - """ - module Simple - let x2 = query { for x in [1;2;3] do - for y in ["1";"2";"3"] do - """+customOperation+""" (x + y(*Marker*)""" - """ - module Simple - let x2 = query { for x in [1;2;3] do - for y in ["1";"2";"3"] do - """+customOperation+""" (x + y(*Marker*))""" - """ - module Simple - let x2 = query { for x in [1;2;3] do - for y in ["1";"2";"3"] do - where (x > y.Length) - """+customOperation+""" (x + y(*Marker*)""" ] - for fileContents in fileContentsList do - printfn "customOperation = %s, fileContents = <<<%s>>>" customOperation fileContents - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = fileContents, - marker = "(*Marker*)", - list = ["Chars";"Length"], - addtlRefAssy=standard40AssemblyRefs) - [] - member public this.``QueryExpression.InsideJoin.Bug204147``() = - this.VerifyDotCompListContainAllAtStartOfMarker( - fileContents = """ - module Simple - type T() = - member x.GetCollection() = [1;2;3;4] - let q = - query { - for e in [1..10] do - join b in T()(*Marker*) - select b - }""", - marker = "(*Marker*)", - list = ["GetCollection"], - addtlRefAssy=queryAssemblyRefs ) -(*------------------------------------------IDE Query automation start -------------------------------------------------*) member private this.AssertDotCompletionListInQuery(fileContents: string, marker : string, list : string list) = let datacode = """ @@ -7665,129 +1053,14 @@ let rec f l = let completions = DotCompletionAtStartOfMarker file2 marker AssertCompListContainsAll(completions, list) - [] - // Intellisense still appears on arguments when the operator is used in error - member public this.``Query.HasErrors.Bug196230``() = - this.AssertDotCompletionListInQuery( - fileContents = """ - open DataSource - // defined in another file; see AssertDotCompletionListInQuery - let products = Products.getProductList() - let sortedProducts = - query { - for p in products do - let x = p.ProductID + "a" - sortBy p(*Marker*) - select p - }""" , - marker = "(*Marker*)", - list = ["ProductID";"ProductName"] ) // Intellisense still appears on arguments when the operator is used in error - [] - member public this.``Query.HasErrors2``() = - this.AssertDotCompletionListInQuery( - fileContents = """ - open DataSource - let products = Products.getProductList() - let sortedProducts = - query { - for p in products do - orderBy (p(*Marker*)) - }""" , - marker = "(*Marker*)", - list = ["ProductID";"ProductName"] ) - - [] - // Shadowed variables have correct Intellisense - member public this.``Query.ShadowedVariables``() = - this.AssertDotCompletionListInQuery( - fileContents = """ - open DataSource - let products = Products.getProductList() - let p = 12 - let sortedProducts = - query { - for p in products do - select p(*Marker*) - }""" , - marker = "(*Marker*)", - list = ["Category";"ProductName"] ) - - [] - // Intellisense works correctly in a nested query - member public this.``Query.InNestedQuery``() = - let fileContents = """ - let tuples = [ (1, 8, 9); (56, 45, 3)] - let numbers = [ 1;2; 8; 9; 15; 23; 3; 42; 4;0; 55;] - - let foo = - query { - for n in numbers do - let maxNumber = query {for x in tuples do maxBy x(*Marker1*)} - select (n, query {for y in numbers do minBy y(*Marker2*)}) } - """ - this.VerifyDotCompListContainAllAtStartOfMarker(fileContents, "(*Marker1*)", - ["Equals";"GetType"], queryAssemblyRefs ) - this.VerifyDotCompListContainAllAtStartOfMarker(fileContents, "(*Marker2*)", - ["Equals";"CompareTo"], queryAssemblyRefs ) - [] - // Intellisense works correctly in a nested expression within a lamda - member public this.``Query.NestedExpressionWithinLamda``() = - let fileContents = """ - let numbers = [ 1;2; 8; 9; 15; 23; 3; 42; 4;0; 55;] - let f (x : string) = () - let foo = - query { - for n in numbers do - let x = 42 |> ignore; numbers |> List.iter( fun n -> f ("1" + "1")(*Marker*)) - skipWhile (n < 30) - } - """ - this.VerifyDotCompListContainAllAtStartOfMarker(fileContents, "(*Marker*)", - ["Chars";"Length"], queryAssemblyRefs ) - - [] - member this.``Verify no completion on dot after module definition``() = - this.VerifyDotCompListIsEmptyAtStartOfMarker( - fileContents = """ - module BasicTest(*Marker*) - let foo x = x - let bar = 1""", - marker = "(*Marker*)") - [] - member this.``Verify no completion after module definition``() = - this.VerifyCtrlSpaceCompListIsEmptyAtEndOfMarker( - fileContents = """ - module BasicTest - - let foo x = x - let bar = 1""", - marker = "module BasicTest ") - [] - member this.``Verify no completion in hash directives``() = - this.VerifyCtrlSpaceCompListIsEmptyAtEndOfMarker( - fileContents = """ - #r (*Marker*) - let foo x = x - let bar = 1""", - marker = "(*Marker*)") - [] - member public this.``ExpressionDotting.Regression.Bug3709``() = - this.VerifyCtrlSpaceListContainAllAtStartOfMarker( - fileContents = """ - let foo = "" - let foo = foo.E(*marker*)n "a" """, - marker = "(*marker*)", - list = ["EndsWith"]) - -// Context project system type UsingProjectSystem() = inherit UsingMSBuild(VsOpts = LanguageServiceExtension.ProjectSystemTestFlavour) diff --git a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.ErrorList.fs b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.ErrorList.fs index ea7f0fa61e8..53519f50758 100644 --- a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.ErrorList.fs +++ b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.ErrorList.fs @@ -117,229 +117,6 @@ type UsingMSBuild() as this = else failwithf "The error list number is not the expected %d" num - [] - member public this.``OverloadsAndExtensionMethodsForGenericTypes``() = - let fileContent = - """ -open System.Linq - -type T = - abstract Count : int -> bool - default this.Count(_ : int) = true - - interface System.Collections.Generic.IEnumerable with - member this.GetEnumerator() : System.Collections.Generic.IEnumerator = failwith "not implemented" - interface System.Collections.IEnumerable with - member this.GetEnumerator() : System.Collections.IEnumerator = failwith "not implemented" - -let g (t : T) = t.Count() - """ - this.VerifyNoErrorListAtOpenProject(fileContent) - - - [] - member public this.``ErrorsInScriptFile``() = - let (solution, project, file) = this.CreateSingleFileProject("", fileKind = SourceFileKind.FSX) - - let checkErrors expected = - let l = List.length (GetErrors project) - Assert.Equal(expected, l) - - TakeCoffeeBreak(this.VS) - checkErrors 0 - - ReplaceFileInMemory file <| - [ - "#r \"System\"" - "#r \"System2\"" - ] - TakeCoffeeBreak(this.VS) - checkErrors 1 - - ReplaceFileInMemory file <| - [ - "#r \"System\"" - ] - TakeCoffeeBreak(this.VS) - checkErrors 0 - - [] - member public this.``LineDirective``() = - use _guard = this.UsingNewVS() - let fileContents = """ - # 100 "foo.fs" - let x = y """ - let solution = this.CreateSolution() - let project = CreateProject(solution, "testproject") - let _ = AddFileFromTextBlob(project, "File1.fs", "namespace LineDirectives") - let _ = AddFileFromTextBlob(project,"File2.fs", fileContents) - - let file = OpenFile(project, "File1.fs") - let _ = OpenFile(project,"File2.fs") - Assert.False(Build(project).BuildSucceeded) - - this.VerifyCountAtSpecifiedFile(project,1) - VerifyErrorListContainedExpectedStr("The value or constructor 'y' is not defined",project) - - [] - member public this.``InvalidConstructorOverload``() = - let content = """ - type X private() = - new(_ : int) = X() - new(_ : bool) = X() - new(_ : float, _ : int) = X() - X(1.0) - """ - - let expectedMessages = [ "No overloads match for method 'X'.\u001d\u001dKnown type of argument: float\u001d\u001dAvailable overloads:\u001d - new: bool -> X // Argument at index 1 doesn't match\u001d - new: int -> X // Argument at index 1 doesn't match" ] - - CheckErrorList content (assertExpectedErrorMessages expectedMessages) - - - [] - member public this.``Query.InvalidJoinRelation.GroupJoin``() = - let content = """ -let x = query { - for x in [1] do - groupJoin y in [2] on ( x < y) into g - select x } - """ - CheckErrorList content <| - fun errors -> - match errors with - | [err] -> - Assert.Equal("Invalid join relation in 'groupJoin'. Expected 'expr expr', where is =, =?, ?= or ?=?.", err.Message) - | errs -> - Assert.Fail("Unexpected content of error list") - - [] - member public this.``Query.NonOpenedNullableModule.Join``() = - let content = """ -let t = - query { - for x in [1] do - join y in [""] on (x ?=? y) - select 1 } - """ - CheckErrorList content <| - fun errors -> - match errors with - | [err] -> - Assert.Equal("The operator '?=?' cannot be resolved. Consider opening the module 'Microsoft.FSharp.Linq.NullableOperators'.", err.Message) - | errs -> - Assert.Fail("Unexpected content of error list") - - [] - member public this.``Query.NonOpenedNullableModule.GroupJoin``() = - let content = """ -let t = - query { - for x in [1] do - groupJoin y in [""] on (x ?=? y) into g - select 1 } - """ - CheckErrorList content <| - fun errors -> - match errors with - | [err] -> - Assert.Equal("The operator '?=?' cannot be resolved. Consider opening the module 'Microsoft.FSharp.Linq.NullableOperators'.", err.Message) - | errs -> - Assert.Fail("Unexpected content of error list") - - - [] - member public this.``Query.InvalidJoinRelation.Join``() = - let content = """ -let x = - query { - for x in [1] do - join y in [""] on (x > y) - select 1 - } - """ - CheckErrorList content <| - fun errors -> - match errors with - | [err] -> - Assert.Equal("Invalid join relation in 'join'. Expected 'expr expr', where is =, =?, ?= or ?=?.", err.Message) - | errs -> - Assert.Fail("Unexpected content of error list") - - [] - member public this.``InvalidMethodOverload``() = - let content = """ - System.Console.WriteLine(null) - """ - let expectedMessages = [ "A unique overload for method 'WriteLine' could not be determined based on type information prior to this program point. A type annotation may be needed.\u001d\u001dKnown type of argument: 'a0 when 'a0: null\u001d\u001dCandidates:\u001d - System.Console.WriteLine(buffer: char array) : unit\u001d - System.Console.WriteLine(format: string, [] arg: obj array) : unit\u001d - System.Console.WriteLine(value: obj) : unit\u001d - System.Console.WriteLine(value: string) : unit" ] - CheckErrorList content (assertExpectedErrorMessages expectedMessages) - - [] - member public this.``InvalidMethodOverload2``() = - let content = """ -type A<'T>() = - member this.Do(a : int, b : 'T) = () - member this.Do(a : int, b : int) = () -type B() = - inherit A() - -let b = B() -b.Do(1, 1) - """ - let expectedMessages = [ "A unique overload for method 'Do' could not be determined based on type information prior to this program point. A type annotation may be needed.\u001d\u001dKnown types of arguments: int * int\u001d\u001dCandidates:\u001d - member A.Do: a: int * b: 'T -> unit\u001d - member A.Do: a: int * b: int -> unit" ] - CheckErrorList content (assertExpectedErrorMessages expectedMessages) - - [] - member public this.``NoErrorInErrList``() = - use _guard = this.UsingNewVS() - let fileContents1 = """ - module NoErrors - - open System.Collections.Generic - // but do not use it - """ - let fileContents2 = """ - // Regression test for FSHARP1.0:3824 - Problems with generic type parameters in type extensions (was: Confusing error/warning on type extension: code is less generic) - module NoErrors2 - - module DictionaryExtension = - - type System.Collections.Generic.IDictionary<'k,'v> with - member this.TryLookup(key : 'k) = - let mutable value = Unchecked.defaultof<'v> - if this.TryGetValue(key, &value) then - Some value - else - None - - open DictionaryExtension""" - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let _ = AddFileFromTextBlob(project,"File1.fs", fileContents1) - let _ = OpenFile(project,"File1.fs") - let _ = AddFileFromTextBlob(project,"File2.fs", fileContents2) - let _ = OpenFile(project,"File2.fs") - Build(project) |> ignore - TakeCoffeeBreak(this.VS) - this.VerifyCountAtSpecifiedFile(project,0) - - [] - member public this.``NoLevel4Warning``() = - use _guard = this.UsingNewVS() - let fileContents = """ - namespace testerrorlist - module nolevel4warnings = - let x = System.DateTime.Now - System.DateTime.Now - x.Add(x) |> ignore """ - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let _ = AddFileFromTextBlob(project,"Module1.fs",fileContents) - - let _ = AddFileFromTextBlob(project,"Script.fsx","") - let _ = OpenFile(project,"Script.fsx") - Build(project) |> ignore - - this.VerifyCountAtSpecifiedFile(project,0) - [] //This is an verify action test & example member public this.``TestErrorMessage``() = @@ -347,534 +124,6 @@ b.Do(1, 1) let expectedStr = "The value, namespace, type or module 'Console' is not defined" this.VerifyErrorListContainedExpectedString(fileContent,expectedStr) - [] - member public this.``TestWrongKeywordInInterfaceImplementation``() = - let fileContent = - """ -type staticInInterface = - class - interface System.IDisposable with - static member Foo() = () - member x.Dispose() = () - end - end""" - - CheckErrorList fileContent (function - | err1 :: _ -> - Assert.True(err1.Message.Contains("No static abstract member was found that corresponds to this override")) - | x -> - Assert.Fail(sprintf "Unexpected errors: %A" x)) - - [] - member public this.``TypeProvider.MultipleErrors`` () = - let tpRef = PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll") - let checkList n = - printfn "===TypeProvider.MultipleErrors: %d===" n - let content = sprintf "type Err = TPErrors.TP<%d>" n - let (solution, project, file) = this.CreateSingleFileProject(content, references = [tpRef]) - TakeCoffeeBreak(this.VS) - let errorList = GetErrors(project) - - for err in errorList do - printfn "Severity: %A, Message: %s" err.Severity err.Message - - Assert.True(List.length errorList = n, "Unexpected size of error list") - let uniqueErrors = - errorList - |> Seq.map (fun m -> m.Message, m.Severity) - |> set - Assert.True(uniqueErrors.Count = n, "List should not contain duplicate errors") - for x = 0 to (n - 1) do - let expectedName = sprintf "The type provider 'DummyProviderForLanguageServiceTesting.TypeProviderThatThrowsErrors' reported an error: Error %d" x - Assert.True(Set.contains (expectedName, Microsoft.VisualStudio.FSharp.LanguageService.Severity.Error) uniqueErrors) - - for i = 1 to 10 do - checkList i - - [] - member public this.``Records.ErrorList.IncorrectBindings1``() = - for code in [ "{_}"; "{_ = }"] do - printfn "checking %s" code - CheckErrorList code <| - fun errs -> - printfn "%A" errs - Assert.True((List.length errs) = 2) - assertContains errs "Field bindings must have the form 'id = expr;'" - assertContains errs "'_' cannot be used as field name" - - [] - member public this.``Records.ErrorList.IncorrectBindings2``() = - CheckErrorList "{_ = 1}" <| - function - | [err] -> Assert.Equal("'_' cannot be used as field name", err.Message) - | x -> printfn "%A" x; Assert.Fail("unexpected content of error list") - - [] - member public this.``Records.ErrorList.IncorrectBindings3``() = - CheckErrorList "{a = 1; _; _ = 1}" <| - fun errs -> - Assert.True((List.length errs) = 3) - let groupedErrs = errs |> Seq.groupBy (fun e -> e.Message) |> Seq.toList - Assert.True((List.length groupedErrs) = 2) - for (msg, e) in groupedErrs do - if msg = "'_' cannot be used as field name" then Assert.Equal(2, Seq.length e) - elif msg = "Field bindings must have the form 'id = expr;'" then Assert.Equal(1, Seq.length e) - else Assert.Fail (sprintf "Unexpected message %s" msg) - - - [] - //This test case Verify the Error List shows the correct error message when the static parameter type is invalid - //Intent: We want to make sure that both errors coming from the TP and the compilation of things specific to type provider are properly flagged in the error list. - member public this.``TypeProvider.StaticParameters.IncorrectType `` () = - // dummy Type Provider exposes a parametric type (N1.T) that takes 2 static params (string * int) - // but here as you can see it's give (int * int) - let fileContent = """ type foo = N1.T< const 42,2>""" - let expectedStr = "This expression was expected to have type\u001d 'string' \u001dbut here has type\u001d 'int'" - this.VerifyErrorListContainedExpectedString(fileContent,expectedStr, - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - //This test case Verify the Error List shows the correct error message when applying invalid static parameter to the provided type - member public this.``TypeProvider.StaticParameters.Incorrect `` () = - - // dummy Type Provider exposes a parametric type (N1.T) that takes 2 static params (string * int) - let fileContent = """ type foo = N1.T< const " ",2>""" - let expectedStr = "An error occurred applying the static arguments to a provided type" - - this.VerifyErrorListContainedExpectedString(fileContent,expectedStr, - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - //This test case Verify that Error List shows the correct error message when Type Provider that takes two static parameter is given only one static parameter. - member public this.``TypeProvider.StaticParameters.IncorrectNumberOfParameter `` () = - - // dummy Type Provider exposes a parametric type (N1.T) that takes 2 static params (string * int) - // but here as you can see it's give (string) - let fileContent = """type foo = N1.T< const "Hello World">""" - let expectedStr = "The static parameter 'ParamIgnored' of the provided type or method 'T' requires a value. Static parameters to type providers may be optionally specified using named arguments, e.g. 'T'." - - this.VerifyErrorListContainedExpectedString(fileContent,expectedStr, - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - [] - member public this.``TypeProvider.ProhibitedMethods`` () = - let cases = - [ - "let x = BadMethods.Arr.GetFirstElement([||])", "GetFirstElement" - "let y = BadMethods.Arr.SetFirstElement([||], 5)", "SetFirstElement" - "let z = BadMethods.Arr.AddressOfFirstElement([||])", "AddressOfFirstElement" - ] - for (code, str) in cases do - this.VerifyErrorListContainedExpectedString - ( - code, - sprintf "The type provider 'DummyProviderForLanguageServiceTesting.TypeProviderThatEmitsBadMethods' reported an error in the context of provided type 'BadMethods.Arr', member '%s'. The error: The operation 'GetMethodImpl' on item 'Int32[]' should not be called on provided type, member or parameter of type 'ProviderImplementation.ProvidedTypes.TypeSymbol'." str, - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")] - ) - - [] - //This test case verify that the Error list count is one in the Error list item when given invalid static parameter that raises an error. - member public this.``TypeProvider.StaticParameters.ErrorListItem `` () = - - this.VerifyErrorListCountAtOpenProject( - fileContents = """ - type foo = N1.T< const "Hello World",2>""", - num = 1) - - [] - //This test case Verify that there is No Error list count in the Error list item when the file content is correct. - member public this.``TypeProvider.StaticParameters.NoErrorListCount `` () = - - this.VerifyNoErrorListAtOpenProject( - fileContents = """ - type foo = N1.T< const "Hello World",2>""", - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - - [] - member public this.``NoError.FlagsAndSettings.TargetOptionsRespected``() = - let fileContent = """ - [] - let fn x = 0 - let y = fn 1""" - // Turn off the "Obsolete" warning. - let (solution, project, file) = this.CreateSingleFileProject(fileContent, disabledWarnings = ["44"]) - - TakeCoffeeBreak(this.VS) // Wait for the background compiler to catch up. - let errorList = GetErrors(project) - Assert.True(errorList.IsEmpty) - - [] - member public this.``UnicodeCharacters``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"新規baApplication5") - let _ = AddFileFromTextBlob(project,"新規baProgram.fsi","") - let _ = AddFileFromTextBlob(project,"新規bcrogram.fs","") - - let file = OpenFile(project,"新規baProgram.fsi") - let file = OpenFile(project,"新規bcrogram.fs") - - Assert.False(Build(project).BuildSucceeded) - Assert.True(GetErrors(project) - |> List.exists(fun error -> (error.ToString().Contains("新規baProgram")))) - - // In this bug, particular warns were still present after nowarn - [] - member public this.``NoWarn.Bug5424``() = - let fileContent = """ - #nowarn "67" // this type test or downcast will always hold - #nowarn "66" // this upcast is unnecessary - the types are identical - namespace Namespace1 - module Test = - open System - let a = ((5 :> obj) :?> Object) - let b = a :> obj""" - this.VerifyNoErrorListAtOpenProject(fileContent) - - /// FEATURE: Errors in flags are sent in Error list. - [] - member public this.``FlagsAndSettings.ErrorsInFlagsDisplayed``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - SetVersionFile(project,"nonexistent") - let file = AddFileFromText(project,"File1.fs",[]) - let file = OpenFile(project,"File1.fs") - TakeCoffeeBreak(this.VS) // Wait for the background compiler to catch up. - VerifyErrorListContainedExpectedStr("nonexistent",project) - - [] - member public this.``BackgroundComplier``() = - this.VerifyErrorListCountAtOpenProject( - fileContents = """ - - - module Test - - module M = - let func (args : string[]) = - if(args.Length=1 && args.[0]="Hello") then 0 else 1 - - [] - let main2 args = - let res = func(args) - exit(res) - - let f x = - let p = x - p + 1 - - let g x = - let p = x - p + 1 - """, - num = 2) - - [] - member public this.``CompilerErrorsInErrList1``() = - this.VerifyErrorListCountAtOpenProject( - fileContents = """ - namespace Errorlist - module CompilerError = - - let a = NoVal""", - num = 1 ) - - // [] disabled for F#8, legacy service, covered in FCS tests instead - member public this.``CompilerErrorsInErrList4``() = - this.VerifyNoErrorListAtOpenProject( - fileContents = """ - #nowarn "47" - - type Fruit (shelfLife : int) as x = - - let mutable m_age = (fun () -> x) - - - #nowarn "25" // FS0025: Incomplete pattern matches on this expression. For example, the value 'C' - - type DU = A | B | C - let f x = function A -> true | B -> false - - - - let _fsyacc_gotos = [| 0us; 1us; 2us|] """ ) - - [] - member public this.``CompilerErrorsInErrList5``() = - this.VerifyErrorListCountAtOpenProject( - fileContents = """ - #r "D:\x\Absent.dll" - - let x = 0 """, - num = 1) - - [] - member public this.``CompilerErrorsInErrList6``() = - this.VerifyErrorListCountAtOpenProject( - fileContents = """ - type EnumOfBigInt = - | A = 0I - | B = 0I - - type EnumOfNatNum = - | A = 0N - | B = 0N """, - num = 2) - - [] - member public this.``CompilerErrorsInErrList7``() = - this.VerifyErrorListCountAtOpenProject( - fileContents = """ - // FSB 1124, Implement constant literals - type EnumType = - | A = 1 - | B = 2 - - type CustomAttrib(a:int, b:string, c:float, d:EnumType) = - inherit System.Attribute() - - //[] - let a = 42 - //[] - let b = "str" - //[] - let c = 3.141 - //[] - let d = EnumType.A - - [] - type SomeClass() = - override this.ToString() = "SomeClass" - - [] - let main0 args = () - - let foo = 1 """, - num = 5) - - [] - member public this.``CompilerErrorsInErrList8``() = - this.VerifyErrorListCountAtOpenProject( - fileContents = """ - type EnumInt8s = | A1 = - 10y """ , - num = 1 ) - - [] - member public this.``CompilerErrorsInErrList9``() = - use _guard = this.UsingNewVS() - let fileContents1 = """ - namespace NS - [] - type Lib() = - class - abstract M : int -> int - end """ - let fileContents2 = """ - namespace NS - module M = - type Lib with - override x.M i = i - """ - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let _ = AddFileFromTextBlob(project,"File1.fs",fileContents1) - let file1 = OpenFile(project,"File1.fs") - let _ = AddFileFromTextBlob(project,"File2.fs",fileContents2) - let file2 = OpenFile(project,"File2.fs") - //this.VerifyErrorListNumberAtOpenProject - this.VerifyCountAtSpecifiedFile(project,1) - TakeCoffeeBreak(this.VS) - Build(project) |> ignore - this.VerifyCountAtSpecifiedFile(project,1) - - [] - member public this.``CompilerErrorsInErrList10``() = - let fileContents = """ - namespace Errorlist - module CompilerError = - - printfn "%A" System.Windows.Forms.Application.UserAppDataPath """ - let (_, project, _) = this.CreateSingleFileProject(fileContents, references = ["PresentationCore.dll"; "PresentationFramework.dll"]) - Build(project) |> ignore - - this.VerifyCountAtSpecifiedFile(project,1) - - [] - member public this.``DoubleClickErrorListItem``() = - this.VerifyErrorListCountAtOpenProject( - fileContents = """ - let x = x """, - num = 1) - [] - member public this.``FixingCodeAfterBuildRemovesErrors01``() = - this.VerifyErrorListCountAtOpenProject( - fileContents = """ - let x = 4 + "x" """, - num = 2) - - [] - member public this.``FixingCodeAfterBuildRemovesErrors02``() = - this.VerifyNoErrorListAtOpenProject( - fileContents = "let x = 4" ) - - [] - member public this.``IncompleteExpression``() = - this.VerifyErrorListCountAtOpenProject( - fileContents = """ - // Regression test for FSHARP1.0:1397 - Warning required on expr of function type who result is immediately thrown away - module Test - - printfn "%A" - - List.map (fun x -> x + 1) """ , - num = 2) - - [] - member public this.``IntellisenseRequest``() = - this.VerifyErrorListCountAtOpenProject( - fileContents = """ - type Foo() = - member a.B(*Marker*) : int = "1" """, - num = 1) - - [] - member public this.``TypeChecking1``() = - this.VerifyErrorListCountAtOpenProject( - fileContents = """ - open System - - module Foo = - type Thread(thread) = - let mutable next : Thread option = thread - member t.Next with get() = next and set(thread) = next - thread - - module Bar = - let x = new Foo.Thread(None) - - x.Next <- Some x """, - num = 1) - - [] - member public this.``TypeChecking2``() = - this.VerifyErrorListContainedExpectedString( - fileContents = """ - open System - - module Foo = - type Thread(thread) = - let mutable next : Thread option = thread - member t.Next with get() = next and set(thread) = next - thread - - module Bar = - let x = new Foo.Thread(None) - - x.Next <- Some x """, - expectedStr = "Foo.Thread option") - - [] - member public this.``TypeChecking3``() = - this.VerifyErrorListCountAtOpenProject( - fileContents = """ - open System - - module Foo = - type Thread(thread) = - let mutable next : Thread option = thread - member t.Next with get() = next and set(thread) = next - thread - - module Bar = - let x = new Foo.Thread(None) - x.Next <- Some 1 """, - num = 1) - - [] - member public this.``TypeChecking4``() = - this.VerifyErrorListContainedExpectedString( - fileContents = """ - open System - - module Foo = - type Thread(thread) = - let mutable next : Thread option = thread - member t.Next with get() = next and set(thread) = next - thread - - module Bar = - let x = new Foo.Thread(None) - x.Next <- Some 1 """, - expectedStr = "operator '-'" ) - -(* TODO why does this portion not work? specifically, last assert fails - printfn "changing file..." - ReplaceFileInMemory file1 [ - "let xx = \"foo\"" // now x is string - "printfn \"hi\""] - - // assert p1 xx is string - MoveCursorToEndOfMarker(file1,"let x") - TakeCoffeeBreak(this.VS) - let tooltip = GetQuickInfoAtCursor file1 - AssertContains(tooltip,"string") - - // assert p2 yy is int - MoveCursorToEndOfMarker(file2,"let y") - let tooltip = GetQuickInfoAtCursor file2 - AssertContains(tooltip,"int") - - AssertNoErrorsOrWarnings(project1) - AssertNoErrorsOrWarnings(project2) - - printfn "rebuilding dependent project..." - // (re)build p1 (with xx now string) - Build(project1) |> ignore - TakeCoffeeBreak(this.VS) - - AssertNoErrorsOrWarnings(project1) - AssertNoErrorsOrWarnings(project2) - - // assert p2 yy is now string - MoveCursorToEndOfMarker(file2,"let y") - let tooltip = GetQuickInfoAtCursor file2 - AssertContains(tooltip,"string") -*) - - [] - member public this.``Warning.ConsistentWithLanguageService``() = - let fileContent = """ - open System - mixin mixin mixin mixin mixin mixin mixin mixin mixin mixin - mixin mixin mixin mixin mixin mixin mixin mixin mixin mixin""" - let (_, project, file) = this.CreateSingleFileProject(fileContent, fileKind = SourceFileKind.FSX) - TakeCoffeeBreak(this.VS) // Wait for the background compiler to catch up. - let warnList = GetWarnings(project) - Assert.Equal(20,warnList.Length) - - [] - member public this.``Warning.ConsistentWithLanguageService.Comment``() = - let fileContent = """ - open System - //mixin mixin mixin mixin mixin mixin mixin mixin mixin mixin - //mixin mixin mixin mixin mixin mixin mixin mixin mixin mixin""" - let (_, project, file) = this.CreateSingleFileProject(fileContent, fileKind = SourceFileKind.FSX) - TakeCoffeeBreak(this.VS) // Wait for the background compiler to catch up. - let warnList = GetWarnings(project) - Assert.Equal(0,warnList.Length) - - [] - member public this.``Errorlist.WorkwithoutNowarning``() = - let fileContent = """ - type Fruit (shelfLife : int) as x = - let mutable m_age = (fun () -> x) - #nowarn "47" - """ - let (_, project, file) = this.CreateSingleFileProject(fileContent) - - Assert.True(Build(project).BuildSucceeded) - TakeCoffeeBreak(this.VS) - let warnList = GetErrors(project) - Assert.Equal(1,warnList.Length) - -// Context project system type UsingProjectSystem() = inherit UsingMSBuild(VsOpts = LanguageServiceExtension.ProjectSystemTestFlavour) diff --git a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.ErrorRecovery.fs b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.ErrorRecovery.fs index e38c503c17d..7872714b264 100644 --- a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.ErrorRecovery.fs +++ b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.ErrorRecovery.fs @@ -28,17 +28,6 @@ type UsingMSBuild() = |> Seq.exists (fun errorMessage -> errorMessage.Contains(expectedStr))) - // Not a recovery case, but make sure we get a squiggle at the unfinished Main() - [] - member public this.``ErrorRecovery.Bug4538_3``() = - let fileContent = """ - type MyType() = - override x.ToString() = "" - let Main() = - let x = MyType()""" - let expectedStr = "The block following this 'let' is unfinished. Every code block is an expression and must have a result. 'let' cannot be the final code element in a block. Consider giving this block an explicit result." - this.VerifyErrorListContainedExpectedString(fileContent,expectedStr) - // Not a recovery case, but make sure we get a squiggle at the unfinished Main() [] member public this.``ErrorRecovery.Bug4538_4``() = @@ -50,208 +39,7 @@ type UsingMSBuild() = let expectedStr = "The block following this 'use' is unfinished. Every code block is an expression and must have a result. 'use' cannot be the final code element in a block. Consider giving this block an explicit result." this.VerifyErrorListContainedExpectedString(fileContent,expectedStr) - [] - member public this.``ErrorRecovery.Bug4881_1``() = - let code = - ["let s = \"\"" - "if true then" - " ()" - "elif s." - "else ()" - ] - let (_, _, file) = this.CreateSingleFileProject(code, fileKind = SourceFileKind.FSX) - MoveCursorToEndOfMarker(file,"elif s.") - TakeCoffeeBreak(this.VS) - let completions = AutoCompleteAtCursor file - AssertCompListContains(completions,"Split") - - [] - member public this.``ErrorRecovery.Bug4881_2``() = - let code = - ["let s = \"\"" - "if true then" - " ()" - "elif true" - "elif s." - "else ()" - ] - let (_, _, file) = this.CreateSingleFileProject(code, fileKind = SourceFileKind.FSX) - MoveCursorToEndOfMarker(file,"elif s.") - TakeCoffeeBreak(this.VS) - let completions = AutoCompleteAtCursor file - AssertCompListContains(completions,"Split") - - [] - member public this.``ErrorRecovery.Bug4881_3``() = - let code = - ["let s = \"\"" - "if true then" - " ()" - "elif s." - "elif true" - "else ()" - ] - let (_, _, file) = this.CreateSingleFileProject(code, fileKind = SourceFileKind.FSX) - MoveCursorToEndOfMarker(file,"elif s.") - TakeCoffeeBreak(this.VS) - let completions = AutoCompleteAtCursor file - AssertCompListContains(completions,"Split") - - - [] - member public this.``ErrorRecovery.Bug4881_4``() = - let code = - ["let s = \"\"" - "if true then" - " ()" - "elif s." - ] - let (_, _, file) = this.CreateSingleFileProject(code, fileKind = SourceFileKind.FSX) - MoveCursorToEndOfMarker(file,"elif s.") - TakeCoffeeBreak(this.VS) - let completions = AutoCompleteAtCursor file - AssertCompListContains(completions,"Split") - - - // This case was fixed while investigating 4538. - [] - member public this.``ErrorRecovery.NotFixing4538_1``() = - let code = - ["type MyType() = " - " override x.ToString() = \"\"" - "let Main() =" - " let _ = new MyT" - " ()" - ] - let (_, _, file) = this.CreateSingleFileProject(code, fileKind = SourceFileKind.FSX) - MoveCursorToEndOfMarker(file,"new MyT") - TakeCoffeeBreak(this.VS) - let completions = CtrlSpaceCompleteAtCursor file - AssertCompListContains(completions,"MyType") - - // This case was fixed while investigating 4538. - [] - member public this.``ErrorRecovery.NotFixing4538_2``() = - let code = - ["type MyType() = " - " override x.ToString() = \"\"" - "let Main() =" - " let _ = MyT" - " ()" - ] - let (_, _, file) = this.CreateSingleFileProject(code, fileKind = SourceFileKind.FSX) - MoveCursorToEndOfMarker(file,"= MyT") - TakeCoffeeBreak(this.VS) - let completions = CtrlSpaceCompleteAtCursor file - AssertCompListContains(completions,"MyType") - - // This case was fixed while investigating 4538. - [] - member public this.``ErrorRecovery.NotFixing4538_3``() = - let code = - ["type MyType() = " - " override x.ToString() = \"\"" - "let Main() =" - " let _ = MyT" - ] - let (_, _, file) = this.CreateSingleFileProject(code, fileKind = SourceFileKind.FSX) - MoveCursorToEndOfMarker(file,"= MyT") - TakeCoffeeBreak(this.VS) - let completions = CtrlSpaceCompleteAtCursor file - AssertCompListContains(completions,"MyType") - - [] - member public this.``ErrorRecovery.Bug4538_1``() = - let code = - ["type MyType() = " - " override x.ToString() = \"\"" - "let Main() =" - " let _ = MyT" - ] - let (_, _, file) = this.CreateSingleFileProject(code, fileKind = SourceFileKind.FSX) - - MoveCursorToEndOfMarker(file,"= MyT") - TakeCoffeeBreak(this.VS) - let completions = CtrlSpaceCompleteAtCursor file - AssertCompListContains(completions,"MyType") - - [] - member public this.``ErrorRecovery.Bug4538_2``() = - let code = - ["type MyType() = " - " override x.ToString() = \"\"" - "let Main() =" - " let x = MyType()" - " let _ = MyT" - ] - let (_, _, file) = this.CreateSingleFileProject(code, fileKind = SourceFileKind.FSX) - MoveCursorToEndOfMarker(file,"_ = MyT") - TakeCoffeeBreak(this.VS) - let completions = CtrlSpaceCompleteAtCursor file - AssertCompListContains(completions,"MyType") - - - - - - [] - member public this.``ErrorRecovery.Bug4538_5``() = - let code = - ["type MyType() = " - " override x.ToString() = \"\"" - "let Main() =" - " use x = null" - " use _ = MyT" - ] - let (_, _, file) = this.CreateSingleFileProject(code, fileKind = SourceFileKind.FSX) - MoveCursorToEndOfMarker(file,"_ = MyT") - TakeCoffeeBreak(this.VS) - let completions = CtrlSpaceCompleteAtCursor file - AssertCompListContains(completions,"MyType") - - - [] - member public this.``ErrorRecovery.Bug4594_1``() = - let code = - ["let Bar(xyz) =" - " let hello =" - " if x" - ] - let (_, _, file) = this.CreateSingleFileProject(code, fileKind = SourceFileKind.FSX) - MoveCursorToEndOfMarker(file,"if x") - TakeCoffeeBreak(this.VS) - let completions = CtrlSpaceCompleteAtCursor file - AssertCompListContains(completions,"xyz") - - /// In this bug, the Module. at the very end of the file was treated as if it were in the scope - /// of Module rather than right after it. This check just makes sure we can see a data tip because - /// Module is available. - [] - member public this.``ErrorRecovery.5878_1``() = - Helper.AssertMemberDataTipContainsInOrder - ( - this.TestRunner, - (*code *) - [ - "module Module =" - " /// Union comment" - " type Union =" - " /// Case comment" - " | Case of int" - "Module." - ] , - (* marker *) - "Module.", - (* completed item *) - "Case", - (* expect to see in order... *) - [ - "union case Module.Union.Case: int -> Module.Union"; - "Case comment"; - ] - ) - // Context project system type UsingProjectSystem() = - inherit UsingMSBuild(VsOpts = LanguageServiceExtension.ProjectSystemTestFlavour) \ No newline at end of file + inherit UsingMSBuild(VsOpts = LanguageServiceExtension.ProjectSystemTestFlavour) diff --git a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.General.fs b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.General.fs index 59dab3c110e..0e4d9c18f39 100644 --- a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.General.fs +++ b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.General.fs @@ -125,73 +125,6 @@ type UsingMSBuild() = let projFileText = System.IO.File.ReadAllText(ProjectFile(project)) AssertMatchesRegex '<' @"\s*\s*link.fs" projFileText - [] - member public this.``Lexer.CommentsLexing.Bug1548``() = - let scan = new FSharpScanner_DEPRECATED(fun source -> - let fileName = "test.fs" - let defines = [ "COMPILED"; "EDITING" ] - - FSharpSourceTokenizer(defines,Some(fileName), None, None).CreateLineTokenizer(source)) - - let cm = Microsoft.VisualStudio.FSharp.LanguageService.TokenColor.Comment - let kw = Microsoft.VisualStudio.FSharp.LanguageService.TokenColor.Keyword - - // This specifies the source code to test and a collection of tokens that - // we want to find in the result (note: it doesn't have to contain every token, because - // behavior for some of them is undefined - e.g. "(* "\"*)" - what is token here? - let sources = - [ "// some comment", - [ (0, 1), cm; (2, 2), cm; (3, 6), cm; (7, 7), cm; (8, 14), cm ] - "// (* hello // 12345\nlet", - [ (6, 10), cm; (15, 19), cm; (0, 2), kw ] // checks 'hello', '12345' and keyword 'let' - "//- test", - [ (0, 2), cm; (4, 7), cm ] // checks whether '//-' isn't treated as an operator - - /// same thing for XML comments - these are treated in a different lexer branch - "/// some comment", - [ (0, 2), cm; (3, 3), cm; (4, 7), cm; (8, 8), cm; (9, 15), cm ] - "/// (* hello // 12345\nmember", - [ (7, 11), cm; (16, 20), cm; (0, 5), kw ] - "///- test", - [ (0, 3), cm; (5, 8), cm ] - - //// same thing for "////" - these are treated in a different lexer branch - "//// some comment", - [ (0, 3), cm; (4, 4), cm; (5, 8), cm; (9, 9), cm; (10, 16), cm ] - "//// (* hello // 12345\nlet", - [ (8, 12), cm; (17, 21), cm; (0, 2), kw ] - "////- test", - [ (0, 4), cm; (6, 9), cm ] - - "(* test 123 (* 456 nested *) comments *)", - [ (3, 6), cm; (8, 10), cm; (15, 17), cm; (19, 24), cm; (29, 36), cm ] // checks 'test', '123', '456', 'nested', 'comments' - "(* \"with 123 \\\" *)\" string *)", - [ (4, 7), cm; (9, 11), cm; (20, 25), cm ] // checks 'with', '123', 'string' - "(* @\"with 123 \"\" *)\" string *)", - [ (5, 8), cm; (10, 12), cm; (21, 26), cm ] // checks 'with', '123', 'string' - ] - - for lineText, expected in sources do - scan.SetLineText lineText - - let currentTokenInfo = new Microsoft.VisualStudio.FSharp.LanguageService.TokenInfo() - let lastColorState = 0 // First line of code, so no previous state - currentTokenInfo.EndIndex <- -1 - let refState = ref (ColorStateLookup_DEPRECATED.LexStateOfColorState lastColorState) - - // Lex the line and add all lexed tokens to a dictionary - let lexed = new System.Collections.Generic.Dictionary<_, _>() - while scan.ScanTokenAndProvideInfoAboutIt(1, currentTokenInfo, refState) do - lexed.Add( (currentTokenInfo.StartIndex, currentTokenInfo.EndIndex), currentTokenInfo.Color ) - - // Verify that all tokens in the specified list occur in the lexed result - for pos, clr in expected do - let (succ, v) = lexed.TryGetValue(pos) - let found = lexed |> Seq.map (fun kvp -> kvp.Key, kvp.Value) |> Seq.toList - AssertEqualWithMessage(true, succ, sprintf "Cannot find token %A at %A in %A\nFound: %A" clr pos lineText found) - AssertEqualWithMessage(clr, v, sprintf "Wrong color of token %A at %A in %A\nFound: %A" clr pos lineText found) - - // This was a bug in ReplaceAllText (subsequent calls to SetMarker would fail) [] member public this.``Salsa.ReplaceAllText``() = @@ -246,167 +179,6 @@ type UsingMSBuild() = Helper.AssertListContainsInOrder(GetOutputWindowPaneLines(this.VS), ["error FS0041: A unique overload for method 'Plot' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: member N.M.LineChart.Plot : f:(float -> float) * xmin:float * xmax:float -> unit, member N.M.LineChart.Plot : f:System.Func * xmin:float * xmax:float -> unit"]) - [] - member public this.``ExhaustivelyScrutinize.ThisOnceAsserted``() = - Helper.ExhaustivelyScrutinize( - this.TestRunner, - [ """let F() = """ - """ if true then [], """ - """ elif true then [],"" """ - """ else [],"" """ ] - ) - - [] - member public this.``ExhaustivelyScrutinize.ThisOnceAssertedToo``() = - Helper.ExhaustivelyScrutinize( - this.TestRunner, - [ "type C() = " - " member this.F() = ()" - " interface System.IComparable with " - " member _.CompareTo(v:obj) = 1" ] - ) - - [] - member public this.``ExhaustivelyScrutinize.ThisOnceAssertedThree``() = - Helper.ExhaustivelyScrutinize( - this.TestRunner, - [ "type Foo =" - " { mutable Data: string }" - " member x.XmlDocSig " - " with get() = x.Data" - " and set(v) = x.Data <- v" ] - ) - [] - member public this.``ExhaustivelyScrutinize.ThisOnceAssertedFour``() = - Helper.ExhaustivelyScrutinize( - this.TestRunner, - [ "let y=new" - "let z=4" ] - ) - - [] - member public this.``ExhaustivelyScrutinize.ThisOnceAssertedFive``() = - Helper.ExhaustivelyScrutinize(this.TestRunner, [ """CSV.File<@"File1.txt">.[0].""" ]) // <@ is one token, wanted < @"... - - [] - member public this.``ExhaustivelyScrutinize.Bug2277``() = - Helper.ExhaustivelyScrutinize( - this.TestRunner, - [ - "open Microsoft.FSharp.Plot.Excel" - "open Microsoft.FSharp.Plot.Interactive" - "let ps = [| (1.,\"c\"); (-2.,\"p\") |]" - "plot (Bars(ps))" - "let xs = [| 1.0 .. 20.0 |]" - "let ys = [| 2.0 .. 21.0 |]" - "let pp= plot(Area(xs,ys))" ] - ) - - [] - member public this.``ExhaustivelyScrutinize.Bug2283``() = - Helper.ExhaustivelyScrutinize( - this.TestRunner, - [ - "#r \"NestedClasses.dll\"" // Scenario requires this assembly not exist. - "//753 atomType -> atomType DOT path typeArgs" - "let specificIdent (x : RootNamespace.ClassOfT.NestedClassOfU) = x" - "let x = new RootNamespace.ClassOfT.NestedClassOfU()" - "if specificIdent x <> x then exit 1" - "exit 0"] - ) - - - /// Verifies that token info returns correct trigger classes - /// - this is used in MPF for triggering various intellisense features - [] - member public this.``TokenInfo.TriggerClasses``() = - let important = - [ // Member select for dot completions - Parser.DOT, (FSharpTokenColorKind.Punctuation,FSharpTokenCharKind.Delimiter,FSharpTokenTriggerClass.MemberSelect) - // for parameter info - Parser.LPAREN, (FSharpTokenColorKind.Punctuation,FSharpTokenCharKind.Delimiter, FSharpTokenTriggerClass.ParamStart ||| FSharpTokenTriggerClass.MatchBraces) - Parser.COMMA, (FSharpTokenColorKind.Punctuation,FSharpTokenCharKind.Delimiter, FSharpTokenTriggerClass.ParamNext) - Parser.RPAREN, (FSharpTokenColorKind.Punctuation,FSharpTokenCharKind.Delimiter, FSharpTokenTriggerClass.ParamEnd ||| FSharpTokenTriggerClass.MatchBraces) ] - let matching = - [ // Other cases where we expect MatchBraces - Parser.LQUOTE("", false); Parser.LBRACK; Parser.LBRACE (Unchecked.defaultof<_>); Parser.LBRACK_BAR; - Parser.RQUOTE("", false); Parser.RBRACK; Parser.RBRACE (Unchecked.defaultof<_>); Parser.BAR_RBRACK ] - |> List.map (fun n -> n, (FSharpTokenColorKind.Punctuation,FSharpTokenCharKind.Delimiter, FSharpTokenTriggerClass.MatchBraces)) - for tok, expected in List.concat [ important; matching ] do - let info = TestExpose.TokenInfo tok - AssertEqual(expected, info) - - [] - member public this.``MatchingBraces.VerifyMatches``() = - let content = - [| - " - let x = (1, 2)//1 - let y = ( 3 + 1 ) * 2 - let z = - async { - return 10 - } - let lst = - [// list_start - 1;2;3 - ]//list_end - let arr = - [| - 1 - 2 - |] - let quote = <@(* S0 *) 1 @>(* E0 *) - let quoteWithNestedList = <@(* S1 *) ['x';'y';'z'](* E_L*) @>(* E1 *) - [< System.Serializable() >] - type T = class end - " - |] - let (_solution, _project, file) = this.CreateSingleFileProject(String.concat Environment.NewLine content) - - let getPos marker = - // fix 1-based positions to 0-based - MoveCursorToStartOfMarker(file, marker) - let (row, col) = GetCursorLocation(file) - (row - 1), (col - 1) - - let setPos row col = - // fix 0-based positions to 1-based - MoveCursorTo(file, row + 1, col + 1) - - let checkBraces startMarker endMarker expectedSpanLen = - let (startRow, startCol) = getPos startMarker - let (endRow, endCol) = getPos endMarker - - let checkTextSpan (actual : TextSpan) expectedRow expectedCol = - Assert.True(actual.iStartLine = actual.iEndLine, "Start and end of the span should be on the same line") - Assert.Equal(expectedRow, actual.iStartLine) - Assert.Equal(expectedCol, actual.iStartIndex) - Assert.True(actual.iEndIndex = (actual.iStartIndex + expectedSpanLen), sprintf "Span should have length == %d" expectedSpanLen) - - let checkBracesForPosition row col = - setPos row col - let braces = GetMatchingBracesForPositionAtCursor(file) - Assert.Equal(1, braces.Length) - - let (lbrace, rbrace) = braces.[0] - checkTextSpan lbrace startRow startCol - checkTextSpan rbrace endRow endCol - - checkBracesForPosition startRow startCol - checkBracesForPosition endRow endCol - - checkBraces "(1" ")//1" 1 - checkBraces "( " ") *" 1 - checkBraces "{" "}" 1 - checkBraces "[// list_start" "]//list_end" 1 - checkBraces "[|" "|]" 2 - checkBraces "<@(* S0 *)" "@>(* E0 *)" 2 - checkBraces "<@(* S1 *)" "@>(* E1 *)" 2 - checkBraces "['x'" "](* E_L*)" 1 - checkBraces "[<" ">]" 2 - - // Context project system type UsingProjectSystem() = inherit UsingMSBuild(VsOpts = LanguageServiceExtension.ProjectSystemTestFlavour) diff --git a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.GotoDefinition.fs b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.GotoDefinition.fs index 3e115779423..cd130c5d97a 100644 --- a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.GotoDefinition.fs +++ b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.GotoDefinition.fs @@ -83,402 +83,12 @@ type UsingMSBuild() = file result - [] - member this.``Operators.TopLevel``() = - this.VerifyGotoDefnSuccessForNonIdentifierAtStartOfMarker( - fileContents = """ - let (===) a b = a = b - let _ = 1 === 2 - """, - marker = "=== 2", - pos=(1,21) - ) - [] - member this.``Operators.Member``() = - this.VerifyGotoDefnSuccessForNonIdentifierAtStartOfMarker( - fileContents = """ - type U = U - with - static member (+++) (U, U) = U - let _ = U +++ U - """, - marker = "++ U", - pos=(3,35) - ) - [] - member public this.``Value``() = - this.VerifyGoToDefnSuccessAtStartOfMarker( - fileContents = """ - type DiscUnion = - | Alpha of string - | Beta of decimal * unit - | Gamma - - let valueX = Beta(1.0M, ())(*GotoTypeDef*) - let valueY = valueX (*GotoValDef*) - """, - marker = "valueX (*GotoValDef*)", - definitionCode = "let valueX = Beta(1.0M, ())(*GotoTypeDef*)") - [] - member public this.``DisUnionMember``() = - this.VerifyGoToDefnSuccessAtStartOfMarker( - fileContents = """ - type DiscUnion = - | Alpha of string - | Beta of decimal * unit - | Gamma - - let valueX = Beta(1.0M, ())(*GotoTypeDef*) - let valueY = valueX (*GotoValDef*) - """, - marker = "Beta(1.0M, ())(*GotoTypeDef*)", - definitionCode = "| Beta of decimal * unit") - [] - member public this.``PrimitiveType``() = - this.VerifyGoToDefnFailAtStartOfMarker( - fileContents = """ - // Can't goto def on an int literal - let bi = 123456I""", - marker = "123456I") - [] - member public this.``OnTypeDefinition``() = - this.VerifyGoToDefnSuccessAtStartOfMarker( - fileContents = """ - //regression test for bug 2516 - type One (*Marker1*) = One - let f (x : One (*Marker2*)) = 2 - """, - marker = "One (*Marker1*)", - definitionCode = "type One (*Marker1*) = One") - [] - member public this.``Parameter``() = - this.VerifyGoToDefnSuccessAtStartOfMarker( - fileContents = """ - //regression test for bug 2516 - type One (*Marker1*) = One - let f (x : One (*Marker2*)) = 2 - """, - marker = "One (*Marker2*)", - definitionCode = "type One (*Marker1*) = One") - - // This test case check the GotoDefinition (i.e. the TypeProviderDefinitionLocation Attribute) - // We expect the correct FilePath, Line and Column on provided: Type, Event, Method, and Property - // TODO: add a case for a provided Field - [] - member public this.``GotoDefinition.TypeProvider.DefinitionLocationAttribute``() = - use _guard = this.UsingNewVS() - // Note that the verification helped method is custom because we *do* care about the column as well, - // which is something that the general purpose method in this file (surprisingly!) does not do. - let VerifyGoToDefnSuccessAtStartOfMarkerColumn(fileContents : string, marker : string, definitionCode : string, typeProviderAssembly : string, columnMarker : string) = - let (sln, proj, file) = GlobalFunctions.CreateNamedSingleFileProject (this.VS, (fileContents, "File.fs")) - - // Add reference to the type provider - this.AddAssemblyReference(proj,typeProviderAssembly) - - // Identify (line,col) of the destination, i.e. where we expect to land after hitting F12 - // We do this to avoid hardcoding absolute numbers in the code. - MoveCursorToStartOfMarker (file,columnMarker) - let _,column = GetCursorLocation(file) - - // Put cursor at start of marker and then hit F12 - MoveCursorToStartOfMarker (file, marker) - let identifier = (GetIdentifierAtCursor file).Value |> fst - let result = GotoDefinitionAtCursor file - - // Execute validation (on file name and line) - CheckGotoDefnResult - (GotoDefnSuccess identifier definitionCode) - file - result - - // Reminder: coordinates in the F# compiler are 1-based for lines, and 0-based for columns - // coordinates from type providers are 1-based for both lines and columns - // GetCursorLocation() seems to return something even more off by 1... - let column' = column - 2 - - match result.ToOption() with - | Some(span,_) -> Assert.Equal(column',span.iStartIndex) - | None -> failwithf "Expected to find the definition at column '%d' but GotoDefn failed." column' - - // Basic scenario on a provided Type - let ``Type.BasicScenario``() = - VerifyGoToDefnSuccessAtStartOfMarkerColumn(""" - let a = typeof - // A0(*ColumnMarker*)1234567890 - // B01234567890 - // C01234567890 """, - "T(*GotoValDef*)", - "// A0(*ColumnMarker*)1234567890", - PathRelativeToTestAssembly(@"DefinitionLocationAttribute.dll"), - "(*ColumnMarker*)") - - // This test case checks the type with space in between like N.``T T`` for GotoDefinition - let ``Type.SpaceInTheType``() = - VerifyGoToDefnSuccessAtStartOfMarkerColumn(""" - let a = typeof - // A0(*ColumnMarker*)1234567890 - // B01234567890 - // C01234567890 """, - "T``", - "// A0(*ColumnMarker*)1234567890", - PathRelativeToTestAssembly(@"DefinitionLocationAttributeWithSpaceInTheType.dll"), - "(*ColumnMarker*)") - - // Basic scenario on a provided Constructor - let ``Constructor.BasicScenario``() = - - VerifyGoToDefnSuccessAtStartOfMarkerColumn(""" - let foo = new N.T(*GotoValDef*)() - // A0(*ColumnMarker*)1234567890 - // B01234567890 - // C01234567890 """, - "T(*GotoValDef*)", - "// A0(*ColumnMarker*)1234567890", - PathRelativeToTestAssembly(@"DefinitionLocationAttribute.dll"), - "(*ColumnMarker*)") - - // Basic scenario on a provided Method - let ``Method.BasicScenario``() = - VerifyGoToDefnSuccessAtStartOfMarkerColumn(""" - let t = new N.T.M(*GotoValDef*)() - // A0(*ColumnMarker*)1234567890 - // B01234567890 - // C01234567890 """, - "M(*GotoValDef*)", - "// A0(*ColumnMarker*)1234567890", - PathRelativeToTestAssembly(@"DefinitionLocationAttribute.dll"), - "(*ColumnMarker*)") - - // Basic scenario on a provided Property - let ``Property.BasicScenario``() = - VerifyGoToDefnSuccessAtStartOfMarkerColumn(""" - let p = N.T.StaticProp(*GotoValDef*) - // A0(*ColumnMarker*)1234567890 - // B01234567890 - // C01234567890 """, - "StaticProp(*GotoValDef*)", - "// A0(*ColumnMarker*)1234567890", - PathRelativeToTestAssembly(@"DefinitionLocationAttribute.dll"), - "(*ColumnMarker*)") - - // Basic scenario on a provided Event - let ``Event.BasicScenario``() = - VerifyGoToDefnSuccessAtStartOfMarkerColumn(""" - let t = new N.T() - t.Event1(*GotoValDef*) - // A0(*ColumnMarker*)1234567890 - // B01234567890 - // C01234567890 """, - "Event1(*GotoValDef*)", - "// A0(*ColumnMarker*)1234567890", - PathRelativeToTestAssembly(@"DefinitionLocationAttribute.dll"), - "(*ColumnMarker*)") - - // Actually execute all the scenarios... - ``Type.BasicScenario``() - ``Type.SpaceInTheType``() - ``Constructor.BasicScenario``() - ``Method.BasicScenario``() - ``Property.BasicScenario``() - ``Event.BasicScenario``() - - - [] - member public this.``GotoDefinition.NoSourceCodeAvailable``() = - this.VerifyGoToDefnFailAtStartOfMarker - ( - fileContents = "System.String.Format(\"\")", - marker = "ormat", - f = (fun (_, result) -> - Assert.False(result.Success) - Assert.True(result.ErrorDescription.Contains("Source code is not available")) - ) - ) - - [] - member public this.``GotoDefinition.NoIdentifierAtLocation``() = - let useCases = - [ - "let x = 1", "1" - "let x = 1.2", ".2" - "let x = \"123\"", "2" - ] - for (source, marker) in useCases do - this.VerifyGoToDefnFailAtStartOfMarker - ( - fileContents = source, - marker = marker, - f = (fun (_, result) -> - Assert.False(result.Success) - Assert.True(result.ErrorDescription.Contains("Cursor is not on identifier")) - ) - ) - - [] - member public this.``GotoDefinition.ProvidedTypeNoDefinitionLocationAttribute``() = - - this.VerifyGoToDefnFailAtStartOfMarker - ( - fileContents = """ - type T = N1.T<"", 1> - """, - marker = "T<", - f = (fun (_, result) -> Assert.False(result.Success) ), - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")] - ) - - [] - member public this.``GotoDefinition.ProvidedMemberNoDefinitionLocationAttribute``() = - let useCases = - [ - """ - type T = N1.T<"", 1> - T.Param1 - """, "ram1", "Param1" - - """ - type T = N1.T1 - T.M1(1) - """, "1(", "M1" - ] - - for (source, marker, name) in useCases do - this.VerifyGoToDefnFailAtStartOfMarker - ( - fileContents = source, - marker = marker, - f = (fun (_, result) -> - Assert.False(result.Success) - let expectedText = sprintf "provided member '%s'" name - Assert.True(result.ErrorDescription.Contains(expectedText)) - ), - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")] - ) - [] - // This test case is when the TypeProviderDefinitionLocationAttribute filepath doesn't exist for TypeProvider Type - member public this.``GotoDefinition.TypeProvider.DefinitionLocationAttribute.Type.FileDoesnotExist``() = - this.VerifyGoToDefnFailAtStartOfMarker( - fileContents = """ - let a = typeof - // A0(*Marker*)1234567890 - // B01234567890 - // C01234567890 """, - marker = "T(*GotoValDef*)", - addtlRefAssy = [PathRelativeToTestAssembly(@"DefinitionLocationAttributeFileDoesnotExist.dll")]) - - [] - //This test case is when the TypeProviderDefinitionLocationAttribute Line doesn't exist for TypeProvider Type - member public this.``GotoDefinition.TypeProvider.DefinitionLocationAttribute.Type.LineDoesnotExist``() = - this.VerifyGoToDefnFailAtStartOfMarker( - fileContents = """ - let a = typeof - // A0(*Marker*)1234567890 - // B01234567890 - // C01234567890 """, - marker = "T(*GotoValDef*)", - addtlRefAssy = [PathRelativeToTestAssembly(@"DefinitionLocationAttributeLineDoesnotExist.dll")]) - - [] - // This test case is when the TypeProviderDefinitionLocationAttribute filepath doesn't exist for TypeProvider Constructor - member public this.``GotoDefinition.TypeProvider.DefinitionLocationAttribute.Constructor.FileDoesnotExist``() = - this.VerifyGoToDefnFailAtStartOfMarker( - fileContents = """ - let foo = new N.T(*GotoValDef*)() - // A0(*Marker*)1234567890 - // B01234567890 - // C01234567890 """, - marker = "T(*GotoValDef*)", - addtlRefAssy = [PathRelativeToTestAssembly(@"DefinitionLocationAttributeFileDoesnotExist.dll")]) - - - - [] - //This test case is when the TypeProviderDefinitionLocationAttribute filepath doesn't exist for TypeProvider Method - member public this.``GotoDefinition.TypeProvider.DefinitionLocationAttribute.Method.FileDoesnotExist``() = - this.VerifyGoToDefnFailAtStartOfMarker( - fileContents = """ - let t = new N.T.M(*GotoValDef*)() - // A0(*Marker*)1234567890 - // B01234567890 - // C01234567890 """, - marker = "M(*GotoValDef*)", - addtlRefAssy = [PathRelativeToTestAssembly(@"DefinitionLocationAttributeFileDoesnotExist.dll")]) - - [] - // This test case is when the TypeProviderDefinitionLocationAttribute filepath doesn't exist for TypeProvider Property - member public this.``GotoDefinition.TypeProvider.DefinitionLocationAttribute.Property.FileDoesnotExist``() = - this.VerifyGoToDefnFailAtStartOfMarker( - fileContents = """ - let p = N.T.StaticProp(*GotoValDef*) - // A0(*Marker*)1234567890 - // B01234567890 - // C01234567890 """, - marker = "StaticProp(*GotoValDef*)", - addtlRefAssy = [PathRelativeToTestAssembly(@"DefinitionLocationAttributeFileDoesnotExist.dll")]) - - [] - //This test case is when the TypeProviderDefinitionLocationAttribute filepath doesn't exist for TypeProvider Event - member public this.``GotoDefinition.TypeProvider.DefinitionLocationAttribute.Event.FileDoesnotExist``() = - this.VerifyGoToDefnFailAtStartOfMarker( - fileContents = """ - let t = new N.T() - t.Event1(*GotoValDef*) - // A0(*Marker*)1234567890 - // B01234567890 - // C01234567890 """, - marker = "Event1(*GotoValDef*)", - addtlRefAssy = [PathRelativeToTestAssembly(@"DefinitionLocationAttributeFileDoesnotExist.dll")]) - - [] - member public this.``ModuleDefinition``() = - this.VerifyGoToDefnSuccessAtStartOfMarker( - fileContents = """ - //regression test for bug 2517 - module Foo (*MarkerModuleDefinition*) = - let x = () - """, - marker = "Foo (*MarkerModuleDefinition*)", - definitionCode = "module Foo (*MarkerModuleDefinition*) =") - - [] - member public this.``Record.Field.Definition``() = - this.VerifyGoToDefnSuccessAtStartOfMarker( - fileContents = """ - //regression test for bug 2518 - type MyRec = - { myX (*MarkerXFieldDefinition*) : int - myY (*MarkerYFieldDefinition*) : int - } - let rDefault = - { myX (*MarkerXField*) = 2 - myY (*MarkerYField*) = 3 - } - """, - marker = "myX (*MarkerXFieldDefinition*)", - definitionCode = "{ myX (*MarkerXFieldDefinition*) : int") - - [] - member public this.``Record.Field.Usage``() = - this.VerifyGoToDefnSuccessAtStartOfMarker( - fileContents = """ - //regression test for bug 2518 - type MyRec = - { myX (*MarkerXFieldDefinition*) : int - myY (*MarkerYFieldDefinition*) : int - } - let rDefault = - { myX (*MarkerXField*) = 2 - myY (*MarkerYField*) = 3 - } - """, - marker = "myY (*MarkerYField*)", - definitionCode = " myY (*MarkerYFieldDefinition*) : int") /// run a GotoDefinition test where the expected result is a file that we /// have an `OpenFile` handle for (this won't work, e.g., if this file is a @@ -524,108 +134,9 @@ type UsingMSBuild() = member this.GotoDefinitionTestWithSimpleFile (startLoc : string)(exp : (string * string) option) : unit = this.SolutionGotoDefinitionTestWithSimpleFile startLoc exp - [] - member this.``GotoDefinition.OverloadResolution``() = - let lines = - [ "type D() =" - " override this.#3#ToString() = System.String.Empty" - " member this.#4#ToString(s : string) = ()" - "" - " member this.#1#Foo() = ()" - " member this.#2#Foo(x) = ()" - "" - "let d = new D()" - "d.Foo$1$()" - "d.Foo$2$(1)" - "d.ToString$3$()" - "d.ToString$4$(\"aaa\") " - ] - this.GotoDefinitionTestWithMarkup lines - [] - member this.``GotoDefinition.OverloadResolutionForProperties``() = - let lines = [ "type D() =" - " member this.#1##2#Foo" - " with get(i:int) = 1" - " and set (i:int) v = ()" - "" - " member this.#3##4#Foo" - " with get (s:string) = 1" - " and set (s:string) v = ()" - "" - "D().$1$Foo 1" - "D().$2$Foo 1 <- 2" - "D().$3$Foo \"abc\"" - "D().$4$Foo \"abc\" <- 2" - ] - this.GotoDefinitionTestWithMarkup lines - [] - member this.``GotoDefinition.OverloadResolutionWithOverrides``() = - let lines = - [ "[]" - "type Base<'T>() =" - " member this.#2#Method() = ()" - " abstract Method : 'T -> unit" - "" - "type Derived() =" - " inherit Base()" - "" - " override this.#1#Method (i:int) = ()" - "" - "let d = new Derived()" - "d.$1$Method 12" - "d.$2$Method()" - ] - this.GotoDefinitionTestWithMarkup lines - [] - member this.``GotoDefinition.OverloadResolutionStatics``() = - let lines = - [ "type T =" - " static member #1#Foo(i : int) = ()" - " static member #2#Foo(s : string) = ()" - "" - "T.$1$Foo 1" - "T.$2$Foo \"abc\"" - ] - this.GotoDefinitionTestWithMarkup lines - [] - member this.``GotoDefinition.Constructors``() = - let lines = - [ "type #1a##1b##1c##1d#B() =" - " #2a##2b##2c##2d#new(i : int) = B()" - " #3a##3b##3c##3d#new(s : string) = B()" - "" - "B()" - "B(1)" - "B(\"abc\")" - "" - "new $1b$B()" - "new $2b$B(1)" - "new $3b$B(\"abc\")" - "" - "type D1() =" - " inherit $1c$B()" - "" - "type D2() =" - " inherit $2c$B(1)" - - "type D3() =" - " inherit $3c$B(\"abc\")" - "" - "let o1 = { new $1d$B() with" - " override this.ToString() = \"\"" - " }" - "let o2 = { new $2d$B(1) with" - " override this.ToString() = \"\"" - " }" - "let o2 = { new $3d$B(\"aaa\") with" - " override this.ToString() = \"\"" - " }" - - ] - this.GotoDefinitionTestWithMarkup lines member internal this.GotoDefinitionTestWithMarkup (lines : string list) = let origins = Dictionary() @@ -873,452 +384,85 @@ type UsingMSBuild() = // ensure that we've found the correct position (i.e., these must be unique // in any given test source file) - [] - member this.``GotoDefinition.InheritedMembers``() = - let lines = - [ "[]" - "type Foo() =" - " abstract Method : unit -> unit" - " abstract Property : int" - "type Bar() =" - " inherit Foo()" - " override this.Method () = ()" - " override this.Property = 1" - "let b = Bar()" - "b.Method(*loc-1*)()" - "b.Property(*loc-2*)" - ] - this.SolutionGotoDefinitionTestWithLines lines "Method(*loc-1*)" (Some("override this.Method () = ()","this.Method")) - this.SolutionGotoDefinitionTestWithLines lines "Property(*loc-2*)" (Some("override this.Property = 1","this.Property")) - /// let #x = () in $x - [] - member public this.``GotoDefinition.InsideClass.Bug3176`` () = - this.GotoDefinitionTestWithSimpleFile "id77 (*loc-77*)" (Some("val id77 (*loc-77*) : int", "id77")) /// let #x = () in $x [] member public this.``GotoDefinition.Simple.Binding.TrivialLetRHS`` () = this.GotoDefinitionTestWithSimpleFile "x (*loc-1*)" (Some("let x = () (*loc-2*)", "x")) - /// let #x = () in x$ - [] - member public this.``GotoDefinition.Simple.Binding.TrivialLetRHSToRight`` () = - this.GotoDefinitionTestWithSimpleFile " (*loc-1*)" (Some("let x = () (*loc-2*)", "x")) - /// let $x = () in x - [] - member public this.``GotoDefinition.Simple.Binding.TrivialLetLHS`` () = - this.GotoDefinitionTestWithSimpleFile "x = () (*loc-2*)" (Some("let x = () (*loc-2*)", "x")) - /// let x = () in let #x = () in $x - [] - member public this.``GotoDefinition.Simple.Binding.NestedLetWithSameNameRHS`` () = - this.GotoDefinitionTestWithSimpleFile "x (*loc-4*)" (Some("let x = () (*loc-3*)", "x")) - /// let x = () in let $x = () in x - [] - member public this.``GotoDefinition.Simple.Binding.NestedLetWithSameNameLHSInner`` () = - this.GotoDefinitionTestWithSimpleFile "x = () (*loc-3*)" (Some("let x = () (*loc-3*)", "x")) - /// let $x = () in let x = () in x - [] - member public this.``GotoDefinition.Simple.Binding.NestedLetWithSameNameLHSOuter`` () = - this.GotoDefinitionTestWithSimpleFile "x = () (*loc-5*)" (Some("let x = () (*loc-5*)", "x")) - /// let #x = () in let x = $x in () - [] - member public this.``GotoDefinition.Simple.Binding.NestedLetWithXIsX`` () = - this.GotoDefinitionTestWithSimpleFile "x (*loc-6*)" (Some("let x = () (*loc-7*)", "x")) - /// let x = () in let rec #x = fun y -> $x y in () - [] - member public this.``GotoDefinition.Simple.Binding.NestedLetWithXRec`` () = - this.GotoDefinitionTestWithSimpleFile "x y (*loc-8*)" (Some("let rec x = (*loc-9*)", "x")) - /// let x = () in let rec x = fun #y -> x $y in () - [] - member public this.``GotoDefinition.Simple.Binding.NestedLetWithXRecParam`` () = - this.GotoDefinitionTestWithSimpleFile "y (*loc-8*)" (Some("fun y -> (*loc-10*)", "y")) - /// let #(+) x _ = x in 2 $+ 3 - [] - member public this.``GotoDefinition.Simple.Binding.Operator`` () = - this.GotoDefinitionTestWithSimpleFile "+ 3 (*loc-11*)" (Some("let (+) x _ = x (*loc-2*)", "+")) - /// type #Zero = - /// let f (_ : $Zero) = 0 - [] - member public this.``GotoDefinition.Simple.Datatype.NullType`` () = - this.GotoDefinitionTestWithSimpleFile "Zero) : 'a = failwith \"hi\" (*loc-14*)" (Some("type Zero = (*loc-13*)", "Zero")) - /// type One = $One - [] - member public this.``GotoDefinition.Simple.Datatype.UnitTypeConsDef`` () = - this.GotoDefinitionTestWithSimpleFile "One (*loc-15*)" (Some("One (*loc-15*)", "One")) - /// type $One = One - [] - member public this.``GotoDefinition.Simple.Datatype.UnitTypeTypenameDef`` () = - this.GotoDefinitionTestWithSimpleFile "One = (*loc-16*)" (Some("type One = (*loc-16*)", "One")) - /// type One = #One - /// let f (_ : One) = $One - [] - member public this.``GotoDefinition.Simple.Datatype.UnitTypeCons`` () = - this.GotoDefinitionTestWithSimpleFile "One (*loc-18*)" (Some("One (*loc-15*)", "One")) - /// type #One = One - /// let f (_ : $One) = One - [] - member public this.``GotoDefinition.Simple.Datatype.UnitTypeTypename`` () = - this.GotoDefinitionTestWithSimpleFile "One) = (*loc-17*)" (Some("type One = (*loc-16*)", "One")) - /// type $Nat = Suc of Nat | Zro - [] - member public this.``GotoDefinition.Simple.Datatype.NatTypeTypenameDef`` () = - this.GotoDefinitionTestWithSimpleFile "Nat = (*loc-19*)" (Some("type Nat = (*loc-19*)", "Nat")) - /// type #Nat = Suc of $Nat | Zro - [] - member public this.``GotoDefinition.Simple.Datatype.NatTypeConsArg`` () = - this.GotoDefinitionTestWithSimpleFile "Nat (*loc-20*)" (Some("type Nat = (*loc-19*)", "Nat")) - /// type Nat = Suc of Nat | #Zro - /// fun m -> match m with | $Zro -> () | _ -> () - [] - member public this.``GotoDefinition.Simple.Datatype.NatPatZro`` () = - this.GotoDefinitionTestWithSimpleFile "Zro -> (*loc-24*)" (Some("| Zro (*loc-21*)", "Zro")) - /// type Nat = $Suc of Nat | Zro - /// fun m -> match m with | Zro -> () | $Suc _ -> () - [] - member public this.``GotoDefinition.Simple.Datatype.NatPatSuc`` () = - this.GotoDefinitionTestWithSimpleFile "Suc m -> (*loc-25*)" (Some("| Suc of Nat (*loc-20*)", "Suc")) - /// let rec plus m n = match m with | Zro -> n | Suc #m -> Suc (plus $m n) - [] - member public this.``GotoDefinition.Simple.Datatype.NatPatSucVarUse`` () = - this.GotoDefinitionTestWithSimpleFile "m n) (*loc-26*)" (Some("| Suc m -> (*loc-25*)", "m")) - /// let rec plus m n = match m with | Zro -> n | Suc #m -> Suc (plus $m n) - [] - member public this.``GotoDefinition.Simple.Datatype.NatPatSucOuterVarUse`` () = - this.GotoDefinitionTestWithSimpleFile "n) (*loc-26*)" (Some("let rec plus m n = (*loc-23*)", "n")) - /// type $MyRec = { myX : int ; myY : int } - [] - member public this.``GotoDefinition.Simple.Datatype.RecordTypenameDef`` () = - this.GotoDefinitionTestWithSimpleFile "MyRec = (*loc-27*)" (Some("type MyRec = (*loc-27*)", "MyRec")) - /// type MyRec = { $myX : int ; myY : int } - [] - member public this.``GotoDefinition.Simple.Datatype.RecordField1Def`` () = - this.GotoDefinitionTestWithSimpleFile "myX : int (*loc-28*)" (Some("{ myX : int (*loc-28*)", "myX")) - /// type MyRec = { myX : int ; $myY : int } - [] - member public this.``GotoDefinition.Simple.Datatype.RecordField2Def`` () = - this.GotoDefinitionTestWithSimpleFile "myY : int (*loc-29*)" (Some("myY : int (*loc-29*)", "myY")) - /// type MyRec = { #myX : int ; myY : int } - /// let rDefault = { $myX = 2 ; myY = 3 } - [] - member public this.``GotoDefinition.Simple.Datatype.RecordField1Use`` () = - this.GotoDefinitionTestWithSimpleFile "myX = 2 (*loc-30*)" (Some("{ myX : int (*loc-28*)", "myX")) - /// type MyRec = { myX : int ; #myY : int } - /// let rDefault = { myX = 2 ; $myY = 3 } - [] - member public this.``GotoDefinition.Simple.Datatype.RecordField2Use`` () = - this.GotoDefinitionTestWithSimpleFile "myY = 3 (*loc-31*)" (Some("myY : int (*loc-29*)", "myY")) - /// type MyRec = { #myX : int ; myY : int } - /// let rDefault = { myX = 2 ; myY = 3 } - /// let _ = { rDefault with $myX = 7 } - [] - member public this.``GotoDefinition.Simple.Datatype.RecordField1UseInWith`` () = - this.GotoDefinitionTestWithSimpleFile "myX = 7 } (*loc-32*)" (Some("{ myX : int (*loc-28*)", "myX")) - /// let a = () in let id (x : '$a) : 'a = x - [] - member public this.``GotoDefinition.Simple.Polymorph.Leftmost`` () = - this.GotoDefinitionTestWithSimpleFile "a) (*loc-33*)" (Some("let id (x : 'a) (*loc-33*)", "'a")) - /// let a = () in let id (x : 'a) : '$a = x - [] - member public this.``GotoDefinition.Simple.Polymorph.NotLeftmost`` () = - this.GotoDefinitionTestWithSimpleFile "a = x (*loc-34*)" (Some("let id (x : 'a) (*loc-33*)", "'a")) - /// let foo = () in let f (_ as $foo) = foo in () - [] - member public this.``GotoDefinition.Simple.Tricky.AsPatLHS`` () = - this.GotoDefinitionTestWithSimpleFile "foo) = (*loc-35*)" (Some("let f (_ as foo) = (*loc-35*)", "foo")) - /// let foo = () in let f (_ as #foo) = $foo in () - [] - member public this.``GotoDefinition.Simple.Tricky.AsPatRHS`` () = - this.GotoDefinitionTestWithSimpleFile "foo (*loc-36*)" (Some("let f (_ as foo) = (*loc-35*)", "foo")) - /// fun $x x -> x - [] - member public this.``GotoDefinition.Simple.Tricky.LambdaMultBind1`` () = - this.GotoDefinitionTestWithSimpleFile "x (*loc-37*)" (Some("fun x (*loc-37*)", "x")) - /// fun x $x -> x - [] - member public this.``GotoDefinition.Simple.Tricky.LambdaMultBind2`` () = - this.GotoDefinitionTestWithSimpleFile "x -> (*loc-38*)" (Some("x -> (*loc-38*)", "x")) - /// fun x $x -> x - [] - member public this.``GotoDefinition.Simple.Tricky.LambdaMultBindBody`` () = - this.GotoDefinitionTestWithSimpleFile "x (*loc-39*)" (Some("x -> (*loc-38*)", "x")) - /// let f = () in let $f = function f -> f in () - [] - member public this.``GotoDefinition.Simple.Tricky.LotsOfFsFunc`` () = - this.GotoDefinitionTestWithSimpleFile "f = (*loc-41*)" (Some("let f = (*loc-41*)", "f")) - /// let f = () in let f = function $f -> f in () - [] - member public this.``GotoDefinition.Simple.Tricky.LotsOfFsPat`` () = - this.GotoDefinitionTestWithSimpleFile "f -> (*loc-42*)" (Some("function f -> (*loc-42*)", "f")) - /// let f = () in let f = function #f -> $f in () - [] - member public this.``GotoDefinition.Simple.Tricky.LotsOfFsUse`` () = - this.GotoDefinitionTestWithSimpleFile "f (*loc-43*)" (Some("function f -> (*loc-42*)", "f")) - /// let f x = match x with | Suc $x | x -> x - [] - member public this.``GotoDefinition.Simple.Tricky.OrPatLeft`` () = - this.GotoDefinitionTestWithSimpleFile "x (*loc-44*)" (Some("| Suc x (*loc-44*)", "x")) - /// let f x = match x with | Suc x | $x -> x - [] - member public this.``GotoDefinition.Simple.Tricky.OrPatRight`` () = - this.GotoDefinitionTestWithSimpleFile "x (*loc-45*)" (Some("| Suc x (*loc-44*)", "x")) // NOTE: or-patterns bind at first occurrence of the variable - /// let f x = match x with | Suc #y & z -> $y - [] - member public this.``GotoDefinition.Simple.Tricky.AndPat`` () = - this.GotoDefinitionTestWithSimpleFile "y (*loc-46*)" (Some("| Suc y & z -> (*loc-47*)", "y")) - /// let f xs = match xs with | #x :: xs -> $x - [] - member public this.``GotoDefinition.Simple.Tricky.ConsPat`` () = - this.GotoDefinitionTestWithSimpleFile "x (*loc-48*)" (Some("| x :: xs -> (*loc-49*)", "x")) - /// let f p = match p with (#y, z) -> $y - [] - member public this.``GotoDefinition.Simple.Tricky.PairPat`` () = - this.GotoDefinitionTestWithSimpleFile "y (*loc-50*)" (Some("| (y : int, z) -> (*loc-51*)", "y")) - /// fun xs -> match xs with x :: #xs when $xs <> [] -> x :: xs - [] - member public this.``GotoDefinition.Simple.Tricky.ConsPatWhenClauseInWhen`` () = - this.GotoDefinitionTestWithSimpleFile "xs <> [] -> (*loc-52*)" (Some("| x :: xs (*loc-54*)", "xs")) - /// fun xs -> match xs with #x :: xs when xs <> [] -> $x :: xs - [] - member public this.``GotoDefinition.Simple.Tricky.ConsPatWhenClauseInWhenRhsX`` () = - this.GotoDefinitionTestWithSimpleFile "x :: xs (*loc-53*)" (Some("| x :: xs (*loc-54*)", "x")) - /// fun xs -> match xs with x :: #xs when xs <> [] -> x :: $xs - [] - member public this.``GotoDefinition.Simple.Tricky.ConsPatWhenClauseInWhenRhsXs`` () = - this.GotoDefinitionTestWithSimpleFile "xs (*loc-53*)" (Some("| x :: xs (*loc-54*)", "xs")) - /// let x = "$x" - [] - member public this.``GotoDefinition.Simple.Tricky.InStringFails`` () = - this.GotoDefinitionTestWithSimpleFile "x(*loc-72*)" None - /// let x = "hello - /// $x - /// " - [] - member public this.``GotoDefinition.Simple.Tricky.InMultiLineStringFails`` () = - this.GotoDefinitionTestWithSimpleFile "x(*loc-73*)" None - [] - member public this.``GotoDefinition.Simple.Tricky.QuotedKeyword`` () = - this.GotoDefinitionTestWithSimpleFile "let`` = (*loc-74*)" (Some("let rec ``let`` = (*loc-74*)", "``let``")) - /// module $Too = let foo = () - [] - member public this.``GotoDefinition.Simple.Module.DefModname`` () = - this.GotoDefinitionTestWithSimpleFile "Too = (*loc-55*)" (Some("module Too = (*loc-55*)", "Too")) - /// module Too = $foo = () - [] - member public this.``GotoDefinition.Simple.Module.DefMember`` () = - this.GotoDefinitionTestWithSimpleFile "foo = 0 (*loc-56*)" (Some("let foo = 0 (*loc-56*)", "foo")) - /// module #Too = foo = () - /// module Bar = open $Too - [] - member public this.``GotoDefinition.Simple.Module.Open`` () = - this.GotoDefinitionTestWithSimpleFile "Too (*loc-57*)" (Some("module Too = (*loc-55*)", "Too")) - /// module #Too = foo = () - /// $Too.foo - [] - member public this.``GotoDefinition.Simple.Module.QualifiedModule`` () = - this.GotoDefinitionTestWithSimpleFile "Too.foo (*loc-58*)" (Some("module Too = (*loc-55*)", "Too")) - /// module Too = #foo = () - /// Too.$foo - [] - member public this.``GotoDefinition.Simple.Module.QualifiedMember`` () = - this.GotoDefinitionTestWithSimpleFile "foo (*loc-58*)" (Some("let foo = 0 (*loc-56*)", "foo")) - /// type Parity = Even | Odd - /// let (|$Even|Odd|) x = if x % 0 = 0 then Even else Odd - [] - member public this.``GotoDefinition.Simple.ActivePat.ConsDefLHS`` () = - this.GotoDefinitionTestWithSimpleFile "Even|Odd|) x = (*loc-59*)" (Some("let (|Even|Odd|) x = (*loc-59*)", "|Even|Odd|")) - /// type Parity = Even | Odd - /// let (|#Even|Odd|) x = if x % 0 = 0 then $Even else Odd - [] - member public this.``GotoDefinition.Simple.ActivePat.ConsDefRhs`` () = - this.GotoDefinitionTestWithSimpleFile "Even (*loc-60*)" (Some("let (|Even|Odd|) x = (*loc-59*)", "|Even|Odd|")) - - /// type Parity = Even | Odd - /// let (|#Even|Odd|) x = if x % 0 = 0 then Even else Odd - /// let foo x = - /// match x with - /// | $Even -> 1 - /// | Odd -> 0 - [] - member public this.``GotoDefinition.Simple.ActivePat.PatUse`` () = - this.GotoDefinitionTestWithSimpleFile "Even -> 1 (*loc-61*)" (Some("let (|Even|Odd|) x = (*loc-59*)", "|Even|Odd|")) - /// let patval = (|Even|Odd|) (*loc-61b*) - [] - member public this.``GotoDefinition.Simple.ActivePat.PatUseValue`` () = - this.GotoDefinitionTestWithSimpleFile "en|Odd|) (*loc-61b*)" (Some("let (|Even|Odd|) x = (*loc-59*)", "|Even|Odd|")) - [] - member public this.``GotoDefinition.Library.InitialTest`` () = - this.GotoDefinitionTestWithLib "map (*loc-1*)" (Some("map", "lis.fs")) + // ********** Tests of OO Stuff ********** - /// type #Class$ () = - /// member c.Method () = () - [] - member public this.``GotoDefinition.ObjectOriented.ClassNameDef`` () = - this.GotoDefinitionTestWithSimpleFile " () = (*loc-62*)" (Some("type Class () = (*loc-62*)", "Class")) - /// type Class () = - /// member c.#Method$ () = () - [] - member public this.``GotoDefinition.ObjectOriented.ILMethodDef`` () = - this.GotoDefinitionTestWithSimpleFile " () = () (*loc-63*)" (Some("member c.Method () = () (*loc-63*)", "c.Method")) - /// type Class () = - /// member #c$.Method () = () - [] - member public this.``GotoDefinition.ObjectOriented.ThisDef`` () = - this.GotoDefinitionTestWithSimpleFile ".Method () = () (*loc-63*)" (Some("member c.Method () = () (*loc-63*)", "c")) - /// type Class () = - /// static member #Foo$ () = () - [] - member public this.``GotoDefinition.ObjectOriented.StaticMethodDef`` () = - this.GotoDefinitionTestWithSimpleFile " () = () (*loc-64*)" (Some("static member Foo () = () (*loc-64*)", "Foo")) - /// type #Class () = - /// member Method () = () - /// let c = Class$ () - [] - member public this.``GotoDefinition.ObjectOriented.ConstructorUse`` () = - this.GotoDefinitionTestWithSimpleFile " () (*loc-65*)" (Some("type Class () = (*loc-62*)", "Class")) - /// type Class () = - /// member #Method () = () - /// let c = Class () - /// c.Method$ () - [] - member public this.``GotoDefinition.ObjectOriented.MethodInvocation`` () = - this.GotoDefinitionTestWithSimpleFile " () (*loc-66*)" (Some("member c.Method () = () (*loc-63*)", "c.Method")) - /// type Class () = - /// static member #Foo () = () - /// Class.Foo$ () - [] - member public this.``GotoDefinition.ObjectOriented.StaticMethodInvocation`` () = - this.GotoDefinitionTestWithSimpleFile " () (*loc-67*)" (Some("static member Foo () = () (*loc-64*)", "Foo")) - /// type Class () = - /// member c.Method# () = c.Method$ () - [] - member public this.``GotoDefinition.ObjectOriented.MethodSelfInvocation`` () = - this.GotoDefinitionTestWithSimpleFile " () (*loc-68*)" (Some("member c.Method () = c.Method () (*loc-68*)", "c.Method")) - /// type Class () = - /// member c.Method1 () = c.Method2$ () - /// member #c.Method2 () = c.Method1 () - [] - member public this.``GotoDefinition.ObjectOriented.MethodToMethodForward`` () = - this.GotoDefinitionTestWithSimpleFile " () (*loc-69*)" (Some("member c.Method2 () = c.Method1 () (*loc-70*)", "c.Method2")) - - /// type Class () = - /// member c.Method () = () - /// type Class' () = - /// member c.Method () = - /// let #c = Class () - /// c$.Method () - [] - member public this.``GotoDefinition.ObjectOriented.ShadowThis`` () = - this.GotoDefinitionTestWithSimpleFile ".Method () (*loc-71*)" (Some("let c = Class ()", "c")) - - /// type Class () = - /// member #c.Method () = () - /// type Class' () = - /// member c.Method () = - /// let c = Class () - /// c.Method$ () - [] - member public this.``GotoDefinition.ObjectOriented.ShadowThisMethodInvocation`` () = - this.GotoDefinitionTestWithSimpleFile " () (*loc-71*)" (Some("member c.Method () = () (*loc-63*)", "c.Method")) - [] - member this.``GotoDefinition.ObjectOriented.StructConstructor`` () = - let lines = - [ - "" - "[]" - "type Astruct(x:int, y:int) =" - " []" - " val mutable a : int" - " new(a) = Astruct(a, a)" - "type AS = Astruct" - "let a1 = Astruct(0)" - "let b1 = Astruct(0, 1)" - "let c1 = Astruct()" - "let a2 = AS(0)" - "let b2 = AS(0, 1)" - "let c2 = AS()" - ] - - let (_,_, file) = this.CreateSingleFileProject(lines) - let checkGTD marker (line, col) = - MoveCursorToStartOfMarker (file, marker) - let res = GotoDefinitionAtCursor file |> fun x -> x.ToOption() |> Option.map (fun (res, _) -> res.iStartLine + 1, res.iStartIndex + 1) - AssertEqual(Some(line, col), res) - - checkGTD "Astruct(0)" (6, 3) - checkGTD "Astruct(0, 1)" (3, 6) - checkGTD "Astruct()" (3, 6) - checkGTD "AS(0)" (6, 3) - checkGTD "AS(0, 1)" (3, 6) - checkGTD "AS()" (3, 6) + + // ********** GetCompleteIdentifierIsland tests ********** @@ -1340,96 +484,20 @@ type UsingMSBuild() = | (None, Some _) -> Assert.Fail("Expected result, but didn't receive one!") - [] - member public this.``GetCompleteIdTest.TrivialBefore`` () = - for tolerate in [true;false] do - this.GetCompleteIdTest tolerate "let $ThisIsAnIdentifier = ()" (Some "ThisIsAnIdentifier") - [] - member public this.``GetCompleteIdTest.TrivialMiddle`` () = - for tolerate in [true;false] do - this.GetCompleteIdTest tolerate "let This$IsAnIdentifier = ()" (Some "ThisIsAnIdentifier") - [] - member public this.``GetCompleteIdTest.TrivialEnd`` () = - this.GetCompleteIdTest true "let ThisIsAnIdentifier$ = ()" (Some "ThisIsAnIdentifier") - this.GetCompleteIdTest false "let ThisIsAnIdentifier$ = ()" None - [] - member public this.``GetCompleteIdTest.GetsUpToDot1`` () = - for tolerate in [true;false] do - this.GetCompleteIdTest tolerate "let ThisIsAnIdentifier = Te$st.Moo.Foo.bar" (Some "Test") - [] - member public this.``GetCompleteIdTest.GetsUpToDot2`` () = - for tolerate in [true;false] do - this.GetCompleteIdTest tolerate "let ThisIsAnIdentifier = Test.Mo$o.Foo.bar" (Some "Test.Moo") - [] - member public this.``GetCompleteIdTest.GetsUpToDot3`` () = - for tolerate in [true;false] do - this.GetCompleteIdTest tolerate "let ThisIsAnIdentifier = Test.Moo.Fo$o.bar" (Some "Test.Moo.Foo") - [] - member public this.``GetCompleteIdTest.GetsUpToDot4`` () = - for tolerate in [true;false] do - this.GetCompleteIdTest tolerate "let ThisIsAnIdentifier = Test.Moo.Foo.ba$r" (Some "Test.Moo.Foo.bar") - [] - member public this.``GetCompleteIdTest.GetsUpToDot5`` () = - this.GetCompleteIdTest true "let ThisIsAnIdentifier = Test.Moo.Foo.bar$" (Some "Test.Moo.Foo.bar") - this.GetCompleteIdTest false "let ThisIsAnIdentifier = Test.Moo.Foo.bar$" None - [] - member public this.``GetCompleteIdTest.GetOperator`` () = - for tolerate in [true;false] do - this.GetCompleteIdTest tolerate "let ThisIsAnIdentifier = 3 +$ 4" None - [] - member public this.``Identifier.IsConstructor.Bug2516``() = - let fileContents = """ - module GotoDefinition - type One(*Mark1*) = One - let f (x : One(*Mark2*)) = 2""" - let definitionCode = "type One(*Mark1*) = One" - this.VerifyGoToDefnSuccessAtStartOfMarker(fileContents,"(*Mark1*)",definitionCode) - [] - member public this.``Identifier.IsTypeName.Bug2516``() = - let fileContents = """ - module GotoDefinition - type One(*Mark1*) = One - let f (x : One(*Mark2*)) = 2""" - let definitionCode = "type One(*Mark1*) = One" - this.VerifyGoToDefnSuccessAtStartOfMarker(fileContents,"(*Mark2*)",definitionCode) - [] - member public this.``ModuleName.OnDefinitionSite.Bug2517``() = - let fileContents = """ - namespace GotoDefinition - module Foo(*Mark*) = - let x = ()""" - let definitionCode = "module Foo(*Mark*) =" - this.VerifyGoToDefnSuccessAtStartOfMarker(fileContents,"(*Mark*)",definitionCode) - - /// GotoDef on abbreviation - [] - member public this.``GotoDefinition.Abbreviation.Bug193064``() = - let fileContents = """ - type X = int - let f (x:X) = x(*Marker*) """ - let definitionCode = "let f (x:X) = x(*Marker*)" - this.VerifyGoToDefnSuccessAtStartOfMarker(fileContents,"x(*Marker*)",definitionCode) - - /// Verify the GotoDefinition on UoM yield does NOT jump out error dialog, - /// will do nothing in automation lab machine or GTD SI.fs on dev machine with enlistment. - [] - member public this.``GotoDefinition.UnitOfMeasure.Bug193064``() = - let fileContents = """ - open Microsoft.FSharp.Data.UnitSystems.SI - UnitSymbols.A(*Marker*)""" - this.VerifyGoToDefnNoErrorDialogAtStartOfMarker(fileContents,"A(*Marker*)", "type A = ampere") + + // Context project system diff --git a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.ParameterInfo.fs b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.ParameterInfo.fs index 110f8b9ac89..38f24f4ff4b 100644 --- a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.ParameterInfo.fs +++ b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.ParameterInfo.fs @@ -113,488 +113,7 @@ type UsingMSBuild() = let methodstr = methodstr.Value Assert.Equal(0, methodstr.GetParameterCount(expectedCount)) - [] - member public this.``Regression.OnConstructor.881644``() = - let fileContent = """new System.IO.StreamReader((*Mark*)""" - let methodstr = this.GetMethodListForAMethodTip(fileContent,"(*Mark*)") - Assert.True(methodstr.IsSome, "Expected a method group") - let methodstr = methodstr.Value - - if not (methodstr.GetDescription(0).Contains("#ctor")) then - failwith "Expected parameter info to contain #ctor" - - [] - member public this.``Regression.InsideWorkflow.6437``() = - let fileContent = """ - open System.IO - let computation2 = - async { use file = File.Open("",FileMode.Open) - let! buffer = file.AsyncRead((*Mark*)0) - return 0 }""" - let methodstr = this.GetMethodListForAMethodTip(fileContent,"(*Mark*)") - Assert.True(methodstr.IsSome, "Expected a method group") - let methodstr = methodstr.Value - - if not (methodstr.GetDescription(0).Contains("AsyncRead")) then - failwith "Expected parameter info to contain AsyncRead" - - [] - member public this.``Regression.MethodInfo.WithColon.Bug4518_1``() = - let fileContent = """ - type T() = - member this.X - with set ((a:int), (b:int)) (c:int) = () - ((new T()).X((*Mark*)""" - this.VerifyFirstParameterInfoColonContent(fileContent,"(*Mark*)",": int") - - [] - member public this.``Regression.MethodInfo.WithColon.Bug4518_2``() = - let fileContent = """ - type IFoo = interface - abstract f : int -> int - end - let i : IFoo = null - i.f((*Mark*)""" - this.VerifyFirstParameterInfoColonContent(fileContent,"(*Mark*)",": int") - - [] - member public this.``Regression.MethodInfo.WithColon.Bug4518_3``() = - let fileContent = """ - type M() = - member this.f x = () - let m = new M() - m.f((*Mark*)""" - this.VerifyFirstParameterInfoColonContent(fileContent,"(*Mark*)",": unit") - - [] - member public this.``Regression.MethodInfo.WithColon.Bug4518_4``() = - let fileContent = """ - type T() = - member this.Foo(a,b) = "" - let t = new T() - t.Foo((*Mark*)""" - this.VerifyFirstParameterInfoColonContent(fileContent,"(*Mark*)",": string") - - [] - member public this.``Regression.MethodInfo.WithColon.Bug4518_5``() = - let fileContent = """ - let f x y = x + y - f((*Mark*)""" - this.VerifyFirstParameterInfoColonContent(fileContent,"(*Mark*)",": (int -> int) ") - - [] - member public this.``Regression.StaticVsInstance.Bug3626.Case1``() = - let fileContent = """ - type Foo() = - member this.Bar(instanceReturnsString:int) = "hllo" - static member Bar(staticReturnsInt:int) = 13 - let z = Foo.Bar((*Mark*))""" - this.VerifyParameterInfoAtStartOfMarker(fileContent,"(*Mark*)",[["staticReturnsInt"]]) - - [] - member public this.``Regression.StaticVsInstance.Bug3626.Case2``() = - let fileContent = """ - type Foo() = - member this.Bar(instanceReturnsString:int) = "hllo" - static member Bar(staticReturnsInt:int) = 13 - let Hoo = new Foo() - let y = Hoo.Bar((*Mark*)""" - this.VerifyParameterInfoAtStartOfMarker(fileContent,"(*Mark*)",[["instanceReturnsString"]]) - - [] - member public this.``Regression.MethodInfo.Bug808310``() = - let fileContent = """System.Console.WriteLine((*Mark*)""" - let methodGroup = this.GetMethodListForAMethodTip(fileContent,"(*Mark*)") - Assert.True(methodGroup.IsSome, "Expected a method group") - let methodGroup = methodGroup.Value - - let description = methodGroup.GetDescription(0) - // Make sure that System.Console.WriteLine is not mentioned anywhere exception in the XML comment signature - let xmlCommentIndex = description.IndexOf("System.Console.WriteLine]") - let noBracket = description.IndexOf("System.Console.WriteLine") - Assert.True(noBracket>=0) - Assert.Equal(noBracket, xmlCommentIndex) - - [] - member public this.``NoArguments``() = - // we want to see e.g. - // g() : int - // and not - // g(unit) : int - let fileContents = """ - type T = - static member F() = 42 - static member G(x:unit) = 42 - - let r1 = T.F((*1*)) - let r2 = T.G((*2*)) - - let g() = 42 - let h((x:unit)) = 42 - let r3 = h((*3*)) - let r4 = g((*4*))""" - this.VerifyParameterCount(fileContents,"(*1*)", 0) - this.VerifyParameterCount(fileContents,"(*2*)", 0) - this.VerifyParameterCount(fileContents,"(*3*)", 0) - this.VerifyParameterCount(fileContents,"(*4*)", 0) - - [] - member public this.``Single.Constructor1``() = - let fileContent = """new System.DateTime((*Mark*)""" - this.VerifyHasParameterInfo(fileContent, "(*Mark*)") - - [] - member public this.``Single.Constructor2``() = - let fileContent = """ - open System - new DateTime((*Mark*)""" - this.VerifyHasParameterInfo(fileContent, "(*Mark*)") - - [] - member public this.``Single.DotNet.StaticMethod``() = - let code = [ "System.Object.ReferenceEquals(" ] - let (_, _, file) = this.CreateSingleFileProject(code) - let gpatcc = GlobalParseAndTypeCheckCounter.StartNew(this.VS) - MoveCursorToEndOfMarker(file,"Object.ReferenceEquals(") - let methodGroup = GetParameterInfoAtCursor file - AssertMethodGroup(methodGroup, [["objA"; "objB"]]) - gpatcc.AssertExactly(0,0) - - [] - member public this.``Regression.NoParameterInfo.100I.Bug5038``() = - let fileContent = """100I((*Mark*)""" - this.VerifyNoParameterInfoAtStartOfMarker(fileContent,"(*Mark*)") - - [] - member public this.``Single.DotNet.InstanceMethod``() = - let fileContent = """ - let s = "Hello" - s.Substring((*Mark*)""" - this.VerifyParameterInfoAtStartOfMarker(fileContent,"(*Mark*)",[["startIndex"]; ["startIndex"; "length"]]) - - [] - member public this.``Single.BasicFSharpFunction``() = - let fileContent = """ - let foo(x) = 1 - foo((*Mark*)""" - this.VerifyParameterInfoAtStartOfMarker(fileContent,"(*Mark*)",[["'a"]]) - - // [] disabled for F#8, legacy service, covered in FCS tests instead - member public this.``Single.DiscriminatedUnion.Construction``() = - let fileContent = """ - type MyDU = - | Case1 of int * string - | Case2 of V1 : int * string * V3 : bool - | Case3 of ``Long Name`` : int * Item2 : string - | Case4 of int - - let x1 = Case1((*Mark1*) - let x2 = Case2((*Mark2*) - let x3 = Case3((*Mark3*) - let x4 = Case4((*Mark4*) - """ - - this.VerifyParameterInfoAtStartOfMarker(fileContent,"(*Mark1*)",[["int"; "string"]]) - this.VerifyParameterInfoAtStartOfMarker(fileContent,"(*Mark2*)",[["V1: int"; "string"; "V3: bool"]]) - this.VerifyParameterInfoAtStartOfMarker(fileContent,"(*Mark3*)",[["``Long Name`` : int"; "string"]]) - this.VerifyParameterInfoAtStartOfMarker(fileContent,"(*Mark4*)",[["int"]]) - - // [] disabled for F#8, legacy service, covered in FCS tests instead - member public this.``Single.Exception.Construction``() = - let fileContent = """ - exception E1 of int * string - exception E2 of V1 : int * string * V3 : bool - exception E3 of ``Long Name`` : int * Data1 : string - - let x1 = E1((*Mark1*) - let x2 = E2((*Mark2*) - let x3 = E3((*Mark3*) - """ - - this.VerifyParameterInfoAtStartOfMarker(fileContent,"(*Mark1*)",[["int"; "string"]]) - this.VerifyParameterInfoAtStartOfMarker(fileContent,"(*Mark2*)",[["V1: int"; "string"; "V3: bool" ]]) - this.VerifyParameterInfoAtStartOfMarker(fileContent,"(*Mark3*)",[["``Long Name`` : int"; "string" ]]) - - [] - //This test verifies that ParamInfo on a provided type that exposes one (static) method that takes one argument works normally. - member public this.``TypeProvider.StaticMethodWithOneParam`` () = - let fileContent = """ - let foo = N1.T1.M1((*Marker*) - """ - this.VerifyParameterInfoAtStartOfMarker(fileContent,"(*Marker*)",[["arg1"]], - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - //This test verifies that ParamInfo on a provided type that exposes a (static) method that takes >1 arguments works normally. - member public this.``TypeProvider.StaticMethodWithMoreParam`` () = - let fileContent = """ - let foo = N1.T1.M2((*Marker*) - """ - this.VerifyParameterInfoAtStartOfMarker(fileContent,"(*Marker*)",[["arg1";"arg2"]], - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - //This test case verify the TypeProvider static method return type or colon content of the method - //This test verifies that ParamInfo on a provided type that exposes one (static) method that takes one argument - //and returns something works correctly (more precisely, it checks that the return type is 'int') - member public this.``TypeProvider.StaticMethodColonContent`` () = - let fileContent = """ - let foo = N1.T1.M2((*Marker*) - """ - this.VerifyFirstParameterInfoColonContent(fileContent,"(*Marker*)",": int", - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - - [] - //This test verifies that ParamInfo on a provided type that exposes a Constructor that takes no argument works normally. - member public this.``TypeProvider.ConstructorWithNoParam`` () = - let fileContent = """ - let foo = new N1.T1((*Marker*) - """ - this.VerifyParameterInfoOverloadMethodIndex(fileContent,"(*Marker*)",0,[], - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - //This test verifies that ParamInfo on a provided type that exposes a Constructor that takes one argument works normally. - member public this.``TypeProvider.ConstructorWithOneParam`` () = - let fileContent = """ - let foo = new N1.T1((*Marker*) - """ - this.VerifyParameterInfoOverloadMethodIndex(fileContent,"(*Marker*)",1,["arg1"], - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - //This test verifies that ParamInfo on a provided type that exposes a Constructor that takes >1 argument works normally. - member public this.``TypeProvider.ConstructorWithMoreParam`` () = - let fileContent = """ - let foo = new N1.T1((*Marker*) - """ - this.VerifyParameterInfoOverloadMethodIndex(fileContent,"(*Marker*)",2,["arg1";"arg2"], - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - //This test verifies that ParamInfo on a provided type that exposes a static parameter that takes >1 argument works normally. - member public this.``TypeProvider.Type.WhenOpeningBracket`` () = - let fileContent = """ - type foo = N1.T<(*Marker*) - """ - this.VerifyParameterInfoAtStartOfMarker(fileContent,"(*Marker*)",[["Param1";"ParamIgnored"]], - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - //This test verifies that after closing bracket ">" the ParamInfo isn't showing on a provided type that exposes a static parameter that takes >1 argument works normally. - //This is a regression test for Bug DevDiv:181000 - member public this.``TypeProvider.Type.AfterCloseBracket`` () = - let fileContent = """ - type foo = N1.T< "Hello", 2>(*Marker*) - """ - this.VerifyNoParameterInfoAtStartOfMarker(fileContent,"(*Marker*)", - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - //This test verifies that ParamInfo is showing after delimiter "," on a provided type that exposes a static parameter that takes >1 argument works normally. - member public this.``TypeProvider.Type.AfterDelimiter`` () = - let fileContent = """ - type foo = N1.T<"Hello",(*Marker*) - """ - this.VerifyParameterInfoContainedAtStartOfMarker(fileContent,"(*Marker*)",["Param1";"ParamIgnored"], - [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - - [] - member public this.``Single.InMatchClause``() = - let v461 = Version(4,6,1) - let fileContent = """ - let rec f l = - match l with - | [] -> System.String.Format((*Mark*) - | x :: xs -> f xs""" - // Note, 3 of these 8 are only available on .NET 4.6.1. On .NET 4.5 only 5 overloads are returned. - let expected = [["format"; "arg0"]; //Net4.5 - ["format"; "args"]; //Net4.5 - ["provider"; "format"; "args"]; //Net4.5 - ["format"; "arg0"; "arg1"]; //Net4.5 - ["format"; "arg0"; "arg1"; "arg2"]; //Net4.5 - ["provider"; "format"; "arg0"]; //Net4.6.1 - ["provider"; "format"; "arg0"; "arg1"]; //Net4.6.1 - ["provider"; "format"; "arg0"; "arg1"; "arg2"]] //Net4.6.1 - - this.VerifyParameterInfoAtStartOfMarker(fileContent,"(*Mark*)", expected) - - (* --- Parameter Info Systematic Tests ------------------------------------------------- *) - - member public this.TestSystematicParameterInfo (marker, methReq, ?startOfMarker) = - let code = - ["let arr = " - " seq { for c = 'a' to 'z' do yield c }" - " |> Seq.map ( fun c ->" - " async { let x = c.ToString() in" - " return System.String.Format(\"[{0}] for [{1}]\"(*loc-1*), x.ToUpperInvariant()(*loc-2*), c) })" - " |> Async.Parallel" - " |> Async.RunSynchronously" - - "let (alist: System.Collections.ArrayList) = System.Collections.ArrayList(2)" - "alist.[0] |> ignore" - "<@@ let x = 1 in x(*loc-8*) @@>" - - "type FunkyType =" - " private (*loc-4*)new() = {}" - " static member ConvertToInt32 (s : string) =" - " let mutable n = 0 in" - " let parseRes = System.Int32.TryParse(s, &n) in" - " if not parseRes then" - " raise (new System.ArgumentException(\"incorrect number format\"))" - " n" - - "type Fruit = | Apple | Banana" - "type KeyValuePair = { Key : int; Value : float }" - "let print (x : Fruit, kvp : KeyValuePair) = System.Console.WriteLine(x); System.Console.WriteLine(kvp)" - "print ((*loc-9*)Banana, {Key = 0; Value = 0.0})" - - "type Emp = " - " []" - " static val mutable private m_ID : int" - " static member private NextID () = Emp.m_ID <- Emp.m_ID + 1; Emp.m_ID" - " val mutable private m_EmpID : int" - " val mutable private m_Name : string" - " val mutable private m_Salary : float" - " val mutable private m_DoB : System.DateTime" - " (*loc-5*)" - - " // Overloaded Constructors" - " public new() =" - " { m_EmpID = Emp.NextID();" - " m_Name = System.String.Empty;" - " m_Salary = 0.0;" - " m_DoB = System.DateTime.Today }" - - " public new(name, salary, dob) as self = " - " new Emp() then" - " self.m_Name <- name" - " self.m_Salary <- salary" - " self.m_DoB <- dob" - - " public new(name, dob) =" - " new (*loc-3*)Emp(name, 0.0, dob)" - - " // Overloaded methods" - " member this.IncreaseBy(amount : float ) = this.m_Salary <- this.m_Salary + amount" - " member this.IncreaseBy(amount : int ) = this.IncreaseBy(float(amount))" - " member this.IncreaseBy(amount : float32) = this.IncreaseBy(float(amount))" - - "let ``Random Number Generator`` = System.Random()" - "let ``?Max!Value?`` = 100" - "let swap (a, b) = (b, a)" - - "[ \"Kevin\", System.DateTime.Today.AddYears(-25); \"John\", new System.DateTime(1980, 1, 1) ]" - "|> List.map ( fun a -> let pair = swap a in Emp(dob = fst pair, name = snd pair) )" - "|> List.iter ( fun a -> a.IncreaseBy(``Random Number Generator``.Next((*loc-7*)``?Max!Value?``)) )" - - "System.Console.ReadLine(" - ] - let (_, _, file) = this.CreateSingleFileProject(code) - match startOfMarker with - | Some(start) when start = true - -> MoveCursorToStartOfMarker(file, marker) - | _ -> MoveCursorToEndOfMarker(file, marker) - - let methodGroup = GetParameterInfoAtCursor file - if (methReq = []) then - Assert.True(methodGroup.IsNone, "Expected no method group") - else - AssertMethodGroup(methodGroup, methReq) - // Test on .NET functions with no parameter - [] - member public this.``Single.DotNet.NoParameters`` () = - this.TestSystematicParameterInfo("x.ToUpperInvariant(", [ [] ]) - - // Test on .NET function with one parameter - [] - member public this.``Single.DotNet.OneParameter`` () = - this.TestSystematicParameterInfo("System.DateTime.Today.AddYears(", [ ["value: int"] ] ) - - // Test appearance of PI on second parameter of .NET function - [] - member public this.``Single.DotNet.OnSecondParameter`` () = - this.TestSystematicParameterInfo("loc-1*),", [ ["format"; "args"]; - ["format"; "arg0"]; - ["provider"; "format"; "args"]; - ["format"; "arg0"; "arg1"]; - ["format"; "arg0"; "arg1"; "arg2"] ] ) - // Test on .NET functions with parameter array - [] - member public this.``Single.DotNet.ParameterArray`` () = - this.TestSystematicParameterInfo("loc-2*),", [ ["format"; "args"]; - ["format"; "arg0"]; - ["provider"; "format"; "args"]; - ["format"; "arg0"; "arg1"]; - ["format"; "arg0"; "arg1"; "arg2"] ] ) - // Test on .NET indexers - [] - member public this.``Single.DotNet.IndexerParameter`` () = - this.TestSystematicParameterInfo("alist.[", [ ["index: int"] ] ) - - // Test on .NET parameters passed with 'out' keyword (byref) - [] - member public this.``Single.DotNet.ParameterByReference`` () = - this.TestSystematicParameterInfo("Int32.TryParse(s,", [ ["s: string"; "result: int byref"]; ["s"; "style"; "provider"; "result"] ] ) - - // Test on reference type and value type parameters (e.g. string & DateTime) - [] - member public this.``Single.DotNet.RefTypeValueType`` () = - this.TestSystematicParameterInfo("loc-3*)Emp(", [ []; - ["name: string"; "dob: System.DateTime"]; - ["name: string"; "salary: float"; "dob: System.DateTime"] ] ) - - // Test PI does not pop up at point of definition/declaration - [] - member public this.``Single.Locations.PointOfDefinition`` () = - this.TestSystematicParameterInfo("loc-4*)new(", [ ] ) - this.TestSystematicParameterInfo("member ConvertToInt32 (", [ ] ) - this.TestSystematicParameterInfo("member this.IncreaseBy(", [ ] ) - - // Test PI does not pop up on whitespace after type annotation - [] - member public this.``Single.Locations.AfterTypeAnnotation`` () = - this.TestSystematicParameterInfo("(*loc-5*)", [], true) - - - // Test PI does not pop up after non-parameterized properties - [] - member public this.``Single.Locations.AfterProperties`` () = - this.TestSystematicParameterInfo("System.DateTime.Today", []) - //this.TestSystematicParameterInfo("(*loc-8*)", [], true) - - // Test PI does not pop up after non-function values - [] - member public this.``Single.Locations.AfterValues`` () = - this.TestSystematicParameterInfo("(*loc-8*)", [], true) - - // Test PI does not pop up after non-parameterized properties and after values - [] - member public this.``Single.Locations.EndOfFile`` () = - this.TestSystematicParameterInfo("System.Console.ReadLine(", [ [] ]) - - // Test PI pop up on parameter list for attributes - [] - member public this.``Single.OnAttributes`` () = - this.TestSystematicParameterInfo("(*loc-6*)", [ []; [ "check: bool" ] ], true) - - // Test PI when quoted identifiers are used as parameter - [] - member public this.``Single.QuotedIdentifier`` () = - this.TestSystematicParameterInfo("(*loc-7*)", [ []; [ "maxValue" ]; [ "minValue"; "maxValue" ] ], true) - - // Test PI with parameters of custom type - [] - member public this.``Single.RecordAndUnionType`` () = - this.TestSystematicParameterInfo("(*loc-9*)", [ [ "Fruit"; "KeyValuePair" ] ], true) - - (* --- End Of Parameter Info Systematic Tests ------------------------------------------ *) - -(* Tests for Generic parameterinfos -------------------------------------------------------- *) - member private this.TestGenericParameterInfo (testLine, methReq) = let code = [ "open System"; "open System.Threading"; ""; testLine ] let (_, _, file) = this.CreateSingleFileProject(code) @@ -605,55 +124,6 @@ type UsingMSBuild() = else AssertMethodGroup(methodGroup, methReq) - [] - member public this.``Single.Generics.Typeof``() = - this.TestGenericParameterInfo("typeof(", []) - - [] - member public this.``Single.Generics.MathAbs``() = - let sevenTimes l = [ l; l; l; l; l; l; l ] - this.TestGenericParameterInfo("Math.Abs(", sevenTimes ["value"]) - - [] - member public this.``Single.Generics.ExchangeInt``() = - let sevenTimes l = [ l; l; l; l; l; l; l ] - this.TestGenericParameterInfo("Interlocked.Exchange(", sevenTimes ["location1"; "value"]) - - [] - member public this.``Single.Generics.Exchange``() = - let sevenTimes l = [ l; l; l; l; l; l; l ] - this.TestGenericParameterInfo("Interlocked.Exchange(", sevenTimes ["location1"; "value"]) - - [] - member public this.``Single.Generics.ExchangeUnder``() = - let sevenTimes l = [ l; l; l; l; l; l; l ] - this.TestGenericParameterInfo("Interlocked.Exchange<_> (", sevenTimes ["location1"; "value"]) - - [] - member public this.``Single.Generics.Dictionary``() = - this.TestGenericParameterInfo("System.Collections.Generic.Dictionary<_, option>(", [ []; ["capacity"]; ["comparer"]; ["capacity"; "comparer"]; ["dictionary"]; ["dictionary"; "comparer"] ]) - - [] - member public this.``Single.Generics.List``() = - this.TestGenericParameterInfo("new System.Collections.Generic.List< _ > ( ", [ []; ["capacity"]; ["collection"] ]) - - [] - member public this.``Single.Generics.ListInt``() = - this.TestGenericParameterInfo("System.Collections.Generic.List(", [ []; ["capacity"]; ["collection"] ]) - - [] - member public this.``Single.Generics.EventHandler``() = - this.TestGenericParameterInfo("new System.EventHandler( ", [ [""] ]) // function arg doesn't have a name - - [] - member public this.``Single.Generics.EventHandlerEventArgs``() = - this.TestGenericParameterInfo("System.EventHandler(", [ [""] ]) // function arg doesn't have a name - - [] - member public this.``Single.Generics.EventHandlerEventArgsNew``() = - this.TestGenericParameterInfo("new System.EventHandler ( ", [ [""] ]) // function arg doesn't have a name - - // Split into multiple lines using "\n" and find the index of "$" (and remove it from the text) member private this.ExtractLineInfo (line:string) = let idx, lines, foundDollar = line.Split([| '\r'; '\n' |], StringSplitOptions.RemoveEmptyEntries) |> List.ofArray |> List.foldBack (fun l (idx, lines, foundDollar) -> let i = l.IndexOf("$") @@ -700,141 +170,12 @@ type UsingMSBuild() = member public this.``Single.Locations.Simple``() = this.TestParameterInfoLocation("let a = System.Math.Sin($", 8) - [] - member public this.``Single.Locations.LineWithSpaces``() = - this.TestParameterInfoLocation("let r =\n"+ - " System.Math.Abs($0)", 3) // on the beginning of "System", not line! - - [] - member public this.``Single.Locations.FullCall``() = - this.TestParameterInfoLocation("System.Math.Abs($0)", 0) - - [] - member public this.``Single.Locations.SpacesAfterParen``() = - this.TestParameterInfoLocation("let a = Math.Sign( $-10 )", 8) - - [] - member public this.``Single.Locations.WithNamespace``() = - this.TestParameterInfoLocation("let a = System.Threading.Interlocked.Exchange($", 8) - - [] - member public this.``ParameterInfo.Locations.WithoutNamespace``() = - this.TestParameterInfoLocation("let a = Interlocked.Exchange($", 8) - - [] - member public this.``Single.Locations.WithGenericArgs``() = - this.TestParameterInfoLocation("Interlocked.Exchange($", 0) - - [] - member public this.``Single.Locations.FunctionWithSpace``() = - this.TestParameterInfoLocation("let a = sin 0$.0", 8) - - [] - member public this.``Single.Locations.MethodCallWithoutParens``() = - this.TestParameterInfoLocation("let n = Math.Sin 1$0.0", 8) - - [] - member public this.``Single.Locations.GenericCtorWithNamespace``() = - this.TestParameterInfoLocation("let _ = new System.Collections.Generic.Dictionary<_, _>($)", 12) // on the beginning of "System" (not on "new") - - [] - member public this.``Single.Locations.GenericCtor``() = - this.TestParameterInfoLocation("let _ = new Dictionary<_, _>($)", 12) // on the beginning of "System" (not on "new") - - [] //This test verifies that ParamInfo location on a provided type with namespace that exposes static parameter that takes >1 argument works normally. - member public this.``TypeProvider.Type.ParameterInfoLocation.WithNamespace`` () = - this.TestParameterInfoLocation("type boo = N1.T<$",11, - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] //This test verifies that ParamInfo location on a provided type without the namespace that exposes static parameter that takes >1 argument works normally. - member public this.``TypeProvider.Type.ParameterInfoLocation.WithOutNamespace`` () = - this.TestParameterInfoLocation("open N1 \n"+"type boo = T<$", - expectedPos = 11, - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] //This test verifies that no ParamInfo in a string for a provided type that exposes static parameter that takes >1 argument works normally. //The intent here to make sure the ParamInfo is not shown when inside a string - member public this.``TypeProvider.Type.Negative.InString`` () = - this.TestParameterInfoNegative("type boo = \"N1.T<$\"", - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] //This test verifies that no ParamInfo in a Comment for a provided type that exposes static parameter that takes >1 argument works normally. //The intent here to make sure the ParamInfo is not shown when inside a comment - member public this.``TypeProvider.Type.Negative.InComment`` () = - this.TestParameterInfoNegative("// type boo = N1.T<$", - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - - // Following are tricky: - // if we can't find end of the identifier on the current line, - // we *must* look at the previous line to find the location where NameRes info ends - // so in these cases we can find the identifier and location of tooltip is beginning of it - // (but in general, we don't search for it) - [] - member public this.``Single.Locations.Multiline.IdentOnPrevLineWithGenerics``() = - this.TestParameterInfoLocation("let d = Dictionary<_, option< int >> \n" + - " ( $ )", 8) // on the "D" (line untestable) - - [] - member public this.``Single.Locations.Multiline.IdentOnPrevLine``() = - this.TestParameterInfoLocation("do Console.WriteLine\n" + - " ($\"Multiline\")", 3) - [] - member public this.``Single.Locations.Multiline.IdentOnPrevPrevLine``() = - this.TestParameterInfoLocation("do Console.WriteLine\n" + - " ( \n" + - " $ \"Multiline\")", 3) - - [] - member public this.``Single.Locations.GenericCtorWithoutNew``() = - this.TestParameterInfoLocation("let d = System.Collections.Generic.Dictionary<_, option< int >> ( $ )", 8) // on "S" - standard - - [] - member public this.``Single.Locations.Multiline.GenericTyargsOnTheSameLine``() = - this.TestParameterInfoLocation("let dict3 = System.Collections.Generic.Dictionary<_, \n" + - " option< int>>( $ )", 12) // on "S" (beginning of "System") - [] - member public this.``Single.Locations.Multiline.LongIdentSplit``() = - this.TestParameterInfoLocation("let ll = new System.Collections.\n" + - " Generic.List< _ > ($)", 13) // on "S" (beginning of "System") - - [] - member public this.``Single.Locations.OperatorTrick3``() = - this.TestParameterInfoLocation - ("let mutable n = null\n" + - "let aaa = Interlocked.Exchange(&n$, new obj())", 10) // "I" of Interlocked - - // A several cases that are tricky and we don't want to show anything - // in the following cases, we may return a location of an operator (its ambiguous), but we don't want to show info about it! - - [] - member public this.``Single.Negative.OperatorTrick1``() = - this.TestParameterInfoNegative - ("let fooo = 0\n" + - " >($ 1 )") // this may be end of a generic args specification - - [] - member public this.``Single.Negative.OperatorTrick2``() = - this.TestParameterInfoNegative - ("let fooo = 0\n" + - " <($ 1 )") - - /// No intellisense in comments/strings! - [] - member public this.``Single.InString``() = - this.TestParameterInfoNegative - ("let s = \"System.Console.WriteLine($)\"") - - /// No intellisense in comments/strings! - [] - member public this.``Single.InComment``() = - this.TestParameterInfoNegative - ("// System.Console.WriteLine($)") - [] member this.``Regression.LocationOfParams.AfterQuicklyTyping.Bug91373``() = let code = [ "let f x = x " @@ -909,28 +250,6 @@ We really need to rewrite some code paths here to use the real parse tree rather AssertEqual([|(1,14);(1,21);(1,21);(4,0)|], info.GetParameterLocations()) *) - [] - member public this.``ParameterInfo.NamesOfParams``() = - let testLines = [ - "type Foo =" - " static member F(a:int, b:bool, c:int, d:int, ?e:int) = ()" - "let a = 42" - "Foo.F(0,(a=42),d=3,?e=Some 4,c=2)" - "// names are _,_,d,e,c" ] - let (_, _, file) = this.CreateSingleFileProject(testLines) - MoveCursorToStartOfMarker(file, "0") - let info = GetParameterInfoAtCursor file - Assert.True(info.IsSome, "expected parameter info") - let info = info.Value - let names = info.GetParameterNames() - AssertEqual([| null; null; "d"; "e"; "c" |], names) - - // $ is the location of the cursor/caret - // ^ marks all of these expected points: - // - start of the long id that is the method call containing the caret - // - end of the long id that is the method call containing the caret - // - open paren of the method call (or first char of arg expression if no open paren) - // - for every param, end of expr that is the param (or closeparen if no params (unit)) member public this.TestParameterInfoLocationOfParams (testLine, ?markAtEOF, ?additionalReferenceAssemblies) = let cursorPrefix, testLines = this.ExtractLineInfo testLine let testLinesAndLocs = testLines |> List.mapi (fun i s -> @@ -977,305 +296,6 @@ We really need to rewrite some code paths here to use the real parse tree rather let info = GetParameterInfoAtCursor file Assert.True(info.IsNone, "expected no parameter info for this particular test, though it would be nice if this has started to work") - [] - member public this.``LocationOfParams.Case1``() = - this.TestParameterInfoLocationOfParams("""^System.Console.WriteLine^(^"hel$lo"^)""") - - [] - member public this.``LocationOfParams.Case2``() = - this.TestParameterInfoLocationOfParams("""^System.Console.WriteLine^ (^ "hel$lo {0}" ,^ "Brian" ^)""") - - [] - member public this.``LocationOfParams.Case3``() = - this.TestParameterInfoLocationOfParams( - """^System.Console.WriteLine^ - (^ - "hel$lo {0}" ,^ - "Brian" ^) """) - - [] - member public this.``LocationOfParams.Case4``() = - this.TestParameterInfoLocationOfParams("""^System.Console.WriteLine^ (^ "hello {0}" ,^ ("tuples","don't $ confuse it") ^)""") - - [] - member public this.``ParameterInfo.LocationOfParams.Bug112688``() = - let testLines = [ - "let f x y = ()" - "module MailboxProcessorBasicTests =" - " do f 0" - " 0" - " let zz = 42" - " for timeout in [0; 10] do" - " ()" ] - let (_,_, file) = this.CreateSingleFileProject(testLines) - MoveCursorToStartOfMarker(file, "let zz") - // in the bug, this caused an assert to fire - let info = GetParameterInfoAtCursor file - () - - [] - member public this.``ParameterInfo.LocationOfParams.Bug112340``() = - let testLines = [ - """let a = typeof] - member public this.``Regression.LocationOfParams.Bug91479``() = - this.TestParameterInfoLocationOfParams("""let z = fun x -> x + ^System.Int16.Parse^(^$ """, markAtEOF=true) - - [] - member public this.``LocationOfParams.Attributes.Bug230393``() = - this.TestParameterInfoLocationOfParams(""" - let paramTest((strA : string),(strB : string)) = - strA + strB - ^paramTest^(^ $ - - [<^Measure>] - type RMB - """) - - [] - member public this.``LocationOfParams.InfixOperators.Case1``() = - // infix operators like '+' do not give their own param info - this.TestParameterInfoLocationOfParams("""^System.Console.WriteLine^(^"" + "$"^)""") - - [] - member public this.``LocationOfParams.InfixOperators.Case2``() = - // infix operators like '+' do give param info when used as prefix ops - this.TestParameterInfoLocationOfParams("""System.Console.WriteLine((^+^)(^$3^)(4))""") - - [] - member public this.``LocationOfParams.GenericMethodExplicitTypeArgs()``() = - this.TestParameterInfoLocationOfParams(""" - type T<'a> = - static member M(x:int, y:string) = x + y.Length - let x = ^T.M^(^1,^ $"test"^) """) - - [] - member public this.``LocationOfParams.InsideAMemberOfAType``() = - this.TestParameterInfoLocationOfParams(""" - type Widget(z) = - member x.a = (1 <> ^System.Int32.Parse^(^"$"^)) """) - - [] - member public this.``LocationOfParams.InsidePropertyGettersAndSetters.Case1``() = - this.TestParameterInfoLocationOfParams(""" - type Widget(z) = - member x.P1 - with get() = ^System.Int32.Parse^(^"$"^) - and set(z) = System.Int32.Parse("") |> ignore - member x.P2 with get() = System.Int32.Parse("") - member x.P2 with set(z) = System.Int32.Parse("") |> ignore """) - - [] - member public this.``LocationOfParams.InsidePropertyGettersAndSetters.Case2``() = - this.TestParameterInfoLocationOfParams(""" - type Widget(z) = - member x.P1 - with get() = System.Int32.Parse("") - and set(z) = ^System.Int32.Parse^(^"$"^) |> ignore - member x.P2 with get() = System.Int32.Parse("") - member x.P2 with set(z) = System.Int32.Parse("") |> ignore """) - - [] - member public this.``LocationOfParams.InsidePropertyGettersAndSetters.Case3``() = - this.TestParameterInfoLocationOfParams(""" - type Widget(z) = - member x.P1 - with get() = System.Int32.Parse("") - and set(z) = System.Int32.Parse("") |> ignore - member x.P2 with get() = ^System.Int32.Parse^(^"$"^) - member x.P2 with set(z) = System.Int32.Parse("") |> ignore """) - - [] - member public this.``LocationOfParams.InsidePropertyGettersAndSetters.Case4``() = - this.TestParameterInfoLocationOfParams(""" - type Widget(z) = - member x.P1 - with get() = System.Int32.Parse("") - and set(z) = System.Int32.Parse("") |> ignore - member x.P2 with get() = System.Int32.Parse("") - member x.P2 with set(z) = ^System.Int32.Parse^(^"$"^) |> ignore """) - - [] - member public this.``LocationOfParams.InsideObjectExpression``() = - this.TestParameterInfoLocationOfParams(""" - let _ = { new ^System.Object^(^$^) with member _.GetHashCode() = 2}""") - - [] - member public this.``LocationOfParams.Nested1``() = - this.TestParameterInfoLocationOfParams("""System.Console.WriteLine("hello {0}" , ^sin^ (^4$2.0 ^) )""") - - - [] - member public this.``LocationOfParams.MatchGuard``() = - this.TestParameterInfoLocationOfParams("""match [1] with | [x] when ^box^(^$x^) <> null -> ()""") - - [] - member public this.``LocationOfParams.Nested2``() = - this.TestParameterInfoLocationOfParams("""System.Console.WriteLine("hello {0}" , ^sin^ 4^$2.0^ )""") - - [] - member public this.``LocationOfParams.Generics1``() = - this.TestParameterInfoLocationOfParams(""" - let f<'T,'U>(x:'T, y:'U) = (y,x) - let r = ^f^(^4$2,^""^)""") - - [] - member public this.``LocationOfParams.Generics2``() = - this.TestParameterInfoLocationOfParams("""let x = ^System.Collections.Generic.Dictionary^(^42,^n$ull^)""") - - [] - member public this.``LocationOfParams.Unions1``() = - this.TestParameterInfoLocationOfParams(""" - type MyDU = - | FOO of int * string - let r = ^FOO^(^42,^"$"^) """) - - [] - member public this.``LocationOfParams.EvenWhenOverloadResolutionFails.Case1``() = - this.TestParameterInfoLocationOfParams("""let a = new ^System.IO.FileStream^(^$^)""") - - [] - member public this.``LocationOfParams.EvenWhenOverloadResolutionFails.Case2``() = - this.TestParameterInfoLocationOfParams(""" - open System.Collections.Generic - open System.Linq - let l = List([||]) - ^l.Aggregate^(^$^) // was once a bug""") - - [] - member public this.``LocationOfParams.BY_DESIGN.WayThatMismatchedParensFailOver.Case1``() = - // when only one 'statement' after the mismatched parens after a comma, the comma swallows it and it becomes a badly-indented - // continuation of the expression from the previous line - this.TestParameterInfoLocationOfParams(""" - type CC() = - member this.M(a,b,c,d) = a+b+c+d - let c = new CC() - ^c.M^(^1,^2,^3,^ $ - c.M(1,2,3,4)""", markAtEOF=true) - - [] - member public this.``LocationOfParams.BY_DESIGN.WayThatMismatchedParensFailOver.Case2``() = - // when multiple 'statements' after the mismatched parens after a comma, the parser sees a single argument to the method that - // is a statement sequence, e.g. a bunch of discarded expressions. That is, - // c.M(1,2,3, - // c.M(1,2,3,4) - // c.M(1,2,3,4) - // c.M(1,2,3,4) - // is like - // c.M(let r = 1,2,3, - // c.M(1,2,3,4) - // c.M(1,2,3,4) - // c.M(1,2,3,4) - // in r) - this.TestParameterInfoLocationOfParams(""" - type CC() = - member this.M(a,b,c,d) = a+b+c+d - let c = new CC() - ^c.M^(^1,2,3, $ - c.M(1,2,3,4) - c.M(1,2,3,4) - c.M(1,2,3,4)""", markAtEOF=true) - - [] - member public this.``LocationOfParams.Tuples.Bug91360.Case1``() = - this.TestParameterInfoLocationOfParams(""" - ^System.Console.WriteLine^(^ (4$2,43) ^) // oops""") - - [] - member public this.``LocationOfParams.Tuples.Bug91360.Case2``() = - this.TestParameterInfoLocationOfParams(""" - ^System.Console.WriteLine^(^ $(42,43) ^) // oops""") - - [] - member public this.``LocationOfParams.Tuples.Bug123219``() = - this.TestParameterInfoLocationOfParams(""" - type Expr = | Num of int - type T<'a>() = - member this.M1(a:int*string, b:'a -> unit) = () - let x = new T() - - ^x.M1^(^(1,$ """, markAtEOF=true) - - [] - member public this.``LocationOfParams.UnmatchedParens.Bug91609.OtherCases.Open``() = - this.TestParameterInfoLocationOfParams(""" - let arr = Array.create 4 1 - arr.[1] <- ^System.Int32.Parse^(^$ - open^ System""") - - [] - member public this.``LocationOfParams.UnmatchedParens.Bug91609.OtherCases.Module``() = - this.TestParameterInfoLocationOfParams(""" - let arr = Array.create 4 1 - arr.[1] <- ^System.Int32.Parse^(^$ - ^module Foo = - let x = 42""") - - [] - member public this.``LocationOfParams.UnmatchedParens.Bug91609.OtherCases.Namespace``() = - this.TestParameterInfoLocationOfParams(""" - namespace Foo - module Bar = - let arr = Array.create 4 1 - arr.[1] <- ^System.Int32.Parse^(^$ - namespace^ Other""") - - [] - member this.``LocationOfParams.InheritsClause.Bug192134``() = - this.TestParameterInfoLocationOfParams(""" - type B(x : int) = - new(x1:int, x2: int) = new B(10) - type A() = - inherit ^B^(^1$,^2^)""") - - [] - member public this.``LocationOfParams.ThisOnceAsserted``() = - this.TestNoParameterInfo(""" - module CSVTypeProvider - - f(fun x -> - match args with - | [| y |] -> - for name, kind in (headerNames, - rowType.AddMember(new ^ProvidedProperty^(^$ - null - | _ -> failwith "unexpected generic params" ) - - let rec emitRegKeyNamedType (container:TypeContainer) (typeName:string) (key:RegistryKey) = - let keyType = 0 - keyType - - match types |> Array.tryFind (fun ty -> ty.Name = typeName^) with _ -> ()""") - - [] - member public this.``LocationOfParams.ThisOnceAssertedToo``() = - this.TestNoParameterInfo(""" - let readString() = - let x = 42 - while ('"' = '""' then - () - else - let sb = new System.Text.StringBuilder() - while true do - ($) """) - - [] - member public this.``LocationOfParams.UnmatchedParensBeforeModuleKeyword.Bug245850.Case2a``() = - this.TestParameterInfoLocationOfParams(""" - module Repro = - query { for a in ^System.Int16.TryParse^(^$ - ^module AA = - let x = 10 """) - - (* Tests for type provider static argument parameterinfos ------------------------------------------ *) - member public this.TestParameterInfoLocationOfParamsWithVariousSurroundingContexts (testLine:string, ?markAtEnd, ?additionalReferenceAssemblies) = let numSpacesOfIndent = let lines = testLine.Split[|'\n'|] @@ -1319,700 +339,3 @@ We really need to rewrite some code paths here to use the real parse tree rather printfn "%s" allText this.TestParameterInfoLocationOfParams (allText, markAtEOF=needMarkAtEnd, ?additionalReferenceAssemblies=additionalReferenceAssemblies) ) - - [] - member public this.``LocationOfParams.TypeProviders.Basic``() = - this.TestParameterInfoLocationOfParamsWithVariousSurroundingContexts(""" - type U = ^N1.T^<^ "fo$o",^ 42 ^>""", - additionalReferenceAssemblies = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - member public this.``LocationOfParams.TypeProviders.BasicNamed``() = - this.TestParameterInfoLocationOfParamsWithVariousSurroundingContexts(""" - type U = ^N1.T^<^ "fo$o",^ ParamIgnored=42 ^>""", - additionalReferenceAssemblies = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - - [] - member public this.``LocationOfParams.TypeProviders.Prefix0``() = - this.TestParameterInfoLocationOfParamsWithVariousSurroundingContexts(""" - type U = ^N1.T^<^ $ """, // missing all params, just have < - markAtEnd = true, - additionalReferenceAssemblies = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - member public this.``LocationOfParams.TypeProviders.Prefix1``() = - this.TestParameterInfoLocationOfParamsWithVariousSurroundingContexts(""" - type U = ^N1.T^<^ "fo$o",^ 42 """, // missing > - markAtEnd = true, - additionalReferenceAssemblies = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - member public this.``LocationOfParams.TypeProviders.Prefix1Named``() = - this.TestParameterInfoLocationOfParamsWithVariousSurroundingContexts(""" - type U = ^N1.T^<^ "fo$o",^ ParamIgnored=42 """, // missing > - markAtEnd = true, - additionalReferenceAssemblies = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - member public this.``LocationOfParams.TypeProviders.Prefix2``() = - this.TestParameterInfoLocationOfParamsWithVariousSurroundingContexts(""" - type U = ^N1.T^<^ "fo$o",^ """, // missing last param - markAtEnd = true, - additionalReferenceAssemblies = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - member public this.``LocationOfParams.TypeProviders.Prefix2Named1``() = - this.TestParameterInfoLocationOfParamsWithVariousSurroundingContexts(""" - type U = ^N1.T^<^ "fo$o",^ ParamIgnored= """, // missing last param after name with equals - markAtEnd = true, - additionalReferenceAssemblies = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - member public this.``LocationOfParams.TypeProviders.Prefix2Named2``() = - this.TestParameterInfoLocationOfParamsWithVariousSurroundingContexts(""" - type U = ^N1.T^<^ "fo$o",^ ParamIgnored """, // missing last param after name sans equals - markAtEnd = true, - additionalReferenceAssemblies = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - member public this.``LocationOfParams.TypeProviders.Negative1``() = - this.TestNoParameterInfo(""" - type D = ^System.Collections.Generic.Dictionary^<^ in$t, int ^>""") - - [] - member public this.``LocationOfParams.TypeProviders.Negative2``() = - this.TestNoParameterInfo(""" - type D = ^System.Collections.Generic.List^<^ in$t ^>""") - - [] - member public this.``LocationOfParams.TypeProviders.Negative3``() = - this.TestNoParameterInfo(""" - let i = 42 - let b = ^i^<^ 4$2""") - - [] - member public this.``LocationOfParams.TypeProviders.Negative4.Bug181000``() = - this.TestNoParameterInfo(""" - type U = ^N1.T^<^ "foo",^ 42 ^>$ """, // when the caret is right of the '>', we should not report any param info - additionalReferenceAssemblies = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - member public this.``LocationOfParams.TypeProviders.BasicWithinExpr``() = - this.TestNoParameterInfo(""" - let f() = - let r = id( ^N1.T^<^ "fo$o",^ ParamIgnored=42 ^> ) - r """, - additionalReferenceAssemblies = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - member public this.``LocationOfParams.TypeProviders.BasicWithinExpr.DoesNotInterfereWithOuterFunction``() = - this.TestParameterInfoLocationOfParams(""" - let f() = - let r = ^id^(^ N1.$T< "foo", ParamIgnored=42 > ^) - r """, - additionalReferenceAssemblies = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - member public this.``LocationOfParams.TypeProviders.Bug199744.ExcessCommasShouldNotAssertAndShouldGiveInfo.Case1``() = - this.TestParameterInfoLocationOfParamsWithVariousSurroundingContexts(""" - type U = ^N1.T^<^ "fo$o",^ 42,^ ,^ ^>""", - additionalReferenceAssemblies = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - member public this.``LocationOfParams.TypeProviders.Bug199744.ExcessCommasShouldNotAssertAndShouldGiveInfo.Case2``() = - this.TestParameterInfoLocationOfParamsWithVariousSurroundingContexts(""" - type U = ^N1.T^<^ "fo$o",^ ,^ ^>""", - additionalReferenceAssemblies = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - member public this.``LocationOfParams.TypeProviders.Bug199744.ExcessCommasShouldNotAssertAndShouldGiveInfo.Case3``() = - this.TestParameterInfoLocationOfParamsWithVariousSurroundingContexts(""" - type U = ^N1.T^<^ ,^$ ^>""", - additionalReferenceAssemblies = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - member public this.``LocationOfParams.TypeProviders.StaticParametersAtConstructorCallSite``() = - this.TestParameterInfoLocationOfParamsWithVariousSurroundingContexts(""" - let x = new ^N1.T^<^ "fo$o",^ 42 ^>()""", - additionalReferenceAssemblies = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - member public this.``TypeProvider.FormatOfNamesOfSystemTypes``() = - let code = ["""type TTT = N1.T< "foo", ParamIgnored=42 > """] - let references = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")] - let (_, _, file) = this.CreateSingleFileProject(code, references = references) - let gpatcc = GlobalParseAndTypeCheckCounter.StartNew(this.VS) - MoveCursorToEndOfMarker(file,"foo") - let methodGroup = GetParameterInfoAtCursor file - Assert.True(methodGroup.IsSome, "expected parameter info") - let methodGroup = methodGroup.Value - let actualDisplays = - [ for i = 0 to methodGroup.GetCount() - 1 do - yield [ for j = 0 to methodGroup.GetParameterCount(i) - 1 do - let (name,display,description) = methodGroup.GetParameterInfo(i,j) - yield display ] ] - let expected = [["Param1: string"; "ParamIgnored: int"]] // key here is we want e.g. "int" and not "System.Int32" - AssertEqual(expected, actualDisplays) - gpatcc.AssertExactly(0,0) - - [] - member public this.``ParameterNamesInFunctionsDefinedByLetBindings``() = - let useCases = - [ - """ - let foo (n1 : int) (n2 : int) = n1 + n2 - foo( - """, "foo(", ["n1: int"] - - """ - let foo (n1 : int, n2 : int) = n1 + n2 - foo( - """, "foo(", ["n1: int"; "n2: int"] - - """ - let foo (n1 : int, n2 : int) = n1 + n2 - foo(2, - """, "foo(2,", ["n1: int"; "n2: int"] - - (* Negative tests - display only types*) - """ - let foo = List.map - foo( - """, "foo(", ["'a -> 'b"] - - """ - let foo x = - let bar y = x + y - bar( - """, "bar(", ["int"] - - """ - let f (Some x) = x + 1 - f( - """, "f(", ["int option"] - ] - - for (code, marker, expectedParams) in useCases do - let (_, _, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file, marker) - let methodGroup = GetParameterInfoAtCursor file - - Assert.True(methodGroup.IsSome, "expected parameter info") - let methodGroup = methodGroup.Value - - Assert.Equal(1, methodGroup.GetCount()) - - let expectedParamsCount = List.length expectedParams - Assert.Equal(expectedParamsCount, methodGroup.GetParameterCount(0)) - - let actualParams = [ for i = 0 to (expectedParamsCount - 1) do yield methodGroup.GetParameterInfo(0, i) ] - let ok = - actualParams - |> List.map (fun (_, d, _) -> d) - |> List.forall2 (=) expectedParams - if not ok then - printfn "==Parameters don't match==" - printfn "Expected parameters %A" expectedParams - printfn "Actual parameters %A" actualParams - failwith "Parameters don't match" - - (* Tests for multi-parameterinfos ------------------------------------------------------------------ *) - - [] - member public this.``ParameterInfo.ArgumentsWithParamsArrayAttribute``() = - let content = """let _ = System.String.Format("",(*MARK*))""" - let methodTip = this.GetMethodListForAMethodTip(content, "(*MARK*)") - Assert.True(methodTip.IsSome, "expected parameter info") - let methodTip = methodTip.Value - - let overloadWithTwoParamsOpt = - Seq.init (methodTip.GetCount()) (fun i -> - let count = methodTip.GetParameterCount(i) - let paramInfos = - [ - for c = 0 to (count - 1) do - let name = ref "" - let display = ref "" - let description = ref "" - methodTip.GetParameterInfo(i, c, name, display, description) - yield !name, !display,!description - ] - count, paramInfos - ) - |> Seq.tryFind(fun (i, _) -> i = 2) - match overloadWithTwoParamsOpt with - | Some(_, [_;(_name, display, _description)]) -> Assert.True(display.Contains("[] args")) - | x -> Assert.Fail(sprintf "Expected overload not found, current result %A" x) - - (* DotNet functions for multi-parameterinfo tests -------------------------------------------------- *) - [] - member public this.``Multi.DotNet.StaticMethod``() = - let fileContents = """System.Console.WriteLine("Today is {0:dd MMM yyyy}",(*Mark*)System.DateTime.Today)""" - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Mark*)",["string";"obj"]) - - [] - member public this.``Multi.DotNet.StaticMethod.WithinClassMember``() = - let fileContents = """ - type Widget(z) = - member x.a = (1 <> System.Int32.Parse("",(*Mark*) - - let widget = Widget(1) - 45""" - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Mark*)",["string";"System.Globalization.NumberStyles"]) - - [] - member public this.``Multi.DotNet.StaticMethod.WithinLambda``() = - let fileContents = """let z = fun x -> x + System.Int16.Parse("",(*Mark*)""" - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Mark*)",["string";"System.Globalization.NumberStyles"]) - - [] - member public this.``Multi.DotNet.StaticMethod.WithinLambda2``() = - let fileContents = "let _ = fun file -> new System.IO.FileInfo((*Mark*)" - this.VerifyParameterInfoAtStartOfMarker(fileContents,"(*Mark*)",[["string"]]) - - [] - member public this.``Multi.DotNet.InstanceMethod``() = - let fileContents = """ - let s = "Hello" - s.Substring(0,(*Mark*)""" - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Mark*)",["int";"int"]) - - (* Common functions for multi-parameterinfo tests -------------------------------------------------- *) - [] - member public this.``Multi.DotNet.Constructor``() = - let fileContents = "let _ = new System.DateTime(2010,12,(*Mark*)" - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Mark*)",["int";"int";"int"]) - - [] - member public this.``Multi.Constructor.WithinObjectExpression``() = - let fileContents = "let _ = { new System.Object((*Mark*)) with member _.GetHashCode() = 2}" - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Mark*)",[]) - - [] - member public this.``Multi.Function.InTheClassMember``() = - let fileContents = """ - type Foo() = - let foo1(a : int, b:int) = () - - member this.A() = - foo1(1,(*Mark*) - member this.A(a : string, b:int) = ()""" - this.VerifyParameterInfoAtStartOfMarker(fileContents,"(*Mark*)",[["int";"int"]]) - - [] - member public this.``Multi.ParamAsTupleType``() = - let fileContents = """ - let tuple((a : int, b : int), c : int) = a * b + c - let result = tuple((1, 2)(*Mark*), 3)""" - this.VerifyParameterInfoAtStartOfMarker(fileContents,"(*Mark*)",[["int * int";"int"]]) - - [] - member public this.``Multi.ParamAsCurryType``() = - let fileContents = """ - let multi (x : float) (y : float) = 0 - let sum(a, b) = a + b - let rtnValue = sum(multi (1.0(*Mark*)) 3.0, 5)""" - this.VerifyParameterInfoAtStartOfMarker(fileContents,"(*Mark*)",[["float"]]) - - [] - member public this.``Multi.MethodInMatchCause``() = - let fileContents = """ - let rec f l = - match l with - | [] -> System.String.Format("{0:X2}",(*Mark*) - | x :: xs -> f xs""" - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Mark*)",["string";"obj"]) - - [] - member public this.``Regression.Multi.IndexerProperty.Bug93945``() = - let fileContents = """ - type Year2(year : int) = - member this.Item (month : int, day : int) = - let monthIdx = - match month with - | _ when month > 12 -> failwithf "Invalid month [%d]" month - | _ when month < 1 -> failwithf "Invalid month [%d]" month - | _ -> month - let dateStr = sprintf "1-1-%d" year - DateTime.Parse(dateStr).AddMonths(monthIdx - 1).AddDays(float (day - 1)) - - let O'seven = new Year2(2007) - let randomDay = O'seven.[12,(*Mark*)""" - this.VerifyParameterInfoAtStartOfMarker(fileContents,"(*Mark*)",[["int";"int"]]) - - [] - member public this.``Regression.Multi.ExplicitAnnotate.Bug93188``() = - let fileContents = """ - type LiveAnimalAttribute(a : int, b: string) = - inherit System.Attribute() - - [] - type Wombat() = class end""" - this.VerifyParameterInfoAtStartOfMarker(fileContents,"(*Mark*)",[["int";"string"]]) - - [] - member public this.``Multi.Function.WithRecordType``() = - let fileContents = """ - type Vector = - { X : float; Y : float; Z : float } - let foo(x : int,v : Vector) = () - foo(12, { X = 10.0; Y = (*Mark*)20.0; Z = 30.0 })""" - this.VerifyParameterInfoAtStartOfMarker(fileContents,"(*Mark*)",[["int";"Vector"]]) - - [] - member public this.``Multi.Function.AsParameter``() = - let fileContents = """ - let isLessThanZero x = (x < 0) - let containsNegativeNumbers intList = - let filteredList = List.filter isLessThanZero intList - if List.length filteredList > 0 - then Some(filteredList) - else None - let _ = Option.get(containsNegativeNumbers [6; 20; (*Mark*)8; 45; 5])""" - this.VerifyParameterInfoAtStartOfMarker(fileContents,"(*Mark*)",[["int list"]]) - - [] - member public this.``Multi.Function.WithOptionType``() = - let fileContents = """ - let foo( a : int option, b : string ref) = 0 - let _ = foo(Some(12),(*Mark*)""" - this.VerifyParameterInfoAtStartOfMarker(fileContents,"(*Mark*)",[["int option";"string ref"]]) - - [] - member public this.``Multi.Function.WithOptionType2``() = - let fileContents = """ - let multi (x : float) (y : float) = x * y - let sum(a : int, b) = a + b - let options(a1 : int option, b1 : float option) = a1.ToString() + b1.ToString() - let rtnOption = options(Some(sum(1, 3)), (*Mark*)Some(multi 3.1 5.0)) """ - this.VerifyParameterInfoAtStartOfMarker(fileContents,"(*Mark*)",[["int option";"float option"]]) - - [] - member public this.``Multi.Function.WithRefType``() = - let fileContents = """ - let foo( a : int ref, b : string ref) = 0 - let _ = foo(ref 12,(*Mark*)""" - this.VerifyParameterInfoAtStartOfMarker(fileContents,"(*Mark*)",[["int ref";"string ref"]]) - - (* Overload list/Adjust method's param for multi-parameterinfo tests ------------------------------ *) - - [] - member public this.``Multi.OverloadMethod.OrderedParameters``() = - let fileContents = "new System.DateTime(2000,12,(*Mark*)" - this.VerifyParameterInfoOverloadMethodIndex(fileContents,"(*Mark*)",3(*The fourth method*),["int";"int";"int"]) - - [] - member public this.``Multi.Overload.WithSameParameterCount``() = - let fileContents = """ - type Foo() = - member this.A1(x1 : int, x2 : int, ?y : string, ?Z: bool) = () - member this.A1(x1 : int, X2 : string, ?y : int, ?Z: bool) = () - let foo = new Foo() - foo.A1(1,1,(*Mark*)""" - this.VerifyParameterInfoAtStartOfMarker(fileContents,"(*Mark*)",[["int";"int";"string";"bool"];["int";"string";"int";"bool"]]) - - [] - member public this.``ExtensionMethod.Overloads``() = - let fileContents = """ - module MyCode = - type A() = - member this.Method(a:string) = "" - module MyExtension = - type MyCode.A with - member this.Method(a:int) = "" - - open MyCode - open MyExtension - let foo = A() - foo.Method((*Mark*)""" - this.VerifyParameterInfoAtStartOfMarker(fileContents,"(*Mark*)",[["string"];["int"]]) - - [] - member public this.``ExtensionProperty.Overloads``() = - let fileContents = """ - module MyCode = - type A() = - member this.Prop with get(a:string) = "" - module MyExtension = - type MyCode.A with - member this.Prop with get(a:int) = "" - - open MyCode - open MyExtension - let foo = A() - foo.Prop((*Mark*)""" - this.VerifyParameterInfoAtStartOfMarker(fileContents,"(*Mark*)",[["string"];["int"]]) - - (* Generic functions for multi-parameterinfo tests ------------------------------------------------ *) - - [] - member public this.``Multi.Generic.ExchangeInt``() = - let fileContents = "System.Threading.Interlocked.Exchange(123,(*Mark*)" - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Mark*)",["byref";"int"]) - - [] - member public this.``Multi.Generic.Exchange.``() = - let fileContents = "System.Threading.Interlocked.Exchange(12.0,(*Mark*)" - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Mark*)",["byref";"float"]) - - [] - member public this.``Multi.Generic.ExchangeUnder``() = - let fileContents = "System.Threading.Interlocked.Exchange<_> (obj,(*Mark*)" - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Mark*)",["byref";"obj"]) - - [] - member public this.``Multi.Generic.Dictionary``() = - let fileContents = "System.Collections.Generic.Dictionary<_, option>(12,(*Mark*)" - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Mark*)",["int";"System.Collections.Generic.IEqualityComparer"]) - - [] - member public this.``Multi.Generic.HashSet``() = - let fileContents = "System.Collections.Generic.HashSet({ 1 ..12 },(*Mark*)" - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Mark*)",["Seq<'a>";"System.Collections.Generic.IEqualityComparer<'a>"]) - - [] - member public this.``Multi.Generic.SortedList``() = - let fileContents = "System.Collections.Generic.SortedList<_,option> (12,(*Mark*)" - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Mark*)",["int";"System.Collections.Generic.IComparer<'TKey>"]) - - (* No Param Info Shown for multi-parameterinfo tests ---------------------------------------------- *) - - [] - member public this.``ParameterInfo.Multi.NoParameterInfo.InComments``() = - let fileContents = "//let _ = System.Object((*Mark*))" - this.VerifyNoParameterInfoAtStartOfMarker(fileContents,"(*Mark*)") - - [] - member public this.``Multi.NoParameterInfo.InComments2``() = - let fileContents = """(*System.Console.WriteLine((*Mark*)"Test on Fsharp style comments.")*)""" - this.VerifyNoParameterInfoAtStartOfMarker(fileContents,"(*Mark*)") - - [] - member public this.``Multi.NoParameterInfo.OnFunctionDeclaration``() = - let fileContents = "let Foo(x : int, (*Mark*)b : string) = ()" - this.VerifyNoParameterInfoAtStartOfMarker(fileContents,"(*Mark*)") - - [] - member public this.``Multi.NoParameterInfo.WithinString``() = - let fileContents = """let s = "new System.DateTime(2000,12(*Mark*)" """ - this.VerifyNoParameterInfoAtStartOfMarker(fileContents,"(*Mark*)") - - [] - member public this.``Multi.NoParameterInfo.OnProperty``() = - let fileContents = """ - let s = "Hello" - let _ = s.Length(*Mark*)""" - this.VerifyNoParameterInfoAtStartOfMarker(fileContents,"(*Mark*)") - - [] - member public this.``Multi.NoParameterInfo.OnValues``() = - let fileContents = """ - type Foo = class - val private size : int - val private path : string - new (s : int, p : string) = {size = s; path(*Mark*) = p} - end""" - this.VerifyNoParameterInfoAtStartOfMarker(fileContents,"(*Mark*)") - - (* Regression tests/negative tests for multi-parameterinfos --------------------------------------- *) - // To be added when the bugs are fixed... - [] - //[] - member public this.``Regression.ParameterWithOperators.Bug90832``() = - let fileContents = """System.Console.WriteLine("This(*Mark*) is a" + " bug.")""" - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Mark*)",["string"]) - - [] - member public this.``Regression.OptionalArguments.Bug4042``() = - let fileContents = """ - module ParameterInfo - type TT(x : int, ?y : int) = - let z = y - do printfn "%A" z - member this.Foo(?z : int) = z - - type TT2(x : int, y : int option) = - let z = y - do printfn "%A" z - let tt = TT((*Mark*)""" - this.VerifyParameterInfoAtStartOfMarker(fileContents,"(*Mark*)",[["int";"int"]]) - - [] - //[] - member public this.``Regression.ParameterFirstTypeOpenParen.Bug90798``() = - let fileContents = """ - let a = async { - Async.AsBeginEnd((*Mark*) - } - let p = 10""" - this.VerifyParameterInfoAtStartOfMarker(fileContents,"(*Mark*)",[["'Arg -> Async<'T>"]]) - - [] - // regression test for bug 3878: no parameter info triggered by "(" - member public this.``Regression.NoParameterInfoTriggeredByOpenBrace.Bug3878``() = - let fileContents = """ - module ParameterInfo - let x = 1 + 2 - - let _ = System.Console.WriteLine ((*Mark*)) - - let y = 1""" - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Mark*)",[""]) - - [] - // regression test for bug 4495 : Should alway sort method lists in order of argument count - member public this.``Regression.MethodSortedByArgumentCount.Bug4495.Case1``() = - let fileContents = """ - module ParameterInfo - - let a1 = System.Reflection.Assembly.Load("mscorlib") - let m = a1.GetType("System.Decimal").GetConstructor((*Mark*)null)""" - this.VerifyParameterInfoOverloadMethodIndex(fileContents,"(*Mark*)",0,["System.Type array"]) - - [] - member public this.``Regression.MethodSortedByArgumentCount.Bug4495.Case2``() = - let fileContents = """ - module ParameterInfo - - let a1 = System.Reflection.Assembly.Load("mscorlib") - let m = a1.GetType("System.Decimal").GetConstructor((*Mark*)null)""" - this.VerifyParameterInfoOverloadMethodIndex(fileContents,"(*Mark*)",1,["System.Reflection.BindingFlags"; - "System.Reflection.Binder"; - "System.Type array"; - "System.Reflection.ParameterModifier array"]) - - [] - member public this.``BasicBehavior.WithReference``() = - let fileContents = """ - open System.ServiceModel - let serviceHost = new ServiceHost((*Mark*))""" - let (solution, project, file) = this.CreateSingleFileProject(fileContents, references = ["System.ServiceModel"]) - - MoveCursorToStartOfMarker(file, "(*Mark*)") - TakeCoffeeBreak(this.VS) - let methodstr = GetParameterInfoAtCursor(file) - printfn "%A" methodstr - let expected = ["System.Type";"System.Uri []"] - AssertMethodGroupContain(methodstr,expected) - - [] - member public this.``BasicBehavior.CommonFunction``() = - let fileContents = """ - let f(x) = 1 - f((*Mark*))""" - this.VerifyParameterInfoAtStartOfMarker(fileContents,"(*Mark*)",[["'a"]]) - - [] - member public this.``BasicBehavior.DotNet.Static``() = - let fileContents = """System.String.Format((*Mark*)""" - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Mark*)",["string";"obj array"]) - -(*------------------------------------------IDE Query automation start -------------------------------------------------*) - [] - // ParamInfo works normally for calls as query operator arguments - // works fine In nested queries - member public this.``Query.InNestedQuery``() = - let fileContents = """ - let tuples = [ (1, 8, 9); (56, 45, 3)] - let numbers = [ 1;2; 8; 9; 15; 23; 3; 42; 4;0; 55;] - let tp = (2,3,6) - let foo = - query { - for n in numbers do - yield (n, query {for x in tuples do - let r = x.Equals((*Marker1*)tp) - let _ = System.String.Format("",(*Marker2*)x) - select r }) - }""" - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Marker1*)",["obj"],queryAssemblyRefs) - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Marker2*)",["string";"obj array"],queryAssemblyRefs) - - [] - // ParamInfo works normally for calls as query operator arguments - // ParamInfo Still works when an error exists - member public this.``Query.WithErrors``() = - let fileContents = """ - let tuples = [ (1, 8, 9); (56, 45, 3)] - let tp = (2,3,6) - let foo = - query { - for t in tuples do - orderBy (t.Equals((*Marker*)tp)) - }""" - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Marker*)",["obj"],queryAssemblyRefs) - - [] - // ParamInfo works normally for calls as query operator arguments - member public this.``Query.OperatorWithParentheses``() = - let fileContents = """ - type Product() = - let mutable id = 0 - let mutable name = "" - - member x.ProductID with get() = id and set(v) = id <- v - member x.ProductName with get() = name and set(v) = name <- v - - let getProductList() = - [ - Product(ProductID = 1, ProductName = "Chai"); - Product(ProductID = 2, ProductName = "Chang"); ] - let products = getProductList() - let categories = ["Beverages"; "Condiments"; "Vegetables";] - // Group Join - let q2 = - query { - for c in categories do - groupJoin((*Marker1*)for p in products(*Marker2*) -> c = p.ProductName) into ps - select (c, ps) - } |> Seq.toArray""" - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Marker1*)",[],queryAssemblyRefs) - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Marker2*)",[],queryAssemblyRefs) - - [] - // ParamInfo works normally for calls as query operator arguments - // ParamInfo Still works when there is an optional argument - member public this.``Query.OptionalArgumentsInQuery``() = - let fileContents = """ - type TT(x : int, ?y : int) = - let z = y - do printfn "%A" z - member this.Foo(?z : int) = z - - type TT2(x : int, y : int option) = - let z = y - do printfn "%A" z - let numbers = [ 1;2; 8; 9; 15; 23; 3; 42; 4;0; 55;] - - let test3 = - query { - for n in numbers do - let tt = TT((*Marker*) - minBy n - }""" - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Marker*)",["int";"int"],queryAssemblyRefs) - - [] - // ParamInfo works normally for calls as query operator arguments - // ParamInfo Still works when there are overload methods with the same param count - member public this.``Query.OverloadMethod.InQuery``() = - let fileContents = """ - let numbers = [ 1;2; 8; 9; 15; 23; 3; 42; 4;0; 55;] - - type Foo() = - member this.A1(x1 : int, x2 : int, ?y : string, ?Z: bool) = () - member this.A1(x1 : int, X2 : string, ?y : int, ?Z: bool) = () - - let test3 = - query { - for n in numbers do - let foo = new Foo() - foo.A1(1,1,(*Marker*) - minBy n - }""" - this.VerifyParameterInfoContainedAtStartOfMarker(fileContents,"(*Marker*)",["int";"int";"string";"bool"],queryAssemblyRefs) - - -// Context project system -type UsingProjectSystem() = - inherit UsingMSBuild(VsOpts = LanguageServiceExtension.ProjectSystemTestFlavour) diff --git a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.QuickInfo.fs b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.QuickInfo.fs index bb9571afa67..ce47668a6fd 100644 --- a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.QuickInfo.fs +++ b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.QuickInfo.fs @@ -124,852 +124,45 @@ type UsingMSBuild() = let tooltip = time1 GetQuickInfoAtCursor file "Time of first tooltip" AssertContainsInOrder(tooltip, expectedExactOrder) - [] - member public this.``NestedTypesOrder``() = - this.VerifyOrderOfNestedTypesInQuickInfo( - source = "type t = System.Runtime.CompilerServices.RuntimeHelpers(*M*)", - marker = "(*M*)", - expectedExactOrder = ["GetHashCode"; "GetObjectValue"] - ) - [] - member public this.``Operators.TopLevel``() = - let source = """ - /// tooltip for operator - let (===) a b = a + b - let _ = "" === "" - """ - this.CheckTooltip( - code = source, - marker = "== \"\"", - atStart = true, - f = (fun ((text, _), _) -> printfn "actual %s" text; Assert.True(text.Contains "tooltip for operator")) - ) - [] - member public this.``Operators.Member``() = - let source = """ - type U = U - with - /// tooltip for operator - static member (+++) (U, U) = U - let _ = U +++ U - """ - this.CheckTooltip( - code = source, - marker = "++ U", - atStart = true, - f = (fun ((text, _), _) -> printfn "actual %s" text; Assert.True(text.Contains "tooltip for operator")) - ) - - [] - member public this.``QuickInfo.HiddenMember``() = - // Tooltips showed hidden members - #50 - let source = """ - open System.ComponentModel - - type TypeU = { Element : string } - with - [] - [] - member x._Print = x.Element.ToString() - - let u = { Element = "abc" } - """ - this.CheckTooltip( - code = source, - marker = "ypeU =", - atStart = true, - f = (fun ((text, _), _) -> printfn "actual %s" text; Assert.False(text.Contains "member _Print")) - ) - - [] - member public this.``QuickInfo.ObsoleteMember``() = - // Tooltips showed obsolete members - #50 - let source = """ - type TypeU = { Element : string } - with - [] - member x.Print1 = x.Element.ToString() - member x.Print2 = x.Element.ToString() - - let u = { Element = "abc" } - """ - this.CheckTooltip( - code = source, - marker = "ypeU =", - atStart = true, - f = (fun ((text, _), _) -> printfn "actual %s" text; Assert.False(text.Contains "member Print1")) - ) - - [] - member public this.``QuickInfo.HideBaseClassMembersTP``() = - let fileContents = "type foo = HiddenMembersInBaseClass.HiddenBaseMembersTP(*Marker*)" - - this.AssertQuickInfoContainsAtStartOfMarker( - fileContents, - marker = "MembersTP(*Marker*)", - expected = "type HiddenBaseMembersTP =\n inherit TPBaseTy", - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - member public this.``QuickInfo.OverridenMethods``() = - let source = """ - type A() = - abstract member M: unit -> unit - /// 1234 - default this.M() = () - - type AA() = - inherit A() - /// 5678 - override this.M() = () - let x = new AA() - x.M() - - let y = new A() - y.M() - """ - for (marker, expected) in ["x.M", "5678"; "y.M", "1234"] do - this.CheckTooltip - ( - code = source, - marker = marker, - atStart = false, - f = (fun ((text : string, _), _) -> printfn "expected %s, actual %s" expected text; Assert.True (text.Contains(expected))) - ) - - [] - member public this.``QuickInfoForQuotedIdentifiers``() = - let source = """ - /// The fff function - let fff x = x - /// The gg gg function - let ``gg gg`` x = x - let r = fff 1 + ``gg gg`` 2 // no tip hovering over""" - let identifier = "``gg gg``" - for i = 1 to (identifier.Length - 1) do - let marker = "+ " + (identifier.Substring(0, i)) - this.CheckTooltip (source, marker, false, checkTooltip "gg gg") - [] - member public this.``QuickInfoSingleCharQuotedIdentifier``() = - let source = """ - let ``x`` = 10 - ``x``|> printfn "%A" - """ - this.CheckTooltip(source, "x``|>", true, checkTooltip "x") - - [] - member public this.QuickInfoForTypesWithHiddenRepresentation() = - let source = """ - let x = Async.AsBeginEnd - 1 - """ - let expectedTooltip = """ -type Async = - static member AsBeginEnd: computation: ('Arg -> Async<'T>) -> ('Arg * AsyncCallback * objnull -> IAsyncResult) * (IAsyncResult -> 'T) * (IAsyncResult -> unit) - static member AwaitEvent: event: IEvent<'Del,'T> * ?cancelAction: (unit -> unit) -> Async<'T> (requires delegate and 'Del :> Delegate and 'Del: not null) - static member AwaitIAsyncResult: iar: IAsyncResult * ?millisecondsTimeout: int -> Async - static member AwaitTask: task: Task<'T> -> Async<'T> + 1 overload - static member AwaitWaitHandle: waitHandle: WaitHandle * ?millisecondsTimeout: int -> Async - static member CancelDefaultToken: unit -> unit - static member Catch: computation: Async<'T> -> Async> - static member Choice: computations: Async<'T option> seq -> Async<'T option> - static member FromBeginEnd: beginAction: (AsyncCallback * objnull -> IAsyncResult) * endAction: (IAsyncResult -> 'T) * ?cancelAction: (unit -> unit) -> Async<'T> + 3 overloads - static member FromContinuations: callback: (('T -> unit) * (exn -> unit) * (OperationCanceledException -> unit) -> unit) -> Async<'T> - ... -Full name: Microsoft.FSharp.Control.Async""".TrimStart().Replace("\r\n", "\n") - - this.CheckTooltip(source, "Asyn", false, checkTooltip expectedTooltip) - - [] - member public this.``TypeProviders.NestedTypesOrder``() = - let code = "type t = N1.TypeWithNestedTypes(*M*)" - let tpReference = PathRelativeToTestAssembly( @"DummyProviderForLanguageServiceTesting.dll") - this.VerifyOrderOfNestedTypesInQuickInfo( - source = code, - marker = "(*M*)", - expectedExactOrder = ["A"; "X"; "Z"], - extraRefs = [tpReference] - ) - - [] - member public this.``GetterSetterInsideInterfaceImpl.ThisOnceAsserted``() = - let fileContent =""" - type IFoo = - abstract member X: int with get,set - - type Bar = - interface IFoo with - member this.X - with get() = 42 // hello - and set(v) = id() """ - this.AssertQuickInfoContainsAtStartOfMarker(fileContent, "id", "Operators.id") - - //regression test for bug 3184 -- intellisense should normalize to ¡°int[]¡± so that [] is not mistaken for list. - [] - member public this.IntArrayQuickInfo() = - - let fileContents = """ - let x(*MIntArray1*) : int array = [| 1; 2; 3 |] - let y(*MInt[]*) : int [] = [| 1; 2; 3 |] - """ - this.AssertQuickInfoContainsAtStartOfMarker(fileContents, "x(*MIntArray1*)", "int array") - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "y(*MInt[]*)", "int array") - - //Verify no quickinfo -- link name string have - [] - member public this.LinkNameStringQuickInfo() = - - let fileContents = """ - let y = 1 - let f x = "x"(*Marker1*) - let g z = "y"(*Marker2*) - """ - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "\"x\"(*Marker1*)", "") - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "\"y\"(*Marker2*)", "") - - [] - //This is to test the correct TypeProvider Type message is shown or not in the TypeProviderXmlDocAttribute - member public this.``TypeProvider.XmlDocAttribute.Type.Comment``() = - - let fileContents = """ - let a = typeof """ - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "T(*Marker*)", "This is a synthetic type created by me!", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithAdequateComment.dll")]) - - [] - //This is to test for long message in the TypeProviderXmlDocAttribute for TypeProvider Type - member public this.``TypeProvider.XmlDocAttribute.Type.WithLongComment``() = - - let fileContents = """ - let a = typeof """ - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "T(*Marker*)", - "This is a synthetic type created by me!. Which is used to test the tool tip of the typeprovider type to check if it shows the right message or not.", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithLongComment.dll")]) - - [] - //This is to test when the message is null in the TypeProviderXmlDocAttribute for TypeProvider Type - member public this.``TypeProvider.XmlDocAttribute.Type.WithNullComment``() = - - let fileContents = """ - let a = typeof """ - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "T(*Marker*)", - "type T =\n new: unit -> T\n static member M: unit -> int []\n static member StaticProp: decimal\n member Event1: EventHandler", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithNullComment.dll")]) - - [] - //This is to test when there is empty message from the TypeProviderXmlDocAttribute for TypeProvider Type - member public this.``TypeProvider.XmlDocAttribute.Type.WithEmptyComment``() = - - let fileContents = """ - let a = typeof """ - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "T(*Marker*)", - "type T =\n new : unit -> T\n static member M: unit -> int []\n static member StaticProp: decimal\n member Event1: EventHandler", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithEmptyComment.dll")]) - - - [] - //This is to test the multi-language in the TypeProviderXmlDocAttribute for TypeProvider Type - member public this.``TypeProvider.XmlDocAttribute.Type.LocalizedComment``() = - - let fileContents = """ - let a = typeof """ - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "T(*Marker*)", - "This is a synthetic type Localized! ኤፍ ሻርፕ", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithLocalizedComment.dll")]) - - [] - //This is to test the correct TypeProvider Constructor message is shown or not in the TypeProviderXmlDocAttribute - member public this.``TypeProvider.XmlDocAttribute.Constructor.Comment``() = - - let fileContents = """ - let foo = new N.T(*Marker*)() """ - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "T(*Marker*)", "This is a synthetic .ctor created by me for N.T", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithAdequateComment.dll")]) - - [] - //This is to test for long message in the TypeProviderXmlDocAttribute for TypeProvider Constructor - member public this.``TypeProvider.XmlDocAttribute.Constructor.WithLongComment``() = - - let fileContents = """ - let foo = new N.T(*Marker*)() """ - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "T(*Marker*)", - "This is a synthetic .ctor created by me for N.T. Which is used to test the tool tip of the typeprovider Constructor to check if it shows the right message or not.", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithLongComment.dll")]) - - [] - //This is to test when the message is null in the TypeProviderXmlDocAttribute for TypeProvider Constructor - member public this.``TypeProvider.XmlDocAttribute.Constructor.WithNullComment``() = - - let fileContents = """ - let foo = new N.T(*Marker*)() """ - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "T(*Marker*)", - "N.T() : N.T", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithNullComment.dll")]) - [] - //This is to test when there is empty message from the TypeProviderXmlDocAttribute for TypeProvider Constructor - member public this.``TypeProvider.XmlDocAttribute.Constructor.WithEmptyComment``() = - let fileContents = """ - let foo = new N.T(*Marker*)() """ - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "T(*Marker*)", - "N.T() : N.T", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithEmptyComment.dll")]) - - [] - //This is to test the multi-language in the TypeProviderXmlDocAttribute for TypeProvider Constructor - member public this.``TypeProvider.XmlDocAttribute.Constructor.LocalizedComment``() = - - let fileContents = """ - let foo = new N.T(*Marker*)() """ - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "T(*Marker*)", - "This is a synthetic .ctor Localized! ኤፍ ሻርፕ for N.T", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithLocalizedComment.dll")]) - - - [] - //This is to test the correct TypeProvider event message is shown or not in the TypeProviderXmlDocAttribute - member public this.``TypeProvider.XmlDocAttribute.Event.Comment``() = - - let fileContents = """ - let t = new N.T() - t.Event1(*Marker*)""" - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "Event1(*Marker*)", - "This is a synthetic *event* created by me for N.T", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithAdequateComment.dll")]) - [] - //This is to test the multi-language in the TypeProviderXmlDocAttribute for TypeProvider Event - member public this.``TypeProvider.XmlDocAttribute.Event.LocalizedComment``() = - - let fileContents = """ - let t = new N.T() - t.Event1(*Marker*)""" - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "Event1(*Marker*)", - "This is a synthetic *event* Localized! ኤፍ ሻርፕ for N.T", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithLocalizedComment.dll")]) - - [] - //This is to test the multi-language in the TypeProviderXmlDocAttribute for TypeProvider Event - member public this.``TypeProvider.ParamsAttributeTest``() = - - let fileContents = """ - let t = "a".Split('c')""" - this.AssertQuickInfoContainsAtEndOfMarker (fileContents, "Spl", "[] separator") - [] - //This is to test for long message in the TypeProviderXmlDocAttribute for TypeProvider Event - member public this.``TypeProvider.XmlDocAttribute.Event.WithLongComment``() = - - let fileContents = """ - let t = new N.T() - t.Event1(*Marker*)""" - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "Event1(*Marker*)", - "This is a synthetic *event* created by me for N.T. Which is used to test the tool tip of the typeprovider Event to check if it shows the right message or not.!", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithLongComment.dll")]) - - [] - //This is to test when the message is null in the TypeProviderXmlDocAttribute for TypeProvider Event - member public this.``TypeProvider.XmlDocAttribute.Event.WithNullComment``() = - - let fileContents = """ - let t = new N.T() - t.Event1(*Marker*)""" - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "Event1(*Marker*)", - "member N.T.Event1: IEvent", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithNullComment.dll")]) - - [] - //This is to test when there is empty message from the TypeProviderXmlDocAttribute for TypeProvider Event - member public this.``TypeProvider.XmlDocAttribute.Event.WithEmptyComment``() = - - let fileContents = """ - let t = new N.T() - t.Event1(*Marker*)""" - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "Event1(*Marker*)", - "member N.T.Event1: IEvent", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithEmptyComment.dll")]) - - - [] - //This is to test the correct TypeProvider Method message is shown or not in the TypeProviderXmlDocAttribute - member public this.``TypeProvider.XmlDocAttribute.Method.Comment``() = - - let fileContents = """ - let t = new N.T.M(*Marker*)()""" - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "M(*Marker*)", - "This is a synthetic *method* created by me!!", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithAdequateComment.dll")]) - - [] - //This is to test the multi-language in the TypeProviderXmlDocAttribute for TypeProvider Method - member public this.``TypeProvider.XmlDocAttribute.Method.LocalizedComment``() = - - let fileContents = """ - let t = new N.T.M(*Marker*)()""" - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "M(*Marker*)", - "This is a synthetic *method* Localized! ኤፍ ሻርፕ", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithLocalizedComment.dll")]) - - [] - //This is to test for long message in the TypeProviderXmlDocAttribute for TypeProvider Method - member public this.``TypeProvider.XmlDocAttribute.Method.WithLongComment``() = - - let fileContents = """ - let t = new N.T.M(*Marker*)()""" - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "M(*Marker*)", - "This is a synthetic *method* created by me!!. Which is used to test the tool tip of the typeprovider Method to check if it shows the right message or not.!", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithLongComment.dll")]) - - [] - //This is to test when the message is null in the TypeProviderXmlDocAttribute for TypeProvider Method - member public this.``TypeProvider.XmlDocAttribute.Method.WithNullComment``() = - - let fileContents = """ - let t = new N.T.M(*Marker*)()""" - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "M(*Marker*)", - "N.T.M() : int array", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithNullComment.dll")]) - - [] - //This is to test when there is empty message from the TypeProviderXmlDocAttribute for TypeProvider Method - member public this.``TypeProvider.XmlDocAttribute.Method.WithEmptyComment``() = - - let fileContents = """ - let t = new N.T.M(*Marker*)()""" - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "M(*Marker*)", - "N.T.M() : int array", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithEmptyComment.dll")]) - - - [] - //This is to test the correct TypeProvider Property message is shown or not in the TypeProviderXmlDocAttribute - member public this.``TypeProvider.XmlDocAttribute.Property.Comment``() = - - let fileContents = """ - let p = N.T.StaticProp(*Marker*)""" - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "StaticProp(*Marker*)", - "This is a synthetic *property* created by me for N.T", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithAdequateComment.dll")]) - - [] - //This is to test the multi-language in the TypeProviderXmlDocAttribute for TypeProvider Property - member public this.``TypeProvider.XmlDocAttribute.Property.LocalizedComment``() = - - let fileContents = """ - let p = N.T.StaticProp(*Marker*)""" - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "StaticProp(*Marker*)", - "This is a synthetic *property* Localized! ኤፍ ሻርፕ for N.T", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithLocalizedComment.dll")]) - - [] - //This is to test for long message in the TypeProviderXmlDocAttribute for TypeProvider Property - member public this.``TypeProvider.XmlDocAttribute.Property.WithLongComment``() = - - let fileContents = """ - let p = N.T.StaticProp(*Marker*)""" - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "StaticProp(*Marker*)", - "This is a synthetic *property* created by me for N.T. Which is used to test the tool tip of the typeprovider Property to check if it shows the right message or not.!", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithLongComment.dll")]) - - [] - //This is to test when the message is null in the TypeProviderXmlDocAttribute for TypeProvider Property - member public this.``TypeProvider.XmlDocAttribute.Property.WithNullComment``() = - - let fileContents = """ - let p = N.T.StaticProp(*Marker*)""" - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "StaticProp(*Marker*)", - "property N.T.StaticProp: decimal", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithNullComment.dll")]) - - [] - //This is to test when there is empty message from the TypeProviderXmlDocAttribute for TypeProvider Property - member public this.``TypeProvider.XmlDocAttribute.Property.WithEmptyComment``() = - - let fileContents = """ - let p = N.T.StaticProp(*Marker*)""" - - this.AssertQuickInfoContainsAtStartOfMarker (fileContents, "StaticProp(*Marker*)", - "property N.T.StaticProp: decimal", - addtlRefAssy = [PathRelativeToTestAssembly( @"XmlDocAttributeWithEmptyComment.dll")]) - - - [] - //This test case Verify that when Hover over foo the correct quickinfo is displayed for TypeProvider static parameter - //Dummy Type Provider exposes a parametric type (N1.T) that takes 2 static params (string * int) - member public this.``TypeProvider.StaticParameters.Correct``() = - - let fileContents = """ - type foo(*Marker*) = N1.T< const "Hello World",2>""" - - this.AssertQuickInfoContainsAtStartOfMarker( - fileContents, - marker = "foo(*Marker*)", - expected = "type foo = N1.T", - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - //This test case Verify that when Hover over foo the correct quickinfo is displayed - //Dummy Type Provider exposes a parametric type (N1.T) that takes 2 static params (string * int) - //As you can see this is "Negative Case" to check that when given invalid static Parameter quickinfo shows "type foo = obj" - member public this.``TypeProvider.StaticParameters.Negative.Invalid``() = - - let fileContents = """ - type foo(*Marker*) = N1.T< const 100,2>""" - - this.AssertQuickInfoContainsAtStartOfMarker( - fileContents, - marker = "foo(*Marker*)", - expected = "type foo", - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - //This test case Verify that when Hover over foo the XmlComment is shown in quickinfo - //Dummy Type Provider exposes a parametric type (N1.T) that takes 2 static params (string * int) - member public this.``TypeProvider.StaticParameters.XmlComment``() = - - let fileContents = """ - ///XMLComment - type foo(*Marker*) = N1.T< const "Hello World",2>""" - - this.AssertQuickInfoContainsAtStartOfMarker( - fileContents, - marker = "foo(*Marker*)", - expected = "XMLComment", - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - member public this.``TypeProvider.StaticParameters.QuickInfo.OnTheErasedType``() = - let fileContents = """type TTT = Samples.FSharp.RegexTypeProvider.RegexTyped< @"(?^\d{3})-(?\d{3}-\d{7}$)">""" - this.AssertQuickInfoContainsAtStartOfMarker( - fileContents, - marker = "TTT", - expected = "type TTT = Samples.FSharp.RegexTypeProvider.RegexTyped<...>\nFull name: File1.TTT", - addtlRefAssy = ["System"; PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - - [] - member public this.``TypeProvider.StaticParameters.QuickInfo.OnNestedErasedTypeProperty``() = - let fileContents = """ - type T = Samples.FSharp.RegexTypeProvider.RegexTyped< @"(?^\d{3})-(?\d{3}-\d{7}$)"> - let reg = T() - let r = reg.Match("425-123-2345").AreaCode.Value - """ - this.AssertQuickInfoContainsAtStartOfMarker( - fileContents, - marker = "reaCode.Val", - expected = """property Samples.FSharp.RegexTypeProvider.RegexTyped<...>.MatchType.AreaCode: System.Text.RegularExpressions.Group""", - addtlRefAssy = ["System"; PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) // Regression for 2948 - [] - member public this.TypeRecordQuickInfo() = - - let fileContents = """namespace NS - type Re(*MarkerRecord*) = { X : int } """ - let expectedQuickinfoTypeRecord = "type Re = { X: int }" - - this.InfoInDeclarationTestQuickInfoImplWithTrim fileContents "Re(*MarkerRecord*)" expectedQuickinfoTypeRecord - [] - member public this.``QuickInfo.LetBindingsInTypes``() = - let code = - """ - type A() = - let fff n = n + 1 - """ - this.AssertQuickInfoContainsAtEndOfMarker(code, "let ff", "val fff: n: int -> int") // Regression for 2494 - [] - member public this.TypeConstructorQuickInfo() = - - let fileContents = """ - open System - - type PriorityQueue(*MarkerType*)<'k,'a> = - | Nil(*MarkerDataConstructor*) - | Branch of 'k * 'a * PriorityQueue<'k,'a> * PriorityQueue<'k,'a> - - module PriorityQueue(*MarkerModule*) = - let empty = Nil - - let minKeyValue = function - | Nil -> failwith "empty queue" - | Branch(k,a,_,_) -> (k,a) - - let minKey pq = fst (minKeyValue pq(*MarkerVal*)) - - let singleton(*MarkerLastLine*) k a = Branch(k,a,Nil,Nil) - """ - //Verify the quick info as expected - let expectedquickinfoPriorityQueue = "type PriorityQueue<'k,'a> = | Nil | Branch of 'k * 'a * PriorityQueue<'k,'a> * PriorityQueue<'k,'a>" - let expectedquickinfoNil = "union case PriorityQueue.Nil: PriorityQueue<'k,'a>" - let expectedquickinfoPriorityQueueinModule = "module PriorityQueue\n\nfrom File1" - let expectedquickinfoVal = "val pq: PriorityQueue<'a,'b>" - let expectedquickinfoLastLine = "val singleton: k: 'a -> a: 'b -> PriorityQueue<'a,'b>" - - this.InfoInDeclarationTestQuickInfoImplWithTrim fileContents "PriorityQueue(*MarkerType*)" expectedquickinfoPriorityQueue - this.InfoInDeclarationTestQuickInfoImplWithTrim fileContents "Nil(*MarkerDataConstructor*)" expectedquickinfoNil - this.InfoInDeclarationTestQuickInfoImplWithTrim fileContents "PriorityQueue(*MarkerModule*)" expectedquickinfoPriorityQueueinModule - this.InfoInDeclarationTestQuickInfoImplWithTrim fileContents "pq(*MarkerVal*)" expectedquickinfoVal - this.InfoInDeclarationTestQuickInfoImplWithTrim fileContents "singleton(*MarkerLastLine*)" expectedquickinfoLastLine - [] - member public this.NamedDUFieldQuickInfo() = - - let fileContents = """ - type NamedFieldDU(*MarkerType*) = - | Case1(*MarkerCase1*) of V1 : int * bool * V3 : float - | Case2(*MarkerCase2*) of ``Big Name`` : int * Item2 : bool - | Case3(*MarkerCase3*) of Item : int - - exception NamedExn(*MarkerException*) of int * V2 : string * bool * Data9 : float - """ - //Verify the quick info as expected - let expectedquickinfoType = "type NamedFieldDU = | Case1 of V1: int * bool * V3: float | Case2 of ``Big Name`` : int * bool | Case3 of int" - let expectedquickinfoCase1 = "union case NamedFieldDU.Case1: V1: int * bool * V3: float -> NamedFieldDU" - let expectedquickinfoCase2 = "union case NamedFieldDU.Case2: ``Big Name`` : int * bool -> NamedFieldDU" - let expectedquickinfoCase3 = "union case NamedFieldDU.Case3: int -> NamedFieldDU" - let expectedquickinfoException = "exception NamedExn of int * V2: string * bool * Data9: float" - - this.InfoInDeclarationTestQuickInfoImplWithTrim fileContents "NamedFieldDU(*MarkerType*)" expectedquickinfoType - this.InfoInDeclarationTestQuickInfoImplWithTrim fileContents "Case1(*MarkerCase1*)" expectedquickinfoCase1 - this.InfoInDeclarationTestQuickInfoImplWithTrim fileContents "Case2(*MarkerCase2*)" expectedquickinfoCase2 - this.InfoInDeclarationTestQuickInfoImplWithTrim fileContents "Case3(*MarkerCase3*)" expectedquickinfoCase3 - this.InfoInDeclarationTestQuickInfoImplWithTrim fileContents "NamedExn(*MarkerException*)" expectedquickinfoException - [] - member public this.``EnsureNoAssertFromBadParserRangeOnAttribute``() = - let fileContents = """ - [] - Types foo = int""" - this.AssertQuickInfoContainsAtEndOfMarker (fileContents, "ype", "") // just want to ensure there is no assertion fired by the parse tree walker - [] - member public this.``ActivePatterns.Declaration``() = - this.AssertQuickInfoContainsAtEndOfMarker - ("""let ( |One|Two| ) x = One(x+1)""","ne|Tw","int -> Choice") - - [] - member public this.``ActivePatterns.Result``() = - this.AssertQuickInfoContainsAtEndOfMarker - ("""let ( |One|Two| ) x = One(x+1)""","= On","active pattern result One: int -> Choice") - - - [] - member public this.``ActivePatterns.Value``() = - this.AssertQuickInfoContainsAtEndOfMarker - ("""let ( |One|Two| ) x = One(x+1) - let patval = (|One|Two|) // use""","= (|On","int -> Choice") - - [] - member public this.``Regression.InDeclaration.Bug3176a``() = - this.AssertQuickInfoContainsAtEndOfMarker - ("""type T<'a> = { aaaa : 'a; bbbb : int } ""","aa","aaaa") - - [] - member public this.``Regression.InDeclaration.Bug3176c``() = - this.AssertQuickInfoContainsAtEndOfMarker - ("""type C = - val aaaa: int""","aa","aaaa") - - [] - member public this.``Regression.InDeclaration.Bug3176d``() = - this.AssertQuickInfoContainsAtEndOfMarker - ("""type DU<'a> = - | DULabel of 'a""","DULab","DULabel") - - [] - member public this.``Regression.Generic.3773a``() = - this.AssertQuickInfoContainsAtEndOfMarker - ("""let rec M2<'a>(a:'a) = M2(a)""","let rec M","val M2: a: 'a -> obj") - // Before this fix, if the user hovered over 'cccccc' they would see 'Yield' - [] - member public this.``Regression.ComputationExpressionMemberAppearingInQuickInfo``() = - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker - """ - module Test - let q2 = - query { - for p in [1;2] do - join cccccc in [3;4] on (p = cccccc) - yield cccccc - }""" - "yield ccc" "Yield" - // Before this fix, if the user hovered over get or set in a property then - // they would see a quickinfo for any available function named get or set. - // The tests below define a get function with 'let' and then test to make sure that - // this isn't the get seen in the tool tip. - [] - member public this.``Regression.AccessorMutator.Bug4903a``() = - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker - """namespace CountChocula - type BooBerry() = - let get() = "" - member source.Prop - with get() : int = 0 - and set(value:int) : unit = ()""" - "with g" "string" - [] - member public this.``Regression.AccessorMutator.Bug4903d``() = - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker - """namespace CountChocula - type BooBerry() = - member source.AMethod() = () - member source.AProperty - with get() : int = 0 - and set(value:int) : unit = ()""" - "AMetho" "string" - [] - member public this.``Regression.AccessorMutator.Bug4903b``() = - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker - """namespace CountChocula - type BooBerry() = - let get() = "" - member source.Prop - with get() : int = 0 - and set(value:int) : unit = ()""" - "and s" "seq" - - [] - member public this.``Regression.AccessorMutator.Bug4903c``() = - this.AssertQuickInfoContainsAtEndOfMarker - ("""namespace CountChocula - type BooBerry() = - let get() = "" - member source.Prop - with get() : int = 0 - and set(value:int) : unit = ()""", - "let g","string") - [] - member public this.``ParamsArrayArgument.OnType``() = - this.AssertQuickInfoContainsAtEndOfMarker - (""" - type A() = - static member Foo([] a : int[]) = () - let r = A.Foo(42)""" , - "type A","[] a:" ) - [] - member public this.``ParamsArrayArgument.OnMethod``() = - this.AssertQuickInfoContainsAtEndOfMarker - (""" - type A() = - static member Foo([] a : int[]) = () - let r = A.Foo(42)""" , - "A.Foo","[] a:" ) - [] - member public this.``Regression.AccessorMutator.Bug4903e``() = - this.AssertQuickInfoContainsAtEndOfMarker - ("""namespace CountChocula - type BooBerry() = - let get() = "" - member source.Prop - with get() : int = 0 - and set(value:int) : unit = ()""" , - "member source.Pr","Prop" ) - [] - member public this.``Regression.AccessorMutator.Bug4903f``() = - this.AssertQuickInfoContainsAtEndOfMarker - ("""namespace CountChocula - type BooBerry() = - let get() = "" - member source.Prop - with get() : int = 0 - and set(value:int) : unit = ()""" , - "member source.Pr","int" ) - [] - member public this.``Regression.AccessorMutator.Bug4903g``() = - this.AssertQuickInfoContainsAtEndOfMarker - ("""namespace CountChocula - type BooBerry() = - let get() = "" - member source.Prop - with get() : int = 0 - and set(value:int) : unit = ()""" , - "member sou","source" ) - [] - member public this.``Regression.RecursiveDefinition.Generic.3773b``() = - this.AssertQuickInfoContainsAtEndOfMarker - ("""let rec M1<'a>(a:'a) = M1(0)""","let rec M","val M1: a: int -> 'a") - //regression test for bug Dev11:138110 - "F# language service hover tip for ITypeProvider does now show Invalidate event" - [] - member public this.``Regression.ImportedEvent.138110``() = - let fileContents = """ -open Microsoft.FSharp.Core.CompilerServices -let f (tp:ITypeProvider(*$$$*)) = tp.Invalidate - """ - this.AssertQuickInfoContainsAtStartOfMarker( - fileContents, - "Provider(*$$$*)", - "Invalidate", addtlRefAssy=standard40AssemblyRefs ) //"FSharp.Core" add the reference in SxS will cause build failure and intellisense broken, the dll is added by default - [] - member public this.``Declaration.CyclicalDeclarationDoesNotCrash``() = - this.AssertQuickInfoContainsAtEndOfMarker - ("""type (*1*)A = int * (*2*)A ""","(*2*)","type A") [] member public this.``JustAfterIdentifier``() = this.AssertQuickInfoContainsAtEndOfMarker ("""let f x = x + 1 ""","let f","int") - [] - member public this.``FrameworkClass``() = - let fileContent = """let l = new System.Collections.Generic.List()""" - let marker = "Generic.List" - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,marker,"member Capacity: int\n") - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,marker,"member Clear: unit -> unit\n") - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker fileContent marker "get_Capacity" - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker fileContent marker "set_Capacity" - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker fileContent marker "get_Count" - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker fileContent marker "set_Count" - [] - member public this.``FrameworkClassNoMethodImpl``() = - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker - """let l = new System.Collections.Generic.LinkedList()""" - "Generic.LinkedList" "System.Collections.ICollection.ISynchronized" // Bug 5092: A framework class contained a private method impl // Disabled due to issue #11752 --- https://github.com/dotnet/fsharp/issues/11752 //[] @@ -1016,177 +209,16 @@ let f (tp:ITypeProvider(*$$$*)) = tp.Invalidate (* ------------------------------------------------------------------------------------- *) - /// Even though we don't show squiggles, some types will still be known. For example, System.String. - [] - member public this.``OrphanFs.BaselineIntellisenseStillWorks``() = - this.AssertQuickInfoContainsAtEndOfMarker - ("""let astring = "Hello" ""","let astr","string") - /// FEATURE: User may hover over a type or identifier and get basic information about it in a tooltip. - [] - member public this.``Basic``() = - let fileContent = """type (*bob*)Bob() = - let x = 1""" - let marker = "(*bob*)" - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,marker,"Bob =") - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,marker,"Bob =") - [] - member public this.``ModuleDefinition.ModuleNoNewLines``() = - let fileContent = """module XXX - type t = C3 - module YYY = - type t = C4 - ///Doc - module ZZZ = - type t = C5 """ - // The arises because the xml doc mechanism places these before handing them to VS for processing. - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"XX","module XXX") - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"YY","module YYY\n\nfrom XXX") - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"ZZ","module ZZZ\n\nfrom XXX\n\nDoc") - [] - member public this.``IdentifierWithTick``() = - let code = - [ - "let x = 1" - "let x' = \"foo\"" - "if (*aaa*)x = 1 then (*bbb*)x' else \"\"" - ] - let (_, _, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file,"(*aaa*)") - let tooltip = GetQuickInfoAtCursor file - AssertContains(tooltip,"val x: int") - MoveCursorToEndOfMarker(file,"(*bbb*)") - let tooltip = GetQuickInfoAtCursor file - AssertContains(tooltip,"val x': string") - [] - member public this.``NegativeTest.CharLiteralNotConfusedWithIdentifierWithTick``() = - let fileContent = """let x = 1" - let y = 'x' """ - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"'x","") // no tooltips for char literals - - [] - member public this.``QueryExpression.QuickInfoSmokeTest1``() = - let fileContent = """let q = query { for x in ["1"] do select x }""" - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"selec","custom operation: select", addtlRefAssy=standard40AssemblyRefs) - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"selec","custom operation: select ('Result)" , addtlRefAssy=standard40AssemblyRefs) - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"selec","Calls" , addtlRefAssy=standard40AssemblyRefs) - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"selec","Linq.QueryBuilder.Select" , addtlRefAssy=standard40AssemblyRefs ) - - [] - member public this.``QueryExpression.QuickInfoSmokeTest2``() = - let fileContent = """let q = query { for x in ["1"] do join y in ["2"] on (x = y); select (x,y) }""" - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"joi","custom operation: join" , addtlRefAssy=standard40AssemblyRefs ) - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"joi","join var in collection on (outerKey = innerKey)" , addtlRefAssy=standard40AssemblyRefs) - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"joi","Calls" , addtlRefAssy=standard40AssemblyRefs ) - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"joi","Linq.QueryBuilder.Join" , addtlRefAssy=standard40AssemblyRefs ) - - [] - member public this.``QueryExpression.QuickInfoSmokeTest3``() = - let fileContent = """let q = query { for x in ["1"] do groupJoin y in ["2"] on (x = y) into g; select (x,g) }""" - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"groupJoin","custom operation: groupJoin" , addtlRefAssy=standard40AssemblyRefs ) - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"groupJoin","groupJoin var in collection on (outerKey = innerKey)" , addtlRefAssy=standard40AssemblyRefs) - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"groupJoin","Calls" , addtlRefAssy=standard40AssemblyRefs ) - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"groupJoin","Linq.QueryBuilder.GroupJoin" , addtlRefAssy=standard40AssemblyRefs) - - - /// Hovering over a literal string should not show data tips for variable names that appear in the string - [] - member public this.``StringLiteralWithIdentifierLookALikes.Bug2360_A``() = - let fileContent = """let y = 1 - let f x = "x" - let g z = "y" """ - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker fileContent "f x = \"" "val" - /// Hovering over a literal string should not show data tips for variable names that appear in the string - [] - member public this.``Regression.StringLiteralWithIdentifierLookALikes.Bug2360_B``() = - let fileContent = """let y = 1""" - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"let ","int") - /// FEATURE: Intellisense information from types in earlier files in the project is available in subsequent files. - [] - member public this.``AcrossMultipleFiles``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let file1 = AddFileFromText(project,"File1.fs", - [ - "type Bob() = " - " let x = 1"]) - let file2 = AddFileFromText(project,"File2.fs", - [ "let bob = new File1.Bob()"]) - let file1 = OpenFile(project,"File1.fs") - let file2 = OpenFile(project,"File2.fs") - - // Get the tooltip at type Bob - MoveCursorToEndOfMarker(file2,"let bo") - let tooltip = time1 GetQuickInfoAtCursor file2 "Time of first tooltip" - printf "First-%s\n" tooltip - AssertContains(tooltip,"File1.Bob") - - // Get the tooltip again - MoveCursorToEndOfMarker(file2,"let bo") - let tooltip = time1 GetQuickInfoAtCursor file2 "Time of second tooltip" - printf "Second-%s\n" tooltip - AssertContains(tooltip,"File1.Bob") - /// FEATURE: Linked files work - [] - member public this.``AcrossLinkedFiles``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let file1 = AddLinkedFileFromTextEx(project, @"..\LINK.FS", @"..\link.fs", @"MyLink.fs", - [ - "type Bob() = " - " let x = 1"]) - let file2 = AddFileFromText(project,"File2.fs", - [ "let bob = new Link.Bob()"]) - let file1 = OpenFile(project, @"..\link.fs") - let file2 = OpenFile(project, @"File2.fs") - - // Get the tooltip at type Bob - MoveCursorToEndOfMarker(file2,"let bo") - let tooltip = time1 GetQuickInfoAtCursor file2 "Time of first tooltip" - printf "First-%s\n" tooltip - AssertContains(tooltip,"Link.Bob") - - // Get the tooltip again - MoveCursorToEndOfMarker(file2,"let bo") - let tooltip = time1 GetQuickInfoAtCursor file2 "Time of second tooltip" - printf "Second-%s\n" tooltip - AssertContains(tooltip,"Link.Bob") - [] - member public this.``TauStarter``() = - let code = - [ - "type (*Scenario01*)Bob() =" - " let x = 1" - "type (*Scenario021*)Bob =" - " class" - " public new() = { }" - "end" - "type (*Scenario022*)Alice =" - " class" - " public new() = { }" - "end"] - let (_, _, file) = this.CreateSingleFileProject(code) - TakeCoffeeBreak(this.VS) - MoveCursorToEndOfMarker(file,"(*Scenario021*)") - let tooltip = time1 GetQuickInfoAtCursor file "Time of first tooltip" - printf "First-%s\n" tooltip - Assert.True(tooltip.Contains("Bob =")) - - MoveCursorToEndOfMarker(file,"(*Scenario022*)") - let tooltip = time1 GetQuickInfoAtCursor file "Time of first tooltip" - printf "First-%s\n" tooltip - Assert.True(tooltip.Contains("Alice =")) member private this.QuickInfoResolutionTest lines queries = let code = [ yield! lines ] @@ -1233,385 +265,33 @@ let f (tp:ITypeProvider(*$$$*)) = tp.Invalidate ("type Test0e = System.Collections.Generic.","KeyNotFoundException","Generic.KeyNotFoundException"); // note resolves to type ] - [] - member public this.``LongPaths``() = - let text,cases = this.GetLongPathsTestCases() - this.QuickInfoResolutionTest text cases - [] - member public this.``Global.LongPaths``() = - let text,cases = this.GetLongPathsTestCases() - let replace (s:string) = s.Replace("System", "global.System") - let text = text |> List.map (fun s -> replace s) - let cases = - cases - |> List.filter (fun (a,_,_) -> a.Contains "System") - |> List.map (fun (a,b,expectedResult) -> replace a, replace b, expectedResult) - - this.QuickInfoResolutionTest text cases - [] - member public this.``TypeAndModuleReferences``() = - this.QuickInfoResolutionTest - ["let test1 = List.length" - "let test2 = List.Empty" - "let test3 = (\"1\").Length" - "let test3b = (id \"1\").Length"] - - // The quick info specification // Some of the expected quick info text - [("let test1 = ","List" ,"module List"); - ("let test1 = List.","length" ,"length"); - ("let test2 = ","List" ,"Collections.List"); - ("let test2 = List.","Empty" ,"List.Empty"); - ("let test3 = (\"1\").","Length" ,"String.Length"); - ("let test3b = (id \"1\").","Length" ,"String.Length") ] - [] - member public this.``ModuleNameAndMisc``() = - this.QuickInfoResolutionTest - ["module (*test3q*)MM3 =" - " let y = 2" - "let test4 = lock"; - "let (*test5*) ffff xx = xx + 1" ] - - // The quick info specification // Some of the expected quick info text - [("module (*test3q*)","MM3" ,"module MM3"); - ("let test4 = ","lock" ,"lock"); - ("let (*test5*) ","ffff" ,"ffff") ] - [] - member public this.``MemberIdentifiers``() = - this.QuickInfoResolutionTest - ["type TestType() =" - " member (*test6*) xx.PPPP = 1" - " member (*test7*) xx.QQQQ(x) = 3.0" - "let test8 = (TestType()).PPPP"] - - // The quick info specification // Some of the expected quick info text - [("member (*test6*) ","xx" ,"TestType"); - ("member (*test6*) xx.","PPPP" ,"PPPP"); - ("member (*test7*) ","xx" ,"TestType"); - ("member (*test7*) xx.","QQQQ" ,"float"); - ("member (*test7*) xx.","QQQQ" ,"float"); - ("let test8 = (TestType()).", "PPPP" , "PPPP") ] - - [] - member public this.``IdentifiersForFields``() = - this.QuickInfoResolutionTest - ["type TestType9 = { XXX : int }" - "let test11 = { XXX = 1 }"] - - // The quick info specification // Some of the expected quick info text - [("type TestType9 = { ", "XXX" , "XXX: int"); - ("let test11 = { ", "XXX" , "XXX");] - [] - member public this.``IdentifiersForUnionCases``() = - this.QuickInfoResolutionTest - ["type TestType10 = Case1 | Case2 of int" - "let test12 = (Case1,Case2(3))"] - - // The quick info specification // Some of the expected quick info text - [("type TestType10 = ", "Case1" , "union case TestType10.Case1"); - ("type TestType10 = Case1 | ", "Case2" , "union case TestType10.Case2"); - ("let test12 = (", "Case1" , "union case TestType10.Case1"); - ("let test12 = (Case1,", "Case2" , "union case TestType10.Case2");] - [] - member public this.``IdentifiersInAttributes``() = - this.QuickInfoResolutionTest - ["[<(*test13*)System.CLSCompliant(true)>]" - "let test13 = 1" - "open System" - "[<(*test14*)CLSCompliant(true)>]" - "let test14 = 1"] - - // The quick info specification // Some of the expected quick info text - [("[<(*test13*)", "System" , "namespace System"); - ("[<(*test13*)System.", "CLSCompliant" , "CLSCompliantAttribute"); - ("[<(*test14*)", "CLSCompliant" , "CLSCompliantAttribute");] - [] - member public this.``ArgumentAndPropertyNames``() = - this.QuickInfoResolutionTest - ["type R = { mutable AAA : int }" - " static member M() = { AAA = 1 }" - "let test13 = R.M(AAA=3)" - "type R2() = " - " static member M() = System.Reflection.InterfaceMapping()" - "" - "let test14 = R2.M(InterfaceMethods= [| |])" - "" - "let test15 = new System.Reflection.AssemblyName(Name=\"Foo\")" - "let test16 = new System.Reflection.AssemblyName(assemblyName=\"Foo\")"] - - // The quick info specification // Some of the expected quick info text - [("let test13 = R.M(", "AAA" , "R.AAA: int"); - ("let test14 = R2.M(", "InterfaceMethods" , "field System.Reflection.InterfaceMapping.InterfaceMethods"); - ("let test15 = new System.Reflection.AssemblyName(", "Name" , "property System.Reflection.AssemblyName.Name"); - ("let test16 = new System.Reflection.AssemblyName(", "assemblyName", "argument assemblyName")] - /// Quickinfo was throwing an exception when the mouse was over the end of a line. - [] - member public this.``AtEndOfLine``() = - let fileContent = """//""" - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker fileContent "//" "Bug:" - [] - member public this.``Regression.FieldRepeatedInToolTip.Bug3538``() = - this.AssertIdentifierInToolTipExactlyOnce - """ - open System.Runtime.InteropServices - [] - type A() = - [] - val mutable x : int""" - "LayoutKind.Expl" "Explicit" - [] - member public this.``Regression.FieldRepeatedInToolTip.Bug3818``() = - this.AssertIdentifierInToolTipExactlyOnce - """ - [] - type A() = - do ()""" - "Inherite" "Inherited" // Get the tooltip at "Inherite" & Verify that it contains the 'Inherited' field exactly once - [] - member public this.``MethodAndPropTooltip``() = - let fileContent = """ - open System - do - Console.Clear() - Console.BackgroundColor |> ignore""" - this.AssertIdentifierInToolTipExactlyOnce fileContent "Console.Cle" "Clear" - this.AssertIdentifierInToolTipExactlyOnce fileContent "Console.Back" "BackgroundColor" - [] - member public this.``Regression.StaticVsInstance.Bug3626``() = - let fileContent = """ - type Foo() = - member this.Bar () = "hllo" - static member Bar() = 13 - let z = (*int*) Foo.Bar() - let Hoo = new Foo() - let y = (*string*) Hoo.Bar() """ - // Get the tooltip at "Foo.Bar(" - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"(*int*) Foo.Ba","Foo.Bar") - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"(*int*) Foo.Ba","-> int") - // Get the tooltip at "Hoo.Bar(" - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"(*string*) Hoo.Ba","Foo.Bar") - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"(*string*) Hoo.Ba","-> string") - - [] - member public this.``Class.OnlyClassInfo``() = - let fileContent = """type TT(x : int, ?y : int) = - class end""" - - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"type T","type TT") - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker fileContent "type T" "---" - - //KnownFail: [] - member public this.``Async.AsyncToolTips``() = - let fileContent = """let a = - async { - let ms = new System.IO.MemoryStream(Array.create 1000 1uy) - let toFill = Array.create 2000 0uy - let! x = ms.AsyncRead(2000) - return x - }""" - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"asy","AsyncBuilder") - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker fileContent "asy" "---" - - [] - member public this.``Regression.Exceptions.Bug3723``() = - let fileContent = """exception E3E of int * int - exception E4E of (int * int) - exception E5E = E4E""" - // E3E should be un-parenthesized - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker fileContent "exception E3" "(int * int)" - // E4E should be parenthesized - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"exception E4","(int * int)") - // E5E is an alias - should contain name of the aliased exception - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"exception E5","E4E") - [] - member public this.``Regression.Classes.Bug4066``() = - let fileContent = """type Foo() as this = - do this |> ignore - member this.Bar() = this""" - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"type Foo() as thi","this") - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker fileContent "type Foo() as thi" "ref" - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"do thi","this") - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker fileContent "do thi" "ref" - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"member thi","this") - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker fileContent "member thi" "ref" - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"Bar() = thi","this") - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker fileContent "Bar() = thi" "ref" - [] - member public this.``Regression.Classes.Bug2362``() = - let fileContent = """let append mm nn = fun ac -> mm (nn ac)""" - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"let appen","mm: ('a -> 'b) -> nn: ('c -> 'a) -> ac: 'c -> 'b") - // check consistency of QuickInfo for 'm' and 'n', which is the main point of this test - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"let append m","'a -> 'b") - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"let append mm n","'c -> 'a") - [] - member public this.``Regression.ModuleAlias.Bug3790a``() = - let fileContent = """module ``Some`` = Microsoft.FSharp.Collections.List - module None = Microsoft.FSharp.Collections.List""" - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker fileContent "module ``So" "Option" - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker fileContent "module No" "Option" - [] - member public this.``Regression.ModuleAlias.Bug3790b``() = - let code = - [ - "module ``Some`` = Microsoft.FSharp.Collections.List" - "let _ = ``Some``.append [] []" ] - let (_, _, file) = this.CreateSingleFileProject(code) - - // Test quickinfo in place where the declaration is used - MoveCursorToEndOfMarker(file, "= ``So") - let tooltip = GetQuickInfoAtCursor file - AssertNotContains(tooltip, "Option") - [] - member public this.``Regression.ActivePatterns.Bug4100a``() = - let fileContent = """let (|Lazy|) x = x - match 0 with | Lazy y -> ()""" - // Test quickinfo in place where the declaration is used - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker fileContent "with | Laz" "'?" // e.g. "Lazy: '?3107 -> '?3107", "Lazy: 'a -> 'a" will be fine - - [] - member public this.``Regression.ActivePatterns.Bug4100b``() = - let fileContent = """let Some (a:int) = a - match None with - | Some _ -> () - | _ -> () - - let (|NSome|) (a:int) = a - let NSome (a:int) = a.ToString() - match 0 with - | NSome _ -> ()""" - // This shouldn't be the local function - it should find the 'Some' union case - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker fileContent "| Som" "int -> int" - // This shouldn't find the function returning string but a pattern returning int - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker fileContent "| NSom" "int -> string" - - [] - member public this.``Regression.ActivePatterns.Bug4103``() = - let fileContent = """let (|Lazy|) x = x - match 0 with | Lazy y -> ()""" - // Test quickinfo in place where the declaration is used - this.VerifyQuickInfoDoesNotContainAnyAtEndOfMarker fileContent "(|Laz" "Control.Lazy" - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"(|Laz","|Lazy|") - - // This test checks that we don't show any tooltips for operators - // (which is currently not supported, but it used to collide with support for active patterns) - [] - member public this.``Regression.NoTooltipForOperators.Bug4567``() = - let fileContent = """let ( |+| ) a b = a + b - let n = 1 |+| 2 - let b = true || false - ()""" - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"( |+","") - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"1 |+","") - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"true |","") // Check to see that two distinct projects can be present - [] - member public this.``AcrossTwoProjects``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project1 = CreateProject(solution,"testproject1") - let file1 = AddFileFromText(project1,"File1.fs", - [ - "type (*bob*)Bob1() = " - " let x = 1"]) - let file1 = OpenFile(project1,"File1.fs") - let project2 = CreateProject(solution,"testproject2") - let file2 = AddFileFromText(project2,"File2.fs", - [ - "type (*bob*)Bob2() = " - " let x = 1"]) - let file2 = OpenFile(project2,"File2.fs") - - // Check Bob1 - MoveCursorToEndOfMarker(file1,"type (*bob*)Bob") - let tooltip = time1 GetQuickInfoAtCursor file1 "Time of file1 tooltip" - printf "Tooltip for file1:\n%s\n" tooltip - Assert.True(tooltip.Contains("Bob1 =")) - - // Check Bob2 - MoveCursorToEndOfMarker(file2,"type (*bob*)Bob") - let tooltip = time1 GetQuickInfoAtCursor file2 "Time of file2 tooltip" - printf "Tooltip for file2:\n%s\n" tooltip - Assert.True(tooltip.Contains("Bob2 =")) // In this bug, relative paths with .. in them weren't working. - [] - member public this.``BugInRelativePaths``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let file1 = AddFileFromText(project,"File1.fs", - [ - "type Bob() = " - " let x = 1"]) - let file2 = AddFileFromText(project,"..\\File2.fs", - [ - "let bob = new File1.Bob()"]) - let file1 = OpenFile(project,"File1.fs") - let file2 = OpenFile(project,"..\\File2.fs") - - // Get the tooltip at type Bob - MoveCursorToEndOfMarker(file2,"let bo") - let tooltip = time1 GetQuickInfoAtCursor file2 "Time of first tooltip" - printf "First-%s\n" tooltip - AssertContains(tooltip,"File1.Bob") - - // Get the tooltip again - MoveCursorToEndOfMarker(file2,"let bo") - let tooltip = time1 GetQuickInfoAtCursor file2 "Time of second tooltip" - printf "Second-%s\n" tooltip - AssertContains(tooltip,"File1.Bob") - // QuickInfo over a type that references types in an unreferenced assembly works. - [] - member public this.``MissingDependencyReferences.QuickInfo.Bug5409``() = - let code = - [ - "let myForm = new System.Windows.Forms.Form()" - ] - let (_, _, file) = this.CreateSingleFileProject(code, references = ["System.Windows.Forms"]) - MoveCursorToEndOfMarker(file,"myFo") - let tooltip = time1 GetQuickInfoAtCursor file "Time of first tooltip" - printf "First-%s\n" tooltip -// ShowErrors(project) - AssertContains(tooltip,"Form") - - /// In this bug, the EOF token was reached before the parser could close the (, with, and let - /// The fix--at the point in time it was fixed--was to modify the parser to send a limited number - /// of additional EOF tokens to allow the recovery code to proceed up the change of productions - /// in the grammar. - [] - member public this.``Regression.Bug1605``() = - let fileContent = """let rec f l = - match l with - | [] -> string.Format( - | x::xs -> "hello" """ - // This string doesn't matter except that it should prove there is some datatip present. - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"| [] -> str","string") + - [] - member public this.``Regression.Bug4642``() = - let fileContent = """ "AA".Chars """ - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"\"AA\".Ch","int -> char") /// Complete a member completion and confirm that its data tip contains the fragments /// in rhsContainsOrder @@ -1629,319 +309,19 @@ let f (tp:ITypeProvider(*$$$*)) = tp.Invalidate ShowErrors(project) failwith $"Could not find completion name '{completionName}'" - [] - //``CompletiongListItem.DocCommentsOnMembers`` and with //Regression 5856 - member public this.``Regression.MemberDefinition.DocComments.Bug5856_1``() = - this.AssertMemberDataTipContainsInOrder - ((*code *) - [ - "type MyType = " - " /// Hello" - " static member Overload() = 0" - " /// Hello2" - " static member Overload(x:int) = 0" - " /// Hello3" - " static member NonOverload() = 0" - "MyType." - ] , - (* marker *) - "MyType.", - (* completed item *) - "Overload", - (* expect to see in order... *) - [ - "static member MyType.Overload: unit -> int"; - "static member MyType.Overload: x: int -> int"; - "Hello" - ] - ) - - [] - member public this.``Regression.MemberDefinition.DocComments.Bug5856_2``() = - this.AssertMemberDataTipContainsInOrder - ((*code *) - [ - "module Outer =" - " /// Comment" - " module Inner =" - " let x = 1" - "let x() = " - " Outer." - ] , - (* marker *) - "Outer.", - (* completed item *) - "Inner", - (* expect to see in order... *) - [ - "module Inner"; - "from"; "Outer"; - "Comment" - ] - ) - [] - member public this.``Regression.MemberDefinition.DocComments.Bug5856_3``() = - this.AssertMemberDataTipContainsInOrder - ((*code *) - [ - "module Module =" - " /// Union comment" - " type Union =" - " /// Case comment" - " | Case of int" - "let x() = " - " Module." - ] , - (* marker *) - "Module.", - (* completed item *) - "Case", - (* expect to see in order... *) - [ - "union case Module.Union.Case: int -> Module.Union"; - "Case comment"; - ] - ) - [] - member public this.``Regression.MemberDefinition.DocComments.Bug5856_4``() = - this.AssertMemberDataTipContainsInOrder - ((*code *) - [ - "module Module =" - " /// Union comment" - " type Union =" - " /// Case comment" - " | Case of int" - "let x() = " - " Module." - ] , - (* marker *) - "Module.", - (* completed item *) - "Union", - (* expect to see in order... *) - [ - "type Union ="; - " | Case of int"; - //"Full name:"; "Module.Union"; - "Union comment"; - ] - ) - [] - member public this.``Regression.MemberDefinition.DocComments.Bug5856_5``() = - this.AssertMemberDataTipContainsInOrder - ((*code *) - [ - "module Module =" - " /// Pattern comment" - " let (|Pattern|) = 0" - "let x() = " - " Module." - ] , - (* marker *) - "Module.", - (* completed item *) - "Pattern", - (* expect to see in order... *) - [ - "active recognizer Pattern: int"; - //"Full name:"; "Module"; "|Pattern|"; - "Pattern comment"; - ] - ) - [] - member public this.``Regression.MemberDefinition.DocComments.Bug5856_6``() = - this.AssertMemberDataTipContainsInOrder - ((*code *) - [ - "module Module =" - " /// A comment" - " exception MyException of int" - "let x() = " - " Module." - ] , - (* marker *) - "Module.", - (* completed item *) - "MyException", - (* expect to see in order... *) - [ - "exception MyException of int"; - //"Full name:"; "Module"; "MyException"; - "A comment"; - ] - ) - [] - member public this.``Regression.MemberDefinition.DocComments.Bug5856_7``() = - this.AssertMemberDataTipContainsInOrder - ((*code *) - [ - "type Record = {" - " /// A comment" - " field : int" - " }" - "let record = {field = 1}" - "let x() =" - " record." - ] , - (* marker *) - "record.", - (* completed item *) - "field", - (* expect to see in order... *) - [ - "Record.field: int"; - "A comment"; - ] - ) - [] - member public this.``Regression.MemberDefinition.DocComments.Bug5856_8``() = - this.AssertMemberDataTipContainsInOrder - ((*code *) - [ - "type Foo =" - " /// A comment" - " static member Property" - " with get() = \"\"" - "let x() = " - " Foo." - ] , - (* marker *) - "Foo.", - (* completed item *) - "Property", - (* expect to see in order... *) - [ - "property Foo.Property: string"; - "A comment"; - ] - ) - [] - member public this.``Regression.MemberDefinition.DocComments.Bug5856_9``() = - this.AssertMemberDataTipContainsInOrder - ((*code *) - [ - "module Module =" - " /// A comment" - " type Class = class end" - "let x() = " - " Module." - ] , - (* marker *) - "Module.", - (* completed item *) - "Class", - (* expect to see in order... *) - [ - "type Class"; - //"Full name:"; "Module"; "Class"; - "A comment"; - ] - ) - [] - member public this.``Regression.MemberDefinition.DocComments.Bug5856_10``() = - this.AssertMemberDataTipContainsInOrder - ((*code *) - [ - "System.String." - ] , - (* marker *) - "String.", - (* completed item *) - "Format", - (* expect to see in order... *) - [ - "System.String.Format("; - "[Filename:"; "mscorlib.dll]"; - "[Signature:M:System.String.Format(System.String,System.Object[])]"; - ] - ) - [] - member public this.``Regression.MemberDefinition.DocComments.Bug5856_13``() = - this.AssertMemberDataTipContainsInOrder - ((*code *) - [ - "System.Collections.Generic.Dictionary." - ] , - (* marker *) - "Dictionary.", - (* completed item *) - "KeyCollection", - (* expect to see in order... *) - [ - "type KeyCollection<"; - "member CopyTo"; - """Represents the collection of keys in a . This class cannot be inherited.""" - ] - ) - [] - member public this.``Regression.MemberDefinition.DocComments.Bug5856_14``() = - this.AssertMemberDataTipContainsInOrder - ((*code *) - [ - "System." - ] , - (* marker *) - "System.", - (* completed item *) - "ArgumentException", - (* expect to see in order... *) - [ - "type ArgumentException"; - "member Message"; - "The exception that is thrown when one of the arguments provided to a method is not valid.] - member public this.``Regression.MemberDefinition.DocComments.Bug5856_15``() = - this.AssertMemberDataTipContainsInOrder - ((*code *) - [ - "System.AppDomain." - ] , - (* marker *) - "AppDomain.", - (* completed item *) - "CurrentDomain", - (* expect to see in order... *) - [ - "property System.AppDomain.CurrentDomain: System.AppDomain"; - """Gets the current application domain for the current .""" - ] - ) - [] - member public this.``Regression.ExtensionMethods.DocComments.Bug6028``() = - this.AssertMemberDataTipContainsInOrder - ((*code *) - [ - @"open System.Linq -let rec query:System.Linq.IQueryable<_> = null -query." - ] , - (* marker *) - "query.", - (* completed item *) - "All", - (* expect to see in order... *) - [ - "IQueryable.All"; - "[Filename"; "System.Core.dll]"; - "[Signature:M:System.Linq.Enumerable.All``1" - ] - ) [] member public this.``Regression.OnMscorlibMethodInScript.Bug6489``() = @@ -1964,850 +344,35 @@ query." ) - /// BUG: intellisense on "self" parameter in implicit ctor classes is wrong - [] - member public this.``Regression.CompListItemInfo.Bug5694``() = - this.AssertMemberDataTipContainsInOrder - ((*code *) - [ - "type Form2() as self =" - " inherit System.Windows.Forms.Form()" - " let f() = self." - ] , - (* marker *) - "self.", - (* completed item *) - "AcceptButton", - (* expect to see in order... *) - [ - "Gets or sets the button on the form that is clicked when the user presses the ENTER key." - ] - ) - - - /// Bug 4592: Check that ctors are displayed from C# classes, i.e. the "new" lines below. - [] - member public this.``Regression.Class.Printing.CSharp.Classes.Only.Bug4592``() = - this.AssertMemberDataTipContainsInOrder - ((*code *) - ["System.Random"] , - (* marker *) - "System.Random", - (* completed item *) - "Random", - (* expect to see in order... *) - ["type Random ="; - " new: unit -> unit + 1 overload" - " member Next: unit -> int + 2 overloads"; - " member NextBytes: buffer: byte array -> unit"; - " member NextDouble: unit -> float"] - ) - - [] - member public this.``GenericDotNetMethodShowsComment``() = - this.AssertMemberDataTipContainsInOrder - ((*code *) - ["System.Linq.ParallelEnumerable."] , - (* marker *) - "ParallelEnumerable.", - (* completed item *) - "ElementAt", - (* expect to see in order... *) - [ - "Signature:M:System.Linq.ParallelEnumerable.ElementAt``1(System.Linq.ParallelQuery{``0},System.Int32" - ] - ) - - /// Bug 4624: Check the order in which members are printed, C# classes - [] - member public this.``Regression.Class.Printing.CSharp.Classes.Bug4624``() = - this.AssertMemberDataTipContainsInOrder - ((*code *) - ["System.Security.Policy.CodeConnectAccess"], - (* marker *) - "System.Security.Policy.CodeConnectAccess", - (* completed item *) - "CodeConnectAccess", - (* expect to see in order... *) - // Pre fix output is mixed up - [ "type CodeConnectAccess ="; - " new: allowScheme: string * allowPort: int -> unit"; - " member Equals: o: obj -> bool"; - " member GetHashCode: unit -> int"; - " static member CreateAnySchemeAccess: allowPort: int -> CodeConnectAccess"; - " static member CreateOriginSchemeAccess: allowPort: int -> CodeConnectAccess"; - " static val AnyScheme: string"; - " static val DefaultPort: int"; - " ..."; - ]) - - /// Bug 4624: Check the order in which members are printed, F# classes - [] - member public this.``Regression.Class.Printing.FSharp.Classes.Bug4624``() = - this.AssertMemberDataTipContainsInOrder - ((*code *) - ["type F1() = "; - " class "; - " inherit System.Windows.Forms.Form()"; - " abstract AAA : int with get"; - " abstract ZZZ : int with get"; - " abstract AAA : bool with set"; - " val x : F1"; - " static val x : F1"; - " static member A() = 12"; - " member this.B() = 12"; - " static member C() = 12"; - " member this.D() = 12"; - " member this.D with get() = 12 and set(12) = ()"; - " member this.D(x:int,y:int) = 12"; - " member this.D(x:int) = 12"; - " member this.D x y z = [1;x;y;z]"; - " override this.ToString() = \"\""; - " interface System.IDisposable with"; - " override this.Dispose() = () "; - " end"; - " end"; - "type A1 = F1"], - (* marker *) - "type A1 = F1", - (* completed item *) - "F1", - (* expect to see in order... *) - // Pre fix output is mixed up - [ "type F1 ="; - " inherit Form"; - " interface IDisposable"; - " new: unit -> F1"; - " val x: F1" - " member B: unit -> int"; - " override ToString: unit -> string"; - " static member A: unit -> int"; - " static member C: unit -> int"; - " abstract AAA: int"; - " member D: int"; - " ..."; - ]) -(*------------------------------------------IDE automation starts here -------------------------------------------------*) - [] - member public this.``Automation.Regression.AccessibilityOnTypeMembers.Bug4168``() = - let fileContent = """module Test - type internal Foo2(*Marker*) () = - member public this.Prop1 = 12 - member internal this.Prop2 = 12 - member private this.Prop3 = 12 - public new(x:int) = new Foo2() - internal new(x:int,y:int) = new Foo2() - private new(x:int,y:int,z:int) = new Foo2()""" - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker*)", "type internal Foo2") - [] - member public this.``Automation.Regression.AccessorsAndMutators.Bug4276``() = - let fileContent = """type TestType1(*Marker1*)( x : int , y : int ) = - let mutable x = x - let mutable y = y - - // Property with getter and setter - member this.X with get () = x - and set x' = x <- x' - - // Property with setter only - member this.Y with set y' = y <- y' - - // Property with getter only - member this.Length with get () = sqrt(float (x * x + y * y)) - - member this.Item with get (i : int) = match i with | 0 -> x | 1 -> y | _ -> failwith "Incorrect index" - - let point = TestType1(10,10) - - point.X <- 3 - point.Y <- 4 - - let x = point.[0] - let y = point.[1] - - let bitArray = new System.Collections.BitArray(*Marker2*)(1) - - point.Length |> ignore""" - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker1*)", "type TestType1") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker1*)", "member Length: float") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker1*)", "member Item") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker1*)", "member X: int") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker1*)", "member Y: int") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker2*)", "type BitArray") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker2*)", "member Not: unit -> BitArray") - this.VerifyQuickInfoDoesNotContainAnyAtStartOfMarker fileContent "(*Marker2*)" "get_Length" - this.VerifyQuickInfoDoesNotContainAnyAtStartOfMarker fileContent "(*Marker2*)" "set_Length" - - [] - member public this.``Automation.AutoOpenMyNamespace``() = - let fileContent ="""namespace System.Numerics - type t = BigInteger(*Marker1*)""" - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "r(*Marker1*)", "type BigInteger") - [] - member public this.``Automation.Regression.BeforeAndAfterIdentifier.Bug4371``() = - let fileContent = """module Test - let f arg1 (arg2, arg3, arg4) arg5 = 42 - let goo a = f(*Marker1*) 12 a - - type printer = System.Console - let z = (*Marker3*)printer.BufferWidth(*Marker2*)""" - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker1*)", "Full name: Test.f") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker1*)", "val f") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker2*)", "property System.Console.BufferWidth: int") - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"(*Marker3*)","Full name: Test.printer") - [] - member public this.``Automation.Regression.ConstructorWithSameNameAsType.Bug2739``() = - let fileContent = """namespace AA - module AA = - type AA = | AA(*Marker1*) = 1 - | BB = 2 - type BB = { BB(*Marker2*) : string; }""" - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker1*)", "AA.AA: AA") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker2*)", "BB.BB: string") - [] - member public this.``Automation.Regression.EventImplementation.Bug5471``() = - let fileContent = """namespace regressiontest - open System - open System.Windows - open System.Windows.Input - - type CommandReference() = - inherit Freezable() - - static let commandProperty = - DependencyProperty.Register( - "Command", - typeof, - typeof, - PropertyMetadata(PropertyChangedCallback(fun o e -> CommandReference.OnCommandChanged(o, e)))) - - let evt = Event() - - member this.Command - with get () = this.GetValue(commandProperty) :?> ICommand - and set v = this.SetValue(commandProperty, (v: ICommand) ) - - interface ICommand with - - member this.CanExecute(parameter) = - if this.Command <> null then - this.Command.CanExecute(parameter) - else false - - member this.Execute(parameter) = - this.Command.Execute(parameter) - - [] - member x.CanExecuteChanged(*Marker*) = evt.Publish - - static member OnCommandChanged(d: DependencyObject, e: DependencyPropertyChangedEventArgs) = - let commandReference = (d :?> CommandReference) :> ICommand - let oldCommand = e.OldValue :?> ICommand - let newCommand = e.NewValue :?> ICommand - if oldCommand <> null then - // Error: This expression has type IEvent but is here used with type EventHandler - oldCommand.CanExecuteChanged.RemoveHandler(commandReference.CanExecuteChanged) - if newCommand <> null then - // Error: This expression has type IEvent but is here used with type EventHandler - newCommand.CanExecuteChanged.AddHandler(commandReference.CanExecuteChanged) - - override this.CreateInstanceCore() = - raise (NotImplementedException())""" - let (_, _, file) = this.CreateSingleFileProject(fileContent, references = ["PresentationCore"; "WindowsBase"]) - MoveCursorToStartOfMarker(file, "(*Marker*)") - let tooltip = time1 GetQuickInfoAtCursor file "Time of first tooltip" - AssertContains(tooltip, "override CommandReference.CanExecuteChanged: IEvent") - AssertContains(tooltip, "regressiontest.CommandReference.CanExecuteChanged") - [] - member public this.``Automation.ExtensionMethod``() = - let fileContent ="""namespace TestQuickinfo - - module BCLExtensions = - type System.Random with - /// BCL class Extension method - member this.NextDice() = this.Next() + 1 - /// new BCL class Extension method with overload - member this.NextDice(a : bool) = this.Next() + 1 - /// existing BCL class Extension method with overload - member this.Next(a : bool) = this.Next() + 1 - /// BCL class Extension property - member this.DiceValue with get() = 6 - - type System.ConsoleKeyInfo with - /// BCL struct extension method - member this.ExtensionMethod() = 100 - /// BCL struct extension property - member this.ExtensionProperty with get() = "Foo" - - module OwnCode = - /// fs class - type FSClass() = - class - /// fs class method original - member this.Method(a:string) = "" - /// fs class property original - member this.Prop with get(a:string) = "" - end - - /// fs struct - type FSStruct(x:int) = - struct - end - - module OwnCodeExtensions = - type OwnCode.FSClass with - /// fs class extension method - member this.ExtensionMethod() = 100 - - /// fs class extension property - member this.ExtensionProperty with get() = "Foo" - - /// fs class method extension overload - member this.Method(a:int) = "" - - /// fs class property extension overload - member this.Prop with get(a:int) = "" - - type OwnCode.FSStruct with - /// fs struct extension method - member this.ExtensionMethod() = 100 - - /// fs struct extension property - member this.ExtensionProperty with get() = "Foo" - - module BCLClass = - open BCLExtensions - let rnd = new System.Random() - rnd.DiceValue(*Marker11*) |>ignore - rnd.NextDice(*Marker12*)() |>ignore - rnd.NextDice(*Marker13*)(true) |>ignore - rnd.Next(*Marker14*)(true) |>ignore - - - module BCLStruct = - open BCLExtensions - let cki = new System.ConsoleKeyInfo() - cki.ExtensionMethod(*Marker21*) |>ignore - cki.ExtensionProperty(*Marker22*) |>ignore - - module OwnClass = - open OwnCode - open OwnCodeExtensions - let rnd = new FSClass() - rnd.ExtensionMethod(*Marker31*) |>ignore - rnd.ExtensionProperty(*Marker32*) |>ignore - rnd.Method(*Marker33*)("") |>ignore - rnd.Method(*Marker34*)(6) |>ignore - rnd.Prop(*Marker35*)("") |>ignore - rnd.Prop(*Marker36*)(6) |>ignore - - module OwnStruct = - open OwnCode - open OwnCodeExtensions - let cki = new FSStruct(100) - cki.ExtensionMethod(*Marker41*) |>ignore - cki.ExtensionProperty(*Marker42*) |>ignore""" - - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker11*)", "property System.Random.DiceValue: int") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker11*)", "BCL class Extension property") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker12*)", "member System.Random.NextDice: unit -> int") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker12*)", "BCL class Extension method") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker13*)", "member System.Random.NextDice: a: bool -> int") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker13*)", "new BCL class Extension method with overload") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker14*)", "member System.Random.Next: a: bool -> int") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker14*)", "existing BCL class Extension method with overload") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker21*)", "member System.ConsoleKeyInfo.ExtensionMethod: unit -> int") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker21*)", "BCL struct extension method") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker22*)", "System.ConsoleKeyInfo.ExtensionProperty: string") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker22*)", "BCL struct extension property") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker31*)", "member FSClass.ExtensionMethod: unit -> int") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker31*)", "fs class extension method") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker32*)", "FSClass.ExtensionProperty: string") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker32*)", "fs class extension property") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker33*)", "member FSClass.Method: a: string -> string") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker33*)", "fs class method original") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker34*)", "member FSClass.Method: a: int -> string") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker34*)", "fs class method extension overload") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker35*)", "property FSClass.Prop: string -> string") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker35*)", "fs class property original") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker36*)", "property FSClass.Prop: int -> string") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker36*)", "fs class property extension overload") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker41*)", "member FSStruct.ExtensionMethod: unit -> int") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker41*)", "fs struct extension method") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker42*)", "FSStruct.ExtensionProperty: string") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker42*)", "fs struct extension property") +(*------------------------------------------IDE automation starts here -------------------------------------------------*) - [] - member public this.``Automation.Regression.GenericFunction.Bug2868``() = - let fileContent ="""module Test - // Hovering over a generic function (generic argument decorated with [] attribute yields a bad tooltip - let F (f :_ -> float<_>) = fun x -> f (x+1.0) - let rec Gen<[] 'u> (f:float<'u> -> float<'u>) = - Gen(*Marker*)(F f)""" - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker*)", "val Gen: f: (float -> float) -> 'a") - this.VerifyQuickInfoDoesNotContainAnyAtStartOfMarker fileContent "(*Marker*)" "Exception" - this.VerifyQuickInfoDoesNotContainAnyAtStartOfMarker fileContent "(*Marker*)" "thrown" - - [] - member public this.``Automation.IdentifierHaveDiffMeanings``() = - let fileContent ="""namespace NS - module float(*Marker1_1*) = - - let GenerateTuple = fun x -> let tuple = (x,x.ToString(),(float(*Marker1_2*))x, ( fun y -> (y.ToString(),y+1)) ) - tuple - - let MySeq : (*Marker2_1*)seq = - seq(*Marker2_2*) { - - for i in 1..9 do - - let myTuple = GenerateTuple i - let fieldInt,fieldString,fieldFloat,_ = myTuple - yield fieldFloat - } - - let MySet : (*Marker3_1*)Set = - MySeq - |> Array.ofSeq - |> List.ofArray - |> Set(*Marker3_2*).ofList - let int(*Marker4_1*) : int(*Marker4_2*) = 1 - type int(*Marker4_3*)() = - member this.M = 1 - type T(*Marker5_1*)() = - [] - val mutable T : T - let T = new T() - let t = T.T.T.T(*Marker5_2*); - - type ValType() = - member this.Value with get(*Marker6_1*) () = 10 - and set(*Marker6_2*) x = x + 1 |> ignore""" - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker1_1*)", "module float") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker1_2*)", "val float: 'T -> float (requires member op_Explicit)") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker1_2*)", "Full name: Microsoft.FSharp.Core.Operators.float") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker1_3*)", "type float = System.Double") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker1_3*)", "Full name: Microsoft.FSharp.Core.float") - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"(*Marker2_1*)","type seq<'T> = System.Collections.Generic.IEnumerable<'T>") - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"(*Marker2_1*)","Full name: Microsoft.FSharp.Collections.seq<_>") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker2_2*)", "val seq: 'T seq -> 'T seq") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker2_2*)", "Full name: Microsoft.FSharp.Core.Operators.seq") - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"(*Marker3_1*)","type Set<'T (requires comparison)> =") - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"(*Marker3_1*)","Full name: Microsoft.FSharp.Collections.Set") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker3_2*)", "module Set") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker3_2*)", "Functional programming operators related to the Set<_> type") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker4_1*)", "val int: int") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker4_1*)", "Full name: NS.float.int") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker4_2*)", "type int = int32") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker4_2*)", "Full name: Microsoft.FSharp.Core.int") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker4_3*)", "type int =") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker4_3*)", "member M: int") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker5_1*)", "type T =") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker5_1*)", "new : unit -> T") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker5_1*)", "val mutable T: T") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker5_2*)", "T.T: T") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker6_1*)", "member ValType.Value : int") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker6_2*)", "member ValType.Value : int with set") - this.VerifyQuickInfoDoesNotContainAnyAtStartOfMarker fileContent "(*Marker6_2*)" "Microsoft.FSharp.Core.ExtraTopLevelOperators.set" - [] - member public this.``Automation.Regression.ModuleIdentifier.Bug2937``() = - let fileContent ="""module XXX(*Marker*) - type t = C3""" - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker*)", "module XXX") - this.VerifyQuickInfoDoesNotContainAnyAtStartOfMarker fileContent "(*Marker*)" "\n" - [] - member public this.``Automation.Regression.NamesArgument.Bug3818``() = - let fileContent ="""module m - [] - type T = class - end""" - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker1*)", "property System.AttributeUsageAttribute.AllowMultiple: bool") - - [] - member public this.``Automation.OnUnitsOfMeasure``() = - let fileContent ="""namespace TestQuickinfo - - module TestCase1 = - [] - /// this type represents kilogram in UOM - type kg - let mass(*Marker11*) = 2.0 - - module TestCase2 = - [] - /// use Set as the type name of UoM - type Set - - let v1 = [1.0 .. 2.0 .. 5.0] |> Seq.item 1 - - (if v1 = 3.0 then 0 else 1) |> ignore - - let twoSets = 2.0 - - [1.0] - |> Set.ofList - |> Set(*Marker22*).isEmpty - |> ignore""" - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker11*)", "val mass: float") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker11*)", "Full name: TestQuickinfo.TestCase1.mass") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker11*)", "inherits: System.ValueType") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker12*)", "[]") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker12*)", "type kg") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker12*)", "this type represents kilogram in UOM") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker12*)", "Full name: TestQuickinfo.TestCase1.kg") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker21*)", "[]") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker21*)", "type Set") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker21*)", "use Set as the type name of UoM") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker21*)", "Full name: TestQuickinfo.TestCase2.Set") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker22*)", "module Set") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker22*)", "from Microsoft.FSharp.Collections") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker22*)", "Functional programming operators related to the Set<_> type.") - [] - member public this.``Automation.OverRiddenMembers``() = - let fileContent ="""namespace QuickinfoGeneric - - module FSharpOwnCode = - [] - type TextOutputSink() = - abstract WriteChar : char -> unit - abstract WriteString : string -> unit - default x.WriteString(s) = s |> String.iter x.WriteChar - - type ByteOutputSink() = - inherit TextOutputSink() - default sink.WriteChar(c) = System.Console.Write(c) - override sink.WriteString(s) = System.Console.Write(s) - - let sink = new ByteOutputSink() - sink.WriteChar(*Marker11*)('c') - sink.WriteString(*Marker12*)("Hello World!")""" - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker11*)", "override ByteOutputSink.WriteChar: c: char -> unit") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker12*)", "override ByteOutputSink.WriteString: s: string -> unit") - [] - member public this.``Automation.Regression.QuotedIdentifier.Bug3790``() = - let fileContent ="""module Test - module ``Some``(*Marker1*) = Microsoft.FSharp.Collections.List - let _ = ``Some``(*Marker2*).append [] [] """ - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "``(*Marker1*)", "module List") - this.VerifyQuickInfoDoesNotContainAnyAtStartOfMarker fileContent "``(*Marker1*)" "Option.Some" - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "``(*Marker2*)", "module List") - this.VerifyQuickInfoDoesNotContainAnyAtStartOfMarker fileContent "``(*Marker2*)" "Option.Some" - - [] - member public this.``Automation.Setter``() = - let fileContent ="""type T() = - member this.XX - with set ((a:int), (b:int), (c:int)) = () - - (new T()).XX(*Marker1*) <- (1,2,3) - //=================================================== - // More cases: - //=================================================== - type IFoo = interface - abstract foo : int -> int - end - let i : IFoo = Unchecked.defaultof - i.foo(*Marker2*) |> ignore - //=================================================== - type Rec = { bar:int->int->int } - let r = {bar = fun x y -> x + y } - - r.bar(*Marker3*) 1 2 |>ignore - //=================================================== - type M() = - member this.baz x y = x + y - let m = new M() - m.baz(*Marker3*) 1 2 |>ignore - //=================================================== - type T2() = - member this.Foo(a,b) = "" - let t = new T2() - t.Foo(*Marker4*)(1,2) |>ignore - //=================================================== - let foo (x:int) (y:int) : int = 1 - foo(*Marker5*) 2 3 |> ignore""" - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker1*)", "T.XX: int * int * int") - this.VerifyQuickInfoDoesNotContainAnyAtStartOfMarker fileContent "(*Marker1*)" "->" - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker2*)", "IFoo.foo: int -> int") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker3*)", "Rec.bar: int -> int -> int") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker4*)", "T2.Foo: a: 'a * b: 'b -> string") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker5*)", "val foo: int -> int -> int") - [] - member public this.``Automation.Regression.TupleException.Bug3723``() = - let fileContent ="""namespace TestQuickinfo - exception E3(*Marker1*) of int * int - exception E4(*Marker2*) of (int * int) - exception E5(*Marker3*) = E4""" - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker1*)", "exception E3 of int * int") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker1*)", "Full name: TestQuickinfo.E3") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker2*)", "exception E4 of (int * int)") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker2*)", "Full name: TestQuickinfo.E4") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker3*)", "exception E5 = E4") - [] - member public this.``Automation.TypeAbbreviations``() = - let fileContent ="""namespace NS - module TypeAbbreviation = - - type MyInt(*Marker1_1*) = int - - type PairOfFloat(*Marker2_1*) = float * float - - - type AbAttrName(*Marker5_1*) = AbstractClassAttribute - - - type IA(*Marker3_1*) = - abstract AbstractMember : int -> int - - [] - type ClassIA(*Marker3_2*)() = - interface IA with - member this.AbstractMember x = x + 1 - - type GenericClass(*Marker4_1*)<'a when 'a :> IA>() = - static member StaticMember(x:'a) = x.AbstractMember(1) - let GenerateTuple = fun ( x : MyInt) -> - let myInt(*Marker1_2*),float1,float2,function1 = (x,(float)x,(float)x, ( fun y -> (y.ToString(),y+1)) ) - myInt,((float1,float2):PairOfFloat),function1 - let MySeq(*Marker2_2*) = - seq { - - for i in 1..9 do - let myInt,pairofFloat,function1 = GenerateTuple i - - yield pairofFloat - } - - let genericClass(*Marker4_2*) = new GenericClass()""" - - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker1_1*)", "type MyInt = int") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker1_2*)", "val myInt: MyInt") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker2_1*)", "type PairOfFloat = float * float") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker2_2*)", "val MySeq: PairOfFloat seq") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker3_1*)", "type IA =") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker3_2*)", "type ClassIA =") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker4_1*)", "type GenericClass<'a (requires 'a :> IA)> =") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker4_2*)", "val genericClass: GenericClass") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker5_1*)", "type AbAttrName = AbstractClassAttribute") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker5_2*)", "type AbAttrName = AbstractClassAttribute") - [] - member public this.``Automation.Regression.TypeInferenceScenarios.Bug2362&3538``() = - let fileContent ="""module Test.Module1 - open System - open System.Diagnostics - open System.Runtime.InteropServices - #nowarn "9" - let append m(*Marker1*) n(*Marker2*) = fun ac(*Marker3*) -> m (n ac) - type Foo() as this(*Marker4*) = - do this(*Marker5*) |> ignore - member this.Bar() = - this(*Marker6*) |> ignore - () - [] - type A = - [] - val mutable x : int - new () = { } - member this.Prop = this.x - - let x = new (*Marker7*)A()""" - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker1*)", "val m: ('a -> 'b)") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker2*)", "val n: ('c -> 'a)") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker3*)", "val ac: 'c") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker4*)", "val this: Foo") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker5*)", "val this: Foo") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker6*)", "val this: Foo") - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"(*Marker7*)","type A =") - this.AssertQuickInfoContainsAtEndOfMarker(fileContent,"(*Marker7*)","val mutable x: int") - [] - member public this.``Automation.Regression.TypemoduleConstructorLastLine.Bug2494``() = - let fileContent ="""namespace NS - open System - //regression test for bug 2494 - - type PriorityQueue(*MarkerType*)<'k,'a> = - | Nil(*MarkerDataConstructor*) - | Branch of 'k * 'a * PriorityQueue<'k,'a> * PriorityQueue<'k,'a> - - module PriorityQueue(*Marker3*) = - let empty = Nil - - let minKeyValue = function - | Nil -> failwith "empty queue" - | Branch(k,a,_,_) -> (k,a) - - let minKey pq = fst (minKeyValue pq(*MarkerVal*)) - - let singleton(*MarkerLastLine*) k a = Branch(k,a,Nil,Nil)""" - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*MarkerType*)", "type PriorityQueue") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*MarkerDataConstructor*)", "union case PriorityQueue.Nil: PriorityQueue<'k,'a>") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker3*)", "module PriorityQueue") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*MarkerVal*)", "val pq: PriorityQueue<'a,'b>") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*MarkerLastLine*)", "val singleton: k: 'a -> a: 'b -> PriorityQueue<'a,'b>") - [] - member public this.``Automation.WhereQuickInfoShouldNotShowUp``() = - let fileContent ="""namespace Test - - module Helper = - /// Tests if passed System.Numerics.BigInteger(*Marker1*) argument is prime - let IsPrime x = - let mutable i = 2I - let mutable foundFactor = false - while not foundFactor && i < x do - (* - the most naive way to test for number being prime - Works great for small int(*Marker2*) - *) - if x % i = 0I then - foundFactor <- true - i <- i + 1I - not foundFactor - - module App = - open Helper - - let sumOfAllPrimesUnder1Mi = - #if TEST_TWO_MI - seq(*Marker4*) { 1I .. 2000000I } - #else - seq { 1I .. 1000000I(*Marker7*) } - #endif - |> Seq.filter(IsPrime) - // find result after filtering seq(*Marker3*) - |> Seq.sum - - let myString hello = "hello"(*Marker5*) - - myString "myString"(*Marker8*) - |> Seq.filter (fun c -> int c > 75) - |> Seq.item 0 - |> (=) 'e'(*Marker6*) - |> ignore""" - this.VerifyQuickInfoDoesNotContainAnyAtStartOfMarker fileContent "(*Marker1*)" "BigInteger" - this.VerifyQuickInfoDoesNotContainAnyAtStartOfMarker fileContent "(*Marker2*)" "int" - this.VerifyQuickInfoDoesNotContainAnyAtStartOfMarker fileContent "(*Marker3*)" "seq" - this.VerifyQuickInfoDoesNotContainAnyAtStartOfMarker fileContent "(*Marker4*)" "seq" - this.VerifyQuickInfoDoesNotContainAnyAtStartOfMarker fileContent "(*Marker5*)" "hello" - this.VerifyQuickInfoDoesNotContainAnyAtStartOfMarker fileContent "(*Marker6*)" "char" - this.VerifyQuickInfoDoesNotContainAnyAtStartOfMarker fileContent "(*Marker7*)" "bigint" - this.VerifyQuickInfoDoesNotContainAnyAtStartOfMarker fileContent "(*Marker8*)" "myString" - - [] - member public this.``Automation.Regression.XmlDocComments.Bug3157``() = - let fileContent ="""namespace TestQuickinfo - module XmlComment = - /// XmlComment J - let func(*Marker*) x = - /// XmlComment K - let rec g x = 1 - g x""" - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker*)", "val func: x: 'a -> int") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker*)", "XmlComment J") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker*)", "Full name: TestQuickinfo.XmlComment.func") - this.VerifyQuickInfoDoesNotContainAnyAtStartOfMarker fileContent "(*Marker*)" "XmlComment K" - - [] - member public this.``Automation.Regression.XmlDocCommentsOnExtensionMembers.Bug138112``() = - let fileContent ="""module Module1 = - type T() = - /// XmlComment M1 - member this.M1() = () - type T with - /// XmlComment M2 - member this.M2() = () - module public Extension = - type T with - /// XmlComment M3 - member this.M3() = () - open Module1 - open Extension - - let x1 = T().M1(*Marker1*)() - let x2 = T().M2(*Marker2*)() - let x3 = T().M3(*Marker3*)()""" - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker1*)", "XmlComment M1") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker2*)", "XmlComment M2") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker3*)", "XmlComment M3") - - [] - member public this.XmlDocCommentsForArguments() = - let fileContent = """ - type bar() = - /// Test for members - /// x1 param! - member this.foo - (x1:int)= - System.Console.WriteLine(x1.ToString()) - - type Uni1 = - /// Test for unions - /// str of case1 - | Case1 of str: string - | None - - /// Test for exception types - /// value param - exception Ex1 of value: string - - // Methods - let f1 = (new bar()).foo(*Marker0*)(x1(*Marker1*) = 10) - let f2 = System.String.Concat(1, arg1(*Marker2*) = "") - - //Unions - let f3 = Case1(str(*Marker3*) = "10") - match f3 with - | Case1(str(*Marker4*) = "10") -> () - | _ -> () - - //Exceptions - let f4 = Ex1(value(*Marker5*) = "") - try - () - with - Ex1(value(*Marker6*) = v) -> () - - //Static parameters of type providers - type provType = N1.T - """ - - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker0*)", "Test for members") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker1*)", "x1 param!") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker2*)", "Concatenates the string representations of two specified objects.") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker3*)", "str of case1") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker4*)", "str of case1") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker5*)", "value param") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker6*)", "value param") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker7*)", "Param1 of string", - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Marker8*)", "Ignored", - addtlRefAssy = [PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll")]) member private this.VerifyUsingFsTestLib fileContent queries crossProject = use _guard = this.UsingNewVS() @@ -2952,139 +517,6 @@ query." AssertContains(tooltip, expectedTip) - [] - member public this.``Automation.XDelegateDUStructfromOwnCode``() = - let fileContent ="""module Test - - open FSTestLib - - open System.Runtime.InteropServices - let ctrlSignal = ref false - [] - extern void SetConsoleCtrlHandler(ControlEventHandler callback,bool add) - let ctrlEventHandlerStatic = new ControlEventHandler(MyCar.Run) - let ctrlEventHandlerInstance = new ControlEventHandler( (new MyCar(10, MyColors.Blue)).Repair ) - - let IsInstanceMethod (controlEventHandler:ControlEventHandler) = - // TC 32 Identifier Delegate Own Code Pattern Match - match controlEventHandler(*Marker1*).Method.IsStatic with - | true -> printf "It's not a instance method. " - | false -> printf " It's a instance method. " - - // TC 33 Event DiscUnion Own Code Quotation - let a = <@ MyDistance.Event(*Marker2*) @> - - let DelegateSeq = - seq { for i in 1..10 do - let newDelegate = new ControlEventHandler(MyCar.Run) - // TC 35 Identifier Delegate Own Code Comp Expression - yield newDelegate(*Marker3*) } - - let StructFieldSeq = - seq { for i in 1..10 do - let a = MyPoint((float)i,2.0) - // TC 36 Field Struct Own Code Comp Expression - yield a.X(*Marker4*) }""" - let queries = [("(*Marker1*)", "val controlEventHandler: ControlEventHandler"); - ("(*Marker2*)", "property MyDistance.Event: Event"); - ("(*Marker3*)", "val newDelegate: ControlEventHandler"); - ("(*Marker4*)", "property MyPoint.X: float"); - ("(*Marker4*)", "Gets and sets X")] - this.VerifyUsingFsTestLib fileContent queries false - - [] - member public this.``Automation.StructDelegateDUfromOwnCode``() = - let fileContent ="""module Test - - open FSTestLib - - open System.Runtime.InteropServices - let ctrlSignal = ref false - [] - extern void SetConsoleCtrlHandler(ControlEventHandler callback,bool add) - let ctrlEventHandlerStatic = new ControlEventHandler(MyCar.Run) - let ctrlEventHandlerInstance = new ControlEventHandler( (new MyCar(10, MyColors.Blue)).Repair ) - - let IsInstanceMethod (controlEventHandler:ControlEventHandler) = - // TC 32 Identifier Delegate Own Code Pattern Match - match controlEventHandler(*Marker1*).Method.IsStatic with - | true -> printf "It's not a instance method. " - | false -> printf " It's a instance method. " - - // TC 33 Event DiscUnion Own Code Quotation - let a = <@ MyDistance.Event(*Marker2*) @> - - - let DelegateSeq = - seq { for i in 1..10 do - let newDelegate = new ControlEventHandler(MyCar.Run) - // TC 35 Identifier Delegate Own Code Comp Expression - yield newDelegate(*Marker3*) } - - let StructFieldSeq = - seq { for i in 1..10 do - let a = MyPoint((float)i,2.0) - // TC 36 Field Struct Own Code Comp Expression - yield a.X(*Marker4*) }""" - let queries = [("(*Marker1*)", "val controlEventHandler: ControlEventHandler"); - ("(*Marker2*)", "property MyDistance.Event: Event"); - ("(*Marker3*)", "val newDelegate: ControlEventHandler"); - ("(*Marker4*)", "property MyPoint.X: float"); - ("(*Marker4*)", "Gets and sets X"); - ] - this.VerifyUsingFsTestLib fileContent queries false - - [] - member public this.``Automation.TupleRecordClassfromOwnCode``() = - let fileContent ="""module Test - - open FSTestLib - - let AbsTuple = fun x -> let tuple1 = (x,x.ToString(),(float)x, ( fun y -> (y.ToString(),y+1)) ) - let tuple2 = (-x,(-x).ToString(),(float)(-x), ( fun y -> (y.ToString(),y+1)) ) - if x >= 0 then - // TC 29 Self Tuple Own Code Imperative - tuple1(*Marker1*) - else - tuple2 - - let GenerateMyEmployee name age = - let a = MyEmployee.MakeDummy() - a.Name <- name - a.Age <- age - a.IsFTE <- System.Convert.ToBoolean(System.Random().Next(2)) - match a.IsFTE with - | true -> a - // TC 30 Operator Record Own Code Pattern Match - | _ -> MyEmployee(*Marker2*).MakeDummy() - - // TC 31 Self Class Own Code Quotation - let myCarQuot = <@ new MyCar(*Marker3*)(19,MyColors.Red) @> - - open System.Runtime.InteropServices - let ctrlSignal = ref false - [] - extern void SetConsoleCtrlHandler(ControlEventHandler callback,bool add) - let ctrlEventHandlerStatic = new ControlEventHandler(MyCar.Run) - let ctrlEventHandlerInstance = new ControlEventHandler( (new MyCar(10, MyColors.Blue)).Repair ) - - let MaxTuple x y = - let tuplex = (x,x.ToString() ) - let tupley = (y,(y).ToString()) - match x>y with - // TC 34 Operator Tuple Own Code Pattern Match - | true -> tuplex(*Marker4*) - | false -> tupley""" - let queries = [("(*Marker1*)", "val tuple1: int * string * float * (int -> string * int)"); - ("(*Marker2*)", "type MyEmployee"); - ("(*Marker2*)", "Full name: FSTestLib.MyEmployee"); - ("(*Marker3*)", "type MyCar"); - ("(*Marker3*)", "Full name: FSTestLib.MyCar"); - ("(*Marker4*)", "val tuplex: 'a * string") - ] - this.VerifyUsingFsTestLib fileContent queries false - -(*------------------------------------------IDE Query automation start -------------------------------------------------*) member private this.AssertQuickInfoInQuery(code: string, mark : string, expectedstring : string) = use _guard = this.UsingNewVS() @@ -3130,179 +562,6 @@ query." gpatcc.AssertExactly(0,0) - [] - // QuickInfo still works on valid operators in a query with errors elsewhere in it - member public this.``Query.WithError1.Bug196137``() = - let fileContent =""" - open DataSource - // get the product list, defined in another file, see AssertQuickInfoInQuery - let products = Products.getProductList() - let sortedProducts = - query { - for p in products do - let x = p.ProductID + "a" - sortBy p.ProductName(*Mark*) - select p - }""" - this.AssertQuickInfoInQuery (fileContent, "(*Mark*)", "Product.ProductName: string") - - [] - // QuickInfo still works on valid operators in a query with errors elsewhere in it - member public this.``Query.WithError2``() = - let fileContent =""" - open DataSource - let products = Products.getProductList() - let test = - query { - for p in products do - let x = p.ProductID + "1" - minBy(*Mark*) p.UnitPrice - }""" - this.AssertQuickInfoInQuery (fileContent, "(*Mark*)", "custom operation: minBy ('Value)") - - [] - // QuickInfo works in a large query (using many operators) - member public this.``Query.WithinLargeQuery``() = - let fileContent =""" - open DataSource - let products = Products.getProductList() - let numbers = [ 1;2; 8; 9; 15; 23; 3; 42; 4;0; 55;] - let largequery = - query { - for p in products do - sortBy p.ProductName - thenBy p.UnitPrice - thenByDescending p.Category - where (p.UnitsInStock < 100) - where (p.Category = "Condiments") - groupValBy(*Mark1*) p p.Category into g - let maxPrice = query { for x in g do maxBy(*Mark2*) x.UnitPrice } - let mostExpensiveProducts = query { for x in g do where (x.UnitPrice = maxPrice) } - select (g.Key, mostExpensiveProducts, query { - for n in numbers do - where (n%2 = 0) - where(*Mark3*) (n > 2) - where (n < 40) - select n}) - distinct(*Mark4*) - }""" - this.AssertQuickInfoInQuery (fileContent, "(*Mark1*)", "custom operation: groupValBy ('Value) ('Key)") - this.AssertQuickInfoInQuery (fileContent, "(*Mark2*)", "custom operation: maxBy ('Value)") - this.AssertQuickInfoInQuery (fileContent, "(*Mark3*)", "custom operation: where (bool)") - this.AssertQuickInfoInQuery (fileContent, "(*Mark4*)", "custom operation: distinct") - - [] - // Arguments to query operators have correct QuickInfo - // quickinfo should be correct including when the operator is causing an error - member public this.``Query.ArgumentToQuery.OperatorError``() = - let fileContent =""" - let numbers = [ 1;2; 8; 9; 15; 23; 3; 42; 4;0; 55;] - let foo = - query { - for n in numbers do - orderBy (n.GetType()) - select n}""" - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "n.GetType()", "val n: int",queryAssemblyRefs) - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "Type()", "System.Object.GetType() : System.Type",queryAssemblyRefs) - - [] - // Arguments to query operators have correct QuickInfo - // quickinfo should be correct In a nested query - member public this.``Query.ArgumentToQuery.InNestedQuery``() = - let fileContent =""" - open DataSource - let products = Products.getProductList() - let test1 = - query { - for p in products do - sortBy p.ProductName - select (p.ProductName, query { for f in products do - groupValBy(*Mark3*) f f.Category into g - let maxPrice = query { for x in g do maxBy x.UnitPrice } - let mostExpensiveProducts = query { for x in g do where(*Mark1*) (x.UnitPrice = maxPrice(*Mark2*)) } - select(*Mark4*) (g.Key, g)}) } """ - this.AssertQuickInfoInQuery (fileContent, "(*Mark1*)", "custom operation: where (bool)") - this.AssertQuickInfoInQuery (fileContent, "(*Mark2*)", "val maxPrice: decimal") - this.AssertQuickInfoInQuery (fileContent, "(*Mark3*)", "custom operation: groupValBy ('Value) ('Key)") - this.AssertQuickInfoInQuery (fileContent, "(*Mark4*)", "custom operation: select ('Result)") - - [] - // A computation expression with its own custom operators has correct QuickInfo displayed - member public this.``Query.ComputationExpression.Method``() = - let fileContent =""" - open System.Collections.Generic - let chars = ["A";"B";"C"] - type WorkflowBuilder() = - - let yieldedItems = new List() - member this.Items = yieldedItems |> Array.ofSeq - - member this.Yield(item) = yieldedItems.Add(item) - member this.YieldFrom(items : seq) = - items |> Seq.iter (fun item -> yieldedItems.Add(item.ToUpper())) - () - - member this.Combine(f, g) = g - member this.Delay (f : unit -> 'a) = - f() - - member this.Zero() = () - member this.Return _ = this.Items - - let computationExpreQuery = - query { - for char in chars do - let workflow = new WorkflowBuilder() - let result = - workflow { - yield "foo" - yield "bar" - yield! [| "a"; "b"; "c" |] - - return () - } - let t = workflow.Combine(*Mark1*)("a","b") - let d = workflow.Zero(*Mark2*)() - where (result |> Array.exists(fun i -> i = char)) - yield char - } """ - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Mark1*)", "member WorkflowBuilder.Combine: f: 'b0 * g: 'c1 -> 'c1",queryAssemblyRefs) - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Mark2*)", "member WorkflowBuilder.Zero: unit -> unit",queryAssemblyRefs) - - [] - // A computation expression with its own custom operators has correct QuickInfo displayed - member public this.``Query.ComputationExpression.CustomOp``() = - let fileContent =""" - open System - open Microsoft.FSharp.Quotations - - type EventBuilder() = - member _.For(ev:IObservable<'T>, loop:('T -> #IObservable<'U>)) : IObservable<'U> = failwith "" - member _.Yield(v:'T) : IObservable<'T> = failwith "" - member _.Quote(v:Quotations.Expr<'T>) : Expr<'T> = v - member _.Run(x:Expr<'T>) = Microsoft.FSharp.Linq.RuntimeHelpers.LeafExpressionConverter.EvaluateQuotation x :?> 'T - - [] - member _.Where (x, [] f) = Observable.filter f x - - [] - member _.Select (x, [] f) = Observable.map f x - - [] - member inline _.ScanSumBy (source, [] f : 'T -> 'U) : IObservable<'U> = Observable.scan (fun a b -> a + f b) LanguagePrimitives.GenericZero<'U> source - - let myquery = EventBuilder() - let f = new Event() - let e1 = - myquery { for x in f.Publish do - myWhere(*Mark1*) (fst x < 100) - scanSumBy(*Mark2*) (snd x) - } """ - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Mark1*)", "custom operation: myWhere (bool)") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Mark1*)", "Calls EventBuilder.Where") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Mark2*)", "custom operation: scanSumBy ('U)") - this.AssertQuickInfoContainsAtStartOfMarker (fileContent, "(*Mark2*)", "Calls EventBuilder.ScanSumBy") - // Context project system type UsingProjectSystem() = diff --git a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.QuickParse.fs b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.QuickParse.fs index 40efc4655a8..5f3c941d2b6 100644 --- a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.QuickParse.fs +++ b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.QuickParse.fs @@ -1,166 +1,11 @@ // Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. -namespace Tests.LanguageService - -open System -open Xunit -open FSharp.Compiler.EditorServices - -type QuickParse() = +// The QuickParse unit tests that used to live here (the CheckGetPartialLongName member and the +// CheckIsland0..CheckIsland50 members) were direct public-API tests of +// FSharp.Compiler.EditorServices.QuickParse with no Salsa harness. They were migrated to the +// cross-platform corpus at tests/FSharp.Compiler.Service.Tests/QuickParseTests.fs (M2 +// quickparse batch 1), where the CheckIsland family is a single parametrized Theory, the +// GetPartialLongNameEx checks are a second parametrized Theory, and the commented-out +// CheckIsland25 is a skipped Fact. This file is intentionally left as an empty namespace. - let CheckIsland(tolerateJustAfter:bool, s : string, p : int, expected) = - let actual = - match QuickParse.GetCompleteIdentifierIsland tolerateJustAfter s p with - | Some (s, col, _) -> Some (s, col) - | None -> None - Assert.Equal(expected, actual) - - [] - member public qp.CheckGetPartialLongName() = - let CheckAt(line, index, expected) = - let actual = QuickParse.GetPartialLongNameEx(line, index) - if (actual.QualifyingIdents, actual.PartialIdent, actual.LastDotPos) <> expected then - failwithf "Expected %A but got %A" expected actual - - let Check(line,expected) = - CheckAt(line, line.Length-1, expected) - - Check("let y = List.",(["List"], "", Some 12)) - Check("let y = List.conc",(["List"], "conc", Some 12)) - Check("let y = S", ([], "S", None)) - Check("S", ([], "S", None)) - Check("let y=", ([], "", None)) - Check("Console.Wr", (["Console"], "Wr", Some 7)) - Check(" .", ([""], "", Some 1)) - Check(".", ([""], "", Some 0)) - Check("System.Console.Wr", (["System";"Console"],"Wr", Some 14)) - Check("let y=f'", ([], "f'", None)) - Check("let y=SomeModule.f'", (["SomeModule"], "f'", Some 16)) - Check("let y=Some.OtherModule.f'", (["Some";"OtherModule"], "f'", Some 22)) - Check("let y=f'g", ([], "f'g", None)) - Check("let y=SomeModule.f'g", (["SomeModule"], "f'g", Some 16)) - Check("let y=Some.OtherModule.f'g", (["Some";"OtherModule"], "f'g", Some 22)) - Check("let y=FSharp.Data.File.``msft-prices.csv``", ([], "", None)) - Check("let y=FSharp.Data.File.``msft-prices.csv", (["FSharp";"Data";"File"], "msft-prices.csv", Some 22)) - Check("let y=SomeModule. f", (["SomeModule"], "f", Some 16)) - Check("let y=SomeModule .f", (["SomeModule"], "f", Some 18)) - Check("let y=SomeModule . f", (["SomeModule"], "f", Some 18)) - Check("let y=SomeModule .", (["SomeModule"], "", Some 18)) - Check("let y=SomeModule . ", (["SomeModule"], "", Some 18)) - - - [] - member public qp.CheckIsland0() = CheckIsland(true, "", -1, None) - [] - member public qp.CheckIsland1() = CheckIsland(false, "", -1, None) - - [] - member public qp.CheckIsland2() = CheckIsland(true, "", 0, None) - [] - member public qp.CheckIsland3() = CheckIsland(false, "", 0, None) - - [] - member public qp.CheckIsland4() = CheckIsland(true, null, 0, None) - [] - member public qp.CheckIsland5() = CheckIsland(false, null, 0, None) - - [] - member public qp.CheckIsland6() = CheckIsland(false, "identifier", 0, Some("identifier",10)) - [] - member public qp.CheckIsland7() = CheckIsland(false, "identifier", 8, Some("identifier",10)) - - [] - member public qp.CheckIsland8() = CheckIsland(true, "identifier", 0, Some("identifier",10)) - [] - member public qp.CheckIsland9() = CheckIsland(true, "identifier", 8, Some("identifier",10)) - - // A place where tolerateJustAfter matters - [] - member public qp.CheckIsland10() = CheckIsland(false, "identifier", 10, None) - [] - member public qp.CheckIsland11() = CheckIsland(true, "identifier", 10, Some("identifier",10)) - - // Index which overflows the line - [] - member public qp.CheckIsland12() = CheckIsland(true, "identifier", 11, None) - [] - member public qp.CheckIsland13() = CheckIsland(false, "identifier", 11, None) - - // Match active pattern identifiers - [] - member public qp.CheckIsland14() = CheckIsland(false, "|Identifier|", 0, Some("|Identifier|",12)) - [] - member public qp.CheckIsland15() = CheckIsland(true, "|Identifier|", 0, Some("|Identifier|",12)) - [] - member public qp.CheckIsland16() = CheckIsland(false, "|Identifier|", 12, None) - [] - member public qp.CheckIsland17() = CheckIsland(true, "|Identifier|", 12, Some("|Identifier|",12)) - [] - member public qp.CheckIsland18() = CheckIsland(false, "|Identifier|", 13, None) - [] - member public qp.CheckIsland19() = CheckIsland(true, "|Identifier|", 13, None) - - // ``Quoted`` identifiers - [] - member public qp.CheckIsland20() = CheckIsland(false, "``Space Man``", 0, Some("``Space Man``",13)) - [] - member public qp.CheckIsland21() = CheckIsland(true, "``Space Man``", 0, Some("``Space Man``",13)) - [] - member public qp.CheckIsland22() = CheckIsland(false, "``Space Man``", 10, Some("``Space Man``",13)) - [] - member public qp.CheckIsland23() = CheckIsland(true, "``Space Man``", 10, Some("``Space Man``",13)) - [] - member public qp.CheckIsland24() = CheckIsland(false, "``Space Man``", 11, Some("``Space Man``",13)) - // [] - // member public qp.CheckIsland25() = CheckIsland(true, "``Space Man``", 11, Some("Man",11)) // This is probably not what the user wanted. Not enforcing this test. - [] - member public qp.CheckIsland26() = CheckIsland(false, "``Space Man``", 12, Some("``Space Man``",13)) - [] - member public qp.CheckIsland27() = CheckIsland(true, "``Space Man``", 12, Some("``Space Man``",13)) - [] - member public qp.CheckIsland28() = CheckIsland(false, "``Space Man``", 13, None) - [] - member public qp.CheckIsland29() = CheckIsland(true, "``Space Man``", 13, Some("``Space Man``",13)) - [] - member public qp.CheckIsland30() = CheckIsland(false, "``Space Man``", 14, None) - [] - member public qp.CheckIsland31() = CheckIsland(true, "``Space Man``", 14, None) - [] - member public qp.CheckIsland32() = CheckIsland(true, "``msft-prices.csv``", 14, Some("``msft-prices.csv``",19)) - // handle extracting islands from arrays - [] - member public qp.CheckIsland33() = CheckIsland(true, "[|abc;def|]", 2, Some("abc",5)) - [] - member public qp.CheckIsland34() = CheckIsland(true, "[|abc;def|]", 4, Some("abc",5)) - [] - member public qp.CheckIsland35() = CheckIsland(true, "[|abc;def|]", 5, Some("abc",5)) - [] - member public qp.CheckIsland36() = CheckIsland(true, "[|abc;def|]", 6, Some("def",9)) - [] - member public qp.CheckIsland37() = CheckIsland(true, "[|abc;def|]", 8, Some("def",9)) - [] - member public qp.CheckIsland38() = CheckIsland(true, "[|abc;def|]", 9, Some("def",9)) - [] - member public qp.CheckIsland39() = CheckIsland(false, "identifier(*boo*)", 0, Some("identifier",10)) - [] - member public qp.CheckIsland40() = CheckIsland(true, "identifier(*boo*)", 0, Some("identifier",10)) - [] - member public qp.CheckIsland41() = CheckIsland(false, "identifier(*boo*)", 10, None) - [] - member public qp.CheckIsland42() = CheckIsland(true, "identifier(*boo*)", 10, Some("identifier",10)) - [] - member public qp.CheckIsland43() = CheckIsland(false, "identifier(*boo*)", 11, None) - [] - member public qp.CheckIsland44() = CheckIsland(true, "identifier(*boo*)", 11, None) - [] - member public qp.CheckIsland45() = CheckIsland(false, "``Space Man (*boo*)``", 13, Some("``Space Man (*boo*)``",21)) - [] - member public qp.CheckIsland46() = CheckIsland(true, "``Space Man (*boo*)``", 13, Some("``Space Man (*boo*)``",21)) - [] - member public qp.CheckIsland47() = CheckIsland(false, "(*boo*)identifier", 11, Some("identifier",17)) - [] - member public qp.CheckIsland48() = CheckIsland(true, "(*boo*)identifier", 11, Some("identifier",17)) - [] - member public qp.CheckIsland49() = CheckIsland(false, "identifier(*(* *)boo*)", 0, Some("identifier",10)) - [] - member public qp.CheckIsland50() = CheckIsland(true, "identifier(*(* *)boo*)", 0, Some("identifier",10)) +namespace Tests.LanguageService diff --git a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.Script.fs b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.Script.fs index dbb2b996de2..43b5ec39b99 100644 --- a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.Script.fs +++ b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.Script.fs @@ -130,775 +130,6 @@ type UsingMSBuild() as this = let tooltip = GetQuickInfoAtCursor file AssertNotContains(tooltip, notexpected) - /// There was a problem with Salsa that caused squiggles not to be shown for .fsx files. - [] - member public this.``Fsx.Squiggles.ShowInFsxFiles``() = - let fileContent = """open Thing1.Thing2""" - this.VerifyFSXErrorListContainedExpectedString(fileContent,"Thing1") - - /// Regression test for FSharp1.0:4861 - #r to nonexistent file causes the first line to be squiggled - /// There was a problem with Salsa that caused squiggles not to be shown for .fsx files. - [] - member public this.``Fsx.Hash.RProperSquiggleForNonExistentFile``() = - let fileContent = """#r "NonExistent" """ - this.VerifyFSXErrorListContainedExpectedString(fileContent,"was not found or is invalid") - - /// Nonexistent hash. There was a problem with Salsa that caused squiggles not to be shown for .fsx files. - [] - member public this.``Fsx.Hash.RDoesNotExist.Bug3325``() = - let fileContent = """#r "ThisDLLDoesNotExist" """ - this.VerifyFSXErrorListContainedExpectedString(fileContent,"'ThisDLLDoesNotExist' was not found or is invalid") - - // There was a spurious error message on the first line. - [] - member public this.``Fsx.ExactlyOneError.Bug4861``() = - let code = - ["//" // First line is important in this repro - "#r \"Nonexistent\"" - ] - let (project, _) = createSingleFileFsxFromLines code - AssertExactlyCountErrorSeenContaining(project, "Nonexistent", 1) // ...and not an error on the first line. - - [] - member public this.``Fsx.InvalidHashLoad.ShouldBeASquiggle.Bug3012``() = - let fileContent = """ - #load "Bar.fs" - """ - this.VerifyFSXErrorListContainedExpectedString(fileContent,"Bar.fs") - - // Transitive to existing property. - [] - member public this.``Fsx.ScriptClosure.TransitiveLoad1``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let file1 = AddFileFromText(project,"File1.fs", - ["namespace Namespace" - "type Foo = " - " static member public Property = 0" - ]) - let file1 = OpenFile(project,"File1.fs") - let script2 = AddFileFromText(project,"Script2.fsx", - ["#load \"File1.fs\"" - ]) - let script2 = OpenFile(project,"Script2.fsx") - let script2 = AddFileFromText(project,"Script1.fsx", - ["#load \"Script1.fsx\"" - "Namespace.Foo.Property" - ]) - let script2 = OpenFile(project,"Script2.fsx") - TakeCoffeeBreak(this.VS) - AssertNoErrorsOrWarnings(project) - - // Transitive to nonexisting property. - [] - member public this.``Fsx.ScriptClosure.TransitiveLoad2``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let file1 = AddFileFromText(project,"File1.fs", - ["namespace Namespace" - "type Foo = " - " static member public Property = 0" - ]) - let script2 = AddFileFromText(project,"Script2.fsx", - ["#load \"File1.fs\"" - ]) - let script1 = AddFileFromText(project,"Script1.fsx", - ["#load \"Script2.fsx\"" - "Namespace.Foo.NonExistingProperty" - ]) - let script1 = OpenFile(project,"Script1.fsx") - TakeCoffeeBreak(this.VS) - AssertExactlyOneErrorSeenContaining(project, "NonExistingProperty") - - /// FEATURE: Typing a #r into a file will cause it to be recognized by intellisense. - [] - member public this.``Fsx.HashR.AddedIn``() = - let code = - [ - "//#r \"System.Transactions.dll\"" // Pick anything that isn't in the standard set of assemblies. - "open System.Transactions" - ] - let (project, file) = createSingleFileFsxFromLines code - VerifyErrorListContainedExpectedStr("Transactions",project) - - let gpatcc = GlobalParseAndTypeCheckCounter.StartNew(this.VS) - ReplaceFileInMemory file - [ - "#r \"System.Transactions.dll\"" // <-- Uncomment this line - "open System.Transactions" - ] - AssertNoErrorsOrWarnings(project) - gpatcc.AssertExactly(notAA[file],notAA[file], true (* expectCreate, because dependent DLL set changed *)) - - // FEATURE: Adding a #load to a file will cause types from that file to be visible in intellisense - [] - member public this.``Fsx.HashLoad.Added``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let fs = AddFileFromText(project,"File1.fs", - [ - "namespace MyNamespace" - " module MyModule =" - " let x = 1" - ]) - - let fsx = AddFileFromText(project,"File2.fsx", - [ - "//#load \"File1.fs\"" - "open MyNamespace.MyModule" - "printfn \"%d\" x" - ]) - let fsx = OpenFile(project,"File2.fsx") - VerifyErrorListContainedExpectedStr("MyNamespace",project) - - ReplaceFileInMemory fsx - [ - "#load \"File1.fs\"" - "open MyNamespace.MyModule" - "printfn \"%d\" x" - ] - TakeCoffeeBreak(this.VS) - AssertNoErrorsOrWarnings(project) - - // FEATURE: Removing a #load to a file will cause types from that file to no longer be visible in intellisense - [] - member public this.``Fsx.HashLoad.Removed``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let fs = AddFileFromText(project,"File1.fs", - [ - "namespace MyNamespace" - " module MyModule =" - " let x = 1" - ]) - - let fsx = AddFileFromText(project,"File2.fsx", - [ - "#load \"File1.fs\"" - "open MyNamespace.MyModule" - "printfn \"%d\" x" - ]) - let fsx = OpenFile(project,"File2.fsx") - AssertNoErrorsOrWarnings(project) - - ReplaceFileInMemory fsx - [ - "//#load \"File1.fs\"" - "open MyNamespace.MyModule" - "printfn \"%d\" x" - ] - TakeCoffeeBreak(this.VS) - VerifyErrorListContainedExpectedStr("MyNamespace",project) - - [] - member public this.``Fsx.HashLoad.Conditionals``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let fs = AddFileFromText(project,"File1.fs", - ["module InDifferentFS" - "#if INTERACTIVE" - "let x = 1" - "#else" - "let y = 2" - "#endif" - "#if DEBUG" - "let A = 3" - "#else" - "let B = 4" - "#endif" - ]) - - let fsx = AddFileFromText(project,"File2.fsx", - [ - "#load \"File1.fs\"" - "InDifferentFS." - ]) - let fsx = OpenFile(project,"File2.fsx") - - MoveCursorToEndOfMarker(fsx, "InDifferentFS.") - let completion = AutoCompleteAtCursor fsx - let completion = completion |> Array.map (fun (CompletionItem(name, _, _, _, _)) -> name) |> set - Assert.Equal(Set.count completion, 2) - Assert.True(completion.Contains "x", "Completion list should contain x because INTERACTIVE is defined") - Assert.True(completion.Contains "B", "Completion list should contain B because DEBUG is not defined") - - - /// FEATURE: Removing a #r into a file will cause it to no longer be seen by intellisense. - [] - member public this.``Fsx.HashR.Removed``() = - let code = - [ - "#r \"System.Transactions.dll\"" // Pick anything that isn't in the standard set of assemblies. - "open System.Transactions" - ] - let (project, file) = createSingleFileFsxFromLines code - TakeCoffeeBreak(this.VS) - AssertNoErrorsOrWarnings(project) - - let gpatcc = GlobalParseAndTypeCheckCounter.StartNew(this.VS) - ReplaceFileInMemory file - [ - "//#r \"System.Transactions.dll\"" // <-- Comment this line - "open System.Transactions" - ] - SaveFileToDisk(file) - TakeCoffeeBreak(this.VS) - VerifyErrorListContainedExpectedStr("Transactions",project) - gpatcc.AssertExactly(notAA[file], notAA[file], true (* expectCreate, because dependent DLL set changed *)) - - - - // Corecursive load to existing property. - [] - member public this.``Fsx.NoError.ScriptClosure.TransitiveLoad3``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let file1 = AddFileFromText(project,"File1.fs", - ["namespace Namespace" - "type Foo = " - " static member public Property = 0" - ]) - let script2 = AddFileFromText(project,"Script2.fsx", - ["#load \"Script1.fsx\"" - "#load \"File1.fs\"" - ]) - let script1 = AddFileFromText(project,"Script1.fsx", - ["#load \"Script2.fsx\"" - "#load \"File1.fs\"" - "Namespace.Foo.Property" - ]) - let script1 = OpenFile(project,"Script1.fsx") - TakeCoffeeBreak(this.VS) - AssertNoErrorsOrWarnings(project) - - // #load of .fsi is respected (for non-hidden property) - [] - member public this.``Fsx.NoError.ScriptClosure.TransitiveLoad9``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let file1fsi = AddFileFromText(project,"File1.fsi", - ["namespace Namespace" - "type Foo =" - " class" - " static member Property : int" // Not exposing 'HiddenProperty' - " end" - ]) - let file1 = AddFileFromText(project,"File1.fs", - ["namespace Namespace" - "type Foo = " - " static member public HiddenProperty = 0" - " static member public Property = 0" - ]) - - let script1 = AddFileFromText(project,"Script1.fsx", - ["#load \"File1.fsi\"" - "#load \"File1.fs\"" - "Namespace.Foo.Property" - ]) - let script1 = OpenFile(project,"Script1.fsx") - AssertNoErrorsOrWarnings(project) - - // #load of .fsi is respected at second #load level (for non-hidden property) - [] - member public this.``Fsx.NoError.ScriptClosure.TransitiveLoad10``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let file1fsi = AddFileFromText(project,"File1.fsi", - ["namespace Namespace" - "type Foo =" - " class" - " static member Property : int" // Not exposing 'HiddenProperty' - " end" - ]) - let file1 = AddFileFromText(project,"File1.fs", - ["namespace Namespace" - "type Foo = " - " static member public HiddenProperty = 0" - " static member public Property = 0" - ]) - - let script1 = AddFileFromText(project,"Script1.fsx", - ["#load \"File1.fsi\"" - "#load \"File1.fs\"" - ]) - let script2 = AddFileFromText(project,"Script2.fsx", - ["#load \"Script1.fsx\"" - "Namespace.Foo.Property" - ]) - let script2 = OpenFile(project,"Script2.fsx") - AssertNoErrorsOrWarnings(project) - - // #load of .fsi is respected when dispersed between two #load levels (for non-hidden property) - [] - member public this.``Fsx.NoError.ScriptClosure.TransitiveLoad11``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let file1fsi = AddFileFromText(project,"File1.fsi", - ["namespace Namespace" - "type Foo =" - " class" - " static member Property : int" // Not exposing 'HiddenProperty' - " end" - ]) - let file1 = AddFileFromText(project,"File1.fs", - ["namespace Namespace" - "type Foo = " - " static member public HiddenProperty = 0" - " static member public Property = 0" - ]) - - let script1 = AddFileFromText(project,"Script1.fsx", - ["#load \"File1.fsi\"" - ]) - let script2 = AddFileFromText(project,"Script2.fsx", - ["#load \"Script1.fsx\"" - "#load \"File1.fs\"" - "Namespace.Foo.Property" - ]) - let script2 = OpenFile(project,"Script2.fsx") - AssertNoErrorsOrWarnings(project) - - // #load of .fsi is respected when dispersed between two #load levels (the other way) (for non-hidden property) - [] - member public this.``Fsx.NoError.ScriptClosure.TransitiveLoad12``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let file1fsi = AddFileFromText(project,"File1.fsi", - ["namespace Namespace" - "type Foo =" - " class" - " static member Property : int" // Not exposing 'HiddenProperty' - " end" - ]) - let file1 = AddFileFromText(project,"File1.fs", - ["namespace Namespace" - "type Foo = " - " static member public HiddenProperty = 0" - " static member public Property = 0" - ]) - - let script1 = AddFileFromText(project,"Script1.fsx", - ["#load \"File1.fs\"" - ]) - let script2 = AddFileFromText(project,"Script2.fsx", - ["#load \"File1.fsi\"" - "#load \"Script1.fsx\"" - "Namespace.Foo.Property" - ]) - let script2 = OpenFile(project,"Script2.fsx") - AssertNoErrorsOrWarnings(project) - - // #nowarn seen in closed .fsx is global to the closure - [] - member public this.``Fsx.NoError.ScriptClosure.TransitiveLoad16``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let thisProject = AddFileFromText(project,"ThisProject.fsx", - ["#nowarn \"44\"" - ]) - let script1 = AddFileFromText(project,"Script1.fsx", - ["#load \"ThisProject.fsx\"" // Should bring in #nowarn "44" so we don't see this warning: - "[]" - "let fn x = 0" - "let y = fn 1" - ]) - - let script1 = OpenFile(project,"Script1.fsx") - MoveCursorToEndOfMarker(script1,"let y = f") - TakeCoffeeBreak(this.VS) - AssertExactlyOneErrorSeenContaining(project, "This construct is deprecated. x") // This is expected for langVersion >= 10.0 - - /// FEATURE: #r in .fsx to a .dll name works. - [] - member public this.``Fsx.NoError.HashR.DllWithNoPath``() = - let fileContent = """ - #r "System.Transactions.dll" - open System.Transactions""" - this.VerifyFSXNoErrorList(fileContent) - - - [] - // 'System' is in the default set. Make sure we can still resolve it. - member public this.``Fsx.NoError.HashR.BugDefaultReferenceFileIsAlsoResolved``() = - let fileContent = """ - #r "System" - """ - this.VerifyFSXNoErrorList(fileContent) - - [] - member public this.``Fsx.NoError.HashR.DoubleReference``() = - let fileContent = """ - #r "System" - #r "System" - """ - this.VerifyFSXNoErrorList(fileContent) - - [] - // 'CustomMarshalers' is loaded from the GAC _and_ it is available on XP and above. - member public this.``Fsx.NoError.HashR.ResolveFromGAC``() = - let fileContent = """ - #r "CustomMarshalers" - """ - this.VerifyFSXNoErrorList(fileContent) - - [] - member public this.``Fsx.NoError.HashR.ResolveFromFullyQualifiedPath``() = - let fullyqualifiepathtoddll = System.IO.Path.Combine( System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory(), "System.configuration.dll" ) - let code = ["#r @\"" + fullyqualifiepathtoddll + "\""] - let (project, _) = createSingleFileFsxFromLines code - AssertNoErrorsOrWarnings(project) - - [] - member public this.``Fsx.NoError.HashR.RelativePath1``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let file1 = AddFileFromText(project,"lib.fs", - ["module Lib" - "let X = 42" - ]) - - let bld = Build(project) - - let script1Dir = Path.Combine(ProjectDirectory(project), "ccc") - let script1Path = Path.Combine(script1Dir, "Script1.fsx") - let script2Dir = Path.Combine(ProjectDirectory(project), "aaa\\bbb") - let script2Path = Path.Combine(script2Dir, "Script2.fsx") - - Directory.CreateDirectory(script1Dir) |> ignore - Directory.CreateDirectory(script2Dir) |> ignore - File.Move(bld.ExecutableOutput, Path.Combine(ProjectDirectory(project), "aaa\\lib.exe")) - - let script1 = File.WriteAllLines(script1Path, - ["#load \"../aaa/bbb/Script2.fsx\"" - "printfn \"%O\" Lib.X" - ]) - let script2 = File.WriteAllLines(script2Path, - ["#r \"../lib.exe\"" - ]) - - let script1 = OpenFile(project, script1Path) - TakeCoffeeBreak(this.VS) - - MoveCursorToEndOfMarker(script1,"#load") - let ans = GetSquiggleAtCursor(script1) - AssertNoSquiggle(ans) - - [] - member public this.``Fsx.NoError.HashR.RelativePath2``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let file1 = AddFileFromText(project,"lib.fs", - ["module Lib" - "let X = 42" - ]) - - let bld = Build(project) - - let script1Dir = Path.Combine(ProjectDirectory(project), "ccc") - let script1Path = Path.Combine(script1Dir, "Script1.fsx") - let script2Dir = Path.Combine(ProjectDirectory(project), "aaa") - let script2Path = Path.Combine(script2Dir, "Script2.fsx") - - Directory.CreateDirectory(script1Dir) |> ignore - Directory.CreateDirectory(script2Dir) |> ignore - File.Move(bld.ExecutableOutput, Path.Combine(ProjectDirectory(project), "aaa\\lib.exe")) - - let script1 = File.WriteAllLines(script1Path, - ["#load \"../aaa/Script2.fsx\"" - "printfn \"%O\" Lib.X" - ]) - let script2 = File.WriteAllLines(script2Path, - ["#r \"lib.exe\"" - ]) - - let script1 = OpenFile(project, script1Path) - TakeCoffeeBreak(this.VS) - - MoveCursorToEndOfMarker(script1,"#load") - let ans = GetSquiggleAtCursor(script1) - AssertNoSquiggle(ans) - - /// FEATURE: #load in an .fsx file will include that file in the 'build' of the .fsx. - [] - member public this.``Fsx.NoError.HashLoad.Simple``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let fs = AddFileFromText(project,"File1.fs", - [ - "namespace MyNamespace" - " module MyModule =" - " let x = 1" - ]) - - let fsx = AddFileFromText(project,"File2.fsx", - [ - "#load \"File1.fs\"" - "open MyNamespace.MyModule" - "printfn \"%d\" x" - ]) - let fsx = OpenFile(project,"File2.fsx") - AssertNoErrorsOrWarnings(project) - - // In this bug the #loaded file contains a level-4 warning (copy to avoid mutation). This warning was reported at the #load in file2.fsx but shouldn't have been.s - [] - member public this.``Fsx.NoWarn.OnLoadedFile.Bug4837``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let fs = AddFileFromText(project,"File1.fs", - ["module File1Module" - "let x = System.DateTime.Now - System.DateTime.Now" - "x.Add(x) |> ignore" - ]) - - let fsx = AddFileFromText(project,"File2.fsx", - [ - "#load \"File1.fs\"" - ]) - let fsx = OpenFile(project,"File2.fsx") - AssertNoErrorsOrWarnings(project) - - /// FEATURE: .fsx files have automatic imports of certain system assemblies. - //There is a test bug here. The actual scenario works. Need to revisit. - [] - member public this.``Fsx.NoError.AutomaticImportsForFsxFiles``() = - let fileContent = """ - open System - open System.Xml - open System.Drawing - open System.Runtime.Remoting - open System.Runtime.Serialization.Formatters.Soap - open System.Data - open System.Drawing - open System.Web - open System.Web.Services - open System.Windows.Forms""" - this.VerifyFSXNoErrorList(fileContent) - - // Corecursive load to nonexisting property. - [] - member public this.``Fsx.ExactlyOneError.ScriptClosure.TransitiveLoad4``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let file1 = AddFileFromText(project,"File1.fs", - ["namespace Namespace" - "type Foo = " - " static member public Property = 0" - ]) - let script2 = AddFileFromText(project,"Script2.fsx", - ["#load \"Script1.fsx\"" - "#load \"File1.fs\"" - ]) - let script1 = AddFileFromText(project,"Script1.fsx", - ["#load \"Script2.fsx\"" - "#load \"File1.fs\"" - "Namespace.Foo.NonExistingProperty" - ]) - let script1 = OpenFile(project,"Script1.fsx") - AssertExactlyOneErrorSeenContaining(project, "NonExistingProperty") - - // #load of .fsi is respected - [] - member public this.``Fsx.ExactlyOneError.ScriptClosure.TransitiveLoad5``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let file1fsi = AddFileFromText(project,"File1.fsi", - ["namespace Namespace" - "type Foo =" - " class" - " static member Property : int" // Not exposing 'HiddenProperty' - " end" - ]) - let file1 = AddFileFromText(project,"File1.fs", - ["namespace Namespace" - "type Foo = " - " static member public HiddenProperty = 0" - " static member public Property = 0" - ]) - - let script1 = AddFileFromText(project,"Script1.fsx", - ["#load \"File1.fsi\"" - "#load \"File1.fs\"" - "Namespace.Foo.HiddenProperty" - ]) - let script1 = OpenFile(project,"Script1.fsx") - AssertExactlyOneErrorSeenContaining(project, "HiddenProperty") - - // #load of .fsi is respected at second #load level - [] - member public this.``Fsx.ExactlyOneError.ScriptClosure.TransitiveLoad6``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let file1fsi = AddFileFromText(project,"File1.fsi", - ["namespace Namespace" - "type Foo =" - " class" - " static member Property : int" // Not exposing 'HiddenProperty' - " end" - ]) - let file1 = AddFileFromText(project,"File1.fs", - ["namespace Namespace" - "type Foo = " - " static member public HiddenProperty = 0" - " static member public Property = 0" - ]) - - let script1 = AddFileFromText(project,"Script1.fsx", - ["#load \"File1.fsi\"" - "#load \"File1.fs\"" - ]) - let script2 = AddFileFromText(project,"Script2.fsx", - ["#load \"Script1.fsx\"" - "Namespace.Foo.HiddenProperty" - ]) - let script2 = OpenFile(project,"Script2.fsx") - AssertExactlyOneErrorSeenContaining(project, "HiddenProperty") - - // #load of .fsi is respected when dispersed between two #load levels - [] - member public this.``Fsx.ExactlyOneError.ScriptClosure.TransitiveLoad7``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let file1fsi = AddFileFromText(project,"File1.fsi", - ["namespace Namespace" - "type Foo =" - " class" - " static member Property : int" // Not exposing 'HiddenProperty' - " end" - ]) - let file1 = AddFileFromText(project,"File1.fs", - ["namespace Namespace" - "type Foo = " - " static member public HiddenProperty = 0" - " static member public Property = 0" - ]) - - let script1 = AddFileFromText(project,"Script1.fsx", - ["#load \"File1.fsi\"" - ]) - let script2 = AddFileFromText(project,"Script2.fsx", - ["#load \"Script1.fsx\"" - "#load \"File1.fs\"" - "Namespace.Foo.HiddenProperty" - ]) - let script2 = OpenFile(project,"Script2.fsx") - AssertExactlyOneErrorSeenContaining(project, "HiddenProperty") - - // #load of .fsi is respected when dispersed between two #load levels (the other way) - [] - member public this.``Fsx.ExactlyOneError.ScriptClosure.TransitiveLoad8``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let file1fsi = AddFileFromText(project,"File1.fsi", - ["namespace Namespace" - "type Foo =" - " class" - " static member Property : int" // Not exposing 'HiddenProperty' - " end" - ]) - let file1 = AddFileFromText(project,"File1.fs", - ["namespace Namespace" - "type Foo = " - " static member public HiddenProperty = 0" - " static member public Property = 0" - ]) - - let script1 = AddFileFromText(project,"Script1.fsx", - ["#load \"File1.fs\"" - ]) - let script2 = AddFileFromText(project,"Script2.fsx", - ["#load \"File1.fsi\"" - "#load \"Script1.fsx\"" - "Namespace.Foo.HiddenProperty" - ]) - let script2 = OpenFile(project,"Script2.fsx") - AssertExactlyOneErrorSeenContaining(project, "HiddenProperty") - - // Bug seen during development: A #load in an .fs would be followed. - [] - member public this.``Fsx.ExactlyOneError.ScriptClosure.TransitiveLoad15``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let file2 = AddFileFromText(project,"File2.fs", - ["namespace Namespace" - "type Type() =" - " static member Property = 0" - ]) - let file1 = AddFileFromText(project,"File1.fs", - ["#load \"File2.fs\"" // This is not allowed but it was working anyway. - "namespace File2Namespace" - ]) - let script1 = AddFileFromText(project,"Script1.fsx", - ["#load \"File1.fs\"" - "Namespace.Type.Property" - ]) - - let script1 = OpenFile(project,"Script1.fsx") - TakeCoffeeBreak(this.VS) - AssertExactlyOneErrorSeenContaining(project, "Namespace") - - [] - member public this.``Fsx.Bug4311HoverOverReferenceInFirstLine``() = - let fileContent = """#r "PresentationFramework.dll" - - #r "PresentationCore.dll" """ - let marker = "#r \"PresentationFrame" - this.AssertQuickInfoContainsAtEndOfMarkerInFsxFile fileContent marker "PresentationFramework.dll" - this.AssertQuickInfoNotContainsAtEndOfMarkerInFsxFile fileContent marker "multiple results" - - [] - member public this.``Fsx.QuickInfo.Bug4979``() = - let code = - ["System.ConsoleModifiers.Shift |> ignore " - "(3).ToString().Length |> ignore "] - let (project, file) = createSingleFileFsxFromLines code - MoveCursorToEndOfMarker(file, "System.ConsoleModifiers.Sh") - let tooltip = GetQuickInfoAtCursor file - AssertContains(tooltip, @"The left or right SHIFT modifier key.") - - MoveCursorToEndOfMarker(file, "(3).ToString().Len") - let tooltip = GetQuickInfoAtCursor file - AssertContains(tooltip, @"[Signature:P:System.String.Length]") // A message from the mock IDocumentationBuilder - AssertContains(tooltip, @"[Filename:") - AssertContains(tooltip, @"netstandard.dll]") // The assembly we expect the documentation to get taken from - - // Especially under 4.0 we need #r of .NET framework assemblies to resolve from like, - // - // %program files%\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0 - // - // because this is where the .XML files are. - // - // When executing scripts, however, we need to _not_ resolve from these directories because - // they may be metadata-only assemblies. - // - // "Reference Assemblies" was only introduced in 3.5sp1, so not all 2.0 F# boxes will have it, so only run on 4.0 - [] - member public this.``Fsx.Bug5073``() = - let fileContent = """#r "System" """ - let marker = "#r \"System" - this.AssertQuickInfoContainsAtEndOfMarkerInFsxFile fileContent marker @"Reference Assemblies\Microsoft" - this.AssertQuickInfoContainsAtEndOfMarkerInFsxFile fileContent marker ".NET Framework" - /// FEATURE: Hovering over a resolved #r file will show a data tip with the fully qualified path to that file. [] member public this.``Fsx.HashR_QuickInfo.ShowFilenameOfResolvedAssembly``() = @@ -906,290 +137,6 @@ type UsingMSBuild() as this = """#r "System.Transactions" """ // Pick anything that isn't in the standard set of assemblies. "#r \"System.Tra" "System.Transactions.dll" - [] - member public this.``Fsx.HashR_QuickInfo.BugDefaultReferenceFileIsAlsoResolved``() = - this.AssertQuickInfoContainsAtEndOfMarkerInFsxFile - """#r "System" """ // 'System' is in the default set. Make sure we can still resolve it. - "#r \"Syst" "System.dll" - - [] - member public this.``Fsx.HashR_QuickInfo.DoubleReference``() = - let fileContent = """#r "System" // Mark1 - #r "System" // Mark2 """ // The same reference repeated twice. - this.AssertQuickInfoContainsAtStartOfMarkerInFsxFile fileContent "tem\" // Mark1" "System.dll" - this.AssertQuickInfoContainsAtStartOfMarkerInFsxFile fileContent "tem\" // Mark2" "System.dll" - - [] - member public this.``Fsx.HashR_QuickInfo.ResolveFromGAC``() = - this.AssertQuickInfoContainsAtEndOfMarkerInFsxFile - """#r "CustomMarshalers" """ // 'mscorcfg' is loaded from the GAC _and_ it is available on XP and above. - "#r \"Custo" ".NET Framework" - - [] - member public this.``Fsx.HashR_QuickInfo.ResolveFromFullyQualifiedPath``() = - let fullyqualifiepathtoddll = System.IO.Path.Combine( System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory(), "System.configuration.dll" ) // Can be any fully qualified path to an assembly - let expectedtooltip = System.Reflection.Assembly.ReflectionOnlyLoadFrom(fullyqualifiepathtoddll).FullName - let fileContent = "#r @\"" + fullyqualifiepathtoddll + "\"" - let marker = "#r @\"" + fullyqualifiepathtoddll.Substring(0,fullyqualifiepathtoddll.Length/2) // somewhere in the middle of the string - this.AssertQuickInfoContainsAtEndOfMarkerInFsxFile fileContent marker expectedtooltip - //this.AssertQuickInfoNotContainsAtEndOfMarkerInFsxFile fileContent marker ".dll" - - [] - member public this.``Fsx.InvalidHashReference.ShouldBeASquiggle.Bug3012``() = - let code = ["#r \"Bar.dll\""] - let (project, file) = createSingleFileFsxFromLines code - MoveCursorToEndOfMarker(file,"#r \"Ba") - let squiggle = GetSquiggleAtCursor(file) - TakeCoffeeBreak(this.VS) - Assert.True(snd squiggle.Value |> fun str -> str.Contains("Bar.dll")) - - // Bug seen during development: The unresolved reference error would x-ray through to the root. - [] - member public this.``Fsx.ScriptClosure.TransitiveLoad14``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let script2 = AddFileFromText(project,"Script2.fsx", - ["#load \"Script1.fsx\"" - "#r \"NonExisting\"" - ]) - let script1 = AddFileFromText(project,"Script1.fsx", - ["#load \"Script2.fsx\"" - "#r \"System\"" - ]) - - let script1 = OpenFile(project,"Script1.fsx") - TakeCoffeeBreak(this.VS) - MoveCursorToEndOfMarker(script1,"#r \"Sys") - AssertEqual(None,GetSquiggleAtCursor(script1)) - - member private this.TestFsxHashDirectivesAreErrors(mark : string, expectedStr : string) = - let code = - [ - "#r \"JoeBob\"" - "#I \".\"" - "#load \"Dooby\"" - ] - let (_, _, file) = this.CreateSingleFileProject(code) - MoveCursorToEndOfMarker(file,mark) - let ans = GetSquiggleAtCursor(file) - match ans with - | Some(sev,msg) -> - AssertEqual(Microsoft.VisualStudio.FSharp.LanguageService.Severity.Error, sev) - AssertContains(msg, expectedStr) - | _ -> failwith "" - - /// FEATURE: #r, #I, #load are all errors when running under the language service - [] - member public this.``Fsx.HashDirectivesAreErrors.InNonScriptFiles.Case1``() = - this.TestFsxHashDirectivesAreErrors("#r \"Joe", "may only be used in F# script files") - - [] - member public this.``Fsx.HashDirectivesAreErrors.InNonScriptFiles.Case2``() = - this.TestFsxHashDirectivesAreErrors("#I \"", "may only be used in F# script files") - - [] - member public this.``Fsx.HashDirectivesAreErrors.InNonScriptFiles.Case3``() = - this.TestFsxHashDirectivesAreErrors("#load \"Doo", "may only be used in F# script files") - - /// FEATURE: #reference against a non-assembly .EXE gives a reasonable error message - //[] - member public this.``Fsx.HashReferenceAgainstNonAssemblyExe``() = - let windows = System.Environment.GetEnvironmentVariable("windir") - let code = - [ - sprintf "#reference @\"%s\"" (Path.Combine(windows,"notepad.exe")) - " let x = 1"] - let (_, file) = createSingleFileFsxFromLines code - - MoveCursorToEndOfMarker(file,"#refe") - let ans = GetSquiggleAtCursor(file) - AssertSquiggleIsErrorContaining(ans, "was not found or is invalid") - - (* ---------------------------------------------------------------------------------- *) - - // FEATURE: A #loaded file is squiggled with an error if there are errors in that file. - [] - member public this.``Fsx.HashLoadedFileWithErrors.Bug3149``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - - let file1 = AddFileFromText(project,"File1.fs", - [ - "module File1" - "DogChow" // <-- error - ]) - - let file2 = AddFileFromText(project,"File2.fsx", - [ - "#load @\"File1.fs\"" - ]) - let file2 = OpenFile(project,"File2.fsx") - - MoveCursorToEndOfMarker(file2,"#load @\"Fi") - TakeCoffeeBreak(this.VS) - let ans = GetSquiggleAtCursor(file2) - AssertSquiggleIsErrorContaining(ans, "DogChow") - - - // FEATURE: A #loaded file is squiggled with a warning if there are warning that file. - [] - member public this.``Fsx.HashLoadedFileWithWarnings.Bug3149``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - - let file1 = AddFileFromText(project,"File1.fs", - ["module File1Module" - "type WarningHere<'a> = static member X() = 0" - "let y = WarningHere.X" - ]) - - let file2 = AddFileFromText(project,"File2.fsx", - [ - "#load @\"File1.fs\"" - ]) - let file2 = OpenFile(project,"File2.fsx") - - MoveCursorToEndOfMarker(file2,"#load @\"Fi") - let ans = GetSquiggleAtCursor(file2) - AssertSquiggleIsWarningContaining(ans, "WarningHere") - - // Bug: #load should report the first error message from a file - [] - member public this.``Fsx.HashLoadedFileWithErrors.Bug3652``() = - use _guard = this.UsingNewVS() - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - - let file1 = AddFileFromText(project,"File1.fs", - [ - "module File1" - "let a = 1 + \"\"" - "let c = new obj()" - "let b = c.foo()" - ]) - let file2 = AddFileFromText(project,"File2.fsx", - [ - "#load @\"File1.fs\"" - ]) - let file2 = OpenFile(project,"File2.fsx") - - MoveCursorToEndOfMarker(file2,"#load @\"Fi") - let ans = GetSquiggleAtCursor(file2) - AssertSquiggleIsErrorContaining(ans, "'string'") - AssertSquiggleIsErrorContaining(ans, "'int'") - AssertSquiggleIsErrorNotContaining(ans, "foo") - - // In this bug the .fsx project directory was wrong so it couldn't reference a relative file. - [] - member public this.``Fsx.ScriptCanReferenceBinDirectoryOutput.Bug3151``() = - use _guard = this.UsingNewVS() - let stopWatch = new System.Diagnostics.Stopwatch() - let ResetStopWatch() = stopWatch.Reset(); stopWatch.Start() - let time1 op a message = - ResetStopWatch() - let result = op a - printf "%s %d ms\n" message stopWatch.ElapsedMilliseconds - result - let solution = this.CreateSolution() - let project = CreateProject(solution,"testproject") - let file1 = AddFileFromText(project,"File1.fs", []) - let projectOutput = time1 Build project "Time to build project" - printfn "Output of building project was %s" projectOutput.ExecutableOutput - printfn "Project directory is %s" (ProjectDirectory project) - - let file2 = AddFileFromText(project,"File2.fsx", - [ - "#reference @\"bin\\Debug\\testproject.exe\"" - ]) - let file2 = OpenFile(project,"File2.fsx") - - MoveCursorToEndOfMarker(file2,"#reference @\"bin\\De") - let ans = GetSquiggleAtCursor(file2) - AssertNoSquiggle(ans) - - - - /// In this bug, multiple references to mscorlib .dll were causing problem in load closure - [] - member public this.``Fsx.BugAllowExplicitReferenceToMsCorlib``() = - let code = - ["#r \"mscorlib\"" - "fsi." - ] - let (_, file) = createSingleFileFsxFromLines code - MoveCursorToEndOfMarker(file,"fsi.") - TakeCoffeeBreak(this.VS) - let completions = AutoCompleteAtCursor file - AssertCompListContains(completions,"CommandLineArgs") - - /// FEATURE: There is a global fsi module that should be in scope for script files. - [] - member public this.``Fsx.Bug2530FsiObject``() = - let code = - [ - "fsi." - ] - let (_, file) = createSingleFileFsxFromLines code - MoveCursorToEndOfMarker(file,"fsi.") - TakeCoffeeBreak(this.VS) - let completions = AutoCompleteAtCursor file - AssertCompListContains(completions,"CommandLineArgs") - - // Ensure that the script closure algorithm gets the right order of hash directives - [] - member public this.``Fsx.ScriptClosure.SurfaceOrderOfHashes``() = - let code = - ["#r \"System.Runtime.Remoting\"" - "#r \"System.Transactions\"" - "#load \"Load1.fs\"" - "#load \"Load2.fsx\"" - ] - let (project, file) = createSingleFileFsxFromLines code - let projectFolder = ProjectDirectory(project) - let fas = GetProjectOptionsOfScript(file) - AssertArrayContainsPartialMatchOf(fas.OtherOptions, "--noframework") - AssertArrayContainsPartialMatchOf(fas.OtherOptions, "System.Runtime.Remoting.dll") - AssertArrayContainsPartialMatchOf(fas.OtherOptions, "System.Transactions.dll") - AssertArrayContainsPartialMatchOf(fas.OtherOptions, "FSharp.Compiler.Interactive.Settings.dll") - Assert.Equal(Path.Combine(projectFolder,"File1.fsx"), fas.SourceFiles.[0]) - Assert.Equal(1, fas.SourceFiles.Length) - - - /// FEATURE: #reference against a strong name should work. - [] - member public this.``Fsx.HashReferenceAgainstStrongName``() = - let code = - [ - sprintf "#reference \"System.Core, Version=%s, Culture=neutral, PublicKeyToken=b77a5c561934e089\"" (System.Environment.Version.ToString()) - "open System."] - let (_, file) = createSingleFileFsxFromLines code - MoveCursorToEndOfMarker(file,"open System.") - let completions = AutoCompleteAtCursor file - AssertCompListContains(completions,"Linq") - - - /// Try out some bogus file names in #r, #I and #load. - [] - member public this.``Fsx.InvalidMetaCommandFilenames``() = - let code = - [ - "#r @\"\"" - "#load @\"\"" - "#I @\"\"" - "#r @\"*\"" - "#load @\"*\"" - "#I @\"*\"" - "#r @\"?\"" - "#load @\"?\"" - "#I @\"?\"" - """#r @"C:\path\does\not\exist.dll" """ - ] - let (_, file) = createSingleFileFsxFromLines code - TakeCoffeeBreak(this.VS) // This used to assert - /// FEATURE: .fsx files have INTERACTIVE #defined [] member public this.``Fsx.INTERACTIVEIsDefinedInFsxFiles``() = @@ -1423,76 +370,6 @@ type UsingMSBuild() as this = Assert.True(not(build.BuildSucceeded), "Expected build to fail") - /// There was a problem in which synthetic tokens like #load were causing asserts - [] - member public this.``Fsx.SyntheticTokens``() = - Helper.ExhaustivelyScrutinize( - this.TestRunner, - [ - "#r \"\"" - "#reference \"\"" - "#load \"\"" - "#line 52" - "#nowarn 72"] - ) - - /// There was a problem where an unclosed reference picked up the text of the reference on the next line. - [] - member public this.``Fsx.ShouldBeAbleToReference30Assemblies.Bug2050``() = - let code = - [ - "#r \"System.Core.dll\"" - "open System." - ] - let (_, file) = createSingleFileFsxFromLines code - MoveCursorToEndOfMarker(file,"open System.") - let completions = AutoCompleteAtCursor file - AssertCompListContains(completions,"Linq") - - /// There was a problem where an unclosed reference picked up the text of the reference on the next line. - [] - member public this.``Fsx.UnclosedHashReference.Case1``() = - Helper.ExhaustivelyScrutinize( - this.TestRunner, - [ - "#reference \"" // Unclosed - "#reference \"Hello There\""] - ) - [] - member public this.``Fsx.UnclosedHashReference.Case2``() = - Helper.ExhaustivelyScrutinize( - this.TestRunner, - [ - "#r \"" // Unclosed - "# \"Hello There\""] - ) - - /// There was a problem where an unclosed reference picked up the text of the reference on the next line. - [] - member public this.``Fsx.UnclosedHashLoad``() = - Helper.ExhaustivelyScrutinize( - this.TestRunner, - [ - "#load \"" // Unclosed - "#load \"Hello There\""] - ) - - [] - member public this.``TypeProvider.UnitsOfMeasure.SmokeTest1``() = - let code = - ["open Microsoft.FSharp.Data.UnitSystems.SI.UnitNames" - "let x : System.Nullable> = N1.T1.MethodWithTypesInvolvingUnitsOfMeasure(1.0)" - "let x2 : int = N1.T1().MethodWithErasedCodeUsingConditional()" - "let x3 : int = N1.T1().MethodWithErasedCodeUsingTypeAs()" - ] - let refs = - [ - PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll") - ] - let (_, project, file) = this.CreateSingleFileProject(code, references = refs) - TakeCoffeeBreak(this.VS) - AssertNoErrorsOrWarnings(project) - member public this.TypeProviderDisposalSmokeTest(clearing) = use _guard = this.UsingNewVS() let providerAssemblyName = PathRelativeToTestAssembly(@"DummyProviderForLanguageServiceTesting.dll") From 24d731a50ab7a3878b9ad8afed70187e07ecb2ad Mon Sep 17 00:00:00 2001 From: Nat Elkins Date: Fri, 24 Jul 2026 06:37:22 -0400 Subject: [PATCH 13/33] Add Roslyn-format EnC CustomDebugInformation codec and portable PDB method CDI emission (#20018) * Add Roslyn-format EnC CustomDebugInformation codec and portable PDB method CDI emission Adds an internal AbstractIL module implementing, byte for byte, the three Portable PDB CustomDebugInformation blob formats Roslyn persists per method for Edit and Continue (EnC Local Slot Map, EnC Lambda and Closure Map, EnC State Machine State Map), with serializers, deserializers, a portable PDB read-back helper, and an occurrence-key packing helper for deterministic syntax-offset slots. Plumbs an optional methodCustomDebugInfoRows side channel through the IL binary writer options into the portable PDB generator so a compilation can attach CDI rows to named methods. Names that do not identify exactly one method row are dropped. All existing writer call sites pass an empty map, so emitted PDBs are byte-identical to before. No in-tree caller populates the map yet; the consumer is the F# hot reload work in dotnet/fsharp#19941, following the same pattern as #20017 (land isolated, test-covered infrastructure first, wire the feature later). Tests: blob round-trips, Roslyn golden-byte encodings, cross-validation against CDI blobs emitted by a real Roslyn compilation, fail-closed occurrence-key packing (including an int32-overflow regression where a wrapped negative key previously escaped the bound check), and end-to-end synthetic PDB emission proving correct MethodDef parenting, zero rows for an empty map, and no rows for absent or ambiguous names. --- .../.FSharp.Compiler.Service/11.0.100.md | 1 + .../AbstractIL/EncMethodDebugInformation.fs | 557 +++++++++++++++ .../AbstractIL/EncMethodDebugInformation.fsi | 178 +++++ src/Compiler/AbstractIL/ilwrite.fs | 14 +- src/Compiler/AbstractIL/ilwrite.fsi | 41 +- src/Compiler/AbstractIL/ilwritepdb.fs | 55 +- src/Compiler/AbstractIL/ilwritepdb.fsi | 7 + src/Compiler/Driver/fsc.fs | 2 + src/Compiler/FSharp.Compiler.Service.fsproj | 2 + src/Compiler/Interactive/fsi.fs | 1 + .../EncMethodDebugInformationTests.fs | 659 ++++++++++++++++++ .../FSharp.Compiler.ComponentTests.fsproj | 1 + 12 files changed, 1494 insertions(+), 24 deletions(-) create mode 100644 src/Compiler/AbstractIL/EncMethodDebugInformation.fs create mode 100644 src/Compiler/AbstractIL/EncMethodDebugInformation.fsi create mode 100644 tests/FSharp.Compiler.ComponentTests/CompilerService/EncMethodDebugInformationTests.fs diff --git a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md index b49aa2d0835..299ffeef32b 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md +++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md @@ -140,6 +140,7 @@ * Checker: recover on checking language version ([PR ##19970](https://github.com/dotnet/fsharp/pull/19970)) * Implied argument names for function-to-delegate coercions now fall back to the delegate's `Invoke` parameter names when the function has no recoverable names (e.g. a partial application like `System.Func((+) 1)`), instead of synthetic `delegateArg0`, `delegateArg1`, … names. ([PR #20001](https://github.com/dotnet/fsharp/pull/20001)) * Add internal `ResetCompilerGeneratedNameState` to `CompilerGlobalState` name generators so warm-checker re-compilation can produce fresh-process-identical generated names. ([PR #20017](https://github.com/dotnet/fsharp/pull/20017)) +* Add Roslyn-format EnC CustomDebugInformation codec and portable PDB method CDI emission support to AbstractIL. ([PR #20018](https://github.com/dotnet/fsharp/pull/20018)) ### Improved diff --git a/src/Compiler/AbstractIL/EncMethodDebugInformation.fs b/src/Compiler/AbstractIL/EncMethodDebugInformation.fs new file mode 100644 index 00000000000..e605b2208a4 --- /dev/null +++ b/src/Compiler/AbstractIL/EncMethodDebugInformation.fs @@ -0,0 +1,557 @@ +/// Edit-and-Continue method debug information blobs. +/// +/// This module replicates, byte for byte, the three Portable-PDB CustomDebugInformation +/// blob formats Roslyn persists per method to support Edit and Continue +/// (roslyn/src/Compilers/Core/Portable/Emit/EditAndContinueMethodDebugInformation.cs): +/// +/// - EnC Local Slot Map (kind 755F52A8-91C5-45BE-B4B8-209571E552BD) +/// - EnC Lambda and Closure Map (kind A643004C-0240-496F-A783-30D64F4979DE) +/// - EnC State Machine State Map (kind 8B78CD68-2EDE-420B-980B-E15884B8AAA3) +/// +/// (GUIDs: roslyn/src/Dependencies/CodeAnalysis.Debugging/PortableCustomDebugInfoKinds.cs.) +/// +/// All multi-byte integers use the ECMA-335 compressed unsigned/signed encodings via +/// System.Reflection.Metadata's BlobBuilder.WriteCompressedInteger / +/// WriteCompressedSignedInteger and BlobReader.ReadCompressedInteger / +/// ReadCompressedSignedInteger, exactly as Roslyn writes/reads them. +/// +/// Every "syntax offset" slot in these blobs is an opaque, caller-defined integer key +/// (Roslyn: the syntax offset of the lambda/closure/state-machine-suspension syntax +/// node). This module does not require the key to be a source offset; it only requires +/// determinism across generations. tryEncodeOccurrenceKey/decodeOccurrenceKey provide one +/// reusable way to pack a short (depth <= 2) ordinal chain into such a key. +module internal FSharp.Compiler.AbstractIL.EncMethodDebugInformation + +#nowarn "9" // NativePtr: BlobReader only exposes a byte*-based constructor + +open System +open System.Collections.Generic +open System.Collections.Immutable +open System.IO +open System.Reflection.Metadata +open System.Reflection.Metadata.Ecma335 +open System.Runtime.InteropServices +open Microsoft.FSharp.NativeInterop + +/// Portable-PDB CustomDebugInformation kind GUIDs for the EnC blobs, copied verbatim +/// from roslyn/src/Dependencies/CodeAnalysis.Debugging/PortableCustomDebugInfoKinds.cs. +[] +module PortableCustomDebugInfoKinds = + + /// EnC Local Slot Map CDI kind. + let encLocalSlotMap = Guid("755F52A8-91C5-45BE-B4B8-209571E552BD") + + /// EnC Lambda and Closure Map CDI kind. + let encLambdaAndClosureMap = Guid("A643004C-0240-496F-A783-30D64F4979DE") + + /// EnC State Machine State Map CDI kind. + let encStateMachineStateMap = Guid("8B78CD68-2EDE-420B-980B-E15884B8AAA3") + +/// Closure ordinal of a lambda that is lowered to a static (non-capturing) method. +/// Mirrors Roslyn's LambdaDebugInfo.StaticClosureOrdinal. +[] +let StaticClosureOrdinal = -1 + +/// Closure ordinal of a lambda closed over the 'this' pointer only. +/// Mirrors Roslyn's LambdaDebugInfo.ThisOnlyClosureOrdinal. +[] +let ThisOnlyClosureOrdinal = -2 + +/// Smallest valid closure ordinal. Mirrors Roslyn's LambdaDebugInfo.MinClosureOrdinal. +[] +let MinClosureOrdinal = ThisOnlyClosureOrdinal + +/// Method ordinal of a method that has no lambda map (an empty blob decodes to this). +/// Mirrors Roslyn's DebugId.UndefinedOrdinal. +[] +let UndefinedMethodOrdinal = -1 + +/// Marker byte introducing the (optional) negative syntax-offset baseline in the +/// local-slot-map blob. Mirrors Roslyn's SyntaxOffsetBaseline = 0xFF. +[] +let private SyntaxOffsetBaselineMarker = 0xFFuy + +/// Largest synthesized-local kind serializable in the slot map: the kind is stored as +/// (kind + 1) in bits 0-5 of the leading byte (bit 6 is unused, bit 7 flags a trailing ordinal), and +/// Roslyn's reader recovers it with mask 0x3F, so only kinds 0..0x3E round-trip. +[] +let MaxSerializableLocalKind = 0x3E + +/// One slot in the EnC Local Slot Map: the local variable layout of a method body, +/// recorded so a later generation can map its locals onto the same slot indices. +[] +type EncLocalSlotInfo = + /// A short-lived lowering temp: serialized as the single byte 0x00, carrying no + /// identity (a later generation never reuses it). + | Temp + + /// A long-lived synthesized local. + /// kind: synthesized-local kind (Roslyn SynthesizedLocalKind value, 0..MaxSerializableLocalKind; + /// 0 = user-defined local). + /// syntaxOffset: caller-defined key of the declaring occurrence + /// (Roslyn: syntax offset of the local's declarator). + /// ordinal: zero-based disambiguator among slots sharing the same kind and offset (>= 0). + | Slot of kind: int * syntaxOffset: int * ordinal: int + +/// One closure scope in the EnC Lambda and Closure Map. The closure's ordinal is its +/// index in EncMethodDebugInformation.Closures; lambdas reference closures by that index. +type EncClosureInfo = + { + /// Caller-defined key (Roslyn: syntax offset of the scope owning the closure). + SyntaxOffset: int + } + +/// One lambda in the EnC Lambda and Closure Map. +type EncLambdaInfo = + { + /// Caller-defined key (Roslyn: syntax offset of the lambda body). + SyntaxOffset: int + /// Index into EncMethodDebugInformation.Closures of the closure holding the + /// lambda's captures, or StaticClosureOrdinal / ThisOnlyClosureOrdinal. + ClosureOrdinal: int + } + +/// One suspension point in the EnC State Machine State Map. +type EncStateMachineStateInfo = + { + /// State machine state number assigned to the suspension point (may be negative: + /// Roslyn uses negative numbers for increasing-iteration finalize states). + StateNumber: int + /// Caller-defined key (Roslyn: syntax offset of the await/yield syntax node). + SyntaxOffset: int + } + +/// Debugging information associated with a method, persisted by the compiler in the +/// Portable PDB to support Edit and Continue. Mirrors Roslyn's +/// EditAndContinueMethodDebugInformation. +type EncMethodDebugInformation = + { + /// Ordinal of the method within its generation (>= -1; UndefinedMethodOrdinal when absent). + MethodOrdinal: int + /// Local slot layout, in slot-index order (EnC Local Slot Map). + LocalSlots: EncLocalSlotInfo list + /// Closure scopes, in ordinal order (EnC Lambda and Closure Map). + Closures: EncClosureInfo list + /// Lambdas, in ordinal order (EnC Lambda and Closure Map). + Lambdas: EncLambdaInfo list + /// State machine suspension points (EnC State Machine State Map). + StateMachineStates: EncStateMachineStateInfo list + } + + /// An empty map (no slots, lambdas, closures or states; undefined method ordinal). + static member Empty = + { + MethodOrdinal = UndefinedMethodOrdinal + LocalSlots = [] + Closures = [] + Lambdas = [] + StateMachineStates = [] + } + +// --------------------------------------------------------------------------- +// Occurrence-key packing +// --------------------------------------------------------------------------- + +/// Maximum encodable occurrence ordinal: each chain segment is 16 bits. +[] +let private MaxOccurrenceSegment = 0xFFFF + +/// Compressed unsigned integers must lie in [0, 0x1FFFFFFF); after baseline adjustment +/// the serialized value is (key - baseline) with baseline <= -1, so keys must stay +/// strictly below 0x1FFFFFFF - 1 to be writable. Cap at 29 bits minus the adjustment. +[] +let private MaxOccurrenceKey = 0x1FFFFFFD + +/// Packs an ordinal chain (root-first enclosing ordinals, ending with the innermost +/// ordinal) into a deterministic int suitable for a "syntax offset" blob slot. Packing: +/// 16-bit segments, least-significant segment = the innermost ordinal; an enclosing +/// ordinal p is stored as (p + 1) shifted left 16 so that depth-1 keys (< 0x10000) and +/// depth-2 keys (>= 0x10000) never collide. Fails closed (None) past the limits: chains +/// deeper than 2, ordinals > 0xFFFF, or keys exceeding the compressed-integer budget — +/// callers must then treat the chain as unmappable, never truncate. +let tryEncodeOccurrenceKey (ordinalChain: int list) : int option = + match ordinalChain with + | [ ordinal ] when ordinal >= 0 && ordinal <= MaxOccurrenceSegment -> Some ordinal + | [ parent; ordinal ] when + parent >= 0 + && ordinal >= 0 + && ordinal <= MaxOccurrenceSegment + && parent < MaxOccurrenceSegment + -> + // Pack in int64: a large parent (e.g. 0xFFFE) would wrap ((parent + 1) <<< 16) negative in + // int32 and a negative key slips past the <= MaxOccurrenceKey bound, failing OPEN. + let key = ((int64 parent + 1L) <<< 16) ||| int64 ordinal + + if key <= int64 MaxOccurrenceKey then + Some(int key) + else + None + | _ -> None + +/// Unpacks an occurrence key produced by tryEncodeOccurrenceKey back into its +/// root-first ordinal chain. +let decodeOccurrenceKey (key: int) : int list = + if key < 0 then + invalidArg (nameof key) $"occurrence key must be non-negative, got %d{key}" + elif key <= MaxOccurrenceSegment then + [ key ] + else + [ (key >>> 16) - 1; key &&& MaxOccurrenceSegment ] + +// --------------------------------------------------------------------------- +// Blob helpers +// --------------------------------------------------------------------------- + +let private invalidData (blobName: string) (offset: int) = + raise (InvalidDataException $"invalid EnC %s{blobName} blob: unexpected data at offset %d{offset}") + +// Absent CDI rows arrive as null at runtime even though the parameter is non-null in the +// nullness model, so guard with box (FS3261-safe) rather than dropping the check. +let private isEmpty (blob: byte[]) = isNull (box blob) || blob.Length = 0 + +// --------------------------------------------------------------------------- +// EnC Local Slot Map +// Format (EditAndContinueMethodDebugInformation.cs, SerializeLocalSlots lines 145-191, +// UncompressSlotMap lines 92-143): optional baseline record [0xFF, compressed(-baseline)], +// then one record per slot: 0x00 for a temp, otherwise a leading byte with bits 0-5 = +// kind + 1 and bit 7 = has-ordinal flag, followed by compressed(syntaxOffset - baseline) +// and, when flagged, compressed(ordinal). +// --------------------------------------------------------------------------- + +/// Serializes the EnC Local Slot Map blob for 'info', byte-for-byte as Roslyn's +/// SerializeLocalSlots. Returns the empty array when there are no slots (no CDI row +/// should be emitted then). +let serializeLocalSlots (info: EncMethodDebugInformation) : byte[] = + match info.LocalSlots with + | [] -> Array.empty + | slots -> + let builder = BlobBuilder() + + // The baseline is the most negative syntax offset, or -1 when none is negative + // (Roslyn lines 147-160). Offsets are stored relative to it so the common + // all-non-negative case costs no baseline record. + let syntaxOffsetBaseline = + (-1, slots) + ||> List.fold (fun acc slot -> + match slot with + | EncLocalSlotInfo.Temp -> acc + | EncLocalSlotInfo.Slot(_, syntaxOffset, _) -> min acc syntaxOffset) + + if syntaxOffsetBaseline <> -1 then + builder.WriteByte SyntaxOffsetBaselineMarker + builder.WriteCompressedInteger(-syntaxOffsetBaseline) + + for slot in slots do + match slot with + | EncLocalSlotInfo.Temp -> builder.WriteByte 0uy + | EncLocalSlotInfo.Slot(kind, syntaxOffset, ordinal) -> + if kind < 0 || kind > MaxSerializableLocalKind then + invalidArg (nameof info) $"local slot kind %d{kind} is outside the serializable range 0..%d{MaxSerializableLocalKind}" + + if ordinal < 0 then + invalidArg (nameof info) $"local slot ordinal must be non-negative, got %d{ordinal}" + + let hasOrdinal = ordinal > 0 + let b = byte (kind + 1) ||| (if hasOrdinal then 0x80uy else 0uy) + builder.WriteByte b + builder.WriteCompressedInteger(syntaxOffset - syntaxOffsetBaseline) + + if hasOrdinal then + builder.WriteCompressedInteger ordinal + + builder.ToArray() + +/// Deserializes an EnC Local Slot Map blob, byte-for-byte as Roslyn's UncompressSlotMap. +/// An empty (or null) blob yields no slots. +let deserializeLocalSlots (blob: byte[]) : EncLocalSlotInfo list = + if isEmpty blob then + [] + else + let handle = GCHandle.Alloc(blob, GCHandleType.Pinned) + + try + let mutable reader = + BlobReader(NativePtr.ofNativeInt (handle.AddrOfPinnedObject()), blob.Length) + + let slots = ResizeArray() + let mutable syntaxOffsetBaseline = -1 + + try + while reader.RemainingBytes > 0 do + let b = reader.ReadByte() + + if b = SyntaxOffsetBaselineMarker then + syntaxOffsetBaseline <- -reader.ReadCompressedInteger() + elif b = 0uy then + slots.Add EncLocalSlotInfo.Temp + else + // Roslyn recovers the kind with mask 0x3F (line 126); bit 7 flags + // a trailing ordinal, bit 6 is unused by the writer. + let kind = int (b &&& 0x3Fuy) - 1 + let hasOrdinal = b &&& 0x80uy <> 0uy + let syntaxOffset = reader.ReadCompressedInteger() + syntaxOffsetBaseline + let ordinal = if hasOrdinal then reader.ReadCompressedInteger() else 0 + slots.Add(EncLocalSlotInfo.Slot(kind, syntaxOffset, ordinal)) + with :? BadImageFormatException -> + invalidData "local slot map" reader.Offset + + List.ofSeq slots + finally + handle.Free() + +// --------------------------------------------------------------------------- +// EnC Lambda and Closure Map +// Format (SerializeLambdaMap lines 261-302, UncompressLambdaMap lines 197-259): +// compressed(methodOrdinal + 1), compressed(-baseline), compressed(closureCount), +// closureCount * compressed(syntaxOffset - baseline), then until the blob ends: +// [compressed(syntaxOffset - baseline), compressed(closureOrdinal - MinClosureOrdinal)] +// per lambda. +// --------------------------------------------------------------------------- + +/// Serializes the EnC Lambda and Closure Map blob for 'info', byte-for-byte as Roslyn's +/// SerializeLambdaMap. Returns the empty array when there are no lambdas and no closures +/// (Roslyn's MetadataWriter skips the CDI row in that case; note the method ordinal is +/// then not persisted and decodes back as UndefinedMethodOrdinal). +let serializeLambdaMap (info: EncMethodDebugInformation) : byte[] = + match info.Closures, info.Lambdas with + | [], [] -> Array.empty + | closures, lambdas -> + if info.MethodOrdinal < -1 then + invalidArg (nameof info) $"method ordinal must be >= -1, got %d{info.MethodOrdinal}" + + let builder = BlobBuilder() + builder.WriteCompressedInteger(info.MethodOrdinal + 1) + + // Negative offsets are rare (Roslyn: field/property initializers), so the + // baseline is -1 unless a smaller offset exists (Roslyn lines 266-286). + let syntaxOffsetBaseline = + let closureMin = (-1, closures) ||> List.fold (fun acc c -> min acc c.SyntaxOffset) + (closureMin, lambdas) ||> List.fold (fun acc l -> min acc l.SyntaxOffset) + + builder.WriteCompressedInteger(-syntaxOffsetBaseline) + builder.WriteCompressedInteger closures.Length + + for closure in closures do + builder.WriteCompressedInteger(closure.SyntaxOffset - syntaxOffsetBaseline) + + for lambda in lambdas do + if + lambda.ClosureOrdinal < MinClosureOrdinal + || lambda.ClosureOrdinal >= closures.Length + then + invalidArg + (nameof info) + $"lambda closure ordinal %d{lambda.ClosureOrdinal} is outside [%d{MinClosureOrdinal}, %d{closures.Length})" + + builder.WriteCompressedInteger(lambda.SyntaxOffset - syntaxOffsetBaseline) + builder.WriteCompressedInteger(lambda.ClosureOrdinal - MinClosureOrdinal) + + builder.ToArray() + +/// Deserializes an EnC Lambda and Closure Map blob, byte-for-byte as Roslyn's +/// UncompressLambdaMap. An empty (or null) blob yields (UndefinedMethodOrdinal, [], []). +let deserializeLambdaMap (blob: byte[]) : int * EncClosureInfo list * EncLambdaInfo list = + if isEmpty blob then + UndefinedMethodOrdinal, [], [] + else + let handle = GCHandle.Alloc(blob, GCHandleType.Pinned) + + try + let mutable reader = + BlobReader(NativePtr.ofNativeInt (handle.AddrOfPinnedObject()), blob.Length) + + let closures = ResizeArray() + let lambdas = ResizeArray() + let mutable methodOrdinal = UndefinedMethodOrdinal + + try + methodOrdinal <- reader.ReadCompressedInteger() - 1 + let syntaxOffsetBaseline = -reader.ReadCompressedInteger() + let closureCount = reader.ReadCompressedInteger() + + for _ in 1..closureCount do + let syntaxOffset = reader.ReadCompressedInteger() + syntaxOffsetBaseline + closures.Add { SyntaxOffset = syntaxOffset } + + while reader.RemainingBytes > 0 do + let syntaxOffset = reader.ReadCompressedInteger() + syntaxOffsetBaseline + let closureOrdinal = reader.ReadCompressedInteger() + MinClosureOrdinal + + if closureOrdinal >= closureCount then + invalidData "lambda map" reader.Offset + + lambdas.Add + { + SyntaxOffset = syntaxOffset + ClosureOrdinal = closureOrdinal + } + with :? BadImageFormatException -> + invalidData "lambda map" reader.Offset + + methodOrdinal, List.ofSeq closures, List.ofSeq lambdas + finally + handle.Free() + +// --------------------------------------------------------------------------- +// EnC State Machine State Map +// Format (SerializeStateMachineStates lines 364-381, UncompressStateMachineStates +// lines 309-362): compressed(count); when count > 0: compressed(-baseline) followed by +// count * [compressedSigned(stateNumber), compressed(syntaxOffset - baseline)], entries +// ordered by syntax offset. +// --------------------------------------------------------------------------- + +/// Serializes the EnC State Machine State Map blob for 'info', byte-for-byte as +/// Roslyn's SerializeStateMachineStates: entries are sorted by syntax offset (stably, +/// preserving relative order of equal offsets, which encodes the per-offset relative +/// ordinal). Returns the empty array when there are no states (no CDI row then). +let serializeStateMachineStates (info: EncMethodDebugInformation) : byte[] = + match info.StateMachineStates with + | [] -> Array.empty + | states -> + let builder = BlobBuilder() + builder.WriteCompressedInteger states.Length + + // Unlike the other two blobs the baseline here is min(minOffset, 0) + // (Roslyn line 372). + let syntaxOffsetBaseline = + min (states |> List.map (fun s -> s.SyntaxOffset) |> List.min) 0 + + builder.WriteCompressedInteger(-syntaxOffsetBaseline) + + // Roslyn's reader rejects more than 256 entries sharing one syntax offset + // (relative ordinal must fit a byte, line 344); fail closed at write time. + for _, group in states |> List.groupBy (fun s -> s.SyntaxOffset) do + if group.Length > 256 then + invalidArg (nameof info) $"more than 256 state machine states share syntax offset %d{group.Head.SyntaxOffset}" + + for state in states |> List.sortBy (fun s -> s.SyntaxOffset) do + builder.WriteCompressedSignedInteger state.StateNumber + builder.WriteCompressedInteger(state.SyntaxOffset - syntaxOffsetBaseline) + + builder.ToArray() + +/// Deserializes an EnC State Machine State Map blob, byte-for-byte as Roslyn's +/// UncompressStateMachineStates (including the ordered-by-offset and <= 256-per-offset +/// validations). An empty (or null) blob yields no states. +let deserializeStateMachineStates (blob: byte[]) : EncStateMachineStateInfo list = + if isEmpty blob then + [] + else + let handle = GCHandle.Alloc(blob, GCHandleType.Pinned) + + try + let mutable reader = + BlobReader(NativePtr.ofNativeInt (handle.AddrOfPinnedObject()), blob.Length) + + let states = ResizeArray() + + try + let count = reader.ReadCompressedInteger() + + if count > 0 then + let syntaxOffsetBaseline = -reader.ReadCompressedInteger() + let mutable lastSyntaxOffset = Int32.MinValue + let mutable relativeOrdinal = 0 + + for _ in 1..count do + let stateNumber = reader.ReadCompressedSignedInteger() + let syntaxOffset = syntaxOffsetBaseline + reader.ReadCompressedInteger() + + // Entries must be ordered by syntax offset and at most 256 may + // share one offset (Roslyn lines 336-347). + if syntaxOffset < lastSyntaxOffset then + invalidData "state machine state map" reader.Offset + + relativeOrdinal <- + if syntaxOffset = lastSyntaxOffset then + relativeOrdinal + 1 + else + 0 + + if relativeOrdinal > 255 then + invalidData "state machine state map" reader.Offset + + states.Add + { + StateNumber = stateNumber + SyntaxOffset = syntaxOffset + } + + lastSyntaxOffset <- syntaxOffset + with :? BadImageFormatException -> + invalidData "state machine state map" reader.Offset + + List.ofSeq states + finally + handle.Free() + +/// Deserializes EnC method debug information from the three blobs (any of which may be +/// null or empty). Mirrors Roslyn's EditAndContinueMethodDebugInformation.Create. +let deserialize (slotMapBlob: byte[]) (lambdaMapBlob: byte[]) (stateMachineStateMapBlob: byte[]) : EncMethodDebugInformation = + let methodOrdinal, closures, lambdas = deserializeLambdaMap lambdaMapBlob + + { + MethodOrdinal = methodOrdinal + LocalSlots = deserializeLocalSlots slotMapBlob + Closures = closures + Lambdas = lambdas + StateMachineStates = deserializeStateMachineStates stateMachineStateMapBlob + } + +/// Decodes every method-level EnC CustomDebugInformation row of a portable PDB image into +/// per-method EnC debug information, keyed by MethodDef token (0x06xxxxxx). The CDI parent +/// of the EnC rows is always a MethodDef handle, so token keying is unambiguous. +/// Fail safe: a null/empty or non-PDB image yields the empty map, and a method whose +/// blobs do not decode is omitted rather than guessed. +let readEncMethodDebugInfoFromPortablePdb (pdbBytes: byte[]) : Map = + if isEmpty pdbBytes then + Map.empty + else + try + use provider = + MetadataReaderProvider.FromPortablePdbImage(ImmutableArray.CreateRange pdbBytes) + + let reader = provider.GetMetadataReader() + + let slotMapBlobs = Dictionary() + let lambdaMapBlobs = Dictionary() + let stateMapBlobs = Dictionary() + + for cdiHandle in reader.CustomDebugInformation do + let cdi = reader.GetCustomDebugInformation cdiHandle + + if cdi.Parent.Kind = HandleKind.MethodDefinition then + let methodToken = MetadataTokens.GetToken cdi.Parent + let kind = reader.GetGuid cdi.Kind + + if kind = PortableCustomDebugInfoKinds.encLocalSlotMap then + slotMapBlobs[methodToken] <- reader.GetBlobBytes cdi.Value + elif kind = PortableCustomDebugInfoKinds.encLambdaAndClosureMap then + lambdaMapBlobs[methodToken] <- reader.GetBlobBytes cdi.Value + elif kind = PortableCustomDebugInfoKinds.encStateMachineStateMap then + stateMapBlobs[methodToken] <- reader.GetBlobBytes cdi.Value + + let methodTokens = + Seq.concat [ slotMapBlobs.Keys :> seq; lambdaMapBlobs.Keys; stateMapBlobs.Keys ] + |> Seq.distinct + + let tryBlob (blobs: Dictionary) token = + match blobs.TryGetValue token with + | true, blob -> blob + | _ -> Array.empty + + (Map.empty, methodTokens) + ||> Seq.fold (fun acc token -> + try + let info = + deserialize (tryBlob slotMapBlobs token) (tryBlob lambdaMapBlobs token) (tryBlob stateMapBlobs token) + + Map.add token info acc + with :? InvalidDataException -> + // Fail closed per method: an undecodable blob never yields a partial + // (and so potentially mismatched) map for its method. + acc) + with :? BadImageFormatException -> + // Not a portable PDB image (or a corrupted one): callers still get an empty + // map instead of a crash. + Map.empty diff --git a/src/Compiler/AbstractIL/EncMethodDebugInformation.fsi b/src/Compiler/AbstractIL/EncMethodDebugInformation.fsi new file mode 100644 index 00000000000..1e2ba76e7c8 --- /dev/null +++ b/src/Compiler/AbstractIL/EncMethodDebugInformation.fsi @@ -0,0 +1,178 @@ +/// Edit-and-Continue method debug information blobs. +/// +/// This module replicates, byte for byte, the three Portable-PDB CustomDebugInformation +/// blob formats Roslyn persists per method to support Edit and Continue +/// (roslyn/src/Compilers/Core/Portable/Emit/EditAndContinueMethodDebugInformation.cs): +/// +/// - EnC Local Slot Map (kind 755F52A8-91C5-45BE-B4B8-209571E552BD) +/// - EnC Lambda and Closure Map (kind A643004C-0240-496F-A783-30D64F4979DE) +/// - EnC State Machine State Map (kind 8B78CD68-2EDE-420B-980B-E15884B8AAA3) +/// +/// (GUIDs: roslyn/src/Dependencies/CodeAnalysis.Debugging/PortableCustomDebugInfoKinds.cs.) +/// +/// All multi-byte integers use the ECMA-335 compressed unsigned/signed encodings via +/// System.Reflection.Metadata's BlobBuilder.WriteCompressedInteger / +/// WriteCompressedSignedInteger and BlobReader.ReadCompressedInteger / +/// ReadCompressedSignedInteger, exactly as Roslyn writes/reads them. +/// +/// Every "syntax offset" slot in these blobs is an opaque, caller-defined integer key +/// (Roslyn: the syntax offset of the lambda/closure/state-machine-suspension syntax +/// node). This module does not require the key to be a source offset; it only requires +/// determinism across generations. tryEncodeOccurrenceKey/decodeOccurrenceKey provide one +/// reusable way to pack a short (depth <= 2) ordinal chain into such a key. +module internal FSharp.Compiler.AbstractIL.EncMethodDebugInformation + +/// Portable-PDB CustomDebugInformation kind GUIDs for the EnC blobs, copied verbatim +/// from roslyn/src/Dependencies/CodeAnalysis.Debugging/PortableCustomDebugInfoKinds.cs. +[] +module PortableCustomDebugInfoKinds = + + /// EnC Local Slot Map CDI kind. + val encLocalSlotMap: System.Guid + + /// EnC Lambda and Closure Map CDI kind. + val encLambdaAndClosureMap: System.Guid + + /// EnC State Machine State Map CDI kind. + val encStateMachineStateMap: System.Guid + +/// Closure ordinal of a lambda that is lowered to a static (non-capturing) method. +/// Mirrors Roslyn's LambdaDebugInfo.StaticClosureOrdinal. +[] +val StaticClosureOrdinal: int = -1 + +/// Closure ordinal of a lambda closed over the 'this' pointer only. +/// Mirrors Roslyn's LambdaDebugInfo.ThisOnlyClosureOrdinal. +[] +val ThisOnlyClosureOrdinal: int = -2 + +/// Smallest valid closure ordinal. Mirrors Roslyn's LambdaDebugInfo.MinClosureOrdinal. +[] +val MinClosureOrdinal: int = -2 + +/// Method ordinal of a method that has no lambda map (an empty blob decodes to this). +/// Mirrors Roslyn's DebugId.UndefinedOrdinal. +[] +val UndefinedMethodOrdinal: int = -1 + +/// Largest synthesized-local kind serializable in the slot map: the kind is stored as +/// (kind + 1) in bits 0-5 of the leading byte (bit 6 is unused, bit 7 flags a trailing ordinal), and +/// Roslyn's reader recovers it with mask 0x3F, so only kinds 0..0x3E round-trip. +[] +val MaxSerializableLocalKind: int = 0x3E + +/// One slot in the EnC Local Slot Map: the local variable layout of a method body, +/// recorded so a later generation can map its locals onto the same slot indices. +[] +type EncLocalSlotInfo = + /// A short-lived lowering temp: serialized as the single byte 0x00, carrying no + /// identity (a later generation never reuses it). + | Temp + + /// A long-lived synthesized local. + /// kind: synthesized-local kind (Roslyn SynthesizedLocalKind value, 0..MaxSerializableLocalKind; + /// 0 = user-defined local). + /// syntaxOffset: caller-defined key of the declaring occurrence + /// (Roslyn: syntax offset of the local's declarator). + /// ordinal: zero-based disambiguator among slots sharing the same kind and offset (>= 0). + | Slot of kind: int * syntaxOffset: int * ordinal: int + +/// One closure scope in the EnC Lambda and Closure Map. The closure's ordinal is its +/// index in EncMethodDebugInformation.Closures; lambdas reference closures by that index. +type EncClosureInfo = + { + /// Caller-defined key (Roslyn: syntax offset of the scope owning the closure). + SyntaxOffset: int + } + +/// One lambda in the EnC Lambda and Closure Map. +type EncLambdaInfo = + { + /// Caller-defined key (Roslyn: syntax offset of the lambda body). + SyntaxOffset: int + /// Index into EncMethodDebugInformation.Closures of the closure holding the + /// lambda's captures, or StaticClosureOrdinal / ThisOnlyClosureOrdinal. + ClosureOrdinal: int + } + +/// One suspension point in the EnC State Machine State Map. +type EncStateMachineStateInfo = + { + /// State machine state number assigned to the suspension point (may be negative: + /// Roslyn uses negative numbers for increasing-iteration finalize states). + StateNumber: int + /// Caller-defined key (Roslyn: syntax offset of the await/yield syntax node). + SyntaxOffset: int + } + +/// Debugging information associated with a method, persisted by the compiler in the +/// Portable PDB to support Edit and Continue. Mirrors Roslyn's +/// EditAndContinueMethodDebugInformation. +type EncMethodDebugInformation = + { + /// Ordinal of the method within its generation (>= -1; UndefinedMethodOrdinal when absent). + MethodOrdinal: int + /// Local slot layout, in slot-index order (EnC Local Slot Map). + LocalSlots: EncLocalSlotInfo list + /// Closure scopes, in ordinal order (EnC Lambda and Closure Map). + Closures: EncClosureInfo list + /// Lambdas, in ordinal order (EnC Lambda and Closure Map). + Lambdas: EncLambdaInfo list + /// State machine suspension points (EnC State Machine State Map). + StateMachineStates: EncStateMachineStateInfo list + } + + /// An empty map (no slots, lambdas, closures or states; undefined method ordinal). + static member Empty: EncMethodDebugInformation + +/// Packs an ordinal chain (root-first enclosing ordinals, ending with the innermost +/// ordinal) into a deterministic int suitable for a "syntax offset" blob slot. Fails +/// closed (None) past the limits: chains deeper than 2, ordinals > 0xFFFF, or keys +/// exceeding the compressed-integer budget. +val tryEncodeOccurrenceKey: ordinalChain: int list -> int option + +/// Unpacks an occurrence key produced by tryEncodeOccurrenceKey back into its +/// root-first ordinal chain. +val decodeOccurrenceKey: key: int -> int list + +/// Serializes the EnC Local Slot Map blob for 'info', byte-for-byte as Roslyn's +/// SerializeLocalSlots. Returns the empty array when there are no slots (no CDI row +/// should be emitted then). +val serializeLocalSlots: info: EncMethodDebugInformation -> byte[] + +/// Deserializes an EnC Local Slot Map blob, byte-for-byte as Roslyn's UncompressSlotMap. +/// An empty (or null) blob yields no slots. +val deserializeLocalSlots: blob: byte[] -> EncLocalSlotInfo list + +/// Serializes the EnC Lambda and Closure Map blob for 'info', byte-for-byte as Roslyn's +/// SerializeLambdaMap. Returns the empty array when there are no lambdas and no closures +/// (Roslyn's MetadataWriter skips the CDI row in that case; note the method ordinal is +/// then not persisted and decodes back as UndefinedMethodOrdinal). +val serializeLambdaMap: info: EncMethodDebugInformation -> byte[] + +/// Deserializes an EnC Lambda and Closure Map blob, byte-for-byte as Roslyn's +/// UncompressLambdaMap. An empty (or null) blob yields (UndefinedMethodOrdinal, [], []). +val deserializeLambdaMap: blob: byte[] -> int * EncClosureInfo list * EncLambdaInfo list + +/// Serializes the EnC State Machine State Map blob for 'info', byte-for-byte as +/// Roslyn's SerializeStateMachineStates: entries are sorted by syntax offset (stably, +/// preserving relative order of equal offsets, which encodes the per-offset relative +/// ordinal). Returns the empty array when there are no states (no CDI row then). +val serializeStateMachineStates: info: EncMethodDebugInformation -> byte[] + +/// Deserializes an EnC State Machine State Map blob, byte-for-byte as Roslyn's +/// UncompressStateMachineStates (including the ordered-by-offset and <= 256-per-offset +/// validations). An empty (or null) blob yields no states. +val deserializeStateMachineStates: blob: byte[] -> EncStateMachineStateInfo list + +/// Deserializes EnC method debug information from the three blobs (any of which may be +/// null or empty). Mirrors Roslyn's EditAndContinueMethodDebugInformation.Create. +val deserialize: + slotMapBlob: byte[] -> lambdaMapBlob: byte[] -> stateMachineStateMapBlob: byte[] -> EncMethodDebugInformation + +/// Decodes every method-level EnC CustomDebugInformation row of a portable PDB image into +/// per-method EnC debug information, keyed by MethodDef token (0x06xxxxxx). The CDI parent +/// of the EnC rows is always a MethodDef handle, so token keying is unambiguous. +/// Fail safe: a null/empty or non-PDB image yields the empty map, and a method whose +/// blobs do not decode is omitted rather than guessed. +val readEncMethodDebugInfoFromPortablePdb: pdbBytes: byte[] -> Map diff --git a/src/Compiler/AbstractIL/ilwrite.fs b/src/Compiler/AbstractIL/ilwrite.fs index 13feeab294a..bf6277bf485 100644 --- a/src/Compiler/AbstractIL/ilwrite.fs +++ b/src/Compiler/AbstractIL/ilwrite.fs @@ -2699,8 +2699,11 @@ let GenMethodDefAsRow cenv env midx (mdef: ILMethodDef) = cenv.AddCode code addr | MethodBody.Abstract - | MethodBody.PInvoke _ -> + | MethodBody.PInvoke _ + | MethodBody.NotAvailable -> // Now record the PDB record for this method - we write this out later. + // Metadata-only methods still participate in name ambiguity checks and occupy + // MethodDebugInformation rows even though they have no sequence points. if cenv.generatePdb then cenv.pdbinfo.Add { MethToken = getUncodedToken TableNames.Method midx @@ -2713,7 +2716,7 @@ let GenMethodDefAsRow cenv env midx (mdef: ILMethodDef) = 0x0000 | MethodBody.Native -> failwith "cannot write body of native method - Abstract IL cannot roundtrip mixed native/managed binaries" - | _ -> 0x0000) + ) UnsharedRow [| ULong codeAddr @@ -3859,7 +3862,10 @@ type options = referenceAssemblyOnly: bool referenceAssemblyAttribOpt: ILAttribute option referenceAssemblySignatureHash : int option - pathMap: PathMap } + pathMap: PathMap + /// Per-method EnC CustomDebugInformation rows for the portable PDB writer, keyed by + /// IL method name. Empty for ordinary compiles, so flag-off output stays byte-identical. + methodCustomDebugInfoRows: Map } let writeBinaryAux (stream: Stream, options: options, modul, normalizeAssemblyRefs) = @@ -4022,7 +4028,7 @@ let writeBinaryAux (stream: Stream, options: options, modul, normalizeAssemblyRe match options.pdbfile, options.portablePDB with | Some _, true -> let pdbInfo = - generatePortablePdb options.embedAllSource options.embedSourceList options.sourceLink options.checksumAlgorithm pdbData options.pathMap + generatePortablePdb options.embedAllSource options.embedSourceList options.sourceLink options.checksumAlgorithm pdbData options.pathMap options.methodCustomDebugInfoRows if options.embeddedPDB then let uncompressedLength, contentId, stream, algorithmName, checkSum = pdbInfo diff --git a/src/Compiler/AbstractIL/ilwrite.fsi b/src/Compiler/AbstractIL/ilwrite.fsi index d074f0bc584..08321664c2f 100644 --- a/src/Compiler/AbstractIL/ilwrite.fsi +++ b/src/Compiler/AbstractIL/ilwrite.fsi @@ -9,24 +9,29 @@ open FSharp.Compiler.AbstractIL.ILPdbWriter open FSharp.Compiler.AbstractIL.StrongNameSign type options = - { ilg: ILGlobals - outfile: string - pdbfile: string option - portablePDB: bool - embeddedPDB: bool - embedAllSource: bool - embedSourceList: string list - allGivenSources: ILSourceDocument list - sourceLink: string - checksumAlgorithm: HashAlgorithm - signer: ILStrongNameSigner option - emitTailcalls: bool - deterministic: bool - dumpDebugInfo: bool - referenceAssemblyOnly: bool - referenceAssemblyAttribOpt: ILAttribute option - referenceAssemblySignatureHash: int option - pathMap: PathMap } + { + ilg: ILGlobals + outfile: string + pdbfile: string option + portablePDB: bool + embeddedPDB: bool + embedAllSource: bool + embedSourceList: string list + allGivenSources: ILSourceDocument list + sourceLink: string + checksumAlgorithm: HashAlgorithm + signer: ILStrongNameSigner option + emitTailcalls: bool + deterministic: bool + dumpDebugInfo: bool + referenceAssemblyOnly: bool + referenceAssemblyAttribOpt: ILAttribute option + referenceAssemblySignatureHash: int option + pathMap: PathMap + /// Per-method EnC CustomDebugInformation rows for the portable PDB writer, keyed by + /// IL method name. Empty for ordinary compiles, so flag-off output stays byte-identical. + methodCustomDebugInfoRows: Map + } /// Write a binary to the file system. val WriteILBinaryFile: options: options * inputModule: ILModuleDef * (ILAssemblyRef -> ILAssemblyRef) -> unit diff --git a/src/Compiler/AbstractIL/ilwritepdb.fs b/src/Compiler/AbstractIL/ilwritepdb.fs index 86a19d50c6c..70f88b471d7 100644 --- a/src/Compiler/AbstractIL/ilwritepdb.fs +++ b/src/Compiler/AbstractIL/ilwritepdb.fs @@ -118,6 +118,10 @@ type PdbMethodData = DebugPoints: PdbDebugPoint array } +/// A pre-serialized CustomDebugInformation row (kind GUID + blob) to attach to a method +/// definition row in the portable PDB. +type PdbMethodCustomDebugInfo = { KindGuid: Guid; Blob: byte[] } + module SequencePoint = let orderBySource sp1 sp2 = let c1 = compare sp1.Document sp2.Document @@ -337,7 +341,15 @@ let scopeSorter (scope1: PdbMethodScope) (scope2: PdbMethodScope) = 0 type PortablePdbGenerator - (embedAllSource: bool, embedSourceList: string list, sourceLink: string, checksumAlgorithm, info: PdbData, pathMap: PathMap) = + ( + embedAllSource: bool, + embedSourceList: string list, + sourceLink: string, + checksumAlgorithm, + info: PdbData, + pathMap: PathMap, + methodCustomDebugInfoRows: Map + ) = // Deterministic: build the Document table in a stable order by mapped file path, // but preserve the original-document-index -> handle mapping by filename. @@ -488,6 +500,27 @@ type PortablePdbGenerator let moduleImportScopeHandle = MetadataTokens.ImportScopeHandle(1) let importScopesTable = Dictionary() + // Per-method CustomDebugInformation rows keyed by IL method name. Names that match + // more than one method row (overloads, same name on different types) fail closed and + // attach nothing, so a row can never land on the wrong method. + let methodCustomDebugInfoByName = + if Map.isEmpty methodCustomDebugInfoRows then + methodCustomDebugInfoRows + else + let nameCounts = Dictionary() + + for minfo in info.Methods do + nameCounts[minfo.MethName] <- + match nameCounts.TryGetValue minfo.MethName with + | true, count -> count + 1 + | _ -> 1 + + methodCustomDebugInfoRows + |> Map.filter (fun methName _ -> + match nameCounts.TryGetValue methName with + | true, 1 -> true + | _ -> false) + let serializeImport (writer: BlobBuilder) (import: PdbImport) = match import with // We don't yet emit these kinds of imports @@ -777,6 +810,23 @@ type PortablePdbGenerator metadata.AddMethodDebugInformation(docHandle, sequencePointBlob) |> ignore + // MetadataBuilder sorts the CustomDebugInformation table by parent at serialize + // time, so adding rows in method order here is safe. + match Map.tryFind minfo.MethName methodCustomDebugInfoByName with + | Some cdiRows -> + // MethToken is the uncoded token (0x06 <<< 24 ||| rid); the handle needs the rid. + let methodHandle = + MetadataTokens.MethodDefinitionHandle(minfo.MethToken &&& 0x00FFFFFF) + + for cdiRow in cdiRows do + metadata.AddCustomDebugInformation( + MethodDefinitionHandle.op_Implicit methodHandle, + metadata.GetOrAddGuid cdiRow.KindGuid, + metadata.GetOrAddBlob cdiRow.Blob + ) + |> ignore + | None -> () + match minfo.RootScope with | None -> () | Some scope -> writeMethodScopes minfo.MethToken scope @@ -831,9 +881,10 @@ let generatePortablePdb checksumAlgorithm (info: PdbData) (pathMap: PathMap) + (methodCustomDebugInfoRows: Map) = let generator = - PortablePdbGenerator(embedAllSource, embedSourceList, sourceLink, checksumAlgorithm, info, pathMap) + PortablePdbGenerator(embedAllSource, embedSourceList, sourceLink, checksumAlgorithm, info, pathMap, methodCustomDebugInfoRows) generator.Emit() diff --git a/src/Compiler/AbstractIL/ilwritepdb.fsi b/src/Compiler/AbstractIL/ilwritepdb.fsi index 5987cc165e3..09d380e44cc 100644 --- a/src/Compiler/AbstractIL/ilwritepdb.fsi +++ b/src/Compiler/AbstractIL/ilwritepdb.fsi @@ -67,6 +67,12 @@ type PdbMethodData = DebugRange: (PdbSourceLoc * PdbSourceLoc) option DebugPoints: PdbDebugPoint[] } +/// A pre-serialized CustomDebugInformation row to attach to a method definition row in +/// the portable PDB (kind GUID + blob). Supplied by the compiler as a side channel keyed +/// by IL method name. The writer attaches the rows only when the name identifies exactly +/// one method row (fail closed on ambiguity). +type PdbMethodCustomDebugInfo = { KindGuid: System.Guid; Blob: byte[] } + [] type PdbData = { @@ -109,6 +115,7 @@ val generatePortablePdb: checksumAlgorithm: HashAlgorithm -> info: PdbData -> pathMap: PathMap -> + methodCustomDebugInfoRows: Map -> int64 * BlobContentId * MemoryStream * string * byte[] val compressPortablePdbStream: stream: MemoryStream -> MemoryStream diff --git a/src/Compiler/Driver/fsc.fs b/src/Compiler/Driver/fsc.fs index 43157660212..f5aa287b6a7 100644 --- a/src/Compiler/Driver/fsc.fs +++ b/src/Compiler/Driver/fsc.fs @@ -1149,6 +1149,7 @@ let main6 referenceAssemblyAttribOpt = referenceAssemblyAttribOpt referenceAssemblySignatureHash = refAssemblySignatureHash pathMap = tcConfig.pathMap + methodCustomDebugInfoRows = Map.empty }, ilxMainModule, normalizeAssemblyRefs @@ -1180,6 +1181,7 @@ let main6 referenceAssemblyAttribOpt = None referenceAssemblySignatureHash = None pathMap = tcConfig.pathMap + methodCustomDebugInfoRows = Map.empty }, ilxMainModule, normalizeAssemblyRefs diff --git a/src/Compiler/FSharp.Compiler.Service.fsproj b/src/Compiler/FSharp.Compiler.Service.fsproj index 5510af6b3f6..2d0b77fbf69 100644 --- a/src/Compiler/FSharp.Compiler.Service.fsproj +++ b/src/Compiler/FSharp.Compiler.Service.fsproj @@ -236,6 +236,8 @@ + + diff --git a/src/Compiler/Interactive/fsi.fs b/src/Compiler/Interactive/fsi.fs index fcb93b6c985..a41b658cab1 100644 --- a/src/Compiler/Interactive/fsi.fs +++ b/src/Compiler/Interactive/fsi.fs @@ -1941,6 +1941,7 @@ type internal FsiDynamicCompiler referenceAssemblyAttribOpt = None referenceAssemblySignatureHash = None pathMap = tcConfig.pathMap + methodCustomDebugInfoRows = Map.empty } let assemblyBytes, pdbBytes = WriteILBinaryInMemory(opts, ilxMainModule, id) diff --git a/tests/FSharp.Compiler.ComponentTests/CompilerService/EncMethodDebugInformationTests.fs b/tests/FSharp.Compiler.ComponentTests/CompilerService/EncMethodDebugInformationTests.fs new file mode 100644 index 00000000000..831d9c6f020 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/CompilerService/EncMethodDebugInformationTests.fs @@ -0,0 +1,659 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +module CompilerService.EncMethodDebugInformationTests + +open System +open System.Collections.Immutable +open System.IO +open System.Reflection +open System.Reflection.Metadata +open System.Reflection.Metadata.Ecma335 +open System.Reflection.PortableExecutable +open Xunit + +open Internal.Utilities +open FSharp.Compiler.AbstractIL.IL +open FSharp.Compiler.AbstractIL.ILBinaryWriter +open FSharp.Compiler.AbstractIL.ILPdbWriter +open FSharp.Compiler.AbstractIL.EncMethodDebugInformation + +// ----------------------------------------------------------------------- +// Round-trip properties (pure codec) +// ----------------------------------------------------------------------- + +[] +let ``Empty maps serialize to empty blobs and deserialize to the empty record`` () = + let info = EncMethodDebugInformation.Empty + + Assert.Empty(serializeLocalSlots info) + Assert.Empty(serializeLambdaMap info) + Assert.Empty(serializeStateMachineStates info) + + let decoded = deserialize Array.empty Array.empty Array.empty + Assert.Equal(EncMethodDebugInformation.Empty, decoded) + + // Null blobs (absent CDI rows) behave like empty ones. + let decodedNull = deserialize null null null + Assert.Equal(EncMethodDebugInformation.Empty, decodedNull) + +[] +let ``Lambda map with a single closure round-trips`` () = + let info = + { EncMethodDebugInformation.Empty with + MethodOrdinal = 0 + Closures = [ { SyntaxOffset = 3 } ] } + + let blob = serializeLambdaMap info + let methodOrdinal, closures, lambdas = deserializeLambdaMap blob + + Assert.Equal(0, methodOrdinal) + Assert.Equal([ { SyntaxOffset = 3 } ], closures) + Assert.Empty lambdas + +[] +let ``Lambda map with several lambdas and negative-baseline offsets round-trips`` () = + // Out-of-order and negative offsets exercise the syntax-offset-baseline record; + // closure ordinals cover in-range, static (-1) and this-only (-2) lambdas. + let closures = [ { SyntaxOffset = 12 }; { SyntaxOffset = -7 }; { SyntaxOffset = 3 } ] + + let lambdas = + [ { SyntaxOffset = 30; ClosureOrdinal = 1 } + { SyntaxOffset = -7; ClosureOrdinal = StaticClosureOrdinal } + { SyntaxOffset = 0; ClosureOrdinal = ThisOnlyClosureOrdinal } + { SyntaxOffset = 5; ClosureOrdinal = 2 } ] + + let info = + { EncMethodDebugInformation.Empty with + MethodOrdinal = 5 + Closures = closures + Lambdas = lambdas } + + let blob = serializeLambdaMap info + let methodOrdinal, decodedClosures, decodedLambdas = deserializeLambdaMap blob + + Assert.Equal(5, methodOrdinal) + Assert.Equal(closures, decodedClosures) + Assert.Equal(lambdas, decodedLambdas) + +[] +let ``Lambda map golden bytes match the Roslyn encoding`` () = + // methodOrdinal 0 -> compressed(1); baseline -1 -> compressed(1); one closure at + // offset 0 -> compressed(1); lambda at offset 5 -> compressed(6) with closure + // ordinal 0 -> compressed(0 - (-2)) = compressed(2). + let info = + { EncMethodDebugInformation.Empty with + MethodOrdinal = 0 + Closures = [ { SyntaxOffset = 0 } ] + Lambdas = [ { SyntaxOffset = 5; ClosureOrdinal = 0 } ] } + + Assert.Equal([| 0x01uy; 0x01uy; 0x01uy; 0x01uy; 0x06uy; 0x02uy |], serializeLambdaMap info) + +[] +let ``Lambda map rejects closure ordinals outside the valid range`` () = + let mk ordinal = + { EncMethodDebugInformation.Empty with + MethodOrdinal = 0 + Closures = [ { SyntaxOffset = 0 } ] + Lambdas = [ { SyntaxOffset = 1; ClosureOrdinal = ordinal } ] } + + Assert.Throws(fun () -> serializeLambdaMap (mk 1) |> ignore) |> ignore + Assert.Throws(fun () -> serializeLambdaMap (mk -3) |> ignore) |> ignore + +[] +let ``Slot map with temps, ordinal-flagged slots and negative offsets round-trips`` () = + let slots = + [ EncLocalSlotInfo.Temp + EncLocalSlotInfo.Slot(0, 10, 0) + EncLocalSlotInfo.Slot(MaxSerializableLocalKind, -42, 3) + EncLocalSlotInfo.Temp + EncLocalSlotInfo.Slot(7, 0, 1) ] + + let info = + { EncMethodDebugInformation.Empty with + LocalSlots = slots } + + let blob = serializeLocalSlots info + Assert.Equal(slots, deserializeLocalSlots blob) + + // The baseline record must be present (an offset below -1 exists) and must be + // the Roslyn marker byte 0xFF followed by compressed(42). + Assert.Equal(0xFFuy, blob[0]) + +[] +let ``Slot map golden bytes match the Roslyn encoding`` () = + // No offset below -1 -> no baseline record (implicit baseline -1). + // Temp -> 0x00. + // Slot(kind 0, offset 0, ordinal 0) -> byte 0x01 (kind+1), compressed(0 - (-1)) = 0x01. + // Slot(kind 1, offset 2, ordinal 3) -> byte 0x82 (kind+1, bit 7 = has ordinal), + // compressed(3), compressed(3). + let info = + { EncMethodDebugInformation.Empty with + LocalSlots = + [ EncLocalSlotInfo.Temp + EncLocalSlotInfo.Slot(0, 0, 0) + EncLocalSlotInfo.Slot(1, 2, 3) ] } + + Assert.Equal([| 0x00uy; 0x01uy; 0x01uy; 0x82uy; 0x03uy; 0x03uy |], serializeLocalSlots info) + +[] +let ``Slot map rejects kinds outside the serializable range`` () = + let mk kind = + { EncMethodDebugInformation.Empty with + LocalSlots = [ EncLocalSlotInfo.Slot(kind, 0, 0) ] } + + Assert.Throws(fun () -> serializeLocalSlots (mk -1) |> ignore) |> ignore + + Assert.Throws(fun () -> serializeLocalSlots (mk (MaxSerializableLocalKind + 1)) |> ignore) + |> ignore + +[] +let ``State machine map with negative state numbers round-trips ordered by offset`` () = + // Input deliberately unsorted; the writer orders entries by syntax offset + // (stably, so the two entries sharing offset 20 keep their relative order). + let states = + [ { StateNumber = -4; SyntaxOffset = 20 } + { StateNumber = 0; SyntaxOffset = -5 } + { StateNumber = 3; SyntaxOffset = 20 } + { StateNumber = 1; SyntaxOffset = 7 } ] + + let info = + { EncMethodDebugInformation.Empty with + StateMachineStates = states } + + let expected = + [ { StateNumber = 0; SyntaxOffset = -5 } + { StateNumber = 1; SyntaxOffset = 7 } + { StateNumber = -4; SyntaxOffset = 20 } + { StateNumber = 3; SyntaxOffset = 20 } ] + + let blob = serializeStateMachineStates info + Assert.Equal(expected, deserializeStateMachineStates blob) + +[] +let ``Full record round-trips through the three blobs`` () = + let info = + { MethodOrdinal = 2 + LocalSlots = [ EncLocalSlotInfo.Slot(0, 4, 0); EncLocalSlotInfo.Temp ] + Closures = [ { SyntaxOffset = 0 } ] + Lambdas = [ { SyntaxOffset = 9; ClosureOrdinal = 0 } ] + StateMachineStates = [ { StateNumber = 0; SyntaxOffset = 9 } ] } + + let decoded = + deserialize (serializeLocalSlots info) (serializeLambdaMap info) (serializeStateMachineStates info) + + Assert.Equal(info, decoded) + +// ----------------------------------------------------------------------- +// Occurrence-key packing +// ----------------------------------------------------------------------- + +[] +let ``Occurrence keys pack and unpack ordinal chains`` () = + // Depth 1: the key is the ordinal itself. + Assert.Equal(Some 0, tryEncodeOccurrenceKey [ 0 ]) + Assert.Equal(Some 5, tryEncodeOccurrenceKey [ 5 ]) + Assert.Equal(Some 0xFFFF, tryEncodeOccurrenceKey [ 0xFFFF ]) + Assert.Equal([ 5 ], decodeOccurrenceKey 5) + + // Depth 2: the parent segment is stored biased by one, so [0; 0] never + // collides with the depth-1 key 0. + Assert.Equal(Some 0x10000, tryEncodeOccurrenceKey [ 0; 0 ]) + Assert.Equal([ 0; 0 ], decodeOccurrenceKey 0x10000) + Assert.Equal(Some 0x40007, tryEncodeOccurrenceKey [ 3; 7 ]) + Assert.Equal([ 3; 7 ], decodeOccurrenceKey 0x40007) + + // Every encodable chain round-trips ([0x1FFE; 0xFFFD] packs to the maximum + // key 0x1FFFFFFD that still fits the compressed-integer budget after the + // baseline adjustment). + for chain in [ [ 0 ]; [ 42 ]; [ 0xFFFF ]; [ 0; 0 ]; [ 3; 7 ]; [ 0x1FFE; 0xFFFD ] ] do + match tryEncodeOccurrenceKey chain with + | Some key -> Assert.Equal(chain, decodeOccurrenceKey key) + | None -> failwith $"expected chain %A{chain} to be encodable" + +[] +let ``Occurrence key packing fails closed past its limits`` () = + // Deeper than two segments. + Assert.Equal(None, tryEncodeOccurrenceKey [ 1; 2; 3 ]) + // Empty chain. + Assert.Equal(None, tryEncodeOccurrenceKey []) + // Ordinal past 16 bits. + Assert.Equal(None, tryEncodeOccurrenceKey [ 0x10000 ]) + Assert.Equal(None, tryEncodeOccurrenceKey [ 0; 0x10000 ]) + // Parent past the compressed-integer budget (29 bits incl. the bias). + Assert.Equal(None, tryEncodeOccurrenceKey [ 0x1FFF; 0 ]) + // Packed key past the budget even though both segments are individually valid. + Assert.Equal(None, tryEncodeOccurrenceKey [ 0x1FFE; 0xFFFF ]) + // Regression: a large in-range parent whose packed key wraps NEGATIVE in int32 + // ((0xFFFE + 1) <<< 16). The int32 packing accepted the wrapped key (negative + // <= MaxOccurrenceKey), failing open; the int64 packing must reject it. + Assert.Equal(None, tryEncodeOccurrenceKey [ 0xFFFE; 0 ]) + Assert.Equal(None, tryEncodeOccurrenceKey [ 0x7FFF; 0xFFFF ]) + // Negative ordinals. + Assert.Equal(None, tryEncodeOccurrenceKey [ -1 ]) + Assert.Equal(None, tryEncodeOccurrenceKey [ -1; 0 ]) + +// ----------------------------------------------------------------------- +// Cross-validation against Roslyn-emitted blobs +// ----------------------------------------------------------------------- + +/// C# source with nested capturing lambdas, LINQ lambdas, and an async method, so a +/// debug build emits all three EnC CDI kinds. +let private crossValidationSource = + """ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Scratch +{ + public class Lambdas + { + public Func MakeAdder(int x) + { + int y = x + 1; + Func inner = a => a + x + y; + return b => inner(b) + x; + } + + public int UseLinq(IEnumerable items, int threshold) + { + var filtered = items.Where(i => i > threshold).Select(i => i * 2); + return filtered.Sum(i => i + threshold); + } + + public async Task ComputeAsync(int x) + { + await Task.Delay(1); + int y = x * 2; + await Task.Yield(); + Func f = a => a + y; + return f(x); + } + } +} +""" + +/// Builds the cross-validation C# library with the repo SDK (DebugType=portable) and +/// returns the path of the produced Portable PDB. +let private buildCSharpScratchPdb () = + let workDir = + Path.Combine(Path.GetTempPath(), "fsharp-enc-cdi-" + Guid.NewGuid().ToString("N")) + + Directory.CreateDirectory workDir |> ignore + let projPath = Path.Combine(workDir, "scratch.csproj") + File.WriteAllText(Path.Combine(workDir, "Scratch.cs"), crossValidationSource) + + File.WriteAllText( + projPath, + """ + + Library + net10.0 + portable + false + true + disable + + +""" + ) + + let psi = System.Diagnostics.ProcessStartInfo() + // Resolve the dotnet host like the rest of the test framework: repo-local .dotnet + // first, PATH fallback otherwise (the hand-rolled path misses on some CI images). + psi.FileName <- TestFramework.initialConfig.DotNetExe + // ProcessStartInfo.ArgumentList does not exist on net472, so build the quoted argument + // string by hand (projPath is the only argument that can contain spaces). + psi.Arguments <- $"build \"{projPath}\" -c Debug -p:DebugType=portable -v m" + // net472 defaults UseShellExecute to true, which is incompatible with stream + // redirection; set it explicitly so the Desktop test legs can start the process. + psi.UseShellExecute <- false + psi.RedirectStandardOutput <- true + psi.RedirectStandardError <- true + psi.WorkingDirectory <- workDir + + use p = new System.Diagnostics.Process() + p.StartInfo <- psi + p.Start() |> ignore + let stdout = p.StandardOutput.ReadToEnd() + let stderr = p.StandardError.ReadToEnd() + p.WaitForExit() + + if p.ExitCode <> 0 then + failwith $"dotnet build of the C# scratch library failed: {stdout}\n{stderr}" + + let pdbPath = Path.Combine(workDir, "bin", "Debug", "net10.0", "scratch.pdb") + Assert.True(File.Exists pdbPath, $"expected portable PDB at {pdbPath}") + workDir, pdbPath + +/// Reads all CustomDebugInformation rows of the given kind from a portable PDB, +/// returning (parent method token, blob bytes) pairs. +let private readCdiBlobs (reader: MetadataReader) (kind: Guid) = + [ for cdiHandle in reader.CustomDebugInformation do + let cdi = reader.GetCustomDebugInformation cdiHandle + + if reader.GetGuid cdi.Kind = kind then + let parent = MetadataTokens.GetToken cdi.Parent + parent, reader.GetBlobBytes cdi.Value ] + +[] +let ``Roslyn-emitted EnC CDI blobs decode and re-encode byte-for-byte`` () = + let workDir, pdbPath = buildCSharpScratchPdb () + + try + use stream = File.OpenRead pdbPath + use provider = MetadataReaderProvider.FromPortablePdbStream stream + let reader = provider.GetMetadataReader() + + // ---- EnC Lambda and Closure Map ---- + let lambdaMaps = readCdiBlobs reader PortableCustomDebugInfoKinds.encLambdaAndClosureMap + Assert.NotEmpty lambdaMaps + + let mutable totalLambdas = 0 + let mutable totalClosures = 0 + + for _, blob in lambdaMaps do + let methodOrdinal, closures, lambdas = deserializeLambdaMap blob + + // Structural sanity: defined ordinal, at least one lambda or closure, + // closure ordinals within range. + Assert.True(methodOrdinal >= 0, "Roslyn lambda maps carry a defined method ordinal") + Assert.True(not (List.isEmpty closures) || not (List.isEmpty lambdas)) + + for lambda in lambdas do + Assert.InRange(lambda.ClosureOrdinal, MinClosureOrdinal, closures.Length - 1) + + totalLambdas <- totalLambdas + lambdas.Length + totalClosures <- totalClosures + closures.Length + + // Byte-for-byte: re-encoding the decoded map must reproduce Roslyn's blob. + let reencoded = + serializeLambdaMap + { EncMethodDebugInformation.Empty with + MethodOrdinal = methodOrdinal + Closures = closures + Lambdas = lambdas } + + Assert.Equal(blob, reencoded) + + // The source has 6 lambdas (2 in MakeAdder, 3 in UseLinq, 1 in ComputeAsync) + // and capturing closures in every method. + Assert.True(totalLambdas >= 6, $"expected at least 6 lambdas, found {totalLambdas}") + Assert.True(totalClosures >= 3, $"expected at least 3 closures, found {totalClosures}") + + // ---- EnC Local Slot Map ---- + let slotMaps = readCdiBlobs reader PortableCustomDebugInfoKinds.encLocalSlotMap + Assert.NotEmpty slotMaps + + let mutable longLivedSlots = 0 + + for _, blob in slotMaps do + let slots = deserializeLocalSlots blob + Assert.NotEmpty slots + + for slot in slots do + match slot with + | EncLocalSlotInfo.Temp -> () + | EncLocalSlotInfo.Slot(kind, _, ordinal) -> + Assert.InRange(kind, 0, MaxSerializableLocalKind) + Assert.True(ordinal >= 0) + longLivedSlots <- longLivedSlots + 1 + + let reencoded = + serializeLocalSlots + { EncMethodDebugInformation.Empty with + LocalSlots = slots } + + Assert.Equal(blob, reencoded) + + Assert.True(longLivedSlots > 0, "expected at least one long-lived local slot") + + // ---- EnC State Machine State Map ---- + let stateMaps = readCdiBlobs reader PortableCustomDebugInfoKinds.encStateMachineStateMap + Assert.NotEmpty stateMaps + + for _, blob in stateMaps do + let states = deserializeStateMachineStates blob + + // ComputeAsync has two suspension points (await Task.Delay, await + // Task.Yield); the decoder enforces monotone offsets, re-check here. + Assert.True(states.Length >= 2, $"expected at least 2 states, found {states.Length}") + + let offsets = states |> List.map (fun s -> s.SyntaxOffset) + Assert.Equal(List.sort offsets, offsets) + + let reencoded = + serializeStateMachineStates + { EncMethodDebugInformation.Empty with + StateMachineStates = states } + + Assert.Equal(blob, reencoded) + finally + try + Directory.Delete(workDir, true) + with _ -> + () + +// ----------------------------------------------------------------------- +// Synthetic plumbing: exercise the real ILBinaryWriter/PortablePdbGenerator path +// (no hot reload flag, no session machinery) with a synthetic CDI row map. +// ----------------------------------------------------------------------- + +module private Plumbing = + + // A real primary-assembly reference (this process's own corelib) so ilg.typ_Object + // resolves to an external TypeRef; the IL writer requires every type's 'extends' to + // resolve to a real System.Object, even one it never loads. + let private primaryAssemblyRef = ILAssemblyRef.FromAssemblyName(typeof.Assembly.GetName()) + + let private ilg = + mkILGlobals (ILScopeRef.Assembly primaryAssemblyRef, [], ILScopeRef.Assembly primaryAssemblyRef) + + let private mkMethod (name: string) (body: MethodBody) : ILMethodDef = + mkILNonGenericStaticMethod (name, ILMemberAccess.Public, [], mkILReturn ILType.Void, body) + + let private mkType (typeName: string) (methods: (string * MethodBody) list) : ILTypeDef = + let methods = methods |> List.map (fun (name, body) -> mkMethod name body) |> mkILMethods + + ILTypeDef( + typeName, + TypeAttributes.Public, + ILTypeDefLayout.Auto, + [], + [], + Some ilg.typ_Object, + methods, + mkILTypeDefs [], + mkILFields [], + emptyILMethodImpls, + mkILEvents [], + mkILProperties [], + emptyILSecurityDecls, + emptyILCustomAttrsStored + ) + + /// Builds a minimal in-memory module with one type per (typeName, methodNames) pair. + /// Two types may each declare a method of the same name: the IL writer's per-type + /// method table forbids two same-named methods of the same arity *within one type* + /// (unrelated to CDI), but the CDI name-keying this test exercises is per-assembly, + /// so cross-type name clashes are exactly the ambiguous case to cover. + let buildModuleOfMethodBodies (types: (string * (string * MethodBody) list) list) : ILModuleDef = + let typeDefs = types |> List.map (fun (typeName, methods) -> mkType typeName methods) + + let assemblyName = "EncCdiPlumbing_" + Guid.NewGuid().ToString("N") + + mkILSimpleModule + assemblyName + assemblyName + true + (4, 0) + false + (mkILTypeDefs typeDefs) + None + None + 0 + (mkILExportedTypes []) + "v4.0.30319" // Non-empty: pins the metadata version explicitly rather than relying on primaryAssemblyRef's. + + let buildModuleOfTypes (types: (string * string list) list) : ILModuleDef = + types + |> List.map (fun (typeName, methodNames) -> + typeName, methodNames |> List.map (fun name -> name, MethodBody.Abstract)) + |> buildModuleOfMethodBodies + + /// Builds a minimal in-memory module with one type "T" declaring 'methodNames'. + let buildModule (methodNames: string list) : ILModuleDef = buildModuleOfTypes [ "T", methodNames ] + + /// Writes 'modul' through the same in-memory ILBinaryWriter entry point fsi.fs uses for + /// dynamic assembly emission, attaching 'methodCustomDebugInfoRows' as the CDI side + /// channel. No hot reload flag or session state is involved. + let writeInMemory (modul: ILModuleDef) (methodCustomDebugInfoRows: Map) = + let options: options = + { + ilg = ilg + outfile = "test.dll" + pdbfile = Some "test.pdb" + portablePDB = true + embeddedPDB = false + embedAllSource = false + embedSourceList = [] + allGivenSources = [] + sourceLink = "" + checksumAlgorithm = HashAlgorithm.Sha256 + signer = None + emitTailcalls = true + deterministic = false + dumpDebugInfo = false + referenceAssemblyOnly = false + referenceAssemblyAttribOpt = None + referenceAssemblySignatureHash = None + pathMap = PathMap.empty + methodCustomDebugInfoRows = methodCustomDebugInfoRows + } + + match WriteILBinaryInMemory(options, modul, id) with + | assemblyBytes, Some pdbBytes -> assemblyBytes, pdbBytes + | _, None -> failwith "expected a portable PDB to be produced" + + type CdiRow = + { + MethodName: string option + Kind: Guid + Blob: byte[] + } + + /// All method-parented CustomDebugInformation rows in the produced PDB, read back with + /// System.Reflection.Metadata (independent of this codebase's own decoders), resolving + /// each row's parent MethodDef token to its name via the companion assembly image. + let readAllCdiRows (assemblyBytes: byte[]) (pdbBytes: byte[]) : CdiRow list = + use peReader = new PEReader(ImmutableArray.CreateRange assemblyBytes) + let peMdReader = peReader.GetMetadataReader() + + use pdbProvider = MetadataReaderProvider.FromPortablePdbImage(ImmutableArray.CreateRange pdbBytes) + let pdbMdReader = pdbProvider.GetMetadataReader() + + let methodTokenToName = + [ for h: MethodDefinitionHandle in peMdReader.MethodDefinitions -> + MetadataTokens.GetToken(MethodDefinitionHandle.op_Implicit h: EntityHandle), + peMdReader.GetString(peMdReader.GetMethodDefinition(h).Name) ] + |> Map.ofList + + [ for cdiHandle in pdbMdReader.CustomDebugInformation do + let cdi = pdbMdReader.GetCustomDebugInformation cdiHandle + + if cdi.Parent.Kind = HandleKind.MethodDefinition then + { + MethodName = Map.tryFind (MetadataTokens.GetToken cdi.Parent) methodTokenToName + Kind = pdbMdReader.GetGuid cdi.Kind + Blob = pdbMdReader.GetBlobBytes cdi.Value + } ] + +[] +let ``Synthetic CustomDebugInformation row attaches to the right MethodDef`` () = + let modul = Plumbing.buildModule [ "Foo"; "Bar" ] + + let blob = + serializeLambdaMap + { EncMethodDebugInformation.Empty with + MethodOrdinal = 0 + Closures = [ { SyntaxOffset = 0 } ] + Lambdas = [ { SyntaxOffset = 5; ClosureOrdinal = 0 } ] } + + let rows = + Map.ofList [ "Foo", [ { KindGuid = PortableCustomDebugInfoKinds.encLambdaAndClosureMap; Blob = blob } ] ] + + let assemblyBytes, pdbBytes = Plumbing.writeInMemory modul rows + let cdiRows = Plumbing.readAllCdiRows assemblyBytes pdbBytes + + let row = Assert.Single cdiRows + Assert.Equal(Some "Foo", row.MethodName) + Assert.Equal(PortableCustomDebugInfoKinds.encLambdaAndClosureMap, row.Kind) + Assert.Equal(blob, row.Blob) + + // Full circle: the codec decodes exactly what was written. + let methodOrdinal, closures, lambdas = deserializeLambdaMap row.Blob + Assert.Equal(0, methodOrdinal) + Assert.Equal([ { SyntaxOffset = 0 } ], closures) + Assert.Equal([ { SyntaxOffset = 5; ClosureOrdinal = 0 } ], lambdas) + +[] +let ``Empty map produces zero CustomDebugInformation rows`` () = + let modul = Plumbing.buildModule [ "Foo" ] + let assemblyBytes, pdbBytes = Plumbing.writeInMemory modul Map.empty + Assert.Empty(Plumbing.readAllCdiRows assemblyBytes pdbBytes) + +[] +let ``A method name absent from the module attaches nothing`` () = + // Fail closed, matching the feature this codec ports from: an unresolvable name is + // silently dropped rather than raising, so it can never attach to the wrong method. + let modul = Plumbing.buildModule [ "Foo" ] + + let blob = + serializeStateMachineStates + { EncMethodDebugInformation.Empty with + StateMachineStates = [ { StateNumber = 0; SyntaxOffset = 1 } ] } + + let rows = + Map.ofList [ "DoesNotExist", [ { KindGuid = PortableCustomDebugInfoKinds.encStateMachineStateMap; Blob = blob } ] ] + + let assemblyBytes, pdbBytes = Plumbing.writeInMemory modul rows + Assert.Empty(Plumbing.readAllCdiRows assemblyBytes pdbBytes) + +[] +let ``An ambiguous method name attaches to neither method`` () = + // Two distinct types each declaring a "Dup" method: the CDI name-keying in + // PortablePdbGenerator is per-assembly (IL method name only, not qualified by + // declaring type), so this reproduces the ambiguous case without hitting the + // unrelated IL writer invariant that forbids two same-named/same-arity methods + // within a single type. + let modul = Plumbing.buildModuleOfTypes [ "T1", [ "Dup" ]; "T2", [ "Dup" ] ] + + let blob = + serializeStateMachineStates + { EncMethodDebugInformation.Empty with + StateMachineStates = [ { StateNumber = 0; SyntaxOffset = 1 } ] } + + let rows = + Map.ofList [ "Dup", [ { KindGuid = PortableCustomDebugInfoKinds.encStateMachineStateMap; Blob = blob } ] ] + + let assemblyBytes, pdbBytes = Plumbing.writeInMemory modul rows + Assert.Empty(Plumbing.readAllCdiRows assemblyBytes pdbBytes) + +[] +let ``A method name shared with unavailable metadata attaches to neither method`` () = + let modul = + Plumbing.buildModuleOfMethodBodies + [ "T1", [ "Dup", MethodBody.Abstract ] + "T2", [ "Dup", MethodBody.NotAvailable ] ] + + let blob = + serializeStateMachineStates + { EncMethodDebugInformation.Empty with + StateMachineStates = [ { StateNumber = 0; SyntaxOffset = 1 } ] } + + let rows = + Map.ofList [ "Dup", [ { KindGuid = PortableCustomDebugInfoKinds.encStateMachineStateMap; Blob = blob } ] ] + + let assemblyBytes, pdbBytes = Plumbing.writeInMemory modul rows + Assert.Empty(Plumbing.readAllCdiRows assemblyBytes pdbBytes) diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj index 5070905529f..b4d96794e14 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj +++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj @@ -470,6 +470,7 @@ + From 2e838bbba1983a34c10390973a28e929f72b8b2d Mon Sep 17 00:00:00 2001 From: Nat Elkins Date: Fri, 24 Jul 2026 06:38:42 -0400 Subject: [PATCH 14/33] Add stable synthesized-name replay infrastructure for hot reload (#20024) * Extract stable synthesized-name replay layer Add internal generated-name normalization and synthesized-name map replay support as a standalone slice. The new map state is side-channel based, all new compiler modules remain internal, and CompilerGlobalState preserves the existing no-map counter path while checking an accessor captured once per compiler state. Route existing IlxGen generated-name allocations through inert helper wrappers, add pure name-map and normalizer tests, add a normal compilation determinism guard over emitted generated names, and document the extracted seams in P5_REPORT.md. Verification: built FSharp.Compiler.Service, FSharp.Compiler.Service.Tests, FSharp.Compiler.ComponentTests, and FSharpSuite.Tests in Release; ran the migrated service test classes, the component determinism class, FSharpSuite DeterministicTests, and the FCS SurfaceArea class successfully. * Fix generated-name scope test in stable names slice * Validate hot reload generated names before classification * Format hot reload compiler sources Verified with the repository-wide Fantomas check. * Retry CI after Linux runner memory exhaustion * Make synthesized name snapshots deterministic --- .../.FSharp.Compiler.Service/11.0.100.md | 3 +- src/Compiler/CodeGen/IlxGen.fs | 64 ++--- src/Compiler/FSharp.Compiler.Service.fsproj | 3 + .../CompilerGeneratedNameMapState.fs | 68 +++++ src/Compiler/TypedTree/CompilerGlobalState.fs | 48 +++- src/Compiler/TypedTree/GeneratedNames.fs | 248 ++++++++++++++++ src/Compiler/TypedTree/SynthesizedTypeMaps.fs | 266 ++++++++++++++++++ .../CompilerGeneratedNameDeterminism.fs | 136 +++++++++ .../FSharp.Compiler.ComponentTests.fsproj | 1 + .../FSharp.Compiler.Service.Tests.fsproj | 2 + .../HotReload/GeneratedNamesTests.fs | 185 ++++++++++++ .../HotReload/NameMapTests.fs | 216 ++++++++++++++ 12 files changed, 1180 insertions(+), 60 deletions(-) create mode 100644 src/Compiler/TypedTree/CompilerGeneratedNameMapState.fs create mode 100644 src/Compiler/TypedTree/GeneratedNames.fs create mode 100644 src/Compiler/TypedTree/SynthesizedTypeMaps.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/CompilerGeneratedNameDeterminism.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/HotReload/GeneratedNamesTests.fs create mode 100644 tests/FSharp.Compiler.Service.Tests/HotReload/NameMapTests.fs diff --git a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md index 299ffeef32b..bd4c804b4f2 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md +++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md @@ -128,6 +128,7 @@ ### Added +* Added internal synthesized-name replay infrastructure for compiler-generated names, preserving normal compilation output while enabling future hot reload name stability work. * Added `FSharpMemberOrFunctionOrValue.IsPropertyAccessor` convenience property that returns true for compiler-generated property accessors (`get_X` / `set_X`). ([Issue #18157](https://github.com/dotnet/fsharp/issues/18157), [PR #19883](https://github.com/dotnet/fsharp/pull/19883)) * Added warning FS3884 when a function or delegate value is used as an interpolated string argument. ([PR #19289](https://github.com/dotnet/fsharp/pull/19289)) * Symbols: add ObsoleteDiagnosticInfo ([PR #19359](https://github.com/dotnet/fsharp/pull/19359)) @@ -152,4 +153,4 @@ * Exception field serialization (`GetObjectData` and field-restoring constructor) is now gated behind `langversion:11` (`LanguageFeature.ExceptionFieldSerializationSupport`). With langversion ≤10, exception codegen is unchanged from pre-#19342 behavior. ([PR #19746](https://github.com/dotnet/fsharp/pull/19746)) ### Breaking Changes -* Optimizer: don't inline named functions in debug builds ([PR #19548](https://github.com/dotnet/fsharp/pull/19548) \ No newline at end of file +* Optimizer: don't inline named functions in debug builds ([PR #19548](https://github.com/dotnet/fsharp/pull/19548) diff --git a/src/Compiler/CodeGen/IlxGen.fs b/src/Compiler/CodeGen/IlxGen.fs index 986acc7bba6..6e6f252606c 100644 --- a/src/Compiler/CodeGen/IlxGen.fs +++ b/src/Compiler/CodeGen/IlxGen.fs @@ -45,6 +45,13 @@ open FSharp.Compiler.TypedTreeOps.DebugPrint open FSharp.Compiler.TypeHierarchy open FSharp.Compiler.TypeRelations +// Naming wrappers routed through here so synthesized-name replay stays enforceable. +let private freshIlxName (g: TcGlobals) name m = + g.CompilerGlobalState.Value.IlxGenNiceNameGenerator.FreshCompilerGeneratedName(name, m) + +let private freshCoreName (g: TcGlobals) name m = + g.CompilerGlobalState.Value.NiceNameGenerator.FreshCompilerGeneratedName(name, m) + let getEmptyStackGuard () = StackGuard("IlxAssemblyGenerator") let IsNonErasedTypar (tp: Typar) = not tp.IsErased @@ -876,16 +883,12 @@ let GenFieldSpecForStaticField (isInteractive, g: TcGlobals, ilContainerTy, vspe elif g.realsig then assert (g.CompilerGlobalState |> Option.isSome) - mkILFieldSpecInTy ( - ilContainerTy, - CompilerGeneratedName(g.CompilerGlobalState.Value.IlxGenNiceNameGenerator.FreshCompilerGeneratedName(nm, m)), - ilTy - ) + mkILFieldSpecInTy (ilContainerTy, CompilerGeneratedName(freshIlxName g nm m), ilTy) else let fieldName = // Ensure that we have an g.CompilerGlobalState assert (g.CompilerGlobalState |> Option.isSome) - g.CompilerGlobalState.Value.IlxGenNiceNameGenerator.FreshCompilerGeneratedName(nm, m) + freshIlxName g nm m let ilFieldContainerTy = mkILTyForCompLoc (CompLocForInitClass cloc) mkILFieldSpecInTy (ilFieldContainerTy, fieldName, ilTy) @@ -4693,7 +4696,7 @@ and GenApp (cenv: cenv) cgbuf eenv (f, fty, tyargs, curriedArgs, m) sequel = let locName = // Ensure that we have an g.CompilerGlobalState assert (g.CompilerGlobalState |> Option.isSome) - g.CompilerGlobalState.Value.IlxGenNiceNameGenerator.FreshCompilerGeneratedName("arg", m), ilTy, false + freshIlxName g "arg" m, ilTy, false let loc, _realloc, eenv = AllocLocal cenv cgbuf eenv true locName scopeMarks GenExpr cenv cgbuf eenv laterArg Continue @@ -5030,13 +5033,7 @@ and GenTry cenv cgbuf eenv scopeMarks (e1, m, resultTy, spTry) = assert (cenv.g.CompilerGlobalState |> Option.isSome) let whereToSave, _realloc, eenvinner = - AllocLocal - cenv - cgbuf - eenvinner - true - (cenv.g.CompilerGlobalState.Value.IlxGenNiceNameGenerator.FreshCompilerGeneratedName("tryres", m), ilResultTy, false) - (startTryMark, endTryMark) + AllocLocal cenv cgbuf eenvinner true (freshIlxName cenv.g "tryres" m, ilResultTy, false) (startTryMark, endTryMark) Some(whereToSave, ilResultTy), eenvinner @@ -5311,8 +5308,7 @@ and GenIntegerForLoop cenv cgbuf eenv (spFor, spTo, v, e1, dir, e2, loopBody, m) // Ensure that we have an g.CompilerGlobalState assert (g.CompilerGlobalState |> Option.isSome) - let vName = - g.CompilerGlobalState.Value.IlxGenNiceNameGenerator.FreshCompilerGeneratedName("endLoop", m) + let vName = freshIlxName g "endLoop" m let v, _realloc, eenvinner = AllocLocal cenv cgbuf eenvinner true (vName, g.ilg.typ_Int32, false) (start, finish) @@ -5940,13 +5936,7 @@ and GenDefaultValue cenv cgbuf eenv (ty, m) = // Ensure that we have an g.CompilerGlobalState assert (g.CompilerGlobalState |> Option.isSome) - AllocLocal - cenv - cgbuf - eenv - true - (g.CompilerGlobalState.Value.IlxGenNiceNameGenerator.FreshCompilerGeneratedName("default", m), ilTy, false) - scopeMarks + AllocLocal cenv cgbuf eenv true (freshIlxName g "default" m, ilTy, false) scopeMarks // We can normally rely on .NET IL zero-initialization of the temporaries // we create to get zero values for struct types. // @@ -6625,25 +6615,11 @@ and GenStructStateMachine cenv cgbuf eenvouter (res: LoweredStateMachine) sequel // The local for the state machine let locIdx, realloc, _ = - AllocLocal - cenv - cgbuf - eenvouter - true - (g.CompilerGlobalState.Value.IlxGenNiceNameGenerator.FreshCompilerGeneratedName("machine", m), ilCloTy, false) - scopeMarks + AllocLocal cenv cgbuf eenvouter true (freshIlxName g "machine" m, ilCloTy, false) scopeMarks // The local for the state machine address let locIdx2, _realloc2, _ = - AllocLocal - cenv - cgbuf - eenvouter - true - (g.CompilerGlobalState.Value.IlxGenNiceNameGenerator.FreshCompilerGeneratedName(afterCodeThisVar.DisplayName, m), - ilMachineAddrTy, - false) - scopeMarks + AllocLocal cenv cgbuf eenvouter true (freshIlxName g afterCodeThisVar.DisplayName m, ilMachineAddrTy, false) scopeMarks let eenvouter = eenvouter @@ -9412,7 +9388,7 @@ and GenParams if takenNames.Contains(id.idText) then // Ensure that we have an g.CompilerGlobalState assert (g.CompilerGlobalState |> Option.isSome) - g.CompilerGlobalState.Value.NiceNameGenerator.FreshCompilerGeneratedName(id.idText, id.idRange) + freshCoreName g id.idText id.idRange else id.idText @@ -10481,13 +10457,7 @@ and EmitSaveStack cenv cgbuf eenv m scopeMarks = // Ensure that we have an g.CompilerGlobalState assert (cenv.g.CompilerGlobalState |> Option.isSome) - AllocLocal - cenv - cgbuf - eenv - true - (cenv.g.CompilerGlobalState.Value.IlxGenNiceNameGenerator.FreshCompilerGeneratedName("spill", m), ty, false) - scopeMarks + AllocLocal cenv cgbuf eenv true (freshIlxName cenv.g "spill" m, ty, false) scopeMarks idx, eenv) diff --git a/src/Compiler/FSharp.Compiler.Service.fsproj b/src/Compiler/FSharp.Compiler.Service.fsproj index 2d0b77fbf69..1f5278f6ecc 100644 --- a/src/Compiler/FSharp.Compiler.Service.fsproj +++ b/src/Compiler/FSharp.Compiler.Service.fsproj @@ -308,6 +308,8 @@ SyntaxTree\LexHelpers.fs + + SyntaxTree\FsLexOutput\pplex.fsi @@ -328,6 +330,7 @@ + diff --git a/src/Compiler/TypedTree/CompilerGeneratedNameMapState.fs b/src/Compiler/TypedTree/CompilerGeneratedNameMapState.fs new file mode 100644 index 00000000000..196ab294e8c --- /dev/null +++ b/src/Compiler/TypedTree/CompilerGeneratedNameMapState.fs @@ -0,0 +1,68 @@ +module internal FSharp.Compiler.CompilerGeneratedNameMapState + +open System.Runtime.CompilerServices + +/// Minimal abstraction for compiler-generated name replay/state. +/// Implementations can be hot-reload aware without coupling core compiler paths +/// to a concrete synthesized-name map type. +type ICompilerGeneratedNameMap = + /// Resets allocation cursors so the next serialized code-generation pass replays the snapshot from its first slot. + abstract BeginSession: unit -> unit + + /// Returns the next name in deterministic encounter order for this basic name. + /// Consumers must serialize code generation while a map is installed: synchronization prevents data races, + /// but concurrent callers cannot make encounter order independent of thread scheduling. + abstract GetOrAddName: basicName: string -> string + + /// Captures the names in allocation order, grouped by normalized basic name. + abstract Snapshot: seq + + /// Replaces the current replay state with a previously captured allocation-order snapshot. + abstract LoadSnapshot: snapshot: seq -> unit + +// Keep optional name-map state external to CompilerGlobalState so core signatures can remain stable. +type private NameMapHolder() = + // Reads vastly outnumber writes. Installs happen at most a handful of times per + // compile, so the slot is a single volatile field rather than a lock-guarded one. + // Reference reads and writes are atomic, and the volatile semantics preserve the + // visibility ordering the lock provided. + [] + let mutable current: ICompilerGeneratedNameMap option = None + + member _.TryGet() = current + member _.Set(value: ICompilerGeneratedNameMap option) = current <- value + +let private holders = ConditionalWeakTable() + +let private getOrCreateHolder (owner: obj) = + holders.GetValue(owner, fun _ -> NameMapHolder()) + +/// Pure read: never inserts, so a compile that never installs a map pays a single +/// failed weak-table lookup. +let private tryGetHolder (owner: obj) = + match holders.TryGetValue owner with + | true, holder -> Some holder + | _ -> None + +let tryGetCompilerGeneratedNameMap (owner: obj) = + match tryGetHolder owner with + | Some holder -> holder.TryGet() + | None -> None + +/// A reader for the owner's name-map slot. The holder is resolved exactly once here +/// and captured by the returned closure, so each generated name costs a single +/// volatile field read rather than a ConditionalWeakTable probe and lock. +/// +/// The holder is created eagerly on purpose: the emit hook can install the map later +/// in the compile, after CompilerGlobalState and therefore this accessor have been +/// constructed, and it installs through the same owner. Pre-creating the holder means +/// that later install mutates the object this closure captured, so the map is observed. +let getCompilerGeneratedNameMapAccessor (owner: obj) : unit -> ICompilerGeneratedNameMap option = + let holder = getOrCreateHolder owner + fun () -> holder.TryGet() + +let setCompilerGeneratedNameMap (owner: obj) (map: ICompilerGeneratedNameMap) = (getOrCreateHolder owner).Set(Some map) + +let setCompilerGeneratedNameMapOpt (owner: obj) (map: ICompilerGeneratedNameMap option) = (getOrCreateHolder owner).Set(map) + +let clearCompilerGeneratedNameMap (owner: obj) = (getOrCreateHolder owner).Set(None) diff --git a/src/Compiler/TypedTree/CompilerGlobalState.fs b/src/Compiler/TypedTree/CompilerGlobalState.fs index 1f46a53ad6c..cd7ccb9a60a 100644 --- a/src/Compiler/TypedTree/CompilerGlobalState.fs +++ b/src/Compiler/TypedTree/CompilerGlobalState.fs @@ -8,6 +8,7 @@ open System open System.Collections.Concurrent open System.Threading open Internal.Utilities.Library +open FSharp.Compiler.CompilerGeneratedNameMapState open FSharp.Compiler.Syntax.PrettyNaming open FSharp.Compiler.Text @@ -18,7 +19,7 @@ open FSharp.Compiler.Text /// It is made concurrency-safe since a global instance of the type is allocated in tast.fs, and it is good /// policy to make all globally-allocated objects concurrency safe in case future versions of the compiler /// are used to host multiple concurrent instances of compilation. -type NiceNameGenerator() = +type NiceNameGenerator(getCompilerGeneratedNameMap: unit -> ICompilerGeneratedNameMap option) = let basicNameCounts = ConcurrentDictionary(max Environment.ProcessorCount 1, 127) // Cache this as a delegate. let basicNameCountsAddDelegate = Func(fun _ -> ref 0) @@ -34,16 +35,32 @@ type NiceNameGenerator() = CompilerGeneratedNameSuffix basicName (string m.StartLine + (match (count - 1) with 0 -> "" | n -> "-" + string n)) member _.FreshCompilerGeneratedNameOfBasicName (basicName, m: range) = - let count = increment basicName m - mkName basicName m count + match getCompilerGeneratedNameMap() with + | Some map -> map.GetOrAddName basicName + | None -> + let count = increment basicName m + mkName basicName m count member this.FreshCompilerGeneratedName (name, m: range) = this.FreshCompilerGeneratedNameOfBasicName (GetBasicNameOfPossibleCompilerGeneratedName name, m) member _.FreshCompilerGeneratedNameInScope (scopeFileIndex: int, name: string, m: range) = let basicName = GetBasicNameOfPossibleCompilerGeneratedName name - let count = incrementBucket basicName scopeFileIndex - mkName basicName m count + + // The replay map must win over per-file occurrence buckets, exactly as it + // does in FreshCompilerGeneratedNameOfBasicName. When a session installs the + // map, every allocation path replays the baseline's stable names. Otherwise, + // line-based per-file names would drift under edits. The map is only ever + // installed by the hot reload emit hook or by an in-process compile, so the + // deterministic per-file bucketing from https://github.com/dotnet/fsharp/issues/19732 + // is untouched in normal compilation. + match getCompilerGeneratedNameMap() with + | Some map -> map.GetOrAddName basicName + | None -> + let count = incrementBucket basicName scopeFileIndex + mkName basicName m count + + new () = NiceNameGenerator(fun () -> None) /// Reset the per-(basicName, file) occurrence counters so a subsequent codegen run assigns the /// same compiler-generated occurrence names a fresh process would. Callers must ensure no @@ -56,16 +73,18 @@ type NiceNameGenerator() = /// /// This type may be accessed concurrently, though in practice it is only used from the compilation thread. /// It is made concurrency-safe since a global instance of the type is allocated in tast.fs. -type StableNiceNameGenerator() = +type StableNiceNameGenerator(getCompilerGeneratedNameMap: unit -> ICompilerGeneratedNameMap option) = let niceNames = ConcurrentDictionary>(max Environment.ProcessorCount 1, 127) - let innerGenerator = NiceNameGenerator() + let innerGenerator = NiceNameGenerator(getCompilerGeneratedNameMap) member x.GetUniqueCompilerGeneratedName (name, m: range, uniq) = let basicName = GetBasicNameOfPossibleCompilerGeneratedName name let key = basicName, uniq niceNames.GetOrAddLazy(key, fun (basicName, _) -> innerGenerator.FreshCompilerGeneratedNameOfBasicName(basicName, m)) + new () = StableNiceNameGenerator(fun () -> None) + /// Reset the stable-name cache and inner occurrence counters, so both the cached stable names and /// the underlying occurrence counters are cleared. See NiceNameGenerator.ResetCompilerGeneratedNameState. member _.ResetCompilerGeneratedNameState() = @@ -78,15 +97,20 @@ type PerFileNamingScope internal (nng: NiceNameGenerator, fileIndex: int) = member _.Fresh (name: string, m: range) = nng.FreshCompilerGeneratedNameInScope(fileIndex, name, m) -type internal CompilerGlobalState () = +type internal CompilerGlobalState () as this = + /// Reader for the optional synthesized-name map attached to this instance. The + /// accessor resolves the side-channel slot once, so each generated name costs a + /// single None check, not a weak-table probe and lock, when no map is installed. + let getCompilerGeneratedNameMap = getCompilerGeneratedNameMapAccessor (this :> obj) + /// A global generator of compiler generated names - let globalNng = NiceNameGenerator() + let globalNng = NiceNameGenerator(getCompilerGeneratedNameMap) /// A global generator of stable compiler generated names - let globalStableNameGenerator = StableNiceNameGenerator () + let globalStableNameGenerator = StableNiceNameGenerator(getCompilerGeneratedNameMap) /// A name generator used by IlxGen for static fields, some generated arguments and other things. - let ilxgenGlobalNng = NiceNameGenerator () + let ilxgenGlobalNng = NiceNameGenerator(getCompilerGeneratedNameMap) member _.NiceNameGenerator = globalNng @@ -118,4 +142,4 @@ let newUnique() = Interlocked.Increment &uniqueCount let mutable private stampCount = 0L let newStamp() = let stamp = Interlocked.Increment &stampCount - stamp \ No newline at end of file + stamp diff --git a/src/Compiler/TypedTree/GeneratedNames.fs b/src/Compiler/TypedTree/GeneratedNames.fs new file mode 100644 index 00000000000..ff09f7bcee9 --- /dev/null +++ b/src/Compiler/TypedTree/GeneratedNames.fs @@ -0,0 +1,248 @@ +module internal FSharp.Compiler.GeneratedNames + +open System +open System.Text.RegularExpressions + +/// Marker of occurrence-keyed closure class names produced by hot reload closure +/// name allocation: +/// `{base}@hotreload#g{generation}_o{occurrenceChain}`. Generation 0 names are minted +/// by flag-on baseline compiles. Generation N >= 1 names are minted for occurrences +/// first allocated by a delta compile of session generation N. The `#g..._o...` +/// suffix space is disjoint from the replayable `-{ordinal}` suffix space of +/// FSharpSynthesizedTypeMaps, so these names never parse as replay ordinals and are +/// never produced by sequence replay. +[] +let HotReloadGenerationSuffixedNameInfix = "@hotreload#g" + +type SynthesizedPositionalName = + { + NormalizedBasicName: string + Ordinal: int list + } + +type HotReloadReplayName = + { + NormalizedBasicName: string + ReplayOrdinal: int + } + +type HotReloadGenerationName = + { + NormalizedBasicName: string + Generation: int + OccurrenceOrdinal: int list + } + +let private debugPipeNameRegex = + lazy Regex(@"^Pipe #[1-9][0-9]* (?:input|stage #[1-9][0-9]*) at line ([1-9][0-9]*)$", RegexOptions.CultureInvariant) + +let private tryParseNonNegativeInt (text: string) = + match Int32.TryParse text with + | true, value when value >= 0 -> Some value + | _ -> None + +let private tryParsePositiveInt (text: string) = + match Int32.TryParse text with + | true, value when value > 0 -> Some value + | _ -> None + +let private tryParseLineOrdinalSuffix (suffix: string) = + let dashIndex = suffix.IndexOf('-') + + if dashIndex < 0 then + tryParsePositiveInt suffix |> Option.map (fun line -> line, 0) + elif dashIndex > 0 && dashIndex < suffix.Length - 1 then + match tryParsePositiveInt (suffix.Substring(0, dashIndex)), tryParseNonNegativeInt (suffix.Substring(dashIndex + 1)) with + | Some line, Some ordinal -> Some(line, ordinal) + | _ -> None + else + None + +let private tryNormalizeDebugPipeBasicName (name: string) = + let matchResult = debugPipeNameRegex.Value.Match name + + if matchResult.Success then + match tryParsePositiveInt matchResult.Groups[1].Value with + | Some line -> + let marker = " at line " + let markerIndex = name.LastIndexOf(marker, StringComparison.Ordinal) + + if markerIndex > 0 then + Some(name.Substring(0, markerIndex), line) + else + None + | None -> None + else + None + +let private tryParseOccurrenceOrdinal (text: string) = + if String.IsNullOrWhiteSpace text then + None + else + let parts = text.Split([| '_' |], StringSplitOptions.None) + + if parts |> Array.exists String.IsNullOrWhiteSpace then + None + else + let parsed = parts |> Array.map tryParseNonNegativeInt + + if parsed |> Array.forall Option.isSome then + Some(parsed |> Array.map Option.get |> Array.toList) + else + None + +let private positionalName normalizedBasicName ordinal = + { + NormalizedBasicName = normalizedBasicName + Ordinal = ordinal + } + +let private tryNormalizeDebugPipeName (name: string) = + tryNormalizeDebugPipeBasicName name + |> Option.map (fun (normalizedBasicName, line) -> positionalName normalizedBasicName [ line; 0 ]) + +let TryNormalizeHotReloadGenerationName (name: string) = + let markerIndex = + name.IndexOf(HotReloadGenerationSuffixedNameInfix, StringComparison.Ordinal) + + if markerIndex <= 0 then + None + else + let baseName = name.Substring(0, markerIndex) + let generationStart = markerIndex + HotReloadGenerationSuffixedNameInfix.Length + let ordinalMarker = "_o" + + let ordinalMarkerIndex = + name.IndexOf(ordinalMarker, generationStart, StringComparison.Ordinal) + + if + ordinalMarkerIndex <= generationStart + || ordinalMarkerIndex + ordinalMarker.Length >= name.Length + || String.IsNullOrWhiteSpace baseName + || baseName.IndexOf("@", StringComparison.Ordinal) >= 0 + then + None + else + match + tryParseNonNegativeInt (name.Substring(generationStart, ordinalMarkerIndex - generationStart)), + tryParseOccurrenceOrdinal (name.Substring(ordinalMarkerIndex + ordinalMarker.Length)) + with + | Some generation, Some occurrenceOrdinal -> + let normalizedBasicName = + match tryNormalizeDebugPipeBasicName baseName with + | Some(normalizedPipeName, _) -> normalizedPipeName + | None -> baseName + + Some + { + NormalizedBasicName = normalizedBasicName + Generation = generation + OccurrenceOrdinal = occurrenceOrdinal + } + | _ -> None + +/// Recognizes well-formed occurrence-keyed generation-suffixed closure class names: +/// `{base}@hotreload#g{N}_o{chain}`, any generation. +let IsHotReloadGenerationSuffixedName (name: string) = + not (String.IsNullOrEmpty name) + && (TryNormalizeHotReloadGenerationName name |> Option.isSome) + +/// Parses the generation of a well-formed occurrence-keyed closure class name: +/// `f@hotreload#g2_o3` -> Some 2. None when the name is not generation-suffixed +/// or any part of the name is malformed. +let TryGetHotReloadNameGeneration (name: string) : int option = + if String.IsNullOrEmpty name then + None + else + TryNormalizeHotReloadGenerationName name |> Option.map _.Generation + +let TryNormalizeHotReloadReplayName (name: string) = + let marker = "@hotreload" + let markerIndex = name.LastIndexOf(marker, StringComparison.Ordinal) + + if markerIndex <= 0 then + None + else + let suffixStart = markerIndex + marker.Length + let suffix = name.Substring suffixStart + let baseName = name.Substring(0, markerIndex) + + if + String.IsNullOrWhiteSpace baseName + || baseName.IndexOf("@", StringComparison.Ordinal) >= 0 + then + None + else + let ordinalOpt = + if suffix = "" then + Some 0 + elif suffix.StartsWith("-", StringComparison.Ordinal) then + tryParsePositiveInt (suffix.Substring 1) + else + None + + ordinalOpt + |> Option.map (fun ordinal -> + let normalizedBasicName = + match tryNormalizeDebugPipeBasicName baseName with + | Some(normalizedPipeName, _) -> normalizedPipeName + | None -> baseName + + { + NormalizedBasicName = normalizedBasicName + ReplayOrdinal = ordinal + }) + +let private tryNormalizeHotReloadOrdinalName (name: string) = + TryNormalizeHotReloadReplayName name + |> Option.map (fun replayName -> + let ordinal = + let markerIndex = name.LastIndexOf("@hotreload", StringComparison.Ordinal) + let baseName = name.Substring(0, markerIndex) + + match tryNormalizeDebugPipeBasicName baseName with + | Some(_, line) -> [ line; replayName.ReplayOrdinal ] + | None -> [ replayName.ReplayOrdinal ] + + positionalName replayName.NormalizedBasicName ordinal) + +let private tryNormalizeLineOrdinalName (name: string) = + let atIndex = name.LastIndexOf('@') + + if atIndex <= 0 || atIndex = name.Length - 1 then + None + else + let baseName = name.Substring(0, atIndex) + let suffix = name.Substring(atIndex + 1) + + match tryParseLineOrdinalSuffix suffix with + | None -> None + | Some(line, ordinal) -> + match tryNormalizeDebugPipeBasicName baseName with + | Some(normalizedPipeName, pipeLine) when pipeLine = line -> Some(positionalName normalizedPipeName [ line; ordinal ]) + | Some _ -> None + | None -> + if + String.IsNullOrWhiteSpace baseName + || baseName.IndexOf("@", StringComparison.Ordinal) >= 0 + || baseName.StartsWith("Pipe #", StringComparison.Ordinal) + then + None + else + Some(positionalName baseName [ line; ordinal ]) + +let tryNormalizeSynthesizedTypeNameForPositionalPairing (name: string) = + if String.IsNullOrWhiteSpace name then + None + else + match tryNormalizeHotReloadOrdinalName name with + | Some normalized -> Some normalized + | None -> + match tryNormalizeLineOrdinalName name with + | Some normalized -> Some normalized + | None -> tryNormalizeDebugPipeName name + +let SynthesizedNameMapKey (basicName: string) = + match tryNormalizeSynthesizedTypeNameForPositionalPairing basicName with + | Some normalized -> normalized.NormalizedBasicName + | None -> basicName diff --git a/src/Compiler/TypedTree/SynthesizedTypeMaps.fs b/src/Compiler/TypedTree/SynthesizedTypeMaps.fs new file mode 100644 index 00000000000..3af9e23add4 --- /dev/null +++ b/src/Compiler/TypedTree/SynthesizedTypeMaps.fs @@ -0,0 +1,266 @@ +module internal FSharp.Compiler.SynthesizedTypeMaps + +open System +open System.Collections.Generic + +open FSharp.Compiler.CompilerGeneratedNameMapState +open FSharp.Compiler.GeneratedNames +open FSharp.Compiler.Syntax.PrettyNaming + +/// +/// Provides stable compiler-generated names across hot reload sessions. +/// +/// Replay buckets are keyed by line-normalized basic name. Bucket values remain the +/// original generation-0 full names, so a matched closure whose code moves from line +/// 28 to line 30 still gets its line-28 birth name back. That mirrors Roslyn EnC: +/// identity is established at first allocation and replayed exactly. +/// +type FSharpSynthesizedTypeMaps() = + let syncLock = obj () + // Every access is protected by syncLock so allocation order and bucket updates stay atomic. + let buckets = Dictionary>(StringComparer.Ordinal) + let ordinals = Dictionary(StringComparer.Ordinal) + let mutable usesRecordedSnapshot = false + + let makeHotReloadName (baseName: string) ordinal = + let suffix = if ordinal <= 0 then "hotreload" else $"hotreload-{ordinal}" + + CompilerGeneratedNameSuffix baseName suffix + + let createBucket (names: string[]) = + let bucket = ResizeArray() + + for name in names do + bucket.Add(name) + + bucket + + let computeName basicName index = makeHotReloadName basicName index + + let getOrAddBucket mapKey = + match buckets.TryGetValue mapKey with + | true, bucket -> bucket + | _ -> + let bucket = ResizeArray() + buckets.Add(mapKey, bucket) + bucket + + let tryGetHotReloadOrdinal (mapKey: string) (name: string) = + match TryNormalizeHotReloadReplayName name with + | Some replayName when replayName.NormalizedBasicName = mapKey -> Some replayName.ReplayOrdinal + | _ -> None + + let tryGetStableOrdinal (mapKey: string) (name: string) = + match TryNormalizeHotReloadReplayName name with + | Some replayName when replayName.NormalizedBasicName = mapKey -> Some [ replayName.ReplayOrdinal ] + | _ -> + match TryNormalizeHotReloadGenerationName name with + | Some generationName when generationName.NormalizedBasicName = mapKey -> Some generationName.OccurrenceOrdinal + | _ -> None + + let canonicalizeSnapshotNames mapKey (names: string[]) = + let parsed = + names + |> Array.mapi (fun index name -> index, name, tryGetHotReloadOrdinal mapKey name) + + if parsed |> Array.forall (fun (_, _, ordinalOpt) -> ordinalOpt.IsSome) then + // IL metadata can enumerate synthesized helpers in a different order than allocation. + // Normalize pure hot-reload buckets so replay always starts at ordinal 0, then 1, etc. + let sorted = + parsed + |> Array.sortBy (fun (index, _, ordinalOpt) -> struct (ordinalOpt.Value, index)) + + let ordinalsAreDistinct = + let ordinals = sorted |> Array.map (fun (_, _, ordinalOpt) -> ordinalOpt.Value) + (Array.distinct ordinals).Length = ordinals.Length + + if ordinalsAreDistinct && sorted.Length > 0 then + // Place every name at the slot index its ordinal records, filling holes + // with the computed name for that slot. Holes arise exactly where an + // allocation's replay name never surfaced in IL. The filler equals what + // GetOrAddName produced for that slot originally, so replay positions + // are exact. + let maxOrdinal = + sorted |> Array.map (fun (_, _, ordinalOpt) -> ordinalOpt.Value) |> Array.max + + let namesByOrdinal = + sorted + |> Array.map (fun (_, name, ordinalOpt) -> ordinalOpt.Value, name) + |> Map.ofArray + + let replayFillBasicName = + let rawBasicNames = + sorted + |> Array.choose (fun (_, name, _) -> + let rawBasicName = GetBasicNameOfPossibleCompilerGeneratedName name + + if String.Equals(SynthesizedNameMapKey rawBasicName, mapKey, StringComparison.Ordinal) then + Some rawBasicName + else + None) + |> Array.distinct + + match rawBasicNames with + | [| rawBasicName |] -> rawBasicName + | _ -> mapKey + + Array.init (maxOrdinal + 1) (fun slot -> + match Map.tryFind slot namesByOrdinal with + | Some name -> name + | None -> makeHotReloadName replayFillBasicName slot) + else + sorted |> Array.map (fun (_, name, _) -> name) + else + let parsed = + names + |> Array.mapi (fun index name -> index, name, tryGetStableOrdinal mapKey name) + + if parsed |> Array.forall (fun (_, _, ordinalOpt) -> ordinalOpt.IsSome) then + let sorted = + parsed + |> Array.sortBy (fun (index, _, ordinalOpt) -> struct (ordinalOpt.Value, index)) + + let ordinalsAreDistinct = + let ordinals = sorted |> Array.map (fun (_, _, ordinalOpt) -> ordinalOpt.Value) + (Array.distinct ordinals).Length = ordinals.Length + + if ordinalsAreDistinct then + sorted |> Array.map (fun (_, name, _) -> name) + else + names + else + names + + let nameMapKeyFromSnapshotName (name: string) = + GetBasicNameOfPossibleCompilerGeneratedName name |> SynthesizedNameMapKey + + /// Validates that a generated name belongs to the normalized map key. + let validateName mapKey (name: string) index = + // Snapshots can contain legacy/basic synthesized names, for example + // "@_instance", alongside hot-reload-managed names. Accept both forms so + // existing sessions restore. + let actualKey = nameMapKeyFromSnapshotName name + + if not (String.Equals(actualKey, mapKey, StringComparison.Ordinal)) then + invalidArg "snapshot" $"Name '{name}' at index {index} belongs to normalized key '{actualKey}', not snapshot key '{mapKey}'" + + let loadSnapshotCore canonicalize (snapshot: seq) = + lock syncLock (fun () -> + buckets.Clear() + ordinals.Clear() + usesRecordedSnapshot <- not canonicalize + + let normalizedBuckets = + Dictionary>(StringComparer.Ordinal) + + for struct (basicName, names) in snapshot do + let mapKey = SynthesizedNameMapKey basicName + + if canonicalize then + // Validate each name matches the normalized key. Loading normalizes + // old raw-key snapshots, so on-disk baselines captured before this + // change replay through the same line-stable buckets. + names |> Array.iteri (fun i name -> validateName mapKey name i) + else + // Recorded snapshots are allocation-key to final-emitted-name slots. + // Occurrence-keyed closure overrides can intentionally move a final + // name into a bucket whose allocation key differs from the name's + // derived key, so only null validation applies here. + names + |> Array.iteri (fun i name -> + if isNull (box name) then + invalidArg "snapshot" $"Name at index {i} in snapshot key '{mapKey}' is null") + + let namesToLoad = + if canonicalize then + canonicalizeSnapshotNames mapKey names + else + // Recorded snapshots are already in allocation order. Keep them + // identity-preserving after validation. Old reconstructed + // snapshots continue through canonicalization. + Array.copy names + + let bucket = + match normalizedBuckets.TryGetValue mapKey with + | true, existing -> existing + | _ -> + let created = ResizeArray() + normalizedBuckets[mapKey] <- created + created + + for name in namesToLoad do + if canonicalize then + if not (bucket.Contains name) then + bucket.Add name + else + bucket.Add name + + for KeyValue(mapKey, bucket) in normalizedBuckets do + buckets[mapKey] <- createBucket (bucket.ToArray()) + ordinals[mapKey] <- 0) + + member _.GetOrAddName(basicName: string) = + lock syncLock (fun () -> + let mapKey = SynthesizedNameMapKey basicName + let bucket = getOrAddBucket mapKey + + // Keep ordinal reservation and bucket mutation in one critical section so + // concurrent callers cannot observe or produce out-of-order allocations. + // The ordinal is intentionally the encounter order within the normalized + // bucket. If same-bucket closures are reordered, the downstream + // positional-pairing shape guard owns that concern. This allocator only + // replays generation-0 names for matching allocation slots. + let index = + match ordinals.TryGetValue mapKey with + | true, current -> + ordinals[mapKey] <- current + 1 + current + | _ -> + ordinals[mapKey] <- 1 + 0 + + if index < bucket.Count then + bucket[index] + else + let name = computeName basicName index + bucket.Add name + name) + + /// Resets allocation state so subsequent edits reuse the original name ordering. + member _.BeginSession() = + lock syncLock (fun () -> + for KeyValue(key, _) in buckets do + ordinals[key] <- 0) + + /// Captures the current stable names grouped by compiler-generated base name. + member _.Snapshot: seq = + lock syncLock (fun () -> + buckets + |> Seq.map (fun (KeyValue(key, bucket)) -> struct (key, bucket.ToArray())) + |> Seq.sortWith (fun struct (left, _) struct (right, _) -> StringComparer.Ordinal.Compare(left, right)) + |> Seq.toArray + :> seq) + + member _.UsesRecordedSnapshot = lock syncLock (fun () -> usesRecordedSnapshot) + + /// Loads a previously captured snapshot, replacing any existing allocation state. + member _.LoadSnapshot(snapshot: seq) = loadSnapshotCore true snapshot + + /// + /// Loads a snapshot that was recorded from this allocator's own allocation slots. + /// The bucket arrays are ground truth, so this intentionally skips IL-order + /// reconstruction canonicalization and key-derived name validation. + /// + member _.LoadRecordedSnapshot(snapshot: seq) = loadSnapshotCore false snapshot + + interface ICompilerGeneratedNameMap with + member this.BeginSession() = this.BeginSession() + member this.GetOrAddName(basicName) = this.GetOrAddName(basicName) + member this.Snapshot = this.Snapshot + member this.LoadSnapshot(snapshot) = this.LoadSnapshot(snapshot) + +/// Retrieves a stable compiler-generated name or falls back to the provided generator. +let nextName (mapOpt: ICompilerGeneratedNameMap option) basicName generate = + match mapOpt with + | Some map -> map.GetOrAddName basicName + | None -> generate () diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/CompilerGeneratedNameDeterminism.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/CompilerGeneratedNameDeterminism.fs new file mode 100644 index 00000000000..ed66a783e46 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/CompilerGeneratedNameDeterminism.fs @@ -0,0 +1,136 @@ +namespace EmittedIL + +open System +open System.IO +open System.Reflection +open System.Reflection.Metadata +open System.Reflection.PortableExecutable +open Xunit + +open FSharp.Test.Compiler + +module CompilerGeneratedNameDeterminismTests = + + let private source = + """ +module GeneratedNameDeterminismSample + +open System.Threading.Tasks + +let makeAdder x = + let inner y = x + y + inner + +let asyncValue () = + async { + let! value = async { return 1 } + return value + 1 + } + +let taskValue () = + task { + let! value = Task.FromResult 1 + return value + 1 + } + +type Builder() = + member _.Bind(x, f) = f x + member _.Return(x) = x + +let builder = Builder() + +let computed value = + builder { + let! x = value + return x + 1 + } +""" + + let private getOutputPath = function + | CompilationResult.Success success -> + match success.OutputPath with + | Some path -> path + | None -> failwith "Compilation did not produce an output path." + | CompilationResult.Failure failure -> + failwithf "Compilation was expected to succeed, but failed with: %A" failure.Diagnostics + + let private compileLibrary outputDirectory = + FSharp source + |> withOutputDirectory (Some(DirectoryInfo outputDirectory)) + |> withOptions [ "--debug:portable"; "--deterministic"; "--optimize-" ] + |> asLibrary + |> compile + |> shouldSucceed + |> getOutputPath + + let private typeName (reader: MetadataReader) (handle: TypeDefinitionHandle) = + let rec buildName (handle: TypeDefinitionHandle) = + let typeDef = reader.GetTypeDefinition handle + let name = reader.GetString typeDef.Name + + let visibility = typeDef.Attributes &&& TypeAttributes.VisibilityMask + + let isNested = + match visibility with + | TypeAttributes.NestedPublic + | TypeAttributes.NestedPrivate + | TypeAttributes.NestedFamily + | TypeAttributes.NestedAssembly + | TypeAttributes.NestedFamORAssem + | TypeAttributes.NestedFamANDAssem -> true + | _ -> false + + if isNested then + let declaringTypeHandle = typeDef.GetDeclaringType() + $"{buildName declaringTypeHandle}+{name}" + else + let namespaceName = + if typeDef.Namespace.IsNil then + "" + else + reader.GetString typeDef.Namespace + + if String.IsNullOrEmpty namespaceName then + name + else + $"{namespaceName}.{name}" + + buildName handle + + let private emittedGeneratedNames assemblyPath = + use stream = File.OpenRead assemblyPath + use peReader = new PEReader(stream) + let reader = peReader.GetMetadataReader() + + let names = + [ for typeHandle in reader.TypeDefinitions do + yield typeName reader typeHandle + + let typeDef = reader.GetTypeDefinition typeHandle + + for methodHandle in typeDef.GetMethods() do + let methodDef = reader.GetMethodDefinition methodHandle + yield reader.GetString methodDef.Name ] + + names + |> List.filter (fun name -> name.IndexOf('@') >= 0) + |> List.sort + + [] + let ``normal compilation emits identical generated names across two compiles`` () = + let tempRoot = + Path.Combine(Path.GetTempPath(), "fsharp-generated-name-determinism-" + Guid.NewGuid().ToString("N")) + + try + let firstOutput = Path.Combine(tempRoot, "first") + let secondOutput = Path.Combine(tempRoot, "second") + + let firstNames = compileLibrary firstOutput |> emittedGeneratedNames + let secondNames = compileLibrary secondOutput |> emittedGeneratedNames + + Assert.True(not firstNames.IsEmpty, "Expected at least one compiler-generated name in emitted metadata.") + Assert.DoesNotContain(firstNames, fun name -> name.Contains("@hotreload")) + Assert.Equal(firstNames, secondNames) + finally + if Directory.Exists tempRoot then + Directory.Delete(tempRoot, true) diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj index b4d96794e14..f4fb24145dd 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj +++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj @@ -256,6 +256,7 @@ + diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj index 6f4a9c75063..5b589936a98 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj @@ -29,6 +29,8 @@ + + diff --git a/tests/FSharp.Compiler.Service.Tests/HotReload/GeneratedNamesTests.fs b/tests/FSharp.Compiler.Service.Tests/HotReload/GeneratedNamesTests.fs new file mode 100644 index 00000000000..736f2b9dbeb --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/HotReload/GeneratedNamesTests.fs @@ -0,0 +1,185 @@ +namespace FSharp.Compiler.Service.Tests.HotReload + +open Xunit + +open FSharp.Compiler.CompilerGeneratedNameMapState +open FSharp.Compiler.CompilerGlobalState +open FSharp.Compiler.GeneratedNames +open FSharp.Compiler.SynthesizedTypeMaps +open FSharp.Compiler.Text + +module GeneratedNamesTests = + + let zeroRange = Range.range0 + + let private expectPositionalName input expectedName expectedOrdinal = + match tryNormalizeSynthesizedTypeNameForPositionalPairing input with + | Some actual -> + Assert.Equal(expectedName, actual.NormalizedBasicName) + Assert.Equal(expectedOrdinal, actual.Ordinal) + | None -> failwithf "Expected '%s' to normalize for positional pairing." input + + let private expectNoPositionalName input = + Assert.True( + Option.isNone (tryNormalizeSynthesizedTypeNameForPositionalPairing input), + sprintf "Expected '%s' not to normalize for positional pairing." input + ) + + [] + let ``NiceNameGenerator without map uses legacy suffix`` () = + let compilerState = CompilerGlobalState() + clearCompilerGeneratedNameMap (compilerState :> obj) + let generator = compilerState.NiceNameGenerator + + let first = generator.FreshCompilerGeneratedName("lambda", zeroRange) + let second = generator.FreshCompilerGeneratedName("lambda", zeroRange) + + Assert.Equal("lambda@1", first) + Assert.Equal("lambda@1-1", second) + + [] + let ``NiceNameGenerator with synthesized map replays snapshot`` () = + let compilerState = CompilerGlobalState() + let map = FSharpSynthesizedTypeMaps() + map.BeginSession() + setCompilerGeneratedNameMap (compilerState :> obj) (map :> ICompilerGeneratedNameMap) + + let generator = compilerState.NiceNameGenerator + + let first = generator.FreshCompilerGeneratedName("closure", zeroRange) + let second = generator.FreshCompilerGeneratedName("closure", zeroRange) + + let snapshot = + map.Snapshot + |> Seq.find (fun struct (key, _) -> key = "closure") + |> fun struct (_, names) -> names + + map.BeginSession() + + let replayFirst = generator.FreshCompilerGeneratedName("closure", zeroRange) + let replaySecond = generator.FreshCompilerGeneratedName("closure", zeroRange) + + Assert.Equal("closure@hotreload", first) + Assert.Equal("closure@hotreload-1", second) + Assert.Equal(snapshot, [| first; second |]) + Assert.Equal(snapshot, [| replayFirst; replaySecond |]) + + [] + let ``NiceNameGenerator counters not incremented during replay mode`` () = + let compilerState = CompilerGlobalState() + let map = FSharpSynthesizedTypeMaps() + map.BeginSession() + setCompilerGeneratedNameMap (compilerState :> obj) (map :> ICompilerGeneratedNameMap) + + let generator = compilerState.NiceNameGenerator + + generator.FreshCompilerGeneratedName("test", zeroRange) |> ignore + generator.FreshCompilerGeneratedName("test", zeroRange) |> ignore + + clearCompilerGeneratedNameMap (compilerState :> obj) + + let first = generator.FreshCompilerGeneratedName("test", zeroRange) + let second = generator.FreshCompilerGeneratedName("test", zeroRange) + + Assert.Equal("test@1", first) + Assert.Equal("test@1-1", second) + + [] + let ``NiceNameGenerator without map keys ordinals by file index`` () = + let compilerState = CompilerGlobalState() + clearCompilerGeneratedNameMap (compilerState :> obj) + let generator = compilerState.NiceNameGenerator + let start = Position.mkPos 42 0 + let fileOneRange = Range.mkRange "/tmp/generated-names-file-one.fs" start start + let fileTwoRange = Range.mkRange "/tmp/generated-names-file-two.fs" start start + + let fileOneFirst = generator.FreshCompilerGeneratedName("closure", fileOneRange) + let fileOneSecond = generator.FreshCompilerGeneratedName("closure", fileOneRange) + let fileTwoFirst = generator.FreshCompilerGeneratedName("closure", fileTwoRange) + let fileOneThird = generator.FreshCompilerGeneratedName("closure", fileOneRange) + + Assert.Equal("closure@42", fileOneFirst) + Assert.Equal("closure@42-1", fileOneSecond) + Assert.Equal("closure@42", fileTwoFirst) + Assert.Equal("closure@42-2", fileOneThird) + + [] + let ``PerFileNamingScope uses map before per-file buckets`` () = + let compilerState = CompilerGlobalState() + let map = FSharpSynthesizedTypeMaps() + map.BeginSession() + setCompilerGeneratedNameMap (compilerState :> obj) (map :> ICompilerGeneratedNameMap) + + let start = Position.mkPos 42 0 + let fileRange = Range.mkRange "/tmp/generated-names-file-scope.fs" start start + let scope = compilerState.NewFileScope fileRange + + let first = scope.Fresh("closure", fileRange) + let second = scope.Fresh("closure", fileRange) + + clearCompilerGeneratedNameMap (compilerState :> obj) + let fallback = scope.Fresh("closure", fileRange) + + Assert.Equal("closure@hotreload", first) + Assert.Equal("closure@hotreload-1", second) + Assert.Equal("closure@42", fallback) + + [] + let ``Per-file naming scope remains one-based and file-index scoped`` () = + let compilerState = CompilerGlobalState() + clearCompilerGeneratedNameMap (compilerState :> obj) + let start = Position.mkPos 7 0 + let fileOneRange = Range.mkRange "/tmp/per-file-scope-one.fs" start start + let fileTwoRange = Range.mkRange "/tmp/per-file-scope-two.fs" start start + + let fileOneScope = compilerState.NewFileScope(fileOneRange) + let fileTwoScope = compilerState.NewFileScope(fileTwoRange) + + let first = fileOneScope.Fresh("closure", fileOneRange) + let second = fileOneScope.Fresh("closure", fileTwoRange) + let third = fileTwoScope.Fresh("closure", fileOneRange) + + Assert.Equal("closure@7", first) + Assert.Equal("closure@7-1", second) + Assert.Equal("closure@7", third) + + [] + let ``positional synthesized name normalization recognizes pipe and ordinal labels`` () = + expectPositionalName "Pipe #1 input at line 28@28" "Pipe #1 input" [ 28; 0 ] + expectPositionalName "Pipe #1 stage #2 at line 28@28" "Pipe #1 stage #2" [ 28; 0 ] + expectPositionalName "Pipe #1 stage #2 at line 28" "Pipe #1 stage #2" [ 28; 0 ] + expectPositionalName "Pipe #1 stage #2 at line 28@hotreload-1" "Pipe #1 stage #2" [ 28; 1 ] + expectPositionalName "endpoints@hotreload" "endpoints" [ 0 ] + expectPositionalName "endpoints@hotreload-2" "endpoints" [ 2 ] + expectPositionalName "endpoints@42-1" "endpoints" [ 42; 1 ] + + [] + let ``positional synthesized name normalization rejects unrelated generated-looking names`` () = + expectNoPositionalName "" + expectNoPositionalName "not generated" + expectNoPositionalName "Pipe #1 stage #2 line 28@28" + expectNoPositionalName "Pipe #1 stage #2 at line 28@29" + expectNoPositionalName "Pipe #1 input at line 2147483648" + expectNoPositionalName "endpoints@hotreload#g0_o0" + + [] + let ``generation-suffixed name parsing recognizes generation and occurrence`` () = + Assert.True(IsHotReloadGenerationSuffixedName "f@hotreload#g2_o3_4") + Assert.Equal(Some 2, TryGetHotReloadNameGeneration "f@hotreload#g2_o3_4") + + match TryNormalizeHotReloadGenerationName "Pipe #1 stage #2 at line 28@hotreload#g0_o1_2" with + | Some actual -> + Assert.Equal("Pipe #1 stage #2", actual.NormalizedBasicName) + Assert.Equal(0, actual.Generation) + Assert.Equal([ 1; 2 ], actual.OccurrenceOrdinal) + | None -> failwith "Expected generation-suffixed name to normalize." + + [] + let ``generation-suffixed name parsing rejects malformed names`` () = + Assert.Equal(None, TryGetHotReloadNameGeneration "") + Assert.Equal(None, TryGetHotReloadNameGeneration "f@hotreload#g_o3") + Assert.False(IsHotReloadGenerationSuffixedName "f@hotreload#g2_oBAD") + Assert.Equal(None, TryGetHotReloadNameGeneration "f@hotreload#g2_oBAD") + Assert.Equal(None, TryGetHotReloadNameGeneration "@hotreload#g2_o0") + Assert.Equal(None, TryNormalizeHotReloadGenerationName "f@hotreload#g1_o") + Assert.Equal(None, TryNormalizeHotReloadGenerationName "f@bad@hotreload#g1_o0") diff --git a/tests/FSharp.Compiler.Service.Tests/HotReload/NameMapTests.fs b/tests/FSharp.Compiler.Service.Tests/HotReload/NameMapTests.fs new file mode 100644 index 00000000000..652e738665e --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/HotReload/NameMapTests.fs @@ -0,0 +1,216 @@ +namespace FSharp.Compiler.Service.Tests.HotReload + +open System +open Xunit + +open FSharp.Compiler.SynthesizedTypeMaps + +module NameMapTests = + + [] + let ``name map replays recorded sequence`` () = + let map = FSharpSynthesizedTypeMaps() + map.BeginSession() + + let first = map.GetOrAddName "lambda" + let second = map.GetOrAddName "lambda" + + map.BeginSession() + + let replayFirst = map.GetOrAddName "lambda" + let replaySecond = map.GetOrAddName "lambda" + + Assert.Equal(first, replayFirst) + Assert.Equal(second, replaySecond) + + let private hasLineNumberSuffix (name: string) = + let atIndex = name.IndexOf('@') + atIndex >= 0 && atIndex + 1 < name.Length && Char.IsDigit name[atIndex + 1] + + [] + let ``generated names avoid source line suffixes`` () = + let map = FSharpSynthesizedTypeMaps() + map.BeginSession() + + let name = map.GetOrAddName "closure" + let another = map.GetOrAddName "closure" + + Assert.False(hasLineNumberSuffix name, $"Expected '{name}' to avoid line-number suffixes.") + Assert.False(hasLineNumberSuffix another, $"Expected '{another}' to avoid line-number suffixes.") + + [] + let ``snapshot reload restores recorded names`` () = + let map = FSharpSynthesizedTypeMaps() + map.BeginSession() + + let first = map.GetOrAddName "anon" + let second = map.GetOrAddName "anon" + + let snapshot = map.Snapshot |> Seq.toArray + + let replay = FSharpSynthesizedTypeMaps() + replay.LoadSnapshot snapshot + replay.BeginSession() + + let replayFirst = replay.GetOrAddName "anon" + let replaySecond = replay.GetOrAddName "anon" + + Assert.Equal(first, replayFirst) + Assert.Equal(second, replaySecond) + + [] + let ``snapshot orders buckets by ordinal key`` () = + let map = FSharpSynthesizedTypeMaps() + map.BeginSession() + + for key in [ "zeta"; "alpha"; "mu"; "beta"; "omega"; "aardvark"; "zzzz" ] do + map.GetOrAddName key |> ignore + + let actualKeys = map.Snapshot |> Seq.map (fun struct (key, _) -> key) |> Seq.toArray + let expectedKeys = + actualKeys |> Array.sortWith (fun left right -> StringComparer.Ordinal.Compare(left, right)) + + Assert.Equal(expectedKeys, actualKeys) + + [] + let ``line-normalized replay preserves generation-zero pipe name`` () = + let map = FSharpSynthesizedTypeMaps() + map.BeginSession() + + let baselineName = map.GetOrAddName "Pipe #1 stage #2 at line 28" + + map.BeginSession() + + let replayedName = map.GetOrAddName "Pipe #1 stage #2 at line 30" + + Assert.Equal("Pipe #1 stage #2 at line 28@hotreload", baselineName) + Assert.Equal(baselineName, replayedName) + Assert.Contains("line 28", replayedName) + Assert.DoesNotContain("line 30", replayedName) + + [] + let ``LoadSnapshot normalizes old raw pipe keys`` () = + let map = FSharpSynthesizedTypeMaps() + + let oldSnapshot = + [| struct ("Pipe #1 stage #2 at line 28", [| "Pipe #1 stage #2 at line 28@hotreload" |]) |] + + map.LoadSnapshot oldSnapshot + map.BeginSession() + + let replayedName = map.GetOrAddName "Pipe #1 stage #2 at line 30" + let snapshot = map.Snapshot |> Seq.toArray + let struct (snapshotKey, snapshotNames) = Assert.Single snapshot + + Assert.Equal("Pipe #1 stage #2 at line 28@hotreload", replayedName) + Assert.Equal("Pipe #1 stage #2", snapshotKey) + Assert.Equal([| "Pipe #1 stage #2 at line 28@hotreload" |], snapshotNames) + + [] + let ``LoadSnapshot fills normalized pipe replay holes with birth-line names`` () = + let map = FSharpSynthesizedTypeMaps() + + let gappedSnapshot = + [| struct ( + "Pipe #1 stage #2", + [| "Pipe #1 stage #2 at line 28@hotreload-2"; "Pipe #1 stage #2 at line 28@hotreload" |] + ) |] + + map.LoadSnapshot gappedSnapshot + map.BeginSession() + + let replayed = [| for _ in 0 .. 2 -> map.GetOrAddName "Pipe #1 stage #2 at line 30" |] + + Assert.Equal( + [| "Pipe #1 stage #2 at line 28@hotreload" + "Pipe #1 stage #2 at line 28@hotreload-1" + "Pipe #1 stage #2 at line 28@hotreload-2" |], + replayed + ) + + [] + let ``LoadSnapshot canonicalizes hot reload ordinals for replay`` () = + let map = FSharpSynthesizedTypeMaps() + + let outOfOrderSnapshot = + [| struct ("closure", [| "closure@hotreload-10"; "closure@hotreload"; "closure@hotreload-2"; "closure@hotreload-1" |]) |] + + map.LoadSnapshot outOfOrderSnapshot + map.BeginSession() + + // Replay is ordinal-positioned. A gapped bucket keeps every surviving name + // at its exact allocation slot and re-computes the missing slots' names. + let replayed = [| for _ in 0 .. 10 -> map.GetOrAddName "closure" |] + + let expected = + [| "closure@hotreload" + yield! [| for i in 1 .. 10 -> $"closure@hotreload-{i}" |] |] + + Assert.Equal(expected, replayed) + Assert.Equal("closure@hotreload-10", replayed[10]) + + [] + let ``LoadSnapshot preserves occurrence-keyed generation-zero names`` () = + let map = FSharpSynthesizedTypeMaps() + + let snapshot = + [| struct ("f", [| "f@hotreload-2"; "f@hotreload#g0_o0"; "f@hotreload-1" |]) |] + + map.LoadSnapshot snapshot + map.BeginSession() + + let replayed = [| for _ in 0 .. 2 -> map.GetOrAddName "f" |] + Assert.Equal([| "f@hotreload#g0_o0"; "f@hotreload-1"; "f@hotreload-2" |], replayed) + + [] + let ``LoadSnapshot validates name prefix`` () = + let map = FSharpSynthesizedTypeMaps() + + let validSnapshot = + [| struct ("test", [| "test@hotreload"; "test@hotreload-1" |]) + struct ("Name", [| "Name@" |]) + struct ("Circle", [| "Circle@DebugTypeProxy" |]) |] + + map.LoadSnapshot validSnapshot + + [] + let ``LoadSnapshot accepts legacy basic names`` () = + let map = FSharpSynthesizedTypeMaps() + + let legacySnapshot = + [| struct ("@_instance", [| "@_instance" |]) + struct ("cached", [| "cached"; "cached@hotreload" |]) |] + + map.LoadSnapshot legacySnapshot + + [] + let ``LoadSnapshot rejects basicName mismatch`` () = + let map = FSharpSynthesizedTypeMaps() + + let mismatchedSnapshot = [| struct ("foo", [| "bar@hotreload" |]) |] + let ex = Assert.Throws(fun () -> map.LoadSnapshot mismatchedSnapshot) + Assert.Contains("snapshot key 'foo'", ex.Message) + Assert.Contains("bar@hotreload", ex.Message) + + [] + let ``LoadSnapshot rejects name without marker`` () = + let map = FSharpSynthesizedTypeMaps() + + let invalidSnapshot = [| struct ("test", [| "testhotreload" |]) |] + let ex = Assert.Throws(fun () -> map.LoadSnapshot invalidSnapshot) + Assert.Contains("snapshot key 'test'", ex.Message) + Assert.Contains("testhotreload", ex.Message) + + [] + let ``LoadRecordedSnapshot preserves allocation-key slots`` () = + let map = FSharpSynthesizedTypeMaps() + + let recordedSnapshot = + [| struct ("allocation", [| "final@hotreload#g0_o0"; "allocation@hotreload-1" |]) |] + + map.LoadRecordedSnapshot recordedSnapshot + map.BeginSession() + + Assert.True(map.UsesRecordedSnapshot) + Assert.Equal("final@hotreload#g0_o0", map.GetOrAddName "allocation") + Assert.Equal("allocation@hotreload-1", map.GetOrAddName "allocation") From 4a2749ee96dc6d7ccc08b42a87b74657f0906348 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Fri, 24 Jul 2026 15:51:40 +0200 Subject: [PATCH 15/33] Fix #19457: lift CE constructs from plain let RHS in computation expressions (#19868) --- .../.FSharp.Compiler.Service/11.0.100.md | 1 + .../CheckComputationExpressions.fs | 311 +++++----- src/Compiler/SyntaxTree/SyntaxTreeOps.fs | 22 + src/Compiler/SyntaxTree/SyntaxTreeOps.fsi | 3 + .../Language/ComputationExpressionTests.fs | 531 +++++++++++++++++- 5 files changed, 718 insertions(+), 150 deletions(-) diff --git a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md index bd4c804b4f2..8aa1498216d 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md +++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md @@ -1,5 +1,6 @@ ### Fixed +* Fix FS0750 "This construct may only be used within computation expressions" incorrectly raised for `let!`/`use!`/`do!` appearing in the right-hand side of a plain `let` binding inside a computation expression. The right-hand side is now desugared as a nested computation of the same builder whose result is bound with `let!`, keeping its bindings correctly scoped. ([Issue #19457](https://github.com/dotnet/fsharp/issues/19457), [PR #19868](https://github.com/dotnet/fsharp/pull/19868)) * Stop leaking a `System.Diagnostics.Metrics.MeterListener` per `Cache` in DEBUG builds. Each cache created a `CacheMetrics.CacheMetricsListener` (which starts a `MeterListener` registered in the process-global metrics registry) and never disposed it, so listeners accumulated for the lifetime of the process. Because every cache hit/miss/add published to all registered listeners, the per-operation cost grew linearly with the number of leaked listeners, so repeated checks (and Debug FCS test runs) slowed down over time. The per-cache `CacheMetricsListener` and the per-instance `cacheId` tag are removed; `DebugDisplay` and tests now read the existing name-aggregated stats populated by the single `ListenToAll` listener, so no per-cache listener is created and no per-operation cost is added. ([PR #19995](https://github.com/dotnet/fsharp/pull/19995)) * Fix state machine lowering dropping the side-effectful receiver of an unused unit-typed member access (e.g. inside `task { (effectful()).UnitProp }`). ([Issue #13099](https://github.com/dotnet/fsharp/issues/13099), [PR #19885](https://github.com/dotnet/fsharp/pull/19885)) * `--deterministic` Release builds now produce byte-identical `FSharp.Compiler.Service.dll` under `--parallelcompilation+` and `--parallelcompilation-`, so it is restored to the determinism gate (now also checked sequential-vs-parallel). Code generation runs the same deferred per-file drain in both modes, with type/member/field emit-order keys and generated names derived from the file being emitted rather than thread-scheduling order. ([Issue #19928](https://github.com/dotnet/fsharp/issues/19928), [PR #19929](https://github.com/dotnet/fsharp/pull/19929)) diff --git a/src/Compiler/Checking/Expressions/CheckComputationExpressions.fs b/src/Compiler/Checking/Expressions/CheckComputationExpressions.fs index 8c2b84011f3..040b61f9a89 100644 --- a/src/Compiler/Checking/Expressions/CheckComputationExpressions.fs +++ b/src/Compiler/Checking/Expressions/CheckComputationExpressions.fs @@ -1013,6 +1013,112 @@ let requireBuilderMethod methodName ceenv m1 m2 = if not (hasBuilderMethod ceenv m1 methodName) then error (Error(FSComp.SR.tcRequireBuilderMethod methodName, m2)) +/// One `let`/`use`/`let!`/`use!`/`do!` binding step, exposing whether it is a "bang" construct, its +/// continuation body, and how to rebuild the step around a rewritten body. +let (|CeBindingStep|_|) expr = + match expr with + | SynExpr.LetOrUse({ IsRecursive = false } as data) -> + Some(data.IsBang, data.Body, (fun body -> SynExpr.LetOrUse { data with Body = body })) + | SynExpr.Sequential(sp, isTrueSeq, (SynExpr.DoBang _ as doBang), body, mSeq, trivia) -> + Some(true, body, (fun body -> SynExpr.Sequential(sp, isTrueSeq, doBang, body, mSeq, trivia))) + | _ -> None + +/// A function or constructor-pattern binding (`let f x = ...`, `let (Some x) = ...`) is not a simple +/// value binding. At this stage both take the same shape (`SynPat.LongIdent` with argument patterns or +/// type parameters), and neither should be treated as the pattern of a `let!`. +let private isSimpleValuePat pat = + match pat with + | SynPat.LongIdent(argPats = SynArgPats.Pats(_ :: _)) + | SynPat.LongIdent(argPats = SynArgPats.NamePatPairs(pats = _ :: _)) + | SynPat.LongIdent(typarDecls = Some _) -> false + | _ -> true + +/// #19457: a plain `let p = rhs` inside a computation expression, where `rhs` contains a bang construct +/// (`let!`/`use!`/`do!`), is rebound as `let! p = builder { rhs }`. Running the rhs as a nested +/// computation of the same builder keeps its bindings scoped there rather than leaking past `p`. +/// Returns None (leaving the ordinary `let` path) unless the rhs is a simple value binding whose spine +/// reaches a bang. +let tryRebindCeLetWithBangRhs (ceenv: ComputationExpressionContext<'a>) isRec m trivia binds innerComp : SynExpr option = + // A leading paren or return-type annotation belongs to the `let` binding, not to the nested + // computation: parens are not valid computation-expression body syntax, and the type is carried onto + // the `let!` pattern by mkTypedHeadPat. Strip them to get the computation the user actually wrote. + let rec coreOf expr = + match expr with + | SynExpr.Paren(expr = e) + | SynExpr.Typed(expr = e) -> coreOf e + | e -> e + + // Does the binding spine reach a bang? This must mirror where `returnify` descends, so the gate and + // the transformation agree: plain lets, a leading statement, paren/type annotations, and the branches + // of an `if`/`match`. `try` (and `match!`) stay out — `returnify` treats a `try` as a value leaf, so a + // bang only inside a `try` is deliberately left reporting FS0750. + let rec spineHasBang expr = + match expr with + | CeBindingStep(isBang, body, _) -> isBang || spineHasBang body + | SynExpr.Sequential(expr2 = e2) -> spineHasBang e2 + | SynExpr.Paren(expr = e) + | SynExpr.Typed(expr = e) -> spineHasBang e + | SynExpr.IfThenElse(thenExpr = th; elseExpr = el) -> spineHasBang th || Option.exists spineHasBang el + | SynExpr.Match(clauses = cs) -> cs |> List.exists (fun (SynMatchClause(resultExpr = r)) -> spineHasBang r) + | _ -> false + + // Make the nested computation produce its final value: wrap plain value leaves in `return`, leaving + // constructs that already produce in the computation untouched, and pushing through lets, sequencing, + // `if` and `match` to reach the leaves. Loops (`while`/`for`) and the bang constructs are left as-is: + // they produce unit (or their own value) directly. A `try`, by contrast, is an ordinary value + // expression here, so it takes the leaf path and is returned as a whole (`return (try ...)`). + let rec returnify expr = + match expr with + | CeBindingStep(_, body, rebuild) -> rebuild (returnify body) + | SynExpr.Paren(expr = e) -> returnify e + | SynExpr.Sequential(sp, isTrueSeq, e1, e2, ms, tr) -> SynExpr.Sequential(sp, isTrueSeq, e1, returnify e2, ms, tr) + | SynExpr.IfThenElse(g, th, el, sp, r, mi, tr) -> SynExpr.IfThenElse(g, returnify th, Option.map returnify el, sp, r, mi, tr) + | SynExpr.Match(sp, e, clauses, mm, tr) -> + let clauses = + clauses + |> List.map (fun (SynMatchClause(p, w, res, mc, dp, ctr)) -> SynMatchClause(p, w, returnify res, mc, dp, ctr)) + + SynExpr.Match(sp, e, clauses, mm, tr) + | SynExpr.YieldOrReturn _ + | SynExpr.YieldOrReturnFrom _ + | SynExpr.DoBang _ + | SynExpr.MatchBang _ + | SynExpr.WhileBang _ + | SynExpr.While _ + | SynExpr.For _ + | SynExpr.ForEach _ -> expr + | leaf -> SynExpr.YieldOrReturn((false, true), leaf, leaf.Range, SynExprYieldOrReturnTrivia.Zero) + + // Only a single, non-inline, non-mutable, non-recursive plain 'let' binding to a simple value pattern + // whose spine reaches a bang is rewritten. A 'use', a bang buried inside a 'try', and a 'match!' are + // deliberately out of scope and keep reporting FS0750. `spineHasBang` and `returnify` walk the same + // spine (lets, sequencing, and if/match branches) so the gate and the rewrite agree. + match binds with + | [ SynBinding(headPat = pat; isInline = false; isMutable = false; expr = rhs; debugPoint = spBind) as binding ] when + not (ceenv.isQuery || isRec) && isSimpleValuePat pat && spineHasBang rhs + -> + let core = coreOf rhs + let mCe = core.Range + let builder = mkSynIdGet mCe ceenv.builderValName + + let nestedCe = + SynExpr.App(ExprAtomicFlag.NonAtomic, false, builder, SynExpr.ComputationExpr(false, returnify core, mCe), mCe) + + let letBang = mkSynLetBangBinding mCe (mkTypedHeadPat binding) nestedCe spBind m + + Some( + SynExpr.LetOrUse + { + IsRecursive = false + IsFromSource = false + Bindings = [ letBang ] + Body = innerComp + Range = m + Trivia = trivia + } + ) + | _ -> None + /// /// Try translate the syntax sugar /// @@ -1454,24 +1560,7 @@ let rec TryTranslateComputationExpression let setCondExpr = SynExpr.Set(SynExpr.Ident idCond, SynExpr.Ident idFirst, mGuard) let binding = - SynBinding( - accessibility = None, - kind = SynBindingKind.Normal, - isInline = false, - isMutable = false, - attributes = [], - xmlDoc = PreXmlDoc.Empty, - valData = SynInfo.emptySynValData, - headPat = patFirst, - returnInfo = None, - expr = guardExpr, - range = guardExpr.Range, - debugPoint = DebugPointAtBinding.NoneAtSticky, - trivia = - { SynBindingTrivia.Zero with - LeadingKeyword = SynLeadingKeyword.LetBang mGuard - } - ) + mkSynLetBangBinding mGuard patFirst guardExpr DebugPointAtBinding.NoneAtSticky guardExpr.Range let bindCondExpr = SynExpr.LetOrUse @@ -1514,24 +1603,7 @@ let rec TryTranslateComputationExpression } let binding = - SynBinding( - accessibility = None, - kind = SynBindingKind.Normal, - isInline = false, - isMutable = false, - attributes = [], - xmlDoc = PreXmlDoc.Empty, - valData = SynInfo.emptySynValData, - headPat = patFirst, - returnInfo = None, - expr = guardExpr, - range = guardExpr.Range, - debugPoint = DebugPointAtBinding.NoneAtSticky, - trivia = - { SynBindingTrivia.Zero with - LeadingKeyword = SynLeadingKeyword.LetBang mGuard - } - ) + mkSynLetBangBinding mGuard patFirst guardExpr DebugPointAtBinding.NoneAtSticky guardExpr.Range SynExpr.LetOrUse { @@ -1733,24 +1805,7 @@ let rec TryTranslateComputationExpression | DebugPointAtSequential.SuppressNeither -> DebugPointAtBinding.Yes mKeyword let binding = - SynBinding( - accessibility = None, - kind = SynBindingKind.Normal, - isInline = false, - isMutable = false, - attributes = [], - xmlDoc = PreXmlDoc.Empty, - valData = SynInfo.emptySynValData, - headPat = SynPat.Const(SynConst.Unit, rhsExpr.Range), - returnInfo = None, - expr = rhsExpr, - range = rhsExpr.Range, - debugPoint = sp, - trivia = - { SynBindingTrivia.Zero with - LeadingKeyword = SynLeadingKeyword.LetBang mKeyword - } - ) + mkSynLetBangBinding mKeyword (SynPat.Const(SynConst.Unit, rhsExpr.Range)) rhsExpr sp rhsExpr.Range Some( TranslateComputationExpression @@ -1847,51 +1902,57 @@ let rec TryTranslateComputationExpression false, false) -> - // For 'query' check immediately - if ceenv.isQuery then - match (List.map (BindingNormalization.NormalizeBinding ValOrMemberBinding cenv ceenv.env) binds) with - | [ NormalizedBinding(_, SynBindingKind.Normal, false, false, _, _, _, _, _, _, _, _) ] when not isRec -> () - | normalizedBindings -> - let failAt m = - error (Error(FSComp.SR.tcNonSimpleLetBindingInQuery (), m)) + // #19457: a plain 'let' whose rhs begins with let!/use!/do! runs as a nested computation. + match tryRebindCeLetWithBangRhs ceenv isRec m trivia binds innerComp with + | Some rewritten -> + Some(TranslateComputationExpression ceenv CompExprTranslationPass.Initial q varSpace rewritten translatedCtxt) + | None -> - match normalizedBindings with - | NormalizedBinding(mBinding = mBinding) :: _ -> failAt mBinding - | _ -> failAt m + // For 'query' check immediately + if ceenv.isQuery then + match (List.map (BindingNormalization.NormalizeBinding ValOrMemberBinding cenv ceenv.env) binds) with + | [ NormalizedBinding(_, SynBindingKind.Normal, false, false, _, _, _, _, _, _, _, _) ] when not isRec -> () + | normalizedBindings -> + let failAt m = + error (Error(FSComp.SR.tcNonSimpleLetBindingInQuery (), m)) - // Add the variables to the query variable space, on demand - let varSpace = - addVarsToVarSpace varSpace (fun mQueryOp env -> - // Normalize the bindings before detecting the bound variables - match (List.map (BindingNormalization.NormalizeBinding ValOrMemberBinding cenv env) binds) with - | [ NormalizedBinding(kind = SynBindingKind.Normal; shouldInline = false; isMutable = false; pat = pat) ] -> - // successful case - use _holder = TemporarilySuspendReportingTypecheckResultsToSink cenv.tcSink + match normalizedBindings with + | NormalizedBinding(mBinding = mBinding) :: _ -> failAt mBinding + | _ -> failAt m - let _, _, vspecs, envinner, _ = - TcMatchPattern cenv (NewInferenceType cenv.g) env ceenv.tpenv pat None TcTrueMatchClause.No + // Add the variables to the query variable space, on demand + let varSpace = + addVarsToVarSpace varSpace (fun mQueryOp env -> + // Normalize the bindings before detecting the bound variables + match (List.map (BindingNormalization.NormalizeBinding ValOrMemberBinding cenv env) binds) with + | [ NormalizedBinding(kind = SynBindingKind.Normal; shouldInline = false; isMutable = false; pat = pat) ] -> + // successful case + use _holder = TemporarilySuspendReportingTypecheckResultsToSink cenv.tcSink - vspecs, envinner - | _ -> - // error case - error (Error(FSComp.SR.tcCustomOperationMayNotBeUsedInConjunctionWithNonSimpleLetBindings (), mQueryOp))) + let _, _, vspecs, envinner, _ = + TcMatchPattern cenv (NewInferenceType cenv.g) env ceenv.tpenv pat None TcTrueMatchClause.No - Some( - TranslateComputationExpression ceenv CompExprTranslationPass.Initial q varSpace innerComp (fun holeFill -> - translatedCtxt ( - SynExpr.LetOrUse - { - IsRecursive = isRec - //isUse = false, - IsFromSource = isFromSource - //isBang = false, - Bindings = binds - Body = holeFill - Range = m - Trivia = trivia - } - )) - ) + vspecs, envinner + | _ -> + // error case + error (Error(FSComp.SR.tcCustomOperationMayNotBeUsedInConjunctionWithNonSimpleLetBindings (), mQueryOp))) + + Some( + TranslateComputationExpression ceenv CompExprTranslationPass.Initial q varSpace innerComp (fun holeFill -> + translatedCtxt ( + SynExpr.LetOrUse + { + IsRecursive = isRec + //isUse = false, + IsFromSource = isFromSource + //isBang = false, + Bindings = binds + Body = holeFill + Range = m + Trivia = trivia + } + )) + ) // 'use x = expr in expr' | LetOrUse({ @@ -2528,24 +2589,12 @@ and ConsumeCustomOpClauses let rebind = if maintainsVarSpaceUsingBind then let binding = - SynBinding( - accessibility = None, - kind = SynBindingKind.Normal, - isInline = false, - isMutable = false, - attributes = [], - xmlDoc = PreXmlDoc.Empty, - valData = SynInfo.emptySynValData, - headPat = intoPat, - returnInfo = None, - expr = dataCompAfterOp, - range = dataCompAfterOp.Range, - debugPoint = DebugPointAtBinding.NoneAtLet, - trivia = - { SynBindingTrivia.Zero with - LeadingKeyword = SynLeadingKeyword.LetBang intoPat.Range - } - ) + mkSynLetBangBinding + intoPat.Range + intoPat + dataCompAfterOp + DebugPointAtBinding.NoneAtLet + dataCompAfterOp.Range SynExpr.LetOrUse { @@ -2589,24 +2638,7 @@ and ConsumeCustomOpClauses let rebind = if lastUsesBind then let binding = - SynBinding( - accessibility = None, - kind = SynBindingKind.Normal, - isInline = false, - isMutable = false, - attributes = [], - xmlDoc = PreXmlDoc.Empty, - valData = SynInfo.emptySynValData, - headPat = varSpacePat, - returnInfo = None, - expr = dataCompPrior, - range = dataCompPrior.Range, - debugPoint = DebugPointAtBinding.NoneAtLet, - trivia = - { SynBindingTrivia.Zero with - LeadingKeyword = SynLeadingKeyword.LetBang dataCompPrior.Range - } - ) + mkSynLetBangBinding dataCompPrior.Range varSpacePat dataCompPrior DebugPointAtBinding.NoneAtLet dataCompPrior.Range SynExpr.LetOrUse { @@ -2878,24 +2910,7 @@ and TranslateComputationExpression (ceenv: ComputationExpressionContext<'a>) fir let letBangBind = let binding = - SynBinding( - accessibility = None, - kind = SynBindingKind.Normal, - isInline = false, - isMutable = false, - attributes = [], - xmlDoc = PreXmlDoc.Empty, - valData = SynInfo.emptySynValData, - headPat = SynPat.Const(SynConst.Unit, mUnit), - returnInfo = None, - expr = rhsExpr, - range = rhsExpr.Range, - debugPoint = DebugPointAtBinding.NoneAtDo, - trivia = - { SynBindingTrivia.Zero with - LeadingKeyword = SynLeadingKeyword.LetBang m - } - ) + mkSynLetBangBinding m (SynPat.Const(SynConst.Unit, mUnit)) rhsExpr DebugPointAtBinding.NoneAtDo rhsExpr.Range SynExpr.LetOrUse { diff --git a/src/Compiler/SyntaxTree/SyntaxTreeOps.fs b/src/Compiler/SyntaxTree/SyntaxTreeOps.fs index fa30545d480..e6a995e3e19 100644 --- a/src/Compiler/SyntaxTree/SyntaxTreeOps.fs +++ b/src/Compiler/SyntaxTree/SyntaxTreeOps.fs @@ -823,6 +823,28 @@ let mkSynBinding let mBind = unionRangeWithXmlDoc xmlDoc mBind SynBinding(vis, SynBindingKind.Normal, isInline, isMutable, attrs, xmlDoc, info, headPat, retTyOpt, rhsExpr, mBind, spBind, trivia) +/// A compiler-generated `let!` binding, as produced while desugaring computation expressions: the +/// usual binding defaults with the leading keyword marked as `let!` at mKeyword. +let mkSynLetBangBinding mKeyword headPat rhs debugPoint mBind = + SynBinding( + accessibility = None, + kind = SynBindingKind.Normal, + isInline = false, + isMutable = false, + attributes = [], + xmlDoc = PreXmlDoc.Empty, + valData = SynInfo.emptySynValData, + headPat = headPat, + returnInfo = None, + expr = rhs, + range = mBind, + debugPoint = debugPoint, + trivia = + { SynBindingTrivia.Zero with + LeadingKeyword = SynLeadingKeyword.LetBang mKeyword + } + ) + let NonVirtualMemberFlags k : SynMemberFlags = { MemberKind = k diff --git a/src/Compiler/SyntaxTree/SyntaxTreeOps.fsi b/src/Compiler/SyntaxTree/SyntaxTreeOps.fsi index 246d661e663..c4915300652 100644 --- a/src/Compiler/SyntaxTree/SyntaxTreeOps.fsi +++ b/src/Compiler/SyntaxTree/SyntaxTreeOps.fsi @@ -308,6 +308,9 @@ val mkSynBinding: trivia: SynBindingTrivia -> SynBinding +val mkSynLetBangBinding: + mKeyword: range -> headPat: SynPat -> rhs: SynExpr -> debugPoint: DebugPointAtBinding -> mBind: range -> SynBinding + val NonVirtualMemberFlags: k: SynMemberKind -> SynMemberFlags val CtorMemberFlags: SynMemberFlags diff --git a/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs index f34388a5494..8ae3b0d4ef6 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs @@ -2400,9 +2400,11 @@ let foo() = |> typecheck |> shouldSucceed - // https://github.com/dotnet/fsharp/issues/19456 + // https://github.com/dotnet/fsharp/issues/19457: a let!/use!/do!-headed RHS of a plain 'let' + // inside a CE now runs as a nested computation. The following tests pin both compilation and the + // runtime values (scoping in particular). [] - let ``Issue 19456 - let bang nested in plain let binding inside task CE should raise FS0750`` () = + let ``Issue 19457 - let bang nested in plain let binding inside task CE should compile`` () = FSharp """ open System.Threading.Tasks @@ -2412,6 +2414,531 @@ let y() = let! b = Task.FromResult([| "hello" |]) b return a + } + """ + |> asLibrary + |> typecheck + |> shouldSucceed + + [] + let ``Issue 19457 - let bang nested in plain let returns awaited value not Task`` () = + FSharp """ +module Test +open System.Threading.Tasks +let y() = + task { + let a = + let! b = Task.FromResult(42) + b + return a + } +[] +let main _ = + let r = y().Result + if r <> 42 then failwithf "expected 42, got %d" r + 0 + """ + |> compileExeAndRun + |> shouldSucceed + + [] + let ``Issue 19457 - do bang nested in plain let inside task CE compiles and runs`` () = + FSharp """ +module Test +open System.Threading.Tasks +let mutable x = 0 +let test() = + task { + let a = + do! Task.Delay(0) + x <- 1 + 42 + return a + } +[] +let main _ = + let r = test().Result + if r <> 42 then failwithf "expected 42, got %d" r + if x <> 1 then failwithf "expected x=1, got %d" x + 0 + """ + |> compileExeAndRun + |> shouldSucceed + + [] + let ``Issue 19457 - multiple sequential let bang nested in plain let inside task CE`` () = + FSharp """ +module Test +open System.Threading.Tasks +let test() = + task { + let result = + let! a = Task.FromResult(1) + let! b = Task.FromResult(2) + a + b + return result + } +[] +let main _ = + let r = test().Result + if r <> 3 then failwithf "expected 3, got %d" r + 0 + """ + |> compileExeAndRun + |> shouldSucceed + + [] + let ``Issue 19457 - let bang nested in plain let inside async CE`` () = + FSharp """ +module Test +let test() = + async { + let a = + let! b = async { return 42 } + b + return a + } +[] +let main _ = + let r = Async.RunSynchronously(test()) + if r <> 42 then failwithf "expected 42, got %d" r + 0 + """ + |> compileExeAndRun + |> shouldSucceed + + [] + let ``Issue 19457 - plain let ahead of let bang in the RHS head chain`` () = + FSharp """ +module Test +open System.Threading.Tasks +let test() = + task { + let a = + let c = 10 + let! b = Task.FromResult(c) + b + return a + } +[] +let main _ = + let r = test().Result + if r <> 10 then failwithf "expected 10, got %d" r + 0 + """ + |> compileExeAndRun + |> shouldSucceed + + // Only the linear let!/use!/do! head chain is rewritten; a match! forming the whole RHS is not, + // so it keeps reporting FS0750. + [] + let ``Issue 19457 - match bang forming the whole plain let RHS is out of scope`` () = + FSharp """ +module Test +open System.Threading.Tasks +let test() = + task { + let result = + match! Task.FromResult(Some 42) with + | Some x -> x + | None -> 0 + return result + } + """ + |> asLibrary + |> typecheck + |> shouldFail + |> withErrorCode 750 + + // A let!-bound name in the RHS is scoped to the sub-computation, so it must not shadow the outer + // 'b' the continuation returns. + [] + let ``Issue 19457 - inner let bang does not shadow outer binding used in continuation`` () = + FSharp """ +module Test +open System.Threading.Tasks +let test() = + task { + let b = 999 + let a = + let! b = Task.FromResult 42 + b + return (a, b) + } +[] +let main _ = + let (a, b) = test().Result + if a <> 42 then failwithf "expected a=42, got %d" a + if b <> 999 then failwithf "expected b=999, got %d" b + 0 + """ + |> compileExeAndRun + |> shouldSucceed + + // A plain 'let' in the RHS head chain is likewise scoped to the sub-computation: the inner 'x' + // must not leak into the continuation, so the result is 13, not 14. + [] + let ``Issue 19457 - plain let inside RHS head chain does not leak into continuation`` () = + FSharp """ +module Test +let test() = + async { + let x = 1 + let p = + let x = 2 + let! y = async { return 10 } + x + y + return p + x + } +[] +let main _ = + let r = Async.RunSynchronously(test()) + if r <> 13 then failwithf "expected 13, got %d" r + 0 + """ + |> compileExeAndRun + |> shouldSucceed + + // 'use!' is disposed at the end of the sub-computation (its lexical scope): U inside, then D on + // disposal, then A in the outer CE. + [] + let ``Issue 19457 - use bang in plain let RHS is disposed within the sub-computation`` () = + FSharp """ +module Test +open System.Threading.Tasks +let log = System.Text.StringBuilder() +let mkDisp (tag: string) = + { new System.IDisposable with member _.Dispose() = log.Append tag |> ignore } +let test() = + task { + let a = + use! h = Task.FromResult(mkDisp "D") + log.Append "U" |> ignore + 99 + log.Append "A" |> ignore + return a + } +[] +let main _ = + let r = test().Result + if r <> 99 then failwithf "expected 99, got %d" r + if log.ToString() <> "UDA" then failwithf "expected UDA, got %s" (log.ToString()) + 0 + """ + |> compileExeAndRun + |> shouldSucceed + + // The sub-computation is returned exactly once: an explicit 'return' already in tail position must + // not be wrapped in a second 'return'. + [] + let ``Issue 19457 - explicit return in RHS tail is not double wrapped`` () = + FSharp """ +module Test +open System.Threading.Tasks +let test() = + task { + let a = + let! b = Task.FromResult 42 + return b + return a + } +[] +let main _ = + if test().Result <> 42 then failwith "expected 42" + 0 + """ + |> compileExeAndRun + |> shouldSucceed + + // The implicit 'return' is pushed into the branches of an 'if' tail, so branches that already + // 'return' are left untouched. + [] + let ``Issue 19457 - if with return branches in RHS tail compiles and runs`` () = + FSharp """ +module Test +open System.Threading.Tasks +let test() = + task { + let a = + let! b = Task.FromResult 42 + if b > 0 then return b else return 0 + return a + } +[] +let main _ = + if test().Result <> 42 then failwith "expected 42" + 0 + """ + |> compileExeAndRun + |> shouldSucceed + + // A return-type annotation on the plain 'let' is carried onto the 'let!' pattern. + [] + let ``Issue 19457 - return type annotation on the plain let is honoured`` () = + FSharp """ +module Test +open System.Threading.Tasks +let test() = + task { + let a : int = + let! b = Task.FromResult 42 + b + return a + } +[] +let main _ = + if test().Result <> 42 then failwith "expected 42" + 0 + """ + |> compileExeAndRun + |> shouldSucceed + + // A parenthesized RHS is unwrapped: parentheses are not valid computation-expression body syntax. + [] + let ``Issue 19457 - parenthesized RHS compiles and runs`` () = + FSharp """ +module Test +let test() = + async { + let a = ( + let! b = async { return 41 } + b + 1) + return a + } +[] +let main _ = + if Async.RunSynchronously(test()) <> 42 then failwith "expected 42" + 0 + """ + |> compileExeAndRun + |> shouldSucceed + + // A `try`/`with` (or `try`/`finally`) in tail position is an ordinary value expression, not a + // computation-expression control construct: it must be returned as a whole rather than having its + // body treated as CE code (which would silently yield unit). + [] + let ``Issue 19457 - try with in RHS tail returns the value`` () = + FSharp """ +module Test +open System.Threading.Tasks +let test() = + task { + let x = + let! a = Task.FromResult 41 + try a + 1 with _ -> 0 + return x + } +[] +let main _ = + if test().Result <> 42 then failwith "expected 42" + 0 + """ + |> compileExeAndRun + |> shouldSucceed + + // A leading statement before the `let!` is carried into the nested computation and runs exactly + // once, in order, before the bind. + [] + let ``Issue 19457 - leading statement before the bang is preserved`` () = + FSharp """ +module Test +open System.Threading.Tasks +let mutable count = 0 +let test() = + task { + let x = + count <- count + 1 + let! b = Task.FromResult 5 + b + 1 + return x + } +[] +let main _ = + if test().Result <> 6 then failwith "expected 6" + if count <> 1 then failwithf "expected the statement to run once, ran %d times" count + 0 + """ + |> compileExeAndRun + |> shouldSucceed + + // A function binding is not a simple value: it keeps the ordinary 'let' translation and reports + // FS0750 rather than being rebound as 'let! (f x) = ...'. + [] + let ``Issue 19457 - function binding with bang body is not lifted`` () = + FSharp """ +module Test +open System.Threading.Tasks +let test() = + task { + let f x = + let! b = Task.FromResult 42 + b + x + return f 1 + } + """ + |> asLibrary + |> typecheck + |> shouldFail + |> withErrorCode 750 + + // A mutable binding is likewise not lifted (its mutability would otherwise be silently dropped). + [] + let ``Issue 19457 - mutable binding with bang RHS is not lifted`` () = + FSharp """ +module Test +open System.Threading.Tasks +let test() = + task { + let mutable a = + let! b = Task.FromResult 42 + b + return a + } + """ + |> asLibrary + |> typecheck + |> shouldFail + |> withErrorCode 750 + + // Only a plain 'let' is rewritten; a 'use' whose RHS is a bang head-chain is left to the 'use' arm + // and keeps reporting FS0750. Pinning the boundary so it can't drift into a silent rewrite. + [] + let ``Issue 19457 - use binding with bang RHS is out of scope`` () = + FSharp """ +module Test +open System.Threading.Tasks +let test() = + task { + use a = + let! b = Task.FromResult 42 + b + return a + } + """ + |> asLibrary + |> typecheck + |> shouldFail + |> withErrorCode 750 + + // The rewrite only looks through the linear let/let!/use!/do! head chain, not into a 'try', so a bang + // buried inside a 'try' in the RHS is not lifted and keeps reporting FS0750. + [] + let ``Issue 19457 - bang inside a try in the RHS is out of scope`` () = + FSharp """ +module Test +open System.Threading.Tasks +let test() = + task { + let a = + try + let! b = Task.FromResult 42 + b + with _ -> 0 + return a + } + """ + |> asLibrary + |> typecheck + |> shouldFail + |> withErrorCode 750 + + // Running the RHS as a nested computation means the builder must supply the members that computation + // needs. A builder with 'Bind' but no 'Return' now reports the missing member (FS0708) rather than + // FS0750; the diagnostic still names exactly what to add. + [] + let ``Issue 19457 - minimal builder without Return reports the missing member`` () = + FSharp """ +module Test +type MinBuilder() = + member _.Bind(x, f) = f x +let mb = MinBuilder() +let test() = + mb { + let a = + let! b = 41 + b + return a + } + """ + |> asLibrary + |> typecheck + |> shouldFail + |> withErrorCode 708 + |> withDiagnosticMessageMatches "'Return'" + + // The gate that decides whether to rewrite descends into 'if'/'match' branches just like the rewrite + // does, so a bang reached only through a branch is handled the same whether or not an unrelated bang + // also leads the spine. + [] + let ``Issue 19457 - bang only inside an if branch compiles and runs`` () = + FSharp """ +module Test +open System.Threading.Tasks +let cond = true +let test() = + task { + let p = if cond then (let! y = Task.FromResult 10 in y) else 0 + return p + } +[] +let main _ = + if test().Result <> 10 then failwith "expected 10" + 0 + """ + |> compileExeAndRun + |> shouldSucceed + + [] + let ``Issue 19457 - bang only inside a match branch compiles and runs`` () = + FSharp """ +module Test +open System.Threading.Tasks +let test n = + task { + let p = match n with 0 -> (let! y = Task.FromResult 10 in y) | _ -> 0 + return p + } +[] +let main _ = + if test(0).Result <> 10 then failwith "expected 10" + 0 + """ + |> compileExeAndRun + |> shouldSucceed + + // A one-armed 'if' whose branch produces unit leans on the builder's implicit 'Zero' for the missing + // else, and still runs as a nested computation. + [] + let ``Issue 19457 - bang inside a one-armed if uses implicit Zero`` () = + FSharp """ +module Test +open System.Threading.Tasks +let cond = true +let test() = + task { + let p = if cond then (let! _ = Task.FromResult 10 in ()) + return p + } +[] +let main _ = + test().Result + 0 + """ + |> compileExeAndRun + |> shouldSucceed + + // The 'if'/'match' descent stops at a 'try', matching the rewrite, so a bang buried in a 'try' within a + // branch stays out of scope. + [] + let ``Issue 19457 - bang inside a try within an if branch is out of scope`` () = + FSharp """ +module Test +open System.Threading.Tasks +let cond = true +let test() = + task { + let p = if cond then (try (let! y = Task.FromResult 10 in y) with _ -> 0) else 0 + return p } """ |> asLibrary From 1d8dc39f50f42b6bc4eaee48292d8d727d11555e Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Fri, 24 Jul 2026 15:52:14 +0200 Subject: [PATCH 16/33] Fix attribute resolution in recursive module/namespace scopes (#19744) --- .../.FSharp.Compiler.Service/11.0.100.md | 1 + src/Compiler/Checking/CheckDeclarations.fs | 179 ++++--- .../AttributeResolutionInRecursiveScopes.fs | 11 +- .../FSharp.Compiler.ComponentTests.fsproj | 1 + .../AttributeResolutionInRecursiveScopes.fs | 440 ++++++++++++++++++ 5 files changed, 560 insertions(+), 72 deletions(-) create mode 100644 tests/FSharp.Compiler.ComponentTests/Language/AttributeResolutionInRecursiveScopes.fs diff --git a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md index 8aa1498216d..9b7e4989514 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md +++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md @@ -126,6 +126,7 @@ * Fix FSI pretty printing to distinguish anonymous records (`{| ... |}`) from nominal records (`{ ... }`). ([Issue #6116](https://github.com/dotnet/fsharp/issues/6116), [PR #19919](https://github.com/dotnet/fsharp/pull/19919)) * Fix dot-completion after indexed expressions (`a.[0].Data.`, `a[0].Data.`, `[1;2].Length.`) returning unrelated global completions instead of expression-typings members. ([Issue #4966](https://github.com/dotnet/fsharp/issues/4966), [PR #19934](https://github.com/dotnet/fsharp/pull/19934)) * Quotations of `match s with "" -> _` no longer leak the `s <> null && s.Length = 0` lowering; the empty-string optimization moved from pattern-match compilation to the optimizer so quoted expressions keep `op_Equality(s, "")`. ([Issue #19873](https://github.com/dotnet/fsharp/issues/19873)) +* Fix #5795: Allow attributes defined in a `module rec` / `namespace rec` scope to be used on union cases, record fields, and generic type parameters of types in the same recursive scope. ([Issue #5795](https://github.com/dotnet/fsharp/issues/5795), [PR #19744](https://github.com/dotnet/fsharp/pull/19744)) ### Added diff --git a/src/Compiler/Checking/CheckDeclarations.fs b/src/Compiler/Checking/CheckDeclarations.fs index b5055ce2dd9..dfa348ab19f 100644 --- a/src/Compiler/Checking/CheckDeclarations.fs +++ b/src/Compiler/Checking/CheckDeclarations.fs @@ -431,14 +431,17 @@ module TcRecdUnionAndEnumDeclarations = let vis = CombineReprAccess parent vis Construct.NewRecdField isStatic konst id nameGenerated tyR isMutable vol attrsForProperty attrsForField xmldoc vis false - let TcFieldDecl (cenv: cenv) env parent isIncrClass tpenv (isStatic, synAttrs, id: Ident, nameGenerated, ty, isMutable, xmldoc, vis) = + let TcFieldDecl (cenv: cenv) env parent isIncrClass tpenv addFixup (isStatic, synAttrs, id: Ident, nameGenerated, ty, isMutable, xmldoc, vis) = let g = cenv.g let m = id.idRange - let attrs, _ = TcAttributesWithPossibleTargets TcCanFail.ReportAllErrors cenv env AttributeTargets.FieldDecl synAttrs + // Attribute types from the same recursive group may not resolve yet; the fixup re-resolves later. + let attrs, hasUnresolvedAttrs = TcAttributesWithPossibleTargets TcCanFail.IgnoreAllErrors cenv env AttributeTargets.FieldDecl synAttrs - let attrsForProperty, attrsForField = attrs |> List.partition (fun (attrTargets, _) -> (attrTargets &&& AttributeTargets.Property) <> enum 0) - let attrsForProperty = (List.map snd attrsForProperty) - let attrsForField = (List.map snd attrsForField) + let splitAttrs (attrsWithTargets: (AttributeTargets * Attrib) list) = + let propAttribs, fieldAttribs = attrsWithTargets |> List.partition (fun (attrTargets, _) -> (attrTargets &&& AttributeTargets.Property) <> enum 0) + List.map snd propAttribs, List.map snd fieldAttribs + + let attrsForProperty, attrsForField = splitAttrs attrs let tyR, _ = TcTypeAndRecover cenv NoNewTypars CheckCxs ItemOccurrence.UseInType WarnOnIWSAM.Yes env tpenv ty let fieldFlags = computeValWellKnownFlags g attrsForField let zeroInit = hasFlag fieldFlags (WellKnownValAttributes.DefaultValueAttribute_True ||| WellKnownValAttributes.DefaultValueAttribute_False) @@ -457,22 +460,37 @@ module TcRecdUnionAndEnumDeclarations = if isStatic && (not zeroInit || not isMutable || not isPrivate) then errorR(Error(FSComp.SR.tcStaticValFieldsMustBeMutableAndPrivate(), m)) let konst = if zeroInit then Some Const.Zero else None let rfspec = MakeRecdFieldSpec g env parent (isStatic, konst, tyR, attrsForProperty, attrsForField, id, nameGenerated, isMutable, isVolatile, xmldoc, vis, m) - match parent with - | Parent tcref when useGenuineField tcref.Deref rfspec -> - // Recheck the attributes for errors if the definition only generates a field - TcAttributesWithPossibleTargets TcCanFail.ReportAllErrors cenv env AttributeTargets.FieldDeclRestricted synAttrs |> ignore - | _ -> () + let isGenuineField = match parent with Parent tcref -> useGenuineField tcref.Deref rfspec | _ -> false + + // Recheck the attributes for errors if the definition only generates a field. When the attribute type + // is from the same recursive group its constructor is not yet established, so defer to the fixup below. + let recheckGenuineField () = + if isGenuineField then + TcAttributesWithPossibleTargets TcCanFail.ReportAllErrors cenv env AttributeTargets.FieldDeclRestricted synAttrs |> ignore + if not hasUnresolvedAttrs then recheckGenuineField () + + let fixupAttrs () = + let finalAttrs = + if hasUnresolvedAttrs then + let reresolved = TcAttributesWithPossibleTargets TcCanFail.ReportAllErrors cenv env AttributeTargets.FieldDecl synAttrs |> fst + recheckGenuineField () + reresolved + else attrs + let propAttribs', fieldAttribs' = splitAttrs finalAttrs + rfspec.rfield_pattribs <- propAttribs' + rfspec.rfield_fattribs <- fieldAttribs' + addFixup fixupAttrs rfspec - let TcAnonFieldDecl cenv env parent tpenv nm (SynField(Attributes attribs, isStatic, idOpt, ty, isMutable, xmldoc, vis, m, _)) = + let TcAnonFieldDecl cenv env parent tpenv addFixup nm (SynField(Attributes attribs, isStatic, idOpt, ty, isMutable, xmldoc, vis, m, _)) = let mName = m.MakeSynthetic() let id = match idOpt with None -> mkSynId mName nm | Some id -> id let checkXmlDocs = cenv.diagnosticOptions.CheckXmlDocs let xmlDoc = xmldoc.ToXmlDoc(checkXmlDocs, Some []) - TcFieldDecl cenv env parent false tpenv (isStatic, attribs, id, idOpt.IsNone, ty, isMutable, xmlDoc, vis) + TcFieldDecl cenv env parent false tpenv addFixup (isStatic, attribs, id, idOpt.IsNone, ty, isMutable, xmlDoc, vis) - let TcNamedFieldDecl cenv env parent isIncrClass tpenv (SynField(Attributes attribs, isStatic, id, ty, isMutable, xmldoc, vis, m, _)) = + let TcNamedFieldDecl cenv env parent isIncrClass tpenv addFixup (SynField(Attributes attribs, isStatic, id, ty, isMutable, xmldoc, vis, m, _)) = match id with | None -> errorR (Error(FSComp.SR.tcFieldRequiresName(), m)) @@ -480,10 +498,10 @@ module TcRecdUnionAndEnumDeclarations = | Some id -> let checkXmlDocs = cenv.diagnosticOptions.CheckXmlDocs let xmlDoc = xmldoc.ToXmlDoc(checkXmlDocs, Some []) - Some(TcFieldDecl cenv env parent isIncrClass tpenv (isStatic, attribs, id, false, ty, isMutable, xmlDoc, vis)) + Some(TcFieldDecl cenv env parent isIncrClass tpenv addFixup (isStatic, attribs, id, false, ty, isMutable, xmlDoc, vis)) - let TcNamedFieldDecls cenv env parent isIncrClass tpenv fields = - fields |> List.choose (TcNamedFieldDecl cenv env parent isIncrClass tpenv) + let TcNamedFieldDecls cenv env parent isIncrClass tpenv addFixup fields = + fields |> List.choose (TcNamedFieldDecl cenv env parent isIncrClass tpenv addFixup) //------------------------------------------------------------------------- // Bind other elements of type definitions (constructors etc.) @@ -528,13 +546,15 @@ module TcRecdUnionAndEnumDeclarations = | _ -> seen.Add(f.LogicalName, sf)) - let TcUnionCaseDecl (cenv: cenv) env parent thisTy thisTyInst tpenv hasRQAAttribute (SynUnionCase(Attributes synAttrs, SynIdent(id, _), args, xmldoc, vis, m, _)) = + let TcUnionCaseDecl (cenv: cenv) env parent thisTy thisTyInst tpenv hasRQAAttribute addFixup (SynUnionCase(Attributes synAttrs, SynIdent(id, _), args, xmldoc, vis, m, _)) = let g = cenv.g let vis, _ = ComputeAccessAndCompPath g env None m vis None parent let vis = CombineReprAccess parent vis CheckUnionCaseName cenv id hasRQAAttribute + // Field fixups run after the union-case attributes below, preserving the non-deferred order. + let fieldFixups = ResizeArray() let rfields, recordTy = match args with | SynUnionCaseKind.Fields flds -> @@ -546,9 +566,9 @@ module TcRecdUnionAndEnumDeclarations = | Some fieldId, Parent tcref -> let item = Item.UnionCaseField (UnionCaseInfo (thisTyInst, UnionCaseRef (tcref, id.idText)), i) CallNameResolutionSink cenv.tcSink (fieldId.idRange, env.NameEnv, item, emptyTyparInst, ItemOccurrence.Binding, env.AccessRights) - TcNamedFieldDecl cenv env parent false tpenv fld + TcNamedFieldDecl cenv env parent false tpenv fieldFixups.Add fld | _ -> - Some(TcAnonFieldDecl cenv env parent tpenv (mkUnionCaseFieldName nFields i) fld) + Some(TcAnonFieldDecl cenv env parent tpenv fieldFixups.Add (mkUnionCaseFieldName nFields i) fld) ) |> List.choose (fun x -> x) @@ -582,42 +602,50 @@ module TcRecdUnionAndEnumDeclarations = let checkXmlDocs = cenv.diagnosticOptions.CheckXmlDocs let xmlDoc = xmldoc.ToXmlDoc(checkXmlDocs, Some names) - let attrs = TcAttributes cenv env AttributeTargets.UnionCaseDecl synAttrs - (* - The attributes of a union case decl get attached to the generated "static factory" method. - Enforce union-cases AttributeTargets: - - AttributeTargets.Method - type SomeUnion = - | Case1 of int // Compiles down to a static method - - AttributeTargets.Property - type SomeUnion = - | Case1 // Compiles down to a static property - *) - if g.langVersion.SupportsFeature(LanguageFeature.EnforceAttributeTargets) then - let attrTargets = - attrs - |> List.collect (fun attr -> - attr.TyconRef.Attribs - |> List.choose (fun attr -> - match attr with - | Attrib(unnamedArgs = [ AttribInt32Arg validOn ]) -> Some validOn - | _ -> None)) - - attrTargets - |> List.iter (fun target -> - // If the union case has fields, and the target is not AttributeTargets.Method || AttributeTargets.All. Then we raise a separate opt-in warning - let hasNotMethodTarget = (enum target &&& AttributeTargets.Method) = enum 0 - if hasNotMethodTarget then - warning(Error(FSComp.SR.tcAttributeIsNotValidForUnionCaseWithFields(), id.idRange))) - - Construct.NewUnionCase id rfields recordTy attrs xmlDoc vis - - let TcUnionCaseDecls (cenv: cenv) env (parent: ParentRef) (thisTy: TType) (thisTyInst: TypeInst) hasRQAAttribute tpenv unionCases = + let attrs, getFinalAttrs = TcAttributesCanFail cenv env AttributeTargets.UnionCaseDecl synAttrs + let unionCase = Construct.NewUnionCase id rfields recordTy attrs xmlDoc vis + + // Attribute types from the same recursive group resolve only once the group is established. + addFixup (fun () -> + let attrs = getFinalAttrs () + unionCase.Attribs <- attrs + (* + The attributes of a union case decl get attached to the generated "static factory" method. + Enforce union-cases AttributeTargets: + - AttributeTargets.Method + type SomeUnion = + | Case1 of int // Compiles down to a static method + - AttributeTargets.Property + type SomeUnion = + | Case1 // Compiles down to a static property + *) + if g.langVersion.SupportsFeature(LanguageFeature.EnforceAttributeTargets) then + let attrTargets = + attrs + |> List.collect (fun attr -> + attr.TyconRef.Attribs + |> List.choose (fun attr -> + match attr with + | Attrib(unnamedArgs = [ AttribInt32Arg validOn ]) -> Some validOn + | _ -> None)) + + attrTargets + |> List.iter (fun target -> + // If the union case has fields, and the target is not AttributeTargets.Method || AttributeTargets.All. Then we raise a separate opt-in warning + let hasNotMethodTarget = (enum target &&& AttributeTargets.Method) = enum 0 + if hasNotMethodTarget then + warning(Error(FSComp.SR.tcAttributeIsNotValidForUnionCaseWithFields(), id.idRange))) + + for f in fieldFixups do f()) + + unionCase + + let TcUnionCaseDecls (cenv: cenv) env (parent: ParentRef) (thisTy: TType) (thisTyInst: TypeInst) hasRQAAttribute tpenv addFixup unionCases = let unionCasesR = unionCases |> List.filter (fun (SynUnionCase(_, SynIdent(id, _), _, _, _, _, _)) -> id.idText <> "") - |> List.map (TcUnionCaseDecl cenv env parent thisTy thisTyInst tpenv hasRQAAttribute) - unionCasesR |> CheckDuplicates (fun uc -> uc.Id) "union case" + |> List.map (TcUnionCaseDecl cenv env parent thisTy thisTyInst tpenv hasRQAAttribute addFixup) + unionCasesR |> CheckDuplicates (fun uc -> uc.Id) "union case" let MakeEnumCaseSpec g cenv env parent attrs thisTy caseRange (caseIdent: Ident) (xmldoc: PreXmlDoc) value = let vis, _ = ComputeAccessAndCompPath g env None caseRange None None parent @@ -2448,7 +2476,7 @@ module TcExceptionDeclarations = CallNameResolutionSink cenv.tcSink (fieldId.idRange, env.NameEnv, item, emptyTyparInst, ItemOccurrence.Binding, env.AccessRights) | _ -> () - TcRecdUnionAndEnumDeclarations.TcAnonFieldDecl cenv env parent emptyUnscopedTyparEnv (mkExceptionFieldName i) fdef) + TcRecdUnionAndEnumDeclarations.TcAnonFieldDecl cenv env parent emptyUnscopedTyparEnv (fun f -> f ()) (mkExceptionFieldName i) fdef) TcRecdUnionAndEnumDeclarations.ValidateFieldNames(args, args') let repr = match reprIdOpt with @@ -2798,6 +2826,16 @@ module EstablishTypeDefinitionCores = let innerTypeNames = TypeNamesInMutRecDecls cenv envForDecls decls MutRecDefnsPhase2DataForModule (moduleTyAcc, moduleEntity), (innerParent, innerTypeNames, envForDecls) + /// Re-resolve type-parameter attributes once the recursive group's attribute types are + /// established. Phase1A resolves them tentatively with diagnostics suppressed; this runs in the + /// deferred fixup, mirroring the entity/field/union attribute fixups. + let private fixupTyparAttrs (cenv: cenv) env (synTypars: SynTyparDecl list) (typars: Typar list) = + (synTypars, typars) ||> List.iter2 (fun (SynTyparDecl (attributes = Attributes synAttrs)) tp -> + if not (isNil synAttrs) then + TcAttributes cenv env AttributeTargets.GenericParameter synAttrs + |> filterOutWellKnownAttribs cenv.g WellKnownEntityAttributes.MeasureAttribute WellKnownValAttributes.None + |> tp.SetAttribs) + /// Establish 'type C < T1... TN > = ...' including /// - computing the mangled name for C /// but @@ -2805,7 +2843,10 @@ module EstablishTypeDefinitionCores = let private TcTyconDefnCore_Phase1A_BuildInitialTycon (cenv: cenv) env parent (MutRecDefnsPhase1DataForTycon(synTyconInfo, synTyconRepr, _, preEstablishedHasDefaultCtor, hasSelfReferentialCtor, _)) = let g = cenv.g let (SynComponentInfo (_, TyparDecls synTypars, _, id, xmlDoc, preferPostfix, synVis, _)) = synTyconInfo - let checkedTypars = TcTyparDecls cenv env synTypars + // In a recursive group a type-parameter's attribute type may be defined later in the group and + // not yet resolvable. Resolve tentatively with diagnostics suppressed; the deferred fixup + // re-resolves against the completed environment (see fixupTyparAttrs at the drain). + let checkedTypars = suppressErrorReporting (fun () -> TcTyparDecls cenv env synTypars) id |> List.iter (CheckNamespaceModuleOrTypeName g) match synTyconRepr with @@ -3445,7 +3486,7 @@ module EstablishTypeDefinitionCores = with RecoverableException exn -> errorRecovery exn m)) /// Establish the fields, dispatch slots and union cases of a type - let private TcTyconDefnCore_Phase1G_EstablishRepresentation (cenv: cenv) envinner tpenv inSig (MutRecDefnsPhase1DataForTycon(_, synTyconRepr, _, _, _, _)) (tycon: Tycon) (attrs: Attribs) = + let private TcTyconDefnCore_Phase1G_EstablishRepresentation (cenv: cenv) envinner tpenv inSig (MutRecDefnsPhase1DataForTycon(_, synTyconRepr, _, _, _, _)) (tycon: Tycon) (attrs: Attribs) addFixup = let g = cenv.g let m = tycon.Range try @@ -3637,7 +3678,7 @@ module EstablishTypeDefinitionCores = structLayoutAttributeCheck false let hasRQAAttribute = EntityHasWellKnownAttribute cenv.g WellKnownEntityAttributes.RequireQualifiedAccessAttribute tycon - let unionCases = TcRecdUnionAndEnumDeclarations.TcUnionCaseDecls cenv envinner innerParent thisTy thisTyInst hasRQAAttribute tpenv unionCases + let unionCases = TcRecdUnionAndEnumDeclarations.TcUnionCaseDecls cenv envinner innerParent thisTy thisTyInst hasRQAAttribute tpenv addFixup unionCases multiCaseUnionStructCheck unionCases writeFakeUnionCtorsToSink unionCases @@ -3651,7 +3692,7 @@ module EstablishTypeDefinitionCores = noAbstractClassAttributeCheck() noAllowNullLiteralAttributeCheck() structLayoutAttributeCheck true // these are allowed for records - let recdFields = TcRecdUnionAndEnumDeclarations.TcNamedFieldDecls cenv envinner innerParent false tpenv fields + let recdFields = TcRecdUnionAndEnumDeclarations.TcNamedFieldDecls cenv envinner innerParent false tpenv addFixup fields recdFields |> CheckDuplicates (fun f -> f.Id) "field" |> ignore writeFakeRecordFieldsToSink recdFields CallEnvSink cenv.tcSink (mRepr, envinner.NameEnv, ad) @@ -3677,7 +3718,7 @@ module EstablishTypeDefinitionCores = TAsmRepr s, None, NoSafeInitInfo | SynTypeDefnSimpleRepr.General (kind, inherits, slotsigs, fields, isConcrete, isIncrClass, implicitCtorSynPats, _) -> - let userFields = TcRecdUnionAndEnumDeclarations.TcNamedFieldDecls cenv envinner innerParent isIncrClass tpenv fields + let userFields = TcRecdUnionAndEnumDeclarations.TcNamedFieldDecls cenv envinner innerParent isIncrClass tpenv addFixup fields let implicitStructFields = [ // For structs with an implicit ctor, determine the fields immediately based on the arguments match implicitCtorSynPats with @@ -4241,14 +4282,18 @@ module EstablishTypeDefinitionCores = // checking the members. let withBaseValsAndSafeInitInfos = (envMutRecPrelim, withAttrs) ||> MutRecShapes.mapTyconsWithEnv (fun envForDecls (origInfo, tyconAndAttrsOpt) -> - let info = + let info, tyconOpt, fixupFinalAttrs = match origInfo, tyconAndAttrsOpt with - | (typeDefCore, _, _), Some (tycon, (attrs, _)) -> TcTyconDefnCore_Phase1G_EstablishRepresentation cenv envForDecls tpenv inSig typeDefCore tycon attrs - | _ -> None, NoSafeInitInfo - let tyconOpt, fixupFinalAttrs = - match tyconAndAttrsOpt with - | None -> None, (fun () -> ()) - | Some (tycon, (_prelimAttrs, getFinalAttrs)) -> Some tycon, (fun () -> tycon.entity_attribs <- WellKnownEntityAttribs.Create(getFinalAttrs())) + | (typeDefCore, _, _), Some (tycon, (attrs, getFinalAttrs)) -> + let fixups = ResizeArray() + let info = TcTyconDefnCore_Phase1G_EstablishRepresentation cenv envForDecls tpenv inSig typeDefCore tycon attrs fixups.Add + let (MutRecDefnsPhase1DataForTycon(SynComponentInfo(typeParams=TyparDecls synTypars), _, _, _, _, _)) = typeDefCore + let fixupFinalAttrs () = + tycon.entity_attribs <- WellKnownEntityAttribs.Create(getFinalAttrs()) + fixupTyparAttrs cenv envForDecls synTypars tycon.Typars + for fixup in fixups do fixup() + info, Some tycon, fixupFinalAttrs + | _ -> (None, NoSafeInitInfo), None, ignore (origInfo, tyconOpt, fixupFinalAttrs, info)) @@ -4938,6 +4983,10 @@ module TcDeclarations = let mutRecDefnsAfterVals = TcMutRecSignatureDecls_Phase2 cenv scopem envMutRecPrelimWithReprs withEnvs + // Now the sibling types and their constructors are established, re-resolve any attributes + // that referred to them (mirrors the implementation path in TcMutRecDefns_Phase2_Bindings). + mutRecDefnsAfterCore |> MutRecShapes.iterTycons (fun (_, _, fixupFinalAttrs, _, _) -> fixupFinalAttrs()) + // Updates the types of the modules to contain the contents so far, which now includes values and members MutRecBindingChecking.TcMutRecDefns_UpdateModuleContents mutRecNSInfo mutRecDefnsAfterVals diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeResolutionInRecursiveScopes.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeResolutionInRecursiveScopes.fs index 42390f21aa0..c33f6808bdb 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeResolutionInRecursiveScopes.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeResolutionInRecursiveScopes.fs @@ -55,7 +55,7 @@ type CustomAttribute() = |> typecheck |> shouldSucceed - // https://github.com/dotnet/fsharp/issues/5795 - attribute on union case in rec module is not yet resolved + // https://github.com/dotnet/fsharp/issues/5795 - attribute on union case in rec module now resolves [] let ``Issue 5795 - attribute on union case in rec module`` () = FSharp """ @@ -67,11 +67,9 @@ type CustomAttribute() = type A = | [] A """ |> typecheck - |> shouldFail - |> withDiagnostics - [ Error 1133, Line 7, Col 14, Line 7, Col 29, "No constructors are available for the type 'CustomAttribute'" ] + |> shouldSucceed - // https://github.com/dotnet/fsharp/issues/5795 - attribute on type parameter in rec module is not yet resolved + // https://github.com/dotnet/fsharp/issues/5795 - attribute on type parameter in rec module now resolves [] let ``Issue 5795 - attribute on type parameter in rec module`` () = FSharp """ @@ -83,8 +81,7 @@ type CustomAttribute() = type B<[]'a> = | B of 'a """ |> typecheck - |> shouldFail - |> withErrorCode 39 + |> shouldSucceed // Nested module case: open inside outer module, attribute on inner module [] diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj index f4fb24145dd..02f6ff6b621 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj +++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj @@ -355,6 +355,7 @@ + diff --git a/tests/FSharp.Compiler.ComponentTests/Language/AttributeResolutionInRecursiveScopes.fs b/tests/FSharp.Compiler.ComponentTests/Language/AttributeResolutionInRecursiveScopes.fs new file mode 100644 index 00000000000..d43093283c8 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/AttributeResolutionInRecursiveScopes.fs @@ -0,0 +1,440 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace Language + +open Xunit +open FSharp.Test +open FSharp.Test.Compiler + +module AttributeResolutionInRecursiveScopes = + + // Baselines: these attribute positions already worked before #5795. + + [] + let ``attribute on type declaration in module rec resolves to attribute defined in same module`` () = + Fsx """ +module rec M + +type CustomAttribute() = inherit System.Attribute() + +[] +type A = | A +""" + |> compile + |> shouldSucceed + + [] + let ``attribute on let binding in module rec resolves to attribute defined in same module`` () = + Fsx """ +module rec M + +type CustomAttribute() = inherit System.Attribute() + +[] +let a = () +""" + |> compile + |> shouldSucceed + + [] + let ``attribute on type declaration in namespace rec resolves to attribute defined in same namespace`` () = + Fsx """ +namespace rec Ns + +type CustomAttribute() = inherit System.Attribute() + +[] +type A = | A +""" + |> compile + |> shouldSucceed + + [] + let ``attribute on let binding in non-rec module resolves to attribute defined in same module`` () = + Fsx """ +module M + +type CustomAttribute() = inherit System.Attribute() + +[] +let a = () +""" + |> compile + |> shouldSucceed + + [] + let ``attribute on union case in module rec resolves to attribute defined in same module`` () = + Fsx """ +module rec M + +type CustomAttribute() = inherit System.Attribute() + +type A = | [] A +""" + |> compile + |> shouldSucceed + + [] + let ``attribute on union case in namespace rec resolves to attribute defined in same namespace`` () = + Fsx """ +namespace rec Ns + +type CustomAttribute() = inherit System.Attribute() + +type A = | [] A +""" + |> compile + |> shouldSucceed + + [] + let ``attribute on every case of a DU in module rec resolves to attribute defined in same module`` () = + Fsx """ +module rec M + +type CustomAttribute() = inherit System.Attribute() + +type Shape = + | [] Circle of float + | [] Square of float +""" + |> compile + |> shouldSucceed + + [] + let ``attribute shorthand on union case in module rec resolves to attribute defined in same module`` () = + Fsx """ +module rec M + +type CustomAttribute() = inherit System.Attribute() + +type A = | [] A +""" + |> compile + |> shouldSucceed + + [] + let ``attribute on record field in module rec resolves to attribute defined in same module`` () = + Fsx """ +module rec M + +type CustomAttribute() = inherit System.Attribute() + +type R = { [] X: int } +""" + |> compile + |> shouldSucceed + + [] + let ``attribute on multiple record fields in module rec resolves to attributes defined in same module`` () = + Fsx """ +module rec M + +type CustomAttribute() = inherit System.Attribute() +type AnotherAttribute() = inherit System.Attribute() + +type R = { + [] X: int + [] Y: string + [] Z: float +} +""" + |> compile + |> shouldSucceed + + [] + let ``attribute on record field in namespace rec resolves to attribute defined in same namespace`` () = + Fsx """ +namespace rec Ns + +type CustomAttribute() = inherit System.Attribute() + +type R = { [] X: int } +""" + |> compile + |> shouldSucceed + + [] + let ``attribute on type parameter in module rec resolves to attribute defined in same module`` () = + Fsx """ +module rec M + +type CustomAttribute() = inherit System.Attribute() + +type B<[]'a> = | B of 'a +""" + |> compile + |> shouldSucceed + + [] + let ``attribute on type parameter in namespace rec resolves to attribute defined in same namespace`` () = + Fsx """ +namespace rec Ns + +type CustomAttribute() = inherit System.Attribute() + +type B<[]'a> = | B of 'a +""" + |> compile + |> shouldSucceed + + [] + let ``attribute on type parameter combined with framework Measure attribute in module rec compiles`` () = + Fsx """ +module rec M + +type CustomAttribute() = inherit System.Attribute() + +type B<[]'u, []'a> = B of 'a +""" + |> compile + |> shouldSucceed + + // Edge cases + + [] + let ``attribute defined in nested module of rec scope resolves on union case`` () = + Fsx """ +module rec M + +module Nested = + type CustomAttribute() = inherit System.Attribute() + +type A = | [] A +""" + |> compile + |> shouldSucceed + + [] + let ``attribute defined in nested module of rec scope resolves on type parameter`` () = + Fsx """ +module rec M + +module Nested = + type CustomAttribute() = inherit System.Attribute() + +type B<[]'a> = B of 'a +""" + |> compile + |> shouldSucceed + + [] + let ``attribute defined in nested module of rec scope resolves on record field`` () = + Fsx """ +module rec M + +module Nested = + type CustomAttribute() = inherit System.Attribute() + +type R = { [] X: int } +""" + |> compile + |> shouldSucceed + + [] + let ``multiple attributes mixing framework Obsolete and rec-scope custom on union case compile`` () = + Fsx """ +module rec M + +open System + +type CustomAttribute() = inherit System.Attribute() + +type A = | [] A +""" + |> ignoreWarnings + |> compile + |> shouldSucceed + + [] + let ``opt-in AttributeTargets warning fires for rec-scope attribute on union case with fields`` () = + // Parity with the non-rec case: FS3878 must still fire when the attribute type is defined in + // the same recursive group, whose target is only known after the deferred fixup re-resolves it. + Fsx """ +module rec M + +open System + +[] +type CustomAttribute() = inherit System.Attribute() + +type A = | [] Case of int +""" + |> withWarnOn 3878 + |> compile + |> shouldFail + |> withDiagnosticMessageMatches "This attribute is not valid for use on union cases with fields" + + [] + let ``rec-scope attribute shadows outer-scope attribute on union case in nested rec module`` () = + Fsx """ +module Root + +type CustomAttribute() = inherit System.Attribute() + +module rec M = + type CustomAttribute() = inherit System.Attribute() + type A = | [] A +""" + |> compile + |> shouldSucceed + + // [] resolves to the user's MeasureAttribute by name, so kind inference breaks. + // Unrelated to #5795 rec-scope fix. + [] + let ``user-defined MeasureAttribute in rec scope does not break framework Measure kind inference`` () = + Fsx """ +module rec M + +type MeasureAttribute() = inherit System.Attribute() + +[] type kg +""" + |> compile + |> shouldSucceed + + // Negative tests — must still error after the fix. + + [] + let ``non-attribute type used on union case in module rec still produces diagnostic`` () = + // FS3242: "does not inherit Attribute" — warning, not error. + Fsx """ +module rec M + +type NotAnAttribute() = class end + +type A = | [] A +""" + |> ignoreWarnings + |> compile + |> shouldSucceed + |> withDiagnosticMessageMatches "does not inherit Attribute" + + [] + let ``unknown attribute name on union case in module rec still errors with FS0039`` () = + Fsx """ +module rec M + +type A = | [] A +""" + |> compile + |> shouldFail + |> withErrorCode 39 + + [] + let ``unknown attribute name on type parameter in module rec still errors with FS0039`` () = + Fsx """ +module rec M + +type B<[]'a> = B of 'a +""" + |> compile + |> shouldFail + |> withErrorCode 39 + + [] + let ``unknown attribute name on record field in module rec still errors with FS0039`` () = + Fsx """ +module rec M + +type R = { [] X: int } +""" + |> compile + |> shouldFail + |> withErrorCode 39 + + // Signature files go through the same deferred attribute-resolution path as implementations. + // These guard against the fixup being skipped for signatures (which would silently swallow + // unresolved attribute names and drop rec-scoped attributes). + + let private sigAndImpl (fsi: string) (fs: string) = + Fsi fsi |> withAdditionalSourceFile (FsSource fs) + + [] + let ``unknown attribute on record field in signature still errors with FS0039`` () = + sigAndImpl + "module rec Lib\n\ntype Foo =\n { [] Field: int }\n" + "module rec Lib\n\ntype Foo =\n { Field: int }\n" + |> compile + |> shouldFail + |> withErrorCode 39 + + [] + let ``unknown attribute on union case in signature still errors with FS0039`` () = + sigAndImpl + "module rec Lib\n\ntype U =\n | [] A of int\n" + "module rec Lib\n\ntype U =\n | A of int\n" + |> compile + |> shouldFail + |> withErrorCode 39 + + [] + let ``unknown attribute on type parameter in signature still errors with FS0039`` () = + sigAndImpl + "module rec Lib\n\n[]\ntype C<[] 'T> =\n abstract M: 'T -> unit\n" + "module rec Lib\n\n[]\ntype C<'T>() =\n abstract M: 'T -> unit\n" + |> compile + |> shouldFail + |> withErrorCode 39 + + [] + let ``unknown attribute on type in signature still errors with FS0039`` () = + sigAndImpl + "module rec Lib\n\n[]\ntype Foo =\n { Field: int }\n" + "module rec Lib\n\ntype Foo =\n { Field: int }\n" + |> compile + |> shouldFail + |> withErrorCode 39 + + [] + let ``attribute defined in same module rec resolves on record field in signature`` () = + sigAndImpl + "module rec Lib\n\ntype CustomAttribute =\n inherit System.Attribute\n new: unit -> CustomAttribute\n\ntype Foo =\n { [] Field: int }\n" + "module rec Lib\n\ntype CustomAttribute() =\n inherit System.Attribute()\n\ntype Foo =\n { [] Field: int }\n" + |> compile + |> shouldSucceed + + [] + let ``attribute defined in same module rec resolves on union case in signature`` () = + sigAndImpl + "module rec Lib\n\ntype CustomAttribute =\n inherit System.Attribute\n new: unit -> CustomAttribute\n\ntype U =\n | [] A of int\n" + "module rec Lib\n\ntype CustomAttribute() =\n inherit System.Attribute()\n\ntype U =\n | [] A of int\n" + |> compile + |> shouldSucceed + + [] + let ``attribute defined in same module rec resolves on type parameter in signature`` () = + sigAndImpl + "module rec Lib\n\ntype CustomAttribute =\n inherit System.Attribute\n new: unit -> CustomAttribute\n\n[]\ntype C<[] 'T> =\n abstract M: 'T -> unit\n" + "module rec Lib\n\ntype CustomAttribute() =\n inherit System.Attribute()\n\n[]\ntype C<[] 'T>() =\n abstract M: 'T -> unit\n" + |> compile + |> shouldSucceed + + [] + let ``attribute defined in same module rec resolves on explicit val mutable field`` () = + Fsx """ +module rec M + +type C() = + [] + val mutable x : int + +type CustomAttribute() = inherit System.Attribute() +""" + |> compile + |> shouldSucceed + + [] + let ``property-only attribute in same module rec still warns on explicit val mutable field`` () = + Fsx """ +module rec M + +type C() = + [] + val mutable x : int + +[] +type CustomAttribute() = inherit System.Attribute() +""" + |> compile + |> shouldFail + |> withDiagnosticMessageMatches "This attribute cannot be applied to field. Valid targets are: property" From 1dc395ad3415561bd2425a32e5c1f7eb50e63066 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Fri, 24 Jul 2026 15:29:08 +0000 Subject: [PATCH 17/33] Correct StructLayout size emission for data-less struct unions (#19759) --- .../.FSharp.Compiler.Service/11.0.100.md | 1 + src/Compiler/CodeGen/IlxGen.fs | 14 ++------- .../CustomAttributes/Basic/Basic.fs | 30 ++++++++++++++++--- .../EmittedIL/Structure/Structure.fs | 18 +++++++++++ 4 files changed, 48 insertions(+), 15 deletions(-) diff --git a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md index 9b7e4989514..87fcd750640 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md +++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md @@ -1,5 +1,6 @@ ### Fixed +* Fix incorrect `StructLayout(Size = 1)` emission for data-less struct unions where the compiler-generated tag field makes the actual runtime size larger. ([PR #19759](https://github.com/dotnet/fsharp/pull/19759)) * Fix FS0750 "This construct may only be used within computation expressions" incorrectly raised for `let!`/`use!`/`do!` appearing in the right-hand side of a plain `let` binding inside a computation expression. The right-hand side is now desugared as a nested computation of the same builder whose result is bound with `let!`, keeping its bindings correctly scoped. ([Issue #19457](https://github.com/dotnet/fsharp/issues/19457), [PR #19868](https://github.com/dotnet/fsharp/pull/19868)) * Stop leaking a `System.Diagnostics.Metrics.MeterListener` per `Cache` in DEBUG builds. Each cache created a `CacheMetrics.CacheMetricsListener` (which starts a `MeterListener` registered in the process-global metrics registry) and never disposed it, so listeners accumulated for the lifetime of the process. Because every cache hit/miss/add published to all registered listeners, the per-operation cost grew linearly with the number of leaked listeners, so repeated checks (and Debug FCS test runs) slowed down over time. The per-cache `CacheMetricsListener` and the per-instance `cacheId` tag are removed; `DebugDisplay` and tests now read the existing name-aggregated stats populated by the single `ListenToAll` listener, so no per-cache listener is created and no per-operation cost is added. ([PR #19995](https://github.com/dotnet/fsharp/pull/19995)) * Fix state machine lowering dropping the side-effectful receiver of an unused unit-typed member access (e.g. inside `task { (effectful()).UnitProp }`). ([Issue #13099](https://github.com/dotnet/fsharp/issues/13099), [PR #19885](https://github.com/dotnet/fsharp/pull/19885)) diff --git a/src/Compiler/CodeGen/IlxGen.fs b/src/Compiler/CodeGen/IlxGen.fs index 6e6f252606c..c170a757715 100644 --- a/src/Compiler/CodeGen/IlxGen.fs +++ b/src/Compiler/CodeGen/IlxGen.fs @@ -12228,18 +12228,10 @@ and GenTypeDef cenv mgbuf lazyInitInfo eenv m (tycon: Tycon) : ILTypeRef option } let layout = - // Structs with no instance fields get size 1, pack 0 + // Multi-case struct unions carry a hidden tag field; single-case struct unions + // are handled by the CLR's minimum-1-byte guarantee. No explicit size needed. if isStructTy g thisTy then - if - (tycon.AllFieldsArray.Length = 0 - || tycon.AllFieldsArray |> Array.exists (fun f -> not f.IsStatic)) - && (alternatives - |> Array.collect (fun a -> a.FieldDefs) - |> Array.exists (fun fd -> not fd.ILField.IsStatic)) - then - ILTypeDefLayout.Sequential { Size = None; Pack = None } - else - ILTypeDefLayout.Sequential { Size = Some 1; Pack = Some 0us } + ILTypeDefLayout.Sequential { Size = None; Pack = None } else ILTypeDefLayout.Auto diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/Basic/Basic.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/Basic/Basic.fs index dde97126f13..d47e20daefc 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/Basic/Basic.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/Basic/Basic.fs @@ -439,7 +439,7 @@ if Convert.ToString(prop, Globalization.CultureInfo.InvariantCulture) <> "B" the ] [] - let ``StructLayoutAttribute has size=1 for struct DUs with no instance fields`` () = + let ``StructLayoutAttribute doesn't have size=1 for multi-case struct DUs with no instance fields`` () = Fsx """ [] type Option<'T> = None | Some """ @@ -455,8 +455,6 @@ if Convert.ToString(prop, Globalization.CultureInfo.InvariantCulture) <> "B" the [runtime]System.IComparable, [runtime]System.Collections.IStructuralComparable { - .pack 0 - .size 1 .custom instance void [FSharp.Core]Microsoft.FSharp.Core.StructAttribute::.ctor() = ( 01 00 00 00 ) .custom instance void [runtime]System.Diagnostics.DebuggerDisplayAttribute::.ctor(string) = ( 01 00 15 7B 5F 5F 44 65 62 75 67 44 69 73 70 6C 61 79 28 29 2C 6E 71 7D 00 00 ) @@ -468,4 +466,28 @@ if Convert.ToString(prop, Globalization.CultureInfo.InvariantCulture) <> "B" the .field public static literal int32 Some = int32(0x00000001) } """ - ] \ No newline at end of file + ] + + [] + let ``StructLayoutAttribute doesn't have size=1 for single-case struct DU`` () = + Fsx """ + [] type X = | Y + """ + |> compile + |> shouldSucceed + |> verifyIL [ + """ + .class sequential autochar serializable sealed nested public beforefieldinit X + extends [runtime]System.ValueType + implements class [runtime]System.IEquatable`1, + [runtime]System.Collections.IStructuralEquatable, + class [runtime]System.IComparable`1, + [runtime]System.IComparable, + [runtime]System.Collections.IStructuralComparable + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.StructAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerDisplayAttribute::.ctor(string) = ( 01 00 15 7B 5F 5F 44 65 62 75 67 44 69 73 70 6C + 61 79 28 29 2C 6E 71 7D 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 01 00 00 00 00 00 ) + """ + ] diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Structure/Structure.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Structure/Structure.fs index cef637ee350..e0179800b93 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Structure/Structure.fs +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Structure/Structure.fs @@ -235,3 +235,21 @@ module Structure = compilation |> getCompilation |> verifyExecution + + [] + let ``sizeof reports correct sizes for various struct DU forms`` () = + Fsx """ +[] type SingleCase = | Only +[] type MultiNoData = A | B | C +[] type OneIntField = N | S of int +[] type TwoIntFields = T0 | T1 of x: int * y: int + +[] +let main _ = + printf "SingleCase=%i;MultiNoData=%i;OneIntField=%i;TwoIntFields=%i" sizeof sizeof sizeof sizeof + 0 + """ + |> asExe + |> compileAndRun + |> shouldSucceed + |> verifyOutput "SingleCase=1;MultiNoData=4;OneIntField=8;TwoIntFields=12" From 8c0e444de18218ecec91475a6022872e93299e10 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Sun, 26 Jul 2026 10:27:14 +0200 Subject: [PATCH 18/33] Report FS3888 for generic attribute type abbreviations instead of FS0193 (#19915) --- .../.FSharp.Compiler.Service/11.0.100.md | 1 + .../Checking/Expressions/CheckExpressions.fs | 8 ++ src/Compiler/FSComp.txt | 1 + src/Compiler/xlf/FSComp.txt.cs.xlf | 5 + src/Compiler/xlf/FSComp.txt.de.xlf | 5 + src/Compiler/xlf/FSComp.txt.es.xlf | 5 + src/Compiler/xlf/FSComp.txt.fr.xlf | 5 + src/Compiler/xlf/FSComp.txt.it.xlf | 5 + src/Compiler/xlf/FSComp.txt.ja.xlf | 5 + src/Compiler/xlf/FSComp.txt.ko.xlf | 5 + src/Compiler/xlf/FSComp.txt.pl.xlf | 5 + src/Compiler/xlf/FSComp.txt.pt-BR.xlf | 5 + src/Compiler/xlf/FSComp.txt.ru.xlf | 5 + src/Compiler/xlf/FSComp.txt.tr.xlf | 5 + src/Compiler/xlf/FSComp.txt.zh-Hans.xlf | 5 + src/Compiler/xlf/FSComp.txt.zh-Hant.xlf | 5 + .../GenericAttributeAbbreviations.fs | 98 +++++++++++++++++++ .../FSharp.Compiler.ComponentTests.fsproj | 1 + 18 files changed, 174 insertions(+) create mode 100644 tests/FSharp.Compiler.ComponentTests/Attributes/GenericAttributeAbbreviations.fs diff --git a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md index 87fcd750640..01747f0b583 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md +++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md @@ -119,6 +119,7 @@ * Warn FS3888 when a compiler-semantic attribute on a value/member or type/module is present in the `.fs` but missing from the `.fsi`. Such attributes were previously ignored at the consumer side. Under the `ErrorOnMissingSignatureAttribute` preview language feature, FS3888 is an error. ([Issue #19560](https://github.com/dotnet/fsharp/issues/19560), [PR #19880](https://github.com/dotnet/fsharp/pull/19880)) * Emit debug points at a stack-empty position ([PR #19877](https://github.com/dotnet/fsharp/pull/19877)) * Fix spurious XmlDoc warnings (unknown parameter / no documentation for parameter) under `--warnon:3390` when a get/set property documents the full parameter set across both accessors. ([Issue #13684](https://github.com/dotnet/fsharp/issues/13684), [PR #19884](https://github.com/dotnet/fsharp/pull/19884)) +* Replace internal compiler error FS0193 with a clear FS3891 diagnostic when a type abbreviation aliases a generic attribute type (e.g. `type B = A` then `[] ...`). Generic attributes remain unsupported in F#. ([Issue #7877](https://github.com/dotnet/fsharp/issues/7877), [PR #19915](https://github.com/dotnet/fsharp/pull/19915)) * Fix Go to Metadata rendering of IL literal (`const`) fields - they now appear with `[]` and their constant value, e.g. `System.Char.MaxValue` no longer shows as a plain `static val`. ([Issue #11526](https://github.com/dotnet/fsharp/issues/11526), [PR #19922](https://github.com/dotnet/fsharp/pull/19922)) * FSI multi-assembly emit (`--multiemit+`) now attaches `System.Diagnostics.DebuggableAttribute(DisableOptimizations|Default)` to each submission's manifest when local optimizations are disabled (`--optimize-`), matching the single-emit and regular-compiler behavior so debuggers see submissions as unoptimized. ([Issue #14572](https://github.com/dotnet/fsharp/issues/14572), [PR #19921](https://github.com/dotnet/fsharp/pull/19921)) * Stop F# Interactive from mutating script arguments that follow `--`. Abbreviated flags like `-d`, `-r`, `-I` after the `--` separator are no longer colon-joined with their next token in `fsi.CommandLineArgs`. ([Issue #10819](https://github.com/dotnet/fsharp/issues/10819), [PR #19926](https://github.com/dotnet/fsharp/pull/19926)) diff --git a/src/Compiler/Checking/Expressions/CheckExpressions.fs b/src/Compiler/Checking/Expressions/CheckExpressions.fs index aba29d0aa86..288f99e67e7 100644 --- a/src/Compiler/Checking/Expressions/CheckExpressions.fs +++ b/src/Compiler/Checking/Expressions/CheckExpressions.fs @@ -11745,6 +11745,14 @@ and TcAttributeEx canFail (cenv: cenv) (env: TcEnv) attrTgt attrEx (synAttr: Syn let tcref = tcrefOfAppTy g ty + if not tcref.Typars.IsEmpty then + match canFail with + | TcCanFail.IgnoreAllErrors | TcCanFail.IgnoreMemberResoutionError -> [], true + | TcCanFail.ReportAllErrors -> + errorR(Error(FSComp.SR.tcGenericAttributesNotSupported(tcref.DisplayName), mAttr)) + [], false + else + let conditionalCallDefineOpt = TryFindTyconRefStringAttribute g mAttr g.attrib_ConditionalAttribute tcref match conditionalCallDefineOpt, cenv.conditionalDefines with diff --git a/src/Compiler/FSComp.txt b/src/Compiler/FSComp.txt index c6cbc797da5..52f284ca0dc 100644 --- a/src/Compiler/FSComp.txt +++ b/src/Compiler/FSComp.txt @@ -1822,6 +1822,7 @@ featurePreprocessorElif,"#elif preprocessor directive" 3888,implAttributeMissingFromSignature,"The attribute '%s' is present on '%s' in the implementation but not in the signature, which takes precedence for tooling and consumers. Add the attribute to the signature, to ensure the attribute is not ignored by the compiler." 3889,tastNamespaceAndTypeWithSameNameInAssembly,"The namespace '%s' clashes with the type '%s'." 3890,tcRecursiveInlineNotAllowed,"The value or member '%s' has been marked 'inline' but is part of a recursive binding group. F# does not support recursive 'inline' values. Either remove the 'inline' modifier or refactor the recursion." +3891,tcGenericAttributesNotSupported,"Generic attribute types are not supported in F#. The type '%s' has type parameters and cannot be used as an attribute." featureExceptionFieldSerializationSupport,"emit GetObjectData and field-restoring deserialization constructor for exception types" featureErrorOnMissingSignatureAttribute,"error (rather than warning) when an enforced compiler-semantic attribute is present in the .fs but missing from the .fsi" featureAccessProtectedBaseFieldFromClosure,"Access a protected base-class field from a closure inside a member" diff --git a/src/Compiler/xlf/FSComp.txt.cs.xlf b/src/Compiler/xlf/FSComp.txt.cs.xlf index 48fae4742da..9334bfd8de2 100644 --- a/src/Compiler/xlf/FSComp.txt.cs.xlf +++ b/src/Compiler/xlf/FSComp.txt.cs.xlf @@ -1527,6 +1527,11 @@ Expected unit-of-measure type parameter must be marked with the [<Measure>] attribute. + + Generic attribute types are not supported in F#. The type '{0}' has type parameters and cannot be used as an attribute. + Generic attribute types are not supported in F#. The type '{0}' has type parameters and cannot be used as an attribute. + + The syntax 'expr1[expr2]' is used for indexing. Consider adding a type annotation to enable indexing, or if calling a function add a space, e.g. 'expr1 [expr2]'. Syntaxe expr1[expr2] se používá pro indexování. Pokud chcete povolit indexování, zvažte možnost přidat anotaci typu, nebo pokud voláte funkci, přidejte mezeru, třeba expr1 [expr2]. diff --git a/src/Compiler/xlf/FSComp.txt.de.xlf b/src/Compiler/xlf/FSComp.txt.de.xlf index 256a5b49e0f..c17001c39ee 100644 --- a/src/Compiler/xlf/FSComp.txt.de.xlf +++ b/src/Compiler/xlf/FSComp.txt.de.xlf @@ -1527,6 +1527,11 @@ Expected unit-of-measure type parameter must be marked with the [<Measure>] attribute. + + Generic attribute types are not supported in F#. The type '{0}' has type parameters and cannot be used as an attribute. + Generic attribute types are not supported in F#. The type '{0}' has type parameters and cannot be used as an attribute. + + The syntax 'expr1[expr2]' is used for indexing. Consider adding a type annotation to enable indexing, or if calling a function add a space, e.g. 'expr1 [expr2]'. Die Syntax "expr1[expr2]" wird für die Indizierung verwendet. Fügen Sie ggf. eine Typanmerkung hinzu, um die Indizierung zu aktivieren, oder fügen Sie beim Aufrufen einer Funktion ein Leerzeichen hinzu, z. B. "expr1 [expr2]". diff --git a/src/Compiler/xlf/FSComp.txt.es.xlf b/src/Compiler/xlf/FSComp.txt.es.xlf index 965b77b54c1..9d678e0a8c2 100644 --- a/src/Compiler/xlf/FSComp.txt.es.xlf +++ b/src/Compiler/xlf/FSComp.txt.es.xlf @@ -1527,6 +1527,11 @@ Expected unit-of-measure type parameter must be marked with the [<Measure>] attribute. + + Generic attribute types are not supported in F#. The type '{0}' has type parameters and cannot be used as an attribute. + Generic attribute types are not supported in F#. The type '{0}' has type parameters and cannot be used as an attribute. + + The syntax 'expr1[expr2]' is used for indexing. Consider adding a type annotation to enable indexing, or if calling a function add a space, e.g. 'expr1 [expr2]'. La sintaxis "expr1[expr2]" se usa para la indexación. Considere la posibilidad de agregar una anotación de tipo para habilitar la indexación, si se llama a una función, agregue un espacio, por ejemplo, "expr1 [expr2]". diff --git a/src/Compiler/xlf/FSComp.txt.fr.xlf b/src/Compiler/xlf/FSComp.txt.fr.xlf index 36af4f462ea..59431250f44 100644 --- a/src/Compiler/xlf/FSComp.txt.fr.xlf +++ b/src/Compiler/xlf/FSComp.txt.fr.xlf @@ -1527,6 +1527,11 @@ Expected unit-of-measure type parameter must be marked with the [<Measure>] attribute. + + Generic attribute types are not supported in F#. The type '{0}' has type parameters and cannot be used as an attribute. + Generic attribute types are not supported in F#. The type '{0}' has type parameters and cannot be used as an attribute. + + The syntax 'expr1[expr2]' is used for indexing. Consider adding a type annotation to enable indexing, or if calling a function add a space, e.g. 'expr1 [expr2]'. La syntaxe « expr1[expr2] » est utilisée pour l’indexation. Envisagez d’ajouter une annotation de type pour activer l’indexation, ou si vous appelez une fonction, ajoutez un espace, par exemple « expr1 [expr2] ». diff --git a/src/Compiler/xlf/FSComp.txt.it.xlf b/src/Compiler/xlf/FSComp.txt.it.xlf index cf5834247b2..0c5bd18a17a 100644 --- a/src/Compiler/xlf/FSComp.txt.it.xlf +++ b/src/Compiler/xlf/FSComp.txt.it.xlf @@ -1527,6 +1527,11 @@ Expected unit-of-measure type parameter must be marked with the [<Measure>] attribute. + + Generic attribute types are not supported in F#. The type '{0}' has type parameters and cannot be used as an attribute. + Generic attribute types are not supported in F#. The type '{0}' has type parameters and cannot be used as an attribute. + + The syntax 'expr1[expr2]' is used for indexing. Consider adding a type annotation to enable indexing, or if calling a function add a space, e.g. 'expr1 [expr2]'. La sintassi 'expr1[expr2]' viene usata per l'indicizzazione. Provare ad aggiungere un'annotazione di tipo per abilitare l'indicizzazione oppure se la chiamata a una funzione aggiunge uno spazio, ad esempio 'expr1 [expr2]'. diff --git a/src/Compiler/xlf/FSComp.txt.ja.xlf b/src/Compiler/xlf/FSComp.txt.ja.xlf index d684f435a7f..c18e74bd681 100644 --- a/src/Compiler/xlf/FSComp.txt.ja.xlf +++ b/src/Compiler/xlf/FSComp.txt.ja.xlf @@ -1527,6 +1527,11 @@ Expected unit-of-measure type parameter must be marked with the [<Measure>] attribute. + + Generic attribute types are not supported in F#. The type '{0}' has type parameters and cannot be used as an attribute. + Generic attribute types are not supported in F#. The type '{0}' has type parameters and cannot be used as an attribute. + + The syntax 'expr1[expr2]' is used for indexing. Consider adding a type annotation to enable indexing, or if calling a function add a space, e.g. 'expr1 [expr2]'. 構文 'expr1[expr2]' はインデックス作成に使用されます。インデックスを有効にするために型の注釈を追加するか、関数を呼び出す場合には、'expr1 [expr2]' のようにスペースを入れます。 diff --git a/src/Compiler/xlf/FSComp.txt.ko.xlf b/src/Compiler/xlf/FSComp.txt.ko.xlf index ae0bdce0e1f..30fedb9db77 100644 --- a/src/Compiler/xlf/FSComp.txt.ko.xlf +++ b/src/Compiler/xlf/FSComp.txt.ko.xlf @@ -1527,6 +1527,11 @@ Expected unit-of-measure type parameter must be marked with the [<Measure>] attribute. + + Generic attribute types are not supported in F#. The type '{0}' has type parameters and cannot be used as an attribute. + Generic attribute types are not supported in F#. The type '{0}' has type parameters and cannot be used as an attribute. + + The syntax 'expr1[expr2]' is used for indexing. Consider adding a type annotation to enable indexing, or if calling a function add a space, e.g. 'expr1 [expr2]'. 인덱싱에는 'expr1[expr2]' 구문이 사용됩니다. 인덱싱을 사용하도록 설정하기 위해 형식 주석을 추가하는 것을 고려하거나 함수를 호출하는 경우 공백을 추가하세요(예: 'expr1 [expr2]'). diff --git a/src/Compiler/xlf/FSComp.txt.pl.xlf b/src/Compiler/xlf/FSComp.txt.pl.xlf index e7f9fbedc3e..72b79d252d3 100644 --- a/src/Compiler/xlf/FSComp.txt.pl.xlf +++ b/src/Compiler/xlf/FSComp.txt.pl.xlf @@ -1527,6 +1527,11 @@ Expected unit-of-measure type parameter must be marked with the [<Measure>] attribute. + + Generic attribute types are not supported in F#. The type '{0}' has type parameters and cannot be used as an attribute. + Generic attribute types are not supported in F#. The type '{0}' has type parameters and cannot be used as an attribute. + + The syntax 'expr1[expr2]' is used for indexing. Consider adding a type annotation to enable indexing, or if calling a function add a space, e.g. 'expr1 [expr2]'. Do indeksowania używana jest składnia „expr1[expr2]”. Rozważ dodanie adnotacji typu, aby umożliwić indeksowanie, lub jeśli wywołujesz funkcję dodaj spację, np. „expr1 [expr2]”. diff --git a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf index 2ee0777fb1b..acd4495941f 100644 --- a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf +++ b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf @@ -1527,6 +1527,11 @@ Expected unit-of-measure type parameter must be marked with the [<Measure>] attribute. + + Generic attribute types are not supported in F#. The type '{0}' has type parameters and cannot be used as an attribute. + Generic attribute types are not supported in F#. The type '{0}' has type parameters and cannot be used as an attribute. + + The syntax 'expr1[expr2]' is used for indexing. Consider adding a type annotation to enable indexing, or if calling a function add a space, e.g. 'expr1 [expr2]'. A sintaxe 'expr1[expr2]' é usada para indexação. Considere adicionar uma anotação de tipo para habilitar a indexação ou, se chamar uma função, adicione um espaço, por exemplo, 'expr1 [expr2]'. diff --git a/src/Compiler/xlf/FSComp.txt.ru.xlf b/src/Compiler/xlf/FSComp.txt.ru.xlf index 4b425932b82..d2b1901323b 100644 --- a/src/Compiler/xlf/FSComp.txt.ru.xlf +++ b/src/Compiler/xlf/FSComp.txt.ru.xlf @@ -1527,6 +1527,11 @@ Expected unit-of-measure type parameter must be marked with the [<Measure>] attribute. + + Generic attribute types are not supported in F#. The type '{0}' has type parameters and cannot be used as an attribute. + Generic attribute types are not supported in F#. The type '{0}' has type parameters and cannot be used as an attribute. + + The syntax 'expr1[expr2]' is used for indexing. Consider adding a type annotation to enable indexing, or if calling a function add a space, e.g. 'expr1 [expr2]'. Для индексирования используется синтаксис "expr1[expr2]". Рассмотрите возможность добавления аннотации типа для включения индексации или при вызове функции добавьте пробел, например "expr1 [expr2]". diff --git a/src/Compiler/xlf/FSComp.txt.tr.xlf b/src/Compiler/xlf/FSComp.txt.tr.xlf index 851fc063da5..d366bb71ee7 100644 --- a/src/Compiler/xlf/FSComp.txt.tr.xlf +++ b/src/Compiler/xlf/FSComp.txt.tr.xlf @@ -1527,6 +1527,11 @@ Expected unit-of-measure type parameter must be marked with the [<Measure>] attribute. + + Generic attribute types are not supported in F#. The type '{0}' has type parameters and cannot be used as an attribute. + Generic attribute types are not supported in F#. The type '{0}' has type parameters and cannot be used as an attribute. + + The syntax 'expr1[expr2]' is used for indexing. Consider adding a type annotation to enable indexing, or if calling a function add a space, e.g. 'expr1 [expr2]'. Söz dizimi “expr1[expr2]” dizin oluşturma için kullanılıyor. Dizin oluşturmayı etkinleştirmek için bir tür ek açıklama eklemeyi düşünün veya bir işlev çağırıyorsanız bir boşluk ekleyin, örn. “expr1 [expr2]”. diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf index 589fc4eac1a..8dce1744238 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf @@ -1527,6 +1527,11 @@ Expected unit-of-measure type parameter must be marked with the [<Measure>] attribute. + + Generic attribute types are not supported in F#. The type '{0}' has type parameters and cannot be used as an attribute. + Generic attribute types are not supported in F#. The type '{0}' has type parameters and cannot be used as an attribute. + + The syntax 'expr1[expr2]' is used for indexing. Consider adding a type annotation to enable indexing, or if calling a function add a space, e.g. 'expr1 [expr2]'. 语法“expr1[expr2]”用于索引。考虑添加类型批注来启用索引,或者在调用函数添加空格,例如“expr1 [expr2]”。 diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf index e3f84137cdb..919e332bb06 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf @@ -1527,6 +1527,11 @@ Expected unit-of-measure type parameter must be marked with the [<Measure>] attribute. + + Generic attribute types are not supported in F#. The type '{0}' has type parameters and cannot be used as an attribute. + Generic attribute types are not supported in F#. The type '{0}' has type parameters and cannot be used as an attribute. + + The syntax 'expr1[expr2]' is used for indexing. Consider adding a type annotation to enable indexing, or if calling a function add a space, e.g. 'expr1 [expr2]'. 語法 'expr1[expr2]' 已用於編製索引。請考慮新增類型註釋來啟用編製索引,或是呼叫函式並新增空格,例如 'expr1 [expr2]'。 diff --git a/tests/FSharp.Compiler.ComponentTests/Attributes/GenericAttributeAbbreviations.fs b/tests/FSharp.Compiler.ComponentTests/Attributes/GenericAttributeAbbreviations.fs new file mode 100644 index 00000000000..4b303792554 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Attributes/GenericAttributeAbbreviations.fs @@ -0,0 +1,98 @@ +namespace FSharp.Compiler.ComponentTests.Attributes + +open Xunit +open FSharp.Test.Compiler + +module GenericAttributeAbbreviations = + + // Repro from https://github.com/dotnet/fsharp/issues/7877. + // A type abbreviation of a generic attribute type must not crash with + // FS0193 "The lists had different lengths" - it must report FS3891. + [] + let ``Type abbreviation of generic attribute reports FS3891 instead of crashing`` () = + Fsx """ +type A<'T>() = inherit System.Attribute() +type B = A +[] type C = class end +""" + |> compile + |> shouldFail + |> withSingleDiagnostic (Error 3891, Line 4, Col 3, Line 4, Col 4, "Generic attribute types are not supported in F#. The type 'A' has type parameters and cannot be used as an attribute.") + |> ignore + + [] + [")>] + [")>] + [")>] + [>")>] + let ``Generic attribute abbreviation variants all report FS3891`` (abbrev: string) = + Fsx (sprintf """ +type A<'T>() = inherit System.Attribute() +%s +[] type C = class end +""" abbrev) + |> compile + |> shouldFail + |> withErrorCode 3891 + |> ignore + + [] + let ``Two-parameter generic attribute abbreviation reports FS3891`` () = + Fsx """ +type A2<'T, 'U>() = inherit System.Attribute() +type B = A2 +[] type C = class end +""" + |> compile + |> shouldFail + |> withErrorCode 3891 + |> ignore + + [] + let ``Chained abbreviation through a generic attribute reports FS3891`` () = + Fsx """ +type A<'T>() = inherit System.Attribute() +type B = A +type C2 = B +[] type D = class end +""" + |> compile + |> shouldFail + |> withErrorCode 3891 + |> ignore + + // Non-regression: a non-generic attribute abbreviation must still compile. + [] + let ``Non-generic attribute abbreviation is unchanged`` () = + Fsx """ +type A() = inherit System.Attribute() +type B = A +[] type C = class end +""" + |> compile + |> shouldSucceed + |> ignore + + // Non-regression: built-in attribute abbreviated and used should compile. + [] + let ``Abbreviation of non-generic System attribute compiles`` () = + Fsx """ +type MyObsolete = System.ObsoleteAttribute +[] +let foo () = () +""" + |> compile + |> shouldSucceed + |> ignore + + // Non-regression: the direct `[>]` syntax is rejected by the parser, + // not by the new check. Behavior here must not change. + [] + let ``Direct generic attribute syntax remains a parse-level rejection`` () = + Fsx """ +type A<'T>() = inherit System.Attribute() +[>] type C = class end +""" + |> compile + |> shouldFail + |> ignore diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj index 02f6ff6b621..962871768cc 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj +++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj @@ -520,6 +520,7 @@ + From fd6ed49fd083fae8b9a2bdbcac726c5f9adb8552 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Tue, 28 Jul 2026 20:12:57 +0200 Subject: [PATCH 19/33] Move to .NET 11 (SDK, Arcade, product TargetFramework) (#20080) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Upgrade the repo to build on .NET 11 and target net11.0, plus the adaptations the SDK/Arcade 11 bump forces. Core version switch: - global.json: sdk.version 11.0.100-preview.6.26359.118 with rollForward=latestMinor + allowPrerelease (newer local 11.x still wins). A 2-part "11.0" is not a valid concrete SDK version, so the muxer fell back to $host$ and the end-to-end tests built with the machine net10 SDK (NETSDK1045); a concrete version resolves .dotnet's net11 SDK. Arcade.Sdk 11.0.0-beta.26369.1. - eng/TargetFrameworks.props: FSharpNetCoreProductTargetFramework net11.0. - eng/Version.Details.xml + eng/Version.Details.props: Arcade.Sdk 11.0.0-beta.26369.1 (+Sha) — the value Maestro flows from dotnet/arcade onto the net11 channel, not a hand-picked one. - eng/Versions.props: MicrosoftTestPlatformVersion 18.0.1 (net11 SDK bundles vstest 18.x; Microsoft.TestPlatform.ObjectModel must track that generation). - eng/common: regenerated to Arcade 11 (26369.1). Arcade-11 / SDK adaptations: - Microsoft.FSharp.Compiler.fsproj: NuGetRepack property casing, drop the obsolete UsingTask, add no-op PackageReleasePackages override (#19557). - fsi.fsproj: PublishReadyToRun=false (crossgen2 preview crashes on fsi). - tests/Directory.Build.props: mark .ComponentTests IsTestProject (excludes from SymStore PDB conversion that crashes on large test assemblies). - FSharp.DependencyManager.ProjectFile.fs: resolve framework-provided assemblies (Microsoft.Extensions.* now in the shared framework) for FSI #r "nuget:"; RestoreEnablePackagePruning=false. - regression-test-jobs.yml: install the compiler SDK into the TestRepo. net11 test-behavior: - EditorTests.fs: RegexOptions.AnyNewLine (2048) under NET11_0_OR_GREATER. - CompilerAssert.fs: derive runtimeconfig runtime version from FrameworkDescription + rollForward LatestMinor (preview is semver-lower). - ILChecker.fs: normalize System.Linq assembly extern (version-independent). - DependencyManagerInteractiveTests.fs: on net11 Microsoft.Extensions.* are shared-framework, so #r "nuget:" resolves the ref-pack path and one root. - ilverify.ps1: map versioned netN.0 baselines to generic netcoreapp; rename the two FSharp.Compiler.Service baselines accordingly. - EndToEndBuildTests: MicrosoftTestPlatformVersion 18.0.1. Validated: ./build.sh -c Release green (0/0); EmittedIL 1413 pass/0 fail; EditorTests AnyNewLine pass; DependencyManager nuget-roots test pass; ilverify FCS net11.0 exact-matches baseline. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .github/skills/pr-description/SKILL.md | 12 +- eng/TargetFrameworks.props | 2 +- eng/Version.Details.props | 2 +- eng/Version.Details.xml | 4 +- eng/Versions.props | 2 +- eng/common/AGENTS.md | 5 + eng/common/SetupNugetSources.ps1 | 28 +- eng/common/SetupNugetSources.sh | 22 +- eng/common/build.ps1 | 30 +- eng/common/build.sh | 39 +- .../core-templates/job/helix-job-monitor.yml | 235 ++++++++ eng/common/core-templates/job/job.yml | 14 + eng/common/core-templates/job/onelocbuild.yml | 3 + .../job/publish-build-assets.yml | 12 +- eng/common/core-templates/job/renovate.yml | 196 +++++++ .../job/source-index-stage1.yml | 6 +- .../core-templates/jobs/codeql-build.yml | 32 -- .../post-build/common-variables.yml | 2 - .../core-templates/post-build/post-build.yml | 518 ++++++++---------- eng/common/core-templates/stages/renovate.yml | 111 ++++ .../steps/enable-internal-sources.yml | 24 + .../steps/install-microbuild-impl.yml | 34 ++ .../steps/install-microbuild.yml | 64 ++- .../core-templates/steps/publish-logs.yml | 2 +- .../core-templates/steps/send-to-helix.yml | 22 +- .../core-templates/steps/source-build.yml | 2 +- .../steps/source-index-stage1-publish.yml | 12 +- eng/common/cross/build-rootfs.sh | 57 +- eng/common/cross/toolchain.cmake | 5 +- eng/common/darc-init.sh | 2 +- eng/common/dotnet-install.ps1 | 9 +- eng/common/dotnet-install.sh | 15 +- eng/common/dotnet.sh | 2 +- eng/common/internal-feed-operations.sh | 2 +- eng/common/msbuild.ps1 | 6 +- eng/common/msbuild.sh | 6 +- eng/common/native/NativeAotSupported.props | 2 + eng/common/native/init-os-and-arch.sh | 6 +- eng/common/pipeline-logging-functions.ps1 | 2 +- eng/common/post-build/redact-logs.ps1 | 3 +- .../post-build/sourcelink-validation.ps1 | 327 ----------- eng/common/renovate.env | 42 ++ eng/common/sdk-task.ps1 | 34 +- eng/common/sdk-task.sh | 24 +- eng/common/sdl/NuGet.config | 18 - eng/common/sdl/configure-sdl-tool.ps1 | 130 ----- eng/common/sdl/execute-all-sdl-tools.ps1 | 167 ------ eng/common/sdl/extract-artifact-archives.ps1 | 63 --- eng/common/sdl/extract-artifact-packages.ps1 | 82 --- eng/common/sdl/init-sdl.ps1 | 55 -- eng/common/sdl/packages.config | 4 - eng/common/sdl/run-sdl.ps1 | 49 -- eng/common/sdl/sdl.ps1 | 38 -- eng/common/sdl/trim-assets-version.ps1 | 75 --- eng/common/template-guidance.md | 3 - .../templates-official/jobs/codeql-build.yml | 7 - .../variables/sdl-variables.yml | 7 - eng/common/templates/job/job.yml | 5 - eng/common/templates/jobs/codeql-build.yml | 7 - eng/common/tools.ps1 | 368 +++++++------ eng/common/tools.sh | 204 +++++-- eng/templates/regression-test-jobs.yml | 22 + global.json | 7 +- .../FSharp.DependencyManager.ProjectFile.fs | 15 + .../Microsoft.FSharp.Compiler.fsproj | 12 +- src/fsi/fsiProject/fsi.fsproj | 3 +- tests/Directory.Build.props | 4 + .../EndToEndBuildTests/Directory.Build.props | 2 +- .../DependencyManagerInteractiveTests.fs | 10 +- .../EditorTests.fs | 3 + tests/FSharp.Test.Utilities/CompilerAssert.fs | 9 +- tests/FSharp.Test.Utilities/ILChecker.fs | 3 +- tests/ILVerify/ilverify.ps1 | 5 +- ...arp.Compiler.Service_Debug_netcoreapp.bsl} | 0 ...p.Compiler.Service_Release_netcoreapp.bsl} | 0 75 files changed, 1594 insertions(+), 1762 deletions(-) create mode 100644 eng/common/AGENTS.md create mode 100644 eng/common/core-templates/job/helix-job-monitor.yml create mode 100644 eng/common/core-templates/job/renovate.yml delete mode 100644 eng/common/core-templates/jobs/codeql-build.yml create mode 100644 eng/common/core-templates/stages/renovate.yml create mode 100644 eng/common/core-templates/steps/install-microbuild-impl.yml delete mode 100644 eng/common/post-build/sourcelink-validation.ps1 create mode 100644 eng/common/renovate.env delete mode 100644 eng/common/sdl/NuGet.config delete mode 100644 eng/common/sdl/configure-sdl-tool.ps1 delete mode 100644 eng/common/sdl/execute-all-sdl-tools.ps1 delete mode 100644 eng/common/sdl/extract-artifact-archives.ps1 delete mode 100644 eng/common/sdl/extract-artifact-packages.ps1 delete mode 100644 eng/common/sdl/init-sdl.ps1 delete mode 100644 eng/common/sdl/packages.config delete mode 100644 eng/common/sdl/run-sdl.ps1 delete mode 100644 eng/common/sdl/sdl.ps1 delete mode 100644 eng/common/sdl/trim-assets-version.ps1 delete mode 100644 eng/common/templates-official/jobs/codeql-build.yml delete mode 100644 eng/common/templates-official/variables/sdl-variables.yml delete mode 100644 eng/common/templates/jobs/codeql-build.yml rename tests/ILVerify/{ilverify_FSharp.Compiler.Service_Debug_net10.0.bsl => ilverify_FSharp.Compiler.Service_Debug_netcoreapp.bsl} (100%) rename tests/ILVerify/{ilverify_FSharp.Compiler.Service_Release_net10.0.bsl => ilverify_FSharp.Compiler.Service_Release_netcoreapp.bsl} (100%) diff --git a/.github/skills/pr-description/SKILL.md b/.github/skills/pr-description/SKILL.md index 9cd0918015e..41b7833a45b 100644 --- a/.github/skills/pr-description/SKILL.md +++ b/.github/skills/pr-description/SKILL.md @@ -9,13 +9,14 @@ Reviewers can already see the Files tab, the commit log, and the issue thread. S ## Rules -Rules 1, 2, 4, 5 are defaults; if the user insists, push back once then comply. Rule 3 is non-negotiable — `-b "..."` ships broken markdown (see PR #19866). +Rules 1, 2, 4, 5, 6 are defaults; if the user insists, push back once then comply. Rule 3 is non-negotiable — `-b "..."` ships broken markdown (see PR #19866). 1. **No change inventory.** No file/module/method/test lists. No `## Changes`/`## Implementation` section. Mention an identifier only when it *is* the user-visible behavior. Whatever the reader already has (Files tab for PRs, commit log for follow-up comments, issue history for issue edits) — don't re-list it. 2. **No LLM slop, no justification scaffolding.** No emoji headers, no "TL;DR" above a 3-line body, no Motivation/Background/Approach/Testing sections, no re-stating the title or the comment you're replying to. No "matching the X norm", no "preventing the Y failure (PR #ZZZZ)", no stats, no links to past PRs as proof. The diff is the proof. 3. **Body via `--body-file`, built without shell expansion.** Write the file with your file-creation/edit tool (it writes bytes verbatim — no `$`/backtick evaluation, no delimiter collisions, OS-agnostic). Never `-b "..."` / `--body "..."` — backticks and `$` get shell-evaluated and the render breaks. If you build the file in a shell, use a pwsh verbatim here-string `@'...'@` (cross-platform; single-quoted is mandatory). Applies to `gh pr create/edit/comment/review`, `gh issue create/edit/comment`. 4. **`Fixes #N` to close issues.** Use only when the PR actually closes #N (auto-closes on merge). It is the highest-value line in most PR bodies — never omit it when valid. No "Related to" / speculative links. Preserve existing trailers (`Co-authored-by:`, `Signed-off-by:`, `Reverts #N`); don't invent them. 5. **Title:** imperative, ≤72 chars, no trailing period, no `fix:`/`feat:` prefix. Name the behavior, not the file. A specific title lets the body shrink to `Fixes #N` + one sentence. +6. **No hard-wrapped prose.** Write each paragraph as one unbroken line and let GitHub's renderer wrap it — blank lines separate paragraphs, and that's the only break you author. Manual mid-sentence line breaks (wrapping at a fixed column) are a machine tell and render raggedly across window widths. ## PR-body shapes (pick the smallest that carries the signal) @@ -28,16 +29,14 @@ Update .NET SDK from 10.0.202 to 10.0.204. ~~~ Fixes #18009 -Wrong colorization when a qualified type name with generic parameters -is used in a static member access expression. +Wrong colorization when a qualified type name with generic parameters is used in a static member access expression. ~~~ **Issue link + 1-sentence why** — the most common non-trivial shape: ~~~ Fixes #19751 -`--refout` MVIDs were unstable because hashing relied on per-process -string randomization. Switched to a deterministic hash. +`--refout` MVIDs were unstable because hashing relied on per-process string randomization. Switched to a deterministic hash. ~~~ **Before/After code block** — when prose loses information; ≤15 lines, language tag: @@ -73,8 +72,7 @@ Show the title + body (or comment text) in chat first. **Do not run `gh` until t ```powershell @' - Fix false-positive FS3261 when nullness narrowing leaks across iterations - of seq/list/array comprehensions. + Fix false-positive FS3261 when nullness narrowing leaks across iterations of seq/list/array comprehensions. Fixes #19644 '@ | Set-Content -NoNewline pr-body.md diff --git a/eng/TargetFrameworks.props b/eng/TargetFrameworks.props index d384e5fbcaa..e3938d0f73a 100644 --- a/eng/TargetFrameworks.props +++ b/eng/TargetFrameworks.props @@ -11,7 +11,7 @@ - net10.0 + net11.0 $([System.Text.RegularExpressions.Regex]::Replace('$(FSharpNetCoreProductTargetFramework)', '^net(\d+)\.0$', '$1')) diff --git a/eng/Version.Details.props b/eng/Version.Details.props index 43bc8e6d8e0..775ff7a16c2 100644 --- a/eng/Version.Details.props +++ b/eng/Version.Details.props @@ -6,7 +6,7 @@ This file should be imported by eng/Versions.props - 10.0.0-beta.26371.2 + 11.0.0-beta.26369.1 18.10.0-1.26370.18 18.10.0-1.26370.18 diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index b00667f5028..9dadf91aba4 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -82,9 +82,9 @@ - + https://github.com/dotnet/arcade - c38c50f518aac7fac47ca488c42c7176d40e695c + 09bc8c946f4c4ae5d031c8875b85a6b8f1876b93 https://dev.azure.com/dnceng/internal/_git/dotnet-optimization diff --git a/eng/Versions.props b/eng/Versions.props index 8f756067e4d..b22e821a2de 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -176,7 +176,7 @@ 5.0.0-preview.7.20364.11 5.0.0-preview.7.20364.11 - 17.14.1 + 18.0.1 2.0.2 13.0.4 3.2.2 diff --git a/eng/common/AGENTS.md b/eng/common/AGENTS.md new file mode 100644 index 00000000000..a5ed8f72926 --- /dev/null +++ b/eng/common/AGENTS.md @@ -0,0 +1,5 @@ +# `eng/common` + +Files under `eng/common` come from [Arcade](https://github.com/dotnet/arcade). +Edits in `eng/common` will be overwritten by automation unless the changes are made directly in the Arcade repository. +For more information, see the [Arcade documentation](https://github.com/dotnet/arcade/tree/main/Documentation). diff --git a/eng/common/SetupNugetSources.ps1 b/eng/common/SetupNugetSources.ps1 index 65ed3a8adef..b3bddff355e 100644 --- a/eng/common/SetupNugetSources.ps1 +++ b/eng/common/SetupNugetSources.ps1 @@ -1,7 +1,6 @@ # This script adds internal feeds required to build commits that depend on internal package sources. For instance, -# dotnet6-internal would be added automatically if dotnet6 was found in the nuget.config file. Similarly, -# dotnet-eng-internal and dotnet-tools-internal are added if dotnet-eng and dotnet-tools are present. -# In addition, this script also enables disabled internal Maestro (darc-int*) feeds. +# dotnet6-internal would be added automatically if dotnet6 was found in the nuget.config file. In addition also enables +# disabled internal Maestro (darc-int*) feeds. # # Optionally, this script also adds a credential entry for each of the internal feeds if supplied. # @@ -14,7 +13,11 @@ # filePath: $(System.DefaultWorkingDirectory)/eng/common/SetupNugetSources.ps1 # arguments: -ConfigFile $(System.DefaultWorkingDirectory)/NuGet.config -Password $Env:Token # env: -# Token: $(dn-bot-dnceng-artifact-feeds-rw) +# Token: $(InternalFeedToken) +# +# Note: This logic is abstracted into enable-internal-sources.yml, which uses +# NuGetAuthenticate or a WIF-backed service connection. Prefer that template +# over calling this script directly. # # Note that the NuGetAuthenticate task should be called after SetupNugetSources. # This ensures that: @@ -33,6 +36,11 @@ $ErrorActionPreference = "Stop" Set-StrictMode -Version 2.0 [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +# This script only consumes helper functions from tools.ps1 to configure NuGet feeds. +# Skip importing configure-toolset.ps1 so that repo-specific toolset setup (e.g. acquiring +# a bootstrap SDK) is not triggered as a side effect of feed configuration. +$disableConfigureToolsetImport = $true + . $PSScriptRoot\tools.ps1 # Adds or enables the package source with the given name @@ -174,16 +182,4 @@ foreach ($dotnetVersion in $dotnetVersions) { } } -# Check for dotnet-eng and add dotnet-eng-internal if present -$dotnetEngSource = $sources.SelectSingleNode("add[@key='dotnet-eng']") -if ($dotnetEngSource -ne $null) { - AddOrEnablePackageSource -Sources $sources -DisabledPackageSources $disabledSources -SourceName "dotnet-eng-internal" -SourceEndPoint "https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet-eng-internal/nuget/$feedSuffix" -Creds $creds -Username $userName -pwd $Password -} - -# Check for dotnet-tools and add dotnet-tools-internal if present -$dotnetToolsSource = $sources.SelectSingleNode("add[@key='dotnet-tools']") -if ($dotnetToolsSource -ne $null) { - AddOrEnablePackageSource -Sources $sources -DisabledPackageSources $disabledSources -SourceName "dotnet-tools-internal" -SourceEndPoint "https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet-tools-internal/nuget/$feedSuffix" -Creds $creds -Username $userName -pwd $Password -} - $doc.Save($filename) diff --git a/eng/common/SetupNugetSources.sh b/eng/common/SetupNugetSources.sh index b2163abbe71..67e7e0942ca 100755 --- a/eng/common/SetupNugetSources.sh +++ b/eng/common/SetupNugetSources.sh @@ -1,9 +1,8 @@ #!/usr/bin/env bash # This script adds internal feeds required to build commits that depend on internal package sources. For instance, -# dotnet6-internal would be added automatically if dotnet6 was found in the nuget.config file. Similarly, -# dotnet-eng-internal and dotnet-tools-internal are added if dotnet-eng and dotnet-tools are present. -# In addition, this script also enables disabled internal Maestro (darc-int*) feeds. +# dotnet6-internal would be added automatically if dotnet6 was found in the nuget.config file. In addition also enables +# disabled internal Maestro (darc-int*) feeds. # # Optionally, this script also adds a credential entry for each of the internal feeds if supplied. # @@ -41,6 +40,11 @@ while [[ -h "$source" ]]; do done scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" +# This script only consumes helper functions from tools.sh to configure NuGet feeds. +# Skip importing configure-toolset.sh so that repo-specific toolset setup (e.g. acquiring +# a bootstrap SDK) is not triggered as a side effect of feed configuration. +disable_configure_toolset_import=1 + . "$scriptroot/tools.sh" if [ ! -f "$ConfigFile" ]; then @@ -174,18 +178,6 @@ for DotNetVersion in ${DotNetVersions[@]} ; do fi done -# Check for dotnet-eng and add dotnet-eng-internal if present -grep -i " /dev/null -if [ "$?" == "0" ]; then - AddOrEnablePackageSource "dotnet-eng-internal" "https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet-eng-internal/nuget/$FeedSuffix" -fi - -# Check for dotnet-tools and add dotnet-tools-internal if present -grep -i " /dev/null -if [ "$?" == "0" ]; then - AddOrEnablePackageSource "dotnet-tools-internal" "https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet-tools-internal/nuget/$FeedSuffix" -fi - # I want things split line by line PrevIFS=$IFS IFS=$'\n' diff --git a/eng/common/build.ps1 b/eng/common/build.ps1 index 8cfee107e7a..dd84699f500 100644 --- a/eng/common/build.ps1 +++ b/eng/common/build.ps1 @@ -6,6 +6,7 @@ Param( [string][Alias('v')]$verbosity = "minimal", [string] $msbuildEngine = $null, [bool] $warnAsError = $true, + [string] $warnNotAsError = '', [bool] $nodeReuse = $true, [switch] $buildCheck = $false, [switch][Alias('r')]$restore, @@ -22,7 +23,9 @@ Param( [switch] $clean, [switch][Alias('pb')]$productBuild, [switch]$fromVMR, + [switch]$disablePipelineSetResult, [switch][Alias('bl')]$binaryLog, + [string][Alias('bln')]$binaryLogName = '', [switch][Alias('nobl')]$excludeCIBinarylog, [switch] $ci, [switch] $prepareMachine, @@ -45,6 +48,7 @@ function Print-Usage() { Write-Host " -platform Platform configuration: 'x86', 'x64' or any valid Platform value to pass to msbuild" Write-Host " -verbosity Msbuild verbosity: q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic] (short: -v)" Write-Host " -binaryLog Output binary log (short: -bl)" + Write-Host " -binaryLogName Binary log file name or path; implies -binaryLog (short: -bln)" Write-Host " -help Print help and exit" Write-Host "" @@ -70,12 +74,14 @@ function Print-Usage() { Write-Host " -excludeCIBinarylog Don't output binary log (short: -nobl)" Write-Host " -prepareMachine Prepare machine for CI run, clean up processes after build" Write-Host " -warnAsError Sets warnaserror msbuild parameter ('true' or 'false')" + Write-Host " -warnNotAsError Sets a semi-colon delimited list of warning codes that should not be treated as errors" Write-Host " -msbuildEngine Msbuild engine to use to run build ('dotnet', 'vs', or unspecified)." Write-Host " -excludePrereleaseVS Set to exclude build engines in prerelease versions of Visual Studio" Write-Host " -nativeToolsOnMachine Sets the native tools on machine environment variable (indicating that the script should use native tools on machine)" Write-Host " -nodeReuse Sets nodereuse msbuild parameter ('true' or 'false')" Write-Host " -buildCheck Sets /check msbuild parameter" Write-Host " -fromVMR Set when building from within the VMR" + Write-Host " -disablePipelineSetResult Set to disable masking the actual exit code in the pipeline when the build fails" Write-Host "" Write-Host "Command line arguments not listed above are passed thru to msbuild." @@ -100,7 +106,19 @@ function Build { $toolsetBuildProj = InitializeToolset InitializeCustomToolset - $bl = if ($binaryLog) { '/bl:' + (Join-Path $LogDir 'Build.binlog') } else { '' } + $bl = '' + if ($binaryLog) { + $binaryLogPath = if ([string]::IsNullOrEmpty($binaryLogName)) { + Join-Path $LogDir 'Build.binlog' + } elseif ([System.IO.Path]::IsPathRooted($binaryLogName)) { + $binaryLogName + } else { + Join-Path $LogDir $binaryLogName + } + + Create-Directory (Split-Path -Parent $binaryLogPath) + $bl = '/bl:' + $binaryLogPath + } $platformArg = if ($platform) { "/p:Platform=$platform" } else { '' } $check = if ($buildCheck) { '/check' } else { '' } @@ -157,7 +175,15 @@ try { if (-not $excludeCIBinarylog) { $binaryLog = $true } - $nodeReuse = $false + # Disable node reuse on CI unless explicitly opted in via MSBUILD_NODEREUSE_ENABLED. + # Internal testing only; this env var will be replaced with a switch (https://github.com/dotnet/arcade/issues/17013) and must not be depended on. + if ($env:MSBUILD_NODEREUSE_ENABLED -ne "1") { + $nodeReuse = $false + } + } + + if (-not [string]::IsNullOrEmpty($binaryLogName)) { + $binaryLog = $true } if ($nativeToolsOnMachine) { diff --git a/eng/common/build.sh b/eng/common/build.sh index 9767bb411a4..e37edd6cff3 100755 --- a/eng/common/build.sh +++ b/eng/common/build.sh @@ -13,6 +13,7 @@ usage() echo " --configuration Build configuration: 'Debug' or 'Release' (short: -c)" echo " --verbosity Msbuild verbosity: q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic] (short: -v)" echo " --binaryLog Create MSBuild binary log (short: -bl)" + echo " --binaryLogName Binary log file name or path; implies --binaryLog (short: -bln)" echo " --help Print help and exit (short: -h)" echo "" @@ -39,11 +40,14 @@ usage() echo " --projects Project or solution file(s) to build" echo " --ci Set when running on CI server" echo " --excludeCIBinarylog Don't output binary log (short: -nobl)" + echo " --pipelinesLog Promote msbuild errors/warnings to Azure Pipelines timeline issues; defaults to on in CI (short: -pl)" echo " --prepareMachine Prepare machine for CI run, clean up processes after build" echo " --nodeReuse Sets nodereuse msbuild parameter ('true' or 'false')" echo " --warnAsError Sets warnaserror msbuild parameter ('true' or 'false')" + echo " --warnNotAsError Sets a semi-colon delimited list of warning codes that should not be treated as errors" echo " --buildCheck Sets /check msbuild parameter" echo " --fromVMR Set when building from within the VMR" + echo " --disablePipelineSetResult Set to disable masking the actual exit code in the pipeline when the build fails" echo "" echo "Command line arguments not listed above are passed thru to msbuild." echo "Arguments can also be passed in with a single hyphen." @@ -66,6 +70,7 @@ build=false source_build=false product_build=false from_vmr=false +disable_pipeline_set_result=false rebuild=false test=false integration_test=false @@ -78,9 +83,11 @@ ci=false clean=false warn_as_error=true +warn_not_as_error='' node_reuse=true build_check=false binary_log=false +binary_log_name='' exclude_ci_binary_log=false pipelines_log=false @@ -92,7 +99,7 @@ runtime_source_feed='' runtime_source_feed_key='' properties=() -while [[ $# > 0 ]]; do +while [[ $# -gt 0 ]]; do opt="$(echo "${1/#--/-}" | tr "[:upper:]" "[:lower:]")" case "$opt" in -help|-h) @@ -113,6 +120,11 @@ while [[ $# > 0 ]]; do -binarylog|-bl) binary_log=true ;; + -binarylogname|-bln) + binary_log=true + binary_log_name=$2 + shift + ;; -excludecibinarylog|-nobl) exclude_ci_binary_log=true ;; @@ -147,6 +159,9 @@ while [[ $# > 0 ]]; do -fromvmr|-from-vmr) from_vmr=true ;; + -disablepipelinesetresult|-disable-pipeline-set-result) + disable_pipeline_set_result=true + ;; -test|-t) test=true ;; @@ -176,6 +191,10 @@ while [[ $# > 0 ]]; do warn_as_error=$2 shift ;; + -warnnotaserror) + warn_not_as_error=$2 + shift + ;; -nodereuse) node_reuse=$2 shift @@ -205,7 +224,11 @@ fi if [[ "$ci" == true ]]; then pipelines_log=true - node_reuse=false + # Disable node reuse on CI unless explicitly opted in via MSBUILD_NODEREUSE_ENABLED. + # Internal testing only; this env var will be replaced with a switch (https://github.com/dotnet/arcade/issues/17013) and must not be depended on. + if [[ "${MSBUILD_NODEREUSE_ENABLED:-}" != "1" ]]; then + node_reuse=false + fi if [[ "$exclude_ci_binary_log" == false ]]; then binary_log=true fi @@ -231,7 +254,17 @@ function Build { local bl="" if [[ "$binary_log" == true ]]; then - bl="/bl:\"$log_dir/Build.binlog\"" + local binary_log_path="" + if [[ -z "$binary_log_name" ]]; then + binary_log_path="$log_dir/Build.binlog" + elif [[ "$binary_log_name" = /* ]]; then + binary_log_path="$binary_log_name" + else + binary_log_path="$log_dir/$binary_log_name" + fi + + mkdir -p "$(dirname "$binary_log_path")" + bl="/bl:\"$binary_log_path\"" fi local check="" diff --git a/eng/common/core-templates/job/helix-job-monitor.yml b/eng/common/core-templates/job/helix-job-monitor.yml new file mode 100644 index 00000000000..0da13cf69db --- /dev/null +++ b/eng/common/core-templates/job/helix-job-monitor.yml @@ -0,0 +1,235 @@ +parameters: +# Maximum run time of the monitor job in minutes. Also used for --max-wait-minutes. +- name: timeoutInMinutes + type: number + default: 360 + +# Owner segment of the source repository (e.g. 'dotnet' for 'dotnet/runtime') passed via --organization. +# Defaults to the owner segment of BUILD_REPOSITORY_NAME when empty. +- name: organization + type: string + default: '' + +# Name of the source repository (e.g. 'runtime' for 'dotnet/runtime') passed via --repository. +# Defaults to the repo segment of BUILD_REPOSITORY_NAME when empty. +- name: repository + type: string + default: '' + +# Optional dependency list for the generated job. +- name: dependsOn + type: object + default: [] + +# Optional condition for the generated job. +- name: condition + type: string + default: '' + +# NuGet package id of the Helix job monitor tool. +- name: toolPackageId + type: string + default: Microsoft.DotNet.Helix.JobMonitor + +# Console command exposed by the installed tool package. +- name: toolCommand + type: string + default: dotnet-helix-job-monitor + +# Optional explicit tool version. Only honored when 'toolNupkgArtifactName' is set; in the +# default code path the version is taken from the consuming repo's .config/dotnet-tools.json. +- name: toolVersion + type: string + default: '' + +# Base URI for the Helix service (--helix-base-uri). +- name: helixBaseUri + type: string + default: https://helix.dot.net/ + +# Helix API access token forwarded to the tool via the HELIX_ACCESSTOKEN environment variable. +- name: helixAccessToken + type: string + default: '' + +# Polling interval in seconds (--polling-interval-seconds). +- name: pollingIntervalSeconds + type: number + default: 30 + +# When 'true' (the default), Helix work items that exit 0 but have failed AzDO test results +# are treated as failed: they count toward the monitor's exit code and are resubmitted by a +# later invocation's retry pass. Set to 'false' to fall back to exit-code-only outcomes. +# Forwarded as --fail-on-failed-tests. +- name: failWorkItemsWithFailedTests + type: boolean + default: true + +# When true, test results are reported to Azure DevOps using the fully qualified test name +# (Namespace.Type.Method) as the stable automatedTestName and the visible title is qualified as +# well (--use-fully-qualified-test-name). Opt-in because it changes AzDO test identity and display; +# primarily useful for frameworks like MSTest whose display name is only the method name. +- name: useFullyQualifiedTestName + type: boolean + default: false + +# Advanced: optional pipeline artifact (produced earlier in this run) that contains the tool +# nupkg. When set, the artifact is downloaded and the tool is installed from the nupkg into +# a local tool-path; this bypasses the repo's .config/dotnet-tools.json manifest and is +# primarily intended for the Arcade repository itself, where the Helix job monitor tool is +# built in the same pipeline that runs this template. +# +# When this parameter is empty (the default), the consuming repository must declare the tool +# in its .config/dotnet-tools.json manifest (alongside other local .NET tools); the template +# will check out the repo and run 'dotnet tool restore' to install the version pinned there. +- name: toolNupkgArtifactName + type: string + default: '' + +# Advanced: sub-path within the downloaded artifact where the tool nupkg is located. Defaults +# to the standard Arcade non-shipping packages location for a Release build (relative to the +# pipeline artifact root, which is itself the build's 'artifacts' directory). +- name: toolNupkgArtifactSubPath + type: string + default: 'packages/Release/NonShipping' + +jobs: +- job: HelixJobMonitor + displayName: Monitor Helix Jobs + timeoutInMinutes: ${{ parameters.timeoutInMinutes }} + ${{ if ne(length(parameters.dependsOn), 0) }}: + dependsOn: ${{ parameters.dependsOn }} + ${{ if ne(parameters.condition, '') }}: + condition: ${{ parameters.condition }} + pool: + ${{ if eq(variables['System.TeamProject'], 'public') }}: + name: $(DncEngPublicBuildPool) + demands: ImageOverride -equals build.azurelinux.3.amd64.open + ${{ else }}: + name: $(DncEngInternalBuildPool) + demands: ImageOverride -equals build.azurelinux.3.amd64 + steps: + - checkout: self + fetchDepth: 1 + + - ${{ if ne(parameters.toolNupkgArtifactName, '') }}: + - task: DownloadPipelineArtifact@2 + displayName: Download Helix Job Monitor artifact + inputs: + buildType: current + artifactName: ${{ parameters.toolNupkgArtifactName }} + itemPattern: '${{ parameters.toolNupkgArtifactSubPath }}/${{ parameters.toolPackageId }}.*.nupkg' + targetPath: $(Agent.TempDirectory)/helix-job-monitor-nupkg + + - bash: | + set -euo pipefail + + toolPath="$AGENT_TEMPDIRECTORY/helix-job-monitor-tool" + mkdir -p "$toolPath" + + packageId='${{ parameters.toolPackageId }}' + toolVersion='${{ parameters.toolVersion }}' + nupkgArtifactSubPath='${{ parameters.toolNupkgArtifactSubPath }}' + nupkgDir="$AGENT_TEMPDIRECTORY/helix-job-monitor-nupkg/$nupkgArtifactSubPath" + + if [ ! -d "$nupkgDir" ]; then + echo "Expected nupkg directory '$nupkgDir' was not produced by the artifact download." >&2 + exit 1 + fi + + nupkg=$(find "$nupkgDir" -maxdepth 1 -type f -name "$packageId.*.nupkg" | head -n 1) + if [ -z "$nupkg" ]; then + echo "No '$packageId.*.nupkg' found in '$nupkgDir'." >&2 + exit 1 + fi + + # Derive the version from the nupkg filename so the local package is selected + # deterministically instead of resolving against any other configured feed. + nupkgBase=$(basename "$nupkg" .nupkg) + derivedVersion="${nupkgBase#${packageId}.}" + if [ -z "$toolVersion" ]; then + toolVersion="$derivedVersion" + fi + + echo "Using locally built '$packageId' version '$toolVersion' from '$nupkgDir'." + + # Create a minimal NuGet.config that only references the local nupkg directory. + # This avoids conflicts with the repo's package source mapping which blocks --add-source. + toolNugetConfig="$AGENT_TEMPDIRECTORY/helix-job-monitor-nuget.config" + printf '\n\n \n \n \n \n\n' "$nupkgDir" > "$toolNugetConfig" + + pushd "$(Build.SourcesDirectory)" > /dev/null + ./eng/common/dotnet.sh tool install \ + --tool-path "$toolPath" "$packageId" \ + --version "$toolVersion" \ + --configfile "$toolNugetConfig" + + # Locate the tool DLL so the run step can invoke it via ./eng/common/dotnet.sh exec. + toolDll=$(find "$toolPath/.store" -path '*/tools/*/any/*.deps.json' -type f | head -n 1) + toolDll="${toolDll%.deps.json}.dll" + if [ ! -f "$toolDll" ]; then + echo "Could not find tool DLL in '$toolPath/.store'." >&2 + exit 1 + fi + + echo "Tool DLL: $toolDll" + echo "##vso[task.setvariable variable=HelixJobMonitorDll]$toolDll" + displayName: Install Helix Job Monitor + + - ${{ else }}: + - bash: ./eng/common/dotnet.sh tool restore + displayName: Restore Helix Job Monitor + + - bash: | + set -euo pipefail + + toolArgs=( + --helix-base-uri '${{ parameters.helixBaseUri }}' + --polling-interval-seconds '${{ parameters.pollingIntervalSeconds }}' + --fail-on-failed-tests '${{ parameters.failWorkItemsWithFailedTests }}' + --use-fully-qualified-test-name '${{ parameters.useFullyQualifiedTestName }}' + --max-wait-minutes "$((${{ parameters.timeoutInMinutes }} - 5))" # Set the tool's timeout slightly lower than the Azure DevOps job timeout to allow it to exit gracefully. + --stage-name '$(System.StageName)' + ) + + organization='${{ parameters.organization }}' + repository='${{ parameters.repository }}' + + # Fall back to Azure DevOps-provided environment variables when the caller did not + # supply organization / repository explicitly. BUILD_REPOSITORY_NAME is typically + # 'owner/repo' for GitHub-backed builds. + if [ -z "$organization" ] || [ -z "$repository" ]; then + buildRepoName="${BUILD_REPOSITORY_NAME:-}" + if [ -n "$buildRepoName" ] && [[ "$buildRepoName" == */* ]]; then + repoOwner="${buildRepoName%%/*}" + repoName="${buildRepoName#*/}" + if [ -z "$organization" ]; then organization="$repoOwner"; fi + if [ -z "$repository" ]; then repository="$repoName"; fi + fi + fi + + if [ -n "$organization" ]; then toolArgs+=( --organization "$organization" ); fi + if [ -n "$repository" ]; then toolArgs+=( --repository "$repository" ); fi + + # Build.Reason and Build.SourceBranch are required to derive the Helix source filter + # the same way the Helix SDK submitter does (PR -> 'pr', internal -> 'official', + # otherwise -> 'ci'). Without these, manually-queued / scheduled / CI builds would + # be looked up under the wrong source prefix and find zero jobs. + toolArgs+=( --build-reason "$(Build.Reason)" ) + toolArgs+=( --source-branch "$(Build.SourceBranch)" ) + + if [ -n '${{ parameters.toolNupkgArtifactName }}' ]; then + # Tool was installed from a local nupkg; run the DLL via the repo-local dotnet. + export DOTNET_ROOT="$(Build.SourcesDirectory)/.dotnet" + ./eng/common/dotnet.sh exec "$(HelixJobMonitorDll)" "${toolArgs[@]}" + else + # Tool was restored from the local .config/dotnet-tools.json manifest; invoke it + # through the manifest from the repo root. + pushd "$BUILD_SOURCESDIRECTORY" > /dev/null + trap 'popd > /dev/null' EXIT + ./eng/common/dotnet.sh tool run '${{ parameters.toolCommand }}' -- "${toolArgs[@]}" + fi + displayName: Monitor Helix Jobs + env: + SYSTEM_ACCESSTOKEN: $(System.AccessToken) + HELIX_ACCESSTOKEN: ${{ parameters.helixAccessToken }} diff --git a/eng/common/core-templates/job/job.yml b/eng/common/core-templates/job/job.yml index eaed6d87e65..cb60f529784 100644 --- a/eng/common/core-templates/job/job.yml +++ b/eng/common/core-templates/job/job.yml @@ -19,6 +19,8 @@ parameters: # publishing defaults artifacts: '' enableMicrobuild: false + enablePreviewMicrobuild: false + microbuildPluginVersion: 'latest' enableMicrobuildForMacAndLinux: false microbuildUseESRP: true enablePublishBuildArtifacts: false @@ -71,6 +73,14 @@ jobs: templateContext: ${{ parameters.templateContext }} variables: + - name: AllowPtrToDetectTestRunRetryFiles + value: true + # Component Governance detection and CodeQL are not run in the public project + - ${{ if eq(variables['System.TeamProject'], 'public') }}: + - name: skipComponentGovernanceDetection + value: true + - name: Codeql.SkipTaskAutoInjection + value: true - ${{ if ne(parameters.enableTelemetry, 'false') }}: - name: DOTNET_CLI_TELEMETRY_PROFILE value: '$(Build.Repository.Uri)' @@ -128,6 +138,8 @@ jobs: - template: /eng/common/core-templates/steps/install-microbuild.yml parameters: enableMicrobuild: ${{ parameters.enableMicrobuild }} + enablePreviewMicrobuild: ${{ parameters.enablePreviewMicrobuild }} + microbuildPluginVersion: ${{ parameters.microbuildPluginVersion }} enableMicrobuildForMacAndLinux: ${{ parameters.enableMicrobuildForMacAndLinux }} microbuildUseESRP: ${{ parameters.microbuildUseESRP }} continueOnError: ${{ parameters.continueOnError }} @@ -150,6 +162,8 @@ jobs: - template: /eng/common/core-templates/steps/cleanup-microbuild.yml parameters: enableMicrobuild: ${{ parameters.enableMicrobuild }} + enablePreviewMicrobuild: ${{ parameters.enablePreviewMicrobuild }} + microbuildPluginVersion: ${{ parameters.microbuildPluginVersion }} enableMicrobuildForMacAndLinux: ${{ parameters.enableMicrobuildForMacAndLinux }} continueOnError: ${{ parameters.continueOnError }} diff --git a/eng/common/core-templates/job/onelocbuild.yml b/eng/common/core-templates/job/onelocbuild.yml index 12d7e55a94b..2816d2905a0 100644 --- a/eng/common/core-templates/job/onelocbuild.yml +++ b/eng/common/core-templates/job/onelocbuild.yml @@ -28,6 +28,7 @@ parameters: GitHubOrg: dotnet MirrorRepo: '' MirrorBranch: main + xLocCustomPowerShellScript: '' condition: '' JobNameSuffix: '' is1ESPipeline: '' @@ -115,6 +116,8 @@ jobs: gitHubOrganization: ${{ parameters.GitHubOrg }} mirrorRepo: ${{ parameters.MirrorRepo }} mirrorBranch: ${{ parameters.MirrorBranch }} + ${{ if ne(parameters.xLocCustomPowerShellScript, '') }}: + xLocCustomPowerShellScript: ${{ parameters.xLocCustomPowerShellScript }} condition: ${{ parameters.condition }} # Copy the locProject.json to the root of the Loc directory, then publish a pipeline artifact diff --git a/eng/common/core-templates/job/publish-build-assets.yml b/eng/common/core-templates/job/publish-build-assets.yml index 53af522d6d4..4229288d3d3 100644 --- a/eng/common/core-templates/job/publish-build-assets.yml +++ b/eng/common/core-templates/job/publish-build-assets.yml @@ -91,8 +91,8 @@ jobs: fetchDepth: 3 clean: true - - ${{ if eq(parameters.isAssetlessBuild, 'false') }}: - - ${{ if eq(parameters.publishingVersion, 3) }}: + - ${{ if eq(parameters.isAssetlessBuild, 'false') }}: + - ${{ if eq(parameters.publishingVersion, 3) }}: - task: DownloadPipelineArtifact@2 displayName: Download Asset Manifests inputs: @@ -117,12 +117,12 @@ jobs: flattenFolders: true condition: ${{ parameters.condition }} continueOnError: ${{ parameters.continueOnError }} - + - task: NuGetAuthenticate@1 # Populate internal runtime variables. - template: /eng/common/templates/steps/enable-internal-sources.yml - + - template: /eng/common/templates/steps/enable-internal-runtimes.yml - task: AzureCLI@2 @@ -142,7 +142,7 @@ jobs: condition: ${{ parameters.condition }} continueOnError: ${{ parameters.continueOnError }} - + - task: powershell@2 displayName: Create ReleaseConfigs Artifact inputs: @@ -188,7 +188,7 @@ jobs: BARBuildId: ${{ parameters.BARBuildId }} PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} is1ESPipeline: ${{ parameters.is1ESPipeline }} - + # Darc is targeting 8.0, so make sure it's installed - task: UseDotNet@2 inputs: diff --git a/eng/common/core-templates/job/renovate.yml b/eng/common/core-templates/job/renovate.yml new file mode 100644 index 00000000000..ff86c80b468 --- /dev/null +++ b/eng/common/core-templates/job/renovate.yml @@ -0,0 +1,196 @@ +# -------------------------------------------------------------------------------------- +# Renovate Bot Job Template +# -------------------------------------------------------------------------------------- +# This Azure DevOps pipeline job template runs Renovate (https://docs.renovatebot.com/) +# to automatically update dependencies in a GitHub repository. +# +# Renovate scans the repository for dependency files and creates pull requests to update +# outdated dependencies based on the configuration specified in the renovateConfigPath +# parameter. +# +# Usage: +# For each product repo wanting to make use of Renovate, this template is called from +# an internal Azure DevOps pipeline, typically with a schedule trigger, to check for +# and propose dependency updates. +# +# For more info, see https://github.com/dotnet/arcade/blob/main/Documentation/Renovate.md +# -------------------------------------------------------------------------------------- + +parameters: + +# Path to the Renovate configuration file within the repository. +- name: renovateConfigPath + type: string + default: 'eng/renovate.json' + +# GitHub repository to run Renovate against, in the format 'owner/repo'. +# This could technically be any repo but convention is to target the same +# repo that contains the calling pipeline. The Renovate config file would +# be co-located with the pipeline's repo and, in most cases, the config +# file is specific to the repo being targeted. +- name: gitHubRepo + type: string + +# List of base branches to target for Renovate PRs. +# NOTE: The Renovate configuration file is always read from the branch where the +# pipeline is run, NOT from the target branches specified here. If you need different +# configurations for different branches, run the pipeline from each branch separately. +- name: baseBranches + type: object + default: + - main + +# When true, Renovate will run in dry run mode, which previews changes without creating PRs. +# See the 'Run Renovate' step log output for details of what would have been changed. +- name: dryRun + type: boolean + default: false + +# By default, Renovate will not recreate a PR for a given dependency/version pair that was +# previously closed. This allows opting in to always recreating PRs even if they were +# previously closed. +- name: forceRecreatePR + type: boolean + default: false + +# Name of the arcade repository resource in the pipeline. +# This allows repos which haven't been onboarded to Arcade to still use this +# template by checking out the repo as a resource with a custom name and pointing +# this parameter to it. +- name: arcadeRepoResource + type: string + default: self + +# Directory name for the self repo under $(Build.SourcesDirectory) in multi-checkout. +# In multi-checkout (when arcadeRepoResource != 'self'), Azure DevOps checks out the +# self repo to $(Build.SourcesDirectory)/. Set this to match the auto-generated +# directory name. Using the auto-generated name is necessary rather than explicitly +# defining a checkout path because container jobs expect repos to live under the agent's +# workspace ($(Pipeline.Workspace)). On some self-hosted setups the host path +# (e.g., /mnt/vss/_work) differs from the container path (e.g., /__w), and a custom checkout +# path can fail validation. Using the default checkout location keeps the paths consistent +# and avoids this issue. +- name: selfRepoName + type: string + default: '' +- name: arcadeRepoName + type: string + default: '' + +# Pool configuration for the job. +- name: pool + type: object + default: + name: NetCore1ESPool-Internal + image: build.azurelinux.3.amd64 + os: linux + +jobs: +- job: Renovate + displayName: Run Renovate + container: RenovateContainer + variables: + - group: dotnet-renovate-bot + # The Renovate version is automatically updated by https://github.com/dotnet/arcade/blob/main/azure-pipelines-renovate.yml. + # Changing the variable name here would require updating the name in https://github.com/dotnet/arcade/blob/main/eng/renovate.json as well. + - name: renovateVersion + value: '42' + readonly: true + - name: renovateLogFilePath + value: '$(Build.ArtifactStagingDirectory)/renovate.json' + readonly: true + - name: dryRunArg + readonly: true + ${{ if eq(parameters.dryRun, true) }}: + value: 'full' + ${{ else }}: + value: '' + - name: recreateWhenArg + readonly: true + ${{ if eq(parameters.forceRecreatePR, true) }}: + value: 'always' + ${{ else }}: + value: '' + # In multi-checkout (without custom paths), Azure DevOps places each repo under + # $(Build.SourcesDirectory)/. selfRepoName must be provided in that case. + - name: selfRepoPath + readonly: true + ${{ if eq(parameters.arcadeRepoResource, 'self') }}: + value: '$(Build.SourcesDirectory)' + ${{ else }}: + value: '$(Build.SourcesDirectory)/${{ parameters.selfRepoName }}' + - name: arcadeRepoPath + readonly: true + ${{ if eq(parameters.arcadeRepoResource, 'self') }}: + value: '$(Build.SourcesDirectory)' + ${{ else }}: + value: '$(Build.SourcesDirectory)/${{ parameters.arcadeRepoName }}' + pool: ${{ parameters.pool }} + + templateContext: + outputParentDirectory: $(Build.ArtifactStagingDirectory) + outputs: + - output: pipelineArtifact + displayName: Publish Renovate Log + condition: succeededOrFailed() + targetPath: $(Build.ArtifactStagingDirectory) + artifactName: $(Agent.JobName)_Logs_Attempt$(System.JobAttempt) + isProduction: false # logs are non-production artifacts + + steps: + - checkout: self + fetchDepth: 1 + + - ${{ if ne(parameters.arcadeRepoResource, 'self') }}: + - checkout: ${{ parameters.arcadeRepoResource }} + fetchDepth: 1 + + - script: | + renovate-config-validator $(selfRepoPath)/${{parameters.renovateConfigPath}} 2>&1 | tee /tmp/renovate-config-validator.out + validatorExit=${PIPESTATUS[0]} + if grep -q '^ WARN:' /tmp/renovate-config-validator.out; then + echo "##vso[task.logissue type=warning]Renovate config validator produced warnings." + echo "##vso[task.complete result=SucceededWithIssues]" + fi + exit $validatorExit + displayName: Validate Renovate config + env: + LOG_LEVEL: info + LOG_FILE_LEVEL: debug + LOG_FILE: $(Build.ArtifactStagingDirectory)/renovate-config-validator.json + + - script: | + . $(arcadeRepoPath)/eng/common/renovate.env + renovate 2>&1 | tee /tmp/renovate.out + renovateExit=${PIPESTATUS[0]} + if grep -q '^ WARN:' /tmp/renovate.out; then + echo "##vso[task.logissue type=warning]Renovate produced warnings." + echo "##vso[task.complete result=SucceededWithIssues]" + fi + exit $renovateExit + displayName: Run Renovate + env: + RENOVATE_FORK_TOKEN: $(BotAccount-dotnet-renovate-bot-PAT) + RENOVATE_TOKEN: $(BotAccount-dotnet-renovate-bot-PAT) + RENOVATE_REPOSITORIES: ${{parameters.gitHubRepo}} + RENOVATE_BASE_BRANCHES: ${{ convertToJson(parameters.baseBranches) }} + RENOVATE_DRY_RUN: $(dryRunArg) + RENOVATE_RECREATE_WHEN: $(recreateWhenArg) + LOG_LEVEL: info + LOG_FILE_LEVEL: debug + LOG_FILE: $(renovateLogFilePath) + RENOVATE_CONFIG_FILE: $(selfRepoPath)/${{parameters.renovateConfigPath}} + + - script: | + echo "PRs created by Renovate:" + if [ -s "$(renovateLogFilePath)" ]; then + if ! jq -r 'select(.msg == "PR created" and .pr != null) | "https://github.com/\(.repository)/pull/\(.pr)"' "$(renovateLogFilePath)" | sort -u; then + echo "##vso[task.logissue type=warning]Failed to parse Renovate log file with jq." + echo "##vso[task.complete result=SucceededWithIssues]" + fi + else + echo "##vso[task.logissue type=warning]No Renovate log file found or file is empty." + echo "##vso[task.complete result=SucceededWithIssues]" + fi + displayName: List created PRs + condition: and(succeededOrFailed(), eq('${{ parameters.dryRun }}', false)) diff --git a/eng/common/core-templates/job/source-index-stage1.yml b/eng/common/core-templates/job/source-index-stage1.yml index 76baf5c2725..bac6ac5faac 100644 --- a/eng/common/core-templates/job/source-index-stage1.yml +++ b/eng/common/core-templates/job/source-index-stage1.yml @@ -15,6 +15,8 @@ jobs: variables: - name: BinlogPath value: ${{ parameters.binlogPath }} + - name: skipComponentGovernanceDetection + value: true - template: /eng/common/core-templates/variables/pool-providers.yml parameters: is1ESPipeline: ${{ parameters.is1ESPipeline }} @@ -25,10 +27,10 @@ jobs: pool: ${{ if eq(variables['System.TeamProject'], 'public') }}: name: $(DncEngPublicBuildPool) - image: windows.vs2026preview.scout.amd64.open + image: windows.vs2026.amd64.open ${{ if eq(variables['System.TeamProject'], 'internal') }}: name: $(DncEngInternalBuildPool) - image: windows.vs2026preview.scout.amd64 + image: windows.vs2026.amd64 steps: - ${{ if eq(parameters.is1ESPipeline, '') }}: diff --git a/eng/common/core-templates/jobs/codeql-build.yml b/eng/common/core-templates/jobs/codeql-build.yml deleted file mode 100644 index dbc14ac580a..00000000000 --- a/eng/common/core-templates/jobs/codeql-build.yml +++ /dev/null @@ -1,32 +0,0 @@ -parameters: - # See schema documentation in /Documentation/AzureDevOps/TemplateSchema.md - continueOnError: false - # Required: A collection of jobs to run - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job - jobs: [] - # Optional: if specified, restore and use this version of Guardian instead of the default. - overrideGuardianVersion: '' - is1ESPipeline: '' - -jobs: -- template: /eng/common/core-templates/jobs/jobs.yml - parameters: - is1ESPipeline: ${{ parameters.is1ESPipeline }} - enableMicrobuild: false - enablePublishBuildArtifacts: false - enablePublishTestResults: false - enablePublishBuildAssets: false - enableTelemetry: true - - variables: - - group: Publish-Build-Assets - # The Guardian version specified in 'eng/common/sdl/packages.config'. This value must be kept in - # sync with the packages.config file. - - name: DefaultGuardianVersion - value: 0.109.0 - - name: GuardianPackagesConfigFile - value: $(System.DefaultWorkingDirectory)\eng\common\sdl\packages.config - - name: GuardianVersion - value: ${{ coalesce(parameters.overrideGuardianVersion, '$(DefaultGuardianVersion)') }} - - jobs: ${{ parameters.jobs }} - diff --git a/eng/common/core-templates/post-build/common-variables.yml b/eng/common/core-templates/post-build/common-variables.yml index d5627a994ae..db298ae16ba 100644 --- a/eng/common/core-templates/post-build/common-variables.yml +++ b/eng/common/core-templates/post-build/common-variables.yml @@ -11,8 +11,6 @@ variables: - name: MaestroApiVersion value: "2020-02-20" - - name: SourceLinkCLIVersion - value: 3.0.0 - name: SymbolToolVersion value: 1.0.1 - name: BinlogToolVersion diff --git a/eng/common/core-templates/post-build/post-build.yml b/eng/common/core-templates/post-build/post-build.yml index 135fc9a5051..9d951352696 100644 --- a/eng/common/core-templates/post-build/post-build.yml +++ b/eng/common/core-templates/post-build/post-build.yml @@ -1,118 +1,108 @@ parameters: - # Which publishing infra should be used. THIS SHOULD MATCH THE VERSION ON THE BUILD MANIFEST. - # Publishing V1 is no longer supported - # Publishing V2 is no longer supported - # Publishing V3 is the default - - name: publishingInfraVersion - displayName: Which version of publishing should be used to promote the build definition? - type: number - default: 3 - values: - - 3 - - 4 - - - name: BARBuildId - displayName: BAR Build Id - type: number - default: 0 - - - name: PromoteToChannelIds - displayName: Channel to promote BARBuildId to - type: string - default: '' - - - name: enableSourceLinkValidation - displayName: Enable SourceLink validation - type: boolean - default: false - - - name: enableSigningValidation - displayName: Enable signing validation - type: boolean - default: true - - - name: enableSymbolValidation - displayName: Enable symbol validation - type: boolean - default: false - - - name: enableNugetValidation - displayName: Enable NuGet validation - type: boolean - default: true - - - name: publishInstallersAndChecksums - displayName: Publish installers and checksums - type: boolean - default: true - - - name: requireDefaultChannels - displayName: Fail the build if there are no default channel(s) registrations for the current build - type: boolean - default: false - - - name: SDLValidationParameters - type: object - default: - enable: false - publishGdn: false - continueOnError: false - params: '' - artifactNames: '' - downloadArtifacts: true - - - name: isAssetlessBuild - type: boolean - displayName: Is Assetless Build - default: false - - # These parameters let the user customize the call to sdk-task.ps1 for publishing - # symbols & general artifacts as well as for signing validation - - name: symbolPublishingAdditionalParameters - displayName: Symbol publishing additional parameters - type: string - default: '' - - - name: artifactsPublishingAdditionalParameters - displayName: Artifact publishing additional parameters - type: string - default: '' - - - name: signingValidationAdditionalParameters - displayName: Signing validation additional parameters - type: string - default: '' - - # Which stages should finish execution before post-build stages start - - name: validateDependsOn - type: object - default: - - build - - - name: publishDependsOn - type: object - default: - - Validate - - # Optional: Call asset publishing rather than running in a separate stage - - name: publishAssetsImmediately - type: boolean - default: false - - - name: is1ESPipeline - type: boolean - default: false +# Which publishing infra should be used. THIS SHOULD MATCH THE VERSION ON THE BUILD MANIFEST. +# Publishing V1 is no longer supported +# Publishing V2 is no longer supported +# Publishing V3 is the default +- name: publishingInfraVersion + displayName: Which version of publishing should be used to promote the build definition? + type: number + default: 3 + values: + - 3 + - 4 + +- name: BARBuildId + displayName: BAR Build Id + type: number + default: 0 + +- name: PromoteToChannelIds + displayName: Channel to promote BARBuildId to + type: string + default: '' + +- name: enableSourceLinkValidation + displayName: Enable SourceLink validation + type: boolean + default: false + +- name: enableSigningValidation + displayName: Enable signing validation + type: boolean + default: true + +- name: enableSymbolValidation + displayName: Enable symbol validation + type: boolean + default: false + +- name: enableNugetValidation + displayName: Enable NuGet validation + type: boolean + default: true + +- name: publishInstallersAndChecksums + displayName: Publish installers and checksums + type: boolean + default: true + +- name: requireDefaultChannels + displayName: Fail the build if there are no default channel(s) registrations for the current build + type: boolean + default: false + +- name: isAssetlessBuild + type: boolean + displayName: Is Assetless Build + default: false + +# These parameters let the user customize the call to sdk-task.ps1 for publishing +# symbols & general artifacts as well as for signing validation +- name: symbolPublishingAdditionalParameters + displayName: Symbol publishing additional parameters + type: string + default: '' + +- name: artifactsPublishingAdditionalParameters + displayName: Artifact publishing additional parameters + type: string + default: '' + +- name: signingValidationAdditionalParameters + displayName: Signing validation additional parameters + type: string + default: '' + +# Which stages should finish execution before post-build stages start +- name: validateDependsOn + type: object + default: + - build + +- name: publishDependsOn + type: object + default: + - Validate + +# Optional: Call asset publishing rather than running in a separate stage +- name: publishAssetsImmediately + type: boolean + default: false + +- name: is1ESPipeline + type: boolean + default: false stages: -- ${{ if or(eq( parameters.enableNugetValidation, 'true'), eq(parameters.enableSigningValidation, 'true'), eq(parameters.enableSourceLinkValidation, 'true'), eq(parameters.SDLValidationParameters.enable, 'true')) }}: +- ${{ if or(eq( parameters.enableNugetValidation, 'true'), eq(parameters.enableSigningValidation, 'true'), eq(parameters.enableSourceLinkValidation, 'true')) }}: - stage: Validate dependsOn: ${{ parameters.validateDependsOn }} displayName: Validate Build Assets variables: - - template: /eng/common/core-templates/post-build/common-variables.yml - - template: /eng/common/core-templates/variables/pool-providers.yml - parameters: - is1ESPipeline: ${{ parameters.is1ESPipeline }} + - template: /eng/common/core-templates/post-build/common-variables.yml + - template: /eng/common/core-templates/variables/pool-providers.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} jobs: - job: displayName: NuGet Validation @@ -128,49 +118,49 @@ stages: ${{ else }}: ${{ if eq(parameters.is1ESPipeline, true) }}: name: $(DncEngInternalBuildPool) - image: windows.vs2026preview.scout.amd64 + image: windows.vs2026.amd64 os: windows ${{ else }}: name: $(DncEngInternalBuildPool) - demands: ImageOverride -equals windows.vs2026preview.scout.amd64 + demands: ImageOverride -equals windows.vs2026.amd64 steps: - - template: /eng/common/core-templates/post-build/setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - is1ESPipeline: ${{ parameters.is1ESPipeline }} - - - ${{ if ne(parameters.publishingInfraVersion, 4) }}: - - task: DownloadBuildArtifacts@0 - displayName: Download Package Artifacts - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - artifactName: PackageArtifacts - checkDownloadedFiles: true - - ${{ if eq(parameters.publishingInfraVersion, 4) }}: - - task: DownloadPipelineArtifact@2 - displayName: Download Pipeline Artifacts (V4) - inputs: - itemPattern: '*/packages/**/*.nupkg' - targetPath: '$(Build.ArtifactStagingDirectory)/PipelineArtifactsDownload' - - task: CopyFiles@2 - displayName: Flatten packages to PackageArtifacts - inputs: - SourceFolder: '$(Build.ArtifactStagingDirectory)/PipelineArtifactsDownload' - Contents: '**/*.nupkg' - TargetFolder: '$(Build.ArtifactStagingDirectory)/PackageArtifacts' - flattenFolders: true - - - task: PowerShell@2 - displayName: Validate + - template: /eng/common/core-templates/post-build/setup-maestro-vars.yml + parameters: + BARBuildId: ${{ parameters.BARBuildId }} + PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} + is1ESPipeline: ${{ parameters.is1ESPipeline }} + + - ${{ if ne(parameters.publishingInfraVersion, 4) }}: + - task: DownloadBuildArtifacts@0 + displayName: Download Package Artifacts + inputs: + buildType: specific + buildVersionToDownload: specific + project: $(AzDOProjectName) + pipeline: $(AzDOPipelineId) + buildId: $(AzDOBuildId) + artifactName: PackageArtifacts + checkDownloadedFiles: true + - ${{ if eq(parameters.publishingInfraVersion, 4) }}: + - task: DownloadPipelineArtifact@2 + displayName: Download Pipeline Artifacts (V4) + inputs: + itemPattern: '*/packages/**/*.nupkg' + targetPath: '$(Build.ArtifactStagingDirectory)/PipelineArtifactsDownload' + - task: CopyFiles@2 + displayName: Flatten packages to PackageArtifacts inputs: - filePath: $(System.DefaultWorkingDirectory)/eng/common/post-build/nuget-validation.ps1 - arguments: -PackagesPath $(Build.ArtifactStagingDirectory)/PackageArtifacts/ + SourceFolder: '$(Build.ArtifactStagingDirectory)/PipelineArtifactsDownload' + Contents: '**/*.nupkg' + TargetFolder: '$(Build.ArtifactStagingDirectory)/PackageArtifacts' + flattenFolders: true + + - task: PowerShell@2 + displayName: Validate + inputs: + filePath: $(System.DefaultWorkingDirectory)/eng/common/post-build/nuget-validation.ps1 + arguments: -PackagesPath $(Build.ArtifactStagingDirectory)/PackageArtifacts/ - job: displayName: Signing Validation @@ -184,143 +174,96 @@ stages: os: windows # If it's not devdiv, it's dnceng ${{ else }}: - ${{ if eq(parameters.is1ESPipeline, true) }}: + ${{ if eq(parameters.is1ESPipeline, true) }}: name: $(DncEngInternalBuildPool) image: windows.vs2026.amd64 os: windows ${{ else }}: name: $(DncEngInternalBuildPool) - demands: ImageOverride -equals windows.vs2026preview.scout.amd64 + demands: ImageOverride -equals windows.vs2026.amd64 steps: - - template: /eng/common/core-templates/post-build/setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - is1ESPipeline: ${{ parameters.is1ESPipeline }} - - - ${{ if ne(parameters.publishingInfraVersion, 4) }}: - - task: DownloadBuildArtifacts@0 - displayName: Download Package Artifacts - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - artifactName: PackageArtifacts - checkDownloadedFiles: true - - ${{ if eq(parameters.publishingInfraVersion, 4) }}: - - task: DownloadPipelineArtifact@2 - displayName: Download Pipeline Artifacts (V4) - inputs: - itemPattern: '*/packages/**/*.nupkg' - targetPath: '$(Build.ArtifactStagingDirectory)/PipelineArtifactsDownload' - - task: CopyFiles@2 - displayName: Flatten packages to PackageArtifacts - inputs: - SourceFolder: '$(Build.ArtifactStagingDirectory)/PipelineArtifactsDownload' - Contents: '**/*.nupkg' - TargetFolder: '$(Build.ArtifactStagingDirectory)/PackageArtifacts' - flattenFolders: true - - # This is necessary whenever we want to publish/restore to an AzDO private feed - # Since sdk-task.ps1 tries to restore packages we need to do this authentication here - # otherwise it'll complain about accessing a private feed. - - task: NuGetAuthenticate@1 - displayName: 'Authenticate to AzDO Feeds' - - # Signing validation will optionally work with the buildmanifest file which is downloaded from - # Azure DevOps above. - - task: PowerShell@2 - displayName: Validate - inputs: - filePath: eng\common\sdk-task.ps1 - arguments: -task SigningValidation -restore -msbuildEngine vs - /p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts' - /p:SignCheckExclusionsFile='$(System.DefaultWorkingDirectory)/eng/SignCheckExclusionsFile.txt' - ${{ parameters.signingValidationAdditionalParameters }} - - - template: /eng/common/core-templates/steps/publish-logs.yml - parameters: - is1ESPipeline: ${{ parameters.is1ESPipeline }} - StageLabel: 'Validation' - JobLabel: 'Signing' - BinlogToolVersion: $(BinlogToolVersion) + - template: /eng/common/core-templates/post-build/setup-maestro-vars.yml + parameters: + BARBuildId: ${{ parameters.BARBuildId }} + PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} + is1ESPipeline: ${{ parameters.is1ESPipeline }} - - job: - displayName: SourceLink Validation - condition: eq( ${{ parameters.enableSourceLinkValidation }}, 'true') - pool: - # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - name: AzurePipelines-EO - image: 1ESPT-Windows2025 - demands: Cmd - os: windows - # If it's not devdiv, it's dnceng - ${{ else }}: - ${{ if eq(parameters.is1ESPipeline, true) }}: - name: $(DncEngInternalBuildPool) - image: windows.vs2026.amd64 - os: windows - ${{ else }}: - name: $(DncEngInternalBuildPool) - demands: ImageOverride -equals windows.vs2026preview.scout.amd64 - steps: - - template: /eng/common/core-templates/post-build/setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - is1ESPipeline: ${{ parameters.is1ESPipeline }} - - - ${{ if ne(parameters.publishingInfraVersion, 4) }}: - - task: DownloadBuildArtifacts@0 - displayName: Download Blob Artifacts - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - artifactName: BlobArtifacts - checkDownloadedFiles: true - - ${{ if eq(parameters.publishingInfraVersion, 4) }}: - - task: DownloadPipelineArtifact@2 - displayName: Download Pipeline Artifacts (V4) - inputs: - itemPattern: '*/assets/**' - targetPath: '$(Build.ArtifactStagingDirectory)/PipelineArtifactsDownload' - - task: CopyFiles@2 - displayName: Flatten assets to BlobArtifacts - inputs: - SourceFolder: '$(Build.ArtifactStagingDirectory)/PipelineArtifactsDownload' - Contents: '**/*' - TargetFolder: '$(Build.ArtifactStagingDirectory)/BlobArtifacts' - flattenFolders: true - - - task: PowerShell@2 - displayName: Validate + - ${{ if ne(parameters.publishingInfraVersion, 4) }}: + - task: DownloadBuildArtifacts@0 + displayName: Download Package Artifacts + inputs: + buildType: specific + buildVersionToDownload: specific + project: $(AzDOProjectName) + pipeline: $(AzDOPipelineId) + buildId: $(AzDOBuildId) + artifactName: PackageArtifacts + checkDownloadedFiles: true + - ${{ if eq(parameters.publishingInfraVersion, 4) }}: + - task: DownloadPipelineArtifact@2 + displayName: Download Pipeline Artifacts (V4) + inputs: + itemPattern: '*/packages/**/*.nupkg' + targetPath: '$(Build.ArtifactStagingDirectory)/PipelineArtifactsDownload' + - task: CopyFiles@2 + displayName: Flatten packages to PackageArtifacts inputs: - filePath: $(System.DefaultWorkingDirectory)/eng/common/post-build/sourcelink-validation.ps1 - arguments: -InputPath $(Build.ArtifactStagingDirectory)/BlobArtifacts/ - -ExtractPath $(Agent.BuildDirectory)/Extract/ - -GHRepoName $(Build.Repository.Name) - -GHCommit $(Build.SourceVersion) - -SourcelinkCliVersion $(SourceLinkCLIVersion) - continueOnError: true + SourceFolder: '$(Build.ArtifactStagingDirectory)/PipelineArtifactsDownload' + Contents: '**/*.nupkg' + TargetFolder: '$(Build.ArtifactStagingDirectory)/PackageArtifacts' + flattenFolders: true + + # This is necessary whenever we want to publish/restore to an AzDO private feed + # Since sdk-task.ps1 tries to restore packages we need to do this authentication here + # otherwise it'll complain about accessing a private feed. + - task: NuGetAuthenticate@1 + displayName: 'Authenticate to AzDO Feeds' + + # Signing validation will optionally work with the buildmanifest file which is downloaded from + # Azure DevOps above. + - task: PowerShell@2 + displayName: Validate + inputs: + filePath: eng\common\sdk-task.ps1 + arguments: -task SigningValidation -restore -msbuildEngine dotnet + /p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts' + /p:SignCheckExclusionsFile='$(System.DefaultWorkingDirectory)/eng/SignCheckExclusionsFile.txt' + ${{ parameters.signingValidationAdditionalParameters }} + + - template: /eng/common/core-templates/steps/publish-logs.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + StageLabel: 'Validation' + JobLabel: 'Signing' + BinlogToolVersion: $(BinlogToolVersion) + + # SourceLink validation has been removed — the underlying CLI tool + # (targeting netcoreapp2.1) has not functioned for years. + # The enableSourceLinkValidation parameter is kept but ignored so + # existing pipelines that pass it are not broken. + # See https://github.com/dotnet/arcade/issues/16647 + - ${{ if eq(parameters.enableSourceLinkValidation, 'true') }}: + - job: + displayName: 'SourceLink Validation Removed - please remove enableSourceLinkValidation from your pipeline' + pool: server + steps: + - task: Delay@1 + displayName: 'Warning: SourceLink validation removed (see https://github.com/dotnet/arcade/issues/16647)' + inputs: + delayForMinutes: '0' - ${{ if ne(parameters.publishAssetsImmediately, 'true') }}: - stage: publish_using_darc - ${{ if or(eq(parameters.enableNugetValidation, 'true'), eq(parameters.enableSigningValidation, 'true'), eq(parameters.enableSourceLinkValidation, 'true'), eq(parameters.SDLValidationParameters.enable, 'true')) }}: + ${{ if or(eq(parameters.enableNugetValidation, 'true'), eq(parameters.enableSigningValidation, 'true'), eq(parameters.enableSourceLinkValidation, 'true')) }}: dependsOn: ${{ parameters.publishDependsOn }} ${{ else }}: dependsOn: ${{ parameters.validateDependsOn }} displayName: Publish using Darc variables: - - template: /eng/common/core-templates/post-build/common-variables.yml - - template: /eng/common/core-templates/variables/pool-providers.yml - parameters: - is1ESPipeline: ${{ parameters.is1ESPipeline }} + - template: /eng/common/core-templates/post-build/common-variables.yml + - template: /eng/common/core-templates/variables/pool-providers.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} jobs: - job: displayName: Publish Using Darc @@ -334,7 +277,7 @@ stages: os: windows # If it's not devdiv, it's dnceng ${{ else }}: - ${{ if eq(parameters.is1ESPipeline, true) }}: + ${{ if eq(parameters.is1ESPipeline, true) }}: name: NetCore1ESPool-Publishing-Internal image: windows.vs2026.amd64 os: windows @@ -342,32 +285,31 @@ stages: name: NetCore1ESPool-Publishing-Internal demands: ImageOverride -equals windows.vs2026.amd64 steps: - - template: /eng/common/core-templates/post-build/setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - is1ESPipeline: ${{ parameters.is1ESPipeline }} + - template: /eng/common/core-templates/post-build/setup-maestro-vars.yml + parameters: + BARBuildId: ${{ parameters.BARBuildId }} + PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} + is1ESPipeline: ${{ parameters.is1ESPipeline }} - - task: NuGetAuthenticate@1 + - task: NuGetAuthenticate@1 - # Populate internal runtime variables. - - template: /eng/common/templates/steps/enable-internal-sources.yml + # Populate internal runtime variables. + - template: /eng/common/templates/steps/enable-internal-sources.yml - - template: /eng/common/templates/steps/enable-internal-runtimes.yml + - template: /eng/common/templates/steps/enable-internal-runtimes.yml - # Darc is targeting 8.0, so make sure it's installed - - task: UseDotNet@2 - inputs: - version: 8.0.x + - task: UseDotNet@2 + inputs: + version: 8.0.x - - task: AzureCLI@2 - displayName: Publish Using Darc - inputs: - azureSubscription: "Darc: Maestro Production" - scriptType: ps - scriptLocation: scriptPath - scriptPath: $(System.DefaultWorkingDirectory)/eng/common/post-build/publish-using-darc.ps1 - arguments: > + - task: AzureCLI@2 + displayName: Publish Using Darc + inputs: + azureSubscription: "Darc: Maestro Production" + scriptType: ps + scriptLocation: scriptPath + scriptPath: $(System.DefaultWorkingDirectory)/eng/common/post-build/publish-using-darc.ps1 + arguments: > -BuildId $(BARBuildId) -PublishingInfraVersion 3 -AzdoToken '$(System.AccessToken)' diff --git a/eng/common/core-templates/stages/renovate.yml b/eng/common/core-templates/stages/renovate.yml new file mode 100644 index 00000000000..edab2818258 --- /dev/null +++ b/eng/common/core-templates/stages/renovate.yml @@ -0,0 +1,111 @@ +# -------------------------------------------------------------------------------------- +# Renovate Pipeline Template +# -------------------------------------------------------------------------------------- +# This template provides a complete reusable pipeline definition for running Renovate +# in a 1ES Official pipeline. Pipelines can extend from this template and only need +# to pass the Renovate job parameters. +# +# For more info, see https://github.com/dotnet/arcade/blob/main/Documentation/Renovate.md +# -------------------------------------------------------------------------------------- + +parameters: + +# Path to the Renovate configuration file within the repository. +- name: renovateConfigPath + type: string + default: 'eng/renovate.json' + +# GitHub repository to run Renovate against, in the format 'owner/repo'. +- name: gitHubRepo + type: string + +# List of base branches to target for Renovate PRs. +- name: baseBranches + type: object + default: + - main + +# When true, Renovate will run in dry run mode. +- name: dryRun + type: boolean + default: false + +# When true, Renovate will recreate PRs even if they were previously closed. +- name: forceRecreatePR + type: boolean + default: false + +# Name of the arcade repository resource in the pipeline. +# This allows repos which haven't been onboarded to Arcade to still use this +# template by checking out the repo as a resource with a custom name and pointing +# this parameter to it. +- name: arcadeRepoResource + type: string + default: 'self' + +- name: selfRepoName + type: string + default: '' +- name: arcadeRepoName + type: string + default: '' + +# Pool configuration for the pipeline. +- name: pool + type: object + default: + name: NetCore1ESPool-Internal + image: build.azurelinux.3.amd64 + os: linux + +# Renovate version used in the container image tag. +- name: renovateVersion + default: 43 + type: number + +# Pool configuration for SDL analysis. +- name: sdlPool + type: object + default: + name: NetCore1ESPool-Internal + image: windows.vs2026.amd64 + os: windows + +resources: + repositories: + - repository: 1ESPipelineTemplates + type: git + name: 1ESPipelineTemplates/1ESPipelineTemplates + ref: refs/tags/release + +extends: + template: v1/1ES.Official.PipelineTemplate.yml@1ESPipelineTemplates + parameters: + pool: ${{ parameters.pool }} + sdl: + sourceAnalysisPool: ${{ parameters.sdlPool }} + # When repos that aren't onboarded to Arcade use this template, they set the + # arcadeRepoResource parameter to point to their Arcade repo resource. In that case, + # Aracde will be excluded from SDL analysis. + ${{ if ne(parameters.arcadeRepoResource, 'self') }}: + sourceRepositoriesToScan: + exclude: + - repository: ${{ parameters.arcadeRepoResource }} + containers: + RenovateContainer: + image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-renovate-${{ parameters.renovateVersion }}-amd64 + stages: + - stage: Renovate + displayName: Run Renovate + jobs: + - template: /eng/common/core-templates/job/renovate.yml@${{ parameters.arcadeRepoResource }} + parameters: + renovateConfigPath: ${{ parameters.renovateConfigPath }} + gitHubRepo: ${{ parameters.gitHubRepo }} + baseBranches: ${{ parameters.baseBranches }} + dryRun: ${{ parameters.dryRun }} + forceRecreatePR: ${{ parameters.forceRecreatePR }} + pool: ${{ parameters.pool }} + arcadeRepoResource: ${{ parameters.arcadeRepoResource }} + selfRepoName: ${{ parameters.selfRepoName }} + arcadeRepoName: ${{ parameters.arcadeRepoName }} diff --git a/eng/common/core-templates/steps/enable-internal-sources.yml b/eng/common/core-templates/steps/enable-internal-sources.yml index 4085512b690..51af9a01709 100644 --- a/eng/common/core-templates/steps/enable-internal-sources.yml +++ b/eng/common/core-templates/steps/enable-internal-sources.yml @@ -15,32 +15,56 @@ steps: - ${{ if ne(variables['System.TeamProject'], 'public') }}: - ${{ if ne(parameters.legacyCredential, '') }}: - task: PowerShell@2 + condition: and(succeeded(), eq(variables['Agent.Os'], 'Windows_NT')) displayName: Setup Internal Feeds inputs: filePath: $(System.DefaultWorkingDirectory)/eng/common/SetupNugetSources.ps1 arguments: -ConfigFile $(System.DefaultWorkingDirectory)/NuGet.config -Password $Env:Token env: Token: ${{ parameters.legacyCredential }} + - task: Bash@3 + condition: and(succeeded(), ne(variables['Agent.Os'], 'Windows_NT')) + displayName: Setup Internal Feeds + inputs: + targetType: inline + script: | + "$(System.DefaultWorkingDirectory)/eng/common/SetupNugetSources.sh" "$(System.DefaultWorkingDirectory)/NuGet.config" "$Token" + env: + Token: ${{ parameters.legacyCredential }} # If running on dnceng (internal project), just use the default behavior for NuGetAuthenticate. # If running on DevDiv, NuGetAuthenticate is not really an option. It's scoped to a single feed, and we have many feeds that # may be added. Instead, we'll use the traditional approach (add cred to nuget.config), but use an account token. - ${{ else }}: - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - task: PowerShell@2 + condition: and(succeeded(), eq(variables['Agent.Os'], 'Windows_NT')) displayName: Setup Internal Feeds inputs: filePath: $(System.DefaultWorkingDirectory)/eng/common/SetupNugetSources.ps1 arguments: -ConfigFile $(System.DefaultWorkingDirectory)/NuGet.config + - task: Bash@3 + condition: and(succeeded(), ne(variables['Agent.Os'], 'Windows_NT')) + displayName: Setup Internal Feeds + inputs: + filePath: $(System.DefaultWorkingDirectory)/eng/common/SetupNugetSources.sh + arguments: $(System.DefaultWorkingDirectory)/NuGet.config - ${{ else }}: - template: /eng/common/templates/steps/get-federated-access-token.yml parameters: federatedServiceConnection: ${{ parameters.nugetFederatedServiceConnection }} outputVariableName: 'dnceng-artifacts-feeds-read-access-token' - task: PowerShell@2 + condition: and(succeeded(), eq(variables['Agent.Os'], 'Windows_NT')) displayName: Setup Internal Feeds inputs: filePath: $(System.DefaultWorkingDirectory)/eng/common/SetupNugetSources.ps1 arguments: -ConfigFile $(System.DefaultWorkingDirectory)/NuGet.config -Password $(dnceng-artifacts-feeds-read-access-token) + - task: Bash@3 + condition: and(succeeded(), ne(variables['Agent.Os'], 'Windows_NT')) + displayName: Setup Internal Feeds + inputs: + filePath: $(System.DefaultWorkingDirectory)/eng/common/SetupNugetSources.sh + arguments: $(System.DefaultWorkingDirectory)/NuGet.config $(dnceng-artifacts-feeds-read-access-token) # This is required in certain scenarios to install the ADO credential provider. # It installed by default in some msbuild invocations (e.g. VS msbuild), but needs to be installed for others # (e.g. dotnet msbuild). diff --git a/eng/common/core-templates/steps/install-microbuild-impl.yml b/eng/common/core-templates/steps/install-microbuild-impl.yml new file mode 100644 index 00000000000..da22beb3f60 --- /dev/null +++ b/eng/common/core-templates/steps/install-microbuild-impl.yml @@ -0,0 +1,34 @@ +parameters: + - name: microbuildTaskInputs + type: object + default: {} + + - name: microbuildEnv + type: object + default: {} + + - name: enablePreviewMicrobuild + type: boolean + default: false + + - name: condition + type: string + + - name: continueOnError + type: boolean + +steps: +- ${{ if eq(parameters.enablePreviewMicrobuild, true) }}: + - task: MicroBuildSigningPluginPreview@4 + displayName: Install Preview MicroBuild plugin + inputs: ${{ parameters.microbuildTaskInputs }} + env: ${{ parameters.microbuildEnv }} + continueOnError: ${{ parameters.continueOnError }} + condition: ${{ parameters.condition }} +- ${{ else }}: + - task: MicroBuildSigningPlugin@4 + displayName: Install MicroBuild plugin + inputs: ${{ parameters.microbuildTaskInputs }} + env: ${{ parameters.microbuildEnv }} + continueOnError: ${{ parameters.continueOnError }} + condition: ${{ parameters.condition }} diff --git a/eng/common/core-templates/steps/install-microbuild.yml b/eng/common/core-templates/steps/install-microbuild.yml index 553fce66b94..76a54e157fd 100644 --- a/eng/common/core-templates/steps/install-microbuild.yml +++ b/eng/common/core-templates/steps/install-microbuild.yml @@ -4,6 +4,8 @@ parameters: # Enable install tasks for MicroBuild on Mac and Linux # Will be ignored if 'enableMicrobuild' is false or 'Agent.Os' is 'Windows_NT' enableMicrobuildForMacAndLinux: false + # Enable preview version of MB signing plugin + enablePreviewMicrobuild: false # Determines whether the ESRP service connection information should be passed to the signing plugin. # This overlaps with _SignType to some degree. We only need the service connection for real signing. # It's important that the service connection not be passed to the MicroBuildSigningPlugin task in this place. @@ -13,6 +15,8 @@ parameters: microbuildUseESRP: true # Microbuild installation directory microBuildOutputFolder: $(Agent.TempDirectory)/MicroBuild + # Microbuild version + microbuildPluginVersion: 'latest' continueOnError: false @@ -69,42 +73,46 @@ steps: # YAML expansion, and Windows vs. Linux/Mac uses different service connections. However, # we can avoid including the MB install step if not enabled at all. This avoids a bunch of # extra pipeline authorizations, since most pipelines do not sign on non-Windows. - - task: MicroBuildSigningPlugin@4 - displayName: Install MicroBuild plugin (Windows) - inputs: - signType: $(_SignType) - zipSources: false - feedSource: https://dnceng.pkgs.visualstudio.com/_packaging/MicroBuildToolset/nuget/v3/index.json - ${{ if eq(parameters.microbuildUseESRP, true) }}: - ConnectedServiceName: 'MicroBuild Signing Task (DevDiv)' - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - ConnectedPMEServiceName: 6cc74545-d7b9-4050-9dfa-ebefcc8961ea - ${{ else }}: - ConnectedPMEServiceName: 248d384a-b39b-46e3-8ad5-c2c210d5e7ca - env: - TeamName: $(_TeamName) - MicroBuildOutputFolderOverride: ${{ parameters.microBuildOutputFolder }} - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - continueOnError: ${{ parameters.continueOnError }} - condition: and(succeeded(), eq(variables['Agent.Os'], 'Windows_NT'), in(variables['_SignType'], 'real', 'test')) - - - ${{ if eq(parameters.enableMicrobuildForMacAndLinux, true) }}: - - task: MicroBuildSigningPlugin@4 - displayName: Install MicroBuild plugin (non-Windows) - inputs: + - template: /eng/common/core-templates/steps/install-microbuild-impl.yml + parameters: + enablePreviewMicrobuild: ${{ parameters.enablePreviewMicrobuild }} + microbuildTaskInputs: signType: $(_SignType) zipSources: false feedSource: https://dnceng.pkgs.visualstudio.com/_packaging/MicroBuildToolset/nuget/v3/index.json - workingDirectory: ${{ parameters.microBuildOutputFolder }} + version: ${{ parameters.microbuildPluginVersion }} ${{ if eq(parameters.microbuildUseESRP, true) }}: ConnectedServiceName: 'MicroBuild Signing Task (DevDiv)' ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - ConnectedPMEServiceName: beb8cb23-b303-4c95-ab26-9e44bc958d39 + ConnectedPMEServiceName: 6cc74545-d7b9-4050-9dfa-ebefcc8961ea ${{ else }}: - ConnectedPMEServiceName: c24de2a5-cc7a-493d-95e4-8e5ff5cad2bc - env: + ConnectedPMEServiceName: 248d384a-b39b-46e3-8ad5-c2c210d5e7ca + microbuildEnv: TeamName: $(_TeamName) MicroBuildOutputFolderOverride: ${{ parameters.microBuildOutputFolder }} SYSTEM_ACCESSTOKEN: $(System.AccessToken) continueOnError: ${{ parameters.continueOnError }} - condition: and(succeeded(), ne(variables['Agent.Os'], 'Windows_NT'), eq(variables['_SignType'], 'real')) + condition: and(succeeded(), eq(variables['Agent.Os'], 'Windows_NT'), in(variables['_SignType'], 'real', 'test')) + + - ${{ if eq(parameters.enableMicrobuildForMacAndLinux, true) }}: + - template: /eng/common/core-templates/steps/install-microbuild-impl.yml + parameters: + enablePreviewMicrobuild: ${{ parameters.enablePreviewMicrobuild }} + microbuildTaskInputs: + signType: $(_SignType) + zipSources: false + feedSource: https://dnceng.pkgs.visualstudio.com/_packaging/MicroBuildToolset/nuget/v3/index.json + version: ${{ parameters.microbuildPluginVersion }} + workingDirectory: ${{ parameters.microBuildOutputFolder }} + ${{ if eq(parameters.microbuildUseESRP, true) }}: + ConnectedServiceName: 'MicroBuild Signing Task (DevDiv)' + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + ConnectedPMEServiceName: beb8cb23-b303-4c95-ab26-9e44bc958d39 + ${{ else }}: + ConnectedPMEServiceName: c24de2a5-cc7a-493d-95e4-8e5ff5cad2bc + microbuildEnv: + TeamName: $(_TeamName) + MicroBuildOutputFolderOverride: ${{ parameters.microBuildOutputFolder }} + SYSTEM_ACCESSTOKEN: $(System.AccessToken) + continueOnError: ${{ parameters.continueOnError }} + condition: and(succeeded(), ne(variables['Agent.Os'], 'Windows_NT'), eq(variables['_SignType'], 'real')) diff --git a/eng/common/core-templates/steps/publish-logs.yml b/eng/common/core-templates/steps/publish-logs.yml index 694f55a926e..2731e48cce4 100644 --- a/eng/common/core-templates/steps/publish-logs.yml +++ b/eng/common/core-templates/steps/publish-logs.yml @@ -33,7 +33,6 @@ steps: '$(publishing-dnceng-devdiv-code-r-build-re)' '$(dn-bot-all-orgs-artifact-feeds-rw)' '$(akams-client-id)' - '$(dn-bot-all-orgs-build-rw-code-rw)' '$(System.AccessToken)' ${{parameters.CustomSensitiveDataList}} continueOnError: true @@ -58,3 +57,4 @@ steps: condition: always() retryCountOnTaskFailure: 10 # for any files being locked isProduction: false # logs are non-production artifacts + diff --git a/eng/common/core-templates/steps/send-to-helix.yml b/eng/common/core-templates/steps/send-to-helix.yml index 68fa739c4ab..ec7a2000399 100644 --- a/eng/common/core-templates/steps/send-to-helix.yml +++ b/eng/common/core-templates/steps/send-to-helix.yml @@ -10,6 +10,7 @@ parameters: HelixConfiguration: '' # optional -- additional property attached to a job HelixPreCommands: '' # optional -- commands to run before Helix work item execution HelixPostCommands: '' # optional -- commands to run after Helix work item execution + UseHelixMonitor: false # optional -- true will submit Helix jobs configured for the standalone Helix Job Monitor (results are reported/waited on out-of-band; this step will not wait, and WaitForWorkItemCompletion will be overridden) WorkItemDirectory: '' # optional -- a payload directory to zip up and send to Helix; requires WorkItemCommand; incompatible with XUnitProjects WorkItemCommand: '' # optional -- a command to execute on the payload; requires WorkItemDirectory; incompatible with XUnitProjects WorkItemTimeout: '' # optional -- a timeout in TimeSpan.Parse-ready value (e.g. 00:02:00) for the work item command; requires WorkItemDirectory; incompatible with XUnitProjects @@ -31,7 +32,15 @@ parameters: continueOnError: false # optional -- determines whether to continue the build if the step errors; defaults to false steps: - - powershell: 'powershell "$env:BUILD_SOURCESDIRECTORY\eng\common\msbuild.ps1 $env:BUILD_SOURCESDIRECTORY/${{ parameters.HelixProjectPath }} /restore /p:TreatWarningsAsErrors=false ${{ parameters.HelixProjectArguments }} /t:Test /bl:$env:BUILD_SOURCESDIRECTORY\artifacts\log\$env:BuildConfig\SendToHelix.binlog"' + - powershell: > + $(Build.SourcesDirectory)\eng\common\msbuild.ps1 + $(Build.SourcesDirectory)/${{ parameters.HelixProjectPath }} + /restore + /p:TreatWarningsAsErrors=false + /p:EnableHelixJobMonitor=${{ parameters.UseHelixMonitor }} + ${{ parameters.HelixProjectArguments }} + /t:Test + /bl:$(Build.SourcesDirectory)/artifacts/log/$(_BuildConfig)/SendToHelix.binlog displayName: ${{ parameters.DisplayNamePrefix }} (Windows) env: BuildConfig: $(_BuildConfig) @@ -61,7 +70,15 @@ steps: SYSTEM_ACCESSTOKEN: $(System.AccessToken) condition: and(${{ parameters.condition }}, eq(variables['Agent.Os'], 'Windows_NT')) continueOnError: ${{ parameters.continueOnError }} - - script: $BUILD_SOURCESDIRECTORY/eng/common/msbuild.sh $BUILD_SOURCESDIRECTORY/${{ parameters.HelixProjectPath }} /restore /p:TreatWarningsAsErrors=false ${{ parameters.HelixProjectArguments }} /t:Test /bl:$BUILD_SOURCESDIRECTORY/artifacts/log/$BuildConfig/SendToHelix.binlog + - script: > + $(Build.SourcesDirectory)/eng/common/msbuild.sh + $(Build.SourcesDirectory)/${{ parameters.HelixProjectPath }} + /restore + /p:TreatWarningsAsErrors=false + /p:EnableHelixJobMonitor=${{ parameters.UseHelixMonitor }} + ${{ parameters.HelixProjectArguments }} + /t:Test + /bl:$(Build.SourcesDirectory)/artifacts/log/$(_BuildConfig)/SendToHelix.binlog displayName: ${{ parameters.DisplayNamePrefix }} (Unix) env: BuildConfig: $(_BuildConfig) @@ -91,3 +108,4 @@ steps: SYSTEM_ACCESSTOKEN: $(System.AccessToken) condition: and(${{ parameters.condition }}, ne(variables['Agent.Os'], 'Windows_NT')) continueOnError: ${{ parameters.continueOnError }} + diff --git a/eng/common/core-templates/steps/source-build.yml b/eng/common/core-templates/steps/source-build.yml index 09ae5cd73ae..b75f59c428d 100644 --- a/eng/common/core-templates/steps/source-build.yml +++ b/eng/common/core-templates/steps/source-build.yml @@ -24,7 +24,7 @@ steps: # in the default public locations. internalRuntimeDownloadArgs= if [ '$(dotnetbuilds-internal-container-read-token-base64)' != '$''(dotnetbuilds-internal-container-read-token-base64)' ]; then - internalRuntimeDownloadArgs='/p:DotNetRuntimeSourceFeed=https://ci.dot.net/internal /p:DotNetRuntimeSourceFeedKey=$(dotnetbuilds-internal-container-read-token-base64) --runtimesourcefeed https://ci.dot.net/internal --runtimesourcefeedkey '$(dotnetbuilds-internal-container-read-token-base64)'' + internalRuntimeDownloadArgs='/p:DotNetRuntimeSourceFeed=https://ci.dot.net/internal /p:DotNetRuntimeSourceFeedKey=$(dotnetbuilds-internal-container-read-token-base64) --runtimesourcefeed https://ci.dot.net/internal --runtimesourcefeedkey $(dotnetbuilds-internal-container-read-token-base64)' fi buildConfig=Release diff --git a/eng/common/core-templates/steps/source-index-stage1-publish.yml b/eng/common/core-templates/steps/source-index-stage1-publish.yml index 6e7666b4dcf..fdca622357f 100644 --- a/eng/common/core-templates/steps/source-index-stage1-publish.yml +++ b/eng/common/core-templates/steps/source-index-stage1-publish.yml @@ -1,21 +1,21 @@ parameters: - sourceIndexUploadPackageVersion: 2.0.0-20250818.1 - sourceIndexProcessBinlogPackageVersion: 1.0.1-20250818.1 + sourceIndexUploadPackageVersion: 2.0.0-20260521.2 + sourceIndexProcessBinlogPackageVersion: 1.0.1-20260521.2 sourceIndexPackageSource: https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json binlogPath: artifacts/log/Debug/Build.binlog steps: - task: UseDotNet@2 - displayName: "Source Index: Use .NET 9 SDK" + displayName: "Source Index: Use .NET 10 SDK" inputs: packageType: sdk - version: 9.0.x + version: 10.0.x installationPath: $(Agent.TempDirectory)/dotnet workingDirectory: $(Agent.TempDirectory) - script: | - $(Agent.TempDirectory)/dotnet/dotnet tool install BinLogToSln --version ${{parameters.sourceIndexProcessBinlogPackageVersion}} --source ${{parameters.SourceIndexPackageSource}} --tool-path $(Agent.TempDirectory)/.source-index/tools - $(Agent.TempDirectory)/dotnet/dotnet tool install UploadIndexStage1 --version ${{parameters.sourceIndexUploadPackageVersion}} --source ${{parameters.SourceIndexPackageSource}} --tool-path $(Agent.TempDirectory)/.source-index/tools + $(Agent.TempDirectory)/dotnet/dotnet tool install BinLogToSln --version ${{parameters.sourceIndexProcessBinlogPackageVersion}} --source ${{parameters.sourceIndexPackageSource}} --tool-path $(Agent.TempDirectory)/.source-index/tools + $(Agent.TempDirectory)/dotnet/dotnet tool install UploadIndexStage1 --version ${{parameters.sourceIndexUploadPackageVersion}} --source ${{parameters.sourceIndexPackageSource}} --tool-path $(Agent.TempDirectory)/.source-index/tools displayName: "Source Index: Download netsourceindex Tools" # Set working directory to temp directory so 'dotnet' doesn't try to use global.json and use the repo's sdk. workingDirectory: $(Agent.TempDirectory) diff --git a/eng/common/cross/build-rootfs.sh b/eng/common/cross/build-rootfs.sh index 3150ccac6fc..38a3512f148 100755 --- a/eng/common/cross/build-rootfs.sh +++ b/eng/common/cross/build-rootfs.sh @@ -18,7 +18,10 @@ usage() echo "--skipsigcheck - optional, will skip package signature checks (allowing untrusted packages)." echo "--skipemulation - optional, will skip qemu and debootstrap requirement when building environment for debian based systems." echo "--use-mirror - optional, use mirror URL to fetch resources, when available." - echo "--jobs N - optional, restrict to N jobs." + echo "--ubuntu-repo - optional, override the Ubuntu apt repository base URL." + echo "--debian-repo - optional, override the Debian apt repository base URL." + echo "--alpine-repo - optional, override the Alpine Linux repository base URL." + echo "--jobs N (or --use-jobs N) - optional, restrict to N jobs." exit 1 } @@ -144,6 +147,9 @@ __KeyringFile="/usr/share/keyrings/ubuntu-archive-keyring.gpg" __SkipSigCheck=0 __SkipEmulation=0 __UseMirror=0 +__UbuntuRepoOverride= +__DebianRepoOverride= +__AlpineRepoOverride= __UnprocessedBuildArgs= while :; do @@ -397,6 +403,31 @@ while :; do --use-mirror) __UseMirror=1 ;; + --ubuntu-repo|-ubuntu-repo) + shift + if [[ "$#" -le 0 ]]; then + echo "ERROR: --ubuntu-repo requires a URL argument." + usage + fi + __UbuntuRepoOverride="$1" + ;; + --debian-repo|-debian-repo) + shift + if [[ "$#" -le 0 ]]; then + echo "ERROR: --debian-repo requires a URL argument." + usage + fi + __DebianRepoOverride="$1" + ;; + --alpine-repo|-alpine-repo) + shift + if [[ "$#" -le 0 ]]; then + echo "ERROR: --alpine-repo requires a URL argument." + usage + fi + __AlpineRepoOverride="$1" + ;; + # Removed duplicate/invalid option handling block (was breaking case statement parsing). --use-jobs) shift MAXJOBS=$1 @@ -422,9 +453,12 @@ case "$__AlpineVersion" in elif [[ "$__AlpineArch" == "x86" ]]; then __AlpineVersion=3.17 # minimum version that supports lldb-dev __AlpinePackages+=" llvm15-libs" - elif [[ "$__AlpineArch" == "riscv64" || "$__AlpineArch" == "loongarch64" ]]; then + elif [[ "$__AlpineArch" == "loongarch64" ]]; then __AlpineVersion=3.21 # minimum version that supports lldb-dev __AlpinePackages+=" llvm19-libs" + elif [[ "$__AlpineArch" == "riscv64" ]]; then + __AlpineVersion=3.22 # lldb-dev requires 3.21+, but 3.22+ provides the newer linux-headers needed for RISC-V extension probes + __AlpinePackages+=" llvm20-libs" elif [[ -n "$__AlpineMajorVersion" ]]; then # use whichever alpine version is provided and select the latest toolchain libs __AlpineLlvmLibsLookup=1 @@ -446,6 +480,12 @@ if [[ -z "$__UbuntuRepo" ]]; then __UbuntuRepo="https://ports.ubuntu.com/" fi +if [[ -n "$__UbuntuRepoOverride" && "$__KeyringFile" == *ubuntu* ]]; then + __UbuntuRepo="$__UbuntuRepoOverride" +elif [[ -n "$__DebianRepoOverride" && "$__KeyringFile" == *debian* ]]; then + __UbuntuRepo="$__DebianRepoOverride" +fi + if [[ -n "$__LLVM_MajorVersion" ]]; then __UbuntuPackages+=" libclang-common-${__LLVM_MajorVersion}${__LLVM_MinorVersion:+.$__LLVM_MinorVersion}-dev" fi @@ -486,6 +526,7 @@ if [[ "$__CodeName" == "alpine" ]]; then __ApkToolsDir="$(mktemp -d)" __ApkKeysDir="$(mktemp -d)" arch="$(uname -m)" + __AlpineRepo="${__AlpineRepoOverride:-https://dl-cdn.alpinelinux.org/alpine}" ensureDownloadTool @@ -530,15 +571,15 @@ if [[ "$__CodeName" == "alpine" ]]; then # initialize DB # shellcheck disable=SC2086 "$__ApkToolsDir/apk.static" \ - -X "https://dl-cdn.alpinelinux.org/alpine/$version/main" \ - -X "https://dl-cdn.alpinelinux.org/alpine/$version/community" \ + -X "$__AlpineRepo/$version/main" \ + -X "$__AlpineRepo/$version/community" \ -U $__ApkSignatureArg --root "$__RootfsDir" --arch "$__AlpineArch" --initdb add if [[ "$__AlpineLlvmLibsLookup" == 1 ]]; then # shellcheck disable=SC2086 __AlpinePackages+=" $("$__ApkToolsDir/apk.static" \ - -X "https://dl-cdn.alpinelinux.org/alpine/$version/main" \ - -X "https://dl-cdn.alpinelinux.org/alpine/$version/community" \ + -X "$__AlpineRepo/$version/main" \ + -X "$__AlpineRepo/$version/community" \ -U $__ApkSignatureArg --root "$__RootfsDir" --arch "$__AlpineArch" \ search 'llvm*-libs' | grep -E '^llvm' | sort | tail -1 | sed 's/-[^-]*//2g')" fi @@ -546,8 +587,8 @@ if [[ "$__CodeName" == "alpine" ]]; then # install all packages in one go # shellcheck disable=SC2086 "$__ApkToolsDir/apk.static" \ - -X "https://dl-cdn.alpinelinux.org/alpine/$version/main" \ - -X "https://dl-cdn.alpinelinux.org/alpine/$version/community" \ + -X "$__AlpineRepo/$version/main" \ + -X "$__AlpineRepo/$version/community" \ -U $__ApkSignatureArg --root "$__RootfsDir" --arch "$__AlpineArch" $__NoEmulationArg \ add $__AlpinePackages diff --git a/eng/common/cross/toolchain.cmake b/eng/common/cross/toolchain.cmake index f65c689f695..70b71395e3b 100644 --- a/eng/common/cross/toolchain.cmake +++ b/eng/common/cross/toolchain.cmake @@ -87,6 +87,8 @@ elseif(TARGET_ARCH_NAME STREQUAL "ppc64le") set(CMAKE_SYSTEM_PROCESSOR ppc64le) if(EXISTS ${CROSS_ROOTFS}/usr/lib/gcc/powerpc64le-alpine-linux-musl) set(TOOLCHAIN "powerpc64le-alpine-linux-musl") + elseif(FREEBSD) + set(TOOLCHAIN "powerpc64le-unknown-freebsd14") else() set(TOOLCHAIN "powerpc64le-linux-gnu") endif() @@ -159,6 +161,7 @@ if(TIZEN) else() find_toolchain_dir("${CROSS_ROOTFS}/usr/lib64/gcc/${TIZEN_TOOLCHAIN}") endif() + include_directories(SYSTEM ${TIZEN_TOOLCHAIN_PATH}/include/c++) include_directories(SYSTEM ${TIZEN_TOOLCHAIN_PATH}/include/c++/${TIZEN_TOOLCHAIN}) endif() @@ -226,7 +229,7 @@ elseif(HAIKU) set(CMAKE_C_STANDARD_LIBRARIES "${CMAKE_C_STANDARD_LIBRARIES} -lssp") set(CMAKE_CXX_STANDARD_LIBRARIES "${CMAKE_CXX_STANDARD_LIBRARIES} -lssp") - if ("$ENV{CCC_CC}" MATCHES ".*gcc.*") + if ($ENV{CCC_CC} MATCHES ".*gcc.*") set(CMAKE_PROGRAM_PATH "${CMAKE_PROGRAM_PATH};${CROSS_ROOTFS}/cross-tools-x86_64/bin") locate_toolchain_exec(gcc CMAKE_C_COMPILER) locate_toolchain_exec(g++ CMAKE_CXX_COMPILER) diff --git a/eng/common/darc-init.sh b/eng/common/darc-init.sh index e6ba4ee28c1..b56d40e5706 100755 --- a/eng/common/darc-init.sh +++ b/eng/common/darc-init.sh @@ -5,7 +5,7 @@ darcVersion='' versionEndpoint='https://maestro.dot.net/api/assets/darc-version?api-version=2020-02-20' verbosity='minimal' -while [[ $# > 0 ]]; do +while [[ $# -gt 0 ]]; do opt="$(echo "$1" | tr "[:upper:]" "[:lower:]")" case "$opt" in --darcversion) diff --git a/eng/common/dotnet-install.ps1 b/eng/common/dotnet-install.ps1 index 811f0f717f7..b6d45f2bdc4 100644 --- a/eng/common/dotnet-install.ps1 +++ b/eng/common/dotnet-install.ps1 @@ -4,13 +4,20 @@ Param( [string] $architecture = '', [string] $version = 'Latest', [string] $runtime = 'dotnet', + [string] $dotnetPath = '', [string] $RuntimeSourceFeed = '', [string] $RuntimeSourceFeedKey = '' ) . $PSScriptRoot\tools.ps1 -$dotnetRoot = Join-Path $RepoRoot '.dotnet' +if (-not [string]::IsNullOrEmpty($dotnetPath)) { + $dotnetRoot = $dotnetPath +} elseif (-not [string]::IsNullOrEmpty($env:DOTNET_GLOBAL_INSTALL_DIR)) { + $dotnetRoot = $env:DOTNET_GLOBAL_INSTALL_DIR +} else { + $dotnetRoot = Join-Path $RepoRoot '.dotnet' +} $installdir = $dotnetRoot try { diff --git a/eng/common/dotnet-install.sh b/eng/common/dotnet-install.sh index 7b9d97e3bd4..58a7e6f384e 100755 --- a/eng/common/dotnet-install.sh +++ b/eng/common/dotnet-install.sh @@ -16,9 +16,10 @@ scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" version='Latest' architecture='' runtime='dotnet' +dotnetPath='' runtimeSourceFeed='' runtimeSourceFeedKey='' -while [[ $# > 0 ]]; do +while [[ $# -gt 0 ]]; do opt="$(echo "$1" | tr "[:upper:]" "[:lower:]")" case "$opt" in -version|-v) @@ -33,6 +34,10 @@ while [[ $# > 0 ]]; do shift runtime="$1" ;; + -dotnetpath) + shift + dotnetPath="$1" + ;; -runtimesourcefeed) shift runtimeSourceFeed="$1" @@ -80,7 +85,13 @@ case $cpuname in ;; esac -dotnetRoot="${repo_root}.dotnet" +if [[ -n "${dotnetPath:-}" ]]; then + dotnetRoot="$dotnetPath" +elif [[ -n "${DOTNET_GLOBAL_INSTALL_DIR:-}" ]]; then + dotnetRoot="$DOTNET_GLOBAL_INSTALL_DIR" +else + dotnetRoot="${repo_root}.dotnet" +fi if [[ $architecture != "" ]] && [[ $architecture != $buildarch ]]; then dotnetRoot="$dotnetRoot/$architecture" fi diff --git a/eng/common/dotnet.sh b/eng/common/dotnet.sh index 2ef68235675..f6d24871c1d 100755 --- a/eng/common/dotnet.sh +++ b/eng/common/dotnet.sh @@ -19,7 +19,7 @@ source $scriptroot/tools.sh InitializeDotNetCli true # install # Invoke acquired SDK with args if they are provided -if [[ $# > 0 ]]; then +if [[ $# -gt 0 ]]; then __dotnetDir=${_InitializeDotNetCli} dotnetPath=${__dotnetDir}/dotnet ${dotnetPath} "$@" diff --git a/eng/common/internal-feed-operations.sh b/eng/common/internal-feed-operations.sh index 9378223ba09..6299e7effd4 100755 --- a/eng/common/internal-feed-operations.sh +++ b/eng/common/internal-feed-operations.sh @@ -100,7 +100,7 @@ operation='' authToken='' repoName='' -while [[ $# > 0 ]]; do +while [[ $# -gt 0 ]]; do opt="$(echo "$1" | tr "[:upper:]" "[:lower:]")" case "$opt" in --operation) diff --git a/eng/common/msbuild.ps1 b/eng/common/msbuild.ps1 index f041e5ddd95..495d533a909 100644 --- a/eng/common/msbuild.ps1 +++ b/eng/common/msbuild.ps1 @@ -14,7 +14,11 @@ Param( try { if ($ci) { - $nodeReuse = $false + # Disable node reuse on CI unless explicitly opted in via MSBUILD_NODEREUSE_ENABLED. + # Internal testing only; this env var will be replaced with a switch (https://github.com/dotnet/arcade/issues/17013) and must not be depended on. + if ($env:MSBUILD_NODEREUSE_ENABLED -ne "1") { + $nodeReuse = $false + } } MSBuild @extraArgs diff --git a/eng/common/msbuild.sh b/eng/common/msbuild.sh index 20d3dad5435..333be3232fc 100755 --- a/eng/common/msbuild.sh +++ b/eng/common/msbuild.sh @@ -51,7 +51,11 @@ done . "$scriptroot/tools.sh" if [[ "$ci" == true ]]; then - node_reuse=false + # Disable node reuse on CI unless explicitly opted in via MSBUILD_NODEREUSE_ENABLED. + # Internal testing only; this env var will be replaced with a switch (https://github.com/dotnet/arcade/issues/17013) and must not be depended on. + if [[ "${MSBUILD_NODEREUSE_ENABLED:-}" != "1" ]]; then + node_reuse=false + fi fi MSBuild $extra_args diff --git a/eng/common/native/NativeAotSupported.props b/eng/common/native/NativeAotSupported.props index 559a6663929..cdff9ef0361 100644 --- a/eng/common/native/NativeAotSupported.props +++ b/eng/common/native/NativeAotSupported.props @@ -13,6 +13,8 @@ <_NativeAotSupportedArch Condition=" '$(TargetArchitecture)' != 'wasm' and + '$(TargetArchitecture)' != 's390x' and + '$(TargetArchitecture)' != 'ppc64le' and ('$(TargetArchitecture)' != 'x86' or '$(TargetOS)' == 'windows') ">true diff --git a/eng/common/native/init-os-and-arch.sh b/eng/common/native/init-os-and-arch.sh index 38921d4338f..62d62fed522 100644 --- a/eng/common/native/init-os-and-arch.sh +++ b/eng/common/native/init-os-and-arch.sh @@ -27,6 +27,10 @@ if [ "$os" = "sunos" ]; then os="solaris" fi CPUName=$(isainfo -n) +elif [ "$os" = "freebsd" ]; then + # FreeBSD's `uname -m` is the machine class ("powerpc" for every PowerPC + # variant); `uname -p` gives the specific processor (e.g. powerpc64le). + CPUName=$(uname -p) else # For the rest of the operating systems, use uname(1) to determine what the CPU is. CPUName=$(uname -m) @@ -75,7 +79,7 @@ case "$CPUName" in arch=s390x ;; - ppc64le) + ppc64le|powerpc64le) arch=ppc64le ;; *) diff --git a/eng/common/pipeline-logging-functions.ps1 b/eng/common/pipeline-logging-functions.ps1 index 8e422c561e4..9f85c291708 100644 --- a/eng/common/pipeline-logging-functions.ps1 +++ b/eng/common/pipeline-logging-functions.ps1 @@ -32,7 +32,7 @@ function Write-PipelineTelemetryError { $PSBoundParameters.Remove('Category') | Out-Null if ($Force -Or ((Test-Path variable:ci) -And $ci)) { - $Message = "(NETCORE_ENGINEERING_TELEMETRY=$Category) $Message" + $Message = "($Category) $Message" } $PSBoundParameters.Remove('Message') | Out-Null $PSBoundParameters.Add('Message', $Message) diff --git a/eng/common/post-build/redact-logs.ps1 b/eng/common/post-build/redact-logs.ps1 index c1e4104b79a..672f4e2652e 100644 --- a/eng/common/post-build/redact-logs.ps1 +++ b/eng/common/post-build/redact-logs.ps1 @@ -9,7 +9,8 @@ param( [Parameter(Mandatory=$false)][string] $TokensFilePath, [Parameter(ValueFromRemainingArguments=$true)][String[]]$TokensToRedact, [Parameter(Mandatory=$false)][string] $runtimeSourceFeed, - [Parameter(Mandatory=$false)][string] $runtimeSourceFeedKey) + [Parameter(Mandatory=$false)][string] $runtimeSourceFeedKey +) try { $ErrorActionPreference = 'Stop' diff --git a/eng/common/post-build/sourcelink-validation.ps1 b/eng/common/post-build/sourcelink-validation.ps1 deleted file mode 100644 index 1976ef70fb8..00000000000 --- a/eng/common/post-build/sourcelink-validation.ps1 +++ /dev/null @@ -1,327 +0,0 @@ -param( - [Parameter(Mandatory=$true)][string] $InputPath, # Full path to directory where Symbols.NuGet packages to be checked are stored - [Parameter(Mandatory=$true)][string] $ExtractPath, # Full path to directory where the packages will be extracted during validation - [Parameter(Mandatory=$false)][string] $GHRepoName, # GitHub name of the repo including the Org. E.g., dotnet/arcade - [Parameter(Mandatory=$false)][string] $GHCommit, # GitHub commit SHA used to build the packages - [Parameter(Mandatory=$true)][string] $SourcelinkCliVersion # Version of SourceLink CLI to use -) - -$ErrorActionPreference = 'Stop' -Set-StrictMode -Version 2.0 - -# `tools.ps1` checks $ci to perform some actions. Since the post-build -# scripts don't necessarily execute in the same agent that run the -# build.ps1/sh script this variable isn't automatically set. -$ci = $true -$disableConfigureToolsetImport = $true -. $PSScriptRoot\..\tools.ps1 - -# Cache/HashMap (File -> Exist flag) used to consult whether a file exist -# in the repository at a specific commit point. This is populated by inserting -# all files present in the repo at a specific commit point. -$global:RepoFiles = @{} - -# Maximum number of jobs to run in parallel -$MaxParallelJobs = 16 - -$MaxRetries = 5 -$RetryWaitTimeInSeconds = 30 - -# Wait time between check for system load -$SecondsBetweenLoadChecks = 10 - -if (!$InputPath -or !(Test-Path $InputPath)){ - Write-Host "No files to validate." - ExitWithExitCode 0 -} - -$ValidatePackage = { - param( - [string] $PackagePath # Full path to a Symbols.NuGet package - ) - - . $using:PSScriptRoot\..\tools.ps1 - - # Ensure input file exist - if (!(Test-Path $PackagePath)) { - Write-Host "Input file does not exist: $PackagePath" - return [pscustomobject]@{ - result = 1 - packagePath = $PackagePath - } - } - - # Extensions for which we'll look for SourceLink information - # For now we'll only care about Portable & Embedded PDBs - $RelevantExtensions = @('.dll', '.exe', '.pdb') - - Write-Host -NoNewLine 'Validating ' ([System.IO.Path]::GetFileName($PackagePath)) '...' - - $PackageId = [System.IO.Path]::GetFileNameWithoutExtension($PackagePath) - $ExtractPath = Join-Path -Path $using:ExtractPath -ChildPath $PackageId - $FailedFiles = 0 - - Add-Type -AssemblyName System.IO.Compression.FileSystem - - [System.IO.Directory]::CreateDirectory($ExtractPath) | Out-Null - - try { - $zip = [System.IO.Compression.ZipFile]::OpenRead($PackagePath) - - $zip.Entries | - Where-Object {$RelevantExtensions -contains [System.IO.Path]::GetExtension($_.Name)} | - ForEach-Object { - $FileName = $_.FullName - $Extension = [System.IO.Path]::GetExtension($_.Name) - $FakeName = -Join((New-Guid), $Extension) - $TargetFile = Join-Path -Path $ExtractPath -ChildPath $FakeName - - # We ignore resource DLLs - if ($FileName.EndsWith('.resources.dll')) { - return [pscustomobject]@{ - result = 0 - packagePath = $PackagePath - } - } - - [System.IO.Compression.ZipFileExtensions]::ExtractToFile($_, $TargetFile, $true) - - $ValidateFile = { - param( - [string] $FullPath, # Full path to the module that has to be checked - [string] $RealPath, - [ref] $FailedFiles - ) - - $sourcelinkExe = "$env:USERPROFILE\.dotnet\tools" - $sourcelinkExe = Resolve-Path "$sourcelinkExe\sourcelink.exe" - $SourceLinkInfos = & $sourcelinkExe print-urls $FullPath | Out-String - - if ($LASTEXITCODE -eq 0 -and -not ([string]::IsNullOrEmpty($SourceLinkInfos))) { - $NumFailedLinks = 0 - - # We only care about Http addresses - $Matches = (Select-String '(http[s]?)(:\/\/)([^\s,]+)' -Input $SourceLinkInfos -AllMatches).Matches - - if ($Matches.Count -ne 0) { - $Matches.Value | - ForEach-Object { - $Link = $_ - $CommitUrl = "https://raw.githubusercontent.com/${using:GHRepoName}/${using:GHCommit}/" - - $FilePath = $Link.Replace($CommitUrl, "") - $Status = 200 - $Cache = $using:RepoFiles - - $attempts = 0 - - while ($attempts -lt $using:MaxRetries) { - if ( !($Cache.ContainsKey($FilePath)) ) { - try { - $Uri = $Link -as [System.URI] - - if ($Link -match "submodules") { - # Skip submodule links until sourcelink properly handles submodules - $Status = 200 - } - elseif ($Uri.AbsoluteURI -ne $null -and ($Uri.Host -match 'github' -or $Uri.Host -match 'githubusercontent')) { - # Only GitHub links are valid - $Status = (Invoke-WebRequest -Uri $Link -UseBasicParsing -Method HEAD -TimeoutSec 5).StatusCode - } - else { - # If it's not a github link, we want to break out of the loop and not retry. - $Status = 0 - $attempts = $using:MaxRetries - } - } - catch { - Write-Host $_ - $Status = 0 - } - } - - if ($Status -ne 200) { - $attempts++ - - if ($attempts -lt $using:MaxRetries) - { - $attemptsLeft = $using:MaxRetries - $attempts - Write-Warning "Download failed, $attemptsLeft attempts remaining, will retry in $using:RetryWaitTimeInSeconds seconds" - Start-Sleep -Seconds $using:RetryWaitTimeInSeconds - } - else { - if ($NumFailedLinks -eq 0) { - if ($FailedFiles.Value -eq 0) { - Write-Host - } - - Write-Host "`tFile $RealPath has broken links:" - } - - Write-Host "`t`tFailed to retrieve $Link" - - $NumFailedLinks++ - } - } - else { - break - } - } - } - } - - if ($NumFailedLinks -ne 0) { - $FailedFiles.value++ - $global:LASTEXITCODE = 1 - } - } - } - - &$ValidateFile $TargetFile $FileName ([ref]$FailedFiles) - } - } - catch { - Write-Host $_ - } - finally { - $zip.Dispose() - } - - if ($FailedFiles -eq 0) { - Write-Host 'Passed.' - return [pscustomobject]@{ - result = 0 - packagePath = $PackagePath - } - } - else { - Write-PipelineTelemetryError -Category 'SourceLink' -Message "$PackagePath has broken SourceLink links." - return [pscustomobject]@{ - result = 1 - packagePath = $PackagePath - } - } -} - -function CheckJobResult( - $result, - $packagePath, - [ref]$ValidationFailures, - [switch]$logErrors) { - if ($result -ne '0') { - if ($logErrors) { - Write-PipelineTelemetryError -Category 'SourceLink' -Message "$packagePath has broken SourceLink links." - } - $ValidationFailures.Value++ - } -} - -function ValidateSourceLinkLinks { - if ($GHRepoName -ne '' -and !($GHRepoName -Match '^[^\s\/]+/[^\s\/]+$')) { - if (!($GHRepoName -Match '^[^\s-]+-[^\s]+$')) { - Write-PipelineTelemetryError -Category 'SourceLink' -Message "GHRepoName should be in the format / or -. '$GHRepoName'" - ExitWithExitCode 1 - } - else { - $GHRepoName = $GHRepoName -replace '^([^\s-]+)-([^\s]+)$', '$1/$2'; - } - } - - if ($GHCommit -ne '' -and !($GHCommit -Match '^[0-9a-fA-F]{40}$')) { - Write-PipelineTelemetryError -Category 'SourceLink' -Message "GHCommit should be a 40 chars hexadecimal string. '$GHCommit'" - ExitWithExitCode 1 - } - - if ($GHRepoName -ne '' -and $GHCommit -ne '') { - $RepoTreeURL = -Join('https://api.github.com/repos/', $GHRepoName, '/git/trees/', $GHCommit, '?recursive=1') - $CodeExtensions = @('.cs', '.vb', '.fs', '.fsi', '.fsx', '.fsscript') - - try { - # Retrieve the list of files in the repo at that particular commit point and store them in the RepoFiles hash - $Data = Invoke-WebRequest $RepoTreeURL -UseBasicParsing | ConvertFrom-Json | Select-Object -ExpandProperty tree - - foreach ($file in $Data) { - $Extension = [System.IO.Path]::GetExtension($file.path) - - if ($CodeExtensions.Contains($Extension)) { - $RepoFiles[$file.path] = 1 - } - } - } - catch { - Write-Host "Problems downloading the list of files from the repo. Url used: $RepoTreeURL . Execution will proceed without caching." - } - } - elseif ($GHRepoName -ne '' -or $GHCommit -ne '') { - Write-Host 'For using the http caching mechanism both GHRepoName and GHCommit should be informed.' - } - - if (Test-Path $ExtractPath) { - Remove-Item $ExtractPath -Force -Recurse -ErrorAction SilentlyContinue - } - - $ValidationFailures = 0 - - # Process each NuGet package in parallel - Get-ChildItem "$InputPath\*.symbols.nupkg" | - ForEach-Object { - Write-Host "Starting $($_.FullName)" - Start-Job -ScriptBlock $ValidatePackage -ArgumentList $_.FullName | Out-Null - $NumJobs = @(Get-Job -State 'Running').Count - - while ($NumJobs -ge $MaxParallelJobs) { - Write-Host "There are $NumJobs validation jobs running right now. Waiting $SecondsBetweenLoadChecks seconds to check again." - sleep $SecondsBetweenLoadChecks - $NumJobs = @(Get-Job -State 'Running').Count - } - - foreach ($Job in @(Get-Job -State 'Completed')) { - $jobResult = Wait-Job -Id $Job.Id | Receive-Job - CheckJobResult $jobResult.result $jobResult.packagePath ([ref]$ValidationFailures) -LogErrors - Remove-Job -Id $Job.Id - } - } - - foreach ($Job in @(Get-Job)) { - $jobResult = Wait-Job -Id $Job.Id | Receive-Job - CheckJobResult $jobResult.result $jobResult.packagePath ([ref]$ValidationFailures) - Remove-Job -Id $Job.Id - } - if ($ValidationFailures -gt 0) { - Write-PipelineTelemetryError -Category 'SourceLink' -Message "$ValidationFailures package(s) failed validation." - ExitWithExitCode 1 - } -} - -function InstallSourcelinkCli { - $sourcelinkCliPackageName = 'sourcelink' - - $dotnetRoot = InitializeDotNetCli -install:$true - $dotnet = "$dotnetRoot\dotnet.exe" - $toolList = & "$dotnet" tool list --global - - if (($toolList -like "*$sourcelinkCliPackageName*") -and ($toolList -like "*$sourcelinkCliVersion*")) { - Write-Host "SourceLink CLI version $sourcelinkCliVersion is already installed." - } - else { - Write-Host "Installing SourceLink CLI version $sourcelinkCliVersion..." - Write-Host 'You may need to restart your command window if this is the first dotnet tool you have installed.' - & "$dotnet" tool install $sourcelinkCliPackageName --version $sourcelinkCliVersion --verbosity "minimal" --global - } -} - -try { - InstallSourcelinkCli - - foreach ($Job in @(Get-Job)) { - Remove-Job -Id $Job.Id - } - - ValidateSourceLinkLinks -} -catch { - Write-Host $_.Exception - Write-Host $_.ScriptStackTrace - Write-PipelineTelemetryError -Category 'SourceLink' -Message $_ - ExitWithExitCode 1 -} diff --git a/eng/common/renovate.env b/eng/common/renovate.env new file mode 100644 index 00000000000..17ecc05d9b1 --- /dev/null +++ b/eng/common/renovate.env @@ -0,0 +1,42 @@ +# Renovate Global Configuration +# https://docs.renovatebot.com/self-hosted-configuration/ +# +# NOTE: This file uses bash/shell format and is sourced via `. renovate.env`. +# Values containing spaces or special characters must be quoted. + +# Author to use for git commits made by Renovate +# https://docs.renovatebot.com/configuration-options/#gitauthor +export RENOVATE_GIT_AUTHOR='.NET Renovate ' + +# Disable rate limiting for PR creation (0 = unlimited) +# https://docs.renovatebot.com/presets-default/#prhourlylimitnone +# https://docs.renovatebot.com/presets-default/#prconcurrentlimitnone +export RENOVATE_PR_HOURLY_LIMIT=0 +export RENOVATE_PR_CONCURRENT_LIMIT=0 + +# Skip the onboarding PR that Renovate normally creates for new repos +# https://docs.renovatebot.com/config-overview/#onboarding +export RENOVATE_ONBOARDING=false + +# Any Renovate config file in the cloned repository is ignored. Only +# the Renovate config file from the repo where the pipeline is running +# is used (yes, those are the same repo but the sources may be different). +# https://docs.renovatebot.com/self-hosted-configuration/#requireconfig +export RENOVATE_REQUIRE_CONFIG=ignored + +# Customize the PR body content. This removes some of the default +# sections that aren't relevant in a self-hosted config. +# https://docs.renovatebot.com/configuration-options/#prheader +# https://docs.renovatebot.com/configuration-options/#prbodynotes +# https://docs.renovatebot.com/configuration-options/#prbodytemplate +export RENOVATE_PR_HEADER='## Automated Dependency Update' +export RENOVATE_PR_BODY_NOTES='["This PR has been created automatically by the [.NET Renovate Bot](https://github.com/dotnet/arcade/blob/main/Documentation/Renovate.md) to update one or more dependencies in your repo. Please review the changes and merge the PR if everything looks good."]' +export RENOVATE_PR_BODY_TEMPLATE='{{{header}}}{{{table}}}{{{warnings}}}{{{notes}}}{{{changelogs}}}' + +# Extend the global config with additional presets +# https://docs.renovatebot.com/self-hosted-configuration/#globalextends +# Disable the Dependency Dashboard issue that tracks all updates +export RENOVATE_GLOBAL_EXTENDS='[":disableDependencyDashboard"]' + +# Allow all commands for post-upgrade commands. +export RENOVATE_ALLOWED_COMMANDS='[".*"]' diff --git a/eng/common/sdk-task.ps1 b/eng/common/sdk-task.ps1 index b64b66a6275..8d72d803dd2 100644 --- a/eng/common/sdk-task.ps1 +++ b/eng/common/sdk-task.ps1 @@ -4,7 +4,9 @@ Param( [string] $task, [string] $verbosity = 'minimal', [string] $msbuildEngine = $null, - [switch] $restore, + # Restore defaults to on; -restore is retained only so existing consumers that pass it don't break. Use -norestore to opt out. + [switch] $restore = $true, + [switch] $norestore, [switch] $prepareMachine, [switch][Alias('nobl')]$excludeCIBinaryLog, [switch]$noWarnAsError, @@ -18,12 +20,23 @@ $ci = $true $binaryLog = if ($excludeCIBinaryLog) { $false } else { $true } $warnAsError = if ($noWarnAsError) { $false } else { $true } +# Reconcile the restore state before importing tools.ps1: it reads $restore at import time to +# decide whether toolset/SDK acquisition installs. -norestore must win so that skipping restore +# also skips toolset initialization, not just the explicit Restore build below. +if ($norestore) { $restore = $false } + +# sdk-task runs a standalone Arcade SDK task and does not need repo-specific toolset setup. +# Skip importing configure-toolset.ps1 so its side effects (e.g. a repo's configure-toolset.ps1 +# calling exit) don't terminate this script before the task runs. +$disableConfigureToolsetImport = $true + . $PSScriptRoot\tools.ps1 function Print-Usage() { Write-Host "Common settings:" - Write-Host " -task Name of Arcade task (name of a project in SdkTasks directory of the Arcade SDK package)" - Write-Host " -restore Restore dependencies" + Write-Host " -task Name of Arcade task (name of a project in toolset directory of the Arcade SDK package)" + Write-Host " -restore (Legacy) Restore runs by default; retained for backward compatibility. Use -norestore to skip" + Write-Host " -norestore Skip restoring dependencies" Write-Host " -verbosity Msbuild verbosity: q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic]" Write-Host " -help Print help and exit" Write-Host "" @@ -66,20 +79,7 @@ try { if( $msbuildEngine -eq "vs") { # Ensure desktop MSBuild is available for sdk tasks. - if( -not ($GlobalJson.tools.PSObject.Properties.Name -contains "vs" )) { - $GlobalJson.tools | Add-Member -Name "vs" -Value (ConvertFrom-Json "{ `"version`": `"16.5`" }") -MemberType NoteProperty - } - if( -not ($GlobalJson.tools.PSObject.Properties.Name -match "xcopy-msbuild" )) { - $GlobalJson.tools | Add-Member -Name "xcopy-msbuild" -Value "18.0.0" -MemberType NoteProperty - } - if ($GlobalJson.tools."xcopy-msbuild".Trim() -ine "none") { - $xcopyMSBuildToolsFolder = InitializeXCopyMSBuild $GlobalJson.tools."xcopy-msbuild" -install $true - } - if ($xcopyMSBuildToolsFolder -eq $null) { - throw 'Unable to get xcopy downloadable version of msbuild' - } - - $global:_MSBuildExe = "$($xcopyMSBuildToolsFolder)\MSBuild\Current\Bin\MSBuild.exe" + $global:_MSBuildExe = InitializeVisualStudioMSBuild } $taskProject = GetSdkTaskProject $task diff --git a/eng/common/sdk-task.sh b/eng/common/sdk-task.sh index 3270f83fa9a..a7f1ba060d7 100644 --- a/eng/common/sdk-task.sh +++ b/eng/common/sdk-task.sh @@ -2,8 +2,9 @@ show_usage() { echo "Common settings:" - echo " --task Name of Arcade task (name of a project in SdkTasks directory of the Arcade SDK package)" - echo " --restore Restore dependencies" + echo " --task Name of Arcade task (name of a project in toolset directory of the Arcade SDK package)" + echo " --restore (Legacy) Restore runs by default; retained for backward compatibility. Use --norestore to skip" + echo " --norestore Skip restoring dependencies" echo " --verbosity Msbuild verbosity: q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic]" echo " --help Print help and exit" echo "" @@ -50,10 +51,11 @@ binary_log=true configuration="Debug" verbosity="minimal" exclude_ci_binary_log=false -restore=false +# restore defaults to on; --restore is retained only so existing consumers that pass it don't break. Use --norestore to opt out. +restore=true help=false properties='' -warnAsError=true +warn_as_error=true while (($# > 0)); do lowerI="$(echo $1 | tr "[:upper:]" "[:lower:]")" @@ -63,7 +65,10 @@ while (($# > 0)); do shift 2 ;; --restore) - restore=true + shift 1 + ;; + --norestore) + restore=false shift 1 ;; --verbosity) @@ -75,8 +80,8 @@ while (($# > 0)); do exclude_ci_binary_log=true shift 1 ;; - --noWarnAsError) - warnAsError=false + --nowarnaserror) + warn_as_error=false shift 1 ;; --help) @@ -97,6 +102,11 @@ if $help; then exit 0 fi +# sdk-task runs a standalone Arcade SDK task and does not need repo-specific toolset setup. +# Skip importing configure-toolset.sh so its side effects (e.g. a repo's configure-toolset.sh +# calling exit) don't terminate this script before the task runs. +disable_configure_toolset_import=1 + . "$scriptroot/tools.sh" InitializeToolset diff --git a/eng/common/sdl/NuGet.config b/eng/common/sdl/NuGet.config deleted file mode 100644 index 3849bdb3cf5..00000000000 --- a/eng/common/sdl/NuGet.config +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/eng/common/sdl/configure-sdl-tool.ps1 b/eng/common/sdl/configure-sdl-tool.ps1 deleted file mode 100644 index 27f5a4115fc..00000000000 --- a/eng/common/sdl/configure-sdl-tool.ps1 +++ /dev/null @@ -1,130 +0,0 @@ -Param( - [string] $GuardianCliLocation, - [string] $WorkingDirectory, - [string] $TargetDirectory, - [string] $GdnFolder, - # The list of Guardian tools to configure. For each object in the array: - # - If the item is a [hashtable], it must contain these entries: - # - Name = The tool name as Guardian knows it. - # - Scenario = (Optional) Scenario-specific name for this configuration entry. It must be unique - # among all tool entries with the same Name. - # - Args = (Optional) Array of Guardian tool configuration args, like '@("Target > C:\temp")' - # - If the item is a [string] $v, it is treated as '@{ Name="$v" }' - [object[]] $ToolsList, - [string] $GuardianLoggerLevel='Standard', - # Optional: Additional params to add to any tool using CredScan. - [string[]] $CrScanAdditionalRunConfigParams, - # Optional: Additional params to add to any tool using PoliCheck. - [string[]] $PoliCheckAdditionalRunConfigParams, - # Optional: Additional params to add to any tool using CodeQL/Semmle. - [string[]] $CodeQLAdditionalRunConfigParams, - # Optional: Additional params to add to any tool using Binskim. - [string[]] $BinskimAdditionalRunConfigParams -) - -$ErrorActionPreference = 'Stop' -Set-StrictMode -Version 2.0 -$disableConfigureToolsetImport = $true -$global:LASTEXITCODE = 0 - -try { - # `tools.ps1` checks $ci to perform some actions. Since the SDL - # scripts don't necessarily execute in the same agent that run the - # build.ps1/sh script this variable isn't automatically set. - $ci = $true - . $PSScriptRoot\..\tools.ps1 - - # Normalize tools list: all in [hashtable] form with defined values for each key. - $ToolsList = $ToolsList | - ForEach-Object { - if ($_ -is [string]) { - $_ = @{ Name = $_ } - } - - if (-not ($_['Scenario'])) { $_.Scenario = "" } - if (-not ($_['Args'])) { $_.Args = @() } - $_ - } - - Write-Host "List of tools to configure:" - $ToolsList | ForEach-Object { $_ | Out-String | Write-Host } - - # We store config files in the r directory of .gdn - $gdnConfigPath = Join-Path $GdnFolder 'r' - $ValidPath = Test-Path $GuardianCliLocation - - if ($ValidPath -eq $False) - { - Write-PipelineTelemetryError -Force -Category 'Sdl' -Message "Invalid Guardian CLI Location." - ExitWithExitCode 1 - } - - foreach ($tool in $ToolsList) { - # Put together the name and scenario to make a unique key. - $toolConfigName = $tool.Name - if ($tool.Scenario) { - $toolConfigName += "_" + $tool.Scenario - } - - Write-Host "=== Configuring $toolConfigName..." - - $gdnConfigFile = Join-Path $gdnConfigPath "$toolConfigName-configure.gdnconfig" - - # For some tools, add default and automatic args. - switch -Exact ($tool.Name) { - 'credscan' { - if ($targetDirectory) { - $tool.Args += "`"TargetDirectory < $TargetDirectory`"" - } - $tool.Args += "`"OutputType < pre`"" - $tool.Args += $CrScanAdditionalRunConfigParams - } - 'policheck' { - if ($targetDirectory) { - $tool.Args += "`"Target < $TargetDirectory`"" - } - $tool.Args += $PoliCheckAdditionalRunConfigParams - } - {$_ -in 'semmle', 'codeql'} { - if ($targetDirectory) { - $tool.Args += "`"SourceCodeDirectory < $TargetDirectory`"" - } - $tool.Args += $CodeQLAdditionalRunConfigParams - } - 'binskim' { - if ($targetDirectory) { - # Binskim crashes due to specific PDBs. GitHub issue: https://github.com/microsoft/binskim/issues/924. - # We are excluding all `_.pdb` files from the scan. - $tool.Args += "`"Target < $TargetDirectory\**;-:file|$TargetDirectory\**\_.pdb`"" - } - $tool.Args += $BinskimAdditionalRunConfigParams - } - } - - # Create variable pointing to the args array directly so we can use splat syntax later. - $toolArgs = $tool.Args - - # Configure the tool. If args array is provided or the current tool has some default arguments - # defined, add "--args" and splat each element on the end. Arg format is "{Arg id} < {Value}", - # one per parameter. Doc page for "guardian configure": - # https://dev.azure.com/securitytools/SecurityIntegration/_wiki/wikis/Guardian/1395/configure - Exec-BlockVerbosely { - & $GuardianCliLocation configure ` - --working-directory $WorkingDirectory ` - --tool $tool.Name ` - --output-path $gdnConfigFile ` - --logger-level $GuardianLoggerLevel ` - --noninteractive ` - --force ` - $(if ($toolArgs) { "--args" }) @toolArgs - Exit-IfNZEC "Sdl" - } - - Write-Host "Created '$toolConfigName' configuration file: $gdnConfigFile" - } -} -catch { - Write-Host $_.ScriptStackTrace - Write-PipelineTelemetryError -Force -Category 'Sdl' -Message $_ - ExitWithExitCode 1 -} diff --git a/eng/common/sdl/execute-all-sdl-tools.ps1 b/eng/common/sdl/execute-all-sdl-tools.ps1 deleted file mode 100644 index 4715d75e974..00000000000 --- a/eng/common/sdl/execute-all-sdl-tools.ps1 +++ /dev/null @@ -1,167 +0,0 @@ -Param( - [string] $GuardianPackageName, # Required: the name of guardian CLI package (not needed if GuardianCliLocation is specified) - [string] $NugetPackageDirectory, # Required: directory where NuGet packages are installed (not needed if GuardianCliLocation is specified) - [string] $GuardianCliLocation, # Optional: Direct location of Guardian CLI executable if GuardianPackageName & NugetPackageDirectory are not specified - [string] $Repository=$env:BUILD_REPOSITORY_NAME, # Required: the name of the repository (e.g. dotnet/arcade) - [string] $BranchName=$env:BUILD_SOURCEBRANCH, # Optional: name of branch or version of gdn settings; defaults to master - [string] $SourceDirectory=$env:BUILD_SOURCESDIRECTORY, # Required: the directory where source files are located - [string] $ArtifactsDirectory = (Join-Path $env:BUILD_ARTIFACTSTAGINGDIRECTORY ('artifacts')), # Required: the directory where build artifacts are located - [string] $AzureDevOpsAccessToken, # Required: access token for dnceng; should be provided via KeyVault - - # Optional: list of SDL tools to run on source code. See 'configure-sdl-tool.ps1' for tools list - # format. - [object[]] $SourceToolsList, - # Optional: list of SDL tools to run on built artifacts. See 'configure-sdl-tool.ps1' for tools - # list format. - [object[]] $ArtifactToolsList, - # Optional: list of SDL tools to run without automatically specifying a target directory. See - # 'configure-sdl-tool.ps1' for tools list format. - [object[]] $CustomToolsList, - - [bool] $TsaPublish=$False, # Optional: true will publish results to TSA; only set to true after onboarding to TSA; TSA is the automated framework used to upload test results as bugs. - [string] $TsaBranchName=$env:BUILD_SOURCEBRANCH, # Optional: required for TSA publish; defaults to $(Build.SourceBranchName); TSA is the automated framework used to upload test results as bugs. - [string] $TsaRepositoryName=$env:BUILD_REPOSITORY_NAME, # Optional: TSA repository name; will be generated automatically if not submitted; TSA is the automated framework used to upload test results as bugs. - [string] $BuildNumber=$env:BUILD_BUILDNUMBER, # Optional: required for TSA publish; defaults to $(Build.BuildNumber) - [bool] $UpdateBaseline=$False, # Optional: if true, will update the baseline in the repository; should only be run after fixing any issues which need to be fixed - [bool] $TsaOnboard=$False, # Optional: if true, will onboard the repository to TSA; should only be run once; TSA is the automated framework used to upload test results as bugs. - [string] $TsaInstanceUrl, # Optional: only needed if TsaOnboard or TsaPublish is true; the instance-url registered with TSA; TSA is the automated framework used to upload test results as bugs. - [string] $TsaCodebaseName, # Optional: only needed if TsaOnboard or TsaPublish is true; the name of the codebase registered with TSA; TSA is the automated framework used to upload test results as bugs. - [string] $TsaProjectName, # Optional: only needed if TsaOnboard or TsaPublish is true; the name of the project registered with TSA; TSA is the automated framework used to upload test results as bugs. - [string] $TsaNotificationEmail, # Optional: only needed if TsaOnboard is true; the email(s) which will receive notifications of TSA bug filings (e.g. alias@microsoft.com); TSA is the automated framework used to upload test results as bugs. - [string] $TsaCodebaseAdmin, # Optional: only needed if TsaOnboard is true; the aliases which are admins of the TSA codebase (e.g. DOMAIN\alias); TSA is the automated framework used to upload test results as bugs. - [string] $TsaBugAreaPath, # Optional: only needed if TsaOnboard is true; the area path where TSA will file bugs in AzDO; TSA is the automated framework used to upload test results as bugs. - [string] $TsaIterationPath, # Optional: only needed if TsaOnboard is true; the iteration path where TSA will file bugs in AzDO; TSA is the automated framework used to upload test results as bugs. - [string] $GuardianLoggerLevel='Standard', # Optional: the logger level for the Guardian CLI; options are Trace, Verbose, Standard, Warning, and Error - [string[]] $CrScanAdditionalRunConfigParams, # Optional: Additional Params to custom build a CredScan run config in the format @("xyz:abc","sdf:1") - [string[]] $PoliCheckAdditionalRunConfigParams, # Optional: Additional Params to custom build a Policheck run config in the format @("xyz:abc","sdf:1") - [string[]] $CodeQLAdditionalRunConfigParams, # Optional: Additional Params to custom build a Semmle/CodeQL run config in the format @("xyz < abc","sdf < 1") - [string[]] $BinskimAdditionalRunConfigParams, # Optional: Additional Params to custom build a Binskim run config in the format @("xyz < abc","sdf < 1") - [bool] $BreakOnFailure=$False # Optional: Fail the build if there were errors during the run -) - -try { - $ErrorActionPreference = 'Stop' - Set-StrictMode -Version 2.0 - $disableConfigureToolsetImport = $true - $global:LASTEXITCODE = 0 - - # `tools.ps1` checks $ci to perform some actions. Since the SDL - # scripts don't necessarily execute in the same agent that run the - # build.ps1/sh script this variable isn't automatically set. - $ci = $true - . $PSScriptRoot\..\tools.ps1 - - #Replace repo names to the format of org/repo - if (!($Repository.contains('/'))) { - $RepoName = $Repository -replace '(.*?)-(.*)', '$1/$2'; - } - else{ - $RepoName = $Repository; - } - - if ($GuardianPackageName) { - $guardianCliLocation = Join-Path $NugetPackageDirectory (Join-Path $GuardianPackageName (Join-Path 'tools' 'guardian.cmd')) - } else { - $guardianCliLocation = $GuardianCliLocation - } - - $workingDirectory = (Split-Path $SourceDirectory -Parent) - $ValidPath = Test-Path $guardianCliLocation - - if ($ValidPath -eq $False) - { - Write-PipelineTelemetryError -Force -Category 'Sdl' -Message 'Invalid Guardian CLI Location.' - ExitWithExitCode 1 - } - - Exec-BlockVerbosely { - & $(Join-Path $PSScriptRoot 'init-sdl.ps1') -GuardianCliLocation $guardianCliLocation -Repository $RepoName -BranchName $BranchName -WorkingDirectory $workingDirectory -AzureDevOpsAccessToken $AzureDevOpsAccessToken -GuardianLoggerLevel $GuardianLoggerLevel - } - $gdnFolder = Join-Path $workingDirectory '.gdn' - - if ($TsaOnboard) { - if ($TsaCodebaseName -and $TsaNotificationEmail -and $TsaCodebaseAdmin -and $TsaBugAreaPath) { - Exec-BlockVerbosely { - & $guardianCliLocation tsa-onboard --codebase-name "$TsaCodebaseName" --notification-alias "$TsaNotificationEmail" --codebase-admin "$TsaCodebaseAdmin" --instance-url "$TsaInstanceUrl" --project-name "$TsaProjectName" --area-path "$TsaBugAreaPath" --iteration-path "$TsaIterationPath" --working-directory $workingDirectory --logger-level $GuardianLoggerLevel - } - if ($LASTEXITCODE -ne 0) { - Write-PipelineTelemetryError -Force -Category 'Sdl' -Message "Guardian tsa-onboard failed with exit code $LASTEXITCODE." - ExitWithExitCode $LASTEXITCODE - } - } else { - Write-PipelineTelemetryError -Force -Category 'Sdl' -Message 'Could not onboard to TSA -- not all required values ($TsaCodebaseName, $TsaNotificationEmail, $TsaCodebaseAdmin, $TsaBugAreaPath) were specified.' - ExitWithExitCode 1 - } - } - - # Configure a list of tools with a default target directory. Populates the ".gdn/r" directory. - function Configure-ToolsList([object[]] $tools, [string] $targetDirectory) { - if ($tools -and $tools.Count -gt 0) { - Exec-BlockVerbosely { - & $(Join-Path $PSScriptRoot 'configure-sdl-tool.ps1') ` - -GuardianCliLocation $guardianCliLocation ` - -WorkingDirectory $workingDirectory ` - -TargetDirectory $targetDirectory ` - -GdnFolder $gdnFolder ` - -ToolsList $tools ` - -AzureDevOpsAccessToken $AzureDevOpsAccessToken ` - -GuardianLoggerLevel $GuardianLoggerLevel ` - -CrScanAdditionalRunConfigParams $CrScanAdditionalRunConfigParams ` - -PoliCheckAdditionalRunConfigParams $PoliCheckAdditionalRunConfigParams ` - -CodeQLAdditionalRunConfigParams $CodeQLAdditionalRunConfigParams ` - -BinskimAdditionalRunConfigParams $BinskimAdditionalRunConfigParams - if ($BreakOnFailure) { - Exit-IfNZEC "Sdl" - } - } - } - } - - # Configure Artifact and Source tools with default Target directories. - Configure-ToolsList $ArtifactToolsList $ArtifactsDirectory - Configure-ToolsList $SourceToolsList $SourceDirectory - # Configure custom tools with no default Target directory. - Configure-ToolsList $CustomToolsList $null - - # At this point, all tools are configured in the ".gdn" directory. Run them all in a single call. - # (If we used "run" multiple times, each run would overwrite data from earlier runs.) - Exec-BlockVerbosely { - & $(Join-Path $PSScriptRoot 'run-sdl.ps1') ` - -GuardianCliLocation $guardianCliLocation ` - -WorkingDirectory $SourceDirectory ` - -UpdateBaseline $UpdateBaseline ` - -GdnFolder $gdnFolder - } - - if ($TsaPublish) { - if ($TsaBranchName -and $BuildNumber) { - if (-not $TsaRepositoryName) { - $TsaRepositoryName = "$($Repository)-$($BranchName)" - } - Exec-BlockVerbosely { - & $guardianCliLocation tsa-publish --all-tools --repository-name "$TsaRepositoryName" --branch-name "$TsaBranchName" --build-number "$BuildNumber" --onboard $True --codebase-name "$TsaCodebaseName" --notification-alias "$TsaNotificationEmail" --codebase-admin "$TsaCodebaseAdmin" --instance-url "$TsaInstanceUrl" --project-name "$TsaProjectName" --area-path "$TsaBugAreaPath" --iteration-path "$TsaIterationPath" --working-directory $workingDirectory --logger-level $GuardianLoggerLevel - } - if ($LASTEXITCODE -ne 0) { - Write-PipelineTelemetryError -Force -Category 'Sdl' -Message "Guardian tsa-publish failed with exit code $LASTEXITCODE." - ExitWithExitCode $LASTEXITCODE - } - } else { - Write-PipelineTelemetryError -Force -Category 'Sdl' -Message 'Could not publish to TSA -- not all required values ($TsaBranchName, $BuildNumber) were specified.' - ExitWithExitCode 1 - } - } - - if ($BreakOnFailure) { - Write-Host "Failing the build in case of breaking results..." - Exec-BlockVerbosely { - & $guardianCliLocation break --working-directory $workingDirectory --logger-level $GuardianLoggerLevel - } - } else { - Write-Host "Letting the build pass even if there were breaking results..." - } -} -catch { - Write-Host $_.ScriptStackTrace - Write-PipelineTelemetryError -Force -Category 'Sdl' -Message $_ - exit 1 -} diff --git a/eng/common/sdl/extract-artifact-archives.ps1 b/eng/common/sdl/extract-artifact-archives.ps1 deleted file mode 100644 index 68da4fbf257..00000000000 --- a/eng/common/sdl/extract-artifact-archives.ps1 +++ /dev/null @@ -1,63 +0,0 @@ -# This script looks for each archive file in a directory and extracts it into the target directory. -# For example, the file "$InputPath/bin.tar.gz" extracts to "$ExtractPath/bin.tar.gz.extracted/**". -# Uses the "tar" utility added to Windows 10 / Windows 2019 that supports tar.gz and zip. -param( - # Full path to directory where archives are stored. - [Parameter(Mandatory=$true)][string] $InputPath, - # Full path to directory to extract archives into. May be the same as $InputPath. - [Parameter(Mandatory=$true)][string] $ExtractPath -) - -$ErrorActionPreference = 'Stop' -Set-StrictMode -Version 2.0 - -$disableConfigureToolsetImport = $true - -try { - # `tools.ps1` checks $ci to perform some actions. Since the SDL - # scripts don't necessarily execute in the same agent that run the - # build.ps1/sh script this variable isn't automatically set. - $ci = $true - . $PSScriptRoot\..\tools.ps1 - - Measure-Command { - $jobs = @() - - # Find archive files for non-Windows and Windows builds. - $archiveFiles = @( - Get-ChildItem (Join-Path $InputPath "*.tar.gz") - Get-ChildItem (Join-Path $InputPath "*.zip") - ) - - foreach ($targzFile in $archiveFiles) { - $jobs += Start-Job -ScriptBlock { - $file = $using:targzFile - $fileName = [System.IO.Path]::GetFileName($file) - $extractDir = Join-Path $using:ExtractPath "$fileName.extracted" - - New-Item $extractDir -ItemType Directory -Force | Out-Null - - Write-Host "Extracting '$file' to '$extractDir'..." - - # Pipe errors to stdout to prevent PowerShell detecting them and quitting the job early. - # This type of quit skips the catch, so we wouldn't be able to tell which file triggered the - # error. Save output so it can be stored in the exception string along with context. - $output = tar -xf $file -C $extractDir 2>&1 - # Handle NZEC manually rather than using Exit-IfNZEC: we are in a background job, so we - # don't have access to the outer scope. - if ($LASTEXITCODE -ne 0) { - throw "Error extracting '$file': non-zero exit code ($LASTEXITCODE). Output: '$output'" - } - - Write-Host "Extracted to $extractDir" - } - } - - Receive-Job $jobs -Wait - } -} -catch { - Write-Host $_ - Write-PipelineTelemetryError -Force -Category 'Sdl' -Message $_ - ExitWithExitCode 1 -} diff --git a/eng/common/sdl/extract-artifact-packages.ps1 b/eng/common/sdl/extract-artifact-packages.ps1 deleted file mode 100644 index f031ed5b25e..00000000000 --- a/eng/common/sdl/extract-artifact-packages.ps1 +++ /dev/null @@ -1,82 +0,0 @@ -param( - [Parameter(Mandatory=$true)][string] $InputPath, # Full path to directory where artifact packages are stored - [Parameter(Mandatory=$true)][string] $ExtractPath # Full path to directory where the packages will be extracted -) - -$ErrorActionPreference = 'Stop' -Set-StrictMode -Version 2.0 - -$disableConfigureToolsetImport = $true - -function ExtractArtifacts { - if (!(Test-Path $InputPath)) { - Write-Host "Input Path does not exist: $InputPath" - ExitWithExitCode 0 - } - $Jobs = @() - Get-ChildItem "$InputPath\*.nupkg" | - ForEach-Object { - $Jobs += Start-Job -ScriptBlock $ExtractPackage -ArgumentList $_.FullName - } - - foreach ($Job in $Jobs) { - Wait-Job -Id $Job.Id | Receive-Job - } -} - -try { - # `tools.ps1` checks $ci to perform some actions. Since the SDL - # scripts don't necessarily execute in the same agent that run the - # build.ps1/sh script this variable isn't automatically set. - $ci = $true - . $PSScriptRoot\..\tools.ps1 - - $ExtractPackage = { - param( - [string] $PackagePath # Full path to a NuGet package - ) - - if (!(Test-Path $PackagePath)) { - Write-PipelineTelemetryError -Category 'Build' -Message "Input file does not exist: $PackagePath" - ExitWithExitCode 1 - } - - $RelevantExtensions = @('.dll', '.exe', '.pdb') - Write-Host -NoNewLine 'Extracting ' ([System.IO.Path]::GetFileName($PackagePath)) '...' - - $PackageId = [System.IO.Path]::GetFileNameWithoutExtension($PackagePath) - $ExtractPath = Join-Path -Path $using:ExtractPath -ChildPath $PackageId - - Add-Type -AssemblyName System.IO.Compression.FileSystem - - [System.IO.Directory]::CreateDirectory($ExtractPath); - - try { - $zip = [System.IO.Compression.ZipFile]::OpenRead($PackagePath) - - $zip.Entries | - Where-Object {$RelevantExtensions -contains [System.IO.Path]::GetExtension($_.Name)} | - ForEach-Object { - $TargetPath = Join-Path -Path $ExtractPath -ChildPath (Split-Path -Path $_.FullName) - [System.IO.Directory]::CreateDirectory($TargetPath); - - $TargetFile = Join-Path -Path $ExtractPath -ChildPath $_.FullName - [System.IO.Compression.ZipFileExtensions]::ExtractToFile($_, $TargetFile) - } - } - catch { - Write-Host $_ - Write-PipelineTelemetryError -Force -Category 'Sdl' -Message $_ - ExitWithExitCode 1 - } - finally { - $zip.Dispose() - } - } - Measure-Command { ExtractArtifacts } -} -catch { - Write-Host $_ - Write-PipelineTelemetryError -Force -Category 'Sdl' -Message $_ - ExitWithExitCode 1 -} diff --git a/eng/common/sdl/init-sdl.ps1 b/eng/common/sdl/init-sdl.ps1 deleted file mode 100644 index 3ac1d92b370..00000000000 --- a/eng/common/sdl/init-sdl.ps1 +++ /dev/null @@ -1,55 +0,0 @@ -Param( - [string] $GuardianCliLocation, - [string] $Repository, - [string] $BranchName='master', - [string] $WorkingDirectory, - [string] $AzureDevOpsAccessToken, - [string] $GuardianLoggerLevel='Standard' -) - -$ErrorActionPreference = 'Stop' -Set-StrictMode -Version 2.0 -$disableConfigureToolsetImport = $true -$global:LASTEXITCODE = 0 - -# `tools.ps1` checks $ci to perform some actions. Since the SDL -# scripts don't necessarily execute in the same agent that run the -# build.ps1/sh script this variable isn't automatically set. -$ci = $true -. $PSScriptRoot\..\tools.ps1 - -# Don't display the console progress UI - it's a huge perf hit -$ProgressPreference = 'SilentlyContinue' - -# Construct basic auth from AzDO access token; construct URI to the repository's gdn folder stored in that repository; construct location of zip file -$encodedPat = [Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$AzureDevOpsAccessToken")) -$escapedRepository = [Uri]::EscapeDataString("/$Repository/$BranchName/.gdn") -$uri = "https://dev.azure.com/dnceng/internal/_apis/git/repositories/sdl-tool-cfg/Items?path=$escapedRepository&versionDescriptor[versionOptions]=0&`$format=zip&api-version=5.0" -$zipFile = "$WorkingDirectory/gdn.zip" - -Add-Type -AssemblyName System.IO.Compression.FileSystem -$gdnFolder = (Join-Path $WorkingDirectory '.gdn') - -try { - # if the folder does not exist, we'll do a guardian init and push it to the remote repository - Write-Host 'Initializing Guardian...' - Write-Host "$GuardianCliLocation init --working-directory $WorkingDirectory --logger-level $GuardianLoggerLevel" - & $GuardianCliLocation init --working-directory $WorkingDirectory --logger-level $GuardianLoggerLevel - if ($LASTEXITCODE -ne 0) { - Write-PipelineTelemetryError -Force -Category 'Build' -Message "Guardian init failed with exit code $LASTEXITCODE." - ExitWithExitCode $LASTEXITCODE - } - # We create the mainbaseline so it can be edited later - Write-Host "$GuardianCliLocation baseline --working-directory $WorkingDirectory --name mainbaseline" - & $GuardianCliLocation baseline --working-directory $WorkingDirectory --name mainbaseline - if ($LASTEXITCODE -ne 0) { - Write-PipelineTelemetryError -Force -Category 'Build' -Message "Guardian baseline failed with exit code $LASTEXITCODE." - ExitWithExitCode $LASTEXITCODE - } - ExitWithExitCode 0 -} -catch { - Write-Host $_.ScriptStackTrace - Write-PipelineTelemetryError -Force -Category 'Sdl' -Message $_ - ExitWithExitCode 1 -} diff --git a/eng/common/sdl/packages.config b/eng/common/sdl/packages.config deleted file mode 100644 index e5f543ea68c..00000000000 --- a/eng/common/sdl/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/eng/common/sdl/run-sdl.ps1 b/eng/common/sdl/run-sdl.ps1 deleted file mode 100644 index 2eac8c78f10..00000000000 --- a/eng/common/sdl/run-sdl.ps1 +++ /dev/null @@ -1,49 +0,0 @@ -Param( - [string] $GuardianCliLocation, - [string] $WorkingDirectory, - [string] $GdnFolder, - [string] $UpdateBaseline, - [string] $GuardianLoggerLevel='Standard' -) - -$ErrorActionPreference = 'Stop' -Set-StrictMode -Version 2.0 -$disableConfigureToolsetImport = $true -$global:LASTEXITCODE = 0 - -try { - # `tools.ps1` checks $ci to perform some actions. Since the SDL - # scripts don't necessarily execute in the same agent that run the - # build.ps1/sh script this variable isn't automatically set. - $ci = $true - . $PSScriptRoot\..\tools.ps1 - - # We store config files in the r directory of .gdn - $gdnConfigPath = Join-Path $GdnFolder 'r' - $ValidPath = Test-Path $GuardianCliLocation - - if ($ValidPath -eq $False) - { - Write-PipelineTelemetryError -Force -Category 'Sdl' -Message "Invalid Guardian CLI Location." - ExitWithExitCode 1 - } - - $gdnConfigFiles = Get-ChildItem $gdnConfigPath -Recurse -Include '*.gdnconfig' - Write-Host "Discovered Guardian config files:" - $gdnConfigFiles | Out-String | Write-Host - - Exec-BlockVerbosely { - & $GuardianCliLocation run ` - --working-directory $WorkingDirectory ` - --baseline mainbaseline ` - --update-baseline $UpdateBaseline ` - --logger-level $GuardianLoggerLevel ` - --config @gdnConfigFiles - Exit-IfNZEC "Sdl" - } -} -catch { - Write-Host $_.ScriptStackTrace - Write-PipelineTelemetryError -Force -Category 'Sdl' -Message $_ - ExitWithExitCode 1 -} diff --git a/eng/common/sdl/sdl.ps1 b/eng/common/sdl/sdl.ps1 deleted file mode 100644 index 648c5068d7d..00000000000 --- a/eng/common/sdl/sdl.ps1 +++ /dev/null @@ -1,38 +0,0 @@ - -function Install-Gdn { - param( - [Parameter(Mandatory=$true)] - [string]$Path, - - # If omitted, install the latest version of Guardian, otherwise install that specific version. - [string]$Version - ) - - $ErrorActionPreference = 'Stop' - Set-StrictMode -Version 2.0 - $disableConfigureToolsetImport = $true - $global:LASTEXITCODE = 0 - - # `tools.ps1` checks $ci to perform some actions. Since the SDL - # scripts don't necessarily execute in the same agent that run the - # build.ps1/sh script this variable isn't automatically set. - $ci = $true - . $PSScriptRoot\..\tools.ps1 - - $argumentList = @("install", "Microsoft.Guardian.Cli", "-Source https://securitytools.pkgs.visualstudio.com/_packaging/Guardian/nuget/v3/index.json", "-OutputDirectory $Path", "-NonInteractive", "-NoCache") - - if ($Version) { - $argumentList += "-Version $Version" - } - - Start-Process nuget -Verbose -ArgumentList $argumentList -NoNewWindow -Wait - - $gdnCliPath = Get-ChildItem -Filter guardian.cmd -Recurse -Path $Path - - if (!$gdnCliPath) - { - Write-PipelineTelemetryError -Category 'Sdl' -Message 'Failure installing Guardian' - } - - return $gdnCliPath.FullName -} \ No newline at end of file diff --git a/eng/common/sdl/trim-assets-version.ps1 b/eng/common/sdl/trim-assets-version.ps1 deleted file mode 100644 index 0daa2a9e946..00000000000 --- a/eng/common/sdl/trim-assets-version.ps1 +++ /dev/null @@ -1,75 +0,0 @@ -<# -.SYNOPSIS -Install and run the 'Microsoft.DotNet.VersionTools.Cli' tool with the 'trim-artifacts-version' command to trim the version from the NuGet assets file name. - -.PARAMETER InputPath -Full path to directory where artifact packages are stored - -.PARAMETER Recursive -Search for NuGet packages recursively - -#> - -Param( - [string] $InputPath, - [bool] $Recursive = $true -) - -$CliToolName = "Microsoft.DotNet.VersionTools.Cli" - -function Install-VersionTools-Cli { - param( - [Parameter(Mandatory=$true)][string]$Version - ) - - Write-Host "Installing the package '$CliToolName' with a version of '$version' ..." - $feed = "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json" - - $argumentList = @("tool", "install", "--local", "$CliToolName", "--add-source $feed", "--no-cache", "--version $Version", "--create-manifest-if-needed") - Start-Process "$dotnet" -Verbose -ArgumentList $argumentList -NoNewWindow -Wait -} - -# ------------------------------------------------------------------- - -if (!(Test-Path $InputPath)) { - Write-Host "Input Path '$InputPath' does not exist" - ExitWithExitCode 1 -} - -$ErrorActionPreference = 'Stop' -Set-StrictMode -Version 2.0 - -$disableConfigureToolsetImport = $true -$global:LASTEXITCODE = 0 - -# `tools.ps1` checks $ci to perform some actions. Since the SDL -# scripts don't necessarily execute in the same agent that run the -# build.ps1/sh script this variable isn't automatically set. -$ci = $true -. $PSScriptRoot\..\tools.ps1 - -try { - $dotnetRoot = InitializeDotNetCli -install:$true - $dotnet = "$dotnetRoot\dotnet.exe" - - $toolsetVersion = Read-ArcadeSdkVersion - Install-VersionTools-Cli -Version $toolsetVersion - - $cliToolFound = (& "$dotnet" tool list --local | Where-Object {$_.Split(' ')[0] -eq $CliToolName}) - if ($null -eq $cliToolFound) { - Write-PipelineTelemetryError -Force -Category 'Sdl' -Message "The '$CliToolName' tool is not installed." - ExitWithExitCode 1 - } - - Exec-BlockVerbosely { - & "$dotnet" $CliToolName trim-assets-version ` - --assets-path $InputPath ` - --recursive $Recursive - Exit-IfNZEC "Sdl" - } -} -catch { - Write-Host $_ - Write-PipelineTelemetryError -Force -Category 'Sdl' -Message $_ - ExitWithExitCode 1 -} diff --git a/eng/common/template-guidance.md b/eng/common/template-guidance.md index e2b07a865f1..f772aa3d78f 100644 --- a/eng/common/template-guidance.md +++ b/eng/common/template-guidance.md @@ -71,7 +71,6 @@ eng\common\ source-build.yml (shim) source-index-stage1.yml (shim) jobs\ - codeql-build.yml (shim) jobs.yml (shim) source-build.yml (shim) post-build\ @@ -88,7 +87,6 @@ eng\common\ source-build.yml (shim) variables\ pool-providers.yml (logic + redirect) # templates/variables/pool-providers.yml will redirect to templates-official/variables/pool-providers.yml if you are running in the internal project - sdl-variables.yml (logic) core-templates\ job\ job.yml (logic) @@ -97,7 +95,6 @@ eng\common\ source-build.yml (logic) source-index-stage1.yml (logic) jobs\ - codeql-build.yml (logic) jobs.yml (logic) source-build.yml (logic) post-build\ diff --git a/eng/common/templates-official/jobs/codeql-build.yml b/eng/common/templates-official/jobs/codeql-build.yml deleted file mode 100644 index a726322ecfe..00000000000 --- a/eng/common/templates-official/jobs/codeql-build.yml +++ /dev/null @@ -1,7 +0,0 @@ -jobs: -- template: /eng/common/core-templates/jobs/codeql-build.yml - parameters: - is1ESPipeline: true - - ${{ each parameter in parameters }}: - ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/variables/sdl-variables.yml b/eng/common/templates-official/variables/sdl-variables.yml deleted file mode 100644 index f1311bbb1b3..00000000000 --- a/eng/common/templates-official/variables/sdl-variables.yml +++ /dev/null @@ -1,7 +0,0 @@ -variables: -# The Guardian version specified in 'eng/common/sdl/packages.config'. This value must be kept in -# sync with the packages.config file. -- name: DefaultGuardianVersion - value: 0.109.0 -- name: GuardianPackagesConfigFile - value: $(System.DefaultWorkingDirectory)\eng\common\sdl\packages.config \ No newline at end of file diff --git a/eng/common/templates/job/job.yml b/eng/common/templates/job/job.yml index 5e261f34db4..85501406a54 100644 --- a/eng/common/templates/job/job.yml +++ b/eng/common/templates/job/job.yml @@ -21,11 +21,6 @@ jobs: - ${{ each step in parameters.steps }}: - ${{ step }} - # we don't run CG in public - - ${{ if eq(variables['System.TeamProject'], 'public') }}: - - script: echo "##vso[task.setvariable variable=skipComponentGovernanceDetection]true" - displayName: Set skipComponentGovernanceDetection variable - artifactPublishSteps: - ${{ if ne(parameters.artifacts.publish, '') }}: - ${{ if and(ne(parameters.artifacts.publish.artifacts, 'false'), ne(parameters.artifacts.publish.artifacts, '')) }}: diff --git a/eng/common/templates/jobs/codeql-build.yml b/eng/common/templates/jobs/codeql-build.yml deleted file mode 100644 index 517f24d6a52..00000000000 --- a/eng/common/templates/jobs/codeql-build.yml +++ /dev/null @@ -1,7 +0,0 @@ -jobs: -- template: /eng/common/core-templates/jobs/codeql-build.yml - parameters: - is1ESPipeline: false - - ${{ each parameter in parameters }}: - ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/tools.ps1 b/eng/common/tools.ps1 index c6a1d6eaec4..ebc31f7ecdc 100644 --- a/eng/common/tools.ps1 +++ b/eng/common/tools.ps1 @@ -15,7 +15,7 @@ # Set to true to use the pipelines logger which will enable Azure logging output. # https://github.com/Microsoft/azure-pipelines-tasks/blob/master/docs/authoring/commands.md -# This flag is meant as a temporary opt-opt for the feature while validate it across +# This flag is meant as a temporary opt-in for the feature while validating it across # our consumers. It will be deleted in the future. [bool]$pipelinesLog = if (Test-Path variable:pipelinesLog) { $pipelinesLog } else { $ci } @@ -34,6 +34,9 @@ # Configures warning treatment in msbuild. [bool]$warnAsError = if (Test-Path variable:warnAsError) { $warnAsError } else { $true } +# Specifies semi-colon delimited list of warning codes that should not be treated as errors. +[string]$warnNotAsError = if (Test-Path variable:warnNotAsError) { $warnNotAsError } else { '' } + # Specifies which msbuild engine to use for build: 'vs', 'dotnet' or unspecified (determined based on presence of tools.vs in global.json). [string]$msbuildEngine = if (Test-Path variable:msbuildEngine) { $msbuildEngine } else { $null } @@ -68,6 +71,8 @@ $ErrorActionPreference = 'Stop' # True when the build is running within the VMR. [bool]$fromVMR = if (Test-Path variable:fromVMR) { $fromVMR } else { $false } +[bool]$disablePipelineSetResult = if (Test-Path variable:disablePipelineSetResult) { $disablePipelineSetResult } else { $false } + function Create-Directory ([string[]] $path) { New-Item -Path $path -Force -ItemType 'Directory' | Out-Null } @@ -157,9 +162,6 @@ function InitializeDotNetCli([bool]$install, [bool]$createSdkLocationFile) { return $global:_DotNetInstallDir } - # Don't resolve runtime, shared framework, or SDK from other locations to ensure build determinism - $env:DOTNET_MULTILEVEL_LOOKUP=0 - # Disable first run since we do not need all ASP.NET packages restored. $env:DOTNET_NOLOGO=1 @@ -185,7 +187,11 @@ function InitializeDotNetCli([bool]$install, [bool]$createSdkLocationFile) { if ((-not $globalJsonHasRuntimes) -and (-not [string]::IsNullOrEmpty($env:DOTNET_INSTALL_DIR)) -and (Test-Path(Join-Path $env:DOTNET_INSTALL_DIR "sdk\$dotnetSdkVersion"))) { $dotnetRoot = $env:DOTNET_INSTALL_DIR } else { - $dotnetRoot = Join-Path $RepoRoot '.dotnet' + if (-not [string]::IsNullOrEmpty($env:DOTNET_GLOBAL_INSTALL_DIR)) { + $dotnetRoot = $env:DOTNET_GLOBAL_INSTALL_DIR + } else { + $dotnetRoot = Join-Path $RepoRoot '.dotnet' + } if (-not (Test-Path(Join-Path $dotnetRoot "sdk\$dotnetSdkVersion"))) { if ($install) { @@ -225,7 +231,6 @@ function InitializeDotNetCli([bool]$install, [bool]$createSdkLocationFile) { # Make Sure that our bootstrapped dotnet cli is available in future steps of the Azure Pipelines build Write-PipelinePrependPath -Path $dotnetRoot - Write-PipelineSetVariable -Name 'DOTNET_MULTILEVEL_LOOKUP' -Value '0' Write-PipelineSetVariable -Name 'DOTNET_NOLOGO' -Value '1' return $global:_DotNetInstallDir = $dotnetRoot @@ -299,6 +304,8 @@ function InstallDotNet([string] $dotnetRoot, $dotnetVersionLabel = "'sdk v$version'" + # For performance this check is duplicated in src/Microsoft.DotNet.Arcade.Sdk/src/InstallDotNetCore.cs + # if you are making changes here, consider if you need to make changes there as well. if ($runtime -ne '' -and $runtime -ne 'sdk') { $runtimePath = $dotnetRoot $runtimePath = $runtimePath + "\shared" @@ -374,12 +381,11 @@ function InstallDotNet([string] $dotnetRoot, # # 1. MSBuild from an active VS command prompt # 2. MSBuild from a compatible VS installation -# 3. MSBuild from the xcopy tool package # # Returns full path to msbuild.exe. # Throws on failure. # -function InitializeVisualStudioMSBuild([bool]$install, [object]$vsRequirements = $null) { +function InitializeVisualStudioMSBuild([object]$vsRequirements = $null) { if (-not (IsWindowsPlatform)) { throw "Cannot initialize Visual Studio on non-Windows" } @@ -389,13 +395,7 @@ function InitializeVisualStudioMSBuild([bool]$install, [object]$vsRequirements = } # Minimum VS version to require. - $vsMinVersionReqdStr = '17.7' - $vsMinVersionReqd = [Version]::new($vsMinVersionReqdStr) - - # If the version of msbuild is going to be xcopied, - # use this version. Version matches a package here: - # https://dev.azure.com/dnceng/public/_artifacts/feed/dotnet-eng/NuGet/Microsoft.DotNet.Arcade.MSBuild.Xcopy/versions/18.0.0 - $defaultXCopyMSBuildVersion = '18.0.0' + $vsMinVersionReqdStr = '18.0' if (!$vsRequirements) { if (Get-Member -InputObject $GlobalJson.tools -Name 'vs') { @@ -425,56 +425,46 @@ function InitializeVisualStudioMSBuild([bool]$install, [object]$vsRequirements = } } - # Locate Visual Studio installation or download x-copy msbuild. + # Locate Visual Studio installation. $vsInfo = LocateVisualStudio $vsRequirements - if ($vsInfo -ne $null -and $env:ForceUseXCopyMSBuild -eq $null) { + if ($vsInfo -ne $null) { # Ensure vsInstallDir has a trailing slash $vsInstallDir = Join-Path $vsInfo.installationPath "\" $vsMajorVersion = $vsInfo.installationVersion.Split('.')[0] InitializeVisualStudioEnvironmentVariables $vsInstallDir $vsMajorVersion } else { - if (Get-Member -InputObject $GlobalJson.tools -Name 'xcopy-msbuild') { - $xcopyMSBuildVersion = $GlobalJson.tools.'xcopy-msbuild' - $vsMajorVersion = $xcopyMSBuildVersion.Split('.')[0] - } else { - #if vs version provided in global.json is incompatible (too low) then use the default version for xcopy msbuild download - if($vsMinVersion -lt $vsMinVersionReqd){ - Write-Host "Using xcopy-msbuild version of $defaultXCopyMSBuildVersion since VS version $vsMinVersionStr provided in global.json is not compatible" - $xcopyMSBuildVersion = $defaultXCopyMSBuildVersion - $vsMajorVersion = $xcopyMSBuildVersion.Split('.')[0] - } - else{ - # If the VS version IS compatible, look for an xcopy msbuild package - # with a version matching VS. - # Note: If this version does not exist, then an explicit version of xcopy msbuild - # can be specified in global.json. This will be required for pre-release versions of msbuild. - $vsMajorVersion = $vsMinVersion.Major - $vsMinorVersion = $vsMinVersion.Minor - $xcopyMSBuildVersion = "$vsMajorVersion.$vsMinorVersion.0" - } - } - - $vsInstallDir = $null - if ($xcopyMSBuildVersion.Trim() -ine "none") { - $vsInstallDir = InitializeXCopyMSBuild $xcopyMSBuildVersion $install - if ($vsInstallDir -eq $null) { - throw "Could not xcopy msbuild. Please check that package 'Microsoft.DotNet.Arcade.MSBuild.Xcopy @ $xcopyMSBuildVersion' exists on feed 'dotnet-eng'." - } - } - if ($vsInstallDir -eq $null) { - throw 'Unable to find Visual Studio that has required version and components installed' - } + throw 'Unable to find Visual Studio that has required version and components installed' } $msbuildVersionDir = if ([int]$vsMajorVersion -lt 16) { "$vsMajorVersion.0" } else { "Current" } $local:BinFolder = Join-Path $vsInstallDir "MSBuild\$msbuildVersionDir\Bin" - $local:Prefer64bit = if (Get-Member -InputObject $vsRequirements -Name 'Prefer64bit') { $vsRequirements.Prefer64bit } else { $false } - if ($local:Prefer64bit -and (Test-Path(Join-Path $local:BinFolder "amd64"))) { - $global:_MSBuildExe = Join-Path $local:BinFolder "amd64\msbuild.exe" - } else { - $global:_MSBuildExe = Join-Path $local:BinFolder "msbuild.exe" + + # Use the MSBuild matching the host's process architecture (e.g. amd64 or arm64), + # falling back to the 32-bit MSBuild in the root Bin folder when no matching subfolder exists. + + # Determine the architecture of the current process, accounting for a 32-bit process + # running on a 64-bit OS (PROCESSOR_ARCHITEW6432 holds the real machine architecture). + $local:ProcessArchitecture = $env:PROCESSOR_ARCHITECTURE + if (($local:ProcessArchitecture -eq 'x86') -and ($env:PROCESSOR_ARCHITEW6432)) { + $local:ProcessArchitecture = $env:PROCESSOR_ARCHITEW6432 + } + + # Map the architecture to the corresponding MSBuild subfolder. The 32-bit MSBuild lives in the + # root Bin folder, so x86 maps to an empty subfolder. + $local:MSBuildArchSubFolder = switch ($local:ProcessArchitecture) { + 'AMD64' { 'amd64' } + 'ARM64' { 'arm64' } + default { '' } + } + + $global:_MSBuildExe = Join-Path $local:BinFolder "msbuild.exe" + if ($local:MSBuildArchSubFolder) { + $local:ArchMSBuildExe = Join-Path $local:BinFolder (Join-Path $local:MSBuildArchSubFolder "msbuild.exe") + if (Test-Path $local:ArchMSBuildExe) { + $global:_MSBuildExe = $local:ArchMSBuildExe + } } return $global:_MSBuildExe @@ -491,38 +481,6 @@ function InitializeVisualStudioEnvironmentVariables([string] $vsInstallDir, [str } } -function InstallXCopyMSBuild([string]$packageVersion) { - return InitializeXCopyMSBuild $packageVersion -install $true -} - -function InitializeXCopyMSBuild([string]$packageVersion, [bool]$install) { - $packageName = 'Microsoft.DotNet.Arcade.MSBuild.Xcopy' - $packageDir = Join-Path $ToolsDir "msbuild\$packageVersion" - $packagePath = Join-Path $packageDir "$packageName.$packageVersion.nupkg" - - if (!(Test-Path $packageDir)) { - if (!$install) { - return $null - } - - Create-Directory $packageDir - - Write-Host "Downloading $packageName $packageVersion" - $ProgressPreference = 'SilentlyContinue' # Don't display the console progress UI - it's a huge perf hit - Retry({ - Invoke-WebRequest "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/flat2/$packageName/$packageVersion/$packageName.$packageVersion.nupkg" -UseBasicParsing -OutFile $packagePath - }) - - if (!(Test-Path $packagePath)) { - Write-PipelineTelemetryError -Category 'InitializeToolset' -Message "See https://dev.azure.com/dnceng/internal/_wiki/wikis/DNCEng%20Services%20Wiki/1074/Updating-Microsoft.DotNet.Arcade.MSBuild.Xcopy-WAS-RoslynTools.MSBuild-(xcopy-msbuild)-generation?anchor=troubleshooting for help troubleshooting issues with XCopy MSBuild" - throw - } - Unzip $packagePath $packageDir - } - - return Join-Path $packageDir 'tools' -} - # # Locates Visual Studio instance that meets the minimal requirements specified by tools.vs object in global.json. # @@ -544,7 +502,6 @@ function LocateVisualStudio([object]$vsRequirements = $null){ if (Get-Member -InputObject $GlobalJson.tools -Name 'vswhere') { $vswhereVersion = $GlobalJson.tools.vswhere } else { - # keep this in sync with the VSWhereVersion in DefaultVersions.props $vswhereVersion = '3.1.7' } @@ -592,11 +549,26 @@ function LocateVisualStudio([object]$vsRequirements = $null){ return $null } + if ($null -eq $vsInfo -or $vsInfo.Count -eq 0) { + throw "No instance of Visual Studio meeting the requirements specified was found. Requirements: $($args -join ' ')" + return $null + } + # use first matching instance return $vsInfo[0] } function InitializeBuildTool() { + # Allow a caller (e.g. a bootstrap script running out-of-proc) to inject the build tool via + # environment variables instead of the in-proc $global:_BuildTool variable. Only Path and + # Command are consumed by the MSBuild function below, so those are all that's needed. + if ($env:_BuildToolPath) { + return $global:_BuildTool = @{ + Path = $env:_BuildToolPath + Command = $env:_BuildToolCommand + } + } + if (Test-Path variable:global:_BuildTool) { # If the requested msbuild parameters do not match, clear the cached variables. if($global:_BuildTool.Contains('ExcludePrereleaseVS') -and $global:_BuildTool.ExcludePrereleaseVS -ne $excludePrereleaseVS) { @@ -624,16 +596,16 @@ function InitializeBuildTool() { } $dotnetPath = Join-Path $dotnetRoot (GetExecutableFileName 'dotnet') - $buildTool = @{ Path = $dotnetPath; Command = 'msbuild'; Tool = 'dotnet'; Framework = 'net' } + $buildTool = @{ Path = $dotnetPath; Command = 'msbuild' } } elseif ($msbuildEngine -eq "vs") { try { - $msbuildPath = InitializeVisualStudioMSBuild -install:$restore + $msbuildPath = InitializeVisualStudioMSBuild } catch { Write-PipelineTelemetryError -Category 'InitializeToolset' -Message $_ ExitWithExitCode 1 } - $buildTool = @{ Path = $msbuildPath; Command = ""; Tool = "vs"; Framework = "netframework"; ExcludePrereleaseVS = $excludePrereleaseVS } + $buildTool = @{ Path = $msbuildPath; Command = ""; ExcludePrereleaseVS = $excludePrereleaseVS } } else { Write-PipelineTelemetryError -Category 'InitializeToolset' -Message "Unexpected value of -msbuildEngine: '$msbuildEngine'." ExitWithExitCode 1 @@ -656,16 +628,16 @@ function GetDefaultMSBuildEngine() { ExitWithExitCode 1 } -function GetNuGetPackageCachePath() { +function InitializeNuGetPackageCachePath() { if ($env:NUGET_PACKAGES -eq $null) { # Use local cache on CI to ensure deterministic build. - # Avoid using the http cache as workaround for https://github.com/NuGet/Home/issues/3116 # use global cache in dev builds to avoid cost of downloading packages. # For directory normalization, see also: https://github.com/NuGet/Home/issues/7968 if ($useGlobalNuGetCache) { - $env:NUGET_PACKAGES = Join-Path $env:UserProfile '.nuget\packages\' + $userProfile = if (IsWindowsPlatform) { $env:UserProfile } else { $env:HOME } + $env:NUGET_PACKAGES = [IO.Path]::Combine($userProfile, '.nuget', 'packages') + [IO.Path]::DirectorySeparatorChar } else { - $env:NUGET_PACKAGES = Join-Path $RepoRoot '.packages\' + $env:NUGET_PACKAGES = [IO.Path]::Combine($RepoRoot, '.packages') + [IO.Path]::DirectorySeparatorChar } } @@ -674,7 +646,13 @@ function GetNuGetPackageCachePath() { # Returns a full path to an Arcade SDK task project file. function GetSdkTaskProject([string]$taskName) { - return Join-Path (Split-Path (InitializeToolset) -Parent) "SdkTasks\$taskName.proj" + $toolsetDir = Split-Path (InitializeToolset) -Parent + $proj = Join-Path $toolsetDir "$taskName.proj" + if (Test-Path $proj) { + return $proj + } + + throw "Unable to find $taskName.proj in toolset at: $toolsetDir" } function InitializeNativeTools() { @@ -708,16 +686,19 @@ function InitializeToolset() { return $global:_InitializeToolset } - $nugetCache = GetNuGetPackageCachePath - $toolsetVersion = Read-ArcadeSdkVersion - $toolsetLocationFile = Join-Path $ToolsetDir "$toolsetVersion.txt" + $toolsetToolsDir = Join-Path $ToolsetDir $toolsetVersion - if (Test-Path $toolsetLocationFile) { - $path = Get-Content $toolsetLocationFile -TotalCount 1 - if (Test-Path $path) { - return $global:_InitializeToolset = $path - } + # Check if the toolset has already been extracted + $toolsetBuildProj = $null + $buildProjPath = Join-Path $toolsetToolsDir 'Build.proj' + + if (Test-Path $buildProjPath) { + $toolsetBuildProj = $buildProjPath + } + + if ($toolsetBuildProj -ne $null) { + return $global:_InitializeToolset = $toolsetBuildProj } if (-not $restore) { @@ -725,25 +706,55 @@ function InitializeToolset() { ExitWithExitCode 1 } - $buildTool = InitializeBuildTool + $downloadArgs = @("package", "download", "Microsoft.DotNet.Arcade.Sdk@$toolsetVersion", "--verbosity", "minimal", "--prerelease", "--output", "$nugetPackageCachePath") + $nugetConfig = $env:NUGET_CONFIG + if (-not $nugetConfig) { + # Search for any variation of nuget.config in the RepoRoot + $configFile = Get-ChildItem -Path $RepoRoot -File | Where-Object { $_.Name -ieq "nuget.config" } | Select-Object -First 1 - $proj = Join-Path $ToolsetDir 'restore.proj' - $bl = if ($binaryLog) { '/bl:' + (Join-Path $LogDir 'ToolsetRestore.binlog') } else { '' } + if ($configFile) { + $nugetConfig = $configFile.FullName + } + } - '' | Set-Content $proj + if ($nugetConfig) { + $downloadArgs += "--configfile" + $downloadArgs += $nugetConfig + } - MSBuild-Core $proj $bl /t:__WriteToolsetLocation /clp:ErrorsOnly`;NoSummary /p:__ToolsetLocationOutputFile=$toolsetLocationFile /p:RestoreIgnoreFailedSources=true + # 'dotnet package download' fails outright if any source in the repo's NuGet.config is + # unavailable (for example a transport feed that was decommissioned after a release). The + # Arcade SDK is always published to the public dotnet-eng feed, so if the config-driven + # download fails, retry once against that feed directly (which ignores the other sources) + # before giving up, so a single dead source doesn't block the build. + $downloadExitCode = DotNet -ignoreFailure @downloadArgs + if ($downloadExitCode) { + Write-Host "Restoring the Arcade SDK from the configured sources failed; retrying from the public dotnet-eng feed." + DotNet @downloadArgs --source "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json" + } + + $packageDir = Join-Path $nugetPackageCachePath (Join-Path 'microsoft.dotnet.arcade.sdk' $toolsetVersion) + $packageToolsetDir = Join-Path $packageDir 'toolset' - $path = Get-Content $toolsetLocationFile -Encoding UTF8 -TotalCount 1 - if (!(Test-Path $path)) { - throw "Invalid toolset path: $path" + if (!(Test-Path $packageToolsetDir)) { + Write-PipelineTelemetryError -Category 'InitializeToolset' -Message "Arcade SDK package does not contain a toolset or tools folder: $packageDir" + ExitWithExitCode 3 } - return $global:_InitializeToolset = $path + New-Item -ItemType Directory -Path $toolsetToolsDir -Force | Out-Null + Copy-Item -Path "$packageToolsetDir\*" -Destination $toolsetToolsDir -Recurse -Force + + if (Test-Path $buildProjPath) { + $toolsetBuildProj = $buildProjPath + } else { + throw "Unable to find Build.proj in toolset at: $toolsetToolsDir" + } + + return $global:_InitializeToolset = $toolsetBuildProj } function ExitWithExitCode([int] $exitCode) { - if ($ci -and $prepareMachine) { + if ($prepareMachine) { Stop-Processes } exit $exitCode @@ -773,55 +784,28 @@ function Stop-Processes() { # Terminates the script if the build fails. # function MSBuild() { - if ($pipelinesLog) { - $buildTool = InitializeBuildTool - - if ($ci -and $buildTool.Tool -eq 'dotnet') { - $env:NUGET_PLUGIN_HANDSHAKE_TIMEOUT_IN_SECONDS = 20 - $env:NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS = 20 - Write-PipelineSetVariable -Name 'NUGET_PLUGIN_HANDSHAKE_TIMEOUT_IN_SECONDS' -Value '20' - Write-PipelineSetVariable -Name 'NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS' -Value '20' - } - - Enable-Nuget-EnhancedRetry - - $toolsetBuildProject = InitializeToolset - $basePath = Split-Path -parent $toolsetBuildProject - $selectedPath = Join-Path $basePath (Join-Path $buildTool.Framework 'Microsoft.DotNet.ArcadeLogging.dll') - - if (-not $selectedPath) { - Write-PipelineTelemetryError -Category 'Build' -Message "Unable to find arcade sdk logger assembly: $selectedPath" - ExitWithExitCode 1 - } - - $args += "/logger:$selectedPath" - } - - MSBuild-Core @args -} - -# -# Executes msbuild (or 'dotnet msbuild') with arguments passed to the function. -# The arguments are automatically quoted. -# Terminates the script if the build fails. -# -function MSBuild-Core() { if ($ci) { if (!$binaryLog -and !$excludeCIBinarylog) { Write-PipelineTelemetryError -Category 'Build' -Message 'Binary log must be enabled in CI build, or explicitly opted-out from with the -excludeCIBinarylog switch.' ExitWithExitCode 1 } - - if ($nodeReuse) { - Write-PipelineTelemetryError -Category 'Build' -Message 'Node reuse must be disabled in CI build.' - ExitWithExitCode 1 - } } - Enable-Nuget-EnhancedRetry - $buildTool = InitializeBuildTool + if ($pipelinesLog) { + $toolsetBuildProject = InitializeToolset + $basePath = Split-Path -parent $toolsetBuildProject + $selectedPath = Join-Path $basePath (Join-Path 'net' 'Microsoft.DotNet.ArcadeLogging.dll') + + # Only inject the logger when it's present. A last-known-good Arcade used to bootstrap + # the build may not ship the logger yet, so its absence must not be a hard error. + # Specify the logger type explicitly so loading is deterministic. + if (Test-Path $selectedPath) { + $args += "/logger:Microsoft.DotNet.ArcadeLogging.PipelinesLogger,$selectedPath" + } + } + $cmdArgs = "$($buildTool.Command) /m /nologo /clp:Summary /v:$verbosity /nr:$nodeReuse /p:ContinuousIntegrationBuild=$ci" # Add -mt flag for MSBuild multithreaded mode if enabled via environment variable @@ -836,6 +820,10 @@ function MSBuild-Core() { $cmdArgs += ' /p:TreatWarningsAsErrors=false' } + if ($warnAsError -and $warnNotAsError) { + $cmdArgs += " /warnnotaserror:$warnNotAsError /p:AdditionalWarningsNotAsErrors=$warnNotAsError" + } + foreach ($arg in $args) { if ($null -ne $arg -and $arg.Trim() -ne "") { if ($arg.EndsWith('\')) { @@ -855,14 +843,9 @@ function MSBuild-Core() { # The build already logged an error, that's the reason it failed. Producing an error here only adds noise. Write-Host "Build failed with exit code $exitCode. Check errors above." -ForegroundColor Red - $buildLog = GetMSBuildBinaryLogCommandLineArgument $args - if ($null -ne $buildLog) { - Write-Host "See log: $buildLog" -ForegroundColor DarkGray - } - # When running on Azure Pipelines, override the returned exit code to avoid double logging. - # Skip this when the build is a child of the VMR build. - if ($ci -and $env:SYSTEM_TEAMPROJECT -ne $null -and !$fromVMR) { + # Skip this when the build is a child of the VMR build, or when -disablePipelineSetResult is set so the real exit code propagates. + if ($ci -and $env:SYSTEM_TEAMPROJECT -ne $null -and !$fromVMR -and !$disablePipelineSetResult) { Write-PipelineSetResult -Result "Failed" -Message "msbuild execution failed." # Exiting with an exit code causes the azure pipelines task to log yet another "noise" error # The above Write-PipelineSetResult will cause the task to be marked as failure without adding yet another error @@ -873,21 +856,44 @@ function MSBuild-Core() { } } -function GetMSBuildBinaryLogCommandLineArgument($arguments) { - foreach ($argument in $arguments) { - if ($argument -ne $null) { - $arg = $argument.Trim() - if ($arg.StartsWith('/bl:', "OrdinalIgnoreCase")) { - return $arg.Substring('/bl:'.Length) - } +# +# Executes a dotnet command with arguments passed to the function. +# Terminates the script if the command fails. +# +function DotNet([switch]$ignoreFailure) { + $dotnetRoot = InitializeDotNetCli -install:$restore + $dotnetPath = Join-Path $dotnetRoot (GetExecutableFileName 'dotnet') - if ($arg.StartsWith('/binaryLogger:', 'OrdinalIgnoreCase')) { - return $arg.Substring('/binaryLogger:'.Length) + $cmdArgs = "" + foreach ($arg in $args) { + if ($null -ne $arg -and $arg.Trim() -ne "") { + if ($arg.EndsWith('\')) { + $arg = $arg + "\" } + $cmdArgs += " `"$arg`"" } } - return $null + $env:ARCADE_BUILD_TOOL_COMMAND = "`"$dotnetPath`" $cmdArgs" + + $exitCode = Exec-Process $dotnetPath $cmdArgs + + if ($exitCode -ne 0) { + # When -ignoreFailure is set, return the exit code to the caller so it can implement + # its own fallback logic instead of terminating the script. + if ($ignoreFailure) { + return $exitCode + } + + Write-Host "dotnet command failed with exit code $exitCode. Check errors above." -ForegroundColor Red + + if ($ci -and $env:SYSTEM_TEAMPROJECT -ne $null -and !$fromVMR -and !$disablePipelineSetResult) { + Write-PipelineSetResult -Result "Failed" -Message "dotnet command execution failed." + ExitWithExitCode 0 + } else { + ExitWithExitCode $exitCode + } + } } function GetExecutableFileName($baseName) { @@ -930,6 +936,12 @@ Create-Directory $ToolsetDir Create-Directory $TempDir Create-Directory $LogDir +# Direct MSBuild crash diagnostics (MSB4166 failure.txt files) to a known location +# under artifacts/log so they are captured as build artifacts in CI. +if (-not $env:MSBUILDDEBUGPATH) { + $env:MSBUILDDEBUGPATH = Join-Path $LogDir 'MsbuildDebugLogs' +} + Write-PipelineSetVariable -Name 'Artifacts' -Value $ArtifactsDir Write-PipelineSetVariable -Name 'Artifacts.Toolset' -Value $ToolsetDir Write-PipelineSetVariable -Name 'Artifacts.Log' -Value $LogDir @@ -951,19 +963,5 @@ if (!$disableConfigureToolsetImport) { } } -# -# If $ci flag is set, turn on (and log that we did) special environment variables for improved Nuget client retry logic. -# -function Enable-Nuget-EnhancedRetry() { - if ($ci) { - Write-Host "Setting NUGET enhanced retry environment variables" - $env:NUGET_ENABLE_ENHANCED_HTTP_RETRY = 'true' - $env:NUGET_ENHANCED_MAX_NETWORK_TRY_COUNT = 6 - $env:NUGET_ENHANCED_NETWORK_RETRY_DELAY_MILLISECONDS = 1000 - $env:NUGET_RETRY_HTTP_429 = 'true' - Write-PipelineSetVariable -Name 'NUGET_ENABLE_ENHANCED_HTTP_RETRY' -Value 'true' - Write-PipelineSetVariable -Name 'NUGET_ENHANCED_MAX_NETWORK_TRY_COUNT' -Value '6' - Write-PipelineSetVariable -Name 'NUGET_ENHANCED_NETWORK_RETRY_DELAY_MILLISECONDS' -Value '1000' - Write-PipelineSetVariable -Name 'NUGET_RETRY_HTTP_429' -Value 'true' - } -} +# Initialize the nuget package cache vars +$nugetPackageCachePath = InitializeNuGetPackageCachePath diff --git a/eng/common/tools.sh b/eng/common/tools.sh index 62aeb73fe51..cd31d8a0a0e 100755 --- a/eng/common/tools.sh +++ b/eng/common/tools.sh @@ -10,7 +10,7 @@ source_build=${source_build:-false} # Set to true to use the pipelines logger which will enable Azure logging output. # https://github.com/Microsoft/azure-pipelines-tasks/blob/master/docs/authoring/commands.md -# This flag is meant as a temporary opt-opt for the feature while validate it across +# This flag is meant as a temporary opt-in for the feature while validating it across # our consumers. It will be deleted in the future. if [[ "$ci" == true ]]; then pipelines_log=${pipelines_log:-true} @@ -52,6 +52,9 @@ fi # Configures warning treatment in msbuild. warn_as_error=${warn_as_error:-true} +# Specifies semi-colon delimited list of warning codes that should not be treated as errors. +warn_not_as_error=${warn_not_as_error:-''} + # True to attempt using .NET Core already that meets requirements specified in global.json # installed on the machine instead of downloading one. use_installed_dotnet_cli=${use_installed_dotnet_cli:-true} @@ -75,6 +78,8 @@ runtime_source_feed_key=${runtime_source_feed_key:-''} # True when the build is running within the VMR. from_vmr=${from_vmr:-false} +disable_pipeline_set_result=${disable_pipeline_set_result:-false} + # Resolve any symlinks in the given path. function ResolvePath { local path=$1 @@ -115,9 +120,6 @@ function InitializeDotNetCli { local install=$1 - # Don't resolve runtime, shared framework, or SDK from other locations to ensure build determinism - export DOTNET_MULTILEVEL_LOOKUP=0 - # Disable first run since we want to control all package sources export DOTNET_NOLOGO=1 @@ -148,7 +150,11 @@ function InitializeDotNetCli { if [[ $global_json_has_runtimes == false && -n "${DOTNET_INSTALL_DIR:-}" && -d "$DOTNET_INSTALL_DIR/sdk/$dotnet_sdk_version" ]]; then dotnet_root="$DOTNET_INSTALL_DIR" else - dotnet_root="${repo_root}.dotnet" + if [[ -n "${DOTNET_GLOBAL_INSTALL_DIR:-}" ]]; then + dotnet_root="$DOTNET_GLOBAL_INSTALL_DIR" + else + dotnet_root="${repo_root}.dotnet" + fi export DOTNET_INSTALL_DIR="$dotnet_root" @@ -166,7 +172,6 @@ function InitializeDotNetCli { # build steps from using anything other than what we've downloaded. Write-PipelinePrependPath -path "$dotnet_root" - Write-PipelineSetVariable -name "DOTNET_MULTILEVEL_LOOKUP" -value "0" Write-PipelineSetVariable -name "DOTNET_NOLOGO" -value "1" # return value @@ -188,6 +193,8 @@ function InstallDotNet { local version=$2 local runtime=$4 + # For performance this check is duplicated in src/Microsoft.DotNet.Arcade.Sdk/src/InstallDotNetCore.cs + # if you are making changes here, consider if you need to make changes there as well. local dotnetVersionLabel="'$runtime v$version'" if [[ -n "${4:-}" ]] && [ "$4" != 'sdk' ]; then runtimePath="$root" @@ -358,6 +365,15 @@ function GetDotNetInstallScript { } function InitializeBuildTool { + # Allow a caller (e.g. a bootstrap script running out-of-proc) to inject the build tool via + # environment variables instead of the in-proc _InitializeBuildTool variable. Only the tool path and + # command are consumed by the MSBuild function below, so those are all that's needed. + if [[ -n "${_BuildToolPath:-}" ]]; then + _InitializeBuildTool="$_BuildToolPath" + _InitializeBuildToolCommand="$_BuildToolCommand" + return + fi + if [[ -n "${_InitializeBuildTool:-}" ]]; then return fi @@ -369,7 +385,7 @@ function InitializeBuildTool { _InitializeBuildToolCommand="msbuild" } -function GetNuGetPackageCachePath { +function InitializeNuGetPackageCachePath { if [[ -z ${NUGET_PACKAGES:-} ]]; then if [[ "$use_global_nuget_cache" == true ]]; then export NUGET_PACKAGES="$HOME/.nuget/packages/" @@ -379,7 +395,7 @@ function GetNuGetPackageCachePath { fi # return value - _GetNuGetPackageCachePath=$NUGET_PACKAGES + _InitializeNuGetPackageCachePath=$NUGET_PACKAGES } function InitializeNativeTools() { @@ -401,20 +417,21 @@ function InitializeToolset { return fi - GetNuGetPackageCachePath - ReadGlobalVersion "Microsoft.DotNet.Arcade.Sdk" local toolset_version=$_ReadGlobalVersion - local toolset_location_file="$toolset_dir/$toolset_version.txt" + local toolset_tools_dir="$toolset_dir/$toolset_version" - if [[ -a "$toolset_location_file" ]]; then - local path=`cat "$toolset_location_file"` - if [[ -a "$path" ]]; then - # return value - _InitializeToolset="$path" - return - fi + # Check if the toolset has already been extracted + local toolset_build_proj="" + if [[ -a "$toolset_tools_dir/Build.proj" ]]; then + toolset_build_proj="$toolset_tools_dir/Build.proj" + fi + + if [[ -n "$toolset_build_proj" ]]; then + # return value + _InitializeToolset="$toolset_build_proj" + return fi if [[ "$restore" != true ]]; then @@ -422,20 +439,46 @@ function InitializeToolset { ExitWithExitCode 2 fi - local proj="$toolset_dir/restore.proj" + local download_args=("package" "download" "Microsoft.DotNet.Arcade.Sdk@$toolset_version" "--verbosity" "minimal" "--prerelease" "--output" "$_InitializeNuGetPackageCachePath") + local nuget_config="${NUGET_CONFIG:-}" + if [[ -z "$nuget_config" ]]; then + # Search for any variation of nuget.config in the RepoRoot + local found_config + found_config=$(find "$repo_root" -maxdepth 1 -type f -iname nuget.config | head -n 1) + + if [[ -n "$found_config" ]]; then + nuget_config="$found_config" + fi + fi + + if [[ -n "$nuget_config" ]]; then + download_args+=("--configfile" "$nuget_config") + fi - local bl="" - if [[ "$binary_log" == true ]]; then - bl="/bl:$log_dir/ToolsetRestore.binlog" + # 'dotnet package download' fails outright if any source in the repo's NuGet.config is + # unavailable (for example a transport feed that was decommissioned after a release). The + # Arcade SDK is always published to the public dotnet-eng feed, so if the config-driven + # download fails, retry once against that feed directly (which ignores the other sources) + # before giving up, so a single dead source doesn't block the build. + if ! DotNet true "${download_args[@]}"; then + echo "Restoring the Arcade SDK from the configured sources failed; retrying from the public dotnet-eng feed." + DotNet "${download_args[@]}" --source "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json" fi - echo '' > "$proj" - MSBuild-Core "$proj" $bl /t:__WriteToolsetLocation /clp:ErrorsOnly\;NoSummary /p:__ToolsetLocationOutputFile="$toolset_location_file" /p:RestoreIgnoreFailedSources=true + local package_dir="$_InitializeNuGetPackageCachePath/microsoft.dotnet.arcade.sdk/$toolset_version" - local toolset_build_proj=`cat "$toolset_location_file"` + if [[ ! -d "$package_dir/toolset" ]]; then + Write-PipelineTelemetryError -category 'InitializeToolset' "Arcade SDK package does not contain a toolset folder: $package_dir" + ExitWithExitCode 3 + fi - if [[ ! -a "$toolset_build_proj" ]]; then - Write-PipelineTelemetryError -category 'Build' "Invalid toolset path: $toolset_build_proj" + mkdir -p "$toolset_tools_dir" + cp -r "$package_dir/toolset/." "$toolset_tools_dir" + + if [[ -a "$toolset_tools_dir/Build.proj" ]]; then + toolset_build_proj="$toolset_tools_dir/Build.proj" + else + Write-PipelineTelemetryError -category 'Build' "Unable to find Build.proj in toolset at: $toolset_tools_dir" ExitWithExitCode 3 fi @@ -444,7 +487,7 @@ function InitializeToolset { } function ExitWithExitCode { - if [[ "$ci" == true && "$prepare_machine" == true ]]; then + if [[ "$prepare_machine" == true ]]; then StopProcesses fi exit $1 @@ -453,52 +496,70 @@ function ExitWithExitCode { function StopProcesses { echo "Killing running build processes..." pkill -9 "dotnet" || true - pkill -9 "vbcscompiler" || true + pkill -9 -i -x VBCSCompiler || true + pkill -9 -i -x MSBuild || true return 0 } -function MSBuild { - local args=( "$@" ) - if [[ "$pipelines_log" == true ]]; then - InitializeBuildTool - InitializeToolset +function DotNet { + # When the first argument is 'true' or 'false' it controls the exit behavior on failure: + # 'true' returns the dotnet exit code to the caller (so it can implement its own fallback), + # while the default terminates the script. Any other first argument is treated as a dotnet argument. + local ignore_failure=false + if [[ "$1" == 'true' || "$1" == 'false' ]]; then + ignore_failure="$1" + shift + fi - if [[ "$ci" == true ]]; then - export NUGET_PLUGIN_HANDSHAKE_TIMEOUT_IN_SECONDS=20 - export NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS=20 - Write-PipelineSetVariable -name "NUGET_PLUGIN_HANDSHAKE_TIMEOUT_IN_SECONDS" -value "20" - Write-PipelineSetVariable -name "NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS" -value "20" - fi + InitializeDotNetCli $restore - local toolset_dir="${_InitializeToolset%/*}" - local selectedPath="$toolset_dir/net/Microsoft.DotNet.ArcadeLogging.dll" + local dotnet_path="$_InitializeDotNetCli/dotnet" - if [[ -z "$selectedPath" ]]; then - Write-PipelineTelemetryError -category 'Build' "Unable to find arcade sdk logger assembly: $selectedPath" - ExitWithExitCode 1 + export ARCADE_BUILD_TOOL_COMMAND="$dotnet_path $@" + + "$dotnet_path" "$@" || { + local exit_code=$? + + if [[ "$ignore_failure" == true ]]; then + return $exit_code fi - args+=( "-logger:$selectedPath" ) - fi + echo "dotnet command failed with exit code $exit_code. Check errors above." - MSBuild-Core "${args[@]}" + if [[ "$ci" == true && -n ${SYSTEM_TEAMPROJECT:-} && "$from_vmr" != true && "$disable_pipeline_set_result" != true ]]; then + Write-PipelineSetResult -result "Failed" -message "dotnet command execution failed." + ExitWithExitCode 0 + else + ExitWithExitCode $exit_code + fi + } } -function MSBuild-Core { +function MSBuild { if [[ "$ci" == true ]]; then if [[ "$binary_log" != true && "$exclude_ci_binary_log" != true ]]; then - Write-PipelineTelemetryError -category 'Build' "Binary log must be enabled in CI build, or explicitly opted-out from with the -noBinaryLog switch." - ExitWithExitCode 1 - fi - - if [[ "$node_reuse" == true ]]; then - Write-PipelineTelemetryError -category 'Build' "Node reuse must be disabled in CI build." + Write-PipelineTelemetryError -category 'Build' "Binary log must be enabled in CI build, or explicitly opted-out from with the --excludeCIBinarylog switch." ExitWithExitCode 1 fi fi InitializeBuildTool + local logger_switch=() + if [[ "$pipelines_log" == true ]]; then + InitializeToolset + + local toolset_dir="${_InitializeToolset%/*}" + local selectedPath="$toolset_dir/net/Microsoft.DotNet.ArcadeLogging.dll" + + # Only inject the logger when it's present. A last-known-good Arcade used to bootstrap + # the build may not ship the logger yet, so its absence must not be a hard error. + # Specify the logger type explicitly so loading is deterministic. + if [[ -f "$selectedPath" ]]; then + logger_switch=("-logger:Microsoft.DotNet.ArcadeLogging.PipelinesLogger,$selectedPath") + fi + fi + local warnaserror_switch="" if [[ $warn_as_error == true ]]; then warnaserror_switch="/warnaserror" @@ -514,8 +575,8 @@ function MSBuild-Core { echo "Build failed with exit code $exit_code. Check errors above." # When running on Azure Pipelines, override the returned exit code to avoid double logging. - # Skip this when the build is a child of the VMR build. - if [[ "$ci" == true && -n ${SYSTEM_TEAMPROJECT:-} && "$from_vmr" != true ]]; then + # Skip this when the build is a child of the VMR build, or when -disablePipelineSetResult is set so the real exit code propagates. + if [[ "$ci" == true && -n ${SYSTEM_TEAMPROJECT:-} && "$from_vmr" != true && "$disable_pipeline_set_result" != true ]]; then Write-PipelineSetResult -result "Failed" -message "msbuild execution failed." # Exiting with an exit code causes the azure pipelines task to log yet another "noise" error # The above Write-PipelineSetResult will cause the task to be marked as failure without adding yet another error @@ -532,7 +593,12 @@ function MSBuild-Core { mt_switch="-mt" fi - RunBuildTool "$_InitializeBuildToolCommand" /m /nologo /clp:Summary /v:$verbosity /nr:$node_reuse $warnaserror_switch $mt_switch /p:TreatWarningsAsErrors=$warn_as_error /p:ContinuousIntegrationBuild=$ci "$@" + local warnnotaserror_switch="" + if [[ -n "$warn_not_as_error" && "$warn_as_error" == true ]]; then + warnnotaserror_switch="/warnnotaserror:$warn_not_as_error /p:AdditionalWarningsNotAsErrors=$warn_not_as_error" + fi + + RunBuildTool "$_InitializeBuildToolCommand" /m /nologo /clp:Summary /v:$verbosity /nr:$node_reuse $warnaserror_switch $mt_switch $warnnotaserror_switch "${logger_switch[@]}" /p:TreatWarningsAsErrors=$warn_as_error /p:ContinuousIntegrationBuild=$ci "$@" } function GetDarc { @@ -549,8 +615,17 @@ function GetDarc { # Returns a full path to an Arcade SDK task project file. function GetSdkTaskProject { - taskName=$1 - echo "$(dirname $_InitializeToolset)/SdkTasks/$taskName.proj" + local taskName=$1 + local toolsetDir + toolsetDir="$(dirname "$_InitializeToolset")" + local proj="$toolsetDir/$taskName.proj" + if [[ -a "$proj" ]]; then + echo "$proj" + return + fi + + Write-PipelineTelemetryError -category 'Build' "Unable to find $taskName.proj in toolset at: $toolsetDir" + ExitWithExitCode 3 } ResolvePath "${BASH_SOURCE[0]}" @@ -588,6 +663,12 @@ mkdir -p "$toolset_dir" mkdir -p "$temp_dir" mkdir -p "$log_dir" +# Direct MSBuild crash diagnostics (MSB4166 failure.txt files) to a known location +# under artifacts/log so they are captured as build artifacts in CI. +if [[ -z "${MSBUILDDEBUGPATH:-}" ]]; then + export MSBUILDDEBUGPATH="$log_dir/MsbuildDebugLogs" +fi + Write-PipelineSetVariable -name "Artifacts" -value "$artifacts_dir" Write-PipelineSetVariable -name "Artifacts.Toolset" -value "$toolset_dir" Write-PipelineSetVariable -name "Artifacts.Log" -value "$log_dir" @@ -608,3 +689,6 @@ fi if [[ -n "${useInstalledDotNetCli:-}" ]]; then use_installed_dotnet_cli="$useInstalledDotNetCli" fi + +# Initialize the nuget package cache vars +InitializeNuGetPackageCachePath diff --git a/eng/templates/regression-test-jobs.yml b/eng/templates/regression-test-jobs.yml index 16da81059c2..ba7a3c19dab 100644 --- a/eng/templates/regression-test-jobs.yml +++ b/eng/templates/regression-test-jobs.yml @@ -141,6 +141,28 @@ jobs: version: '10.0.100' installationPath: $(Pipeline.Workspace)/TestRepo/.dotnet + # Install the SDK that built the compiler (version from global.json) + # into the regression test's .dotnet so fsc.dll can find the runtime. + # Tries default feed first, then ci.dot.net/public (same fallback as eng/common). + - pwsh: | + $v = (Get-Content "$(Build.SourcesDirectory)/global.json" | ConvertFrom-Json).tools.dotnet + $d = "$(Pipeline.Workspace)/TestRepo/.dotnet" + $u = "https://builds.dotnet.microsoft.com/dotnet/scripts/v1" + if ($IsWindows) { + Invoke-WebRequest "$u/dotnet-install.ps1" -OutFile "$d/dotnet-install.ps1" + & "$d/dotnet-install.ps1" -Version $v -InstallDir $d -SkipNonVersionedFiles + if ($LASTEXITCODE -ne 0) { + & "$d/dotnet-install.ps1" -Version $v -InstallDir $d -SkipNonVersionedFiles -AzureFeed "https://ci.dot.net/public" + } + } else { + Invoke-WebRequest "$u/dotnet-install.sh" -OutFile "$d/dotnet-install.sh" + chmod +x "$d/dotnet-install.sh" + bash "$d/dotnet-install.sh" --version $v --install-dir $d --skip-non-versioned-files || + bash "$d/dotnet-install.sh" --version $v --install-dir $d --skip-non-versioned-files --azure-feed "https://ci.dot.net/public" + } + displayName: Install compiler SDK for ${{ item.displayName }} + continueOnError: true + - pwsh: | Set-Location $(Pipeline.Workspace)/TestRepo diff --git a/global.json b/global.json index 88decf7c2a9..6dc5358084a 100644 --- a/global.json +++ b/global.json @@ -1,7 +1,8 @@ { "sdk": { - "version": "10.0.301", + "version": "11.0.100-preview.6.26359.118", "allowPrerelease": true, + "rollForward": "latestMinor", "paths": [ ".dotnet", "$host$" @@ -12,7 +13,7 @@ "runner": "Microsoft.Testing.Platform" }, "tools": { - "dotnet": "10.0.301", + "dotnet": "11.0.100-preview.6.26359.118", "vs": { "version": "18.0", "components": [ @@ -22,7 +23,7 @@ "xcopy-msbuild": "18.0.0" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.26371.2", + "Microsoft.DotNet.Arcade.Sdk": "11.0.0-beta.26369.1", "Microsoft.DotNet.Helix.Sdk": "8.0.0-beta.23255.2" } } diff --git a/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.ProjectFile.fs b/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.ProjectFile.fs index 5386ea5a283..dfe128da71d 100644 --- a/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.ProjectFile.fs +++ b/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.ProjectFile.fs @@ -52,6 +52,7 @@ $(POUND_R) $(RUNTIMEIDENTIFIER) false true + false true @@ -114,6 +115,7 @@ $(PACKAGEREFERENCES) <__Conflicts>@(__ConflictsList, ';'); + <_CopyLocalNames>;@(__InteractiveReferencedAssembliesCopyLocal->'%(Filename)', ';'); @@ -138,6 +140,19 @@ $(PACKAGEREFERENCES) %(__InteractiveReferencedAssembliesCopyLocal.NuGetPackageId) %(__InteractiveReferencedAssembliesCopyLocal.NuGetPackageVersion) + + + + runtime + %(InteractiveResolvedFile.PackageRoot)content\%(InteractiveResolvedFile.NugetPackageId)$(SCRIPTEXTENSION) diff --git a/src/Microsoft.FSharp.Compiler/Microsoft.FSharp.Compiler.fsproj b/src/Microsoft.FSharp.Compiler/Microsoft.FSharp.Compiler.fsproj index 36d7036a22c..066a59b1538 100644 --- a/src/Microsoft.FSharp.Compiler/Microsoft.FSharp.Compiler.fsproj +++ b/src/Microsoft.FSharp.Compiler/Microsoft.FSharp.Compiler.fsproj @@ -12,14 +12,8 @@ - + - - - $(NuGetPackageRoot)microsoft.dotnet.nugetrepack.tasks\$(MicrosoftDotNetNuGetRepackTasksVersion)\tools\netframework\Microsoft.DotNet.NuGetRepack.Tasks.dll - $(NuGetPackageRoot)microsoft.dotnet.nugetrepack.tasks\$(MicrosoftDotNetNuGetRepackTasksVersion)\tools\net\Microsoft.DotNet.NuGetRepack.Tasks.dll - - @@ -101,4 +95,8 @@ DependsOnTargets="PackDependentProjectsCore;PackageReleaseDependentPackages"> + + + + diff --git a/src/fsi/fsiProject/fsi.fsproj b/src/fsi/fsiProject/fsi.fsproj index 1b955f9564e..58a300a0de9 100644 --- a/src/fsi/fsiProject/fsi.fsproj +++ b/src/fsi/fsiProject/fsi.fsproj @@ -10,7 +10,8 @@ $(FSharpNetCoreProductTargetFramework) - $(EnablePublishReadyToRun) + + false $(NETCoreSdkRuntimeIdentifier) diff --git a/tests/Directory.Build.props b/tests/Directory.Build.props index ccc7e44ffa3..0c1a2882fda 100644 --- a/tests/Directory.Build.props +++ b/tests/Directory.Build.props @@ -22,6 +22,10 @@ true + + true diff --git a/tests/EndToEndBuildTests/Directory.Build.props b/tests/EndToEndBuildTests/Directory.Build.props index f97db4e1684..66d1e05ada9 100644 --- a/tests/EndToEndBuildTests/Directory.Build.props +++ b/tests/EndToEndBuildTests/Directory.Build.props @@ -8,7 +8,7 @@ 3.2.2 2.0.2 8.0.0 - 17.14.1 + 18.0.1 diff --git a/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs b/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs index 565753806c2..041905bffb4 100644 --- a/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs +++ b/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs @@ -227,14 +227,16 @@ type DependencyManagerInteractiveTests() = Assert.True((result1.Roots |> Seq.head).EndsWith("/microsoft.extensions.configuration.abstractions/3.1.1/")) // Netstandard gets fewer dependencies than desktop, because desktop framework doesn't contain assemblies like System.Memory - // Those assemblies must be delivered by nuget for desktop apps + // Those assemblies must be delivered by nuget for desktop apps. + // In .NET 11+, Microsoft.Extensions.* assemblies are part of the shared framework. + // The conflict resolution returns framework ref pack paths instead of NuGet cache paths. + // Only the directly-requested package root is available (transitive deps are framework-provided). let result2 = dp1.Resolve(idm1, ".fsx", [|"r", "Microsoft.Extensions.Configuration.Abstractions, 3.1.1"|], reportError, TestFramework.productTfm) Assert.Equal(true, result2.Success) Assert.Equal(2, result2.Resolutions |> Seq.length) - let expected = "/netcoreapp3.1/" - Assert.True((result2.Resolutions |> Seq.head).Contains(expected)) + Assert.True((result2.Resolutions |> Seq.head).Contains("Microsoft.Extensions.Configuration.Abstractions")) Assert.Equal(1, result2.SourceFiles |> Seq.length) - Assert.Equal(2, result2.Roots |> Seq.length) + Assert.Equal(1, result2.Roots |> Seq.length) Assert.True((result2.Roots |> Seq.head).EndsWith("/microsoft.extensions.configuration.abstractions/3.1.1/")) () diff --git a/tests/FSharp.Compiler.Service.Tests/EditorTests.fs b/tests/FSharp.Compiler.Service.Tests/EditorTests.fs index be06517681c..94bded2a3c0 100644 --- a/tests/FSharp.Compiler.Service.Tests/EditorTests.fs +++ b/tests/FSharp.Compiler.Service.Tests/EditorTests.fs @@ -760,6 +760,9 @@ let test3 = System.Text.RegularExpressions.RegexOptions.Compiled ("CultureInvariant", Some (box 512)) #if NETCOREAPP ("NonBacktracking", Some 1024) +#endif +#if NET11_0_OR_GREATER + ("AnyNewLine", Some 2048) #endif ] |] diff --git a/tests/FSharp.Test.Utilities/CompilerAssert.fs b/tests/FSharp.Test.Utilities/CompilerAssert.fs index d09896563e5..7a6315d81ec 100644 --- a/tests/FSharp.Test.Utilities/CompilerAssert.fs +++ b/tests/FSharp.Test.Utilities/CompilerAssert.fs @@ -634,12 +634,17 @@ module CompilerAssertHelpers = let fileName = "dotnet" let arguments = outputFilePath - // Derive the runtime version from productTfm (e.g., "net10.0" -> "10.0.0") - let runtimeVersion = productTfm.Replace("net", "") + ".0" + // Use the actual runtime version so framework resolution works on preview SDKs + // (preview versions like 11.0.0-preview.1 are semver-lower than 11.0.0). + let runtimeVersion = + let desc = System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription + // ".NET 11.0.0-preview.1.26078.121" → "11.0.0-preview.1.26078.121" + desc.Replace(".NET ", "") let runtimeconfig = $""" {{ "runtimeOptions": {{ "tfm": "{productTfm}", + "rollForward": "LatestMinor", "framework": {{ "name": "Microsoft.NETCore.App", "version": "{runtimeVersion}" diff --git a/tests/FSharp.Test.Utilities/ILChecker.fs b/tests/FSharp.Test.Utilities/ILChecker.fs index 24ff56e0587..ad7e01a5baf 100644 --- a/tests/FSharp.Test.Utilities/ILChecker.fs +++ b/tests/FSharp.Test.Utilities/ILChecker.fs @@ -61,7 +61,8 @@ module ILChecker = "\[System\.Runtime\]|\[System\.Console\]|\[System\.Runtime\.Extensions\]|\[mscorlib\]|\[System\.Memory\]|\[System\.Collections\]", "[runtime]" "(\.assembly extern (System\.Runtime|System\.Console|System\.Runtime\.Extensions|mscorlib|System\.Memory)){1}([^\}]*)\}", ".assembly extern runtime { }" "(\.assembly extern (System\.Collections)){1}([^\}]*)\}\\s+", "" - "(\.assembly extern (FSharp.Core)){1}([^\}]*)\}", ".assembly extern FSharp.Core { }" ] + "(\.assembly extern (FSharp.Core)){1}([^\}]*)\}", ".assembly extern FSharp.Core { }" + "(\.assembly extern (System\.Linq)){1}([^\}]*)\}", ".assembly extern System.Linq { }" ] let unifyImageBase ilCode = replace ilCode ("\.imagebase\s*0x\d*", ".imagebase {value}") diff --git a/tests/ILVerify/ilverify.ps1 b/tests/ILVerify/ilverify.ps1 index 1b32a044609..c870bbcf3d5 100644 --- a/tests/ILVerify/ilverify.ps1 +++ b/tests/ILVerify/ilverify.ps1 @@ -164,7 +164,10 @@ foreach ($project in $projects.Keys) { } } - $baseline_file = Join-Path $repo_path "tests/ILVerify" "ilverify_${project}_${configuration}_${tfm}.bsl" + # Map versioned netcoreapp TFMs (net10.0, net11.0, ...) to generic name so baselines + # don't need updating on every TFM bump — the ILVerify output is the same across versions. + $baseline_tfm = if ($tfm -match '^net\d+\.0$') { "netcoreapp" } else { $tfm } + $baseline_file = Join-Path $repo_path "tests/ILVerify" "ilverify_${project}_${configuration}_${baseline_tfm}.bsl" $baseline_actual_file = [System.IO.Path]::ChangeExtension($baseline_file, 'bsl.actual') diff --git a/tests/ILVerify/ilverify_FSharp.Compiler.Service_Debug_net10.0.bsl b/tests/ILVerify/ilverify_FSharp.Compiler.Service_Debug_netcoreapp.bsl similarity index 100% rename from tests/ILVerify/ilverify_FSharp.Compiler.Service_Debug_net10.0.bsl rename to tests/ILVerify/ilverify_FSharp.Compiler.Service_Debug_netcoreapp.bsl diff --git a/tests/ILVerify/ilverify_FSharp.Compiler.Service_Release_net10.0.bsl b/tests/ILVerify/ilverify_FSharp.Compiler.Service_Release_netcoreapp.bsl similarity index 100% rename from tests/ILVerify/ilverify_FSharp.Compiler.Service_Release_net10.0.bsl rename to tests/ILVerify/ilverify_FSharp.Compiler.Service_Release_netcoreapp.bsl From 0c94e4e0c6a3f477cea980e30d0db257de9e4e09 Mon Sep 17 00:00:00 2001 From: kerams Date: Tue, 28 Jul 2026 20:16:45 +0200 Subject: [PATCH 20/33] Support NotNullIfNotNullAttribute (#19977) --- .../.FSharp.Compiler.Service/11.0.100.md | 1 + docs/release-notes/.Language/preview.md | 1 + src/Compiler/AbstractIL/il.fs | 1 + src/Compiler/AbstractIL/il.fsi | 1 + .../Checking/Expressions/CheckExpressions.fs | 79 ++- src/Compiler/Checking/MethodCalls.fs | 8 + src/Compiler/Checking/NicePrint.fs | 2 +- .../AssemblyResolveHandler.fs | 4 +- src/Compiler/FSComp.txt | 1 + src/Compiler/Facilities/LanguageFeatures.fs | 3 + src/Compiler/Facilities/LanguageFeatures.fsi | 1 + .../TypedTree/TypedTreeOps.Attributes.fs | 6 + src/Compiler/TypedTree/WellKnownAttribs.fs | 1 + src/Compiler/TypedTree/WellKnownAttribs.fsi | 1 + src/Compiler/Utilities/range.fs | 2 +- src/Compiler/xlf/FSComp.txt.cs.xlf | 5 + src/Compiler/xlf/FSComp.txt.de.xlf | 5 + src/Compiler/xlf/FSComp.txt.es.xlf | 5 + src/Compiler/xlf/FSComp.txt.fr.xlf | 5 + src/Compiler/xlf/FSComp.txt.it.xlf | 5 + src/Compiler/xlf/FSComp.txt.ja.xlf | 5 + src/Compiler/xlf/FSComp.txt.ko.xlf | 5 + src/Compiler/xlf/FSComp.txt.pl.xlf | 5 + src/Compiler/xlf/FSComp.txt.pt-BR.xlf | 5 + src/Compiler/xlf/FSComp.txt.ru.xlf | 5 + src/Compiler/xlf/FSComp.txt.tr.xlf | 5 + src/Compiler/xlf/FSComp.txt.zh-Hans.xlf | 5 + src/Compiler/xlf/FSComp.txt.zh-Hant.xlf | 5 + .../FSharp.Compiler.ComponentTests.fsproj | 1 + .../Nullness/NotNullIfNotNullTests.fs | 537 ++++++++++++++++++ ...iler.Service.SurfaceArea.netstandard20.bsl | 1 + 31 files changed, 711 insertions(+), 5 deletions(-) create mode 100644 tests/FSharp.Compiler.ComponentTests/Language/Nullness/NotNullIfNotNullTests.fs diff --git a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md index 01747f0b583..632fcac6b93 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md +++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md @@ -142,6 +142,7 @@ * Debug: rework for expressions stepping ([PR #19894](https://github.com/dotnet/fsharp/pull/19894)) * Debug: rework conditional erasure, fix stepping over literals ([PR #19897](https://github.com/dotnet/fsharp/pull/19897)) * Debug: fix if and match condition sequence points ([PR #19932](https://github.com/dotnet/fsharp/pull/19932)) +* Support common types of `NotNullIfNotNullAttribute` usage. If a method parameter is marked with `NotNullIfNotNullAttribute`, the compiler will now honor this attribute and mark the return type as non-null. ([PR #19977](https://github.com/dotnet/fsharp/pull/19977)) * Checker: recover on checking language version ([PR ##19970](https://github.com/dotnet/fsharp/pull/19970)) * Implied argument names for function-to-delegate coercions now fall back to the delegate's `Invoke` parameter names when the function has no recoverable names (e.g. a partial application like `System.Func((+) 1)`), instead of synthetic `delegateArg0`, `delegateArg1`, … names. ([PR #20001](https://github.com/dotnet/fsharp/pull/20001)) * Add internal `ResetCompilerGeneratedNameState` to `CompilerGlobalState` name generators so warm-checker re-compilation can produce fresh-process-identical generated names. ([PR #20017](https://github.com/dotnet/fsharp/pull/20017)) diff --git a/docs/release-notes/.Language/preview.md b/docs/release-notes/.Language/preview.md index 8172d510f76..1c37adc77c2 100644 --- a/docs/release-notes/.Language/preview.md +++ b/docs/release-notes/.Language/preview.md @@ -3,6 +3,7 @@ * Warn (FS3884) when a function or delegate value is used as an interpolated string argument, since it will be formatted via `ToString` rather than being applied. ([PR #19289](https://github.com/dotnet/fsharp/pull/19289)) * Added `MethodOverloadsCache` language feature (preview) that caches overload resolution results for repeated method calls, significantly improving compilation performance. ([PR #19072](https://github.com/dotnet/fsharp/pull/19072)) * Added `ErrorOnMissingSignatureAttribute` preview language feature: makes FS3888 (compiler-semantic attribute on the `.fs` but not on the `.fsi`) an error instead of a warning. ([Issue #19560](https://github.com/dotnet/fsharp/issues/19560), [PR #19880](https://github.com/dotnet/fsharp/pull/19880)) +* Support common types of `NotNullIfNotNullAttribute` usage. If a method parameter is marked with `NotNullIfNotNullAttribute`, the compiler will now honor this attribute and mark the return type as non-null. ([PR #19977](https://github.com/dotnet/fsharp/pull/19977)) * Added `AccessProtectedBaseFieldFromClosure` preview language feature: a derived member can now read a `protected` base-class field from an ordinary closure (lambda, delegate, `async`/`seq`/`lazy`, `function`, or list/array literal), which previously failed with FS1097 even though direct access compiles. Object expressions remain unsupported — bind the field to a local function or expose it through a member. ([Issue #5302](https://github.com/dotnet/fsharp/issues/5302)) * Added `ImprovedImpliedArgumentNamesPartTwo` language feature: when a function with no recoverable parameter names is coerced to a delegate (e.g. a partial application like `System.Func((+) 1)`), the synthesized `Invoke` parameters take their names from the delegate's own `Invoke` signature instead of synthetic `delegateArg0`, `delegateArg1`, … names. ([PR #20001](https://github.com/dotnet/fsharp/pull/20001)) diff --git a/src/Compiler/AbstractIL/il.fs b/src/Compiler/AbstractIL/il.fs index c3023ed9579..e2002731aa8 100644 --- a/src/Compiler/AbstractIL/il.fs +++ b/src/Compiler/AbstractIL/il.fs @@ -1258,6 +1258,7 @@ type WellKnownILAttributes = | RequiredMemberAttribute = (1u <<< 22) | NullableContextAttribute = (1u <<< 23) | AttributeUsageAttribute = (1u <<< 24) + | NotNullIfNotNullAttribute = (1u <<< 25) | NotComputed = (1u <<< 31) type internal ILAttributesStoredRepr = diff --git a/src/Compiler/AbstractIL/il.fsi b/src/Compiler/AbstractIL/il.fsi index aef29b61d9b..050921650c3 100644 --- a/src/Compiler/AbstractIL/il.fsi +++ b/src/Compiler/AbstractIL/il.fsi @@ -912,6 +912,7 @@ type WellKnownILAttributes = | RequiredMemberAttribute = (1u <<< 22) | NullableContextAttribute = (1u <<< 23) | AttributeUsageAttribute = (1u <<< 24) + | NotNullIfNotNullAttribute = (1u <<< 25) | NotComputed = (1u <<< 31) /// Represents the efficiency-oriented storage of ILAttributes in another item. diff --git a/src/Compiler/Checking/Expressions/CheckExpressions.fs b/src/Compiler/Checking/Expressions/CheckExpressions.fs index 288f99e67e7..b3fa0965216 100644 --- a/src/Compiler/Checking/Expressions/CheckExpressions.fs +++ b/src/Compiler/Checking/Expressions/CheckExpressions.fs @@ -3359,6 +3359,46 @@ let GetMethodArgs arg = unnamedCallerArgs, namedCallerArgs +let NotNullIfNotNullParamNames g (minfo: MethInfo) = + match minfo with + | ILMeth(ilMethInfo = ilminfo) when ilminfo.RawMetadata.Return.CustomAttrsStored.HasWellKnownAttribute (g, WellKnownILAttributes.NotNullIfNotNullAttribute) -> + ilminfo.RawMetadata.Return.CustomAttrs.AsArray() + |> Array.toList + |> List.choose (fun attr -> + if classifyILAttrib attr &&& WellKnownILAttributes.NotNullIfNotNullAttribute <> WellKnownILAttributes.None then + match decodeILAttribData attr with + | [ ILAttribElem.String (Some paramName) ], _ -> Some paramName + | _ -> None + else + None) + | FSMeth(valRef = vref) -> + match vref.ValReprInfo with + | Some (ValReprInfo(result = retInfo)) when ArgReprInfoHasWellKnownAttribute g WellKnownValAttributes.NotNullIfNotNullAttribute retInfo -> + retInfo.Attribs.AsList() + |> List.choose (fun attrib -> + if classifyValAttrib g attrib &&& WellKnownValAttributes.NotNullIfNotNullAttribute <> WellKnownValAttributes.None then + match attrib with + | Attrib(unnamedArgs = [ AttribStringArg paramName ]) -> Some paramName + | _ -> None + else + None) + | _ -> [] + | _ -> [] + +// Resolve the caller argument bound to 'paramName' and return the type of its type-checked expression. +let TryGetCallerArgType g (minfo: MethInfo) (callerArgs: CallerArgs<_>) paramName = + // First try to find a named argument with the given name + callerArgs.Named + |> List.tryPick (List.tryPick (fun (CallerNamedArg(id, arg)) -> if id.idText = paramName then Some arg else None)) + |> Option.orElseWith (fun () -> + // If there is no matching named argument, find the argument in the same position as the parameter with the given name + minfo.GetParamNames() + |> Seq.concat + |> Seq.tryFindIndex (fun nm -> match nm with Some nm -> nm = paramName | _ -> false) + |> Option.bind (fun idx -> Seq.concat callerArgs.Unnamed |> Seq.tryItem idx) + ) + |> Option.map (fun arg -> tyOfExpr g arg.Expr) + //------------------------------------------------------------------------- // Helpers dealing with sequence expressions //------------------------------------------------------------------------- @@ -10307,12 +10347,26 @@ and TcMethodApplication_UniqueOverloadInference let arityFilteredCandidates = candidateMethsAndProps - let makeOneCalledMeth (minfo, pinfoOpt, usesParamArrayConversion) = + let makeOneCalledMeth (minfo: MethInfo, pinfoOpt, usesParamArrayConversion) = let minst = FreshenMethInfo mItem minfo let callerTyArgs = match tyArgsOpt with | Some tyargs -> minfo.AdjustUserTypeInstForFSharpStyleIndexedExtensionMembers tyargs | None -> minst + + // If the return value is [], give the return a fresh nullness inference variable here so that + // unique-overload inference does not prematurely commit the result to the declared (nullable) nullness. The real + // nullness is resolved post argument type-checking (see below), once the argument types are known. + let minfo = + if not minfo.IsConstructor && g.checkNullness && g.langVersion.SupportsFeature LanguageFeature.NotNullIfNotNull then + match NotNullIfNotNullParamNames g minfo with + | [ _ ] -> + let retTy = minfo.GetFSharpReturnType(cenv.amap, mMethExpr, callerTyArgs) + MethInfoWithModifiedReturnType(minfo, replaceNullnessOfTy (NewNullnessVar()) retTy) + | _ -> minfo + else + minfo + CalledMeth(cenv.infoReader, Some(env.NameEnv), isCheckingAttributeCall, FreshenMethInfo, mMethExpr, ad, minfo, minst, callerTyArgs, pinfoOpt, callerObjArgTys, callerArgs, usesParamArrayConversion, true, objTyOpt, staticTyOpt) let preArgumentTypeCheckingCalledMethGroup = @@ -10570,6 +10624,29 @@ and TcMethodApplication match tyArgsOpt with | Some tyargs -> minfo.AdjustUserTypeInstForFSharpStyleIndexedExtensionMembers tyargs | None -> minst + + let minfo = + if not minfo.IsConstructor && g.checkNullness && g.langVersion.SupportsFeature LanguageFeature.NotNullIfNotNull then + // 'minfo' may already carry a placeholder return nullness from unique-overload inference (phase 1); + // strip it back to the base method before applying the real (argument-derived) nullness. + let baseMinfo = match minfo with MethInfoWithModifiedReturnType(inner, _) -> inner | _ -> minfo + match NotNullIfNotNullParamNames g baseMinfo with + | [ paramName ] -> + match TryGetCallerArgType g baseMinfo callerArgs paramName with + | Some callerArgTy -> + let callerArgTy = if isByrefTy g callerArgTy then destByrefTy g callerArgTy else callerArgTy + let retTy = baseMinfo.GetFSharpReturnType(cenv.amap, mMethExpr, callerTyArgs) + let argNullness = + if TypeNullIsTrueValue g callerArgTy || TypeNullIsExtraValueNew g mMethExpr callerArgTy then + g.knownWithNull + else + nullnessOfTy g callerArgTy + MethInfoWithModifiedReturnType(baseMinfo, replaceNullnessOfTy argNullness retTy) + | None -> baseMinfo + | _ -> baseMinfo + else + minfo + CalledMeth(cenv.infoReader, Some(env.NameEnv), isCheckingAttributeCall, FreshenMethInfo, mMethExpr, ad, minfo, minst, callerTyArgs, pinfoOpt, callerObjArgTys, callerArgs, usesParamArrayConversion, true, objTyOpt, staticTyOpt)) // Commit unassociated constraints prior to member overload resolution where there is ambiguity diff --git a/src/Compiler/Checking/MethodCalls.fs b/src/Compiler/Checking/MethodCalls.fs index 156e52faee1..adf79f17a67 100644 --- a/src/Compiler/Checking/MethodCalls.fs +++ b/src/Compiler/Checking/MethodCalls.fs @@ -1250,6 +1250,14 @@ let rec BuildMethodCall tcVal g amap isMutable m isProp minfo valUseFlags minst let expr = mkCoerceExpr (expr, retTy, m, exprTy) expr, retTy + | MethInfoWithModifiedReturnType((FSMeth(_, _, vref, _) as innerMeth), retTy) -> + // Build the inner call directly, without re-invoking TakeObjAddrForMethodCall. + let vExpr, vExprTy = tcVal vref valUseFlags (innerMeth.DeclaringTypeInst @ minst) m + let expr, exprTy = BuildFSharpMethodApp g m vref vExpr vExprTy allArgs + + let expr = mkCoerceExpr (expr, retTy, m, exprTy) + expr, retTy + | MethInfoWithModifiedReturnType _ -> failwith "MethInfoWithModifiedReturnType: unexpected inner method kind" diff --git a/src/Compiler/Checking/NicePrint.fs b/src/Compiler/Checking/NicePrint.fs index 91751d5c8e5..673a74c82b9 100644 --- a/src/Compiler/Checking/NicePrint.fs +++ b/src/Compiler/Checking/NicePrint.fs @@ -1742,7 +1742,7 @@ module InfoMemberPrinting = let layout,paramLayouts = match denv.showCsharpCodeAnalysisAttributes, minfo with - | true, ILMeth(_g,mi,_e) -> + | true, (ILMeth(_, mi, _) | MethInfoWithModifiedReturnType(ILMeth(_, mi, _), _)) -> let methodLayout = // Render Method attributes and [return:..] attributes on separate lines above (@@) the method definition PrintTypes.layoutCsharpCodeAnalysisIlAttributes denv (minfo.GetCustomAttrs()) (squareAngleL >> (@@)) layout diff --git a/src/Compiler/DependencyManager/AssemblyResolveHandler.fs b/src/Compiler/DependencyManager/AssemblyResolveHandler.fs index 6daf749f87f..d59b65d835e 100644 --- a/src/Compiler/DependencyManager/AssemblyResolveHandler.fs +++ b/src/Compiler/DependencyManager/AssemblyResolveHandler.fs @@ -54,7 +54,7 @@ type AssemblyResolveHandlerCoreclr(assemblyProbingPaths: AssemblyResolutionProbe let assemblyPathOpt = assemblyPaths - |> Seq.tryFind (fun path -> Path.GetFileNameWithoutExtension(path) = simpleName) + |> Seq.tryFind (fun path -> String.Equals(Path.GetFileNameWithoutExtension(path), simpleName)) match assemblyPathOpt with | Some path -> loadAssembly path @@ -84,7 +84,7 @@ type AssemblyResolveHandlerDeskTop(assemblyProbingPaths: AssemblyResolutionProbe let assemblyPathOpt = assemblyPaths - |> Seq.tryFind (fun path -> Path.GetFileNameWithoutExtension(path) = simpleName) + |> Seq.tryFind (fun path -> String.Equals(Path.GetFileNameWithoutExtension(path), simpleName)) match assemblyPathOpt with | Some path -> Assembly.LoadFrom path diff --git a/src/Compiler/FSComp.txt b/src/Compiler/FSComp.txt index 52f284ca0dc..2b4bc25c5a7 100644 --- a/src/Compiler/FSComp.txt +++ b/src/Compiler/FSComp.txt @@ -1825,5 +1825,6 @@ featurePreprocessorElif,"#elif preprocessor directive" 3891,tcGenericAttributesNotSupported,"Generic attribute types are not supported in F#. The type '%s' has type parameters and cannot be used as an attribute." featureExceptionFieldSerializationSupport,"emit GetObjectData and field-restoring deserialization constructor for exception types" featureErrorOnMissingSignatureAttribute,"error (rather than warning) when an enforced compiler-semantic attribute is present in the .fs but missing from the .fsi" +featureNotNullIfNotNull,"honor the 'NotNullIfNotNull' attribute on a method's return value" featureAccessProtectedBaseFieldFromClosure,"Access a protected base-class field from a closure inside a member" featureImprovedImpliedArgumentNamesPartTwo,"Improved implied argument names with partial application" diff --git a/src/Compiler/Facilities/LanguageFeatures.fs b/src/Compiler/Facilities/LanguageFeatures.fs index 9ecc56472c6..1356335fd28 100644 --- a/src/Compiler/Facilities/LanguageFeatures.fs +++ b/src/Compiler/Facilities/LanguageFeatures.fs @@ -110,6 +110,7 @@ type LanguageFeature = | PreprocessorElif | ExceptionFieldSerializationSupport | ErrorOnMissingSignatureAttribute + | NotNullIfNotNull | AccessProtectedBaseFieldFromClosure | ImprovedImpliedArgumentNamesPartTwo @@ -256,6 +257,7 @@ type LanguageVersion(versionText, ?disabledFeaturesArray: LanguageFeature array) LanguageFeature.WarnWhenFunctionValueUsedAsInterpolatedStringArg, languageVersion110 LanguageFeature.PreprocessorElif, languageVersion110 LanguageFeature.ExceptionFieldSerializationSupport, languageVersion110 + LanguageFeature.NotNullIfNotNull, languageVersion110 LanguageFeature.ImprovedImpliedArgumentNamesPartTwo, languageVersion110 // Difference between languageVersion110 and preview - 11.0 gets turned on automatically by picking a preview .NET 11 SDK @@ -463,6 +465,7 @@ type LanguageVersion(versionText, ?disabledFeaturesArray: LanguageFeature array) | LanguageFeature.PreprocessorElif -> FSComp.SR.featurePreprocessorElif () | LanguageFeature.ExceptionFieldSerializationSupport -> FSComp.SR.featureExceptionFieldSerializationSupport () | LanguageFeature.ErrorOnMissingSignatureAttribute -> FSComp.SR.featureErrorOnMissingSignatureAttribute () + | LanguageFeature.NotNullIfNotNull -> FSComp.SR.featureNotNullIfNotNull () | LanguageFeature.AccessProtectedBaseFieldFromClosure -> FSComp.SR.featureAccessProtectedBaseFieldFromClosure () | LanguageFeature.ImprovedImpliedArgumentNamesPartTwo -> FSComp.SR.featureImprovedImpliedArgumentNamesPartTwo () diff --git a/src/Compiler/Facilities/LanguageFeatures.fsi b/src/Compiler/Facilities/LanguageFeatures.fsi index 4aa85a42224..c5d4009bc04 100644 --- a/src/Compiler/Facilities/LanguageFeatures.fsi +++ b/src/Compiler/Facilities/LanguageFeatures.fsi @@ -101,6 +101,7 @@ type LanguageFeature = | PreprocessorElif | ExceptionFieldSerializationSupport | ErrorOnMissingSignatureAttribute + | NotNullIfNotNull | AccessProtectedBaseFieldFromClosure | ImprovedImpliedArgumentNamesPartTwo diff --git a/src/Compiler/TypedTree/TypedTreeOps.Attributes.fs b/src/Compiler/TypedTree/TypedTreeOps.Attributes.fs index dd2b7cebe14..8eb82ec2639 100644 --- a/src/Compiler/TypedTree/TypedTreeOps.Attributes.fs +++ b/src/Compiler/TypedTree/TypedTreeOps.Attributes.fs @@ -183,6 +183,7 @@ module internal ILExtensions = WellKnownILAttributes.SetsRequiredMembersAttribute | "System.ObsoleteAttribute" -> WellKnownILAttributes.ObsoleteAttribute | "System.Diagnostics.CodeAnalysis.ExperimentalAttribute" -> WellKnownILAttributes.ExperimentalAttribute + | "System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute" -> WellKnownILAttributes.NotNullIfNotNullAttribute | "System.AttributeUsageAttribute" -> WellKnownILAttributes.AttributeUsageAttribute | _ -> WellKnownILAttributes.None @@ -592,6 +593,11 @@ module internal AttributeHelpers = | "ConditionalAttribute" -> WellKnownValAttributes.ConditionalAttribute | _ -> WellKnownValAttributes.None + | [| "System"; "Diagnostics"; "CodeAnalysis"; name |] -> + match name with + | "NotNullIfNotNullAttribute" -> WellKnownValAttributes.NotNullIfNotNullAttribute + | _ -> WellKnownValAttributes.None + | [| "System"; name |] -> match name with | "ThreadStaticAttribute" -> WellKnownValAttributes.ThreadStaticAttribute diff --git a/src/Compiler/TypedTree/WellKnownAttribs.fs b/src/Compiler/TypedTree/WellKnownAttribs.fs index fac3508a56e..748f525b89c 100644 --- a/src/Compiler/TypedTree/WellKnownAttribs.fs +++ b/src/Compiler/TypedTree/WellKnownAttribs.fs @@ -116,6 +116,7 @@ type internal WellKnownValAttributes = | NoEagerConstraintApplicationAttribute = (1uL <<< 38) | ValueAsStaticPropertyAttribute = (1uL <<< 39) | TailCallAttribute = (1uL <<< 40) + | NotNullIfNotNullAttribute = (1uL <<< 41) | NotComputed = (1uL <<< 63) module internal Flags = diff --git a/src/Compiler/TypedTree/WellKnownAttribs.fsi b/src/Compiler/TypedTree/WellKnownAttribs.fsi index da7a7b67f33..4939f94aaa8 100644 --- a/src/Compiler/TypedTree/WellKnownAttribs.fsi +++ b/src/Compiler/TypedTree/WellKnownAttribs.fsi @@ -114,6 +114,7 @@ type internal WellKnownValAttributes = | NoEagerConstraintApplicationAttribute = (1uL <<< 38) | ValueAsStaticPropertyAttribute = (1uL <<< 39) | TailCallAttribute = (1uL <<< 40) + | NotNullIfNotNullAttribute = (1uL <<< 41) | NotComputed = (1uL <<< 63) module internal Flags = diff --git a/src/Compiler/Utilities/range.fs b/src/Compiler/Utilities/range.fs index 3a22199c32f..2a05fa74c75 100755 --- a/src/Compiler/Utilities/range.fs +++ b/src/Compiler/Utilities/range.fs @@ -334,7 +334,7 @@ type Range(code1: int64, code2: int64) = member m.FileName = fileOfFileIndex m.FileIndex member internal m.ShortFileName = - Path.GetFileName(fileOfFileIndex m.FileIndex) |> nonNull + Path.GetFileName(fileOfFileIndex m.FileIndex) |> Unchecked.nonNull member m.ApplyLineDirectives() = match LineDirectives.store.TryFind m.FileIndex with diff --git a/src/Compiler/xlf/FSComp.txt.cs.xlf b/src/Compiler/xlf/FSComp.txt.cs.xlf index 9334bfd8de2..97a0e7790ea 100644 --- a/src/Compiler/xlf/FSComp.txt.cs.xlf +++ b/src/Compiler/xlf/FSComp.txt.cs.xlf @@ -537,6 +537,11 @@ neproměnné vzory napravo od vzorů typu „jako“ + + honor the 'NotNullIfNotNull' attribute on a method's return value + honor the 'NotNullIfNotNull' attribute on a method's return value + + nullable optional interop nepovinný zprostředkovatel komunikace s možnou hodnotou null diff --git a/src/Compiler/xlf/FSComp.txt.de.xlf b/src/Compiler/xlf/FSComp.txt.de.xlf index c17001c39ee..a503b84d990 100644 --- a/src/Compiler/xlf/FSComp.txt.de.xlf +++ b/src/Compiler/xlf/FSComp.txt.de.xlf @@ -537,6 +537,11 @@ Nicht-Variablenmuster rechts neben as-Mustern + + honor the 'NotNullIfNotNull' attribute on a method's return value + honor the 'NotNullIfNotNull' attribute on a method's return value + + nullable optional interop Interop, NULL-Werte zulassend, optional diff --git a/src/Compiler/xlf/FSComp.txt.es.xlf b/src/Compiler/xlf/FSComp.txt.es.xlf index 9d678e0a8c2..bceeb3bd1c0 100644 --- a/src/Compiler/xlf/FSComp.txt.es.xlf +++ b/src/Compiler/xlf/FSComp.txt.es.xlf @@ -537,6 +537,11 @@ patrones no variables a la derecha de los patrones "as" + + honor the 'NotNullIfNotNull' attribute on a method's return value + honor the 'NotNullIfNotNull' attribute on a method's return value + + nullable optional interop interoperabilidad opcional que admite valores NULL diff --git a/src/Compiler/xlf/FSComp.txt.fr.xlf b/src/Compiler/xlf/FSComp.txt.fr.xlf index 59431250f44..e07e1f49ea6 100644 --- a/src/Compiler/xlf/FSComp.txt.fr.xlf +++ b/src/Compiler/xlf/FSComp.txt.fr.xlf @@ -537,6 +537,11 @@ modèles non variables à droite de modèles « as » + + honor the 'NotNullIfNotNull' attribute on a method's return value + honor the 'NotNullIfNotNull' attribute on a method's return value + + nullable optional interop interopérabilité facultative pouvant accepter une valeur null diff --git a/src/Compiler/xlf/FSComp.txt.it.xlf b/src/Compiler/xlf/FSComp.txt.it.xlf index 0c5bd18a17a..38976ac7b68 100644 --- a/src/Compiler/xlf/FSComp.txt.it.xlf +++ b/src/Compiler/xlf/FSComp.txt.it.xlf @@ -537,6 +537,11 @@ modelli non variabili a destra dei modelli 'as' + + honor the 'NotNullIfNotNull' attribute on a method's return value + honor the 'NotNullIfNotNull' attribute on a method's return value + + nullable optional interop Interop facoltativo nullable diff --git a/src/Compiler/xlf/FSComp.txt.ja.xlf b/src/Compiler/xlf/FSComp.txt.ja.xlf index c18e74bd681..7887ada006d 100644 --- a/src/Compiler/xlf/FSComp.txt.ja.xlf +++ b/src/Compiler/xlf/FSComp.txt.ja.xlf @@ -537,6 +537,11 @@ 'as' パターンの右側の非変数パターン + + honor the 'NotNullIfNotNull' attribute on a method's return value + honor the 'NotNullIfNotNull' attribute on a method's return value + + nullable optional interop Null 許容のオプションの相互運用 diff --git a/src/Compiler/xlf/FSComp.txt.ko.xlf b/src/Compiler/xlf/FSComp.txt.ko.xlf index 30fedb9db77..a56015989b0 100644 --- a/src/Compiler/xlf/FSComp.txt.ko.xlf +++ b/src/Compiler/xlf/FSComp.txt.ko.xlf @@ -537,6 +537,11 @@ 'as' 패턴의 오른쪽에 있는 변수가 아닌 패턴 + + honor the 'NotNullIfNotNull' attribute on a method's return value + honor the 'NotNullIfNotNull' attribute on a method's return value + + nullable optional interop nullable 선택적 interop diff --git a/src/Compiler/xlf/FSComp.txt.pl.xlf b/src/Compiler/xlf/FSComp.txt.pl.xlf index 72b79d252d3..99f0175e0ac 100644 --- a/src/Compiler/xlf/FSComp.txt.pl.xlf +++ b/src/Compiler/xlf/FSComp.txt.pl.xlf @@ -537,6 +537,11 @@ stałe wzorce po prawej stronie wzorców typu „as” + + honor the 'NotNullIfNotNull' attribute on a method's return value + honor the 'NotNullIfNotNull' attribute on a method's return value + + nullable optional interop opcjonalna międzyoperacyjność dopuszczająca wartość null diff --git a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf index acd4495941f..0e9f94e1b47 100644 --- a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf +++ b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf @@ -537,6 +537,11 @@ padrões não-variáveis à direita dos padrões 'as'. + + honor the 'NotNullIfNotNull' attribute on a method's return value + honor the 'NotNullIfNotNull' attribute on a method's return value + + nullable optional interop interoperabilidade opcional anulável diff --git a/src/Compiler/xlf/FSComp.txt.ru.xlf b/src/Compiler/xlf/FSComp.txt.ru.xlf index d2b1901323b..917dfd8f862 100644 --- a/src/Compiler/xlf/FSComp.txt.ru.xlf +++ b/src/Compiler/xlf/FSComp.txt.ru.xlf @@ -537,6 +537,11 @@ шаблоны без переменных справа от шаблонов "as" + + honor the 'NotNullIfNotNull' attribute on a method's return value + honor the 'NotNullIfNotNull' attribute on a method's return value + + nullable optional interop необязательное взаимодействие, допускающее значение NULL diff --git a/src/Compiler/xlf/FSComp.txt.tr.xlf b/src/Compiler/xlf/FSComp.txt.tr.xlf index d366bb71ee7..42aa78dda0c 100644 --- a/src/Compiler/xlf/FSComp.txt.tr.xlf +++ b/src/Compiler/xlf/FSComp.txt.tr.xlf @@ -537,6 +537,11 @@ 'as' desenlerinin sağındaki değişken olmayan desenler + + honor the 'NotNullIfNotNull' attribute on a method's return value + honor the 'NotNullIfNotNull' attribute on a method's return value + + nullable optional interop null atanabilir isteğe bağlı birlikte çalışma diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf index 8dce1744238..712bae2f841 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf @@ -537,6 +537,11 @@ "as" 模式右侧的非变量模式 + + honor the 'NotNullIfNotNull' attribute on a method's return value + honor the 'NotNullIfNotNull' attribute on a method's return value + + nullable optional interop 可以为 null 的可选互操作 diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf index 919e332bb06..1e59d46c405 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf @@ -537,6 +537,11 @@ 'as' 模式右邊的非變數模式 + + honor the 'NotNullIfNotNull' attribute on a method's return value + honor the 'NotNullIfNotNull' attribute on a method's return value + + nullable optional interop 可為 Null 的選擇性 Interop diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj index 962871768cc..18ec085a3f2 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj +++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj @@ -382,6 +382,7 @@ + diff --git a/tests/FSharp.Compiler.ComponentTests/Language/Nullness/NotNullIfNotNullTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/Nullness/NotNullIfNotNullTests.fs new file mode 100644 index 00000000000..f9305cc1ba5 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/Nullness/NotNullIfNotNullTests.fs @@ -0,0 +1,537 @@ +module Language.NotNullIfNotNull + +open FSharp.Test +open FSharp.Test.Compiler + +let withStrictNullness cu = + cu + |> withLangVersionPreview + |> withCheckNulls + |> withWarnOn 3261 + |> withOptions ["--warnaserror+"] + +let typeCheckWithStrictNullness cu = + cu + |> withStrictNullness + |> typecheck + +let csNotNullLib = + CSharp """ +#nullable enable +using System.Diagnostics.CodeAnalysis; +namespace NotNullLib { + public class C { + [return: NotNullIfNotNull("input")] + public static string? Echo(string? input) => input; + + // The result is non-null when the SECOND parameter is non-null. + [return: NotNullIfNotNull("second")] + public static string? DependsOnSecond(string? first, string? second) => second; + + // Generic echo: 'T' is inferred to the F# argument type with no coercion, so the + // argument's own nullness (including runtime representations like option/unit) is preserved. + [return: NotNullIfNotNull("input")] + public static T EchoGeneric(T input) => input; + + // Object echo: the argument is coerced to 'object', but a 'with null' nullness rides along. + [return: NotNullIfNotNull("input")] + public static object? EchoObj(object? input) => input; + + // Byref echo: the argument arrives as byref; the referenced nullness is the + // element's, not the (always non-null) byref wrapper's. + [return: NotNullIfNotNull("s")] + public static string? RefEcho(ref string? s) => s; + } + + public static class Extensions { + // Degenerate case: the return depends on the 'this' parameter of a C#-style extension method. + // When called instance-style the receiver is an object argument, not an unnamed caller argument. + [return: NotNullIfNotNull("self")] + public static string? PreferSelf(this string? self, string? other) => self ?? other; + } + + public static class Variadic { + // The result depends on an optional parameter ('b') that is not in the first position. + [return: NotNullIfNotNull("b")] + public static string? PickB(string? a = null, string? b = null) => b ?? a; + + // The result depends on the first parameter, which precedes a params array. + [return: NotNullIfNotNull("first")] + public static string? JoinRest(string? first, params string?[] rest) => first; + } +}""" |> withName "csNotNullLib" + +let private nullableExpected = "was expected but this expression is nullable" + +[] +let ``BCL Path.GetExtension - non-null input yields non-null result`` () = + FSharp """module MyLibrary +open System.IO + +let nonNull : string = "file.txt" +let ext : string = Path.GetExtension(nonNull) +""" + |> asLibrary + |> typeCheckWithStrictNullness + |> shouldSucceed + +[] +let ``BCL Path.GetExtension - nullable input yields nullable result`` () = + FSharp """module MyLibrary +open System.IO + +let maybeNull : string | null = "file.txt" +let ext : string = Path.GetExtension(maybeNull) +""" + |> asLibrary + |> typeCheckWithStrictNullness + |> shouldFail + |> withDiagnosticMessageMatches nullableExpected + +[] +let ``Multiple NotNullIfNotNull attributes are not supported - Delegate.Combine stays nullable`` () = + // Delegate.Combine carries two [return: NotNullIfNotNull] attributes. We cannot currently represent nullness linking + // to multiple types (logical OR), so the declared nullable return type is kept even though an argument is non-null. + FSharp """module MyLibrary +open System + +let d1 : Delegate = Action(fun () -> ()) :> Delegate +let dMaybe : Delegate | null = null + +let combined : Delegate = Delegate.Combine(d1, dMaybe) +""" + |> asLibrary + |> typeCheckWithStrictNullness + |> shouldFail + |> withDiagnosticMessageMatches nullableExpected + +[] +let ``Csharp NotNullIfNotNull - non-null propagation works positionally`` () = + FSharp """module MyLibrary +open NotNullLib + +let notNull : string = "x" +let maybeNull : string | null = "y" + +// Single referenced parameter, passed positionally +let r1 : string = C.Echo(notNull) + +// Referenced parameter is the second one; nullable first, non-null second -> non-null. +// Arguments are positional (no named arguments), so this proves the parameter is identified by name. +let r2 : string = C.DependsOnSecond(maybeNull, notNull) +""" + |> asLibrary + |> withReferences [csNotNullLib] + |> withStrictNullness + |> compile + |> shouldSucceed + +[] +let ``Csharp NotNullIfNotNull - non-null propagation works with named arguments`` () = + FSharp """module MyLibrary +open NotNullLib + +let notNull : string = "x" +let maybeNull : string | null = "y" + +let r : string = C.DependsOnSecond(second = notNull, first = maybeNull) +""" + |> asLibrary + |> withReferences [csNotNullLib] + |> withStrictNullness + |> compile + |> shouldSucceed + +[] +let ``Csharp NotNullIfNotNull - Echo stays nullable for nullable input`` () = + FSharp """module MyLibrary +open NotNullLib + +let maybeNull : string | null = "y" +let r : string = C.Echo(maybeNull) +""" + |> asLibrary + |> withReferences [csNotNullLib] + |> withStrictNullness + |> compile + |> shouldFail + |> withDiagnosticMessageMatches nullableExpected + +[] +let ``Csharp NotNullIfNotNull - depends on second parameter, not the first`` () = + FSharp """module MyLibrary +open NotNullLib + +let notNull : string = "x" +let maybeNull : string | null = "y" + +// Non-null first but nullable referenced (second) parameter -> result stays nullable +let r : string = C.DependsOnSecond(notNull, maybeNull) +""" + |> asLibrary + |> withReferences [csNotNullLib] + |> withStrictNullness + |> compile + |> shouldFail + |> withDiagnosticMessageMatches nullableExpected + +[] +let ``Csharp NotNullIfNotNull - extension this-parameter must be identified, not the explicit argument`` () = + FSharp """module MyLibrary +open NotNullLib + +let notNull : string = "x" +let maybeNull : string | null = "y" + +// Result depends on 'self' (the receiver), which is nullable -> result must stay nullable and warn. +let r : string = maybeNull.PreferSelf(notNull) +""" + |> asLibrary + |> withReferences [csNotNullLib] + |> withStrictNullness + |> compile + |> shouldFail + |> withDiagnosticMessageMatches nullableExpected + +[] +let ``Csharp NotNullIfNotNull - optional parameter referenced positionally`` () = + FSharp """module MyLibrary +open NotNullLib + +let notNull : string = "x" +let maybeNull : string | null = "y" + +// 'b' is the referenced (second, optional) parameter, passed positionally and non-null -> result non-null. +let r : string = Variadic.PickB(maybeNull, notNull) +""" + |> asLibrary + |> withReferences [csNotNullLib] + |> withStrictNullness + |> compile + |> shouldSucceed + +[] +let ``Csharp NotNullIfNotNull - optional parameter referenced by name`` () = + FSharp """module MyLibrary +open NotNullLib + +let notNull : string = "x" + +// Only the referenced optional parameter is supplied, by name and non-null -> result non-null. +let r : string = Variadic.PickB(b = notNull) +""" + |> asLibrary + |> withReferences [csNotNullLib] + |> withStrictNullness + |> compile + |> shouldSucceed + +[] +let ``Csharp NotNullIfNotNull - optional parameter omitted stays nullable`` () = + FSharp """module MyLibrary +open NotNullLib + +let notNull : string = "x" + +// The referenced optional parameter 'b' is omitted (defaults to null) -> result stays nullable. +let r : string = Variadic.PickB(notNull) +""" + |> asLibrary + |> withReferences [csNotNullLib] + |> withStrictNullness + |> compile + |> shouldFail + |> withDiagnosticMessageMatches nullableExpected + +[] +let ``Csharp NotNullIfNotNull - parameter before params array, non-null propagation`` () = + FSharp """module MyLibrary +open NotNullLib + +let notNull : string = "x" +let maybeNull : string | null = "y" + +// Referenced parameter 'first' precedes the params array; non-null first -> result non-null. +let r : string = Variadic.JoinRest(notNull, maybeNull, maybeNull) +""" + |> asLibrary + |> withReferences [csNotNullLib] + |> withStrictNullness + |> compile + |> shouldSucceed + +[] +let ``Csharp NotNullIfNotNull - parameter before params array, stays nullable`` () = + FSharp """module MyLibrary +open NotNullLib + +let notNull : string = "x" +let maybeNull : string | null = "y" + +// Referenced parameter 'first' is nullable -> result stays nullable regardless of params args. +let r : string = Variadic.JoinRest(maybeNull, notNull, notNull) +""" + |> asLibrary + |> withReferences [csNotNullLib] + |> withStrictNullness + |> compile + |> shouldFail + |> withDiagnosticMessageMatches nullableExpected + +// F# <-> runtime interop: a value can be 'null' at runtime even when its F# type is statically non-null. +// 'option' (None) is represented as null via UseNullAsTrueValue, so EchoGeneric of a None must keep the +// result nullable. This case is the one that exercises the TypeNullIsTrueValue branch of the derivation. +[] +let ``Csharp NotNullIfNotNull - generic echo of None stays nullable`` () = + FSharp """module MyLibrary +open NotNullLib + +let none : int option = None +let r : int option = C.EchoGeneric none +""" + |> asLibrary + |> withReferences [csNotNullLib] + |> withStrictNullness + |> compile + |> shouldFail + |> withDiagnosticMessageMatches nullableExpected + +// unit is also represented as null at runtime, so EchoGeneric of '()' must keep the result nullable. +// Like None, this travels the same-tycon nullness subsumption path (unit-with-null vs unit-without-null). +[] +let ``Csharp NotNullIfNotNull - generic echo of unit stays nullable`` () = + FSharp """module MyLibrary +open NotNullLib + +let r : unit = C.EchoGeneric (()) +""" + |> asLibrary + |> withReferences [csNotNullLib] + |> withStrictNullness + |> compile + |> shouldFail + |> withDiagnosticMessageMatches nullableExpected + +// Control: a genuinely non-null reference value yields a non-null result through the generic echo. +[] +let ``Csharp NotNullIfNotNull - generic echo of non-null reference is non-null`` () = + FSharp """module MyLibrary +open NotNullLib + +let notNull : string = "x" +let r : string = C.EchoGeneric notNull +""" + |> asLibrary + |> withReferences [csNotNullLib] + |> withStrictNullness + |> compile + |> shouldSucceed + +// A 'T | null typar argument coming from a generic function keeps the result nullable. +[] +let ``Csharp NotNullIfNotNull - generic echo of nullable typar stays nullable`` () = + FSharp """module MyLibrary +open NotNullLib + +let wrap (x: 'T | null) : 'T = C.EchoGeneric x +""" + |> asLibrary + |> withReferences [csNotNullLib] + |> withStrictNullness + |> compile + |> shouldFail + |> withDiagnosticMessageMatches nullableExpected + +// The object-accepting echo coerces the argument to 'object', but a 'with null' nullness rides along. +[] +let ``Csharp NotNullIfNotNull - object echo of nullable reference stays nullable`` () = + FSharp """module MyLibrary +open NotNullLib + +let maybeNull : string | null = "y" +let r : obj = C.EchoObj maybeNull +""" + |> asLibrary + |> withReferences [csNotNullLib] + |> withStrictNullness + |> compile + |> shouldFail + |> withDiagnosticMessageMatches nullableExpected + +[] +let ``Csharp NotNullIfNotNull - object echo of non-null reference is non-null`` () = + FSharp """module MyLibrary +open NotNullLib + +let notNull : string = "y" +let r : obj = C.EchoObj notNull +""" + |> asLibrary + |> withReferences [csNotNullLib] + |> withStrictNullness + |> compile + |> shouldSucceed + +[] +let ``Csharp NotNullIfNotNull - object echo of None stays nullable`` () = + FSharp """module MyLibrary +open NotNullLib + +let r : obj = C.EchoObj (None : int option) +""" + |> asLibrary + |> withReferences [csNotNullLib] + |> withStrictNullness + |> compile + |> shouldFail + |> withDiagnosticMessageMatches nullableExpected + +[] +let ``Csharp NotNullIfNotNull - byref argument uses the element nullness, not the wrapper`` () = + FSharp """module MyLibrary +open NotNullLib + +let mutable s : string | null = null +let r : string = C.RefEcho(&s) +""" + |> asLibrary + |> withReferences [csNotNullLib] + |> withStrictNullness + |> compile + |> shouldFail + |> withDiagnosticMessageMatches nullableExpected + +[] +let ``Csharp NotNullIfNotNull - unannotated parameter with non-null return annotation fails`` () = + FSharp """module MyLibrary +open NotNullLib + +let f x : string = C.Echo(x) +let _ : string = f null +""" + |> asLibrary + |> withReferences [csNotNullLib] + |> withStrictNullness + |> compile + |> shouldFail + |> withDiagnosticMessageMatches "Nullness warning: The type 'string' does not support 'null'." + +[] +let ``Local F# method with NotNullIfNotNull - non-null propagation`` () = + FSharp """module MyLibrary +open System.Diagnostics.CodeAnalysis + +type C = + [] + static member Echo(x: string | null) : string | null = x + +let notNull : string = "a" +let ok : string = C.Echo(notNull) +""" + |> asLibrary + |> typeCheckWithStrictNullness + |> shouldSucceed + +[] +let ``Local F# method with NotNullIfNotNull - stays nullable for nullable input`` () = + FSharp """module MyLibrary +open System.Diagnostics.CodeAnalysis + +type C = + [] + static member Echo(x: string | null) : string | null = x + +let maybeNull : string | null = "a" +let bad : string = C.Echo(maybeNull) +""" + |> asLibrary + |> typeCheckWithStrictNullness + |> shouldFail + |> withDiagnosticMessageMatches nullableExpected + +[] +let ``Referenced F# method with NotNullIfNotNull - non-null propagation`` () = + let fsharpLib = + FSharp """module NotNullFSharpLib +open System.Diagnostics.CodeAnalysis + +type C = + [] + static member Echo(x: string | null) : string | null = x +""" + |> withCheckNulls + |> withName "NotNullFSharpLib" + + FSharp """module MyLibrary +open NotNullFSharpLib + +let notNull : string = "a" +let ok : string = C.Echo(notNull) +""" + |> asLibrary + |> withReferences [fsharpLib] + |> withStrictNullness + |> compile + |> shouldSucceed + +[] +let ``Referenced F# method with NotNullIfNotNull - stays nullable for nullable input`` () = + let fsharpLib = + FSharp """module NotNullFSharpLib +open System.Diagnostics.CodeAnalysis + +type C = + [] + static member Echo(x: string | null) : string | null = x +""" + |> withCheckNulls + |> withName "NotNullFSharpLib" + + FSharp """module MyLibrary +open NotNullFSharpLib + +let maybeNull : string | null = "a" +let bad : string = C.Echo(maybeNull) +""" + |> asLibrary + |> withReferences [fsharpLib] + |> withStrictNullness + |> compile + |> shouldFail + |> withDiagnosticMessageMatches nullableExpected + +[] +let ``BCL Path.GetExtension - null literal input yields nullable result`` () = + FSharp """module MyLibrary +open System.IO + +let ext : string = Path.GetExtension(null) +""" + |> asLibrary + |> typeCheckWithStrictNullness + |> shouldFail + |> withDiagnosticMessageMatches nullableExpected + +[] +let ``BCL Path.GetExtension - null-bound variable input yields nullable result`` () = + FSharp """module MyLibrary +open System.IO + +let maybeNull = null +let ext : string = Path.GetExtension(maybeNull) +""" + |> asLibrary + |> typeCheckWithStrictNullness + |> shouldFail + |> withDiagnosticMessageMatches nullableExpected + +[] +let ``BCL Path.GetExtension - explicit non-null parameter annotation yields non-null result`` () = + FSharp """module MyLibrary +open System.IO + +let f (x: string) : string = Path.GetExtension x +""" + |> asLibrary + |> typeCheckWithStrictNullness + |> shouldSucceed \ No newline at end of file diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.bsl b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.bsl index 0c81c8df894..cd6be26fa07 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.bsl +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.bsl @@ -1842,6 +1842,7 @@ FSharp.Compiler.AbstractIL.IL+WellKnownILAttributes: WellKnownILAttributes IsUnm FSharp.Compiler.AbstractIL.IL+WellKnownILAttributes: WellKnownILAttributes NoEagerConstraintApplicationAttribute FSharp.Compiler.AbstractIL.IL+WellKnownILAttributes: WellKnownILAttributes None FSharp.Compiler.AbstractIL.IL+WellKnownILAttributes: WellKnownILAttributes NotComputed +FSharp.Compiler.AbstractIL.IL+WellKnownILAttributes: WellKnownILAttributes NotNullIfNotNullAttribute FSharp.Compiler.AbstractIL.IL+WellKnownILAttributes: WellKnownILAttributes NullableAttribute FSharp.Compiler.AbstractIL.IL+WellKnownILAttributes: WellKnownILAttributes NullableContextAttribute FSharp.Compiler.AbstractIL.IL+WellKnownILAttributes: WellKnownILAttributes ObsoleteAttribute From 5dfbf7f1f9adc57ebe99d0ea11e61f3856127393 Mon Sep 17 00:00:00 2001 From: Adam Boniecki <20281641+abonie@users.noreply.github.com> Date: Wed, 29 Jul 2026 18:19:58 +0200 Subject: [PATCH 21/33] Move SDL/TSA validation to 1ES templates after Arcade 11 upgrade (#20096) Arcade 11 removed the SDL post-build scripts and the SDLValidationParameters parameter, breaking the official build. Move PoliCheck exclusions into the 1ES sdl: block and drop the obsolete post-build parameter and its variable group. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 7df99ba6-98b9-4cab-898b-422577b9e6dc --- azure-pipelines-PR.yml | 2 -- azure-pipelines.yml | 21 +++------------------ 2 files changed, 3 insertions(+), 20 deletions(-) diff --git a/azure-pipelines-PR.yml b/azure-pipelines-PR.yml index 8647164d91a..1f18517bccb 100644 --- a/azure-pipelines-PR.yml +++ b/azure-pipelines-PR.yml @@ -65,8 +65,6 @@ variables: value: Products/$(System.TeamProject)/$(Build.Repository.Name)/$(Build.SourceBranchName)/$(Build.BuildNumber) - name: Codeql.Enabled value: true - - ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - group: DotNet-FSharp-SDLValidation-Params - ${{ if and(eq(variables['System.TeamProject'], 'public'), eq(variables['Build.Reason'], 'PullRequest')) }}: - name: RunningAsPullRequest value: true diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 9b730e2f3f0..1517ff30b68 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -48,7 +48,6 @@ variables: value: Products/$(System.TeamProject)/$(Build.Repository.Name)/$(Build.SourceBranchName)/$(Build.BuildNumber) - name: Codeql.Enabled value: "true" - - group: DotNet-FSharp-SDLValidation-Params - template: /eng/common/templates-official/variables/pool-providers.yml@self resources: @@ -68,6 +67,7 @@ extends: enabled: true policheck: enabled: true + exclusionsFile: '$(Build.SourcesDirectory)/eng/policheck_exclusions.xml' sbom: enabled: false # VS SBOM is generated with other steps justificationForDisabling: 'SBOM for F# is generated via build process. Will be migrated at later date.' @@ -219,23 +219,8 @@ extends: enableSymbolValidation: false # SourceLink improperly looks for generated files. See https://github.com/dotnet/arcade/issues/3069 enableSourceLinkValidation: false - # Enable SDL validation, passing through values from the 'DotNet-FSharp-SDLValidation-Params' group. - SDLValidationParameters: - enable: true - params: >- - -SourceToolsList @("policheck","credscan") - -ArtifactToolsList @("binskim") - -BinskimAdditionalRunConfigParams @("IgnorePdbLoadError < True","Recurse < True") - -TsaInstanceURL $(_TsaInstanceURL) - -TsaProjectName $(_TsaProjectName) - -TsaNotificationEmail $(_TsaNotificationEmail) - -TsaCodebaseAdmin $(_TsaCodebaseAdmin) - -TsaBugAreaPath $(_TsaBugAreaPath) - -TsaIterationPath $(_TsaIterationPath) - -TsaRepositoryName "FSharp" - -TsaCodebaseName "FSharp-GitHub" - -TsaPublish $True - -PoliCheckAdditionalRunConfigParams @("UserExclusionPath < $(Build.SourcesDirectory)/eng/policheck_exclusions.xml") + # SDL validation (PoliCheck, CredScan, BinSkim) and TSA reporting are handled by the 1ES Pipeline + # Templates via the 'sdl:' block in the 'extends' section above; TSA config lives in eng/TSAConfig.gdntsa. #---------------------------------------------------------------------------------------------------------------------# # VS Insertion # From 17cb50388d0078e83378d3fed646db915582497d Mon Sep 17 00:00:00 2001 From: Charles Roddie Date: Thu, 30 Jul 2026 13:24:34 +0100 Subject: [PATCH 22/33] Compiled ToStrings under -reflectionfree for DUs and Records (#19976) * Add a compiler intrinsic for the 'string' operator Adds string_operator_info / mkCallStringOperator so generated code can call Operators.string. These lines are duplicated by the interpolated-string PR (dotnet/fsharp#19971); kept identical there so a future merge resolves cleanly. Co-Authored-By: Claude Opus 4.8 (1M context) * Generate a match-based ToString for unions under --reflectionfree Under --reflectionfree the union ToString previously emitted nothing, so DUs fell back to Object.ToString() (the namespace-qualified type name). Instead generate a match over the cases that builds "CaseName(f0, f1, ...)" using the 'string' operator on each field, via a TypedTree expression fed to CodeGenMethodForExpr. This recurses naturally into nested unions and is reflection-free. The default (sprintf "%+A") path is unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) * Extract mkStringConcat helper for arity-dispatched String.Concat The "concatenate a list of string exprs, picking the cheapest String.Concat overload by arity" pattern was duplicated in CheckExpressions (interpolation lowering) and the optimizer, and our new union ToString used the array overload unconditionally. Extract mkStringConcat into TypedTreeOps.ExprOps and route all three through it. This also lets single-field union cases emit Concat3 instead of allocating a string[] (IlxGen runs after the optimizer, so nothing else would collapse that array form). Co-Authored-By: Claude Opus 4.8 (1M context) * Fix generated union ToString for generic unions The match-based ToString body is a TypedTree expression codegen'd via CodeGenMethodForExpr, but it was built with `eenv`, which lacks the tycon's type parameters. For generic unions this produced wrong IL: the wrong case branch (always the null-as-true-value case) or a NullReferenceException for single-case unions. Use `eenvinner` (the per-tycon environment) so the generic method body resolves its type parameters. The old sprintf path was unaffected because it emits raw IL off the pre-built ilThisTy. Co-Authored-By: Claude Opus 4.8 (1M context) * Render union ToString fields like option (null -> "null") To make a generated union ToString consistent with how option/list format their contents (LanguagePrimitives.anyToStringShowingNull), format each field as: if (box field) is non-null then 'string field' else "null". Previously a null field rendered as "" (the 'string' operator's null behaviour). Generated inline rather than calling anyToStringShowingNull, which is internal to FSharp.Core and so not callable from user-compiled code. Co-Authored-By: Claude Opus 4.8 (1M context) * Tidy reflection-free union ToString tests Normalize union declarations to a leading '|', use System.Console.WriteLine instead of printfn (the printf machinery is what these changes move away from), and make the null-field test compare the union's rendering directly against option's rather than asserting a fixed string. Co-Authored-By: Claude Opus 4.8 (1M context) * Add reflection-free ToString to Result and Choice Result and Choice had no ToString override, so they fell back to the compiler-generated sprintf "%+A" one, which uses reflection. Give them hand-written overrides mirroring option/list (String.Concat + anyToStringShowingNull), e.g. Ok 5 -> "Ok(5)", Choice1Of2 7 -> "Choice1Of2(7)". This is reflection-free / AOT-friendly and consistent with option's "Some(x)" rendering. Note: this changes the observable ToString of Result/Choice from the "%A"-style "Ok 5" to "Ok(5)". Co-Authored-By: Claude Opus 4.8 (1M context) * Generate a single-line ToString for records under --reflectionfree Records previously fell back to Object.ToString() (the namespace-qualified type name) under --reflectionfree. Generate "{ F1 = v1; F2 = v2 }" on a single line (no line breaks, unlike sprintf "%+A"), with fields formatted like union fields (null -> "null", otherwise via 'string'). Factor the shared field formatter and ToString-method emission out of the union path. The default (sprintf "%+A") path is unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) * Update FSharp.Core surface-area baselines for Result/Choice ToString Result and Choice`2..7 now declare an explicit ToString() override, so they appear in the public surface area. Co-Authored-By: Claude Opus 4.8 (1M context) * Add release notes Co-Authored-By: Claude Opus 4.8 (1M context) * Generate a single-line ToString for anonymous records under --reflectionfree Drive anonymous-record ToString through the synthetic record tycon (already built for equality/comparison) rather than sprintf "%A", so under --reflectionfree it renders "{| Name = value; ... |}" on a single line. GenRecordToStringMethod now takes open/close brace strings ("{ "/" }" for records, "{| "/" |}" for anonymous records). The default (non-reflection-free) codegen path is unchanged and still falls back to sprintf "%+A". Co-Authored-By: Claude Opus 4.8 (1M context) * Test that a hand-written ToString override is kept under --reflectionfree Addresses review feedback: generation is gated on `not (HasMember "ToString")`, so a user-defined ToString on a union or record wins over the generated one. Co-Authored-By: Claude Opus 4.8 (1M context) * Rename ToString generators for clarity Addresses review feedback: distinguish the reflective sprintf path from the structural one. GenPrintingMethod -> GenSprintfPrintingMethod (the sprintf "%+A" ToString/get_Message), GenToStringMethodFromExpr -> EmitToStringMethodDef. Co-Authored-By: Claude Opus 4.8 (1M context) * Restore tabular layout for string_operator_info in TcGlobals Addresses review feedback: keep the column-aligned layout of the surrounding intrinsic table. Also makes these two lines byte-identical to the same intrinsic added by #19971, so a future merge resolves cleanly. Co-Authored-By: Claude Opus 4.8 (1M context) * Add reflection-free ToString tests for field shapes, structs, anon records and recursion Covers DU field shapes (multiple fields vs a single tuple field), explicit vs unnamed field names rendering identically, struct unions/records, anonymous and struct anonymous records, and finite recursive/nesting types. Co-Authored-By: Claude Opus 4.8 * Add EmittedIL tests for reflection-free record and union ToString Locks in the IL emitted under --reflectionfree: each field is boxed and rendered through Operators.ToString with a null guard, and the parts are joined with String.Concat (array form for the record, 3-arg form for the single-field union case). Nullary union cases return the bare case name. Co-Authored-By: Claude Opus 4.8 * Generate reflection-free ToString in the augmentation phase The structural ToString for --reflectionfree records and unions was built in IlxGen, after the optimizer, so its per-field 'string' operator calls were never inlined: each value-type field was boxed and rendered through the generic Operators.ToString, behind a null guard that is dead for a value type. Move the generation into the type-augmentation phase (alongside Equals/GetHashCode/CompareTo) so the body flows through the optimizer. The 'string' operator is now specialised - a value-type field renders via a direct, allocation-free invariant-culture ToString with no boxing and no null guard (reference fields keep the guard so null still renders as "null"). The shared body builders live in AugmentTypeDefinitions; anonymous record types are synthesized too late for augmentation, so they keep generating in IlxGen but reuse the same builder. Output is unchanged; the EmittedIL baselines are updated to the leaner IL. Co-Authored-By: Claude Opus 4.8 * Guard generated reflection-free ToString against deep-recursion overflow The augmentation-generated structural ToString recurses into fields, so a deeply nested value can exhaust the stack with an uncatchable StackOverflowException. Emit RuntimeHelpers.EnsureSufficientExecutionStack() at method entry (as C# records do in PrintMembers) so it throws a catchable InsufficientExecutionStackException instead, when the runtime provides the method. The guard is skipped for types whose every field is a flat primitive (integer/float/decimal/string/char/bool/unit/enum), which cannot recurse. Co-Authored-By: Claude Opus 4.8 * Test the reflection-free ToString deep-recursion guard A 1,000,000-deep value's generated ToString throws a catchable InsufficientExecutionStackException rather than hard-crashing the process. Co-Authored-By: Claude Opus 4.8 * revert ToString additions to fsharp.core types * Remove stale FSharp.Core release note for the reverted Result/Choice ToString Co-Authored-By: Claude Opus 4.8 * Fix code formatting in IlxGen.fs (dotnet fantomas) Co-Authored-By: Claude Opus 4.8 * don't use quoted name * int version of reflectionfree-printing doc * doc tweaks * Link release note to the printing doc and cover anonymous records Co-Authored-By: Claude Opus 4.8 * test backticks * Share the ToString recursion guard with anonymous records The guard lived in MakeBindingsForToStringAugmentation, which anonymous records bypass: they are synthesized too late for type augmentation and reach mkRecdToString from IlxGen instead. Deep nesting overflowed the stack rather than raising InsufficientExecutionStackException. Move it into mkToStringRecursionGuard, applied inside mkRecdToString and mkUnionToString, so every caller of the body builders gets it. Co-Authored-By: Claude Opus 4.8 * Add EmittedIL baselines for struct and anonymous record ToString Struct records and unions read fields off the this pointer and switch on the tag, and the anonymous record path is generated separately in IlxGen, so each gets its own baseline. The anonymous baseline omits the field reads: they name the anonymous type, whose mangled name is not stable across compilations. Co-Authored-By: Claude Opus 4.8 * Fix empty anonymous record ToString rendering a doubled space The open/close braces carry inner spaces ("{| " and " |}"); with no fields they abut and render "{| |}". Trim the leading space when the field list is empty, matching %A's "{| |}". Co-Authored-By: Claude Opus 4.8 * tidy comment --------- Co-authored-by: Claude Opus 4.8 (1M context) --- docs/reflectionfree-printing.md | 73 +++++ .../.FSharp.Compiler.Service/11.0.100.md | 1 + .../Checking/AugmentWithHashCompare.fs | 148 +++++++++ .../Checking/AugmentWithHashCompare.fsi | 12 + src/Compiler/Checking/CheckDeclarations.fs | 17 +- src/Compiler/CodeGen/IlxGen.fs | 82 ++++- src/Compiler/Optimize/Optimizer.fs | 14 +- src/Compiler/TypedTree/TcGlobals.fs | 2 + src/Compiler/TypedTree/TcGlobals.fsi | 2 + .../TypedTree/TypedTreeOps.ExprOps.fs | 14 + .../TypedTree/TypedTreeOps.ExprOps.fsi | 7 + .../CompilerOptions/fsc/reflectionfree.fs | 287 +++++++++++++++++- .../EmittedIL/ReflectionFreeToString.fs | 284 +++++++++++++++++ .../FSharp.Compiler.ComponentTests.fsproj | 1 + 14 files changed, 912 insertions(+), 32 deletions(-) create mode 100644 docs/reflectionfree-printing.md create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/ReflectionFreeToString.fs diff --git a/docs/reflectionfree-printing.md b/docs/reflectionfree-printing.md new file mode 100644 index 00000000000..68e3091faf6 --- /dev/null +++ b/docs/reflectionfree-printing.md @@ -0,0 +1,73 @@ +# Simple vs Reflection-based DU and Record printing + +This document describes two modes for printing Discriminated Unions (DUs) and Records in F#: a **simple** reflection-free mode that delegates to a `string`-like operator for printing field values, and a `sprintf` mode (`sprintf "%A"`), which uses **reflection** to create output looking like F# code. In this document, the terms *simple* and *reflection* are used to distinguish the two modes. + +Without the `--reflectionfree` flag, the compiler generates a `ToString` for DUs and Records that calls `sprintf "%A"`. With the flag, the compiler generates a `ToString` that uses the simple mode. + +Users can choose between the two modes by 1. use of `--reflectionfree`, and by 2. calling with a `sprintf`-type caller or a `string`-type caller (e.g. the `string` operator, `ToString`, or interpolated strings). + +If `x` is a DU or Record, then output will be simple or reflection-based as follows: +| | `--reflectionfree` | no `--reflectionfree` | +|---|---|---| +| `string x` | simple | reflection | +| `x.ToString()` | simple | reflection | +| `$"{x}"` | simple | reflection | +| `sprintf "%A" x` | disallowed (would be reflection) | reflection | + +As such, the current default reflection `ToString` generation forces reflection formatting on all callers. On the other hand, generating simple `ToString` output means that the records and DUs are printed with simple or reflection formatting depending on whether the caller is of simple or reflection affinity. The `--reflectionfree` flag combines this property with a ban on `sprintf` to prevent the reflection mode from being used. + +In addition to user-defined types, the FSharp.Core `option` type uses simple printing, while other types either have no `ToString` or use some other format. + +## Behaviour: definitions + +In simple printing, field values are printed with `string`-type formatting, more precisely `anyToStringShowingNull`. No line breaks are inserted. + +- **Record**: `{ Name1 = value1; Name2 = value2 }`. +- **Anonymous record**: the same, but with `{| ` and ` |}`. +- **Union**: A case with no fields renders as just its name. A case with fields renders as `CaseName(value1, value2)`. + +`[]` records and unions, and struct anonymous records, render identically to their reference-type forms. + +A type that supplies its own `ToString` override keeps it, with no `ToString` generated for it (either simple or reflection). + +Reflection-mode printing is described in [plain text formatting](https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/plaintext-formatting). + +## Behavioural differences + +### Differences in field rendering + +The following differences between `string` and `sprintf "%A"` carry over directly into differences in field rendering between simple and reflection printing: + +| F# value | simple (`anyToStringShowingNull`) | reflection (`sprintf "%A"`) | +|---|---|---| +| string field `"hi"` | `hi` | `"hi"` | +| char field `'a'` | `a` | `'a'` | +| float `5.0` | `5` | `5.0` | +| `250uy` / `42n` / `1.5M` | `250` / `42` / `1.5` | `250uy` / `42n` / `1.5M` | +| option field `None` | `null` | `None` | +| array field `[\|1;2;3\|]` | `System.Int32[]` | `[\|1; 2; 3\|]` | +| unit field `()` | `null` | `()` | + +The overall differences here are: +- Simple printing converts to strings, while reflection printing is more bi-directional, often generating compilable F# code. +- F# types that have null representation (`unit`, `option`, and in general types with `AllowNullLiteral` or `UseNullAsTrueValue`) are printed as `null` in simple printing, while reflection printing uses a more F#-like representation. + +### Other differences + +These differences are in the printing of the record or DU itself rather than of its fields: + +| F# value | simple (`string`) | reflection (`sprintf "%A"`) | +|---|---|---| +| `B 5` (single field) | `B(5)` | `B 5` | +| `C (3, 4)` (two fields) | `C(3, 4)` | `C (3, 4)` | +| record `{ X = 1; Y = 2 }` | `{ X = 1; Y = 2 }` | `{ X = 1`⏎` Y = 2 }` | +| `[")>]` | `{ X = 5 }` | `Custom<5>` | + +The overall differences here are: +- Simple printing always brackets a case's fields and never pads, while reflection printing omits brackets for a single non-tuple field and inserts a space before them otherwise. +- Simple printing uses a single line (unless a field's own rendering contains breaks), while reflection printing breaks records and nested values across lines with indentation. +- `StructuredFormatDisplay` is ignored in simple printing and honoured in reflection printing. + +## Recursion and depth + +Rendering recurses into nested records and unions. Deep nesting is guarded by `RuntimeHelpers.EnsureSufficientExecutionStack`, raising a catchable `InsufficientExecutionStackException` rather than `StackOverflowException`; cycles (which require mutation to construct) still overflow, as `option` and `list` do. \ No newline at end of file diff --git a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md index 632fcac6b93..476df124084 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md +++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md @@ -142,6 +142,7 @@ * Debug: rework for expressions stepping ([PR #19894](https://github.com/dotnet/fsharp/pull/19894)) * Debug: rework conditional erasure, fix stepping over literals ([PR #19897](https://github.com/dotnet/fsharp/pull/19897)) * Debug: fix if and match condition sequence points ([PR #19932](https://github.com/dotnet/fsharp/pull/19932)) +* Under `--reflectionfree`, discriminated unions, records and anonymous records now get a [generated `ToString`](../../reflectionfree-printing.md) (rendering each field like `Option` does) instead of falling back to the namespace-qualified type name. ([PR #19976](https://github.com/dotnet/fsharp/pull/19976)) * Support common types of `NotNullIfNotNullAttribute` usage. If a method parameter is marked with `NotNullIfNotNullAttribute`, the compiler will now honor this attribute and mark the return type as non-null. ([PR #19977](https://github.com/dotnet/fsharp/pull/19977)) * Checker: recover on checking language version ([PR ##19970](https://github.com/dotnet/fsharp/pull/19970)) * Implied argument names for function-to-delegate coercions now fall back to the delegate's `Invoke` parameter names when the function has no recoverable names (e.g. a partial application like `System.Func((+) 1)`), instead of synthetic `delegateArg0`, `delegateArg1`, … names. ([PR #20001](https://github.com/dotnet/fsharp/pull/20001)) diff --git a/src/Compiler/Checking/AugmentWithHashCompare.fs b/src/Compiler/Checking/AugmentWithHashCompare.fs index c5ae2d1459f..0ae09df3996 100644 --- a/src/Compiler/Checking/AugmentWithHashCompare.fs +++ b/src/Compiler/Checking/AugmentWithHashCompare.fs @@ -81,6 +81,9 @@ let mkGetHashCodeSlotSig (g: TcGlobals) = let mkEqualsSlotSig (g: TcGlobals) = TSlotSig("Equals", g.obj_ty_noNulls, [], [], [ [ TSlotParam(Some("obj"), g.obj_ty_withNulls, false, false, false, []) ] ], Some g.bool_ty) +let mkToStringSlotSig (g: TcGlobals) = + TSlotSig("ToString", g.obj_ty_noNulls, [], [], [ [] ], Some g.string_ty) + //------------------------------------------------------------------------- // Helpers associated with code-generation of comparison/hash augmentations //------------------------------------------------------------------------- @@ -112,6 +115,9 @@ let mkEqualsWithComparerTyExact g ty = let mkHashTy g ty = mkFunTy g (mkThisTy g ty) (mkFunTy g g.unit_ty g.int_ty) +let mkToStringTy (g: TcGlobals, ty: TType) = + mkFunTy g (mkThisTy g ty) (mkFunTy g g.unit_ty g.string_ty) + let mkHashWithComparerTy g ty = mkFunTy g (mkThisTy g ty) (mkFunTy g g.IEqualityComparer_ty g.int_ty) @@ -1697,3 +1703,145 @@ let MakeBindingsForUnionAugmentation g (tycon: Tycon) (vals: ValRef list) = let isdata = mkUnionCaseTest g (thise, ucr, tinst, m) let expr = mkLambdas g m tps [ thisv; unitv ] (isdata, g.bool_ty) mkCompGenBind v.Deref expr) + +//------------------------------------------------------------------------- +// Build reflection-free ToString functions for union and record types. +// +// Under --reflectionfree the reflective 'sprintf "%+A"' ToString is unavailable, so we build a structural +// one here (during type augmentation, so the 'string' operator calls flow through the optimizer and get +// specialised - e.g. an int field renders via a direct, allocation-free ToString rather than a boxed call). +//------------------------------------------------------------------------- + +// Guard deep recursion with a catchable exception, as C# records' PrintMembers do, when the runtime provides +// it. A type whose fields are all primitive cannot nest, so it skips the guard. +let mkToStringRecursionGuard (g: TcGlobals, m: Text.range, fieldTys: TType list, body: Expr) = + let isPrimitive (ty: TType) = + isIntegerTy g ty + || isFpTy g ty + || isDecimalTy g ty + || isStringTy g ty + || typeEquiv g g.char_ty ty + || isBoolTy g ty + || isUnitTy g ty + || isEnumTy g ty + + if fieldTys |> List.forall isPrimitive then + body + else + match g.TryFindSysILTypeRef "System.Runtime.CompilerServices.RuntimeHelpers" with + | Some tref -> + let mspec = + mkILNonGenericStaticMethSpecInTy (mkILNonGenericBoxedTy tref, "EnsureSufficientExecutionStack", [], ILType.Void) + + mkSequential m (mkAsmExpr ([ mkNormalCall mspec ], [], [], [], m)) body + | None -> body + +// Render one field value as a string the way option/list do (LanguagePrimitives.anyToStringShowingNull): +// a null reference renders as "null", everything else via the 'string' operator. A value-type field can +// never be null, so it skips the box+null-guard and renders directly. +let mkFieldToString (g: TcGlobals, m: Text.range, fe: Expr) = + let fieldTy = tyOfExpr g fe + + if isStructTy g fieldTy then + mkCallStringOperator g m fieldTy fe + else + let v, ve = mkCompGenLocal m "field" fieldTy + mkCompGenLet m v fe (mkNonNullCond g m g.string_ty (mkCallBox g m fieldTy ve) (mkCallStringOperator g m fieldTy ve) (mkString g m "null")) + +// A record's ToString as a single line "{ F1 = v1; F2 = v2 }" (no line breaks, unlike "%+A"). +// openBrace/closeBrace are "{ "/" }" for records and "{| "/" |}" for anonymous records. +let mkRecdToString (g: TcGlobals, tcref: TyconRef, tycon: Tycon, openBrace: string, closeBrace: string) = + let m = tycon.Range + let tinst, ty = mkMinimalTy g tcref + let thisv, thise = mkThisVar g m ty + + let fieldParts = + tcref.AllInstanceFieldsAsList + |> List.mapi (fun i fspec -> + let fref = tcref.MakeNestedRecdFieldRef fspec + let value = mkFieldToString (g, m, mkRecdFieldGetViaExprAddr (thise, fref, tinst, m)) + let nameEq = mkString g m (fspec.DisplayNameCore + " = ") + if i = 0 then [ nameEq; value ] else [ mkString g m "; "; nameEq; value ]) + |> List.concat + + let close = + if List.isEmpty fieldParts then + // Avoid a double space in an empty record. + closeBrace.TrimStart() + else closeBrace + let parts = mkString g m openBrace :: fieldParts @ [ mkString g m close ] + let fieldTys = tcref.AllInstanceFieldsAsList |> List.map (fun fspec -> fspec.FormalType) + thisv, mkToStringRecursionGuard (g, m, fieldTys, mkStringConcat (g, m, parts)) + +// A union's ToString as a match over the cases building "CaseName(f0, f1, ...)" (or just "CaseName" for a +// nullary case). +let mkUnionToString (g: TcGlobals, tcref: TyconRef, tycon: Tycon) = + let m = tycon.Range + let tinst, ty = mkMinimalTy g tcref + let thisv, thise = mkThisVar g m ty + let mbuilder = MatchBuilder(DebugPointAtBinding.NoneAtInvisible, m) + + let mkResult (ucase: UnionCase) = + let cref = tcref.MakeNestedUnionCaseRef ucase + let rfields = ucase.RecdFields + + if isNil rfields then + mkString g m ucase.DisplayNameCore + else + // provene is an expression proven to be of this case (the value itself for struct unions, + // otherwise a 'UnionCaseProof'), from which fields can be read. + let mkBody (provene: Expr) = + let fieldStrs = + rfields + |> List.mapi (fun j _ -> mkFieldToString (g, m, mkUnionCaseFieldGetProvenViaExprAddr (provene, cref, tinst, j, m))) + + let sep = mkString g m ", " + + let fieldsWithSeps = + fieldStrs |> List.mapi (fun i fe -> if i = 0 then [ fe ] else [ sep; fe ]) |> List.concat + + let parts = mkString g m (ucase.DisplayNameCore + "(") :: fieldsWithSeps @ [ mkString g m ")" ] + mkStringConcat (g, m, parts) + + if cref.Tycon.IsStructOrEnumTycon then + mkBody thise + else + let ucv, ucve = mkCompGenLocal m "thisCast" (mkProvenUnionCaseTy cref tinst) + mkCompGenLet m ucv (mkUnionCaseProof (thise, cref, tinst, m)) (mkBody ucve) + + let cases = + tcref.UnionCasesAsList + |> List.map (fun ucase -> + let cref = tcref.MakeNestedUnionCaseRef ucase + mkCase (DecisionTreeTest.UnionCase(cref, tinst), mbuilder.AddResultTarget(mkResult ucase))) + + let dtree = TDSwitch(thise, cases, None, m) + + let fieldTys = + tcref.UnionCasesAsList |> List.collect (fun uc -> uc.RecdFields) |> List.map (fun rf -> rf.FormalType) + + thisv, mkToStringRecursionGuard (g, m, fieldTys, mbuilder.Close(dtree, m, g.string_ty)) + +let TyconIsCandidateForAugmentationWithToString (g: TcGlobals, tycon: Tycon) = + g.useReflectionFreeCodeGen && (tycon.IsUnionTycon || tycon.IsRecordTycon) + +let MakeValsForToStringAugmentation (g: TcGlobals, tcref: TyconRef) = + let _, ty = mkMinimalTy g tcref + let vis = tcref.Accessibility + let tps = tcref.Typars + mkValSpec g tcref ty vis (Some(mkToStringSlotSig g)) "ToString" (tps +-> (mkToStringTy (g, ty))) unitArg false + +let MakeBindingsForToStringAugmentation (g: TcGlobals, tycon: Tycon, toStringVal: Val) = + let tcref = mkLocalTyconRef tycon + let m = tycon.Range + let tps = tycon.Typars + + let thisv, body = + if tycon.IsUnionTycon then + mkUnionToString (g, tcref, tycon) + else + mkRecdToString (g, tcref, tycon, "{ ", " }") + + let unitv, _ = mkCompGenLocal m "unitArg" g.unit_ty + let expr = mkLambdas g m tps [ thisv; unitv ] (body, g.string_ty) + [ mkCompGenBind toStringVal expr ] diff --git a/src/Compiler/Checking/AugmentWithHashCompare.fsi b/src/Compiler/Checking/AugmentWithHashCompare.fsi index b57e25f32cc..424026f1330 100644 --- a/src/Compiler/Checking/AugmentWithHashCompare.fsi +++ b/src/Compiler/Checking/AugmentWithHashCompare.fsi @@ -51,3 +51,15 @@ val TypeDefinitelyHasEquality: TcGlobals -> TType -> bool val MakeValsForUnionAugmentation: TcGlobals -> TyconRef -> Val list val MakeBindingsForUnionAugmentation: TcGlobals -> Tycon -> ValRef list -> Binding list + +/// Build a record's single-line reflection-free ToString body, recursion guard included; returns the 'this' value and the body expression. +val mkRecdToString: g: TcGlobals * tcref: TyconRef * tycon: Tycon * openBrace: string * closeBrace: string -> Val * Expr + +/// Whether a reflection-free structural ToString should be generated for this type. +val TyconIsCandidateForAugmentationWithToString: g: TcGlobals * tycon: Tycon -> bool + +/// Make the ToString override slot for a reflection-free record or union. +val MakeValsForToStringAugmentation: g: TcGlobals * tcref: TyconRef -> Val + +/// Build the body binding for a reflection-free record or union ToString override. +val MakeBindingsForToStringAugmentation: g: TcGlobals * tycon: Tycon * toStringVal: Val -> Binding list diff --git a/src/Compiler/Checking/CheckDeclarations.fs b/src/Compiler/Checking/CheckDeclarations.fs index dfa348ab19f..6df195958f8 100644 --- a/src/Compiler/Checking/CheckDeclarations.fs +++ b/src/Compiler/Checking/CheckDeclarations.fs @@ -944,6 +944,18 @@ module AddAugmentationDeclarations = else [] else [] + // Under --reflectionfree the structural ToString is generated here (rather than in IlxGen) so the 'string' + // operator calls in its body flow through the optimizer and get specialised. Like the Equals override, this + // runs late so tycon.HasMember gives correct results for a user-written ToString. + let AddReflectionFreeToStringBindings (cenv: cenv, env: TcEnv, tycon: Tycon) = + let g = cenv.g + if AugmentTypeDefinitions.TyconIsCandidateForAugmentationWithToString(g, tycon) && not (tycon.HasMember g "ToString" []) then + let tcref = mkLocalTyconRef tycon + let toStringVal = AugmentTypeDefinitions.MakeValsForToStringAugmentation(g, tcref) + PublishValueDefn cenv env ModuleOrMemberBinding toStringVal + AugmentTypeDefinitions.MakeBindingsForToStringAugmentation(g, tycon, toStringVal) + else [] + let ShouldAugmentUnion (g: TcGlobals) (tycon: Tycon) = g.langVersion.SupportsFeature LanguageFeature.UnionIsPropertiesVisible && HasDefaultAugmentationAttribute g (mkLocalTyconRef tycon) && @@ -4816,8 +4828,9 @@ module TcDeclarations = // We put the hash/compare bindings before the type definitions and the // equality bindings after because tha is the order they've always been generated // in, and there are code generation tests to check that. - let binds = AddAugmentationDeclarations.AddGenericHashAndComparisonBindings cenv tycon + let binds = AddAugmentationDeclarations.AddGenericHashAndComparisonBindings cenv tycon let binds3 = AddAugmentationDeclarations.AddGenericEqualityBindings cenv envForDecls tycon + let binds5 = AddAugmentationDeclarations.AddReflectionFreeToStringBindings(cenv, envForDecls, tycon) let binds4 = if tycon.IsUnionTycon && AddAugmentationDeclarations.ShouldAugmentUnion g tycon then let unionVals = @@ -4827,7 +4840,7 @@ module TcDeclarations = AugmentTypeDefinitions.MakeBindingsForUnionAugmentation g tycon (List.map mkLocalValRef unionVals) else [] - binds@binds4, binds3) + binds@binds4, binds3@binds5) // Check for cyclic structs and inheritance all over again, since we may have added some fields to the struct when generating the implicit construction syntax EstablishTypeDefinitionCores.TcTyconDefnCore_CheckForCyclicStructsAndInheritance cenv tycons diff --git a/src/Compiler/CodeGen/IlxGen.fs b/src/Compiler/CodeGen/IlxGen.fs index c170a757715..a6aa05c4035 100644 --- a/src/Compiler/CodeGen/IlxGen.fs +++ b/src/Compiler/CodeGen/IlxGen.fs @@ -2264,7 +2264,6 @@ type AnonTypeGenerationTable() = mkLdfldMethodDef ("get_" + propName, ILMemberAccess.Public, false, ilTy, fldName, fldTy, ILAttributes.Empty, attrs) |> g.AddMethodGeneratedAttributes - yield! genToStringMethod ilTy ] let ilBaseTy = (if isStruct then g.iltyp_ValueType else g.ilg.typ_Object) @@ -2367,6 +2366,10 @@ type AnonTypeGenerationTable() = Some(mkLocalValRef augmentation.EqualsExactWithComparer) ) + // Generate ToString through the synthetic record tycon (renders "{| Name = value; ... |}" under + // --reflectionfree, otherwise sprintf "%+A"). Done here, not in ilMethods above, because it needs the tycon. + let ilToStringMethodDefs = genToStringMethod (ilTy, tycon) + // Build the ILTypeDef. We don't rely on the normal record generation process because we want very specific field names let ilTypeDefAttribs = @@ -2389,7 +2392,7 @@ type AnonTypeGenerationTable() = ilGenericParams, ilBaseTy, ilInterfaceTys, - mkILMethods (ilCtorDef :: ilMethods), + mkILMethods (ilCtorDef :: ilMethods @ ilToStringMethodDefs), ilFieldDefs, emptyILTypeDefs, ilProperties, @@ -3870,7 +3873,11 @@ and GenAllocRecd cenv cgbuf eenv ctorInfo (tcref, argTys, args, m) sequel = and GenAllocAnonRecd cenv cgbuf eenv (anonInfo: AnonRecdTypeInfo, tyargs, args, m) sequel = let anonCtor, _anonMethods, anonType = - cgbuf.mgbuf.LookupAnonType((fun ilThisTy -> GenToStringMethod cenv eenv ilThisTy m), anonInfo) + cgbuf.mgbuf.LookupAnonType( + (fun (ilThisTy, tycon) -> + GenRecordToStringMethod(cenv, cgbuf.mgbuf, EnvForTycon tycon eenv, ilThisTy, mkLocalTyconRef tycon, m, "{| ", " |}")), + anonInfo + ) let boxity = anonType.Boxity GenExprs cenv cgbuf eenv args @@ -3884,7 +3891,11 @@ and GenAllocAnonRecd cenv cgbuf eenv (anonInfo: AnonRecdTypeInfo, tyargs, args, and GenGetAnonRecdField cenv cgbuf eenv (anonInfo: AnonRecdTypeInfo, e, tyargs, n, m) sequel = let _anonCtor, anonMethods, anonType = - cgbuf.mgbuf.LookupAnonType((fun ilThisTy -> GenToStringMethod cenv eenv ilThisTy m), anonInfo) + cgbuf.mgbuf.LookupAnonType( + (fun (ilThisTy, tycon) -> + GenRecordToStringMethod(cenv, cgbuf.mgbuf, EnvForTycon tycon eenv, ilThisTy, mkLocalTyconRef tycon, m, "{| ", " |}")), + anonInfo + ) let boxity = anonType.Boxity let ilTypeArgs = GenTypeArgs cenv m eenv.tyenv tyargs @@ -10952,7 +10963,11 @@ and GenImplFile cenv (mgbuf: AssemblyBuilder) mainInfoOpt eenv (implFile: Checke // Generate all the anonymous record types mentioned anywhere in this module for anonInfo in anonRecdTypes.Values do - mgbuf.GenerateAnonType((fun ilThisTy -> GenToStringMethod cenv eenv ilThisTy m), anonInfo) + mgbuf.GenerateAnonType( + (fun (ilThisTy, tycon) -> + GenRecordToStringMethod(cenv, mgbuf, EnvForTycon tycon eenv, ilThisTy, mkLocalTyconRef tycon, m, "{| ", " |}")), + anonInfo + ) let withQName (loc: CompileLocation) = { loc with @@ -11320,11 +11335,8 @@ and GenAbstractBinding cenv eenv tref (vref: ValRef) = else [], [], [] -and GenToStringMethod cenv eenv ilThisTy m = - GenPrintingMethod cenv eenv "ToString" ilThisTy m - /// Generate a ToString/get_Message method that calls 'sprintf "%A"' -and GenPrintingMethod cenv eenv methName ilThisTy m = +and GenSprintfPrintingMethod cenv eenv methName ilThisTy m = let g = cenv.g [ @@ -11389,6 +11401,42 @@ and GenPrintingMethod cenv eenv methName ilThisTy m = | _ -> () ] +/// Emit a [] virtual ToString override whose body is the given string-typed expression. +/// 'thisv' is the 'this' value (stored at arg 0) referenced by bodyExpr. +and EmitToStringMethodDef (cenv: cenv, mgbuf: AssemblyBuilder, eenv: IlxGenEnv, thisv: Val, bodyExpr: Expr) = + let g = cenv.g + let eenvForMeth = AddStorageForLocalVals g [ (thisv, Arg 0) ] eenv + + let ilMethodBody = + CodeGenMethodForExpr cenv mgbuf ([], "ToString", eenvForMeth, 0, Some thisv, bodyExpr, Return) + + let mdef = + mkILNonGenericVirtualInstanceMethod ( + "ToString", + ILMemberAccess.Public, + [], + mkILReturn g.ilg.typ_String, + MethodBody.IL(InterruptibleLazy.FromValue ilMethodBody) + ) + + [ mdef.With(customAttrs = mkILCustomAttrs [ g.CompilerGeneratedAttribute ]) ] + +/// Generate an anonymous record's ToString as a single line "{| F1 = v1; F2 = v2 |}". Nominal records and +/// unions get their reflection-free ToString from the type-augmentation phase instead (so the 'string' +/// operator calls are optimized), but anonymous record types are synthesized too late for that, so they are +/// generated here. Under non-reflection-free codegen, falls back to sprintf "%+A". +and GenRecordToStringMethod + (cenv: cenv, mgbuf: AssemblyBuilder, eenv: IlxGenEnv, ilThisTy: ILType, tcref: TyconRef, m: range, openBrace: string, closeBrace: string) = + let g = cenv.g + + if not g.useReflectionFreeCodeGen then + GenSprintfPrintingMethod cenv eenv "ToString" ilThisTy m + else + let thisv, body = + AugmentTypeDefinitions.mkRecdToString (g, tcref, tcref.Deref, openBrace, closeBrace) + + EmitToStringMethodDef(cenv, mgbuf, eenv, thisv, body) + and GenTypeDef cenv mgbuf lazyInitInfo eenv m (tycon: Tycon) : ILTypeRef option = let g = cenv.g let tcref = mkLocalTyconRef tycon @@ -11972,8 +12020,10 @@ and GenTypeDef cenv mgbuf lazyInitInfo eenv m (tycon: Tycon) : ILTypeRef option then yield mkILSimpleStorageCtor (Some g.ilg.typ_Object.TypeSpec, ilThisTy, [], [], reprAccess, None, eenv.imports) - if not (tycon.HasMember g "ToString" []) then - yield! GenToStringMethod cenv eenv ilThisTy m + // Reflection-free nominal records get their ToString from the type-augmentation phase; here we + // only emit the sprintf "%+A" ToString for the non-reflection-free case. + if not g.useReflectionFreeCodeGen && not (tycon.HasMember g "ToString" []) then + yield! GenSprintfPrintingMethod cenv eenvinner "ToString" ilThisTy m | TFSharpTyconRepr r when tycon.IsFSharpDelegateTycon -> @@ -11996,8 +12046,12 @@ and GenTypeDef cenv mgbuf lazyInitInfo eenv m (tycon: Tycon) : ILTypeRef option yield! mkILDelegateMethods reprAccess g.ilg (g.iltyp_AsyncCallback, g.iltyp_IAsyncResult) (parameters, ret) | _ -> () - | TFSharpTyconRepr { fsobjmodel_kind = TFSharpUnion } when not (tycon.HasMember g "ToString" []) -> - yield! GenToStringMethod cenv eenv ilThisTy m + // Reflection-free nominal unions get their ToString from the type-augmentation phase; here we + // only emit the sprintf "%+A" ToString for the non-reflection-free case. + | TFSharpTyconRepr { fsobjmodel_kind = TFSharpUnion } when + not g.useReflectionFreeCodeGen && not (tycon.HasMember g "ToString" []) + -> + yield! GenSprintfPrintingMethod cenv eenvinner "ToString" ilThisTy m | _ -> () ] @@ -12613,7 +12667,7 @@ and GenExnDef cenv mgbuf eenv m (exnc: Tycon) : ILTypeRef option = && not (exnc.HasMember g "Message" []) && not (fspecs |> List.exists (fun rf -> rf.DisplayNameCore = "Message")) then - yield! GenPrintingMethod cenv eenv "get_Message" ilThisTy m + yield! GenSprintfPrintingMethod cenv eenv "get_Message" ilThisTy m ] let interfaces = diff --git a/src/Compiler/Optimize/Optimizer.fs b/src/Compiler/Optimize/Optimizer.fs index 4748685287d..3d88004e673 100644 --- a/src/Compiler/Optimize/Optimizer.fs +++ b/src/Compiler/Optimize/Optimizer.fs @@ -2579,19 +2579,7 @@ and MakeOptimizedSystemStringConcatCall cenv env m args = let args = optimizeArgs args [] - let expr = - match args with - | [ arg ] -> - arg - | [ arg1; arg2 ] -> - mkStaticCall_String_Concat2 g m arg1 arg2 - | [ arg1; arg2; arg3 ] -> - mkStaticCall_String_Concat3 g m arg1 arg2 arg3 - | [ arg1; arg2; arg3; arg4 ] -> - mkStaticCall_String_Concat4 g m arg1 arg2 arg3 arg4 - | args -> - let arg = mkArray (g.string_ty, args, m) - mkStaticCall_String_Concat_Array g m arg + let expr = mkStringConcat (g, m, args) match expr with | Expr.Op(TOp.ILCall(_, _, _, _, _, _, _, ilMethRef, _, _, _) as op, tyargs, args, m) diff --git a/src/Compiler/TypedTree/TcGlobals.fs b/src/Compiler/TypedTree/TcGlobals.fs index 237ec492651..5b55012f907 100644 --- a/src/Compiler/TypedTree/TcGlobals.fs +++ b/src/Compiler/TypedTree/TcGlobals.fs @@ -806,6 +806,7 @@ type TcGlobals( let v_byte_operator_info = makeIntrinsicValRef(fslib_MFOperators_nleref, "byte" , None , Some "ToByte", [vara], ([[varaTy]], v_byte_ty)) let v_sbyte_operator_info = makeIntrinsicValRef(fslib_MFOperators_nleref, "sbyte" , None , Some "ToSByte", [vara], ([[varaTy]], v_sbyte_ty)) + let v_string_operator_info = makeIntrinsicValRef(fslib_MFOperators_nleref, "string" , None , Some "ToString", [vara], ([[varaTy]], v_string_ty)) let v_int16_operator_info = makeIntrinsicValRef(fslib_MFOperators_nleref, "int16" , None , Some "ToInt16", [vara], ([[varaTy]], v_int16_ty)) let v_uint16_operator_info = makeIntrinsicValRef(fslib_MFOperators_nleref, "uint16" , None , Some "ToUInt16", [vara], ([[varaTy]], v_uint16_ty)) let v_int32_operator_info = makeIntrinsicValRef(fslib_MFOperators_nleref, "int32" , None , Some "ToInt32", [vara], ([[varaTy]], v_int32_ty)) @@ -1610,6 +1611,7 @@ type TcGlobals( member _.byte_operator_info = v_byte_operator_info member _.sbyte_operator_info = v_sbyte_operator_info + member _.string_operator_info = v_string_operator_info member _.int16_operator_info = v_int16_operator_info member _.uint16_operator_info = v_uint16_operator_info member _.int32_operator_info = v_int32_operator_info diff --git a/src/Compiler/TypedTree/TcGlobals.fsi b/src/Compiler/TypedTree/TcGlobals.fsi index 214ad0d17cd..8ecc7e83f00 100644 --- a/src/Compiler/TypedTree/TcGlobals.fsi +++ b/src/Compiler/TypedTree/TcGlobals.fsi @@ -941,6 +941,8 @@ type internal TcGlobals = member sbyte_operator_info: IntrinsicValRef + member string_operator_info: IntrinsicValRef + member sbyte_tcr: TypedTree.EntityRef member sbyte_ty: TypedTree.TType diff --git a/src/Compiler/TypedTree/TypedTreeOps.ExprOps.fs b/src/Compiler/TypedTree/TypedTreeOps.ExprOps.fs index 91ed02ee1a3..d5dc5ef07f0 100644 --- a/src/Compiler/TypedTree/TypedTreeOps.ExprOps.fs +++ b/src/Compiler/TypedTree/TypedTreeOps.ExprOps.fs @@ -1368,6 +1368,9 @@ module internal Makers = let mkCallNewFormat (g: TcGlobals) m aty bty cty dty ety formatStringExpr = mkApps g (typedExprForIntrinsic g m g.new_format_info, [ [ aty; bty; cty; dty; ety ] ], [ formatStringExpr ], m) + let mkCallStringOperator (g: TcGlobals) m argTy e = + mkApps g (typedExprForIntrinsic g m g.string_operator_info, [ [ argTy ] ], [ e ], m) + let tryMkCallBuiltInWitness (g: TcGlobals) traitInfo argExprs m = let info, tinst = g.MakeBuiltInWitnessInfo traitInfo let vref = ValRefForIntrinsic info @@ -1572,6 +1575,17 @@ module internal Makers = m ) + /// Concatenate string-valued expressions, choosing the cheapest String.Concat overload by arity. + /// An empty list yields "" and a singleton yields itself. + let mkStringConcat (g: TcGlobals, m: range, exprs: Expr list) = + match exprs with + | [] -> mkString g m "" + | [ arg ] -> arg + | [ arg1; arg2 ] -> mkStaticCall_String_Concat2 g m arg1 arg2 + | [ arg1; arg2; arg3 ] -> mkStaticCall_String_Concat3 g m arg1 arg2 arg3 + | [ arg1; arg2; arg3; arg4 ] -> mkStaticCall_String_Concat4 g m arg1 arg2 arg3 arg4 + | _ -> mkStaticCall_String_Concat_Array g m (mkArray (g.string_ty, exprs, m)) + // Quotations can't contain any IL. // As a result, we aim to get rid of all IL generation in the typechecker and pattern match // compiler, or else train the quotation generator to understand the generated IL. diff --git a/src/Compiler/TypedTree/TypedTreeOps.ExprOps.fsi b/src/Compiler/TypedTree/TypedTreeOps.ExprOps.fsi index ad90c5c818c..70379648e63 100644 --- a/src/Compiler/TypedTree/TypedTreeOps.ExprOps.fsi +++ b/src/Compiler/TypedTree/TypedTreeOps.ExprOps.fsi @@ -208,6 +208,9 @@ module internal Makers = val mkCallNewFormat: TcGlobals -> range -> TType -> TType -> TType -> TType -> TType -> formatStringExpr: Expr -> Expr + /// Build a call to the 'string' operator (Operators.ToString) at the given argument type. + val mkCallStringOperator: TcGlobals -> range -> argTy: TType -> Expr -> Expr + val mkCallGetGenericComparer: TcGlobals -> range -> Expr val mkCallGetGenericEREqualityComparer: TcGlobals -> range -> Expr @@ -446,6 +449,10 @@ module internal Makers = val mkStaticCall_String_Concat_Array: TcGlobals -> range -> Expr -> Expr + /// Concatenate string-valued expressions, choosing the cheapest String.Concat overload by arity. + /// An empty list yields "" and a singleton yields itself. + val mkStringConcat: TcGlobals * range * Expr list -> Expr + val mkDecr: TcGlobals -> range -> Expr -> Expr val mkIncr: TcGlobals -> range -> Expr -> Expr diff --git a/tests/FSharp.Compiler.ComponentTests/CompilerOptions/fsc/reflectionfree.fs b/tests/FSharp.Compiler.ComponentTests/CompilerOptions/fsc/reflectionfree.fs index 65b96d7d9c8..da96fa9bb96 100644 --- a/tests/FSharp.Compiler.ComponentTests/CompilerOptions/fsc/reflectionfree.fs +++ b/tests/FSharp.Compiler.ComponentTests/CompilerOptions/fsc/reflectionfree.fs @@ -35,15 +35,296 @@ let someCode = """ [] -let ``Records and DUs don't have generated ToString`` () = +let ``Classes don't have a generated ToString`` () = someCode |> withOptions [ "--reflectionfree" ] |> compileExeAndRun |> shouldSucceed - |> withStdOutContains "Thing says: Test+MyRecord" - |> withStdOutContains "Thing says: Test+MyUnion+B" |> withStdOutContains "Thing says: Test+MyClass" +[] +let ``Records get a generated single-line ToString`` () = + FSharp """ +module Test +type Point = { X: int; Y: int } +type Nested = { P: Point; S: string } + +[] +let main _ = + { X = 1; Y = 2 } |> string |> System.Console.WriteLine + { P = { X = 1; Y = 2 }; S = null } |> string |> System.Console.WriteLine // nested record + null field + 0 + """ + |> asExe + |> withOptions [ "--reflectionfree" ] + |> compileExeAndRun + |> shouldSucceed + |> withStdOutContains "{ X = 1; Y = 2 }" + |> withStdOutContains "{ P = { X = 1; Y = 2 }; S = null }" + +[] +let ``Unions have a generated ToString that matches on the case`` () = + someCode + |> withOptions [ "--reflectionfree" ] + |> compileExeAndRun + |> shouldSucceed + |> withStdOutContains "Thing says: B(foo)" + +[] +let ``Generic unions get a correct generated ToString`` () = + FSharp """ +module Test +type Box<'T> = + | Box of 'T + | Empty +type Single<'T> = | Just of 'T + +[] +let main _ = + Box 42 |> string |> System.Console.WriteLine + Box (Box 7) |> string |> System.Console.WriteLine // nested generic + (Empty: Box) |> string |> System.Console.WriteLine + Just 5 |> string |> System.Console.WriteLine // single-case generic union + 0 + """ + |> asExe + |> withOptions [ "--reflectionfree" ] + |> compileExeAndRun + |> shouldSucceed + |> withStdOutContains "Box(42)" + |> withStdOutContains "Box(Box(7))" + |> withStdOutContains "Empty" + |> withStdOutContains "Just(5)" + +[] +let ``Generated ToString renders a field the same way option does`` () = + FSharp """ +module Test +type Wrapper = | Wrap of string + +[] +let main _ = + let value: string = null + // A union field should render its content the same way option does. Compare the two directly rather + // than asserting a fixed rendering. "Wrap" and "Some" are both 4 chars, so dropping them leaves the + // field rendering to compare. + let fromUnion = (Wrap value |> string).Substring 4 + let fromOption = ((Some value).ToString()).Substring 4 + if fromUnion = fromOption then System.Console.WriteLine "fields-render-alike" + else System.Console.WriteLine("DIFFER: " + fromUnion + " vs " + fromOption) + 0 + """ + |> asExe + |> withOptions [ "--reflectionfree" ] + |> compileExeAndRun + |> shouldSucceed + |> withStdOutContains "fields-render-alike" + +[] +let ``A hand-written ToString override is kept, not replaced by the generated one`` () = + FSharp """ +module Test +type MyDU = + | A of int + override _.ToString() = "custom-du" + +type MyRecord = + { X: int } + override _.ToString() = "custom-record" + +[] +let main _ = + A 1 |> string |> System.Console.WriteLine + { X = 1 } |> string |> System.Console.WriteLine + 0 + """ + |> asExe + |> withOptions [ "--reflectionfree" ] + |> compileExeAndRun + |> shouldSucceed + |> withStdOutContains "custom-du" + |> withStdOutContains "custom-record" + +[] +let ``Union field shapes: multiple fields versus a single tuple field`` () = + FSharp """ +module Test +type TwoFields = | Two of int * int +type OneTupleField = | OneTup of (int * int) +type NamedFields = | Named of x: int * y: int + +[] +let main _ = + Two (1, 2) |> string |> System.Console.WriteLine + OneTup (1, 2) |> string |> System.Console.WriteLine // a single tuple field keeps its own parens + Named (1, 2) |> string |> System.Console.WriteLine // named fields render positionally, names are not shown + 0 + """ + |> asExe + |> withOptions [ "--reflectionfree" ] + |> compileExeAndRun + |> shouldSucceed + |> withStdOutContains "Two(1, 2)" + |> withStdOutContains "OneTup((1, 2))" + |> withStdOutContains "Named(1, 2)" + +[] +let ``Explicit field names do not change the rendering`` () = + FSharp """ +module Test +type Labelled = | WithNames of first: int * second: string +type Plain = | WithoutNames of int * string + +[] +let main _ = + WithNames (1, "a") |> string |> System.Console.WriteLine + WithoutNames (1, "a") |> string |> System.Console.WriteLine // unnamed fields render the same way as named ones + 0 + """ + |> asExe + |> withOptions [ "--reflectionfree" ] + |> compileExeAndRun + |> shouldSucceed + |> withStdOutContains "WithNames(1, a)" + |> withStdOutContains "WithoutNames(1, a)" + +[] +let ``Backtick-quoted names render without their backticks`` () = + FSharp """ +module Test +type Quoted = | ``My Case`` of int +type QuotedField = { ``My Field``: int } + +[] +let main _ = + ``My Case`` 5 |> string |> System.Console.WriteLine + { ``My Field`` = 5 } |> string |> System.Console.WriteLine + 0 + """ + |> asExe + |> withOptions [ "--reflectionfree" ] + |> compileExeAndRun + |> shouldSucceed + |> withStdOutContains "My Case(5)" + |> withStdOutContains "{ My Field = 5 }" + +[] +let ``Struct unions and struct records get a generated ToString`` () = + FSharp """ +module Test +[] type StructUnion = | SA of a: int +[] type StructRecord = { SX: int; SY: int } + +[] +let main _ = + SA 7 |> string |> System.Console.WriteLine + { SX = 1; SY = 2 } |> string |> System.Console.WriteLine + 0 + """ + |> asExe + |> withOptions [ "--reflectionfree" ] + |> compileExeAndRun + |> shouldSucceed + |> withStdOutContains "SA(7)" + |> withStdOutContains "{ SX = 1; SY = 2 }" + +[] +let ``Anonymous records get a generated single-line ToString`` () = + FSharp """ +module Test +[] +let main _ = + {| A = 1; B = "hi" |} |> string |> System.Console.WriteLine + (struct {| A = 1; B = "hi" |}) |> string |> System.Console.WriteLine // a struct anonymous record renders identically + 0 + """ + |> asExe + |> withOptions [ "--reflectionfree" ] + |> compileExeAndRun + |> shouldSucceed + |> withStdOutContains "{| A = 1; B = hi |}" + +[] +let ``An empty anonymous record renders with a single inner space`` () = + FSharp """ +module Test +[] +let main _ = + System.Console.WriteLine("[" + string {| |} + "]") // the empty braces keep a single space, not a doubled one + 0 + """ + |> asExe + |> withOptions [ "--reflectionfree" ] + |> compileExeAndRun + |> shouldSucceed + |> withStdOutContains "[{| |}]" + +[] +let ``Recursively defined types render when the data is finite`` () = + FSharp """ +module Test +type Tree = | Leaf | Node of Tree * int * Tree +type TreeNode = { Value: int; Parent: TreeNode option } // an upward-only parent pointer stays finite + +[] +let main _ = + Node (Node (Leaf, 1, Leaf), 2, Leaf) |> string |> System.Console.WriteLine + let root = { Value = 0; Parent = None } + { Value = 1; Parent = Some root } |> string |> System.Console.WriteLine + 0 + """ + |> asExe + |> withOptions [ "--reflectionfree" ] + |> compileExeAndRun + |> shouldSucceed + |> withStdOutContains "Node(Node(Leaf, 1, Leaf), 2, Leaf)" + |> withStdOutContains "{ Value = 1; Parent = Some({ Value = 0; Parent = null }) }" + +[] +let ``Deeply nested data fails the generated ToString with a catchable exception, not a hard overflow`` () = + FSharp """ +module Test +type Chain = | End | Link of int * Chain + +[] +let main _ = + let mutable c = End + for i in 1 .. 1_000_000 do c <- Link(i, c) + try + c.ToString() |> ignore + System.Console.WriteLine "rendered" + with :? System.InsufficientExecutionStackException -> + System.Console.WriteLine "caught" + 0 + """ + |> asExe + |> withOptions [ "--reflectionfree" ] + |> compileExeAndRun + |> shouldSucceed + |> withStdOutContains "caught" + +[] +let ``Deeply nested anonymous records fail the generated ToString with a catchable exception, not a hard overflow`` () = + FSharp """ +module Test + +[] +let main _ = + let mutable o: obj = box 0 + for _ in 1 .. 1_000_000 do o <- box {| Next = o |} + try + o.ToString() |> ignore + System.Console.WriteLine "rendered" + with :? System.InsufficientExecutionStackException -> + System.Console.WriteLine "caught" + 0 + """ + |> asExe + |> withOptions [ "--reflectionfree" ] + |> compileExeAndRun + |> shouldSucceed + |> withStdOutContains "caught" + [] let ``No debug display attribute`` () = someCode diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/ReflectionFreeToString.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/ReflectionFreeToString.fs new file mode 100644 index 00000000000..e85db29e560 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/ReflectionFreeToString.fs @@ -0,0 +1,284 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace EmittedIL + +open Xunit +open FSharp.Test.Compiler + +module ``ReflectionFreeToString`` = + + // Under --reflectionfree, records and unions get a structural ToString (fields joined with String.Concat, + // value-type fields rendered via a direct allocation-free ToString, no PrintfFormat) instead of sprintf "%+A". + + [] + let ``Record ToString is generated structurally without printf`` () = + FSharp """ +module ReflectionFreeToString +type Point = { X: int; Y: int } + """ + |> withOptions [ "--reflectionfree" ] + |> compile + |> shouldSucceed + |> verifyIL [""" +.method public hidebysig virtual final instance string ToString() cil managed +{ +.custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + +.maxstack 8 +.locals init (int32 V_0) +IL_0000: ldc.i4.7 +IL_0001: newarr [runtime]System.String +IL_0006: dup +IL_0007: ldc.i4.0 +IL_0008: ldstr "{ " +IL_000d: stelem [runtime]System.String +IL_0012: dup +IL_0013: ldc.i4.1 +IL_0014: ldstr "X = " +IL_0019: stelem [runtime]System.String +IL_001e: dup +IL_001f: ldc.i4.2 +IL_0020: ldarg.0 +IL_0021: ldfld int32 ReflectionFreeToString/Point::X@ +IL_0026: stloc.0 +IL_0027: ldloca.s V_0 +IL_0029: ldnull +IL_002a: call class [netstandard]System.Globalization.CultureInfo [netstandard]System.Globalization.CultureInfo::get_InvariantCulture() +IL_002f: call instance string [netstandard]System.Int32::ToString(string, +class [netstandard]System.IFormatProvider) +IL_0034: stelem [runtime]System.String +IL_0039: dup +IL_003a: ldc.i4.3 +IL_003b: ldstr "; " +IL_0040: stelem [runtime]System.String +IL_0045: dup +IL_0046: ldc.i4.4 +IL_0047: ldstr "Y = " +IL_004c: stelem [runtime]System.String +IL_0051: dup +IL_0052: ldc.i4.5 +IL_0053: ldarg.0 +IL_0054: ldfld int32 ReflectionFreeToString/Point::Y@ +IL_0059: stloc.0 +IL_005a: ldloca.s V_0 +IL_005c: ldnull +IL_005d: call class [netstandard]System.Globalization.CultureInfo [netstandard]System.Globalization.CultureInfo::get_InvariantCulture() +IL_0062: call instance string [netstandard]System.Int32::ToString(string, +class [netstandard]System.IFormatProvider) +IL_0067: stelem [runtime]System.String +IL_006c: dup +IL_006d: ldc.i4.6 +IL_006e: ldstr " }" +IL_0073: stelem [runtime]System.String +IL_0078: call string [runtime]System.String::Concat(string[]) +IL_007d: ret +}"""] + + [] + let ``Union ToString is generated structurally without printf`` () = + FSharp """ +module ReflectionFreeToString +type Color = | Red | Custom of int + """ + |> withOptions [ "--reflectionfree" ] + |> compile + |> shouldSucceed + |> verifyIL [""" +.method public hidebysig virtual final instance string ToString() cil managed +{ +.custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + +.maxstack 6 +.locals init (class ReflectionFreeToString/Color/Custom V_0, +int32 V_1) +IL_0000: ldarg.0 +IL_0001: isinst ReflectionFreeToString/Color/_Red +IL_0006: brfalse.s IL_000e + +IL_0008: ldstr "Red" +IL_000d: ret + +IL_000e: ldarg.0 +IL_000f: castclass ReflectionFreeToString/Color/Custom +IL_0014: stloc.0 +IL_0015: ldstr "Custom(" +IL_001a: ldloc.0 +IL_001b: ldfld int32 ReflectionFreeToString/Color/Custom::item +IL_0020: stloc.1 +IL_0021: ldloca.s V_1 +IL_0023: ldnull +IL_0024: call class [netstandard]System.Globalization.CultureInfo [netstandard]System.Globalization.CultureInfo::get_InvariantCulture() +IL_0029: call instance string [netstandard]System.Int32::ToString(string, +class [netstandard]System.IFormatProvider) +IL_002e: ldstr ")" +IL_0033: call string [runtime]System.String::Concat(string, +string, +string) +IL_0038: ret +}"""] + + [] + let ``Struct record ToString reads its fields directly off the this pointer`` () = + FSharp """ +module ReflectionFreeToString +[] type SPoint = { SX: int; SY: int } + """ + |> withOptions [ "--reflectionfree" ] + |> compile + |> shouldSucceed + |> verifyIL [""" +.method public hidebysig virtual final instance string ToString() cil managed +{ +.custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + +.maxstack 8 +.locals init (int32 V_0) +IL_0000: ldc.i4.7 +IL_0001: newarr [runtime]System.String +IL_0006: dup +IL_0007: ldc.i4.0 +IL_0008: ldstr "{ " +IL_000d: stelem [runtime]System.String +IL_0012: dup +IL_0013: ldc.i4.1 +IL_0014: ldstr "SX = " +IL_0019: stelem [runtime]System.String +IL_001e: dup +IL_001f: ldc.i4.2 +IL_0020: ldarg.0 +IL_0021: ldfld int32 ReflectionFreeToString/SPoint::SX@ +IL_0026: stloc.0 +IL_0027: ldloca.s V_0 +IL_0029: ldnull +IL_002a: call class [netstandard]System.Globalization.CultureInfo [netstandard]System.Globalization.CultureInfo::get_InvariantCulture() +IL_002f: call instance string [netstandard]System.Int32::ToString(string, +class [netstandard]System.IFormatProvider) +IL_0034: stelem [runtime]System.String +IL_0039: dup +IL_003a: ldc.i4.3 +IL_003b: ldstr "; " +IL_0040: stelem [runtime]System.String +IL_0045: dup +IL_0046: ldc.i4.4 +IL_0047: ldstr "SY = " +IL_004c: stelem [runtime]System.String +IL_0051: dup +IL_0052: ldc.i4.5 +IL_0053: ldarg.0 +IL_0054: ldfld int32 ReflectionFreeToString/SPoint::SY@ +IL_0059: stloc.0 +IL_005a: ldloca.s V_0 +IL_005c: ldnull +IL_005d: call class [netstandard]System.Globalization.CultureInfo [netstandard]System.Globalization.CultureInfo::get_InvariantCulture() +IL_0062: call instance string [netstandard]System.Int32::ToString(string, +class [netstandard]System.IFormatProvider) +IL_0067: stelem [runtime]System.String +IL_006c: dup +IL_006d: ldc.i4.6 +IL_006e: ldstr " }" +IL_0073: stelem [runtime]System.String +IL_0078: call string [runtime]System.String::Concat(string[]) +IL_007d: ret +}"""] + + [] + let ``Struct union ToString switches on the tag rather than the case type`` () = + FSharp """ +module ReflectionFreeToString +[] type SColor = | SRed | SCustom of item: int + """ + |> withOptions [ "--reflectionfree" ] + |> compile + |> shouldSucceed + |> verifyIL [""" +.method public hidebysig virtual final instance string ToString() cil managed +{ +.custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + +.maxstack 6 +.locals init (int32 V_0) +IL_0000: ldarg.0 +IL_0001: call instance int32 ReflectionFreeToString/SColor::get_Tag() +IL_0006: ldc.i4.0 +IL_0007: bne.un.s IL_000f + +IL_0009: ldstr "SRed" +IL_000e: ret + +IL_000f: ldstr "SCustom(" +IL_0014: ldarg.0 +IL_0015: ldfld int32 ReflectionFreeToString/SColor::_item +IL_001a: stloc.0 +IL_001b: ldloca.s V_0 +IL_001d: ldnull +IL_001e: call class [netstandard]System.Globalization.CultureInfo [netstandard]System.Globalization.CultureInfo::get_InvariantCulture() +IL_0023: call instance string [netstandard]System.Int32::ToString(string, +class [netstandard]System.IFormatProvider) +IL_0028: ldstr ")" +IL_002d: call string [runtime]System.String::Concat(string, +string, +string) +IL_0032: ret +}"""] + + // An anonymous record's fields are type parameters, so each renders through the generic box+null guard and + // the recursion guard is always emitted. The field reads are left out of the baseline: they name the + // anonymous type, whose mangled name is not stable. + [] + let ``Anonymous record ToString is generated with a recursion guard`` () = + FSharp """ +module ReflectionFreeToString +let anon (o: obj) = {| A = 1; N = o |} + """ + |> withOptions [ "--reflectionfree" ] + |> compile + |> shouldSucceed + |> verifyIL [""" +.method public strict virtual instance string ToString() cil managed +{ +.custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + +.maxstack 6 +.locals init (!'j__TPar' V_0, +!'j__TPar' V_1) +IL_0000: call void [runtime]System.Runtime.CompilerServices.RuntimeHelpers::EnsureSufficientExecutionStack() +IL_0005: ldc.i4.7 +IL_0006: newarr [runtime]System.String +IL_000b: dup +IL_000c: ldc.i4.0 +IL_000d: ldstr "{| " +IL_0012: stelem [runtime]System.String +IL_0017: dup +IL_0018: ldc.i4.1 +IL_0019: ldstr "A = " +IL_001e: stelem [runtime]System.String +IL_0023: dup +IL_0024: ldc.i4.2 +IL_0025: ldarg.0""" + """ +IL_002d: call object [FSharp.Core]Microsoft.FSharp.Core.Operators::Boxj__TPar'>(!!0) +IL_0032: brfalse.s IL_003c + +IL_0034: ldloc.0 +IL_0035: call string [FSharp.Core]Microsoft.FSharp.Core.Operators::ToStringj__TPar'>(!!0) +IL_003a: br.s IL_0041 + +IL_003c: ldstr "null" +IL_0041: stelem [runtime]System.String +IL_0046: dup +IL_0047: ldc.i4.3 +IL_0048: ldstr "; " +IL_004d: stelem [runtime]System.String +IL_0052: dup +IL_0053: ldc.i4.4 +IL_0054: ldstr "N = " +IL_0059: stelem [runtime]System.String +IL_005e: dup +IL_005f: ldc.i4.5 +IL_0060: ldarg.0""" + """ +IL_0083: ldstr " |}" +IL_0088: stelem [runtime]System.String +IL_008d: call string [runtime]System.String::Concat(string[]) +IL_0092: ret +}"""] diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj index 18ec085a3f2..a4589a97a2b 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj +++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj @@ -249,6 +249,7 @@ + From c00299f285bce6edeb535d28261ea7a46998e721 Mon Sep 17 00:00:00 2001 From: Adam Boniecki <20281641+abonie@users.noreply.github.com> Date: Thu, 30 Jul 2026 20:57:05 +0200 Subject: [PATCH 23/33] Run ilverify via the tool manifest instead of a hard-coded cache path (#20101) --- tests/FSharp.Test.Utilities/ILVerifierModule.fs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/tests/FSharp.Test.Utilities/ILVerifierModule.fs b/tests/FSharp.Test.Utilities/ILVerifierModule.fs index 30ff766287e..c570b4cc150 100644 --- a/tests/FSharp.Test.Utilities/ILVerifierModule.fs +++ b/tests/FSharp.Test.Utilities/ILVerifierModule.fs @@ -26,13 +26,10 @@ module ILVerifierModule = Commands.executeProcess dotnetExe arguments workingDirectory let private verifyPEFileCore peverifierArgs (dllFilePath: string) = - let nuget_packages = - match Environment.GetEnvironmentVariable("NUGET_PACKAGES") with - | null -> - let profile = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) - $"""{profile}/.nuget/packages""" - | path -> path - let peverifyFullArgs = [ yield "exec"; yield $"""{nuget_packages}/dotnet-ilverify/9.0.0/tools/net9.0/any/ILVerify.dll"""; yield "--verbose"; yield dllFilePath; yield! peverifierArgs ] + // Resolve ilverify through the local tool manifest (.config/dotnet-tools.json) rather than a + // hard-coded NuGet cache path. `dotnet tool run` locates the tool wherever it was restored, so + // verification does not depend on the NuGet cache layout, tool version, or target framework. + let peverifyFullArgs = [ yield "tool"; yield "run"; yield "ilverify"; yield "--"; yield "--verbose"; yield dllFilePath; yield! peverifierArgs ] let workingDirectory = Path.GetDirectoryName dllFilePath let exitCode, outputText, errorText = let peverifierCommandPath = Path.ChangeExtension(dllFilePath, ".peverifierCommandPath.cmd") From f4b785f189aedc4a0f1ec22182e3653a0b9dd142 Mon Sep 17 00:00:00 2001 From: Brian Rourke Boll Date: Sat, 1 Aug 2026 02:19:29 -0400 Subject: [PATCH 24/33] Record spreads (#18927) --- .../.FSharp.Compiler.Service/11.0.100.md | 1 + docs/release-notes/.Language/preview.md | 3 +- src/Compiler/Checking/CheckDeclarations.fs | 333 ++- src/Compiler/Checking/CheckPatterns.fs | 18 +- .../Checking/CheckRecordSyntaxHelpers.fs | 125 +- .../Checking/CheckRecordSyntaxHelpers.fsi | 9 +- src/Compiler/Checking/ConstraintSolver.fs | 9 +- src/Compiler/Checking/ConstraintSolver.fsi | 3 + .../Checking/Expressions/CheckExpressions.fs | 512 ++-- .../Checking/Expressions/CheckExpressions.fsi | 10 +- src/Compiler/Checking/NameResolution.fs | 62 +- src/Compiler/Checking/NameResolution.fsi | 23 +- src/Compiler/Checking/Spreads.fs | 663 +++++ src/Compiler/Driver/CompilerDiagnostics.fs | 3 +- .../GraphChecking/FileContentMapping.fs | 44 +- src/Compiler/FSComp.txt | 15 + src/Compiler/FSStrings.resx | 7 +- src/Compiler/FSharp.Compiler.Service.fsproj | 1 + src/Compiler/Facilities/LanguageFeatures.fs | 3 + src/Compiler/Facilities/LanguageFeatures.fsi | 1 + src/Compiler/Service/FSharpCheckerResults.fs | 49 +- .../Service/FSharpParseFileResults.fs | 16 +- .../Service/ServiceInterfaceStubGenerator.fs | 8 +- src/Compiler/Service/ServiceLexing.fs | 6 +- src/Compiler/Service/ServiceLexing.fsi | 6 +- src/Compiler/Service/ServiceNavigation.fs | 28 +- src/Compiler/Service/ServiceParseTreeWalk.fs | 152 +- src/Compiler/Service/ServiceParseTreeWalk.fsi | 4 +- src/Compiler/Service/ServiceParsedInputOps.fs | 90 +- .../Service/ServiceParsedInputOps.fsi | 11 + src/Compiler/Service/ServiceStructure.fs | 15 +- src/Compiler/Service/SynExpr.fs | 13 +- src/Compiler/SyntaxTree/LexFilter.fs | 15 +- src/Compiler/SyntaxTree/ParseHelpers.fs | 28 +- src/Compiler/SyntaxTree/ParseHelpers.fsi | 6 +- src/Compiler/SyntaxTree/SyntaxTree.fs | 48 +- src/Compiler/SyntaxTree/SyntaxTree.fsi | 59 +- src/Compiler/SyntaxTree/SyntaxTreeOps.fs | 15 +- src/Compiler/lex.fsl | 2 + src/Compiler/pars.fsy | 119 +- src/Compiler/xlf/FSComp.txt.cs.xlf | 77 +- src/Compiler/xlf/FSComp.txt.de.xlf | 77 +- src/Compiler/xlf/FSComp.txt.es.xlf | 77 +- src/Compiler/xlf/FSComp.txt.fr.xlf | 77 +- src/Compiler/xlf/FSComp.txt.it.xlf | 77 +- src/Compiler/xlf/FSComp.txt.ja.xlf | 77 +- src/Compiler/xlf/FSComp.txt.ko.xlf | 77 +- src/Compiler/xlf/FSComp.txt.pl.xlf | 77 +- src/Compiler/xlf/FSComp.txt.pt-BR.xlf | 77 +- src/Compiler/xlf/FSComp.txt.ru.xlf | 77 +- src/Compiler/xlf/FSComp.txt.tr.xlf | 77 +- src/Compiler/xlf/FSComp.txt.zh-Hans.xlf | 77 +- src/Compiler/xlf/FSComp.txt.zh-Hant.xlf | 77 +- src/Compiler/xlf/FSStrings.cs.xlf | 5 + src/Compiler/xlf/FSStrings.de.xlf | 5 + src/Compiler/xlf/FSStrings.es.xlf | 5 + src/Compiler/xlf/FSStrings.fr.xlf | 5 + src/Compiler/xlf/FSStrings.it.xlf | 5 + src/Compiler/xlf/FSStrings.ja.xlf | 5 + src/Compiler/xlf/FSStrings.ko.xlf | 5 + src/Compiler/xlf/FSStrings.pl.xlf | 5 + src/Compiler/xlf/FSStrings.pt-BR.xlf | 5 + src/Compiler/xlf/FSStrings.ru.xlf | 5 + src/Compiler/xlf/FSStrings.tr.xlf | 5 + src/Compiler/xlf/FSStrings.zh-Hans.xlf | 5 + src/Compiler/xlf/FSStrings.zh-Hant.xlf | 5 + .../Conformance/Constraints/Unmanaged.fs | 2 +- .../Conformance/Spreads/RecordSpreads.fsx | 86 + .../Conformance/Spreads/RecordSpreadsTests.fs | 28 + .../Conformance/Spreads/SpreadInlineLib.fs | 7 + .../Types/RecordTypes/AnonymousRecords.fs | 20 +- .../Types/RecordTypes/RecordTypes.fs | 20 +- .../AnonymousRecordExpressionSpreads.fs | 84 + .../Expression_Anonymous_CoercionsApplied.fs | 13 + ...ssion_Anonymous_CoercionsApplied.fs.il.bsl | 678 +++++ ...ression_Anonymous_ExplicitShadowsSpread.fs | 3 + ..._Anonymous_ExplicitShadowsSpread.fs.il.bsl | 544 ++++ ...ression_Anonymous_ExtraFieldsAreIgnored.fs | 3 + ..._Anonymous_ExtraFieldsAreIgnored.fs.il.bsl | 984 +++++++ .../Expression_Anonymous_NestedUpdates.fs | 4 + ...pression_Anonymous_NestedUpdates.fs.il.bsl | 1360 +++++++++ ...ion_Anonymous_NoOverlap_Explicit_Spread.fs | 3 + ...nymous_NoOverlap_Explicit_Spread.fs.il.bsl | 1084 +++++++ ...ion_Anonymous_NoOverlap_Spread_Explicit.fs | 3 + ...nymous_NoOverlap_Spread_Explicit.fs.il.bsl | 1084 +++++++ ...ssion_Anonymous_NoOverlap_Spread_Spread.fs | 5 + ...nonymous_NoOverlap_Spread_Spread.fs.il.bsl | 1673 +++++++++++ ...ression_Anonymous_SpreadShadowsExplicit.fs | 3 + ..._Anonymous_SpreadShadowsExplicit.fs.il.bsl | 545 ++++ ...xpression_Anonymous_SpreadShadowsSpread.fs | 5 + ...on_Anonymous_SpreadShadowsSpread.fs.il.bsl | 916 ++++++ .../Expression_Anonymous_Structness.fs | 21 + .../Expression_Anonymous_Structness.fs.il.bsl | 2517 ++++++++++++++++ .../Expression_Nominal_CoercionsApplied.fs | 14 + ...ression_Nominal_CoercionsApplied.fs.il.bsl | 1576 ++++++++++ ...xpression_Nominal_ExplicitShadowsSpread.fs | 5 + ...on_Nominal_ExplicitShadowsSpread.fs.il.bsl | 203 ++ ...xpression_Nominal_ExtraFieldsAreIgnored.fs | 7 + ...on_Nominal_ExtraFieldsAreIgnored.fs.il.bsl | 288 ++ .../Expression_Nominal_NestedUpdates.fs | 13 + ...Expression_Nominal_NestedUpdates.fs.il.bsl | 381 +++ ...ssion_Nominal_NoOverlap_Explicit_Spread.fs | 10 + ...ominal_NoOverlap_Explicit_Spread.fs.il.bsl | 783 +++++ ...ession_Nominal_NoOverlap_SpreadFromAnon.fs | 4 + ...Nominal_NoOverlap_SpreadFromAnon.fs.il.bsl | 656 +++++ ...ssion_Nominal_NoOverlap_Spread_Explicit.fs | 10 + ...ominal_NoOverlap_Spread_Explicit.fs.il.bsl | 783 +++++ ...ression_Nominal_NoOverlap_Spread_Spread.fs | 16 + ..._Nominal_NoOverlap_Spread_Spread.fs.il.bsl | 1420 +++++++++ ...xpression_Nominal_SpreadShadowsExplicit.fs | 5 + ...on_Nominal_SpreadShadowsExplicit.fs.il.bsl | 204 ++ .../Expression_Nominal_SpreadShadowsSpread.fs | 5 + ...sion_Nominal_SpreadShadowsSpread.fs.il.bsl | 553 ++++ .../Spreads/Expression_Nominal_Structness.fs | 16 + .../Expression_Nominal_Structness.fs.il.bsl | 2035 +++++++++++++ .../Spreads/NominalRecordExpressionSpreads.fs | 90 + .../EmittedIL/Spreads/RecordTypeSpreads.fs | 78 + .../Spreads/Type_AttributesAreShadowed.fs | 7 + .../Type_AttributesAreShadowed.fs.il.bsl | 255 ++ .../Spreads/Type_ExplicitShadowsSpread.fs | 4 + .../Type_ExplicitShadowsSpread.fs.il.bsl | 217 ++ .../Spreads/Type_NoOverlap_Explicit_Spread.fs | 4 + .../Type_NoOverlap_Explicit_Spread.fs.il.bsl | 243 ++ ...Type_NoOverlap_Explicit_Spread_Generics.fs | 6 + ...Overlap_Explicit_Spread_Generics.fs.il.bsl | 255 ++ .../Spreads/Type_NoOverlap_SpreadFromAnon.fs | 3 + .../Type_NoOverlap_SpreadFromAnon.fs.il.bsl | 162 + .../Spreads/Type_NoOverlap_Spread_Explicit.fs | 4 + .../Type_NoOverlap_Spread_Explicit.fs.il.bsl | 243 ++ .../Spreads/Type_NoOverlap_Spread_Spread.fs | 8 + .../Type_NoOverlap_Spread_Spread.fs.il.bsl | 479 +++ .../Spreads/Type_SpreadShadowsExplicit.fs | 4 + .../Type_SpreadShadowsExplicit.fs.il.bsl | 217 ++ .../Spreads/Type_SpreadShadowsSpread.fs | 8 + .../Type_SpreadShadowsSpread.fs.il.bsl | 356 +++ .../FSharp.Compiler.ComponentTests.fsproj | 5 + .../Language/CopyAndUpdateTests.fs | 12 +- .../Language/RecordSpreadsTests.fs | 2609 +++++++++++++++++ .../CompletionTests.fs | 104 +- ...iler.Service.SurfaceArea.netstandard20.bsl | 183 +- .../ParsedInputModuleTests.fs | 11 +- .../FSharp.Compiler.Service.Tests/Symbols.fs | 57 + .../TreeVisitorTests.fs | 4 +- .../XmlDocTests.fs | 9 +- .../Expression/AnonRecd - Quotation 01.fs.bsl | 105 +- .../Expression/AnonRecd - Quotation 02.fs.bsl | 105 +- .../Expression/AnonRecd - Quotation 03.fs.bsl | 150 +- .../Expression/AnonRecd - Quotation 04.fs.bsl | 114 +- .../Expression/AnonymousRecords-01.fs.bsl | 16 +- .../Expression/AnonymousRecords-02.fs.bsl | 8 +- .../Expression/AnonymousRecords-03.fs.bsl | 8 +- .../Expression/AnonymousRecords-06.fs.bsl | 28 +- .../Expression/AnonymousRecords-07.fs.bsl | 76 +- .../Expression/AnonymousRecords-08.fs.bsl | 144 +- .../Expression/AnonymousRecords-09.fs.bsl | 60 +- .../Expression/AnonymousRecords-10.fs.bsl | 68 +- .../Expression/AnonymousRecords-11.fs.bsl | 92 +- .../Expression/AnonymousRecords-12.fs.bsl | 60 +- .../Expression/AnonymousRecords-13.fs.bsl | 22 +- ...OfTheEqualsSignInSynExprRecordField.fs.bsl | 17 +- .../Expression/InheritRecord - Field 1.fs.bsl | 20 +- .../Expression/InheritRecord - Field 2.fs.bsl | 35 +- ...OfTheEqualsSignInSynExprRecordField.fs.bsl | 13 +- .../Expression/Record - Anon 01.fs.bsl | 8 +- .../Expression/Record - Anon 02.fs.bsl | 7 +- .../Expression/Record - Anon 07.fs.bsl | 14 +- .../Expression/Record - Anon 08.fs.bsl | 14 +- .../Expression/Record - Anon 09.fs.bsl | 35 +- .../Expression/Record - Anon 10.fs.bsl | 22 +- .../Expression/Record - Anon 11.fs.bsl | 28 +- .../Expression/Record - Field 03.fs.bsl | 9 +- .../Expression/Record - Field 04.fs.bsl | 12 +- .../Expression/Record - Field 05.fs.bsl | 7 +- .../Expression/Record - Field 06.fs.bsl | 9 +- .../Expression/Record - Field 08.fs.bsl | 14 +- .../Expression/Record - Field 09.fs.bsl | 14 +- .../Expression/Record - Field 11.fs.bsl | 7 +- .../Expression/Record - Field 12.fs.bsl | 31 +- .../Expression/Record - Field 13.fs.bsl | 14 +- .../Expression/Record - Field 14.fs.bsl | 38 +- .../SynExprAnonRecdWithStructKeyword.fs.bsl | 6 +- ...sTheRangeOfTheEqualsSignInTheFields.fs.bsl | 22 +- ...OfTheEqualsSignInSynExprRecordField.fs.bsl | 36 +- ...dFieldsContainCorrectAmountOfTrivia.fs.bsl | 104 +- .../SyntaxTree/Pattern/Named field 07.fs.bsl | 10 +- .../SyntaxTree/Pattern/Named field 08.fs.bsl | 10 +- ...esShouldBeIncludedInRecursiveTypes.fsi.bsl | 14 +- ...DefnSigRecordShouldEndAtLastMember.fsi.bsl | 14 +- .../Type/Module Inside Record 01.fs.bsl | 14 +- .../Type/Module Same Indentation 01.fs.bsl | 14 +- ...tesShouldBeIncludedInRecursiveTypes.fs.bsl | 39 +- .../SyntaxTree/Type/Record - Access 01.fs.bsl | 12 +- .../SyntaxTree/Type/Record - Access 02.fs.bsl | 16 +- .../SyntaxTree/Type/Record - Access 03.fs.bsl | 18 +- .../SyntaxTree/Type/Record - Access 04.fs.bsl | 14 +- .../Type/Record - Mutable 01.fs.bsl | 16 +- .../Type/Record - Mutable 02.fs.bsl | 30 +- .../Type/Record - Mutable 03.fs.bsl | 28 +- .../Type/Record - Mutable 04.fs.bsl | 42 +- .../Type/Record - Mutable 05.fs.bsl | 44 +- .../data/SyntaxTree/Type/Record 01.fs.bsl | 26 +- .../data/SyntaxTree/Type/Record 02.fs.bsl | 27 +- .../data/SyntaxTree/Type/Record 04.fs.bsl | 11 +- .../data/SyntaxTree/Type/Record 05.fs.bsl | 39 +- ...ordContainsTheRangeOfTheWithKeyword.fs.bsl | 14 +- .../SemanticClassificationServiceTests.fs | 2 +- 206 files changed, 30506 insertions(+), 1460 deletions(-) create mode 100644 src/Compiler/Checking/Spreads.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/Conformance/Spreads/RecordSpreads.fsx create mode 100644 tests/FSharp.Compiler.ComponentTests/Conformance/Spreads/RecordSpreadsTests.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/Conformance/Spreads/SpreadInlineLib.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/AnonymousRecordExpressionSpreads.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_CoercionsApplied.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_CoercionsApplied.fs.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_ExplicitShadowsSpread.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_ExplicitShadowsSpread.fs.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_ExtraFieldsAreIgnored.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_ExtraFieldsAreIgnored.fs.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_NestedUpdates.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_NestedUpdates.fs.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_NoOverlap_Explicit_Spread.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_NoOverlap_Explicit_Spread.fs.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_NoOverlap_Spread_Explicit.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_NoOverlap_Spread_Explicit.fs.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_NoOverlap_Spread_Spread.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_NoOverlap_Spread_Spread.fs.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_SpreadShadowsExplicit.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_SpreadShadowsExplicit.fs.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_SpreadShadowsSpread.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_SpreadShadowsSpread.fs.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_Structness.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_Structness.fs.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_CoercionsApplied.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_CoercionsApplied.fs.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_ExplicitShadowsSpread.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_ExplicitShadowsSpread.fs.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_ExtraFieldsAreIgnored.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_ExtraFieldsAreIgnored.fs.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_NestedUpdates.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_NestedUpdates.fs.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_NoOverlap_Explicit_Spread.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_NoOverlap_Explicit_Spread.fs.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_NoOverlap_SpreadFromAnon.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_NoOverlap_SpreadFromAnon.fs.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_NoOverlap_Spread_Explicit.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_NoOverlap_Spread_Explicit.fs.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_NoOverlap_Spread_Spread.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_NoOverlap_Spread_Spread.fs.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_SpreadShadowsExplicit.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_SpreadShadowsExplicit.fs.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_SpreadShadowsSpread.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_SpreadShadowsSpread.fs.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_Structness.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_Structness.fs.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/NominalRecordExpressionSpreads.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/RecordTypeSpreads.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_AttributesAreShadowed.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_AttributesAreShadowed.fs.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_ExplicitShadowsSpread.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_ExplicitShadowsSpread.fs.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_NoOverlap_Explicit_Spread.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_NoOverlap_Explicit_Spread.fs.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_NoOverlap_Explicit_Spread_Generics.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_NoOverlap_Explicit_Spread_Generics.fs.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_NoOverlap_SpreadFromAnon.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_NoOverlap_SpreadFromAnon.fs.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_NoOverlap_Spread_Explicit.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_NoOverlap_Spread_Explicit.fs.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_NoOverlap_Spread_Spread.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_NoOverlap_Spread_Spread.fs.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_SpreadShadowsExplicit.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_SpreadShadowsExplicit.fs.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_SpreadShadowsSpread.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_SpreadShadowsSpread.fs.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/Language/RecordSpreadsTests.fs diff --git a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md index 476df124084..c0233963b7e 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md +++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md @@ -141,6 +141,7 @@ * Add diagnostic FS3889 when a namespace and a type have the same fully-qualified name in the same assembly, replacing the misleading FS0247 "namespace and a module" error. ([Issue #17827](https://github.com/dotnet/fsharp/issues/17827), [PR #19802](https://github.com/dotnet/fsharp/pull/19802)) * Debug: rework for expressions stepping ([PR #19894](https://github.com/dotnet/fsharp/pull/19894)) * Debug: rework conditional erasure, fix stepping over literals ([PR #19897](https://github.com/dotnet/fsharp/pull/19897)) +* Spread operator for records ([RFC FS-1151](https://github.com/fsharp/fslang-design/pull/805), [PR #18927](https://github.com/dotnet/fsharp/pull/18927)) * Debug: fix if and match condition sequence points ([PR #19932](https://github.com/dotnet/fsharp/pull/19932)) * Under `--reflectionfree`, discriminated unions, records and anonymous records now get a [generated `ToString`](../../reflectionfree-printing.md) (rendering each field like `Option` does) instead of falling back to the namespace-qualified type name. ([PR #19976](https://github.com/dotnet/fsharp/pull/19976)) * Support common types of `NotNullIfNotNullAttribute` usage. If a method parameter is marked with `NotNullIfNotNullAttribute`, the compiler will now honor this attribute and mark the return type as non-null. ([PR #19977](https://github.com/dotnet/fsharp/pull/19977)) diff --git a/docs/release-notes/.Language/preview.md b/docs/release-notes/.Language/preview.md index 1c37adc77c2..d48e49c4e21 100644 --- a/docs/release-notes/.Language/preview.md +++ b/docs/release-notes/.Language/preview.md @@ -4,9 +4,10 @@ * Added `MethodOverloadsCache` language feature (preview) that caches overload resolution results for repeated method calls, significantly improving compilation performance. ([PR #19072](https://github.com/dotnet/fsharp/pull/19072)) * Added `ErrorOnMissingSignatureAttribute` preview language feature: makes FS3888 (compiler-semantic attribute on the `.fs` but not on the `.fsi`) an error instead of a warning. ([Issue #19560](https://github.com/dotnet/fsharp/issues/19560), [PR #19880](https://github.com/dotnet/fsharp/pull/19880)) * Support common types of `NotNullIfNotNullAttribute` usage. If a method parameter is marked with `NotNullIfNotNullAttribute`, the compiler will now honor this attribute and mark the return type as non-null. ([PR #19977](https://github.com/dotnet/fsharp/pull/19977)) +* Spread operator for records ([RFC FS-1151](https://github.com/fsharp/fslang-design/pull/805), [PR #18927](https://github.com/dotnet/fsharp/pull/18927)) * Added `AccessProtectedBaseFieldFromClosure` preview language feature: a derived member can now read a `protected` base-class field from an ordinary closure (lambda, delegate, `async`/`seq`/`lazy`, `function`, or list/array literal), which previously failed with FS1097 even though direct access compiles. Object expressions remain unsupported — bind the field to a local function or expose it through a member. ([Issue #5302](https://github.com/dotnet/fsharp/issues/5302)) * Added `ImprovedImpliedArgumentNamesPartTwo` language feature: when a function with no recoverable parameter names is coerced to a delegate (e.g. a partial application like `System.Func((+) 1)`), the synthesized `Invoke` parameters take their names from the delegate's own `Invoke` signature instead of synthetic `delegateArg0`, `delegateArg1`, … names. ([PR #20001](https://github.com/dotnet/fsharp/pull/20001)) ### Fixed -### Changed \ No newline at end of file +### Changed diff --git a/src/Compiler/Checking/CheckDeclarations.fs b/src/Compiler/Checking/CheckDeclarations.fs index 6df195958f8..8b8acecaba0 100644 --- a/src/Compiler/Checking/CheckDeclarations.fs +++ b/src/Compiler/Checking/CheckDeclarations.fs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. module internal FSharp.Compiler.CheckDeclarations @@ -2664,6 +2664,8 @@ module EstablishTypeDefinitionCores = let g = cenv.g let env = AddDeclaredTypars CheckForDuplicateTypars (tycon.Typars) env let env = MakeInnerEnvForTyconRef env thisTyconRef false + let ad = env.AccessRights + let spreadSrcTys = ResizeArray () [ match synTyconRepr with | SynTypeDefnSimpleRepr.None _ -> () | SynTypeDefnSimpleRepr.Union (_, unionCases, _) -> @@ -2707,13 +2709,31 @@ module EstablishTypeDefinitionCores = errorR(Error(FSComp.SR.tcStructsMustDeclareTypesOfImplicitCtorArgsExplicitly(), m)) yield (ty, m) - | SynTypeDefnSimpleRepr.Record (_, fields, _) -> - for SynField(fieldType = ty; range = m) in fields do + | SynTypeDefnSimpleRepr.Record (_, fieldsAndSpreads, _) -> + let tcField (SynField (fieldType = ty; range = m)) = let tyR, _ = TcTypeAndRecover cenv NoNewTypars NoCheckCxs ItemOccurrence.UseInType WarnOnIWSAM.Yes env tpenv ty - yield (tyR, m) + (tyR, m), ignore + + let tcSpread (SynTypeSpread (ty = ty; range = m)) = + let spreadSrcTy, _ = TcTypeAndRecover cenv NoNewTypars NoCheckCxs ItemOccurrence.UseInType WarnOnIWSAM.Yes env tpenv ty + + if isRecdTy g spreadSrcTy then + spreadSrcTys.Add spreadSrcTy + ResolveRecordOrClassFieldsOfType cenv.nameResolver m ad spreadSrcTy false + |> List.choose (function + | Item.RecdField field -> Some (field.RecdField.Id.idText, (field.FieldType, m), ignore) + | _ -> None) + else + match tryDestAnonRecdTy g spreadSrcTy with + | ValueSome (anonInfo, tys) -> tys |> List.mapi (fun i ty -> (anonInfo.SortedNames[i], (ty, m), ignore)) + | ValueNone -> [] + + // We must apply the spread shadowing logic here + // to get the correct set of field types. + yield! fieldsAndSpreads |> Spreads.Types.Records.check ignore tcField tcSpread | _ -> - () ] + () ], spreadSrcTys let ComputeModuleOrNamespaceKind g isModule typeNames attribs nm = if not isModule then (Namespace true) @@ -3631,22 +3651,22 @@ module EstablishTypeDefinitionCores = let item = Item.UnionCase(info, false) CallNameResolutionSink cenv.tcSink (unionCase.Range, nenv, item, emptyTyparInst, ItemOccurrence.Binding, ad) - let typeRepr, baseValOpt, safeInitInfo = + let (typeRepr, baseValOpt, safeInitInfo), recheck = match synTyconRepr with | SynTypeDefnSimpleRepr.Exception synExnDefnRepr -> let parent = Parent (mkLocalTyconRef tycon) TcExceptionDeclarations.TcExnDefnCore_Phase1G_EstablishRepresentation cenv envinner parent tycon synExnDefnRepr |> ignore - TNoRepr, None, NoSafeInitInfo + (TNoRepr, None, NoSafeInitInfo), ignore | SynTypeDefnSimpleRepr.None _ -> hiddenReprChecks false noAllowNullLiteralAttributeCheck() if hasMeasureAttr then let repr = TFSharpTyconRepr (Construct.NewEmptyFSharpTyconData TFSharpClass) - repr, None, NoSafeInitInfo + (repr, None, NoSafeInitInfo), ignore else - TNoRepr, None, NoSafeInitInfo + (TNoRepr, None, NoSafeInitInfo), ignore // This unfortunate case deals with "type x = A" // In F# this only defines a new type if A is not in scope @@ -3661,10 +3681,10 @@ module EstablishTypeDefinitionCores = TcRecdUnionAndEnumDeclarations.CheckUnionCaseName cenv unionCaseName hasRQAAttribute let unionCase = Construct.NewUnionCase unionCaseName [] thisTy [] XmlDoc.Empty tycon.Accessibility writeFakeUnionCtorsToSink [ unionCase ] - Construct.MakeUnionRepr [ unionCase ], None, NoSafeInitInfo + (Construct.MakeUnionRepr [ unionCase ], None, NoSafeInitInfo), ignore | SynTypeDefnSimpleRepr.TypeAbbrev(ParserDetail.ErrorRecovery, _rhsType, _) -> - TNoRepr, None, NoSafeInitInfo + (TNoRepr, None, NoSafeInitInfo), ignore | SynTypeDefnSimpleRepr.TypeAbbrev(ParserDetail.Ok, rhsType, _) -> if hasSealedAttr = Some true then @@ -3675,12 +3695,12 @@ module EstablishTypeDefinitionCores = let kind = if hasMeasureAttr then TyparKind.Measure else TyparKind.Type let theTypeAbbrev, _ = TcTypeOrMeasureAndRecover (Some kind) cenv NoNewTypars CheckCxs ItemOccurrence.UseInType WarnOnIWSAM.No envinner tpenv rhsType - TMeasureableRepr theTypeAbbrev, None, NoSafeInitInfo + (TMeasureableRepr theTypeAbbrev, None, NoSafeInitInfo), ignore // If we already computed a representation, e.g. for a generative type definition, then don't change it here. elif (match tycon.TypeReprInfo with TNoRepr -> false | _ -> true) then - tycon.TypeReprInfo, None, NoSafeInitInfo + (tycon.TypeReprInfo, None, NoSafeInitInfo), ignore else - TNoRepr, None, NoSafeInitInfo + (TNoRepr, None, NoSafeInitInfo), ignore | SynTypeDefnSimpleRepr.Union (_, unionCases, mRepr) -> noMeasureAttributeCheck() @@ -3696,29 +3716,148 @@ module EstablishTypeDefinitionCores = writeFakeUnionCtorsToSink unionCases CallEnvSink cenv.tcSink (mRepr, envinner.NameEnv, ad) let repr = Construct.MakeUnionRepr unionCases - repr, None, NoSafeInitInfo + (repr, None, NoSafeInitInfo), ignore - | SynTypeDefnSimpleRepr.Record (_, fields, mRepr) -> + | SynTypeDefnSimpleRepr.Record (_accessibility, fieldsAndSpreads, mRepr) -> noMeasureAttributeCheck() noSealedAttributeCheck FSComp.SR.tcTypesAreAlwaysSealedRecord noAbstractClassAttributeCheck() noAllowNullLiteralAttributeCheck() structLayoutAttributeCheck true // these are allowed for records - let recdFields = TcRecdUnionAndEnumDeclarations.TcNamedFieldDecls cenv envinner innerParent false tpenv addFixup fields - recdFields |> CheckDuplicates (fun f -> f.Id) "field" |> ignore - writeFakeRecordFieldsToSink recdFields - CallEnvSink cenv.tcSink (mRepr, envinner.NameEnv, ad) - let data = - { - fsobjmodel_cases = Construct.MakeUnionCases [] - fsobjmodel_kind = TFSharpRecord - fsobjmodel_vslots = [] - fsobjmodel_rfields = Construct.MakeRecdFieldsTable recdFields - } + let check pass = + let firstPass = pass = FirstPass + let recdFields = + let tcField synField = + let field = TcRecdUnionAndEnumDeclarations.TcNamedFieldDecl cenv envinner innerParent false tpenv addFixup synField |> Option.get + let errorAmbiguousShadowing () = if firstPass then errorR (Duplicate ("field", field.Id.idText, field.Id.idRange)) + field, errorAmbiguousShadowing + + let tcSpread (SynTypeSpread (ty = ty; range = m)) = + let mTy = ty.Range + let (spreadSrcTy, _tpenv), error = + try TcType cenv NoNewTypars CheckCxs ItemOccurrence.UseInType WarnOnIWSAM.Yes envinner tpenv ty, false with + | RecoverableException e -> + if firstPass then + errorRecovery e ty.Range + (g.obj_ty_ambivalent, tpenv), true + + let spreadSrcTyIsNullable = g.checkNullness && (nullnessOfTy g spreadSrcTy).Evaluate() = NullnessInfo.WithNull + let spreadSrcTyIsRecd = error || isRecdTy g spreadSrcTy || isAnonRecdTy g spreadSrcTy + + let isValidSpreadSrcTy = not spreadSrcTyIsNullable && spreadSrcTyIsRecd + + if isValidSpreadSrcTy then + let spreadSrcTy = + tryAppTy g spreadSrcTy + |> ValueOption.map (fun (tcref, tinst) -> + let _, _, newTinst = FreshenTypeInst g m tcref.Typars + SolveTyparsEqualTypes g cenv.css m newTinst tinst + TType_app (tcref, newTinst, g.knownWithoutNull)) + |> ValueOption.defaultValue spreadSrcTy + + let recordFieldsFromSpread = + if isRecdTy g spreadSrcTy then + ResolveRecordOrClassFieldsOfType cenv.nameResolver m ad spreadSrcTy false + else + tryDestAnonRecdTy g spreadSrcTy + |> ValueOption.map (fun (anonInfo, tys) -> + anonInfo.SortedIds + |> List.ofArray + |> List.mapi (fun i id -> Item.AnonRecdField (anonInfo, tys, i, id.idRange))) + |> ValueOption.defaultValue [] + + recordFieldsFromSpread + |> List.choose (fun field -> + match field with + | Item.RecdField fieldInfo -> + // Update the field ID's range to be that of the spread. + let syntheticId = ident (fieldInfo.RecdField.Id.idText, mTy) + let fieldTy = fieldInfo.FieldType + let vis = + let vis, _ = ComputeAccessAndCompPath g envinner None mTy None None innerParent + combineAccess vis thisTyconRef.TypeReprAccessibility + + let recdField = + { fieldInfo.RecdField with + rfield_id = syntheticId + rfield_type = fieldTy + rfield_access = vis } + + let warnAmbiguousShadowing () = + let fmtedSpreadField = NicePrint.stringOfRecdField envinner.DisplayEnv cenv.infoReader fieldInfo.TyconRef recdField + let fmtedSpreadSrcTy = NicePrint.stringOfTy envinner.DisplayEnv spreadSrcTy + warning (Error (FSComp.SR.tcRecordTypeDefinitionSpreadFieldShadowsExplicitField (fmtedSpreadField, fmtedSpreadSrcTy), m)) + + Some (fieldInfo.RecdField.Id.idText, recdField, warnAmbiguousShadowing) + + | Item.AnonRecdField (anonInfo, tys, fieldIndex, _) -> + let fieldId = + let orig = anonInfo.SortedIds[fieldIndex] + ident (orig.idText, m) + + let ty = tys[fieldIndex] + + let field = + let stat = false + let konst = None + let generated = false + let mut = false + let volatile = false + let pattribs = [] + let fattribs = [] + let vis = None + TcRecdUnionAndEnumDeclarations.MakeRecdFieldSpec g envinner innerParent (stat, konst, ty, pattribs, fattribs, fieldId, generated, mut, volatile, XmlDoc.Empty, vis, mTy) + + let warnAmbiguousShadowing () = + let typars = tryAppTy g ty |> ValueOption.map (snd >> List.choose (tryDestTyparTy g >> ValueOption.toOption)) |> ValueOption.defaultValue [] + let fmtedSpreadField = LayoutRender.showL (NicePrint.prettyLayoutOfMemberSig envinner.DisplayEnv ([], fieldId.idText, typars, [], ty)) + let fmtedSpreadSrcTy = NicePrint.stringOfTy envinner.DisplayEnv spreadSrcTy + warning (Error (FSComp.SR.tcRecordTypeDefinitionSpreadFieldShadowsExplicitField (fmtedSpreadField, fmtedSpreadSrcTy), m)) + + Some (fieldId.idText, field, warnAmbiguousShadowing) + + | _ -> None) + elif not firstPass then + [] + else + if not ty.IsFromParseError then + if not spreadSrcTyIsRecd then + errorR (Error (FSComp.SR.tcRecordTypeDefinitionSpreadSourceMustBeRecord (), m)) + elif spreadSrcTyIsNullable then + errorR (Error (FSComp.SR.tcRecordTypeDefinitionSpreadSourceCannotBeNullable (), m)) + [] - let repr = TFSharpTyconRepr data - repr, None, NoSafeInitInfo + let checkSpreadsLanguageFeature m = + if firstPass then + checkLanguageFeatureAndRecover g.langVersion LanguageFeature.RecordSpreads m + + fieldsAndSpreads |> Spreads.Types.Records.check checkSpreadsLanguageFeature tcField tcSpread + + writeFakeRecordFieldsToSink recdFields + CallEnvSink cenv.tcSink (mRepr, envinner.NameEnv, ad) + + let data = + { + fsobjmodel_cases = Construct.MakeUnionCases [] + fsobjmodel_kind = TFSharpRecord + fsobjmodel_vslots = [] + fsobjmodel_rfields = Construct.MakeRecdFieldsTable recdFields + } + + let repr = TFSharpTyconRepr data + repr, None, NoSafeInitInfo + + let recheck = + if fieldsAndSpreads |> List.exists (function SynFieldOrSpread.Spread _ -> true | SynFieldOrSpread.Field _ -> false) then + fun () -> + let repr, _, _ = check SecondPass + tycon.entity_tycon_repr <- repr + else + ignore + + + check FirstPass, recheck | SynTypeDefnSimpleRepr.LibraryOnlyILAssembly (s, _) -> let s = (s :?> ILType) @@ -3727,7 +3866,7 @@ module EstablishTypeDefinitionCores = noAllowNullLiteralAttributeCheck() structLayoutAttributeCheck false noAbstractClassAttributeCheck() - TAsmRepr s, None, NoSafeInitInfo + (TAsmRepr s, None, NoSafeInitInfo), ignore | SynTypeDefnSimpleRepr.General (kind, inherits, slotsigs, fields, isConcrete, isIncrClass, implicitCtorSynPats, _) -> let userFields = TcRecdUnionAndEnumDeclarations.TcNamedFieldDecls cenv envinner innerParent isIncrClass tpenv addFixup fields @@ -3758,7 +3897,7 @@ module EstablishTypeDefinitionCores = | SynTypeDefnKind.Opaque -> hiddenReprChecks true noAllowNullLiteralAttributeCheck() - TNoRepr, None, NoSafeInitInfo + (TNoRepr, None, NoSafeInitInfo), ignore | _ -> // Note: for a mutually recursive set we can't check this condition @@ -3881,7 +4020,7 @@ module EstablishTypeDefinitionCores = fsobjmodel_rfields = Construct.MakeRecdFieldsTable (userFields @ implicitStructFields @ safeInitFields) } let repr = TFSharpTyconRepr data - repr, baseValOpt, safeInitInfo + (repr, baseValOpt, safeInitInfo), ignore | SynTypeDefnSimpleRepr.Enum (decls, m) -> let fieldTy, fields' = TcRecdUnionAndEnumDeclarations.TcEnumDecls cenv envinner tpenv innerParent thisTy decls @@ -3905,7 +4044,7 @@ module EstablishTypeDefinitionCores = fsobjmodel_rfields = Construct.MakeRecdFieldsTable (vfld :: fields') } let repr = TFSharpTyconRepr data - repr, None, NoSafeInitInfo + (repr, None, NoSafeInitInfo), ignore tycon.entity_tycon_repr <- typeRepr // We check this just after establishing the representation @@ -3919,10 +4058,10 @@ module EstablishTypeDefinitionCores = errorR(Error(FSComp.SR.tcConditionalAttributeUsage(), m)) | _ -> () - (baseValOpt, safeInitInfo) + baseValOpt, safeInitInfo, recheck with RecoverableException exn -> - errorRecovery exn m - None, NoSafeInitInfo + errorRecovery exn m + None, NoSafeInitInfo, ignore /// Check that a set of type definitions is free of cycles in abbreviations let private TcTyconDefnCore_CheckForCyclicAbbreviations tycons = @@ -4246,14 +4385,49 @@ module EstablishTypeDefinitionCores = // be satisfied, so we have to do this prior to checking any constraints. // // First find all the field types in all the structural types - let tyconsWithStructuralTypes = - (envMutRecPrelim, withEnvs) - ||> MutRecShapes.mapTyconsWithEnv (fun envForDecls (origInfo, tyconOpt) -> - match origInfo, tyconOpt with + let tyconsWithStructuralTypesAndSpreadSources = + (envMutRecPrelim, withEnvs) + ||> MutRecShapes.mapTyconsWithEnv (fun envForDecls (origInfo, tyconOpt) -> + match origInfo, tyconOpt with | (typeDefCore, _, _), Some tycon -> Some (tycon, GetStructuralElementsOfTyconDefn cenv envForDecls tpenv typeDefCore tycon) - | _ -> None) - |> MutRecShapes.collectTycons + | _ -> None) + |> MutRecShapes.collectTycons |> List.choose id + + let tyconsWithStructuralTypes = + [ + for tycon, (tys, _) in tyconsWithStructuralTypesAndSpreadSources -> + tycon, tys + ] + + // Check for cyclic spreads. + do + if cenv.g.langVersion.SupportsFeature LanguageFeature.RecordSpreads then + let (|PotentiallyRecursiveTycon|_|) ty = + tryTcrefOfAppTy cenv.g ty + |> ValueOption.bind _.TryDeref + + let edges = + [ + for dst, (_, spreadSrcs) in tyconsWithStructuralTypesAndSpreadSources do + for src in spreadSrcs do + match src with + | PotentiallyRecursiveTycon src -> dst, src + | _ -> () + ] + + let tycons = + let seen = HashSet () + [ + for dst, src in edges do + if seen.Add dst.Stamp then + yield dst + if seen.Add src.Stamp then + yield src + ] + + let graph = Graph (_.Stamp, tycons, edges) + graph.IterateCycles (fun path -> errorR (Error (FSComp.SR.tcTypeDefinitionIsCyclicThroughSpreads (), (List.head path).Range))) let scSet = TyconConstraintInference.InferSetOfTyconsSupportingComparable cenv envMutRecPrelim.DisplayEnv tyconsWithStructuralTypes let seSet = TyconConstraintInference.InferSetOfTyconsSupportingEquatable cenv envMutRecPrelim.DisplayEnv tyconsWithStructuralTypes @@ -4293,22 +4467,65 @@ module EstablishTypeDefinitionCores = // Now do the representations. Each baseValOpt is a residue from the representation which is potentially available when // checking the members. let withBaseValsAndSafeInitInfos = - (envMutRecPrelim, withAttrs) ||> MutRecShapes.mapTyconsWithEnv (fun envForDecls (origInfo, tyconAndAttrsOpt) -> - let info, tyconOpt, fixupFinalAttrs = - match origInfo, tyconAndAttrsOpt with - | (typeDefCore, _, _), Some (tycon, (attrs, getFinalAttrs)) -> - let fixups = ResizeArray() - let info = TcTyconDefnCore_Phase1G_EstablishRepresentation cenv envForDecls tpenv inSig typeDefCore tycon attrs fixups.Add - let (MutRecDefnsPhase1DataForTycon(SynComponentInfo(typeParams=TyparDecls synTypars), _, _, _, _, _)) = typeDefCore - let fixupFinalAttrs () = - tycon.entity_attribs <- WellKnownEntityAttribs.Create(getFinalAttrs()) - fixupTyparAttrs cenv envForDecls synTypars tycon.Typars - for fixup in fixups do fixup() - info, Some tycon, fixupFinalAttrs - | _ -> (None, NoSafeInitInfo), None, ignore - - (origInfo, tyconOpt, fixupFinalAttrs, info)) - + let passOne = + (envMutRecPrelim, withAttrs) ||> MutRecShapes.mapTyconsWithEnv (fun envForDecls (origInfo, tyconAndAttrsOpt) -> + let info, tyconOpt, fixupFinalAttrs = + match origInfo, tyconAndAttrsOpt with + | (typeDefCore, _, _), Some (tycon, (attrs, getFinalAttrs)) -> + let fixups = ResizeArray() + let info = TcTyconDefnCore_Phase1G_EstablishRepresentation cenv envForDecls tpenv inSig typeDefCore tycon attrs fixups.Add + let (MutRecDefnsPhase1DataForTycon(SynComponentInfo(typeParams=TyparDecls synTypars), _, _, _, _, _)) = typeDefCore + let fixupFinalAttrs () = + tycon.entity_attribs <- WellKnownEntityAttribs.Create(getFinalAttrs()) + fixupTyparAttrs cenv envForDecls synTypars tycon.Typars + for fixup in fixups do fixup() + info, Some tycon, fixupFinalAttrs + | _ -> (None, NoSafeInitInfo, ignore), None, ignore + + (origInfo, tyconOpt, fixupFinalAttrs, info)) + + let rechecks = + [ + for _, tyconOpt, _, (_, _, recheck) in passOne |> MutRecShapes.collectTycons do + match tyconOpt with + | Some tycon -> tycon.Stamp, recheck + | None -> () + ] + + let spreadDependencies = + Map.ofList [ + for tycon, (_, spreadSrcTys) in tyconsWithStructuralTypesAndSpreadSources -> + tycon.Stamp, [ + for ty in spreadSrcTys do + match tryTcrefOfAppTy cenv.g ty |> ValueOption.bind _.TryDeref with + | ValueSome tycon -> tycon.Stamp + | ValueNone -> () + ] + ] + + let recheckMap = Map.ofList rechecks + let seen = HashSet () + + let rec recheck tyconStamp = + if seen.Add tyconStamp then + match spreadDependencies |> Map.tryFind tyconStamp with + | Some spreadSrcStamps -> + for spreadSrcStamp in spreadSrcStamps do + if recheckMap |> Map.containsKey spreadSrcStamp then + recheck spreadSrcStamp + | None -> () + + match recheckMap |> Map.tryFind tyconStamp with + | Some recheck -> recheck () + | None -> () + + // Spreads require a second pass once all fields in the group are known. + for tyconStamp, _ in rechecks do + recheck tyconStamp + + passOne |> MutRecShapes.mapTycons (fun (origInfo, tyconOpt, fixupFinalAttrs, (v, safeInit, _)) -> + (origInfo, tyconOpt, fixupFinalAttrs, (v, safeInit))) + // Now check for cyclic structs and inheritance. It's possible these should be checked as separate conditions. // REVIEW: checking for cyclic inheritance is happening too late. See note above. TcTyconDefnCore_CheckForCyclicStructsAndInheritance cenv tycons diff --git a/src/Compiler/Checking/CheckPatterns.fs b/src/Compiler/Checking/CheckPatterns.fs index 55295562303..d7b1ffd4e3e 100644 --- a/src/Compiler/Checking/CheckPatterns.fs +++ b/src/Compiler/Checking/CheckPatterns.fs @@ -498,13 +498,18 @@ and TcPatArrayOrList warnOnUpper cenv env vFlags patEnv ty isArray args m = phase2, acc and TcRecordPat warnOnUpper (cenv: cenv) env vFlags patEnv ty fieldPats m = - let fieldPats = + let idents = + let (|Last|) = List.last + fieldPats + |> List.map (fun (NamePatPairField (fieldName = SynLongIdent (id = Last fieldId))) -> fieldId) + + let fieldPats = fieldPats - |> List.map (fun (NamePatPairField(fieldName = fieldLid; pat = pat)) -> - match fieldLid.LongIdent with - | [id] -> ([], id), pat - | lid -> List.frontAndBack lid, pat) + |> List.map (fun (NamePatPairField(fieldName = fieldLid; pat = pat)) -> + let path, fieldId = List.frontAndBack fieldLid.LongIdent + fieldId, ExplicitOrSpread.Explicit (path, pat)) + CheckRecdExprDuplicateFields idents match BuildFieldMap cenv env false ty fieldPats m with | None -> (fun _ -> TPat_error m), patEnv | Some(tinst, tcref, fldsmap, _fldsList) -> @@ -520,13 +525,14 @@ and TcRecordPat warnOnUpper (cenv: cenv) env vFlags patEnv ty fieldPats m = let fieldPats, patEnvR = (patEnv, ftys) ||> List.mapFold (fun s (ty, fsp) -> match fldsmap.TryGetValue fsp.rfield_id.idText with - | true, v -> + | true, ExplicitOrSpread.Explicit v -> let warnOnUpper = if cenv.g.langVersion.SupportsFeature(LanguageFeature.DontWarnOnUppercaseIdentifiersInBindingPatterns) then AllIdsOK else warnOnUpper TcPat warnOnUpper cenv env None vFlags s ty v + | true, ExplicitOrSpread.Spread _ -> (* Unreachable. *) error (InternalError ("Spreads in patterns are not supported.", m)) | _ -> (fun _ -> TPat_wild m), s) let phase2 values = diff --git a/src/Compiler/Checking/CheckRecordSyntaxHelpers.fs b/src/Compiler/Checking/CheckRecordSyntaxHelpers.fs index b973bc17286..1df28906810 100644 --- a/src/Compiler/Checking/CheckRecordSyntaxHelpers.fs +++ b/src/Compiler/Checking/CheckRecordSyntaxHelpers.fs @@ -2,6 +2,7 @@ module internal FSharp.Compiler.CheckRecordSyntaxHelpers +open System open FSharp.Compiler.CheckBasics open FSharp.Compiler.DiagnosticsLogger open FSharp.Compiler.Features @@ -14,47 +15,6 @@ open FSharp.Compiler.TypedTree open FSharp.Compiler.Xml open FSharp.Compiler.SyntaxTrivia -/// Merges updates to nested record fields on the same level in record copy-and-update. -/// -/// `TransformAstForNestedUpdates` expands `{ x with A.B = 10; A.C = "" }` -/// -/// into -/// -/// { x with -/// A = { x.A with B = 10 }; -/// A = { x.A with C = "" } -/// } -/// -/// which we here convert to -/// -/// { x with A = { x.A with B = 10; C = "" } } -let GroupUpdatesToNestedFields (fields: ((Ident list * Ident) * SynExpr option) list) = - let rec groupIfNested res xs = - match xs with - | [] -> res - | [ x ] -> x :: res - | x :: y :: ys -> - match x, y with - | (lidwid, Some(SynExpr.Record(baseInfo, copyInfo, fields1, m))), (_, Some(SynExpr.Record(recordFields = fields2))) -> - let reducedRecd = - (lidwid, Some(SynExpr.Record(baseInfo, copyInfo, fields1 @ fields2, m))) - - groupIfNested res (reducedRecd :: ys) - | (lidwid, Some(SynExpr.AnonRecd(isStruct, copyInfo, fields1, m, trivia))), (_, Some(SynExpr.AnonRecd(recordFields = fields2))) -> - let reducedRecd = - (lidwid, Some(SynExpr.AnonRecd(isStruct, copyInfo, fields1 @ fields2, m, trivia))) - - groupIfNested res (reducedRecd :: ys) - | _ -> groupIfNested (x :: res) (y :: ys) - - fields - |> List.groupBy (fun ((_, field), _) -> field.idText) - |> List.collect (fun (_, fields) -> - if fields.Length < 2 then - fields - else - groupIfNested [] fields) - /// Expands a long identifier into nested copy-and-update expressions. /// /// `{ x with A.B = 0; A.C = "" }` becomes `{ x with A = { x.A with B = 0 }; A = { x.A with C = "" } }` @@ -122,17 +82,27 @@ let TransformAstForNestedUpdates (cenv: TcFileState) (env: TcEnv) overallTy (lid | Item.AnonRecdField( anonInfo = { AnonRecdTypeInfo.TupInfo = TupInfo.Const isStruct - }) -> - let fields = [ LongIdentWithDots([ fieldId ], []), None, nestedField ] + } + range = m) -> + let fields = + [ + SynExprAnonRecordFieldOrSpread.Field( + SynExprAnonRecordField(LongIdentWithDots([ fieldId ], []), None, nestedField, m), + None + ) + ] + SynExpr.AnonRecd(isStruct, copyInfo outerFieldId, fields, outerFieldId.idRange, { OpeningBraceRange = range0 }) | _ -> let fields = [ - SynExprRecordField( - (LongIdentWithDots([ fieldId ], []), true), - None, - Some nestedField, - unionRanges fieldId.idRange nestedField.Range, + SynExprRecordFieldOrSpread.Field( + SynExprRecordField( + (LongIdentWithDots([ fieldId ], []), true), + None, + Some nestedField, + unionRanges fieldId.idRange nestedField.Range + ), None ) ] @@ -149,7 +119,7 @@ let TransformAstForNestedUpdates (cenv: TcFileState) (env: TcEnv) overallTy (lid match access, fields with | _, [] -> failwith "unreachable" - | accessIds, [ (fieldId, _) ] -> (accessIds, fieldId), Some exprBeingAssigned + | accessIds, [ (fieldId, _) ] -> (accessIds, fieldId), exprBeingAssigned | accessIds, (outerFieldId, item) :: rest -> checkLanguageFeatureAndRecover cenv.g.langVersion LanguageFeature.NestedCopyAndUpdate (rangeOfLid lid) @@ -157,22 +127,20 @@ let TransformAstForNestedUpdates (cenv: TcFileState) (env: TcEnv) overallTy (lid let outerFieldId = ident (outerFieldId.idText, outerFieldId.idRange.MakeSynthetic()) - (accessIds, outerFieldId), - Some(synExprRecd (recdExprCopyInfo (fields |> List.map fst) withExpr) outerFieldId rest exprBeingAssigned) + (accessIds, outerFieldId), synExprRecd (recdExprCopyInfo (fields |> List.map fst) withExpr) outerFieldId rest exprBeingAssigned /// This name is used when a complex expression is bound for use as a binding in a copy-and-update expression. /// For example, in `{ f () with ... }`, `f ()` is replaced by `let bind@ = f ()` let BindIdText = "bind@" /// Finding the 'bind@' identifier is the only way to detect that an expression has already been bound. -let inline (|IsSimpleOrBoundExpr|_|) (withExprOpt: (SynExpr * BlockSeparator) option) = - match withExprOpt with - | None -> true - | Some(expr, _) -> - match expr with - | SynExpr.LongIdent(_, lIds, _, _) -> lIds.LongIdent |> List.exists (fun id -> id.idText = BindIdText) - | SynExpr.Ident _ -> true - | _ -> false +let inline (|IsSimpleOrBoundExpr|_|) (withExpr: SynExpr) = + match withExpr with + | SynExpr.LongIdent(_, lIds, _, _) -> + lIds.LongIdent + |> List.exists _.idText.StartsWith(BindIdText, StringComparison.Ordinal) + | SynExpr.Ident _ -> true + | _ -> false /// When the original expression in copy-and-update is more complex than `{ x with ... }`, like `{ f () with ... }`, /// we bind it first, so that it's not evaluated multiple times during a nested update @@ -209,3 +177,42 @@ let BindOriginalRecdExpr (withExpr: SynExpr * BlockSeparator) mkRecdExpr = Range = mOrigExprSynth Trivia = SynLetOrUseTrivia.Zero } + +let mutable private bindId = 0 + +let private newBindId () = + System.Threading.Interlocked.Increment &bindId + +let bindSrcIn (spreadSrcExpr: SynExpr) = + let mOrigExprSynth = spreadSrcExpr.Range.MakeSynthetic() + let id = mkSynId mOrigExprSynth $"%s{BindIdText}-%d{newBindId ()}" + let newSpreadSrcExpr = SynExpr.Ident id + + let binding = + mkSynBinding + (PreXmlDoc.Empty, mkSynPatVar None id) + (None, + false, + false, + mOrigExprSynth, + DebugPointAtBinding.NoneAtSticky, + None, + spreadSrcExpr, + mOrigExprSynth, + [], + [], + None, + SynBindingTrivia.Zero) + + fun mkBody -> + SynExpr.LetOrUse + { + IsRecursive = false + //isUse = false, + IsFromSource = false // compiler generated during desugaring + // isBang = false, + Bindings = [ binding ] + Body = mkBody newSpreadSrcExpr + Range = mOrigExprSynth + Trivia = SynLetOrUseTrivia.Zero + } diff --git a/src/Compiler/Checking/CheckRecordSyntaxHelpers.fsi b/src/Compiler/Checking/CheckRecordSyntaxHelpers.fsi index dc68f8a73e2..c8457832087 100644 --- a/src/Compiler/Checking/CheckRecordSyntaxHelpers.fsi +++ b/src/Compiler/Checking/CheckRecordSyntaxHelpers.fsi @@ -7,9 +7,6 @@ open FSharp.Compiler.Syntax open FSharp.Compiler.Text open FSharp.Compiler.TypedTree -val GroupUpdatesToNestedFields: - fields: ((Ident list * Ident) * SynExpr option) list -> ((Ident list * Ident) * SynExpr option) list - val TransformAstForNestedUpdates<'a> : cenv: TcFileState -> env: TcEnv -> @@ -17,11 +14,13 @@ val TransformAstForNestedUpdates<'a> : lid: LongIdent -> exprBeingAssigned: SynExpr -> withExpr: SynExpr * (range * 'a) -> - (Ident list * Ident) * SynExpr option + (Ident list * Ident) * SynExpr val BindIdText: string -val inline (|IsSimpleOrBoundExpr|_|): withExprOpt: (SynExpr * BlockSeparator) option -> bool +val inline (|IsSimpleOrBoundExpr|_|): withExpr: SynExpr -> bool val BindOriginalRecdExpr: withExpr: SynExpr * BlockSeparator -> mkRecdExpr: ((SynExpr * BlockSeparator) option -> SynExpr) -> SynExpr + +val bindSrcIn: spreadSrcExpr: SynExpr -> ((SynExpr -> SynExpr) -> SynExpr) diff --git a/src/Compiler/Checking/ConstraintSolver.fs b/src/Compiler/Checking/ConstraintSolver.fs index ca4fe23ae79..dda55156397 100644 --- a/src/Compiler/Checking/ConstraintSolver.fs +++ b/src/Compiler/Checking/ConstraintSolver.fs @@ -1161,7 +1161,7 @@ and SolveTyparEqualsType (csenv: ConstraintSolverEnv) ndeep m2 (trace: OptionalT } // Like SolveTyparEqualsType but asserts all typar equalities simultaneously instead of one by one -and SolveTyparsEqualTypes (csenv: ConstraintSolverEnv) ndeep m2 (trace: OptionalTrace) tpTys tys = +and SolveTyparsEqualTypesAux (csenv: ConstraintSolverEnv) ndeep m2 (trace: OptionalTrace) tpTys tys = trackErrors { do! Iterate2D ( fun tpTy ty -> @@ -4340,7 +4340,7 @@ let CodegenWitnessesForTyparInst tcVal g amap m typars tyargs = let csenv = MakeConstraintSolverEnv ContextInfo.NoContext css m (DisplayEnv.Empty g) let ftps, _renaming, tinst = FreshenTypeInst g m typars let traitInfos = GetTraitConstraintInfosOfTypars g ftps - let! _res = SolveTyparsEqualTypes csenv 0 m NoTrace tinst tyargs + let! _res = SolveTyparsEqualTypesAux csenv 0 m NoTrace tinst tyargs return GenWitnessArgs amap g m traitInfos } @@ -4418,3 +4418,8 @@ let IsApplicableMethApprox g amap m (minfo: MethInfo) availObjTy = | _ -> true else true + +let SolveTyparsEqualTypes g (css: ConstraintSolverState) m (typars: TypeInst) (tys: TypeInst) = + let csenv = MakeConstraintSolverEnv ContextInfo.NoContext css m (DisplayEnv.Empty g) + SolveTyparsEqualTypesAux csenv 0 m NoTrace typars tys + |> CommitOperationResult diff --git a/src/Compiler/Checking/ConstraintSolver.fsi b/src/Compiler/Checking/ConstraintSolver.fsi index eebd72c2e60..ec9cd0d515f 100644 --- a/src/Compiler/Checking/ConstraintSolver.fsi +++ b/src/Compiler/Checking/ConstraintSolver.fsi @@ -380,3 +380,6 @@ val ChooseTyparSolutionAndSolve: ConstraintSolverState -> DisplayEnv -> Typar -> val IsApplicableMethApprox: TcGlobals -> ImportMap -> range -> MethInfo -> TType -> bool val CanonicalizePartialInferenceProblem: ConstraintSolverState -> DisplayEnv -> range -> Typars -> unit + +val SolveTyparsEqualTypes: + g: TcGlobals -> css: ConstraintSolverState -> m: range -> typars: TypeInst -> tys: TypeInst -> unit diff --git a/src/Compiler/Checking/Expressions/CheckExpressions.fs b/src/Compiler/Checking/Expressions/CheckExpressions.fs index b3fa0965216..cb4543e7498 100644 --- a/src/Compiler/Checking/Expressions/CheckExpressions.fs +++ b/src/Compiler/Checking/Expressions/CheckExpressions.fs @@ -659,31 +659,6 @@ let UnifyTupleTypeAndInferCharacteristics contextInfo (cenv: cenv) denv m knownT AddCxTypeEqualsType contextInfo denv cenv.css m knownTy ty2 tupInfo, ptys -// Allow inference of assembly-affinity and structness from the known type - even from another assembly. This is a rule of -// the language design and allows effective cross-assembly use of anonymous types in some limited circumstances. -let UnifyAnonRecdTypeAndInferCharacteristics contextInfo (cenv: cenv) denv m ty isExplicitStruct unsortedNames = - let g = cenv.g - let anonInfo, ptys = - match tryDestAnonRecdTy g ty with - | ValueSome (anonInfo, ptys) -> - // Note: use the assembly of the known type, not the current assembly - // Note: use the structness of the known type, unless explicit - // Note: use the names of our type, since they are always explicit - let tupInfo = (if isExplicitStruct then tupInfoStruct else anonInfo.TupInfo) - let anonInfo = AnonRecdTypeInfo.Create(anonInfo.Assembly, tupInfo, unsortedNames) - let ptys = - if List.length ptys = Array.length unsortedNames then ptys - else NewInferenceTypes g (Array.toList anonInfo.SortedNames) - anonInfo, ptys - | ValueNone -> - // Note: no known anonymous record type - use our assembly - let anonInfo = AnonRecdTypeInfo.Create(cenv.thisCcu, mkTupInfo isExplicitStruct, unsortedNames) - anonInfo, NewInferenceTypes g (Array.toList anonInfo.SortedNames) - let ty2 = TType_anon (anonInfo, ptys) - AddCxTypeEqualsType contextInfo denv cenv.css m ty ty2 - anonInfo, ptys - - /// Optimized unification routine that avoids creating new inference /// variables unnecessarily let UnifyFunctionTypeUndoIfFailed (cenv: cenv) denv m ty = @@ -2000,24 +1975,23 @@ let CheckRecdExprDuplicateFields (elems: Ident list) = //------------------------------------------------------------------------- /// Helper used to check record expressions and record patterns -let BuildFieldMap (cenv: cenv) env isPartial ty (flds: ((Ident list * Ident) * 'T) list) m = +let BuildFieldMap (cenv: cenv) env isPartial ty (flds: (Ident * ExplicitOrSpread) list) m = let g = cenv.g let ad = env.eAccessRights - let allFields = flds |> List.map (fun ((_, ident), _) -> ident) - if allFields.Length > 1 then - // In the case of nested record fields on the same level in record copy-and-update. - // We need to reverse the list to get the correct order of fields. - let idents = if isPartial then allFields |> List.rev else allFields - CheckRecdExprDuplicateFields idents + let allFields = flds |> List.map (fun (ident, _) -> ident) let fldResolutions = flds - |> List.choose (fun (fld, fldExpr) -> + |> List.choose (fun (fldId, fld) -> try - let fldPath, fldId = fld - let frefSet = ResolveField cenv.tcSink cenv.nameResolver env.eNameResEnv ad ty fldPath fldId allFields - Some(fld, frefSet, fldExpr) + let fldExpr, fldInfo = + match fld with + | ExplicitOrSpread.Explicit (path, fldExpr) -> ExplicitOrSpread.Explicit fldExpr, ExplicitOrSpread.Explicit (path, fldId) + | ExplicitOrSpread.Spread fldExpr -> ExplicitOrSpread.Spread fldExpr, ExplicitOrSpread.Spread fldId + + ResolveField cenv.tcSink cenv.nameResolver env.eNameResEnv ad ty fldInfo allFields + |> Option.map (fun frefSet -> fldId, frefSet, fldExpr) with e -> errorRecoveryNoRange e None @@ -2051,7 +2025,7 @@ let BuildFieldMap (cenv: cenv) env isPartial ty (flds: ((Ident list * Ident) * ' rfinfo1.TypeInst, rfinfo1.TyconRef let fldsmap, rfldsList = - ((Map.empty, []), fldResolutions) ||> List.fold (fun (fs, rfldsList) ((_, ident), frefs, fldExpr) -> + ((Map.empty, []), fldResolutions) ||> List.fold (fun (fs, rfldsList) (ident, frefs, fldExpr) -> match frefs |> List.filter (fun (FieldResolution(rfinfo2, _)) -> tyconRefEq g tcref rfinfo2.TyconRef) with | [FieldResolution(rfinfo2, showDeprecated)] -> @@ -6095,11 +6069,33 @@ and TcExprUndelayed (cenv: cenv) (overallTy: OverallTy) env tpenv (synExpr: SynE | SynExpr.AnonRecd (isStruct, withExprOpt, unsortedFieldExprs, mWholeExpr, trivia) -> match withExprOpt with - | None | IsSimpleOrBoundExpr -> - TcNonControlFlowExpr env <| fun env -> - TcPossiblyPropagatingExprLeafThenConvert (fun ty -> isAnonRecdTy g ty || isTyparTy g ty) cenv overallTy env mWholeExpr (fun overallTy -> - TcAnonRecdExpr cenv overallTy env tpenv (isStruct, withExprOpt, unsortedFieldExprs, mWholeExpr) - ) + | None | Some (IsSimpleOrBoundExpr, _) -> + let anySpreadsNotSimpleOrBound = + unsortedFieldExprs + |> List.exists (function + | SynExprAnonRecordFieldOrSpread.Field _ + | SynExprAnonRecordFieldOrSpread.Spread (SynExprSpread (expr = IsSimpleOrBoundExpr), _) -> false + | SynExprAnonRecordFieldOrSpread.Spread _ -> true) + + if anySpreadsNotSimpleOrBound then + let rec loop unsortedFieldExprs cont = + match unsortedFieldExprs with + | [] -> cont [] + | (SynExprAnonRecordFieldOrSpread.Field _ as fieldOrSpread) :: unsortedFieldExprs + | (SynExprAnonRecordFieldOrSpread.Spread (SynExprSpread (expr = IsSimpleOrBoundExpr), _) as fieldOrSpread) :: unsortedFieldExprs -> + loop unsortedFieldExprs (cont << fun fields -> fieldOrSpread :: fields) + | SynExprAnonRecordFieldOrSpread.Spread (SynExprSpread (spreadRange, spreadExpr, m), maybeBlockSep) :: unsortedFieldExprs -> + bindSrcIn spreadExpr (fun spreadExpr -> + loop unsortedFieldExprs (cont << fun fields -> + SynExprAnonRecordFieldOrSpread.Spread (SynExprSpread (spreadRange, spreadExpr, m), maybeBlockSep) :: fields)) + + let wrappedExpr = loop unsortedFieldExprs (fun synRecdFields -> SynExpr.AnonRecd (isStruct, withExprOpt, synRecdFields, mWholeExpr, trivia)) + TcExpr cenv overallTy env tpenv wrappedExpr + else + TcNonControlFlowExpr env <| fun env -> + TcPossiblyPropagatingExprLeafThenConvert (fun ty -> isAnonRecdTy g ty || isTyparTy g ty) cenv overallTy env mWholeExpr (fun overallTy -> + TcAnonRecdExpr cenv overallTy env tpenv (isStruct, withExprOpt, unsortedFieldExprs, mWholeExpr) + ) | Some withExpr -> BindOriginalRecdExpr withExpr (fun withExpr -> SynExpr.AnonRecd (isStruct, withExpr, unsortedFieldExprs, mWholeExpr, trivia)) |> TcExpr cenv overallTy env tpenv @@ -6134,9 +6130,31 @@ and TcExprUndelayed (cenv: cenv) (overallTy: OverallTy) env tpenv (synExpr: SynE | SynExpr.Record (inherits, withExprOpt, synRecdFields, mWholeExpr) -> match withExprOpt with - | None | IsSimpleOrBoundExpr -> - TcNonControlFlowExpr env <| fun env -> - TcExprRecord cenv overallTy env tpenv (inherits, withExprOpt, synRecdFields, mWholeExpr) + | None | Some (IsSimpleOrBoundExpr, _) -> + let anySpreadsNotSimpleOrBound = + synRecdFields + |> List.exists (function + | SynExprRecordFieldOrSpread.Field _ + | SynExprRecordFieldOrSpread.Spread (SynExprSpread (expr = IsSimpleOrBoundExpr), _) -> false + | SynExprRecordFieldOrSpread.Spread _ -> true) + + if anySpreadsNotSimpleOrBound then + let rec loop synRecdFields cont = + match synRecdFields with + | [] -> cont [] + | (SynExprRecordFieldOrSpread.Field _ as fieldOrSpread) :: synRecdFields + | (SynExprRecordFieldOrSpread.Spread (SynExprSpread (expr = IsSimpleOrBoundExpr), _) as fieldOrSpread) :: synRecdFields -> + loop synRecdFields (cont << fun fields -> fieldOrSpread :: fields) + | SynExprRecordFieldOrSpread.Spread (SynExprSpread (spreadRange, spreadExpr, m), maybeBlockSep) :: synRecdFields -> + bindSrcIn spreadExpr (fun spreadExpr -> + loop synRecdFields (cont << fun fields -> + SynExprRecordFieldOrSpread.Spread (SynExprSpread (spreadRange, spreadExpr, m), maybeBlockSep) :: fields)) + + let wrappedExpr = loop synRecdFields (fun synRecdFields -> SynExpr.Record (inherits, withExprOpt, synRecdFields, mWholeExpr)) + TcExpr cenv overallTy env tpenv wrappedExpr + else + TcNonControlFlowExpr env <| fun env -> + TcExprRecord cenv overallTy env tpenv (inherits, withExprOpt, synRecdFields, mWholeExpr) | Some withExpr -> BindOriginalRecdExpr withExpr (fun withExpr -> SynExpr.Record (inherits, withExpr, synRecdFields, mWholeExpr)) |> TcExpr cenv overallTy env tpenv @@ -6491,6 +6509,13 @@ and TcExprRecord (cenv: cenv) overallTy env tpenv (inherits, withExprOpt, synRec let g = cenv.g CallExprHasTypeSink cenv.tcSink (mWholeExpr, env.NameEnv, overallTy.Commit, env.AccessRights) let requiresCtor = (GetCtorShapeCounter env = 1) // Get special expression forms for constructors + + if requiresCtor then + for fieldOrSpread in synRecdFields do + match fieldOrSpread with + | SynExprRecordFieldOrSpread.Spread (SynExprSpread (spreadRange = m), _) -> errorR (Error (FSComp.SR.parsSpreadNotSupported (), m)) + | SynExprRecordFieldOrSpread.Field _ -> () + let haveCtor = Option.isSome inherits TcPossiblyPropagatingExprLeafThenConvert (fun ty -> requiresCtor || haveCtor || isRecdTy g ty || isTyparTy g ty) cenv overallTy env mWholeExpr (fun overallTy -> TcRecdExpr cenv overallTy env tpenv (inherits, withExprOpt, synRecdFields, mWholeExpr) @@ -7099,7 +7124,7 @@ and TcCtorCall isNaked cenv env tpenv (overallTy: OverallTy) objTy mObjTyOpt ite error(Error(FSComp.SR.tcSyntaxCanOnlyBeUsedToCreateObjectTypes(if superInit then "inherit" else "new"), mWholeCall)) // Check a record construction expression -and TcRecordConstruction (cenv: cenv) (overallTy: TType) isObjExpr env tpenv withExprInfoOpt objTy fldsList m = +and TcRecordConstruction (cenv: cenv) (overallTy: TType) isObjExpr env tpenv withExprInfoOpt (spreadSrcs : (Expr -> Expr) list) objTy fldsList m = let g = cenv.g let tcref, tinst = destAppTy g objTy @@ -7112,24 +7137,44 @@ and TcRecordConstruction (cenv: cenv) (overallTy: TType) isObjExpr env tpenv wit errorR(Error(FSComp.SR.tcConstructorRequiresCall(tycon.DisplayName), m)) let fspecs = tycon.TrueInstanceFieldsAsList - // Freshen types and work out their subtype flexibility - let fldsList = - [ for fname, fexpr in fldsList do - let fspec = - try - fspecs |> List.find (fun fspec -> fspec.LogicalName = fname) - with :? KeyNotFoundException -> - error (Error(FSComp.SR.tcUndefinedField(fname, NicePrint.minimalStringOfType env.DisplayEnv objTy), m)) - let fty = actualTyOfRecdFieldForTycon tycon tinst fspec - let flex = not (isTyparTy g fty) - yield (fname, fexpr, fty, flex) ] + // Freshen types and work out their subtype flexibility // Type check and generalize the supplied bindings let fldsList, tpenv = let env = { env with eContextInfo = ContextInfo.RecordFields } - (tpenv, fldsList) ||> List.mapFold (fun tpenv (fname, fexpr, fty, flex) -> - let fieldExpr, tpenv = TcExprFlex cenv flex false fty env tpenv fexpr - (fname, fieldExpr), tpenv) + let rec tcFields checkedFields tpenv fields = + match fields with + | [] -> List.rev checkedFields, tpenv + | (fname, ExplicitOrSpread.Explicit fexpr) :: fields -> + let checkedFields, tpenv = + fspecs + |> List.tryFind (fun fspec -> fspec.LogicalName = fname) + |> Option.map (fun fspec -> + let fty = actualTyOfRecdFieldForTycon tycon tinst fspec + let flex = not (isTyparTy g fty) + let fieldExpr, tpenv = TcExprFlex cenv flex false fty env tpenv fexpr + (fname, fieldExpr) :: checkedFields, tpenv) + |> Option.defaultWith (fun () -> + error (Error(FSComp.SR.tcUndefinedField(fname, NicePrint.minimalStringOfType env.DisplayEnv objTy), m))) + + tcFields checkedFields tpenv fields + + | (fname, ExplicitOrSpread.Spread (ty, spreadValue)) :: fields -> + let checkedFields = + fspecs + |> List.tryPick (fun fspec -> + if fspec.LogicalName = fname then + let fty = actualTyOfRecdFieldForTycon tycon tinst fspec + let overallTy = MustConvertTo (false, fty) + UnifyOverallType cenv env m overallTy ty + let fieldExpr = TcAdjustExprForTypeDirectedConversions cenv overallTy ty env m spreadValue + Some ((fname, mkCoerceIfNeeded g fty (tyOfExpr g fieldExpr) fieldExpr) :: checkedFields) + else None) + |> Option.defaultValue checkedFields // We ignore extra fields from spreads. + + tcFields checkedFields tpenv fields + + tcFields [] tpenv fldsList // Add rebindings for unbound field when an "old value" is available // Effect order: mutable fields may get modified by other bindings... @@ -7189,16 +7234,20 @@ and TcRecordConstruction (cenv: cenv) (overallTy: TType) isObjExpr env tpenv wit let expr = mkRecordExpr g (GetRecdInfo env, tcref, tinst, rfrefs, args, m) let expr = - match withExprInfoOpt with - | None -> - // '{ recd fields }'. // - expr + let locals = + [ + match withExprInfoOpt with + | None -> id + | Some (withExpr, withExprAddrVal, _) -> + // '{ recd with fields }'. + // Assign the first object to a tmp and then construct + let wrap, oldaddr, _readonly, _writeonly = mkExprAddrOfExpr g tycon.IsStructOrEnumTycon false NeverMutates withExpr None m + fun expr -> wrap (mkCompGenLet m withExprAddrVal oldaddr expr) - | Some (withExpr, withExprAddrVal, _) -> - // '{ recd with fields }'. - // Assign the first object to a tmp and then construct - let wrap, oldaddr, _readonly, _writeonly = mkExprAddrOfExpr g tycon.IsStructOrEnumTycon false NeverMutates withExpr None m - wrap (mkCompGenLet m withExprAddrVal oldaddr expr) + yield! spreadSrcs + ] + + (locals, expr) ||> List.foldBack (fun local expr -> local expr) expr, tpenv @@ -7490,10 +7539,11 @@ and TcObjectExpr (cenv: cenv) env tpenv (objTy, realObjTy, argopt, binds, extraI let fldsList = binds |> List.map (fun b -> match BindingNormalization.NormalizeBinding ObjExprBinding cenv env b with - | NormalizedBinding (_, _, _, _, [], _, _, _, SynPat.Named(SynIdent(id,_), _, _, _), NormalizedBindingRhs(_, _, rhsExpr), _, _) -> id.idText, rhsExpr + | NormalizedBinding (_, _, _, _, [], _, _, _, SynPat.Named(SynIdent(id,_), _, _, _), NormalizedBindingRhs(_, _, rhsExpr), _, _) -> id.idText, ExplicitOrSpread.Explicit rhsExpr | _ -> error(Error(FSComp.SR.tcOnlySimpleBindingsCanBeUsedInConstructionExpressions(), b.RangeOfBindingWithoutRhs))) - TcRecordConstruction cenv objTy true env tpenv None objTy fldsList mWholeExpr + let spreadSrcs = [] + TcRecordConstruction cenv objTy true env tpenv None spreadSrcs objTy fldsList mWholeExpr else // object expression construction e.g. { new A() with ... } or { new IA with ... } let ctorCall, baseIdOpt, tpenv = @@ -8005,6 +8055,7 @@ and TcAssertExpr cenv overallTy env (m: range) tpenv x = and TcRecdExpr cenv overallTy env tpenv (inherits, withExprOpt, synRecdFields, mWholeExpr) = CallExprHasTypeSink cenv.tcSink (mWholeExpr, env.NameEnv, overallTy, env.eAccessRights) let g = cenv.g + let ad = env.eAccessRights let requiresCtor = (GetCtorShapeCounter env = 1) // Get special expression forms for constructors let haveCtor = Option.isSome inherits @@ -8021,27 +8072,24 @@ and TcRecdExpr cenv overallTy env tpenv (inherits, withExprOpt, synRecdFields, m let hasOrigExpr = withExprOptChecked.IsSome - let fldsList = - let flds = - synRecdFields - |> List.map (fun (SynExprRecordField (fieldName = (synLongId, isOk); expr = exprBeingAssigned)) -> - // if we met at least one field that is not syntactically correct - raise ReportedError to transfer control to the recovery routine - if not isOk then - // raising ReportedError None transfers control to the closest errorRecovery point but do not make any records into log - // we assume that parse errors were already reported - raise (ReportedError None) - - match withExprOpt, synLongId.LongIdent, exprBeingAssigned with - | _, [ id ], _ -> ([], id), exprBeingAssigned - | Some withExpr, lid, Some exprBeingAssigned -> TransformAstForNestedUpdates cenv env overallTy lid exprBeingAssigned withExpr - | _ -> List.frontAndBack synLongId.LongIdent, exprBeingAssigned) - - let flds = if hasOrigExpr then GroupUpdatesToNestedFields flds else flds + let spreadSrcs, fldsList, tpenv = + let spreadSrcTys, spreadSrcs, flds = + Spreads.Values.Records.check + TcExprFlex + g + env + cenv + tpenv + ad + mWholeExpr + withExprOpt + overallTy + synRecdFields + // Check if the overall type is an anon record type and if so raise an copy-update syntax error // let f (r: {| A: int; C: int |}) = { r with A = 1; B = 2; C = 3 } if isAnonRecdTy cenv.g overallTy || isStructAnonRecdTy cenv.g overallTy then - for fld, _ in flds do - let _, fldId = fld + for fldId, _ in flds do match TryFindAnonRecdFieldOfType g overallTy fldId.idText with | Some item -> CallNameResolutionSink cenv.tcSink (fldId.idRange, env.eNameResEnv, item, emptyTyparInst, ItemOccurrence.UseInType, env.eAccessRights) @@ -8052,30 +8100,42 @@ and TcRecdExpr cenv overallTy env tpenv (inherits, withExprOpt, synRecdFields, m // Use the right } in the expression let lastPartRange = withStartEnd (mkPos mWholeExpr.StartLine (mWholeExpr.EndColumn - 1)) (mkPos mWholeExpr.StartLine mWholeExpr.EndColumn) mWholeExpr errorR(Error(FSComp.SR.chkCopyUpdateSyntaxInAnonRecords(), lastPartRange)) - [] + [], [], tpenv else // If the overall type is a record type build a map of the fields - match flds with - | [] -> [] - | _ -> - match BuildFieldMap cenv env hasOrigExpr overallTy flds mWholeExpr with - | None -> [] - | Some(tinst, tcref, _, fldsList) -> + let fieldMap = + match flds with + | [] -> [] + | _ -> + let tcrefs = + spreadSrcTys + |> List.choose (tryTcrefOfAppTy g >> ValueOption.toOption) + + let env = { env with eNameResEnv = (env.eNameResEnv, tcrefs) ||> AddTyconRefsToNameEnv BulkAdd.Yes false g cenv.amap ad mWholeExpr false } + + match BuildFieldMap cenv env hasOrigExpr overallTy flds mWholeExpr with + | None -> [] + | Some(tinst, tcref, _, fldsList) -> - let gtyp = mkWoNullAppTy tcref tinst - UnifyTypes cenv env mWholeExpr overallTy gtyp + let gtyp = mkWoNullAppTy tcref tinst + UnifyTypes cenv env mWholeExpr overallTy gtyp - // (#15290) For copy-and-update expressions, register the record type as a related symbol - // so that "Find All References" on the record type includes copy-and-update usages. - // Reported via CallRelatedSymbolSink to avoid affecting colorization or symbol info. - if hasOrigExpr then - let item = Item.Types(tcref.DisplayName, [gtyp]) - CallRelatedSymbolSink cenv.tcSink (mWholeExpr, item, RelatedSymbolUseKind.CopyAndUpdateRecord) + // (#15290) For copy-and-update expressions, register the record type as a related symbol + // so that "Find All References" on the record type includes copy-and-update usages. + // Reported via CallRelatedSymbolSink to avoid affecting colorization or symbol info. + if hasOrigExpr then + let item = Item.Types(tcref.DisplayName, [gtyp]) + CallRelatedSymbolSink cenv.tcSink (mWholeExpr, item, RelatedSymbolUseKind.CopyAndUpdateRecord) - [ for n, v in fldsList do - match v with - | Some v -> yield n, v - | None -> () ] + [ + for fldId, fld in fldsList do + match fld with + | ExplicitOrSpread.Explicit None -> () + | ExplicitOrSpread.Explicit (Some fieldExpr) -> fldId, ExplicitOrSpread.Explicit fieldExpr + | ExplicitOrSpread.Spread spread -> fldId, ExplicitOrSpread.Spread spread + ] + + spreadSrcs, fieldMap, tpenv let withExprInfoOpt = match withExprOptChecked with @@ -8121,7 +8181,7 @@ and TcRecdExpr cenv overallTy env tpenv (inherits, withExprOpt, synRecdFields, m SolveTypeAsError env.DisplayEnv cenv.css mWholeExpr overallTy mkDefault (mWholeExpr, overallTy), tpenv else - let expr, tpenv = TcRecordConstruction cenv overallTy false env tpenv withExprInfoOpt overallTy fldsList mWholeExpr + let expr, tpenv = TcRecordConstruction cenv overallTy false env tpenv withExprInfoOpt spreadSrcs overallTy fldsList mWholeExpr let expr = match superInitExprOpt with @@ -8130,12 +8190,6 @@ and TcRecdExpr cenv overallTy env tpenv (inherits, withExprOpt, synRecdFields, m | None -> expr expr, tpenv -and CheckAnonRecdExprDuplicateFields (elems: Ident array) = - elems |> Array.iteri (fun i (uc1: Ident) -> - elems |> Array.iteri (fun j (uc2: Ident) -> - if j > i && uc1.idText = uc2.idText then - errorR(Error (FSComp.SR.tcAnonRecdDuplicateFieldId(uc1.idText), uc1.idRange)))) - // Check '{| .... |}' and TcAnonRecdExpr cenv (overallTy: TType) env tpenv (isStruct, optOrigSynExpr, unsortedFieldIdsAndSynExprsGiven, mWholeExpr) = match optOrigSynExpr with @@ -8146,7 +8200,10 @@ and TcAnonRecdExpr cenv (overallTy: TType) env tpenv (isStruct, optOrigSynExpr, // Ideally we should also check for duplicate field IDs in the TcCopyAndUpdateAnonRecdExpr case, but currently the logic is too complex to guarantee a proper error reporting // So here we error instead errorR to avoid cascading internal errors unsortedFieldIdsAndSynExprsGiven - |> List.countBy (fun (fId, _, _) -> textOfLid fId.LongIdent) + |> List.choose (function + | SynExprAnonRecordFieldOrSpread.Field (SynExprAnonRecordField (fieldName = SynLongIdent (name, _, _)), _) -> Some name + | SynExprAnonRecordFieldOrSpread.Spread _ -> (* Spreads are allowed to shadow fields. *) None) + |> List.countBy textOfLid |> List.iter (fun (label, count) -> if count > 1 then error (Error (FSComp.SR.tcAnonRecdDuplicateFieldId(label), mWholeExpr))) @@ -8155,39 +8212,74 @@ and TcAnonRecdExpr cenv (overallTy: TType) env tpenv (isStruct, optOrigSynExpr, and TcNewAnonRecdExpr cenv (overallTy: TType) env tpenv (isStruct, unsortedFieldIdsAndSynExprsGiven, mWholeExpr) = let g = cenv.g - let unsortedFieldSynExprsGiven = unsortedFieldIdsAndSynExprsGiven |> List.map (fun (_, _, fieldExpr) -> fieldExpr) - let unsortedFieldIds = unsortedFieldIdsAndSynExprsGiven |> List.map (fun (synLongIdent, _, _) -> synLongIdent.LongIdent[0]) |> List.toArray - let anonInfo, sortedFieldTys = UnifyAnonRecdTypeAndInferCharacteristics env.eContextInfo cenv env.DisplayEnv mWholeExpr overallTy isStruct unsortedFieldIds - - if unsortedFieldIds.Length > 1 then - CheckAnonRecdExprDuplicateFields unsortedFieldIds - - // Sort into canonical order - let sortedIndexedArgs = - unsortedFieldIdsAndSynExprsGiven - |> List.indexed - |> List.sortBy (fun (i,_) -> unsortedFieldIds[i].idText) - - // Map from sorted indexes to unsorted indexes - let sigma = sortedIndexedArgs |> List.map fst |> List.toArray - let sortedFieldExprs = sortedIndexedArgs |> List.map snd - - sortedFieldExprs |> List.iteri (fun j (synLongIdent, _, _) -> - let m = rangeOfLid synLongIdent.LongIdent - let item = Item.AnonRecdField(anonInfo, sortedFieldTys, j, m) - CallNameResolutionSink cenv.tcSink (m, env.NameEnv, item, emptyTyparInst, ItemOccurrence.Use, env.eAccessRights)) - - let unsortedFieldTys = - sortedFieldTys - |> List.indexed - |> List.sortBy (fun (sortedIdx, _) -> sigma[sortedIdx]) - |> List.map snd + let ad = env.eAccessRights - let flexes = unsortedFieldTys |> List.map (fun _ -> true) + let maybeAnonRecdTargetTy = tryDestAnonRecdTy g overallTy + + let spreadSrcs, unsortedFields, anonInfo, tpenv = + let spreadSrcs, fieldIdsInAlphabeticalOrder, fieldTysInAlphabeticalOrder, fieldsInSrcOrder = + Spreads.Values.AnonymousRecords.check + TcExprFlex + TcAdjustExprForTypeDirectedConversions + MustConvertTo + UnifyOverallType + ignore + g + env + cenv + tpenv + ad + mWholeExpr + maybeAnonRecdTargetTy + None + overallTy + unsortedFieldIdsAndSynExprsGiven + + // Unify the overall ty with the inferred target anonymous record type. + let anonInfo, sortedFieldTys = + let anonInfo, sortedFieldTys = + let unsortedNames = + fieldsInSrcOrder + |> List.map (fun (fieldId, _, _) -> fieldId) + |> List.toArray + + match maybeAnonRecdTargetTy with + | ValueSome (anonInfo, _) -> + // Note: use the assembly of the known type, not the current assembly + // Note: use the structness of the known type, unless explicit + // Note: use the names of our type, since they are always explicit + let tupInfo = if isStruct then tupInfoStruct else anonInfo.TupInfo + let anonInfo = AnonRecdTypeInfo.Create(anonInfo.Assembly, tupInfo, unsortedNames) + anonInfo, fieldTysInAlphabeticalOrder + | ValueNone -> + // Note: no known anonymous record type - use our assembly + let anonInfo = AnonRecdTypeInfo.Create(cenv.thisCcu, mkTupInfo isStruct, unsortedNames) + anonInfo, fieldTysInAlphabeticalOrder + let ty2 = TType_anon (anonInfo, sortedFieldTys) + AddCxTypeEqualsType env.eContextInfo env.DisplayEnv cenv.css mWholeExpr overallTy ty2 + anonInfo, sortedFieldTys + + // All sorted field identifiers, including potential duplicates. + let sortedNames = fieldIdsInAlphabeticalOrder + + // Call name resolution. + sortedNames + |> List.iteri (fun j fieldName -> + let m = fieldName.idRange + let item = Item.AnonRecdField(anonInfo, sortedFieldTys, j, m) + CallNameResolutionSink cenv.tcSink (m, env.NameEnv, item, emptyTyparInst, ItemOccurrence.Use, env.eAccessRights)) + + spreadSrcs, fieldsInSrcOrder, anonInfo, tpenv + + let unsortedNames = [| for fieldName, _, _ in unsortedFields -> fieldName |] + let unsortedTys = [ for _, fieldTy, _ in unsortedFields -> fieldTy ] + let unsortedExprs = [ for _, _, tcField in unsortedFields -> tcField () ] - let unsortedCheckedArgs, tpenv = TcExprsWithFlexes cenv env mWholeExpr tpenv flexes unsortedFieldTys unsortedFieldSynExprsGiven + let expr = + (spreadSrcs, mkAnonRecd g mWholeExpr anonInfo unsortedNames unsortedExprs unsortedTys) + ||> List.foldBack (fun wrap expr -> wrap expr) - mkAnonRecd g mWholeExpr anonInfo unsortedFieldIds unsortedCheckedArgs unsortedFieldTys, tpenv + expr, tpenv and TcCopyAndUpdateAnonRecdExpr cenv (overallTy: TType) env tpenv (isStruct, (origExpr, blockSeparator), unsortedFieldIdsAndSynExprsGiven, mWholeExpr) = // The fairly complex case '{| origExpr with X = 1; Y = 2 |}' @@ -8200,6 +8292,7 @@ and TcCopyAndUpdateAnonRecdExpr cenv (overallTy: TType) env tpenv (isStruct, (or // Unlike in the case of record type copy-and-update {| a with X = 1 |} does not force a.X to exist or have had type 'int' let g = cenv.g + let ad = env.eAccessRights let origExprTy = NewInferenceType g let origExprChecked, tpenv = TcExpr cenv (MustEqual origExprTy) env tpenv origExpr let oldv, oldve = mkCompGenLocal mWholeExpr "inputRecord" origExprTy @@ -8208,17 +8301,27 @@ and TcCopyAndUpdateAnonRecdExpr cenv (overallTy: TType) env tpenv (isStruct, (or if not (isAppTy g origExprTy || isAnonRecdTy g origExprTy) then error (Error (FSComp.SR.tcCopyAndUpdateNeedsRecordType(), mOrigExpr)) - // Expand expressions with respect to potential nesting - let unsortedFieldIdsAndSynExprsGiven = - unsortedFieldIdsAndSynExprsGiven - |> List.map (fun (synLongIdent, _, exprBeingAssigned) -> - match synLongIdent.LongIdent with - | [] -> error(Error(FSComp.SR.nrUnexpectedEmptyLongId(), mWholeExpr)) - | [ id ] -> ([], id), Some exprBeingAssigned - | lid -> TransformAstForNestedUpdates cenv env origExprTy lid exprBeingAssigned (origExpr, blockSeparator)) - |> GroupUpdatesToNestedFields - - let unsortedFieldSynExprsGiven = unsortedFieldIdsAndSynExprsGiven |> List.choose snd + let maybeAnonRecdTargetTy = tryDestAnonRecdTy g overallTy + + // Collect explicitly-defined fields and fields from spreads + // and expand expressions with respect to potential nesting. + let spreadSrcs, _fieldIdsInAlphabeticalOrder, _fieldTysInAlphabeticalOrder, fieldsInSrcOrder = + Spreads.Values.AnonymousRecords.check + TcExprFlex + TcAdjustExprForTypeDirectedConversions + MustConvertTo + UnifyOverallType + (fun m -> errorR (Error (FSComp.SR.tcRecordExprSpreadWithCannotBeUsedWithSpreads (), m))) + g + env + cenv + tpenv + ad + mWholeExpr + maybeAnonRecdTargetTy + (Some (origExpr, blockSeparator)) + origExprTy + unsortedFieldIdsAndSynExprsGiven let origExprIsStruct = match tryDestAnonRecdTy g origExprTy with @@ -8235,37 +8338,59 @@ and TcCopyAndUpdateAnonRecdExpr cenv (overallTy: TType) env tpenv (isStruct, (or /// - Choice2Of2 for a binding coming from the original expression let unsortedIdAndExprsAll = [| - for (_, id), e in unsortedFieldIdsAndSynExprsGiven do - yield (id, Choice1Of2 e) + for id, ty, tcField in fieldsInSrcOrder do + yield (id, ty, Choice1Of2 tcField) + match tryDestAnonRecdTy g origExprTy with | ValueSome (anonInfo, tinst) -> for i, id in Array.indexed anonInfo.SortedIds do - yield id, Choice2Of2 (mkAnonRecdFieldGetViaExprAddr (anonInfo, oldveaddr, tinst, i, mOrigExpr)) + yield id, NewInferenceType g, Choice2Of2 (mkAnonRecdFieldGetViaExprAddr (anonInfo, oldveaddr, tinst, i, mOrigExpr)) | ValueNone -> match tryAppTy g origExprTy with | ValueSome(tcref, tinst) when tcref.IsRecordTycon -> let fspecs = tcref.Deref.TrueInstanceFieldsAsList for fspec in fspecs do - yield fspec.Id, Choice2Of2 (mkRecdFieldGetViaExprAddr (oldveaddr, tcref.MakeNestedRecdFieldRef fspec, tinst, mOrigExpr)) + yield fspec.Id, NewInferenceType g, Choice2Of2 (mkRecdFieldGetViaExprAddr (oldveaddr, tcref.MakeNestedRecdFieldRef fspec, tinst, mOrigExpr)) | _ -> error (Error (FSComp.SR.tcCopyAndUpdateNeedsRecordType(), mOrigExpr)) |] - |> Array.distinctBy (fst >> textOfId) + |> Array.distinctBy (fun (fieldId, _, _) -> textOfId fieldId) - let unsortedFieldIdsAll = Array.map fst unsortedIdAndExprsAll + let unsortedFieldIdsAll = [|for fieldId, _, _ in unsortedIdAndExprsAll -> fieldId|] - let anonInfo, sortedFieldTysAll = UnifyAnonRecdTypeAndInferCharacteristics env.eContextInfo cenv env.DisplayEnv mWholeExpr overallTy isStruct unsortedFieldIdsAll - - let sortedIndexedFieldsAll = unsortedIdAndExprsAll |> Array.indexed |> Array.sortBy (snd >> fst >> textOfId) + let sortedIndexedFieldsAll = unsortedIdAndExprsAll |> Array.indexed |> Array.sortBy (fun (_, (fieldId, _, _)) -> textOfId fieldId) // map from sorted indexes to unsorted indexes let sigma = Array.map fst sortedIndexedFieldsAll let sortedFieldsAll = Array.map snd sortedIndexedFieldsAll + // Unify the overall ty with the inferred target anonymous record type. + let anonInfo, sortedFieldTysAll = + let anonInfo = + let unsortedNames = unsortedFieldIdsAll + + match maybeAnonRecdTargetTy with + | ValueSome (anonInfo, _) -> + // Note: use the assembly of the known type, not the current assembly + // Note: use the structness of the known type, unless explicit + // Note: use the names of our type, since they are always explicit + let tupInfo = if isStruct then tupInfoStruct else anonInfo.TupInfo + let anonInfo = AnonRecdTypeInfo.Create(anonInfo.Assembly, tupInfo, unsortedNames) + anonInfo + | ValueNone -> + // Note: no known anonymous record type - use our assembly + let anonInfo = AnonRecdTypeInfo.Create(cenv.thisCcu, mkTupInfo isStruct, unsortedNames) + anonInfo + + let sortedFieldTysAll = [for _, ty, _ in sortedFieldsAll -> ty] + let ty2 = TType_anon (anonInfo, sortedFieldTysAll) + AddCxTypeEqualsType env.eContextInfo env.DisplayEnv cenv.css mWholeExpr overallTy ty2 + anonInfo, sortedFieldTysAll + // Report _all_ identifiers to name resolution. We should likely just report the ones // that are explicit in source code. - sortedFieldsAll |> Array.iteri (fun j (fieldId, expr) -> + sortedFieldsAll |> Array.iteri (fun j (fieldId, _, expr) -> match expr with | Choice1Of2 _ -> let item = Item.AnonRecdField(anonInfo, sortedFieldTysAll, j, fieldId.idRange) @@ -8278,33 +8403,21 @@ and TcCopyAndUpdateAnonRecdExpr cenv (overallTy: TType) env tpenv (isStruct, (or |> List.sortBy (fun (sortedIdx, _) -> sigma[sortedIdx]) |> List.map snd - let unsortedFieldTysGiven = - unsortedFieldTysAll - |> List.take unsortedFieldIdsAndSynExprsGiven.Length - - let flexes = unsortedFieldTysGiven |> List.map (fun _ -> true) - // Check the expressions in unsorted order - let unsortedFieldExprsGiven, tpenv = - TcExprsWithFlexes cenv env mWholeExpr tpenv flexes unsortedFieldTysGiven unsortedFieldSynExprsGiven - - let unsortedFieldExprsGiven = unsortedFieldExprsGiven |> List.toArray - - let unsortedFieldIds = - unsortedIdAndExprsAll - |> Array.map fst + let unsortedFieldExprsGiven = fieldsInSrcOrder |> List.map (fun (_, _, tcField) -> tcField ()) |> List.toArray + let unsortedFieldIds = unsortedFieldIdsAll let unsortedFieldExprs = unsortedIdAndExprsAll - |> Array.mapi (fun unsortedIdx (_, expr) -> + |> Array.mapi (fun unsortedIdx (_fieldId, ty, expr) -> match expr with | Choice1Of2 _ -> unsortedFieldExprsGiven[unsortedIdx] - | Choice2Of2 subExpr -> UnifyTypes cenv env mOrigExpr (tyOfExpr g subExpr) unsortedFieldTysAll[unsortedIdx]; subExpr) + | Choice2Of2 subExpr -> UnifyTypes cenv env mOrigExpr (tyOfExpr g subExpr) ty; subExpr) |> List.ofArray // Permute the expressions to sorted order in the TAST let expr = mkAnonRecd g mWholeExpr anonInfo unsortedFieldIds unsortedFieldExprs unsortedFieldTysAll - let expr = wrap expr + let expr = (wrap :: spreadSrcs, expr) ||> List.foldBack (fun wrap expr -> wrap expr) // Bind the original expression let expr = mkCompGenLet mOrigExpr oldv origExprChecked expr @@ -8874,6 +8987,13 @@ and TcApplicationThen (cenv: cenv) (overallTy: OverallTy) env tpenv mExprAndArg | [] when g.langVersion.SupportsFeature LanguageFeature.EmptyBodiedComputationExpressions -> Some (EmptyFieldListAsUnit (SynExpr.Const (SynConst.Unit, range0))) | _ -> None + let (|SpreadsOnly|_|) recordFields = + if g.langVersion.SupportsFeature LanguageFeature.RecordSpreads && not (List.isEmpty recordFields) && recordFields |> List.forall (function SynExprRecordFieldOrSpread.Spread _ -> true | _ -> false) then + let spreadRanges = recordFields |> List.choose (function SynExprRecordFieldOrSpread.Spread (SynExprSpread (spreadRange = m), _) -> Some m | _ -> None) + Some (SpreadsOnly spreadRanges) + else + None + // If the type of 'synArg' unifies as a function type, then this is a function application, otherwise // it is an error or a computation expression or indexer or delegate invoke match UnifyFunctionTypeUndoIfFailed cenv denv mLeftExpr exprTy with @@ -8894,15 +9014,21 @@ and TcApplicationThen (cenv: cenv) (overallTy: OverallTy) env tpenv mExprAndArg // Note that 'seq' predated computation expressions and is not actually a computation expression builder // though users don't realise that. let synArg = - match synArg with + match leftExpr with // seq { comp } // seq { } - | SynExpr.ComputationExpr (false, comp, m) - | SynExpr.Record (None, None, EmptyFieldListAsUnit comp, m) when - (match leftExpr with - | ApplicableExpr(expr=Expr.Op(TOp.Coerce, _, [SeqExpr g], _)) -> true - | _ -> false) -> - SynExpr.ComputationExpr (true, comp, m) + | ApplicableExpr(expr=Expr.Op(TOp.Coerce, _, [SeqExpr g], _)) -> + match synArg with + | SynExpr.ComputationExpr (false, comp, m) + | SynExpr.Record (None, None, EmptyFieldListAsUnit comp, m) -> + SynExpr.ComputationExpr (true, comp, m) + + | SynExpr.Record (None, None, SpreadsOnly spreadRanges, m) -> + for m in spreadRanges do + errorR (Error (FSComp.SR.parsSpreadNotSupported (), m)) + SynExpr.ComputationExpr (true, arbExpr ("spreadsInSeqExpr", m), m) + + | _ -> synArg | _ -> synArg @@ -9486,7 +9612,9 @@ and TcImplicitOpItemThen (cenv: cenv) overallTy env id sln tpenv mItem delayed = | SynExpr.Tuple (_, synExprs, _, _) | SynExpr.ArrayOrList (_, synExprs, _) -> synExprs |> List.forall isSimpleArgument - | SynExpr.Record (copyInfo=copyOpt; recordFields=fields) -> copyOpt |> Option.forall (fst >> isSimpleArgument) && fields |> List.forall ((fun (SynExprRecordField(expr=e)) -> e) >> Option.forall isSimpleArgument) + | SynExpr.Record (copyInfo=copyOpt; recordFields=fields) -> + copyOpt |> Option.forall (fst >> isSimpleArgument) + && fields |> List.forall ((function SynExprRecordFieldOrSpread.Field (SynExprRecordField(expr=e), _) -> e | _ -> None) >> Option.forall isSimpleArgument) | SynExpr.App (_, _, synExpr, synExpr2, _) -> isSimpleArgument synExpr && isSimpleArgument synExpr2 | SynExpr.IfThenElse (ifExpr=synExpr; thenExpr=synExpr2; elseExpr=synExprOpt) -> isSimpleArgument synExpr && isSimpleArgument synExpr2 && Option.forall isSimpleArgument synExprOpt | SynExpr.DotIndexedGet (synExpr, _, _, _) -> isSimpleArgument synExpr diff --git a/src/Compiler/Checking/Expressions/CheckExpressions.fsi b/src/Compiler/Checking/Expressions/CheckExpressions.fsi index 4fc6a1dfde7..199ce0e720e 100644 --- a/src/Compiler/Checking/Expressions/CheckExpressions.fsi +++ b/src/Compiler/Checking/Expressions/CheckExpressions.fsi @@ -907,15 +907,21 @@ val UnifyTupleTypeAndInferCharacteristics: 'T list -> TupInfo * TTypes +/// Helper used to check for duplicate fields in records. +val CheckRecdExprDuplicateFields: elems: Ident list -> unit + /// Helper used to check both record expressions and record patterns val BuildFieldMap: cenv: TcFileState -> env: TcEnv -> isPartial: bool -> ty: TType -> - flds: ((Ident list * Ident) * 'T) list -> + flds: (Ident * ExplicitOrSpread) list -> m: range -> - (TypeInst * TyconRef * Map * (string * 'T) list) option + (TypeInst * + TyconRef * + Map> * + (string * ExplicitOrSpread<'Explicit, 'Spread>) list) option /// Check a long identifier 'Case' or 'Case argsR' that has been resolved to an active pattern case val TcPatLongIdentActivePatternCase: diff --git a/src/Compiler/Checking/NameResolution.fs b/src/Compiler/Checking/NameResolution.fs index 9be3d04e58f..ffb206076f6 100644 --- a/src/Compiler/Checking/NameResolution.fs +++ b/src/Compiler/Checking/NameResolution.fs @@ -4011,17 +4011,30 @@ let SuggestLabelsOfRelatedRecords g (nenv: NameResolutionEnv) (id: Ident) (allFi UndefinedName(0, FSComp.SR.undefinedNameRecordLabel, id, suggestLabels) +[] +type internal ExplicitOrSpread<'Explicit, 'Spread> = + /// An expression or value derived from an explicit member or record field. + | Explicit of 'Explicit + + /// An expression or value derived from a member or field coming from a spread. + | Spread of 'Spread + +let (|ExplicitOrSpread|) (ExplicitOrSpread.Explicit value | ExplicitOrSpread.Spread value) = value + /// Resolve a long identifier representing a record field -let ResolveFieldPrim sink (ncenv: NameResolver) nenv ad ty (mp, id: Ident) allFields = +let ResolveFieldPrim sink (ncenv: NameResolver) nenv ad ty (fldInfo: ExplicitOrSpread<'Explicit * Ident, Ident>) allFields = + let m = match fldInfo with ExplicitOrSpread.Explicit (_, id) | ExplicitOrSpread.Spread id -> id.idRange let typeNameResInfo = TypeNameResolutionInfo.Default let g = ncenv.g - let m = id.idRange - match mp with - | [] -> + + match fldInfo with + | ExplicitOrSpread.Explicit ([], id) + | ExplicitOrSpread.Spread id -> let lookup() = let frefs = - try Map.find id.idText nenv.eFieldLabels - with :? KeyNotFoundException -> + match Map.tryFind id.idText nenv.eFieldLabels with + | Some frefs -> frefs + | None -> // record label is unknown -> suggest related labels and give a hint to the user error(SuggestLabelsOfRelatedRecords g nenv id allFields) @@ -4038,9 +4051,10 @@ let ResolveFieldPrim sink (ncenv: NameResolver) nenv ad ty (mp, id: Ident) allFi match tryTcrefOfAppTy g ty with | ValueSome tcref -> match ncenv.InfoReader.TryFindRecdOrClassFieldInfoOfType(id.idText, m, ty) with - | ValueSome (RecdFieldInfo(_, rfref)) -> [ResolutionInfo.Empty, FieldResolution(FreshenRecdFieldRef ncenv m rfref, false)] + | ValueSome (RecdFieldInfo(_, rfref)) -> Some [ResolutionInfo.Empty, FieldResolution(FreshenRecdFieldRef ncenv m rfref, false)] | _ -> - if tcref.IsRecordTycon then + if fldInfo.IsSpread then None + elif tcref.IsRecordTycon then // record label doesn't belong to record type -> suggest other labels of same record let suggestLabels (addToBuffer: string -> unit) = for label in SuggestOtherLabelsOfSameRecordType g nenv ty id allFields do @@ -4050,9 +4064,9 @@ let ResolveFieldPrim sink (ncenv: NameResolver) nenv ad ty (mp, id: Ident) allFi let errorText = FSComp.SR.nrRecordDoesNotContainSuchLabel(typeName, id.idText) error(ErrorWithSuggestions(errorText, m, id.idText, suggestLabels)) else - lookup() - | ValueNone -> lookup() - | _ -> + Some (lookup()) + | ValueNone -> Some (lookup()) + | ExplicitOrSpread.Explicit (mp, id) -> let lid = (mp@[id]) let tyconSearch ad () = match lid with @@ -4082,17 +4096,18 @@ let ResolveFieldPrim sink (ncenv: NameResolver) nenv ad ty (mp, id: Ident) allFi if not (isNil rest) then errorR(Error(FSComp.SR.nrInvalidFieldLabel(), (List.head rest).idRange)) - [(resInfo, item)] + Some [(resInfo, item)] -let ResolveField sink ncenv nenv ad ty mp id allFields = - let res = ResolveFieldPrim sink ncenv nenv ad ty (mp, id) allFields +let ResolveField sink ncenv nenv ad ty fldInfo allFields = + let res = ResolveFieldPrim sink ncenv nenv ad ty fldInfo allFields // Register the results of any field paths "Module.Type" in "Module.Type.field" as a name resolution. (Note, the path resolution // info is only non-empty if there was a unique resolution of the field) - let checker = ResultTyparChecker(fun () -> true) res - |> List.map (fun (resInfo, rfref) -> - ResolutionInfo.SendEntityPathToSink(sink, ncenv, nenv, ItemOccurrence.UseInType, ad, resInfo, checker) - rfref) + |> Option.map (fun res -> + let checker = ResultTyparChecker(fun () -> true) + res |> List.map (fun (resInfo, rfref) -> + ResolutionInfo.SendEntityPathToSink(sink, ncenv, nenv, ItemOccurrence.UseInType, ad, resInfo, checker) + rfref)) /// Resolve a long identifier representing a nested record field. /// @@ -5214,6 +5229,17 @@ let getRecordFieldsInScope nenv = Item.RecdField(RecdFieldInfo(typeInsts, fref))) |> List.ofSeq +let getRecordTyconsInScope g (ncenv: NameResolver) nenv ad m = + [ + for KeyValue (_, tcref) in nenv.eTyconsByDemangledNameAndArity do + if + not (tcref.LogicalName.Contains ",") && + tcref.IsRecordTycon && + not (IsTyconUnseen ad g ncenv.amap m false tcref) + then + tcref, ItemOfTyconRef ncenv m tcref + ] + /// allowObsolete - specifies whether we should return obsolete types & modules /// as (no other obsolete items are returned) let rec ResolvePartialLongIdentToClassOrRecdFields (ncenv: NameResolver) (nenv: NameResolutionEnv) m ad plid (allowObsolete: bool) (fieldsOnly: bool) = diff --git a/src/Compiler/Checking/NameResolution.fsi b/src/Compiler/Checking/NameResolution.fsi index 79d1dfbdb49..bfa074d6bac 100755 --- a/src/Compiler/Checking/NameResolution.fsi +++ b/src/Compiler/Checking/NameResolution.fsi @@ -842,6 +842,16 @@ val internal ResolveTypeLongIdent: genOk: PermitDirectReferenceToGeneratedType -> ResultOrException +[] +type internal ExplicitOrSpread<'Explicit, 'Spread> = + /// An expression or value derived from an explicit member or record field. + | Explicit of 'Explicit + + /// An expression or value derived from a member or field coming from a spread. + | Spread of 'Spread + +val (|ExplicitOrSpread|): ExplicitOrSpread<'Value, 'Value> -> 'Value + /// Resolve a long identifier to a field val internal ResolveField: sink: TcResultsSink -> @@ -849,10 +859,9 @@ val internal ResolveField: nenv: NameResolutionEnv -> ad: AccessorDomain -> ty: TType -> - mp: Ident list -> - id: Ident -> + fldInfo: ExplicitOrSpread -> allFields: Ident list -> - FieldResolution list + FieldResolution list option /// Resolve a long identifier to a nested field val internal ResolveNestedField: @@ -878,6 +887,14 @@ val internal ResolveExprLongIdent: val internal getRecordFieldsInScope: NameResolutionEnv -> Item list +val internal getRecordTyconsInScope: + g: TcGlobals -> + ncenv: NameResolver -> + nenv: NameResolutionEnv -> + ad: AccessorDomain -> + m: range -> + (TyconRef * Item) list + /// Resolve a (possibly incomplete) long identifier to a list of possible class or record fields val internal ResolvePartialLongIdentToClassOrRecdFields: NameResolver -> NameResolutionEnv -> range -> AccessorDomain -> string list -> bool -> bool -> Item list diff --git a/src/Compiler/Checking/Spreads.fs b/src/Compiler/Checking/Spreads.fs new file mode 100644 index 00000000000..19ee2fa821d --- /dev/null +++ b/src/Compiler/Checking/Spreads.fs @@ -0,0 +1,663 @@ +[] +module internal FSharp.Compiler.Spreads + +open System +open FSharp.Compiler +open FSharp.Compiler.AccessibilityLogic +open FSharp.Compiler.CheckRecordSyntaxHelpers +open FSharp.Compiler.CheckBasics +open FSharp.Compiler.DiagnosticsLogger +open FSharp.Compiler.Features +open FSharp.Compiler.NameResolution +open FSharp.Compiler.Syntax +open FSharp.Compiler.SyntaxTreeOps +open FSharp.Compiler.TcGlobals +open FSharp.Compiler.Text +open FSharp.Compiler.TypedTree +open FSharp.Compiler.TypedTreeOps +open Internal.Utilities.Library + +[] +module private Patterns = + [] + let LeftwardExplicit = true + + [] + let NoLeftwardExplicit = false + +/// Merges updates to nested record fields on the same level in record copy-and-update. +/// +/// `CheckRecordSyntaxHelpers.TransformAstForNestedUpdates` expands `{ x with A.B = 10; A.C = "" }` +/// +/// into +/// +/// { x with +/// A = { x.A with B = 10 }; +/// A = { x.A with C = "" } +/// } +/// +/// which we here combine into +/// +/// { x with A = { x.A with B = 10; C = "" } } +let private (|NestedUpdate|_|) expr2 expr1 = + match expr1, expr2 with + | SynExpr.Record(baseInfo, copyInfo, fields1, m), SynExpr.Record(recordFields = fields2) -> + Some(SynExpr.Record(baseInfo, copyInfo, fields1 @ fields2, m)) + | SynExpr.AnonRecd(isStruct, copyInfo, fields1, m, trivia), SynExpr.AnonRecd(recordFields = fields2) -> + Some(SynExpr.AnonRecd(isStruct, copyInfo, fields1 @ fields2, m, trivia)) + | _ -> None + +/// Functions for checking type spreads. +[] +module Types = + /// Functions for checking record type spreads. + [] + module Records = + /// Typechecks the given list of record fields or spreads. + let check checkSpreadsLanguageFeature tcField tcSpread (fieldsAndSpreads: SynFieldOrSpread list) : _ list = + let rec loop fields i fieldsAndSpreads = + match fieldsAndSpreads with + | [] -> + fields + |> Map.toList + |> List.collect (fun (_, (_, dupes)) -> dupes) + |> List.sortBy (fun (i, _) -> i) + |> List.map (fun (_, r) -> r) + + | SynFieldOrSpread.Field(SynField(idOpt = None)) :: fieldsAndSpreads -> loop fields i fieldsAndSpreads + + | SynFieldOrSpread.Field(SynField(idOpt = Some fieldId) as synField) :: fieldsAndSpreads -> + let field, errorAmbiguousShadowing = tcField synField + + let fields = + fields + |> Map.change fieldId.idText (function + | None -> Some(LeftwardExplicit, [ i, field ]) + | Some(LeftwardExplicit, dupes) -> + errorAmbiguousShadowing () + Some(LeftwardExplicit, (i, field) :: dupes) + | Some(NoLeftwardExplicit, _dupes) -> Some(LeftwardExplicit, [ i, field ])) + + loop fields (i + 1) fieldsAndSpreads + + | SynFieldOrSpread.Spread(SynTypeSpread(range = m) as synSpread) :: fieldsAndSpreads -> + checkSpreadsLanguageFeature m + + let rec collectFieldsFromSpread fields i fieldsFromSpread = + match fieldsFromSpread with + | [] -> fields, i + | (fieldId, field, warnAmbiguousShadowing) :: fieldsFromSpread -> + let fields = + fields + |> Map.change fieldId (function + | None -> Some(NoLeftwardExplicit, [ i, field ]) + | Some(LeftwardExplicit, _dupes) -> + warnAmbiguousShadowing () + Some(LeftwardExplicit, [ i, field ]) + | Some(NoLeftwardExplicit, _dupes) -> Some(NoLeftwardExplicit, [ i, field ])) + + collectFieldsFromSpread fields (i + 1) fieldsFromSpread + + let fields, i = collectFieldsFromSpread fields i (tcSpread synSpread) + loop fields i fieldsAndSpreads + + loop Map.empty 0 fieldsAndSpreads + +/// Functions for checking value spreads. +[] +module Values = + /// Functions for checking record spreads. + [] + module Records = + let private establishFields checkSpreadsLanguageFeature tcField tcSpread (fieldsAndSpreads: SynExprRecordFieldOrSpread list) = + let rec loop fields i spreadSrcTys spreadSrcExprs interveningSpreadSrcs fieldsAndSpreads = + match fieldsAndSpreads with + | [] -> + let fields = + fields + |> Map.toList + |> List.collect (fun (_, (_, _, dupes)) -> dupes) + |> List.sortBy (fun (i, _) -> i) + |> List.map (fun (_, r) -> r) + + List.rev spreadSrcTys, List.rev spreadSrcExprs, fields + + | SynExprRecordFieldOrSpread.Field(SynExprRecordField(fieldName = _, (* isOk *) false), _) :: _ -> + // if we met at least one field that is not syntactically correct - raise ReportedError to transfer control to the recovery routine + // raising ReportedError None transfers control to the closest errorRecovery point but do not make any records into log + // we assume that parse errors were already reported + raise (FSharp.Compiler.DiagnosticsLogger.ReportedError None) + + | SynExprRecordFieldOrSpread.Field((SynExprRecordField(fieldName = synLongId, _; expr = fieldExpr; range = m)), _) :: fieldsAndSpreads -> + let interveningSpreadSrc = + interveningSpreadSrcs |> Map.tryFind (textOfId (List.head synLongId.LongIdent)) + + let fieldId, path, fieldExpr, errorAmbiguousShadowing = + tcField interveningSpreadSrc synLongId fieldExpr m + + let fields = + let (|NestedUpdate|_|) expr1 expr2 = + match expr1, expr2 with + | None, _ + | _, None -> None + | Some fieldExpr, Some expr -> (|NestedUpdate|_|) fieldExpr expr + + fields + |> Map.change (textOfId fieldId) (function + | None -> Some(LeftwardExplicit, fieldExpr, [ i, (fieldId, ExplicitOrSpread.Explicit(path, fieldExpr)) ]) + | Some(LeftwardExplicit, NestedUpdate fieldExpr combinedExpr, _ :: dupes) -> + Some( + LeftwardExplicit, + Some combinedExpr, + (i, (fieldId, ExplicitOrSpread.Explicit(path, Some combinedExpr))) :: dupes + ) + | Some(LeftwardExplicit, _dupeExpr, dupes) -> + errorAmbiguousShadowing () + + Some(LeftwardExplicit, fieldExpr, (i, (fieldId, ExplicitOrSpread.Explicit(path, fieldExpr))) :: dupes) + | Some(NoLeftwardExplicit, _dupeExpr, _dupes) -> + Some(LeftwardExplicit, fieldExpr, [ i, (fieldId, ExplicitOrSpread.Explicit(path, fieldExpr)) ])) + + loop fields (i + 1) spreadSrcTys spreadSrcExprs interveningSpreadSrcs fieldsAndSpreads + + | SynExprRecordFieldOrSpread.Spread(SynExprSpread(expr = spreadSrcSynExpr; range = m) as synExprSpread, _) :: fieldsAndSpreads -> + checkSpreadsLanguageFeature m + + match tcSpread synExprSpread with + | Some(spreadSrcExpr, spreadSrcTy, fieldsFromSpread) -> + let rec collectFieldsFromSpread fields i interveningSpreadSrcs fieldsFromSpread = + match fieldsFromSpread with + | [] -> fields, i, interveningSpreadSrcs + | (fieldId, field, warnAmbiguousShadowing) :: fieldsFromSpread -> + let tys = + fields + |> Map.change (textOfId fieldId) (function + | None -> Some(NoLeftwardExplicit, Some spreadSrcSynExpr, [ i, (fieldId, field) ]) + | Some(LeftwardExplicit, _existingExpr, _dupes) -> + warnAmbiguousShadowing () + Some(LeftwardExplicit, Some spreadSrcSynExpr, [ i, (fieldId, field) ]) + | Some(NoLeftwardExplicit, _existingExpr, _dupes) -> + Some(NoLeftwardExplicit, Some spreadSrcSynExpr, [ i, (fieldId, field) ])) + + let interveningSpreadSrcs = + interveningSpreadSrcs + |> Map.add (textOfId fieldId) (spreadSrcSynExpr, spreadSrcTy) + + collectFieldsFromSpread tys (i + 1) interveningSpreadSrcs fieldsFromSpread + + let fields, i, interveningSpreadSrcs = + collectFieldsFromSpread fields i interveningSpreadSrcs fieldsFromSpread + + loop fields i (spreadSrcTy :: spreadSrcTys) (spreadSrcExpr :: spreadSrcExprs) interveningSpreadSrcs fieldsAndSpreads + + | None -> loop fields i spreadSrcTys spreadSrcExprs interveningSpreadSrcs fieldsAndSpreads + + loop Map.empty 0 [] [] Map.empty fieldsAndSpreads + + /// Typechecks the given list of record fields or spreads. + let check + TcExprFlex + (g: TcGlobals) + (env: TcEnv) + (cenv: TcFileState) + (tpenv: UnscopedTyparEnv) + (ad: AccessorDomain) + (mWholeExpr: range) + withExprOpt + overallTy + (fieldsAndSpreads: SynExprRecordFieldOrSpread list) + = + let tcField (spreadSrcOpt: (SynExpr * TType) option) (SynLongIdent(lid, _, _)) exprBeingAssigned m = + let isFromNestedUpdate, path, fieldId, field = + let srcExprOpt = + spreadSrcOpt + |> Option.map (fun (spreadSrc, _) -> spreadSrc, (spreadSrc.Range, None)) + |> Option.orElse withExprOpt + + let srcExprTy = + spreadSrcOpt + |> Option.map (fun (_, spreadSrcTy) -> spreadSrcTy) + |> Option.defaultValue overallTy + + match srcExprOpt, lid, exprBeingAssigned with + | _, [ id ], _ -> false, [], id, exprBeingAssigned + | Some srcExpr, lid, Some exprBeingAssigned -> + let (path, id), exprBeingAssigned = + TransformAstForNestedUpdates cenv env srcExprTy lid exprBeingAssigned srcExpr + + true, path, id, Some exprBeingAssigned + | _ -> + let (path, id) = List.frontAndBack lid + false, path, id, exprBeingAssigned + + let isFromSpread = Option.isSome spreadSrcOpt + + let errorAmbiguousShadowing () = + if not isFromNestedUpdate || isFromSpread then + errorR (Error(FSComp.SR.tcMultipleFieldsInRecord fieldId.idText, m)) + + fieldId, path, field, errorAmbiguousShadowing + + let tcSpread (SynExprSpread(expr = expr; range = m)) = + let mExpr = expr.Range + + if Option.isSome withExprOpt then + errorR (Error(FSComp.SR.tcRecordExprSpreadWithCannotBeUsedWithSpreads (), m)) + + let flex = false + + let spreadSrcExpr, _tpenv = + TcExprFlex cenv flex false (NewInferenceType g) env tpenv expr + + let tyOfSpreadSrcExpr = tyOfExpr g spreadSrcExpr + + let spreadSrcTyIsNullable = + g.checkNullness + && (nullnessOfTy g tyOfSpreadSrcExpr).Evaluate() = NullnessInfo.WithNull + + let spreadSrcTyIsRecd = + isRecdTy g tyOfSpreadSrcExpr || isAnonRecdTy g tyOfSpreadSrcExpr + + let isValidSpreadSrcTy = not spreadSrcTyIsNullable && spreadSrcTyIsRecd + + if isValidSpreadSrcTy then + let spreadSrcAddrExpr, spreadSrc = + let srcTyIsStruct = isStructTy g tyOfSpreadSrcExpr + + let spreadSrcAddrVal, spreadSrcAddrExpr = + mkCompGenLocal + mWholeExpr + "spreadSrc" + (if srcTyIsStruct then + mkByrefTy g tyOfSpreadSrcExpr + else + tyOfSpreadSrcExpr) + + let wrap, oldAddr, _readonly, _writeonly = + mkExprAddrOfExpr g srcTyIsStruct false NeverMutates spreadSrcExpr None m + + spreadSrcAddrExpr, (fun expr -> wrap (mkCompGenLet m spreadSrcAddrVal oldAddr expr)) + + let recordFieldsFromSpread = + if isRecdTy g tyOfSpreadSrcExpr then + ResolveRecordOrClassFieldsOfType cenv.nameResolver m ad tyOfSpreadSrcExpr false + else + tryDestAnonRecdTy g tyOfSpreadSrcExpr + |> ValueOption.map (fun (anonInfo, tys) -> + anonInfo.SortedIds + |> List.ofArray + |> List.mapi (fun i id -> Item.AnonRecdField(anonInfo, tys, i, id.idRange))) + |> ValueOption.defaultValue [] + + let fields = + recordFieldsFromSpread + |> List.choose (fun field -> + match field with + | Item.RecdField fieldInfo -> + let fieldExpr = + mkRecdFieldGetViaExprAddr (spreadSrcAddrExpr, fieldInfo.RecdFieldRef, fieldInfo.TypeInst, mExpr) + + let fieldId = ident (fieldInfo.RecdField.Id.idText, mExpr) + let ty = fieldInfo.FieldType + + let warnAmbiguousShadowing () = + let fmtedSpreadField = + NicePrint.stringOfRecdField env.DisplayEnv cenv.infoReader fieldInfo.TyconRef fieldInfo.RecdField + + warning (Error(FSComp.SR.tcRecordExprSpreadFieldShadowsExplicitField fmtedSpreadField, m)) + + Some(fieldId, ExplicitOrSpread.Spread(ty, fieldExpr), warnAmbiguousShadowing) + + | Item.AnonRecdField(anonInfo, tys, fieldIndex, _) -> + let fieldExpr = + mkAnonRecdFieldGet g (anonInfo, spreadSrcAddrExpr, tys, fieldIndex, mExpr) + + let fieldId = anonInfo.SortedIds[fieldIndex] + let ty = tys[fieldIndex] + + let warnAmbiguousShadowing () = + let typars = + tryAppTy g ty + |> ValueOption.map (snd >> List.choose (tryDestTyparTy g >> ValueOption.toOption)) + |> ValueOption.defaultValue [] + + let fmtedSpreadField = + LayoutRender.showL ( + NicePrint.prettyLayoutOfMemberSig env.DisplayEnv ([], fieldId.idText, typars, [], ty) + ) + + warning (Error(FSComp.SR.tcRecordExprSpreadFieldShadowsExplicitField fmtedSpreadField, m)) + + Some(fieldId, ExplicitOrSpread.Spread(ty, fieldExpr), warnAmbiguousShadowing) + + | _ -> None) + + Some(spreadSrc, tyOfSpreadSrcExpr, fields) + else + if not expr.IsArbExprAndThusAlreadyReportedError then + if not spreadSrcTyIsRecd then + errorR (Error(FSComp.SR.tcRecordExprSpreadSourceMustBeRecord (), m)) + elif spreadSrcTyIsNullable then + errorR (Error(FSComp.SR.tcRecordExprSpreadSourceCannotBeNullable (), m)) + + None + + let checkSpreadsLanguageFeature m = + checkLanguageFeatureAndRecover g.langVersion LanguageFeature.RecordSpreads m + + establishFields checkSpreadsLanguageFeature tcField tcSpread fieldsAndSpreads + + /// Functions for checking anonymous record spreads. + module AnonymousRecords = + let private establishFields + checkSpreadsLanguageFeature + tcField + tcSpread + (targetAnonRecordTy, targetAnonRecordTyContainsField) + (fieldsAndSpreads: SynExprAnonRecordFieldOrSpread list) + = + let rec loop fields i spreadSrcExprs interveningSpreadSrcs fieldsAndSpreads = + match fieldsAndSpreads with + | [] -> + let processedFieldsList = Map.toList fields + + let processedFieldsList = + // If the target type is a known anonymous record type, + // keep only those fields that are present in that type + // or that are explicitly defined in this one. + if targetAnonRecordTy then + processedFieldsList + |> List.filter (function + | _, (LeftwardExplicit, _, _) -> true + | fieldId, (NoLeftwardExplicit, _, _) -> targetAnonRecordTyContainsField fieldId) + else + processedFieldsList + + let (|Head|) = List.head + + let fieldsInAlphabeticalOrder = + processedFieldsList |> List.sortBy (fun (fieldName, _) -> fieldName) + + let fieldTysInAlphabeticalOrder = + fieldsInAlphabeticalOrder + |> List.map (fun (_, (_, _, Head(_, (_, fieldTy, _)))) -> fieldTy) + + let fieldIdsInAlphabeticalOrder = + fieldsInAlphabeticalOrder + |> List.map (fun (_, (_, _, Head(_, (fieldId, _, _)))) -> fieldId) + + let fieldsInSrcOrder = + processedFieldsList + |> List.collect (fun (_, (_, _, dupes)) -> dupes) + |> List.sortBy (fun (i, _) -> i) + |> List.map (fun (_, field) -> field) + + List.rev spreadSrcExprs, fieldIdsInAlphabeticalOrder, fieldTysInAlphabeticalOrder, fieldsInSrcOrder + + | SynExprAnonRecordFieldOrSpread.Field(SynExprAnonRecordField(fieldName = synLongId) as synExprAnonRecordField, _) :: fieldsAndSpreads -> + let interveningSpreadSrc = + interveningSpreadSrcs |> Map.tryFind (textOfId (List.head synLongId.LongIdent)) + + let fieldId, fieldTy, transformedFieldExpr, mkTcField, errorAmbiguousShadowing = + tcField interveningSpreadSrc synExprAnonRecordField + + let fields = + fields + |> Map.change (textOfId fieldId) (function + | None -> + Some(LeftwardExplicit, transformedFieldExpr, [ i, (fieldId, fieldTy, mkTcField transformedFieldExpr) ]) + | Some(LeftwardExplicit, NestedUpdate transformedFieldExpr groupedExpr, _ :: dupes) -> + Some(LeftwardExplicit, groupedExpr, (i, (fieldId, fieldTy, mkTcField groupedExpr)) :: dupes) + | Some(LeftwardExplicit, _dupeExpr, dupes) -> + errorAmbiguousShadowing () + + Some( + LeftwardExplicit, + transformedFieldExpr, + (i, (fieldId, fieldTy, mkTcField transformedFieldExpr)) :: dupes + ) + | Some(NoLeftwardExplicit, _dupeExpr, _dupes) -> + Some(LeftwardExplicit, transformedFieldExpr, [ i, (fieldId, fieldTy, mkTcField transformedFieldExpr) ])) + + loop fields (i + 1) spreadSrcExprs interveningSpreadSrcs fieldsAndSpreads + + | SynExprAnonRecordFieldOrSpread.Spread(SynExprSpread(expr = spreadSrcSynExpr; range = m), _) :: fieldsAndSpreads -> + checkSpreadsLanguageFeature m + + match tcSpread spreadSrcSynExpr m with + | Some(spreadSrcExpr, spreadSrcTy, fieldsFromSpread) -> + let rec collectFieldsFromSpread fields i interveningSpreadSrcs fieldsFromSpread = + match fieldsFromSpread with + | [] -> fields, i, interveningSpreadSrcs + | (fieldId, fieldTy, tcField, warnAmbiguousShadowing) :: fieldsFromSpread -> + let tys = + fields + |> Map.change (textOfId fieldId) (function + | None -> Some(NoLeftwardExplicit, spreadSrcSynExpr, [ i, (fieldId, fieldTy, tcField) ]) + | Some(LeftwardExplicit, _existingExpr, _dupes) -> + warnAmbiguousShadowing () + Some(LeftwardExplicit, spreadSrcSynExpr, [ i, (fieldId, fieldTy, tcField) ]) + | Some(NoLeftwardExplicit, _existingExpr, _dupes) -> + Some(NoLeftwardExplicit, spreadSrcSynExpr, [ i, (fieldId, fieldTy, tcField) ])) + + let interveningSpreadSrcs = + interveningSpreadSrcs + |> Map.add (textOfId fieldId) (spreadSrcSynExpr, spreadSrcTy) + + collectFieldsFromSpread tys (i + 1) interveningSpreadSrcs fieldsFromSpread + + let fields, i, interveningSpreadSrcs = + collectFieldsFromSpread fields i interveningSpreadSrcs fieldsFromSpread + + loop fields i (spreadSrcExpr :: spreadSrcExprs) interveningSpreadSrcs fieldsAndSpreads + + | None -> loop fields i spreadSrcExprs interveningSpreadSrcs fieldsAndSpreads + + loop Map.empty 0 [] Map.empty fieldsAndSpreads + + /// Typechecks the given list of anonymous record fields or spreads. + let check + TcExprFlex + TcAdjustExprForTypeDirectedConversions + MustConvertTo + UnifyOverallType + errorRIfSpreadUsedWithWith + (g: TcGlobals) + (env: TcEnv) + (cenv: TcFileState) + (tpenv: UnscopedTyparEnv) + (ad: AccessorDomain) + (mWholeExpr: range) + (maybeAnonRecdTargetTy: (AnonRecdTypeInfo * TType list) voption) + (origExprOpt: (SynExpr * BlockSeparator) option) + (origExprTyOrOverallTy: TType) + (unsortedFieldIdsAndSynExprsGiven: SynExprAnonRecordFieldOrSpread list) + = + let checkSpreadsLanguageFeature m = + checkLanguageFeatureAndRecover g.langVersion LanguageFeature.RecordSpreads m + + let possibleTargetTyAt = + match maybeAnonRecdTargetTy with + | ValueSome(anonInfo, tys) -> + let names = anonInfo.SortedNames + let tys = List.toArray tys + + fun name -> + let i = Array.BinarySearch(names, name) + if i < 0 then ValueNone else ValueSome tys[i] + | ValueNone -> fun _ -> ValueNone + + let tcField + (spreadSrcOpt: (SynExpr * TType) option) + (SynExprAnonRecordField(fieldName = SynLongIdent(fieldLid, _, _) as synLongIdent; expr = expr; range = m)) + = + let isFromNestedUpdate, fieldId, transformedFieldExpr = + let srcExpr, srcTy = + spreadSrcOpt + |> Option.map (fun (spreadSrc, spreadSrcTy) -> (spreadSrc, (spreadSrc.Range, None)), spreadSrcTy) + |> Option.orElseWith (fun () -> origExprOpt |> Option.map (fun origExpr -> origExpr, origExprTyOrOverallTy)) + |> Option.defaultWith (fun () -> + (arbExpr ("nestedUpdateSrcExpr", synLongIdent.Range), (synLongIdent.Range, None)), origExprTyOrOverallTy) + + match fieldLid with + | [] -> error (Error(FSComp.SR.nrUnexpectedEmptyLongId (), mWholeExpr)) + | [ id ] -> false, id, expr + | lid -> + let (_, id), exprBeingAssigned = + TransformAstForNestedUpdates cenv env srcTy lid expr srcExpr + + true, id, exprBeingAssigned + + let fieldTy = + possibleTargetTyAt fieldId.idText + |> ValueOption.defaultWith (fun () -> NewInferenceType g) + + let tcField expr = + fun () -> let fieldExpr, _ = TcExprFlex cenv true false fieldTy env tpenv expr in fieldExpr + + let errorAmbiguousShadowing () = + if not isFromNestedUpdate then + errorR (Error(FSComp.SR.tcAnonRecdDuplicateFieldId fieldId.idText, m)) + + fieldId, fieldTy, transformedFieldExpr, tcField, errorAmbiguousShadowing + + let tcSpread (expr: SynExpr) m = + errorRIfSpreadUsedWithWith m + + let flex = false + + let spreadSrcExpr, _ = + TcExprFlex cenv flex false (NewInferenceType g) env tpenv expr + + let tyOfSpreadSrcExpr = tyOfExpr g spreadSrcExpr + + let spreadSrcTyIsNullable = + g.checkNullness + && (nullnessOfTy g tyOfSpreadSrcExpr).Evaluate() = NullnessInfo.WithNull + + let spreadSrcTyIsRecd = + isRecdTy g tyOfSpreadSrcExpr || isAnonRecdTy g tyOfSpreadSrcExpr + + let isValidSpreadSrcTy = not spreadSrcTyIsNullable && spreadSrcTyIsRecd + + if isValidSpreadSrcTy then + let spreadSrcAddrExpr, spreadSrcExpr = + let srcTyIsStruct = isStructTy g tyOfSpreadSrcExpr + + let spreadSrcAddrVal, spreadSrcAddrExpr = + mkCompGenLocal + mWholeExpr + "spreadSrc" + (if srcTyIsStruct then + mkByrefTy g tyOfSpreadSrcExpr + else + tyOfSpreadSrcExpr) + + let wrap, oldAddr, _readonly, _writeonly = + mkExprAddrOfExpr g srcTyIsStruct false NeverMutates spreadSrcExpr None m + + spreadSrcAddrExpr, (fun expr -> wrap (mkCompGenLet m spreadSrcAddrVal oldAddr expr)) + + let recordFieldsFromSpread = + if isRecdTy g tyOfSpreadSrcExpr then + ResolveRecordOrClassFieldsOfType cenv.nameResolver m ad tyOfSpreadSrcExpr false + else + tryDestAnonRecdTy g tyOfSpreadSrcExpr + |> ValueOption.map (fun (anonInfo, tys) -> + anonInfo.SortedIds + |> List.ofArray + |> List.mapi (fun i id -> Item.AnonRecdField(anonInfo, tys, i, id.idRange))) + |> ValueOption.defaultValue [] + + let fields = + recordFieldsFromSpread + |> List.choose (fun field -> + match field with + | Item.RecdField fieldInfo -> + let fieldId = fieldInfo.RecdField.Id + + let ty = + possibleTargetTyAt fieldId.idText + |> ValueOption.defaultValue fieldInfo.FieldType + + let tcField () = + let get = + mkRecdFieldGetViaExprAddr (spreadSrcAddrExpr, fieldInfo.RecdFieldRef, fieldInfo.TypeInst, m) + + let overallTy = MustConvertTo(false, ty) + UnifyOverallType cenv env m overallTy fieldInfo.FieldType + + let fieldExpr = + TcAdjustExprForTypeDirectedConversions cenv overallTy fieldInfo.FieldType env m get + + let fieldExpr = mkCoerceIfNeeded g ty (tyOfExpr g fieldExpr) fieldExpr + fieldExpr + + let warnAmbiguousShadowing () = + let fmtedSpreadField = + NicePrint.stringOfRecdField env.DisplayEnv cenv.infoReader fieldInfo.TyconRef fieldInfo.RecdField + + warning (Error(FSComp.SR.tcRecordExprSpreadFieldShadowsExplicitField fmtedSpreadField, m)) + + Some(fieldId, ty, tcField, warnAmbiguousShadowing) + + | Item.AnonRecdField(anonInfo, tys, fieldIndex, _) -> + let fieldId = anonInfo.SortedIds[fieldIndex] + + let ty = + possibleTargetTyAt fieldId.idText + |> ValueOption.defaultWith (fun () -> tys[fieldIndex]) + + let tcField () = + let get = + mkAnonRecdFieldGetViaExprAddr (anonInfo, spreadSrcAddrExpr, tys, fieldIndex, m) + + let overallTy = MustConvertTo(false, ty) + UnifyOverallType cenv env m overallTy tys[fieldIndex] + + let fieldExpr = + TcAdjustExprForTypeDirectedConversions cenv overallTy tys[fieldIndex] env m get + + let fieldExpr = mkCoerceIfNeeded g ty (tyOfExpr g fieldExpr) fieldExpr + fieldExpr + + let warnAmbiguousShadowing () = + let typars = + tryAppTy g ty + |> ValueOption.map (snd >> List.choose (tryDestTyparTy g >> ValueOption.toOption)) + |> ValueOption.defaultValue [] + + let fmtedSpreadField = + LayoutRender.showL ( + NicePrint.prettyLayoutOfMemberSig env.DisplayEnv ([], fieldId.idText, typars, [], ty) + ) + + warning (Error(FSComp.SR.tcRecordExprSpreadFieldShadowsExplicitField fmtedSpreadField, m)) + + Some(fieldId, ty, tcField, warnAmbiguousShadowing) + + | _ -> None) + + Some(spreadSrcExpr, tyOfSpreadSrcExpr, fields) + else + if not expr.IsArbExprAndThusAlreadyReportedError then + if not spreadSrcTyIsRecd then + errorR (Error(FSComp.SR.tcAnonRecordExprSpreadSourceMustBeRecord (), expr.Range)) + elif spreadSrcTyIsNullable then + errorR (Error(FSComp.SR.tcAnonRecordExprSpreadSourceCannotBeNullable (), m)) + + None + + let targetAnonRecordTy, targetAnonRecordTyContainsField = + maybeAnonRecdTargetTy + |> ValueOption.map (fun (anonInfo, _) -> + let sortedNames = anonInfo.SortedNames + true, fun fieldId -> Array.BinarySearch(sortedNames, fieldId) >= 0) + |> ValueOption.defaultValue (false, fun _ -> false) + + establishFields + checkSpreadsLanguageFeature + tcField + tcSpread + (targetAnonRecordTy, targetAnonRecordTyContainsField) + unsortedFieldIdsAndSynExprsGiven diff --git a/src/Compiler/Driver/CompilerDiagnostics.fs b/src/Compiler/Driver/CompilerDiagnostics.fs index 7cce266b405..5aaf9b70257 100644 --- a/src/Compiler/Driver/CompilerDiagnostics.fs +++ b/src/Compiler/Driver/CompilerDiagnostics.fs @@ -1187,7 +1187,8 @@ type Exception with | Parser.TOKEN_COLON_QMARK -> SR.GetString("Parser.TOKEN.COLON.QMARK") | Parser.TOKEN_INT32_DOT_DOT -> SR.GetString("Parser.TOKEN.INT32.DOT.DOT") | Parser.TOKEN_DOT_DOT -> SR.GetString("Parser.TOKEN.DOT.DOT") - | Parser.TOKEN_DOT_DOT_HAT -> SR.GetString("Parser.TOKEN.DOT.DOT") + | Parser.TOKEN_DOT_DOT_HAT -> SR.GetString("Parser.TOKEN.DOT.DOT.HAT") + | Parser.TOKEN_DOT_DOT_DOT -> SR.GetString("Parser.TOKEN.DOT.DOT.DOT") | Parser.TOKEN_QUOTE -> SR.GetString("Parser.TOKEN.QUOTE") | Parser.TOKEN_STAR -> SR.GetString("Parser.TOKEN.STAR") | Parser.TOKEN_HIGH_PRECEDENCE_TYAPP -> SR.GetString("Parser.TOKEN.HIGH.PRECEDENCE.TYAPP") diff --git a/src/Compiler/Driver/GraphChecking/FileContentMapping.fs b/src/Compiler/Driver/GraphChecking/FileContentMapping.fs index 38ce5a8d8cd..48376289dcc 100644 --- a/src/Compiler/Driver/GraphChecking/FileContentMapping.fs +++ b/src/Compiler/Driver/GraphChecking/FileContentMapping.fs @@ -1,4 +1,4 @@ -module internal rec FSharp.Compiler.GraphChecking.FileContentMapping +module internal rec FSharp.Compiler.GraphChecking.FileContentMapping open FSharp.Compiler.Syntax open FSharp.Compiler.SyntaxTreeOps @@ -127,7 +127,13 @@ let visitSynTypeDefn match simpleRepr with | SynTypeDefnSimpleRepr.Union(unionCases = unionCases) -> yield! List.collect visitSynUnionCase unionCases | SynTypeDefnSimpleRepr.Enum(cases = cases) -> yield! List.collect visitSynEnumCase cases - | SynTypeDefnSimpleRepr.Record(recordFields = recordFields) -> yield! List.collect visitSynField recordFields + | SynTypeDefnSimpleRepr.Record(recordFieldsAndSpreads = fieldsAndSpreads) -> + yield! + List.collect + (function + | SynFieldOrSpread.Field field -> visitSynField field + | SynFieldOrSpread.Spread spread -> visitSynTypeSpread spread) + fieldsAndSpreads // This is only used in the typed tree // The parser doesn't construct this | SynTypeDefnSimpleRepr.General _ @@ -168,7 +174,13 @@ let visitSynTypeDefnSig match simpleRepr with | SynTypeDefnSimpleRepr.Union(unionCases = unionCases) -> yield! List.collect visitSynUnionCase unionCases | SynTypeDefnSimpleRepr.Enum(cases = cases) -> yield! List.collect visitSynEnumCase cases - | SynTypeDefnSimpleRepr.Record(recordFields = recordFields) -> yield! List.collect visitSynField recordFields + | SynTypeDefnSimpleRepr.Record(recordFieldsAndSpreads = fieldsAndSpreads) -> + yield! + List.collect + (function + | SynFieldOrSpread.Field field -> visitSynField field + | SynFieldOrSpread.Spread spread -> visitSynTypeSpread spread) + fieldsAndSpreads // This is only used in the typed tree // The parser doesn't construct this | SynTypeDefnSimpleRepr.General _ @@ -204,6 +216,8 @@ let visitSynValSig (SynValSig(attributes = attributes; synType = synType; synExp let visitSynField (SynField(attributes = attributes; fieldType = fieldType)) = visitSynAttributes attributes @ visitSynType fieldType +let visitSynTypeSpread (SynTypeSpread(ty = ty)) = visitSynType ty + let visitSynMemberDefn (md: SynMemberDefn) : FileContentEntry list = [ match md with @@ -386,8 +400,19 @@ let visitSynExpr (e: SynExpr) : FileContentEntry list = | SynExpr.AnonRecd(copyInfo = copyInfo; recordFields = recordFields) -> let continuations = match copyInfo with - | None -> List.map (fun (_, _, e) -> visit e) recordFields - | Some(cp, _) -> visit cp :: List.map (fun (_, _, e) -> visit e) recordFields + | None -> + List.map + (function + | SynExprAnonRecordFieldOrSpread.Field(SynExprAnonRecordField(_, _, e, _), _) + | SynExprAnonRecordFieldOrSpread.Spread(spread = SynExprSpread(expr = e)) -> visit e) + recordFields + | Some(cp, _) -> + visit cp + :: List.map + (function + | SynExprAnonRecordFieldOrSpread.Field(SynExprAnonRecordField(_, _, e, _), _) + | SynExprAnonRecordFieldOrSpread.Spread(spread = SynExprSpread(expr = e)) -> visit e) + recordFields Continuation.concatenate continuations continuation | SynExpr.ArrayOrList(exprs = exprs) -> @@ -396,9 +421,12 @@ let visitSynExpr (e: SynExpr) : FileContentEntry list = | SynExpr.Record(baseInfo = baseInfo; copyInfo = copyInfo; recordFields = recordFields) -> let fieldNodes = [ - for SynExprRecordField(fieldName = (si, _); expr = expr) in recordFields do - yield! visitSynLongIdent si - yield! collectFromOption visitSynExpr expr + for fieldOrSpread in recordFields do + match fieldOrSpread with + | SynExprRecordFieldOrSpread.Field(SynExprRecordField(fieldName = (si, _); expr = expr), _) -> + yield! visitSynLongIdent si + yield! collectFromOption visitSynExpr expr + | SynExprRecordFieldOrSpread.Spread(spread = SynExprSpread(expr = expr)) -> yield! visitSynExpr expr ] match baseInfo, copyInfo with diff --git a/src/Compiler/FSComp.txt b/src/Compiler/FSComp.txt index 2b4bc25c5a7..5af5d874d05 100644 --- a/src/Compiler/FSComp.txt +++ b/src/Compiler/FSComp.txt @@ -1828,3 +1828,18 @@ featureErrorOnMissingSignatureAttribute,"error (rather than warning) when an enf featureNotNullIfNotNull,"honor the 'NotNullIfNotNull' attribute on a method's return value" featureAccessProtectedBaseFieldFromClosure,"Access a protected base-class field from a closure inside a member" featureImprovedImpliedArgumentNamesPartTwo,"Improved implied argument names with partial application" +3891,tcRecordTypeDefinitionSpreadSourceMustBeRecord,"The source type of a spread into a record type definition must itself be a nominal or anonymous record type." +3892,tcRecordTypeDefinitionSpreadSourceCannotBeNullable,"The source type of a spread into a record type definition cannot be nullable." +3893,tcRecordExprSpreadSourceMustBeRecord,"The source expression of a spread into a nominal record expression must have a nominal or anonymous record type." +3894,tcRecordExprSpreadSourceCannotBeNullable,"The source expression of a spread into a nominal record expression cannot be nullable." +3895,tcAnonRecordExprSpreadSourceMustBeRecord,"The source expression of a spread into an anonymous record expression must have a nominal or anonymous record type." +3896,tcAnonRecordExprSpreadSourceCannotBeNullable,"The source expression of a spread into an anonymous record expression cannot be nullable." +3897,tcRecordTypeDefinitionSpreadFieldShadowsExplicitField,"Spread field '%s' from type '%s' shadows an explicitly declared field with the same name." +3898,tcRecordExprSpreadFieldShadowsExplicitField,"Spread field '%s' shadows an explicitly declared field with the same name." +3899,parsMissingSpreadSrcExpr,"Missing spread source expression after '...'." +3900,parsMissingSpreadSrcTy,"Missing spread source type after '...'." +3901,tcTypeDefinitionIsCyclicThroughSpreads,"This type definition involves a cyclic reference through a spread." +3902,parsSpreadNotSupported,"Spreading is not supported in this construct." +3903,parsSpreadNotSupportedBeforeWith,"Spreading is not supported in this position. Use one of the forms {{ ...expr1; A = expr2 }} or {{ expr1 with A = expr2 }} instead." +3904,tcRecordExprSpreadWithCannotBeUsedWithSpreads,"Spread expressions and 'with' cannot be used together in the same copy-and-update expression." +featureRecordSpreads,"record type and expression spreads" diff --git a/src/Compiler/FSStrings.resx b/src/Compiler/FSStrings.resx index 698881678c2..ef058b350c1 100644 --- a/src/Compiler/FSStrings.resx +++ b/src/Compiler/FSStrings.resx @@ -371,10 +371,10 @@ symbol '>|}' - + symbol '@>|}' or '@@>|}' - + symbol '>|]' @@ -1179,4 +1179,7 @@ No constructors are available for the type '{0}' + + symbol '...' + \ No newline at end of file diff --git a/src/Compiler/FSharp.Compiler.Service.fsproj b/src/Compiler/FSharp.Compiler.Service.fsproj index 1f5278f6ecc..bd9be2c907f 100644 --- a/src/Compiler/FSharp.Compiler.Service.fsproj +++ b/src/Compiler/FSharp.Compiler.Service.fsproj @@ -407,6 +407,7 @@ + diff --git a/src/Compiler/Facilities/LanguageFeatures.fs b/src/Compiler/Facilities/LanguageFeatures.fs index 1356335fd28..e4feee0c451 100644 --- a/src/Compiler/Facilities/LanguageFeatures.fs +++ b/src/Compiler/Facilities/LanguageFeatures.fs @@ -113,6 +113,7 @@ type LanguageFeature = | NotNullIfNotNull | AccessProtectedBaseFieldFromClosure | ImprovedImpliedArgumentNamesPartTwo + | RecordSpreads /// LanguageVersion management type LanguageVersion(versionText, ?disabledFeaturesArray: LanguageFeature array) = @@ -269,6 +270,7 @@ type LanguageVersion(versionText, ?disabledFeaturesArray: LanguageFeature array) LanguageFeature.ImplicitDIMCoverage, languageVersion110 LanguageFeature.ErrorOnMissingSignatureAttribute, previewVersion // Opt-in: turn FS3888 from warning into error LanguageFeature.AccessProtectedBaseFieldFromClosure, previewVersion // #5302: read a protected base field from a closure + LanguageFeature.RecordSpreads, previewVersion ] static let defaultLanguageVersion = LanguageVersion("default") @@ -468,6 +470,7 @@ type LanguageVersion(versionText, ?disabledFeaturesArray: LanguageFeature array) | LanguageFeature.NotNullIfNotNull -> FSComp.SR.featureNotNullIfNotNull () | LanguageFeature.AccessProtectedBaseFieldFromClosure -> FSComp.SR.featureAccessProtectedBaseFieldFromClosure () | LanguageFeature.ImprovedImpliedArgumentNamesPartTwo -> FSComp.SR.featureImprovedImpliedArgumentNamesPartTwo () + | LanguageFeature.RecordSpreads -> FSComp.SR.featureRecordSpreads () /// Get a version string associated with the given feature. static member GetFeatureVersionString feature = diff --git a/src/Compiler/Facilities/LanguageFeatures.fsi b/src/Compiler/Facilities/LanguageFeatures.fsi index c5d4009bc04..e77a0a377a7 100644 --- a/src/Compiler/Facilities/LanguageFeatures.fsi +++ b/src/Compiler/Facilities/LanguageFeatures.fsi @@ -104,6 +104,7 @@ type LanguageFeature = | NotNullIfNotNull | AccessProtectedBaseFieldFromClosure | ImprovedImpliedArgumentNamesPartTwo + | RecordSpreads /// LanguageVersion management type LanguageVersion = diff --git a/src/Compiler/Service/FSharpCheckerResults.fs b/src/Compiler/Service/FSharpCheckerResults.fs index c7b36f720e2..f31fa90332a 100644 --- a/src/Compiler/Service/FSharpCheckerResults.fs +++ b/src/Compiler/Service/FSharpCheckerResults.fs @@ -1567,11 +1567,16 @@ type internal TypeCheckInfo allSymbols: unit -> AssemblySymbol list, options: FSharpCodeCompletionOptions ) = + let isSpread = + FindFirstNonWhitespacePosition lineStr (colAtEndOfNamesAndResidue - 1) + |> Option.exists (fun i -> + (i > 2 && lineStr[i - 3] <> '.' || i = 2) + && lineStr.AsSpan(i - 2).StartsWith("...".AsSpan())) // Are the last two chars (except whitespaces) = ".." let isLikeRangeOp = match FindFirstNonWhitespacePosition lineStr (colAtEndOfNamesAndResidue - 1) with - | Some x when x >= 1 && lineStr[x] = '.' && lineStr[x - 1] = '.' -> true + | Some x when not isSpread && x >= 1 && lineStr[x] = '.' && lineStr[x - 1] = '.' -> true | _ -> false // if last two chars are .. and we are not in range operator context - no completion @@ -1601,7 +1606,7 @@ type internal TypeCheckInfo |> Option.orElseWith (fun _ -> FindFirstNonWhitespacePosition lineStr (colAtEndOfNamesAndResidue - 1)) match lastPos with - | Some p when lineStr[p] = '.' -> + | Some p when not isSpread && lineStr[p] = '.' -> match FindFirstNonWhitespacePosition lineStr (p - 1) with | Some colAtEndOfNames -> let colAtEndOfNames = colAtEndOfNames + 1 // convert 0-based to 1-based @@ -1640,7 +1645,7 @@ type internal TypeCheckInfo lastDotPos |> Option.orElseWith (fun _ -> FindFirstNonWhitespacePosition lineStr (colAtEndOfNamesAndResidue - 1)) with - | Some p when lineStr[p] = '.' -> + | Some p when not isSpread && lineStr[p] = '.' -> match FindFirstNonWhitespacePosition lineStr (p - 1) with | Some colAtEndOfNames -> let colAtEndOfNames = colAtEndOfNames + 1 // convert 0-based to 1-based @@ -1970,6 +1975,44 @@ type internal TypeCheckInfo // No completion at '...: string' | Some(CompletionContext.RecordField(RecordContext.Declaration true)) -> None + // Completion at 'let r = { ...| }' + | Some(CompletionContext.RecordSpread RecordSpreadContext.Construction) -> + let envItems = getDeclaredItemsNotInRangeOpWithAllSymbols () + + envItems + |> Option.map (fun (items, denv, m) -> + let items = + [ + for completionItem in items do + match completionItem.Item with + | Item.Value vref when isRecdTy g vref.Type || isAnonRecdTy g vref.Type -> completionItem + | _ -> () + ] + + items, denv, m) + + // Completion at 'type R = { ...| }' + | Some(CompletionContext.RecordSpread RecordSpreadContext.Declaration) -> + let (nenv, ad), m = GetBestEnvForPos pos + let recordTycons = getRecordTyconsInScope g ncenv nenv ad m + + let completionItems = + [ + for tcref, item in recordTycons -> + { + ItemWithInst = ItemWithNoInst item + Kind = CompletionItemKind.Other + MinorPriority = 0 + IsOwnMember = false + Type = Some tcref + Unresolved = None + CustomInsertText = ValueNone + CustomDisplayText = ValueNone + } + ] + + Some(completionItems, nenv.DisplayEnv, m) + // Completion at ' SomeMethod( ... ) ' or ' [] ' with named arguments | Some(CompletionContext.ParameterList(endPos, fields)) -> let results = diff --git a/src/Compiler/Service/FSharpParseFileResults.fs b/src/Compiler/Service/FSharpParseFileResults.fs index 119669f22d9..7fd257947b5 100644 --- a/src/Compiler/Service/FSharpParseFileResults.fs +++ b/src/Compiler/Service/FSharpParseFileResults.fs @@ -633,14 +633,26 @@ type FSharpParseFileResults(diagnostics: FSharpDiagnostic[], input: ParsedInput, | Some(e, _) -> yield! walkExpr true e | None -> () - yield! walkExprs (fs |> List.choose (fun (SynExprRecordField(expr = e)) -> e)) + yield! + walkExprs ( + fs + |> List.choose (function + | SynExprRecordFieldOrSpread.Field(SynExprRecordField(expr = e), _) -> e + | SynExprRecordFieldOrSpread.Spread(spread = SynExprSpread(expr = e)) -> Some e) + ) | SynExpr.AnonRecd(copyInfo = copyExprOpt; recordFields = fs) -> match copyExprOpt with | Some(e, _) -> yield! walkExpr true e | None -> () - yield! walkExprs (fs |> List.map (fun (_, _, e) -> e)) + yield! + walkExprs ( + fs + |> List.map (function + | SynExprAnonRecordFieldOrSpread.Field(SynExprAnonRecordField(_, _, e, _), _) + | SynExprAnonRecordFieldOrSpread.Spread(spread = SynExprSpread(expr = e)) -> e) + ) | SynExpr.ObjExpr(argOptions = args; bindings = bs; members = ms; extraImpls = is) -> let bs = unionBindingAndMembers bs ms diff --git a/src/Compiler/Service/ServiceInterfaceStubGenerator.fs b/src/Compiler/Service/ServiceInterfaceStubGenerator.fs index 2687b4e0f54..096ea38438f 100644 --- a/src/Compiler/Service/ServiceInterfaceStubGenerator.fs +++ b/src/Compiler/Service/ServiceInterfaceStubGenerator.fs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. namespace FSharp.Compiler.EditorServices @@ -850,7 +850,11 @@ module InterfaceStubGenerator = | SynExpr.ArrayOrList(_, synExprList, _range) -> List.tryPick walkExpr synExprList | SynExpr.Record(_inheritOpt, _copyOpt, fields, _range) -> - List.tryPick (fun (SynExprRecordField(expr = e)) -> Option.bind walkExpr e) fields + List.tryPick + (function + | SynExprRecordFieldOrSpread.Field(SynExprRecordField(expr = e), _) -> Option.bind walkExpr e + | SynExprRecordFieldOrSpread.Spread(spread = SynExprSpread(expr = e)) -> walkExpr e) + fields | SynExpr.New(_, _synType, synExpr, _range) -> walkExpr synExpr diff --git a/src/Compiler/Service/ServiceLexing.fs b/src/Compiler/Service/ServiceLexing.fs index 5ce87706c51..e8e05595b75 100644 --- a/src/Compiler/Service/ServiceLexing.fs +++ b/src/Compiler/Service/ServiceLexing.fs @@ -63,6 +63,7 @@ module FSharpTokenTag = let DOT = tagOfToken DOT let DOT_DOT = tagOfToken DOT_DOT let DOT_DOT_HAT = tagOfToken DOT_DOT_HAT + let DOT_DOT_DOT = tagOfToken DOT_DOT_DOT let INT32_DOT_DOT = tagOfToken (INT32_DOT_DOT(0, true)) let UNDERSCORE = tagOfToken UNDERSCORE let BAR = tagOfToken BAR @@ -233,7 +234,8 @@ module internal TokenClassifications = | INFIX_AMP_OP _ -> (FSharpTokenColorKind.Operator, FSharpTokenCharKind.Operator, FSharpTokenTriggerClass.None) | DOT_DOT - | DOT_DOT_HAT -> (FSharpTokenColorKind.Operator, FSharpTokenCharKind.Operator, FSharpTokenTriggerClass.MemberSelect) + | DOT_DOT_HAT + | DOT_DOT_DOT -> (FSharpTokenColorKind.Operator, FSharpTokenCharKind.Operator, FSharpTokenTriggerClass.MemberSelect) | COMMA -> (FSharpTokenColorKind.Punctuation, FSharpTokenCharKind.Delimiter, FSharpTokenTriggerClass.ParamNext) @@ -1322,6 +1324,7 @@ type FSharpTokenKind = | End | DotDot | DotDotHat + | DotDotDot | BarBar | Upcast | Downcast @@ -1521,6 +1524,7 @@ type FSharpToken = | END -> FSharpTokenKind.End | DOT_DOT -> FSharpTokenKind.DotDot | DOT_DOT_HAT -> FSharpTokenKind.DotDotHat + | DOT_DOT_DOT -> FSharpTokenKind.DotDotDot | BAR_BAR -> FSharpTokenKind.BarBar | UPCAST -> FSharpTokenKind.Upcast | DOWNCAST -> FSharpTokenKind.Downcast diff --git a/src/Compiler/Service/ServiceLexing.fsi b/src/Compiler/Service/ServiceLexing.fsi index fab55c4645e..4aad2727e7e 100755 --- a/src/Compiler/Service/ServiceLexing.fsi +++ b/src/Compiler/Service/ServiceLexing.fsi @@ -176,9 +176,12 @@ module FSharpTokenTag = /// Indicates the token is a `..` val DOT_DOT: int - /// Indicates the token is a `..` + /// Indicates the token is a `..^` val DOT_DOT_HAT: int + /// Indicates the token is a `...` + val DOT_DOT_DOT: int + /// Indicates the token is a `..^` val INT32_DOT_DOT: int @@ -500,6 +503,7 @@ type public FSharpTokenKind = | End | DotDot | DotDotHat + | DotDotDot | BarBar | Upcast | Downcast diff --git a/src/Compiler/Service/ServiceNavigation.fs b/src/Compiler/Service/ServiceNavigation.fs index a56b4d4eb6e..2da61ee108e 100755 --- a/src/Compiler/Service/ServiceNavigation.fs +++ b/src/Compiler/Service/ServiceNavigation.fs @@ -289,12 +289,14 @@ module NavigationImpl = createTypeDecl (baseName, lid, FSharpGlyph.Enum, m, mBody, nested, NavigationEntityKind.Enum, access) ] - | SynTypeDefnSimpleRepr.Record(_, fields, mBody) -> + | SynTypeDefnSimpleRepr.Record(_, fieldsAndSpreads, mBody) -> let fields = [ - for SynField(idOpt = id; range = m) in fields do - match id with - | Some ident -> yield createMember (ident, NavigationItemKind.Field, FSharpGlyph.Field, m, NavigationEntityKind.Record, false, access) + for fieldOrSpread in fieldsAndSpreads do + match fieldOrSpread with + | SynFieldOrSpread.Field(SynField(idOpt = Some ident; range = m)) -> + yield createMember (ident, NavigationItemKind.Field, FSharpGlyph.Field, m, NavigationEntityKind.Record, false, access) + | SynFieldOrSpread.Spread _ | _ -> () ] @@ -546,12 +548,14 @@ module NavigationImpl = let nested = cases @ topMembers let mBody = bodyRange mBody nested createTypeDecl (baseName, lid, FSharpGlyph.Enum, m, mBody, nested, NavigationEntityKind.Enum, access) - | SynTypeDefnSimpleRepr.Record(_, fields, mBody) -> + | SynTypeDefnSimpleRepr.Record(_, fieldsAndSpreads, mBody) -> let fields = [ - for SynField(idOpt = id; range = m) in fields do - match id with - | Some ident -> yield createMember (ident, NavigationItemKind.Field, FSharpGlyph.Field, m, NavigationEntityKind.Record, false, access) + for fieldOrSpread in fieldsAndSpreads do + match fieldOrSpread with + | SynFieldOrSpread.Field(SynField(idOpt = Some ident; range = m)) -> + yield createMember (ident, NavigationItemKind.Field, FSharpGlyph.Field, m, NavigationEntityKind.Record, false, access) + | SynFieldOrSpread.Spread _ | _ -> () ] @@ -994,10 +998,12 @@ module NavigateTo = | SynTypeDefnSimpleRepr.Enum(enumCases, _) -> for c in enumCases do addEnumCase c isSig container - | SynTypeDefnSimpleRepr.Record(_, fields, _) -> - for f in fields do + | SynTypeDefnSimpleRepr.Record(_, fieldsAndSpreads, _) -> + for fieldOrSpread in fieldsAndSpreads do // TODO: add specific case for record field? - addField f isSig container + match fieldOrSpread with + | SynFieldOrSpread.Field f -> addField f isSig container + | SynFieldOrSpread.Spread _ -> () | SynTypeDefnSimpleRepr.Union(_, unionCases, _) -> for uc in unionCases do addUnionCase uc isSig container diff --git a/src/Compiler/Service/ServiceParseTreeWalk.fs b/src/Compiler/Service/ServiceParseTreeWalk.fs index 4a1177b7b26..4b1df951386 100644 --- a/src/Compiler/Service/ServiceParseTreeWalk.fs +++ b/src/Compiler/Service/ServiceParseTreeWalk.fs @@ -110,10 +110,10 @@ type SyntaxVisitorBase<'T>() = None /// VisitRecordDefn allows overriding behavior when visiting record definitions (by default do nothing) - abstract VisitRecordDefn: path: SyntaxVisitorPath * fields: SynField list * range -> 'T option + abstract VisitRecordDefn: path: SyntaxVisitorPath * fieldsAndSpreads: SynFieldOrSpread list * range -> 'T option - default _.VisitRecordDefn(path, fields, range) = - ignore (path, fields, range) + default _.VisitRecordDefn(path, fieldsAndSpreads, range) = + ignore (path, fieldsAndSpreads, range) None /// VisitUnionDefn allows overriding behavior when visiting union definitions (by default do nothing) @@ -458,9 +458,14 @@ module SyntaxTraversal = None) | _ -> () - for field, _, x in fields do - yield dive () field.Range (fun () -> visitor.VisitRecordField(path, copyOpt |> Option.map fst, Some field)) - yield dive x x.Range traverseSynExpr + for fieldOrSpread in fields do + match fieldOrSpread with + | SynExprAnonRecordFieldOrSpread.Field(SynExprAnonRecordField(field, _, x, _), _) -> + yield dive () field.Range (fun () -> visitor.VisitRecordField(path, copyOpt |> Option.map fst, Some field)) + yield dive x x.Range traverseSynExpr + | SynExprAnonRecordFieldOrSpread.Spread(spread = SynExprSpread(expr = expr; range = m)) -> + yield dive () m (fun () -> visitor.VisitExpr(path, traverseSynExpr, traverseSynExpr, expr)) + yield dive expr expr.Range traverseSynExpr ] |> pick expr @@ -525,57 +530,74 @@ module SyntaxTraversal = let copyOpt = Option.map fst copyOpt - for SynExprRecordField(fieldName = (field, _); expr = e; blockSeparator = sepOpt) in fields do - yield - dive (path, copyOpt, Some field) field.Range (fun r -> - // Treat the caret placed right after the field name (before '=' or a value) as "inside" the field, - // but only if the field does not yet have a value. - // - // Examples (the '$' marks the caret): - // { r with Field1$ } - // { r with - // Field1$ - // } - let isCaretAfterFieldNameWithoutValue = (e.IsNone && posEq pos field.Range.End) - - if rangeContainsPos field.Range pos || isCaretAfterFieldNameWithoutValue then - visitor.VisitRecordField r - else - None) - - let offsideColumn = - match inheritOpt with - | Some(_, _, _, _, inheritRange) -> inheritRange.StartColumn - | None -> field.Range.StartColumn - - match e with - | Some e -> + for fieldOrSpread in fields do + match fieldOrSpread with + | SynExprRecordFieldOrSpread.Field(SynExprRecordField(fieldName = (field, _); expr = e), sepOpt) -> yield - dive e e.Range (fun expr -> - // special case: caret is below field binding - // field x = 5 - // $ - if - not (rangeContainsPos e.Range pos) - && sepOpt.IsNone - && pos.Column = offsideColumn - then - visitor.VisitRecordField(path, copyOpt, None) + dive (path, copyOpt, Some field) field.Range (fun r -> + // Treat the caret placed right after the field name (before '=' or a value) as "inside" the field, + // but only if the field does not yet have a value. + // + // Examples (the '$' marks the caret): + // { r with Field1$ } + // { r with + // Field1$ + // } + let isCaretAfterFieldNameWithoutValue = (e.IsNone && posEq pos field.Range.End) + + if rangeContainsPos field.Range pos || isCaretAfterFieldNameWithoutValue then + visitor.VisitRecordField r else - traverseSynExpr expr) - | None -> () - - match sepOpt with - | Some(sep, scPosOpt) -> - yield - dive () sep (fun () -> - // special case: caret is between field bindings - // field1 = 5 - // $ - // field2 = 5 - diveIntoSeparator offsideColumn scPosOpt copyOpt) - | _ -> () - + None) + + let offsideColumn = + match inheritOpt with + | Some(_, _, _, _, inheritRange) -> inheritRange.StartColumn + | None -> field.Range.StartColumn + + match e with + | Some e -> + yield + dive e e.Range (fun expr -> + // special case: caret is below field binding + // field x = 5 + // $ + if + not (rangeContainsPos e.Range pos) + && sepOpt.IsNone + && pos.Column = offsideColumn + then + visitor.VisitRecordField(path, copyOpt, None) + else + traverseSynExpr expr) + | None -> () + + match sepOpt with + | Some(sep, scPosOpt) -> + yield + dive () sep (fun () -> + // special case: caret is between field bindings + // field1 = 5 + // $ + // field2 = 5 + diveIntoSeparator offsideColumn scPosOpt copyOpt) + | None -> () + + | SynExprRecordFieldOrSpread.Spread(SynExprSpread(spreadRange = spreadRange; expr = expr; range = m), sepOpt) -> + yield dive () m (fun () -> visitor.VisitExpr(path, traverseSynExpr, traverseSynExpr, expr)) + yield dive expr expr.Range traverseSynExpr + + match sepOpt with + | Some(sep, scPosOpt) -> + yield + dive () sep (fun () -> + // special case: caret is between field bindings + // field1 = 5 + // $ + // field2 = 5 + let offsideColumn = spreadRange.StartColumn + diveIntoSeparator offsideColumn scPosOpt copyOpt) + | None -> () ] |> pick expr @@ -909,10 +931,13 @@ module SyntaxTraversal = ] |> pick tRange tydef - and traverseRecordDefn path fields m = - fields - |> List.tryPick (fun (SynField(attributes = attributes)) -> attributeApplicationDives path attributes |> pick m attributes) - |> Option.orElseWith (fun () -> visitor.VisitRecordDefn(path, fields, m)) + and traverseRecordDefn path fieldsAndSpreads m = + fieldsAndSpreads + |> List.tryPick (function + | SynFieldOrSpread.Field(SynField(attributes = attributes)) -> + attributeApplicationDives path attributes |> pick m attributes + | SynFieldOrSpread.Spread _ -> None) + |> Option.orElseWith (fun () -> visitor.VisitRecordDefn(path, fieldsAndSpreads, m)) and traverseEnumDefn path cases m = cases @@ -1160,7 +1185,12 @@ module SyntaxTraversal = module SyntaxNode = let (|Attributes|) node = let (|All|) = List.collect - let field (SynField(attributes = attributes)) = attributes + + let fieldOrSpread = + function + | SynFieldOrSpread.Field(SynField(attributes = attributes)) -> attributes + | SynFieldOrSpread.Spread _ -> [] + let unionCase (SynUnionCase(attributes = attributes)) = attributes let enumCase (SynEnumCase(attributes = attributes)) = attributes let typar (SynTyparDecl(attributes = attributes)) = attributes @@ -1186,7 +1216,7 @@ module SyntaxNode = | SyntaxNode.SynModule(SynModuleDecl.Attributes(attributes = attributes)) | SyntaxNode.SynTypeDefn(SynTypeDefn(typeInfo = SynComponentInfo attributes)) | SyntaxNode.SynTypeDefn(SynTypeDefn( - typeRepr = SynTypeDefnRepr.Simple(SynTypeDefnSimpleRepr.Record(recordFields = All field attributes), _))) + typeRepr = SynTypeDefnRepr.Simple(SynTypeDefnSimpleRepr.Record(recordFieldsAndSpreads = All fieldOrSpread attributes), _))) | SyntaxNode.SynTypeDefn(SynTypeDefn( typeRepr = SynTypeDefnRepr.Simple(SynTypeDefnSimpleRepr.Union(unionCases = All unionCase attributes), _))) | SyntaxNode.SynTypeDefn(SynTypeDefn( diff --git a/src/Compiler/Service/ServiceParseTreeWalk.fsi b/src/Compiler/Service/ServiceParseTreeWalk.fsi index ab9e98f6e81..d8a9e142148 100644 --- a/src/Compiler/Service/ServiceParseTreeWalk.fsi +++ b/src/Compiler/Service/ServiceParseTreeWalk.fsi @@ -101,8 +101,8 @@ type SyntaxVisitorBase<'T> = range: range -> 'T option - abstract VisitRecordDefn: path: SyntaxVisitorPath * fields: SynField list * range -> 'T option - default VisitRecordDefn: path: SyntaxVisitorPath * fields: SynField list * range -> 'T option + abstract VisitRecordDefn: path: SyntaxVisitorPath * fieldsAndSpreads: SynFieldOrSpread list * range -> 'T option + default VisitRecordDefn: path: SyntaxVisitorPath * fieldsAndSpreads: SynFieldOrSpread list * range -> 'T option abstract VisitUnionDefn: path: SyntaxVisitorPath * cases: SynUnionCase list * range -> 'T option default VisitUnionDefn: path: SyntaxVisitorPath * cases: SynUnionCase list * range -> 'T option diff --git a/src/Compiler/Service/ServiceParsedInputOps.fs b/src/Compiler/Service/ServiceParsedInputOps.fs index 00dbde0eae9..cfc181ef355 100644 --- a/src/Compiler/Service/ServiceParsedInputOps.fs +++ b/src/Compiler/Service/ServiceParsedInputOps.fs @@ -50,6 +50,14 @@ type RecordContext = | New of path: CompletionPath * isFirstField: bool | Declaration of isInIdentifier: bool +[] +type RecordSpreadContext = + /// type R = { ...| } + | Declaration + + /// let r = { ...| } + | Construction + [] type PatternContext = /// Completing union case field pattern (e.g. fun (Some v| ) -> ) or fun (Some (v| )) -> ). In theory, this could also be parameterized active pattern usage. @@ -87,6 +95,9 @@ type CompletionContext = /// Completing records field | RecordField of context: RecordContext + /// Completing a record spread: { ...| } + | RecordSpread of context: RecordSpreadContext + | RangeOperator /// Completing named parameters\setters in parameter list of attributes\constructor\method calls @@ -808,7 +819,10 @@ module ParsedInput = | SynExpr.Record(_, _, fields, r) -> ifPosInRange r (fun _ -> fields - |> List.tryPick (fun (SynExprRecordField(expr = e)) -> e |> Option.bind (walkExprWithKind parentKind))) + |> List.tryPick (function + | SynExprRecordFieldOrSpread.Field(SynExprRecordField(expr = e), _) -> + e |> Option.bind (walkExprWithKind parentKind) + | SynExprRecordFieldOrSpread.Spread(spread = SynExprSpread(expr = e)) -> walkExprWithKind parentKind e)) | SynExpr.ObjExpr(objType = ty; bindings = bindings; members = ms; extraImpls = ifaces) -> let bindings = unionBindingAndMembers bindings ms @@ -856,6 +870,8 @@ module ParsedInput = let (SynField(attributes = Attributes attrs; fieldType = t)) = synField List.tryPick walkAttribute attrs |> Option.orElseWith (fun () -> walkType t) + and walkTypeSpread (SynTypeSpread(ty = ty)) = walkType ty + and walkValSig synValSig = let (SynValSig(attributes = Attributes attrs; synType = t)) = synValSig List.tryPick walkAttribute attrs |> Option.orElseWith (fun () -> walkType t) @@ -929,7 +945,12 @@ module ParsedInput = match synTypeDefn with | SynTypeDefnSimpleRepr.Enum(cases, _) -> List.tryPick walkEnumCase cases | SynTypeDefnSimpleRepr.Union(_, cases, _) -> List.tryPick walkUnionCase cases - | SynTypeDefnSimpleRepr.Record(_, fields, _) -> List.tryPick walkField fields + | SynTypeDefnSimpleRepr.Record(_, fields, _) -> + List.tryPick + (function + | SynFieldOrSpread.Field field -> walkField field + | SynFieldOrSpread.Spread spread -> walkTypeSpread spread) + fields | SynTypeDefnSimpleRepr.TypeAbbrev(_, t, _) -> walkType t | _ -> None @@ -1479,6 +1500,26 @@ module ParsedInput = -> Some(CompletionContext.Inherit(InheritanceContext.Unknown, ([], None))) + // { ...$ } + | SynExpr.Record(recordFields = fields) -> + fields + |> List.tryPick (function + | SynExprRecordFieldOrSpread.Spread(SynExprSpread(expr = expr), _) when rangeContainsPos expr.Range pos -> + Some(CompletionContext.RecordSpread RecordSpreadContext.Construction) + | SynExprRecordFieldOrSpread.Spread _ + | SynExprRecordFieldOrSpread.Field _ -> None) + |> Option.orElseWith (fun () -> defaultTraverse expr) + + // {| ...$ |} + | SynExpr.AnonRecd(recordFields = fields) -> + fields + |> List.tryPick (function + | SynExprAnonRecordFieldOrSpread.Spread(SynExprSpread(expr = expr), _) when rangeContainsPos expr.Range pos -> + Some(CompletionContext.RecordSpread RecordSpreadContext.Construction) + | SynExprAnonRecordFieldOrSpread.Spread _ + | SynExprAnonRecordFieldOrSpread.Field _ -> None) + |> Option.orElseWith (fun () -> defaultTraverse expr) + | _ -> defaultTraverse expr member _.VisitRecordField(path, copyOpt, field) = @@ -1488,10 +1529,12 @@ module ParsedInput = | SyntaxNode.SynExpr _ :: SyntaxNode.SynBinding _ :: SyntaxNode.SynMemberDefn _ :: SyntaxNode.SynTypeDefn(SynTypeDefn( typeInfo = SynComponentInfo(longId = [ id ]))) :: _ -> RecordContext.Constructor(id.idText) - | SyntaxNode.SynExpr(SynExpr.Record(None, _, fields, _)) :: _ -> + | SyntaxNode.SynExpr(SynExpr.Record(None, _, fieldsAndSpreads, _)) :: _ -> let isFirstField = - match field, fields with - | Some contextLid, SynExprRecordField(fieldName = lid, _) :: _ -> contextLid.Range = lid.Range + match field, fieldsAndSpreads with + | Some contextLid, SynExprRecordFieldOrSpread.Field(SynExprRecordField(fieldName = lid, _), _) :: _ -> + contextLid.Range = lid.Range + | Some _, SynExprRecordFieldOrSpread.Spread _ :: _ -> false | _ -> false RecordContext.New(completionPath, isFirstField) @@ -1780,13 +1823,19 @@ module ParsedInput = member _.VisitRecordDefn(_, fields, range) = fields - |> List.tryPick (fun (SynField(idOpt = idOpt; range = fieldRange; fieldType = fieldType)) -> - match idOpt, fieldType with - | Some id, _ when rangeContainsPos id.idRange pos -> - Some(CompletionContext.RecordField(RecordContext.Declaration true)) - | _ when rangeContainsPos fieldRange pos -> Some(CompletionContext.RecordField(RecordContext.Declaration false)) - | _, SynType.FromParseError _ -> Some(CompletionContext.RecordField(RecordContext.Declaration false)) - | _ -> None) + |> List.tryPick (function + | SynFieldOrSpread.Field(SynField(idOpt = idOpt; range = fieldRange; fieldType = fieldType)) -> + match idOpt, fieldType with + | Some id, _ when rangeContainsPos id.idRange pos -> + Some(CompletionContext.RecordField(RecordContext.Declaration true)) + | _ when rangeContainsPos fieldRange pos -> Some(CompletionContext.RecordField(RecordContext.Declaration false)) + | _, SynType.FromParseError _ -> Some(CompletionContext.RecordField(RecordContext.Declaration false)) + | _ -> None + | SynFieldOrSpread.Spread(SynTypeSpread(ty = ty)) -> + if rangeContainsPos ty.Range pos then + Some(CompletionContext.RecordSpread RecordSpreadContext.Declaration) + else + None) // No completions in a record outside of all fields, except in attributes, which is established earlier in VisitAttributeApplication |> Option.orElseWith (fun _ -> if rangeContainsPos range pos then @@ -2072,9 +2121,11 @@ module ParsedInput = | SynExpr.Record(recordFields = fields) -> fields - |> List.iter (fun (SynExprRecordField(fieldName = (ident, _); expr = e)) -> - addLongIdentWithDots ident - e |> Option.iter walkExpr) + |> List.iter (function + | SynExprRecordFieldOrSpread.Field(SynExprRecordField(fieldName = (ident, _); expr = e), _) -> + addLongIdentWithDots ident + e |> Option.iter walkExpr + | SynExprRecordFieldOrSpread.Spread(spread = SynExprSpread(expr = e)) -> walkExpr e) | SynExpr.Ident ident -> addIdent ident @@ -2197,6 +2248,8 @@ module ParsedInput = List.iter walkAttribute attrs walkType t + and walkTypeSpread (SynTypeSpread(ty = ty)) = walkType ty + and walkValSig (SynValSig(attributes = Attributes attrs; synType = t; arity = SynValInfo(argInfos, argInfo))) = List.iter walkAttribute attrs walkType t @@ -2268,7 +2321,12 @@ module ParsedInput = match typeDefn with | SynTypeDefnSimpleRepr.Enum(cases, _) -> List.iter walkEnumCase cases | SynTypeDefnSimpleRepr.Union(_, cases, _) -> List.iter walkUnionCase cases - | SynTypeDefnSimpleRepr.Record(_, fields, _) -> List.iter walkField fields + | SynTypeDefnSimpleRepr.Record(_, fields, _) -> + List.iter + (function + | SynFieldOrSpread.Field field -> walkField field + | SynFieldOrSpread.Spread spread -> walkTypeSpread spread) + fields | SynTypeDefnSimpleRepr.TypeAbbrev(_, t, _) -> walkType t | _ -> () diff --git a/src/Compiler/Service/ServiceParsedInputOps.fsi b/src/Compiler/Service/ServiceParsedInputOps.fsi index b063468dc50..1b28bfb18d3 100644 --- a/src/Compiler/Service/ServiceParsedInputOps.fsi +++ b/src/Compiler/Service/ServiceParsedInputOps.fsi @@ -22,6 +22,14 @@ type public RecordContext = | New of path: CompletionPath * isFirstField: bool | Declaration of isInIdentifier: bool +[] +type public RecordSpreadContext = + /// type R = { ...| } + | Declaration + + /// let r = { ...| } + | Construction + [] type public PatternContext = /// Completing union case field pattern (e.g. fun (Some v| ) -> ) or fun (Some (v| )) -> ). In theory, this could also be parameterized active pattern usage. @@ -59,6 +67,9 @@ type public CompletionContext = /// Completing records field | RecordField of context: RecordContext + /// Completing a record spread: { ...| } + | RecordSpread of context: RecordSpreadContext + | RangeOperator /// Completing named parameters\setters in parameter list of attributes\constructor\method calls diff --git a/src/Compiler/Service/ServiceStructure.fs b/src/Compiler/Service/ServiceStructure.fs index 577902a9146..fe85763c675 100644 --- a/src/Compiler/Service/ServiceStructure.fs +++ b/src/Compiler/Service/ServiceStructure.fs @@ -440,7 +440,9 @@ module Structure = | _ -> () recordFields - |> List.choose (fun (SynExprRecordField(expr = e)) -> e) + |> List.choose (function + | SynExprRecordFieldOrSpread.Field(SynExprRecordField(expr = e), _) -> e + | SynExprRecordFieldOrSpread.Spread(spread = SynExprSpread(expr = e)) -> Some e) |> List.iter parseExpr // exclude the opening `{` and closing `}` of the record from collapsing let m = Range.modBoth 1 1 r @@ -607,12 +609,15 @@ module Structure = rcheck Scope.EnumCase Collapse.Below cr cr parseAttributes attrs - | SynTypeDefnSimpleRepr.Record(_, fields, rr) -> + | SynTypeDefnSimpleRepr.Record(_, fieldsAndSpreads, rr) -> rcheck Scope.RecordDefn Collapse.Same rr rr - for SynField(attributes = attrs; range = fr) in fields do - rcheck Scope.RecordField Collapse.Below fr fr - parseAttributes attrs + for fieldOrSpread in fieldsAndSpreads do + match fieldOrSpread with + | SynFieldOrSpread.Field(SynField(attributes = attrs; range = fr)) -> + rcheck Scope.RecordField Collapse.Below fr fr + parseAttributes attrs + | SynFieldOrSpread.Spread _ -> () | SynTypeDefnSimpleRepr.Union(_, cases, ur) -> rcheck Scope.UnionDefn Collapse.Same ur ur diff --git a/src/Compiler/Service/SynExpr.fs b/src/Compiler/Service/SynExpr.fs index 8a81d77193e..deff02fe9b0 100644 --- a/src/Compiler/Service/SynExpr.fs +++ b/src/Compiler/Service/SynExpr.fs @@ -1116,8 +1116,13 @@ module SynExpr = let rec loop recordFields = match recordFields with | [] -> false - | SynExprRecordField(expr = Some(SynExpr.Paren(expr = Is inner)); blockSeparator = Some _) :: SynExprRecordField( - fieldName = SynLongIdent(id = id :: _), _) :: _ -> problematic inner.Range id.idRange + | SynExprRecordFieldOrSpread.Field( + field = SynExprRecordField(expr = Some(SynExpr.Paren(expr = Is inner))); blockSeparator = Some _) :: SynExprRecordFieldOrSpread.Field(SynExprRecordField( + fieldName = SynLongIdent( + id = id :: _), + _), + _) :: _ -> + problematic inner.Range id.idRange | _ :: recordFields -> loop recordFields loop recordFields @@ -1126,8 +1131,8 @@ module SynExpr = let rec loop recordFields = match recordFields with | [] -> false - | (_, Some _blockSeparator, SynExpr.Paren(expr = Is inner)) :: (SynLongIdent(id = id :: _), _, _) :: _ -> - problematic inner.Range id.idRange + | SynExprAnonRecordFieldOrSpread.Field(SynExprAnonRecordField(_, Some _equalsRange, SynExpr.Paren(expr = Is inner), _), + _) :: next :: _ -> problematic inner.Range next.Range | _ :: recordFields -> loop recordFields loop recordFields diff --git a/src/Compiler/SyntaxTree/LexFilter.fs b/src/Compiler/SyntaxTree/LexFilter.fs index e0e450c398f..96207878289 100644 --- a/src/Compiler/SyntaxTree/LexFilter.fs +++ b/src/Compiler/SyntaxTree/LexFilter.fs @@ -2374,6 +2374,7 @@ type LexFilterImpl ( match lookaheadTokenTup.Token with | RBRACE _ | IDENT _ + | DOT_DOT_DOT // The next clause detects the access annotations after the 'with' in: // member x.PublicGetSetProperty // with public get i = "Ralf" @@ -2414,18 +2415,26 @@ type LexFilterImpl ( // // with x = ... // + // or + // + // with ...spreadSrc + // // Which can only be part of // // { r with x = ... } // + // or + // + // { r with ...spreadSrc } + // // and in this case push a CtxtSeqBlock to cover the sequence - let isFollowedByLongIdentEquals = + let isFollowedByLongIdentEqualsOrDotDotDot = let tokenTup = popNextTokenTup() - let res = isLongIdentEquals tokenTup.Token + let res = isLongIdentEquals tokenTup.Token || match tokenTup.Token with DOT_DOT_DOT -> true | _ -> false delayToken tokenTup res - if isFollowedByLongIdentEquals then + if isFollowedByLongIdentEqualsOrDotDotDot then pushCtxtSeqBlock tokenTup NoAddBlockEnd returnToken tokenLexbufState OWITH diff --git a/src/Compiler/SyntaxTree/ParseHelpers.fs b/src/Compiler/SyntaxTree/ParseHelpers.fs index b329d48ee34..ff54b94af30 100644 --- a/src/Compiler/SyntaxTree/ParseHelpers.fs +++ b/src/Compiler/SyntaxTree/ParseHelpers.fs @@ -720,13 +720,27 @@ let rebindRanges first fields lastSep = | Some mEq -> unionRanges lidwd.Range mEq | None -> lidwd.Range - let rec run (name, mEquals, value: SynExpr option) l acc = - let lidwd, _ = name - let fieldRange = calculateFieldRange lidwd mEquals value - - match l with - | [] -> List.rev (SynExprRecordField(name, mEquals, value, fieldRange, lastSep) :: acc) - | (f, m) :: xs -> run f xs (SynExprRecordField(name, mEquals, value, fieldRange, m) :: acc) + let rec run fieldOrSpread l acc = + match fieldOrSpread with + | RecordBinding.Field((lidwd, _ as name), mEquals, value) -> + let fieldRange = calculateFieldRange lidwd mEquals value + + match l with + | [] -> + let field = + SynExprRecordFieldOrSpread.Field(SynExprRecordField(name, mEquals, value, fieldRange), lastSep) + + List.rev (field :: acc) + | (f, m) :: xs -> + let field = + SynExprRecordFieldOrSpread.Field(SynExprRecordField(name, mEquals, value, fieldRange), m) + + run f xs (field :: acc) + + | RecordBinding.Spread spread -> + match l with + | [] -> List.rev (SynExprRecordFieldOrSpread.Spread(spread, lastSep) :: acc) + | (f, _) :: xs -> run f xs (SynExprRecordFieldOrSpread.Spread(spread, lastSep) :: acc) run first fields [] diff --git a/src/Compiler/SyntaxTree/ParseHelpers.fsi b/src/Compiler/SyntaxTree/ParseHelpers.fsi index aae952d210c..b5286edf872 100644 --- a/src/Compiler/SyntaxTree/ParseHelpers.fsi +++ b/src/Compiler/SyntaxTree/ParseHelpers.fsi @@ -166,10 +166,10 @@ val exprFromParseError: e: SynExpr -> SynExpr val patFromParseError: e: SynPat -> SynPat val rebindRanges: - first: (RecordFieldName * range option * SynExpr option) -> - fields: ((RecordFieldName * range option * SynExpr option) * BlockSeparator option) list -> + first: RecordBinding -> + fields: (RecordBinding * BlockSeparator option) list -> lastSep: BlockSeparator option -> - SynExprRecordField list + SynExprRecordFieldOrSpread list val mkUnderscoreRecdField: m: range -> SynLongIdent * bool diff --git a/src/Compiler/SyntaxTree/SyntaxTree.fs b/src/Compiler/SyntaxTree/SyntaxTree.fs index f35bb3297de..27b01c376c6 100644 --- a/src/Compiler/SyntaxTree/SyntaxTree.fs +++ b/src/Compiler/SyntaxTree/SyntaxTree.fs @@ -317,6 +317,11 @@ type BlockSeparator = range * pos option type RecordFieldName = SynLongIdent * bool +[] +type RecordBinding = + | Field of name: RecordFieldName * equalsRange: range option * declExpr: SynExpr option + | Spread of spread: SynExprSpread + type ExprAtomicFlag = | Atomic = 0 | NonAtomic = 1 @@ -541,7 +546,7 @@ type SynExpr = | AnonRecd of isStruct: bool * copyInfo: (SynExpr * BlockSeparator) option * - recordFields: (SynLongIdent * range option * SynExpr) list * + recordFields: SynExprAnonRecordFieldOrSpread list * range: range * trivia: SynExprAnonRecdTrivia @@ -550,7 +555,7 @@ type SynExpr = | Record of baseInfo: (SynType * SynExpr * range * BlockSeparator option * range) option * copyInfo: (SynExpr * BlockSeparator) option * - recordFields: SynExprRecordField list * + recordFields: SynExprRecordFieldOrSpread list * range: range | New of isProtected: bool * targetType: SynType * expr: SynExpr * range: range @@ -864,13 +869,31 @@ type SynExpr = | _ -> false [] -type SynExprRecordField = - | SynExprRecordField of - fieldName: RecordFieldName * - equalsRange: range option * - expr: SynExpr option * - range: range * - blockSeparator: BlockSeparator option +type SynTypeSpread = SynTypeSpread of spreadRange: range * ty: SynType * range: range + +[] +type SynExprSpread = SynExprSpread of spreadRange: range * expr: SynExpr * range: range + +[] +type SynExprRecordField = SynExprRecordField of fieldName: RecordFieldName * equalsRange: range option * expr: SynExpr option * range: range + +[] +type SynExprRecordFieldOrSpread = + | Field of field: SynExprRecordField * blockSeparator: BlockSeparator option + | Spread of spread: SynExprSpread * blockSeparator: BlockSeparator option + +[] +type SynExprAnonRecordField = SynExprAnonRecordField of fieldName: SynLongIdent * equalsRange: range option * expr: SynExpr * range: range + +[] +type SynExprAnonRecordFieldOrSpread = + | Field of field: SynExprAnonRecordField * blockSeparator: BlockSeparator option + | Spread of spread: SynExprSpread * blockSeparator: BlockSeparator option + + member this.Range = + match this with + | SynExprAnonRecordFieldOrSpread.Field(SynExprAnonRecordField(_, _, _, m), _) + | SynExprAnonRecordFieldOrSpread.Spread(SynExprSpread(_, _, m), _) -> m [] type SynInterpolatedStringPart = @@ -1263,7 +1286,7 @@ type SynTypeDefnSimpleRepr = | Enum of cases: SynEnumCase list * range: range - | Record of accessibility: SynAccess option * recordFields: SynField list * range: range + | Record of accessibility: SynAccess option * recordFieldsAndSpreads: SynFieldOrSpread list * range: range | General of kind: SynTypeDefnKind * @@ -1296,6 +1319,11 @@ type SynTypeDefnSimpleRepr = | None(range = m) -> m | Exception t -> t.Range +[] +type SynFieldOrSpread = + | Field of field: SynField + | Spread of spread: SynTypeSpread + [] type SynEnumCase = diff --git a/src/Compiler/SyntaxTree/SyntaxTree.fsi b/src/Compiler/SyntaxTree/SyntaxTree.fsi index 8b152ba2d69..3b254636f68 100644 --- a/src/Compiler/SyntaxTree/SyntaxTree.fsi +++ b/src/Compiler/SyntaxTree/SyntaxTree.fsi @@ -363,6 +363,12 @@ type BlockSeparator = range * pos option /// correct and can be used in name resolution. type RecordFieldName = SynLongIdent * bool +/// Represents either a record field name or a spread expression. +[] +type RecordBinding = + | Field of name: RecordFieldName * equalsRange: range option * declExpr: SynExpr option + | Spread of spread: SynExprSpread + /// Indicates if an expression is an atomic expression. /// /// An atomic expression has no whitespace unless enclosed in parentheses, e.g. @@ -620,7 +626,7 @@ type SynExpr = | AnonRecd of isStruct: bool * copyInfo: (SynExpr * BlockSeparator) option * - recordFields: (SynLongIdent * range option * SynExpr) list * + recordFields: SynExprAnonRecordFieldOrSpread list * range: range * trivia: SynExprAnonRecdTrivia @@ -634,7 +640,7 @@ type SynExpr = | Record of baseInfo: (SynType * SynExpr * range * BlockSeparator option * range) option * copyInfo: (SynExpr * BlockSeparator) option * - recordFields: SynExprRecordField list * + recordFields: SynExprRecordFieldOrSpread list * range: range /// F# syntax: new C(...) @@ -987,14 +993,43 @@ type SynExpr = /// Indicates if this expression arises from error recovery member IsArbExprAndThusAlreadyReportedError: bool +/// Represents a type spread in a type definition. +/// +/// type Ty2 = { ...Ty1 } +[] +type SynTypeSpread = SynTypeSpread of spreadRange: range * ty: SynType * range: range + +/// Represents a spread expression. +/// +/// ...expr +[] +type SynExprSpread = SynExprSpread of spreadRange: range * expr: SynExpr * range: range + [] type SynExprRecordField = - | SynExprRecordField of - fieldName: RecordFieldName * - equalsRange: range option * - expr: SynExpr option * - range: range * - blockSeparator: BlockSeparator option + | SynExprRecordField of fieldName: RecordFieldName * equalsRange: range option * expr: SynExpr option * range: range + +/// Represents either a field declaration or a spread expression in a nominal record construction expression. +/// +/// let r = { A = 3; ...b; C = true } +[] +type SynExprRecordFieldOrSpread = + | Field of field: SynExprRecordField * blockSeparator: BlockSeparator option + | Spread of spread: SynExprSpread * blockSeparator: BlockSeparator option + +[] +type SynExprAnonRecordField = + | SynExprAnonRecordField of fieldName: SynLongIdent * equalsRange: range option * expr: SynExpr * range: range + +/// Represents either a field declaration or a spread expression in an anonymous record construction expression. +/// +/// let r = {| A = 3; ...b; C = true |} +[] +type SynExprAnonRecordFieldOrSpread = + | Field of field: SynExprAnonRecordField * blockSeparator: BlockSeparator option + | Spread of spread: SynExprSpread * blockSeparator: BlockSeparator option + + member Range: range [] type SynInterpolatedStringPart = @@ -1379,7 +1414,7 @@ type SynTypeDefnSimpleRepr = | Enum of cases: SynEnumCase list * range: range /// A record type definition, type X = { A: int; B: int } - | Record of accessibility: SynAccess option * recordFields: SynField list * range: range + | Record of accessibility: SynAccess option * recordFieldsAndSpreads: SynFieldOrSpread list * range: range /// An object oriented type definition. This is not a parse-tree form, but represents the core /// type representation which the type checker splits out from the "ObjectModel" cases of type definitions. @@ -1412,6 +1447,12 @@ type SynTypeDefnSimpleRepr = /// Gets the syntax range of this construct member Range: range +/// Represents either a field declaration or a type spread. +[] +type SynFieldOrSpread = + | Field of field: SynField + | Spread of spread: SynTypeSpread + /// Represents the syntax tree for one case in an enum definition. [] type SynEnumCase = diff --git a/src/Compiler/SyntaxTree/SyntaxTreeOps.fs b/src/Compiler/SyntaxTree/SyntaxTreeOps.fs index e6a995e3e19..ffca6718f56 100644 --- a/src/Compiler/SyntaxTree/SyntaxTreeOps.fs +++ b/src/Compiler/SyntaxTree/SyntaxTreeOps.fs @@ -1000,13 +1000,24 @@ let rec synExprContainsError inpExpr = (match origExpr with | Some(e, _) -> walkExpr e | None -> false) - || walkExprs (List.map (fun (_, _, e) -> e) flds) + || walkExprs ( + List.map + (function + | SynExprAnonRecordFieldOrSpread.Field(SynExprAnonRecordField(_, _, e, _), _) + | SynExprAnonRecordFieldOrSpread.Spread(spread = SynExprSpread(expr = e)) -> e) + flds + ) | SynExpr.Record(_, origExpr, fs, _) -> (match origExpr with | Some(e, _) -> walkExpr e | None -> false) - || (let flds = fs |> List.choose (fun (SynExprRecordField(expr = v)) -> v) + || (let flds = + fs + |> List.choose (function + | SynExprRecordFieldOrSpread.Field(SynExprRecordField(expr = v), _) -> v + | SynExprRecordFieldOrSpread.Spread(SynExprSpread(expr = e), _) -> Some e) + walkExprs flds) | SynExpr.ObjExpr(bindings = bs; members = ms; extraImpls = is) -> diff --git a/src/Compiler/lex.fsl b/src/Compiler/lex.fsl index ce4dd5955a6..ed6227723ea 100644 --- a/src/Compiler/lex.fsl +++ b/src/Compiler/lex.fsl @@ -850,6 +850,8 @@ rule token (args: LexArgs) (skip: bool) = parse | "..^" { DOT_DOT_HAT } + | "..." { DOT_DOT_DOT } + | "." { DOT } | ":" { COLON } diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy index 01120123a36..24a7cd63f70 100644 --- a/src/Compiler/pars.fsy +++ b/src/Compiler/pars.fsy @@ -80,7 +80,7 @@ let parse_error_rich = Some(fun (ctxt: ParseErrorContext<_>) -> %token PERCENT_OP BINDER %token LQUOTE RQUOTE RQUOTE_DOT RQUOTE_BAR_RBRACE %token BAR_BAR UPCAST DOWNCAST NULL RESERVED MODULE NAMESPACE DELEGATE CONSTRAINT BASE -%token AND AS ASSERT OASSERT ASR BEGIN DO DONE DOWNTO ELSE ELIF END DOT_DOT DOT_DOT_HAT +%token AND AS ASSERT OASSERT ASR BEGIN DO DONE DOWNTO ELSE ELIF END DOT_DOT_DOT DOT_DOT DOT_DOT_HAT %token EXCEPTION FALSE FOR FUN FUNCTION IF IN JOIN_IN FINALLY DO_BANG %token LAZY OLAZY MATCH MATCH_BANG MUTABLE NEW OF %token OPEN OR REC THEN TO TRUE TRY TYPE VAL INLINE INTERFACE INSTANCE CONST @@ -2163,7 +2163,6 @@ classDefnMember: let leadingKeyword = SynTypeDefnLeadingKeyword.StaticType(rhs parseState 3, rhs parseState 4) [ SynMemberDefn.NestedType($5 leadingKeyword, None, rhs2 parseState 1 5) ] } - /* A 'val' definition in an object type definition */ valDefnDecl: | VAL opt_mutable opt_access ident COLON typ @@ -2951,7 +2950,8 @@ unionCaseReprElement: unionCaseRepr: | braceFieldDeclList { errorR(Deprecated(FSComp.SR.parsConsiderUsingSeparateRecordType(), lhs parseState)) - $1, rhs parseState 1 } + let fields = $1 |> List.choose (function SynFieldOrSpread.Field field -> Some field | _ -> None) + fields, rhs parseState 1 } | unionCaseReprElements { $1 } @@ -2972,7 +2972,16 @@ recdFieldDecl: let (SynField (a, b, c, d, e, xmlDoc, vis, mWhole, trivia)) = fld if Option.isSome vis then errorR (Error (FSComp.SR.parsRecordFieldsCannotHaveVisibilityDeclarations (), rhs parseState 2)) let mWhole = unionRangeWithXmlDoc xmlDoc mWhole - SynField (a, b, c, d, e, xmlDoc, None, mWhole, trivia) } + SynFieldOrSpread.Field (SynField (a, b, c, d, e, xmlDoc, None, mWhole, trivia)) } + + | DOT_DOT_DOT typ + { let m = rhs2 parseState 1 2 + SynFieldOrSpread.Spread (SynTypeSpread (rhs parseState 1, $2, m)) } + + | DOT_DOT_DOT + { let m = rhs parseState 1 + reportParseErrorAt m (FSComp.SR.parsMissingSpreadSrcTy ()) + SynFieldOrSpread.Spread (SynTypeSpread (m, SynType.FromParseError m, m)) } /* Part of a field or val declaration in a record type or object type */ fieldDecl: @@ -4934,6 +4943,16 @@ declExpr: { let m = rhs parseState 1 SynExpr.IndexRange(None, m, None, m, m, m) } + | DOT_DOT_DOT declExpr + { let m = rhs parseState 1 + reportParseErrorAt m (FSComp.SR.parsSpreadNotSupported ()) + arbExpr ("dotDotDotDeclExpr", m) } + + | DOT_DOT_DOT + { let m = rhs parseState 1 + reportParseErrorAt m (FSComp.SR.parsSpreadNotSupported ()) + arbExpr ("dotDotDot", m) } + | minusExpr %prec expr_prefix_plus_minus { $1 } whileExprCore: @@ -5656,6 +5675,11 @@ braceExpr: { let m, r = $2 r (rhs2 parseState 1 3) } + | LBRACE DOT_DOT_DOT rbrace + { let m = rhs parseState 2 + reportParseErrorAt m (FSComp.SR.parsMissingSpreadSrcExpr ()) + SynExpr.Record (None, None, rebindRanges (RecordBinding.Spread (SynExprSpread (m, arbExpr ("spreadSrcExpr", m), m))) [] None, m) } + | LBRACE braceExprBody recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedBrace()) let m, r = $2 @@ -5779,8 +5803,11 @@ recdExpr: { let arg = match $4 with None -> mkSynUnit (lhs parseState) | Some e -> e let l = List.rev $5 let dummyField = mkRecdField (SynLongIdent([], [], [])) // dummy identifier, it will be discarded - let l = rebindRanges (dummyField, None, None) l $6 - let (SynExprRecordField(_, _, _, _, inheritsSep)) = List.head l + let l = rebindRanges (RecordBinding.Field (dummyField, None, None)) l $6 + let inheritsSep = + match List.head l with + | SynExprRecordFieldOrSpread.Field (SynExprRecordField(_, _, _, _), inheritsSep) -> inheritsSep + | _ -> None let bindings = List.tail l (Some($2, arg, rhs2 parseState 2 4, inheritsSep, rhs parseState 1), None, bindings) } @@ -5789,13 +5816,26 @@ recdExpr: None, a, b } recdExprCore: + | DOT_DOT_DOT declExprBlock recdExprBindings opt_seps_block + { let mSpread = rhs parseState 1 + let m = rhs2 parseState 1 2 + let l = List.rev $3 + let l = rebindRanges (RecordBinding.Spread (SynExprSpread (mSpread, $2, m))) l $4 + None, l } + + | DOT_DOT_DOT + { let mSpread = rhs parseState 1 + let m = mSpread + reportParseErrorAt m (FSComp.SR.parsMissingSpreadSrcExpr ()) + None, rebindRanges (RecordBinding.Spread (SynExprSpread (mSpread, arbExpr ("spreadSrcExpr", m), m))) [] None } + | appExpr EQUALS declExprBlock recdExprBindings opt_seps_block { match $1 with | LongOrSingleIdent(false, (SynLongIdent _ as f), None, m) -> let f = mkRecdField f let mEquals = rhs parseState 2 let l = List.rev $4 - let l = rebindRanges (f, Some mEquals, Some $3) l $5 + let l = rebindRanges (RecordBinding.Field (f, Some mEquals, Some $3)) l $5 (None, l) | _ -> raiseParseErrorAt (rhs parseState 2) (FSComp.SR.parsFieldBinding()) } @@ -5804,7 +5844,7 @@ recdExprCore: | LongOrSingleIdent(false, (SynLongIdent _ as f), None, m) -> let f = mkRecdField f let mEquals = rhs parseState 2 - let l = rebindRanges (f, Some mEquals, None) [] None + let l = rebindRanges (RecordBinding.Field (f, Some mEquals, None)) [] None None, l | _ -> raiseParseErrorAt (rhs parseState 2) (FSComp.SR.parsFieldBinding ()) } @@ -5822,7 +5862,7 @@ recdExprCore: reportParseErrorAt m (FSComp.SR.parsUnderscoreInvalidFieldName()) reportParseErrorAt m (FSComp.SR.parsFieldBinding()) let f = mkUnderscoreRecdField m - (None, [ SynExprRecordField(f, None, None, m, None) ]) } + (None, [ SynExprRecordFieldOrSpread.Field (SynExprRecordField(f, None, None, m), None) ]) } | UNDERSCORE EQUALS { let m = rhs parseState 1 @@ -5831,25 +5871,41 @@ recdExprCore: let mEquals = rhs parseState 2 reportParseErrorAt (rhs2 parseState 1 2) (FSComp.SR.parsFieldBinding()) - (None, [ SynExprRecordField(f, Some mEquals, None, (rhs2 parseState 1 2), None) ]) } + (None, [ SynExprRecordFieldOrSpread.Field (SynExprRecordField(f, Some mEquals, None, (rhs2 parseState 1 2)), None) ]) } | UNDERSCORE EQUALS declExprBlock recdExprBindings opt_seps_block { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnderscoreInvalidFieldName()) let f = mkUnderscoreRecdField (rhs parseState 1) let mEquals = rhs parseState 2 let l = List.rev $4 - let l = rebindRanges (f, Some mEquals, Some $3) l $5 + let l = rebindRanges (RecordBinding.Field (f, Some mEquals, Some $3)) l $5 (None, l) } /* handles case like {x with} */ + | DOT_DOT_DOT appExpr WITH recdBinding recdExprBindings opt_seps_block + { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsSpreadNotSupportedBeforeWith ()) + let l = List.rev $5 + let l = rebindRanges $4 l $6 + (Some($2, (rhs parseState 3, None)), l) } + | appExpr WITH recdBinding recdExprBindings opt_seps_block { let l = List.rev $4 let l = rebindRanges $3 l $5 (Some($1, (rhs parseState 2, None)), l) } + | DOT_DOT_DOT appExpr OWITH opt_seps_block OEND + { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsSpreadNotSupportedBeforeWith ()) + (Some($2, (rhs parseState 3, None)), []) } + | appExpr OWITH opt_seps_block OEND { (Some($1, (rhs parseState 2, None)), []) } + | DOT_DOT_DOT appExpr OWITH recdBinding recdExprBindings opt_seps_block OEND + { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsSpreadNotSupportedBeforeWith ()) + let l = List.rev $5 + let l = rebindRanges $4 l $6 + (Some($2, (rhs parseState 3, None)), l) } + | appExpr OWITH recdBinding recdExprBindings opt_seps_block OEND { let l = List.rev $4 let l = rebindRanges $3 l $5 @@ -5895,27 +5951,38 @@ recdExprBindings: { [] } recdBinding: + | DOT_DOT_DOT declExprBlock + { let mSpread = rhs parseState 1 + let m = rhs2 parseState 1 2 + RecordBinding.Spread (SynExprSpread (mSpread, $2, m)) } + | pathOrUnderscore EQUALS declExprBlock { let mEquals = rhs parseState 2 - ($1, Some mEquals, Some $3) } + RecordBinding.Field ($1, Some mEquals, Some $3) } | pathOrUnderscore EQUALS { let mEquals = rhs parseState 2 reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsFieldBinding()) - ($1, Some mEquals, None) } + RecordBinding.Field ($1, Some mEquals, None) } | pathOrUnderscore EQUALS ends_coming_soon_or_recover { let mEquals = rhs parseState 2 reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsFieldBinding()) - ($1, Some mEquals, None) } + RecordBinding.Field ($1, Some mEquals, None) } | pathOrUnderscore { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsFieldBinding()) - ($1, None, None) } + RecordBinding.Field ($1, None, None) } | pathOrUnderscore ends_coming_soon_or_recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsFieldBinding()) - ($1, None, None) } + RecordBinding.Field ($1, None, None) } + + | DOT_DOT_DOT + { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsMissingSpreadSrcExpr ()) + let mSpread = rhs parseState 1 + let m = mSpread + RecordBinding.Spread (SynExprSpread (mSpread, arbExpr ("spreadSrcExpr", m), m)) } /* There is a minor conflict between seq { new ty() } // sequence expression with one very odd 'action' expression @@ -6016,10 +6083,12 @@ braceBarExprCore: { let orig, flds = $2 let flds = flds |> List.choose (function - | SynExprRecordField((synLongIdent, _), mEquals, Some e, _, _) when orig.IsSome -> Some(synLongIdent, mEquals, e) // copy-and-update, long identifier signifies nesting - | SynExprRecordField((SynLongIdent([ _id ], _, _) as synLongIdent, _), mEquals, Some e, _, _) -> Some(synLongIdent, mEquals, e) // record construction, long identifier not valid - | SynExprRecordField((synLongIdent, _), mEquals, None, _, _) -> Some(synLongIdent, mEquals, arbExpr ("anonField", synLongIdent.Range)) - | _ -> reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsInvalidAnonRecdType()); None) + | SynExprRecordFieldOrSpread.Field (SynExprRecordField((synLongIdent, _), mEquals, Some e, m), sep) -> + Some (SynExprAnonRecordFieldOrSpread.Field (SynExprAnonRecordField (synLongIdent, mEquals, e, m), sep)) // copy-and-update, long identifier signifies nesting + | SynExprRecordFieldOrSpread.Field (SynExprRecordField((synLongIdent, _), mEquals, None, m), sep) -> + Some (SynExprAnonRecordFieldOrSpread.Field (SynExprAnonRecordField (synLongIdent, mEquals, arbExpr ("anonField", synLongIdent.Range), m), sep)) + | SynExprRecordFieldOrSpread.Spread (spread, sep) -> + Some (SynExprAnonRecordFieldOrSpread.Spread (spread, sep))) let mLeftBrace = rhs parseState 1 let mRightBrace = rhs parseState 3 (fun (mStruct: range option) -> @@ -6031,8 +6100,12 @@ braceBarExprCore: let orig, flds = $2 let flds = flds |> List.map (function - | SynExprRecordField((synLongIdent, _), mEquals, Some e, _, _) -> (synLongIdent, mEquals, e) - | SynExprRecordField((synLongIdent, _), mEquals, None, _, _) -> (synLongIdent, mEquals, arbExpr ("anonField", synLongIdent.Range))) + | SynExprRecordFieldOrSpread.Field (SynExprRecordField((synLongIdent, _), mEquals, Some e, m), sep) -> + SynExprAnonRecordFieldOrSpread.Field (SynExprAnonRecordField (synLongIdent, mEquals, e, m), sep) + | SynExprRecordFieldOrSpread.Field (SynExprRecordField((synLongIdent, _), mEquals, None, m), sep) -> + SynExprAnonRecordFieldOrSpread.Field (SynExprAnonRecordField (synLongIdent, mEquals, arbExpr ("anonField", synLongIdent.Range), m), sep) + | SynExprRecordFieldOrSpread.Spread (spread, sep) -> + SynExprAnonRecordFieldOrSpread.Spread (spread, sep)) let mLeftBrace = rhs parseState 1 let mExpr = rhs parseState 2 (fun (mStruct: range option) -> @@ -6623,7 +6696,7 @@ atomTypeOrAnonRecdType: { let flds, isStruct = $1 let flds2 = flds |> List.choose (function - | (SynField([], false, Some id, ty, false, _xmldoc, None, _m, _trivia)) -> Some(id, ty) + | SynFieldOrSpread.Field (SynField([], false, Some id, ty, false, _xmldoc, None, _m, _trivia)) -> Some(id, ty) | _ -> reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsInvalidAnonRecdType()); None) SynType.AnonRecd(isStruct, flds2, rhs parseState 1) } diff --git a/src/Compiler/xlf/FSComp.txt.cs.xlf b/src/Compiler/xlf/FSComp.txt.cs.xlf index 97a0e7790ea..27327ec82f3 100644 --- a/src/Compiler/xlf/FSComp.txt.cs.xlf +++ b/src/Compiler/xlf/FSComp.txt.cs.xlf @@ -1,4 +1,4 @@ - + @@ -607,6 +607,11 @@ vypsat literály libovolné velikosti + + record type and expression spreads + record type and expression spreads + + informational messages related to reference cells informační zprávy související s referenčními buňkami @@ -1252,6 +1257,16 @@ Očekává se text člena + + Missing spread source expression after '...'. + Missing spread source expression after '...'. + + + + Missing spread source type after '...'. + Missing spread source type after '...'. + + Missing union case name Chybí název případu sjednocení @@ -1267,6 +1282,16 @@ V primárních konstruktorech jsou povoleny pouze jednoduché vzory. + + Spreading is not supported in this construct. + Spreading is not supported in this construct. + + + + Spreading is not supported in this position. Use one of the forms {{ ...expr1; A = expr2 }} or {{ expr1 with A = expr2 }} instead. + Spreading is not supported in this position. Use one of the forms {{ ...expr1; A = expr2 }} or {{ expr1 with A = expr2 }} instead. + + Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration. Neúplná deklarace statického konstruktoru. Pro deklaraci použijte „static let“, „static do“, „static member“ nebo „static val“. @@ -1487,6 +1512,16 @@ Pole {0} se v tomto anonymním typu záznamu vyskytuje vícekrát. + + The source expression of a spread into an anonymous record expression cannot be nullable. + The source expression of a spread into an anonymous record expression cannot be nullable. + + + + The source expression of a spread into an anonymous record expression must have a nominal or anonymous record type. + The source expression of a spread into an anonymous record expression must have a nominal or anonymous record type. + + This attribute is not valid for use on union cases with fields. This attribute is not valid for use on union cases with fields. @@ -1777,6 +1812,41 @@ The value or member '{0}' has been marked 'inline' but is part of a recursive binding group. F# does not support recursive 'inline' values. Either remove the 'inline' modifier or refactor the recursion. + + Spread field '{0}' shadows an explicitly declared field with the same name. + Spread field '{0}' shadows an explicitly declared field with the same name. + + + + The source expression of a spread into a nominal record expression cannot be nullable. + The source expression of a spread into a nominal record expression cannot be nullable. + + + + The source expression of a spread into a nominal record expression must have a nominal or anonymous record type. + The source expression of a spread into a nominal record expression must have a nominal or anonymous record type. + + + + Spread expressions and 'with' cannot be used together in the same copy-and-update expression. + Spread expressions and 'with' cannot be used together in the same copy-and-update expression. + + + + Spread field '{0}' from type '{1}' shadows an explicitly declared field with the same name. + Spread field '{0}' from type '{1}' shadows an explicitly declared field with the same name. + + + + The source type of a spread into a record type definition cannot be nullable. + The source type of a spread into a record type definition cannot be nullable. + + + + The source type of a spread into a record type definition must itself be a nominal or anonymous record type. + The source type of a spread into a record type definition must itself be a nominal or anonymous record type. + + The 'let! ... and! ...' construct may only be used if the computation expression builder defines either a '{0}' method or appropriate 'MergeSources' and 'Bind' methods Konstrukt „let! ... and! ...“ se dá použít jen v případě, že tvůrce výpočetních výrazů definuje buď metodu „{0}“, nebo vhodné metody „MergeSource“ a „Bind“. @@ -1862,6 +1932,11 @@ Vlastnost nesmí určovat volitelné argumenty, in, out, ParamArray, CallerInfo nebo Quote. + + This type definition involves a cyclic reference through a spread. + This type definition involves a cyclic reference through a spread. + + The type '{0}' does not support a nullness qualification. The type '{0}' does not support a nullness qualification. diff --git a/src/Compiler/xlf/FSComp.txt.de.xlf b/src/Compiler/xlf/FSComp.txt.de.xlf index a503b84d990..cffe0a18264 100644 --- a/src/Compiler/xlf/FSComp.txt.de.xlf +++ b/src/Compiler/xlf/FSComp.txt.de.xlf @@ -1,4 +1,4 @@ - + @@ -607,6 +607,11 @@ Literale beliebiger Größe auflisten + + record type and expression spreads + record type and expression spreads + + informational messages related to reference cells Informationsmeldungen im Zusammenhang mit Bezugszellen @@ -1252,6 +1257,16 @@ Membertext wird erwartet + + Missing spread source expression after '...'. + Missing spread source expression after '...'. + + + + Missing spread source type after '...'. + Missing spread source type after '...'. + + Missing union case name Fehlender Union-Fallname @@ -1267,6 +1282,16 @@ In primären Konstruktoren sind nur einfache Muster zulässig + + Spreading is not supported in this construct. + Spreading is not supported in this construct. + + + + Spreading is not supported in this position. Use one of the forms {{ ...expr1; A = expr2 }} or {{ expr1 with A = expr2 }} instead. + Spreading is not supported in this position. Use one of the forms {{ ...expr1; A = expr2 }} or {{ expr1 with A = expr2 }} instead. + + Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration. Unvollständige Deklaration eines statischen Konstrukts. Verwenden Sie "static let", "static do", "static member" oder "static val" für die Deklaration. @@ -1487,6 +1512,16 @@ Das Feld "{0}" ist in diesem anonymen Datensatztyp mehrmals vorhanden. + + The source expression of a spread into an anonymous record expression cannot be nullable. + The source expression of a spread into an anonymous record expression cannot be nullable. + + + + The source expression of a spread into an anonymous record expression must have a nominal or anonymous record type. + The source expression of a spread into an anonymous record expression must have a nominal or anonymous record type. + + This attribute is not valid for use on union cases with fields. This attribute is not valid for use on union cases with fields. @@ -1777,6 +1812,41 @@ The value or member '{0}' has been marked 'inline' but is part of a recursive binding group. F# does not support recursive 'inline' values. Either remove the 'inline' modifier or refactor the recursion. + + Spread field '{0}' shadows an explicitly declared field with the same name. + Spread field '{0}' shadows an explicitly declared field with the same name. + + + + The source expression of a spread into a nominal record expression cannot be nullable. + The source expression of a spread into a nominal record expression cannot be nullable. + + + + The source expression of a spread into a nominal record expression must have a nominal or anonymous record type. + The source expression of a spread into a nominal record expression must have a nominal or anonymous record type. + + + + Spread expressions and 'with' cannot be used together in the same copy-and-update expression. + Spread expressions and 'with' cannot be used together in the same copy-and-update expression. + + + + Spread field '{0}' from type '{1}' shadows an explicitly declared field with the same name. + Spread field '{0}' from type '{1}' shadows an explicitly declared field with the same name. + + + + The source type of a spread into a record type definition cannot be nullable. + The source type of a spread into a record type definition cannot be nullable. + + + + The source type of a spread into a record type definition must itself be a nominal or anonymous record type. + The source type of a spread into a record type definition must itself be a nominal or anonymous record type. + + The 'let! ... and! ...' construct may only be used if the computation expression builder defines either a '{0}' method or appropriate 'MergeSources' and 'Bind' methods Das Konstrukt "let! ... and! ..." kann nur verwendet werden, wenn der Berechnungsausdrucks-Generator entweder eine {0}-Methode oder geeignete MergeSources- und Bind-Methoden definiert. @@ -1862,6 +1932,11 @@ Ein Merkmal darf keine Argumente für „optional“, „in“, „out“, „ParamArray“", „CallerInfo“ oder „Quote“ angeben. + + This type definition involves a cyclic reference through a spread. + This type definition involves a cyclic reference through a spread. + + The type '{0}' does not support a nullness qualification. The type '{0}' does not support a nullness qualification. diff --git a/src/Compiler/xlf/FSComp.txt.es.xlf b/src/Compiler/xlf/FSComp.txt.es.xlf index bceeb3bd1c0..ec9a74bd72c 100644 --- a/src/Compiler/xlf/FSComp.txt.es.xlf +++ b/src/Compiler/xlf/FSComp.txt.es.xlf @@ -1,4 +1,4 @@ - + @@ -607,6 +607,11 @@ enumerar literales de cualquier tamaño + + record type and expression spreads + record type and expression spreads + + informational messages related to reference cells mensajes informativos relacionados con las celdas de referencia @@ -1252,6 +1257,16 @@ Se espera el cuerpo del miembro + + Missing spread source expression after '...'. + Missing spread source expression after '...'. + + + + Missing spread source type after '...'. + Missing spread source type after '...'. + + Missing union case name Falta el nombre del caso de unión @@ -1267,6 +1282,16 @@ Solo se permiten patrones simples en constructores principales + + Spreading is not supported in this construct. + Spreading is not supported in this construct. + + + + Spreading is not supported in this position. Use one of the forms {{ ...expr1; A = expr2 }} or {{ expr1 with A = expr2 }} instead. + Spreading is not supported in this position. Use one of the forms {{ ...expr1; A = expr2 }} or {{ expr1 with A = expr2 }} instead. + + Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration. Declaración incompleta de una construcción estática. Use "static let", "static do", "static member" o "static val" para la declaración. @@ -1487,6 +1512,16 @@ El campo "{0}" aparece varias veces en este tipo de registro anónimo. + + The source expression of a spread into an anonymous record expression cannot be nullable. + The source expression of a spread into an anonymous record expression cannot be nullable. + + + + The source expression of a spread into an anonymous record expression must have a nominal or anonymous record type. + The source expression of a spread into an anonymous record expression must have a nominal or anonymous record type. + + This attribute is not valid for use on union cases with fields. This attribute is not valid for use on union cases with fields. @@ -1777,6 +1812,41 @@ The value or member '{0}' has been marked 'inline' but is part of a recursive binding group. F# does not support recursive 'inline' values. Either remove the 'inline' modifier or refactor the recursion. + + Spread field '{0}' shadows an explicitly declared field with the same name. + Spread field '{0}' shadows an explicitly declared field with the same name. + + + + The source expression of a spread into a nominal record expression cannot be nullable. + The source expression of a spread into a nominal record expression cannot be nullable. + + + + The source expression of a spread into a nominal record expression must have a nominal or anonymous record type. + The source expression of a spread into a nominal record expression must have a nominal or anonymous record type. + + + + Spread expressions and 'with' cannot be used together in the same copy-and-update expression. + Spread expressions and 'with' cannot be used together in the same copy-and-update expression. + + + + Spread field '{0}' from type '{1}' shadows an explicitly declared field with the same name. + Spread field '{0}' from type '{1}' shadows an explicitly declared field with the same name. + + + + The source type of a spread into a record type definition cannot be nullable. + The source type of a spread into a record type definition cannot be nullable. + + + + The source type of a spread into a record type definition must itself be a nominal or anonymous record type. + The source type of a spread into a record type definition must itself be a nominal or anonymous record type. + + The 'let! ... and! ...' construct may only be used if the computation expression builder defines either a '{0}' method or appropriate 'MergeSources' and 'Bind' methods La construcción "let! ... and! ..." solo se puede usar si el generador de expresiones de cálculo define un método "{0}" o bien los métodos "MergeSources" y "Bind" adecuados. @@ -1862,6 +1932,11 @@ Un rasgo no puede especificar argumentos opcionales, in, out, ParamArray, CallerInfo o Quote + + This type definition involves a cyclic reference through a spread. + This type definition involves a cyclic reference through a spread. + + The type '{0}' does not support a nullness qualification. The type '{0}' does not support a nullness qualification. diff --git a/src/Compiler/xlf/FSComp.txt.fr.xlf b/src/Compiler/xlf/FSComp.txt.fr.xlf index e07e1f49ea6..5157305f7c8 100644 --- a/src/Compiler/xlf/FSComp.txt.fr.xlf +++ b/src/Compiler/xlf/FSComp.txt.fr.xlf @@ -1,4 +1,4 @@ - + @@ -607,6 +607,11 @@ répertorier les littéraux de n’importe quelle taille + + record type and expression spreads + record type and expression spreads + + informational messages related to reference cells messages d’information liés aux cellules de référence @@ -1252,6 +1257,16 @@ Comité membre attendu + + Missing spread source expression after '...'. + Missing spread source expression after '...'. + + + + Missing spread source type after '...'. + Missing spread source type after '...'. + + Missing union case name Nom du cas syndical manquant @@ -1267,6 +1282,16 @@ Seuls les modèles simples sont autorisés dans les constructeurs principaux + + Spreading is not supported in this construct. + Spreading is not supported in this construct. + + + + Spreading is not supported in this position. Use one of the forms {{ ...expr1; A = expr2 }} or {{ expr1 with A = expr2 }} instead. + Spreading is not supported in this position. Use one of the forms {{ ...expr1; A = expr2 }} or {{ expr1 with A = expr2 }} instead. + + Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration. Déclaration incomplète d’une construction statique. Utilisez « static let », « static do », « static member » ou « static val » pour la déclaration. @@ -1487,6 +1512,16 @@ Le champ '{0}' apparaît plusieurs fois dans ce type d'enregistrement anonyme. + + The source expression of a spread into an anonymous record expression cannot be nullable. + The source expression of a spread into an anonymous record expression cannot be nullable. + + + + The source expression of a spread into an anonymous record expression must have a nominal or anonymous record type. + The source expression of a spread into an anonymous record expression must have a nominal or anonymous record type. + + This attribute is not valid for use on union cases with fields. This attribute is not valid for use on union cases with fields. @@ -1777,6 +1812,41 @@ The value or member '{0}' has been marked 'inline' but is part of a recursive binding group. F# does not support recursive 'inline' values. Either remove the 'inline' modifier or refactor the recursion. + + Spread field '{0}' shadows an explicitly declared field with the same name. + Spread field '{0}' shadows an explicitly declared field with the same name. + + + + The source expression of a spread into a nominal record expression cannot be nullable. + The source expression of a spread into a nominal record expression cannot be nullable. + + + + The source expression of a spread into a nominal record expression must have a nominal or anonymous record type. + The source expression of a spread into a nominal record expression must have a nominal or anonymous record type. + + + + Spread expressions and 'with' cannot be used together in the same copy-and-update expression. + Spread expressions and 'with' cannot be used together in the same copy-and-update expression. + + + + Spread field '{0}' from type '{1}' shadows an explicitly declared field with the same name. + Spread field '{0}' from type '{1}' shadows an explicitly declared field with the same name. + + + + The source type of a spread into a record type definition cannot be nullable. + The source type of a spread into a record type definition cannot be nullable. + + + + The source type of a spread into a record type definition must itself be a nominal or anonymous record type. + The source type of a spread into a record type definition must itself be a nominal or anonymous record type. + + The 'let! ... and! ...' construct may only be used if the computation expression builder defines either a '{0}' method or appropriate 'MergeSources' and 'Bind' methods Le « laissez ! » ... et! ...' ne peut être utilisée que si le générateur d'expression de calcul définit soit une méthode '{0}', soit des méthodes 'MergeSources' et 'Bind' appropriées. @@ -1862,6 +1932,11 @@ Une caractéristique ne peut pas spécifier d’arguments facultatifs, in, out, ParamArray, CallerInfo ou Quote + + This type definition involves a cyclic reference through a spread. + This type definition involves a cyclic reference through a spread. + + The type '{0}' does not support a nullness qualification. The type '{0}' does not support a nullness qualification. diff --git a/src/Compiler/xlf/FSComp.txt.it.xlf b/src/Compiler/xlf/FSComp.txt.it.xlf index 38976ac7b68..53b61ab8458 100644 --- a/src/Compiler/xlf/FSComp.txt.it.xlf +++ b/src/Compiler/xlf/FSComp.txt.it.xlf @@ -1,4 +1,4 @@ - + @@ -607,6 +607,11 @@ elenca valori letterali di qualsiasi dimensione + + record type and expression spreads + record type and expression spreads + + informational messages related to reference cells messaggi informativi relativi alle celle di riferimento @@ -1252,6 +1257,16 @@ Previsto corpo del membro + + Missing spread source expression after '...'. + Missing spread source expression after '...'. + + + + Missing spread source type after '...'. + Missing spread source type after '...'. + + Missing union case name Nome case di unione mancante @@ -1267,6 +1282,16 @@ Nei costruttori primari sono consentiti solo criteri semplici + + Spreading is not supported in this construct. + Spreading is not supported in this construct. + + + + Spreading is not supported in this position. Use one of the forms {{ ...expr1; A = expr2 }} or {{ expr1 with A = expr2 }} instead. + Spreading is not supported in this position. Use one of the forms {{ ...expr1; A = expr2 }} or {{ expr1 with A = expr2 }} instead. + + Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration. Dichiarazione incompleta di un costrutto statico. Usare 'static let','static do','static member' o 'static val' per la dichiarazione. @@ -1487,6 +1512,16 @@ Il campo '{0}' viene visualizzato più volte in questo tipo di record anonimo. + + The source expression of a spread into an anonymous record expression cannot be nullable. + The source expression of a spread into an anonymous record expression cannot be nullable. + + + + The source expression of a spread into an anonymous record expression must have a nominal or anonymous record type. + The source expression of a spread into an anonymous record expression must have a nominal or anonymous record type. + + This attribute is not valid for use on union cases with fields. This attribute is not valid for use on union cases with fields. @@ -1777,6 +1812,41 @@ The value or member '{0}' has been marked 'inline' but is part of a recursive binding group. F# does not support recursive 'inline' values. Either remove the 'inline' modifier or refactor the recursion. + + Spread field '{0}' shadows an explicitly declared field with the same name. + Spread field '{0}' shadows an explicitly declared field with the same name. + + + + The source expression of a spread into a nominal record expression cannot be nullable. + The source expression of a spread into a nominal record expression cannot be nullable. + + + + The source expression of a spread into a nominal record expression must have a nominal or anonymous record type. + The source expression of a spread into a nominal record expression must have a nominal or anonymous record type. + + + + Spread expressions and 'with' cannot be used together in the same copy-and-update expression. + Spread expressions and 'with' cannot be used together in the same copy-and-update expression. + + + + Spread field '{0}' from type '{1}' shadows an explicitly declared field with the same name. + Spread field '{0}' from type '{1}' shadows an explicitly declared field with the same name. + + + + The source type of a spread into a record type definition cannot be nullable. + The source type of a spread into a record type definition cannot be nullable. + + + + The source type of a spread into a record type definition must itself be a nominal or anonymous record type. + The source type of a spread into a record type definition must itself be a nominal or anonymous record type. + + The 'let! ... and! ...' construct may only be used if the computation expression builder defines either a '{0}' method or appropriate 'MergeSources' and 'Bind' methods È possibile usare il costrutto "let! ... and! ..." solo se il generatore di espressioni di calcolo definisce un metodo "{0}" o metodi "MergeSource" e "Bind" appropriati @@ -1862,6 +1932,11 @@ Un tratto non può specificare argomenti optional, in, out, ParamArray, CallerInfo o Quote + + This type definition involves a cyclic reference through a spread. + This type definition involves a cyclic reference through a spread. + + The type '{0}' does not support a nullness qualification. The type '{0}' does not support a nullness qualification. diff --git a/src/Compiler/xlf/FSComp.txt.ja.xlf b/src/Compiler/xlf/FSComp.txt.ja.xlf index 7887ada006d..7f716fd56a7 100644 --- a/src/Compiler/xlf/FSComp.txt.ja.xlf +++ b/src/Compiler/xlf/FSComp.txt.ja.xlf @@ -1,4 +1,4 @@ - + @@ -607,6 +607,11 @@ 任意のサイズのリテラルを一覧表示する + + record type and expression spreads + record type and expression spreads + + informational messages related to reference cells 参照セルに関連する情報メッセージ @@ -1252,6 +1257,16 @@ メンバー本体が必要です + + Missing spread source expression after '...'. + Missing spread source expression after '...'. + + + + Missing spread source type after '...'. + Missing spread source type after '...'. + + Missing union case name 共用体のケース名がありません @@ -1267,6 +1282,16 @@ プライマリ コンストラクターで使用できるのは単純なパターンのみです + + Spreading is not supported in this construct. + Spreading is not supported in this construct. + + + + Spreading is not supported in this position. Use one of the forms {{ ...expr1; A = expr2 }} or {{ expr1 with A = expr2 }} instead. + Spreading is not supported in this position. Use one of the forms {{ ...expr1; A = expr2 }} or {{ expr1 with A = expr2 }} instead. + + Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration. 静的コンストラクトの不完全な宣言。宣言には、'static let'、'static do'、'static member'、または 'static val' を使用します。 @@ -1487,6 +1512,16 @@ この匿名レコードの種類に、フィールド '{0}' が複数回出現します。 + + The source expression of a spread into an anonymous record expression cannot be nullable. + The source expression of a spread into an anonymous record expression cannot be nullable. + + + + The source expression of a spread into an anonymous record expression must have a nominal or anonymous record type. + The source expression of a spread into an anonymous record expression must have a nominal or anonymous record type. + + This attribute is not valid for use on union cases with fields. This attribute is not valid for use on union cases with fields. @@ -1777,6 +1812,41 @@ The value or member '{0}' has been marked 'inline' but is part of a recursive binding group. F# does not support recursive 'inline' values. Either remove the 'inline' modifier or refactor the recursion. + + Spread field '{0}' shadows an explicitly declared field with the same name. + Spread field '{0}' shadows an explicitly declared field with the same name. + + + + The source expression of a spread into a nominal record expression cannot be nullable. + The source expression of a spread into a nominal record expression cannot be nullable. + + + + The source expression of a spread into a nominal record expression must have a nominal or anonymous record type. + The source expression of a spread into a nominal record expression must have a nominal or anonymous record type. + + + + Spread expressions and 'with' cannot be used together in the same copy-and-update expression. + Spread expressions and 'with' cannot be used together in the same copy-and-update expression. + + + + Spread field '{0}' from type '{1}' shadows an explicitly declared field with the same name. + Spread field '{0}' from type '{1}' shadows an explicitly declared field with the same name. + + + + The source type of a spread into a record type definition cannot be nullable. + The source type of a spread into a record type definition cannot be nullable. + + + + The source type of a spread into a record type definition must itself be a nominal or anonymous record type. + The source type of a spread into a record type definition must itself be a nominal or anonymous record type. + + The 'let! ... and! ...' construct may only be used if the computation expression builder defines either a '{0}' method or appropriate 'MergeSources' and 'Bind' methods 'let! ... and! ...' コンストラクトは、コンピュテーション式ビルダーが '{0}' メソッドまたは適切な 'MergeSource' および 'Bind' メソッドのいずれかを定義している場合にのみ使用できます @@ -1862,6 +1932,11 @@ 特性では、オプションの、in 引数、out 引数、ParamArray 引数、CallerInfo 引数、または Quote 引数を指定することはできません + + This type definition involves a cyclic reference through a spread. + This type definition involves a cyclic reference through a spread. + + The type '{0}' does not support a nullness qualification. The type '{0}' does not support a nullness qualification. diff --git a/src/Compiler/xlf/FSComp.txt.ko.xlf b/src/Compiler/xlf/FSComp.txt.ko.xlf index a56015989b0..1e323fe7bc7 100644 --- a/src/Compiler/xlf/FSComp.txt.ko.xlf +++ b/src/Compiler/xlf/FSComp.txt.ko.xlf @@ -1,4 +1,4 @@ - + @@ -607,6 +607,11 @@ 모든 크기의 목록 리터럴 + + record type and expression spreads + record type and expression spreads + + informational messages related to reference cells 참조 셀과 관련된 정보 메시지 @@ -1252,6 +1257,16 @@ 멤버 본문이 필요한 경우 + + Missing spread source expression after '...'. + Missing spread source expression after '...'. + + + + Missing spread source type after '...'. + Missing spread source type after '...'. + + Missing union case name 공용 구조체 대/소문자 이름이 없습니다. @@ -1267,6 +1282,16 @@ 기본 생성자에서는 단순 패턴만 허용됩니다. + + Spreading is not supported in this construct. + Spreading is not supported in this construct. + + + + Spreading is not supported in this position. Use one of the forms {{ ...expr1; A = expr2 }} or {{ expr1 with A = expr2 }} instead. + Spreading is not supported in this position. Use one of the forms {{ ...expr1; A = expr2 }} or {{ expr1 with A = expr2 }} instead. + + Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration. 정적 구문의 선언이 불완전합니다. 선언에 'static let','static do','static member' 또는 'static val'을 사용합니다. @@ -1487,6 +1512,16 @@ '{0}' 필드가 이 익명 레코드 형식에서 여러 번 나타납니다. + + The source expression of a spread into an anonymous record expression cannot be nullable. + The source expression of a spread into an anonymous record expression cannot be nullable. + + + + The source expression of a spread into an anonymous record expression must have a nominal or anonymous record type. + The source expression of a spread into an anonymous record expression must have a nominal or anonymous record type. + + This attribute is not valid for use on union cases with fields. This attribute is not valid for use on union cases with fields. @@ -1777,6 +1812,41 @@ The value or member '{0}' has been marked 'inline' but is part of a recursive binding group. F# does not support recursive 'inline' values. Either remove the 'inline' modifier or refactor the recursion. + + Spread field '{0}' shadows an explicitly declared field with the same name. + Spread field '{0}' shadows an explicitly declared field with the same name. + + + + The source expression of a spread into a nominal record expression cannot be nullable. + The source expression of a spread into a nominal record expression cannot be nullable. + + + + The source expression of a spread into a nominal record expression must have a nominal or anonymous record type. + The source expression of a spread into a nominal record expression must have a nominal or anonymous record type. + + + + Spread expressions and 'with' cannot be used together in the same copy-and-update expression. + Spread expressions and 'with' cannot be used together in the same copy-and-update expression. + + + + Spread field '{0}' from type '{1}' shadows an explicitly declared field with the same name. + Spread field '{0}' from type '{1}' shadows an explicitly declared field with the same name. + + + + The source type of a spread into a record type definition cannot be nullable. + The source type of a spread into a record type definition cannot be nullable. + + + + The source type of a spread into a record type definition must itself be a nominal or anonymous record type. + The source type of a spread into a record type definition must itself be a nominal or anonymous record type. + + The 'let! ... and! ...' construct may only be used if the computation expression builder defines either a '{0}' method or appropriate 'MergeSources' and 'Bind' methods 'let! ... and! ...' 구문은 계산 식 작성기에서 '{0}' 메서드 또는 적절한 'MergeSources' 및 'Bind' 메서드를 정의한 경우에만 사용할 수 있습니다. @@ -1862,6 +1932,11 @@ 특성은 optional, in, out, ParamArray, CallerInfo, Quote 인수를 지정할 수 없습니다. + + This type definition involves a cyclic reference through a spread. + This type definition involves a cyclic reference through a spread. + + The type '{0}' does not support a nullness qualification. The type '{0}' does not support a nullness qualification. diff --git a/src/Compiler/xlf/FSComp.txt.pl.xlf b/src/Compiler/xlf/FSComp.txt.pl.xlf index 99f0175e0ac..2f00a532f3c 100644 --- a/src/Compiler/xlf/FSComp.txt.pl.xlf +++ b/src/Compiler/xlf/FSComp.txt.pl.xlf @@ -1,4 +1,4 @@ - + @@ -607,6 +607,11 @@ wyświetlanie na liście literałów o dowolnym rozmiarze + + record type and expression spreads + record type and expression spreads + + informational messages related to reference cells komunikaty informacyjne związane z odwołaniami do komórek @@ -1252,6 +1257,16 @@ Oczekiwano treści elementu członkowskiego + + Missing spread source expression after '...'. + Missing spread source expression after '...'. + + + + Missing spread source type after '...'. + Missing spread source type after '...'. + + Missing union case name Brak nazwy przypadku unii @@ -1267,6 +1282,16 @@ Tylko proste wzorce są dozwolone w konstruktorach podstawowych + + Spreading is not supported in this construct. + Spreading is not supported in this construct. + + + + Spreading is not supported in this position. Use one of the forms {{ ...expr1; A = expr2 }} or {{ expr1 with A = expr2 }} instead. + Spreading is not supported in this position. Use one of the forms {{ ...expr1; A = expr2 }} or {{ expr1 with A = expr2 }} instead. + + Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration. Niekompletna deklaracja konstrukcji statycznej. Użyj elementu „static let”, „static do”, „static member” lub „static val” na potrzeby deklaracji. @@ -1487,6 +1512,16 @@ Pole „{0}” występuje wielokrotnie w tym anonimowym typie rekordu. + + The source expression of a spread into an anonymous record expression cannot be nullable. + The source expression of a spread into an anonymous record expression cannot be nullable. + + + + The source expression of a spread into an anonymous record expression must have a nominal or anonymous record type. + The source expression of a spread into an anonymous record expression must have a nominal or anonymous record type. + + This attribute is not valid for use on union cases with fields. This attribute is not valid for use on union cases with fields. @@ -1777,6 +1812,41 @@ The value or member '{0}' has been marked 'inline' but is part of a recursive binding group. F# does not support recursive 'inline' values. Either remove the 'inline' modifier or refactor the recursion. + + Spread field '{0}' shadows an explicitly declared field with the same name. + Spread field '{0}' shadows an explicitly declared field with the same name. + + + + The source expression of a spread into a nominal record expression cannot be nullable. + The source expression of a spread into a nominal record expression cannot be nullable. + + + + The source expression of a spread into a nominal record expression must have a nominal or anonymous record type. + The source expression of a spread into a nominal record expression must have a nominal or anonymous record type. + + + + Spread expressions and 'with' cannot be used together in the same copy-and-update expression. + Spread expressions and 'with' cannot be used together in the same copy-and-update expression. + + + + Spread field '{0}' from type '{1}' shadows an explicitly declared field with the same name. + Spread field '{0}' from type '{1}' shadows an explicitly declared field with the same name. + + + + The source type of a spread into a record type definition cannot be nullable. + The source type of a spread into a record type definition cannot be nullable. + + + + The source type of a spread into a record type definition must itself be a nominal or anonymous record type. + The source type of a spread into a record type definition must itself be a nominal or anonymous record type. + + The 'let! ... and! ...' construct may only be used if the computation expression builder defines either a '{0}' method or appropriate 'MergeSources' and 'Bind' methods Konstrukcji „let! ... and! ...” można użyć tylko wtedy, gdy konstruktor wyrażeń obliczeniowych definiuje metodę „{0}” lub odpowiednie metody „MergeSource” i „Bind” @@ -1862,6 +1932,11 @@ Cecha nie może określać opcjonalnych argumentów in, out, ParamArray, CallerInfo lub Quote + + This type definition involves a cyclic reference through a spread. + This type definition involves a cyclic reference through a spread. + + The type '{0}' does not support a nullness qualification. The type '{0}' does not support a nullness qualification. diff --git a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf index 0e9f94e1b47..4febb800c76 100644 --- a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf +++ b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf @@ -1,4 +1,4 @@ - + @@ -607,6 +607,11 @@ literais de lista de qualquer tamanho + + record type and expression spreads + record type and expression spreads + + informational messages related to reference cells mensagens informativas relacionadas a células de referência @@ -1252,6 +1257,16 @@ Esperando corpo do membro + + Missing spread source expression after '...'. + Missing spread source expression after '...'. + + + + Missing spread source type after '...'. + Missing spread source type after '...'. + + Missing union case name Nome do caso de união ausente @@ -1267,6 +1282,16 @@ Somente padrões simples são permitidos em construtores primários + + Spreading is not supported in this construct. + Spreading is not supported in this construct. + + + + Spreading is not supported in this position. Use one of the forms {{ ...expr1; A = expr2 }} or {{ expr1 with A = expr2 }} instead. + Spreading is not supported in this position. Use one of the forms {{ ...expr1; A = expr2 }} or {{ expr1 with A = expr2 }} instead. + + Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration. Declaração incompleta de um constructo estático. Use "static let","static do","static member" ou "static val" para declaração. @@ -1487,6 +1512,16 @@ O campo '{0}' aparece várias vezes nesse tipo de registro anônimo. + + The source expression of a spread into an anonymous record expression cannot be nullable. + The source expression of a spread into an anonymous record expression cannot be nullable. + + + + The source expression of a spread into an anonymous record expression must have a nominal or anonymous record type. + The source expression of a spread into an anonymous record expression must have a nominal or anonymous record type. + + This attribute is not valid for use on union cases with fields. This attribute is not valid for use on union cases with fields. @@ -1777,6 +1812,41 @@ The value or member '{0}' has been marked 'inline' but is part of a recursive binding group. F# does not support recursive 'inline' values. Either remove the 'inline' modifier or refactor the recursion. + + Spread field '{0}' shadows an explicitly declared field with the same name. + Spread field '{0}' shadows an explicitly declared field with the same name. + + + + The source expression of a spread into a nominal record expression cannot be nullable. + The source expression of a spread into a nominal record expression cannot be nullable. + + + + The source expression of a spread into a nominal record expression must have a nominal or anonymous record type. + The source expression of a spread into a nominal record expression must have a nominal or anonymous record type. + + + + Spread expressions and 'with' cannot be used together in the same copy-and-update expression. + Spread expressions and 'with' cannot be used together in the same copy-and-update expression. + + + + Spread field '{0}' from type '{1}' shadows an explicitly declared field with the same name. + Spread field '{0}' from type '{1}' shadows an explicitly declared field with the same name. + + + + The source type of a spread into a record type definition cannot be nullable. + The source type of a spread into a record type definition cannot be nullable. + + + + The source type of a spread into a record type definition must itself be a nominal or anonymous record type. + The source type of a spread into a record type definition must itself be a nominal or anonymous record type. + + The 'let! ... and! ...' construct may only be used if the computation expression builder defines either a '{0}' method or appropriate 'MergeSources' and 'Bind' methods O “let! ... and! ...” só poderá ser usada se o construtor de expressão de cálculo definir um método “{0}” ou métodos “MergeSources” e “Bind” apropriados @@ -1862,6 +1932,11 @@ Uma característica não pode especificar os argumentos optional, in, out, ParamArray, CallerInfo ou Quote + + This type definition involves a cyclic reference through a spread. + This type definition involves a cyclic reference through a spread. + + The type '{0}' does not support a nullness qualification. The type '{0}' does not support a nullness qualification. diff --git a/src/Compiler/xlf/FSComp.txt.ru.xlf b/src/Compiler/xlf/FSComp.txt.ru.xlf index 917dfd8f862..e59e2044060 100644 --- a/src/Compiler/xlf/FSComp.txt.ru.xlf +++ b/src/Compiler/xlf/FSComp.txt.ru.xlf @@ -1,4 +1,4 @@ - + @@ -607,6 +607,11 @@ список литералов любого размера + + record type and expression spreads + record type and expression spreads + + informational messages related to reference cells информационные сообщения, связанные с ссылочными ячейками @@ -1252,6 +1257,16 @@ Требуется текст сообщения элемента + + Missing spread source expression after '...'. + Missing spread source expression after '...'. + + + + Missing spread source type after '...'. + Missing spread source type after '...'. + + Missing union case name Отсутствует имя случая объединения @@ -1267,6 +1282,16 @@ В первичных конструкторах разрешены только простые шаблоны + + Spreading is not supported in this construct. + Spreading is not supported in this construct. + + + + Spreading is not supported in this position. Use one of the forms {{ ...expr1; A = expr2 }} or {{ expr1 with A = expr2 }} instead. + Spreading is not supported in this position. Use one of the forms {{ ...expr1; A = expr2 }} or {{ expr1 with A = expr2 }} instead. + + Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration. Неполное объявление статической конструкции. Для объявления используйте «static let», «static do», «staticmember» или «static val». @@ -1487,6 +1512,16 @@ Поле "{0}" появляется несколько раз в этом типе анонимной записи. + + The source expression of a spread into an anonymous record expression cannot be nullable. + The source expression of a spread into an anonymous record expression cannot be nullable. + + + + The source expression of a spread into an anonymous record expression must have a nominal or anonymous record type. + The source expression of a spread into an anonymous record expression must have a nominal or anonymous record type. + + This attribute is not valid for use on union cases with fields. This attribute is not valid for use on union cases with fields. @@ -1777,6 +1812,41 @@ The value or member '{0}' has been marked 'inline' but is part of a recursive binding group. F# does not support recursive 'inline' values. Either remove the 'inline' modifier or refactor the recursion. + + Spread field '{0}' shadows an explicitly declared field with the same name. + Spread field '{0}' shadows an explicitly declared field with the same name. + + + + The source expression of a spread into a nominal record expression cannot be nullable. + The source expression of a spread into a nominal record expression cannot be nullable. + + + + The source expression of a spread into a nominal record expression must have a nominal or anonymous record type. + The source expression of a spread into a nominal record expression must have a nominal or anonymous record type. + + + + Spread expressions and 'with' cannot be used together in the same copy-and-update expression. + Spread expressions and 'with' cannot be used together in the same copy-and-update expression. + + + + Spread field '{0}' from type '{1}' shadows an explicitly declared field with the same name. + Spread field '{0}' from type '{1}' shadows an explicitly declared field with the same name. + + + + The source type of a spread into a record type definition cannot be nullable. + The source type of a spread into a record type definition cannot be nullable. + + + + The source type of a spread into a record type definition must itself be a nominal or anonymous record type. + The source type of a spread into a record type definition must itself be a nominal or anonymous record type. + + The 'let! ... and! ...' construct may only be used if the computation expression builder defines either a '{0}' method or appropriate 'MergeSources' and 'Bind' methods Конструкцию "let! ... and! ..." можно использовать только в том случае, если построитель выражений с вычислениями определяет либо метод "{0}", либо соответствующие методы "MergeSources" и "Bind" @@ -1862,6 +1932,11 @@ Признак не может указывать необязательные аргументы in, out, ParamArray, CallerInfo или Quote + + This type definition involves a cyclic reference through a spread. + This type definition involves a cyclic reference through a spread. + + The type '{0}' does not support a nullness qualification. The type '{0}' does not support a nullness qualification. diff --git a/src/Compiler/xlf/FSComp.txt.tr.xlf b/src/Compiler/xlf/FSComp.txt.tr.xlf index 42aa78dda0c..e8c0d9a790d 100644 --- a/src/Compiler/xlf/FSComp.txt.tr.xlf +++ b/src/Compiler/xlf/FSComp.txt.tr.xlf @@ -1,4 +1,4 @@ - + @@ -607,6 +607,11 @@ tüm boyutlardaki sabit değerleri listele + + record type and expression spreads + record type and expression spreads + + informational messages related to reference cells başvuru hücreleriyle ilgili bilgi mesajları @@ -1252,6 +1257,16 @@ Üye gövdesi bekleniyor + + Missing spread source expression after '...'. + Missing spread source expression after '...'. + + + + Missing spread source type after '...'. + Missing spread source type after '...'. + + Missing union case name Birleşim durumu adı eksik @@ -1267,6 +1282,16 @@ Birincil oluşturucularda yalnızca basit desenlere izin verilir + + Spreading is not supported in this construct. + Spreading is not supported in this construct. + + + + Spreading is not supported in this position. Use one of the forms {{ ...expr1; A = expr2 }} or {{ expr1 with A = expr2 }} instead. + Spreading is not supported in this position. Use one of the forms {{ ...expr1; A = expr2 }} or {{ expr1 with A = expr2 }} instead. + + Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration. Statik yapının bildirimi eksik. Bildirim için 'static let','static do','static member' veya 'static val' kullanın. @@ -1487,6 +1512,16 @@ '{0}' alanı bu anonim kayıt türünde birden fazla yerde görünüyor. + + The source expression of a spread into an anonymous record expression cannot be nullable. + The source expression of a spread into an anonymous record expression cannot be nullable. + + + + The source expression of a spread into an anonymous record expression must have a nominal or anonymous record type. + The source expression of a spread into an anonymous record expression must have a nominal or anonymous record type. + + This attribute is not valid for use on union cases with fields. This attribute is not valid for use on union cases with fields. @@ -1777,6 +1812,41 @@ The value or member '{0}' has been marked 'inline' but is part of a recursive binding group. F# does not support recursive 'inline' values. Either remove the 'inline' modifier or refactor the recursion. + + Spread field '{0}' shadows an explicitly declared field with the same name. + Spread field '{0}' shadows an explicitly declared field with the same name. + + + + The source expression of a spread into a nominal record expression cannot be nullable. + The source expression of a spread into a nominal record expression cannot be nullable. + + + + The source expression of a spread into a nominal record expression must have a nominal or anonymous record type. + The source expression of a spread into a nominal record expression must have a nominal or anonymous record type. + + + + Spread expressions and 'with' cannot be used together in the same copy-and-update expression. + Spread expressions and 'with' cannot be used together in the same copy-and-update expression. + + + + Spread field '{0}' from type '{1}' shadows an explicitly declared field with the same name. + Spread field '{0}' from type '{1}' shadows an explicitly declared field with the same name. + + + + The source type of a spread into a record type definition cannot be nullable. + The source type of a spread into a record type definition cannot be nullable. + + + + The source type of a spread into a record type definition must itself be a nominal or anonymous record type. + The source type of a spread into a record type definition must itself be a nominal or anonymous record type. + + The 'let! ... and! ...' construct may only be used if the computation expression builder defines either a '{0}' method or appropriate 'MergeSources' and 'Bind' methods 'let! ... and! ...' yapısı, yalnızca hesaplama ifadesi oluşturucu bir '{0}' metodunu ya da uygun 'MergeSources' ve 'Bind' metotlarını tanımlarsa kullanılabilir @@ -1862,6 +1932,11 @@ Bir nitelik optional, in, out, ParamArray, CallerInfo veya Quote bağımsız değişkenlerini belirtemiyor + + This type definition involves a cyclic reference through a spread. + This type definition involves a cyclic reference through a spread. + + The type '{0}' does not support a nullness qualification. The type '{0}' does not support a nullness qualification. diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf index 712bae2f841..1037d060431 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf @@ -1,4 +1,4 @@ - + @@ -607,6 +607,11 @@ 列出任何大小的文本 + + record type and expression spreads + record type and expression spreads + + informational messages related to reference cells 与引用单元格相关的信息性消息 @@ -1252,6 +1257,16 @@ 预期成员正文 + + Missing spread source expression after '...'. + Missing spread source expression after '...'. + + + + Missing spread source type after '...'. + Missing spread source type after '...'. + + Missing union case name 缺少联合用例名称 @@ -1267,6 +1282,16 @@ 主构造函数中只允许使用简单模式 + + Spreading is not supported in this construct. + Spreading is not supported in this construct. + + + + Spreading is not supported in this position. Use one of the forms {{ ...expr1; A = expr2 }} or {{ expr1 with A = expr2 }} instead. + Spreading is not supported in this position. Use one of the forms {{ ...expr1; A = expr2 }} or {{ expr1 with A = expr2 }} instead. + + Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration. 静态构造的声明不完整。使用“static let”、“static do”、“static member”或“static val”进行声明。 @@ -1487,6 +1512,16 @@ 字段“{0}”在此匿名记录类型中多次出现。 + + The source expression of a spread into an anonymous record expression cannot be nullable. + The source expression of a spread into an anonymous record expression cannot be nullable. + + + + The source expression of a spread into an anonymous record expression must have a nominal or anonymous record type. + The source expression of a spread into an anonymous record expression must have a nominal or anonymous record type. + + This attribute is not valid for use on union cases with fields. This attribute is not valid for use on union cases with fields. @@ -1777,6 +1812,41 @@ The value or member '{0}' has been marked 'inline' but is part of a recursive binding group. F# does not support recursive 'inline' values. Either remove the 'inline' modifier or refactor the recursion. + + Spread field '{0}' shadows an explicitly declared field with the same name. + Spread field '{0}' shadows an explicitly declared field with the same name. + + + + The source expression of a spread into a nominal record expression cannot be nullable. + The source expression of a spread into a nominal record expression cannot be nullable. + + + + The source expression of a spread into a nominal record expression must have a nominal or anonymous record type. + The source expression of a spread into a nominal record expression must have a nominal or anonymous record type. + + + + Spread expressions and 'with' cannot be used together in the same copy-and-update expression. + Spread expressions and 'with' cannot be used together in the same copy-and-update expression. + + + + Spread field '{0}' from type '{1}' shadows an explicitly declared field with the same name. + Spread field '{0}' from type '{1}' shadows an explicitly declared field with the same name. + + + + The source type of a spread into a record type definition cannot be nullable. + The source type of a spread into a record type definition cannot be nullable. + + + + The source type of a spread into a record type definition must itself be a nominal or anonymous record type. + The source type of a spread into a record type definition must itself be a nominal or anonymous record type. + + The 'let! ... and! ...' construct may only be used if the computation expression builder defines either a '{0}' method or appropriate 'MergeSources' and 'Bind' methods 仅当计算表达式生成器定义了 "{0}" 方法或适当的 "MergeSources" 和 "Bind" 方法时,才可以使用 "let! ... and! ..." 构造 @@ -1862,6 +1932,11 @@ 特征不能指定 option、in、out、ParamArray、CallerInfo 或 Quote 参数 + + This type definition involves a cyclic reference through a spread. + This type definition involves a cyclic reference through a spread. + + The type '{0}' does not support a nullness qualification. The type '{0}' does not support a nullness qualification. diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf index 1e59d46c405..ceb937ec683 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf @@ -1,4 +1,4 @@ - + @@ -607,6 +607,11 @@ 列出任何大小的常值 + + record type and expression spreads + record type and expression spreads + + informational messages related to reference cells 與參考儲存格相關的資訊訊息 @@ -1252,6 +1257,16 @@ 必須是成員主體 + + Missing spread source expression after '...'. + Missing spread source expression after '...'. + + + + Missing spread source type after '...'. + Missing spread source type after '...'. + + Missing union case name 遺漏聯集案例名稱 @@ -1267,6 +1282,16 @@ 主要建構函式中只允許簡單模式 + + Spreading is not supported in this construct. + Spreading is not supported in this construct. + + + + Spreading is not supported in this position. Use one of the forms {{ ...expr1; A = expr2 }} or {{ expr1 with A = expr2 }} instead. + Spreading is not supported in this position. Use one of the forms {{ ...expr1; A = expr2 }} or {{ expr1 with A = expr2 }} instead. + + Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration. 不完整的靜態建構宣告。使用 'static let'、'static do'、'static member' 或 'static val' 進行宣告。 @@ -1487,6 +1512,16 @@ 欄位 '{0}' 在這個匿名記錄類型中出現多次。 + + The source expression of a spread into an anonymous record expression cannot be nullable. + The source expression of a spread into an anonymous record expression cannot be nullable. + + + + The source expression of a spread into an anonymous record expression must have a nominal or anonymous record type. + The source expression of a spread into an anonymous record expression must have a nominal or anonymous record type. + + This attribute is not valid for use on union cases with fields. This attribute is not valid for use on union cases with fields. @@ -1777,6 +1812,41 @@ The value or member '{0}' has been marked 'inline' but is part of a recursive binding group. F# does not support recursive 'inline' values. Either remove the 'inline' modifier or refactor the recursion. + + Spread field '{0}' shadows an explicitly declared field with the same name. + Spread field '{0}' shadows an explicitly declared field with the same name. + + + + The source expression of a spread into a nominal record expression cannot be nullable. + The source expression of a spread into a nominal record expression cannot be nullable. + + + + The source expression of a spread into a nominal record expression must have a nominal or anonymous record type. + The source expression of a spread into a nominal record expression must have a nominal or anonymous record type. + + + + Spread expressions and 'with' cannot be used together in the same copy-and-update expression. + Spread expressions and 'with' cannot be used together in the same copy-and-update expression. + + + + Spread field '{0}' from type '{1}' shadows an explicitly declared field with the same name. + Spread field '{0}' from type '{1}' shadows an explicitly declared field with the same name. + + + + The source type of a spread into a record type definition cannot be nullable. + The source type of a spread into a record type definition cannot be nullable. + + + + The source type of a spread into a record type definition must itself be a nominal or anonymous record type. + The source type of a spread into a record type definition must itself be a nominal or anonymous record type. + + The 'let! ... and! ...' construct may only be used if the computation expression builder defines either a '{0}' method or appropriate 'MergeSources' and 'Bind' methods 只有在計算運算式產生器定義 '{0}' 方法或正確的 'MergeSource' 和 'Bind' 方法時,才可使用 'let! ... and! ...' 建構 @@ -1862,6 +1932,11 @@ 特徵不能指定選擇性、in、out、ParamArray、CallerInfo 或 Quote 引數 + + This type definition involves a cyclic reference through a spread. + This type definition involves a cyclic reference through a spread. + + The type '{0}' does not support a nullness qualification. The type '{0}' does not support a nullness qualification. diff --git a/src/Compiler/xlf/FSStrings.cs.xlf b/src/Compiler/xlf/FSStrings.cs.xlf index 2a344c5d674..9c7f8dacff3 100644 --- a/src/Compiler/xlf/FSStrings.cs.xlf +++ b/src/Compiler/xlf/FSStrings.cs.xlf @@ -112,6 +112,11 @@ symbol '|' (directly before 'null') + + symbol '...' + symbol '...' + + symbol '..^' symbol ..^ diff --git a/src/Compiler/xlf/FSStrings.de.xlf b/src/Compiler/xlf/FSStrings.de.xlf index eb13919bfaf..dcd1e5c6a30 100644 --- a/src/Compiler/xlf/FSStrings.de.xlf +++ b/src/Compiler/xlf/FSStrings.de.xlf @@ -112,6 +112,11 @@ symbol '|' (directly before 'null') + + symbol '...' + symbol '...' + + symbol '..^' Symbol "..^" diff --git a/src/Compiler/xlf/FSStrings.es.xlf b/src/Compiler/xlf/FSStrings.es.xlf index 1fc832b7e27..a6b1d92f9b2 100644 --- a/src/Compiler/xlf/FSStrings.es.xlf +++ b/src/Compiler/xlf/FSStrings.es.xlf @@ -112,6 +112,11 @@ symbol '|' (directly before 'null') + + symbol '...' + symbol '...' + + symbol '..^' símbolo "..^" diff --git a/src/Compiler/xlf/FSStrings.fr.xlf b/src/Compiler/xlf/FSStrings.fr.xlf index b539a265b93..db5381544a2 100644 --- a/src/Compiler/xlf/FSStrings.fr.xlf +++ b/src/Compiler/xlf/FSStrings.fr.xlf @@ -112,6 +112,11 @@ symbol '|' (directly before 'null') + + symbol '...' + symbol '...' + + symbol '..^' symbole '..^' diff --git a/src/Compiler/xlf/FSStrings.it.xlf b/src/Compiler/xlf/FSStrings.it.xlf index acd4ffcfe20..902108cf645 100644 --- a/src/Compiler/xlf/FSStrings.it.xlf +++ b/src/Compiler/xlf/FSStrings.it.xlf @@ -112,6 +112,11 @@ symbol '|' (directly before 'null') + + symbol '...' + symbol '...' + + symbol '..^' simbolo '..^' diff --git a/src/Compiler/xlf/FSStrings.ja.xlf b/src/Compiler/xlf/FSStrings.ja.xlf index 2d199d7f94e..97c3f25b53b 100644 --- a/src/Compiler/xlf/FSStrings.ja.xlf +++ b/src/Compiler/xlf/FSStrings.ja.xlf @@ -112,6 +112,11 @@ symbol '|' (directly before 'null') + + symbol '...' + symbol '...' + + symbol '..^' シンボル '..^' diff --git a/src/Compiler/xlf/FSStrings.ko.xlf b/src/Compiler/xlf/FSStrings.ko.xlf index 2611ca958be..efd8b23b190 100644 --- a/src/Compiler/xlf/FSStrings.ko.xlf +++ b/src/Compiler/xlf/FSStrings.ko.xlf @@ -112,6 +112,11 @@ symbol '|' (directly before 'null') + + symbol '...' + symbol '...' + + symbol '..^' 기호 '..^' diff --git a/src/Compiler/xlf/FSStrings.pl.xlf b/src/Compiler/xlf/FSStrings.pl.xlf index 27c6d4455ce..8949f6d2643 100644 --- a/src/Compiler/xlf/FSStrings.pl.xlf +++ b/src/Compiler/xlf/FSStrings.pl.xlf @@ -112,6 +112,11 @@ symbol '|' (directly before 'null') + + symbol '...' + symbol '...' + + symbol '..^' symbol „..^” diff --git a/src/Compiler/xlf/FSStrings.pt-BR.xlf b/src/Compiler/xlf/FSStrings.pt-BR.xlf index df00934621b..5e1b18362a9 100644 --- a/src/Compiler/xlf/FSStrings.pt-BR.xlf +++ b/src/Compiler/xlf/FSStrings.pt-BR.xlf @@ -112,6 +112,11 @@ symbol '|' (directly before 'null') + + symbol '...' + symbol '...' + + symbol '..^' símbolo '..^' diff --git a/src/Compiler/xlf/FSStrings.ru.xlf b/src/Compiler/xlf/FSStrings.ru.xlf index a0958ee1efc..df53e00e608 100644 --- a/src/Compiler/xlf/FSStrings.ru.xlf +++ b/src/Compiler/xlf/FSStrings.ru.xlf @@ -112,6 +112,11 @@ symbol '|' (directly before 'null') + + symbol '...' + symbol '...' + + symbol '..^' символ "..^" diff --git a/src/Compiler/xlf/FSStrings.tr.xlf b/src/Compiler/xlf/FSStrings.tr.xlf index 509eb6d5ac6..ccbf93e7d51 100644 --- a/src/Compiler/xlf/FSStrings.tr.xlf +++ b/src/Compiler/xlf/FSStrings.tr.xlf @@ -112,6 +112,11 @@ symbol '|' (directly before 'null') + + symbol '...' + symbol '...' + + symbol '..^' '..^' sembolü diff --git a/src/Compiler/xlf/FSStrings.zh-Hans.xlf b/src/Compiler/xlf/FSStrings.zh-Hans.xlf index 7a3c8482ebc..95cc39ed6f6 100644 --- a/src/Compiler/xlf/FSStrings.zh-Hans.xlf +++ b/src/Compiler/xlf/FSStrings.zh-Hans.xlf @@ -112,6 +112,11 @@ symbol '|' (directly before 'null') + + symbol '...' + symbol '...' + + symbol '..^' 符号 "..^" diff --git a/src/Compiler/xlf/FSStrings.zh-Hant.xlf b/src/Compiler/xlf/FSStrings.zh-Hant.xlf index e671202ffb2..06ed5826235 100644 --- a/src/Compiler/xlf/FSStrings.zh-Hant.xlf +++ b/src/Compiler/xlf/FSStrings.zh-Hant.xlf @@ -112,6 +112,11 @@ symbol '|' (directly before 'null') + + symbol '...' + symbol '...' + + symbol '..^' 符號 '..^' diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/Constraints/Unmanaged.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/Constraints/Unmanaged.fs index 712333340fa..8340ac9be7f 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/Constraints/Unmanaged.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/Constraints/Unmanaged.fs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. namespace Conformance.Constraints diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/Spreads/RecordSpreads.fsx b/tests/FSharp.Compiler.ComponentTests/Conformance/Spreads/RecordSpreads.fsx new file mode 100644 index 00000000000..c83a88a43ab --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/Spreads/RecordSpreads.fsx @@ -0,0 +1,86 @@ +#r "SpreadInlineLib.dll" + +open System +let errors = ResizeArray() +let check label cond = if not cond then errors.Add label + +type Pt = { X : int; Y : int } +type Lbl = { A : int; B : int } + +module ``Units of measure preserved through overriding spread`` = + [] type m + type Tagged = { D : int; Note : string } + check "D measure stripped" ({ ...{ D = 5; Note = "a" }; D = 9 }.D = 9) + +module ``Type alias as spread source`` = + type PtAlias = Pt + type FromAlias = { ...PtAlias; Z : int } + let v : FromAlias = { ...{ X = 10; Y = 20 }; Z = 30 } + check "alias source dropped fields" (v.X = 10 && v.Z = 30) + +module ``Elaborated tree shape inside FSharp Quotations`` = + open Microsoft.FSharp.Quotations.Patterns + let rec args expr = + match expr with + | Let (_, _, body) -> args body + | NewRecord (_, a) -> Some a.Length + | _ -> None + let p = { X = 1; Y = 2 } + check "quotation record/anon shape" (args <@ { ...p; Y = 3 } @> = Some 2 && args <@ {| ...p; W = 5 |} @> = Some 3) + +module ``Spread inside seq, async and task state machines`` = + let b = { A = 1; B = 2 } + let fromSeq = seq { for i in 1..2 -> { ...b; A = i } } |> Seq.toList + check "seq spread wrong" (fromSeq.[1].A = 2) + check "async return wrong" ((async { return { ...b; A = 9 } } |> Async.RunSynchronously).A = 9) + check "task return wrong" ((task { return { ...b; A = 7 } }).Result.A = 7) + +module ``CLIMutable target emits settable IL properties for spread-carried fields`` = + type Src = { A : int; B : int } + [] type Dst = { ...Src; C : int } + let hasCli (t: Type) = t.GetCustomAttributes(typeof, false).Length > 0 + let settable n = typeof.GetProperty(n: string).CanWrite + check "CLIMutable attr leaked to Src" (not (hasCli typeof)) + check "Dst missing CLIMutable" (hasCli typeof) + check "settable A/B/C" (settable "A" && settable "B" && settable "C") + check "Dst C wrong" (({ ...{ A = 1; B = 2 }; C = 3 } : Dst).C = 3) + +module ``Type-level attributes do not propagate from spread source`` = + [] type Src = { A : int; B : int } + type Plain = { ...Src; C : int } + let has<'a when 'a :> Attribute> (t: Type) = t.GetCustomAttributes(typeof<'a>, false).Length > 0 + check "CLIMutable propagated to Plain" (not (has typeof)) + check "NoComparison propagated to Plain" (not (has typeof)) + check "Src lost CLIMutable" (has typeof) + +module ``Mutable field carried via spread, then overridden`` = + type R = { mutable M : int; Name : string } + check "mutable override wrong" ({ ...{ M = 1; Name = "a" }; M = 10 }.M = 10) + +module ``SRTP resolves member carried by the spread source`` = + let inline getB< ^T when ^T : (member B : int)> (x: ^T) = (^T : (member B : int) x) + check "SRTP getB <> 6" (getB {| ...{| A = 5; B = 6 |}; A = 7 |} = 6) + +module ``Inline spread elaboration across an assembly boundary`` = + let r = SpreadInlineLib.bump { SpreadInlineLib.Lbl.A = 0; B = 7 } + check "cross-assembly bump A/B" (r.A = 99 && r.B = 7) + +module ``Property-get expression as spread source`` = + type Holder() = member _.P = { A = 1; B = 2 } + let r = { ...(Holder()).P; B = 9 } + check "property-get source dropped fields" (r.A = 1 && r.B = 9) + +module ``Field-level attribute carries from spread source to target`` = + type Src = { [] A : int; B : int } + type Dst = { ...Src; C : int } + let obsolete (t: Type) = t.GetProperty("A").GetCustomAttributes(typeof, false).Length + check "field attr not carried Src/Dst" (obsolete typeof = 1 && obsolete typeof = 1) + +module ``Linear non-mutual transitive spread chain`` = + type A = { Z : int } + type B = { ...A; Y : int } + type C = { ...B; X : int } + let c : C = { Z = 1; Y = 2; X = 3 } + check "transitive chain dropped fields" (c.Z = 1 && c.X = 3) +if errors.Count > 0 then + failwithf "%d failures:\n%s" errors.Count (String.concat "\n" errors) diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/Spreads/RecordSpreadsTests.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/Spreads/RecordSpreadsTests.fs new file mode 100644 index 00000000000..cea7e7955c6 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/Spreads/RecordSpreadsTests.fs @@ -0,0 +1,28 @@ +module Conformance.Spreads.Records + +open System.IO +open Xunit +open FSharp.Test +open FSharp.Test.Compiler + +[] +let SupportedLangVersion = "preview" + +let inlineLib = + FsFromPath (Path.Combine (__SOURCE_DIRECTORY__, "SpreadInlineLib.fs")) + |> withLangVersion SupportedLangVersion + |> withName "SpreadInlineLib" + |> asLibrary + +let verifyCompileAndRun compilation = + compilation + |> asExe + |> withLangVersion SupportedLangVersion + |> compileAndRun + +[] +let ``RecordSpreads_fsx`` compilation = + compilation + |> withReferences [inlineLib] + |> verifyCompileAndRun + |> shouldSucceed diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/Spreads/SpreadInlineLib.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/Spreads/SpreadInlineLib.fs new file mode 100644 index 00000000000..e157ae30f5b --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/Spreads/SpreadInlineLib.fs @@ -0,0 +1,7 @@ +module SpreadInlineLib +// Library compiled to its own assembly. The inline body below is serialized +// into the assembly's pickled TypedTree and re-elaborated at the caller's +// site in another assembly (Spreading_v1.fsx), exercising the spread +// elaboration across the TypedTreePickle boundary. +type Lbl = { A : int; B : int } +let inline bump (x: Lbl) = { ...x; A = 99 } diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/Types/RecordTypes/AnonymousRecords.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/Types/RecordTypes/AnonymousRecords.fs index beef862b27a..dce13c8da38 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/Types/RecordTypes/AnonymousRecords.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/Types/RecordTypes/AnonymousRecords.fs @@ -446,7 +446,7 @@ let v = {| A = 1; A = 2 |} |> compile |> shouldFail |> withDiagnostics [ - (Error 3522, Line 2, Col 12, Line 2, Col 13, "The field 'A' appears multiple times in this record expression.") + (Error 3522, Line 2, Col 19, Line 2, Col 24, "The field 'A' appears multiple times in this record expression.") ] [] @@ -457,8 +457,8 @@ let v = {| A = 1; A = 2; A = 3 |} |> compile |> shouldFail |> withDiagnostics [ - (Error 3522, Line 2, Col 12, Line 2, Col 13, "The field 'A' appears multiple times in this record expression.") - (Error 3522, Line 2, Col 19, Line 2, Col 20, "The field 'A' appears multiple times in this record expression.") + Error 3522, Line 2, Col 19, Line 2, Col 24, "The field 'A' appears multiple times in this record expression." + Error 3522, Line 2, Col 26, Line 2, Col 31, "The field 'A' appears multiple times in this record expression." ] [] @@ -469,8 +469,8 @@ let v = {| A = 0; B = 2; A = 5; B = 6 |} |> compile |> shouldFail |> withDiagnostics [ - (Error 3522, Line 2, Col 12, Line 2, Col 13, "The field 'A' appears multiple times in this record expression.") - (Error 3522, Line 2, Col 19, Line 2, Col 20, "The field 'B' appears multiple times in this record expression.") + Error 3522, Line 2, Col 26, Line 2, Col 31, "The field 'A' appears multiple times in this record expression." + Error 3522, Line 2, Col 33, Line 2, Col 38, "The field 'B' appears multiple times in this record expression." ] [] @@ -481,7 +481,7 @@ let v = {| A = 2; C = "W"; A = 8; B = 6 |} |> compile |> shouldFail |> withDiagnostics [ - (Error 3522, Line 2, Col 12, Line 2, Col 13, "The field 'A' appears multiple times in this record expression.") + Error 3522, Line 2, Col 28, Line 2, Col 33, "The field 'A' appears multiple times in this record expression." ] [] @@ -492,8 +492,8 @@ let v = {| A = 0; C = ""; A = 1; B = 2; A = 5 |} |> compile |> shouldFail |> withDiagnostics [ - (Error 3522, Line 2, Col 12, Line 2, Col 13, "The field 'A' appears multiple times in this record expression.") - (Error 3522, Line 2, Col 27, Line 2, Col 28, "The field 'A' appears multiple times in this record expression.") + Error 3522, Line 2, Col 27, Line 2, Col 32, "The field 'A' appears multiple times in this record expression." + Error 3522, Line 2, Col 41, Line 2, Col 46, "The field 'A' appears multiple times in this record expression." ] [] @@ -504,8 +504,8 @@ let v = {| ``A`` = 0; B = 5; A = ""; B = 0 |} |> compile |> shouldFail |> withDiagnostics [ - (Error 3522, Line 2, Col 12, Line 2, Col 17, "The field 'A' appears multiple times in this record expression.") - (Error 3522, Line 2, Col 23, Line 2, Col 24, "The field 'B' appears multiple times in this record expression.") + Error 3522, Line 2, Col 30, Line 2, Col 36, "The field 'A' appears multiple times in this record expression." + Error 3522, Line 2, Col 38, Line 2, Col 43, "The field 'B' appears multiple times in this record expression." ] [] diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/Types/RecordTypes/RecordTypes.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/Types/RecordTypes/RecordTypes.fs index 3bae9db5802..8e8bd6a1dd6 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/Types/RecordTypes/RecordTypes.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/Types/RecordTypes/RecordTypes.fs @@ -441,7 +441,7 @@ module RecordTypes = |> typecheck |> shouldFail |> withDiagnostics [ - (Error 668, Line 4, Col 16, Line 4, Col 17, "The field 'B' appears multiple times in this record expression or pattern") + Error 668, Line 4, Col 25, Line 4, Col 32, "The field 'B' appears multiple times in this record expression or pattern" ] [] @@ -454,8 +454,8 @@ module RecordTypes = |> typecheck |> shouldFail |> withDiagnostics [ - (Error 668, Line 4, Col 16, Line 4, Col 17, "The field 'B' appears multiple times in this record expression or pattern") - (Error 668, Line 4, Col 25, Line 4, Col 26, "The field 'B' appears multiple times in this record expression or pattern") + Error 668, Line 4, Col 25, Line 4, Col 32, "The field 'B' appears multiple times in this record expression or pattern" + Error 668, Line 4, Col 34, Line 4, Col 41, "The field 'B' appears multiple times in this record expression or pattern" ] [] @@ -468,8 +468,8 @@ module RecordTypes = |> typecheck |> shouldFail |> withDiagnostics [ - (Error 668, Line 4, Col 16, Line 4, Col 17, "The field 'A' appears multiple times in this record expression or pattern") - (Error 668, Line 4, Col 23, Line 4, Col 24, "The field 'B' appears multiple times in this record expression or pattern") + Error 668, Line 4, Col 30, Line 4, Col 35, "The field 'A' appears multiple times in this record expression or pattern" + Error 668, Line 4, Col 37, Line 4, Col 42, "The field 'B' appears multiple times in this record expression or pattern" ] [] @@ -482,7 +482,7 @@ module RecordTypes = |> typecheck |> shouldFail |> withDiagnostics [ - (Error 668, Line 4, Col 16, Line 4, Col 17, "The field 'A' appears multiple times in this record expression or pattern") + Error 668, Line 4, Col 31, Line 4, Col 36, "The field 'A' appears multiple times in this record expression or pattern" ] [] @@ -495,8 +495,8 @@ module RecordTypes = |> typecheck |> shouldFail |> withDiagnostics [ - (Error 668, Line 4, Col 16, Line 4, Col 17, "The field 'A' appears multiple times in this record expression or pattern") - (Error 668, Line 4, Col 31, Line 4, Col 32, "The field 'A' appears multiple times in this record expression or pattern") + Error 668, Line 4, Col 31, Line 4, Col 36, "The field 'A' appears multiple times in this record expression or pattern" + Error 668, Line 4, Col 45, Line 4, Col 50, "The field 'A' appears multiple times in this record expression or pattern" ] [] @@ -509,8 +509,8 @@ module RecordTypes = |> typecheck |> shouldFail |> withDiagnostics [ - (Error 668, Line 4, Col 16, Line 4, Col 21, "The field 'A' appears multiple times in this record expression or pattern") - (Error 668, Line 4, Col 27, Line 4, Col 28, "The field 'B' appears multiple times in this record expression or pattern") + Error 668, Line 4, Col 34, Line 4, Col 39, "The field 'A' appears multiple times in this record expression or pattern" + Error 668, Line 4, Col 41, Line 4, Col 46, "The field 'B' appears multiple times in this record expression or pattern" ] [] diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/AnonymousRecordExpressionSpreads.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/AnonymousRecordExpressionSpreads.fs new file mode 100644 index 00000000000..d6bcc771f29 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/AnonymousRecordExpressionSpreads.fs @@ -0,0 +1,84 @@ +module EmittedIL.AnonymousRecordExpressionSpreads + +open FSharp.Test +open FSharp.Test.Compiler + +/// Various types in the System.Diagnostics.CodeAnalysis namespace will be generated by the compiler +/// for the Framework target but will be included in the runtime for the .NET (Core) target. +/// Since the only IL that is material here is the field names, types, and ordering, +/// and since the spread logic is entirely framework/runtime-agnostic, +/// it is simpler to run these tests only for the .NET (Core) target. +type TheoryAttribute = TheoryForNETCOREAPPAttribute + +let [] SupportedLangVersion = "preview" + +let verifyCompilation compilation = + compilation + |> withLangVersion SupportedLangVersion + |> asExe + |> withEmbeddedPdb + |> withEmbedAllSource + |> ignoreWarnings + |> compile + |> shouldSucceed + |> verifyILBaseline + +[] +let Expression_Anonymous_ExplicitShadowsSpread_fs compilation = + compilation + |> getCompilation + |> verifyCompilation + +[] +let Expression_Anonymous_ExtraFieldsAreIgnored_fs compilation = + compilation + |> getCompilation + |> verifyCompilation + +[] +let Expression_Anonymous_NoOverlap_Explicit_Spread_fs compilation = + compilation + |> getCompilation + |> verifyCompilation + +[] +let Expression_Anonymous_NoOverlap_Spread_Explicit_fs compilation = + compilation + |> getCompilation + |> verifyCompilation + +[] +let Expression_Anonymous_NoOverlap_Spread_Spread_fs compilation = + compilation + |> getCompilation + |> verifyCompilation + +[] +let Expression_Anonymous_SpreadShadowsExplicit_fs compilation = + compilation + |> getCompilation + |> verifyCompilation + +[] +let Expression_Anonymous_SpreadShadowsSpread_fs compilation = + compilation + |> getCompilation + |> verifyCompilation + +[] +let Expression_Anonymous_CoercionsApplied_fs compilation = + compilation + |> getCompilation + |> verifyCompilation + +[] +let Expression_Anonymous_Structness_fs compilation = + compilation + |> getCompilation + |> verifyCompilation + +[] +let Expression_Anonymous_NestedUpdates_fs compilation = + compilation + |> getCompilation + |> verifyCompilation diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_CoercionsApplied.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_CoercionsApplied.fs new file mode 100644 index 00000000000..ee2234e6ad5 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_CoercionsApplied.fs @@ -0,0 +1,13 @@ +[] +type T = + | T of int + static member op_Implicit (T t) = U t + +and [] U = + | U of int + +#nowarn 3391 + +let r6 : {| A : T |} = {| A = T 3 |} +let r7 : {| A : U |} = {| A = T 3 |} +let r8 : {| A : U |} = {| ...r6 |} diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_CoercionsApplied.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_CoercionsApplied.fs.il.bsl new file mode 100644 index 00000000000..0477036817d --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_CoercionsApplied.fs.il.bsl @@ -0,0 +1,678 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto autochar serializable sealed nested public beforefieldinit T + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.DefaultAugmentationAttribute::.ctor(bool) = ( 01 00 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerDisplayAttribute::.ctor(string) = ( 01 00 15 7B 5F 5F 44 65 62 75 67 44 69 73 70 6C + 61 79 28 29 2C 6E 71 7D 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 01 00 00 00 00 00 ) + .field assembly initonly int32 item + .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 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method public specialname rtspecialname instance void .ctor(int32 item) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 27 45 78 70 72 65 73 73 69 6F + 6E 5F 41 6E 6F 6E 79 6D 6F 75 73 5F 43 6F 65 72 + 63 69 6F 6E 73 41 70 70 6C 69 65 64 2B 54 00 00 ) + .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 [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld int32 assembly/T::item + IL_000d: ret + } + + .method public hidebysig instance int32 get_Item() 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: ldfld int32 assembly/T::item + IL_0006: ret + } + + .method public hidebysig instance int32 get_Tag() 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: pop + IL_0002: ldc.i4.0 + IL_0003: ret + } + + .method assembly hidebysig specialname instance object __DebugDisplay() 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: ldstr "%+0.8A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,string>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/T>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .method public specialname static class assembly/U op_Implicit(class assembly/T _arg1) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld int32 assembly/T::item + IL_0006: newobj instance void assembly/U::.ctor(int32) + IL_000b: ret + } + + .property instance int32 Tag() + { + .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 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .get instance int32 assembly/T::get_Tag() + } + .property instance int32 Item() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + .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 ) + .get instance int32 assembly/T::get_Item() + } + } + + .class auto autochar serializable sealed nested public beforefieldinit U + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.DefaultAugmentationAttribute::.ctor(bool) = ( 01 00 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerDisplayAttribute::.ctor(string) = ( 01 00 15 7B 5F 5F 44 65 62 75 67 44 69 73 70 6C + 61 79 28 29 2C 6E 71 7D 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 01 00 00 00 00 00 ) + .field assembly initonly int32 item + .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 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method public specialname rtspecialname instance void .ctor(int32 item) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 27 45 78 70 72 65 73 73 69 6F + 6E 5F 41 6E 6F 6E 79 6D 6F 75 73 5F 43 6F 65 72 + 63 69 6F 6E 73 41 70 70 6C 69 65 64 2B 55 00 00 ) + .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 [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld int32 assembly/U::item + IL_000d: ret + } + + .method public hidebysig instance int32 get_Item() 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: ldfld int32 assembly/U::item + IL_0006: ret + } + + .method public hidebysig instance int32 get_Tag() 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: pop + IL_0002: ldc.i4.0 + IL_0003: ret + } + + .method assembly hidebysig specialname instance object __DebugDisplay() 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: ldstr "%+0.8A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,string>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/U>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .property instance int32 Tag() + { + .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 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .get instance int32 assembly/U::get_Tag() + } + .property instance int32 Item() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + .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 ) + .get instance int32 assembly/U::get_Item() + } + } + + .field static assembly class '<>f__AnonymousType2396826819`1' r6@11 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly class '<>f__AnonymousType2396826819`1' r7@12 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly class '<>f__AnonymousType2396826819`1' r8@13 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly class assembly/T _arg1@4 + .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 '<>f__AnonymousType2396826819`1' get_r6() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class '<>f__AnonymousType2396826819`1' assembly::r6@11 + IL_0005: ret + } + + .method public specialname static class '<>f__AnonymousType2396826819`1' get_r7() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class '<>f__AnonymousType2396826819`1' assembly::r7@12 + IL_0005: ret + } + + .method public specialname static class '<>f__AnonymousType2396826819`1' get_r8() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class '<>f__AnonymousType2396826819`1' assembly::r8@13 + IL_0005: ret + } + + .method assembly specialname static class assembly/T get__arg1@4() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class assembly/T assembly::_arg1@4 + IL_0005: ret + } + + .method private specialname rtspecialname static void .cctor() cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.0 + IL_0001: stsfld int32 ''.$assembly::init@ + IL_0006: ldsfld int32 ''.$assembly::init@ + IL_000b: pop + IL_000c: ret + } + + .method assembly static void staticInitialization@() cil managed + { + + .maxstack 3 + IL_0000: ldc.i4.3 + IL_0001: newobj instance void assembly/T::.ctor(int32) + IL_0006: newobj instance void class '<>f__AnonymousType2396826819`1'::.ctor(!0) + IL_000b: stsfld class '<>f__AnonymousType2396826819`1' assembly::r6@11 + IL_0010: ldc.i4.3 + IL_0011: newobj instance void assembly/U::.ctor(int32) + IL_0016: newobj instance void class '<>f__AnonymousType2396826819`1'::.ctor(!0) + IL_001b: stsfld class '<>f__AnonymousType2396826819`1' assembly::r7@12 + IL_0020: call class '<>f__AnonymousType2396826819`1' assembly::get_r6() + IL_0025: call instance !0 class '<>f__AnonymousType2396826819`1'::get_A() + IL_002a: stsfld class assembly/T assembly::_arg1@4 + IL_002f: call class assembly/T assembly::get__arg1@4() + IL_0034: ldfld int32 assembly/T::item + IL_0039: newobj instance void assembly/U::.ctor(int32) + IL_003e: newobj instance void class '<>f__AnonymousType2396826819`1'::.ctor(!0) + IL_0043: stsfld class '<>f__AnonymousType2396826819`1' assembly::r8@13 + IL_0048: ret + } + + .property class '<>f__AnonymousType2396826819`1' + r6() + { + .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 class '<>f__AnonymousType2396826819`1' assembly::get_r6() + } + .property class '<>f__AnonymousType2396826819`1' + r7() + { + .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 class '<>f__AnonymousType2396826819`1' assembly::get_r7() + } + .property class '<>f__AnonymousType2396826819`1' + r8() + { + .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 class '<>f__AnonymousType2396826819`1' assembly::get_r8() + } + .property class assembly/T + _arg1@4() + { + .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 class assembly/T assembly::get__arg1@4() + } +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .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 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: call void assembly::staticInitialization@() + IL_0005: ret + } + +} + +.class public auto ansi serializable sealed beforefieldinit '<>f__AnonymousType2396826819`1'<'j__TPar'> + extends [runtime]System.Object + implements [runtime]System.Collections.IStructuralComparable, + [runtime]System.IComparable, + class [runtime]System.IComparable`1f__AnonymousType2396826819`1'j__TPar'>>, + [runtime]System.Collections.IStructuralEquatable, + class [runtime]System.IEquatable`1f__AnonymousType2396826819`1'j__TPar'>> +{ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field private !'j__TPar' A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor(!'j__TPar' A) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 1E 3C 3E 66 5F 5F 41 6E 6F 6E + 79 6D 6F 75 73 54 79 70 65 32 33 39 36 38 32 36 + 38 31 39 60 31 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld !0 class '<>f__AnonymousType2396826819`1'j__TPar'>::A@ + IL_000d: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_A() 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: ldfld !0 class '<>f__AnonymousType2396826819`1'j__TPar'>::A@ + IL_0006: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5f__AnonymousType2396826819`1'j__TPar'>,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class '<>f__AnonymousType2396826819`1'j__TPar'>>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToStringf__AnonymousType2396826819`1'j__TPar'>,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2f__AnonymousType2396826819`1'j__TPar'>,string>::Invoke(!0) + IL_0015: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(class '<>f__AnonymousType2396826819`1'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0021 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_001f + + IL_0006: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_000b: ldarg.0 + IL_000c: ldfld !0 class '<>f__AnonymousType2396826819`1'j__TPar'>::A@ + IL_0011: ldarg.1 + IL_0012: ldfld !0 class '<>f__AnonymousType2396826819`1'j__TPar'>::A@ + IL_0017: tail. + IL_0019: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_001e: ret + + IL_001f: ldc.i4.1 + IL_0020: ret + + IL_0021: ldarg.1 + IL_0022: brfalse.s IL_0026 + + IL_0024: ldc.i4.m1 + IL_0025: ret + + IL_0026: ldc.i4.0 + IL_0027: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: unbox.any class '<>f__AnonymousType2396826819`1'j__TPar'> + IL_0007: tail. + IL_0009: callvirt instance int32 class '<>f__AnonymousType2396826819`1'j__TPar'>::CompareTo(class '<>f__AnonymousType2396826819`1') + IL_000e: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj, class [runtime]System.Collections.IComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType2396826819`1'j__TPar'> V_0, + class '<>f__AnonymousType2396826819`1'j__TPar'> V_1) + IL_0000: ldarg.1 + IL_0001: unbox.any class '<>f__AnonymousType2396826819`1'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: stloc.1 + IL_0009: ldarg.0 + IL_000a: brfalse.s IL_002b + + IL_000c: ldarg.1 + IL_000d: unbox.any class '<>f__AnonymousType2396826819`1'j__TPar'> + IL_0012: brfalse.s IL_0029 + + IL_0014: ldarg.2 + IL_0015: ldarg.0 + IL_0016: ldfld !0 class '<>f__AnonymousType2396826819`1'j__TPar'>::A@ + IL_001b: ldloc.1 + IL_001c: ldfld !0 class '<>f__AnonymousType2396826819`1'j__TPar'>::A@ + IL_0021: tail. + IL_0023: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0028: ret + + IL_0029: ldc.i4.1 + IL_002a: ret + + IL_002b: ldarg.1 + IL_002c: unbox.any class '<>f__AnonymousType2396826819`1'j__TPar'> + IL_0031: brfalse.s IL_0035 + + IL_0033: ldc.i4.m1 + IL_0034: ret + + IL_0035: ldc.i4.0 + IL_0036: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode(class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 7 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0022 + + IL_0003: ldc.i4.0 + IL_0004: stloc.0 + IL_0005: ldc.i4 0x9e3779b9 + IL_000a: ldarg.1 + IL_000b: ldarg.0 + IL_000c: ldfld !0 class '<>f__AnonymousType2396826819`1'j__TPar'>::A@ + IL_0011: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0016: ldloc.0 + IL_0017: ldc.i4.6 + IL_0018: shl + IL_0019: ldloc.0 + IL_001a: ldc.i4.2 + IL_001b: shr + IL_001c: add + IL_001d: add + IL_001e: add + IL_001f: stloc.0 + IL_0020: ldloc.0 + IL_0021: ret + + IL_0022: ldc.i4.0 + IL_0023: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() + IL_0006: tail. + IL_0008: callvirt instance int32 class '<>f__AnonymousType2396826819`1'j__TPar'>::GetHashCode(class [runtime]System.Collections.IEqualityComparer) + IL_000d: ret + } + + .method public hidebysig instance bool Equals(class '<>f__AnonymousType2396826819`1'j__TPar'> obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType2396826819`1'j__TPar'> V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_001f + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_001d + + IL_0006: ldarg.1 + IL_0007: stloc.0 + IL_0008: ldarg.2 + IL_0009: ldarg.0 + IL_000a: ldfld !0 class '<>f__AnonymousType2396826819`1'j__TPar'>::A@ + IL_000f: ldloc.0 + IL_0010: ldfld !0 class '<>f__AnonymousType2396826819`1'j__TPar'>::A@ + IL_0015: tail. + IL_0017: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_001c: ret + + IL_001d: ldc.i4.0 + IL_001e: ret + + IL_001f: ldarg.1 + IL_0020: ldnull + IL_0021: cgt.un + IL_0023: ldc.i4.0 + IL_0024: ceq + IL_0026: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType2396826819`1'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType2396826819`1'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0015 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: ldarg.2 + IL_000d: tail. + IL_000f: callvirt instance bool class '<>f__AnonymousType2396826819`1'j__TPar'>::Equals(class '<>f__AnonymousType2396826819`1', + class [runtime]System.Collections.IEqualityComparer) + IL_0014: ret + + IL_0015: ldc.i4.0 + IL_0016: ret + } + + .method public hidebysig virtual final instance bool Equals(class '<>f__AnonymousType2396826819`1'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_001c + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_001a + + IL_0006: ldarg.0 + IL_0007: ldfld !0 class '<>f__AnonymousType2396826819`1'j__TPar'>::A@ + IL_000c: ldarg.1 + IL_000d: ldfld !0 class '<>f__AnonymousType2396826819`1'j__TPar'>::A@ + IL_0012: tail. + IL_0014: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_0019: ret + + IL_001a: ldc.i4.0 + IL_001b: ret + + IL_001c: ldarg.1 + IL_001d: ldnull + IL_001e: cgt.un + IL_0020: ldc.i4.0 + IL_0021: ceq + IL_0023: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (class '<>f__AnonymousType2396826819`1'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType2396826819`1'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0014 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: tail. + IL_000e: callvirt instance bool class '<>f__AnonymousType2396826819`1'j__TPar'>::Equals(class '<>f__AnonymousType2396826819`1') + IL_0013: ret + + IL_0014: ldc.i4.0 + IL_0015: ret + } + + .property instance !'j__TPar' A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType2396826819`1'::get_A() + } +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_ExplicitShadowsSpread.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_ExplicitShadowsSpread.fs new file mode 100644 index 00000000000..44deb03b4bd --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_ExplicitShadowsSpread.fs @@ -0,0 +1,3 @@ +let r1 = {| A = 1; B = 2 |} + +let r2 : {| A : string; B : int |} = {| ...r1; A = "A" |} diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_ExplicitShadowsSpread.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_ExplicitShadowsSpread.fs.il.bsl new file mode 100644 index 00000000000..b75ee4434dd --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_ExplicitShadowsSpread.fs.il.bsl @@ -0,0 +1,544 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .field static assembly class '<>f__AnonymousType986704712`2' r1@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 class '<>f__AnonymousType986704712`2' r2@3 + .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 '<>f__AnonymousType986704712`2' get_r1() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class '<>f__AnonymousType986704712`2' assembly::r1@1 + IL_0005: ret + } + + .method public specialname static class '<>f__AnonymousType986704712`2' get_r2() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class '<>f__AnonymousType986704712`2' assembly::r2@3 + IL_0005: ret + } + + .method private specialname rtspecialname static void .cctor() cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.0 + IL_0001: stsfld int32 ''.$assembly::init@ + IL_0006: ldsfld int32 ''.$assembly::init@ + IL_000b: pop + IL_000c: ret + } + + .method assembly static void staticInitialization@() cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.1 + IL_0001: ldc.i4.2 + IL_0002: newobj instance void class '<>f__AnonymousType986704712`2'::.ctor(!0, + !1) + IL_0007: stsfld class '<>f__AnonymousType986704712`2' assembly::r1@1 + IL_000c: ldstr "A" + IL_0011: call class '<>f__AnonymousType986704712`2' assembly::get_r1() + IL_0016: call instance !1 class '<>f__AnonymousType986704712`2'::get_B() + IL_001b: newobj instance void class '<>f__AnonymousType986704712`2'::.ctor(!0, + !1) + IL_0020: stsfld class '<>f__AnonymousType986704712`2' assembly::r2@3 + IL_0025: ret + } + + .property class '<>f__AnonymousType986704712`2' + r1() + { + .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 class '<>f__AnonymousType986704712`2' assembly::get_r1() + } + .property class '<>f__AnonymousType986704712`2' + r2() + { + .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 class '<>f__AnonymousType986704712`2' assembly::get_r2() + } +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .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 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: call void assembly::staticInitialization@() + IL_0005: ret + } + +} + +.class public auto ansi serializable sealed beforefieldinit '<>f__AnonymousType986704712`2'<'j__TPar','j__TPar'> + extends [runtime]System.Object + implements [runtime]System.Collections.IStructuralComparable, + [runtime]System.IComparable, + class [runtime]System.IComparable`1f__AnonymousType986704712`2'j__TPar',!'j__TPar'>>, + [runtime]System.Collections.IStructuralEquatable, + class [runtime]System.IEquatable`1f__AnonymousType986704712`2'j__TPar',!'j__TPar'>> +{ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field private !'j__TPar' A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field private !'j__TPar' B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor(!'j__TPar' A, !'j__TPar' B) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 1D 3C 3E 66 5F 5F 41 6E 6F 6E + 79 6D 6F 75 73 54 79 70 65 39 38 36 37 30 34 37 + 31 32 60 32 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld !0 class '<>f__AnonymousType986704712`2'j__TPar',!'j__TPar'>::A@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld !1 class '<>f__AnonymousType986704712`2'j__TPar',!'j__TPar'>::B@ + IL_0014: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_A() 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: ldfld !0 class '<>f__AnonymousType986704712`2'j__TPar',!'j__TPar'>::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_B() 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: ldfld !1 class '<>f__AnonymousType986704712`2'j__TPar',!'j__TPar'>::B@ + IL_0006: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5f__AnonymousType986704712`2'j__TPar',!'j__TPar'>,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class '<>f__AnonymousType986704712`2'j__TPar',!'j__TPar'>>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToStringf__AnonymousType986704712`2'j__TPar',!'j__TPar'>,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2f__AnonymousType986704712`2'j__TPar',!'j__TPar'>,string>::Invoke(!0) + IL_0015: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(class '<>f__AnonymousType986704712`2'j__TPar',!'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0044 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0042 + + IL_0006: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_000b: ldarg.0 + IL_000c: ldfld !0 class '<>f__AnonymousType986704712`2'j__TPar',!'j__TPar'>::A@ + IL_0011: ldarg.1 + IL_0012: ldfld !0 class '<>f__AnonymousType986704712`2'j__TPar',!'j__TPar'>::A@ + IL_0017: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_001c: stloc.0 + IL_001d: ldloc.0 + IL_001e: ldc.i4.0 + IL_001f: bge.s IL_0023 + + IL_0021: ldloc.0 + IL_0022: ret + + IL_0023: ldloc.0 + IL_0024: ldc.i4.0 + IL_0025: ble.s IL_0029 + + IL_0027: ldloc.0 + IL_0028: ret + + IL_0029: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_002e: ldarg.0 + IL_002f: ldfld !1 class '<>f__AnonymousType986704712`2'j__TPar',!'j__TPar'>::B@ + IL_0034: ldarg.1 + IL_0035: ldfld !1 class '<>f__AnonymousType986704712`2'j__TPar',!'j__TPar'>::B@ + IL_003a: tail. + IL_003c: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0041: ret + + IL_0042: ldc.i4.1 + IL_0043: ret + + IL_0044: ldarg.1 + IL_0045: brfalse.s IL_0049 + + IL_0047: ldc.i4.m1 + IL_0048: ret + + IL_0049: ldc.i4.0 + IL_004a: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: unbox.any class '<>f__AnonymousType986704712`2'j__TPar',!'j__TPar'> + IL_0007: tail. + IL_0009: callvirt instance int32 class '<>f__AnonymousType986704712`2'j__TPar',!'j__TPar'>::CompareTo(class '<>f__AnonymousType986704712`2') + IL_000e: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj, class [runtime]System.Collections.IComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType986704712`2'j__TPar',!'j__TPar'> V_0, + class '<>f__AnonymousType986704712`2'j__TPar',!'j__TPar'> V_1, + int32 V_2) + IL_0000: ldarg.1 + IL_0001: unbox.any class '<>f__AnonymousType986704712`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: stloc.1 + IL_0009: ldarg.0 + IL_000a: brfalse.s IL_004a + + IL_000c: ldarg.1 + IL_000d: unbox.any class '<>f__AnonymousType986704712`2'j__TPar',!'j__TPar'> + IL_0012: brfalse.s IL_0048 + + IL_0014: ldarg.2 + IL_0015: ldarg.0 + IL_0016: ldfld !0 class '<>f__AnonymousType986704712`2'j__TPar',!'j__TPar'>::A@ + IL_001b: ldloc.1 + IL_001c: ldfld !0 class '<>f__AnonymousType986704712`2'j__TPar',!'j__TPar'>::A@ + IL_0021: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0026: stloc.2 + IL_0027: ldloc.2 + IL_0028: ldc.i4.0 + IL_0029: bge.s IL_002d + + IL_002b: ldloc.2 + IL_002c: ret + + IL_002d: ldloc.2 + IL_002e: ldc.i4.0 + IL_002f: ble.s IL_0033 + + IL_0031: ldloc.2 + IL_0032: ret + + IL_0033: ldarg.2 + IL_0034: ldarg.0 + IL_0035: ldfld !1 class '<>f__AnonymousType986704712`2'j__TPar',!'j__TPar'>::B@ + IL_003a: ldloc.1 + IL_003b: ldfld !1 class '<>f__AnonymousType986704712`2'j__TPar',!'j__TPar'>::B@ + IL_0040: tail. + IL_0042: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0047: ret + + IL_0048: ldc.i4.1 + IL_0049: ret + + IL_004a: ldarg.1 + IL_004b: unbox.any class '<>f__AnonymousType986704712`2'j__TPar',!'j__TPar'> + IL_0050: brfalse.s IL_0054 + + IL_0052: ldc.i4.m1 + IL_0053: ret + + IL_0054: ldc.i4.0 + IL_0055: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode(class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 7 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_003d + + IL_0003: ldc.i4.0 + IL_0004: stloc.0 + IL_0005: ldc.i4 0x9e3779b9 + IL_000a: ldarg.1 + IL_000b: ldarg.0 + IL_000c: ldfld !1 class '<>f__AnonymousType986704712`2'j__TPar',!'j__TPar'>::B@ + IL_0011: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0016: ldloc.0 + IL_0017: ldc.i4.6 + IL_0018: shl + IL_0019: ldloc.0 + IL_001a: ldc.i4.2 + IL_001b: shr + IL_001c: add + IL_001d: add + IL_001e: add + IL_001f: stloc.0 + IL_0020: ldc.i4 0x9e3779b9 + IL_0025: ldarg.1 + IL_0026: ldarg.0 + IL_0027: ldfld !0 class '<>f__AnonymousType986704712`2'j__TPar',!'j__TPar'>::A@ + IL_002c: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0031: ldloc.0 + IL_0032: ldc.i4.6 + IL_0033: shl + IL_0034: ldloc.0 + IL_0035: ldc.i4.2 + IL_0036: shr + IL_0037: add + IL_0038: add + IL_0039: add + IL_003a: stloc.0 + IL_003b: ldloc.0 + IL_003c: ret + + IL_003d: ldc.i4.0 + IL_003e: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() + IL_0006: tail. + IL_0008: callvirt instance int32 class '<>f__AnonymousType986704712`2'j__TPar',!'j__TPar'>::GetHashCode(class [runtime]System.Collections.IEqualityComparer) + IL_000d: ret + } + + .method public hidebysig instance bool Equals(class '<>f__AnonymousType986704712`2'j__TPar',!'j__TPar'> obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType986704712`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0035 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0033 + + IL_0006: ldarg.1 + IL_0007: stloc.0 + IL_0008: ldarg.2 + IL_0009: ldarg.0 + IL_000a: ldfld !0 class '<>f__AnonymousType986704712`2'j__TPar',!'j__TPar'>::A@ + IL_000f: ldloc.0 + IL_0010: ldfld !0 class '<>f__AnonymousType986704712`2'j__TPar',!'j__TPar'>::A@ + IL_0015: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_001a: brfalse.s IL_0031 + + IL_001c: ldarg.2 + IL_001d: ldarg.0 + IL_001e: ldfld !1 class '<>f__AnonymousType986704712`2'j__TPar',!'j__TPar'>::B@ + IL_0023: ldloc.0 + IL_0024: ldfld !1 class '<>f__AnonymousType986704712`2'j__TPar',!'j__TPar'>::B@ + IL_0029: tail. + IL_002b: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_0030: ret + + IL_0031: ldc.i4.0 + IL_0032: ret + + IL_0033: ldc.i4.0 + IL_0034: ret + + IL_0035: ldarg.1 + IL_0036: ldnull + IL_0037: cgt.un + IL_0039: ldc.i4.0 + IL_003a: ceq + IL_003c: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType986704712`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType986704712`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0015 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: ldarg.2 + IL_000d: tail. + IL_000f: callvirt instance bool class '<>f__AnonymousType986704712`2'j__TPar',!'j__TPar'>::Equals(class '<>f__AnonymousType986704712`2', + class [runtime]System.Collections.IEqualityComparer) + IL_0014: ret + + IL_0015: ldc.i4.0 + IL_0016: ret + } + + .method public hidebysig virtual final instance bool Equals(class '<>f__AnonymousType986704712`2'j__TPar',!'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0031 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_002f + + IL_0006: ldarg.0 + IL_0007: ldfld !0 class '<>f__AnonymousType986704712`2'j__TPar',!'j__TPar'>::A@ + IL_000c: ldarg.1 + IL_000d: ldfld !0 class '<>f__AnonymousType986704712`2'j__TPar',!'j__TPar'>::A@ + IL_0012: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_0017: brfalse.s IL_002d + + IL_0019: ldarg.0 + IL_001a: ldfld !1 class '<>f__AnonymousType986704712`2'j__TPar',!'j__TPar'>::B@ + IL_001f: ldarg.1 + IL_0020: ldfld !1 class '<>f__AnonymousType986704712`2'j__TPar',!'j__TPar'>::B@ + IL_0025: tail. + IL_0027: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_002c: ret + + IL_002d: ldc.i4.0 + IL_002e: ret + + IL_002f: ldc.i4.0 + IL_0030: ret + + IL_0031: ldarg.1 + IL_0032: ldnull + IL_0033: cgt.un + IL_0035: ldc.i4.0 + IL_0036: ceq + IL_0038: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (class '<>f__AnonymousType986704712`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType986704712`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0014 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: tail. + IL_000e: callvirt instance bool class '<>f__AnonymousType986704712`2'j__TPar',!'j__TPar'>::Equals(class '<>f__AnonymousType986704712`2') + IL_0013: ret + + IL_0014: ldc.i4.0 + IL_0015: ret + } + + .property instance !'j__TPar' A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType986704712`2'::get_A() + } + .property instance !'j__TPar' B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType986704712`2'::get_B() + } +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_ExtraFieldsAreIgnored.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_ExtraFieldsAreIgnored.fs new file mode 100644 index 00000000000..55f450f4318 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_ExtraFieldsAreIgnored.fs @@ -0,0 +1,3 @@ +let src = {| A = 1; B = "B"; C = 3m |} + +let typedTarget : {| B : string |} = {| ...src |} diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_ExtraFieldsAreIgnored.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_ExtraFieldsAreIgnored.fs.il.bsl new file mode 100644 index 00000000000..ef776f88dab --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_ExtraFieldsAreIgnored.fs.il.bsl @@ -0,0 +1,984 @@ + + + + + +.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, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .field static assembly class '<>f__AnonymousType3580924027`3' src@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 class '<>f__AnonymousType2283186596`1' typedTarget@3 + .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 '<>f__AnonymousType3580924027`3' get_src() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class '<>f__AnonymousType3580924027`3' assembly::src@1 + IL_0005: ret + } + + .method public specialname static class '<>f__AnonymousType2283186596`1' get_typedTarget() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class '<>f__AnonymousType2283186596`1' assembly::typedTarget@3 + IL_0005: ret + } + + .method private specialname rtspecialname static void .cctor() cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.0 + IL_0001: stsfld int32 ''.$assembly::init@ + IL_0006: ldsfld int32 ''.$assembly::init@ + IL_000b: pop + IL_000c: ret + } + + .method assembly static void staticInitialization@() cil managed + { + + .maxstack 9 + IL_0000: ldc.i4.1 + IL_0001: ldstr "B" + IL_0006: ldc.i4.3 + IL_0007: ldc.i4.0 + IL_0008: ldc.i4.0 + IL_0009: ldc.i4.0 + IL_000a: ldc.i4.0 + IL_000b: newobj instance void [netstandard]System.Decimal::.ctor(int32, + int32, + int32, + bool, + uint8) + IL_0010: newobj instance void class '<>f__AnonymousType3580924027`3'::.ctor(!0, + !1, + !2) + IL_0015: stsfld class '<>f__AnonymousType3580924027`3' assembly::src@1 + IL_001a: call class '<>f__AnonymousType3580924027`3' assembly::get_src() + IL_001f: call instance !1 class '<>f__AnonymousType3580924027`3'::get_B() + IL_0024: newobj instance void class '<>f__AnonymousType2283186596`1'::.ctor(!0) + IL_0029: stsfld class '<>f__AnonymousType2283186596`1' assembly::typedTarget@3 + IL_002e: ret + } + + .property class '<>f__AnonymousType3580924027`3' + src() + { + .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 class '<>f__AnonymousType3580924027`3' assembly::get_src() + } + .property class '<>f__AnonymousType2283186596`1' + typedTarget() + { + .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 class '<>f__AnonymousType2283186596`1' assembly::get_typedTarget() + } +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .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 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: call void assembly::staticInitialization@() + IL_0005: ret + } + +} + +.class public auto ansi serializable sealed beforefieldinit '<>f__AnonymousType2283186596`1'<'j__TPar'> + extends [runtime]System.Object + implements [runtime]System.Collections.IStructuralComparable, + [runtime]System.IComparable, + class [runtime]System.IComparable`1f__AnonymousType2283186596`1'j__TPar'>>, + [runtime]System.Collections.IStructuralEquatable, + class [runtime]System.IEquatable`1f__AnonymousType2283186596`1'j__TPar'>> +{ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field private !'j__TPar' B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor(!'j__TPar' B) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 1E 3C 3E 66 5F 5F 41 6E 6F 6E + 79 6D 6F 75 73 54 79 70 65 32 32 38 33 31 38 36 + 35 39 36 60 31 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld !0 class '<>f__AnonymousType2283186596`1'j__TPar'>::B@ + IL_000d: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_B() 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: ldfld !0 class '<>f__AnonymousType2283186596`1'j__TPar'>::B@ + IL_0006: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5f__AnonymousType2283186596`1'j__TPar'>,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class '<>f__AnonymousType2283186596`1'j__TPar'>>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToStringf__AnonymousType2283186596`1'j__TPar'>,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2f__AnonymousType2283186596`1'j__TPar'>,string>::Invoke(!0) + IL_0015: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(class '<>f__AnonymousType2283186596`1'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0021 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_001f + + IL_0006: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_000b: ldarg.0 + IL_000c: ldfld !0 class '<>f__AnonymousType2283186596`1'j__TPar'>::B@ + IL_0011: ldarg.1 + IL_0012: ldfld !0 class '<>f__AnonymousType2283186596`1'j__TPar'>::B@ + IL_0017: tail. + IL_0019: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_001e: ret + + IL_001f: ldc.i4.1 + IL_0020: ret + + IL_0021: ldarg.1 + IL_0022: brfalse.s IL_0026 + + IL_0024: ldc.i4.m1 + IL_0025: ret + + IL_0026: ldc.i4.0 + IL_0027: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: unbox.any class '<>f__AnonymousType2283186596`1'j__TPar'> + IL_0007: tail. + IL_0009: callvirt instance int32 class '<>f__AnonymousType2283186596`1'j__TPar'>::CompareTo(class '<>f__AnonymousType2283186596`1') + IL_000e: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj, class [runtime]System.Collections.IComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType2283186596`1'j__TPar'> V_0, + class '<>f__AnonymousType2283186596`1'j__TPar'> V_1) + IL_0000: ldarg.1 + IL_0001: unbox.any class '<>f__AnonymousType2283186596`1'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: stloc.1 + IL_0009: ldarg.0 + IL_000a: brfalse.s IL_002b + + IL_000c: ldarg.1 + IL_000d: unbox.any class '<>f__AnonymousType2283186596`1'j__TPar'> + IL_0012: brfalse.s IL_0029 + + IL_0014: ldarg.2 + IL_0015: ldarg.0 + IL_0016: ldfld !0 class '<>f__AnonymousType2283186596`1'j__TPar'>::B@ + IL_001b: ldloc.1 + IL_001c: ldfld !0 class '<>f__AnonymousType2283186596`1'j__TPar'>::B@ + IL_0021: tail. + IL_0023: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0028: ret + + IL_0029: ldc.i4.1 + IL_002a: ret + + IL_002b: ldarg.1 + IL_002c: unbox.any class '<>f__AnonymousType2283186596`1'j__TPar'> + IL_0031: brfalse.s IL_0035 + + IL_0033: ldc.i4.m1 + IL_0034: ret + + IL_0035: ldc.i4.0 + IL_0036: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode(class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 7 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0022 + + IL_0003: ldc.i4.0 + IL_0004: stloc.0 + IL_0005: ldc.i4 0x9e3779b9 + IL_000a: ldarg.1 + IL_000b: ldarg.0 + IL_000c: ldfld !0 class '<>f__AnonymousType2283186596`1'j__TPar'>::B@ + IL_0011: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0016: ldloc.0 + IL_0017: ldc.i4.6 + IL_0018: shl + IL_0019: ldloc.0 + IL_001a: ldc.i4.2 + IL_001b: shr + IL_001c: add + IL_001d: add + IL_001e: add + IL_001f: stloc.0 + IL_0020: ldloc.0 + IL_0021: ret + + IL_0022: ldc.i4.0 + IL_0023: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() + IL_0006: tail. + IL_0008: callvirt instance int32 class '<>f__AnonymousType2283186596`1'j__TPar'>::GetHashCode(class [runtime]System.Collections.IEqualityComparer) + IL_000d: ret + } + + .method public hidebysig instance bool Equals(class '<>f__AnonymousType2283186596`1'j__TPar'> obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType2283186596`1'j__TPar'> V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_001f + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_001d + + IL_0006: ldarg.1 + IL_0007: stloc.0 + IL_0008: ldarg.2 + IL_0009: ldarg.0 + IL_000a: ldfld !0 class '<>f__AnonymousType2283186596`1'j__TPar'>::B@ + IL_000f: ldloc.0 + IL_0010: ldfld !0 class '<>f__AnonymousType2283186596`1'j__TPar'>::B@ + IL_0015: tail. + IL_0017: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_001c: ret + + IL_001d: ldc.i4.0 + IL_001e: ret + + IL_001f: ldarg.1 + IL_0020: ldnull + IL_0021: cgt.un + IL_0023: ldc.i4.0 + IL_0024: ceq + IL_0026: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType2283186596`1'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType2283186596`1'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0015 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: ldarg.2 + IL_000d: tail. + IL_000f: callvirt instance bool class '<>f__AnonymousType2283186596`1'j__TPar'>::Equals(class '<>f__AnonymousType2283186596`1', + class [runtime]System.Collections.IEqualityComparer) + IL_0014: ret + + IL_0015: ldc.i4.0 + IL_0016: ret + } + + .method public hidebysig virtual final instance bool Equals(class '<>f__AnonymousType2283186596`1'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_001c + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_001a + + IL_0006: ldarg.0 + IL_0007: ldfld !0 class '<>f__AnonymousType2283186596`1'j__TPar'>::B@ + IL_000c: ldarg.1 + IL_000d: ldfld !0 class '<>f__AnonymousType2283186596`1'j__TPar'>::B@ + IL_0012: tail. + IL_0014: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_0019: ret + + IL_001a: ldc.i4.0 + IL_001b: ret + + IL_001c: ldarg.1 + IL_001d: ldnull + IL_001e: cgt.un + IL_0020: ldc.i4.0 + IL_0021: ceq + IL_0023: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (class '<>f__AnonymousType2283186596`1'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType2283186596`1'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0014 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: tail. + IL_000e: callvirt instance bool class '<>f__AnonymousType2283186596`1'j__TPar'>::Equals(class '<>f__AnonymousType2283186596`1') + IL_0013: ret + + IL_0014: ldc.i4.0 + IL_0015: ret + } + + .property instance !'j__TPar' B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType2283186596`1'::get_B() + } +} + +.class public auto ansi serializable sealed beforefieldinit '<>f__AnonymousType3580924027`3'<'j__TPar','j__TPar','j__TPar'> + extends [runtime]System.Object + implements [runtime]System.Collections.IStructuralComparable, + [runtime]System.IComparable, + class [runtime]System.IComparable`1f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'>>, + [runtime]System.Collections.IStructuralEquatable, + class [runtime]System.IEquatable`1f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'>> +{ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field private !'j__TPar' A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field private !'j__TPar' B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field private !'j__TPar' C@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public specialname rtspecialname + instance void .ctor(!'j__TPar' A, + !'j__TPar' B, + !'j__TPar' C) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 1E 3C 3E 66 5F 5F 41 6E 6F 6E + 79 6D 6F 75 73 54 79 70 65 33 35 38 30 39 32 34 + 30 32 37 60 33 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld !0 class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'>::A@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld !1 class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'>::B@ + IL_0014: ldarg.0 + IL_0015: ldarg.3 + IL_0016: stfld !2 class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'>::C@ + IL_001b: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_A() 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: ldfld !0 class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'>::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_B() 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: ldfld !1 class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'>::B@ + IL_0006: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_C() 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: ldfld !2 class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'>::C@ + IL_0006: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'>,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'>>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToStringf__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'>,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'>,string>::Invoke(!0) + IL_0015: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (int32 V_0, + int32 V_1) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0067 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0065 + + IL_0006: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_000b: ldarg.0 + IL_000c: ldfld !0 class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'>::A@ + IL_0011: ldarg.1 + IL_0012: ldfld !0 class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'>::A@ + IL_0017: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_001c: stloc.0 + IL_001d: ldloc.0 + IL_001e: ldc.i4.0 + IL_001f: bge.s IL_0023 + + IL_0021: ldloc.0 + IL_0022: ret + + IL_0023: ldloc.0 + IL_0024: ldc.i4.0 + IL_0025: ble.s IL_0029 + + IL_0027: ldloc.0 + IL_0028: ret + + IL_0029: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_002e: ldarg.0 + IL_002f: ldfld !1 class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'>::B@ + IL_0034: ldarg.1 + IL_0035: ldfld !1 class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'>::B@ + IL_003a: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_003f: stloc.1 + IL_0040: ldloc.1 + IL_0041: ldc.i4.0 + IL_0042: bge.s IL_0046 + + IL_0044: ldloc.1 + IL_0045: ret + + IL_0046: ldloc.1 + IL_0047: ldc.i4.0 + IL_0048: ble.s IL_004c + + IL_004a: ldloc.1 + IL_004b: ret + + IL_004c: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_0051: ldarg.0 + IL_0052: ldfld !2 class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'>::C@ + IL_0057: ldarg.1 + IL_0058: ldfld !2 class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'>::C@ + IL_005d: tail. + IL_005f: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0064: ret + + IL_0065: ldc.i4.1 + IL_0066: ret + + IL_0067: ldarg.1 + IL_0068: brfalse.s IL_006c + + IL_006a: ldc.i4.m1 + IL_006b: ret + + IL_006c: ldc.i4.0 + IL_006d: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: unbox.any class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'> + IL_0007: tail. + IL_0009: callvirt instance int32 class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'>::CompareTo(class '<>f__AnonymousType3580924027`3') + IL_000e: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj, class [runtime]System.Collections.IComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'> V_0, + class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'> V_1, + int32 V_2, + int32 V_3) + IL_0000: ldarg.1 + IL_0001: unbox.any class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: stloc.1 + IL_0009: ldarg.0 + IL_000a: brfalse.s IL_0069 + + IL_000c: ldarg.1 + IL_000d: unbox.any class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'> + IL_0012: brfalse.s IL_0067 + + IL_0014: ldarg.2 + IL_0015: ldarg.0 + IL_0016: ldfld !0 class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'>::A@ + IL_001b: ldloc.1 + IL_001c: ldfld !0 class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'>::A@ + IL_0021: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0026: stloc.2 + IL_0027: ldloc.2 + IL_0028: ldc.i4.0 + IL_0029: bge.s IL_002d + + IL_002b: ldloc.2 + IL_002c: ret + + IL_002d: ldloc.2 + IL_002e: ldc.i4.0 + IL_002f: ble.s IL_0033 + + IL_0031: ldloc.2 + IL_0032: ret + + IL_0033: ldarg.2 + IL_0034: ldarg.0 + IL_0035: ldfld !1 class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'>::B@ + IL_003a: ldloc.1 + IL_003b: ldfld !1 class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'>::B@ + IL_0040: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0045: stloc.3 + IL_0046: ldloc.3 + IL_0047: ldc.i4.0 + IL_0048: bge.s IL_004c + + IL_004a: ldloc.3 + IL_004b: ret + + IL_004c: ldloc.3 + IL_004d: ldc.i4.0 + IL_004e: ble.s IL_0052 + + IL_0050: ldloc.3 + IL_0051: ret + + IL_0052: ldarg.2 + IL_0053: ldarg.0 + IL_0054: ldfld !2 class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'>::C@ + IL_0059: ldloc.1 + IL_005a: ldfld !2 class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'>::C@ + IL_005f: tail. + IL_0061: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0066: ret + + IL_0067: ldc.i4.1 + IL_0068: ret + + IL_0069: ldarg.1 + IL_006a: unbox.any class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'> + IL_006f: brfalse.s IL_0073 + + IL_0071: ldc.i4.m1 + IL_0072: ret + + IL_0073: ldc.i4.0 + IL_0074: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode(class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 7 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0058 + + IL_0003: ldc.i4.0 + IL_0004: stloc.0 + IL_0005: ldc.i4 0x9e3779b9 + IL_000a: ldarg.1 + IL_000b: ldarg.0 + IL_000c: ldfld !2 class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'>::C@ + IL_0011: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0016: ldloc.0 + IL_0017: ldc.i4.6 + IL_0018: shl + IL_0019: ldloc.0 + IL_001a: ldc.i4.2 + IL_001b: shr + IL_001c: add + IL_001d: add + IL_001e: add + IL_001f: stloc.0 + IL_0020: ldc.i4 0x9e3779b9 + IL_0025: ldarg.1 + IL_0026: ldarg.0 + IL_0027: ldfld !1 class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'>::B@ + IL_002c: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0031: ldloc.0 + IL_0032: ldc.i4.6 + IL_0033: shl + IL_0034: ldloc.0 + IL_0035: ldc.i4.2 + IL_0036: shr + IL_0037: add + IL_0038: add + IL_0039: add + IL_003a: stloc.0 + IL_003b: ldc.i4 0x9e3779b9 + IL_0040: ldarg.1 + IL_0041: ldarg.0 + IL_0042: ldfld !0 class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'>::A@ + IL_0047: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_004c: ldloc.0 + IL_004d: ldc.i4.6 + IL_004e: shl + IL_004f: ldloc.0 + IL_0050: ldc.i4.2 + IL_0051: shr + IL_0052: add + IL_0053: add + IL_0054: add + IL_0055: stloc.0 + IL_0056: ldloc.0 + IL_0057: ret + + IL_0058: ldc.i4.0 + IL_0059: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() + IL_0006: tail. + IL_0008: callvirt instance int32 class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'>::GetHashCode(class [runtime]System.Collections.IEqualityComparer) + IL_000d: ret + } + + .method public hidebysig instance bool Equals(class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'> obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_004b + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0049 + + IL_0006: ldarg.1 + IL_0007: stloc.0 + IL_0008: ldarg.2 + IL_0009: ldarg.0 + IL_000a: ldfld !0 class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'>::A@ + IL_000f: ldloc.0 + IL_0010: ldfld !0 class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'>::A@ + IL_0015: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_001a: brfalse.s IL_0047 + + IL_001c: ldarg.2 + IL_001d: ldarg.0 + IL_001e: ldfld !1 class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'>::B@ + IL_0023: ldloc.0 + IL_0024: ldfld !1 class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'>::B@ + IL_0029: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_002e: brfalse.s IL_0045 + + IL_0030: ldarg.2 + IL_0031: ldarg.0 + IL_0032: ldfld !2 class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'>::C@ + IL_0037: ldloc.0 + IL_0038: ldfld !2 class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'>::C@ + IL_003d: tail. + IL_003f: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_0044: ret + + IL_0045: ldc.i4.0 + IL_0046: ret + + IL_0047: ldc.i4.0 + IL_0048: ret + + IL_0049: ldc.i4.0 + IL_004a: ret + + IL_004b: ldarg.1 + IL_004c: ldnull + IL_004d: cgt.un + IL_004f: ldc.i4.0 + IL_0050: ceq + IL_0052: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0015 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: ldarg.2 + IL_000d: tail. + IL_000f: callvirt instance bool class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'>::Equals(class '<>f__AnonymousType3580924027`3', + class [runtime]System.Collections.IEqualityComparer) + IL_0014: ret + + IL_0015: ldc.i4.0 + IL_0016: ret + } + + .method public hidebysig virtual final instance bool Equals(class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0046 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0044 + + IL_0006: ldarg.0 + IL_0007: ldfld !0 class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'>::A@ + IL_000c: ldarg.1 + IL_000d: ldfld !0 class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'>::A@ + IL_0012: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_0017: brfalse.s IL_0042 + + IL_0019: ldarg.0 + IL_001a: ldfld !1 class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'>::B@ + IL_001f: ldarg.1 + IL_0020: ldfld !1 class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'>::B@ + IL_0025: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_002a: brfalse.s IL_0040 + + IL_002c: ldarg.0 + IL_002d: ldfld !2 class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'>::C@ + IL_0032: ldarg.1 + IL_0033: ldfld !2 class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'>::C@ + IL_0038: tail. + IL_003a: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_003f: ret + + IL_0040: ldc.i4.0 + IL_0041: ret + + IL_0042: ldc.i4.0 + IL_0043: ret + + IL_0044: ldc.i4.0 + IL_0045: ret + + IL_0046: ldarg.1 + IL_0047: ldnull + IL_0048: cgt.un + IL_004a: ldc.i4.0 + IL_004b: ceq + IL_004d: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0014 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: tail. + IL_000e: callvirt instance bool class '<>f__AnonymousType3580924027`3'j__TPar',!'j__TPar',!'j__TPar'>::Equals(class '<>f__AnonymousType3580924027`3') + IL_0013: ret + + IL_0014: ldc.i4.0 + IL_0015: ret + } + + .property instance !'j__TPar' A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType3580924027`3'::get_A() + } + .property instance !'j__TPar' B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType3580924027`3'::get_B() + } + .property instance !'j__TPar' C() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 02 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType3580924027`3'::get_C() + } +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_NestedUpdates.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_NestedUpdates.fs new file mode 100644 index 00000000000..4efb711a5ac --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_NestedUpdates.fs @@ -0,0 +1,4 @@ +let orig1 () = {| Nested = {| A = "value1"; B = "value1" |}; Other = {| A = "value2"; B = "value2" |} |} +let orig2 () = {| Nested = {| A = "value3"; B = "value3" |} |} + +let actual = {| ...orig1 (); Nested.B = "value4"; ...orig2 (); Other.B = "value5" |} \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_NestedUpdates.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_NestedUpdates.fs.il.bsl new file mode 100644 index 00000000000..f904d2d1049 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_NestedUpdates.fs.il.bsl @@ -0,0 +1,1360 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .field static assembly class '<>f__AnonymousType3986374330`2'f__AnonymousType3104616430`2',class '<>f__AnonymousType3104616430`2'> actual@4 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly class '<>f__AnonymousType3986374330`2'f__AnonymousType3104616430`2',class '<>f__AnonymousType3104616430`2'> bind@4 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly class '<>f__AnonymousType1074009332`1'f__AnonymousType3104616430`2'> 'bind@4-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 class '<>f__AnonymousType3104616430`2' inputRecord@4 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public static class '<>f__AnonymousType3986374330`2'f__AnonymousType3104616430`2',class '<>f__AnonymousType3104616430`2'> orig1() cil managed + { + + .maxstack 8 + IL_0000: ldstr "value1" + IL_0005: ldstr "value1" + IL_000a: newobj instance void class '<>f__AnonymousType3104616430`2'::.ctor(!0, + !1) + IL_000f: ldstr "value2" + IL_0014: ldstr "value2" + IL_0019: newobj instance void class '<>f__AnonymousType3104616430`2'::.ctor(!0, + !1) + IL_001e: newobj instance void class '<>f__AnonymousType3986374330`2'f__AnonymousType3104616430`2',class '<>f__AnonymousType3104616430`2'>::.ctor(!0, + !1) + IL_0023: ret + } + + .method public static class '<>f__AnonymousType1074009332`1'f__AnonymousType3104616430`2'> orig2() cil managed + { + + .maxstack 8 + IL_0000: ldstr "value3" + IL_0005: ldstr "value3" + IL_000a: newobj instance void class '<>f__AnonymousType3104616430`2'::.ctor(!0, + !1) + IL_000f: newobj instance void class '<>f__AnonymousType1074009332`1'f__AnonymousType3104616430`2'>::.ctor(!0) + IL_0014: ret + } + + .method public specialname static class '<>f__AnonymousType3986374330`2'f__AnonymousType3104616430`2',class '<>f__AnonymousType3104616430`2'> get_actual() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class '<>f__AnonymousType3986374330`2'f__AnonymousType3104616430`2',class '<>f__AnonymousType3104616430`2'> assembly::actual@4 + IL_0005: ret + } + + .method assembly specialname static class '<>f__AnonymousType3986374330`2'f__AnonymousType3104616430`2',class '<>f__AnonymousType3104616430`2'> get_bind@4() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class '<>f__AnonymousType3986374330`2'f__AnonymousType3104616430`2',class '<>f__AnonymousType3104616430`2'> assembly::bind@4 + IL_0005: ret + } + + .method assembly specialname static class '<>f__AnonymousType1074009332`1'f__AnonymousType3104616430`2'> 'get_bind@4-1'() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class '<>f__AnonymousType1074009332`1'f__AnonymousType3104616430`2'> assembly::'bind@4-1' + IL_0005: ret + } + + .method assembly specialname static class '<>f__AnonymousType3104616430`2' get_inputRecord@4() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class '<>f__AnonymousType3104616430`2' assembly::inputRecord@4 + IL_0005: ret + } + + .method private specialname rtspecialname static void .cctor() cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.0 + IL_0001: stsfld int32 ''.$assembly::init@ + IL_0006: ldsfld int32 ''.$assembly::init@ + IL_000b: pop + IL_000c: ret + } + + .method assembly static void staticInitialization@() cil managed + { + + .maxstack 5 + IL_0000: nop + IL_0001: ldstr "value1" + IL_0006: ldstr "value1" + IL_000b: newobj instance void class '<>f__AnonymousType3104616430`2'::.ctor(!0, + !1) + IL_0010: ldstr "value2" + IL_0015: ldstr "value2" + IL_001a: newobj instance void class '<>f__AnonymousType3104616430`2'::.ctor(!0, + !1) + IL_001f: newobj instance void class '<>f__AnonymousType3986374330`2'f__AnonymousType3104616430`2',class '<>f__AnonymousType3104616430`2'>::.ctor(!0, + !1) + IL_0024: stsfld class '<>f__AnonymousType3986374330`2'f__AnonymousType3104616430`2',class '<>f__AnonymousType3104616430`2'> assembly::bind@4 + IL_0029: ldstr "value3" + IL_002e: ldstr "value3" + IL_0033: newobj instance void class '<>f__AnonymousType3104616430`2'::.ctor(!0, + !1) + IL_0038: newobj instance void class '<>f__AnonymousType1074009332`1'f__AnonymousType3104616430`2'>::.ctor(!0) + IL_003d: stsfld class '<>f__AnonymousType1074009332`1'f__AnonymousType3104616430`2'> assembly::'bind@4-1' + IL_0042: call class '<>f__AnonymousType1074009332`1'f__AnonymousType3104616430`2'> assembly::'get_bind@4-1'() + IL_0047: call instance !0 class '<>f__AnonymousType1074009332`1'f__AnonymousType3104616430`2'>::get_Nested() + IL_004c: call class '<>f__AnonymousType3986374330`2'f__AnonymousType3104616430`2',class '<>f__AnonymousType3104616430`2'> assembly::get_bind@4() + IL_0051: call instance !1 class '<>f__AnonymousType3986374330`2'f__AnonymousType3104616430`2',class '<>f__AnonymousType3104616430`2'>::get_Other() + IL_0056: stsfld class '<>f__AnonymousType3104616430`2' assembly::inputRecord@4 + IL_005b: call class '<>f__AnonymousType3104616430`2' assembly::get_inputRecord@4() + IL_0060: call instance !0 class '<>f__AnonymousType3104616430`2'::get_A() + IL_0065: ldstr "value5" + IL_006a: newobj instance void class '<>f__AnonymousType3104616430`2'::.ctor(!0, + !1) + IL_006f: newobj instance void class '<>f__AnonymousType3986374330`2'f__AnonymousType3104616430`2',class '<>f__AnonymousType3104616430`2'>::.ctor(!0, + !1) + IL_0074: stsfld class '<>f__AnonymousType3986374330`2'f__AnonymousType3104616430`2',class '<>f__AnonymousType3104616430`2'> assembly::actual@4 + IL_0079: ret + } + + .property class '<>f__AnonymousType3986374330`2'f__AnonymousType3104616430`2',class '<>f__AnonymousType3104616430`2'> + actual() + { + .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 class '<>f__AnonymousType3986374330`2'f__AnonymousType3104616430`2',class '<>f__AnonymousType3104616430`2'> assembly::get_actual() + } + .property class '<>f__AnonymousType3986374330`2'f__AnonymousType3104616430`2',class '<>f__AnonymousType3104616430`2'> + bind@4() + { + .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 class '<>f__AnonymousType3986374330`2'f__AnonymousType3104616430`2',class '<>f__AnonymousType3104616430`2'> assembly::get_bind@4() + } + .property class '<>f__AnonymousType1074009332`1'f__AnonymousType3104616430`2'> + 'bind@4-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 class '<>f__AnonymousType1074009332`1'f__AnonymousType3104616430`2'> assembly::'get_bind@4-1'() + } + .property class '<>f__AnonymousType3104616430`2' + inputRecord@4() + { + .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 class '<>f__AnonymousType3104616430`2' assembly::get_inputRecord@4() + } +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .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 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: call void assembly::staticInitialization@() + IL_0005: ret + } + +} + +.class public auto ansi serializable sealed beforefieldinit '<>f__AnonymousType1074009332`1'<'j__TPar'> + extends [runtime]System.Object + implements [runtime]System.Collections.IStructuralComparable, + [runtime]System.IComparable, + class [runtime]System.IComparable`1f__AnonymousType1074009332`1'j__TPar'>>, + [runtime]System.Collections.IStructuralEquatable, + class [runtime]System.IEquatable`1f__AnonymousType1074009332`1'j__TPar'>> +{ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field private !'j__TPar' Nested@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor(!'j__TPar' Nested) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 1E 3C 3E 66 5F 5F 41 6E 6F 6E + 79 6D 6F 75 73 54 79 70 65 31 30 37 34 30 30 39 + 33 33 32 60 31 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld !0 class '<>f__AnonymousType1074009332`1'j__TPar'>::Nested@ + IL_000d: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_Nested() 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: ldfld !0 class '<>f__AnonymousType1074009332`1'j__TPar'>::Nested@ + IL_0006: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5f__AnonymousType1074009332`1'j__TPar'>,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class '<>f__AnonymousType1074009332`1'j__TPar'>>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToStringf__AnonymousType1074009332`1'j__TPar'>,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2f__AnonymousType1074009332`1'j__TPar'>,string>::Invoke(!0) + IL_0015: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(class '<>f__AnonymousType1074009332`1'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0021 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_001f + + IL_0006: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_000b: ldarg.0 + IL_000c: ldfld !0 class '<>f__AnonymousType1074009332`1'j__TPar'>::Nested@ + IL_0011: ldarg.1 + IL_0012: ldfld !0 class '<>f__AnonymousType1074009332`1'j__TPar'>::Nested@ + IL_0017: tail. + IL_0019: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_001e: ret + + IL_001f: ldc.i4.1 + IL_0020: ret + + IL_0021: ldarg.1 + IL_0022: brfalse.s IL_0026 + + IL_0024: ldc.i4.m1 + IL_0025: ret + + IL_0026: ldc.i4.0 + IL_0027: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: unbox.any class '<>f__AnonymousType1074009332`1'j__TPar'> + IL_0007: tail. + IL_0009: callvirt instance int32 class '<>f__AnonymousType1074009332`1'j__TPar'>::CompareTo(class '<>f__AnonymousType1074009332`1') + IL_000e: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj, class [runtime]System.Collections.IComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType1074009332`1'j__TPar'> V_0, + class '<>f__AnonymousType1074009332`1'j__TPar'> V_1) + IL_0000: ldarg.1 + IL_0001: unbox.any class '<>f__AnonymousType1074009332`1'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: stloc.1 + IL_0009: ldarg.0 + IL_000a: brfalse.s IL_002b + + IL_000c: ldarg.1 + IL_000d: unbox.any class '<>f__AnonymousType1074009332`1'j__TPar'> + IL_0012: brfalse.s IL_0029 + + IL_0014: ldarg.2 + IL_0015: ldarg.0 + IL_0016: ldfld !0 class '<>f__AnonymousType1074009332`1'j__TPar'>::Nested@ + IL_001b: ldloc.1 + IL_001c: ldfld !0 class '<>f__AnonymousType1074009332`1'j__TPar'>::Nested@ + IL_0021: tail. + IL_0023: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0028: ret + + IL_0029: ldc.i4.1 + IL_002a: ret + + IL_002b: ldarg.1 + IL_002c: unbox.any class '<>f__AnonymousType1074009332`1'j__TPar'> + IL_0031: brfalse.s IL_0035 + + IL_0033: ldc.i4.m1 + IL_0034: ret + + IL_0035: ldc.i4.0 + IL_0036: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode(class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 7 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0022 + + IL_0003: ldc.i4.0 + IL_0004: stloc.0 + IL_0005: ldc.i4 0x9e3779b9 + IL_000a: ldarg.1 + IL_000b: ldarg.0 + IL_000c: ldfld !0 class '<>f__AnonymousType1074009332`1'j__TPar'>::Nested@ + IL_0011: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0016: ldloc.0 + IL_0017: ldc.i4.6 + IL_0018: shl + IL_0019: ldloc.0 + IL_001a: ldc.i4.2 + IL_001b: shr + IL_001c: add + IL_001d: add + IL_001e: add + IL_001f: stloc.0 + IL_0020: ldloc.0 + IL_0021: ret + + IL_0022: ldc.i4.0 + IL_0023: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() + IL_0006: tail. + IL_0008: callvirt instance int32 class '<>f__AnonymousType1074009332`1'j__TPar'>::GetHashCode(class [runtime]System.Collections.IEqualityComparer) + IL_000d: ret + } + + .method public hidebysig instance bool Equals(class '<>f__AnonymousType1074009332`1'j__TPar'> obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType1074009332`1'j__TPar'> V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_001f + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_001d + + IL_0006: ldarg.1 + IL_0007: stloc.0 + IL_0008: ldarg.2 + IL_0009: ldarg.0 + IL_000a: ldfld !0 class '<>f__AnonymousType1074009332`1'j__TPar'>::Nested@ + IL_000f: ldloc.0 + IL_0010: ldfld !0 class '<>f__AnonymousType1074009332`1'j__TPar'>::Nested@ + IL_0015: tail. + IL_0017: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_001c: ret + + IL_001d: ldc.i4.0 + IL_001e: ret + + IL_001f: ldarg.1 + IL_0020: ldnull + IL_0021: cgt.un + IL_0023: ldc.i4.0 + IL_0024: ceq + IL_0026: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType1074009332`1'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType1074009332`1'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0015 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: ldarg.2 + IL_000d: tail. + IL_000f: callvirt instance bool class '<>f__AnonymousType1074009332`1'j__TPar'>::Equals(class '<>f__AnonymousType1074009332`1', + class [runtime]System.Collections.IEqualityComparer) + IL_0014: ret + + IL_0015: ldc.i4.0 + IL_0016: ret + } + + .method public hidebysig virtual final instance bool Equals(class '<>f__AnonymousType1074009332`1'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_001c + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_001a + + IL_0006: ldarg.0 + IL_0007: ldfld !0 class '<>f__AnonymousType1074009332`1'j__TPar'>::Nested@ + IL_000c: ldarg.1 + IL_000d: ldfld !0 class '<>f__AnonymousType1074009332`1'j__TPar'>::Nested@ + IL_0012: tail. + IL_0014: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_0019: ret + + IL_001a: ldc.i4.0 + IL_001b: ret + + IL_001c: ldarg.1 + IL_001d: ldnull + IL_001e: cgt.un + IL_0020: ldc.i4.0 + IL_0021: ceq + IL_0023: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (class '<>f__AnonymousType1074009332`1'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType1074009332`1'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0014 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: tail. + IL_000e: callvirt instance bool class '<>f__AnonymousType1074009332`1'j__TPar'>::Equals(class '<>f__AnonymousType1074009332`1') + IL_0013: ret + + IL_0014: ldc.i4.0 + IL_0015: ret + } + + .property instance !'j__TPar' Nested() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType1074009332`1'::get_Nested() + } +} + +.class public auto ansi serializable sealed beforefieldinit '<>f__AnonymousType3104616430`2'<'j__TPar','j__TPar'> + extends [runtime]System.Object + implements [runtime]System.Collections.IStructuralComparable, + [runtime]System.IComparable, + class [runtime]System.IComparable`1f__AnonymousType3104616430`2'j__TPar',!'j__TPar'>>, + [runtime]System.Collections.IStructuralEquatable, + class [runtime]System.IEquatable`1f__AnonymousType3104616430`2'j__TPar',!'j__TPar'>> +{ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field private !'j__TPar' A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field private !'j__TPar' B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor(!'j__TPar' A, !'j__TPar' B) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 1E 3C 3E 66 5F 5F 41 6E 6F 6E + 79 6D 6F 75 73 54 79 70 65 33 31 30 34 36 31 36 + 34 33 30 60 32 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld !0 class '<>f__AnonymousType3104616430`2'j__TPar',!'j__TPar'>::A@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld !1 class '<>f__AnonymousType3104616430`2'j__TPar',!'j__TPar'>::B@ + IL_0014: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_A() 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: ldfld !0 class '<>f__AnonymousType3104616430`2'j__TPar',!'j__TPar'>::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_B() 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: ldfld !1 class '<>f__AnonymousType3104616430`2'j__TPar',!'j__TPar'>::B@ + IL_0006: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5f__AnonymousType3104616430`2'j__TPar',!'j__TPar'>,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class '<>f__AnonymousType3104616430`2'j__TPar',!'j__TPar'>>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToStringf__AnonymousType3104616430`2'j__TPar',!'j__TPar'>,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2f__AnonymousType3104616430`2'j__TPar',!'j__TPar'>,string>::Invoke(!0) + IL_0015: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(class '<>f__AnonymousType3104616430`2'j__TPar',!'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0044 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0042 + + IL_0006: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_000b: ldarg.0 + IL_000c: ldfld !0 class '<>f__AnonymousType3104616430`2'j__TPar',!'j__TPar'>::A@ + IL_0011: ldarg.1 + IL_0012: ldfld !0 class '<>f__AnonymousType3104616430`2'j__TPar',!'j__TPar'>::A@ + IL_0017: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_001c: stloc.0 + IL_001d: ldloc.0 + IL_001e: ldc.i4.0 + IL_001f: bge.s IL_0023 + + IL_0021: ldloc.0 + IL_0022: ret + + IL_0023: ldloc.0 + IL_0024: ldc.i4.0 + IL_0025: ble.s IL_0029 + + IL_0027: ldloc.0 + IL_0028: ret + + IL_0029: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_002e: ldarg.0 + IL_002f: ldfld !1 class '<>f__AnonymousType3104616430`2'j__TPar',!'j__TPar'>::B@ + IL_0034: ldarg.1 + IL_0035: ldfld !1 class '<>f__AnonymousType3104616430`2'j__TPar',!'j__TPar'>::B@ + IL_003a: tail. + IL_003c: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0041: ret + + IL_0042: ldc.i4.1 + IL_0043: ret + + IL_0044: ldarg.1 + IL_0045: brfalse.s IL_0049 + + IL_0047: ldc.i4.m1 + IL_0048: ret + + IL_0049: ldc.i4.0 + IL_004a: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: unbox.any class '<>f__AnonymousType3104616430`2'j__TPar',!'j__TPar'> + IL_0007: tail. + IL_0009: callvirt instance int32 class '<>f__AnonymousType3104616430`2'j__TPar',!'j__TPar'>::CompareTo(class '<>f__AnonymousType3104616430`2') + IL_000e: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj, class [runtime]System.Collections.IComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType3104616430`2'j__TPar',!'j__TPar'> V_0, + class '<>f__AnonymousType3104616430`2'j__TPar',!'j__TPar'> V_1, + int32 V_2) + IL_0000: ldarg.1 + IL_0001: unbox.any class '<>f__AnonymousType3104616430`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: stloc.1 + IL_0009: ldarg.0 + IL_000a: brfalse.s IL_004a + + IL_000c: ldarg.1 + IL_000d: unbox.any class '<>f__AnonymousType3104616430`2'j__TPar',!'j__TPar'> + IL_0012: brfalse.s IL_0048 + + IL_0014: ldarg.2 + IL_0015: ldarg.0 + IL_0016: ldfld !0 class '<>f__AnonymousType3104616430`2'j__TPar',!'j__TPar'>::A@ + IL_001b: ldloc.1 + IL_001c: ldfld !0 class '<>f__AnonymousType3104616430`2'j__TPar',!'j__TPar'>::A@ + IL_0021: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0026: stloc.2 + IL_0027: ldloc.2 + IL_0028: ldc.i4.0 + IL_0029: bge.s IL_002d + + IL_002b: ldloc.2 + IL_002c: ret + + IL_002d: ldloc.2 + IL_002e: ldc.i4.0 + IL_002f: ble.s IL_0033 + + IL_0031: ldloc.2 + IL_0032: ret + + IL_0033: ldarg.2 + IL_0034: ldarg.0 + IL_0035: ldfld !1 class '<>f__AnonymousType3104616430`2'j__TPar',!'j__TPar'>::B@ + IL_003a: ldloc.1 + IL_003b: ldfld !1 class '<>f__AnonymousType3104616430`2'j__TPar',!'j__TPar'>::B@ + IL_0040: tail. + IL_0042: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0047: ret + + IL_0048: ldc.i4.1 + IL_0049: ret + + IL_004a: ldarg.1 + IL_004b: unbox.any class '<>f__AnonymousType3104616430`2'j__TPar',!'j__TPar'> + IL_0050: brfalse.s IL_0054 + + IL_0052: ldc.i4.m1 + IL_0053: ret + + IL_0054: ldc.i4.0 + IL_0055: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode(class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 7 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_003d + + IL_0003: ldc.i4.0 + IL_0004: stloc.0 + IL_0005: ldc.i4 0x9e3779b9 + IL_000a: ldarg.1 + IL_000b: ldarg.0 + IL_000c: ldfld !1 class '<>f__AnonymousType3104616430`2'j__TPar',!'j__TPar'>::B@ + IL_0011: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0016: ldloc.0 + IL_0017: ldc.i4.6 + IL_0018: shl + IL_0019: ldloc.0 + IL_001a: ldc.i4.2 + IL_001b: shr + IL_001c: add + IL_001d: add + IL_001e: add + IL_001f: stloc.0 + IL_0020: ldc.i4 0x9e3779b9 + IL_0025: ldarg.1 + IL_0026: ldarg.0 + IL_0027: ldfld !0 class '<>f__AnonymousType3104616430`2'j__TPar',!'j__TPar'>::A@ + IL_002c: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0031: ldloc.0 + IL_0032: ldc.i4.6 + IL_0033: shl + IL_0034: ldloc.0 + IL_0035: ldc.i4.2 + IL_0036: shr + IL_0037: add + IL_0038: add + IL_0039: add + IL_003a: stloc.0 + IL_003b: ldloc.0 + IL_003c: ret + + IL_003d: ldc.i4.0 + IL_003e: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() + IL_0006: tail. + IL_0008: callvirt instance int32 class '<>f__AnonymousType3104616430`2'j__TPar',!'j__TPar'>::GetHashCode(class [runtime]System.Collections.IEqualityComparer) + IL_000d: ret + } + + .method public hidebysig instance bool Equals(class '<>f__AnonymousType3104616430`2'j__TPar',!'j__TPar'> obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType3104616430`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0035 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0033 + + IL_0006: ldarg.1 + IL_0007: stloc.0 + IL_0008: ldarg.2 + IL_0009: ldarg.0 + IL_000a: ldfld !0 class '<>f__AnonymousType3104616430`2'j__TPar',!'j__TPar'>::A@ + IL_000f: ldloc.0 + IL_0010: ldfld !0 class '<>f__AnonymousType3104616430`2'j__TPar',!'j__TPar'>::A@ + IL_0015: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_001a: brfalse.s IL_0031 + + IL_001c: ldarg.2 + IL_001d: ldarg.0 + IL_001e: ldfld !1 class '<>f__AnonymousType3104616430`2'j__TPar',!'j__TPar'>::B@ + IL_0023: ldloc.0 + IL_0024: ldfld !1 class '<>f__AnonymousType3104616430`2'j__TPar',!'j__TPar'>::B@ + IL_0029: tail. + IL_002b: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_0030: ret + + IL_0031: ldc.i4.0 + IL_0032: ret + + IL_0033: ldc.i4.0 + IL_0034: ret + + IL_0035: ldarg.1 + IL_0036: ldnull + IL_0037: cgt.un + IL_0039: ldc.i4.0 + IL_003a: ceq + IL_003c: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType3104616430`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType3104616430`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0015 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: ldarg.2 + IL_000d: tail. + IL_000f: callvirt instance bool class '<>f__AnonymousType3104616430`2'j__TPar',!'j__TPar'>::Equals(class '<>f__AnonymousType3104616430`2', + class [runtime]System.Collections.IEqualityComparer) + IL_0014: ret + + IL_0015: ldc.i4.0 + IL_0016: ret + } + + .method public hidebysig virtual final instance bool Equals(class '<>f__AnonymousType3104616430`2'j__TPar',!'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0031 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_002f + + IL_0006: ldarg.0 + IL_0007: ldfld !0 class '<>f__AnonymousType3104616430`2'j__TPar',!'j__TPar'>::A@ + IL_000c: ldarg.1 + IL_000d: ldfld !0 class '<>f__AnonymousType3104616430`2'j__TPar',!'j__TPar'>::A@ + IL_0012: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_0017: brfalse.s IL_002d + + IL_0019: ldarg.0 + IL_001a: ldfld !1 class '<>f__AnonymousType3104616430`2'j__TPar',!'j__TPar'>::B@ + IL_001f: ldarg.1 + IL_0020: ldfld !1 class '<>f__AnonymousType3104616430`2'j__TPar',!'j__TPar'>::B@ + IL_0025: tail. + IL_0027: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_002c: ret + + IL_002d: ldc.i4.0 + IL_002e: ret + + IL_002f: ldc.i4.0 + IL_0030: ret + + IL_0031: ldarg.1 + IL_0032: ldnull + IL_0033: cgt.un + IL_0035: ldc.i4.0 + IL_0036: ceq + IL_0038: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (class '<>f__AnonymousType3104616430`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType3104616430`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0014 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: tail. + IL_000e: callvirt instance bool class '<>f__AnonymousType3104616430`2'j__TPar',!'j__TPar'>::Equals(class '<>f__AnonymousType3104616430`2') + IL_0013: ret + + IL_0014: ldc.i4.0 + IL_0015: ret + } + + .property instance !'j__TPar' A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType3104616430`2'::get_A() + } + .property instance !'j__TPar' B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType3104616430`2'::get_B() + } +} + +.class public auto ansi serializable sealed beforefieldinit '<>f__AnonymousType3986374330`2'<'j__TPar','j__TPar'> + extends [runtime]System.Object + implements [runtime]System.Collections.IStructuralComparable, + [runtime]System.IComparable, + class [runtime]System.IComparable`1f__AnonymousType3986374330`2'j__TPar',!'j__TPar'>>, + [runtime]System.Collections.IStructuralEquatable, + class [runtime]System.IEquatable`1f__AnonymousType3986374330`2'j__TPar',!'j__TPar'>> +{ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field private !'j__TPar' Nested@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field private !'j__TPar' Other@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor(!'j__TPar' Nested, !'j__TPar' Other) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 1E 3C 3E 66 5F 5F 41 6E 6F 6E + 79 6D 6F 75 73 54 79 70 65 33 39 38 36 33 37 34 + 33 33 30 60 32 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld !0 class '<>f__AnonymousType3986374330`2'j__TPar',!'j__TPar'>::Nested@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld !1 class '<>f__AnonymousType3986374330`2'j__TPar',!'j__TPar'>::Other@ + IL_0014: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_Nested() 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: ldfld !0 class '<>f__AnonymousType3986374330`2'j__TPar',!'j__TPar'>::Nested@ + IL_0006: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_Other() 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: ldfld !1 class '<>f__AnonymousType3986374330`2'j__TPar',!'j__TPar'>::Other@ + IL_0006: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5f__AnonymousType3986374330`2'j__TPar',!'j__TPar'>,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class '<>f__AnonymousType3986374330`2'j__TPar',!'j__TPar'>>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToStringf__AnonymousType3986374330`2'j__TPar',!'j__TPar'>,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2f__AnonymousType3986374330`2'j__TPar',!'j__TPar'>,string>::Invoke(!0) + IL_0015: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(class '<>f__AnonymousType3986374330`2'j__TPar',!'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0044 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0042 + + IL_0006: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_000b: ldarg.0 + IL_000c: ldfld !0 class '<>f__AnonymousType3986374330`2'j__TPar',!'j__TPar'>::Nested@ + IL_0011: ldarg.1 + IL_0012: ldfld !0 class '<>f__AnonymousType3986374330`2'j__TPar',!'j__TPar'>::Nested@ + IL_0017: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_001c: stloc.0 + IL_001d: ldloc.0 + IL_001e: ldc.i4.0 + IL_001f: bge.s IL_0023 + + IL_0021: ldloc.0 + IL_0022: ret + + IL_0023: ldloc.0 + IL_0024: ldc.i4.0 + IL_0025: ble.s IL_0029 + + IL_0027: ldloc.0 + IL_0028: ret + + IL_0029: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_002e: ldarg.0 + IL_002f: ldfld !1 class '<>f__AnonymousType3986374330`2'j__TPar',!'j__TPar'>::Other@ + IL_0034: ldarg.1 + IL_0035: ldfld !1 class '<>f__AnonymousType3986374330`2'j__TPar',!'j__TPar'>::Other@ + IL_003a: tail. + IL_003c: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0041: ret + + IL_0042: ldc.i4.1 + IL_0043: ret + + IL_0044: ldarg.1 + IL_0045: brfalse.s IL_0049 + + IL_0047: ldc.i4.m1 + IL_0048: ret + + IL_0049: ldc.i4.0 + IL_004a: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: unbox.any class '<>f__AnonymousType3986374330`2'j__TPar',!'j__TPar'> + IL_0007: tail. + IL_0009: callvirt instance int32 class '<>f__AnonymousType3986374330`2'j__TPar',!'j__TPar'>::CompareTo(class '<>f__AnonymousType3986374330`2') + IL_000e: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj, class [runtime]System.Collections.IComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType3986374330`2'j__TPar',!'j__TPar'> V_0, + class '<>f__AnonymousType3986374330`2'j__TPar',!'j__TPar'> V_1, + int32 V_2) + IL_0000: ldarg.1 + IL_0001: unbox.any class '<>f__AnonymousType3986374330`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: stloc.1 + IL_0009: ldarg.0 + IL_000a: brfalse.s IL_004a + + IL_000c: ldarg.1 + IL_000d: unbox.any class '<>f__AnonymousType3986374330`2'j__TPar',!'j__TPar'> + IL_0012: brfalse.s IL_0048 + + IL_0014: ldarg.2 + IL_0015: ldarg.0 + IL_0016: ldfld !0 class '<>f__AnonymousType3986374330`2'j__TPar',!'j__TPar'>::Nested@ + IL_001b: ldloc.1 + IL_001c: ldfld !0 class '<>f__AnonymousType3986374330`2'j__TPar',!'j__TPar'>::Nested@ + IL_0021: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0026: stloc.2 + IL_0027: ldloc.2 + IL_0028: ldc.i4.0 + IL_0029: bge.s IL_002d + + IL_002b: ldloc.2 + IL_002c: ret + + IL_002d: ldloc.2 + IL_002e: ldc.i4.0 + IL_002f: ble.s IL_0033 + + IL_0031: ldloc.2 + IL_0032: ret + + IL_0033: ldarg.2 + IL_0034: ldarg.0 + IL_0035: ldfld !1 class '<>f__AnonymousType3986374330`2'j__TPar',!'j__TPar'>::Other@ + IL_003a: ldloc.1 + IL_003b: ldfld !1 class '<>f__AnonymousType3986374330`2'j__TPar',!'j__TPar'>::Other@ + IL_0040: tail. + IL_0042: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0047: ret + + IL_0048: ldc.i4.1 + IL_0049: ret + + IL_004a: ldarg.1 + IL_004b: unbox.any class '<>f__AnonymousType3986374330`2'j__TPar',!'j__TPar'> + IL_0050: brfalse.s IL_0054 + + IL_0052: ldc.i4.m1 + IL_0053: ret + + IL_0054: ldc.i4.0 + IL_0055: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode(class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 7 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_003d + + IL_0003: ldc.i4.0 + IL_0004: stloc.0 + IL_0005: ldc.i4 0x9e3779b9 + IL_000a: ldarg.1 + IL_000b: ldarg.0 + IL_000c: ldfld !1 class '<>f__AnonymousType3986374330`2'j__TPar',!'j__TPar'>::Other@ + IL_0011: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0016: ldloc.0 + IL_0017: ldc.i4.6 + IL_0018: shl + IL_0019: ldloc.0 + IL_001a: ldc.i4.2 + IL_001b: shr + IL_001c: add + IL_001d: add + IL_001e: add + IL_001f: stloc.0 + IL_0020: ldc.i4 0x9e3779b9 + IL_0025: ldarg.1 + IL_0026: ldarg.0 + IL_0027: ldfld !0 class '<>f__AnonymousType3986374330`2'j__TPar',!'j__TPar'>::Nested@ + IL_002c: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0031: ldloc.0 + IL_0032: ldc.i4.6 + IL_0033: shl + IL_0034: ldloc.0 + IL_0035: ldc.i4.2 + IL_0036: shr + IL_0037: add + IL_0038: add + IL_0039: add + IL_003a: stloc.0 + IL_003b: ldloc.0 + IL_003c: ret + + IL_003d: ldc.i4.0 + IL_003e: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() + IL_0006: tail. + IL_0008: callvirt instance int32 class '<>f__AnonymousType3986374330`2'j__TPar',!'j__TPar'>::GetHashCode(class [runtime]System.Collections.IEqualityComparer) + IL_000d: ret + } + + .method public hidebysig instance bool Equals(class '<>f__AnonymousType3986374330`2'j__TPar',!'j__TPar'> obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType3986374330`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0035 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0033 + + IL_0006: ldarg.1 + IL_0007: stloc.0 + IL_0008: ldarg.2 + IL_0009: ldarg.0 + IL_000a: ldfld !0 class '<>f__AnonymousType3986374330`2'j__TPar',!'j__TPar'>::Nested@ + IL_000f: ldloc.0 + IL_0010: ldfld !0 class '<>f__AnonymousType3986374330`2'j__TPar',!'j__TPar'>::Nested@ + IL_0015: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_001a: brfalse.s IL_0031 + + IL_001c: ldarg.2 + IL_001d: ldarg.0 + IL_001e: ldfld !1 class '<>f__AnonymousType3986374330`2'j__TPar',!'j__TPar'>::Other@ + IL_0023: ldloc.0 + IL_0024: ldfld !1 class '<>f__AnonymousType3986374330`2'j__TPar',!'j__TPar'>::Other@ + IL_0029: tail. + IL_002b: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_0030: ret + + IL_0031: ldc.i4.0 + IL_0032: ret + + IL_0033: ldc.i4.0 + IL_0034: ret + + IL_0035: ldarg.1 + IL_0036: ldnull + IL_0037: cgt.un + IL_0039: ldc.i4.0 + IL_003a: ceq + IL_003c: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType3986374330`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType3986374330`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0015 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: ldarg.2 + IL_000d: tail. + IL_000f: callvirt instance bool class '<>f__AnonymousType3986374330`2'j__TPar',!'j__TPar'>::Equals(class '<>f__AnonymousType3986374330`2', + class [runtime]System.Collections.IEqualityComparer) + IL_0014: ret + + IL_0015: ldc.i4.0 + IL_0016: ret + } + + .method public hidebysig virtual final instance bool Equals(class '<>f__AnonymousType3986374330`2'j__TPar',!'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0031 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_002f + + IL_0006: ldarg.0 + IL_0007: ldfld !0 class '<>f__AnonymousType3986374330`2'j__TPar',!'j__TPar'>::Nested@ + IL_000c: ldarg.1 + IL_000d: ldfld !0 class '<>f__AnonymousType3986374330`2'j__TPar',!'j__TPar'>::Nested@ + IL_0012: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_0017: brfalse.s IL_002d + + IL_0019: ldarg.0 + IL_001a: ldfld !1 class '<>f__AnonymousType3986374330`2'j__TPar',!'j__TPar'>::Other@ + IL_001f: ldarg.1 + IL_0020: ldfld !1 class '<>f__AnonymousType3986374330`2'j__TPar',!'j__TPar'>::Other@ + IL_0025: tail. + IL_0027: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_002c: ret + + IL_002d: ldc.i4.0 + IL_002e: ret + + IL_002f: ldc.i4.0 + IL_0030: ret + + IL_0031: ldarg.1 + IL_0032: ldnull + IL_0033: cgt.un + IL_0035: ldc.i4.0 + IL_0036: ceq + IL_0038: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (class '<>f__AnonymousType3986374330`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType3986374330`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0014 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: tail. + IL_000e: callvirt instance bool class '<>f__AnonymousType3986374330`2'j__TPar',!'j__TPar'>::Equals(class '<>f__AnonymousType3986374330`2') + IL_0013: ret + + IL_0014: ldc.i4.0 + IL_0015: ret + } + + .property instance !'j__TPar' Nested() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType3986374330`2'::get_Nested() + } + .property instance !'j__TPar' Other() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType3986374330`2'::get_Other() + } +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_NoOverlap_Explicit_Spread.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_NoOverlap_Explicit_Spread.fs new file mode 100644 index 00000000000..0ad9bf5b8f6 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_NoOverlap_Explicit_Spread.fs @@ -0,0 +1,3 @@ +let r1 = {| A = 1; B = 2 |} + +let r2 : {| A : int ; B : int; C : int |} = {| C = 3; ...r1 |} diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_NoOverlap_Explicit_Spread.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_NoOverlap_Explicit_Spread.fs.il.bsl new file mode 100644 index 00000000000..cb069a4e819 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_NoOverlap_Explicit_Spread.fs.il.bsl @@ -0,0 +1,1084 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .field static assembly class '<>f__AnonymousType3037170192`2' r1@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 class '<>f__AnonymousType4283677192`3' r2@3 + .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 '<>f__AnonymousType3037170192`2' get_r1() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class '<>f__AnonymousType3037170192`2' assembly::r1@1 + IL_0005: ret + } + + .method public specialname static class '<>f__AnonymousType4283677192`3' get_r2() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class '<>f__AnonymousType4283677192`3' assembly::r2@3 + IL_0005: ret + } + + .method private specialname rtspecialname static void .cctor() cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.0 + IL_0001: stsfld int32 ''.$assembly::init@ + IL_0006: ldsfld int32 ''.$assembly::init@ + IL_000b: pop + IL_000c: ret + } + + .method assembly static void staticInitialization@() cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.1 + IL_0001: ldc.i4.2 + IL_0002: newobj instance void class '<>f__AnonymousType3037170192`2'::.ctor(!0, + !1) + IL_0007: stsfld class '<>f__AnonymousType3037170192`2' assembly::r1@1 + IL_000c: call class '<>f__AnonymousType3037170192`2' assembly::get_r1() + IL_0011: call instance !0 class '<>f__AnonymousType3037170192`2'::get_A() + IL_0016: call class '<>f__AnonymousType3037170192`2' assembly::get_r1() + IL_001b: call instance !1 class '<>f__AnonymousType3037170192`2'::get_B() + IL_0020: ldc.i4.3 + IL_0021: newobj instance void class '<>f__AnonymousType4283677192`3'::.ctor(!0, + !1, + !2) + IL_0026: stsfld class '<>f__AnonymousType4283677192`3' assembly::r2@3 + IL_002b: ret + } + + .property class '<>f__AnonymousType3037170192`2' + r1() + { + .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 class '<>f__AnonymousType3037170192`2' assembly::get_r1() + } + .property class '<>f__AnonymousType4283677192`3' + r2() + { + .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 class '<>f__AnonymousType4283677192`3' assembly::get_r2() + } +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .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 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: call void assembly::staticInitialization@() + IL_0005: ret + } + +} + +.class public auto ansi serializable sealed beforefieldinit '<>f__AnonymousType3037170192`2'<'j__TPar','j__TPar'> + extends [runtime]System.Object + implements [runtime]System.Collections.IStructuralComparable, + [runtime]System.IComparable, + class [runtime]System.IComparable`1f__AnonymousType3037170192`2'j__TPar',!'j__TPar'>>, + [runtime]System.Collections.IStructuralEquatable, + class [runtime]System.IEquatable`1f__AnonymousType3037170192`2'j__TPar',!'j__TPar'>> +{ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field private !'j__TPar' A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field private !'j__TPar' B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor(!'j__TPar' A, !'j__TPar' B) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 1E 3C 3E 66 5F 5F 41 6E 6F 6E + 79 6D 6F 75 73 54 79 70 65 33 30 33 37 31 37 30 + 31 39 32 60 32 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld !0 class '<>f__AnonymousType3037170192`2'j__TPar',!'j__TPar'>::A@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld !1 class '<>f__AnonymousType3037170192`2'j__TPar',!'j__TPar'>::B@ + IL_0014: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_A() 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: ldfld !0 class '<>f__AnonymousType3037170192`2'j__TPar',!'j__TPar'>::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_B() 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: ldfld !1 class '<>f__AnonymousType3037170192`2'j__TPar',!'j__TPar'>::B@ + IL_0006: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5f__AnonymousType3037170192`2'j__TPar',!'j__TPar'>,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class '<>f__AnonymousType3037170192`2'j__TPar',!'j__TPar'>>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToStringf__AnonymousType3037170192`2'j__TPar',!'j__TPar'>,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2f__AnonymousType3037170192`2'j__TPar',!'j__TPar'>,string>::Invoke(!0) + IL_0015: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(class '<>f__AnonymousType3037170192`2'j__TPar',!'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0044 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0042 + + IL_0006: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_000b: ldarg.0 + IL_000c: ldfld !0 class '<>f__AnonymousType3037170192`2'j__TPar',!'j__TPar'>::A@ + IL_0011: ldarg.1 + IL_0012: ldfld !0 class '<>f__AnonymousType3037170192`2'j__TPar',!'j__TPar'>::A@ + IL_0017: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_001c: stloc.0 + IL_001d: ldloc.0 + IL_001e: ldc.i4.0 + IL_001f: bge.s IL_0023 + + IL_0021: ldloc.0 + IL_0022: ret + + IL_0023: ldloc.0 + IL_0024: ldc.i4.0 + IL_0025: ble.s IL_0029 + + IL_0027: ldloc.0 + IL_0028: ret + + IL_0029: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_002e: ldarg.0 + IL_002f: ldfld !1 class '<>f__AnonymousType3037170192`2'j__TPar',!'j__TPar'>::B@ + IL_0034: ldarg.1 + IL_0035: ldfld !1 class '<>f__AnonymousType3037170192`2'j__TPar',!'j__TPar'>::B@ + IL_003a: tail. + IL_003c: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0041: ret + + IL_0042: ldc.i4.1 + IL_0043: ret + + IL_0044: ldarg.1 + IL_0045: brfalse.s IL_0049 + + IL_0047: ldc.i4.m1 + IL_0048: ret + + IL_0049: ldc.i4.0 + IL_004a: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: unbox.any class '<>f__AnonymousType3037170192`2'j__TPar',!'j__TPar'> + IL_0007: tail. + IL_0009: callvirt instance int32 class '<>f__AnonymousType3037170192`2'j__TPar',!'j__TPar'>::CompareTo(class '<>f__AnonymousType3037170192`2') + IL_000e: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj, class [runtime]System.Collections.IComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType3037170192`2'j__TPar',!'j__TPar'> V_0, + class '<>f__AnonymousType3037170192`2'j__TPar',!'j__TPar'> V_1, + int32 V_2) + IL_0000: ldarg.1 + IL_0001: unbox.any class '<>f__AnonymousType3037170192`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: stloc.1 + IL_0009: ldarg.0 + IL_000a: brfalse.s IL_004a + + IL_000c: ldarg.1 + IL_000d: unbox.any class '<>f__AnonymousType3037170192`2'j__TPar',!'j__TPar'> + IL_0012: brfalse.s IL_0048 + + IL_0014: ldarg.2 + IL_0015: ldarg.0 + IL_0016: ldfld !0 class '<>f__AnonymousType3037170192`2'j__TPar',!'j__TPar'>::A@ + IL_001b: ldloc.1 + IL_001c: ldfld !0 class '<>f__AnonymousType3037170192`2'j__TPar',!'j__TPar'>::A@ + IL_0021: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0026: stloc.2 + IL_0027: ldloc.2 + IL_0028: ldc.i4.0 + IL_0029: bge.s IL_002d + + IL_002b: ldloc.2 + IL_002c: ret + + IL_002d: ldloc.2 + IL_002e: ldc.i4.0 + IL_002f: ble.s IL_0033 + + IL_0031: ldloc.2 + IL_0032: ret + + IL_0033: ldarg.2 + IL_0034: ldarg.0 + IL_0035: ldfld !1 class '<>f__AnonymousType3037170192`2'j__TPar',!'j__TPar'>::B@ + IL_003a: ldloc.1 + IL_003b: ldfld !1 class '<>f__AnonymousType3037170192`2'j__TPar',!'j__TPar'>::B@ + IL_0040: tail. + IL_0042: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0047: ret + + IL_0048: ldc.i4.1 + IL_0049: ret + + IL_004a: ldarg.1 + IL_004b: unbox.any class '<>f__AnonymousType3037170192`2'j__TPar',!'j__TPar'> + IL_0050: brfalse.s IL_0054 + + IL_0052: ldc.i4.m1 + IL_0053: ret + + IL_0054: ldc.i4.0 + IL_0055: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode(class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 7 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_003d + + IL_0003: ldc.i4.0 + IL_0004: stloc.0 + IL_0005: ldc.i4 0x9e3779b9 + IL_000a: ldarg.1 + IL_000b: ldarg.0 + IL_000c: ldfld !1 class '<>f__AnonymousType3037170192`2'j__TPar',!'j__TPar'>::B@ + IL_0011: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0016: ldloc.0 + IL_0017: ldc.i4.6 + IL_0018: shl + IL_0019: ldloc.0 + IL_001a: ldc.i4.2 + IL_001b: shr + IL_001c: add + IL_001d: add + IL_001e: add + IL_001f: stloc.0 + IL_0020: ldc.i4 0x9e3779b9 + IL_0025: ldarg.1 + IL_0026: ldarg.0 + IL_0027: ldfld !0 class '<>f__AnonymousType3037170192`2'j__TPar',!'j__TPar'>::A@ + IL_002c: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0031: ldloc.0 + IL_0032: ldc.i4.6 + IL_0033: shl + IL_0034: ldloc.0 + IL_0035: ldc.i4.2 + IL_0036: shr + IL_0037: add + IL_0038: add + IL_0039: add + IL_003a: stloc.0 + IL_003b: ldloc.0 + IL_003c: ret + + IL_003d: ldc.i4.0 + IL_003e: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() + IL_0006: tail. + IL_0008: callvirt instance int32 class '<>f__AnonymousType3037170192`2'j__TPar',!'j__TPar'>::GetHashCode(class [runtime]System.Collections.IEqualityComparer) + IL_000d: ret + } + + .method public hidebysig instance bool Equals(class '<>f__AnonymousType3037170192`2'j__TPar',!'j__TPar'> obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType3037170192`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0035 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0033 + + IL_0006: ldarg.1 + IL_0007: stloc.0 + IL_0008: ldarg.2 + IL_0009: ldarg.0 + IL_000a: ldfld !0 class '<>f__AnonymousType3037170192`2'j__TPar',!'j__TPar'>::A@ + IL_000f: ldloc.0 + IL_0010: ldfld !0 class '<>f__AnonymousType3037170192`2'j__TPar',!'j__TPar'>::A@ + IL_0015: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_001a: brfalse.s IL_0031 + + IL_001c: ldarg.2 + IL_001d: ldarg.0 + IL_001e: ldfld !1 class '<>f__AnonymousType3037170192`2'j__TPar',!'j__TPar'>::B@ + IL_0023: ldloc.0 + IL_0024: ldfld !1 class '<>f__AnonymousType3037170192`2'j__TPar',!'j__TPar'>::B@ + IL_0029: tail. + IL_002b: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_0030: ret + + IL_0031: ldc.i4.0 + IL_0032: ret + + IL_0033: ldc.i4.0 + IL_0034: ret + + IL_0035: ldarg.1 + IL_0036: ldnull + IL_0037: cgt.un + IL_0039: ldc.i4.0 + IL_003a: ceq + IL_003c: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType3037170192`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType3037170192`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0015 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: ldarg.2 + IL_000d: tail. + IL_000f: callvirt instance bool class '<>f__AnonymousType3037170192`2'j__TPar',!'j__TPar'>::Equals(class '<>f__AnonymousType3037170192`2', + class [runtime]System.Collections.IEqualityComparer) + IL_0014: ret + + IL_0015: ldc.i4.0 + IL_0016: ret + } + + .method public hidebysig virtual final instance bool Equals(class '<>f__AnonymousType3037170192`2'j__TPar',!'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0031 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_002f + + IL_0006: ldarg.0 + IL_0007: ldfld !0 class '<>f__AnonymousType3037170192`2'j__TPar',!'j__TPar'>::A@ + IL_000c: ldarg.1 + IL_000d: ldfld !0 class '<>f__AnonymousType3037170192`2'j__TPar',!'j__TPar'>::A@ + IL_0012: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_0017: brfalse.s IL_002d + + IL_0019: ldarg.0 + IL_001a: ldfld !1 class '<>f__AnonymousType3037170192`2'j__TPar',!'j__TPar'>::B@ + IL_001f: ldarg.1 + IL_0020: ldfld !1 class '<>f__AnonymousType3037170192`2'j__TPar',!'j__TPar'>::B@ + IL_0025: tail. + IL_0027: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_002c: ret + + IL_002d: ldc.i4.0 + IL_002e: ret + + IL_002f: ldc.i4.0 + IL_0030: ret + + IL_0031: ldarg.1 + IL_0032: ldnull + IL_0033: cgt.un + IL_0035: ldc.i4.0 + IL_0036: ceq + IL_0038: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (class '<>f__AnonymousType3037170192`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType3037170192`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0014 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: tail. + IL_000e: callvirt instance bool class '<>f__AnonymousType3037170192`2'j__TPar',!'j__TPar'>::Equals(class '<>f__AnonymousType3037170192`2') + IL_0013: ret + + IL_0014: ldc.i4.0 + IL_0015: ret + } + + .property instance !'j__TPar' A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType3037170192`2'::get_A() + } + .property instance !'j__TPar' B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType3037170192`2'::get_B() + } +} + +.class public auto ansi serializable sealed beforefieldinit '<>f__AnonymousType4283677192`3'<'j__TPar','j__TPar','j__TPar'> + extends [runtime]System.Object + implements [runtime]System.Collections.IStructuralComparable, + [runtime]System.IComparable, + class [runtime]System.IComparable`1f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'>>, + [runtime]System.Collections.IStructuralEquatable, + class [runtime]System.IEquatable`1f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'>> +{ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field private !'j__TPar' A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field private !'j__TPar' B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field private !'j__TPar' C@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public specialname rtspecialname + instance void .ctor(!'j__TPar' A, + !'j__TPar' B, + !'j__TPar' C) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 1E 3C 3E 66 5F 5F 41 6E 6F 6E + 79 6D 6F 75 73 54 79 70 65 34 32 38 33 36 37 37 + 31 39 32 60 33 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld !0 class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'>::A@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld !1 class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'>::B@ + IL_0014: ldarg.0 + IL_0015: ldarg.3 + IL_0016: stfld !2 class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'>::C@ + IL_001b: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_A() 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: ldfld !0 class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'>::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_B() 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: ldfld !1 class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'>::B@ + IL_0006: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_C() 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: ldfld !2 class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'>::C@ + IL_0006: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'>,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'>>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToStringf__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'>,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'>,string>::Invoke(!0) + IL_0015: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (int32 V_0, + int32 V_1) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0067 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0065 + + IL_0006: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_000b: ldarg.0 + IL_000c: ldfld !0 class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'>::A@ + IL_0011: ldarg.1 + IL_0012: ldfld !0 class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'>::A@ + IL_0017: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_001c: stloc.0 + IL_001d: ldloc.0 + IL_001e: ldc.i4.0 + IL_001f: bge.s IL_0023 + + IL_0021: ldloc.0 + IL_0022: ret + + IL_0023: ldloc.0 + IL_0024: ldc.i4.0 + IL_0025: ble.s IL_0029 + + IL_0027: ldloc.0 + IL_0028: ret + + IL_0029: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_002e: ldarg.0 + IL_002f: ldfld !1 class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'>::B@ + IL_0034: ldarg.1 + IL_0035: ldfld !1 class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'>::B@ + IL_003a: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_003f: stloc.1 + IL_0040: ldloc.1 + IL_0041: ldc.i4.0 + IL_0042: bge.s IL_0046 + + IL_0044: ldloc.1 + IL_0045: ret + + IL_0046: ldloc.1 + IL_0047: ldc.i4.0 + IL_0048: ble.s IL_004c + + IL_004a: ldloc.1 + IL_004b: ret + + IL_004c: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_0051: ldarg.0 + IL_0052: ldfld !2 class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'>::C@ + IL_0057: ldarg.1 + IL_0058: ldfld !2 class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'>::C@ + IL_005d: tail. + IL_005f: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0064: ret + + IL_0065: ldc.i4.1 + IL_0066: ret + + IL_0067: ldarg.1 + IL_0068: brfalse.s IL_006c + + IL_006a: ldc.i4.m1 + IL_006b: ret + + IL_006c: ldc.i4.0 + IL_006d: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: unbox.any class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'> + IL_0007: tail. + IL_0009: callvirt instance int32 class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'>::CompareTo(class '<>f__AnonymousType4283677192`3') + IL_000e: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj, class [runtime]System.Collections.IComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'> V_0, + class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'> V_1, + int32 V_2, + int32 V_3) + IL_0000: ldarg.1 + IL_0001: unbox.any class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: stloc.1 + IL_0009: ldarg.0 + IL_000a: brfalse.s IL_0069 + + IL_000c: ldarg.1 + IL_000d: unbox.any class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'> + IL_0012: brfalse.s IL_0067 + + IL_0014: ldarg.2 + IL_0015: ldarg.0 + IL_0016: ldfld !0 class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'>::A@ + IL_001b: ldloc.1 + IL_001c: ldfld !0 class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'>::A@ + IL_0021: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0026: stloc.2 + IL_0027: ldloc.2 + IL_0028: ldc.i4.0 + IL_0029: bge.s IL_002d + + IL_002b: ldloc.2 + IL_002c: ret + + IL_002d: ldloc.2 + IL_002e: ldc.i4.0 + IL_002f: ble.s IL_0033 + + IL_0031: ldloc.2 + IL_0032: ret + + IL_0033: ldarg.2 + IL_0034: ldarg.0 + IL_0035: ldfld !1 class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'>::B@ + IL_003a: ldloc.1 + IL_003b: ldfld !1 class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'>::B@ + IL_0040: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0045: stloc.3 + IL_0046: ldloc.3 + IL_0047: ldc.i4.0 + IL_0048: bge.s IL_004c + + IL_004a: ldloc.3 + IL_004b: ret + + IL_004c: ldloc.3 + IL_004d: ldc.i4.0 + IL_004e: ble.s IL_0052 + + IL_0050: ldloc.3 + IL_0051: ret + + IL_0052: ldarg.2 + IL_0053: ldarg.0 + IL_0054: ldfld !2 class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'>::C@ + IL_0059: ldloc.1 + IL_005a: ldfld !2 class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'>::C@ + IL_005f: tail. + IL_0061: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0066: ret + + IL_0067: ldc.i4.1 + IL_0068: ret + + IL_0069: ldarg.1 + IL_006a: unbox.any class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'> + IL_006f: brfalse.s IL_0073 + + IL_0071: ldc.i4.m1 + IL_0072: ret + + IL_0073: ldc.i4.0 + IL_0074: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode(class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 7 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0058 + + IL_0003: ldc.i4.0 + IL_0004: stloc.0 + IL_0005: ldc.i4 0x9e3779b9 + IL_000a: ldarg.1 + IL_000b: ldarg.0 + IL_000c: ldfld !2 class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'>::C@ + IL_0011: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0016: ldloc.0 + IL_0017: ldc.i4.6 + IL_0018: shl + IL_0019: ldloc.0 + IL_001a: ldc.i4.2 + IL_001b: shr + IL_001c: add + IL_001d: add + IL_001e: add + IL_001f: stloc.0 + IL_0020: ldc.i4 0x9e3779b9 + IL_0025: ldarg.1 + IL_0026: ldarg.0 + IL_0027: ldfld !1 class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'>::B@ + IL_002c: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0031: ldloc.0 + IL_0032: ldc.i4.6 + IL_0033: shl + IL_0034: ldloc.0 + IL_0035: ldc.i4.2 + IL_0036: shr + IL_0037: add + IL_0038: add + IL_0039: add + IL_003a: stloc.0 + IL_003b: ldc.i4 0x9e3779b9 + IL_0040: ldarg.1 + IL_0041: ldarg.0 + IL_0042: ldfld !0 class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'>::A@ + IL_0047: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_004c: ldloc.0 + IL_004d: ldc.i4.6 + IL_004e: shl + IL_004f: ldloc.0 + IL_0050: ldc.i4.2 + IL_0051: shr + IL_0052: add + IL_0053: add + IL_0054: add + IL_0055: stloc.0 + IL_0056: ldloc.0 + IL_0057: ret + + IL_0058: ldc.i4.0 + IL_0059: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() + IL_0006: tail. + IL_0008: callvirt instance int32 class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'>::GetHashCode(class [runtime]System.Collections.IEqualityComparer) + IL_000d: ret + } + + .method public hidebysig instance bool Equals(class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'> obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_004b + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0049 + + IL_0006: ldarg.1 + IL_0007: stloc.0 + IL_0008: ldarg.2 + IL_0009: ldarg.0 + IL_000a: ldfld !0 class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'>::A@ + IL_000f: ldloc.0 + IL_0010: ldfld !0 class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'>::A@ + IL_0015: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_001a: brfalse.s IL_0047 + + IL_001c: ldarg.2 + IL_001d: ldarg.0 + IL_001e: ldfld !1 class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'>::B@ + IL_0023: ldloc.0 + IL_0024: ldfld !1 class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'>::B@ + IL_0029: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_002e: brfalse.s IL_0045 + + IL_0030: ldarg.2 + IL_0031: ldarg.0 + IL_0032: ldfld !2 class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'>::C@ + IL_0037: ldloc.0 + IL_0038: ldfld !2 class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'>::C@ + IL_003d: tail. + IL_003f: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_0044: ret + + IL_0045: ldc.i4.0 + IL_0046: ret + + IL_0047: ldc.i4.0 + IL_0048: ret + + IL_0049: ldc.i4.0 + IL_004a: ret + + IL_004b: ldarg.1 + IL_004c: ldnull + IL_004d: cgt.un + IL_004f: ldc.i4.0 + IL_0050: ceq + IL_0052: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0015 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: ldarg.2 + IL_000d: tail. + IL_000f: callvirt instance bool class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'>::Equals(class '<>f__AnonymousType4283677192`3', + class [runtime]System.Collections.IEqualityComparer) + IL_0014: ret + + IL_0015: ldc.i4.0 + IL_0016: ret + } + + .method public hidebysig virtual final instance bool Equals(class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0046 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0044 + + IL_0006: ldarg.0 + IL_0007: ldfld !0 class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'>::A@ + IL_000c: ldarg.1 + IL_000d: ldfld !0 class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'>::A@ + IL_0012: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_0017: brfalse.s IL_0042 + + IL_0019: ldarg.0 + IL_001a: ldfld !1 class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'>::B@ + IL_001f: ldarg.1 + IL_0020: ldfld !1 class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'>::B@ + IL_0025: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_002a: brfalse.s IL_0040 + + IL_002c: ldarg.0 + IL_002d: ldfld !2 class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'>::C@ + IL_0032: ldarg.1 + IL_0033: ldfld !2 class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'>::C@ + IL_0038: tail. + IL_003a: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_003f: ret + + IL_0040: ldc.i4.0 + IL_0041: ret + + IL_0042: ldc.i4.0 + IL_0043: ret + + IL_0044: ldc.i4.0 + IL_0045: ret + + IL_0046: ldarg.1 + IL_0047: ldnull + IL_0048: cgt.un + IL_004a: ldc.i4.0 + IL_004b: ceq + IL_004d: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0014 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: tail. + IL_000e: callvirt instance bool class '<>f__AnonymousType4283677192`3'j__TPar',!'j__TPar',!'j__TPar'>::Equals(class '<>f__AnonymousType4283677192`3') + IL_0013: ret + + IL_0014: ldc.i4.0 + IL_0015: ret + } + + .property instance !'j__TPar' A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType4283677192`3'::get_A() + } + .property instance !'j__TPar' B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType4283677192`3'::get_B() + } + .property instance !'j__TPar' C() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 02 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType4283677192`3'::get_C() + } +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_NoOverlap_Spread_Explicit.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_NoOverlap_Spread_Explicit.fs new file mode 100644 index 00000000000..5be3b1ddbc8 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_NoOverlap_Spread_Explicit.fs @@ -0,0 +1,3 @@ +let r1 = {| A = 1; B = 2 |} + +let r2 : {| A : int ; B : int; C : int |} = {| ...r1; C = 3 |} diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_NoOverlap_Spread_Explicit.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_NoOverlap_Spread_Explicit.fs.il.bsl new file mode 100644 index 00000000000..99e64f109a6 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_NoOverlap_Spread_Explicit.fs.il.bsl @@ -0,0 +1,1084 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .field static assembly class '<>f__AnonymousType998605617`2' r1@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 class '<>f__AnonymousType1772839104`3' r2@3 + .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 '<>f__AnonymousType998605617`2' get_r1() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class '<>f__AnonymousType998605617`2' assembly::r1@1 + IL_0005: ret + } + + .method public specialname static class '<>f__AnonymousType1772839104`3' get_r2() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class '<>f__AnonymousType1772839104`3' assembly::r2@3 + IL_0005: ret + } + + .method private specialname rtspecialname static void .cctor() cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.0 + IL_0001: stsfld int32 ''.$assembly::init@ + IL_0006: ldsfld int32 ''.$assembly::init@ + IL_000b: pop + IL_000c: ret + } + + .method assembly static void staticInitialization@() cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.1 + IL_0001: ldc.i4.2 + IL_0002: newobj instance void class '<>f__AnonymousType998605617`2'::.ctor(!0, + !1) + IL_0007: stsfld class '<>f__AnonymousType998605617`2' assembly::r1@1 + IL_000c: call class '<>f__AnonymousType998605617`2' assembly::get_r1() + IL_0011: call instance !0 class '<>f__AnonymousType998605617`2'::get_A() + IL_0016: call class '<>f__AnonymousType998605617`2' assembly::get_r1() + IL_001b: call instance !1 class '<>f__AnonymousType998605617`2'::get_B() + IL_0020: ldc.i4.3 + IL_0021: newobj instance void class '<>f__AnonymousType1772839104`3'::.ctor(!0, + !1, + !2) + IL_0026: stsfld class '<>f__AnonymousType1772839104`3' assembly::r2@3 + IL_002b: ret + } + + .property class '<>f__AnonymousType998605617`2' + r1() + { + .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 class '<>f__AnonymousType998605617`2' assembly::get_r1() + } + .property class '<>f__AnonymousType1772839104`3' + r2() + { + .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 class '<>f__AnonymousType1772839104`3' assembly::get_r2() + } +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .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 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: call void assembly::staticInitialization@() + IL_0005: ret + } + +} + +.class public auto ansi serializable sealed beforefieldinit '<>f__AnonymousType1772839104`3'<'j__TPar','j__TPar','j__TPar'> + extends [runtime]System.Object + implements [runtime]System.Collections.IStructuralComparable, + [runtime]System.IComparable, + class [runtime]System.IComparable`1f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'>>, + [runtime]System.Collections.IStructuralEquatable, + class [runtime]System.IEquatable`1f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'>> +{ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field private !'j__TPar' A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field private !'j__TPar' B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field private !'j__TPar' C@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public specialname rtspecialname + instance void .ctor(!'j__TPar' A, + !'j__TPar' B, + !'j__TPar' C) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 1E 3C 3E 66 5F 5F 41 6E 6F 6E + 79 6D 6F 75 73 54 79 70 65 31 37 37 32 38 33 39 + 31 30 34 60 33 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld !0 class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'>::A@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld !1 class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'>::B@ + IL_0014: ldarg.0 + IL_0015: ldarg.3 + IL_0016: stfld !2 class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'>::C@ + IL_001b: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_A() 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: ldfld !0 class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'>::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_B() 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: ldfld !1 class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'>::B@ + IL_0006: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_C() 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: ldfld !2 class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'>::C@ + IL_0006: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'>,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'>>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToStringf__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'>,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'>,string>::Invoke(!0) + IL_0015: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (int32 V_0, + int32 V_1) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0067 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0065 + + IL_0006: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_000b: ldarg.0 + IL_000c: ldfld !0 class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'>::A@ + IL_0011: ldarg.1 + IL_0012: ldfld !0 class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'>::A@ + IL_0017: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_001c: stloc.0 + IL_001d: ldloc.0 + IL_001e: ldc.i4.0 + IL_001f: bge.s IL_0023 + + IL_0021: ldloc.0 + IL_0022: ret + + IL_0023: ldloc.0 + IL_0024: ldc.i4.0 + IL_0025: ble.s IL_0029 + + IL_0027: ldloc.0 + IL_0028: ret + + IL_0029: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_002e: ldarg.0 + IL_002f: ldfld !1 class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'>::B@ + IL_0034: ldarg.1 + IL_0035: ldfld !1 class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'>::B@ + IL_003a: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_003f: stloc.1 + IL_0040: ldloc.1 + IL_0041: ldc.i4.0 + IL_0042: bge.s IL_0046 + + IL_0044: ldloc.1 + IL_0045: ret + + IL_0046: ldloc.1 + IL_0047: ldc.i4.0 + IL_0048: ble.s IL_004c + + IL_004a: ldloc.1 + IL_004b: ret + + IL_004c: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_0051: ldarg.0 + IL_0052: ldfld !2 class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'>::C@ + IL_0057: ldarg.1 + IL_0058: ldfld !2 class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'>::C@ + IL_005d: tail. + IL_005f: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0064: ret + + IL_0065: ldc.i4.1 + IL_0066: ret + + IL_0067: ldarg.1 + IL_0068: brfalse.s IL_006c + + IL_006a: ldc.i4.m1 + IL_006b: ret + + IL_006c: ldc.i4.0 + IL_006d: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: unbox.any class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'> + IL_0007: tail. + IL_0009: callvirt instance int32 class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'>::CompareTo(class '<>f__AnonymousType1772839104`3') + IL_000e: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj, class [runtime]System.Collections.IComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'> V_0, + class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'> V_1, + int32 V_2, + int32 V_3) + IL_0000: ldarg.1 + IL_0001: unbox.any class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: stloc.1 + IL_0009: ldarg.0 + IL_000a: brfalse.s IL_0069 + + IL_000c: ldarg.1 + IL_000d: unbox.any class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'> + IL_0012: brfalse.s IL_0067 + + IL_0014: ldarg.2 + IL_0015: ldarg.0 + IL_0016: ldfld !0 class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'>::A@ + IL_001b: ldloc.1 + IL_001c: ldfld !0 class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'>::A@ + IL_0021: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0026: stloc.2 + IL_0027: ldloc.2 + IL_0028: ldc.i4.0 + IL_0029: bge.s IL_002d + + IL_002b: ldloc.2 + IL_002c: ret + + IL_002d: ldloc.2 + IL_002e: ldc.i4.0 + IL_002f: ble.s IL_0033 + + IL_0031: ldloc.2 + IL_0032: ret + + IL_0033: ldarg.2 + IL_0034: ldarg.0 + IL_0035: ldfld !1 class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'>::B@ + IL_003a: ldloc.1 + IL_003b: ldfld !1 class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'>::B@ + IL_0040: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0045: stloc.3 + IL_0046: ldloc.3 + IL_0047: ldc.i4.0 + IL_0048: bge.s IL_004c + + IL_004a: ldloc.3 + IL_004b: ret + + IL_004c: ldloc.3 + IL_004d: ldc.i4.0 + IL_004e: ble.s IL_0052 + + IL_0050: ldloc.3 + IL_0051: ret + + IL_0052: ldarg.2 + IL_0053: ldarg.0 + IL_0054: ldfld !2 class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'>::C@ + IL_0059: ldloc.1 + IL_005a: ldfld !2 class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'>::C@ + IL_005f: tail. + IL_0061: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0066: ret + + IL_0067: ldc.i4.1 + IL_0068: ret + + IL_0069: ldarg.1 + IL_006a: unbox.any class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'> + IL_006f: brfalse.s IL_0073 + + IL_0071: ldc.i4.m1 + IL_0072: ret + + IL_0073: ldc.i4.0 + IL_0074: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode(class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 7 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0058 + + IL_0003: ldc.i4.0 + IL_0004: stloc.0 + IL_0005: ldc.i4 0x9e3779b9 + IL_000a: ldarg.1 + IL_000b: ldarg.0 + IL_000c: ldfld !2 class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'>::C@ + IL_0011: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0016: ldloc.0 + IL_0017: ldc.i4.6 + IL_0018: shl + IL_0019: ldloc.0 + IL_001a: ldc.i4.2 + IL_001b: shr + IL_001c: add + IL_001d: add + IL_001e: add + IL_001f: stloc.0 + IL_0020: ldc.i4 0x9e3779b9 + IL_0025: ldarg.1 + IL_0026: ldarg.0 + IL_0027: ldfld !1 class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'>::B@ + IL_002c: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0031: ldloc.0 + IL_0032: ldc.i4.6 + IL_0033: shl + IL_0034: ldloc.0 + IL_0035: ldc.i4.2 + IL_0036: shr + IL_0037: add + IL_0038: add + IL_0039: add + IL_003a: stloc.0 + IL_003b: ldc.i4 0x9e3779b9 + IL_0040: ldarg.1 + IL_0041: ldarg.0 + IL_0042: ldfld !0 class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'>::A@ + IL_0047: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_004c: ldloc.0 + IL_004d: ldc.i4.6 + IL_004e: shl + IL_004f: ldloc.0 + IL_0050: ldc.i4.2 + IL_0051: shr + IL_0052: add + IL_0053: add + IL_0054: add + IL_0055: stloc.0 + IL_0056: ldloc.0 + IL_0057: ret + + IL_0058: ldc.i4.0 + IL_0059: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() + IL_0006: tail. + IL_0008: callvirt instance int32 class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'>::GetHashCode(class [runtime]System.Collections.IEqualityComparer) + IL_000d: ret + } + + .method public hidebysig instance bool Equals(class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'> obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_004b + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0049 + + IL_0006: ldarg.1 + IL_0007: stloc.0 + IL_0008: ldarg.2 + IL_0009: ldarg.0 + IL_000a: ldfld !0 class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'>::A@ + IL_000f: ldloc.0 + IL_0010: ldfld !0 class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'>::A@ + IL_0015: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_001a: brfalse.s IL_0047 + + IL_001c: ldarg.2 + IL_001d: ldarg.0 + IL_001e: ldfld !1 class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'>::B@ + IL_0023: ldloc.0 + IL_0024: ldfld !1 class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'>::B@ + IL_0029: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_002e: brfalse.s IL_0045 + + IL_0030: ldarg.2 + IL_0031: ldarg.0 + IL_0032: ldfld !2 class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'>::C@ + IL_0037: ldloc.0 + IL_0038: ldfld !2 class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'>::C@ + IL_003d: tail. + IL_003f: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_0044: ret + + IL_0045: ldc.i4.0 + IL_0046: ret + + IL_0047: ldc.i4.0 + IL_0048: ret + + IL_0049: ldc.i4.0 + IL_004a: ret + + IL_004b: ldarg.1 + IL_004c: ldnull + IL_004d: cgt.un + IL_004f: ldc.i4.0 + IL_0050: ceq + IL_0052: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0015 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: ldarg.2 + IL_000d: tail. + IL_000f: callvirt instance bool class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'>::Equals(class '<>f__AnonymousType1772839104`3', + class [runtime]System.Collections.IEqualityComparer) + IL_0014: ret + + IL_0015: ldc.i4.0 + IL_0016: ret + } + + .method public hidebysig virtual final instance bool Equals(class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0046 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0044 + + IL_0006: ldarg.0 + IL_0007: ldfld !0 class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'>::A@ + IL_000c: ldarg.1 + IL_000d: ldfld !0 class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'>::A@ + IL_0012: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_0017: brfalse.s IL_0042 + + IL_0019: ldarg.0 + IL_001a: ldfld !1 class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'>::B@ + IL_001f: ldarg.1 + IL_0020: ldfld !1 class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'>::B@ + IL_0025: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_002a: brfalse.s IL_0040 + + IL_002c: ldarg.0 + IL_002d: ldfld !2 class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'>::C@ + IL_0032: ldarg.1 + IL_0033: ldfld !2 class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'>::C@ + IL_0038: tail. + IL_003a: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_003f: ret + + IL_0040: ldc.i4.0 + IL_0041: ret + + IL_0042: ldc.i4.0 + IL_0043: ret + + IL_0044: ldc.i4.0 + IL_0045: ret + + IL_0046: ldarg.1 + IL_0047: ldnull + IL_0048: cgt.un + IL_004a: ldc.i4.0 + IL_004b: ceq + IL_004d: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0014 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: tail. + IL_000e: callvirt instance bool class '<>f__AnonymousType1772839104`3'j__TPar',!'j__TPar',!'j__TPar'>::Equals(class '<>f__AnonymousType1772839104`3') + IL_0013: ret + + IL_0014: ldc.i4.0 + IL_0015: ret + } + + .property instance !'j__TPar' A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType1772839104`3'::get_A() + } + .property instance !'j__TPar' B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType1772839104`3'::get_B() + } + .property instance !'j__TPar' C() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 02 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType1772839104`3'::get_C() + } +} + +.class public auto ansi serializable sealed beforefieldinit '<>f__AnonymousType998605617`2'<'j__TPar','j__TPar'> + extends [runtime]System.Object + implements [runtime]System.Collections.IStructuralComparable, + [runtime]System.IComparable, + class [runtime]System.IComparable`1f__AnonymousType998605617`2'j__TPar',!'j__TPar'>>, + [runtime]System.Collections.IStructuralEquatable, + class [runtime]System.IEquatable`1f__AnonymousType998605617`2'j__TPar',!'j__TPar'>> +{ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field private !'j__TPar' A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field private !'j__TPar' B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor(!'j__TPar' A, !'j__TPar' B) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 1D 3C 3E 66 5F 5F 41 6E 6F 6E + 79 6D 6F 75 73 54 79 70 65 39 39 38 36 30 35 36 + 31 37 60 32 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld !0 class '<>f__AnonymousType998605617`2'j__TPar',!'j__TPar'>::A@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld !1 class '<>f__AnonymousType998605617`2'j__TPar',!'j__TPar'>::B@ + IL_0014: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_A() 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: ldfld !0 class '<>f__AnonymousType998605617`2'j__TPar',!'j__TPar'>::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_B() 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: ldfld !1 class '<>f__AnonymousType998605617`2'j__TPar',!'j__TPar'>::B@ + IL_0006: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5f__AnonymousType998605617`2'j__TPar',!'j__TPar'>,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class '<>f__AnonymousType998605617`2'j__TPar',!'j__TPar'>>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToStringf__AnonymousType998605617`2'j__TPar',!'j__TPar'>,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2f__AnonymousType998605617`2'j__TPar',!'j__TPar'>,string>::Invoke(!0) + IL_0015: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(class '<>f__AnonymousType998605617`2'j__TPar',!'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0044 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0042 + + IL_0006: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_000b: ldarg.0 + IL_000c: ldfld !0 class '<>f__AnonymousType998605617`2'j__TPar',!'j__TPar'>::A@ + IL_0011: ldarg.1 + IL_0012: ldfld !0 class '<>f__AnonymousType998605617`2'j__TPar',!'j__TPar'>::A@ + IL_0017: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_001c: stloc.0 + IL_001d: ldloc.0 + IL_001e: ldc.i4.0 + IL_001f: bge.s IL_0023 + + IL_0021: ldloc.0 + IL_0022: ret + + IL_0023: ldloc.0 + IL_0024: ldc.i4.0 + IL_0025: ble.s IL_0029 + + IL_0027: ldloc.0 + IL_0028: ret + + IL_0029: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_002e: ldarg.0 + IL_002f: ldfld !1 class '<>f__AnonymousType998605617`2'j__TPar',!'j__TPar'>::B@ + IL_0034: ldarg.1 + IL_0035: ldfld !1 class '<>f__AnonymousType998605617`2'j__TPar',!'j__TPar'>::B@ + IL_003a: tail. + IL_003c: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0041: ret + + IL_0042: ldc.i4.1 + IL_0043: ret + + IL_0044: ldarg.1 + IL_0045: brfalse.s IL_0049 + + IL_0047: ldc.i4.m1 + IL_0048: ret + + IL_0049: ldc.i4.0 + IL_004a: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: unbox.any class '<>f__AnonymousType998605617`2'j__TPar',!'j__TPar'> + IL_0007: tail. + IL_0009: callvirt instance int32 class '<>f__AnonymousType998605617`2'j__TPar',!'j__TPar'>::CompareTo(class '<>f__AnonymousType998605617`2') + IL_000e: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj, class [runtime]System.Collections.IComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType998605617`2'j__TPar',!'j__TPar'> V_0, + class '<>f__AnonymousType998605617`2'j__TPar',!'j__TPar'> V_1, + int32 V_2) + IL_0000: ldarg.1 + IL_0001: unbox.any class '<>f__AnonymousType998605617`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: stloc.1 + IL_0009: ldarg.0 + IL_000a: brfalse.s IL_004a + + IL_000c: ldarg.1 + IL_000d: unbox.any class '<>f__AnonymousType998605617`2'j__TPar',!'j__TPar'> + IL_0012: brfalse.s IL_0048 + + IL_0014: ldarg.2 + IL_0015: ldarg.0 + IL_0016: ldfld !0 class '<>f__AnonymousType998605617`2'j__TPar',!'j__TPar'>::A@ + IL_001b: ldloc.1 + IL_001c: ldfld !0 class '<>f__AnonymousType998605617`2'j__TPar',!'j__TPar'>::A@ + IL_0021: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0026: stloc.2 + IL_0027: ldloc.2 + IL_0028: ldc.i4.0 + IL_0029: bge.s IL_002d + + IL_002b: ldloc.2 + IL_002c: ret + + IL_002d: ldloc.2 + IL_002e: ldc.i4.0 + IL_002f: ble.s IL_0033 + + IL_0031: ldloc.2 + IL_0032: ret + + IL_0033: ldarg.2 + IL_0034: ldarg.0 + IL_0035: ldfld !1 class '<>f__AnonymousType998605617`2'j__TPar',!'j__TPar'>::B@ + IL_003a: ldloc.1 + IL_003b: ldfld !1 class '<>f__AnonymousType998605617`2'j__TPar',!'j__TPar'>::B@ + IL_0040: tail. + IL_0042: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0047: ret + + IL_0048: ldc.i4.1 + IL_0049: ret + + IL_004a: ldarg.1 + IL_004b: unbox.any class '<>f__AnonymousType998605617`2'j__TPar',!'j__TPar'> + IL_0050: brfalse.s IL_0054 + + IL_0052: ldc.i4.m1 + IL_0053: ret + + IL_0054: ldc.i4.0 + IL_0055: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode(class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 7 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_003d + + IL_0003: ldc.i4.0 + IL_0004: stloc.0 + IL_0005: ldc.i4 0x9e3779b9 + IL_000a: ldarg.1 + IL_000b: ldarg.0 + IL_000c: ldfld !1 class '<>f__AnonymousType998605617`2'j__TPar',!'j__TPar'>::B@ + IL_0011: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0016: ldloc.0 + IL_0017: ldc.i4.6 + IL_0018: shl + IL_0019: ldloc.0 + IL_001a: ldc.i4.2 + IL_001b: shr + IL_001c: add + IL_001d: add + IL_001e: add + IL_001f: stloc.0 + IL_0020: ldc.i4 0x9e3779b9 + IL_0025: ldarg.1 + IL_0026: ldarg.0 + IL_0027: ldfld !0 class '<>f__AnonymousType998605617`2'j__TPar',!'j__TPar'>::A@ + IL_002c: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0031: ldloc.0 + IL_0032: ldc.i4.6 + IL_0033: shl + IL_0034: ldloc.0 + IL_0035: ldc.i4.2 + IL_0036: shr + IL_0037: add + IL_0038: add + IL_0039: add + IL_003a: stloc.0 + IL_003b: ldloc.0 + IL_003c: ret + + IL_003d: ldc.i4.0 + IL_003e: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() + IL_0006: tail. + IL_0008: callvirt instance int32 class '<>f__AnonymousType998605617`2'j__TPar',!'j__TPar'>::GetHashCode(class [runtime]System.Collections.IEqualityComparer) + IL_000d: ret + } + + .method public hidebysig instance bool Equals(class '<>f__AnonymousType998605617`2'j__TPar',!'j__TPar'> obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType998605617`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0035 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0033 + + IL_0006: ldarg.1 + IL_0007: stloc.0 + IL_0008: ldarg.2 + IL_0009: ldarg.0 + IL_000a: ldfld !0 class '<>f__AnonymousType998605617`2'j__TPar',!'j__TPar'>::A@ + IL_000f: ldloc.0 + IL_0010: ldfld !0 class '<>f__AnonymousType998605617`2'j__TPar',!'j__TPar'>::A@ + IL_0015: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_001a: brfalse.s IL_0031 + + IL_001c: ldarg.2 + IL_001d: ldarg.0 + IL_001e: ldfld !1 class '<>f__AnonymousType998605617`2'j__TPar',!'j__TPar'>::B@ + IL_0023: ldloc.0 + IL_0024: ldfld !1 class '<>f__AnonymousType998605617`2'j__TPar',!'j__TPar'>::B@ + IL_0029: tail. + IL_002b: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_0030: ret + + IL_0031: ldc.i4.0 + IL_0032: ret + + IL_0033: ldc.i4.0 + IL_0034: ret + + IL_0035: ldarg.1 + IL_0036: ldnull + IL_0037: cgt.un + IL_0039: ldc.i4.0 + IL_003a: ceq + IL_003c: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType998605617`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType998605617`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0015 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: ldarg.2 + IL_000d: tail. + IL_000f: callvirt instance bool class '<>f__AnonymousType998605617`2'j__TPar',!'j__TPar'>::Equals(class '<>f__AnonymousType998605617`2', + class [runtime]System.Collections.IEqualityComparer) + IL_0014: ret + + IL_0015: ldc.i4.0 + IL_0016: ret + } + + .method public hidebysig virtual final instance bool Equals(class '<>f__AnonymousType998605617`2'j__TPar',!'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0031 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_002f + + IL_0006: ldarg.0 + IL_0007: ldfld !0 class '<>f__AnonymousType998605617`2'j__TPar',!'j__TPar'>::A@ + IL_000c: ldarg.1 + IL_000d: ldfld !0 class '<>f__AnonymousType998605617`2'j__TPar',!'j__TPar'>::A@ + IL_0012: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_0017: brfalse.s IL_002d + + IL_0019: ldarg.0 + IL_001a: ldfld !1 class '<>f__AnonymousType998605617`2'j__TPar',!'j__TPar'>::B@ + IL_001f: ldarg.1 + IL_0020: ldfld !1 class '<>f__AnonymousType998605617`2'j__TPar',!'j__TPar'>::B@ + IL_0025: tail. + IL_0027: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_002c: ret + + IL_002d: ldc.i4.0 + IL_002e: ret + + IL_002f: ldc.i4.0 + IL_0030: ret + + IL_0031: ldarg.1 + IL_0032: ldnull + IL_0033: cgt.un + IL_0035: ldc.i4.0 + IL_0036: ceq + IL_0038: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (class '<>f__AnonymousType998605617`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType998605617`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0014 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: tail. + IL_000e: callvirt instance bool class '<>f__AnonymousType998605617`2'j__TPar',!'j__TPar'>::Equals(class '<>f__AnonymousType998605617`2') + IL_0013: ret + + IL_0014: ldc.i4.0 + IL_0015: ret + } + + .property instance !'j__TPar' A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType998605617`2'::get_A() + } + .property instance !'j__TPar' B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType998605617`2'::get_B() + } +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_NoOverlap_Spread_Spread.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_NoOverlap_Spread_Spread.fs new file mode 100644 index 00000000000..dba1ae2aff6 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_NoOverlap_Spread_Spread.fs @@ -0,0 +1,5 @@ +let r1 = {| A = 1 ; B = 2 |} +let r2 = {| C = 3; D = 4 |} + +let r3 : {| A : int ; B : int; C : int; D : int |} = {| ...r1; ...r2 |} +let r4 : {| A : int ; B : int; C : int; D : int |} = {| ...r2; ...r3 |} diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_NoOverlap_Spread_Spread.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_NoOverlap_Spread_Spread.fs.il.bsl new file mode 100644 index 00000000000..1955f2c27c4 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_NoOverlap_Spread_Spread.fs.il.bsl @@ -0,0 +1,1673 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .field static assembly class '<>f__AnonymousType1261546922`2' r1@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 class '<>f__AnonymousType2413989789`2' r2@2 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly class '<>f__AnonymousType1583142996`4' r3@4 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly class '<>f__AnonymousType1583142996`4' r4@5 + .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 '<>f__AnonymousType1261546922`2' get_r1() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class '<>f__AnonymousType1261546922`2' assembly::r1@1 + IL_0005: ret + } + + .method public specialname static class '<>f__AnonymousType2413989789`2' get_r2() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class '<>f__AnonymousType2413989789`2' assembly::r2@2 + IL_0005: ret + } + + .method public specialname static class '<>f__AnonymousType1583142996`4' get_r3() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class '<>f__AnonymousType1583142996`4' assembly::r3@4 + IL_0005: ret + } + + .method public specialname static class '<>f__AnonymousType1583142996`4' get_r4() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class '<>f__AnonymousType1583142996`4' assembly::r4@5 + IL_0005: ret + } + + .method private specialname rtspecialname static void .cctor() cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.0 + IL_0001: stsfld int32 ''.$assembly::init@ + IL_0006: ldsfld int32 ''.$assembly::init@ + IL_000b: pop + IL_000c: ret + } + + .method assembly static void staticInitialization@() cil managed + { + + .maxstack 6 + IL_0000: ldc.i4.1 + IL_0001: ldc.i4.2 + IL_0002: newobj instance void class '<>f__AnonymousType1261546922`2'::.ctor(!0, + !1) + IL_0007: stsfld class '<>f__AnonymousType1261546922`2' assembly::r1@1 + IL_000c: ldc.i4.3 + IL_000d: ldc.i4.4 + IL_000e: newobj instance void class '<>f__AnonymousType2413989789`2'::.ctor(!0, + !1) + IL_0013: stsfld class '<>f__AnonymousType2413989789`2' assembly::r2@2 + IL_0018: call class '<>f__AnonymousType1261546922`2' assembly::get_r1() + IL_001d: call instance !0 class '<>f__AnonymousType1261546922`2'::get_A() + IL_0022: call class '<>f__AnonymousType1261546922`2' assembly::get_r1() + IL_0027: call instance !1 class '<>f__AnonymousType1261546922`2'::get_B() + IL_002c: call class '<>f__AnonymousType2413989789`2' assembly::get_r2() + IL_0031: call instance !0 class '<>f__AnonymousType2413989789`2'::get_C() + IL_0036: call class '<>f__AnonymousType2413989789`2' assembly::get_r2() + IL_003b: call instance !1 class '<>f__AnonymousType2413989789`2'::get_D() + IL_0040: newobj instance void class '<>f__AnonymousType1583142996`4'::.ctor(!0, + !1, + !2, + !3) + IL_0045: stsfld class '<>f__AnonymousType1583142996`4' assembly::r3@4 + IL_004a: call class '<>f__AnonymousType1583142996`4' assembly::get_r3() + IL_004f: call instance !0 class '<>f__AnonymousType1583142996`4'::get_A() + IL_0054: call class '<>f__AnonymousType1583142996`4' assembly::get_r3() + IL_0059: call instance !1 class '<>f__AnonymousType1583142996`4'::get_B() + IL_005e: call class '<>f__AnonymousType1583142996`4' assembly::get_r3() + IL_0063: call instance !2 class '<>f__AnonymousType1583142996`4'::get_C() + IL_0068: call class '<>f__AnonymousType1583142996`4' assembly::get_r3() + IL_006d: call instance !3 class '<>f__AnonymousType1583142996`4'::get_D() + IL_0072: newobj instance void class '<>f__AnonymousType1583142996`4'::.ctor(!0, + !1, + !2, + !3) + IL_0077: stsfld class '<>f__AnonymousType1583142996`4' assembly::r4@5 + IL_007c: ret + } + + .property class '<>f__AnonymousType1261546922`2' + r1() + { + .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 class '<>f__AnonymousType1261546922`2' assembly::get_r1() + } + .property class '<>f__AnonymousType2413989789`2' + r2() + { + .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 class '<>f__AnonymousType2413989789`2' assembly::get_r2() + } + .property class '<>f__AnonymousType1583142996`4' + r3() + { + .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 class '<>f__AnonymousType1583142996`4' assembly::get_r3() + } + .property class '<>f__AnonymousType1583142996`4' + r4() + { + .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 class '<>f__AnonymousType1583142996`4' assembly::get_r4() + } +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .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 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: call void assembly::staticInitialization@() + IL_0005: ret + } + +} + +.class public auto ansi serializable sealed beforefieldinit '<>f__AnonymousType1261546922`2'<'j__TPar','j__TPar'> + extends [runtime]System.Object + implements [runtime]System.Collections.IStructuralComparable, + [runtime]System.IComparable, + class [runtime]System.IComparable`1f__AnonymousType1261546922`2'j__TPar',!'j__TPar'>>, + [runtime]System.Collections.IStructuralEquatable, + class [runtime]System.IEquatable`1f__AnonymousType1261546922`2'j__TPar',!'j__TPar'>> +{ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field private !'j__TPar' A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field private !'j__TPar' B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor(!'j__TPar' A, !'j__TPar' B) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 1E 3C 3E 66 5F 5F 41 6E 6F 6E + 79 6D 6F 75 73 54 79 70 65 31 32 36 31 35 34 36 + 39 32 32 60 32 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld !0 class '<>f__AnonymousType1261546922`2'j__TPar',!'j__TPar'>::A@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld !1 class '<>f__AnonymousType1261546922`2'j__TPar',!'j__TPar'>::B@ + IL_0014: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_A() 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: ldfld !0 class '<>f__AnonymousType1261546922`2'j__TPar',!'j__TPar'>::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_B() 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: ldfld !1 class '<>f__AnonymousType1261546922`2'j__TPar',!'j__TPar'>::B@ + IL_0006: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5f__AnonymousType1261546922`2'j__TPar',!'j__TPar'>,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class '<>f__AnonymousType1261546922`2'j__TPar',!'j__TPar'>>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToStringf__AnonymousType1261546922`2'j__TPar',!'j__TPar'>,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2f__AnonymousType1261546922`2'j__TPar',!'j__TPar'>,string>::Invoke(!0) + IL_0015: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(class '<>f__AnonymousType1261546922`2'j__TPar',!'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0044 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0042 + + IL_0006: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_000b: ldarg.0 + IL_000c: ldfld !0 class '<>f__AnonymousType1261546922`2'j__TPar',!'j__TPar'>::A@ + IL_0011: ldarg.1 + IL_0012: ldfld !0 class '<>f__AnonymousType1261546922`2'j__TPar',!'j__TPar'>::A@ + IL_0017: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_001c: stloc.0 + IL_001d: ldloc.0 + IL_001e: ldc.i4.0 + IL_001f: bge.s IL_0023 + + IL_0021: ldloc.0 + IL_0022: ret + + IL_0023: ldloc.0 + IL_0024: ldc.i4.0 + IL_0025: ble.s IL_0029 + + IL_0027: ldloc.0 + IL_0028: ret + + IL_0029: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_002e: ldarg.0 + IL_002f: ldfld !1 class '<>f__AnonymousType1261546922`2'j__TPar',!'j__TPar'>::B@ + IL_0034: ldarg.1 + IL_0035: ldfld !1 class '<>f__AnonymousType1261546922`2'j__TPar',!'j__TPar'>::B@ + IL_003a: tail. + IL_003c: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0041: ret + + IL_0042: ldc.i4.1 + IL_0043: ret + + IL_0044: ldarg.1 + IL_0045: brfalse.s IL_0049 + + IL_0047: ldc.i4.m1 + IL_0048: ret + + IL_0049: ldc.i4.0 + IL_004a: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: unbox.any class '<>f__AnonymousType1261546922`2'j__TPar',!'j__TPar'> + IL_0007: tail. + IL_0009: callvirt instance int32 class '<>f__AnonymousType1261546922`2'j__TPar',!'j__TPar'>::CompareTo(class '<>f__AnonymousType1261546922`2') + IL_000e: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj, class [runtime]System.Collections.IComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType1261546922`2'j__TPar',!'j__TPar'> V_0, + class '<>f__AnonymousType1261546922`2'j__TPar',!'j__TPar'> V_1, + int32 V_2) + IL_0000: ldarg.1 + IL_0001: unbox.any class '<>f__AnonymousType1261546922`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: stloc.1 + IL_0009: ldarg.0 + IL_000a: brfalse.s IL_004a + + IL_000c: ldarg.1 + IL_000d: unbox.any class '<>f__AnonymousType1261546922`2'j__TPar',!'j__TPar'> + IL_0012: brfalse.s IL_0048 + + IL_0014: ldarg.2 + IL_0015: ldarg.0 + IL_0016: ldfld !0 class '<>f__AnonymousType1261546922`2'j__TPar',!'j__TPar'>::A@ + IL_001b: ldloc.1 + IL_001c: ldfld !0 class '<>f__AnonymousType1261546922`2'j__TPar',!'j__TPar'>::A@ + IL_0021: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0026: stloc.2 + IL_0027: ldloc.2 + IL_0028: ldc.i4.0 + IL_0029: bge.s IL_002d + + IL_002b: ldloc.2 + IL_002c: ret + + IL_002d: ldloc.2 + IL_002e: ldc.i4.0 + IL_002f: ble.s IL_0033 + + IL_0031: ldloc.2 + IL_0032: ret + + IL_0033: ldarg.2 + IL_0034: ldarg.0 + IL_0035: ldfld !1 class '<>f__AnonymousType1261546922`2'j__TPar',!'j__TPar'>::B@ + IL_003a: ldloc.1 + IL_003b: ldfld !1 class '<>f__AnonymousType1261546922`2'j__TPar',!'j__TPar'>::B@ + IL_0040: tail. + IL_0042: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0047: ret + + IL_0048: ldc.i4.1 + IL_0049: ret + + IL_004a: ldarg.1 + IL_004b: unbox.any class '<>f__AnonymousType1261546922`2'j__TPar',!'j__TPar'> + IL_0050: brfalse.s IL_0054 + + IL_0052: ldc.i4.m1 + IL_0053: ret + + IL_0054: ldc.i4.0 + IL_0055: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode(class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 7 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_003d + + IL_0003: ldc.i4.0 + IL_0004: stloc.0 + IL_0005: ldc.i4 0x9e3779b9 + IL_000a: ldarg.1 + IL_000b: ldarg.0 + IL_000c: ldfld !1 class '<>f__AnonymousType1261546922`2'j__TPar',!'j__TPar'>::B@ + IL_0011: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0016: ldloc.0 + IL_0017: ldc.i4.6 + IL_0018: shl + IL_0019: ldloc.0 + IL_001a: ldc.i4.2 + IL_001b: shr + IL_001c: add + IL_001d: add + IL_001e: add + IL_001f: stloc.0 + IL_0020: ldc.i4 0x9e3779b9 + IL_0025: ldarg.1 + IL_0026: ldarg.0 + IL_0027: ldfld !0 class '<>f__AnonymousType1261546922`2'j__TPar',!'j__TPar'>::A@ + IL_002c: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0031: ldloc.0 + IL_0032: ldc.i4.6 + IL_0033: shl + IL_0034: ldloc.0 + IL_0035: ldc.i4.2 + IL_0036: shr + IL_0037: add + IL_0038: add + IL_0039: add + IL_003a: stloc.0 + IL_003b: ldloc.0 + IL_003c: ret + + IL_003d: ldc.i4.0 + IL_003e: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() + IL_0006: tail. + IL_0008: callvirt instance int32 class '<>f__AnonymousType1261546922`2'j__TPar',!'j__TPar'>::GetHashCode(class [runtime]System.Collections.IEqualityComparer) + IL_000d: ret + } + + .method public hidebysig instance bool Equals(class '<>f__AnonymousType1261546922`2'j__TPar',!'j__TPar'> obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType1261546922`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0035 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0033 + + IL_0006: ldarg.1 + IL_0007: stloc.0 + IL_0008: ldarg.2 + IL_0009: ldarg.0 + IL_000a: ldfld !0 class '<>f__AnonymousType1261546922`2'j__TPar',!'j__TPar'>::A@ + IL_000f: ldloc.0 + IL_0010: ldfld !0 class '<>f__AnonymousType1261546922`2'j__TPar',!'j__TPar'>::A@ + IL_0015: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_001a: brfalse.s IL_0031 + + IL_001c: ldarg.2 + IL_001d: ldarg.0 + IL_001e: ldfld !1 class '<>f__AnonymousType1261546922`2'j__TPar',!'j__TPar'>::B@ + IL_0023: ldloc.0 + IL_0024: ldfld !1 class '<>f__AnonymousType1261546922`2'j__TPar',!'j__TPar'>::B@ + IL_0029: tail. + IL_002b: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_0030: ret + + IL_0031: ldc.i4.0 + IL_0032: ret + + IL_0033: ldc.i4.0 + IL_0034: ret + + IL_0035: ldarg.1 + IL_0036: ldnull + IL_0037: cgt.un + IL_0039: ldc.i4.0 + IL_003a: ceq + IL_003c: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType1261546922`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType1261546922`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0015 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: ldarg.2 + IL_000d: tail. + IL_000f: callvirt instance bool class '<>f__AnonymousType1261546922`2'j__TPar',!'j__TPar'>::Equals(class '<>f__AnonymousType1261546922`2', + class [runtime]System.Collections.IEqualityComparer) + IL_0014: ret + + IL_0015: ldc.i4.0 + IL_0016: ret + } + + .method public hidebysig virtual final instance bool Equals(class '<>f__AnonymousType1261546922`2'j__TPar',!'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0031 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_002f + + IL_0006: ldarg.0 + IL_0007: ldfld !0 class '<>f__AnonymousType1261546922`2'j__TPar',!'j__TPar'>::A@ + IL_000c: ldarg.1 + IL_000d: ldfld !0 class '<>f__AnonymousType1261546922`2'j__TPar',!'j__TPar'>::A@ + IL_0012: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_0017: brfalse.s IL_002d + + IL_0019: ldarg.0 + IL_001a: ldfld !1 class '<>f__AnonymousType1261546922`2'j__TPar',!'j__TPar'>::B@ + IL_001f: ldarg.1 + IL_0020: ldfld !1 class '<>f__AnonymousType1261546922`2'j__TPar',!'j__TPar'>::B@ + IL_0025: tail. + IL_0027: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_002c: ret + + IL_002d: ldc.i4.0 + IL_002e: ret + + IL_002f: ldc.i4.0 + IL_0030: ret + + IL_0031: ldarg.1 + IL_0032: ldnull + IL_0033: cgt.un + IL_0035: ldc.i4.0 + IL_0036: ceq + IL_0038: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (class '<>f__AnonymousType1261546922`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType1261546922`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0014 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: tail. + IL_000e: callvirt instance bool class '<>f__AnonymousType1261546922`2'j__TPar',!'j__TPar'>::Equals(class '<>f__AnonymousType1261546922`2') + IL_0013: ret + + IL_0014: ldc.i4.0 + IL_0015: ret + } + + .property instance !'j__TPar' A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType1261546922`2'::get_A() + } + .property instance !'j__TPar' B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType1261546922`2'::get_B() + } +} + +.class public auto ansi serializable sealed beforefieldinit '<>f__AnonymousType1583142996`4'<'j__TPar','j__TPar','j__TPar','j__TPar'> + extends [runtime]System.Object + implements [runtime]System.Collections.IStructuralComparable, + [runtime]System.IComparable, + class [runtime]System.IComparable`1f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>>, + [runtime]System.Collections.IStructuralEquatable, + class [runtime]System.IEquatable`1f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>> +{ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field private !'j__TPar' A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field private !'j__TPar' B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field private !'j__TPar' C@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field private !'j__TPar' D@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public specialname rtspecialname + instance void .ctor(!'j__TPar' A, + !'j__TPar' B, + !'j__TPar' C, + !'j__TPar' D) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 1E 3C 3E 66 5F 5F 41 6E 6F 6E + 79 6D 6F 75 73 54 79 70 65 31 35 38 33 31 34 32 + 39 39 36 60 34 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld !0 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::A@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld !1 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::B@ + IL_0014: ldarg.0 + IL_0015: ldarg.3 + IL_0016: stfld !2 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::C@ + IL_001b: ldarg.0 + IL_001c: ldarg.s D + IL_001e: stfld !3 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::D@ + IL_0023: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_A() 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: ldfld !0 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_B() 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: ldfld !1 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::B@ + IL_0006: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_C() 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: ldfld !2 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::C@ + IL_0006: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_D() 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: ldfld !3 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::D@ + IL_0006: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToStringf__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>,string>::Invoke(!0) + IL_0015: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (int32 V_0, + int32 V_1, + int32 V_2) + IL_0000: ldarg.0 + IL_0001: brfalse IL_0090 + + IL_0006: ldarg.1 + IL_0007: brfalse IL_008e + + IL_000c: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_0011: ldarg.0 + IL_0012: ldfld !0 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::A@ + IL_0017: ldarg.1 + IL_0018: ldfld !0 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::A@ + IL_001d: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0022: stloc.0 + IL_0023: ldloc.0 + IL_0024: ldc.i4.0 + IL_0025: bge.s IL_0029 + + IL_0027: ldloc.0 + IL_0028: ret + + IL_0029: ldloc.0 + IL_002a: ldc.i4.0 + IL_002b: ble.s IL_002f + + IL_002d: ldloc.0 + IL_002e: ret + + IL_002f: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_0034: ldarg.0 + IL_0035: ldfld !1 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::B@ + IL_003a: ldarg.1 + IL_003b: ldfld !1 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::B@ + IL_0040: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0045: stloc.1 + IL_0046: ldloc.1 + IL_0047: ldc.i4.0 + IL_0048: bge.s IL_004c + + IL_004a: ldloc.1 + IL_004b: ret + + IL_004c: ldloc.1 + IL_004d: ldc.i4.0 + IL_004e: ble.s IL_0052 + + IL_0050: ldloc.1 + IL_0051: ret + + IL_0052: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_0057: ldarg.0 + IL_0058: ldfld !2 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::C@ + IL_005d: ldarg.1 + IL_005e: ldfld !2 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::C@ + IL_0063: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0068: stloc.2 + IL_0069: ldloc.2 + IL_006a: ldc.i4.0 + IL_006b: bge.s IL_006f + + IL_006d: ldloc.2 + IL_006e: ret + + IL_006f: ldloc.2 + IL_0070: ldc.i4.0 + IL_0071: ble.s IL_0075 + + IL_0073: ldloc.2 + IL_0074: ret + + IL_0075: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_007a: ldarg.0 + IL_007b: ldfld !3 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::D@ + IL_0080: ldarg.1 + IL_0081: ldfld !3 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::D@ + IL_0086: tail. + IL_0088: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_008d: ret + + IL_008e: ldc.i4.1 + IL_008f: ret + + IL_0090: ldarg.1 + IL_0091: brfalse.s IL_0095 + + IL_0093: ldc.i4.m1 + IL_0094: ret + + IL_0095: ldc.i4.0 + IL_0096: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: unbox.any class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'> + IL_0007: tail. + IL_0009: callvirt instance int32 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::CompareTo(class '<>f__AnonymousType1583142996`4') + IL_000e: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj, class [runtime]System.Collections.IComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'> V_0, + class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'> V_1, + int32 V_2, + int32 V_3, + int32 V_4) + IL_0000: ldarg.1 + IL_0001: unbox.any class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: stloc.1 + IL_0009: ldarg.0 + IL_000a: brfalse IL_0093 + + IL_000f: ldarg.1 + IL_0010: unbox.any class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'> + IL_0015: brfalse IL_0091 + + IL_001a: ldarg.2 + IL_001b: ldarg.0 + IL_001c: ldfld !0 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::A@ + IL_0021: ldloc.1 + IL_0022: ldfld !0 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::A@ + IL_0027: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_002c: stloc.2 + IL_002d: ldloc.2 + IL_002e: ldc.i4.0 + IL_002f: bge.s IL_0033 + + IL_0031: ldloc.2 + IL_0032: ret + + IL_0033: ldloc.2 + IL_0034: ldc.i4.0 + IL_0035: ble.s IL_0039 + + IL_0037: ldloc.2 + IL_0038: ret + + IL_0039: ldarg.2 + IL_003a: ldarg.0 + IL_003b: ldfld !1 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::B@ + IL_0040: ldloc.1 + IL_0041: ldfld !1 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::B@ + IL_0046: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_004b: stloc.3 + IL_004c: ldloc.3 + IL_004d: ldc.i4.0 + IL_004e: bge.s IL_0052 + + IL_0050: ldloc.3 + IL_0051: ret + + IL_0052: ldloc.3 + IL_0053: ldc.i4.0 + IL_0054: ble.s IL_0058 + + IL_0056: ldloc.3 + IL_0057: ret + + IL_0058: ldarg.2 + IL_0059: ldarg.0 + IL_005a: ldfld !2 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::C@ + IL_005f: ldloc.1 + IL_0060: ldfld !2 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::C@ + IL_0065: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_006a: stloc.s V_4 + IL_006c: ldloc.s V_4 + IL_006e: ldc.i4.0 + IL_006f: bge.s IL_0074 + + IL_0071: ldloc.s V_4 + IL_0073: ret + + IL_0074: ldloc.s V_4 + IL_0076: ldc.i4.0 + IL_0077: ble.s IL_007c + + IL_0079: ldloc.s V_4 + IL_007b: ret + + IL_007c: ldarg.2 + IL_007d: ldarg.0 + IL_007e: ldfld !3 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::D@ + IL_0083: ldloc.1 + IL_0084: ldfld !3 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::D@ + IL_0089: tail. + IL_008b: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0090: ret + + IL_0091: ldc.i4.1 + IL_0092: ret + + IL_0093: ldarg.1 + IL_0094: unbox.any class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'> + IL_0099: brfalse.s IL_009d + + IL_009b: ldc.i4.m1 + IL_009c: ret + + IL_009d: ldc.i4.0 + IL_009e: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode(class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 7 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0073 + + IL_0003: ldc.i4.0 + IL_0004: stloc.0 + IL_0005: ldc.i4 0x9e3779b9 + IL_000a: ldarg.1 + IL_000b: ldarg.0 + IL_000c: ldfld !3 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::D@ + IL_0011: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0016: ldloc.0 + IL_0017: ldc.i4.6 + IL_0018: shl + IL_0019: ldloc.0 + IL_001a: ldc.i4.2 + IL_001b: shr + IL_001c: add + IL_001d: add + IL_001e: add + IL_001f: stloc.0 + IL_0020: ldc.i4 0x9e3779b9 + IL_0025: ldarg.1 + IL_0026: ldarg.0 + IL_0027: ldfld !2 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::C@ + IL_002c: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0031: ldloc.0 + IL_0032: ldc.i4.6 + IL_0033: shl + IL_0034: ldloc.0 + IL_0035: ldc.i4.2 + IL_0036: shr + IL_0037: add + IL_0038: add + IL_0039: add + IL_003a: stloc.0 + IL_003b: ldc.i4 0x9e3779b9 + IL_0040: ldarg.1 + IL_0041: ldarg.0 + IL_0042: ldfld !1 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::B@ + IL_0047: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_004c: ldloc.0 + IL_004d: ldc.i4.6 + IL_004e: shl + IL_004f: ldloc.0 + IL_0050: ldc.i4.2 + IL_0051: shr + IL_0052: add + IL_0053: add + IL_0054: add + IL_0055: stloc.0 + IL_0056: ldc.i4 0x9e3779b9 + IL_005b: ldarg.1 + IL_005c: ldarg.0 + IL_005d: ldfld !0 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::A@ + IL_0062: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0067: ldloc.0 + IL_0068: ldc.i4.6 + IL_0069: shl + IL_006a: ldloc.0 + IL_006b: ldc.i4.2 + IL_006c: shr + IL_006d: add + IL_006e: add + IL_006f: add + IL_0070: stloc.0 + IL_0071: ldloc.0 + IL_0072: ret + + IL_0073: ldc.i4.0 + IL_0074: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() + IL_0006: tail. + IL_0008: callvirt instance int32 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::GetHashCode(class [runtime]System.Collections.IEqualityComparer) + IL_000d: ret + } + + .method public hidebysig instance bool Equals(class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'> obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0061 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_005f + + IL_0006: ldarg.1 + IL_0007: stloc.0 + IL_0008: ldarg.2 + IL_0009: ldarg.0 + IL_000a: ldfld !0 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::A@ + IL_000f: ldloc.0 + IL_0010: ldfld !0 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::A@ + IL_0015: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_001a: brfalse.s IL_005d + + IL_001c: ldarg.2 + IL_001d: ldarg.0 + IL_001e: ldfld !1 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::B@ + IL_0023: ldloc.0 + IL_0024: ldfld !1 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::B@ + IL_0029: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_002e: brfalse.s IL_005b + + IL_0030: ldarg.2 + IL_0031: ldarg.0 + IL_0032: ldfld !2 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::C@ + IL_0037: ldloc.0 + IL_0038: ldfld !2 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::C@ + IL_003d: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_0042: brfalse.s IL_0059 + + IL_0044: ldarg.2 + IL_0045: ldarg.0 + IL_0046: ldfld !3 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::D@ + IL_004b: ldloc.0 + IL_004c: ldfld !3 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::D@ + IL_0051: tail. + IL_0053: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_0058: ret + + IL_0059: ldc.i4.0 + IL_005a: ret + + IL_005b: ldc.i4.0 + IL_005c: ret + + IL_005d: ldc.i4.0 + IL_005e: ret + + IL_005f: ldc.i4.0 + IL_0060: ret + + IL_0061: ldarg.1 + IL_0062: ldnull + IL_0063: cgt.un + IL_0065: ldc.i4.0 + IL_0066: ceq + IL_0068: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0015 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: ldarg.2 + IL_000d: tail. + IL_000f: callvirt instance bool class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::Equals(class '<>f__AnonymousType1583142996`4', + class [runtime]System.Collections.IEqualityComparer) + IL_0014: ret + + IL_0015: ldc.i4.0 + IL_0016: ret + } + + .method public hidebysig virtual final instance bool Equals(class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_005b + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0059 + + IL_0006: ldarg.0 + IL_0007: ldfld !0 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::A@ + IL_000c: ldarg.1 + IL_000d: ldfld !0 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::A@ + IL_0012: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_0017: brfalse.s IL_0057 + + IL_0019: ldarg.0 + IL_001a: ldfld !1 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::B@ + IL_001f: ldarg.1 + IL_0020: ldfld !1 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::B@ + IL_0025: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_002a: brfalse.s IL_0055 + + IL_002c: ldarg.0 + IL_002d: ldfld !2 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::C@ + IL_0032: ldarg.1 + IL_0033: ldfld !2 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::C@ + IL_0038: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_003d: brfalse.s IL_0053 + + IL_003f: ldarg.0 + IL_0040: ldfld !3 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::D@ + IL_0045: ldarg.1 + IL_0046: ldfld !3 class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::D@ + IL_004b: tail. + IL_004d: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_0052: ret + + IL_0053: ldc.i4.0 + IL_0054: ret + + IL_0055: ldc.i4.0 + IL_0056: ret + + IL_0057: ldc.i4.0 + IL_0058: ret + + IL_0059: ldc.i4.0 + IL_005a: ret + + IL_005b: ldarg.1 + IL_005c: ldnull + IL_005d: cgt.un + IL_005f: ldc.i4.0 + IL_0060: ceq + IL_0062: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0014 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: tail. + IL_000e: callvirt instance bool class '<>f__AnonymousType1583142996`4'j__TPar',!'j__TPar',!'j__TPar',!'j__TPar'>::Equals(class '<>f__AnonymousType1583142996`4') + IL_0013: ret + + IL_0014: ldc.i4.0 + IL_0015: ret + } + + .property instance !'j__TPar' A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType1583142996`4'::get_A() + } + .property instance !'j__TPar' B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType1583142996`4'::get_B() + } + .property instance !'j__TPar' C() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 02 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType1583142996`4'::get_C() + } + .property instance !'j__TPar' D() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 03 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType1583142996`4'::get_D() + } +} + +.class public auto ansi serializable sealed beforefieldinit '<>f__AnonymousType2413989789`2'<'j__TPar','j__TPar'> + extends [runtime]System.Object + implements [runtime]System.Collections.IStructuralComparable, + [runtime]System.IComparable, + class [runtime]System.IComparable`1f__AnonymousType2413989789`2'j__TPar',!'j__TPar'>>, + [runtime]System.Collections.IStructuralEquatable, + class [runtime]System.IEquatable`1f__AnonymousType2413989789`2'j__TPar',!'j__TPar'>> +{ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field private !'j__TPar' C@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field private !'j__TPar' D@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor(!'j__TPar' C, !'j__TPar' D) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 1E 3C 3E 66 5F 5F 41 6E 6F 6E + 79 6D 6F 75 73 54 79 70 65 32 34 31 33 39 38 39 + 37 38 39 60 32 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld !0 class '<>f__AnonymousType2413989789`2'j__TPar',!'j__TPar'>::C@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld !1 class '<>f__AnonymousType2413989789`2'j__TPar',!'j__TPar'>::D@ + IL_0014: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_C() 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: ldfld !0 class '<>f__AnonymousType2413989789`2'j__TPar',!'j__TPar'>::C@ + IL_0006: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_D() 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: ldfld !1 class '<>f__AnonymousType2413989789`2'j__TPar',!'j__TPar'>::D@ + IL_0006: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5f__AnonymousType2413989789`2'j__TPar',!'j__TPar'>,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class '<>f__AnonymousType2413989789`2'j__TPar',!'j__TPar'>>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToStringf__AnonymousType2413989789`2'j__TPar',!'j__TPar'>,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2f__AnonymousType2413989789`2'j__TPar',!'j__TPar'>,string>::Invoke(!0) + IL_0015: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(class '<>f__AnonymousType2413989789`2'j__TPar',!'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0044 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0042 + + IL_0006: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_000b: ldarg.0 + IL_000c: ldfld !0 class '<>f__AnonymousType2413989789`2'j__TPar',!'j__TPar'>::C@ + IL_0011: ldarg.1 + IL_0012: ldfld !0 class '<>f__AnonymousType2413989789`2'j__TPar',!'j__TPar'>::C@ + IL_0017: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_001c: stloc.0 + IL_001d: ldloc.0 + IL_001e: ldc.i4.0 + IL_001f: bge.s IL_0023 + + IL_0021: ldloc.0 + IL_0022: ret + + IL_0023: ldloc.0 + IL_0024: ldc.i4.0 + IL_0025: ble.s IL_0029 + + IL_0027: ldloc.0 + IL_0028: ret + + IL_0029: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_002e: ldarg.0 + IL_002f: ldfld !1 class '<>f__AnonymousType2413989789`2'j__TPar',!'j__TPar'>::D@ + IL_0034: ldarg.1 + IL_0035: ldfld !1 class '<>f__AnonymousType2413989789`2'j__TPar',!'j__TPar'>::D@ + IL_003a: tail. + IL_003c: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0041: ret + + IL_0042: ldc.i4.1 + IL_0043: ret + + IL_0044: ldarg.1 + IL_0045: brfalse.s IL_0049 + + IL_0047: ldc.i4.m1 + IL_0048: ret + + IL_0049: ldc.i4.0 + IL_004a: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: unbox.any class '<>f__AnonymousType2413989789`2'j__TPar',!'j__TPar'> + IL_0007: tail. + IL_0009: callvirt instance int32 class '<>f__AnonymousType2413989789`2'j__TPar',!'j__TPar'>::CompareTo(class '<>f__AnonymousType2413989789`2') + IL_000e: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj, class [runtime]System.Collections.IComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType2413989789`2'j__TPar',!'j__TPar'> V_0, + class '<>f__AnonymousType2413989789`2'j__TPar',!'j__TPar'> V_1, + int32 V_2) + IL_0000: ldarg.1 + IL_0001: unbox.any class '<>f__AnonymousType2413989789`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: stloc.1 + IL_0009: ldarg.0 + IL_000a: brfalse.s IL_004a + + IL_000c: ldarg.1 + IL_000d: unbox.any class '<>f__AnonymousType2413989789`2'j__TPar',!'j__TPar'> + IL_0012: brfalse.s IL_0048 + + IL_0014: ldarg.2 + IL_0015: ldarg.0 + IL_0016: ldfld !0 class '<>f__AnonymousType2413989789`2'j__TPar',!'j__TPar'>::C@ + IL_001b: ldloc.1 + IL_001c: ldfld !0 class '<>f__AnonymousType2413989789`2'j__TPar',!'j__TPar'>::C@ + IL_0021: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0026: stloc.2 + IL_0027: ldloc.2 + IL_0028: ldc.i4.0 + IL_0029: bge.s IL_002d + + IL_002b: ldloc.2 + IL_002c: ret + + IL_002d: ldloc.2 + IL_002e: ldc.i4.0 + IL_002f: ble.s IL_0033 + + IL_0031: ldloc.2 + IL_0032: ret + + IL_0033: ldarg.2 + IL_0034: ldarg.0 + IL_0035: ldfld !1 class '<>f__AnonymousType2413989789`2'j__TPar',!'j__TPar'>::D@ + IL_003a: ldloc.1 + IL_003b: ldfld !1 class '<>f__AnonymousType2413989789`2'j__TPar',!'j__TPar'>::D@ + IL_0040: tail. + IL_0042: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0047: ret + + IL_0048: ldc.i4.1 + IL_0049: ret + + IL_004a: ldarg.1 + IL_004b: unbox.any class '<>f__AnonymousType2413989789`2'j__TPar',!'j__TPar'> + IL_0050: brfalse.s IL_0054 + + IL_0052: ldc.i4.m1 + IL_0053: ret + + IL_0054: ldc.i4.0 + IL_0055: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode(class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 7 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_003d + + IL_0003: ldc.i4.0 + IL_0004: stloc.0 + IL_0005: ldc.i4 0x9e3779b9 + IL_000a: ldarg.1 + IL_000b: ldarg.0 + IL_000c: ldfld !1 class '<>f__AnonymousType2413989789`2'j__TPar',!'j__TPar'>::D@ + IL_0011: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0016: ldloc.0 + IL_0017: ldc.i4.6 + IL_0018: shl + IL_0019: ldloc.0 + IL_001a: ldc.i4.2 + IL_001b: shr + IL_001c: add + IL_001d: add + IL_001e: add + IL_001f: stloc.0 + IL_0020: ldc.i4 0x9e3779b9 + IL_0025: ldarg.1 + IL_0026: ldarg.0 + IL_0027: ldfld !0 class '<>f__AnonymousType2413989789`2'j__TPar',!'j__TPar'>::C@ + IL_002c: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0031: ldloc.0 + IL_0032: ldc.i4.6 + IL_0033: shl + IL_0034: ldloc.0 + IL_0035: ldc.i4.2 + IL_0036: shr + IL_0037: add + IL_0038: add + IL_0039: add + IL_003a: stloc.0 + IL_003b: ldloc.0 + IL_003c: ret + + IL_003d: ldc.i4.0 + IL_003e: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() + IL_0006: tail. + IL_0008: callvirt instance int32 class '<>f__AnonymousType2413989789`2'j__TPar',!'j__TPar'>::GetHashCode(class [runtime]System.Collections.IEqualityComparer) + IL_000d: ret + } + + .method public hidebysig instance bool Equals(class '<>f__AnonymousType2413989789`2'j__TPar',!'j__TPar'> obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType2413989789`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0035 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0033 + + IL_0006: ldarg.1 + IL_0007: stloc.0 + IL_0008: ldarg.2 + IL_0009: ldarg.0 + IL_000a: ldfld !0 class '<>f__AnonymousType2413989789`2'j__TPar',!'j__TPar'>::C@ + IL_000f: ldloc.0 + IL_0010: ldfld !0 class '<>f__AnonymousType2413989789`2'j__TPar',!'j__TPar'>::C@ + IL_0015: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_001a: brfalse.s IL_0031 + + IL_001c: ldarg.2 + IL_001d: ldarg.0 + IL_001e: ldfld !1 class '<>f__AnonymousType2413989789`2'j__TPar',!'j__TPar'>::D@ + IL_0023: ldloc.0 + IL_0024: ldfld !1 class '<>f__AnonymousType2413989789`2'j__TPar',!'j__TPar'>::D@ + IL_0029: tail. + IL_002b: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_0030: ret + + IL_0031: ldc.i4.0 + IL_0032: ret + + IL_0033: ldc.i4.0 + IL_0034: ret + + IL_0035: ldarg.1 + IL_0036: ldnull + IL_0037: cgt.un + IL_0039: ldc.i4.0 + IL_003a: ceq + IL_003c: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType2413989789`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType2413989789`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0015 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: ldarg.2 + IL_000d: tail. + IL_000f: callvirt instance bool class '<>f__AnonymousType2413989789`2'j__TPar',!'j__TPar'>::Equals(class '<>f__AnonymousType2413989789`2', + class [runtime]System.Collections.IEqualityComparer) + IL_0014: ret + + IL_0015: ldc.i4.0 + IL_0016: ret + } + + .method public hidebysig virtual final instance bool Equals(class '<>f__AnonymousType2413989789`2'j__TPar',!'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0031 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_002f + + IL_0006: ldarg.0 + IL_0007: ldfld !0 class '<>f__AnonymousType2413989789`2'j__TPar',!'j__TPar'>::C@ + IL_000c: ldarg.1 + IL_000d: ldfld !0 class '<>f__AnonymousType2413989789`2'j__TPar',!'j__TPar'>::C@ + IL_0012: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_0017: brfalse.s IL_002d + + IL_0019: ldarg.0 + IL_001a: ldfld !1 class '<>f__AnonymousType2413989789`2'j__TPar',!'j__TPar'>::D@ + IL_001f: ldarg.1 + IL_0020: ldfld !1 class '<>f__AnonymousType2413989789`2'j__TPar',!'j__TPar'>::D@ + IL_0025: tail. + IL_0027: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_002c: ret + + IL_002d: ldc.i4.0 + IL_002e: ret + + IL_002f: ldc.i4.0 + IL_0030: ret + + IL_0031: ldarg.1 + IL_0032: ldnull + IL_0033: cgt.un + IL_0035: ldc.i4.0 + IL_0036: ceq + IL_0038: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (class '<>f__AnonymousType2413989789`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType2413989789`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0014 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: tail. + IL_000e: callvirt instance bool class '<>f__AnonymousType2413989789`2'j__TPar',!'j__TPar'>::Equals(class '<>f__AnonymousType2413989789`2') + IL_0013: ret + + IL_0014: ldc.i4.0 + IL_0015: ret + } + + .property instance !'j__TPar' C() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType2413989789`2'::get_C() + } + .property instance !'j__TPar' D() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType2413989789`2'::get_D() + } +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_SpreadShadowsExplicit.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_SpreadShadowsExplicit.fs new file mode 100644 index 00000000000..d9675cc1eb8 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_SpreadShadowsExplicit.fs @@ -0,0 +1,3 @@ +let r1 = {| A = 1; B = 2 |} + +let r2 : {| A : int; B : int |} = {| A = "A"; ...r1 |} diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_SpreadShadowsExplicit.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_SpreadShadowsExplicit.fs.il.bsl new file mode 100644 index 00000000000..5982c4ae1ff --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_SpreadShadowsExplicit.fs.il.bsl @@ -0,0 +1,545 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .field static assembly class '<>f__AnonymousType1861640520`2' r1@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 class '<>f__AnonymousType1861640520`2' r2@3 + .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 '<>f__AnonymousType1861640520`2' get_r1() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class '<>f__AnonymousType1861640520`2' assembly::r1@1 + IL_0005: ret + } + + .method public specialname static class '<>f__AnonymousType1861640520`2' get_r2() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class '<>f__AnonymousType1861640520`2' assembly::r2@3 + IL_0005: ret + } + + .method private specialname rtspecialname static void .cctor() cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.0 + IL_0001: stsfld int32 ''.$assembly::init@ + IL_0006: ldsfld int32 ''.$assembly::init@ + IL_000b: pop + IL_000c: ret + } + + .method assembly static void staticInitialization@() cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.1 + IL_0001: ldc.i4.2 + IL_0002: newobj instance void class '<>f__AnonymousType1861640520`2'::.ctor(!0, + !1) + IL_0007: stsfld class '<>f__AnonymousType1861640520`2' assembly::r1@1 + IL_000c: call class '<>f__AnonymousType1861640520`2' assembly::get_r1() + IL_0011: call instance !0 class '<>f__AnonymousType1861640520`2'::get_A() + IL_0016: call class '<>f__AnonymousType1861640520`2' assembly::get_r1() + IL_001b: call instance !1 class '<>f__AnonymousType1861640520`2'::get_B() + IL_0020: newobj instance void class '<>f__AnonymousType1861640520`2'::.ctor(!0, + !1) + IL_0025: stsfld class '<>f__AnonymousType1861640520`2' assembly::r2@3 + IL_002a: ret + } + + .property class '<>f__AnonymousType1861640520`2' + r1() + { + .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 class '<>f__AnonymousType1861640520`2' assembly::get_r1() + } + .property class '<>f__AnonymousType1861640520`2' + r2() + { + .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 class '<>f__AnonymousType1861640520`2' assembly::get_r2() + } +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .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 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: call void assembly::staticInitialization@() + IL_0005: ret + } + +} + +.class public auto ansi serializable sealed beforefieldinit '<>f__AnonymousType1861640520`2'<'j__TPar','j__TPar'> + extends [runtime]System.Object + implements [runtime]System.Collections.IStructuralComparable, + [runtime]System.IComparable, + class [runtime]System.IComparable`1f__AnonymousType1861640520`2'j__TPar',!'j__TPar'>>, + [runtime]System.Collections.IStructuralEquatable, + class [runtime]System.IEquatable`1f__AnonymousType1861640520`2'j__TPar',!'j__TPar'>> +{ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field private !'j__TPar' A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field private !'j__TPar' B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor(!'j__TPar' A, !'j__TPar' B) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 1E 3C 3E 66 5F 5F 41 6E 6F 6E + 79 6D 6F 75 73 54 79 70 65 31 38 36 31 36 34 30 + 35 32 30 60 32 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld !0 class '<>f__AnonymousType1861640520`2'j__TPar',!'j__TPar'>::A@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld !1 class '<>f__AnonymousType1861640520`2'j__TPar',!'j__TPar'>::B@ + IL_0014: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_A() 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: ldfld !0 class '<>f__AnonymousType1861640520`2'j__TPar',!'j__TPar'>::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_B() 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: ldfld !1 class '<>f__AnonymousType1861640520`2'j__TPar',!'j__TPar'>::B@ + IL_0006: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5f__AnonymousType1861640520`2'j__TPar',!'j__TPar'>,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class '<>f__AnonymousType1861640520`2'j__TPar',!'j__TPar'>>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToStringf__AnonymousType1861640520`2'j__TPar',!'j__TPar'>,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2f__AnonymousType1861640520`2'j__TPar',!'j__TPar'>,string>::Invoke(!0) + IL_0015: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(class '<>f__AnonymousType1861640520`2'j__TPar',!'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0044 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0042 + + IL_0006: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_000b: ldarg.0 + IL_000c: ldfld !0 class '<>f__AnonymousType1861640520`2'j__TPar',!'j__TPar'>::A@ + IL_0011: ldarg.1 + IL_0012: ldfld !0 class '<>f__AnonymousType1861640520`2'j__TPar',!'j__TPar'>::A@ + IL_0017: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_001c: stloc.0 + IL_001d: ldloc.0 + IL_001e: ldc.i4.0 + IL_001f: bge.s IL_0023 + + IL_0021: ldloc.0 + IL_0022: ret + + IL_0023: ldloc.0 + IL_0024: ldc.i4.0 + IL_0025: ble.s IL_0029 + + IL_0027: ldloc.0 + IL_0028: ret + + IL_0029: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_002e: ldarg.0 + IL_002f: ldfld !1 class '<>f__AnonymousType1861640520`2'j__TPar',!'j__TPar'>::B@ + IL_0034: ldarg.1 + IL_0035: ldfld !1 class '<>f__AnonymousType1861640520`2'j__TPar',!'j__TPar'>::B@ + IL_003a: tail. + IL_003c: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0041: ret + + IL_0042: ldc.i4.1 + IL_0043: ret + + IL_0044: ldarg.1 + IL_0045: brfalse.s IL_0049 + + IL_0047: ldc.i4.m1 + IL_0048: ret + + IL_0049: ldc.i4.0 + IL_004a: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: unbox.any class '<>f__AnonymousType1861640520`2'j__TPar',!'j__TPar'> + IL_0007: tail. + IL_0009: callvirt instance int32 class '<>f__AnonymousType1861640520`2'j__TPar',!'j__TPar'>::CompareTo(class '<>f__AnonymousType1861640520`2') + IL_000e: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj, class [runtime]System.Collections.IComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType1861640520`2'j__TPar',!'j__TPar'> V_0, + class '<>f__AnonymousType1861640520`2'j__TPar',!'j__TPar'> V_1, + int32 V_2) + IL_0000: ldarg.1 + IL_0001: unbox.any class '<>f__AnonymousType1861640520`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: stloc.1 + IL_0009: ldarg.0 + IL_000a: brfalse.s IL_004a + + IL_000c: ldarg.1 + IL_000d: unbox.any class '<>f__AnonymousType1861640520`2'j__TPar',!'j__TPar'> + IL_0012: brfalse.s IL_0048 + + IL_0014: ldarg.2 + IL_0015: ldarg.0 + IL_0016: ldfld !0 class '<>f__AnonymousType1861640520`2'j__TPar',!'j__TPar'>::A@ + IL_001b: ldloc.1 + IL_001c: ldfld !0 class '<>f__AnonymousType1861640520`2'j__TPar',!'j__TPar'>::A@ + IL_0021: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0026: stloc.2 + IL_0027: ldloc.2 + IL_0028: ldc.i4.0 + IL_0029: bge.s IL_002d + + IL_002b: ldloc.2 + IL_002c: ret + + IL_002d: ldloc.2 + IL_002e: ldc.i4.0 + IL_002f: ble.s IL_0033 + + IL_0031: ldloc.2 + IL_0032: ret + + IL_0033: ldarg.2 + IL_0034: ldarg.0 + IL_0035: ldfld !1 class '<>f__AnonymousType1861640520`2'j__TPar',!'j__TPar'>::B@ + IL_003a: ldloc.1 + IL_003b: ldfld !1 class '<>f__AnonymousType1861640520`2'j__TPar',!'j__TPar'>::B@ + IL_0040: tail. + IL_0042: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0047: ret + + IL_0048: ldc.i4.1 + IL_0049: ret + + IL_004a: ldarg.1 + IL_004b: unbox.any class '<>f__AnonymousType1861640520`2'j__TPar',!'j__TPar'> + IL_0050: brfalse.s IL_0054 + + IL_0052: ldc.i4.m1 + IL_0053: ret + + IL_0054: ldc.i4.0 + IL_0055: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode(class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 7 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_003d + + IL_0003: ldc.i4.0 + IL_0004: stloc.0 + IL_0005: ldc.i4 0x9e3779b9 + IL_000a: ldarg.1 + IL_000b: ldarg.0 + IL_000c: ldfld !1 class '<>f__AnonymousType1861640520`2'j__TPar',!'j__TPar'>::B@ + IL_0011: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0016: ldloc.0 + IL_0017: ldc.i4.6 + IL_0018: shl + IL_0019: ldloc.0 + IL_001a: ldc.i4.2 + IL_001b: shr + IL_001c: add + IL_001d: add + IL_001e: add + IL_001f: stloc.0 + IL_0020: ldc.i4 0x9e3779b9 + IL_0025: ldarg.1 + IL_0026: ldarg.0 + IL_0027: ldfld !0 class '<>f__AnonymousType1861640520`2'j__TPar',!'j__TPar'>::A@ + IL_002c: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0031: ldloc.0 + IL_0032: ldc.i4.6 + IL_0033: shl + IL_0034: ldloc.0 + IL_0035: ldc.i4.2 + IL_0036: shr + IL_0037: add + IL_0038: add + IL_0039: add + IL_003a: stloc.0 + IL_003b: ldloc.0 + IL_003c: ret + + IL_003d: ldc.i4.0 + IL_003e: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() + IL_0006: tail. + IL_0008: callvirt instance int32 class '<>f__AnonymousType1861640520`2'j__TPar',!'j__TPar'>::GetHashCode(class [runtime]System.Collections.IEqualityComparer) + IL_000d: ret + } + + .method public hidebysig instance bool Equals(class '<>f__AnonymousType1861640520`2'j__TPar',!'j__TPar'> obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType1861640520`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0035 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0033 + + IL_0006: ldarg.1 + IL_0007: stloc.0 + IL_0008: ldarg.2 + IL_0009: ldarg.0 + IL_000a: ldfld !0 class '<>f__AnonymousType1861640520`2'j__TPar',!'j__TPar'>::A@ + IL_000f: ldloc.0 + IL_0010: ldfld !0 class '<>f__AnonymousType1861640520`2'j__TPar',!'j__TPar'>::A@ + IL_0015: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_001a: brfalse.s IL_0031 + + IL_001c: ldarg.2 + IL_001d: ldarg.0 + IL_001e: ldfld !1 class '<>f__AnonymousType1861640520`2'j__TPar',!'j__TPar'>::B@ + IL_0023: ldloc.0 + IL_0024: ldfld !1 class '<>f__AnonymousType1861640520`2'j__TPar',!'j__TPar'>::B@ + IL_0029: tail. + IL_002b: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_0030: ret + + IL_0031: ldc.i4.0 + IL_0032: ret + + IL_0033: ldc.i4.0 + IL_0034: ret + + IL_0035: ldarg.1 + IL_0036: ldnull + IL_0037: cgt.un + IL_0039: ldc.i4.0 + IL_003a: ceq + IL_003c: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType1861640520`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType1861640520`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0015 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: ldarg.2 + IL_000d: tail. + IL_000f: callvirt instance bool class '<>f__AnonymousType1861640520`2'j__TPar',!'j__TPar'>::Equals(class '<>f__AnonymousType1861640520`2', + class [runtime]System.Collections.IEqualityComparer) + IL_0014: ret + + IL_0015: ldc.i4.0 + IL_0016: ret + } + + .method public hidebysig virtual final instance bool Equals(class '<>f__AnonymousType1861640520`2'j__TPar',!'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0031 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_002f + + IL_0006: ldarg.0 + IL_0007: ldfld !0 class '<>f__AnonymousType1861640520`2'j__TPar',!'j__TPar'>::A@ + IL_000c: ldarg.1 + IL_000d: ldfld !0 class '<>f__AnonymousType1861640520`2'j__TPar',!'j__TPar'>::A@ + IL_0012: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_0017: brfalse.s IL_002d + + IL_0019: ldarg.0 + IL_001a: ldfld !1 class '<>f__AnonymousType1861640520`2'j__TPar',!'j__TPar'>::B@ + IL_001f: ldarg.1 + IL_0020: ldfld !1 class '<>f__AnonymousType1861640520`2'j__TPar',!'j__TPar'>::B@ + IL_0025: tail. + IL_0027: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_002c: ret + + IL_002d: ldc.i4.0 + IL_002e: ret + + IL_002f: ldc.i4.0 + IL_0030: ret + + IL_0031: ldarg.1 + IL_0032: ldnull + IL_0033: cgt.un + IL_0035: ldc.i4.0 + IL_0036: ceq + IL_0038: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (class '<>f__AnonymousType1861640520`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType1861640520`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0014 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: tail. + IL_000e: callvirt instance bool class '<>f__AnonymousType1861640520`2'j__TPar',!'j__TPar'>::Equals(class '<>f__AnonymousType1861640520`2') + IL_0013: ret + + IL_0014: ldc.i4.0 + IL_0015: ret + } + + .property instance !'j__TPar' A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType1861640520`2'::get_A() + } + .property instance !'j__TPar' B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType1861640520`2'::get_B() + } +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_SpreadShadowsSpread.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_SpreadShadowsSpread.fs new file mode 100644 index 00000000000..f89debde485 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_SpreadShadowsSpread.fs @@ -0,0 +1,5 @@ +let r1 = {| A = 1; B = 2 |} +let r2 = {| A = "A" |} + +let r3 : {| A : string; B : int |} = {| ...r1; ...r2 |} +let r4 : {| A : int; B : int |} = {| ...r2; ...r1 |} diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_SpreadShadowsSpread.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_SpreadShadowsSpread.fs.il.bsl new file mode 100644 index 00000000000..51bb35f6d24 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_SpreadShadowsSpread.fs.il.bsl @@ -0,0 +1,916 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .field static assembly class '<>f__AnonymousType3872473412`2' r1@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 class '<>f__AnonymousType3065250744`1' r2@2 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly class '<>f__AnonymousType3872473412`2' r3@4 + .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 B@4 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly class '<>f__AnonymousType3872473412`2' r4@5 + .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 '<>f__AnonymousType3872473412`2' get_r1() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class '<>f__AnonymousType3872473412`2' assembly::r1@1 + IL_0005: ret + } + + .method public specialname static class '<>f__AnonymousType3065250744`1' get_r2() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class '<>f__AnonymousType3065250744`1' assembly::r2@2 + IL_0005: ret + } + + .method public specialname static class '<>f__AnonymousType3872473412`2' get_r3() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class '<>f__AnonymousType3872473412`2' assembly::r3@4 + IL_0005: ret + } + + .method assembly specialname static int32 get_B@4() cil managed + { + + .maxstack 8 + IL_0000: ldsfld int32 assembly::B@4 + IL_0005: ret + } + + .method public specialname static class '<>f__AnonymousType3872473412`2' get_r4() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class '<>f__AnonymousType3872473412`2' assembly::r4@5 + IL_0005: ret + } + + .method private specialname rtspecialname static void .cctor() cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.0 + IL_0001: stsfld int32 ''.$assembly::init@ + IL_0006: ldsfld int32 ''.$assembly::init@ + IL_000b: pop + IL_000c: ret + } + + .method assembly static void staticInitialization@() cil managed + { + + .maxstack 4 + IL_0000: ldc.i4.1 + IL_0001: ldc.i4.2 + IL_0002: newobj instance void class '<>f__AnonymousType3872473412`2'::.ctor(!0, + !1) + IL_0007: stsfld class '<>f__AnonymousType3872473412`2' assembly::r1@1 + IL_000c: ldstr "A" + IL_0011: newobj instance void class '<>f__AnonymousType3065250744`1'::.ctor(!0) + IL_0016: stsfld class '<>f__AnonymousType3065250744`1' assembly::r2@2 + IL_001b: call class '<>f__AnonymousType3872473412`2' assembly::get_r1() + IL_0020: call instance !1 class '<>f__AnonymousType3872473412`2'::get_B() + IL_0025: stsfld int32 assembly::B@4 + IL_002a: call class '<>f__AnonymousType3065250744`1' assembly::get_r2() + IL_002f: call instance !0 class '<>f__AnonymousType3065250744`1'::get_A() + IL_0034: call int32 assembly::get_B@4() + IL_0039: newobj instance void class '<>f__AnonymousType3872473412`2'::.ctor(!0, + !1) + IL_003e: stsfld class '<>f__AnonymousType3872473412`2' assembly::r3@4 + IL_0043: call class '<>f__AnonymousType3872473412`2' assembly::get_r1() + IL_0048: call instance !0 class '<>f__AnonymousType3872473412`2'::get_A() + IL_004d: call class '<>f__AnonymousType3872473412`2' assembly::get_r1() + IL_0052: call instance !1 class '<>f__AnonymousType3872473412`2'::get_B() + IL_0057: newobj instance void class '<>f__AnonymousType3872473412`2'::.ctor(!0, + !1) + IL_005c: stsfld class '<>f__AnonymousType3872473412`2' assembly::r4@5 + IL_0061: ret + } + + .property class '<>f__AnonymousType3872473412`2' + r1() + { + .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 class '<>f__AnonymousType3872473412`2' assembly::get_r1() + } + .property class '<>f__AnonymousType3065250744`1' + r2() + { + .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 class '<>f__AnonymousType3065250744`1' assembly::get_r2() + } + .property class '<>f__AnonymousType3872473412`2' + r3() + { + .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 class '<>f__AnonymousType3872473412`2' assembly::get_r3() + } + .property int32 B@4() + { + .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_B@4() + } + .property class '<>f__AnonymousType3872473412`2' + r4() + { + .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 class '<>f__AnonymousType3872473412`2' assembly::get_r4() + } +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .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 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: call void assembly::staticInitialization@() + IL_0005: ret + } + +} + +.class public auto ansi serializable sealed beforefieldinit '<>f__AnonymousType3065250744`1'<'j__TPar'> + extends [runtime]System.Object + implements [runtime]System.Collections.IStructuralComparable, + [runtime]System.IComparable, + class [runtime]System.IComparable`1f__AnonymousType3065250744`1'j__TPar'>>, + [runtime]System.Collections.IStructuralEquatable, + class [runtime]System.IEquatable`1f__AnonymousType3065250744`1'j__TPar'>> +{ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field private !'j__TPar' A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor(!'j__TPar' A) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 1E 3C 3E 66 5F 5F 41 6E 6F 6E + 79 6D 6F 75 73 54 79 70 65 33 30 36 35 32 35 30 + 37 34 34 60 31 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld !0 class '<>f__AnonymousType3065250744`1'j__TPar'>::A@ + IL_000d: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_A() 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: ldfld !0 class '<>f__AnonymousType3065250744`1'j__TPar'>::A@ + IL_0006: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5f__AnonymousType3065250744`1'j__TPar'>,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class '<>f__AnonymousType3065250744`1'j__TPar'>>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToStringf__AnonymousType3065250744`1'j__TPar'>,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2f__AnonymousType3065250744`1'j__TPar'>,string>::Invoke(!0) + IL_0015: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(class '<>f__AnonymousType3065250744`1'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0021 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_001f + + IL_0006: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_000b: ldarg.0 + IL_000c: ldfld !0 class '<>f__AnonymousType3065250744`1'j__TPar'>::A@ + IL_0011: ldarg.1 + IL_0012: ldfld !0 class '<>f__AnonymousType3065250744`1'j__TPar'>::A@ + IL_0017: tail. + IL_0019: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_001e: ret + + IL_001f: ldc.i4.1 + IL_0020: ret + + IL_0021: ldarg.1 + IL_0022: brfalse.s IL_0026 + + IL_0024: ldc.i4.m1 + IL_0025: ret + + IL_0026: ldc.i4.0 + IL_0027: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: unbox.any class '<>f__AnonymousType3065250744`1'j__TPar'> + IL_0007: tail. + IL_0009: callvirt instance int32 class '<>f__AnonymousType3065250744`1'j__TPar'>::CompareTo(class '<>f__AnonymousType3065250744`1') + IL_000e: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj, class [runtime]System.Collections.IComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType3065250744`1'j__TPar'> V_0, + class '<>f__AnonymousType3065250744`1'j__TPar'> V_1) + IL_0000: ldarg.1 + IL_0001: unbox.any class '<>f__AnonymousType3065250744`1'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: stloc.1 + IL_0009: ldarg.0 + IL_000a: brfalse.s IL_002b + + IL_000c: ldarg.1 + IL_000d: unbox.any class '<>f__AnonymousType3065250744`1'j__TPar'> + IL_0012: brfalse.s IL_0029 + + IL_0014: ldarg.2 + IL_0015: ldarg.0 + IL_0016: ldfld !0 class '<>f__AnonymousType3065250744`1'j__TPar'>::A@ + IL_001b: ldloc.1 + IL_001c: ldfld !0 class '<>f__AnonymousType3065250744`1'j__TPar'>::A@ + IL_0021: tail. + IL_0023: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0028: ret + + IL_0029: ldc.i4.1 + IL_002a: ret + + IL_002b: ldarg.1 + IL_002c: unbox.any class '<>f__AnonymousType3065250744`1'j__TPar'> + IL_0031: brfalse.s IL_0035 + + IL_0033: ldc.i4.m1 + IL_0034: ret + + IL_0035: ldc.i4.0 + IL_0036: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode(class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 7 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0022 + + IL_0003: ldc.i4.0 + IL_0004: stloc.0 + IL_0005: ldc.i4 0x9e3779b9 + IL_000a: ldarg.1 + IL_000b: ldarg.0 + IL_000c: ldfld !0 class '<>f__AnonymousType3065250744`1'j__TPar'>::A@ + IL_0011: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0016: ldloc.0 + IL_0017: ldc.i4.6 + IL_0018: shl + IL_0019: ldloc.0 + IL_001a: ldc.i4.2 + IL_001b: shr + IL_001c: add + IL_001d: add + IL_001e: add + IL_001f: stloc.0 + IL_0020: ldloc.0 + IL_0021: ret + + IL_0022: ldc.i4.0 + IL_0023: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() + IL_0006: tail. + IL_0008: callvirt instance int32 class '<>f__AnonymousType3065250744`1'j__TPar'>::GetHashCode(class [runtime]System.Collections.IEqualityComparer) + IL_000d: ret + } + + .method public hidebysig instance bool Equals(class '<>f__AnonymousType3065250744`1'j__TPar'> obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType3065250744`1'j__TPar'> V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_001f + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_001d + + IL_0006: ldarg.1 + IL_0007: stloc.0 + IL_0008: ldarg.2 + IL_0009: ldarg.0 + IL_000a: ldfld !0 class '<>f__AnonymousType3065250744`1'j__TPar'>::A@ + IL_000f: ldloc.0 + IL_0010: ldfld !0 class '<>f__AnonymousType3065250744`1'j__TPar'>::A@ + IL_0015: tail. + IL_0017: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_001c: ret + + IL_001d: ldc.i4.0 + IL_001e: ret + + IL_001f: ldarg.1 + IL_0020: ldnull + IL_0021: cgt.un + IL_0023: ldc.i4.0 + IL_0024: ceq + IL_0026: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType3065250744`1'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType3065250744`1'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0015 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: ldarg.2 + IL_000d: tail. + IL_000f: callvirt instance bool class '<>f__AnonymousType3065250744`1'j__TPar'>::Equals(class '<>f__AnonymousType3065250744`1', + class [runtime]System.Collections.IEqualityComparer) + IL_0014: ret + + IL_0015: ldc.i4.0 + IL_0016: ret + } + + .method public hidebysig virtual final instance bool Equals(class '<>f__AnonymousType3065250744`1'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_001c + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_001a + + IL_0006: ldarg.0 + IL_0007: ldfld !0 class '<>f__AnonymousType3065250744`1'j__TPar'>::A@ + IL_000c: ldarg.1 + IL_000d: ldfld !0 class '<>f__AnonymousType3065250744`1'j__TPar'>::A@ + IL_0012: tail. + IL_0014: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_0019: ret + + IL_001a: ldc.i4.0 + IL_001b: ret + + IL_001c: ldarg.1 + IL_001d: ldnull + IL_001e: cgt.un + IL_0020: ldc.i4.0 + IL_0021: ceq + IL_0023: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (class '<>f__AnonymousType3065250744`1'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType3065250744`1'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0014 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: tail. + IL_000e: callvirt instance bool class '<>f__AnonymousType3065250744`1'j__TPar'>::Equals(class '<>f__AnonymousType3065250744`1') + IL_0013: ret + + IL_0014: ldc.i4.0 + IL_0015: ret + } + + .property instance !'j__TPar' A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType3065250744`1'::get_A() + } +} + +.class public auto ansi serializable sealed beforefieldinit '<>f__AnonymousType3872473412`2'<'j__TPar','j__TPar'> + extends [runtime]System.Object + implements [runtime]System.Collections.IStructuralComparable, + [runtime]System.IComparable, + class [runtime]System.IComparable`1f__AnonymousType3872473412`2'j__TPar',!'j__TPar'>>, + [runtime]System.Collections.IStructuralEquatable, + class [runtime]System.IEquatable`1f__AnonymousType3872473412`2'j__TPar',!'j__TPar'>> +{ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field private !'j__TPar' A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field private !'j__TPar' B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor(!'j__TPar' A, !'j__TPar' B) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 1E 3C 3E 66 5F 5F 41 6E 6F 6E + 79 6D 6F 75 73 54 79 70 65 33 38 37 32 34 37 33 + 34 31 32 60 32 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld !0 class '<>f__AnonymousType3872473412`2'j__TPar',!'j__TPar'>::A@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld !1 class '<>f__AnonymousType3872473412`2'j__TPar',!'j__TPar'>::B@ + IL_0014: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_A() 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: ldfld !0 class '<>f__AnonymousType3872473412`2'j__TPar',!'j__TPar'>::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_B() 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: ldfld !1 class '<>f__AnonymousType3872473412`2'j__TPar',!'j__TPar'>::B@ + IL_0006: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5f__AnonymousType3872473412`2'j__TPar',!'j__TPar'>,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class '<>f__AnonymousType3872473412`2'j__TPar',!'j__TPar'>>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToStringf__AnonymousType3872473412`2'j__TPar',!'j__TPar'>,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2f__AnonymousType3872473412`2'j__TPar',!'j__TPar'>,string>::Invoke(!0) + IL_0015: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(class '<>f__AnonymousType3872473412`2'j__TPar',!'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0044 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0042 + + IL_0006: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_000b: ldarg.0 + IL_000c: ldfld !0 class '<>f__AnonymousType3872473412`2'j__TPar',!'j__TPar'>::A@ + IL_0011: ldarg.1 + IL_0012: ldfld !0 class '<>f__AnonymousType3872473412`2'j__TPar',!'j__TPar'>::A@ + IL_0017: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_001c: stloc.0 + IL_001d: ldloc.0 + IL_001e: ldc.i4.0 + IL_001f: bge.s IL_0023 + + IL_0021: ldloc.0 + IL_0022: ret + + IL_0023: ldloc.0 + IL_0024: ldc.i4.0 + IL_0025: ble.s IL_0029 + + IL_0027: ldloc.0 + IL_0028: ret + + IL_0029: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_002e: ldarg.0 + IL_002f: ldfld !1 class '<>f__AnonymousType3872473412`2'j__TPar',!'j__TPar'>::B@ + IL_0034: ldarg.1 + IL_0035: ldfld !1 class '<>f__AnonymousType3872473412`2'j__TPar',!'j__TPar'>::B@ + IL_003a: tail. + IL_003c: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0041: ret + + IL_0042: ldc.i4.1 + IL_0043: ret + + IL_0044: ldarg.1 + IL_0045: brfalse.s IL_0049 + + IL_0047: ldc.i4.m1 + IL_0048: ret + + IL_0049: ldc.i4.0 + IL_004a: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: unbox.any class '<>f__AnonymousType3872473412`2'j__TPar',!'j__TPar'> + IL_0007: tail. + IL_0009: callvirt instance int32 class '<>f__AnonymousType3872473412`2'j__TPar',!'j__TPar'>::CompareTo(class '<>f__AnonymousType3872473412`2') + IL_000e: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj, class [runtime]System.Collections.IComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType3872473412`2'j__TPar',!'j__TPar'> V_0, + class '<>f__AnonymousType3872473412`2'j__TPar',!'j__TPar'> V_1, + int32 V_2) + IL_0000: ldarg.1 + IL_0001: unbox.any class '<>f__AnonymousType3872473412`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: stloc.1 + IL_0009: ldarg.0 + IL_000a: brfalse.s IL_004a + + IL_000c: ldarg.1 + IL_000d: unbox.any class '<>f__AnonymousType3872473412`2'j__TPar',!'j__TPar'> + IL_0012: brfalse.s IL_0048 + + IL_0014: ldarg.2 + IL_0015: ldarg.0 + IL_0016: ldfld !0 class '<>f__AnonymousType3872473412`2'j__TPar',!'j__TPar'>::A@ + IL_001b: ldloc.1 + IL_001c: ldfld !0 class '<>f__AnonymousType3872473412`2'j__TPar',!'j__TPar'>::A@ + IL_0021: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0026: stloc.2 + IL_0027: ldloc.2 + IL_0028: ldc.i4.0 + IL_0029: bge.s IL_002d + + IL_002b: ldloc.2 + IL_002c: ret + + IL_002d: ldloc.2 + IL_002e: ldc.i4.0 + IL_002f: ble.s IL_0033 + + IL_0031: ldloc.2 + IL_0032: ret + + IL_0033: ldarg.2 + IL_0034: ldarg.0 + IL_0035: ldfld !1 class '<>f__AnonymousType3872473412`2'j__TPar',!'j__TPar'>::B@ + IL_003a: ldloc.1 + IL_003b: ldfld !1 class '<>f__AnonymousType3872473412`2'j__TPar',!'j__TPar'>::B@ + IL_0040: tail. + IL_0042: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0047: ret + + IL_0048: ldc.i4.1 + IL_0049: ret + + IL_004a: ldarg.1 + IL_004b: unbox.any class '<>f__AnonymousType3872473412`2'j__TPar',!'j__TPar'> + IL_0050: brfalse.s IL_0054 + + IL_0052: ldc.i4.m1 + IL_0053: ret + + IL_0054: ldc.i4.0 + IL_0055: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode(class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 7 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_003d + + IL_0003: ldc.i4.0 + IL_0004: stloc.0 + IL_0005: ldc.i4 0x9e3779b9 + IL_000a: ldarg.1 + IL_000b: ldarg.0 + IL_000c: ldfld !1 class '<>f__AnonymousType3872473412`2'j__TPar',!'j__TPar'>::B@ + IL_0011: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0016: ldloc.0 + IL_0017: ldc.i4.6 + IL_0018: shl + IL_0019: ldloc.0 + IL_001a: ldc.i4.2 + IL_001b: shr + IL_001c: add + IL_001d: add + IL_001e: add + IL_001f: stloc.0 + IL_0020: ldc.i4 0x9e3779b9 + IL_0025: ldarg.1 + IL_0026: ldarg.0 + IL_0027: ldfld !0 class '<>f__AnonymousType3872473412`2'j__TPar',!'j__TPar'>::A@ + IL_002c: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0031: ldloc.0 + IL_0032: ldc.i4.6 + IL_0033: shl + IL_0034: ldloc.0 + IL_0035: ldc.i4.2 + IL_0036: shr + IL_0037: add + IL_0038: add + IL_0039: add + IL_003a: stloc.0 + IL_003b: ldloc.0 + IL_003c: ret + + IL_003d: ldc.i4.0 + IL_003e: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() + IL_0006: tail. + IL_0008: callvirt instance int32 class '<>f__AnonymousType3872473412`2'j__TPar',!'j__TPar'>::GetHashCode(class [runtime]System.Collections.IEqualityComparer) + IL_000d: ret + } + + .method public hidebysig instance bool Equals(class '<>f__AnonymousType3872473412`2'j__TPar',!'j__TPar'> obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType3872473412`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0035 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0033 + + IL_0006: ldarg.1 + IL_0007: stloc.0 + IL_0008: ldarg.2 + IL_0009: ldarg.0 + IL_000a: ldfld !0 class '<>f__AnonymousType3872473412`2'j__TPar',!'j__TPar'>::A@ + IL_000f: ldloc.0 + IL_0010: ldfld !0 class '<>f__AnonymousType3872473412`2'j__TPar',!'j__TPar'>::A@ + IL_0015: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_001a: brfalse.s IL_0031 + + IL_001c: ldarg.2 + IL_001d: ldarg.0 + IL_001e: ldfld !1 class '<>f__AnonymousType3872473412`2'j__TPar',!'j__TPar'>::B@ + IL_0023: ldloc.0 + IL_0024: ldfld !1 class '<>f__AnonymousType3872473412`2'j__TPar',!'j__TPar'>::B@ + IL_0029: tail. + IL_002b: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_0030: ret + + IL_0031: ldc.i4.0 + IL_0032: ret + + IL_0033: ldc.i4.0 + IL_0034: ret + + IL_0035: ldarg.1 + IL_0036: ldnull + IL_0037: cgt.un + IL_0039: ldc.i4.0 + IL_003a: ceq + IL_003c: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType3872473412`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType3872473412`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0015 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: ldarg.2 + IL_000d: tail. + IL_000f: callvirt instance bool class '<>f__AnonymousType3872473412`2'j__TPar',!'j__TPar'>::Equals(class '<>f__AnonymousType3872473412`2', + class [runtime]System.Collections.IEqualityComparer) + IL_0014: ret + + IL_0015: ldc.i4.0 + IL_0016: ret + } + + .method public hidebysig virtual final instance bool Equals(class '<>f__AnonymousType3872473412`2'j__TPar',!'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0031 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_002f + + IL_0006: ldarg.0 + IL_0007: ldfld !0 class '<>f__AnonymousType3872473412`2'j__TPar',!'j__TPar'>::A@ + IL_000c: ldarg.1 + IL_000d: ldfld !0 class '<>f__AnonymousType3872473412`2'j__TPar',!'j__TPar'>::A@ + IL_0012: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_0017: brfalse.s IL_002d + + IL_0019: ldarg.0 + IL_001a: ldfld !1 class '<>f__AnonymousType3872473412`2'j__TPar',!'j__TPar'>::B@ + IL_001f: ldarg.1 + IL_0020: ldfld !1 class '<>f__AnonymousType3872473412`2'j__TPar',!'j__TPar'>::B@ + IL_0025: tail. + IL_0027: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_002c: ret + + IL_002d: ldc.i4.0 + IL_002e: ret + + IL_002f: ldc.i4.0 + IL_0030: ret + + IL_0031: ldarg.1 + IL_0032: ldnull + IL_0033: cgt.un + IL_0035: ldc.i4.0 + IL_0036: ceq + IL_0038: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (class '<>f__AnonymousType3872473412`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType3872473412`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0014 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: tail. + IL_000e: callvirt instance bool class '<>f__AnonymousType3872473412`2'j__TPar',!'j__TPar'>::Equals(class '<>f__AnonymousType3872473412`2') + IL_0013: ret + + IL_0014: ldc.i4.0 + IL_0015: ret + } + + .property instance !'j__TPar' A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType3872473412`2'::get_A() + } + .property instance !'j__TPar' B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType3872473412`2'::get_B() + } +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_Structness.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_Structness.fs new file mode 100644 index 00000000000..213e79f3fad --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_Structness.fs @@ -0,0 +1,21 @@ +type RefNominalRecd = { A : int } +type [] StructNominalRecd = { A : int } + +let refAnonRecd = {| A = 1 |} +let structAnonRecd = struct {| A = 1 |} +let refNominalRecd : RefNominalRecd = { A = 1 } +let structNominalRecd : StructNominalRecd = { A = 1 } + +let ``ref anon src, no explicit target, stays ref`` = {| ...refAnonRecd; B = 2 |} +let ``ref anon src, explicit struct target, becomes struct`` = struct {| ...refAnonRecd; B = 2 |} +let ``ref anon src, inferred struct target, becomes struct`` : struct {| A : int; B : int |} = {| ...refAnonRecd; B = 2 |} +let ``struct anon src, no explicit target, stays struct`` = {| ...structAnonRecd; B = 2 |} +let ``struct anon src, explicit struct target, stays struct`` = struct {| ...structAnonRecd; B = 2 |} +let ``struct anon src, inferred struct target, stays struct`` : struct {| A : int; B : int |} = {| ...structAnonRecd; B = 2 |} + +let ``ref nominal src, no explicit target, stays ref`` = {| ...refAnonRecd; B = 2 |} +let ``ref nominal src, explicit struct target, becomes struct`` = struct {| ...refAnonRecd; B = 2 |} +let ``ref nominal src, inferred struct target, becomes struct`` : struct {| A : int; B : int |} = {| ...refAnonRecd; B = 2 |} +let ``struct nominal src, no explicit target, stays struct`` = {| ...structAnonRecd; B = 2 |} +let ``struct nominal src, explicit struct target, stays struct`` = struct {| ...structAnonRecd; B = 2 |} +let ``struct nominal src, inferred struct target, stays struct`` : struct {| A : int; B : int |} = {| ...structAnonRecd; B = 2 |} diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_Structness.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_Structness.fs.il.bsl new file mode 100644 index 00000000000..faab874bb28 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Anonymous_Structness.fs.il.bsl @@ -0,0 +1,2517 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable sealed nested public RefNominalRecd + extends [runtime]System.Object + implements class [runtime]System.IEquatable`1, + [runtime]System.Collections.IStructuralEquatable, + class [runtime]System.IComparable`1, + [runtime]System.IComparable, + [runtime]System.Collections.IStructuralComparable + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly int32 A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname instance int32 get_A() 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: ldfld int32 assembly/RefNominalRecd::A@ + IL_0006: ret + } + + .method public specialname rtspecialname instance void .ctor(int32 a) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 2E 45 78 70 72 65 73 73 69 6F + 6E 5F 41 6E 6F 6E 79 6D 6F 75 73 5F 53 74 72 75 + 63 74 6E 65 73 73 2B 52 65 66 4E 6F 6D 69 6E 61 + 6C 52 65 63 64 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld int32 assembly/RefNominalRecd::A@ + IL_000d: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/RefNominalRecd>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(class assembly/RefNominalRecd obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class [runtime]System.Collections.IComparer V_0, + int32 V_1, + int32 V_2) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0026 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0024 + + IL_0006: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_000b: stloc.0 + IL_000c: ldarg.0 + IL_000d: ldfld int32 assembly/RefNominalRecd::A@ + IL_0012: stloc.1 + IL_0013: ldarg.1 + IL_0014: ldfld int32 assembly/RefNominalRecd::A@ + IL_0019: stloc.2 + IL_001a: ldloc.1 + IL_001b: ldloc.2 + IL_001c: cgt + IL_001e: ldloc.1 + IL_001f: ldloc.2 + IL_0020: clt + IL_0022: sub + IL_0023: ret + + IL_0024: ldc.i4.1 + IL_0025: ret + + IL_0026: ldarg.1 + IL_0027: brfalse.s IL_002b + + IL_0029: ldc.i4.m1 + IL_002a: ret + + IL_002b: ldc.i4.0 + IL_002c: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: unbox.any assembly/RefNominalRecd + IL_0007: callvirt instance int32 assembly/RefNominalRecd::CompareTo(class assembly/RefNominalRecd) + IL_000c: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj, class [runtime]System.Collections.IComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class assembly/RefNominalRecd V_0, + int32 V_1, + int32 V_2) + IL_0000: ldarg.1 + IL_0001: unbox.any assembly/RefNominalRecd + IL_0006: stloc.0 + IL_0007: ldarg.0 + IL_0008: brfalse.s IL_002c + + IL_000a: ldarg.1 + IL_000b: unbox.any assembly/RefNominalRecd + IL_0010: brfalse.s IL_002a + + IL_0012: ldarg.0 + IL_0013: ldfld int32 assembly/RefNominalRecd::A@ + IL_0018: stloc.1 + IL_0019: ldloc.0 + IL_001a: ldfld int32 assembly/RefNominalRecd::A@ + IL_001f: stloc.2 + IL_0020: ldloc.1 + IL_0021: ldloc.2 + IL_0022: cgt + IL_0024: ldloc.1 + IL_0025: ldloc.2 + IL_0026: clt + IL_0028: sub + IL_0029: ret + + IL_002a: ldc.i4.1 + IL_002b: ret + + IL_002c: ldarg.1 + IL_002d: unbox.any assembly/RefNominalRecd + IL_0032: brfalse.s IL_0036 + + IL_0034: ldc.i4.m1 + IL_0035: ret + + IL_0036: ldc.i4.0 + IL_0037: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode(class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 7 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_001c + + IL_0003: ldc.i4.0 + IL_0004: stloc.0 + IL_0005: ldc.i4 0x9e3779b9 + IL_000a: ldarg.0 + IL_000b: ldfld int32 assembly/RefNominalRecd::A@ + IL_0010: ldloc.0 + IL_0011: ldc.i4.6 + IL_0012: shl + IL_0013: ldloc.0 + IL_0014: ldc.i4.2 + IL_0015: shr + IL_0016: add + IL_0017: add + IL_0018: add + IL_0019: stloc.0 + IL_001a: ldloc.0 + IL_001b: ret + + IL_001c: ldc.i4.0 + IL_001d: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() + IL_0006: callvirt instance int32 assembly/RefNominalRecd::GetHashCode(class [runtime]System.Collections.IEqualityComparer) + IL_000b: ret + } + + .method public hidebysig instance bool Equals(class assembly/RefNominalRecd obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0017 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0015 + + IL_0006: ldarg.0 + IL_0007: ldfld int32 assembly/RefNominalRecd::A@ + IL_000c: ldarg.1 + IL_000d: ldfld int32 assembly/RefNominalRecd::A@ + IL_0012: ceq + IL_0014: ret + + IL_0015: ldc.i4.0 + IL_0016: ret + + IL_0017: ldarg.1 + IL_0018: ldnull + IL_0019: cgt.un + IL_001b: ldc.i4.0 + IL_001c: ceq + IL_001e: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class assembly/RefNominalRecd V_0) + IL_0000: ldarg.1 + IL_0001: isinst assembly/RefNominalRecd + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0013 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: ldarg.2 + IL_000d: callvirt instance bool assembly/RefNominalRecd::Equals(class assembly/RefNominalRecd, + class [runtime]System.Collections.IEqualityComparer) + IL_0012: ret + + IL_0013: ldc.i4.0 + IL_0014: ret + } + + .method public hidebysig virtual final instance bool Equals(class assembly/RefNominalRecd obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0017 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0015 + + IL_0006: ldarg.0 + IL_0007: ldfld int32 assembly/RefNominalRecd::A@ + IL_000c: ldarg.1 + IL_000d: ldfld int32 assembly/RefNominalRecd::A@ + IL_0012: ceq + IL_0014: ret + + IL_0015: ldc.i4.0 + IL_0016: ret + + IL_0017: ldarg.1 + IL_0018: ldnull + IL_0019: cgt.un + IL_001b: ldc.i4.0 + IL_001c: ceq + IL_001e: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (class assembly/RefNominalRecd V_0) + IL_0000: ldarg.1 + IL_0001: isinst assembly/RefNominalRecd + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0012 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: callvirt instance bool assembly/RefNominalRecd::Equals(class assembly/RefNominalRecd) + IL_0011: ret + + IL_0012: ldc.i4.0 + IL_0013: ret + } + + .property instance int32 A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance int32 assembly/RefNominalRecd::get_A() + } + } + + .class sequential ansi serializable sealed nested public StructNominalRecd + extends [runtime]System.ValueType + implements class [runtime]System.IEquatable`1, + [runtime]System.Collections.IStructuralEquatable, + class [runtime]System.IComparable`1, + [runtime]System.IComparable, + [runtime]System.Collections.IStructuralComparable + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.StructAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly int32 A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname instance int32 get_A() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + .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: ldfld int32 assembly/StructNominalRecd::A@ + IL_0006: ret + } + + .method public specialname rtspecialname instance void .ctor(int32 a) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 31 45 78 70 72 65 73 73 69 6F + 6E 5F 41 6E 6F 6E 79 6D 6F 75 73 5F 53 74 72 75 + 63 74 6E 65 73 73 2B 53 74 72 75 63 74 4E 6F 6D + 69 6E 61 6C 52 65 63 64 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld int32 assembly/StructNominalRecd::A@ + IL_0007: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,valuetype assembly/StructNominalRecd>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: ldobj assembly/StructNominalRecd + IL_0015: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_001a: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(valuetype assembly/StructNominalRecd obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class [runtime]System.Collections.IComparer V_0, + int32 V_1, + int32 V_2) + IL_0000: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_0005: stloc.0 + IL_0006: ldarg.0 + IL_0007: ldfld int32 assembly/StructNominalRecd::A@ + IL_000c: stloc.1 + IL_000d: ldarga.s obj + IL_000f: ldfld int32 assembly/StructNominalRecd::A@ + IL_0014: stloc.2 + IL_0015: ldloc.1 + IL_0016: ldloc.2 + IL_0017: cgt + IL_0019: ldloc.1 + IL_001a: ldloc.2 + IL_001b: clt + IL_001d: sub + IL_001e: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: unbox.any assembly/StructNominalRecd + IL_0007: call instance int32 assembly/StructNominalRecd::CompareTo(valuetype assembly/StructNominalRecd) + IL_000c: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj, class [runtime]System.Collections.IComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (valuetype assembly/StructNominalRecd V_0, + int32 V_1, + int32 V_2) + IL_0000: ldarg.1 + IL_0001: unbox.any assembly/StructNominalRecd + IL_0006: stloc.0 + IL_0007: ldarg.0 + IL_0008: ldfld int32 assembly/StructNominalRecd::A@ + IL_000d: stloc.1 + IL_000e: ldloca.s V_0 + IL_0010: ldfld int32 assembly/StructNominalRecd::A@ + IL_0015: stloc.2 + IL_0016: ldloc.1 + IL_0017: ldloc.2 + IL_0018: cgt + IL_001a: ldloc.1 + IL_001b: ldloc.2 + IL_001c: clt + IL_001e: sub + IL_001f: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode(class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 7 + .locals init (int32 V_0) + IL_0000: ldc.i4.0 + IL_0001: stloc.0 + IL_0002: ldc.i4 0x9e3779b9 + IL_0007: ldarg.0 + IL_0008: ldfld int32 assembly/StructNominalRecd::A@ + IL_000d: ldloc.0 + IL_000e: ldc.i4.6 + IL_000f: shl + IL_0010: ldloc.0 + IL_0011: ldc.i4.2 + IL_0012: shr + IL_0013: add + IL_0014: add + IL_0015: add + IL_0016: stloc.0 + IL_0017: ldloc.0 + IL_0018: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() + IL_0006: call instance int32 assembly/StructNominalRecd::GetHashCode(class [runtime]System.Collections.IEqualityComparer) + IL_000b: ret + } + + .method public hidebysig instance bool Equals(valuetype assembly/StructNominalRecd obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld int32 assembly/StructNominalRecd::A@ + IL_0006: ldarga.s obj + IL_0008: ldfld int32 assembly/StructNominalRecd::A@ + IL_000d: ceq + IL_000f: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (valuetype assembly/StructNominalRecd V_0) + IL_0000: ldarg.1 + IL_0001: isinst assembly/StructNominalRecd + IL_0006: brfalse.s IL_001f + + IL_0008: ldarg.1 + IL_0009: unbox.any assembly/StructNominalRecd + IL_000e: stloc.0 + IL_000f: ldarg.0 + IL_0010: ldfld int32 assembly/StructNominalRecd::A@ + IL_0015: ldloca.s V_0 + IL_0017: ldfld int32 assembly/StructNominalRecd::A@ + IL_001c: ceq + IL_001e: ret + + IL_001f: ldc.i4.0 + IL_0020: ret + } + + .method public hidebysig virtual final instance bool Equals(valuetype assembly/StructNominalRecd obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld int32 assembly/StructNominalRecd::A@ + IL_0006: ldarga.s obj + IL_0008: ldfld int32 assembly/StructNominalRecd::A@ + IL_000d: ceq + IL_000f: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (valuetype assembly/StructNominalRecd V_0, + valuetype assembly/StructNominalRecd V_1) + IL_0000: ldarg.1 + IL_0001: isinst assembly/StructNominalRecd + IL_0006: brfalse.s IL_0021 + + IL_0008: ldarg.1 + IL_0009: unbox.any assembly/StructNominalRecd + IL_000e: stloc.0 + IL_000f: ldloc.0 + IL_0010: stloc.1 + IL_0011: ldarg.0 + IL_0012: ldfld int32 assembly/StructNominalRecd::A@ + IL_0017: ldloca.s V_1 + IL_0019: ldfld int32 assembly/StructNominalRecd::A@ + IL_001e: ceq + IL_0020: ret + + IL_0021: ldc.i4.0 + IL_0022: ret + } + + .property instance int32 A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance int32 assembly/StructNominalRecd::get_A() + } + } + + .field static assembly class '<>f__AnonymousType3348076434`1' refAnonRecd@4 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly valuetype '<>f__AnonymousType10002306269156`1' structAnonRecd@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 class assembly/RefNominalRecd refNominalRecd@6 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly valuetype assembly/StructNominalRecd structNominalRecd@7 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly class '<>f__AnonymousType3357665219`2' 'ref anon src, no explicit target, stays ref@9' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly valuetype '<>f__AnonymousType10001789011089`2' 'ref anon src, explicit struct target, becomes struct@10' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly valuetype '<>f__AnonymousType10001789011089`2' 'ref anon src, inferred struct target, becomes struct@11' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly class '<>f__AnonymousType3357665219`2' 'struct anon src, no explicit target, stays struct@12' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly valuetype '<>f__AnonymousType10002306269156`1' copyOfStruct@12 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly valuetype '<>f__AnonymousType10002306269156`1' 'copyOfStruct@12-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 valuetype '<>f__AnonymousType10001789011089`2' 'struct anon src, explicit struct target, stays struct@13' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly valuetype '<>f__AnonymousType10002306269156`1' 'copyOfStruct@13-2' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly valuetype '<>f__AnonymousType10002306269156`1' 'copyOfStruct@13-3' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly valuetype '<>f__AnonymousType10001789011089`2' 'struct anon src, inferred struct target, stays struct@14' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly valuetype '<>f__AnonymousType10002306269156`1' 'copyOfStruct@14-4' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly valuetype '<>f__AnonymousType10002306269156`1' 'copyOfStruct@14-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 class '<>f__AnonymousType3357665219`2' 'ref nominal src, no explicit target, stays ref@16' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly valuetype '<>f__AnonymousType10001789011089`2' 'ref nominal src, explicit struct target, becomes struct@17' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly valuetype '<>f__AnonymousType10001789011089`2' 'ref nominal src, inferred struct target, becomes struct@18' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly class '<>f__AnonymousType3357665219`2' 'struct nominal src, no explicit target, stays struct@19' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly valuetype '<>f__AnonymousType10002306269156`1' 'copyOfStruct@19-6' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly valuetype '<>f__AnonymousType10002306269156`1' 'copyOfStruct@19-7' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly valuetype '<>f__AnonymousType10001789011089`2' 'struct nominal src, explicit struct target, stays struct@20' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly valuetype '<>f__AnonymousType10002306269156`1' 'copyOfStruct@20-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 valuetype '<>f__AnonymousType10002306269156`1' 'copyOfStruct@20-9' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly valuetype '<>f__AnonymousType10001789011089`2' 'struct nominal src, inferred struct target, stays struct@21' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly valuetype '<>f__AnonymousType10002306269156`1' 'copyOfStruct@21-10' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly valuetype '<>f__AnonymousType10002306269156`1' 'copyOfStruct@21-11' + .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 '<>f__AnonymousType3348076434`1' get_refAnonRecd() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class '<>f__AnonymousType3348076434`1' assembly::refAnonRecd@4 + IL_0005: ret + } + + .method public specialname static valuetype '<>f__AnonymousType10002306269156`1' get_structAnonRecd() cil managed + { + + .maxstack 8 + IL_0000: ldsfld valuetype '<>f__AnonymousType10002306269156`1' assembly::structAnonRecd@5 + IL_0005: ret + } + + .method public specialname static class assembly/RefNominalRecd get_refNominalRecd() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class assembly/RefNominalRecd assembly::refNominalRecd@6 + IL_0005: ret + } + + .method public specialname static valuetype assembly/StructNominalRecd get_structNominalRecd() cil managed + { + + .maxstack 8 + IL_0000: ldsfld valuetype assembly/StructNominalRecd assembly::structNominalRecd@7 + IL_0005: ret + } + + .method public specialname static class '<>f__AnonymousType3357665219`2' 'get_ref anon src, no explicit target, stays ref'() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class '<>f__AnonymousType3357665219`2' assembly::'ref anon src, no explicit target, stays ref@9' + IL_0005: ret + } + + .method public specialname static valuetype '<>f__AnonymousType10001789011089`2' 'get_ref anon src, explicit struct target, becomes struct'() cil managed + { + + .maxstack 8 + IL_0000: ldsfld valuetype '<>f__AnonymousType10001789011089`2' assembly::'ref anon src, explicit struct target, becomes struct@10' + IL_0005: ret + } + + .method public specialname static valuetype '<>f__AnonymousType10001789011089`2' 'get_ref anon src, inferred struct target, becomes struct'() cil managed + { + + .maxstack 8 + IL_0000: ldsfld valuetype '<>f__AnonymousType10001789011089`2' assembly::'ref anon src, inferred struct target, becomes struct@11' + IL_0005: ret + } + + .method public specialname static class '<>f__AnonymousType3357665219`2' 'get_struct anon src, no explicit target, stays struct'() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class '<>f__AnonymousType3357665219`2' assembly::'struct anon src, no explicit target, stays struct@12' + IL_0005: ret + } + + .method assembly specialname static valuetype '<>f__AnonymousType10002306269156`1' get_copyOfStruct@12() cil managed + { + + .maxstack 8 + IL_0000: ldsfld valuetype '<>f__AnonymousType10002306269156`1' assembly::copyOfStruct@12 + IL_0005: ret + } + + .method assembly specialname static valuetype '<>f__AnonymousType10002306269156`1' 'get_copyOfStruct@12-1'() cil managed + { + + .maxstack 8 + IL_0000: ldsfld valuetype '<>f__AnonymousType10002306269156`1' assembly::'copyOfStruct@12-1' + IL_0005: ret + } + + .method public specialname static valuetype '<>f__AnonymousType10001789011089`2' 'get_struct anon src, explicit struct target, stays struct'() cil managed + { + + .maxstack 8 + IL_0000: ldsfld valuetype '<>f__AnonymousType10001789011089`2' assembly::'struct anon src, explicit struct target, stays struct@13' + IL_0005: ret + } + + .method assembly specialname static valuetype '<>f__AnonymousType10002306269156`1' 'get_copyOfStruct@13-2'() cil managed + { + + .maxstack 8 + IL_0000: ldsfld valuetype '<>f__AnonymousType10002306269156`1' assembly::'copyOfStruct@13-2' + IL_0005: ret + } + + .method assembly specialname static valuetype '<>f__AnonymousType10002306269156`1' 'get_copyOfStruct@13-3'() cil managed + { + + .maxstack 8 + IL_0000: ldsfld valuetype '<>f__AnonymousType10002306269156`1' assembly::'copyOfStruct@13-3' + IL_0005: ret + } + + .method public specialname static valuetype '<>f__AnonymousType10001789011089`2' 'get_struct anon src, inferred struct target, stays struct'() cil managed + { + + .maxstack 8 + IL_0000: ldsfld valuetype '<>f__AnonymousType10001789011089`2' assembly::'struct anon src, inferred struct target, stays struct@14' + IL_0005: ret + } + + .method assembly specialname static valuetype '<>f__AnonymousType10002306269156`1' 'get_copyOfStruct@14-4'() cil managed + { + + .maxstack 8 + IL_0000: ldsfld valuetype '<>f__AnonymousType10002306269156`1' assembly::'copyOfStruct@14-4' + IL_0005: ret + } + + .method assembly specialname static valuetype '<>f__AnonymousType10002306269156`1' 'get_copyOfStruct@14-5'() cil managed + { + + .maxstack 8 + IL_0000: ldsfld valuetype '<>f__AnonymousType10002306269156`1' assembly::'copyOfStruct@14-5' + IL_0005: ret + } + + .method public specialname static class '<>f__AnonymousType3357665219`2' 'get_ref nominal src, no explicit target, stays ref'() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class '<>f__AnonymousType3357665219`2' assembly::'ref nominal src, no explicit target, stays ref@16' + IL_0005: ret + } + + .method public specialname static valuetype '<>f__AnonymousType10001789011089`2' 'get_ref nominal src, explicit struct target, becomes struct'() cil managed + { + + .maxstack 8 + IL_0000: ldsfld valuetype '<>f__AnonymousType10001789011089`2' assembly::'ref nominal src, explicit struct target, becomes struct@17' + IL_0005: ret + } + + .method public specialname static valuetype '<>f__AnonymousType10001789011089`2' 'get_ref nominal src, inferred struct target, becomes struct'() cil managed + { + + .maxstack 8 + IL_0000: ldsfld valuetype '<>f__AnonymousType10001789011089`2' assembly::'ref nominal src, inferred struct target, becomes struct@18' + IL_0005: ret + } + + .method public specialname static class '<>f__AnonymousType3357665219`2' 'get_struct nominal src, no explicit target, stays struct'() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class '<>f__AnonymousType3357665219`2' assembly::'struct nominal src, no explicit target, stays struct@19' + IL_0005: ret + } + + .method assembly specialname static valuetype '<>f__AnonymousType10002306269156`1' 'get_copyOfStruct@19-6'() cil managed + { + + .maxstack 8 + IL_0000: ldsfld valuetype '<>f__AnonymousType10002306269156`1' assembly::'copyOfStruct@19-6' + IL_0005: ret + } + + .method assembly specialname static valuetype '<>f__AnonymousType10002306269156`1' 'get_copyOfStruct@19-7'() cil managed + { + + .maxstack 8 + IL_0000: ldsfld valuetype '<>f__AnonymousType10002306269156`1' assembly::'copyOfStruct@19-7' + IL_0005: ret + } + + .method public specialname static valuetype '<>f__AnonymousType10001789011089`2' 'get_struct nominal src, explicit struct target, stays struct'() cil managed + { + + .maxstack 8 + IL_0000: ldsfld valuetype '<>f__AnonymousType10001789011089`2' assembly::'struct nominal src, explicit struct target, stays struct@20' + IL_0005: ret + } + + .method assembly specialname static valuetype '<>f__AnonymousType10002306269156`1' 'get_copyOfStruct@20-8'() cil managed + { + + .maxstack 8 + IL_0000: ldsfld valuetype '<>f__AnonymousType10002306269156`1' assembly::'copyOfStruct@20-8' + IL_0005: ret + } + + .method assembly specialname static valuetype '<>f__AnonymousType10002306269156`1' 'get_copyOfStruct@20-9'() cil managed + { + + .maxstack 8 + IL_0000: ldsfld valuetype '<>f__AnonymousType10002306269156`1' assembly::'copyOfStruct@20-9' + IL_0005: ret + } + + .method public specialname static valuetype '<>f__AnonymousType10001789011089`2' 'get_struct nominal src, inferred struct target, stays struct'() cil managed + { + + .maxstack 8 + IL_0000: ldsfld valuetype '<>f__AnonymousType10001789011089`2' assembly::'struct nominal src, inferred struct target, stays struct@21' + IL_0005: ret + } + + .method assembly specialname static valuetype '<>f__AnonymousType10002306269156`1' 'get_copyOfStruct@21-10'() cil managed + { + + .maxstack 8 + IL_0000: ldsfld valuetype '<>f__AnonymousType10002306269156`1' assembly::'copyOfStruct@21-10' + IL_0005: ret + } + + .method assembly specialname static valuetype '<>f__AnonymousType10002306269156`1' 'get_copyOfStruct@21-11'() cil managed + { + + .maxstack 8 + IL_0000: ldsfld valuetype '<>f__AnonymousType10002306269156`1' assembly::'copyOfStruct@21-11' + IL_0005: ret + } + + .method private specialname rtspecialname static void .cctor() cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.0 + IL_0001: stsfld int32 ''.$assembly::init@ + IL_0006: ldsfld int32 ''.$assembly::init@ + IL_000b: pop + IL_000c: ret + } + + .method assembly static void staticInitialization@() cil managed + { + + .maxstack 4 + IL_0000: ldc.i4.1 + IL_0001: newobj instance void class '<>f__AnonymousType3348076434`1'::.ctor(!0) + IL_0006: stsfld class '<>f__AnonymousType3348076434`1' assembly::refAnonRecd@4 + IL_000b: ldc.i4.1 + IL_000c: newobj instance void valuetype '<>f__AnonymousType10002306269156`1'::.ctor(!0) + IL_0011: stsfld valuetype '<>f__AnonymousType10002306269156`1' assembly::structAnonRecd@5 + IL_0016: ldc.i4.1 + IL_0017: newobj instance void assembly/RefNominalRecd::.ctor(int32) + IL_001c: stsfld class assembly/RefNominalRecd assembly::refNominalRecd@6 + IL_0021: ldc.i4.1 + IL_0022: newobj instance void assembly/StructNominalRecd::.ctor(int32) + IL_0027: stsfld valuetype assembly/StructNominalRecd assembly::structNominalRecd@7 + IL_002c: call class '<>f__AnonymousType3348076434`1' assembly::get_refAnonRecd() + IL_0031: call instance !0 class '<>f__AnonymousType3348076434`1'::get_A() + IL_0036: ldc.i4.2 + IL_0037: newobj instance void class '<>f__AnonymousType3357665219`2'::.ctor(!0, + !1) + IL_003c: stsfld class '<>f__AnonymousType3357665219`2' assembly::'ref anon src, no explicit target, stays ref@9' + IL_0041: call class '<>f__AnonymousType3348076434`1' assembly::get_refAnonRecd() + IL_0046: call instance !0 class '<>f__AnonymousType3348076434`1'::get_A() + IL_004b: ldc.i4.2 + IL_004c: newobj instance void valuetype '<>f__AnonymousType10001789011089`2'::.ctor(!0, + !1) + IL_0051: stsfld valuetype '<>f__AnonymousType10001789011089`2' assembly::'ref anon src, explicit struct target, becomes struct@10' + IL_0056: call class '<>f__AnonymousType3348076434`1' assembly::get_refAnonRecd() + IL_005b: call instance !0 class '<>f__AnonymousType3348076434`1'::get_A() + IL_0060: ldc.i4.2 + IL_0061: newobj instance void valuetype '<>f__AnonymousType10001789011089`2'::.ctor(!0, + !1) + IL_0066: stsfld valuetype '<>f__AnonymousType10001789011089`2' assembly::'ref anon src, inferred struct target, becomes struct@11' + IL_006b: call valuetype '<>f__AnonymousType10002306269156`1' assembly::get_structAnonRecd() + IL_0070: stsfld valuetype '<>f__AnonymousType10002306269156`1' assembly::copyOfStruct@12 + IL_0075: call valuetype '<>f__AnonymousType10002306269156`1' assembly::get_copyOfStruct@12() + IL_007a: stsfld valuetype '<>f__AnonymousType10002306269156`1' assembly::'copyOfStruct@12-1' + IL_007f: ldsflda valuetype '<>f__AnonymousType10002306269156`1' assembly::'copyOfStruct@12-1' + IL_0084: call instance !0 valuetype '<>f__AnonymousType10002306269156`1'::get_A() + IL_0089: ldc.i4.2 + IL_008a: newobj instance void class '<>f__AnonymousType3357665219`2'::.ctor(!0, + !1) + IL_008f: stsfld class '<>f__AnonymousType3357665219`2' assembly::'struct anon src, no explicit target, stays struct@12' + IL_0094: call valuetype '<>f__AnonymousType10002306269156`1' assembly::get_structAnonRecd() + IL_0099: stsfld valuetype '<>f__AnonymousType10002306269156`1' assembly::'copyOfStruct@13-2' + IL_009e: call valuetype '<>f__AnonymousType10002306269156`1' assembly::'get_copyOfStruct@13-2'() + IL_00a3: stsfld valuetype '<>f__AnonymousType10002306269156`1' assembly::'copyOfStruct@13-3' + IL_00a8: ldsflda valuetype '<>f__AnonymousType10002306269156`1' assembly::'copyOfStruct@13-3' + IL_00ad: call instance !0 valuetype '<>f__AnonymousType10002306269156`1'::get_A() + IL_00b2: ldc.i4.2 + IL_00b3: newobj instance void valuetype '<>f__AnonymousType10001789011089`2'::.ctor(!0, + !1) + IL_00b8: stsfld valuetype '<>f__AnonymousType10001789011089`2' assembly::'struct anon src, explicit struct target, stays struct@13' + IL_00bd: call valuetype '<>f__AnonymousType10002306269156`1' assembly::get_structAnonRecd() + IL_00c2: stsfld valuetype '<>f__AnonymousType10002306269156`1' assembly::'copyOfStruct@14-4' + IL_00c7: call valuetype '<>f__AnonymousType10002306269156`1' assembly::'get_copyOfStruct@14-4'() + IL_00cc: stsfld valuetype '<>f__AnonymousType10002306269156`1' assembly::'copyOfStruct@14-5' + IL_00d1: ldsflda valuetype '<>f__AnonymousType10002306269156`1' assembly::'copyOfStruct@14-5' + IL_00d6: call instance !0 valuetype '<>f__AnonymousType10002306269156`1'::get_A() + IL_00db: ldc.i4.2 + IL_00dc: newobj instance void valuetype '<>f__AnonymousType10001789011089`2'::.ctor(!0, + !1) + IL_00e1: stsfld valuetype '<>f__AnonymousType10001789011089`2' assembly::'struct anon src, inferred struct target, stays struct@14' + IL_00e6: call class '<>f__AnonymousType3348076434`1' assembly::get_refAnonRecd() + IL_00eb: call instance !0 class '<>f__AnonymousType3348076434`1'::get_A() + IL_00f0: ldc.i4.2 + IL_00f1: newobj instance void class '<>f__AnonymousType3357665219`2'::.ctor(!0, + !1) + IL_00f6: stsfld class '<>f__AnonymousType3357665219`2' assembly::'ref nominal src, no explicit target, stays ref@16' + IL_00fb: call class '<>f__AnonymousType3348076434`1' assembly::get_refAnonRecd() + IL_0100: call instance !0 class '<>f__AnonymousType3348076434`1'::get_A() + IL_0105: ldc.i4.2 + IL_0106: newobj instance void valuetype '<>f__AnonymousType10001789011089`2'::.ctor(!0, + !1) + IL_010b: stsfld valuetype '<>f__AnonymousType10001789011089`2' assembly::'ref nominal src, explicit struct target, becomes struct@17' + IL_0110: call class '<>f__AnonymousType3348076434`1' assembly::get_refAnonRecd() + IL_0115: call instance !0 class '<>f__AnonymousType3348076434`1'::get_A() + IL_011a: ldc.i4.2 + IL_011b: newobj instance void valuetype '<>f__AnonymousType10001789011089`2'::.ctor(!0, + !1) + IL_0120: stsfld valuetype '<>f__AnonymousType10001789011089`2' assembly::'ref nominal src, inferred struct target, becomes struct@18' + IL_0125: call valuetype '<>f__AnonymousType10002306269156`1' assembly::get_structAnonRecd() + IL_012a: stsfld valuetype '<>f__AnonymousType10002306269156`1' assembly::'copyOfStruct@19-6' + IL_012f: call valuetype '<>f__AnonymousType10002306269156`1' assembly::'get_copyOfStruct@19-6'() + IL_0134: stsfld valuetype '<>f__AnonymousType10002306269156`1' assembly::'copyOfStruct@19-7' + IL_0139: ldsflda valuetype '<>f__AnonymousType10002306269156`1' assembly::'copyOfStruct@19-7' + IL_013e: call instance !0 valuetype '<>f__AnonymousType10002306269156`1'::get_A() + IL_0143: ldc.i4.2 + IL_0144: newobj instance void class '<>f__AnonymousType3357665219`2'::.ctor(!0, + !1) + IL_0149: stsfld class '<>f__AnonymousType3357665219`2' assembly::'struct nominal src, no explicit target, stays struct@19' + IL_014e: call valuetype '<>f__AnonymousType10002306269156`1' assembly::get_structAnonRecd() + IL_0153: stsfld valuetype '<>f__AnonymousType10002306269156`1' assembly::'copyOfStruct@20-8' + IL_0158: call valuetype '<>f__AnonymousType10002306269156`1' assembly::'get_copyOfStruct@20-8'() + IL_015d: stsfld valuetype '<>f__AnonymousType10002306269156`1' assembly::'copyOfStruct@20-9' + IL_0162: ldsflda valuetype '<>f__AnonymousType10002306269156`1' assembly::'copyOfStruct@20-9' + IL_0167: call instance !0 valuetype '<>f__AnonymousType10002306269156`1'::get_A() + IL_016c: ldc.i4.2 + IL_016d: newobj instance void valuetype '<>f__AnonymousType10001789011089`2'::.ctor(!0, + !1) + IL_0172: stsfld valuetype '<>f__AnonymousType10001789011089`2' assembly::'struct nominal src, explicit struct target, stays struct@20' + IL_0177: call valuetype '<>f__AnonymousType10002306269156`1' assembly::get_structAnonRecd() + IL_017c: stsfld valuetype '<>f__AnonymousType10002306269156`1' assembly::'copyOfStruct@21-10' + IL_0181: call valuetype '<>f__AnonymousType10002306269156`1' assembly::'get_copyOfStruct@21-10'() + IL_0186: stsfld valuetype '<>f__AnonymousType10002306269156`1' assembly::'copyOfStruct@21-11' + IL_018b: ldsflda valuetype '<>f__AnonymousType10002306269156`1' assembly::'copyOfStruct@21-11' + IL_0190: call instance !0 valuetype '<>f__AnonymousType10002306269156`1'::get_A() + IL_0195: ldc.i4.2 + IL_0196: newobj instance void valuetype '<>f__AnonymousType10001789011089`2'::.ctor(!0, + !1) + IL_019b: stsfld valuetype '<>f__AnonymousType10001789011089`2' assembly::'struct nominal src, inferred struct target, stays struct@21' + IL_01a0: ret + } + + .property class '<>f__AnonymousType3348076434`1' + refAnonRecd() + { + .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 class '<>f__AnonymousType3348076434`1' assembly::get_refAnonRecd() + } + .property valuetype '<>f__AnonymousType10002306269156`1' + structAnonRecd() + { + .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 valuetype '<>f__AnonymousType10002306269156`1' assembly::get_structAnonRecd() + } + .property class assembly/RefNominalRecd + refNominalRecd() + { + .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 class assembly/RefNominalRecd assembly::get_refNominalRecd() + } + .property valuetype assembly/StructNominalRecd + structNominalRecd() + { + .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 valuetype assembly/StructNominalRecd assembly::get_structNominalRecd() + } + .property class '<>f__AnonymousType3357665219`2' + 'ref anon src, no explicit target, stays ref'() + { + .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 class '<>f__AnonymousType3357665219`2' assembly::'get_ref anon src, no explicit target, stays ref'() + } + .property valuetype '<>f__AnonymousType10001789011089`2' + 'ref anon src, explicit struct target, becomes struct'() + { + .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 valuetype '<>f__AnonymousType10001789011089`2' assembly::'get_ref anon src, explicit struct target, becomes struct'() + } + .property valuetype '<>f__AnonymousType10001789011089`2' + 'ref anon src, inferred struct target, becomes struct'() + { + .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 valuetype '<>f__AnonymousType10001789011089`2' assembly::'get_ref anon src, inferred struct target, becomes struct'() + } + .property class '<>f__AnonymousType3357665219`2' + 'struct anon src, no explicit target, stays struct'() + { + .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 class '<>f__AnonymousType3357665219`2' assembly::'get_struct anon src, no explicit target, stays struct'() + } + .property valuetype '<>f__AnonymousType10002306269156`1' + copyOfStruct@12() + { + .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 valuetype '<>f__AnonymousType10002306269156`1' assembly::get_copyOfStruct@12() + } + .property valuetype '<>f__AnonymousType10002306269156`1' + 'copyOfStruct@12-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 valuetype '<>f__AnonymousType10002306269156`1' assembly::'get_copyOfStruct@12-1'() + } + .property valuetype '<>f__AnonymousType10001789011089`2' + 'struct anon src, explicit struct target, stays struct'() + { + .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 valuetype '<>f__AnonymousType10001789011089`2' assembly::'get_struct anon src, explicit struct target, stays struct'() + } + .property valuetype '<>f__AnonymousType10002306269156`1' + 'copyOfStruct@13-2'() + { + .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 valuetype '<>f__AnonymousType10002306269156`1' assembly::'get_copyOfStruct@13-2'() + } + .property valuetype '<>f__AnonymousType10002306269156`1' + 'copyOfStruct@13-3'() + { + .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 valuetype '<>f__AnonymousType10002306269156`1' assembly::'get_copyOfStruct@13-3'() + } + .property valuetype '<>f__AnonymousType10001789011089`2' + 'struct anon src, inferred struct target, stays struct'() + { + .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 valuetype '<>f__AnonymousType10001789011089`2' assembly::'get_struct anon src, inferred struct target, stays struct'() + } + .property valuetype '<>f__AnonymousType10002306269156`1' + 'copyOfStruct@14-4'() + { + .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 valuetype '<>f__AnonymousType10002306269156`1' assembly::'get_copyOfStruct@14-4'() + } + .property valuetype '<>f__AnonymousType10002306269156`1' + 'copyOfStruct@14-5'() + { + .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 valuetype '<>f__AnonymousType10002306269156`1' assembly::'get_copyOfStruct@14-5'() + } + .property class '<>f__AnonymousType3357665219`2' + 'ref nominal src, no explicit target, stays ref'() + { + .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 class '<>f__AnonymousType3357665219`2' assembly::'get_ref nominal src, no explicit target, stays ref'() + } + .property valuetype '<>f__AnonymousType10001789011089`2' + 'ref nominal src, explicit struct target, becomes struct'() + { + .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 valuetype '<>f__AnonymousType10001789011089`2' assembly::'get_ref nominal src, explicit struct target, becomes struct'() + } + .property valuetype '<>f__AnonymousType10001789011089`2' + 'ref nominal src, inferred struct target, becomes struct'() + { + .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 valuetype '<>f__AnonymousType10001789011089`2' assembly::'get_ref nominal src, inferred struct target, becomes struct'() + } + .property class '<>f__AnonymousType3357665219`2' + 'struct nominal src, no explicit target, stays struct'() + { + .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 class '<>f__AnonymousType3357665219`2' assembly::'get_struct nominal src, no explicit target, stays struct'() + } + .property valuetype '<>f__AnonymousType10002306269156`1' + 'copyOfStruct@19-6'() + { + .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 valuetype '<>f__AnonymousType10002306269156`1' assembly::'get_copyOfStruct@19-6'() + } + .property valuetype '<>f__AnonymousType10002306269156`1' + 'copyOfStruct@19-7'() + { + .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 valuetype '<>f__AnonymousType10002306269156`1' assembly::'get_copyOfStruct@19-7'() + } + .property valuetype '<>f__AnonymousType10001789011089`2' + 'struct nominal src, explicit struct target, stays struct'() + { + .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 valuetype '<>f__AnonymousType10001789011089`2' assembly::'get_struct nominal src, explicit struct target, stays struct'() + } + .property valuetype '<>f__AnonymousType10002306269156`1' + 'copyOfStruct@20-8'() + { + .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 valuetype '<>f__AnonymousType10002306269156`1' assembly::'get_copyOfStruct@20-8'() + } + .property valuetype '<>f__AnonymousType10002306269156`1' + 'copyOfStruct@20-9'() + { + .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 valuetype '<>f__AnonymousType10002306269156`1' assembly::'get_copyOfStruct@20-9'() + } + .property valuetype '<>f__AnonymousType10001789011089`2' + 'struct nominal src, inferred struct target, stays struct'() + { + .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 valuetype '<>f__AnonymousType10001789011089`2' assembly::'get_struct nominal src, inferred struct target, stays struct'() + } + .property valuetype '<>f__AnonymousType10002306269156`1' + 'copyOfStruct@21-10'() + { + .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 valuetype '<>f__AnonymousType10002306269156`1' assembly::'get_copyOfStruct@21-10'() + } + .property valuetype '<>f__AnonymousType10002306269156`1' + 'copyOfStruct@21-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 valuetype '<>f__AnonymousType10002306269156`1' assembly::'get_copyOfStruct@21-11'() + } +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .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 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: call void assembly::staticInitialization@() + IL_0005: ret + } + +} + +.class public auto ansi serializable sealed beforefieldinit '<>f__AnonymousType10001789011089`2'<'j__TPar','j__TPar'> + extends [runtime]System.ValueType + implements [runtime]System.Collections.IStructuralComparable, + [runtime]System.IComparable, + class [runtime]System.IComparable`1f__AnonymousType10001789011089`2'j__TPar',!'j__TPar'>>, + [runtime]System.Collections.IStructuralEquatable, + class [runtime]System.IEquatable`1f__AnonymousType10001789011089`2'j__TPar',!'j__TPar'>> +{ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field private !'j__TPar' A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field private !'j__TPar' B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor(!'j__TPar' A, !'j__TPar' B) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 22 3C 3E 66 5F 5F 41 6E 6F 6E + 79 6D 6F 75 73 54 79 70 65 31 30 30 30 31 37 38 + 39 30 31 31 30 38 39 60 32 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld !0 valuetype '<>f__AnonymousType10001789011089`2'j__TPar',!'j__TPar'>::A@ + IL_0007: ldarg.0 + IL_0008: ldarg.2 + IL_0009: stfld !1 valuetype '<>f__AnonymousType10001789011089`2'j__TPar',!'j__TPar'>::B@ + IL_000e: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_A() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + .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: ldfld !0 valuetype '<>f__AnonymousType10001789011089`2'j__TPar',!'j__TPar'>::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_B() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + .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: ldfld !1 valuetype '<>f__AnonymousType10001789011089`2'j__TPar',!'j__TPar'>::B@ + IL_0006: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5f__AnonymousType10001789011089`2'j__TPar',!'j__TPar'>,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,valuetype '<>f__AnonymousType10001789011089`2'j__TPar',!'j__TPar'>>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToStringf__AnonymousType10001789011089`2'j__TPar',!'j__TPar'>,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: ldobj valuetype '<>f__AnonymousType10001789011089`2'j__TPar',!'j__TPar'> + IL_0015: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2f__AnonymousType10001789011089`2'j__TPar',!'j__TPar'>,string>::Invoke(!0) + IL_001a: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(valuetype '<>f__AnonymousType10001789011089`2'j__TPar',!'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (valuetype '<>f__AnonymousType10001789011089`2'j__TPar',!'j__TPar'>& V_0, + int32 V_1) + IL_0000: ldarga.s obj + IL_0002: stloc.0 + IL_0003: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_0008: ldarg.0 + IL_0009: ldfld !0 valuetype '<>f__AnonymousType10001789011089`2'j__TPar',!'j__TPar'>::A@ + IL_000e: ldloc.0 + IL_000f: ldfld !0 valuetype '<>f__AnonymousType10001789011089`2'j__TPar',!'j__TPar'>::A@ + IL_0014: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0019: stloc.1 + IL_001a: ldloc.1 + IL_001b: ldc.i4.0 + IL_001c: bge.s IL_0020 + + IL_001e: ldloc.1 + IL_001f: ret + + IL_0020: ldloc.1 + IL_0021: ldc.i4.0 + IL_0022: ble.s IL_0026 + + IL_0024: ldloc.1 + IL_0025: ret + + IL_0026: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_002b: ldarg.0 + IL_002c: ldfld !1 valuetype '<>f__AnonymousType10001789011089`2'j__TPar',!'j__TPar'>::B@ + IL_0031: ldloc.0 + IL_0032: ldfld !1 valuetype '<>f__AnonymousType10001789011089`2'j__TPar',!'j__TPar'>::B@ + IL_0037: tail. + IL_0039: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_003e: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: unbox.any valuetype '<>f__AnonymousType10001789011089`2'j__TPar',!'j__TPar'> + IL_0007: call instance int32 valuetype '<>f__AnonymousType10001789011089`2'j__TPar',!'j__TPar'>::CompareTo(valuetype '<>f__AnonymousType10001789011089`2') + IL_000c: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj, class [runtime]System.Collections.IComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (valuetype '<>f__AnonymousType10001789011089`2'j__TPar',!'j__TPar'> V_0, + valuetype '<>f__AnonymousType10001789011089`2'j__TPar',!'j__TPar'>& V_1, + int32 V_2) + IL_0000: ldarg.1 + IL_0001: unbox.any valuetype '<>f__AnonymousType10001789011089`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloca.s V_0 + IL_0009: stloc.1 + IL_000a: ldarg.2 + IL_000b: ldarg.0 + IL_000c: ldfld !0 valuetype '<>f__AnonymousType10001789011089`2'j__TPar',!'j__TPar'>::A@ + IL_0011: ldloc.1 + IL_0012: ldfld !0 valuetype '<>f__AnonymousType10001789011089`2'j__TPar',!'j__TPar'>::A@ + IL_0017: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_001c: stloc.2 + IL_001d: ldloc.2 + IL_001e: ldc.i4.0 + IL_001f: bge.s IL_0023 + + IL_0021: ldloc.2 + IL_0022: ret + + IL_0023: ldloc.2 + IL_0024: ldc.i4.0 + IL_0025: ble.s IL_0029 + + IL_0027: ldloc.2 + IL_0028: ret + + IL_0029: ldarg.2 + IL_002a: ldarg.0 + IL_002b: ldfld !1 valuetype '<>f__AnonymousType10001789011089`2'j__TPar',!'j__TPar'>::B@ + IL_0030: ldloc.1 + IL_0031: ldfld !1 valuetype '<>f__AnonymousType10001789011089`2'j__TPar',!'j__TPar'>::B@ + IL_0036: tail. + IL_0038: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_003d: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode(class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 7 + .locals init (int32 V_0) + IL_0000: ldc.i4.0 + IL_0001: stloc.0 + IL_0002: ldc.i4 0x9e3779b9 + IL_0007: ldarg.1 + IL_0008: ldarg.0 + IL_0009: ldfld !1 valuetype '<>f__AnonymousType10001789011089`2'j__TPar',!'j__TPar'>::B@ + IL_000e: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0013: ldloc.0 + IL_0014: ldc.i4.6 + IL_0015: shl + IL_0016: ldloc.0 + IL_0017: ldc.i4.2 + IL_0018: shr + IL_0019: add + IL_001a: add + IL_001b: add + IL_001c: stloc.0 + IL_001d: ldc.i4 0x9e3779b9 + IL_0022: ldarg.1 + IL_0023: ldarg.0 + IL_0024: ldfld !0 valuetype '<>f__AnonymousType10001789011089`2'j__TPar',!'j__TPar'>::A@ + IL_0029: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_002e: ldloc.0 + IL_002f: ldc.i4.6 + IL_0030: shl + IL_0031: ldloc.0 + IL_0032: ldc.i4.2 + IL_0033: shr + IL_0034: add + IL_0035: add + IL_0036: add + IL_0037: stloc.0 + IL_0038: ldloc.0 + IL_0039: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() + IL_0006: call instance int32 valuetype '<>f__AnonymousType10001789011089`2'j__TPar',!'j__TPar'>::GetHashCode(class [runtime]System.Collections.IEqualityComparer) + IL_000b: ret + } + + .method public hidebysig instance bool Equals(valuetype '<>f__AnonymousType10001789011089`2'j__TPar',!'j__TPar'> obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (valuetype '<>f__AnonymousType10001789011089`2'j__TPar',!'j__TPar'>& V_0) + IL_0000: ldarga.s obj + IL_0002: stloc.0 + IL_0003: ldarg.2 + IL_0004: ldarg.0 + IL_0005: ldfld !0 valuetype '<>f__AnonymousType10001789011089`2'j__TPar',!'j__TPar'>::A@ + IL_000a: ldloc.0 + IL_000b: ldfld !0 valuetype '<>f__AnonymousType10001789011089`2'j__TPar',!'j__TPar'>::A@ + IL_0010: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_0015: brfalse.s IL_002c + + IL_0017: ldarg.2 + IL_0018: ldarg.0 + IL_0019: ldfld !1 valuetype '<>f__AnonymousType10001789011089`2'j__TPar',!'j__TPar'>::B@ + IL_001e: ldloc.0 + IL_001f: ldfld !1 valuetype '<>f__AnonymousType10001789011089`2'j__TPar',!'j__TPar'>::B@ + IL_0024: tail. + IL_0026: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_002b: ret + + IL_002c: ldc.i4.0 + IL_002d: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (valuetype '<>f__AnonymousType10001789011089`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives/IntrinsicFunctions::TypeTestGenericf__AnonymousType10001789011089`2'j__TPar',!'j__TPar'>>(object) + IL_0006: brtrue.s IL_000a + + IL_0008: br.s IL_001a + + IL_000a: ldarg.1 + IL_000b: call !!0 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives/IntrinsicFunctions::UnboxGenericf__AnonymousType10001789011089`2'j__TPar',!'j__TPar'>>(object) + IL_0010: stloc.0 + IL_0011: ldarg.0 + IL_0012: ldloc.0 + IL_0013: ldarg.2 + IL_0014: call instance bool valuetype '<>f__AnonymousType10001789011089`2'j__TPar',!'j__TPar'>::Equals(valuetype '<>f__AnonymousType10001789011089`2', + class [runtime]System.Collections.IEqualityComparer) + IL_0019: ret + + IL_001a: ldc.i4.0 + IL_001b: ret + } + + .method public hidebysig virtual final instance bool Equals(valuetype '<>f__AnonymousType10001789011089`2'j__TPar',!'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (valuetype '<>f__AnonymousType10001789011089`2'j__TPar',!'j__TPar'>& V_0) + IL_0000: ldarga.s obj + IL_0002: stloc.0 + IL_0003: ldarg.0 + IL_0004: ldfld !0 valuetype '<>f__AnonymousType10001789011089`2'j__TPar',!'j__TPar'>::A@ + IL_0009: ldloc.0 + IL_000a: ldfld !0 valuetype '<>f__AnonymousType10001789011089`2'j__TPar',!'j__TPar'>::A@ + IL_000f: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_0014: brfalse.s IL_002a + + IL_0016: ldarg.0 + IL_0017: ldfld !1 valuetype '<>f__AnonymousType10001789011089`2'j__TPar',!'j__TPar'>::B@ + IL_001c: ldloc.0 + IL_001d: ldfld !1 valuetype '<>f__AnonymousType10001789011089`2'j__TPar',!'j__TPar'>::B@ + IL_0022: tail. + IL_0024: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_0029: ret + + IL_002a: ldc.i4.0 + IL_002b: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (valuetype '<>f__AnonymousType10001789011089`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives/IntrinsicFunctions::TypeTestGenericf__AnonymousType10001789011089`2'j__TPar',!'j__TPar'>>(object) + IL_0006: brtrue.s IL_000a + + IL_0008: br.s IL_0019 + + IL_000a: ldarg.1 + IL_000b: call !!0 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives/IntrinsicFunctions::UnboxGenericf__AnonymousType10001789011089`2'j__TPar',!'j__TPar'>>(object) + IL_0010: stloc.0 + IL_0011: ldarg.0 + IL_0012: ldloc.0 + IL_0013: call instance bool valuetype '<>f__AnonymousType10001789011089`2'j__TPar',!'j__TPar'>::Equals(valuetype '<>f__AnonymousType10001789011089`2') + IL_0018: ret + + IL_0019: ldc.i4.0 + IL_001a: ret + } + + .property instance !'j__TPar' A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType10001789011089`2'::get_A() + } + .property instance !'j__TPar' B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType10001789011089`2'::get_B() + } +} + +.class public auto ansi serializable sealed beforefieldinit '<>f__AnonymousType10002306269156`1'<'j__TPar'> + extends [runtime]System.ValueType + implements [runtime]System.Collections.IStructuralComparable, + [runtime]System.IComparable, + class [runtime]System.IComparable`1f__AnonymousType10002306269156`1'j__TPar'>>, + [runtime]System.Collections.IStructuralEquatable, + class [runtime]System.IEquatable`1f__AnonymousType10002306269156`1'j__TPar'>> +{ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field private !'j__TPar' A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor(!'j__TPar' A) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 22 3C 3E 66 5F 5F 41 6E 6F 6E + 79 6D 6F 75 73 54 79 70 65 31 30 30 30 32 33 30 + 36 32 36 39 31 35 36 60 31 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld !0 valuetype '<>f__AnonymousType10002306269156`1'j__TPar'>::A@ + IL_0007: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_A() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + .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: ldfld !0 valuetype '<>f__AnonymousType10002306269156`1'j__TPar'>::A@ + IL_0006: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5f__AnonymousType10002306269156`1'j__TPar'>,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,valuetype '<>f__AnonymousType10002306269156`1'j__TPar'>>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToStringf__AnonymousType10002306269156`1'j__TPar'>,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: ldobj valuetype '<>f__AnonymousType10002306269156`1'j__TPar'> + IL_0015: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2f__AnonymousType10002306269156`1'j__TPar'>,string>::Invoke(!0) + IL_001a: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(valuetype '<>f__AnonymousType10002306269156`1'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (valuetype '<>f__AnonymousType10002306269156`1'j__TPar'>& V_0) + IL_0000: ldarga.s obj + IL_0002: stloc.0 + IL_0003: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_0008: ldarg.0 + IL_0009: ldfld !0 valuetype '<>f__AnonymousType10002306269156`1'j__TPar'>::A@ + IL_000e: ldloc.0 + IL_000f: ldfld !0 valuetype '<>f__AnonymousType10002306269156`1'j__TPar'>::A@ + IL_0014: tail. + IL_0016: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_001b: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: unbox.any valuetype '<>f__AnonymousType10002306269156`1'j__TPar'> + IL_0007: call instance int32 valuetype '<>f__AnonymousType10002306269156`1'j__TPar'>::CompareTo(valuetype '<>f__AnonymousType10002306269156`1') + IL_000c: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj, class [runtime]System.Collections.IComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (valuetype '<>f__AnonymousType10002306269156`1'j__TPar'> V_0, + valuetype '<>f__AnonymousType10002306269156`1'j__TPar'>& V_1) + IL_0000: ldarg.1 + IL_0001: unbox.any valuetype '<>f__AnonymousType10002306269156`1'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloca.s V_0 + IL_0009: stloc.1 + IL_000a: ldarg.2 + IL_000b: ldarg.0 + IL_000c: ldfld !0 valuetype '<>f__AnonymousType10002306269156`1'j__TPar'>::A@ + IL_0011: ldloc.1 + IL_0012: ldfld !0 valuetype '<>f__AnonymousType10002306269156`1'j__TPar'>::A@ + IL_0017: tail. + IL_0019: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_001e: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode(class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 7 + .locals init (int32 V_0) + IL_0000: ldc.i4.0 + IL_0001: stloc.0 + IL_0002: ldc.i4 0x9e3779b9 + IL_0007: ldarg.1 + IL_0008: ldarg.0 + IL_0009: ldfld !0 valuetype '<>f__AnonymousType10002306269156`1'j__TPar'>::A@ + IL_000e: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0013: ldloc.0 + IL_0014: ldc.i4.6 + IL_0015: shl + IL_0016: ldloc.0 + IL_0017: ldc.i4.2 + IL_0018: shr + IL_0019: add + IL_001a: add + IL_001b: add + IL_001c: stloc.0 + IL_001d: ldloc.0 + IL_001e: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() + IL_0006: call instance int32 valuetype '<>f__AnonymousType10002306269156`1'j__TPar'>::GetHashCode(class [runtime]System.Collections.IEqualityComparer) + IL_000b: ret + } + + .method public hidebysig instance bool Equals(valuetype '<>f__AnonymousType10002306269156`1'j__TPar'> obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (valuetype '<>f__AnonymousType10002306269156`1'j__TPar'>& V_0) + IL_0000: ldarga.s obj + IL_0002: stloc.0 + IL_0003: ldarg.2 + IL_0004: ldarg.0 + IL_0005: ldfld !0 valuetype '<>f__AnonymousType10002306269156`1'j__TPar'>::A@ + IL_000a: ldloc.0 + IL_000b: ldfld !0 valuetype '<>f__AnonymousType10002306269156`1'j__TPar'>::A@ + IL_0010: tail. + IL_0012: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_0017: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (valuetype '<>f__AnonymousType10002306269156`1'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives/IntrinsicFunctions::TypeTestGenericf__AnonymousType10002306269156`1'j__TPar'>>(object) + IL_0006: brtrue.s IL_000a + + IL_0008: br.s IL_001a + + IL_000a: ldarg.1 + IL_000b: call !!0 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives/IntrinsicFunctions::UnboxGenericf__AnonymousType10002306269156`1'j__TPar'>>(object) + IL_0010: stloc.0 + IL_0011: ldarg.0 + IL_0012: ldloc.0 + IL_0013: ldarg.2 + IL_0014: call instance bool valuetype '<>f__AnonymousType10002306269156`1'j__TPar'>::Equals(valuetype '<>f__AnonymousType10002306269156`1', + class [runtime]System.Collections.IEqualityComparer) + IL_0019: ret + + IL_001a: ldc.i4.0 + IL_001b: ret + } + + .method public hidebysig virtual final instance bool Equals(valuetype '<>f__AnonymousType10002306269156`1'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (valuetype '<>f__AnonymousType10002306269156`1'j__TPar'>& V_0) + IL_0000: ldarga.s obj + IL_0002: stloc.0 + IL_0003: ldarg.0 + IL_0004: ldfld !0 valuetype '<>f__AnonymousType10002306269156`1'j__TPar'>::A@ + IL_0009: ldloc.0 + IL_000a: ldfld !0 valuetype '<>f__AnonymousType10002306269156`1'j__TPar'>::A@ + IL_000f: tail. + IL_0011: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_0016: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (valuetype '<>f__AnonymousType10002306269156`1'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives/IntrinsicFunctions::TypeTestGenericf__AnonymousType10002306269156`1'j__TPar'>>(object) + IL_0006: brtrue.s IL_000a + + IL_0008: br.s IL_0019 + + IL_000a: ldarg.1 + IL_000b: call !!0 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives/IntrinsicFunctions::UnboxGenericf__AnonymousType10002306269156`1'j__TPar'>>(object) + IL_0010: stloc.0 + IL_0011: ldarg.0 + IL_0012: ldloc.0 + IL_0013: call instance bool valuetype '<>f__AnonymousType10002306269156`1'j__TPar'>::Equals(valuetype '<>f__AnonymousType10002306269156`1') + IL_0018: ret + + IL_0019: ldc.i4.0 + IL_001a: ret + } + + .property instance !'j__TPar' A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType10002306269156`1'::get_A() + } +} + +.class public auto ansi serializable sealed beforefieldinit '<>f__AnonymousType3348076434`1'<'j__TPar'> + extends [runtime]System.Object + implements [runtime]System.Collections.IStructuralComparable, + [runtime]System.IComparable, + class [runtime]System.IComparable`1f__AnonymousType3348076434`1'j__TPar'>>, + [runtime]System.Collections.IStructuralEquatable, + class [runtime]System.IEquatable`1f__AnonymousType3348076434`1'j__TPar'>> +{ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field private !'j__TPar' A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor(!'j__TPar' A) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 1E 3C 3E 66 5F 5F 41 6E 6F 6E + 79 6D 6F 75 73 54 79 70 65 33 33 34 38 30 37 36 + 34 33 34 60 31 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld !0 class '<>f__AnonymousType3348076434`1'j__TPar'>::A@ + IL_000d: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_A() 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: ldfld !0 class '<>f__AnonymousType3348076434`1'j__TPar'>::A@ + IL_0006: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5f__AnonymousType3348076434`1'j__TPar'>,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class '<>f__AnonymousType3348076434`1'j__TPar'>>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToStringf__AnonymousType3348076434`1'j__TPar'>,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2f__AnonymousType3348076434`1'j__TPar'>,string>::Invoke(!0) + IL_0015: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(class '<>f__AnonymousType3348076434`1'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0021 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_001f + + IL_0006: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_000b: ldarg.0 + IL_000c: ldfld !0 class '<>f__AnonymousType3348076434`1'j__TPar'>::A@ + IL_0011: ldarg.1 + IL_0012: ldfld !0 class '<>f__AnonymousType3348076434`1'j__TPar'>::A@ + IL_0017: tail. + IL_0019: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_001e: ret + + IL_001f: ldc.i4.1 + IL_0020: ret + + IL_0021: ldarg.1 + IL_0022: brfalse.s IL_0026 + + IL_0024: ldc.i4.m1 + IL_0025: ret + + IL_0026: ldc.i4.0 + IL_0027: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: unbox.any class '<>f__AnonymousType3348076434`1'j__TPar'> + IL_0007: tail. + IL_0009: callvirt instance int32 class '<>f__AnonymousType3348076434`1'j__TPar'>::CompareTo(class '<>f__AnonymousType3348076434`1') + IL_000e: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj, class [runtime]System.Collections.IComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType3348076434`1'j__TPar'> V_0, + class '<>f__AnonymousType3348076434`1'j__TPar'> V_1) + IL_0000: ldarg.1 + IL_0001: unbox.any class '<>f__AnonymousType3348076434`1'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: stloc.1 + IL_0009: ldarg.0 + IL_000a: brfalse.s IL_002b + + IL_000c: ldarg.1 + IL_000d: unbox.any class '<>f__AnonymousType3348076434`1'j__TPar'> + IL_0012: brfalse.s IL_0029 + + IL_0014: ldarg.2 + IL_0015: ldarg.0 + IL_0016: ldfld !0 class '<>f__AnonymousType3348076434`1'j__TPar'>::A@ + IL_001b: ldloc.1 + IL_001c: ldfld !0 class '<>f__AnonymousType3348076434`1'j__TPar'>::A@ + IL_0021: tail. + IL_0023: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0028: ret + + IL_0029: ldc.i4.1 + IL_002a: ret + + IL_002b: ldarg.1 + IL_002c: unbox.any class '<>f__AnonymousType3348076434`1'j__TPar'> + IL_0031: brfalse.s IL_0035 + + IL_0033: ldc.i4.m1 + IL_0034: ret + + IL_0035: ldc.i4.0 + IL_0036: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode(class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 7 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0022 + + IL_0003: ldc.i4.0 + IL_0004: stloc.0 + IL_0005: ldc.i4 0x9e3779b9 + IL_000a: ldarg.1 + IL_000b: ldarg.0 + IL_000c: ldfld !0 class '<>f__AnonymousType3348076434`1'j__TPar'>::A@ + IL_0011: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0016: ldloc.0 + IL_0017: ldc.i4.6 + IL_0018: shl + IL_0019: ldloc.0 + IL_001a: ldc.i4.2 + IL_001b: shr + IL_001c: add + IL_001d: add + IL_001e: add + IL_001f: stloc.0 + IL_0020: ldloc.0 + IL_0021: ret + + IL_0022: ldc.i4.0 + IL_0023: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() + IL_0006: tail. + IL_0008: callvirt instance int32 class '<>f__AnonymousType3348076434`1'j__TPar'>::GetHashCode(class [runtime]System.Collections.IEqualityComparer) + IL_000d: ret + } + + .method public hidebysig instance bool Equals(class '<>f__AnonymousType3348076434`1'j__TPar'> obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType3348076434`1'j__TPar'> V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_001f + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_001d + + IL_0006: ldarg.1 + IL_0007: stloc.0 + IL_0008: ldarg.2 + IL_0009: ldarg.0 + IL_000a: ldfld !0 class '<>f__AnonymousType3348076434`1'j__TPar'>::A@ + IL_000f: ldloc.0 + IL_0010: ldfld !0 class '<>f__AnonymousType3348076434`1'j__TPar'>::A@ + IL_0015: tail. + IL_0017: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_001c: ret + + IL_001d: ldc.i4.0 + IL_001e: ret + + IL_001f: ldarg.1 + IL_0020: ldnull + IL_0021: cgt.un + IL_0023: ldc.i4.0 + IL_0024: ceq + IL_0026: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType3348076434`1'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType3348076434`1'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0015 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: ldarg.2 + IL_000d: tail. + IL_000f: callvirt instance bool class '<>f__AnonymousType3348076434`1'j__TPar'>::Equals(class '<>f__AnonymousType3348076434`1', + class [runtime]System.Collections.IEqualityComparer) + IL_0014: ret + + IL_0015: ldc.i4.0 + IL_0016: ret + } + + .method public hidebysig virtual final instance bool Equals(class '<>f__AnonymousType3348076434`1'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_001c + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_001a + + IL_0006: ldarg.0 + IL_0007: ldfld !0 class '<>f__AnonymousType3348076434`1'j__TPar'>::A@ + IL_000c: ldarg.1 + IL_000d: ldfld !0 class '<>f__AnonymousType3348076434`1'j__TPar'>::A@ + IL_0012: tail. + IL_0014: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_0019: ret + + IL_001a: ldc.i4.0 + IL_001b: ret + + IL_001c: ldarg.1 + IL_001d: ldnull + IL_001e: cgt.un + IL_0020: ldc.i4.0 + IL_0021: ceq + IL_0023: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (class '<>f__AnonymousType3348076434`1'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType3348076434`1'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0014 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: tail. + IL_000e: callvirt instance bool class '<>f__AnonymousType3348076434`1'j__TPar'>::Equals(class '<>f__AnonymousType3348076434`1') + IL_0013: ret + + IL_0014: ldc.i4.0 + IL_0015: ret + } + + .property instance !'j__TPar' A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType3348076434`1'::get_A() + } +} + +.class public auto ansi serializable sealed beforefieldinit '<>f__AnonymousType3357665219`2'<'j__TPar','j__TPar'> + extends [runtime]System.Object + implements [runtime]System.Collections.IStructuralComparable, + [runtime]System.IComparable, + class [runtime]System.IComparable`1f__AnonymousType3357665219`2'j__TPar',!'j__TPar'>>, + [runtime]System.Collections.IStructuralEquatable, + class [runtime]System.IEquatable`1f__AnonymousType3357665219`2'j__TPar',!'j__TPar'>> +{ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field private !'j__TPar' A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field private !'j__TPar' B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor(!'j__TPar' A, !'j__TPar' B) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 1E 3C 3E 66 5F 5F 41 6E 6F 6E + 79 6D 6F 75 73 54 79 70 65 33 33 35 37 36 36 35 + 32 31 39 60 32 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld !0 class '<>f__AnonymousType3357665219`2'j__TPar',!'j__TPar'>::A@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld !1 class '<>f__AnonymousType3357665219`2'j__TPar',!'j__TPar'>::B@ + IL_0014: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_A() 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: ldfld !0 class '<>f__AnonymousType3357665219`2'j__TPar',!'j__TPar'>::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_B() 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: ldfld !1 class '<>f__AnonymousType3357665219`2'j__TPar',!'j__TPar'>::B@ + IL_0006: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5f__AnonymousType3357665219`2'j__TPar',!'j__TPar'>,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class '<>f__AnonymousType3357665219`2'j__TPar',!'j__TPar'>>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToStringf__AnonymousType3357665219`2'j__TPar',!'j__TPar'>,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2f__AnonymousType3357665219`2'j__TPar',!'j__TPar'>,string>::Invoke(!0) + IL_0015: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(class '<>f__AnonymousType3357665219`2'j__TPar',!'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0044 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0042 + + IL_0006: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_000b: ldarg.0 + IL_000c: ldfld !0 class '<>f__AnonymousType3357665219`2'j__TPar',!'j__TPar'>::A@ + IL_0011: ldarg.1 + IL_0012: ldfld !0 class '<>f__AnonymousType3357665219`2'j__TPar',!'j__TPar'>::A@ + IL_0017: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_001c: stloc.0 + IL_001d: ldloc.0 + IL_001e: ldc.i4.0 + IL_001f: bge.s IL_0023 + + IL_0021: ldloc.0 + IL_0022: ret + + IL_0023: ldloc.0 + IL_0024: ldc.i4.0 + IL_0025: ble.s IL_0029 + + IL_0027: ldloc.0 + IL_0028: ret + + IL_0029: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_002e: ldarg.0 + IL_002f: ldfld !1 class '<>f__AnonymousType3357665219`2'j__TPar',!'j__TPar'>::B@ + IL_0034: ldarg.1 + IL_0035: ldfld !1 class '<>f__AnonymousType3357665219`2'j__TPar',!'j__TPar'>::B@ + IL_003a: tail. + IL_003c: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0041: ret + + IL_0042: ldc.i4.1 + IL_0043: ret + + IL_0044: ldarg.1 + IL_0045: brfalse.s IL_0049 + + IL_0047: ldc.i4.m1 + IL_0048: ret + + IL_0049: ldc.i4.0 + IL_004a: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: unbox.any class '<>f__AnonymousType3357665219`2'j__TPar',!'j__TPar'> + IL_0007: tail. + IL_0009: callvirt instance int32 class '<>f__AnonymousType3357665219`2'j__TPar',!'j__TPar'>::CompareTo(class '<>f__AnonymousType3357665219`2') + IL_000e: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj, class [runtime]System.Collections.IComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType3357665219`2'j__TPar',!'j__TPar'> V_0, + class '<>f__AnonymousType3357665219`2'j__TPar',!'j__TPar'> V_1, + int32 V_2) + IL_0000: ldarg.1 + IL_0001: unbox.any class '<>f__AnonymousType3357665219`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: stloc.1 + IL_0009: ldarg.0 + IL_000a: brfalse.s IL_004a + + IL_000c: ldarg.1 + IL_000d: unbox.any class '<>f__AnonymousType3357665219`2'j__TPar',!'j__TPar'> + IL_0012: brfalse.s IL_0048 + + IL_0014: ldarg.2 + IL_0015: ldarg.0 + IL_0016: ldfld !0 class '<>f__AnonymousType3357665219`2'j__TPar',!'j__TPar'>::A@ + IL_001b: ldloc.1 + IL_001c: ldfld !0 class '<>f__AnonymousType3357665219`2'j__TPar',!'j__TPar'>::A@ + IL_0021: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0026: stloc.2 + IL_0027: ldloc.2 + IL_0028: ldc.i4.0 + IL_0029: bge.s IL_002d + + IL_002b: ldloc.2 + IL_002c: ret + + IL_002d: ldloc.2 + IL_002e: ldc.i4.0 + IL_002f: ble.s IL_0033 + + IL_0031: ldloc.2 + IL_0032: ret + + IL_0033: ldarg.2 + IL_0034: ldarg.0 + IL_0035: ldfld !1 class '<>f__AnonymousType3357665219`2'j__TPar',!'j__TPar'>::B@ + IL_003a: ldloc.1 + IL_003b: ldfld !1 class '<>f__AnonymousType3357665219`2'j__TPar',!'j__TPar'>::B@ + IL_0040: tail. + IL_0042: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0047: ret + + IL_0048: ldc.i4.1 + IL_0049: ret + + IL_004a: ldarg.1 + IL_004b: unbox.any class '<>f__AnonymousType3357665219`2'j__TPar',!'j__TPar'> + IL_0050: brfalse.s IL_0054 + + IL_0052: ldc.i4.m1 + IL_0053: ret + + IL_0054: ldc.i4.0 + IL_0055: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode(class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 7 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_003d + + IL_0003: ldc.i4.0 + IL_0004: stloc.0 + IL_0005: ldc.i4 0x9e3779b9 + IL_000a: ldarg.1 + IL_000b: ldarg.0 + IL_000c: ldfld !1 class '<>f__AnonymousType3357665219`2'j__TPar',!'j__TPar'>::B@ + IL_0011: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0016: ldloc.0 + IL_0017: ldc.i4.6 + IL_0018: shl + IL_0019: ldloc.0 + IL_001a: ldc.i4.2 + IL_001b: shr + IL_001c: add + IL_001d: add + IL_001e: add + IL_001f: stloc.0 + IL_0020: ldc.i4 0x9e3779b9 + IL_0025: ldarg.1 + IL_0026: ldarg.0 + IL_0027: ldfld !0 class '<>f__AnonymousType3357665219`2'j__TPar',!'j__TPar'>::A@ + IL_002c: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0031: ldloc.0 + IL_0032: ldc.i4.6 + IL_0033: shl + IL_0034: ldloc.0 + IL_0035: ldc.i4.2 + IL_0036: shr + IL_0037: add + IL_0038: add + IL_0039: add + IL_003a: stloc.0 + IL_003b: ldloc.0 + IL_003c: ret + + IL_003d: ldc.i4.0 + IL_003e: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() + IL_0006: tail. + IL_0008: callvirt instance int32 class '<>f__AnonymousType3357665219`2'j__TPar',!'j__TPar'>::GetHashCode(class [runtime]System.Collections.IEqualityComparer) + IL_000d: ret + } + + .method public hidebysig instance bool Equals(class '<>f__AnonymousType3357665219`2'j__TPar',!'j__TPar'> obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType3357665219`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0035 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0033 + + IL_0006: ldarg.1 + IL_0007: stloc.0 + IL_0008: ldarg.2 + IL_0009: ldarg.0 + IL_000a: ldfld !0 class '<>f__AnonymousType3357665219`2'j__TPar',!'j__TPar'>::A@ + IL_000f: ldloc.0 + IL_0010: ldfld !0 class '<>f__AnonymousType3357665219`2'j__TPar',!'j__TPar'>::A@ + IL_0015: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_001a: brfalse.s IL_0031 + + IL_001c: ldarg.2 + IL_001d: ldarg.0 + IL_001e: ldfld !1 class '<>f__AnonymousType3357665219`2'j__TPar',!'j__TPar'>::B@ + IL_0023: ldloc.0 + IL_0024: ldfld !1 class '<>f__AnonymousType3357665219`2'j__TPar',!'j__TPar'>::B@ + IL_0029: tail. + IL_002b: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_0030: ret + + IL_0031: ldc.i4.0 + IL_0032: ret + + IL_0033: ldc.i4.0 + IL_0034: ret + + IL_0035: ldarg.1 + IL_0036: ldnull + IL_0037: cgt.un + IL_0039: ldc.i4.0 + IL_003a: ceq + IL_003c: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType3357665219`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType3357665219`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0015 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: ldarg.2 + IL_000d: tail. + IL_000f: callvirt instance bool class '<>f__AnonymousType3357665219`2'j__TPar',!'j__TPar'>::Equals(class '<>f__AnonymousType3357665219`2', + class [runtime]System.Collections.IEqualityComparer) + IL_0014: ret + + IL_0015: ldc.i4.0 + IL_0016: ret + } + + .method public hidebysig virtual final instance bool Equals(class '<>f__AnonymousType3357665219`2'j__TPar',!'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0031 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_002f + + IL_0006: ldarg.0 + IL_0007: ldfld !0 class '<>f__AnonymousType3357665219`2'j__TPar',!'j__TPar'>::A@ + IL_000c: ldarg.1 + IL_000d: ldfld !0 class '<>f__AnonymousType3357665219`2'j__TPar',!'j__TPar'>::A@ + IL_0012: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_0017: brfalse.s IL_002d + + IL_0019: ldarg.0 + IL_001a: ldfld !1 class '<>f__AnonymousType3357665219`2'j__TPar',!'j__TPar'>::B@ + IL_001f: ldarg.1 + IL_0020: ldfld !1 class '<>f__AnonymousType3357665219`2'j__TPar',!'j__TPar'>::B@ + IL_0025: tail. + IL_0027: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_002c: ret + + IL_002d: ldc.i4.0 + IL_002e: ret + + IL_002f: ldc.i4.0 + IL_0030: ret + + IL_0031: ldarg.1 + IL_0032: ldnull + IL_0033: cgt.un + IL_0035: ldc.i4.0 + IL_0036: ceq + IL_0038: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (class '<>f__AnonymousType3357665219`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType3357665219`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0014 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: tail. + IL_000e: callvirt instance bool class '<>f__AnonymousType3357665219`2'j__TPar',!'j__TPar'>::Equals(class '<>f__AnonymousType3357665219`2') + IL_0013: ret + + IL_0014: ldc.i4.0 + IL_0015: ret + } + + .property instance !'j__TPar' A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType3357665219`2'::get_A() + } + .property instance !'j__TPar' B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType3357665219`2'::get_B() + } +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_CoercionsApplied.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_CoercionsApplied.fs new file mode 100644 index 00000000000..894c4b0a063 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_CoercionsApplied.fs @@ -0,0 +1,14 @@ +type T = + | T of int + static member op_Implicit (T t) = U t + +and U = + | U of int + +type R1 = { A : T } +type R2 = { A : U } + +#nowarn 3391 + +let r1 : R1 = { A = T 3 } +let r2 : R2 = { ...r1 } diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_CoercionsApplied.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_CoercionsApplied.fs.il.bsl new file mode 100644 index 00000000000..a4066b66ca4 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_CoercionsApplied.fs.il.bsl @@ -0,0 +1,1576 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto autochar serializable sealed nested public beforefieldinit T + extends [runtime]System.Object + implements class [runtime]System.IEquatable`1, + [runtime]System.Collections.IStructuralEquatable, + class [runtime]System.IComparable`1, + [runtime]System.IComparable, + [runtime]System.Collections.IStructuralComparable + { + .custom instance void [runtime]System.Diagnostics.DebuggerDisplayAttribute::.ctor(string) = ( 01 00 15 7B 5F 5F 44 65 62 75 67 44 69 73 70 6C + 61 79 28 29 2C 6E 71 7D 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 01 00 00 00 00 00 ) + .field assembly initonly int32 item + .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 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method public static class assembly/T NewT(int32 item) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 08 00 00 00 00 00 00 00 00 00 ) + .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: newobj instance void assembly/T::.ctor(int32) + IL_0006: ret + } + + .method assembly specialname rtspecialname instance void .ctor(int32 item) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 25 45 78 70 72 65 73 73 69 6F + 6E 5F 4E 6F 6D 69 6E 61 6C 5F 43 6F 65 72 63 69 + 6F 6E 73 41 70 70 6C 69 65 64 2B 54 00 00 ) + .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 [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld int32 assembly/T::item + IL_000d: ret + } + + .method public hidebysig instance int32 get_Item() 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: ldfld int32 assembly/T::item + IL_0006: ret + } + + .method public hidebysig instance int32 get_Tag() 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: pop + IL_0002: ldc.i4.0 + IL_0003: ret + } + + .method assembly hidebysig specialname instance object __DebugDisplay() 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: ldstr "%+0.8A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,string>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/T>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(class assembly/T obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class assembly/T V_0, + class assembly/T V_1, + class [runtime]System.Collections.IComparer V_2, + int32 V_3, + int32 V_4) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_002f + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_002d + + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ldarg.0 + IL_0009: stloc.0 + IL_000a: ldarg.1 + IL_000b: stloc.1 + IL_000c: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_0011: stloc.2 + IL_0012: ldloc.0 + IL_0013: ldfld int32 assembly/T::item + IL_0018: stloc.3 + IL_0019: ldloc.1 + IL_001a: ldfld int32 assembly/T::item + IL_001f: stloc.s V_4 + IL_0021: ldloc.3 + IL_0022: ldloc.s V_4 + IL_0024: cgt + IL_0026: ldloc.3 + IL_0027: ldloc.s V_4 + IL_0029: clt + IL_002b: sub + IL_002c: ret + + IL_002d: ldc.i4.1 + IL_002e: ret + + IL_002f: ldarg.1 + IL_0030: brfalse.s IL_0034 + + IL_0032: ldc.i4.m1 + IL_0033: ret + + IL_0034: ldc.i4.0 + IL_0035: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: unbox.any assembly/T + IL_0007: callvirt instance int32 assembly/T::CompareTo(class assembly/T) + IL_000c: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj, class [runtime]System.Collections.IComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class assembly/T V_0, + class assembly/T V_1, + class assembly/T V_2, + int32 V_3, + int32 V_4) + IL_0000: ldarg.1 + IL_0001: unbox.any assembly/T + IL_0006: stloc.0 + IL_0007: ldarg.0 + IL_0008: brfalse.s IL_0035 + + IL_000a: ldarg.1 + IL_000b: unbox.any assembly/T + IL_0010: brfalse.s IL_0033 + + IL_0012: ldarg.0 + IL_0013: pop + IL_0014: ldarg.0 + IL_0015: stloc.1 + IL_0016: ldloc.0 + IL_0017: stloc.2 + IL_0018: ldloc.1 + IL_0019: ldfld int32 assembly/T::item + IL_001e: stloc.3 + IL_001f: ldloc.2 + IL_0020: ldfld int32 assembly/T::item + IL_0025: stloc.s V_4 + IL_0027: ldloc.3 + IL_0028: ldloc.s V_4 + IL_002a: cgt + IL_002c: ldloc.3 + IL_002d: ldloc.s V_4 + IL_002f: clt + IL_0031: sub + IL_0032: ret + + IL_0033: ldc.i4.1 + IL_0034: ret + + IL_0035: ldarg.1 + IL_0036: unbox.any assembly/T + IL_003b: brfalse.s IL_003f + + IL_003d: ldc.i4.m1 + IL_003e: ret + + IL_003f: ldc.i4.0 + IL_0040: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode(class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 7 + .locals init (int32 V_0, + class assembly/T V_1) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0022 + + IL_0003: ldc.i4.0 + IL_0004: stloc.0 + IL_0005: ldarg.0 + IL_0006: pop + IL_0007: ldarg.0 + IL_0008: stloc.1 + IL_0009: ldc.i4.0 + IL_000a: stloc.0 + IL_000b: ldc.i4 0x9e3779b9 + IL_0010: ldloc.1 + IL_0011: ldfld int32 assembly/T::item + IL_0016: ldloc.0 + IL_0017: ldc.i4.6 + IL_0018: shl + IL_0019: ldloc.0 + IL_001a: ldc.i4.2 + IL_001b: shr + IL_001c: add + IL_001d: add + IL_001e: add + IL_001f: stloc.0 + IL_0020: ldloc.0 + IL_0021: ret + + IL_0022: ldc.i4.0 + IL_0023: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() + IL_0006: callvirt instance int32 assembly/T::GetHashCode(class [runtime]System.Collections.IEqualityComparer) + IL_000b: ret + } + + .method public hidebysig instance bool Equals(class assembly/T obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (class assembly/T V_0, + class assembly/T V_1) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_001d + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_001b + + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ldarg.0 + IL_0009: stloc.0 + IL_000a: ldarg.1 + IL_000b: stloc.1 + IL_000c: ldloc.0 + IL_000d: ldfld int32 assembly/T::item + IL_0012: ldloc.1 + IL_0013: ldfld int32 assembly/T::item + IL_0018: ceq + IL_001a: ret + + IL_001b: ldc.i4.0 + IL_001c: ret + + IL_001d: ldarg.1 + IL_001e: ldnull + IL_001f: cgt.un + IL_0021: ldc.i4.0 + IL_0022: ceq + IL_0024: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class assembly/T V_0) + IL_0000: ldarg.1 + IL_0001: isinst assembly/T + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0013 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: ldarg.2 + IL_000d: callvirt instance bool assembly/T::Equals(class assembly/T, + class [runtime]System.Collections.IEqualityComparer) + IL_0012: ret + + IL_0013: ldc.i4.0 + IL_0014: ret + } + + .method public specialname static class assembly/U op_Implicit(class assembly/T _arg1) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld int32 assembly/T::item + IL_0006: call class assembly/U assembly/U::NewU(int32) + IL_000b: ret + } + + .method public hidebysig virtual final instance bool Equals(class assembly/T obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (class assembly/T V_0, + class assembly/T V_1) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_001d + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_001b + + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ldarg.0 + IL_0009: stloc.0 + IL_000a: ldarg.1 + IL_000b: stloc.1 + IL_000c: ldloc.0 + IL_000d: ldfld int32 assembly/T::item + IL_0012: ldloc.1 + IL_0013: ldfld int32 assembly/T::item + IL_0018: ceq + IL_001a: ret + + IL_001b: ldc.i4.0 + IL_001c: ret + + IL_001d: ldarg.1 + IL_001e: ldnull + IL_001f: cgt.un + IL_0021: ldc.i4.0 + IL_0022: ceq + IL_0024: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (class assembly/T V_0) + IL_0000: ldarg.1 + IL_0001: isinst assembly/T + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0012 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: callvirt instance bool assembly/T::Equals(class assembly/T) + IL_0011: ret + + IL_0012: ldc.i4.0 + IL_0013: ret + } + + .property instance int32 Tag() + { + .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 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .get instance int32 assembly/T::get_Tag() + } + .property instance int32 Item() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + .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 ) + .get instance int32 assembly/T::get_Item() + } + } + + .class auto autochar serializable sealed nested public beforefieldinit U + extends [runtime]System.Object + implements class [runtime]System.IEquatable`1, + [runtime]System.Collections.IStructuralEquatable, + class [runtime]System.IComparable`1, + [runtime]System.IComparable, + [runtime]System.Collections.IStructuralComparable + { + .custom instance void [runtime]System.Diagnostics.DebuggerDisplayAttribute::.ctor(string) = ( 01 00 15 7B 5F 5F 44 65 62 75 67 44 69 73 70 6C + 61 79 28 29 2C 6E 71 7D 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 01 00 00 00 00 00 ) + .field assembly initonly int32 item + .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 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method public static class assembly/U NewU(int32 item) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 08 00 00 00 00 00 00 00 00 00 ) + .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: newobj instance void assembly/U::.ctor(int32) + IL_0006: ret + } + + .method assembly specialname rtspecialname instance void .ctor(int32 item) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 25 45 78 70 72 65 73 73 69 6F + 6E 5F 4E 6F 6D 69 6E 61 6C 5F 43 6F 65 72 63 69 + 6F 6E 73 41 70 70 6C 69 65 64 2B 55 00 00 ) + .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 [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld int32 assembly/U::item + IL_000d: ret + } + + .method public hidebysig instance int32 get_Item() 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: ldfld int32 assembly/U::item + IL_0006: ret + } + + .method public hidebysig instance int32 get_Tag() 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: pop + IL_0002: ldc.i4.0 + IL_0003: ret + } + + .method assembly hidebysig specialname instance object __DebugDisplay() 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: ldstr "%+0.8A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,string>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/U>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(class assembly/U obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class assembly/U V_0, + class assembly/U V_1, + class [runtime]System.Collections.IComparer V_2, + int32 V_3, + int32 V_4) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_002f + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_002d + + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ldarg.0 + IL_0009: stloc.0 + IL_000a: ldarg.1 + IL_000b: stloc.1 + IL_000c: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_0011: stloc.2 + IL_0012: ldloc.0 + IL_0013: ldfld int32 assembly/U::item + IL_0018: stloc.3 + IL_0019: ldloc.1 + IL_001a: ldfld int32 assembly/U::item + IL_001f: stloc.s V_4 + IL_0021: ldloc.3 + IL_0022: ldloc.s V_4 + IL_0024: cgt + IL_0026: ldloc.3 + IL_0027: ldloc.s V_4 + IL_0029: clt + IL_002b: sub + IL_002c: ret + + IL_002d: ldc.i4.1 + IL_002e: ret + + IL_002f: ldarg.1 + IL_0030: brfalse.s IL_0034 + + IL_0032: ldc.i4.m1 + IL_0033: ret + + IL_0034: ldc.i4.0 + IL_0035: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: unbox.any assembly/U + IL_0007: callvirt instance int32 assembly/U::CompareTo(class assembly/U) + IL_000c: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj, class [runtime]System.Collections.IComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class assembly/U V_0, + class assembly/U V_1, + class assembly/U V_2, + int32 V_3, + int32 V_4) + IL_0000: ldarg.1 + IL_0001: unbox.any assembly/U + IL_0006: stloc.0 + IL_0007: ldarg.0 + IL_0008: brfalse.s IL_0035 + + IL_000a: ldarg.1 + IL_000b: unbox.any assembly/U + IL_0010: brfalse.s IL_0033 + + IL_0012: ldarg.0 + IL_0013: pop + IL_0014: ldarg.0 + IL_0015: stloc.1 + IL_0016: ldloc.0 + IL_0017: stloc.2 + IL_0018: ldloc.1 + IL_0019: ldfld int32 assembly/U::item + IL_001e: stloc.3 + IL_001f: ldloc.2 + IL_0020: ldfld int32 assembly/U::item + IL_0025: stloc.s V_4 + IL_0027: ldloc.3 + IL_0028: ldloc.s V_4 + IL_002a: cgt + IL_002c: ldloc.3 + IL_002d: ldloc.s V_4 + IL_002f: clt + IL_0031: sub + IL_0032: ret + + IL_0033: ldc.i4.1 + IL_0034: ret + + IL_0035: ldarg.1 + IL_0036: unbox.any assembly/U + IL_003b: brfalse.s IL_003f + + IL_003d: ldc.i4.m1 + IL_003e: ret + + IL_003f: ldc.i4.0 + IL_0040: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode(class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 7 + .locals init (int32 V_0, + class assembly/U V_1) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0022 + + IL_0003: ldc.i4.0 + IL_0004: stloc.0 + IL_0005: ldarg.0 + IL_0006: pop + IL_0007: ldarg.0 + IL_0008: stloc.1 + IL_0009: ldc.i4.0 + IL_000a: stloc.0 + IL_000b: ldc.i4 0x9e3779b9 + IL_0010: ldloc.1 + IL_0011: ldfld int32 assembly/U::item + IL_0016: ldloc.0 + IL_0017: ldc.i4.6 + IL_0018: shl + IL_0019: ldloc.0 + IL_001a: ldc.i4.2 + IL_001b: shr + IL_001c: add + IL_001d: add + IL_001e: add + IL_001f: stloc.0 + IL_0020: ldloc.0 + IL_0021: ret + + IL_0022: ldc.i4.0 + IL_0023: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() + IL_0006: callvirt instance int32 assembly/U::GetHashCode(class [runtime]System.Collections.IEqualityComparer) + IL_000b: ret + } + + .method public hidebysig instance bool Equals(class assembly/U obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (class assembly/U V_0, + class assembly/U V_1) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_001d + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_001b + + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ldarg.0 + IL_0009: stloc.0 + IL_000a: ldarg.1 + IL_000b: stloc.1 + IL_000c: ldloc.0 + IL_000d: ldfld int32 assembly/U::item + IL_0012: ldloc.1 + IL_0013: ldfld int32 assembly/U::item + IL_0018: ceq + IL_001a: ret + + IL_001b: ldc.i4.0 + IL_001c: ret + + IL_001d: ldarg.1 + IL_001e: ldnull + IL_001f: cgt.un + IL_0021: ldc.i4.0 + IL_0022: ceq + IL_0024: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class assembly/U V_0) + IL_0000: ldarg.1 + IL_0001: isinst assembly/U + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0013 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: ldarg.2 + IL_000d: callvirt instance bool assembly/U::Equals(class assembly/U, + class [runtime]System.Collections.IEqualityComparer) + IL_0012: ret + + IL_0013: ldc.i4.0 + IL_0014: ret + } + + .method public hidebysig virtual final instance bool Equals(class assembly/U obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (class assembly/U V_0, + class assembly/U V_1) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_001d + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_001b + + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ldarg.0 + IL_0009: stloc.0 + IL_000a: ldarg.1 + IL_000b: stloc.1 + IL_000c: ldloc.0 + IL_000d: ldfld int32 assembly/U::item + IL_0012: ldloc.1 + IL_0013: ldfld int32 assembly/U::item + IL_0018: ceq + IL_001a: ret + + IL_001b: ldc.i4.0 + IL_001c: ret + + IL_001d: ldarg.1 + IL_001e: ldnull + IL_001f: cgt.un + IL_0021: ldc.i4.0 + IL_0022: ceq + IL_0024: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (class assembly/U V_0) + IL_0000: ldarg.1 + IL_0001: isinst assembly/U + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0012 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: callvirt instance bool assembly/U::Equals(class assembly/U) + IL_0011: ret + + IL_0012: ldc.i4.0 + IL_0013: ret + } + + .property instance int32 Tag() + { + .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 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .get instance int32 assembly/U::get_Tag() + } + .property instance int32 Item() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + .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 ) + .get instance int32 assembly/U::get_Item() + } + } + + .class auto ansi serializable sealed nested public R1 + extends [runtime]System.Object + implements class [runtime]System.IEquatable`1, + [runtime]System.Collections.IStructuralEquatable, + class [runtime]System.IComparable`1, + [runtime]System.IComparable, + [runtime]System.Collections.IStructuralComparable + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly class assembly/T A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname instance class assembly/T get_A() 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: ldfld class assembly/T assembly/R1::A@ + IL_0006: ret + } + + .method public specialname rtspecialname instance void .ctor(class assembly/T a) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 26 45 78 70 72 65 73 73 69 6F + 6E 5F 4E 6F 6D 69 6E 61 6C 5F 43 6F 65 72 63 69 + 6F 6E 73 41 70 70 6C 69 65 64 2B 52 31 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld class assembly/T assembly/R1::A@ + IL_000d: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/R1>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(class assembly/R1 obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class [runtime]System.Collections.IComparer V_0, + class assembly/T V_1, + class assembly/T V_2) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0025 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0023 + + IL_0006: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_000b: stloc.0 + IL_000c: ldarg.0 + IL_000d: ldfld class assembly/T assembly/R1::A@ + IL_0012: stloc.1 + IL_0013: ldarg.1 + IL_0014: ldfld class assembly/T assembly/R1::A@ + IL_0019: stloc.2 + IL_001a: ldloc.1 + IL_001b: ldloc.2 + IL_001c: ldloc.0 + IL_001d: callvirt instance int32 assembly/T::CompareTo(object, + class [runtime]System.Collections.IComparer) + IL_0022: ret + + IL_0023: ldc.i4.1 + IL_0024: ret + + IL_0025: ldarg.1 + IL_0026: brfalse.s IL_002a + + IL_0028: ldc.i4.m1 + IL_0029: ret + + IL_002a: ldc.i4.0 + IL_002b: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: unbox.any assembly/R1 + IL_0007: callvirt instance int32 assembly/R1::CompareTo(class assembly/R1) + IL_000c: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj, class [runtime]System.Collections.IComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class assembly/R1 V_0, + class assembly/T V_1, + class assembly/T V_2) + IL_0000: ldarg.1 + IL_0001: unbox.any assembly/R1 + IL_0006: stloc.0 + IL_0007: ldarg.0 + IL_0008: brfalse.s IL_002b + + IL_000a: ldarg.1 + IL_000b: unbox.any assembly/R1 + IL_0010: brfalse.s IL_0029 + + IL_0012: ldarg.0 + IL_0013: ldfld class assembly/T assembly/R1::A@ + IL_0018: stloc.1 + IL_0019: ldloc.0 + IL_001a: ldfld class assembly/T assembly/R1::A@ + IL_001f: stloc.2 + IL_0020: ldloc.1 + IL_0021: ldloc.2 + IL_0022: ldarg.2 + IL_0023: callvirt instance int32 assembly/T::CompareTo(object, + class [runtime]System.Collections.IComparer) + IL_0028: ret + + IL_0029: ldc.i4.1 + IL_002a: ret + + IL_002b: ldarg.1 + IL_002c: unbox.any assembly/R1 + IL_0031: brfalse.s IL_0035 + + IL_0033: ldc.i4.m1 + IL_0034: ret + + IL_0035: ldc.i4.0 + IL_0036: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode(class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 7 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0022 + + IL_0003: ldc.i4.0 + IL_0004: stloc.0 + IL_0005: ldc.i4 0x9e3779b9 + IL_000a: ldarg.0 + IL_000b: ldfld class assembly/T assembly/R1::A@ + IL_0010: ldarg.1 + IL_0011: callvirt instance int32 assembly/T::GetHashCode(class [runtime]System.Collections.IEqualityComparer) + IL_0016: ldloc.0 + IL_0017: ldc.i4.6 + IL_0018: shl + IL_0019: ldloc.0 + IL_001a: ldc.i4.2 + IL_001b: shr + IL_001c: add + IL_001d: add + IL_001e: add + IL_001f: stloc.0 + IL_0020: ldloc.0 + IL_0021: ret + + IL_0022: ldc.i4.0 + IL_0023: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() + IL_0006: callvirt instance int32 assembly/R1::GetHashCode(class [runtime]System.Collections.IEqualityComparer) + IL_000b: ret + } + + .method public hidebysig instance bool Equals(class assembly/R1 obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class assembly/T V_0, + class assembly/T V_1) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_001f + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_001d + + IL_0006: ldarg.0 + IL_0007: ldfld class assembly/T assembly/R1::A@ + IL_000c: stloc.0 + IL_000d: ldarg.1 + IL_000e: ldfld class assembly/T assembly/R1::A@ + IL_0013: stloc.1 + IL_0014: ldloc.0 + IL_0015: ldloc.1 + IL_0016: ldarg.2 + IL_0017: callvirt instance bool assembly/T::Equals(class assembly/T, + class [runtime]System.Collections.IEqualityComparer) + IL_001c: ret + + IL_001d: ldc.i4.0 + IL_001e: ret + + IL_001f: ldarg.1 + IL_0020: ldnull + IL_0021: cgt.un + IL_0023: ldc.i4.0 + IL_0024: ceq + IL_0026: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class assembly/R1 V_0) + IL_0000: ldarg.1 + IL_0001: isinst assembly/R1 + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0013 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: ldarg.2 + IL_000d: callvirt instance bool assembly/R1::Equals(class assembly/R1, + class [runtime]System.Collections.IEqualityComparer) + IL_0012: ret + + IL_0013: ldc.i4.0 + IL_0014: ret + } + + .method public hidebysig virtual final instance bool Equals(class assembly/R1 obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_001a + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0018 + + IL_0006: ldarg.0 + IL_0007: ldfld class assembly/T assembly/R1::A@ + IL_000c: ldarg.1 + IL_000d: ldfld class assembly/T assembly/R1::A@ + IL_0012: callvirt instance bool assembly/T::Equals(class assembly/T) + IL_0017: ret + + IL_0018: ldc.i4.0 + IL_0019: ret + + IL_001a: ldarg.1 + IL_001b: ldnull + IL_001c: cgt.un + IL_001e: ldc.i4.0 + IL_001f: ceq + IL_0021: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (class assembly/R1 V_0) + IL_0000: ldarg.1 + IL_0001: isinst assembly/R1 + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0012 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: callvirt instance bool assembly/R1::Equals(class assembly/R1) + IL_0011: ret + + IL_0012: ldc.i4.0 + IL_0013: ret + } + + .property instance class assembly/T + A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance class assembly/T assembly/R1::get_A() + } + } + + .class auto ansi serializable sealed nested public R2 + extends [runtime]System.Object + implements class [runtime]System.IEquatable`1, + [runtime]System.Collections.IStructuralEquatable, + class [runtime]System.IComparable`1, + [runtime]System.IComparable, + [runtime]System.Collections.IStructuralComparable + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly class assembly/U A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname instance class assembly/U get_A() 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: ldfld class assembly/U assembly/R2::A@ + IL_0006: ret + } + + .method public specialname rtspecialname instance void .ctor(class assembly/U a) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 26 45 78 70 72 65 73 73 69 6F + 6E 5F 4E 6F 6D 69 6E 61 6C 5F 43 6F 65 72 63 69 + 6F 6E 73 41 70 70 6C 69 65 64 2B 52 32 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld class assembly/U assembly/R2::A@ + IL_000d: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/R2>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(class assembly/R2 obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class [runtime]System.Collections.IComparer V_0, + class assembly/U V_1, + class assembly/U V_2) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0025 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0023 + + IL_0006: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_000b: stloc.0 + IL_000c: ldarg.0 + IL_000d: ldfld class assembly/U assembly/R2::A@ + IL_0012: stloc.1 + IL_0013: ldarg.1 + IL_0014: ldfld class assembly/U assembly/R2::A@ + IL_0019: stloc.2 + IL_001a: ldloc.1 + IL_001b: ldloc.2 + IL_001c: ldloc.0 + IL_001d: callvirt instance int32 assembly/U::CompareTo(object, + class [runtime]System.Collections.IComparer) + IL_0022: ret + + IL_0023: ldc.i4.1 + IL_0024: ret + + IL_0025: ldarg.1 + IL_0026: brfalse.s IL_002a + + IL_0028: ldc.i4.m1 + IL_0029: ret + + IL_002a: ldc.i4.0 + IL_002b: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: unbox.any assembly/R2 + IL_0007: callvirt instance int32 assembly/R2::CompareTo(class assembly/R2) + IL_000c: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj, class [runtime]System.Collections.IComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class assembly/R2 V_0, + class assembly/U V_1, + class assembly/U V_2) + IL_0000: ldarg.1 + IL_0001: unbox.any assembly/R2 + IL_0006: stloc.0 + IL_0007: ldarg.0 + IL_0008: brfalse.s IL_002b + + IL_000a: ldarg.1 + IL_000b: unbox.any assembly/R2 + IL_0010: brfalse.s IL_0029 + + IL_0012: ldarg.0 + IL_0013: ldfld class assembly/U assembly/R2::A@ + IL_0018: stloc.1 + IL_0019: ldloc.0 + IL_001a: ldfld class assembly/U assembly/R2::A@ + IL_001f: stloc.2 + IL_0020: ldloc.1 + IL_0021: ldloc.2 + IL_0022: ldarg.2 + IL_0023: callvirt instance int32 assembly/U::CompareTo(object, + class [runtime]System.Collections.IComparer) + IL_0028: ret + + IL_0029: ldc.i4.1 + IL_002a: ret + + IL_002b: ldarg.1 + IL_002c: unbox.any assembly/R2 + IL_0031: brfalse.s IL_0035 + + IL_0033: ldc.i4.m1 + IL_0034: ret + + IL_0035: ldc.i4.0 + IL_0036: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode(class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 7 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0022 + + IL_0003: ldc.i4.0 + IL_0004: stloc.0 + IL_0005: ldc.i4 0x9e3779b9 + IL_000a: ldarg.0 + IL_000b: ldfld class assembly/U assembly/R2::A@ + IL_0010: ldarg.1 + IL_0011: callvirt instance int32 assembly/U::GetHashCode(class [runtime]System.Collections.IEqualityComparer) + IL_0016: ldloc.0 + IL_0017: ldc.i4.6 + IL_0018: shl + IL_0019: ldloc.0 + IL_001a: ldc.i4.2 + IL_001b: shr + IL_001c: add + IL_001d: add + IL_001e: add + IL_001f: stloc.0 + IL_0020: ldloc.0 + IL_0021: ret + + IL_0022: ldc.i4.0 + IL_0023: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() + IL_0006: callvirt instance int32 assembly/R2::GetHashCode(class [runtime]System.Collections.IEqualityComparer) + IL_000b: ret + } + + .method public hidebysig instance bool Equals(class assembly/R2 obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class assembly/U V_0, + class assembly/U V_1) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_001f + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_001d + + IL_0006: ldarg.0 + IL_0007: ldfld class assembly/U assembly/R2::A@ + IL_000c: stloc.0 + IL_000d: ldarg.1 + IL_000e: ldfld class assembly/U assembly/R2::A@ + IL_0013: stloc.1 + IL_0014: ldloc.0 + IL_0015: ldloc.1 + IL_0016: ldarg.2 + IL_0017: callvirt instance bool assembly/U::Equals(class assembly/U, + class [runtime]System.Collections.IEqualityComparer) + IL_001c: ret + + IL_001d: ldc.i4.0 + IL_001e: ret + + IL_001f: ldarg.1 + IL_0020: ldnull + IL_0021: cgt.un + IL_0023: ldc.i4.0 + IL_0024: ceq + IL_0026: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class assembly/R2 V_0) + IL_0000: ldarg.1 + IL_0001: isinst assembly/R2 + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0013 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: ldarg.2 + IL_000d: callvirt instance bool assembly/R2::Equals(class assembly/R2, + class [runtime]System.Collections.IEqualityComparer) + IL_0012: ret + + IL_0013: ldc.i4.0 + IL_0014: ret + } + + .method public hidebysig virtual final instance bool Equals(class assembly/R2 obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_001a + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0018 + + IL_0006: ldarg.0 + IL_0007: ldfld class assembly/U assembly/R2::A@ + IL_000c: ldarg.1 + IL_000d: ldfld class assembly/U assembly/R2::A@ + IL_0012: callvirt instance bool assembly/U::Equals(class assembly/U) + IL_0017: ret + + IL_0018: ldc.i4.0 + IL_0019: ret + + IL_001a: ldarg.1 + IL_001b: ldnull + IL_001c: cgt.un + IL_001e: ldc.i4.0 + IL_001f: ceq + IL_0021: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (class assembly/R2 V_0) + IL_0000: ldarg.1 + IL_0001: isinst assembly/R2 + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0012 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: callvirt instance bool assembly/R2::Equals(class assembly/R2) + IL_0011: ret + + IL_0012: ldc.i4.0 + IL_0013: ret + } + + .property instance class assembly/U + A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance class assembly/U assembly/R2::get_A() + } + } + + .field static assembly class assembly/R1 r1@13 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly class assembly/R2 r2@14 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly class assembly/T _arg1@3 + .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 assembly/R1 get_r1() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class assembly/R1 assembly::r1@13 + IL_0005: ret + } + + .method public specialname static class assembly/R2 get_r2() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class assembly/R2 assembly::r2@14 + IL_0005: ret + } + + .method assembly specialname static class assembly/T get__arg1@3() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class assembly/T assembly::_arg1@3 + IL_0005: ret + } + + .method private specialname rtspecialname static void .cctor() cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.0 + IL_0001: stsfld int32 ''.$assembly::init@ + IL_0006: ldsfld int32 ''.$assembly::init@ + IL_000b: pop + IL_000c: ret + } + + .method assembly static void staticInitialization@() cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.3 + IL_0001: call class assembly/T assembly/T::NewT(int32) + IL_0006: newobj instance void assembly/R1::.ctor(class assembly/T) + IL_000b: stsfld class assembly/R1 assembly::r1@13 + IL_0010: call class assembly/R1 assembly::get_r1() + IL_0015: ldfld class assembly/T assembly/R1::A@ + IL_001a: stsfld class assembly/T assembly::_arg1@3 + IL_001f: call class assembly/T assembly::get__arg1@3() + IL_0024: ldfld int32 assembly/T::item + IL_0029: call class assembly/U assembly/U::NewU(int32) + IL_002e: newobj instance void assembly/R2::.ctor(class assembly/U) + IL_0033: stsfld class assembly/R2 assembly::r2@14 + IL_0038: ret + } + + .property class assembly/R1 + r1() + { + .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 class assembly/R1 assembly::get_r1() + } + .property class assembly/R2 + r2() + { + .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 class assembly/R2 assembly::get_r2() + } + .property class assembly/T + _arg1@3() + { + .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 class assembly/T assembly::get__arg1@3() + } +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .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 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: call void assembly::staticInitialization@() + IL_0005: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_ExplicitShadowsSpread.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_ExplicitShadowsSpread.fs new file mode 100644 index 00000000000..de6714a5f49 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_ExplicitShadowsSpread.fs @@ -0,0 +1,5 @@ +[] +type R1 = { A : int; B : int } + +let r1 = { A = 1; B = 2 } +let r1' = { ...r1; A = 99 } diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_ExplicitShadowsSpread.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_ExplicitShadowsSpread.fs.il.bsl new file mode 100644 index 00000000000..ac6df7557b9 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_ExplicitShadowsSpread.fs.il.bsl @@ -0,0 +1,203 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable sealed nested public R1 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.DefaultAugmentationAttribute::.ctor(bool) = ( 01 00 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly int32 A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly int32 B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname instance int32 get_A() 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: ldfld int32 assembly/R1::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance int32 get_B() 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: ldfld int32 assembly/R1::B@ + IL_0006: ret + } + + .method public specialname rtspecialname instance void .ctor(int32 a, int32 b) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 2B 45 78 70 72 65 73 73 69 6F + 6E 5F 4E 6F 6D 69 6E 61 6C 5F 45 78 70 6C 69 63 + 69 74 53 68 61 64 6F 77 73 53 70 72 65 61 64 2B + 52 31 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld int32 assembly/R1::A@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld int32 assembly/R1::B@ + IL_0014: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/R1>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .property instance int32 A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance int32 assembly/R1::get_A() + } + .property instance int32 B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance int32 assembly/R1::get_B() + } + } + + .field static assembly class assembly/R1 r1@4 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly class assembly/R1 'r1\'@5' + .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 assembly/R1 get_r1() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class assembly/R1 assembly::r1@4 + IL_0005: ret + } + + .method public specialname static class assembly/R1 'get_r1\''() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class assembly/R1 assembly::'r1\'@5' + IL_0005: ret + } + + .method private specialname rtspecialname static void .cctor() cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.0 + IL_0001: stsfld int32 ''.$assembly::init@ + IL_0006: ldsfld int32 ''.$assembly::init@ + IL_000b: pop + IL_000c: ret + } + + .method assembly static void staticInitialization@() cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.1 + IL_0001: ldc.i4.2 + IL_0002: newobj instance void assembly/R1::.ctor(int32, + int32) + IL_0007: stsfld class assembly/R1 assembly::r1@4 + IL_000c: ldc.i4.s 99 + IL_000e: call class assembly/R1 assembly::get_r1() + IL_0013: ldfld int32 assembly/R1::B@ + IL_0018: newobj instance void assembly/R1::.ctor(int32, + int32) + IL_001d: stsfld class assembly/R1 assembly::'r1\'@5' + IL_0022: ret + } + + .property class assembly/R1 + r1() + { + .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 class assembly/R1 assembly::get_r1() + } + .property class assembly/R1 + 'r1\''() + { + .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 class assembly/R1 assembly::'get_r1\''() + } +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .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 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: call void assembly::staticInitialization@() + IL_0005: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_ExtraFieldsAreIgnored.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_ExtraFieldsAreIgnored.fs new file mode 100644 index 00000000000..1aa3c943d0f --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_ExtraFieldsAreIgnored.fs @@ -0,0 +1,7 @@ +[] +type R1 = { A : int; B : int; C : int } +[] +type R2 = { B : int } + +let r1 = { A = 1; B = 2; C = 3 } +let r2 : R2 = { ...r1 } diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_ExtraFieldsAreIgnored.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_ExtraFieldsAreIgnored.fs.il.bsl new file mode 100644 index 00000000000..f7e9699db75 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_ExtraFieldsAreIgnored.fs.il.bsl @@ -0,0 +1,288 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable sealed nested public R1 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.DefaultAugmentationAttribute::.ctor(bool) = ( 01 00 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly int32 A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly int32 B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly int32 C@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname instance int32 get_A() 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: ldfld int32 assembly/R1::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance int32 get_B() 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: ldfld int32 assembly/R1::B@ + IL_0006: ret + } + + .method public hidebysig specialname instance int32 get_C() 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: ldfld int32 assembly/R1::C@ + IL_0006: ret + } + + .method public specialname rtspecialname + instance void .ctor(int32 a, + int32 b, + int32 c) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 2B 45 78 70 72 65 73 73 69 6F + 6E 5F 4E 6F 6D 69 6E 61 6C 5F 45 78 74 72 61 46 + 69 65 6C 64 73 41 72 65 49 67 6E 6F 72 65 64 2B + 52 31 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld int32 assembly/R1::A@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld int32 assembly/R1::B@ + IL_0014: ldarg.0 + IL_0015: ldarg.3 + IL_0016: stfld int32 assembly/R1::C@ + IL_001b: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/R1>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .property instance int32 A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance int32 assembly/R1::get_A() + } + .property instance int32 B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance int32 assembly/R1::get_B() + } + .property instance int32 C() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 02 00 00 00 00 00 ) + .get instance int32 assembly/R1::get_C() + } + } + + .class auto ansi serializable sealed nested public R2 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.DefaultAugmentationAttribute::.ctor(bool) = ( 01 00 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly int32 B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname instance int32 get_B() 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: ldfld int32 assembly/R2::B@ + IL_0006: ret + } + + .method public specialname rtspecialname instance void .ctor(int32 b) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 2B 45 78 70 72 65 73 73 69 6F + 6E 5F 4E 6F 6D 69 6E 61 6C 5F 45 78 74 72 61 46 + 69 65 6C 64 73 41 72 65 49 67 6E 6F 72 65 64 2B + 52 32 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld int32 assembly/R2::B@ + IL_000d: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/R2>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .property instance int32 B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance int32 assembly/R2::get_B() + } + } + + .field static assembly class assembly/R1 r1@6 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly class assembly/R2 r2@7 + .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 assembly/R1 get_r1() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class assembly/R1 assembly::r1@6 + IL_0005: ret + } + + .method public specialname static class assembly/R2 get_r2() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class assembly/R2 assembly::r2@7 + IL_0005: ret + } + + .method private specialname rtspecialname static void .cctor() cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.0 + IL_0001: stsfld int32 ''.$assembly::init@ + IL_0006: ldsfld int32 ''.$assembly::init@ + IL_000b: pop + IL_000c: ret + } + + .method assembly static void staticInitialization@() cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.1 + IL_0001: ldc.i4.2 + IL_0002: ldc.i4.3 + IL_0003: newobj instance void assembly/R1::.ctor(int32, + int32, + int32) + IL_0008: stsfld class assembly/R1 assembly::r1@6 + IL_000d: call class assembly/R1 assembly::get_r1() + IL_0012: ldfld int32 assembly/R1::B@ + IL_0017: newobj instance void assembly/R2::.ctor(int32) + IL_001c: stsfld class assembly/R2 assembly::r2@7 + IL_0021: ret + } + + .property class assembly/R1 + r1() + { + .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 class assembly/R1 assembly::get_r1() + } + .property class assembly/R2 + r2() + { + .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 class assembly/R2 assembly::get_r2() + } +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .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 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: call void assembly::staticInitialization@() + IL_0005: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_NestedUpdates.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_NestedUpdates.fs new file mode 100644 index 00000000000..4139fb6789e --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_NestedUpdates.fs @@ -0,0 +1,13 @@ +[] +type NestedRecord = { A : string; B : string } + +[] +type OuterRecord1 = { Nested : NestedRecord; Other : NestedRecord } + +[] +type OuterRecord2 = { Nested : NestedRecord } + +let orig1 () = { Nested = { A = "value1"; B = "value1" }; Other = { A = "value2"; B = "value2" } } +let orig2 () = { Nested = { A = "value3"; B = "value3" } } + +let actual = { ...orig1 (); Nested.B = "value4"; ...orig2 (); Other.B = "value5" } diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_NestedUpdates.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_NestedUpdates.fs.il.bsl new file mode 100644 index 00000000000..3b3cde64da2 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_NestedUpdates.fs.il.bsl @@ -0,0 +1,381 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable sealed nested public NestedRecord + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.DefaultAugmentationAttribute::.ctor(bool) = ( 01 00 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly string A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly string B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname instance string get_A() 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: ldfld string assembly/NestedRecord::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance string get_B() 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: ldfld string assembly/NestedRecord::B@ + IL_0006: ret + } + + .method public specialname rtspecialname instance void .ctor(string a, string b) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 2D 45 78 70 72 65 73 73 69 6F + 6E 5F 4E 6F 6D 69 6E 61 6C 5F 4E 65 73 74 65 64 + 55 70 64 61 74 65 73 2B 4E 65 73 74 65 64 52 65 + 63 6F 72 64 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld string assembly/NestedRecord::A@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld string assembly/NestedRecord::B@ + IL_0014: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/NestedRecord>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .property instance string A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance string assembly/NestedRecord::get_A() + } + .property instance string B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance string assembly/NestedRecord::get_B() + } + } + + .class auto ansi serializable sealed nested public OuterRecord1 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.DefaultAugmentationAttribute::.ctor(bool) = ( 01 00 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly class assembly/NestedRecord Nested@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly class assembly/NestedRecord Other@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname instance class assembly/NestedRecord get_Nested() 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: ldfld class assembly/NestedRecord assembly/OuterRecord1::Nested@ + IL_0006: ret + } + + .method public hidebysig specialname instance class assembly/NestedRecord get_Other() 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: ldfld class assembly/NestedRecord assembly/OuterRecord1::Other@ + IL_0006: ret + } + + .method public specialname rtspecialname instance void .ctor(class assembly/NestedRecord 'nested', class assembly/NestedRecord other) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 2D 45 78 70 72 65 73 73 69 6F + 6E 5F 4E 6F 6D 69 6E 61 6C 5F 4E 65 73 74 65 64 + 55 70 64 61 74 65 73 2B 4F 75 74 65 72 52 65 63 + 6F 72 64 31 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld class assembly/NestedRecord assembly/OuterRecord1::Nested@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld class assembly/NestedRecord assembly/OuterRecord1::Other@ + IL_0014: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/OuterRecord1>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .property instance class assembly/NestedRecord + Nested() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance class assembly/NestedRecord assembly/OuterRecord1::get_Nested() + } + .property instance class assembly/NestedRecord + Other() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance class assembly/NestedRecord assembly/OuterRecord1::get_Other() + } + } + + .class auto ansi serializable sealed nested public OuterRecord2 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.DefaultAugmentationAttribute::.ctor(bool) = ( 01 00 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly class assembly/NestedRecord Nested@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname instance class assembly/NestedRecord get_Nested() 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: ldfld class assembly/NestedRecord assembly/OuterRecord2::Nested@ + IL_0006: ret + } + + .method public specialname rtspecialname instance void .ctor(class assembly/NestedRecord 'nested') cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 2D 45 78 70 72 65 73 73 69 6F + 6E 5F 4E 6F 6D 69 6E 61 6C 5F 4E 65 73 74 65 64 + 55 70 64 61 74 65 73 2B 4F 75 74 65 72 52 65 63 + 6F 72 64 32 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld class assembly/NestedRecord assembly/OuterRecord2::Nested@ + IL_000d: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/OuterRecord2>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .property instance class assembly/NestedRecord + Nested() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance class assembly/NestedRecord assembly/OuterRecord2::get_Nested() + } + } + + .field static assembly class assembly/OuterRecord1 actual@13 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly class assembly/OuterRecord2 bind@13 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public static class assembly/OuterRecord1 orig1() cil managed + { + + .maxstack 8 + IL_0000: ldstr "value1" + IL_0005: ldstr "value1" + IL_000a: newobj instance void assembly/NestedRecord::.ctor(string, + string) + IL_000f: ldstr "value2" + IL_0014: ldstr "value2" + IL_0019: newobj instance void assembly/NestedRecord::.ctor(string, + string) + IL_001e: newobj instance void assembly/OuterRecord1::.ctor(class assembly/NestedRecord, + class assembly/NestedRecord) + IL_0023: ret + } + + .method public static class assembly/OuterRecord2 orig2() cil managed + { + + .maxstack 8 + IL_0000: ldstr "value3" + IL_0005: ldstr "value3" + IL_000a: newobj instance void assembly/NestedRecord::.ctor(string, + string) + IL_000f: newobj instance void assembly/OuterRecord2::.ctor(class assembly/NestedRecord) + IL_0014: ret + } + + .method public specialname static class assembly/OuterRecord1 get_actual() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class assembly/OuterRecord1 assembly::actual@13 + IL_0005: ret + } + + .method assembly specialname static class assembly/OuterRecord2 get_bind@13() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class assembly/OuterRecord2 assembly::bind@13 + IL_0005: ret + } + + .method private specialname rtspecialname static void .cctor() cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.0 + IL_0001: stsfld int32 ''.$assembly::init@ + IL_0006: ldsfld int32 ''.$assembly::init@ + IL_000b: pop + IL_000c: ret + } + + .method assembly static void staticInitialization@() cil managed + { + + .maxstack 8 + IL_0000: nop + IL_0001: ldstr "value3" + IL_0006: ldstr "value3" + IL_000b: newobj instance void assembly/NestedRecord::.ctor(string, + string) + IL_0010: newobj instance void assembly/OuterRecord2::.ctor(class assembly/NestedRecord) + IL_0015: stsfld class assembly/OuterRecord2 assembly::bind@13 + IL_001a: call class assembly/OuterRecord2 assembly::get_bind@13() + IL_001f: ldfld class assembly/NestedRecord assembly/OuterRecord2::Nested@ + IL_0024: ldstr "value2" + IL_0029: ldstr "value5" + IL_002e: newobj instance void assembly/NestedRecord::.ctor(string, + string) + IL_0033: newobj instance void assembly/OuterRecord1::.ctor(class assembly/NestedRecord, + class assembly/NestedRecord) + IL_0038: stsfld class assembly/OuterRecord1 assembly::actual@13 + IL_003d: ret + } + + .property class assembly/OuterRecord1 + actual() + { + .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 class assembly/OuterRecord1 assembly::get_actual() + } + .property class assembly/OuterRecord2 + bind@13() + { + .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 class assembly/OuterRecord2 assembly::get_bind@13() + } +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .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 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: call void assembly::staticInitialization@() + IL_0005: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_NoOverlap_Explicit_Spread.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_NoOverlap_Explicit_Spread.fs new file mode 100644 index 00000000000..c92490f515c --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_NoOverlap_Explicit_Spread.fs @@ -0,0 +1,10 @@ +[] +type R1 = { B : int; C : int } +[] +type R2 = { A : int; B : int; C : int } + +let r1 = { B = 1; C = 2 } +let r2 = { A = 3; ...r1 } + +let r1' = {| B = 1; C = 2 |} +let r2' = { A = 3; ...r1 } diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_NoOverlap_Explicit_Spread.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_NoOverlap_Explicit_Spread.fs.il.bsl new file mode 100644 index 00000000000..7d930d24486 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_NoOverlap_Explicit_Spread.fs.il.bsl @@ -0,0 +1,783 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable sealed nested public R1 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.DefaultAugmentationAttribute::.ctor(bool) = ( 01 00 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly int32 B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly int32 C@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname instance int32 get_B() 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: ldfld int32 assembly/R1::B@ + IL_0006: ret + } + + .method public hidebysig specialname instance int32 get_C() 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: ldfld int32 assembly/R1::C@ + IL_0006: ret + } + + .method public specialname rtspecialname instance void .ctor(int32 b, int32 c) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 2F 45 78 70 72 65 73 73 69 6F + 6E 5F 4E 6F 6D 69 6E 61 6C 5F 4E 6F 4F 76 65 72 + 6C 61 70 5F 45 78 70 6C 69 63 69 74 5F 53 70 72 + 65 61 64 2B 52 31 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld int32 assembly/R1::B@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld int32 assembly/R1::C@ + IL_0014: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/R1>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .property instance int32 B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance int32 assembly/R1::get_B() + } + .property instance int32 C() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance int32 assembly/R1::get_C() + } + } + + .class auto ansi serializable sealed nested public R2 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.DefaultAugmentationAttribute::.ctor(bool) = ( 01 00 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly int32 A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly int32 B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly int32 C@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname instance int32 get_A() 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: ldfld int32 assembly/R2::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance int32 get_B() 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: ldfld int32 assembly/R2::B@ + IL_0006: ret + } + + .method public hidebysig specialname instance int32 get_C() 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: ldfld int32 assembly/R2::C@ + IL_0006: ret + } + + .method public specialname rtspecialname + instance void .ctor(int32 a, + int32 b, + int32 c) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 2F 45 78 70 72 65 73 73 69 6F + 6E 5F 4E 6F 6D 69 6E 61 6C 5F 4E 6F 4F 76 65 72 + 6C 61 70 5F 45 78 70 6C 69 63 69 74 5F 53 70 72 + 65 61 64 2B 52 32 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld int32 assembly/R2::A@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld int32 assembly/R2::B@ + IL_0014: ldarg.0 + IL_0015: ldarg.3 + IL_0016: stfld int32 assembly/R2::C@ + IL_001b: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/R2>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .property instance int32 A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance int32 assembly/R2::get_A() + } + .property instance int32 B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance int32 assembly/R2::get_B() + } + .property instance int32 C() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 02 00 00 00 00 00 ) + .get instance int32 assembly/R2::get_C() + } + } + + .field static assembly class assembly/R1 r1@6 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly class assembly/R2 r2@7 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly class '<>f__AnonymousType1887057234`2' 'r1\'@9' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly class assembly/R2 'r2\'@10' + .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 assembly/R1 get_r1() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class assembly/R1 assembly::r1@6 + IL_0005: ret + } + + .method public specialname static class assembly/R2 get_r2() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class assembly/R2 assembly::r2@7 + IL_0005: ret + } + + .method public specialname static class '<>f__AnonymousType1887057234`2' 'get_r1\''() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class '<>f__AnonymousType1887057234`2' assembly::'r1\'@9' + IL_0005: ret + } + + .method public specialname static class assembly/R2 'get_r2\''() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class assembly/R2 assembly::'r2\'@10' + IL_0005: ret + } + + .method private specialname rtspecialname static void .cctor() cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.0 + IL_0001: stsfld int32 ''.$assembly::init@ + IL_0006: ldsfld int32 ''.$assembly::init@ + IL_000b: pop + IL_000c: ret + } + + .method assembly static void staticInitialization@() cil managed + { + + .maxstack 5 + IL_0000: ldc.i4.1 + IL_0001: ldc.i4.2 + IL_0002: newobj instance void assembly/R1::.ctor(int32, + int32) + IL_0007: stsfld class assembly/R1 assembly::r1@6 + IL_000c: ldc.i4.3 + IL_000d: call class assembly/R1 assembly::get_r1() + IL_0012: ldfld int32 assembly/R1::B@ + IL_0017: call class assembly/R1 assembly::get_r1() + IL_001c: ldfld int32 assembly/R1::C@ + IL_0021: newobj instance void assembly/R2::.ctor(int32, + int32, + int32) + IL_0026: stsfld class assembly/R2 assembly::r2@7 + IL_002b: ldc.i4.1 + IL_002c: ldc.i4.2 + IL_002d: newobj instance void class '<>f__AnonymousType1887057234`2'::.ctor(!0, + !1) + IL_0032: stsfld class '<>f__AnonymousType1887057234`2' assembly::'r1\'@9' + IL_0037: ldc.i4.3 + IL_0038: call class assembly/R1 assembly::get_r1() + IL_003d: ldfld int32 assembly/R1::B@ + IL_0042: call class assembly/R1 assembly::get_r1() + IL_0047: ldfld int32 assembly/R1::C@ + IL_004c: newobj instance void assembly/R2::.ctor(int32, + int32, + int32) + IL_0051: stsfld class assembly/R2 assembly::'r2\'@10' + IL_0056: ret + } + + .property class assembly/R1 + r1() + { + .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 class assembly/R1 assembly::get_r1() + } + .property class assembly/R2 + r2() + { + .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 class assembly/R2 assembly::get_r2() + } + .property class '<>f__AnonymousType1887057234`2' + 'r1\''() + { + .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 class '<>f__AnonymousType1887057234`2' assembly::'get_r1\''() + } + .property class assembly/R2 + 'r2\''() + { + .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 class assembly/R2 assembly::'get_r2\''() + } +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .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 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: call void assembly::staticInitialization@() + IL_0005: ret + } + +} + +.class public auto ansi serializable sealed beforefieldinit '<>f__AnonymousType1887057234`2'<'j__TPar','j__TPar'> + extends [runtime]System.Object + implements [runtime]System.Collections.IStructuralComparable, + [runtime]System.IComparable, + class [runtime]System.IComparable`1f__AnonymousType1887057234`2'j__TPar',!'j__TPar'>>, + [runtime]System.Collections.IStructuralEquatable, + class [runtime]System.IEquatable`1f__AnonymousType1887057234`2'j__TPar',!'j__TPar'>> +{ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field private !'j__TPar' B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field private !'j__TPar' C@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor(!'j__TPar' B, !'j__TPar' C) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 1E 3C 3E 66 5F 5F 41 6E 6F 6E + 79 6D 6F 75 73 54 79 70 65 31 38 38 37 30 35 37 + 32 33 34 60 32 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld !0 class '<>f__AnonymousType1887057234`2'j__TPar',!'j__TPar'>::B@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld !1 class '<>f__AnonymousType1887057234`2'j__TPar',!'j__TPar'>::C@ + IL_0014: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_B() 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: ldfld !0 class '<>f__AnonymousType1887057234`2'j__TPar',!'j__TPar'>::B@ + IL_0006: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_C() 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: ldfld !1 class '<>f__AnonymousType1887057234`2'j__TPar',!'j__TPar'>::C@ + IL_0006: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5f__AnonymousType1887057234`2'j__TPar',!'j__TPar'>,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class '<>f__AnonymousType1887057234`2'j__TPar',!'j__TPar'>>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToStringf__AnonymousType1887057234`2'j__TPar',!'j__TPar'>,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2f__AnonymousType1887057234`2'j__TPar',!'j__TPar'>,string>::Invoke(!0) + IL_0015: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(class '<>f__AnonymousType1887057234`2'j__TPar',!'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0044 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0042 + + IL_0006: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_000b: ldarg.0 + IL_000c: ldfld !0 class '<>f__AnonymousType1887057234`2'j__TPar',!'j__TPar'>::B@ + IL_0011: ldarg.1 + IL_0012: ldfld !0 class '<>f__AnonymousType1887057234`2'j__TPar',!'j__TPar'>::B@ + IL_0017: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_001c: stloc.0 + IL_001d: ldloc.0 + IL_001e: ldc.i4.0 + IL_001f: bge.s IL_0023 + + IL_0021: ldloc.0 + IL_0022: ret + + IL_0023: ldloc.0 + IL_0024: ldc.i4.0 + IL_0025: ble.s IL_0029 + + IL_0027: ldloc.0 + IL_0028: ret + + IL_0029: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_002e: ldarg.0 + IL_002f: ldfld !1 class '<>f__AnonymousType1887057234`2'j__TPar',!'j__TPar'>::C@ + IL_0034: ldarg.1 + IL_0035: ldfld !1 class '<>f__AnonymousType1887057234`2'j__TPar',!'j__TPar'>::C@ + IL_003a: tail. + IL_003c: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0041: ret + + IL_0042: ldc.i4.1 + IL_0043: ret + + IL_0044: ldarg.1 + IL_0045: brfalse.s IL_0049 + + IL_0047: ldc.i4.m1 + IL_0048: ret + + IL_0049: ldc.i4.0 + IL_004a: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: unbox.any class '<>f__AnonymousType1887057234`2'j__TPar',!'j__TPar'> + IL_0007: tail. + IL_0009: callvirt instance int32 class '<>f__AnonymousType1887057234`2'j__TPar',!'j__TPar'>::CompareTo(class '<>f__AnonymousType1887057234`2') + IL_000e: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj, class [runtime]System.Collections.IComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType1887057234`2'j__TPar',!'j__TPar'> V_0, + class '<>f__AnonymousType1887057234`2'j__TPar',!'j__TPar'> V_1, + int32 V_2) + IL_0000: ldarg.1 + IL_0001: unbox.any class '<>f__AnonymousType1887057234`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: stloc.1 + IL_0009: ldarg.0 + IL_000a: brfalse.s IL_004a + + IL_000c: ldarg.1 + IL_000d: unbox.any class '<>f__AnonymousType1887057234`2'j__TPar',!'j__TPar'> + IL_0012: brfalse.s IL_0048 + + IL_0014: ldarg.2 + IL_0015: ldarg.0 + IL_0016: ldfld !0 class '<>f__AnonymousType1887057234`2'j__TPar',!'j__TPar'>::B@ + IL_001b: ldloc.1 + IL_001c: ldfld !0 class '<>f__AnonymousType1887057234`2'j__TPar',!'j__TPar'>::B@ + IL_0021: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0026: stloc.2 + IL_0027: ldloc.2 + IL_0028: ldc.i4.0 + IL_0029: bge.s IL_002d + + IL_002b: ldloc.2 + IL_002c: ret + + IL_002d: ldloc.2 + IL_002e: ldc.i4.0 + IL_002f: ble.s IL_0033 + + IL_0031: ldloc.2 + IL_0032: ret + + IL_0033: ldarg.2 + IL_0034: ldarg.0 + IL_0035: ldfld !1 class '<>f__AnonymousType1887057234`2'j__TPar',!'j__TPar'>::C@ + IL_003a: ldloc.1 + IL_003b: ldfld !1 class '<>f__AnonymousType1887057234`2'j__TPar',!'j__TPar'>::C@ + IL_0040: tail. + IL_0042: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0047: ret + + IL_0048: ldc.i4.1 + IL_0049: ret + + IL_004a: ldarg.1 + IL_004b: unbox.any class '<>f__AnonymousType1887057234`2'j__TPar',!'j__TPar'> + IL_0050: brfalse.s IL_0054 + + IL_0052: ldc.i4.m1 + IL_0053: ret + + IL_0054: ldc.i4.0 + IL_0055: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode(class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 7 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_003d + + IL_0003: ldc.i4.0 + IL_0004: stloc.0 + IL_0005: ldc.i4 0x9e3779b9 + IL_000a: ldarg.1 + IL_000b: ldarg.0 + IL_000c: ldfld !1 class '<>f__AnonymousType1887057234`2'j__TPar',!'j__TPar'>::C@ + IL_0011: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0016: ldloc.0 + IL_0017: ldc.i4.6 + IL_0018: shl + IL_0019: ldloc.0 + IL_001a: ldc.i4.2 + IL_001b: shr + IL_001c: add + IL_001d: add + IL_001e: add + IL_001f: stloc.0 + IL_0020: ldc.i4 0x9e3779b9 + IL_0025: ldarg.1 + IL_0026: ldarg.0 + IL_0027: ldfld !0 class '<>f__AnonymousType1887057234`2'j__TPar',!'j__TPar'>::B@ + IL_002c: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0031: ldloc.0 + IL_0032: ldc.i4.6 + IL_0033: shl + IL_0034: ldloc.0 + IL_0035: ldc.i4.2 + IL_0036: shr + IL_0037: add + IL_0038: add + IL_0039: add + IL_003a: stloc.0 + IL_003b: ldloc.0 + IL_003c: ret + + IL_003d: ldc.i4.0 + IL_003e: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() + IL_0006: tail. + IL_0008: callvirt instance int32 class '<>f__AnonymousType1887057234`2'j__TPar',!'j__TPar'>::GetHashCode(class [runtime]System.Collections.IEqualityComparer) + IL_000d: ret + } + + .method public hidebysig instance bool Equals(class '<>f__AnonymousType1887057234`2'j__TPar',!'j__TPar'> obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType1887057234`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0035 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0033 + + IL_0006: ldarg.1 + IL_0007: stloc.0 + IL_0008: ldarg.2 + IL_0009: ldarg.0 + IL_000a: ldfld !0 class '<>f__AnonymousType1887057234`2'j__TPar',!'j__TPar'>::B@ + IL_000f: ldloc.0 + IL_0010: ldfld !0 class '<>f__AnonymousType1887057234`2'j__TPar',!'j__TPar'>::B@ + IL_0015: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_001a: brfalse.s IL_0031 + + IL_001c: ldarg.2 + IL_001d: ldarg.0 + IL_001e: ldfld !1 class '<>f__AnonymousType1887057234`2'j__TPar',!'j__TPar'>::C@ + IL_0023: ldloc.0 + IL_0024: ldfld !1 class '<>f__AnonymousType1887057234`2'j__TPar',!'j__TPar'>::C@ + IL_0029: tail. + IL_002b: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_0030: ret + + IL_0031: ldc.i4.0 + IL_0032: ret + + IL_0033: ldc.i4.0 + IL_0034: ret + + IL_0035: ldarg.1 + IL_0036: ldnull + IL_0037: cgt.un + IL_0039: ldc.i4.0 + IL_003a: ceq + IL_003c: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType1887057234`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType1887057234`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0015 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: ldarg.2 + IL_000d: tail. + IL_000f: callvirt instance bool class '<>f__AnonymousType1887057234`2'j__TPar',!'j__TPar'>::Equals(class '<>f__AnonymousType1887057234`2', + class [runtime]System.Collections.IEqualityComparer) + IL_0014: ret + + IL_0015: ldc.i4.0 + IL_0016: ret + } + + .method public hidebysig virtual final instance bool Equals(class '<>f__AnonymousType1887057234`2'j__TPar',!'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0031 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_002f + + IL_0006: ldarg.0 + IL_0007: ldfld !0 class '<>f__AnonymousType1887057234`2'j__TPar',!'j__TPar'>::B@ + IL_000c: ldarg.1 + IL_000d: ldfld !0 class '<>f__AnonymousType1887057234`2'j__TPar',!'j__TPar'>::B@ + IL_0012: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_0017: brfalse.s IL_002d + + IL_0019: ldarg.0 + IL_001a: ldfld !1 class '<>f__AnonymousType1887057234`2'j__TPar',!'j__TPar'>::C@ + IL_001f: ldarg.1 + IL_0020: ldfld !1 class '<>f__AnonymousType1887057234`2'j__TPar',!'j__TPar'>::C@ + IL_0025: tail. + IL_0027: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_002c: ret + + IL_002d: ldc.i4.0 + IL_002e: ret + + IL_002f: ldc.i4.0 + IL_0030: ret + + IL_0031: ldarg.1 + IL_0032: ldnull + IL_0033: cgt.un + IL_0035: ldc.i4.0 + IL_0036: ceq + IL_0038: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (class '<>f__AnonymousType1887057234`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType1887057234`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0014 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: tail. + IL_000e: callvirt instance bool class '<>f__AnonymousType1887057234`2'j__TPar',!'j__TPar'>::Equals(class '<>f__AnonymousType1887057234`2') + IL_0013: ret + + IL_0014: ldc.i4.0 + IL_0015: ret + } + + .property instance !'j__TPar' B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType1887057234`2'::get_B() + } + .property instance !'j__TPar' C() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType1887057234`2'::get_C() + } +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_NoOverlap_SpreadFromAnon.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_NoOverlap_SpreadFromAnon.fs new file mode 100644 index 00000000000..8da3238197f --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_NoOverlap_SpreadFromAnon.fs @@ -0,0 +1,4 @@ +[] +type R2 = { A : int; B : int; C : int } + +let r2 = { ...{| A = 1; B = 2 |}; C = 3 } diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_NoOverlap_SpreadFromAnon.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_NoOverlap_SpreadFromAnon.fs.il.bsl new file mode 100644 index 00000000000..d8556321cdc --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_NoOverlap_SpreadFromAnon.fs.il.bsl @@ -0,0 +1,656 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable sealed nested public R2 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.DefaultAugmentationAttribute::.ctor(bool) = ( 01 00 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly int32 A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly int32 B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly int32 C@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname instance int32 get_A() 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: ldfld int32 assembly/R2::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance int32 get_B() 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: ldfld int32 assembly/R2::B@ + IL_0006: ret + } + + .method public hidebysig specialname instance int32 get_C() 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: ldfld int32 assembly/R2::C@ + IL_0006: ret + } + + .method public specialname rtspecialname + instance void .ctor(int32 a, + int32 b, + int32 c) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 2E 45 78 70 72 65 73 73 69 6F + 6E 5F 4E 6F 6D 69 6E 61 6C 5F 4E 6F 4F 76 65 72 + 6C 61 70 5F 53 70 72 65 61 64 46 72 6F 6D 41 6E + 6F 6E 2B 52 32 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld int32 assembly/R2::A@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld int32 assembly/R2::B@ + IL_0014: ldarg.0 + IL_0015: ldarg.3 + IL_0016: stfld int32 assembly/R2::C@ + IL_001b: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/R2>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .property instance int32 A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance int32 assembly/R2::get_A() + } + .property instance int32 B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance int32 assembly/R2::get_B() + } + .property instance int32 C() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 02 00 00 00 00 00 ) + .get instance int32 assembly/R2::get_C() + } + } + + .field static assembly class assembly/R2 r2@4 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly class '<>f__AnonymousType1960999945`2' bind@4 + .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 assembly/R2 get_r2() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class assembly/R2 assembly::r2@4 + IL_0005: ret + } + + .method assembly specialname static class '<>f__AnonymousType1960999945`2' get_bind@4() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class '<>f__AnonymousType1960999945`2' assembly::bind@4 + IL_0005: ret + } + + .method private specialname rtspecialname static void .cctor() cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.0 + IL_0001: stsfld int32 ''.$assembly::init@ + IL_0006: ldsfld int32 ''.$assembly::init@ + IL_000b: pop + IL_000c: ret + } + + .method assembly static void staticInitialization@() cil managed + { + + .maxstack 8 + IL_0000: nop + IL_0001: ldc.i4.1 + IL_0002: ldc.i4.2 + IL_0003: newobj instance void class '<>f__AnonymousType1960999945`2'::.ctor(!0, + !1) + IL_0008: stsfld class '<>f__AnonymousType1960999945`2' assembly::bind@4 + IL_000d: call class '<>f__AnonymousType1960999945`2' assembly::get_bind@4() + IL_0012: call instance !0 class '<>f__AnonymousType1960999945`2'::get_A() + IL_0017: call class '<>f__AnonymousType1960999945`2' assembly::get_bind@4() + IL_001c: call instance !1 class '<>f__AnonymousType1960999945`2'::get_B() + IL_0021: ldc.i4.3 + IL_0022: newobj instance void assembly/R2::.ctor(int32, + int32, + int32) + IL_0027: stsfld class assembly/R2 assembly::r2@4 + IL_002c: ret + } + + .property class assembly/R2 + r2() + { + .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 class assembly/R2 assembly::get_r2() + } + .property class '<>f__AnonymousType1960999945`2' + bind@4() + { + .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 class '<>f__AnonymousType1960999945`2' assembly::get_bind@4() + } +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .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 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: call void assembly::staticInitialization@() + IL_0005: ret + } + +} + +.class public auto ansi serializable sealed beforefieldinit '<>f__AnonymousType1960999945`2'<'j__TPar','j__TPar'> + extends [runtime]System.Object + implements [runtime]System.Collections.IStructuralComparable, + [runtime]System.IComparable, + class [runtime]System.IComparable`1f__AnonymousType1960999945`2'j__TPar',!'j__TPar'>>, + [runtime]System.Collections.IStructuralEquatable, + class [runtime]System.IEquatable`1f__AnonymousType1960999945`2'j__TPar',!'j__TPar'>> +{ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field private !'j__TPar' A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field private !'j__TPar' B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor(!'j__TPar' A, !'j__TPar' B) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 1E 3C 3E 66 5F 5F 41 6E 6F 6E + 79 6D 6F 75 73 54 79 70 65 31 39 36 30 39 39 39 + 39 34 35 60 32 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld !0 class '<>f__AnonymousType1960999945`2'j__TPar',!'j__TPar'>::A@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld !1 class '<>f__AnonymousType1960999945`2'j__TPar',!'j__TPar'>::B@ + IL_0014: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_A() 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: ldfld !0 class '<>f__AnonymousType1960999945`2'j__TPar',!'j__TPar'>::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_B() 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: ldfld !1 class '<>f__AnonymousType1960999945`2'j__TPar',!'j__TPar'>::B@ + IL_0006: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5f__AnonymousType1960999945`2'j__TPar',!'j__TPar'>,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class '<>f__AnonymousType1960999945`2'j__TPar',!'j__TPar'>>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToStringf__AnonymousType1960999945`2'j__TPar',!'j__TPar'>,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2f__AnonymousType1960999945`2'j__TPar',!'j__TPar'>,string>::Invoke(!0) + IL_0015: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(class '<>f__AnonymousType1960999945`2'j__TPar',!'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0044 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0042 + + IL_0006: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_000b: ldarg.0 + IL_000c: ldfld !0 class '<>f__AnonymousType1960999945`2'j__TPar',!'j__TPar'>::A@ + IL_0011: ldarg.1 + IL_0012: ldfld !0 class '<>f__AnonymousType1960999945`2'j__TPar',!'j__TPar'>::A@ + IL_0017: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_001c: stloc.0 + IL_001d: ldloc.0 + IL_001e: ldc.i4.0 + IL_001f: bge.s IL_0023 + + IL_0021: ldloc.0 + IL_0022: ret + + IL_0023: ldloc.0 + IL_0024: ldc.i4.0 + IL_0025: ble.s IL_0029 + + IL_0027: ldloc.0 + IL_0028: ret + + IL_0029: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_002e: ldarg.0 + IL_002f: ldfld !1 class '<>f__AnonymousType1960999945`2'j__TPar',!'j__TPar'>::B@ + IL_0034: ldarg.1 + IL_0035: ldfld !1 class '<>f__AnonymousType1960999945`2'j__TPar',!'j__TPar'>::B@ + IL_003a: tail. + IL_003c: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0041: ret + + IL_0042: ldc.i4.1 + IL_0043: ret + + IL_0044: ldarg.1 + IL_0045: brfalse.s IL_0049 + + IL_0047: ldc.i4.m1 + IL_0048: ret + + IL_0049: ldc.i4.0 + IL_004a: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: unbox.any class '<>f__AnonymousType1960999945`2'j__TPar',!'j__TPar'> + IL_0007: tail. + IL_0009: callvirt instance int32 class '<>f__AnonymousType1960999945`2'j__TPar',!'j__TPar'>::CompareTo(class '<>f__AnonymousType1960999945`2') + IL_000e: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj, class [runtime]System.Collections.IComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType1960999945`2'j__TPar',!'j__TPar'> V_0, + class '<>f__AnonymousType1960999945`2'j__TPar',!'j__TPar'> V_1, + int32 V_2) + IL_0000: ldarg.1 + IL_0001: unbox.any class '<>f__AnonymousType1960999945`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: stloc.1 + IL_0009: ldarg.0 + IL_000a: brfalse.s IL_004a + + IL_000c: ldarg.1 + IL_000d: unbox.any class '<>f__AnonymousType1960999945`2'j__TPar',!'j__TPar'> + IL_0012: brfalse.s IL_0048 + + IL_0014: ldarg.2 + IL_0015: ldarg.0 + IL_0016: ldfld !0 class '<>f__AnonymousType1960999945`2'j__TPar',!'j__TPar'>::A@ + IL_001b: ldloc.1 + IL_001c: ldfld !0 class '<>f__AnonymousType1960999945`2'j__TPar',!'j__TPar'>::A@ + IL_0021: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0026: stloc.2 + IL_0027: ldloc.2 + IL_0028: ldc.i4.0 + IL_0029: bge.s IL_002d + + IL_002b: ldloc.2 + IL_002c: ret + + IL_002d: ldloc.2 + IL_002e: ldc.i4.0 + IL_002f: ble.s IL_0033 + + IL_0031: ldloc.2 + IL_0032: ret + + IL_0033: ldarg.2 + IL_0034: ldarg.0 + IL_0035: ldfld !1 class '<>f__AnonymousType1960999945`2'j__TPar',!'j__TPar'>::B@ + IL_003a: ldloc.1 + IL_003b: ldfld !1 class '<>f__AnonymousType1960999945`2'j__TPar',!'j__TPar'>::B@ + IL_0040: tail. + IL_0042: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0047: ret + + IL_0048: ldc.i4.1 + IL_0049: ret + + IL_004a: ldarg.1 + IL_004b: unbox.any class '<>f__AnonymousType1960999945`2'j__TPar',!'j__TPar'> + IL_0050: brfalse.s IL_0054 + + IL_0052: ldc.i4.m1 + IL_0053: ret + + IL_0054: ldc.i4.0 + IL_0055: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode(class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 7 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_003d + + IL_0003: ldc.i4.0 + IL_0004: stloc.0 + IL_0005: ldc.i4 0x9e3779b9 + IL_000a: ldarg.1 + IL_000b: ldarg.0 + IL_000c: ldfld !1 class '<>f__AnonymousType1960999945`2'j__TPar',!'j__TPar'>::B@ + IL_0011: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0016: ldloc.0 + IL_0017: ldc.i4.6 + IL_0018: shl + IL_0019: ldloc.0 + IL_001a: ldc.i4.2 + IL_001b: shr + IL_001c: add + IL_001d: add + IL_001e: add + IL_001f: stloc.0 + IL_0020: ldc.i4 0x9e3779b9 + IL_0025: ldarg.1 + IL_0026: ldarg.0 + IL_0027: ldfld !0 class '<>f__AnonymousType1960999945`2'j__TPar',!'j__TPar'>::A@ + IL_002c: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0031: ldloc.0 + IL_0032: ldc.i4.6 + IL_0033: shl + IL_0034: ldloc.0 + IL_0035: ldc.i4.2 + IL_0036: shr + IL_0037: add + IL_0038: add + IL_0039: add + IL_003a: stloc.0 + IL_003b: ldloc.0 + IL_003c: ret + + IL_003d: ldc.i4.0 + IL_003e: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() + IL_0006: tail. + IL_0008: callvirt instance int32 class '<>f__AnonymousType1960999945`2'j__TPar',!'j__TPar'>::GetHashCode(class [runtime]System.Collections.IEqualityComparer) + IL_000d: ret + } + + .method public hidebysig instance bool Equals(class '<>f__AnonymousType1960999945`2'j__TPar',!'j__TPar'> obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType1960999945`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0035 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0033 + + IL_0006: ldarg.1 + IL_0007: stloc.0 + IL_0008: ldarg.2 + IL_0009: ldarg.0 + IL_000a: ldfld !0 class '<>f__AnonymousType1960999945`2'j__TPar',!'j__TPar'>::A@ + IL_000f: ldloc.0 + IL_0010: ldfld !0 class '<>f__AnonymousType1960999945`2'j__TPar',!'j__TPar'>::A@ + IL_0015: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_001a: brfalse.s IL_0031 + + IL_001c: ldarg.2 + IL_001d: ldarg.0 + IL_001e: ldfld !1 class '<>f__AnonymousType1960999945`2'j__TPar',!'j__TPar'>::B@ + IL_0023: ldloc.0 + IL_0024: ldfld !1 class '<>f__AnonymousType1960999945`2'j__TPar',!'j__TPar'>::B@ + IL_0029: tail. + IL_002b: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_0030: ret + + IL_0031: ldc.i4.0 + IL_0032: ret + + IL_0033: ldc.i4.0 + IL_0034: ret + + IL_0035: ldarg.1 + IL_0036: ldnull + IL_0037: cgt.un + IL_0039: ldc.i4.0 + IL_003a: ceq + IL_003c: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType1960999945`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType1960999945`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0015 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: ldarg.2 + IL_000d: tail. + IL_000f: callvirt instance bool class '<>f__AnonymousType1960999945`2'j__TPar',!'j__TPar'>::Equals(class '<>f__AnonymousType1960999945`2', + class [runtime]System.Collections.IEqualityComparer) + IL_0014: ret + + IL_0015: ldc.i4.0 + IL_0016: ret + } + + .method public hidebysig virtual final instance bool Equals(class '<>f__AnonymousType1960999945`2'j__TPar',!'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0031 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_002f + + IL_0006: ldarg.0 + IL_0007: ldfld !0 class '<>f__AnonymousType1960999945`2'j__TPar',!'j__TPar'>::A@ + IL_000c: ldarg.1 + IL_000d: ldfld !0 class '<>f__AnonymousType1960999945`2'j__TPar',!'j__TPar'>::A@ + IL_0012: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_0017: brfalse.s IL_002d + + IL_0019: ldarg.0 + IL_001a: ldfld !1 class '<>f__AnonymousType1960999945`2'j__TPar',!'j__TPar'>::B@ + IL_001f: ldarg.1 + IL_0020: ldfld !1 class '<>f__AnonymousType1960999945`2'j__TPar',!'j__TPar'>::B@ + IL_0025: tail. + IL_0027: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_002c: ret + + IL_002d: ldc.i4.0 + IL_002e: ret + + IL_002f: ldc.i4.0 + IL_0030: ret + + IL_0031: ldarg.1 + IL_0032: ldnull + IL_0033: cgt.un + IL_0035: ldc.i4.0 + IL_0036: ceq + IL_0038: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (class '<>f__AnonymousType1960999945`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType1960999945`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0014 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: tail. + IL_000e: callvirt instance bool class '<>f__AnonymousType1960999945`2'j__TPar',!'j__TPar'>::Equals(class '<>f__AnonymousType1960999945`2') + IL_0013: ret + + IL_0014: ldc.i4.0 + IL_0015: ret + } + + .property instance !'j__TPar' A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType1960999945`2'::get_A() + } + .property instance !'j__TPar' B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType1960999945`2'::get_B() + } +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_NoOverlap_Spread_Explicit.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_NoOverlap_Spread_Explicit.fs new file mode 100644 index 00000000000..b192db293b1 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_NoOverlap_Spread_Explicit.fs @@ -0,0 +1,10 @@ +[] +type R1 = { A : int; B : int } +[] +type R2 = { A : int; B : int; C : int } + +let r1 = { A = 1; B = 2 } +let r2 = { ...r1; C = 3 } + +let r1' = {| A = 1; B = 2 |} +let r2' = { ...r1; C = 3 } diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_NoOverlap_Spread_Explicit.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_NoOverlap_Spread_Explicit.fs.il.bsl new file mode 100644 index 00000000000..b825833706e --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_NoOverlap_Spread_Explicit.fs.il.bsl @@ -0,0 +1,783 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable sealed nested public R1 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.DefaultAugmentationAttribute::.ctor(bool) = ( 01 00 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly int32 A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly int32 B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname instance int32 get_A() 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: ldfld int32 assembly/R1::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance int32 get_B() 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: ldfld int32 assembly/R1::B@ + IL_0006: ret + } + + .method public specialname rtspecialname instance void .ctor(int32 a, int32 b) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 2F 45 78 70 72 65 73 73 69 6F + 6E 5F 4E 6F 6D 69 6E 61 6C 5F 4E 6F 4F 76 65 72 + 6C 61 70 5F 53 70 72 65 61 64 5F 45 78 70 6C 69 + 63 69 74 2B 52 31 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld int32 assembly/R1::A@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld int32 assembly/R1::B@ + IL_0014: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/R1>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .property instance int32 A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance int32 assembly/R1::get_A() + } + .property instance int32 B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance int32 assembly/R1::get_B() + } + } + + .class auto ansi serializable sealed nested public R2 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.DefaultAugmentationAttribute::.ctor(bool) = ( 01 00 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly int32 A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly int32 B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly int32 C@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname instance int32 get_A() 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: ldfld int32 assembly/R2::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance int32 get_B() 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: ldfld int32 assembly/R2::B@ + IL_0006: ret + } + + .method public hidebysig specialname instance int32 get_C() 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: ldfld int32 assembly/R2::C@ + IL_0006: ret + } + + .method public specialname rtspecialname + instance void .ctor(int32 a, + int32 b, + int32 c) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 2F 45 78 70 72 65 73 73 69 6F + 6E 5F 4E 6F 6D 69 6E 61 6C 5F 4E 6F 4F 76 65 72 + 6C 61 70 5F 53 70 72 65 61 64 5F 45 78 70 6C 69 + 63 69 74 2B 52 32 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld int32 assembly/R2::A@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld int32 assembly/R2::B@ + IL_0014: ldarg.0 + IL_0015: ldarg.3 + IL_0016: stfld int32 assembly/R2::C@ + IL_001b: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/R2>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .property instance int32 A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance int32 assembly/R2::get_A() + } + .property instance int32 B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance int32 assembly/R2::get_B() + } + .property instance int32 C() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 02 00 00 00 00 00 ) + .get instance int32 assembly/R2::get_C() + } + } + + .field static assembly class assembly/R1 r1@6 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly class assembly/R2 r2@7 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly class '<>f__AnonymousType1701169138`2' 'r1\'@9' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly class assembly/R2 'r2\'@10' + .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 assembly/R1 get_r1() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class assembly/R1 assembly::r1@6 + IL_0005: ret + } + + .method public specialname static class assembly/R2 get_r2() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class assembly/R2 assembly::r2@7 + IL_0005: ret + } + + .method public specialname static class '<>f__AnonymousType1701169138`2' 'get_r1\''() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class '<>f__AnonymousType1701169138`2' assembly::'r1\'@9' + IL_0005: ret + } + + .method public specialname static class assembly/R2 'get_r2\''() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class assembly/R2 assembly::'r2\'@10' + IL_0005: ret + } + + .method private specialname rtspecialname static void .cctor() cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.0 + IL_0001: stsfld int32 ''.$assembly::init@ + IL_0006: ldsfld int32 ''.$assembly::init@ + IL_000b: pop + IL_000c: ret + } + + .method assembly static void staticInitialization@() cil managed + { + + .maxstack 5 + IL_0000: ldc.i4.1 + IL_0001: ldc.i4.2 + IL_0002: newobj instance void assembly/R1::.ctor(int32, + int32) + IL_0007: stsfld class assembly/R1 assembly::r1@6 + IL_000c: call class assembly/R1 assembly::get_r1() + IL_0011: ldfld int32 assembly/R1::A@ + IL_0016: call class assembly/R1 assembly::get_r1() + IL_001b: ldfld int32 assembly/R1::B@ + IL_0020: ldc.i4.3 + IL_0021: newobj instance void assembly/R2::.ctor(int32, + int32, + int32) + IL_0026: stsfld class assembly/R2 assembly::r2@7 + IL_002b: ldc.i4.1 + IL_002c: ldc.i4.2 + IL_002d: newobj instance void class '<>f__AnonymousType1701169138`2'::.ctor(!0, + !1) + IL_0032: stsfld class '<>f__AnonymousType1701169138`2' assembly::'r1\'@9' + IL_0037: call class assembly/R1 assembly::get_r1() + IL_003c: ldfld int32 assembly/R1::A@ + IL_0041: call class assembly/R1 assembly::get_r1() + IL_0046: ldfld int32 assembly/R1::B@ + IL_004b: ldc.i4.3 + IL_004c: newobj instance void assembly/R2::.ctor(int32, + int32, + int32) + IL_0051: stsfld class assembly/R2 assembly::'r2\'@10' + IL_0056: ret + } + + .property class assembly/R1 + r1() + { + .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 class assembly/R1 assembly::get_r1() + } + .property class assembly/R2 + r2() + { + .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 class assembly/R2 assembly::get_r2() + } + .property class '<>f__AnonymousType1701169138`2' + 'r1\''() + { + .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 class '<>f__AnonymousType1701169138`2' assembly::'get_r1\''() + } + .property class assembly/R2 + 'r2\''() + { + .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 class assembly/R2 assembly::'get_r2\''() + } +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .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 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: call void assembly::staticInitialization@() + IL_0005: ret + } + +} + +.class public auto ansi serializable sealed beforefieldinit '<>f__AnonymousType1701169138`2'<'j__TPar','j__TPar'> + extends [runtime]System.Object + implements [runtime]System.Collections.IStructuralComparable, + [runtime]System.IComparable, + class [runtime]System.IComparable`1f__AnonymousType1701169138`2'j__TPar',!'j__TPar'>>, + [runtime]System.Collections.IStructuralEquatable, + class [runtime]System.IEquatable`1f__AnonymousType1701169138`2'j__TPar',!'j__TPar'>> +{ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field private !'j__TPar' A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field private !'j__TPar' B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor(!'j__TPar' A, !'j__TPar' B) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 1E 3C 3E 66 5F 5F 41 6E 6F 6E + 79 6D 6F 75 73 54 79 70 65 31 37 30 31 31 36 39 + 31 33 38 60 32 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld !0 class '<>f__AnonymousType1701169138`2'j__TPar',!'j__TPar'>::A@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld !1 class '<>f__AnonymousType1701169138`2'j__TPar',!'j__TPar'>::B@ + IL_0014: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_A() 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: ldfld !0 class '<>f__AnonymousType1701169138`2'j__TPar',!'j__TPar'>::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_B() 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: ldfld !1 class '<>f__AnonymousType1701169138`2'j__TPar',!'j__TPar'>::B@ + IL_0006: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5f__AnonymousType1701169138`2'j__TPar',!'j__TPar'>,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class '<>f__AnonymousType1701169138`2'j__TPar',!'j__TPar'>>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToStringf__AnonymousType1701169138`2'j__TPar',!'j__TPar'>,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2f__AnonymousType1701169138`2'j__TPar',!'j__TPar'>,string>::Invoke(!0) + IL_0015: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(class '<>f__AnonymousType1701169138`2'j__TPar',!'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0044 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0042 + + IL_0006: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_000b: ldarg.0 + IL_000c: ldfld !0 class '<>f__AnonymousType1701169138`2'j__TPar',!'j__TPar'>::A@ + IL_0011: ldarg.1 + IL_0012: ldfld !0 class '<>f__AnonymousType1701169138`2'j__TPar',!'j__TPar'>::A@ + IL_0017: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_001c: stloc.0 + IL_001d: ldloc.0 + IL_001e: ldc.i4.0 + IL_001f: bge.s IL_0023 + + IL_0021: ldloc.0 + IL_0022: ret + + IL_0023: ldloc.0 + IL_0024: ldc.i4.0 + IL_0025: ble.s IL_0029 + + IL_0027: ldloc.0 + IL_0028: ret + + IL_0029: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_002e: ldarg.0 + IL_002f: ldfld !1 class '<>f__AnonymousType1701169138`2'j__TPar',!'j__TPar'>::B@ + IL_0034: ldarg.1 + IL_0035: ldfld !1 class '<>f__AnonymousType1701169138`2'j__TPar',!'j__TPar'>::B@ + IL_003a: tail. + IL_003c: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0041: ret + + IL_0042: ldc.i4.1 + IL_0043: ret + + IL_0044: ldarg.1 + IL_0045: brfalse.s IL_0049 + + IL_0047: ldc.i4.m1 + IL_0048: ret + + IL_0049: ldc.i4.0 + IL_004a: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: unbox.any class '<>f__AnonymousType1701169138`2'j__TPar',!'j__TPar'> + IL_0007: tail. + IL_0009: callvirt instance int32 class '<>f__AnonymousType1701169138`2'j__TPar',!'j__TPar'>::CompareTo(class '<>f__AnonymousType1701169138`2') + IL_000e: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj, class [runtime]System.Collections.IComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType1701169138`2'j__TPar',!'j__TPar'> V_0, + class '<>f__AnonymousType1701169138`2'j__TPar',!'j__TPar'> V_1, + int32 V_2) + IL_0000: ldarg.1 + IL_0001: unbox.any class '<>f__AnonymousType1701169138`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: stloc.1 + IL_0009: ldarg.0 + IL_000a: brfalse.s IL_004a + + IL_000c: ldarg.1 + IL_000d: unbox.any class '<>f__AnonymousType1701169138`2'j__TPar',!'j__TPar'> + IL_0012: brfalse.s IL_0048 + + IL_0014: ldarg.2 + IL_0015: ldarg.0 + IL_0016: ldfld !0 class '<>f__AnonymousType1701169138`2'j__TPar',!'j__TPar'>::A@ + IL_001b: ldloc.1 + IL_001c: ldfld !0 class '<>f__AnonymousType1701169138`2'j__TPar',!'j__TPar'>::A@ + IL_0021: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0026: stloc.2 + IL_0027: ldloc.2 + IL_0028: ldc.i4.0 + IL_0029: bge.s IL_002d + + IL_002b: ldloc.2 + IL_002c: ret + + IL_002d: ldloc.2 + IL_002e: ldc.i4.0 + IL_002f: ble.s IL_0033 + + IL_0031: ldloc.2 + IL_0032: ret + + IL_0033: ldarg.2 + IL_0034: ldarg.0 + IL_0035: ldfld !1 class '<>f__AnonymousType1701169138`2'j__TPar',!'j__TPar'>::B@ + IL_003a: ldloc.1 + IL_003b: ldfld !1 class '<>f__AnonymousType1701169138`2'j__TPar',!'j__TPar'>::B@ + IL_0040: tail. + IL_0042: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0047: ret + + IL_0048: ldc.i4.1 + IL_0049: ret + + IL_004a: ldarg.1 + IL_004b: unbox.any class '<>f__AnonymousType1701169138`2'j__TPar',!'j__TPar'> + IL_0050: brfalse.s IL_0054 + + IL_0052: ldc.i4.m1 + IL_0053: ret + + IL_0054: ldc.i4.0 + IL_0055: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode(class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 7 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_003d + + IL_0003: ldc.i4.0 + IL_0004: stloc.0 + IL_0005: ldc.i4 0x9e3779b9 + IL_000a: ldarg.1 + IL_000b: ldarg.0 + IL_000c: ldfld !1 class '<>f__AnonymousType1701169138`2'j__TPar',!'j__TPar'>::B@ + IL_0011: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0016: ldloc.0 + IL_0017: ldc.i4.6 + IL_0018: shl + IL_0019: ldloc.0 + IL_001a: ldc.i4.2 + IL_001b: shr + IL_001c: add + IL_001d: add + IL_001e: add + IL_001f: stloc.0 + IL_0020: ldc.i4 0x9e3779b9 + IL_0025: ldarg.1 + IL_0026: ldarg.0 + IL_0027: ldfld !0 class '<>f__AnonymousType1701169138`2'j__TPar',!'j__TPar'>::A@ + IL_002c: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0031: ldloc.0 + IL_0032: ldc.i4.6 + IL_0033: shl + IL_0034: ldloc.0 + IL_0035: ldc.i4.2 + IL_0036: shr + IL_0037: add + IL_0038: add + IL_0039: add + IL_003a: stloc.0 + IL_003b: ldloc.0 + IL_003c: ret + + IL_003d: ldc.i4.0 + IL_003e: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() + IL_0006: tail. + IL_0008: callvirt instance int32 class '<>f__AnonymousType1701169138`2'j__TPar',!'j__TPar'>::GetHashCode(class [runtime]System.Collections.IEqualityComparer) + IL_000d: ret + } + + .method public hidebysig instance bool Equals(class '<>f__AnonymousType1701169138`2'j__TPar',!'j__TPar'> obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType1701169138`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0035 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0033 + + IL_0006: ldarg.1 + IL_0007: stloc.0 + IL_0008: ldarg.2 + IL_0009: ldarg.0 + IL_000a: ldfld !0 class '<>f__AnonymousType1701169138`2'j__TPar',!'j__TPar'>::A@ + IL_000f: ldloc.0 + IL_0010: ldfld !0 class '<>f__AnonymousType1701169138`2'j__TPar',!'j__TPar'>::A@ + IL_0015: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_001a: brfalse.s IL_0031 + + IL_001c: ldarg.2 + IL_001d: ldarg.0 + IL_001e: ldfld !1 class '<>f__AnonymousType1701169138`2'j__TPar',!'j__TPar'>::B@ + IL_0023: ldloc.0 + IL_0024: ldfld !1 class '<>f__AnonymousType1701169138`2'j__TPar',!'j__TPar'>::B@ + IL_0029: tail. + IL_002b: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_0030: ret + + IL_0031: ldc.i4.0 + IL_0032: ret + + IL_0033: ldc.i4.0 + IL_0034: ret + + IL_0035: ldarg.1 + IL_0036: ldnull + IL_0037: cgt.un + IL_0039: ldc.i4.0 + IL_003a: ceq + IL_003c: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType1701169138`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType1701169138`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0015 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: ldarg.2 + IL_000d: tail. + IL_000f: callvirt instance bool class '<>f__AnonymousType1701169138`2'j__TPar',!'j__TPar'>::Equals(class '<>f__AnonymousType1701169138`2', + class [runtime]System.Collections.IEqualityComparer) + IL_0014: ret + + IL_0015: ldc.i4.0 + IL_0016: ret + } + + .method public hidebysig virtual final instance bool Equals(class '<>f__AnonymousType1701169138`2'j__TPar',!'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0031 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_002f + + IL_0006: ldarg.0 + IL_0007: ldfld !0 class '<>f__AnonymousType1701169138`2'j__TPar',!'j__TPar'>::A@ + IL_000c: ldarg.1 + IL_000d: ldfld !0 class '<>f__AnonymousType1701169138`2'j__TPar',!'j__TPar'>::A@ + IL_0012: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_0017: brfalse.s IL_002d + + IL_0019: ldarg.0 + IL_001a: ldfld !1 class '<>f__AnonymousType1701169138`2'j__TPar',!'j__TPar'>::B@ + IL_001f: ldarg.1 + IL_0020: ldfld !1 class '<>f__AnonymousType1701169138`2'j__TPar',!'j__TPar'>::B@ + IL_0025: tail. + IL_0027: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_002c: ret + + IL_002d: ldc.i4.0 + IL_002e: ret + + IL_002f: ldc.i4.0 + IL_0030: ret + + IL_0031: ldarg.1 + IL_0032: ldnull + IL_0033: cgt.un + IL_0035: ldc.i4.0 + IL_0036: ceq + IL_0038: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (class '<>f__AnonymousType1701169138`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType1701169138`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0014 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: tail. + IL_000e: callvirt instance bool class '<>f__AnonymousType1701169138`2'j__TPar',!'j__TPar'>::Equals(class '<>f__AnonymousType1701169138`2') + IL_0013: ret + + IL_0014: ldc.i4.0 + IL_0015: ret + } + + .property instance !'j__TPar' A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType1701169138`2'::get_A() + } + .property instance !'j__TPar' B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType1701169138`2'::get_B() + } +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_NoOverlap_Spread_Spread.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_NoOverlap_Spread_Spread.fs new file mode 100644 index 00000000000..b6930889352 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_NoOverlap_Spread_Spread.fs @@ -0,0 +1,16 @@ +[] +type R1 = { A : int; B : int } +[] +type R2 = { C : int; D : int } +[] +type R3 = { A : int; B : int; C : int; D : int } + +let r1 = { A = 1; B = 2 } +let r2 = { C = 3; D = 4 } +let r3 = { ...r1; ...r2 } +let r3' = { ...r2; ...r3 } + +let r1' = {| A = 1; B = 2 |} +let r2' = {| C = 3; D = 4 |} +let r3'' = { ...r1; ...r2 } +let r3''' = { ...r2; ...r3 } diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_NoOverlap_Spread_Spread.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_NoOverlap_Spread_Spread.fs.il.bsl new file mode 100644 index 00000000000..3edba97630a --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_NoOverlap_Spread_Spread.fs.il.bsl @@ -0,0 +1,1420 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable sealed nested public R1 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.DefaultAugmentationAttribute::.ctor(bool) = ( 01 00 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly int32 A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly int32 B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname instance int32 get_A() 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: ldfld int32 assembly/R1::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance int32 get_B() 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: ldfld int32 assembly/R1::B@ + IL_0006: ret + } + + .method public specialname rtspecialname instance void .ctor(int32 a, int32 b) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 2D 45 78 70 72 65 73 73 69 6F + 6E 5F 4E 6F 6D 69 6E 61 6C 5F 4E 6F 4F 76 65 72 + 6C 61 70 5F 53 70 72 65 61 64 5F 53 70 72 65 61 + 64 2B 52 31 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld int32 assembly/R1::A@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld int32 assembly/R1::B@ + IL_0014: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/R1>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .property instance int32 A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance int32 assembly/R1::get_A() + } + .property instance int32 B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance int32 assembly/R1::get_B() + } + } + + .class auto ansi serializable sealed nested public R2 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.DefaultAugmentationAttribute::.ctor(bool) = ( 01 00 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly int32 C@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly int32 D@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname instance int32 get_C() 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: ldfld int32 assembly/R2::C@ + IL_0006: ret + } + + .method public hidebysig specialname instance int32 get_D() 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: ldfld int32 assembly/R2::D@ + IL_0006: ret + } + + .method public specialname rtspecialname instance void .ctor(int32 c, int32 d) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 2D 45 78 70 72 65 73 73 69 6F + 6E 5F 4E 6F 6D 69 6E 61 6C 5F 4E 6F 4F 76 65 72 + 6C 61 70 5F 53 70 72 65 61 64 5F 53 70 72 65 61 + 64 2B 52 32 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld int32 assembly/R2::C@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld int32 assembly/R2::D@ + IL_0014: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/R2>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .property instance int32 C() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance int32 assembly/R2::get_C() + } + .property instance int32 D() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance int32 assembly/R2::get_D() + } + } + + .class auto ansi serializable sealed nested public R3 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.DefaultAugmentationAttribute::.ctor(bool) = ( 01 00 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly int32 A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly int32 B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly int32 C@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly int32 D@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname instance int32 get_A() 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: ldfld int32 assembly/R3::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance int32 get_B() 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: ldfld int32 assembly/R3::B@ + IL_0006: ret + } + + .method public hidebysig specialname instance int32 get_C() 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: ldfld int32 assembly/R3::C@ + IL_0006: ret + } + + .method public hidebysig specialname instance int32 get_D() 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: ldfld int32 assembly/R3::D@ + IL_0006: ret + } + + .method public specialname rtspecialname + instance void .ctor(int32 a, + int32 b, + int32 c, + int32 d) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 2D 45 78 70 72 65 73 73 69 6F + 6E 5F 4E 6F 6D 69 6E 61 6C 5F 4E 6F 4F 76 65 72 + 6C 61 70 5F 53 70 72 65 61 64 5F 53 70 72 65 61 + 64 2B 52 33 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld int32 assembly/R3::A@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld int32 assembly/R3::B@ + IL_0014: ldarg.0 + IL_0015: ldarg.3 + IL_0016: stfld int32 assembly/R3::C@ + IL_001b: ldarg.0 + IL_001c: ldarg.s d + IL_001e: stfld int32 assembly/R3::D@ + IL_0023: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/R3>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .property instance int32 A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance int32 assembly/R3::get_A() + } + .property instance int32 B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance int32 assembly/R3::get_B() + } + .property instance int32 C() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 02 00 00 00 00 00 ) + .get instance int32 assembly/R3::get_C() + } + .property instance int32 D() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 03 00 00 00 00 00 ) + .get instance int32 assembly/R3::get_D() + } + } + + .field static assembly class assembly/R1 r1@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 class assembly/R2 r2@9 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly class assembly/R3 r3@10 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly class assembly/R3 'r3\'@11' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly class '<>f__AnonymousType3917092570`2' 'r1\'@13' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly class '<>f__AnonymousType4292577119`2' 'r2\'@14' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly class assembly/R3 'r3\'\'@15' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly class assembly/R3 'r3\'\'\'@16' + .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 assembly/R1 get_r1() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class assembly/R1 assembly::r1@8 + IL_0005: ret + } + + .method public specialname static class assembly/R2 get_r2() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class assembly/R2 assembly::r2@9 + IL_0005: ret + } + + .method public specialname static class assembly/R3 get_r3() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class assembly/R3 assembly::r3@10 + IL_0005: ret + } + + .method public specialname static class assembly/R3 'get_r3\''() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class assembly/R3 assembly::'r3\'@11' + IL_0005: ret + } + + .method public specialname static class '<>f__AnonymousType3917092570`2' 'get_r1\''() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class '<>f__AnonymousType3917092570`2' assembly::'r1\'@13' + IL_0005: ret + } + + .method public specialname static class '<>f__AnonymousType4292577119`2' 'get_r2\''() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class '<>f__AnonymousType4292577119`2' assembly::'r2\'@14' + IL_0005: ret + } + + .method public specialname static class assembly/R3 'get_r3\'\''() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class assembly/R3 assembly::'r3\'\'@15' + IL_0005: ret + } + + .method public specialname static class assembly/R3 'get_r3\'\'\''() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class assembly/R3 assembly::'r3\'\'\'@16' + IL_0005: ret + } + + .method private specialname rtspecialname static void .cctor() cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.0 + IL_0001: stsfld int32 ''.$assembly::init@ + IL_0006: ldsfld int32 ''.$assembly::init@ + IL_000b: pop + IL_000c: ret + } + + .method assembly static void staticInitialization@() cil managed + { + + .maxstack 6 + IL_0000: ldc.i4.1 + IL_0001: ldc.i4.2 + IL_0002: newobj instance void assembly/R1::.ctor(int32, + int32) + IL_0007: stsfld class assembly/R1 assembly::r1@8 + IL_000c: ldc.i4.3 + IL_000d: ldc.i4.4 + IL_000e: newobj instance void assembly/R2::.ctor(int32, + int32) + IL_0013: stsfld class assembly/R2 assembly::r2@9 + IL_0018: call class assembly/R1 assembly::get_r1() + IL_001d: ldfld int32 assembly/R1::A@ + IL_0022: call class assembly/R1 assembly::get_r1() + IL_0027: ldfld int32 assembly/R1::B@ + IL_002c: call class assembly/R2 assembly::get_r2() + IL_0031: ldfld int32 assembly/R2::C@ + IL_0036: call class assembly/R2 assembly::get_r2() + IL_003b: ldfld int32 assembly/R2::D@ + IL_0040: newobj instance void assembly/R3::.ctor(int32, + int32, + int32, + int32) + IL_0045: stsfld class assembly/R3 assembly::r3@10 + IL_004a: call class assembly/R3 assembly::get_r3() + IL_004f: ldfld int32 assembly/R3::A@ + IL_0054: call class assembly/R3 assembly::get_r3() + IL_0059: ldfld int32 assembly/R3::B@ + IL_005e: call class assembly/R3 assembly::get_r3() + IL_0063: ldfld int32 assembly/R3::C@ + IL_0068: call class assembly/R3 assembly::get_r3() + IL_006d: ldfld int32 assembly/R3::D@ + IL_0072: newobj instance void assembly/R3::.ctor(int32, + int32, + int32, + int32) + IL_0077: stsfld class assembly/R3 assembly::'r3\'@11' + IL_007c: ldc.i4.1 + IL_007d: ldc.i4.2 + IL_007e: newobj instance void class '<>f__AnonymousType3917092570`2'::.ctor(!0, + !1) + IL_0083: stsfld class '<>f__AnonymousType3917092570`2' assembly::'r1\'@13' + IL_0088: ldc.i4.3 + IL_0089: ldc.i4.4 + IL_008a: newobj instance void class '<>f__AnonymousType4292577119`2'::.ctor(!0, + !1) + IL_008f: stsfld class '<>f__AnonymousType4292577119`2' assembly::'r2\'@14' + IL_0094: call class assembly/R1 assembly::get_r1() + IL_0099: ldfld int32 assembly/R1::A@ + IL_009e: call class assembly/R1 assembly::get_r1() + IL_00a3: ldfld int32 assembly/R1::B@ + IL_00a8: call class assembly/R2 assembly::get_r2() + IL_00ad: ldfld int32 assembly/R2::C@ + IL_00b2: call class assembly/R2 assembly::get_r2() + IL_00b7: ldfld int32 assembly/R2::D@ + IL_00bc: newobj instance void assembly/R3::.ctor(int32, + int32, + int32, + int32) + IL_00c1: stsfld class assembly/R3 assembly::'r3\'\'@15' + IL_00c6: call class assembly/R3 assembly::get_r3() + IL_00cb: ldfld int32 assembly/R3::A@ + IL_00d0: call class assembly/R3 assembly::get_r3() + IL_00d5: ldfld int32 assembly/R3::B@ + IL_00da: call class assembly/R3 assembly::get_r3() + IL_00df: ldfld int32 assembly/R3::C@ + IL_00e4: call class assembly/R3 assembly::get_r3() + IL_00e9: ldfld int32 assembly/R3::D@ + IL_00ee: newobj instance void assembly/R3::.ctor(int32, + int32, + int32, + int32) + IL_00f3: stsfld class assembly/R3 assembly::'r3\'\'\'@16' + IL_00f8: ret + } + + .property class assembly/R1 + r1() + { + .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 class assembly/R1 assembly::get_r1() + } + .property class assembly/R2 + r2() + { + .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 class assembly/R2 assembly::get_r2() + } + .property class assembly/R3 + r3() + { + .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 class assembly/R3 assembly::get_r3() + } + .property class assembly/R3 + 'r3\''() + { + .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 class assembly/R3 assembly::'get_r3\''() + } + .property class '<>f__AnonymousType3917092570`2' + 'r1\''() + { + .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 class '<>f__AnonymousType3917092570`2' assembly::'get_r1\''() + } + .property class '<>f__AnonymousType4292577119`2' + 'r2\''() + { + .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 class '<>f__AnonymousType4292577119`2' assembly::'get_r2\''() + } + .property class assembly/R3 + 'r3\'\''() + { + .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 class assembly/R3 assembly::'get_r3\'\''() + } + .property class assembly/R3 + 'r3\'\'\''() + { + .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 class assembly/R3 assembly::'get_r3\'\'\''() + } +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .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 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: call void assembly::staticInitialization@() + IL_0005: ret + } + +} + +.class public auto ansi serializable sealed beforefieldinit '<>f__AnonymousType3917092570`2'<'j__TPar','j__TPar'> + extends [runtime]System.Object + implements [runtime]System.Collections.IStructuralComparable, + [runtime]System.IComparable, + class [runtime]System.IComparable`1f__AnonymousType3917092570`2'j__TPar',!'j__TPar'>>, + [runtime]System.Collections.IStructuralEquatable, + class [runtime]System.IEquatable`1f__AnonymousType3917092570`2'j__TPar',!'j__TPar'>> +{ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field private !'j__TPar' A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field private !'j__TPar' B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor(!'j__TPar' A, !'j__TPar' B) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 1E 3C 3E 66 5F 5F 41 6E 6F 6E + 79 6D 6F 75 73 54 79 70 65 33 39 31 37 30 39 32 + 35 37 30 60 32 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld !0 class '<>f__AnonymousType3917092570`2'j__TPar',!'j__TPar'>::A@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld !1 class '<>f__AnonymousType3917092570`2'j__TPar',!'j__TPar'>::B@ + IL_0014: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_A() 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: ldfld !0 class '<>f__AnonymousType3917092570`2'j__TPar',!'j__TPar'>::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_B() 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: ldfld !1 class '<>f__AnonymousType3917092570`2'j__TPar',!'j__TPar'>::B@ + IL_0006: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5f__AnonymousType3917092570`2'j__TPar',!'j__TPar'>,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class '<>f__AnonymousType3917092570`2'j__TPar',!'j__TPar'>>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToStringf__AnonymousType3917092570`2'j__TPar',!'j__TPar'>,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2f__AnonymousType3917092570`2'j__TPar',!'j__TPar'>,string>::Invoke(!0) + IL_0015: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(class '<>f__AnonymousType3917092570`2'j__TPar',!'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0044 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0042 + + IL_0006: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_000b: ldarg.0 + IL_000c: ldfld !0 class '<>f__AnonymousType3917092570`2'j__TPar',!'j__TPar'>::A@ + IL_0011: ldarg.1 + IL_0012: ldfld !0 class '<>f__AnonymousType3917092570`2'j__TPar',!'j__TPar'>::A@ + IL_0017: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_001c: stloc.0 + IL_001d: ldloc.0 + IL_001e: ldc.i4.0 + IL_001f: bge.s IL_0023 + + IL_0021: ldloc.0 + IL_0022: ret + + IL_0023: ldloc.0 + IL_0024: ldc.i4.0 + IL_0025: ble.s IL_0029 + + IL_0027: ldloc.0 + IL_0028: ret + + IL_0029: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_002e: ldarg.0 + IL_002f: ldfld !1 class '<>f__AnonymousType3917092570`2'j__TPar',!'j__TPar'>::B@ + IL_0034: ldarg.1 + IL_0035: ldfld !1 class '<>f__AnonymousType3917092570`2'j__TPar',!'j__TPar'>::B@ + IL_003a: tail. + IL_003c: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0041: ret + + IL_0042: ldc.i4.1 + IL_0043: ret + + IL_0044: ldarg.1 + IL_0045: brfalse.s IL_0049 + + IL_0047: ldc.i4.m1 + IL_0048: ret + + IL_0049: ldc.i4.0 + IL_004a: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: unbox.any class '<>f__AnonymousType3917092570`2'j__TPar',!'j__TPar'> + IL_0007: tail. + IL_0009: callvirt instance int32 class '<>f__AnonymousType3917092570`2'j__TPar',!'j__TPar'>::CompareTo(class '<>f__AnonymousType3917092570`2') + IL_000e: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj, class [runtime]System.Collections.IComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType3917092570`2'j__TPar',!'j__TPar'> V_0, + class '<>f__AnonymousType3917092570`2'j__TPar',!'j__TPar'> V_1, + int32 V_2) + IL_0000: ldarg.1 + IL_0001: unbox.any class '<>f__AnonymousType3917092570`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: stloc.1 + IL_0009: ldarg.0 + IL_000a: brfalse.s IL_004a + + IL_000c: ldarg.1 + IL_000d: unbox.any class '<>f__AnonymousType3917092570`2'j__TPar',!'j__TPar'> + IL_0012: brfalse.s IL_0048 + + IL_0014: ldarg.2 + IL_0015: ldarg.0 + IL_0016: ldfld !0 class '<>f__AnonymousType3917092570`2'j__TPar',!'j__TPar'>::A@ + IL_001b: ldloc.1 + IL_001c: ldfld !0 class '<>f__AnonymousType3917092570`2'j__TPar',!'j__TPar'>::A@ + IL_0021: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0026: stloc.2 + IL_0027: ldloc.2 + IL_0028: ldc.i4.0 + IL_0029: bge.s IL_002d + + IL_002b: ldloc.2 + IL_002c: ret + + IL_002d: ldloc.2 + IL_002e: ldc.i4.0 + IL_002f: ble.s IL_0033 + + IL_0031: ldloc.2 + IL_0032: ret + + IL_0033: ldarg.2 + IL_0034: ldarg.0 + IL_0035: ldfld !1 class '<>f__AnonymousType3917092570`2'j__TPar',!'j__TPar'>::B@ + IL_003a: ldloc.1 + IL_003b: ldfld !1 class '<>f__AnonymousType3917092570`2'j__TPar',!'j__TPar'>::B@ + IL_0040: tail. + IL_0042: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0047: ret + + IL_0048: ldc.i4.1 + IL_0049: ret + + IL_004a: ldarg.1 + IL_004b: unbox.any class '<>f__AnonymousType3917092570`2'j__TPar',!'j__TPar'> + IL_0050: brfalse.s IL_0054 + + IL_0052: ldc.i4.m1 + IL_0053: ret + + IL_0054: ldc.i4.0 + IL_0055: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode(class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 7 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_003d + + IL_0003: ldc.i4.0 + IL_0004: stloc.0 + IL_0005: ldc.i4 0x9e3779b9 + IL_000a: ldarg.1 + IL_000b: ldarg.0 + IL_000c: ldfld !1 class '<>f__AnonymousType3917092570`2'j__TPar',!'j__TPar'>::B@ + IL_0011: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0016: ldloc.0 + IL_0017: ldc.i4.6 + IL_0018: shl + IL_0019: ldloc.0 + IL_001a: ldc.i4.2 + IL_001b: shr + IL_001c: add + IL_001d: add + IL_001e: add + IL_001f: stloc.0 + IL_0020: ldc.i4 0x9e3779b9 + IL_0025: ldarg.1 + IL_0026: ldarg.0 + IL_0027: ldfld !0 class '<>f__AnonymousType3917092570`2'j__TPar',!'j__TPar'>::A@ + IL_002c: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0031: ldloc.0 + IL_0032: ldc.i4.6 + IL_0033: shl + IL_0034: ldloc.0 + IL_0035: ldc.i4.2 + IL_0036: shr + IL_0037: add + IL_0038: add + IL_0039: add + IL_003a: stloc.0 + IL_003b: ldloc.0 + IL_003c: ret + + IL_003d: ldc.i4.0 + IL_003e: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() + IL_0006: tail. + IL_0008: callvirt instance int32 class '<>f__AnonymousType3917092570`2'j__TPar',!'j__TPar'>::GetHashCode(class [runtime]System.Collections.IEqualityComparer) + IL_000d: ret + } + + .method public hidebysig instance bool Equals(class '<>f__AnonymousType3917092570`2'j__TPar',!'j__TPar'> obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType3917092570`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0035 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0033 + + IL_0006: ldarg.1 + IL_0007: stloc.0 + IL_0008: ldarg.2 + IL_0009: ldarg.0 + IL_000a: ldfld !0 class '<>f__AnonymousType3917092570`2'j__TPar',!'j__TPar'>::A@ + IL_000f: ldloc.0 + IL_0010: ldfld !0 class '<>f__AnonymousType3917092570`2'j__TPar',!'j__TPar'>::A@ + IL_0015: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_001a: brfalse.s IL_0031 + + IL_001c: ldarg.2 + IL_001d: ldarg.0 + IL_001e: ldfld !1 class '<>f__AnonymousType3917092570`2'j__TPar',!'j__TPar'>::B@ + IL_0023: ldloc.0 + IL_0024: ldfld !1 class '<>f__AnonymousType3917092570`2'j__TPar',!'j__TPar'>::B@ + IL_0029: tail. + IL_002b: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_0030: ret + + IL_0031: ldc.i4.0 + IL_0032: ret + + IL_0033: ldc.i4.0 + IL_0034: ret + + IL_0035: ldarg.1 + IL_0036: ldnull + IL_0037: cgt.un + IL_0039: ldc.i4.0 + IL_003a: ceq + IL_003c: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType3917092570`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType3917092570`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0015 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: ldarg.2 + IL_000d: tail. + IL_000f: callvirt instance bool class '<>f__AnonymousType3917092570`2'j__TPar',!'j__TPar'>::Equals(class '<>f__AnonymousType3917092570`2', + class [runtime]System.Collections.IEqualityComparer) + IL_0014: ret + + IL_0015: ldc.i4.0 + IL_0016: ret + } + + .method public hidebysig virtual final instance bool Equals(class '<>f__AnonymousType3917092570`2'j__TPar',!'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0031 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_002f + + IL_0006: ldarg.0 + IL_0007: ldfld !0 class '<>f__AnonymousType3917092570`2'j__TPar',!'j__TPar'>::A@ + IL_000c: ldarg.1 + IL_000d: ldfld !0 class '<>f__AnonymousType3917092570`2'j__TPar',!'j__TPar'>::A@ + IL_0012: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_0017: brfalse.s IL_002d + + IL_0019: ldarg.0 + IL_001a: ldfld !1 class '<>f__AnonymousType3917092570`2'j__TPar',!'j__TPar'>::B@ + IL_001f: ldarg.1 + IL_0020: ldfld !1 class '<>f__AnonymousType3917092570`2'j__TPar',!'j__TPar'>::B@ + IL_0025: tail. + IL_0027: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_002c: ret + + IL_002d: ldc.i4.0 + IL_002e: ret + + IL_002f: ldc.i4.0 + IL_0030: ret + + IL_0031: ldarg.1 + IL_0032: ldnull + IL_0033: cgt.un + IL_0035: ldc.i4.0 + IL_0036: ceq + IL_0038: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (class '<>f__AnonymousType3917092570`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType3917092570`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0014 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: tail. + IL_000e: callvirt instance bool class '<>f__AnonymousType3917092570`2'j__TPar',!'j__TPar'>::Equals(class '<>f__AnonymousType3917092570`2') + IL_0013: ret + + IL_0014: ldc.i4.0 + IL_0015: ret + } + + .property instance !'j__TPar' A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType3917092570`2'::get_A() + } + .property instance !'j__TPar' B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType3917092570`2'::get_B() + } +} + +.class public auto ansi serializable sealed beforefieldinit '<>f__AnonymousType4292577119`2'<'j__TPar','j__TPar'> + extends [runtime]System.Object + implements [runtime]System.Collections.IStructuralComparable, + [runtime]System.IComparable, + class [runtime]System.IComparable`1f__AnonymousType4292577119`2'j__TPar',!'j__TPar'>>, + [runtime]System.Collections.IStructuralEquatable, + class [runtime]System.IEquatable`1f__AnonymousType4292577119`2'j__TPar',!'j__TPar'>> +{ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field private !'j__TPar' C@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field private !'j__TPar' D@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor(!'j__TPar' C, !'j__TPar' D) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 1E 3C 3E 66 5F 5F 41 6E 6F 6E + 79 6D 6F 75 73 54 79 70 65 34 32 39 32 35 37 37 + 31 31 39 60 32 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld !0 class '<>f__AnonymousType4292577119`2'j__TPar',!'j__TPar'>::C@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld !1 class '<>f__AnonymousType4292577119`2'j__TPar',!'j__TPar'>::D@ + IL_0014: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_C() 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: ldfld !0 class '<>f__AnonymousType4292577119`2'j__TPar',!'j__TPar'>::C@ + IL_0006: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_D() 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: ldfld !1 class '<>f__AnonymousType4292577119`2'j__TPar',!'j__TPar'>::D@ + IL_0006: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5f__AnonymousType4292577119`2'j__TPar',!'j__TPar'>,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class '<>f__AnonymousType4292577119`2'j__TPar',!'j__TPar'>>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToStringf__AnonymousType4292577119`2'j__TPar',!'j__TPar'>,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2f__AnonymousType4292577119`2'j__TPar',!'j__TPar'>,string>::Invoke(!0) + IL_0015: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(class '<>f__AnonymousType4292577119`2'j__TPar',!'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0044 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0042 + + IL_0006: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_000b: ldarg.0 + IL_000c: ldfld !0 class '<>f__AnonymousType4292577119`2'j__TPar',!'j__TPar'>::C@ + IL_0011: ldarg.1 + IL_0012: ldfld !0 class '<>f__AnonymousType4292577119`2'j__TPar',!'j__TPar'>::C@ + IL_0017: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_001c: stloc.0 + IL_001d: ldloc.0 + IL_001e: ldc.i4.0 + IL_001f: bge.s IL_0023 + + IL_0021: ldloc.0 + IL_0022: ret + + IL_0023: ldloc.0 + IL_0024: ldc.i4.0 + IL_0025: ble.s IL_0029 + + IL_0027: ldloc.0 + IL_0028: ret + + IL_0029: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_002e: ldarg.0 + IL_002f: ldfld !1 class '<>f__AnonymousType4292577119`2'j__TPar',!'j__TPar'>::D@ + IL_0034: ldarg.1 + IL_0035: ldfld !1 class '<>f__AnonymousType4292577119`2'j__TPar',!'j__TPar'>::D@ + IL_003a: tail. + IL_003c: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0041: ret + + IL_0042: ldc.i4.1 + IL_0043: ret + + IL_0044: ldarg.1 + IL_0045: brfalse.s IL_0049 + + IL_0047: ldc.i4.m1 + IL_0048: ret + + IL_0049: ldc.i4.0 + IL_004a: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: unbox.any class '<>f__AnonymousType4292577119`2'j__TPar',!'j__TPar'> + IL_0007: tail. + IL_0009: callvirt instance int32 class '<>f__AnonymousType4292577119`2'j__TPar',!'j__TPar'>::CompareTo(class '<>f__AnonymousType4292577119`2') + IL_000e: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj, class [runtime]System.Collections.IComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType4292577119`2'j__TPar',!'j__TPar'> V_0, + class '<>f__AnonymousType4292577119`2'j__TPar',!'j__TPar'> V_1, + int32 V_2) + IL_0000: ldarg.1 + IL_0001: unbox.any class '<>f__AnonymousType4292577119`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: stloc.1 + IL_0009: ldarg.0 + IL_000a: brfalse.s IL_004a + + IL_000c: ldarg.1 + IL_000d: unbox.any class '<>f__AnonymousType4292577119`2'j__TPar',!'j__TPar'> + IL_0012: brfalse.s IL_0048 + + IL_0014: ldarg.2 + IL_0015: ldarg.0 + IL_0016: ldfld !0 class '<>f__AnonymousType4292577119`2'j__TPar',!'j__TPar'>::C@ + IL_001b: ldloc.1 + IL_001c: ldfld !0 class '<>f__AnonymousType4292577119`2'j__TPar',!'j__TPar'>::C@ + IL_0021: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0026: stloc.2 + IL_0027: ldloc.2 + IL_0028: ldc.i4.0 + IL_0029: bge.s IL_002d + + IL_002b: ldloc.2 + IL_002c: ret + + IL_002d: ldloc.2 + IL_002e: ldc.i4.0 + IL_002f: ble.s IL_0033 + + IL_0031: ldloc.2 + IL_0032: ret + + IL_0033: ldarg.2 + IL_0034: ldarg.0 + IL_0035: ldfld !1 class '<>f__AnonymousType4292577119`2'j__TPar',!'j__TPar'>::D@ + IL_003a: ldloc.1 + IL_003b: ldfld !1 class '<>f__AnonymousType4292577119`2'j__TPar',!'j__TPar'>::D@ + IL_0040: tail. + IL_0042: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0047: ret + + IL_0048: ldc.i4.1 + IL_0049: ret + + IL_004a: ldarg.1 + IL_004b: unbox.any class '<>f__AnonymousType4292577119`2'j__TPar',!'j__TPar'> + IL_0050: brfalse.s IL_0054 + + IL_0052: ldc.i4.m1 + IL_0053: ret + + IL_0054: ldc.i4.0 + IL_0055: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode(class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 7 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_003d + + IL_0003: ldc.i4.0 + IL_0004: stloc.0 + IL_0005: ldc.i4 0x9e3779b9 + IL_000a: ldarg.1 + IL_000b: ldarg.0 + IL_000c: ldfld !1 class '<>f__AnonymousType4292577119`2'j__TPar',!'j__TPar'>::D@ + IL_0011: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0016: ldloc.0 + IL_0017: ldc.i4.6 + IL_0018: shl + IL_0019: ldloc.0 + IL_001a: ldc.i4.2 + IL_001b: shr + IL_001c: add + IL_001d: add + IL_001e: add + IL_001f: stloc.0 + IL_0020: ldc.i4 0x9e3779b9 + IL_0025: ldarg.1 + IL_0026: ldarg.0 + IL_0027: ldfld !0 class '<>f__AnonymousType4292577119`2'j__TPar',!'j__TPar'>::C@ + IL_002c: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0031: ldloc.0 + IL_0032: ldc.i4.6 + IL_0033: shl + IL_0034: ldloc.0 + IL_0035: ldc.i4.2 + IL_0036: shr + IL_0037: add + IL_0038: add + IL_0039: add + IL_003a: stloc.0 + IL_003b: ldloc.0 + IL_003c: ret + + IL_003d: ldc.i4.0 + IL_003e: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() + IL_0006: tail. + IL_0008: callvirt instance int32 class '<>f__AnonymousType4292577119`2'j__TPar',!'j__TPar'>::GetHashCode(class [runtime]System.Collections.IEqualityComparer) + IL_000d: ret + } + + .method public hidebysig instance bool Equals(class '<>f__AnonymousType4292577119`2'j__TPar',!'j__TPar'> obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType4292577119`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0035 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0033 + + IL_0006: ldarg.1 + IL_0007: stloc.0 + IL_0008: ldarg.2 + IL_0009: ldarg.0 + IL_000a: ldfld !0 class '<>f__AnonymousType4292577119`2'j__TPar',!'j__TPar'>::C@ + IL_000f: ldloc.0 + IL_0010: ldfld !0 class '<>f__AnonymousType4292577119`2'j__TPar',!'j__TPar'>::C@ + IL_0015: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_001a: brfalse.s IL_0031 + + IL_001c: ldarg.2 + IL_001d: ldarg.0 + IL_001e: ldfld !1 class '<>f__AnonymousType4292577119`2'j__TPar',!'j__TPar'>::D@ + IL_0023: ldloc.0 + IL_0024: ldfld !1 class '<>f__AnonymousType4292577119`2'j__TPar',!'j__TPar'>::D@ + IL_0029: tail. + IL_002b: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_0030: ret + + IL_0031: ldc.i4.0 + IL_0032: ret + + IL_0033: ldc.i4.0 + IL_0034: ret + + IL_0035: ldarg.1 + IL_0036: ldnull + IL_0037: cgt.un + IL_0039: ldc.i4.0 + IL_003a: ceq + IL_003c: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType4292577119`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType4292577119`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0015 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: ldarg.2 + IL_000d: tail. + IL_000f: callvirt instance bool class '<>f__AnonymousType4292577119`2'j__TPar',!'j__TPar'>::Equals(class '<>f__AnonymousType4292577119`2', + class [runtime]System.Collections.IEqualityComparer) + IL_0014: ret + + IL_0015: ldc.i4.0 + IL_0016: ret + } + + .method public hidebysig virtual final instance bool Equals(class '<>f__AnonymousType4292577119`2'j__TPar',!'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0031 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_002f + + IL_0006: ldarg.0 + IL_0007: ldfld !0 class '<>f__AnonymousType4292577119`2'j__TPar',!'j__TPar'>::C@ + IL_000c: ldarg.1 + IL_000d: ldfld !0 class '<>f__AnonymousType4292577119`2'j__TPar',!'j__TPar'>::C@ + IL_0012: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_0017: brfalse.s IL_002d + + IL_0019: ldarg.0 + IL_001a: ldfld !1 class '<>f__AnonymousType4292577119`2'j__TPar',!'j__TPar'>::D@ + IL_001f: ldarg.1 + IL_0020: ldfld !1 class '<>f__AnonymousType4292577119`2'j__TPar',!'j__TPar'>::D@ + IL_0025: tail. + IL_0027: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_002c: ret + + IL_002d: ldc.i4.0 + IL_002e: ret + + IL_002f: ldc.i4.0 + IL_0030: ret + + IL_0031: ldarg.1 + IL_0032: ldnull + IL_0033: cgt.un + IL_0035: ldc.i4.0 + IL_0036: ceq + IL_0038: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (class '<>f__AnonymousType4292577119`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType4292577119`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0014 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: tail. + IL_000e: callvirt instance bool class '<>f__AnonymousType4292577119`2'j__TPar',!'j__TPar'>::Equals(class '<>f__AnonymousType4292577119`2') + IL_0013: ret + + IL_0014: ldc.i4.0 + IL_0015: ret + } + + .property instance !'j__TPar' C() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType4292577119`2'::get_C() + } + .property instance !'j__TPar' D() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType4292577119`2'::get_D() + } +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_SpreadShadowsExplicit.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_SpreadShadowsExplicit.fs new file mode 100644 index 00000000000..f4493a6b47b --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_SpreadShadowsExplicit.fs @@ -0,0 +1,5 @@ +[] +type R1 = { A : int; B : int } + +let r1 = { A = 1; B = 2 } +let r1' = { A = 0; ...r1 } diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_SpreadShadowsExplicit.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_SpreadShadowsExplicit.fs.il.bsl new file mode 100644 index 00000000000..b46a3fe4b21 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_SpreadShadowsExplicit.fs.il.bsl @@ -0,0 +1,204 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable sealed nested public R1 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.DefaultAugmentationAttribute::.ctor(bool) = ( 01 00 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly int32 A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly int32 B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname instance int32 get_A() 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: ldfld int32 assembly/R1::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance int32 get_B() 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: ldfld int32 assembly/R1::B@ + IL_0006: ret + } + + .method public specialname rtspecialname instance void .ctor(int32 a, int32 b) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 2B 45 78 70 72 65 73 73 69 6F + 6E 5F 4E 6F 6D 69 6E 61 6C 5F 53 70 72 65 61 64 + 53 68 61 64 6F 77 73 45 78 70 6C 69 63 69 74 2B + 52 31 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld int32 assembly/R1::A@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld int32 assembly/R1::B@ + IL_0014: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/R1>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .property instance int32 A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance int32 assembly/R1::get_A() + } + .property instance int32 B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance int32 assembly/R1::get_B() + } + } + + .field static assembly class assembly/R1 r1@4 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly class assembly/R1 'r1\'@5' + .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 assembly/R1 get_r1() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class assembly/R1 assembly::r1@4 + IL_0005: ret + } + + .method public specialname static class assembly/R1 'get_r1\''() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class assembly/R1 assembly::'r1\'@5' + IL_0005: ret + } + + .method private specialname rtspecialname static void .cctor() cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.0 + IL_0001: stsfld int32 ''.$assembly::init@ + IL_0006: ldsfld int32 ''.$assembly::init@ + IL_000b: pop + IL_000c: ret + } + + .method assembly static void staticInitialization@() cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.1 + IL_0001: ldc.i4.2 + IL_0002: newobj instance void assembly/R1::.ctor(int32, + int32) + IL_0007: stsfld class assembly/R1 assembly::r1@4 + IL_000c: call class assembly/R1 assembly::get_r1() + IL_0011: ldfld int32 assembly/R1::A@ + IL_0016: call class assembly/R1 assembly::get_r1() + IL_001b: ldfld int32 assembly/R1::B@ + IL_0020: newobj instance void assembly/R1::.ctor(int32, + int32) + IL_0025: stsfld class assembly/R1 assembly::'r1\'@5' + IL_002a: ret + } + + .property class assembly/R1 + r1() + { + .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 class assembly/R1 assembly::get_r1() + } + .property class assembly/R1 + 'r1\''() + { + .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 class assembly/R1 assembly::'get_r1\''() + } +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .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 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: call void assembly::staticInitialization@() + IL_0005: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_SpreadShadowsSpread.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_SpreadShadowsSpread.fs new file mode 100644 index 00000000000..08df2f63e02 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_SpreadShadowsSpread.fs @@ -0,0 +1,5 @@ +[] +type R1 = { A : int; B : int } + +let r1 = { A = 1; B = 2 } +let r1' = { ...r1; ...{| A = 99 |} } diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_SpreadShadowsSpread.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_SpreadShadowsSpread.fs.il.bsl new file mode 100644 index 00000000000..8c8c81feeb3 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_SpreadShadowsSpread.fs.il.bsl @@ -0,0 +1,553 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable sealed nested public R1 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.DefaultAugmentationAttribute::.ctor(bool) = ( 01 00 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly int32 A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly int32 B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname instance int32 get_A() 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: ldfld int32 assembly/R1::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance int32 get_B() 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: ldfld int32 assembly/R1::B@ + IL_0006: ret + } + + .method public specialname rtspecialname instance void .ctor(int32 a, int32 b) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 29 45 78 70 72 65 73 73 69 6F + 6E 5F 4E 6F 6D 69 6E 61 6C 5F 53 70 72 65 61 64 + 53 68 61 64 6F 77 73 53 70 72 65 61 64 2B 52 31 + 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld int32 assembly/R1::A@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld int32 assembly/R1::B@ + IL_0014: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/R1>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .property instance int32 A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance int32 assembly/R1::get_A() + } + .property instance int32 B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance int32 assembly/R1::get_B() + } + } + + .field static assembly class assembly/R1 r1@4 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly class assembly/R1 'r1\'@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 class '<>f__AnonymousType1722350077`1' bind@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 B@5 + .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 assembly/R1 get_r1() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class assembly/R1 assembly::r1@4 + IL_0005: ret + } + + .method public specialname static class assembly/R1 'get_r1\''() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class assembly/R1 assembly::'r1\'@5' + IL_0005: ret + } + + .method assembly specialname static class '<>f__AnonymousType1722350077`1' get_bind@5() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class '<>f__AnonymousType1722350077`1' assembly::bind@5 + IL_0005: ret + } + + .method assembly specialname static int32 get_B@5() cil managed + { + + .maxstack 8 + IL_0000: ldsfld int32 assembly::B@5 + IL_0005: ret + } + + .method private specialname rtspecialname static void .cctor() cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.0 + IL_0001: stsfld int32 ''.$assembly::init@ + IL_0006: ldsfld int32 ''.$assembly::init@ + IL_000b: pop + IL_000c: ret + } + + .method assembly static void staticInitialization@() cil managed + { + + .maxstack 4 + IL_0000: ldc.i4.1 + IL_0001: ldc.i4.2 + IL_0002: newobj instance void assembly/R1::.ctor(int32, + int32) + IL_0007: stsfld class assembly/R1 assembly::r1@4 + IL_000c: nop + IL_000d: ldc.i4.s 99 + IL_000f: newobj instance void class '<>f__AnonymousType1722350077`1'::.ctor(!0) + IL_0014: stsfld class '<>f__AnonymousType1722350077`1' assembly::bind@5 + IL_0019: call class assembly/R1 assembly::get_r1() + IL_001e: ldfld int32 assembly/R1::B@ + IL_0023: stsfld int32 assembly::B@5 + IL_0028: call class '<>f__AnonymousType1722350077`1' assembly::get_bind@5() + IL_002d: call instance !0 class '<>f__AnonymousType1722350077`1'::get_A() + IL_0032: call int32 assembly::get_B@5() + IL_0037: newobj instance void assembly/R1::.ctor(int32, + int32) + IL_003c: stsfld class assembly/R1 assembly::'r1\'@5' + IL_0041: ret + } + + .property class assembly/R1 + r1() + { + .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 class assembly/R1 assembly::get_r1() + } + .property class assembly/R1 + 'r1\''() + { + .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 class assembly/R1 assembly::'get_r1\''() + } + .property class '<>f__AnonymousType1722350077`1' + bind@5() + { + .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 class '<>f__AnonymousType1722350077`1' assembly::get_bind@5() + } + .property int32 B@5() + { + .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_B@5() + } +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .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 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: call void assembly::staticInitialization@() + IL_0005: ret + } + +} + +.class public auto ansi serializable sealed beforefieldinit '<>f__AnonymousType1722350077`1'<'j__TPar'> + extends [runtime]System.Object + implements [runtime]System.Collections.IStructuralComparable, + [runtime]System.IComparable, + class [runtime]System.IComparable`1f__AnonymousType1722350077`1'j__TPar'>>, + [runtime]System.Collections.IStructuralEquatable, + class [runtime]System.IEquatable`1f__AnonymousType1722350077`1'j__TPar'>> +{ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field private !'j__TPar' A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor(!'j__TPar' A) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 1E 3C 3E 66 5F 5F 41 6E 6F 6E + 79 6D 6F 75 73 54 79 70 65 31 37 32 32 33 35 30 + 30 37 37 60 31 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld !0 class '<>f__AnonymousType1722350077`1'j__TPar'>::A@ + IL_000d: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_A() 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: ldfld !0 class '<>f__AnonymousType1722350077`1'j__TPar'>::A@ + IL_0006: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5f__AnonymousType1722350077`1'j__TPar'>,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class '<>f__AnonymousType1722350077`1'j__TPar'>>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToStringf__AnonymousType1722350077`1'j__TPar'>,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2f__AnonymousType1722350077`1'j__TPar'>,string>::Invoke(!0) + IL_0015: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(class '<>f__AnonymousType1722350077`1'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0021 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_001f + + IL_0006: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_000b: ldarg.0 + IL_000c: ldfld !0 class '<>f__AnonymousType1722350077`1'j__TPar'>::A@ + IL_0011: ldarg.1 + IL_0012: ldfld !0 class '<>f__AnonymousType1722350077`1'j__TPar'>::A@ + IL_0017: tail. + IL_0019: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_001e: ret + + IL_001f: ldc.i4.1 + IL_0020: ret + + IL_0021: ldarg.1 + IL_0022: brfalse.s IL_0026 + + IL_0024: ldc.i4.m1 + IL_0025: ret + + IL_0026: ldc.i4.0 + IL_0027: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: unbox.any class '<>f__AnonymousType1722350077`1'j__TPar'> + IL_0007: tail. + IL_0009: callvirt instance int32 class '<>f__AnonymousType1722350077`1'j__TPar'>::CompareTo(class '<>f__AnonymousType1722350077`1') + IL_000e: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj, class [runtime]System.Collections.IComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType1722350077`1'j__TPar'> V_0, + class '<>f__AnonymousType1722350077`1'j__TPar'> V_1) + IL_0000: ldarg.1 + IL_0001: unbox.any class '<>f__AnonymousType1722350077`1'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: stloc.1 + IL_0009: ldarg.0 + IL_000a: brfalse.s IL_002b + + IL_000c: ldarg.1 + IL_000d: unbox.any class '<>f__AnonymousType1722350077`1'j__TPar'> + IL_0012: brfalse.s IL_0029 + + IL_0014: ldarg.2 + IL_0015: ldarg.0 + IL_0016: ldfld !0 class '<>f__AnonymousType1722350077`1'j__TPar'>::A@ + IL_001b: ldloc.1 + IL_001c: ldfld !0 class '<>f__AnonymousType1722350077`1'j__TPar'>::A@ + IL_0021: tail. + IL_0023: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0028: ret + + IL_0029: ldc.i4.1 + IL_002a: ret + + IL_002b: ldarg.1 + IL_002c: unbox.any class '<>f__AnonymousType1722350077`1'j__TPar'> + IL_0031: brfalse.s IL_0035 + + IL_0033: ldc.i4.m1 + IL_0034: ret + + IL_0035: ldc.i4.0 + IL_0036: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode(class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 7 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0022 + + IL_0003: ldc.i4.0 + IL_0004: stloc.0 + IL_0005: ldc.i4 0x9e3779b9 + IL_000a: ldarg.1 + IL_000b: ldarg.0 + IL_000c: ldfld !0 class '<>f__AnonymousType1722350077`1'j__TPar'>::A@ + IL_0011: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0016: ldloc.0 + IL_0017: ldc.i4.6 + IL_0018: shl + IL_0019: ldloc.0 + IL_001a: ldc.i4.2 + IL_001b: shr + IL_001c: add + IL_001d: add + IL_001e: add + IL_001f: stloc.0 + IL_0020: ldloc.0 + IL_0021: ret + + IL_0022: ldc.i4.0 + IL_0023: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() + IL_0006: tail. + IL_0008: callvirt instance int32 class '<>f__AnonymousType1722350077`1'j__TPar'>::GetHashCode(class [runtime]System.Collections.IEqualityComparer) + IL_000d: ret + } + + .method public hidebysig instance bool Equals(class '<>f__AnonymousType1722350077`1'j__TPar'> obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType1722350077`1'j__TPar'> V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_001f + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_001d + + IL_0006: ldarg.1 + IL_0007: stloc.0 + IL_0008: ldarg.2 + IL_0009: ldarg.0 + IL_000a: ldfld !0 class '<>f__AnonymousType1722350077`1'j__TPar'>::A@ + IL_000f: ldloc.0 + IL_0010: ldfld !0 class '<>f__AnonymousType1722350077`1'j__TPar'>::A@ + IL_0015: tail. + IL_0017: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_001c: ret + + IL_001d: ldc.i4.0 + IL_001e: ret + + IL_001f: ldarg.1 + IL_0020: ldnull + IL_0021: cgt.un + IL_0023: ldc.i4.0 + IL_0024: ceq + IL_0026: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType1722350077`1'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType1722350077`1'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0015 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: ldarg.2 + IL_000d: tail. + IL_000f: callvirt instance bool class '<>f__AnonymousType1722350077`1'j__TPar'>::Equals(class '<>f__AnonymousType1722350077`1', + class [runtime]System.Collections.IEqualityComparer) + IL_0014: ret + + IL_0015: ldc.i4.0 + IL_0016: ret + } + + .method public hidebysig virtual final instance bool Equals(class '<>f__AnonymousType1722350077`1'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_001c + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_001a + + IL_0006: ldarg.0 + IL_0007: ldfld !0 class '<>f__AnonymousType1722350077`1'j__TPar'>::A@ + IL_000c: ldarg.1 + IL_000d: ldfld !0 class '<>f__AnonymousType1722350077`1'j__TPar'>::A@ + IL_0012: tail. + IL_0014: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_0019: ret + + IL_001a: ldc.i4.0 + IL_001b: ret + + IL_001c: ldarg.1 + IL_001d: ldnull + IL_001e: cgt.un + IL_0020: ldc.i4.0 + IL_0021: ceq + IL_0023: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (class '<>f__AnonymousType1722350077`1'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType1722350077`1'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0014 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: tail. + IL_000e: callvirt instance bool class '<>f__AnonymousType1722350077`1'j__TPar'>::Equals(class '<>f__AnonymousType1722350077`1') + IL_0013: ret + + IL_0014: ldc.i4.0 + IL_0015: ret + } + + .property instance !'j__TPar' A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType1722350077`1'::get_A() + } +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_Structness.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_Structness.fs new file mode 100644 index 00000000000..73ff6f95bf8 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_Structness.fs @@ -0,0 +1,16 @@ +type RefNominalRecd = { A : int; B : int } +type [] StructNominalRecd = { A : int; B : int } + +let refAnonRecd = {| A = 1; B = 2 |} +let structAnonRecd = struct {| A = 1; B = 2 |} +let refNominalRecd : RefNominalRecd = { A = 1; B = 2 } +let structNominalRecd : StructNominalRecd = { A = 1; B = 2 } + +let ``ref nominal src, ref nominal dst`` : RefNominalRecd = { ...refNominalRecd; B = 3 } +let ``ref nominal src, struct nominal dst`` : StructNominalRecd = { ...refNominalRecd; B = 3 } +let ``struct nominal src, ref nominal dst`` : RefNominalRecd = { ...structNominalRecd; B = 3 } +let ``struct nominal src, struct nominal dst`` : StructNominalRecd = { ...structNominalRecd; B = 3 } +let ``ref anon src, ref nominal dst`` : RefNominalRecd = { ...refAnonRecd; B = 3 } +let ``ref anon src, struct nominal dst`` : StructNominalRecd = { ...refAnonRecd; B = 3 } +let ``struct anon src, ref nominal dst`` : RefNominalRecd = { ...structAnonRecd; B = 3 } +let ``struct anon src, struct nominal dst`` : StructNominalRecd = { ...structAnonRecd; B = 3 } diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_Structness.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_Structness.fs.il.bsl new file mode 100644 index 00000000000..2dbfba342b1 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Expression_Nominal_Structness.fs.il.bsl @@ -0,0 +1,2035 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable sealed nested public RefNominalRecd + extends [runtime]System.Object + implements class [runtime]System.IEquatable`1, + [runtime]System.Collections.IStructuralEquatable, + class [runtime]System.IComparable`1, + [runtime]System.IComparable, + [runtime]System.Collections.IStructuralComparable + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly int32 A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly int32 B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname instance int32 get_A() 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: ldfld int32 assembly/RefNominalRecd::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance int32 get_B() 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: ldfld int32 assembly/RefNominalRecd::B@ + IL_0006: ret + } + + .method public specialname rtspecialname instance void .ctor(int32 a, int32 b) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 2C 45 78 70 72 65 73 73 69 6F + 6E 5F 4E 6F 6D 69 6E 61 6C 5F 53 74 72 75 63 74 + 6E 65 73 73 2B 52 65 66 4E 6F 6D 69 6E 61 6C 52 + 65 63 64 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld int32 assembly/RefNominalRecd::A@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld int32 assembly/RefNominalRecd::B@ + IL_0014: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/RefNominalRecd>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(class assembly/RefNominalRecd obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (int32 V_0, + class [runtime]System.Collections.IComparer V_1, + int32 V_2, + int32 V_3) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0050 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_004e + + IL_0006: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_000b: stloc.1 + IL_000c: ldarg.0 + IL_000d: ldfld int32 assembly/RefNominalRecd::A@ + IL_0012: stloc.2 + IL_0013: ldarg.1 + IL_0014: ldfld int32 assembly/RefNominalRecd::A@ + IL_0019: stloc.3 + IL_001a: ldloc.2 + IL_001b: ldloc.3 + IL_001c: cgt + IL_001e: ldloc.2 + IL_001f: ldloc.3 + IL_0020: clt + IL_0022: sub + IL_0023: stloc.0 + IL_0024: ldloc.0 + IL_0025: ldc.i4.0 + IL_0026: bge.s IL_002a + + IL_0028: ldloc.0 + IL_0029: ret + + IL_002a: ldloc.0 + IL_002b: ldc.i4.0 + IL_002c: ble.s IL_0030 + + IL_002e: ldloc.0 + IL_002f: ret + + IL_0030: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_0035: stloc.1 + IL_0036: ldarg.0 + IL_0037: ldfld int32 assembly/RefNominalRecd::B@ + IL_003c: stloc.2 + IL_003d: ldarg.1 + IL_003e: ldfld int32 assembly/RefNominalRecd::B@ + IL_0043: stloc.3 + IL_0044: ldloc.2 + IL_0045: ldloc.3 + IL_0046: cgt + IL_0048: ldloc.2 + IL_0049: ldloc.3 + IL_004a: clt + IL_004c: sub + IL_004d: ret + + IL_004e: ldc.i4.1 + IL_004f: ret + + IL_0050: ldarg.1 + IL_0051: brfalse.s IL_0055 + + IL_0053: ldc.i4.m1 + IL_0054: ret + + IL_0055: ldc.i4.0 + IL_0056: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: unbox.any assembly/RefNominalRecd + IL_0007: callvirt instance int32 assembly/RefNominalRecd::CompareTo(class assembly/RefNominalRecd) + IL_000c: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj, class [runtime]System.Collections.IComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class assembly/RefNominalRecd V_0, + int32 V_1, + int32 V_2, + int32 V_3) + IL_0000: ldarg.1 + IL_0001: unbox.any assembly/RefNominalRecd + IL_0006: stloc.0 + IL_0007: ldarg.0 + IL_0008: brfalse.s IL_0050 + + IL_000a: ldarg.1 + IL_000b: unbox.any assembly/RefNominalRecd + IL_0010: brfalse.s IL_004e + + IL_0012: ldarg.0 + IL_0013: ldfld int32 assembly/RefNominalRecd::A@ + IL_0018: stloc.2 + IL_0019: ldloc.0 + IL_001a: ldfld int32 assembly/RefNominalRecd::A@ + IL_001f: stloc.3 + IL_0020: ldloc.2 + IL_0021: ldloc.3 + IL_0022: cgt + IL_0024: ldloc.2 + IL_0025: ldloc.3 + IL_0026: clt + IL_0028: sub + IL_0029: stloc.1 + IL_002a: ldloc.1 + IL_002b: ldc.i4.0 + IL_002c: bge.s IL_0030 + + IL_002e: ldloc.1 + IL_002f: ret + + IL_0030: ldloc.1 + IL_0031: ldc.i4.0 + IL_0032: ble.s IL_0036 + + IL_0034: ldloc.1 + IL_0035: ret + + IL_0036: ldarg.0 + IL_0037: ldfld int32 assembly/RefNominalRecd::B@ + IL_003c: stloc.2 + IL_003d: ldloc.0 + IL_003e: ldfld int32 assembly/RefNominalRecd::B@ + IL_0043: stloc.3 + IL_0044: ldloc.2 + IL_0045: ldloc.3 + IL_0046: cgt + IL_0048: ldloc.2 + IL_0049: ldloc.3 + IL_004a: clt + IL_004c: sub + IL_004d: ret + + IL_004e: ldc.i4.1 + IL_004f: ret + + IL_0050: ldarg.1 + IL_0051: unbox.any assembly/RefNominalRecd + IL_0056: brfalse.s IL_005a + + IL_0058: ldc.i4.m1 + IL_0059: ret + + IL_005a: ldc.i4.0 + IL_005b: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode(class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 7 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0031 + + IL_0003: ldc.i4.0 + IL_0004: stloc.0 + IL_0005: ldc.i4 0x9e3779b9 + IL_000a: ldarg.0 + IL_000b: ldfld int32 assembly/RefNominalRecd::B@ + IL_0010: ldloc.0 + IL_0011: ldc.i4.6 + IL_0012: shl + IL_0013: ldloc.0 + IL_0014: ldc.i4.2 + IL_0015: shr + IL_0016: add + IL_0017: add + IL_0018: add + IL_0019: stloc.0 + IL_001a: ldc.i4 0x9e3779b9 + IL_001f: ldarg.0 + IL_0020: ldfld int32 assembly/RefNominalRecd::A@ + IL_0025: ldloc.0 + IL_0026: ldc.i4.6 + IL_0027: shl + IL_0028: ldloc.0 + IL_0029: ldc.i4.2 + IL_002a: shr + IL_002b: add + IL_002c: add + IL_002d: add + IL_002e: stloc.0 + IL_002f: ldloc.0 + IL_0030: ret + + IL_0031: ldc.i4.0 + IL_0032: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() + IL_0006: callvirt instance int32 assembly/RefNominalRecd::GetHashCode(class [runtime]System.Collections.IEqualityComparer) + IL_000b: ret + } + + .method public hidebysig instance bool Equals(class assembly/RefNominalRecd obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0027 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0025 + + IL_0006: ldarg.0 + IL_0007: ldfld int32 assembly/RefNominalRecd::A@ + IL_000c: ldarg.1 + IL_000d: ldfld int32 assembly/RefNominalRecd::A@ + IL_0012: bne.un.s IL_0023 + + IL_0014: ldarg.0 + IL_0015: ldfld int32 assembly/RefNominalRecd::B@ + IL_001a: ldarg.1 + IL_001b: ldfld int32 assembly/RefNominalRecd::B@ + IL_0020: ceq + IL_0022: ret + + IL_0023: ldc.i4.0 + IL_0024: ret + + IL_0025: ldc.i4.0 + IL_0026: ret + + IL_0027: ldarg.1 + IL_0028: ldnull + IL_0029: cgt.un + IL_002b: ldc.i4.0 + IL_002c: ceq + IL_002e: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class assembly/RefNominalRecd V_0) + IL_0000: ldarg.1 + IL_0001: isinst assembly/RefNominalRecd + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0013 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: ldarg.2 + IL_000d: callvirt instance bool assembly/RefNominalRecd::Equals(class assembly/RefNominalRecd, + class [runtime]System.Collections.IEqualityComparer) + IL_0012: ret + + IL_0013: ldc.i4.0 + IL_0014: ret + } + + .method public hidebysig virtual final instance bool Equals(class assembly/RefNominalRecd obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0027 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0025 + + IL_0006: ldarg.0 + IL_0007: ldfld int32 assembly/RefNominalRecd::A@ + IL_000c: ldarg.1 + IL_000d: ldfld int32 assembly/RefNominalRecd::A@ + IL_0012: bne.un.s IL_0023 + + IL_0014: ldarg.0 + IL_0015: ldfld int32 assembly/RefNominalRecd::B@ + IL_001a: ldarg.1 + IL_001b: ldfld int32 assembly/RefNominalRecd::B@ + IL_0020: ceq + IL_0022: ret + + IL_0023: ldc.i4.0 + IL_0024: ret + + IL_0025: ldc.i4.0 + IL_0026: ret + + IL_0027: ldarg.1 + IL_0028: ldnull + IL_0029: cgt.un + IL_002b: ldc.i4.0 + IL_002c: ceq + IL_002e: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (class assembly/RefNominalRecd V_0) + IL_0000: ldarg.1 + IL_0001: isinst assembly/RefNominalRecd + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0012 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: callvirt instance bool assembly/RefNominalRecd::Equals(class assembly/RefNominalRecd) + IL_0011: ret + + IL_0012: ldc.i4.0 + IL_0013: ret + } + + .property instance int32 A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance int32 assembly/RefNominalRecd::get_A() + } + .property instance int32 B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance int32 assembly/RefNominalRecd::get_B() + } + } + + .class sequential ansi serializable sealed nested public StructNominalRecd + extends [runtime]System.ValueType + implements class [runtime]System.IEquatable`1, + [runtime]System.Collections.IStructuralEquatable, + class [runtime]System.IComparable`1, + [runtime]System.IComparable, + [runtime]System.Collections.IStructuralComparable + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.StructAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly int32 A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly int32 B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname instance int32 get_A() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + .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: ldfld int32 assembly/StructNominalRecd::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance int32 get_B() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + .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: ldfld int32 assembly/StructNominalRecd::B@ + IL_0006: ret + } + + .method public specialname rtspecialname instance void .ctor(int32 a, int32 b) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 2F 45 78 70 72 65 73 73 69 6F + 6E 5F 4E 6F 6D 69 6E 61 6C 5F 53 74 72 75 63 74 + 6E 65 73 73 2B 53 74 72 75 63 74 4E 6F 6D 69 6E + 61 6C 52 65 63 64 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld int32 assembly/StructNominalRecd::A@ + IL_0007: ldarg.0 + IL_0008: ldarg.2 + IL_0009: stfld int32 assembly/StructNominalRecd::B@ + IL_000e: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,valuetype assembly/StructNominalRecd>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: ldobj assembly/StructNominalRecd + IL_0015: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_001a: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(valuetype assembly/StructNominalRecd obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (int32 V_0, + class [runtime]System.Collections.IComparer V_1, + int32 V_2, + int32 V_3) + IL_0000: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_0005: stloc.1 + IL_0006: ldarg.0 + IL_0007: ldfld int32 assembly/StructNominalRecd::A@ + IL_000c: stloc.2 + IL_000d: ldarga.s obj + IL_000f: ldfld int32 assembly/StructNominalRecd::A@ + IL_0014: stloc.3 + IL_0015: ldloc.2 + IL_0016: ldloc.3 + IL_0017: cgt + IL_0019: ldloc.2 + IL_001a: ldloc.3 + IL_001b: clt + IL_001d: sub + IL_001e: stloc.0 + IL_001f: ldloc.0 + IL_0020: ldc.i4.0 + IL_0021: bge.s IL_0025 + + IL_0023: ldloc.0 + IL_0024: ret + + IL_0025: ldloc.0 + IL_0026: ldc.i4.0 + IL_0027: ble.s IL_002b + + IL_0029: ldloc.0 + IL_002a: ret + + IL_002b: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_0030: stloc.1 + IL_0031: ldarg.0 + IL_0032: ldfld int32 assembly/StructNominalRecd::B@ + IL_0037: stloc.2 + IL_0038: ldarga.s obj + IL_003a: ldfld int32 assembly/StructNominalRecd::B@ + IL_003f: stloc.3 + IL_0040: ldloc.2 + IL_0041: ldloc.3 + IL_0042: cgt + IL_0044: ldloc.2 + IL_0045: ldloc.3 + IL_0046: clt + IL_0048: sub + IL_0049: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: unbox.any assembly/StructNominalRecd + IL_0007: call instance int32 assembly/StructNominalRecd::CompareTo(valuetype assembly/StructNominalRecd) + IL_000c: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj, class [runtime]System.Collections.IComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (valuetype assembly/StructNominalRecd V_0, + int32 V_1, + int32 V_2, + int32 V_3) + IL_0000: ldarg.1 + IL_0001: unbox.any assembly/StructNominalRecd + IL_0006: stloc.0 + IL_0007: ldarg.0 + IL_0008: ldfld int32 assembly/StructNominalRecd::A@ + IL_000d: stloc.2 + IL_000e: ldloca.s V_0 + IL_0010: ldfld int32 assembly/StructNominalRecd::A@ + IL_0015: stloc.3 + IL_0016: ldloc.2 + IL_0017: ldloc.3 + IL_0018: cgt + IL_001a: ldloc.2 + IL_001b: ldloc.3 + IL_001c: clt + IL_001e: sub + IL_001f: stloc.1 + IL_0020: ldloc.1 + IL_0021: ldc.i4.0 + IL_0022: bge.s IL_0026 + + IL_0024: ldloc.1 + IL_0025: ret + + IL_0026: ldloc.1 + IL_0027: ldc.i4.0 + IL_0028: ble.s IL_002c + + IL_002a: ldloc.1 + IL_002b: ret + + IL_002c: ldarg.0 + IL_002d: ldfld int32 assembly/StructNominalRecd::B@ + IL_0032: stloc.2 + IL_0033: ldloca.s V_0 + IL_0035: ldfld int32 assembly/StructNominalRecd::B@ + IL_003a: stloc.3 + IL_003b: ldloc.2 + IL_003c: ldloc.3 + IL_003d: cgt + IL_003f: ldloc.2 + IL_0040: ldloc.3 + IL_0041: clt + IL_0043: sub + IL_0044: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode(class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 7 + .locals init (int32 V_0) + IL_0000: ldc.i4.0 + IL_0001: stloc.0 + IL_0002: ldc.i4 0x9e3779b9 + IL_0007: ldarg.0 + IL_0008: ldfld int32 assembly/StructNominalRecd::B@ + IL_000d: ldloc.0 + IL_000e: ldc.i4.6 + IL_000f: shl + IL_0010: ldloc.0 + IL_0011: ldc.i4.2 + IL_0012: shr + IL_0013: add + IL_0014: add + IL_0015: add + IL_0016: stloc.0 + IL_0017: ldc.i4 0x9e3779b9 + IL_001c: ldarg.0 + IL_001d: ldfld int32 assembly/StructNominalRecd::A@ + IL_0022: ldloc.0 + IL_0023: ldc.i4.6 + IL_0024: shl + IL_0025: ldloc.0 + IL_0026: ldc.i4.2 + IL_0027: shr + IL_0028: add + IL_0029: add + IL_002a: add + IL_002b: stloc.0 + IL_002c: ldloc.0 + IL_002d: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() + IL_0006: call instance int32 assembly/StructNominalRecd::GetHashCode(class [runtime]System.Collections.IEqualityComparer) + IL_000b: ret + } + + .method public hidebysig instance bool Equals(valuetype assembly/StructNominalRecd obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld int32 assembly/StructNominalRecd::A@ + IL_0006: ldarga.s obj + IL_0008: ldfld int32 assembly/StructNominalRecd::A@ + IL_000d: bne.un.s IL_001f + + IL_000f: ldarg.0 + IL_0010: ldfld int32 assembly/StructNominalRecd::B@ + IL_0015: ldarga.s obj + IL_0017: ldfld int32 assembly/StructNominalRecd::B@ + IL_001c: ceq + IL_001e: ret + + IL_001f: ldc.i4.0 + IL_0020: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (valuetype assembly/StructNominalRecd V_0) + IL_0000: ldarg.1 + IL_0001: isinst assembly/StructNominalRecd + IL_0006: brfalse.s IL_0018 + + IL_0008: ldarg.1 + IL_0009: unbox.any assembly/StructNominalRecd + IL_000e: stloc.0 + IL_000f: ldarg.0 + IL_0010: ldloc.0 + IL_0011: ldarg.2 + IL_0012: call instance bool assembly/StructNominalRecd::Equals(valuetype assembly/StructNominalRecd, + class [runtime]System.Collections.IEqualityComparer) + IL_0017: ret + + IL_0018: ldc.i4.0 + IL_0019: ret + } + + .method public hidebysig virtual final instance bool Equals(valuetype assembly/StructNominalRecd obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld int32 assembly/StructNominalRecd::A@ + IL_0006: ldarga.s obj + IL_0008: ldfld int32 assembly/StructNominalRecd::A@ + IL_000d: bne.un.s IL_001f + + IL_000f: ldarg.0 + IL_0010: ldfld int32 assembly/StructNominalRecd::B@ + IL_0015: ldarga.s obj + IL_0017: ldfld int32 assembly/StructNominalRecd::B@ + IL_001c: ceq + IL_001e: ret + + IL_001f: ldc.i4.0 + IL_0020: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: isinst assembly/StructNominalRecd + IL_0006: brfalse.s IL_0015 + + IL_0008: ldarg.0 + IL_0009: ldarg.1 + IL_000a: unbox.any assembly/StructNominalRecd + IL_000f: call instance bool assembly/StructNominalRecd::Equals(valuetype assembly/StructNominalRecd) + IL_0014: ret + + IL_0015: ldc.i4.0 + IL_0016: ret + } + + .property instance int32 A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance int32 assembly/StructNominalRecd::get_A() + } + .property instance int32 B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance int32 assembly/StructNominalRecd::get_B() + } + } + + .field static assembly class '<>f__AnonymousType3545307392`2' refAnonRecd@4 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly valuetype '<>f__AnonymousType1000930219981`2' structAnonRecd@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 class assembly/RefNominalRecd refNominalRecd@6 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly valuetype assembly/StructNominalRecd structNominalRecd@7 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly class assembly/RefNominalRecd 'ref nominal src, ref nominal dst@9' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly valuetype assembly/StructNominalRecd 'ref nominal src, struct nominal dst@10' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly class assembly/RefNominalRecd 'struct nominal src, ref nominal dst@11' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly valuetype assembly/StructNominalRecd copyOfStruct@11 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly valuetype assembly/StructNominalRecd 'copyOfStruct@11-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 valuetype assembly/StructNominalRecd 'struct nominal src, struct nominal dst@12' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly valuetype assembly/StructNominalRecd 'copyOfStruct@12-2' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly valuetype assembly/StructNominalRecd 'copyOfStruct@12-3' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly class assembly/RefNominalRecd 'ref anon src, ref nominal dst@13' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly valuetype assembly/StructNominalRecd 'ref anon src, struct nominal dst@14' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly class assembly/RefNominalRecd 'struct anon src, ref nominal dst@15' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly valuetype '<>f__AnonymousType1000930219981`2' 'copyOfStruct@15-4' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly valuetype '<>f__AnonymousType1000930219981`2' 'copyOfStruct@15-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 valuetype assembly/StructNominalRecd 'struct anon src, struct nominal dst@16' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly valuetype '<>f__AnonymousType1000930219981`2' 'copyOfStruct@16-6' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly valuetype '<>f__AnonymousType1000930219981`2' 'copyOfStruct@16-7' + .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 '<>f__AnonymousType3545307392`2' get_refAnonRecd() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class '<>f__AnonymousType3545307392`2' assembly::refAnonRecd@4 + IL_0005: ret + } + + .method public specialname static valuetype '<>f__AnonymousType1000930219981`2' get_structAnonRecd() cil managed + { + + .maxstack 8 + IL_0000: ldsfld valuetype '<>f__AnonymousType1000930219981`2' assembly::structAnonRecd@5 + IL_0005: ret + } + + .method public specialname static class assembly/RefNominalRecd get_refNominalRecd() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class assembly/RefNominalRecd assembly::refNominalRecd@6 + IL_0005: ret + } + + .method public specialname static valuetype assembly/StructNominalRecd get_structNominalRecd() cil managed + { + + .maxstack 8 + IL_0000: ldsfld valuetype assembly/StructNominalRecd assembly::structNominalRecd@7 + IL_0005: ret + } + + .method public specialname static class assembly/RefNominalRecd 'get_ref nominal src, ref nominal dst'() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class assembly/RefNominalRecd assembly::'ref nominal src, ref nominal dst@9' + IL_0005: ret + } + + .method public specialname static valuetype assembly/StructNominalRecd 'get_ref nominal src, struct nominal dst'() cil managed + { + + .maxstack 8 + IL_0000: ldsfld valuetype assembly/StructNominalRecd assembly::'ref nominal src, struct nominal dst@10' + IL_0005: ret + } + + .method public specialname static class assembly/RefNominalRecd 'get_struct nominal src, ref nominal dst'() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class assembly/RefNominalRecd assembly::'struct nominal src, ref nominal dst@11' + IL_0005: ret + } + + .method assembly specialname static valuetype assembly/StructNominalRecd get_copyOfStruct@11() cil managed + { + + .maxstack 8 + IL_0000: ldsfld valuetype assembly/StructNominalRecd assembly::copyOfStruct@11 + IL_0005: ret + } + + .method assembly specialname static valuetype assembly/StructNominalRecd 'get_copyOfStruct@11-1'() cil managed + { + + .maxstack 8 + IL_0000: ldsfld valuetype assembly/StructNominalRecd assembly::'copyOfStruct@11-1' + IL_0005: ret + } + + .method public specialname static valuetype assembly/StructNominalRecd 'get_struct nominal src, struct nominal dst'() cil managed + { + + .maxstack 8 + IL_0000: ldsfld valuetype assembly/StructNominalRecd assembly::'struct nominal src, struct nominal dst@12' + IL_0005: ret + } + + .method assembly specialname static valuetype assembly/StructNominalRecd 'get_copyOfStruct@12-2'() cil managed + { + + .maxstack 8 + IL_0000: ldsfld valuetype assembly/StructNominalRecd assembly::'copyOfStruct@12-2' + IL_0005: ret + } + + .method assembly specialname static valuetype assembly/StructNominalRecd 'get_copyOfStruct@12-3'() cil managed + { + + .maxstack 8 + IL_0000: ldsfld valuetype assembly/StructNominalRecd assembly::'copyOfStruct@12-3' + IL_0005: ret + } + + .method public specialname static class assembly/RefNominalRecd 'get_ref anon src, ref nominal dst'() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class assembly/RefNominalRecd assembly::'ref anon src, ref nominal dst@13' + IL_0005: ret + } + + .method public specialname static valuetype assembly/StructNominalRecd 'get_ref anon src, struct nominal dst'() cil managed + { + + .maxstack 8 + IL_0000: ldsfld valuetype assembly/StructNominalRecd assembly::'ref anon src, struct nominal dst@14' + IL_0005: ret + } + + .method public specialname static class assembly/RefNominalRecd 'get_struct anon src, ref nominal dst'() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class assembly/RefNominalRecd assembly::'struct anon src, ref nominal dst@15' + IL_0005: ret + } + + .method assembly specialname static valuetype '<>f__AnonymousType1000930219981`2' 'get_copyOfStruct@15-4'() cil managed + { + + .maxstack 8 + IL_0000: ldsfld valuetype '<>f__AnonymousType1000930219981`2' assembly::'copyOfStruct@15-4' + IL_0005: ret + } + + .method assembly specialname static valuetype '<>f__AnonymousType1000930219981`2' 'get_copyOfStruct@15-5'() cil managed + { + + .maxstack 8 + IL_0000: ldsfld valuetype '<>f__AnonymousType1000930219981`2' assembly::'copyOfStruct@15-5' + IL_0005: ret + } + + .method public specialname static valuetype assembly/StructNominalRecd 'get_struct anon src, struct nominal dst'() cil managed + { + + .maxstack 8 + IL_0000: ldsfld valuetype assembly/StructNominalRecd assembly::'struct anon src, struct nominal dst@16' + IL_0005: ret + } + + .method assembly specialname static valuetype '<>f__AnonymousType1000930219981`2' 'get_copyOfStruct@16-6'() cil managed + { + + .maxstack 8 + IL_0000: ldsfld valuetype '<>f__AnonymousType1000930219981`2' assembly::'copyOfStruct@16-6' + IL_0005: ret + } + + .method assembly specialname static valuetype '<>f__AnonymousType1000930219981`2' 'get_copyOfStruct@16-7'() cil managed + { + + .maxstack 8 + IL_0000: ldsfld valuetype '<>f__AnonymousType1000930219981`2' assembly::'copyOfStruct@16-7' + IL_0005: ret + } + + .method private specialname rtspecialname static void .cctor() cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.0 + IL_0001: stsfld int32 ''.$assembly::init@ + IL_0006: ldsfld int32 ''.$assembly::init@ + IL_000b: pop + IL_000c: ret + } + + .method assembly static void staticInitialization@() cil managed + { + + .maxstack 4 + .locals init (valuetype '<>f__AnonymousType1000930219981`2'& V_0) + IL_0000: ldc.i4.1 + IL_0001: ldc.i4.2 + IL_0002: newobj instance void class '<>f__AnonymousType3545307392`2'::.ctor(!0, + !1) + IL_0007: stsfld class '<>f__AnonymousType3545307392`2' assembly::refAnonRecd@4 + IL_000c: ldc.i4.1 + IL_000d: ldc.i4.2 + IL_000e: newobj instance void valuetype '<>f__AnonymousType1000930219981`2'::.ctor(!0, + !1) + IL_0013: stsfld valuetype '<>f__AnonymousType1000930219981`2' assembly::structAnonRecd@5 + IL_0018: ldc.i4.1 + IL_0019: ldc.i4.2 + IL_001a: newobj instance void assembly/RefNominalRecd::.ctor(int32, + int32) + IL_001f: stsfld class assembly/RefNominalRecd assembly::refNominalRecd@6 + IL_0024: ldc.i4.1 + IL_0025: ldc.i4.2 + IL_0026: newobj instance void assembly/StructNominalRecd::.ctor(int32, + int32) + IL_002b: stsfld valuetype assembly/StructNominalRecd assembly::structNominalRecd@7 + IL_0030: call class assembly/RefNominalRecd assembly::get_refNominalRecd() + IL_0035: ldfld int32 assembly/RefNominalRecd::A@ + IL_003a: ldc.i4.3 + IL_003b: newobj instance void assembly/RefNominalRecd::.ctor(int32, + int32) + IL_0040: stsfld class assembly/RefNominalRecd assembly::'ref nominal src, ref nominal dst@9' + IL_0045: call class assembly/RefNominalRecd assembly::get_refNominalRecd() + IL_004a: ldfld int32 assembly/RefNominalRecd::A@ + IL_004f: ldc.i4.3 + IL_0050: newobj instance void assembly/StructNominalRecd::.ctor(int32, + int32) + IL_0055: stsfld valuetype assembly/StructNominalRecd assembly::'ref nominal src, struct nominal dst@10' + IL_005a: call valuetype assembly/StructNominalRecd assembly::get_structNominalRecd() + IL_005f: stsfld valuetype assembly/StructNominalRecd assembly::copyOfStruct@11 + IL_0064: call valuetype assembly/StructNominalRecd assembly::get_copyOfStruct@11() + IL_0069: stsfld valuetype assembly/StructNominalRecd assembly::'copyOfStruct@11-1' + IL_006e: ldsflda valuetype assembly/StructNominalRecd assembly::'copyOfStruct@11-1' + IL_0073: ldfld int32 assembly/StructNominalRecd::A@ + IL_0078: ldc.i4.3 + IL_0079: newobj instance void assembly/RefNominalRecd::.ctor(int32, + int32) + IL_007e: stsfld class assembly/RefNominalRecd assembly::'struct nominal src, ref nominal dst@11' + IL_0083: call valuetype assembly/StructNominalRecd assembly::get_structNominalRecd() + IL_0088: stsfld valuetype assembly/StructNominalRecd assembly::'copyOfStruct@12-2' + IL_008d: call valuetype assembly/StructNominalRecd assembly::'get_copyOfStruct@12-2'() + IL_0092: stsfld valuetype assembly/StructNominalRecd assembly::'copyOfStruct@12-3' + IL_0097: ldsflda valuetype assembly/StructNominalRecd assembly::'copyOfStruct@12-3' + IL_009c: ldfld int32 assembly/StructNominalRecd::A@ + IL_00a1: ldc.i4.3 + IL_00a2: newobj instance void assembly/StructNominalRecd::.ctor(int32, + int32) + IL_00a7: stsfld valuetype assembly/StructNominalRecd assembly::'struct nominal src, struct nominal dst@12' + IL_00ac: call class '<>f__AnonymousType3545307392`2' assembly::get_refAnonRecd() + IL_00b1: call instance !0 class '<>f__AnonymousType3545307392`2'::get_A() + IL_00b6: ldc.i4.3 + IL_00b7: newobj instance void assembly/RefNominalRecd::.ctor(int32, + int32) + IL_00bc: stsfld class assembly/RefNominalRecd assembly::'ref anon src, ref nominal dst@13' + IL_00c1: call class '<>f__AnonymousType3545307392`2' assembly::get_refAnonRecd() + IL_00c6: call instance !0 class '<>f__AnonymousType3545307392`2'::get_A() + IL_00cb: ldc.i4.3 + IL_00cc: newobj instance void assembly/StructNominalRecd::.ctor(int32, + int32) + IL_00d1: stsfld valuetype assembly/StructNominalRecd assembly::'ref anon src, struct nominal dst@14' + IL_00d6: call valuetype '<>f__AnonymousType1000930219981`2' assembly::get_structAnonRecd() + IL_00db: stsfld valuetype '<>f__AnonymousType1000930219981`2' assembly::'copyOfStruct@15-4' + IL_00e0: call valuetype '<>f__AnonymousType1000930219981`2' assembly::'get_copyOfStruct@15-4'() + IL_00e5: stsfld valuetype '<>f__AnonymousType1000930219981`2' assembly::'copyOfStruct@15-5' + IL_00ea: ldsflda valuetype '<>f__AnonymousType1000930219981`2' assembly::'copyOfStruct@15-5' + IL_00ef: stloc.0 + IL_00f0: ldloca.s V_0 + IL_00f2: call instance !0 valuetype '<>f__AnonymousType1000930219981`2'::get_A() + IL_00f7: ldc.i4.3 + IL_00f8: newobj instance void assembly/RefNominalRecd::.ctor(int32, + int32) + IL_00fd: stsfld class assembly/RefNominalRecd assembly::'struct anon src, ref nominal dst@15' + IL_0102: call valuetype '<>f__AnonymousType1000930219981`2' assembly::get_structAnonRecd() + IL_0107: stsfld valuetype '<>f__AnonymousType1000930219981`2' assembly::'copyOfStruct@16-6' + IL_010c: call valuetype '<>f__AnonymousType1000930219981`2' assembly::'get_copyOfStruct@16-6'() + IL_0111: stsfld valuetype '<>f__AnonymousType1000930219981`2' assembly::'copyOfStruct@16-7' + IL_0116: ldsflda valuetype '<>f__AnonymousType1000930219981`2' assembly::'copyOfStruct@16-7' + IL_011b: stloc.0 + IL_011c: ldloca.s V_0 + IL_011e: call instance !0 valuetype '<>f__AnonymousType1000930219981`2'::get_A() + IL_0123: ldc.i4.3 + IL_0124: newobj instance void assembly/StructNominalRecd::.ctor(int32, + int32) + IL_0129: stsfld valuetype assembly/StructNominalRecd assembly::'struct anon src, struct nominal dst@16' + IL_012e: ret + } + + .property class '<>f__AnonymousType3545307392`2' + refAnonRecd() + { + .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 class '<>f__AnonymousType3545307392`2' assembly::get_refAnonRecd() + } + .property valuetype '<>f__AnonymousType1000930219981`2' + structAnonRecd() + { + .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 valuetype '<>f__AnonymousType1000930219981`2' assembly::get_structAnonRecd() + } + .property class assembly/RefNominalRecd + refNominalRecd() + { + .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 class assembly/RefNominalRecd assembly::get_refNominalRecd() + } + .property valuetype assembly/StructNominalRecd + structNominalRecd() + { + .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 valuetype assembly/StructNominalRecd assembly::get_structNominalRecd() + } + .property class assembly/RefNominalRecd + 'ref nominal src, ref nominal dst'() + { + .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 class assembly/RefNominalRecd assembly::'get_ref nominal src, ref nominal dst'() + } + .property valuetype assembly/StructNominalRecd + 'ref nominal src, struct nominal dst'() + { + .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 valuetype assembly/StructNominalRecd assembly::'get_ref nominal src, struct nominal dst'() + } + .property class assembly/RefNominalRecd + 'struct nominal src, ref nominal dst'() + { + .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 class assembly/RefNominalRecd assembly::'get_struct nominal src, ref nominal dst'() + } + .property valuetype assembly/StructNominalRecd + copyOfStruct@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 valuetype assembly/StructNominalRecd assembly::get_copyOfStruct@11() + } + .property valuetype assembly/StructNominalRecd + 'copyOfStruct@11-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 valuetype assembly/StructNominalRecd assembly::'get_copyOfStruct@11-1'() + } + .property valuetype assembly/StructNominalRecd + 'struct nominal src, struct nominal dst'() + { + .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 valuetype assembly/StructNominalRecd assembly::'get_struct nominal src, struct nominal dst'() + } + .property valuetype assembly/StructNominalRecd + 'copyOfStruct@12-2'() + { + .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 valuetype assembly/StructNominalRecd assembly::'get_copyOfStruct@12-2'() + } + .property valuetype assembly/StructNominalRecd + 'copyOfStruct@12-3'() + { + .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 valuetype assembly/StructNominalRecd assembly::'get_copyOfStruct@12-3'() + } + .property class assembly/RefNominalRecd + 'ref anon src, ref nominal dst'() + { + .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 class assembly/RefNominalRecd assembly::'get_ref anon src, ref nominal dst'() + } + .property valuetype assembly/StructNominalRecd + 'ref anon src, struct nominal dst'() + { + .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 valuetype assembly/StructNominalRecd assembly::'get_ref anon src, struct nominal dst'() + } + .property class assembly/RefNominalRecd + 'struct anon src, ref nominal dst'() + { + .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 class assembly/RefNominalRecd assembly::'get_struct anon src, ref nominal dst'() + } + .property valuetype '<>f__AnonymousType1000930219981`2' + 'copyOfStruct@15-4'() + { + .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 valuetype '<>f__AnonymousType1000930219981`2' assembly::'get_copyOfStruct@15-4'() + } + .property valuetype '<>f__AnonymousType1000930219981`2' + 'copyOfStruct@15-5'() + { + .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 valuetype '<>f__AnonymousType1000930219981`2' assembly::'get_copyOfStruct@15-5'() + } + .property valuetype assembly/StructNominalRecd + 'struct anon src, struct nominal dst'() + { + .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 valuetype assembly/StructNominalRecd assembly::'get_struct anon src, struct nominal dst'() + } + .property valuetype '<>f__AnonymousType1000930219981`2' + 'copyOfStruct@16-6'() + { + .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 valuetype '<>f__AnonymousType1000930219981`2' assembly::'get_copyOfStruct@16-6'() + } + .property valuetype '<>f__AnonymousType1000930219981`2' + 'copyOfStruct@16-7'() + { + .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 valuetype '<>f__AnonymousType1000930219981`2' assembly::'get_copyOfStruct@16-7'() + } +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .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 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: call void assembly::staticInitialization@() + IL_0005: ret + } + +} + +.class public auto ansi serializable sealed beforefieldinit '<>f__AnonymousType1000930219981`2'<'j__TPar','j__TPar'> + extends [runtime]System.ValueType + implements [runtime]System.Collections.IStructuralComparable, + [runtime]System.IComparable, + class [runtime]System.IComparable`1f__AnonymousType1000930219981`2'j__TPar',!'j__TPar'>>, + [runtime]System.Collections.IStructuralEquatable, + class [runtime]System.IEquatable`1f__AnonymousType1000930219981`2'j__TPar',!'j__TPar'>> +{ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field private !'j__TPar' A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field private !'j__TPar' B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor(!'j__TPar' A, !'j__TPar' B) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 21 3C 3E 66 5F 5F 41 6E 6F 6E + 79 6D 6F 75 73 54 79 70 65 31 30 30 30 39 33 30 + 32 31 39 39 38 31 60 32 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld !0 valuetype '<>f__AnonymousType1000930219981`2'j__TPar',!'j__TPar'>::A@ + IL_0007: ldarg.0 + IL_0008: ldarg.2 + IL_0009: stfld !1 valuetype '<>f__AnonymousType1000930219981`2'j__TPar',!'j__TPar'>::B@ + IL_000e: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_A() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + .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: ldfld !0 valuetype '<>f__AnonymousType1000930219981`2'j__TPar',!'j__TPar'>::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_B() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + .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: ldfld !1 valuetype '<>f__AnonymousType1000930219981`2'j__TPar',!'j__TPar'>::B@ + IL_0006: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5f__AnonymousType1000930219981`2'j__TPar',!'j__TPar'>,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,valuetype '<>f__AnonymousType1000930219981`2'j__TPar',!'j__TPar'>>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToStringf__AnonymousType1000930219981`2'j__TPar',!'j__TPar'>,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: ldobj valuetype '<>f__AnonymousType1000930219981`2'j__TPar',!'j__TPar'> + IL_0015: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2f__AnonymousType1000930219981`2'j__TPar',!'j__TPar'>,string>::Invoke(!0) + IL_001a: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(valuetype '<>f__AnonymousType1000930219981`2'j__TPar',!'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (valuetype '<>f__AnonymousType1000930219981`2'j__TPar',!'j__TPar'>& V_0, + int32 V_1) + IL_0000: ldarga.s obj + IL_0002: stloc.0 + IL_0003: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_0008: ldarg.0 + IL_0009: ldfld !0 valuetype '<>f__AnonymousType1000930219981`2'j__TPar',!'j__TPar'>::A@ + IL_000e: ldloc.0 + IL_000f: ldfld !0 valuetype '<>f__AnonymousType1000930219981`2'j__TPar',!'j__TPar'>::A@ + IL_0014: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0019: stloc.1 + IL_001a: ldloc.1 + IL_001b: ldc.i4.0 + IL_001c: bge.s IL_0020 + + IL_001e: ldloc.1 + IL_001f: ret + + IL_0020: ldloc.1 + IL_0021: ldc.i4.0 + IL_0022: ble.s IL_0026 + + IL_0024: ldloc.1 + IL_0025: ret + + IL_0026: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_002b: ldarg.0 + IL_002c: ldfld !1 valuetype '<>f__AnonymousType1000930219981`2'j__TPar',!'j__TPar'>::B@ + IL_0031: ldloc.0 + IL_0032: ldfld !1 valuetype '<>f__AnonymousType1000930219981`2'j__TPar',!'j__TPar'>::B@ + IL_0037: tail. + IL_0039: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_003e: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: unbox.any valuetype '<>f__AnonymousType1000930219981`2'j__TPar',!'j__TPar'> + IL_0007: call instance int32 valuetype '<>f__AnonymousType1000930219981`2'j__TPar',!'j__TPar'>::CompareTo(valuetype '<>f__AnonymousType1000930219981`2') + IL_000c: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj, class [runtime]System.Collections.IComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (valuetype '<>f__AnonymousType1000930219981`2'j__TPar',!'j__TPar'> V_0, + valuetype '<>f__AnonymousType1000930219981`2'j__TPar',!'j__TPar'>& V_1, + int32 V_2) + IL_0000: ldarg.1 + IL_0001: unbox.any valuetype '<>f__AnonymousType1000930219981`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloca.s V_0 + IL_0009: stloc.1 + IL_000a: ldarg.2 + IL_000b: ldarg.0 + IL_000c: ldfld !0 valuetype '<>f__AnonymousType1000930219981`2'j__TPar',!'j__TPar'>::A@ + IL_0011: ldloc.1 + IL_0012: ldfld !0 valuetype '<>f__AnonymousType1000930219981`2'j__TPar',!'j__TPar'>::A@ + IL_0017: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_001c: stloc.2 + IL_001d: ldloc.2 + IL_001e: ldc.i4.0 + IL_001f: bge.s IL_0023 + + IL_0021: ldloc.2 + IL_0022: ret + + IL_0023: ldloc.2 + IL_0024: ldc.i4.0 + IL_0025: ble.s IL_0029 + + IL_0027: ldloc.2 + IL_0028: ret + + IL_0029: ldarg.2 + IL_002a: ldarg.0 + IL_002b: ldfld !1 valuetype '<>f__AnonymousType1000930219981`2'j__TPar',!'j__TPar'>::B@ + IL_0030: ldloc.1 + IL_0031: ldfld !1 valuetype '<>f__AnonymousType1000930219981`2'j__TPar',!'j__TPar'>::B@ + IL_0036: tail. + IL_0038: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_003d: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode(class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 7 + .locals init (int32 V_0) + IL_0000: ldc.i4.0 + IL_0001: stloc.0 + IL_0002: ldc.i4 0x9e3779b9 + IL_0007: ldarg.1 + IL_0008: ldarg.0 + IL_0009: ldfld !1 valuetype '<>f__AnonymousType1000930219981`2'j__TPar',!'j__TPar'>::B@ + IL_000e: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0013: ldloc.0 + IL_0014: ldc.i4.6 + IL_0015: shl + IL_0016: ldloc.0 + IL_0017: ldc.i4.2 + IL_0018: shr + IL_0019: add + IL_001a: add + IL_001b: add + IL_001c: stloc.0 + IL_001d: ldc.i4 0x9e3779b9 + IL_0022: ldarg.1 + IL_0023: ldarg.0 + IL_0024: ldfld !0 valuetype '<>f__AnonymousType1000930219981`2'j__TPar',!'j__TPar'>::A@ + IL_0029: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_002e: ldloc.0 + IL_002f: ldc.i4.6 + IL_0030: shl + IL_0031: ldloc.0 + IL_0032: ldc.i4.2 + IL_0033: shr + IL_0034: add + IL_0035: add + IL_0036: add + IL_0037: stloc.0 + IL_0038: ldloc.0 + IL_0039: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() + IL_0006: call instance int32 valuetype '<>f__AnonymousType1000930219981`2'j__TPar',!'j__TPar'>::GetHashCode(class [runtime]System.Collections.IEqualityComparer) + IL_000b: ret + } + + .method public hidebysig instance bool Equals(valuetype '<>f__AnonymousType1000930219981`2'j__TPar',!'j__TPar'> obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (valuetype '<>f__AnonymousType1000930219981`2'j__TPar',!'j__TPar'>& V_0) + IL_0000: ldarga.s obj + IL_0002: stloc.0 + IL_0003: ldarg.2 + IL_0004: ldarg.0 + IL_0005: ldfld !0 valuetype '<>f__AnonymousType1000930219981`2'j__TPar',!'j__TPar'>::A@ + IL_000a: ldloc.0 + IL_000b: ldfld !0 valuetype '<>f__AnonymousType1000930219981`2'j__TPar',!'j__TPar'>::A@ + IL_0010: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_0015: brfalse.s IL_002c + + IL_0017: ldarg.2 + IL_0018: ldarg.0 + IL_0019: ldfld !1 valuetype '<>f__AnonymousType1000930219981`2'j__TPar',!'j__TPar'>::B@ + IL_001e: ldloc.0 + IL_001f: ldfld !1 valuetype '<>f__AnonymousType1000930219981`2'j__TPar',!'j__TPar'>::B@ + IL_0024: tail. + IL_0026: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_002b: ret + + IL_002c: ldc.i4.0 + IL_002d: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (valuetype '<>f__AnonymousType1000930219981`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives/IntrinsicFunctions::TypeTestGenericf__AnonymousType1000930219981`2'j__TPar',!'j__TPar'>>(object) + IL_0006: brtrue.s IL_000a + + IL_0008: br.s IL_001a + + IL_000a: ldarg.1 + IL_000b: call !!0 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives/IntrinsicFunctions::UnboxGenericf__AnonymousType1000930219981`2'j__TPar',!'j__TPar'>>(object) + IL_0010: stloc.0 + IL_0011: ldarg.0 + IL_0012: ldloc.0 + IL_0013: ldarg.2 + IL_0014: call instance bool valuetype '<>f__AnonymousType1000930219981`2'j__TPar',!'j__TPar'>::Equals(valuetype '<>f__AnonymousType1000930219981`2', + class [runtime]System.Collections.IEqualityComparer) + IL_0019: ret + + IL_001a: ldc.i4.0 + IL_001b: ret + } + + .method public hidebysig virtual final instance bool Equals(valuetype '<>f__AnonymousType1000930219981`2'j__TPar',!'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (valuetype '<>f__AnonymousType1000930219981`2'j__TPar',!'j__TPar'>& V_0) + IL_0000: ldarga.s obj + IL_0002: stloc.0 + IL_0003: ldarg.0 + IL_0004: ldfld !0 valuetype '<>f__AnonymousType1000930219981`2'j__TPar',!'j__TPar'>::A@ + IL_0009: ldloc.0 + IL_000a: ldfld !0 valuetype '<>f__AnonymousType1000930219981`2'j__TPar',!'j__TPar'>::A@ + IL_000f: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_0014: brfalse.s IL_002a + + IL_0016: ldarg.0 + IL_0017: ldfld !1 valuetype '<>f__AnonymousType1000930219981`2'j__TPar',!'j__TPar'>::B@ + IL_001c: ldloc.0 + IL_001d: ldfld !1 valuetype '<>f__AnonymousType1000930219981`2'j__TPar',!'j__TPar'>::B@ + IL_0022: tail. + IL_0024: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_0029: ret + + IL_002a: ldc.i4.0 + IL_002b: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (valuetype '<>f__AnonymousType1000930219981`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives/IntrinsicFunctions::TypeTestGenericf__AnonymousType1000930219981`2'j__TPar',!'j__TPar'>>(object) + IL_0006: brtrue.s IL_000a + + IL_0008: br.s IL_0019 + + IL_000a: ldarg.1 + IL_000b: call !!0 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives/IntrinsicFunctions::UnboxGenericf__AnonymousType1000930219981`2'j__TPar',!'j__TPar'>>(object) + IL_0010: stloc.0 + IL_0011: ldarg.0 + IL_0012: ldloc.0 + IL_0013: call instance bool valuetype '<>f__AnonymousType1000930219981`2'j__TPar',!'j__TPar'>::Equals(valuetype '<>f__AnonymousType1000930219981`2') + IL_0018: ret + + IL_0019: ldc.i4.0 + IL_001a: ret + } + + .property instance !'j__TPar' A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType1000930219981`2'::get_A() + } + .property instance !'j__TPar' B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType1000930219981`2'::get_B() + } +} + +.class public auto ansi serializable sealed beforefieldinit '<>f__AnonymousType3545307392`2'<'j__TPar','j__TPar'> + extends [runtime]System.Object + implements [runtime]System.Collections.IStructuralComparable, + [runtime]System.IComparable, + class [runtime]System.IComparable`1f__AnonymousType3545307392`2'j__TPar',!'j__TPar'>>, + [runtime]System.Collections.IStructuralEquatable, + class [runtime]System.IEquatable`1f__AnonymousType3545307392`2'j__TPar',!'j__TPar'>> +{ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field private !'j__TPar' A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field private !'j__TPar' B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor(!'j__TPar' A, !'j__TPar' B) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 1E 3C 3E 66 5F 5F 41 6E 6F 6E + 79 6D 6F 75 73 54 79 70 65 33 35 34 35 33 30 37 + 33 39 32 60 32 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld !0 class '<>f__AnonymousType3545307392`2'j__TPar',!'j__TPar'>::A@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld !1 class '<>f__AnonymousType3545307392`2'j__TPar',!'j__TPar'>::B@ + IL_0014: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_A() 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: ldfld !0 class '<>f__AnonymousType3545307392`2'j__TPar',!'j__TPar'>::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance !'j__TPar' get_B() 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: ldfld !1 class '<>f__AnonymousType3545307392`2'j__TPar',!'j__TPar'>::B@ + IL_0006: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5f__AnonymousType3545307392`2'j__TPar',!'j__TPar'>,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class '<>f__AnonymousType3545307392`2'j__TPar',!'j__TPar'>>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToStringf__AnonymousType3545307392`2'j__TPar',!'j__TPar'>,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2f__AnonymousType3545307392`2'j__TPar',!'j__TPar'>,string>::Invoke(!0) + IL_0015: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(class '<>f__AnonymousType3545307392`2'j__TPar',!'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0044 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0042 + + IL_0006: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_000b: ldarg.0 + IL_000c: ldfld !0 class '<>f__AnonymousType3545307392`2'j__TPar',!'j__TPar'>::A@ + IL_0011: ldarg.1 + IL_0012: ldfld !0 class '<>f__AnonymousType3545307392`2'j__TPar',!'j__TPar'>::A@ + IL_0017: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_001c: stloc.0 + IL_001d: ldloc.0 + IL_001e: ldc.i4.0 + IL_001f: bge.s IL_0023 + + IL_0021: ldloc.0 + IL_0022: ret + + IL_0023: ldloc.0 + IL_0024: ldc.i4.0 + IL_0025: ble.s IL_0029 + + IL_0027: ldloc.0 + IL_0028: ret + + IL_0029: call class [runtime]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_002e: ldarg.0 + IL_002f: ldfld !1 class '<>f__AnonymousType3545307392`2'j__TPar',!'j__TPar'>::B@ + IL_0034: ldarg.1 + IL_0035: ldfld !1 class '<>f__AnonymousType3545307392`2'j__TPar',!'j__TPar'>::B@ + IL_003a: tail. + IL_003c: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0041: ret + + IL_0042: ldc.i4.1 + IL_0043: ret + + IL_0044: ldarg.1 + IL_0045: brfalse.s IL_0049 + + IL_0047: ldc.i4.m1 + IL_0048: ret + + IL_0049: ldc.i4.0 + IL_004a: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: unbox.any class '<>f__AnonymousType3545307392`2'j__TPar',!'j__TPar'> + IL_0007: tail. + IL_0009: callvirt instance int32 class '<>f__AnonymousType3545307392`2'j__TPar',!'j__TPar'>::CompareTo(class '<>f__AnonymousType3545307392`2') + IL_000e: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj, class [runtime]System.Collections.IComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType3545307392`2'j__TPar',!'j__TPar'> V_0, + class '<>f__AnonymousType3545307392`2'j__TPar',!'j__TPar'> V_1, + int32 V_2) + IL_0000: ldarg.1 + IL_0001: unbox.any class '<>f__AnonymousType3545307392`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: stloc.1 + IL_0009: ldarg.0 + IL_000a: brfalse.s IL_004a + + IL_000c: ldarg.1 + IL_000d: unbox.any class '<>f__AnonymousType3545307392`2'j__TPar',!'j__TPar'> + IL_0012: brfalse.s IL_0048 + + IL_0014: ldarg.2 + IL_0015: ldarg.0 + IL_0016: ldfld !0 class '<>f__AnonymousType3545307392`2'j__TPar',!'j__TPar'>::A@ + IL_001b: ldloc.1 + IL_001c: ldfld !0 class '<>f__AnonymousType3545307392`2'j__TPar',!'j__TPar'>::A@ + IL_0021: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0026: stloc.2 + IL_0027: ldloc.2 + IL_0028: ldc.i4.0 + IL_0029: bge.s IL_002d + + IL_002b: ldloc.2 + IL_002c: ret + + IL_002d: ldloc.2 + IL_002e: ldc.i4.0 + IL_002f: ble.s IL_0033 + + IL_0031: ldloc.2 + IL_0032: ret + + IL_0033: ldarg.2 + IL_0034: ldarg.0 + IL_0035: ldfld !1 class '<>f__AnonymousType3545307392`2'j__TPar',!'j__TPar'>::B@ + IL_003a: ldloc.1 + IL_003b: ldfld !1 class '<>f__AnonymousType3545307392`2'j__TPar',!'j__TPar'>::B@ + IL_0040: tail. + IL_0042: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericComparisonWithComparerj__TPar'>(class [runtime]System.Collections.IComparer, + !!0, + !!0) + IL_0047: ret + + IL_0048: ldc.i4.1 + IL_0049: ret + + IL_004a: ldarg.1 + IL_004b: unbox.any class '<>f__AnonymousType3545307392`2'j__TPar',!'j__TPar'> + IL_0050: brfalse.s IL_0054 + + IL_0052: ldc.i4.m1 + IL_0053: ret + + IL_0054: ldc.i4.0 + IL_0055: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode(class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 7 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_003d + + IL_0003: ldc.i4.0 + IL_0004: stloc.0 + IL_0005: ldc.i4 0x9e3779b9 + IL_000a: ldarg.1 + IL_000b: ldarg.0 + IL_000c: ldfld !1 class '<>f__AnonymousType3545307392`2'j__TPar',!'j__TPar'>::B@ + IL_0011: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0016: ldloc.0 + IL_0017: ldc.i4.6 + IL_0018: shl + IL_0019: ldloc.0 + IL_001a: ldc.i4.2 + IL_001b: shr + IL_001c: add + IL_001d: add + IL_001e: add + IL_001f: stloc.0 + IL_0020: ldc.i4 0x9e3779b9 + IL_0025: ldarg.1 + IL_0026: ldarg.0 + IL_0027: ldfld !0 class '<>f__AnonymousType3545307392`2'j__TPar',!'j__TPar'>::A@ + IL_002c: call int32 [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericHashWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0) + IL_0031: ldloc.0 + IL_0032: ldc.i4.6 + IL_0033: shl + IL_0034: ldloc.0 + IL_0035: ldc.i4.2 + IL_0036: shr + IL_0037: add + IL_0038: add + IL_0039: add + IL_003a: stloc.0 + IL_003b: ldloc.0 + IL_003c: ret + + IL_003d: ldc.i4.0 + IL_003e: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() + IL_0006: tail. + IL_0008: callvirt instance int32 class '<>f__AnonymousType3545307392`2'j__TPar',!'j__TPar'>::GetHashCode(class [runtime]System.Collections.IEqualityComparer) + IL_000d: ret + } + + .method public hidebysig instance bool Equals(class '<>f__AnonymousType3545307392`2'j__TPar',!'j__TPar'> obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType3545307392`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0035 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0033 + + IL_0006: ldarg.1 + IL_0007: stloc.0 + IL_0008: ldarg.2 + IL_0009: ldarg.0 + IL_000a: ldfld !0 class '<>f__AnonymousType3545307392`2'j__TPar',!'j__TPar'>::A@ + IL_000f: ldloc.0 + IL_0010: ldfld !0 class '<>f__AnonymousType3545307392`2'j__TPar',!'j__TPar'>::A@ + IL_0015: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_001a: brfalse.s IL_0031 + + IL_001c: ldarg.2 + IL_001d: ldarg.0 + IL_001e: ldfld !1 class '<>f__AnonymousType3545307392`2'j__TPar',!'j__TPar'>::B@ + IL_0023: ldloc.0 + IL_0024: ldfld !1 class '<>f__AnonymousType3545307392`2'j__TPar',!'j__TPar'>::B@ + IL_0029: tail. + IL_002b: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityWithComparerj__TPar'>(class [runtime]System.Collections.IEqualityComparer, + !!0, + !!0) + IL_0030: ret + + IL_0031: ldc.i4.0 + IL_0032: ret + + IL_0033: ldc.i4.0 + IL_0034: ret + + IL_0035: ldarg.1 + IL_0036: ldnull + IL_0037: cgt.un + IL_0039: ldc.i4.0 + IL_003a: ceq + IL_003c: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (class '<>f__AnonymousType3545307392`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType3545307392`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0015 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: ldarg.2 + IL_000d: tail. + IL_000f: callvirt instance bool class '<>f__AnonymousType3545307392`2'j__TPar',!'j__TPar'>::Equals(class '<>f__AnonymousType3545307392`2', + class [runtime]System.Collections.IEqualityComparer) + IL_0014: ret + + IL_0015: ldc.i4.0 + IL_0016: ret + } + + .method public hidebysig virtual final instance bool Equals(class '<>f__AnonymousType3545307392`2'j__TPar',!'j__TPar'> obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0031 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_002f + + IL_0006: ldarg.0 + IL_0007: ldfld !0 class '<>f__AnonymousType3545307392`2'j__TPar',!'j__TPar'>::A@ + IL_000c: ldarg.1 + IL_000d: ldfld !0 class '<>f__AnonymousType3545307392`2'j__TPar',!'j__TPar'>::A@ + IL_0012: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_0017: brfalse.s IL_002d + + IL_0019: ldarg.0 + IL_001a: ldfld !1 class '<>f__AnonymousType3545307392`2'j__TPar',!'j__TPar'>::B@ + IL_001f: ldarg.1 + IL_0020: ldfld !1 class '<>f__AnonymousType3545307392`2'j__TPar',!'j__TPar'>::B@ + IL_0025: tail. + IL_0027: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::GenericEqualityERj__TPar'>(!!0, + !!0) + IL_002c: ret + + IL_002d: ldc.i4.0 + IL_002e: ret + + IL_002f: ldc.i4.0 + IL_0030: ret + + IL_0031: ldarg.1 + IL_0032: ldnull + IL_0033: cgt.un + IL_0035: ldc.i4.0 + IL_0036: ceq + IL_0038: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (class '<>f__AnonymousType3545307392`2'j__TPar',!'j__TPar'> V_0) + IL_0000: ldarg.1 + IL_0001: isinst class '<>f__AnonymousType3545307392`2'j__TPar',!'j__TPar'> + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: brfalse.s IL_0014 + + IL_000a: ldarg.0 + IL_000b: ldloc.0 + IL_000c: tail. + IL_000e: callvirt instance bool class '<>f__AnonymousType3545307392`2'j__TPar',!'j__TPar'>::Equals(class '<>f__AnonymousType3545307392`2') + IL_0013: ret + + IL_0014: ldc.i4.0 + IL_0015: ret + } + + .property instance !'j__TPar' A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType3545307392`2'::get_A() + } + .property instance !'j__TPar' B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance !'j__TPar' '<>f__AnonymousType3545307392`2'::get_B() + } +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/NominalRecordExpressionSpreads.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/NominalRecordExpressionSpreads.fs new file mode 100644 index 00000000000..ef130a5fc4d --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/NominalRecordExpressionSpreads.fs @@ -0,0 +1,90 @@ +module EmittedIL.NominalRecordExpressionSpreads + +open FSharp.Test +open FSharp.Test.Compiler + +/// Various types in the System.Diagnostics.CodeAnalysis namespace will be generated by the compiler +/// for the Framework target but will be included in the runtime for the .NET (Core) target. +/// Since the only IL that is material here is the field names, types, and ordering, +/// and since the spread logic is entirely framework/runtime-agnostic, +/// it is simpler to run these tests only for the .NET (Core) target. +type TheoryAttribute = TheoryForNETCOREAPPAttribute + +let [] SupportedLangVersion = "preview" + +let verifyCompilation compilation = + compilation + |> withLangVersion SupportedLangVersion + |> asExe + |> withEmbeddedPdb + |> withEmbedAllSource + |> ignoreWarnings + |> compile + |> shouldSucceed + |> verifyILBaseline + +[] +let Expression_Nominal_ExplicitShadowsSpread_fs compilation = + compilation + |> getCompilation + |> verifyCompilation + +[] +let Expression_Nominal_ExtraFieldsAreIgnored_fs compilation = + compilation + |> getCompilation + |> verifyCompilation + +[] +let Expression_Nominal_NoOverlap_Explicit_Spread_fs compilation = + compilation + |> getCompilation + |> verifyCompilation + +[] +let Expression_Nominal_NoOverlap_Spread_Explicit_fs compilation = + compilation + |> getCompilation + |> verifyCompilation + +[] +let Expression_Nominal_NoOverlap_Spread_Spread_fs compilation = + compilation + |> getCompilation + |> verifyCompilation + +[] +let Expression_Nominal_NoOverlap_SpreadFromAnon_fs compilation = + compilation + |> getCompilation + |> verifyCompilation + +[] +let Expression_Nominal_SpreadShadowsExplicit_fs compilation = + compilation + |> getCompilation + |> verifyCompilation + +[] +let Expression_Nominal_SpreadShadowsSpread_fs compilation = + compilation + |> getCompilation + |> verifyCompilation + +[] +let Expression_Nominal_CoercionsApplied_fs compilation = + compilation + |> getCompilation + |> verifyCompilation + +[] +let Expression_Nominal_Structness_fs compilation = + compilation + |> getCompilation + |> verifyCompilation + +[] +let Expression_Nominal_NestedUpdates_fs compilation = + compilation + |> getCompilation + |> verifyCompilation diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/RecordTypeSpreads.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/RecordTypeSpreads.fs new file mode 100644 index 00000000000..00977956e25 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/RecordTypeSpreads.fs @@ -0,0 +1,78 @@ +module EmittedIL.RecordTypeSpreads + +open FSharp.Test +open FSharp.Test.Compiler + +/// Various types in the System.Diagnostics.CodeAnalysis namespace will be generated by the compiler +/// for the Framework target but will be included in the runtime for the .NET (Core) target. +/// Since the only IL that is material here is the field names, types, and ordering, +/// and since the spread logic is entirely framework/runtime-agnostic, +/// it is simpler to run these tests only for the .NET (Core) target. +type TheoryAttribute = TheoryForNETCOREAPPAttribute + +let [] SupportedLangVersion = "preview" + +let verifyCompilation compilation = + compilation + |> withLangVersion SupportedLangVersion + |> asExe + |> withEmbeddedPdb + |> withEmbedAllSource + |> ignoreWarnings + |> compile + |> shouldSucceed + |> verifyILBaseline + +[] +let Type_ExplicitShadowsSpread_fs compilation = + compilation + |> getCompilation + |> verifyCompilation + +[] +let Type_NoOverlap_Explicit_Spread_fs compilation = + compilation + |> getCompilation + |> verifyCompilation + +[] +let Type_NoOverlap_Spread_Explicit_fs compilation = + compilation + |> getCompilation + |> verifyCompilation + +[] +let Type_NoOverlap_Spread_Spread_fs compilation = + compilation + |> getCompilation + |> verifyCompilation + +[] +let Type_NoOverlap_SpreadFromAnon_fs compilation = + compilation + |> getCompilation + |> verifyCompilation + +[] +let Type_SpreadShadowsSpread_fs compilation = + compilation + |> getCompilation + |> verifyCompilation + +[] +let Type_SpreadShadowsExplicit_fs compilation = + compilation + |> getCompilation + |> verifyCompilation + +[] +let Type_Type_AttributesAreShadowed_fs compilation = + compilation + |> getCompilation + |> verifyCompilation + +[] +let Type_NoOverlap_Explicit_Spread_Generics_fs compilation = + compilation + |> getCompilation + |> verifyCompilation diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_AttributesAreShadowed.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_AttributesAreShadowed.fs new file mode 100644 index 00000000000..d2a2c6076ae --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_AttributesAreShadowed.fs @@ -0,0 +1,7 @@ +type Attr1Attribute () = inherit System.Attribute () +type Attr2Attribute () = inherit System.Attribute () + +[] +type R1 = { [] A : int; [] B : int } +[] +type R2 = { ...R1; [] A : string } diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_AttributesAreShadowed.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_AttributesAreShadowed.fs.il.bsl new file mode 100644 index 00000000000..bbc6b8530b6 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_AttributesAreShadowed.fs.il.bsl @@ -0,0 +1,255 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable nested public Attr1Attribute + extends [runtime]System.Attribute + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor() cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: callvirt instance void [runtime]System.Attribute::.ctor() + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ret + } + + } + + .class auto ansi serializable nested public Attr2Attribute + extends [runtime]System.Attribute + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor() cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: callvirt instance void [runtime]System.Attribute::.ctor() + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ret + } + + } + + .class auto ansi serializable sealed nested public R1 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.DefaultAugmentationAttribute::.ctor(bool) = ( 01 00 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly int32 A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly int32 B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname instance int32 get_A() 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: ldfld int32 assembly/R1::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance int32 get_B() 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: ldfld int32 assembly/R1::B@ + IL_0006: ret + } + + .method public specialname rtspecialname instance void .ctor(int32 a, int32 b) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 1D 54 79 70 65 5F 41 74 74 72 + 69 62 75 74 65 73 41 72 65 53 68 61 64 6F 77 65 + 64 2B 52 31 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld int32 assembly/R1::A@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld int32 assembly/R1::B@ + IL_0014: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/R1>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .property instance int32 A() + { + .custom instance void assembly/Attr1Attribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance int32 assembly/R1::get_A() + } + .property instance int32 B() + { + .custom instance void assembly/Attr1Attribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance int32 assembly/R1::get_B() + } + } + + .class auto ansi serializable sealed nested public R2 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.DefaultAugmentationAttribute::.ctor(bool) = ( 01 00 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly int32 B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly string A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname instance int32 get_B() 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: ldfld int32 assembly/R2::B@ + IL_0006: ret + } + + .method public hidebysig specialname instance string get_A() 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: ldfld string assembly/R2::A@ + IL_0006: ret + } + + .method public specialname rtspecialname instance void .ctor(int32 b, string a) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 1D 54 79 70 65 5F 41 74 74 72 + 69 62 75 74 65 73 41 72 65 53 68 61 64 6F 77 65 + 64 2B 52 32 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld int32 assembly/R2::B@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld string assembly/R2::A@ + IL_0014: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/R2>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .property instance int32 B() + { + .custom instance void assembly/Attr1Attribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance int32 assembly/R2::get_B() + } + .property instance string A() + { + .custom instance void assembly/Attr2Attribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance string assembly/R2::get_A() + } + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_ExplicitShadowsSpread.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_ExplicitShadowsSpread.fs new file mode 100644 index 00000000000..48ce14dfbbd --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_ExplicitShadowsSpread.fs @@ -0,0 +1,4 @@ +[] +type R1 = { A : int; B : int } +[] +type R2 = { ...R1; A : string } diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_ExplicitShadowsSpread.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_ExplicitShadowsSpread.fs.il.bsl new file mode 100644 index 00000000000..712b79365d5 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_ExplicitShadowsSpread.fs.il.bsl @@ -0,0 +1,217 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable sealed nested public R1 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.DefaultAugmentationAttribute::.ctor(bool) = ( 01 00 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly int32 A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly int32 B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname instance int32 get_A() 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: ldfld int32 assembly/R1::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance int32 get_B() 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: ldfld int32 assembly/R1::B@ + IL_0006: ret + } + + .method public specialname rtspecialname instance void .ctor(int32 a, int32 b) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 1D 54 79 70 65 5F 45 78 70 6C + 69 63 69 74 53 68 61 64 6F 77 73 53 70 72 65 61 + 64 2B 52 31 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld int32 assembly/R1::A@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld int32 assembly/R1::B@ + IL_0014: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/R1>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .property instance int32 A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance int32 assembly/R1::get_A() + } + .property instance int32 B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance int32 assembly/R1::get_B() + } + } + + .class auto ansi serializable sealed nested public R2 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.DefaultAugmentationAttribute::.ctor(bool) = ( 01 00 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly int32 B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly string A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname instance int32 get_B() 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: ldfld int32 assembly/R2::B@ + IL_0006: ret + } + + .method public hidebysig specialname instance string get_A() 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: ldfld string assembly/R2::A@ + IL_0006: ret + } + + .method public specialname rtspecialname instance void .ctor(int32 b, string a) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 1D 54 79 70 65 5F 45 78 70 6C + 69 63 69 74 53 68 61 64 6F 77 73 53 70 72 65 61 + 64 2B 52 32 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld int32 assembly/R2::B@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld string assembly/R2::A@ + IL_0014: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/R2>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .property instance int32 B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance int32 assembly/R2::get_B() + } + .property instance string A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance string assembly/R2::get_A() + } + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_NoOverlap_Explicit_Spread.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_NoOverlap_Explicit_Spread.fs new file mode 100644 index 00000000000..bc667c62e2e --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_NoOverlap_Explicit_Spread.fs @@ -0,0 +1,4 @@ +[] +type R1 = { B : int; C : int } +[] +type R2 = { A : int; ...R1 } diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_NoOverlap_Explicit_Spread.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_NoOverlap_Explicit_Spread.fs.il.bsl new file mode 100644 index 00000000000..4fc90ee19a3 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_NoOverlap_Explicit_Spread.fs.il.bsl @@ -0,0 +1,243 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable sealed nested public R1 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.DefaultAugmentationAttribute::.ctor(bool) = ( 01 00 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly int32 B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly int32 C@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname instance int32 get_B() 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: ldfld int32 assembly/R1::B@ + IL_0006: ret + } + + .method public hidebysig specialname instance int32 get_C() 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: ldfld int32 assembly/R1::C@ + IL_0006: ret + } + + .method public specialname rtspecialname instance void .ctor(int32 b, int32 c) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 21 54 79 70 65 5F 4E 6F 4F 76 + 65 72 6C 61 70 5F 45 78 70 6C 69 63 69 74 5F 53 + 70 72 65 61 64 2B 52 31 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld int32 assembly/R1::B@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld int32 assembly/R1::C@ + IL_0014: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/R1>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .property instance int32 B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance int32 assembly/R1::get_B() + } + .property instance int32 C() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance int32 assembly/R1::get_C() + } + } + + .class auto ansi serializable sealed nested public R2 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.DefaultAugmentationAttribute::.ctor(bool) = ( 01 00 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly int32 A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly int32 B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly int32 C@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname instance int32 get_A() 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: ldfld int32 assembly/R2::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance int32 get_B() 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: ldfld int32 assembly/R2::B@ + IL_0006: ret + } + + .method public hidebysig specialname instance int32 get_C() 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: ldfld int32 assembly/R2::C@ + IL_0006: ret + } + + .method public specialname rtspecialname + instance void .ctor(int32 a, + int32 b, + int32 c) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 21 54 79 70 65 5F 4E 6F 4F 76 + 65 72 6C 61 70 5F 45 78 70 6C 69 63 69 74 5F 53 + 70 72 65 61 64 2B 52 32 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld int32 assembly/R2::A@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld int32 assembly/R2::B@ + IL_0014: ldarg.0 + IL_0015: ldarg.3 + IL_0016: stfld int32 assembly/R2::C@ + IL_001b: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/R2>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .property instance int32 A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance int32 assembly/R2::get_A() + } + .property instance int32 B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance int32 assembly/R2::get_B() + } + .property instance int32 C() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 02 00 00 00 00 00 ) + .get instance int32 assembly/R2::get_C() + } + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_NoOverlap_Explicit_Spread_Generics.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_NoOverlap_Explicit_Spread_Generics.fs new file mode 100644 index 00000000000..5d91ed24673 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_NoOverlap_Explicit_Spread_Generics.fs @@ -0,0 +1,6 @@ +[] +type R1<'a> = { A : 'a } +[] +type R2<'a> = { B : 'a } +[] +type R3<'a> = { ...R1<'a>; ...R2<'a> } diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_NoOverlap_Explicit_Spread_Generics.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_NoOverlap_Explicit_Spread_Generics.fs.il.bsl new file mode 100644 index 00000000000..04c54f3af6c --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_NoOverlap_Explicit_Spread_Generics.fs.il.bsl @@ -0,0 +1,255 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable sealed nested public R1`1 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.DefaultAugmentationAttribute::.ctor(bool) = ( 01 00 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly !a A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname instance !a get_A() 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: ldfld !0 class assembly/R1`1::A@ + IL_0006: ret + } + + .method public specialname rtspecialname instance void .ctor(!a a) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 2C 54 79 70 65 5F 4E 6F 4F 76 + 65 72 6C 61 70 5F 45 78 70 6C 69 63 69 74 5F 53 + 70 72 65 61 64 5F 47 65 6E 65 72 69 63 73 2B 52 + 31 60 31 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld !0 class assembly/R1`1::A@ + IL_000d: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/R1`1>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,string>::Invoke(!0) + IL_0015: ret + } + + .property instance !a A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance !a assembly/R1`1::get_A() + } + } + + .class auto ansi serializable sealed nested public R2`1 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.DefaultAugmentationAttribute::.ctor(bool) = ( 01 00 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly !a B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname instance !a get_B() 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: ldfld !0 class assembly/R2`1::B@ + IL_0006: ret + } + + .method public specialname rtspecialname instance void .ctor(!a b) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 2C 54 79 70 65 5F 4E 6F 4F 76 + 65 72 6C 61 70 5F 45 78 70 6C 69 63 69 74 5F 53 + 70 72 65 61 64 5F 47 65 6E 65 72 69 63 73 2B 52 + 32 60 31 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld !0 class assembly/R2`1::B@ + IL_000d: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/R2`1>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,string>::Invoke(!0) + IL_0015: ret + } + + .property instance !a B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance !a assembly/R2`1::get_B() + } + } + + .class auto ansi serializable sealed nested public R3`1 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.DefaultAugmentationAttribute::.ctor(bool) = ( 01 00 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly !a A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly !a B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname instance !a get_A() 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: ldfld !0 class assembly/R3`1::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance !a get_B() 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: ldfld !0 class assembly/R3`1::B@ + IL_0006: ret + } + + .method public specialname rtspecialname instance void .ctor(!a a, !a b) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 2C 54 79 70 65 5F 4E 6F 4F 76 + 65 72 6C 61 70 5F 45 78 70 6C 69 63 69 74 5F 53 + 70 72 65 61 64 5F 47 65 6E 65 72 69 63 73 2B 52 + 33 60 31 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld !0 class assembly/R3`1::A@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld !0 class assembly/R3`1::B@ + IL_0014: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,string>,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/R3`1>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString,string>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,string>::Invoke(!0) + IL_0015: ret + } + + .property instance !a A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance !a assembly/R3`1::get_A() + } + .property instance !a B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance !a assembly/R3`1::get_B() + } + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_NoOverlap_SpreadFromAnon.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_NoOverlap_SpreadFromAnon.fs new file mode 100644 index 00000000000..9c0f6e97ac9 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_NoOverlap_SpreadFromAnon.fs @@ -0,0 +1,3 @@ +type R1 = {| A : int; B : int |} +[] +type R2 = { ...R1; C : int } diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_NoOverlap_SpreadFromAnon.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_NoOverlap_SpreadFromAnon.fs.il.bsl new file mode 100644 index 00000000000..97fa4e04bc5 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_NoOverlap_SpreadFromAnon.fs.il.bsl @@ -0,0 +1,162 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable sealed nested public R2 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.DefaultAugmentationAttribute::.ctor(bool) = ( 01 00 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly int32 A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly int32 B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly int32 C@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname instance int32 get_A() 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: ldfld int32 assembly/R2::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance int32 get_B() 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: ldfld int32 assembly/R2::B@ + IL_0006: ret + } + + .method public hidebysig specialname instance int32 get_C() 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: ldfld int32 assembly/R2::C@ + IL_0006: ret + } + + .method public specialname rtspecialname + instance void .ctor(int32 a, + int32 b, + int32 c) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 20 54 79 70 65 5F 4E 6F 4F 76 + 65 72 6C 61 70 5F 53 70 72 65 61 64 46 72 6F 6D + 41 6E 6F 6E 2B 52 32 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld int32 assembly/R2::A@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld int32 assembly/R2::B@ + IL_0014: ldarg.0 + IL_0015: ldarg.3 + IL_0016: stfld int32 assembly/R2::C@ + IL_001b: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/R2>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .property instance int32 A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance int32 assembly/R2::get_A() + } + .property instance int32 B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance int32 assembly/R2::get_B() + } + .property instance int32 C() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 02 00 00 00 00 00 ) + .get instance int32 assembly/R2::get_C() + } + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_NoOverlap_Spread_Explicit.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_NoOverlap_Spread_Explicit.fs new file mode 100644 index 00000000000..c5da8718a02 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_NoOverlap_Spread_Explicit.fs @@ -0,0 +1,4 @@ +[] +type R1 = { A : int; B : int } +[] +type R2 = { ...R1; C : int } diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_NoOverlap_Spread_Explicit.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_NoOverlap_Spread_Explicit.fs.il.bsl new file mode 100644 index 00000000000..f71df039f32 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_NoOverlap_Spread_Explicit.fs.il.bsl @@ -0,0 +1,243 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable sealed nested public R1 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.DefaultAugmentationAttribute::.ctor(bool) = ( 01 00 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly int32 A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly int32 B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname instance int32 get_A() 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: ldfld int32 assembly/R1::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance int32 get_B() 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: ldfld int32 assembly/R1::B@ + IL_0006: ret + } + + .method public specialname rtspecialname instance void .ctor(int32 a, int32 b) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 21 54 79 70 65 5F 4E 6F 4F 76 + 65 72 6C 61 70 5F 53 70 72 65 61 64 5F 45 78 70 + 6C 69 63 69 74 2B 52 31 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld int32 assembly/R1::A@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld int32 assembly/R1::B@ + IL_0014: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/R1>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .property instance int32 A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance int32 assembly/R1::get_A() + } + .property instance int32 B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance int32 assembly/R1::get_B() + } + } + + .class auto ansi serializable sealed nested public R2 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.DefaultAugmentationAttribute::.ctor(bool) = ( 01 00 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly int32 A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly int32 B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly int32 C@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname instance int32 get_A() 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: ldfld int32 assembly/R2::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance int32 get_B() 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: ldfld int32 assembly/R2::B@ + IL_0006: ret + } + + .method public hidebysig specialname instance int32 get_C() 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: ldfld int32 assembly/R2::C@ + IL_0006: ret + } + + .method public specialname rtspecialname + instance void .ctor(int32 a, + int32 b, + int32 c) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 21 54 79 70 65 5F 4E 6F 4F 76 + 65 72 6C 61 70 5F 53 70 72 65 61 64 5F 45 78 70 + 6C 69 63 69 74 2B 52 32 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld int32 assembly/R2::A@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld int32 assembly/R2::B@ + IL_0014: ldarg.0 + IL_0015: ldarg.3 + IL_0016: stfld int32 assembly/R2::C@ + IL_001b: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/R2>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .property instance int32 A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance int32 assembly/R2::get_A() + } + .property instance int32 B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance int32 assembly/R2::get_B() + } + .property instance int32 C() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 02 00 00 00 00 00 ) + .get instance int32 assembly/R2::get_C() + } + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_NoOverlap_Spread_Spread.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_NoOverlap_Spread_Spread.fs new file mode 100644 index 00000000000..447aa272308 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_NoOverlap_Spread_Spread.fs @@ -0,0 +1,8 @@ +[] +type R1 = { A : int; B : int } +[] +type R2 = { C : int; D : int } +[] +type R3 = { ...R1; ...R2 } +[] +type R4 = { ...R2; ...R1 } diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_NoOverlap_Spread_Spread.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_NoOverlap_Spread_Spread.fs.il.bsl new file mode 100644 index 00000000000..9998053a106 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_NoOverlap_Spread_Spread.fs.il.bsl @@ -0,0 +1,479 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable sealed nested public R1 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.DefaultAugmentationAttribute::.ctor(bool) = ( 01 00 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly int32 A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly int32 B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname instance int32 get_A() 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: ldfld int32 assembly/R1::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance int32 get_B() 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: ldfld int32 assembly/R1::B@ + IL_0006: ret + } + + .method public specialname rtspecialname instance void .ctor(int32 a, int32 b) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 1F 54 79 70 65 5F 4E 6F 4F 76 + 65 72 6C 61 70 5F 53 70 72 65 61 64 5F 53 70 72 + 65 61 64 2B 52 31 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld int32 assembly/R1::A@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld int32 assembly/R1::B@ + IL_0014: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/R1>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .property instance int32 A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance int32 assembly/R1::get_A() + } + .property instance int32 B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance int32 assembly/R1::get_B() + } + } + + .class auto ansi serializable sealed nested public R2 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.DefaultAugmentationAttribute::.ctor(bool) = ( 01 00 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly int32 C@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly int32 D@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname instance int32 get_C() 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: ldfld int32 assembly/R2::C@ + IL_0006: ret + } + + .method public hidebysig specialname instance int32 get_D() 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: ldfld int32 assembly/R2::D@ + IL_0006: ret + } + + .method public specialname rtspecialname instance void .ctor(int32 c, int32 d) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 1F 54 79 70 65 5F 4E 6F 4F 76 + 65 72 6C 61 70 5F 53 70 72 65 61 64 5F 53 70 72 + 65 61 64 2B 52 32 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld int32 assembly/R2::C@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld int32 assembly/R2::D@ + IL_0014: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/R2>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .property instance int32 C() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance int32 assembly/R2::get_C() + } + .property instance int32 D() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance int32 assembly/R2::get_D() + } + } + + .class auto ansi serializable sealed nested public R3 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.DefaultAugmentationAttribute::.ctor(bool) = ( 01 00 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly int32 A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly int32 B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly int32 C@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly int32 D@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname instance int32 get_A() 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: ldfld int32 assembly/R3::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance int32 get_B() 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: ldfld int32 assembly/R3::B@ + IL_0006: ret + } + + .method public hidebysig specialname instance int32 get_C() 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: ldfld int32 assembly/R3::C@ + IL_0006: ret + } + + .method public hidebysig specialname instance int32 get_D() 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: ldfld int32 assembly/R3::D@ + IL_0006: ret + } + + .method public specialname rtspecialname + instance void .ctor(int32 a, + int32 b, + int32 c, + int32 d) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 1F 54 79 70 65 5F 4E 6F 4F 76 + 65 72 6C 61 70 5F 53 70 72 65 61 64 5F 53 70 72 + 65 61 64 2B 52 33 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld int32 assembly/R3::A@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld int32 assembly/R3::B@ + IL_0014: ldarg.0 + IL_0015: ldarg.3 + IL_0016: stfld int32 assembly/R3::C@ + IL_001b: ldarg.0 + IL_001c: ldarg.s d + IL_001e: stfld int32 assembly/R3::D@ + IL_0023: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/R3>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .property instance int32 A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance int32 assembly/R3::get_A() + } + .property instance int32 B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance int32 assembly/R3::get_B() + } + .property instance int32 C() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 02 00 00 00 00 00 ) + .get instance int32 assembly/R3::get_C() + } + .property instance int32 D() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 03 00 00 00 00 00 ) + .get instance int32 assembly/R3::get_D() + } + } + + .class auto ansi serializable sealed nested public R4 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.DefaultAugmentationAttribute::.ctor(bool) = ( 01 00 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly int32 C@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly int32 D@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly int32 A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly int32 B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname instance int32 get_C() 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: ldfld int32 assembly/R4::C@ + IL_0006: ret + } + + .method public hidebysig specialname instance int32 get_D() 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: ldfld int32 assembly/R4::D@ + IL_0006: ret + } + + .method public hidebysig specialname instance int32 get_A() 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: ldfld int32 assembly/R4::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance int32 get_B() 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: ldfld int32 assembly/R4::B@ + IL_0006: ret + } + + .method public specialname rtspecialname + instance void .ctor(int32 c, + int32 d, + int32 a, + int32 b) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 1F 54 79 70 65 5F 4E 6F 4F 76 + 65 72 6C 61 70 5F 53 70 72 65 61 64 5F 53 70 72 + 65 61 64 2B 52 34 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld int32 assembly/R4::C@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld int32 assembly/R4::D@ + IL_0014: ldarg.0 + IL_0015: ldarg.3 + IL_0016: stfld int32 assembly/R4::A@ + IL_001b: ldarg.0 + IL_001c: ldarg.s b + IL_001e: stfld int32 assembly/R4::B@ + IL_0023: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/R4>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .property instance int32 C() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance int32 assembly/R4::get_C() + } + .property instance int32 D() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance int32 assembly/R4::get_D() + } + .property instance int32 A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 02 00 00 00 00 00 ) + .get instance int32 assembly/R4::get_A() + } + .property instance int32 B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 03 00 00 00 00 00 ) + .get instance int32 assembly/R4::get_B() + } + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_SpreadShadowsExplicit.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_SpreadShadowsExplicit.fs new file mode 100644 index 00000000000..0a9e73ffa9d --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_SpreadShadowsExplicit.fs @@ -0,0 +1,4 @@ +[] +type R1 = { A : int; B : int } +[] +type R2 = { A : string; ...R1 } diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_SpreadShadowsExplicit.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_SpreadShadowsExplicit.fs.il.bsl new file mode 100644 index 00000000000..df5734beec4 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_SpreadShadowsExplicit.fs.il.bsl @@ -0,0 +1,217 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable sealed nested public R1 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.DefaultAugmentationAttribute::.ctor(bool) = ( 01 00 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly int32 A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly int32 B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname instance int32 get_A() 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: ldfld int32 assembly/R1::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance int32 get_B() 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: ldfld int32 assembly/R1::B@ + IL_0006: ret + } + + .method public specialname rtspecialname instance void .ctor(int32 a, int32 b) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 1D 54 79 70 65 5F 53 70 72 65 + 61 64 53 68 61 64 6F 77 73 45 78 70 6C 69 63 69 + 74 2B 52 31 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld int32 assembly/R1::A@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld int32 assembly/R1::B@ + IL_0014: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/R1>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .property instance int32 A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance int32 assembly/R1::get_A() + } + .property instance int32 B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance int32 assembly/R1::get_B() + } + } + + .class auto ansi serializable sealed nested public R2 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.DefaultAugmentationAttribute::.ctor(bool) = ( 01 00 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly int32 A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly int32 B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname instance int32 get_A() 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: ldfld int32 assembly/R2::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance int32 get_B() 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: ldfld int32 assembly/R2::B@ + IL_0006: ret + } + + .method public specialname rtspecialname instance void .ctor(int32 a, int32 b) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 1D 54 79 70 65 5F 53 70 72 65 + 61 64 53 68 61 64 6F 77 73 45 78 70 6C 69 63 69 + 74 2B 52 32 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld int32 assembly/R2::A@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld int32 assembly/R2::B@ + IL_0014: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/R2>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .property instance int32 A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance int32 assembly/R2::get_A() + } + .property instance int32 B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance int32 assembly/R2::get_B() + } + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_SpreadShadowsSpread.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_SpreadShadowsSpread.fs new file mode 100644 index 00000000000..e4d65018f9e --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_SpreadShadowsSpread.fs @@ -0,0 +1,8 @@ +[] +type R1 = { A : int; B : int } +[] +type R2 = { A : string } +[] +type R3 = { ...R1; ...R2 } +[] +type R4 = { ...R2; ...R1 } diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_SpreadShadowsSpread.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_SpreadShadowsSpread.fs.il.bsl new file mode 100644 index 00000000000..6e925ff053d --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Spreads/Type_SpreadShadowsSpread.fs.il.bsl @@ -0,0 +1,356 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable sealed nested public R1 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.DefaultAugmentationAttribute::.ctor(bool) = ( 01 00 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly int32 A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly int32 B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname instance int32 get_A() 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: ldfld int32 assembly/R1::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance int32 get_B() 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: ldfld int32 assembly/R1::B@ + IL_0006: ret + } + + .method public specialname rtspecialname instance void .ctor(int32 a, int32 b) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 1B 54 79 70 65 5F 53 70 72 65 + 61 64 53 68 61 64 6F 77 73 53 70 72 65 61 64 2B + 52 31 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld int32 assembly/R1::A@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld int32 assembly/R1::B@ + IL_0014: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/R1>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .property instance int32 A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance int32 assembly/R1::get_A() + } + .property instance int32 B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance int32 assembly/R1::get_B() + } + } + + .class auto ansi serializable sealed nested public R2 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.DefaultAugmentationAttribute::.ctor(bool) = ( 01 00 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly string A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname instance string get_A() 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: ldfld string assembly/R2::A@ + IL_0006: ret + } + + .method public specialname rtspecialname instance void .ctor(string a) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 1B 54 79 70 65 5F 53 70 72 65 + 61 64 53 68 61 64 6F 77 73 53 70 72 65 61 64 2B + 52 32 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld string assembly/R2::A@ + IL_000d: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/R2>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .property instance string A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance string assembly/R2::get_A() + } + } + + .class auto ansi serializable sealed nested public R3 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.DefaultAugmentationAttribute::.ctor(bool) = ( 01 00 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly int32 B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly string A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname instance int32 get_B() 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: ldfld int32 assembly/R3::B@ + IL_0006: ret + } + + .method public hidebysig specialname instance string get_A() 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: ldfld string assembly/R3::A@ + IL_0006: ret + } + + .method public specialname rtspecialname instance void .ctor(int32 b, string a) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 1B 54 79 70 65 5F 53 70 72 65 + 61 64 53 68 61 64 6F 77 73 53 70 72 65 61 64 2B + 52 33 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld int32 assembly/R3::B@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld string assembly/R3::A@ + IL_0014: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/R3>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .property instance int32 B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance int32 assembly/R3::get_B() + } + .property instance string A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance string assembly/R3::get_A() + } + } + + .class auto ansi serializable sealed nested public R4 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.DefaultAugmentationAttribute::.ctor(bool) = ( 01 00 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly int32 A@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field assembly int32 B@ + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname instance int32 get_A() 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: ldfld int32 assembly/R4::A@ + IL_0006: ret + } + + .method public hidebysig specialname instance int32 get_B() 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: ldfld int32 assembly/R4::B@ + IL_0006: ret + } + + .method public specialname rtspecialname instance void .ctor(int32 a, int32 b) cil managed + { + .custom instance void [runtime]System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute::.ctor(valuetype [runtime]System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes, + class [runtime]System.Type) = ( 01 00 60 06 00 00 1B 54 79 70 65 5F 53 70 72 65 + 61 64 53 68 61 64 6F 77 73 53 70 72 65 61 64 2B + 52 34 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld int32 assembly/R4::A@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld int32 assembly/R4::B@ + IL_0014: ret + } + + .method public strict virtual instance string ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class assembly/R4>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } + + .property instance int32 A() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance int32 assembly/R4::get_A() + } + .property instance int32 B() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .get instance int32 assembly/R4::get_B() + } + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj index a4589a97a2b..e50201ba8f9 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj +++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj @@ -170,6 +170,7 @@ + @@ -288,6 +289,9 @@ + + + @@ -389,6 +393,7 @@ + diff --git a/tests/FSharp.Compiler.ComponentTests/Language/CopyAndUpdateTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/CopyAndUpdateTests.fs index 94b4571afbb..872d8129b9b 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/CopyAndUpdateTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/CopyAndUpdateTests.fs @@ -1,4 +1,4 @@ -module Language.CopyAndUpdateTests +module Language.CopyAndUpdateTests open Xunit open FSharp.Test.Compiler @@ -17,7 +17,7 @@ let t2 x = { x with D.B = "a"; D.B = "b" } |> typecheck |> shouldFail |> withDiagnostics [ - (Error 668, Line 6, Col 23, Line 6, Col 24, "The field 'B' appears multiple times in this record expression or pattern") + Error 668, Line 6, Col 34, Line 6, Col 41, "The field 'B' appears multiple times in this record expression or pattern" ] [] @@ -32,8 +32,8 @@ let t2 x = { x with D.B = "a"; D.B = "b"; D.B = "c" } |> typecheck |> shouldFail |> withDiagnostics [ - (Error 668, Line 6, Col 23, Line 6, Col 24, "The field 'B' appears multiple times in this record expression or pattern") - (Error 668, Line 6, Col 34, Line 6, Col 35, "The field 'B' appears multiple times in this record expression or pattern") + Error 668, Line 6, Col 34, Line 6, Col 41, "The field 'B' appears multiple times in this record expression or pattern" + Error 668, Line 6, Col 45, Line 6, Col 52, "The field 'B' appears multiple times in this record expression or pattern" ] [] @@ -48,8 +48,8 @@ let t2 x = { x with D.B = "a"; D.C = ""; D.B = "c" ; D.C = "d" } |> typecheck |> shouldFail |> withDiagnostics [ - (Error 668, Line 6, Col 34, Line 6, Col 35, "The field 'C' appears multiple times in this record expression or pattern") - (Error 668, Line 6, Col 23, Line 6, Col 24, "The field 'B' appears multiple times in this record expression or pattern") + Error 668, Line 6, Col 44, Line 6, Col 51, "The field 'B' appears multiple times in this record expression or pattern" + Error 668, Line 6, Col 56, Line 6, Col 63, "The field 'C' appears multiple times in this record expression or pattern" ] [] diff --git a/tests/FSharp.Compiler.ComponentTests/Language/RecordSpreadsTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/RecordSpreadsTests.fs new file mode 100644 index 00000000000..e554e9c5e2e --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/RecordSpreadsTests.fs @@ -0,0 +1,2609 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +module Language.RecordSpreadsTests + +open FSharp.Test.Compiler +open Xunit + +module NominalAndAnonymousRecords = + let [] SupportedLangVersion = "preview" + + module LangVersion = + [] + let ``10 → error`` () = + let src = + """ + type R1 = { A : int; B : int } + type R2 = { ...R1; C : int } + let r1 = { A = 1; B = 2 } + let r2 = { ...r1; C = 3 } + """ + + FSharp src + |> withLangVersion10 + |> typecheck + |> shouldFail + |> withDiagnostics [ + Error 3350, Line 3, Col 29, Line 3, Col 34, "Feature 'record type and expression spreads' is not available in F# 10.0. Please use language version 'PREVIEW' or greater." + Error 3350, Line 5, Col 28, Line 5, Col 33, "Feature 'record type and expression spreads' is not available in F# 10.0. Please use language version 'PREVIEW' or greater." + ] + + [] + let ``> 10 → success`` () = + let src = + """ + type R1 = { A : int; B : int } + type R2 = { ...R1; C : int } + let r1 = { A = 1; B = 2 } + let r2 = { ...r1; C = 3 } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldSucceed + + module Parsing = + [] + let ``{...} → error`` () = + let src = + """ + type R1 = { A : int; B : int } + type R2 = { ... } + let r1 : R1 = { ... } + let r2 = {| ... |} + let r1' : R1 = { r1 with ... } + let r2' = {| r1 with ... |} + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withDiagnostics [ + Error 3900, Line 3, Col 29, Line 3, Col 32, "Missing spread source type after '...'." + Error 3899, Line 4, Col 33, Line 4, Col 36, "Missing spread source expression after '...'." + Error 3899, Line 5, Col 29, Line 5, Col 32, "Missing spread source expression after '...'." + Error 3899, Line 6, Col 42, Line 6, Col 45, "Missing spread source expression after '...'." + Error 3899, Line 7, Col 38, Line 7, Col 41, "Missing spread source expression after '...'." + ] + + [] + let ``{ ...r with } → error`` () = + let src = + """ + type R = { A : int; B : int } + let r1 = { A = 1; B = 2 } + let r2 = { ...r1 with A = 3 } + let r3 = {| ...r1 with A = 3 |} + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withDiagnostics [ + Error 3903, Line 4, Col 28, Line 4, Col 31, "Spreading is not supported in this position. Use one of the forms { ...expr1; A = expr2 } or { expr1 with A = expr2 } instead." + Error 3903, Line 5, Col 29, Line 5, Col 32, "Spreading is not supported in this position. Use one of the forms { ...expr1; A = expr2 } or { expr1 with A = expr2 } instead." + ] + + [] + let ``seq {...} → error`` () = + let src = + """ + let xs = [1..10] + let _ = seq { ... } + let _ = seq { ...xs } + let _ = seq { ...xs; ...xs } + let _ = seq { ...xs; 1 } + let _ = seq { 1; ...xs } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withDiagnostics [ + Error 3899, Line 3, Col 31, Line 3, Col 34, "Missing spread source expression after '...'." + // This is because the sequence expression body is being parsed as a record. + // If we add support for spreads in sequence expressions, we will need to update record parsing. + Error 10, Line 6, Col 38, Line 6, Col 39, "Unexpected integer literal in expression. Expected '}' or other token." + Error 604, Line 6, Col 29, Line 6, Col 30, "Unmatched '{'" + Error 3902, Line 7, Col 34, Line 7, Col 37, "Spreading is not supported in this construct." + ] + + [] + let ``custom {...} → error`` () = + let src = + """ + type Custom () = + member _.Zero () = [] + member _.Yield x = [x] + member _.YieldFrom xs = xs + member _.Combine (xs, ys) = xs @ ys + member _.Delay f = f () + + let custom = Custom () + + let xs = [1..10] + let _ = custom { ... } + let _ = custom { ...xs } + let _ = custom { ...xs; ...xs } + let _ = custom { ...xs; 1 } + let _ = custom { 1; ...xs } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withDiagnostics [ + Error 3899, Line 12, Col 34, Line 12, Col 37, "Missing spread source expression after '...'." + // This is because the computation body is being parsed as a record. + // If we add support for spreads in custom computation expressions, we will need to update record parsing. + Error 10, Line 15, Col 41, Line 15, Col 42, "Unexpected integer literal in expression. Expected '}' or other token." + Error 604, Line 15, Col 32, Line 15, Col 33, "Unmatched '{'" + Error 3902, Line 16, Col 37, Line 16, Col 40, "Spreading is not supported in this construct." + ] + + [] + let ``[ ... ] → error`` () = + let src = + """ + let xs = [1..10] + let _ = [ ... ] + let _ = [ ...xs ] + let _ = [ ...xs; ...xs ] + let _ = [ ...xs; 1 ] + let _ = [ 1; ...xs ] + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withDiagnostics [ + Error 3902, Line 3, Col 27, Line 3, Col 30, "Spreading is not supported in this construct." + Error 3902, Line 4, Col 27, Line 4, Col 30, "Spreading is not supported in this construct." + Error 3902, Line 5, Col 27, Line 5, Col 30, "Spreading is not supported in this construct." + Error 3902, Line 5, Col 34, Line 5, Col 37, "Spreading is not supported in this construct." + Error 3902, Line 6, Col 27, Line 6, Col 30, "Spreading is not supported in this construct." + Error 3902, Line 7, Col 30, Line 7, Col 33, "Spreading is not supported in this construct." + ] + + [] + let ``[| ... |] → error`` () = + let src = + """ + let xs = [1..10] + let _ = [| ... |] + let _ = [| ...xs |] + let _ = [| ...xs; ...xs |] + let _ = [| ...xs; 1 |] + let _ = [| 1; ...xs |] + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withDiagnostics [ + Error 3902, Line 3, Col 28, Line 3, Col 31, "Spreading is not supported in this construct." + Error 3902, Line 4, Col 28, Line 4, Col 31, "Spreading is not supported in this construct." + Error 3902, Line 5, Col 28, Line 5, Col 31, "Spreading is not supported in this construct." + Error 3902, Line 5, Col 35, Line 5, Col 38, "Spreading is not supported in this construct." + Error 3902, Line 6, Col 28, Line 6, Col 31, "Spreading is not supported in this construct." + Error 3902, Line 7, Col 31, Line 7, Col 34, "Spreading is not supported in this construct." + ] + + // Spreads in anonymous record _types_ are not currently supported. + // This does differ from nominal record type definitions, + // but the added complexity to suport them here does not seem worthwhile. + [] + let ``Spread in anonymous record type → error`` () = + let src = + """ + type NominalRecordTy = { A : int } + type AnonymousRecordTy = {| A : int |} + + type Alias1 = {| ...NominalRecordTy |} + type Alias2 = {| ...AnonymousRecordTy |} + + let f (x : {| ...NominalRecordTy |}) = () + let g (x : {| ...AnonymousRecordTy |}) = () + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withDiagnostics [ + Error 3244, Line 5, Col 31, Line 5, Col 55, "Invalid anonymous record type" + Error 3244, Line 6, Col 31, Line 6, Col 57, "Invalid anonymous record type" + Error 3244, Line 8, Col 28, Line 8, Col 52, "Invalid anonymous record type" + Error 3244, Line 9, Col 28, Line 9, Col 54, "Invalid anonymous record type" + ] + + [] + let ``new () = { ... } → error`` () = + let src = + """ + type R = { X : int } + let r = { X = 1 } + type C = + val X : int + new () = { ...r } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withDiagnostics [ + Error 3902, Line 6, Col 32, Line 6, Col 35, "Spreading is not supported in this construct." + ] + + module RecordTypeSpreads = + module Algebra = + /// No overlap, spread ⊕ field. + [] + let ``{...{A,B},C} = {A,B} ⊕ {C} = {A,B,C}`` () = + let src = + """ + type R1 = { A : int; B : int } + type R2 = { ...R1; C : int } + + let _ : R2 = { A = 1; B = 2; C = 3 } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldSucceed + + /// No overlap, spread from anonymous record ⊕ field. + [] + let ``{...{|A,B|},C} = {A,B} ⊕ {C} = {A,B,C}`` () = + let src = + """ + type R2 = { ...{| A : int; B : int |}; C : int } + + let _ : R2 = { A = 1; B = 2; C = 3 } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldSucceed + + /// No overlap, field ⊕ spread. + [] + let ``{A,...{B,C}} = {A} ⊕ {B,C} = {A,B,C}`` () = + let src = + """ + type R1 = { B : int; C : int } + type R2 = { A : int; ...R1 } + + let _ : R2 = { A = 1; B = 2; C = 3 } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldSucceed + + /// No overlap, spread ⊕ spread. + [] + let ``{...{A,B},...{C,D}} = {A,B} ⊕ {C,D} = {A,B,C,D}`` () = + let src = + """ + type R1 = { A : int; B : int } + type R2 = { C : int; D : int } + type R3 = { ...R1; ...R2 } + + let _ : R3 = { A = 1; B = 2; C = 3; D = 4 } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldSucceed + + /// Rightward explicit duplicate field shadows field from spread. + [] + let ``{...{A₀,B},A₁} = {A₀,B} ⊕ {A₁} = {A₁,B,C}`` () = + let src = + """ + type R1 = { A : int; B : int } + type R2 = { ...R1; A : string } + + let _ : R2 = { A = "1"; B = 2 } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldSucceed + + /// Rightward spread field shadows leftward spread field. + [] + let ``{...{A₀,B},...{A₁}} = {A₀,B} ⊕ {A₁} = {A₁,B,C}`` () = + let src = + """ + type R1 = { A : int; B : int } + type R2 = { A : string } + type R3 = { ...R1; ...R2 } + type R4 = { ...R2; ...R1 } + + let _ : R3 = { A = "1"; B = 2 } + let _ : R4 = { A = 1; B = 2 } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldSucceed + + /// Rightward spread field shadows leftward explicit field with warning. + [] + let ``{A₀,...{A₁,B}} = {A₀} ⊕ {A₁,B} = {A₁_warn,B,C}`` () = + let src = + """ + type R1 = { A : int; B : int } + type R2 = { A : string; ...R1 } + + let _ : R2 = { A = 1; B = 2 } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Warning 3897, Line 3, Col 45, Line 3, Col 50, "Spread field 'A: int' from type 'R1' shadows an explicitly declared field with the same name.") + + /// Explicit duplicate fields remain disallowed. + [] + let ``{A₀,...{A₁,B},A₂} = {A₀} ⊕ {A₁,B} ⊕ {A₂} = {A₁_warn,B,A₂_error}`` () = + let src = + """ + type R1 = { A : int; B : int } + type R2 = { A : string; ...R1; A : float } + + let _ : R2 = { A = 1; B = 2 } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withDiagnostics [ + Warning 3897, Line 3, Col 45, Line 3, Col 50, "Spread field 'A: int' from type 'R1' shadows an explicitly declared field with the same name." + Error 37, Line 3, Col 52, Line 3, Col 53, "Duplicate definition of field 'A'" + ] + + [] + let ``No dupes allowed, multiple`` () = + let src = + """ + type R1 = { A : int; B : string } + type R2 = { A : decimal } + type R3 = { ...R2; A : string; ...R1; A : float } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withDiagnostics [ + Warning 3897, Line 4, Col 52, Line 4, Col 57, "Spread field 'A: int' from type 'R1' shadows an explicitly declared field with the same name." + Error 37, Line 4, Col 59, Line 4, Col 60, "Duplicate definition of field 'A'" + ] + + module Accessibility = + /// Fields should have the accessibility of the target type. + /// A spread from less to more accessible is valid as long as the less accessible + /// fields are accessible at the point of the spread. + [] + let ``Accessibility comes from target`` () = + let src = + """ + open System.Reflection + + module A = + type R = internal { A : int; B : int } + + module B = + type T = { ...A.R } + + let (|PropName|) (prop : PropertyInfo) = prop.Name + + match typeof.GetProperties() with + | [|PropName "A"; PropName "B"|] -> () + | unexpected -> failwith $"Expected B.T to have public properties \"A\" and \"B\" but got %A{unexpected}." + """ + + Fsx src + |> withLangVersion SupportedLangVersion + |> compileExeAndRun + |> shouldSucceed + + module Mutability = + [] + let ``Mutability is brought over`` () = + let src = + """ + type R1 = { A : int; mutable B : string } + type R2 = { ...R1 } + + let r2 : R2 = { A = 1; B = "3" } + r2.B <- "99" + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldSucceed + + module GenericTypeParameters = + [] + let ``Single type parameter, inferred at usage`` () = + let src = + """ + type R1<'a> = { A : 'a; B : string } + type R2<'a> = { X : 'a; Y : string } + type R3<'a> = { ...R1<'a>; ...R2<'a> } + + let _ : R3<_> = { A = 3; B = "lol"; X = 4; Y = "haha" } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldSucceed + + [] + let ``Single type parameter, inconsistent instantiation disallowed`` () = + let src = + """ + type R1<'a> = { A : 'a } + type R2<'a> = { B : 'a } + type R3<'a> = { ...R1<'a>; ...R2<'a> } + + let _ : R3 = { A = 3; B = "lol" } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withDiagnostics [ + Error 1, Line 6, Col 52, Line 6, Col 57, "This expression was expected to have type +'int' +but here has type +'string' " + ] + + [] + let ``Single type parameter, annotated at usage`` () = + let src = + """ + type R1<'a> = { A : 'a; B : string } + type R2<'a> = { X : 'a; Y : string } + type R3<'a> = { ...R1<'a>; ...R2<'a> } + + let _ : R3 = { A = 3; B = "lol"; X = 4; Y = "haha" } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldSucceed + + [] + let ``Multiple type parameters`` () = + let src = + """ + type R1<'a> = { A : 'a; B : string } + type R2<'a> = { X : 'a; Y : string } + type R3<'a, 'b> = { ...R1<'a>; ...R2<'b> } + + let _ : R3<_, _> = { A = 3; B = "lol"; X = 3.14; Y = "haha" } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldSucceed + + [] + let ``'a → 'a list`` () = + let src = + """ + type R1<'a> = { A : 'a } + type R2<'a> = { ...R1<'a list> } + + let _ : R2 = { A = [3] } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldSucceed + + [] + let ``Single type parameter, not in scope, not allowed`` () = + let src = + """ + type R1<'a> = { A : 'a; B : string } + type R2<'a> = { X : 'a; Y : string } + type R3<'a> = { ...R1<'a>; ...R2<'b> } + type R4 = { ...R1<'a>; ...R2<'b> } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withDiagnostics [ + Error 39, Line 4, Col 54, Line 4, Col 56, "The type parameter 'b is not defined." + Error 39, Line 5, Col 39, Line 5, Col 41, "The type parameter 'a is not defined." + Error 39, Line 5, Col 50, Line 5, Col 52, "The type parameter 'b is not defined." + ] + + /// Akin to: + /// + /// type R1<[] 'a> = { A : int<'a> } + /// type R2<'a> = { X : R1<'a> } + [] + let ``Measure attribute on source, required on spread destination`` () = + let src = + """ + type R1<[] 'a> = { A : int<'a> } + type R2<'a> = { ...R1<'a> } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 702, Line 3, Col 43, Line 3, Col 45, "Expected unit-of-measure parameter, not type parameter. Explicit unit-of-measure parameters must be marked with the [] attribute.") + + [] + let ``Measure attribute on source, measure on spread destination, OK`` () = + let src = + """ + type R1<[] 'a> = { A : int<'a> } + type R2<[] 'b> = { ...R1<'b> } + + type [] m + type R3 = { ...R1 } + + let _ : R1 = { A = 3 } + let _ : R2 = { A = 3 } + let _ : R3 = { A = 3 } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldSucceed + + /// Akin to: + /// + /// type R1<'a when 'a : comparison> = { A : 'a } + /// type R2<'a> = { X : R1<'a> } + [] + let ``Constraint on source, required on spread destination`` () = + let src = + """ + type R1<'a when 'a : comparison> = { A : 'a } + type R2<'a> = { ...R1<'a> } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 1, Line 3, Col 40, Line 3, Col 46, "A type parameter is missing a constraint 'when 'a: comparison'") + + [] + let ``Constraint on source, required on spread destination, error if not compatible at usage`` () = + let src = + """ + type R1<'a when 'a : comparison> = { A : 'a list } + type R2<'a when 'a : comparison> = { ...R1<'a> } + + let _ : R2<_> = { A = [obj ()] } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 193, Line 5, Col 44, Line 5, Col 50, "The type 'obj' does not support the 'comparison' constraint. For example, it does not support the 'System.IComparable' interface") + + [] + let ``Constraint on source, constraint on spread destination, compatible at usage, OK`` () = + let src = + """ + type R1<'a when 'a : comparison> = { A : 'a } + type R2<'a when 'a : comparison> = { ...R1<'a> } + type R3<'a when 'a : comparison> = { ...R1<'a list> } + + let _ : R1 = { A = 3 } + let _ : R2 = { A = 3 } + let _ : R3 = { A = [3] } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldSucceed + + module NonRecordSource = + [] + let ``{...class} → error`` () = + let src = + """ + type C () = + member _.A = 1 + member _.B = 2 + + type R = { ...C } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3891, Line 6, Col 32, Line 6, Col 36, "The source type of a spread into a record type definition must itself be a nominal or anonymous record type.") + + [] + let ``{...abstract_class} → error`` () = + let src = + """ + [] + type C () = + abstract A : int + default _.A = 1 + abstract B : int + default _.B = 2 + + type R = { ...C } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3891, Line 9, Col 32, Line 9, Col 36, "The source type of a spread into a record type definition must itself be a nominal or anonymous record type.") + + [] + let ``{...struct} → error`` () = + let src = + """ + [] + type S = + member _.A = 1 + member _.B = 2 + + type R = { ...S } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3891, Line 7, Col 32, Line 7, Col 36, "The source type of a spread into a record type definition must itself be a nominal or anonymous record type.") + + [] + let ``{...interface} → error`` () = + let src = + """ + type IFace = + abstract A : int + abstract B : int + + type R = { ...IFace } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3891, Line 6, Col 32, Line 6, Col 40, "The source type of a spread into a record type definition must itself be a nominal or anonymous record type.") + + [] + let ``{...int} → error`` () = + let src = + """ + type R = { ...int } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3891, Line 2, Col 32, Line 2, Col 38, "The source type of a spread into a record type definition must itself be a nominal or anonymous record type.") + + [] + let ``{...(int -> int)} → error`` () = + let src = + """ + type R = { ...(int -> int) } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3891, Line 2, Col 32, Line 2, Col 47, "The source type of a spread into a record type definition must itself be a nominal or anonymous record type.") + + module MembersOtherThanRecordFields = + [] + let ``All members other than record fields are ignored`` () = + let src = + """ + open FSharp.Reflection + + type R1 = + { A : int + B : int } + member this.Lol = this.A + this.B + member _.Ha () = () + static member X = "3" + static member val Y = 42 + static member Q () = () + + [] + module R1Extensions = + type R1 with + member this.Lolol = this.Lol + this.Lol + + type R2 = { ...R1; C : string } + + match + FSharpType.GetRecordFields typeof + |> Array.map _.Name + with + | [|"A"; "B"; "C"|] -> () + | unexpected -> failwith $"Expected R2 to have fields [|\"A\"; \"B\"|] but found %A{unexpected}." + """ + + Fsx src + |> withLangVersion SupportedLangVersion + |> compileExeAndRun + |> shouldSucceed + + module Recursion = + [] + let ``Simple mutually recursive type spreads → one error each`` () = + let src = + """ + module M + + type A = { ...B } + and B = { ...A } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> compile + |> shouldFail + |> withDiagnostics [ + Error 3901, Line 4, Col 26, Line 4, Col 27, "This type definition involves a cyclic reference through a spread." + Error 3901, Line 5, Col 26, Line 5, Col 27, "This type definition involves a cyclic reference through a spread." + ] + + [] + let ``Mutually recursive type spreads → error`` () = + let src = + """ + type R = { A : int; ...S; B : int } + and S = { C : int; ...R; D : int } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withDiagnostics [ + Error 3901, Line 2, Col 26, Line 2, Col 27, "This type definition involves a cyclic reference through a spread." + Error 3901, Line 3, Col 26, Line 3, Col 27, "This type definition involves a cyclic reference through a spread." + Warning 3897, Line 2, Col 41, Line 2, Col 45, "Spread field 'A: int' from type 'S' shadows an explicitly declared field with the same name." + ] + + [] + let ``Mutually recursive type spreads with some indirection → error`` () = + let src = + """ + type R = { A : int; ...S } + and S = { B : int; ...T } + and T = { C : int; ...U } + and U = { D : int; ...R } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withDiagnostics [ + Error 3901, Line 2, Col 26, Line 2, Col 27, "This type definition involves a cyclic reference through a spread." + Error 3901, Line 3, Col 26, Line 3, Col 27, "This type definition involves a cyclic reference through a spread." + Error 3901, Line 4, Col 26, Line 4, Col 27, "This type definition involves a cyclic reference through a spread." + Error 3901, Line 5, Col 26, Line 5, Col 27, "This type definition involves a cyclic reference through a spread." + Warning 3897, Line 2, Col 41, Line 2, Col 45, "Spread field 'A: int' from type 'S' shadows an explicitly declared field with the same name." + ] + + [] + let ``Mutually recursive type spreads in recursive module → error`` () = + let src = + """ + module rec M + + type R = { A : int; ...S; B : int } + type S = { C : int; ...R; D : int } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withDiagnostics [ + Error 3901, Line 4, Col 26, Line 4, Col 27, "This type definition involves a cyclic reference through a spread." + Error 3901, Line 5, Col 26, Line 5, Col 27, "This type definition involves a cyclic reference through a spread." + Warning 3897, Line 4, Col 41, Line 4, Col 45, "Spread field 'A: int' from type 'S' shadows an explicitly declared field with the same name." + ] + + [] + let ``Complex mutually recursive type spreads → error`` () = + let src = + """ + module rec M + + [] + module N = + type R = { A : int; ...O.S } + + module O = + type S = { B : int; ...T } + + type T = { C : int; ...U } + + [] + module P = + [] + module Q = + type U = { D : int; ...R } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withDiagnostics [ + Error 3901, Line 6, Col 30, Line 6, Col 31, "This type definition involves a cyclic reference through a spread." + Error 3901, Line 9, Col 34, Line 9, Col 35, "This type definition involves a cyclic reference through a spread." + Error 3901, Line 11, Col 26, Line 11, Col 27, "This type definition involves a cyclic reference through a spread." + Error 3901, Line 17, Col 34, Line 17, Col 35, "This type definition involves a cyclic reference through a spread." + Warning 3897, Line 6, Col 45, Line 6, Col 51, "Spread field 'A: int' from type 'O.S' shadows an explicitly declared field with the same name." + ] + + [] + let ``Mutually recursive type defns with spreads, no cycles → success`` () = + let src = + """ + module M = + type R = { α : int } + and S = { β : int } + and T = { γ : int } + and U = { δ : int } + + type R = { A : int; ...M.S } + and S = { B : int; ...M.T } + and T = { C : int; ...M.U } + and U = { D : int; ...M.R } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldSucceed + + [] + let ``Mutually recursive type defns with spreads, reverse order → success`` () = + let src = + """ + module M + + type R = { ...S } + and S = { α : int; β : int; } + + let r : R = { α = 1; β = 2 } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldSucceed + + [] + let ``Mutually recursive type defns with spreads, reverse order, transitive → success`` () = + let src = + """ + module M + + type R = { ...S } + and S = { ...T } + and T = { α : int; β : int; } + + let r : R = { α = 1; β = 2 } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldSucceed + + [] + let ``Mutually recursive generic type defns with spreads, reverse order, transitive → success`` () = + let src = + """ + module M + + type R<'T> = { ...S<'T> } + and S<'T> = { ...T<'T> } + and T<'T> = { α : 'T; β : 'T; } + + let r : R = { α = 1; β = 2 } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldSucceed + + [] + let ``Mutually recursive type defns with spreads, reverse order, more complicated → success`` () = + let src = + """ + module M + + type R = { α : int; ...S; δ : int } + and S = { β : int; γ : int } + + let r : R = { α = 1; β = 2; γ = 3; δ = 4 } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldSucceed + + [] + let ``Mutually recursive type defns with spreads, errors → not duplicated`` () = + let src = + """ + module M + + type R = { α : int; ...S; δ : int; δ : int } + and S = { α : int; β : int; γ : int } + + let r : R = { α = 1; β = 2; γ = 3; δ = 4 } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withDiagnostics [ + Error 37, Line 4, Col 56, Line 4, Col 57, "Duplicate definition of field 'δ'" + Warning 3897, Line 4, Col 41, Line 4, Col 45, "Spread field 'α: int' from type 'S' shadows an explicitly declared field with the same name." + ] + + module Nullability = + [] + let ``Can't spread from a nullable type`` () = + let src = + """ + type R1 = { A : int } + type R2 = { ...(R1 | null) } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> withCheckNulls + |> typecheck + |> shouldFail + |> withDiagnostics [ + Error 3892, Line 3, Col 33, Line 3, Col 47, "The source type of a spread into a record type definition cannot be nullable." + ] + + module Signatures = + [] + let ``Can use spreads in signatures`` () = + let src = + """ + type R1 = { A : int } + type R2 = { ...R1; B : int } + type R3 = {| A : int |} + type R4 = { ...R1; B : int } + """ + + Fsi src + |> withLangVersion SupportedLangVersion + |> withCheckNulls + |> typecheck + |> shouldSucceed + + module Structness = + [] + let ``Structness depends only on the target type`` () = + let src = + """ + type [] R1 = { A : int } + type R2 = { ...R1 } + type R3 = { A : int } + type [] R4 = { ...R3 } + + if typeof.IsValueType then + failwith "R2 should not be a struct type because it is not explicitly annotated as such." + + if not typeof.IsValueType then + failwith "R4 should be a struct type because it is explicitly annotated as such." + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> compileExeAndRun + |> shouldSucceed + + module AnonymousRecordExpressionSpreads = + module Algebra = + /// No overlap, spread ⊕ field. + [] + let ``{...{A,B},C} = {A,B} ⊕ {C} = {A,B,C}`` () = + let src = + """ + let r1 = {| A = 1; B = 2 |} + + let r2 : {| A : int ; B : int; C : int |} = {| ...r1; C = 3 |} + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldSucceed + + /// No overlap, field ⊕ spread. + [] + let ``{A,...{B,C}} = {A} ⊕ {B,C} = {A,B,C}`` () = + let src = + """ + let r1 = {| A = 1; B = 2 |} + + let r2 : {| A : int ; B : int; C : int |} = {| C = 3; ...r1 |} + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldSucceed + + /// No overlap, spread ⊕ spread. + [] + let ``{...{A,B},...{C,D}} = {A,B} ⊕ {C,D} = {A,B,C,D}`` () = + let src = + """ + let r1 = {| A = 1 ; B = 2 |} + let r2 = {| C = 3; D = 4 |} + + let r3 : {| A : int ; B : int; C : int; D : int |} = {| ...r1; ...r2 |} + let r4 : {| A : int ; B : int; C : int; D : int |} = {| ...r2; ...r3 |} + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldSucceed + + /// Rightward explicit duplicate field shadows field from spread. + [] + let ``{...{A₀,B},A₁} = {A₀,B} ⊕ {A₁} = {A₁,B,C}`` () = + let src = + """ + let r1 = {| A = 1; B = 2 |} + + let r2 : {| A : string; B : int |} = {| ...r1; A = "A" |} + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldSucceed + + /// Rightward spread field shadows leftward spread field. + [] + let ``{...{A₀,B},...{A₁}} = {A₀,B} ⊕ {A₁} = {A₁,B,C}`` () = + let src = + """ + let r1 = {| A = 1; B = 2 |} + let r2 = {| A = "A" |} + + let r3 : {| A : string; B : int |} = {| ...r1; ...r2 |} + let r4 : {| A : int; B : int |} = {| ...r2; ...r1 |} + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldSucceed + + /// Rightward spread field shadows leftward explicit field with warning. + [] + let ``{A₀,...{A₁,B}} = {A₀} ⊕ {A₁,B} = {A₁_warn,B,C}`` () = + let src = + """ + let r1 = {| A = 1; B = 2 |} + + let r2 : {| A : int; B : int |} = {| A = "A"; ...r1 |} + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withDiagnostics [ + Warning 3898, Line 4, Col 67, Line 4, Col 72, "Spread field 'A: int' shadows an explicitly declared field with the same name." + ] + + /// Explicit duplicate fields remain disallowed. + [] + let ``{A₀,...{A₁,B},A₂} = {A₀} ⊕ {A₁,B} ⊕ {A₂} = {A₁_warn,B,A₂_error}`` () = + let src = + """ + let r1 = {| A = 1; B = 2 |} + + let r2 = {| A = "A"; ...r1; A = 3.14 |} + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withDiagnostics [ + Warning 3898, Line 4, Col 42, Line 4, Col 47, "Spread field 'A: int' shadows an explicitly declared field with the same name." + Error 3522, Line 4, Col 49, Line 4, Col 57, "The field 'A' appears multiple times in this record expression." + ] + + [] + let ``No dupes allowed, multiple`` () = + let src = + """ + let r1 = {| A = 1; B = "B" |} + let r2 = {| A = 3m |} + + let r3 = {| ...r2; A = "A"; ...r1; A = 3.14 |} + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withDiagnostics [ + Warning 3898, Line 5, Col 49, Line 5, Col 54, "Spread field 'A: int' shadows an explicitly declared field with the same name." + Error 3522, Line 5, Col 56, Line 5, Col 64, "The field 'A' appears multiple times in this record expression." + ] + + [] + let ``{...{A,B,C}}:{B} = {A,B,C} ∩ {B} = {B}`` () = + let src = + """ + let src = {| A = 1; B = "B"; C = 3m |} + + let typedTarget : {| B : string |} = {| ...src |} + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldSucceed + + [] + let ``{...{}} = ∅ ⊕ ∅ = ∅`` () = + let src = + """ + module M + + let r = {| ...{||} |} + + if r <> {||} then failwith $"Expected {{||}} but got %A{r}." + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> compileExeAndRun + |> shouldSucceed + + module Accessibility = + /// Fields should have the accessibility of the target type. + /// A spread from less to more accessible is valid as long as the less accessible + /// fields are accessible at the point of the spread. + [] + let ``Accessibility comes from target`` () = + let src = + """ + let private r1 = {| A = 1; B = "B" |} + + let public r2 : {| A : int; B : string |} = {| ...r1 |} + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldSucceed + + module Mutability = + [] + let ``Mutability is _not_ brought over`` () = + let src = + """ + type R1 = { A : int; mutable B : string } + let r1 = { A = 1; B = "B" } + + let r2 = {| ...r1 |} + r2.B <- "99" + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withDiagnostics [ + Error 799, Line 6, Col 24, Line 6, Col 25, "Invalid assignment" + ] + + module GenericTypeParameters = + [] + let ``Single type parameter`` () = + let src = + """ + let f (x : 'a) = + let r1 : {| A : 'a; B : string |} = {| A = x; B = "B" |} + let r2 : {| X : 'a; Y : string |} = {| X = x; Y = "Y" |} + + let r3 : {| A : 'a; B : string; X : 'a; Y : string |} = {| ...r1; ...r2 |} + r3 + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldSucceed + + [] + let ``Multiple type parameters`` () = + let src = + """ + let r1 (x : 'a) = {| A = x; B = "B" |} + let r2 (x : 'a) = {| X = x; Y = "Y" |} + + let r3 (x : 'a) (y : 'b) : {| A : 'a; B : string; X : 'b; Y : string |} = {| ...r1 x; ...r2 y |} + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldSucceed + + [] + let ``Measure attribute on source, present on spread destination`` () = + let src = + """ + let r1 (r2 : {| A : int<'m> |}) : {| A : int<'m> |} = {| ...r2 |} + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldSucceed + + [] + let ``Constraints kept`` () = + let src = + """ + let r1<'a when 'a : comparison> (r2 : {| A : 'a |}) : unit -> {| A : 'a |} = fun () -> {| ...r2 |} + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldSucceed + + module NonRecordSource = + [] + let ``{...class} → error`` () = + let src = + """ + type C () = + member _.A = 1 + member _.B = 2 + + let r = {| ...C () |} + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withDiagnostics [ + Error 3895, Line 6, Col 35, Line 6, Col 39, "The source expression of a spread into an anonymous record expression must have a nominal or anonymous record type." + ] + + [] + let ``{...abstract_class} → error`` () = + let src = + """ + [] + type C () = + abstract A : int + abstract B : int + + let r = + {| + ... + { new C () with + member _.A = 1 + member _.B = 2 } + |} + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withDiagnostics [ + Error 3895, Line 10, Col 33, Line 12, Col 53, "The source expression of a spread into an anonymous record expression must have a nominal or anonymous record type." + ] + + [] + let ``{...struct} → error`` () = + let src = + """ + [] + type S = + member _.A = 1 + member _.B = 2 + + let r = {| ...S () |} + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withDiagnostics [ + Error 3895, Line 7, Col 35, Line 7, Col 39, "The source expression of a spread into an anonymous record expression must have a nominal or anonymous record type." + ] + + [] + let ``{...interface} → error`` () = + let src = + """ + type IFace = + abstract A : int + abstract B : int + + let r = + {| + ... + { new IFace with + member _.A = 1 + member _.B = 2 } + |} + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withDiagnostics [ + Error 3895, Line 9, Col 33, Line 11, Col 53, "The source expression of a spread into an anonymous record expression must have a nominal or anonymous record type." + ] + + [] + let ``{...int} → error`` () = + let src = + """ + let r = {| ...0 |} + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withDiagnostics [ + Error 3895, Line 2, Col 35, Line 2, Col 36, "The source expression of a spread into an anonymous record expression must have a nominal or anonymous record type." + ] + + [] + let ``{...(int -> int)} → error`` () = + let src = + """ + let r = {| ...(fun x -> x + 1) |} + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withDiagnostics [ + Error 3895, Line 2, Col 35, Line 2, Col 51, "The source expression of a spread into an anonymous record expression must have a nominal or anonymous record type." + ] + + [] + let ``{...int list} → error`` () = + let src = + """ + let r = {| ...[1..10] |} + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withDiagnostics [ + Error 3895, Line 2, Col 35, Line 2, Col 42, "The source expression of a spread into an anonymous record expression must have a nominal or anonymous record type." + ] + + module MembersOtherThanRecordFields = + [] + let ``Instance properties that are not record fields are ignored`` () = + let src = + """ + type R1 = + { A : int + B : string } + member this.Lol = string this.A + this.B + + type R2 = { ...R1; C : string } + + let r1 = { A = 3; B = "3"; C = "asdf" } + let r2 : {| A : int; B : string; C : string |} = {| ...r1 |} + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldSucceed + + [] + let ``All members other than record fields are ignored`` () = + let src = + """ + type R1 = + { A : int + B : int } + member this.Lol = this.A + this.B + member _.Ha () = () + static member X = "3" + static member val Y = 42 + static member Q () = () + + [] + module R1Extensions = + type R1 with + member this.Lolol = this.Lol + this.Lol + + type R2 = { ...R1; C : string } + + let r2 : R2 = { A = 3; B = 3; C = "asdf" } + let r3 = {| ...r2 |} + + let typeofR3 = r3.GetType () + if typeofR3 <> typeof<{| A : int; B : int; C : string |}> then + failwith $"Expected r3 to have type {{| A : int; B : int; C : string |}} but got {typeofR3.Name}." + """ + + Fsx src + |> withLangVersion SupportedLangVersion + |> compileExeAndRun + |> shouldSucceed + + module Effects = + [] + let ``Effects in spread sources are evaluated exactly once per spread, even if all fields are shadowed`` () = + let src = + """ + let effects = ResizeArray () + let f () = effects.Add "f"; {| A = 0; B = 1 |} + let g () = effects.Add "g"; {| A = 2; B = 3 |} + let h () = effects.Add "h"; {| A = 99 |} + let r = {| ...g (); ...f (); ...g (); ...h (); A = 100 |} + + let expected = {| A = 100; B = 3 |} + if r <> expected then failwith $"Expected %A{expected} but got %A{r}." + match List.ofSeq effects with + | ["g"; "f"; "g"; "h"] -> () + | unexpected -> failwith $"Expected [\"g\"; \"f\"; \"g\"; \"h\"] but got %A{unexpected}." + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> compileExeAndRun + |> shouldSucceed + + module BackCompat = + [] + let ``Inference works the same`` () = + let src = + """ + module M + + let f x y = + if x = y then () + else failwith $"Expected %A{x} = %A{y}." + + do f {| a = 1 - 1 |} {| a = Unchecked.defaultof<_> |} + do f {| a = 1 - 1 |} {| {||} with a = Unchecked.defaultof<_> |} + + #nowarn FS3898 // Spread shadowing explicit. + + let r = {| a = Unchecked.defaultof<_> |} + do f {| a = 1 - 1 |} {| a = "a"; ...r |} + + let _ = + let r = {| a = Unchecked.defaultof<_> |} + f {| a = 1 - 1 |} {| a = "a"; ...r |} + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> compileExeAndRun + |> shouldSucceed + + [] + let ``Inference works the same, again`` () = + let src = + """ + module M + + let f () = + ([], [1]) ||> List.fold (fun acc x -> + let y = + {| + Left = x + Right = 3 + |} + + match acc with + | [] -> [y] + | head :: tail -> {| y with Left = head.Left |} :: tail) + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> compile + |> shouldSucceed + + [] + let ``Name resolution order is the same`` () = + let src = + """ + module M + + type RecordTypeB = + { Name: string + FieldB: int } + + // When the anonymous record expression is encountered, it must commit to "RecordTypeB". + // The return type of "f" is, at that point, a variable type + // and must be correctly inferred by the point where we process the subsequence + // dot-notation "f().Name" + let rec f() = + {| Name = "" + FieldA = f().Name + |} + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> compile + |> shouldSucceed + + module Conversions = + [] + let ``Coercions work as though they were field assignments`` () = + let src = + """ + let r1 = {| A = 3; B = 4 |} + let r2 : {| A : obj; B : obj |} = {| ...r1 |} + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldSucceed + + [] + let ``Implicit conversions work as though they were field assignments`` () = + let src = + """ + [] + type T = + | T of int + static member op_Implicit (T t) = U t + + and [] U = + | U of int + + #nowarn 3391 + + let r1 : {| A : T |} = {| A = T 3 |} + let r2 : {| A : U |} = {| A = T 3 |} + let r2' : {| A : U |} = {| ...r1 |} + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldSucceed + + module Nullability = + [] + let ``Can't spread from a nullable value`` () = + let src = + """ + let r1 : {| A : int |} | null = null + let r2 = {| ...r1 |} + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> withCheckNulls + |> typecheck + |> shouldFail + |> withDiagnostics [ + Error 3260, Line 2, Col 30, Line 2, Col 50, "The type '{| A: int |}' does not support a nullness qualification." + Error 43, Line 2, Col 53, Line 2, Col 57, "The type '{| A: int |}' does not have 'null' as a proper value" + ] + + module Inference = + [] + let ``Unknown source type → error`` () = + let src = + """ + let f x = {| x with B = 2; C = 3 |} + let g x = {| ...x; B = 2; C = 3 |} + let h x : {| A : int; B : int; C : int |} = {| ...x; B = 2; C = 3 |} + """ + + Fsx src + |> withLangVersion SupportedLangVersion + |> compile + |> shouldFail + |> withDiagnostics [ + Error 3245, Line 2, Col 34, Line 2, Col 35, "The input to a copy-and-update expression that creates an anonymous record must be either an anonymous record or a record" + Error 3895, Line 3, Col 37, Line 3, Col 38, "The source expression of a spread into an anonymous record expression must have a nominal or anonymous record type." + Error 3895, Line 4, Col 71, Line 4, Col 72, "The source expression of a spread into an anonymous record expression must have a nominal or anonymous record type." + Error 1, Line 4, Col 65, Line 4, Col 89, "This anonymous record is missing field 'A'." + ] + + module Structness = + [] + let ``Various structness combinations work`` () = + let src = + """ + type RefNominalRecd = { A : int } + type [] StructNominalRecd = { A : int } + + let refAnonRecd = {| A = 1 |} + let structAnonRecd = struct {| A = 1 |} + let refNominalRecd : RefNominalRecd = { A = 1 } + let structNominalRecd : StructNominalRecd = { A = 1 } + + let ``ref anon src, no explicit target, stays ref`` = {| ...refAnonRecd; B = 2 |} + let ``ref anon src, explicit struct target, becomes struct`` = struct {| ...refAnonRecd; B = 2 |} + let ``ref anon src, inferred struct target, becomes struct`` : struct {| A : int; B : int |} = {| ...refAnonRecd; B = 2 |} + let ``struct anon src, no explicit target, stays struct`` = {| ...structAnonRecd; B = 2 |} + let ``struct anon src, explicit struct target, stays struct`` = struct {| ...structAnonRecd; B = 2 |} + let ``struct anon src, inferred struct target, stays struct`` : struct {| A : int; B : int |} = {| ...structAnonRecd; B = 2 |} + + let ``ref nominal src, no explicit target, stays ref`` = {| ...refAnonRecd; B = 2 |} + let ``ref nominal src, explicit struct target, becomes struct`` = struct {| ...refAnonRecd; B = 2 |} + let ``ref nominal src, inferred struct target, becomes struct`` : struct {| A : int; B : int |} = {| ...refAnonRecd; B = 2 |} + let ``struct nominal src, no explicit target, stays struct`` = {| ...structAnonRecd; B = 2 |} + let ``struct nominal src, explicit struct target, stays struct`` = struct {| ...structAnonRecd; B = 2 |} + let ``struct nominal src, inferred struct target, stays struct`` : struct {| A : int; B : int |} = {| ...structAnonRecd; B = 2 |} + """ + + Fsx src + |> withLangVersion SupportedLangVersion + |> compileExeAndRun + |> shouldSucceed + + module NestedUpdates = + [] + let ``Nested update with no preceding spread: error`` () = + let src = + """ + let orig () = {| Nested = {| A = "value1"; B = "value1" |} |} + + let _ = {| Nested.A = "value2"; Nested.B = "value2"; ...orig () |} + """ + + Fsx src + |> withLangVersion SupportedLangVersion + |> compile + |> shouldFail + |> withDiagnostics [ + Error 39, Line 4, Col 32, Line 4, Col 38, "The namespace or module 'Nested' is not defined." + ] + + [] + let ``Nested update with no matching preceding spread: error`` () = + let src = + """ + let orig () = {| Nested = {| A = "value1"; B = "value1" |} |} + + let _ = {| ...orig (); Other.A = "value2" |} + """ + + Fsx src + |> withLangVersion SupportedLangVersion + |> compile + |> shouldFail + |> withDiagnostics [ + Error 39, Line 4, Col 44, Line 4, Col 49, "The namespace or module 'Other' is not defined." + ] + + [] + let ``Nested updates apply to last matching spread: anynonymous to anynonymous`` () = + let src = + """ + let orig1 () = {| Nested = {| A = "value1"; B = "value1" |}; Other = {| A = "value2"; B = "value2" |} |} + let orig2 () = {| Nested = {| A = "value3"; B = "value3" |} |} + + let actual = {| ...orig1 (); Nested.B = "value4"; ...orig2 (); Other.B = "value5" |} + let expected = {| Nested = {| A = "value3"; B = "value3" |}; Other = {| A = "value2"; B = "value5" |} |} + + if actual <> expected then + failwith $"Expected %A{expected} but got %A{actual}." + """ + + Fsx src + |> withLangVersion SupportedLangVersion + |> ignoreWarnings + |> compileExeAndRun + |> shouldSucceed + |> withDiagnostics [ + Warning 3898, Line 5, Col 71, Line 5, Col 82, "Spread field 'Nested: {| A: string; B: string |}' shadows an explicitly declared field with the same name." + ] + + [] + let ``Nested updates apply to last matching spread: nominal to anonymous`` () = + let src = + """ + type NestedRecord = { A : string; B : string } + type OuterRecord1 = { Nested : NestedRecord; Other : NestedRecord } + type OuterRecord2 = { Nested : NestedRecord } + + let orig1 () = { Nested = { A = "value1"; B = "value1" }; Other = { A = "value2"; B = "value2" } } + let orig2 () = { Nested = { A = "value3"; B = "value3" } } + + let actual = {| ...orig1 (); Nested.B = "value4"; ...orig2 (); Other.B = "value5" |} + let expected = {| Nested = { A = "value3"; B = "value3" }; Other = { A = "value2"; B = "value5" } |} + + if actual <> expected then + failwith $"Expected %A{expected} but got %A{actual}." + """ + + Fsx src + |> withLangVersion SupportedLangVersion + |> ignoreWarnings + |> compileExeAndRun + |> shouldSucceed + |> withDiagnostics [ + Warning 3898, Line 9, Col 71, Line 9, Col 82, "Spread field 'Nested: NestedRecord' shadows an explicitly declared field with the same name." + ] + + [] + let ``We assume any qualified field assignment following any spreads to be nested updates`` () = + let src = + """ + let r1 = {| A = {| B = 1; C = {| D = 2 |} |} |} + let r2 = {| ...r1; A.C.D = 3 |} + """ + + Fsx src + |> withLangVersion SupportedLangVersion + |> ignoreWarnings + |> compile + |> shouldSucceed + + [] + let ``Ambiguity in qualified field assignment following spreads doesn't matter when the target type is an anonymous record`` () = + let src = + """ + module A = + type C = { D : int } + + let r1 = {| A = {| B = 1; C = {| D = 2 |} |} |} + let r2 = {| ...r1; A.C.D = 3 |} + """ + + Fsx src + |> withLangVersion SupportedLangVersion + |> ignoreWarnings + |> compile + |> shouldSucceed + + module NominalRecordExpressionSpreads = + module Algebra = + /// No overlap, spread ⊕ field. + [] + let ``{...{A,B},C} = {A,B} ⊕ {C} = {A,B,C}`` () = + let src = + """ + type R1 = { A : int; B : int } + type R2 = { A : int; B : int; C : int } + + let r1 = { A = 1; B = 2 } + let r2 = { ...r1; C = 3 } + + let r1' = {| A = 1; B = 2 |} + let r2' = { ...r1; C = 3 } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldSucceed + + /// No overlap, field ⊕ spread. + [] + let ``{A,...{B,C}} = {A} ⊕ {B,C} = {A,B,C}`` () = + let src = + """ + type R1 = { B : int; C : int } + type R2 = { A : int; B : int; C : int } + + let r1 = { B = 1; C = 2 } + let r2 = { A = 3; ...r1 } + + let r1' = {| B = 1; C = 2 |} + let r2' = { A = 3; ...r1 } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldSucceed + + /// No overlap, spread ⊕ spread. + [] + let ``{...{A,B},...{C,D}} = {A,B} ⊕ {C,D} = {A,B,C,D}`` () = + let src = + """ + type R1 = { A : int; B : int } + type R2 = { C : int; D : int } + type R3 = { A : int; B : int; C : int; D : int } + + let r1 = { A = 1; B = 2 } + let r2 = { C = 3; D = 4 } + let r3 = { ...r1; ...r2 } + let r3' = { ...r2; ...r3 } + + let r1' = {| A = 1; B = 2 |} + let r2' = {| C = 3; D = 4 |} + let r3'' = { ...r1; ...r2 } + let r3''' = { ...r2; ...r3 } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldSucceed + + /// Rightward explicit duplicate field shadows field from spread. + [] + let ``{...{A₀,B},A₁} = {A₀,B} ⊕ {A₁} = {A₁,B,C}`` () = + let src = + """ + module M + + type R1 = { A : int; B : int } + + let r1 = { A = 1; B = 2 } + let r1' = { ...r1; A = 99 } + + if r1'.A <> 99 then failwith $"Expected r1'.A = 99 but got %A{r1'.A}." + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> compileExeAndRun + |> shouldSucceed + + /// Rightward spread field shadows leftward spread field. + [] + let ``{...{A₀,B},...{A₁}} = {A₀,B} ⊕ {A₁} = {A₁,B,C}`` () = + let src = + """ + module M + + type R1 = { A : int; B : int } + + let r1 = { A = 1; B = 2 } + let r1' = { ...r1; ...{| A = 99 |} } + + if r1'.A <> 99 then failwith $"Expected r1'.A = 99 but got %A{r1'.A}." + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> compileExeAndRun + |> shouldSucceed + + /// Rightward spread field shadows leftward explicit field with warning. + [] + let ``{A₀,...{A₁,B}} = {A₀} ⊕ {A₁,B} = {A₁_warn,B,C}`` () = + let src = + """ + type R1 = { A : int; B : int } + + let r1 = { A = 1; B = 2 } + let r1' = { A = 0; ...r1 } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Warning 3898, Line 5, Col 40, Line 5, Col 45, "Spread field 'A: int' shadows an explicitly declared field with the same name.") + + /// Explicit duplicate fields remain disallowed. + [] + let ``{A₀,...{A₁,B},A₂} = {A₀} ⊕ {A₁,B} ⊕ {A₂} = {A₁_warn,B,A₂_error}`` () = + let src = + """ + type R1 = { A : int; B : int } + + let r1 = { A = 1; B = 2; A = 3; ...{| A = 4 |}; A = 5 } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withDiagnostics [ + Error 668, Line 4, Col 46, Line 4, Col 51, "The field 'A' appears multiple times in this record expression or pattern" + Warning 3898, Line 4, Col 53, Line 4, Col 67, "Spread field 'A: int' shadows an explicitly declared field with the same name." + Error 668, Line 4, Col 69, Line 4, Col 74, "The field 'A' appears multiple times in this record expression or pattern" + ] + + /// Extra fields are ignored. + [] + let ``{...{A,B,C}}:{B} = {A,B,C} ∩ {B} = {B}`` () = + let src = + """ + type R1 = { A : int; B : int; C : int } + type R2 = { B : int } + + let r1 = { A = 1; B = 2; C = 3 } + let r2 : R2 = { ...r1 } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldSucceed + + module Accessibility = + /// Fields should have the accessibility of the target type. + /// A spread from less to more accessible is valid as long as the less accessible + /// fields are accessible at the point of the spread. + [] + let ``Accessibility comes from target`` () = + let src = + """ + type private R1 = { A : int; B : string } + type public R2 = { ...R1 } + + let private r1 = { A = 1; B = "2" } + let public r2 : R2 = { ...r1 } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldSucceed + + module NonRecordSource = + [] + let ``{...class} → error`` () = + let src = + """ + type C () = + member _.A = 1 + member _.B = 2 + + type R = { A : int } + + let r : R = { ...C () } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withDiagnostics [ + Error 3893, Line 8, Col 35, Line 8, Col 42, "The source expression of a spread into a nominal record expression must have a nominal or anonymous record type." + Error 764, Line 8, Col 33, Line 8, Col 44, "No assignment given for field 'A' of type 'Test.R'" + ] + + [] + let ``{...abstract_class} → error`` () = + let src = + """ + [] + type C () = + abstract A : int + abstract B : int + + type R = { A : int } + + let r : R = + { + ... + { new C () with + member _.A = 1 + member _.B = 2 } + } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withDiagnostics [ + Error 3893, Line 11, Col 29, Line 14, Col 53, "The source expression of a spread into a nominal record expression must have a nominal or anonymous record type." + Error 764, Line 10, Col 25, Line 15, Col 26, "No assignment given for field 'A' of type 'Test.R'" + ] + + [] + let ``{...struct} → error`` () = + let src = + """ + [] + type S = + member _.A = 1 + member _.B = 2 + + type R = { A : int } + + let r : R = { ...S () } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withDiagnostics [ + Error 3893, Line 9, Col 35, Line 9, Col 42, "The source expression of a spread into a nominal record expression must have a nominal or anonymous record type." + Error 764, Line 9, Col 33, Line 9, Col 44, "No assignment given for field 'A' of type 'Test.R'" + ] + + [] + let ``{...interface} → error`` () = + let src = + """ + type IFace = + abstract A : int + abstract B : int + + type R = { A : int } + + let r : R = + { + ... + { new IFace with + member _.A = 1 + member _.B = 2 } + } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withDiagnostics [ + Error 3893, Line 10, Col 29, Line 13, Col 53, "The source expression of a spread into a nominal record expression must have a nominal or anonymous record type." + Error 764, Line 9, Col 25, Line 14, Col 26, "No assignment given for field 'A' of type 'Test.R'" + ] + + [] + let ``{...int} → error`` () = + let src = + """ + type R = { A : int } + + let r : R = { ...int } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withDiagnostics [ + Error 3893, Line 4, Col 35, Line 4, Col 41, "The source expression of a spread into a nominal record expression must have a nominal or anonymous record type." + Error 764, Line 4, Col 33, Line 4, Col 43, "No assignment given for field 'A' of type 'Test.R'" + ] + + [] + let ``{...(int -> int)} → error`` () = + let src = + """ + type R = { A : int } + + let r = { ...(fun x -> x + 1) } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3893, Line 4, Col 31, Line 4, Col 50, "The source expression of a spread into a nominal record expression must have a nominal or anonymous record type.") + + module MembersOtherThanRecordFields = + [] + let ``Instance properties that are not record fields are ignored`` () = + let src = + """ + type R1 = + { A : int + B : string } + member this.Lol = string this.A + this.B + + type R2 = { ...R1; C : string } + + let _ : R2 = { A = 3; B = "3"; C = "asdf" } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldSucceed + + [] + let ``All members other than record fields are ignored`` () = + let src = + """ + type R1 = + { A : int + B : int } + member this.Lol = this.A + this.B + member _.Ha () = () + static member X = "3" + static member val Y = 42 + static member Q () = () + + type R2 = { ...R1; C : string } + + let r2 : R2 = { A = 3; B = 3; C = "asdf" } + ignore r2.Lol // Should not exist. + r2.Ha () // Should not exist. + ignore R2.Y // Should not exist. + R2.Q () // Should not exist. + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldFail + |> withDiagnostics [ + Error 39, Line 14, Col 31, Line 14, Col 34, "The type 'R2' does not define a field, constructor, or member named 'Lol'." + Error 39, Line 15, Col 24, Line 15, Col 26, "The type 'R2' does not define a field, constructor, or member named 'Ha'." + Error 39, Line 16, Col 31, Line 16, Col 32, "The type 'R2' does not define a field, constructor, or member named 'Y'." + Error 39, Line 17, Col 24, Line 17, Col 25, "The type 'R2' does not define a field, constructor, or member named 'Q'." + ] + + module Effects = + [] + let ``Effects in spread sources are evaluated exactly once per spread, even if all fields are shadowed`` () = + let src = + """ + type R = { A : int; B : int } + + let effects = ResizeArray () + let f () = effects.Add "f"; { A = 0; B = 1 } + let g () = effects.Add "g"; { A = 2; B = 3 } + let h () = effects.Add "h"; {| A = 99 |} + let r = { ...g (); ...f (); ...g (); ...h (); A = 100 } + + let expected = { A = 100; B = 3 } + if r <> expected then failwith $"Expected %A{expected} but got %A{r}." + match List.ofSeq effects with + | ["g"; "f"; "g"; "h"] -> () + | unexpected -> failwith $"Expected [\"g\"; \"f\"; \"g\"; \"h\"] but got %A{unexpected}." + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> compileExeAndRun + |> shouldSucceed + + module Conversions = + [] + let ``Coercions work as though they were field assignments`` () = + let src = + """ + type R1 = { A : int; B : string } + [] + type R2 = { A : obj; B : obj } + let r1 = { A = 3; B = "4" } + let r2 : R2 = { ...r1 } + let r1' = {| A = 3; B = "4" |} + let r3 : R2 = { ...r1' } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> typecheck + |> shouldSucceed + + [] + let ``Implicit conversions work as though they were field assignments`` () = + let src = + """ + type T = + | T of int + static member op_Implicit (T t) = U t + + and U = + | U of int + + type R1 = { A : T } + type R2 = { A : U } + + let r1 : R1 = { A = T 3 } + let r2 : R2 = { A = T 3 } + let r3 : R2 = { ...r1 } + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> ignoreWarnings + |> typecheck + |> shouldSucceed + |> withDiagnostics [ + Warning 3391, Line 13, Col 41, Line 13, Col 44, """This expression uses the implicit conversion 'static member T.op_Implicit: T -> U' to convert type 'T' to type 'U'. See https://aka.ms/fsharp-implicit-convs. This warning may be disabled using '#nowarn "3391".""" + Warning 3391, Line 14, Col 35, Line 14, Col 44, """This expression uses the implicit conversion 'static member T.op_Implicit: T -> U' to convert type 'T' to type 'U'. See https://aka.ms/fsharp-implicit-convs. This warning may be disabled using '#nowarn "3391".""" + ] + + module Nullability = + [] + let ``Can't spread from a nullable value`` () = + let src = + """ + type R = { A : int} + let r1 : R | null = null + let r2 : R = { ...r1 } + let r2' : {| A : int |} = {| ...r1 |} + """ + + FSharp src + |> withLangVersion SupportedLangVersion + |> withCheckNulls + |> typecheck + |> shouldFail + |> withDiagnostics [ + Error 3894, Line 4, Col 36, Line 4, Col 41, "The source expression of a spread into a nominal record expression cannot be nullable." + Error 764, Line 4, Col 34, Line 4, Col 43, "No assignment given for field 'A' of type 'Test.R'" + Error 3896, Line 5, Col 50, Line 5, Col 55, "The source expression of a spread into an anonymous record expression cannot be nullable." + Error 1, Line 5, Col 47, Line 5, Col 58, "This anonymous record is missing field 'A'." + ] + + module Inference = + [] + let ``No target type specified, no additional fields, target type inferred to be same as spread source type`` () = + let src = + """ + type R1 = { A : int; B : int } + type R2 = { A : int; B : int; C : int } + + let r1 = { A = 1; B = 2 } + let anon1 = {| A = 1; B = 2 |} + let r1InferredFromR1 = { ...r1 } + let r1InferredFromAnon = { ...anon1 } + + let r2 = { A = 1; B = 2; C = 3 } + let anon2 = {| A = 1; B = 2; C = 3 |} + let r2InferredFromR2 = { ...r2 } + let r2InferredFromAnon = { ...anon2 } + + let ``type of r1InferredFromR1`` = r1InferredFromR1.GetType () + if ``type of r1InferredFromR1`` <> typeof then + failwith $"Expected r1InferredFromR1 to have type R1 but got {``type of r1InferredFromR1``.Name}." + + let ``type of r1InferredFromAnon`` = r1InferredFromAnon.GetType () + if ``type of r1InferredFromAnon`` <> typeof then + failwith $"Expected r1InferredFromAnon to have type R1 but got {``type of r1InferredFromAnon``.Name}." + + let ``type of r2InferredFromR2`` = r2InferredFromR2.GetType () + if ``type of r2InferredFromR2`` <> typeof then + failwith $"Expected r2InferredFromR2 to have type R2 but got {``type of r2InferredFromR2``.Name}." + + let ``type of r2InferredFromAnon`` = r2InferredFromAnon.GetType () + if ``type of r2InferredFromAnon`` <> typeof then + failwith $"Expected r2InferredFromAnon to have type R2 but got {``type of r2InferredFromAnon``.Name}." + """ + + Fsx src + |> withLangVersion SupportedLangVersion + |> compileExeAndRun + |> shouldSucceed + + [] + let ``Unknown source type, nominal record type in scope → error`` () = + let src = + """ + type R = { A : int; B : int; C : int } + + let f x = { x with B = 2; C = 3 } // No error; x is inferred to have type R, because source and target type must be the same. + let g x = { ...x; B = 2; C = 3 } // Error; we do not force the source to have the same type as the target. + let h x : R = { ...x; B = 2; C = 3 } // Error; we do not force the source to have the same type as the target. + """ + + Fsx src + |> withLangVersion SupportedLangVersion + |> compile + |> shouldFail + |> withDiagnostics [ + Error 3893, Line 5, Col 33, Line 5, Col 37, "The source expression of a spread into a nominal record expression must have a nominal or anonymous record type." + Error 764, Line 5, Col 31, Line 5, Col 53, "No assignment given for field 'A' of type 'Test.R'" + Error 3893, Line 6, Col 37, Line 6, Col 41, "The source expression of a spread into a nominal record expression must have a nominal or anonymous record type." + Error 764, Line 6, Col 35, Line 6, Col 57, "No assignment given for field 'A' of type 'Test.R'" + ] + + module Structness = + [] + let ``Various structness combinations work`` () = + let src = + """ + type RefNominalRecd = { A : int; B : int } + type [] StructNominalRecd = { A : int; B : int } + + let refAnonRecd = {| A = 1; B = 2 |} + let structAnonRecd = struct {| A = 1; B = 2 |} + let refNominalRecd : RefNominalRecd = { A = 1; B = 2 } + let structNominalRecd : StructNominalRecd = { A = 1; B = 2 } + + let ``ref nominal src, ref nominal dst`` : RefNominalRecd = { ...refNominalRecd; B = 3 } + let ``ref nominal src, struct nominal dst`` : StructNominalRecd = { ...refNominalRecd; B = 3 } + let ``struct nominal src, ref nominal dst`` : RefNominalRecd = { ...structNominalRecd; B = 3 } + let ``struct nominal src, struct nominal dst`` : StructNominalRecd = { ...structNominalRecd; B = 3 } + let ``ref anon src, ref nominal dst`` : RefNominalRecd = { ...refAnonRecd; B = 3 } + let ``ref anon src, struct nominal dst`` : StructNominalRecd = { ...refAnonRecd; B = 3 } + let ``struct anon src, ref nominal dst`` : RefNominalRecd = { ...structAnonRecd; B = 3 } + let ``struct anon src, struct nominal dst`` : StructNominalRecd = { ...structAnonRecd; B = 3 } + """ + + Fsx src + |> withLangVersion SupportedLangVersion + |> compileExeAndRun + |> shouldSucceed + + module WithAndSpreads = + [] + let ``With and spreads cannot be used together`` () = + let src = + """ + type R = { A : int } + + let r1 = { A = 1 } + let r2 = { A = 2 } + let r3 = { r1 with ...r2; A = 3 } + """ + + Fsx src + |> withLangVersion SupportedLangVersion + |> compile + |> shouldFail + |> withDiagnostics [ + Error 3904, Line 6, Col 40, Line 6, Col 45, "Spread expressions and 'with' cannot be used together in the same copy-and-update expression." + ] + + module NestedUpdates = + [] + let ``Nested update with no preceding spread: error`` () = + let src = + """ + type NestedRecord = { A : string; B : string } + type OuterRecord = { Nested : NestedRecord } + + let orig () = { Nested = { A = "value1"; B = "value1" } } + + let _ = { Nested.A = "value2"; Nested.B = "value2"; ...orig () } + """ + + Fsx src + |> withLangVersion SupportedLangVersion + |> compile + |> shouldFail + |> withDiagnostics [ + Error 39, Line 7, Col 31, Line 7, Col 37, "The namespace or module 'Nested' is not defined." + Error 39, Line 7, Col 52, Line 7, Col 58, "The namespace or module 'Nested' is not defined." + ] + + [] + let ``Nested update with no matching preceding spread: error`` () = + let src = + """ + type NestedRecord = { A : string; B : string } + type OuterRecord = { Nested : NestedRecord } + + let orig () = { Nested = { A = "value1"; B = "value1" } } + + let _ = { ...orig (); Other.A = "value2" } + """ + + Fsx src + |> withLangVersion SupportedLangVersion + |> compile + |> shouldFail + |> withDiagnostics [ + Error 39, Line 7, Col 43, Line 7, Col 48, "The namespace or module 'Other' is not defined." + ] + + [] + let ``Nested updates apply to last matching spread: nominal to nominal`` () = + let src = + """ + type NestedRecord = { A : string; B : string } + type OuterRecord1 = { Nested : NestedRecord; Other : NestedRecord } + type OuterRecord2 = { Nested : NestedRecord } + + let orig1 () = { Nested = { A = "value1"; B = "value1" }; Other = { A = "value2"; B = "value2" } } + let orig2 () = { Nested = { A = "value3"; B = "value3" } } + + let actual = { ...orig1 (); Nested.B = "value4"; ...orig2 (); Other.B = "value5" } + let expected = { Nested = { A = "value3"; B = "value3" }; Other = { A = "value2"; B = "value5" } } + + if actual <> expected then + failwith $"Expected %A{expected} but got %A{actual}." + """ + + Fsx src + |> withLangVersion SupportedLangVersion + |> ignoreWarnings + |> compileExeAndRun + |> shouldSucceed + |> withDiagnostics [ + Warning 3898, Line 9, Col 70, Line 9, Col 81, "Spread field 'Nested: NestedRecord' shadows an explicitly declared field with the same name." + ] + + [] + let ``Nested updates apply to last matching spread: anonymous to nominal`` () = + let src = + """ + type NestedRecord = { A : string; B : string } + type OuterRecord = { Nested : NestedRecord; Other : NestedRecord } + + let orig1 () = {| Nested = { A = "value1"; B = "value1" }; Other = { A = "value2"; B = "value2" } |} + let orig2 () = {| Nested = { A = "value3"; B = "value3" } |} + + let actual = { ...orig1 (); Nested.B = "value4"; ...orig2 (); Other.B = "value5" } + let expected = { Nested = { A = "value3"; B = "value3" }; Other = { A = "value2"; B = "value5" } } + + if actual <> expected then + failwith $"Expected %A{expected} but got %A{actual}." + """ + + Fsx src + |> withLangVersion SupportedLangVersion + |> ignoreWarnings + |> compileExeAndRun + |> shouldSucceed + |> withDiagnostics [ + Warning 3898, Line 8, Col 70, Line 8, Col 81, "Spread field 'Nested: NestedRecord' shadows an explicitly declared field with the same name." + ] + + [] + let ``We assume any qualified field assignment following any spreads to be nested updates`` () = + let src = + """ + type Inner = { D : int } + type Middle = { B : int; C : Inner } + type Outer = { A : Middle } + + let r1 = { A = { B = 1; C = { D = 2 } } } + let r2 = { ...r1; A.C.D = 3 } + """ + + Fsx src + |> withLangVersion SupportedLangVersion + |> ignoreWarnings + |> compile + |> shouldSucceed + + [] + let ``Ambiguity in qualified field assignment following spreads in inferred expression leads to error because it would affect target type`` () = + let src = + """ + type Inner = { D : int } + type Middle = { B : int; C : Inner } + type Outer = { A : Middle } + module A = + type C = { D : int } + + let r1 = { A = { B = 1; C = { D = 2 } } } + let r2 = { ...r1; A.C.D = 3 } + """ + + Fsx src + |> withLangVersion SupportedLangVersion + |> ignoreWarnings + |> compile + |> shouldFail + |> withDiagnostics [ + Error 656, Line 9, Col 30, Line 9, Col 50, "This record contains fields from inconsistent types" + ] + + module FieldResolution = + [] + let ``Fields from spreads whose names are not in scope are still resolved`` () = + let src = + """ + module M = + type Source = { X : int; Y : int } + let source = { X = 1; Y = 2 } + + let a = { ...M.source } + let b : M.Source = { ...M.source } + let c = {| ...M.source |} + """ + + Fsx src + |> withLangVersion SupportedLangVersion + |> ignoreWarnings + |> compile + |> shouldSucceed + + [] + let ``Fields from spreads whose names are not in scope are still resolved: mixed spreads and fields`` () = + let src = + """ + module M = + type Source = { X : int; Y : int } + let source = { X = 1; Y = 2 } + + let a = { ...M.source; Y = 3 } + let b : M.Source = { ...M.source; Y = 3 } + let c = {| ...M.source; Y = 3 |} + """ + + Fsx src + |> withLangVersion SupportedLangVersion + |> ignoreWarnings + |> compile + |> shouldSucceed + + [] + let ``Fields from spreads whose names are not in scope are still resolved: total shadowing`` () = + let src = + """ + module M = + type Source = { X : int; Y : int } + let source = { X = 1; Y = 2 } + + let a = { ...M.source; X = 3; Y = 4 } + let b : M.Source = { ...M.source; X = 3; Y = 4 } + let c = {| ...M.source; X = 3; Y = 4 |} + """ + + Fsx src + |> withLangVersion SupportedLangVersion + |> ignoreWarnings + |> compile + |> shouldSucceed diff --git a/tests/FSharp.Compiler.Service.Tests/CompletionTests.fs b/tests/FSharp.Compiler.Service.Tests/CompletionTests.fs index fb359909d0f..5f151c99047 100644 --- a/tests/FSharp.Compiler.Service.Tests/CompletionTests.fs +++ b/tests/FSharp.Compiler.Service.Tests/CompletionTests.fs @@ -1,4 +1,4 @@ -module FSharp.Compiler.Service.Tests.CompletionTests +module FSharp.Compiler.Service.Tests.CompletionTests open FSharp.Compiler.CodeAnalysis open FSharp.Compiler.EditorServices @@ -907,3 +907,105 @@ let _ = System.Uri(uriString = s.{caret}, kind = System.UriKind.Absolute) """ assertHasItemWithNames ["Length"; "Substring"] info assertHasNoItemsWithNames ["uriString"; "kind"] info + +module RecordSpreads = + [] + let private SupportedLangVersion = "preview" + + let private getCompletionInfo markedSource = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| $"--langversion:{SupportedLangVersion}" |] + FSharpCodeCompletionOptions.Default + markedSource + + let private getCompletionInfoFor partialIdent markedSource = + Checker.getCompletionInfoWithCompilerAndCompletionOptions + [| $"--langversion:{SupportedLangVersion}" |] + FSharpCodeCompletionOptions.Default + markedSource + + [] + let ``spread - completion fires inside nominal record type spread, no ident yet`` () = + let info = getCompletionInfo """ +type R1 = { A: int; B: int } +type R2 = class end +type R3 = { ...{caret} } +""" + let names = info.Items |> Array.map _.NameInCode + if not (Array.contains "R1" names) then + failwith $"Expected completion at '{{ ...|caret| }}' to offer in-scope record type 'R1', but got %A{names}." + + if Array.contains "R2" names then + failwith $"Expected completion at '{{ ...|caret| }}' not to offer in-scope non-record type 'R2', but got %A{names}." + + [] + let ``spread - completion fires inside nominal record type spread, partial ident`` () = + let info = getCompletionInfo """ +type R1 = { A: int; B: int } +type R2 = class end +type R3 = { ...R{caret} } +""" + let names = info.Items |> Array.map _.NameInCode + if not (Array.contains "R1" names) then + failwith $"Expected completion at '{{ ...R|caret| }}' to offer in-scope record type 'R1', but got %A{names}." + + if Array.contains "R2" names then + failwith $"Expected completion at '{{ ...R|caret| }}' not to offer in-scope non-record type 'R2', but got %A{names}." + + [] + let ``spread - completion fires inside nominal record expression spread, no ident yet`` () = + let info = getCompletionInfo """ +type R = { A: int; B: int } +let r1 = { A = 1; B = 2 } +let r2 = obj () +let r3 = { ...{caret} } +""" + let names = info.Items |> Array.map _.NameInCode + if not (Array.contains "r1" names) then + failwith $"Expected completion at '{{ ...r|caret| }}' to offer in-scope record value 'r1', but got %A{names}." + + if Array.contains "r2" names then + failwith $"Expected completion at '{{ ...r|caret| }}' not to offer in-scope non-record value 'r2', but got %A{names}." + + [] + let ``spread - completion fires inside nominal record expression spread, partial ident`` () = + let info = getCompletionInfo """ +type R = { A: int; B: int } +let r1 = { A = 1; B = 2 } +let r2 = obj () +let r3 = { ...r{caret} } +""" + let names = info.Items |> Array.map _.NameInCode + if not (Array.contains "r1" names) then + failwith $"Expected completion at '{{ ...r|caret| }}' to offer in-scope record value 'r1', but got %A{names}." + + if Array.contains "r2" names then + failwith $"Expected completion at '{{ ...r|caret| }}' not to offer in-scope non-record value 'r2', but got %A{names}." + + [] + let ``spread - completion fires inside anonymous record expression spread, no ident yet`` () = + let info = getCompletionInfo """ +let r1 = {| A = 1; B = 2 |} +let r2 = obj () +let r3 = {| ...{caret} ; X = 1 |} +""" + let names = info.Items |> Array.map _.NameInCode + if not (Array.contains "r1" names) then + failwith $"Expected completion at '{{| ...|caret| ; X = 1 |}}' to offer in-scope record value 'r1', but got %A{names}." + + if Array.contains "r2" names then + failwith $"Expected completion at '{{ ...|caret| }}' not to offer in-scope non-record value 'r2', but got %A{names}." + + [] + let ``spread - completion fires inside anonymous record expression spread, partial ident`` () = + let info = getCompletionInfo """ +let r1 = {| A = 1; B = 2 |} +let r2 = obj () +let r3 = {| ...r{caret} ; X = 1 |} +""" + let names = info.Items |> Array.map _.NameInCode + if not (Array.contains "r1" names) then + failwith $"Expected completion at '{{| ...r|caret| ; X = 1 |}}' to offer in-scope record value 'r1', but got %A{names}." + + if Array.contains "r2" names then + failwith $"Expected completion at '{{ ...r|caret| }}' not to offer in-scope non-record value 'r2', but got %A{names}." diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.bsl b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.bsl index cd6be26fa07..8ca3e43896e 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.bsl +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.bsl @@ -3130,6 +3130,8 @@ FSharp.Compiler.EditorServices.CompletionContext+Pattern: FSharp.Compiler.Editor FSharp.Compiler.EditorServices.CompletionContext+Pattern: FSharp.Compiler.EditorServices.PatternContext get_context() FSharp.Compiler.EditorServices.CompletionContext+RecordField: FSharp.Compiler.EditorServices.RecordContext context FSharp.Compiler.EditorServices.CompletionContext+RecordField: FSharp.Compiler.EditorServices.RecordContext get_context() +FSharp.Compiler.EditorServices.CompletionContext+RecordSpread: FSharp.Compiler.EditorServices.RecordSpreadContext context +FSharp.Compiler.EditorServices.CompletionContext+RecordSpread: FSharp.Compiler.EditorServices.RecordSpreadContext get_context() FSharp.Compiler.EditorServices.CompletionContext+Tags: Int32 AttributeApplication FSharp.Compiler.EditorServices.CompletionContext+Tags: Int32 Inherit FSharp.Compiler.EditorServices.CompletionContext+Tags: Int32 Invalid @@ -3139,6 +3141,7 @@ FSharp.Compiler.EditorServices.CompletionContext+Tags: Int32 ParameterList FSharp.Compiler.EditorServices.CompletionContext+Tags: Int32 Pattern FSharp.Compiler.EditorServices.CompletionContext+Tags: Int32 RangeOperator FSharp.Compiler.EditorServices.CompletionContext+Tags: Int32 RecordField +FSharp.Compiler.EditorServices.CompletionContext+Tags: Int32 RecordSpread FSharp.Compiler.EditorServices.CompletionContext+Tags: Int32 Type FSharp.Compiler.EditorServices.CompletionContext+Tags: Int32 TypeAbbreviationOrSingleCaseUnion FSharp.Compiler.EditorServices.CompletionContext+Tags: Int32 UnionCaseFieldsDeclaration @@ -3155,6 +3158,7 @@ FSharp.Compiler.EditorServices.CompletionContext: Boolean IsParameterList FSharp.Compiler.EditorServices.CompletionContext: Boolean IsPattern FSharp.Compiler.EditorServices.CompletionContext: Boolean IsRangeOperator FSharp.Compiler.EditorServices.CompletionContext: Boolean IsRecordField +FSharp.Compiler.EditorServices.CompletionContext: Boolean IsRecordSpread FSharp.Compiler.EditorServices.CompletionContext: Boolean IsType FSharp.Compiler.EditorServices.CompletionContext: Boolean IsTypeAbbreviationOrSingleCaseUnion FSharp.Compiler.EditorServices.CompletionContext: Boolean IsUnionCaseFieldsDeclaration @@ -3167,6 +3171,7 @@ FSharp.Compiler.EditorServices.CompletionContext: Boolean get_IsParameterList() FSharp.Compiler.EditorServices.CompletionContext: Boolean get_IsPattern() FSharp.Compiler.EditorServices.CompletionContext: Boolean get_IsRangeOperator() FSharp.Compiler.EditorServices.CompletionContext: Boolean get_IsRecordField() +FSharp.Compiler.EditorServices.CompletionContext: Boolean get_IsRecordSpread() FSharp.Compiler.EditorServices.CompletionContext: Boolean get_IsType() FSharp.Compiler.EditorServices.CompletionContext: Boolean get_IsTypeAbbreviationOrSingleCaseUnion() FSharp.Compiler.EditorServices.CompletionContext: Boolean get_IsUnionCaseFieldsDeclaration() @@ -3178,6 +3183,7 @@ FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext NewParameterList(FSharp.Compiler.Text.Position, System.Collections.Generic.HashSet`1[System.String]) FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext NewPattern(FSharp.Compiler.EditorServices.PatternContext) FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext NewRecordField(FSharp.Compiler.EditorServices.RecordContext) +FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext NewRecordSpread(FSharp.Compiler.EditorServices.RecordSpreadContext) FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext RangeOperator FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext Type FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext TypeAbbreviationOrSingleCaseUnion @@ -3194,6 +3200,7 @@ FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext+ParameterList FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext+Pattern FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext+RecordField +FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext+RecordSpread FSharp.Compiler.EditorServices.CompletionContext: FSharp.Compiler.EditorServices.CompletionContext+Tags FSharp.Compiler.EditorServices.CompletionContext: Int32 GetHashCode() FSharp.Compiler.EditorServices.CompletionContext: Int32 GetHashCode(System.Collections.IEqualityComparer) @@ -4307,6 +4314,29 @@ FSharp.Compiler.EditorServices.RecordContext: Int32 GetHashCode(System.Collectio FSharp.Compiler.EditorServices.RecordContext: Int32 Tag FSharp.Compiler.EditorServices.RecordContext: Int32 get_Tag() FSharp.Compiler.EditorServices.RecordContext: System.String ToString() +FSharp.Compiler.EditorServices.RecordSpreadContext+Tags: Int32 Construction +FSharp.Compiler.EditorServices.RecordSpreadContext+Tags: Int32 Declaration +FSharp.Compiler.EditorServices.RecordSpreadContext: Boolean Equals(FSharp.Compiler.EditorServices.RecordSpreadContext) +FSharp.Compiler.EditorServices.RecordSpreadContext: Boolean Equals(FSharp.Compiler.EditorServices.RecordSpreadContext, System.Collections.IEqualityComparer) +FSharp.Compiler.EditorServices.RecordSpreadContext: Boolean Equals(System.Object) +FSharp.Compiler.EditorServices.RecordSpreadContext: Boolean Equals(System.Object, System.Collections.IEqualityComparer) +FSharp.Compiler.EditorServices.RecordSpreadContext: Boolean IsConstruction +FSharp.Compiler.EditorServices.RecordSpreadContext: Boolean IsDeclaration +FSharp.Compiler.EditorServices.RecordSpreadContext: Boolean get_IsConstruction() +FSharp.Compiler.EditorServices.RecordSpreadContext: Boolean get_IsDeclaration() +FSharp.Compiler.EditorServices.RecordSpreadContext: FSharp.Compiler.EditorServices.RecordSpreadContext Construction +FSharp.Compiler.EditorServices.RecordSpreadContext: FSharp.Compiler.EditorServices.RecordSpreadContext Declaration +FSharp.Compiler.EditorServices.RecordSpreadContext: FSharp.Compiler.EditorServices.RecordSpreadContext get_Construction() +FSharp.Compiler.EditorServices.RecordSpreadContext: FSharp.Compiler.EditorServices.RecordSpreadContext get_Declaration() +FSharp.Compiler.EditorServices.RecordSpreadContext: FSharp.Compiler.EditorServices.RecordSpreadContext+Tags +FSharp.Compiler.EditorServices.RecordSpreadContext: Int32 CompareTo(FSharp.Compiler.EditorServices.RecordSpreadContext) +FSharp.Compiler.EditorServices.RecordSpreadContext: Int32 CompareTo(System.Object) +FSharp.Compiler.EditorServices.RecordSpreadContext: Int32 CompareTo(System.Object, System.Collections.IComparer) +FSharp.Compiler.EditorServices.RecordSpreadContext: Int32 GetHashCode() +FSharp.Compiler.EditorServices.RecordSpreadContext: Int32 GetHashCode(System.Collections.IEqualityComparer) +FSharp.Compiler.EditorServices.RecordSpreadContext: Int32 Tag +FSharp.Compiler.EditorServices.RecordSpreadContext: Int32 get_Tag() +FSharp.Compiler.EditorServices.RecordSpreadContext: System.String ToString() FSharp.Compiler.EditorServices.ScopeKind+Tags: Int32 HashDirective FSharp.Compiler.EditorServices.ScopeKind+Tags: Int32 Namespace FSharp.Compiler.EditorServices.ScopeKind+Tags: Int32 NestedModule @@ -5622,7 +5652,6 @@ FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean EventIsStandard FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean HasGetterMethod FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean HasSetterMethod FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean HasSignatureFile -FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean IsPropertyAccessor FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean IsActivePattern FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean IsBaseValue FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean IsCompilerGenerated @@ -5645,6 +5674,7 @@ FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean IsModuleValueOrMe FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean IsMutable FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean IsOverrideOrExplicitInterfaceImplementation FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean IsProperty +FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean IsPropertyAccessor FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean IsPropertyGetterMethod FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean IsPropertySetterMethod FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean IsRefCell @@ -5658,7 +5688,6 @@ FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean get_EventIsStanda FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean get_HasGetterMethod() FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean get_HasSetterMethod() FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean get_HasSignatureFile() -FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean get_IsPropertyAccessor() FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean get_IsActivePattern() FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean get_IsBaseValue() FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean get_IsCompilerGenerated() @@ -5681,6 +5710,7 @@ FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean get_IsModuleValue FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean get_IsMutable() FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean get_IsOverrideOrExplicitInterfaceImplementation() FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean get_IsProperty() +FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean get_IsPropertyAccessor() FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean get_IsPropertyGetterMethod() FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean get_IsPropertySetterMethod() FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue: Boolean get_IsRefCell() @@ -6618,6 +6648,28 @@ FSharp.Compiler.Syntax.QualifiedNameOfFile: Int32 get_Tag() FSharp.Compiler.Syntax.QualifiedNameOfFile: System.String Text FSharp.Compiler.Syntax.QualifiedNameOfFile: System.String ToString() FSharp.Compiler.Syntax.QualifiedNameOfFile: System.String get_Text() +FSharp.Compiler.Syntax.RecordBinding+Field: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynExpr] declExpr +FSharp.Compiler.Syntax.RecordBinding+Field: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynExpr] get_declExpr() +FSharp.Compiler.Syntax.RecordBinding+Field: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] equalsRange +FSharp.Compiler.Syntax.RecordBinding+Field: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] get_equalsRange() +FSharp.Compiler.Syntax.RecordBinding+Field: System.Tuple`2[FSharp.Compiler.Syntax.SynLongIdent,System.Boolean] get_name() +FSharp.Compiler.Syntax.RecordBinding+Field: System.Tuple`2[FSharp.Compiler.Syntax.SynLongIdent,System.Boolean] name +FSharp.Compiler.Syntax.RecordBinding+Spread: FSharp.Compiler.Syntax.SynExprSpread get_spread() +FSharp.Compiler.Syntax.RecordBinding+Spread: FSharp.Compiler.Syntax.SynExprSpread spread +FSharp.Compiler.Syntax.RecordBinding+Tags: Int32 Field +FSharp.Compiler.Syntax.RecordBinding+Tags: Int32 Spread +FSharp.Compiler.Syntax.RecordBinding: Boolean IsField +FSharp.Compiler.Syntax.RecordBinding: Boolean IsSpread +FSharp.Compiler.Syntax.RecordBinding: Boolean get_IsField() +FSharp.Compiler.Syntax.RecordBinding: Boolean get_IsSpread() +FSharp.Compiler.Syntax.RecordBinding: FSharp.Compiler.Syntax.RecordBinding NewField(System.Tuple`2[FSharp.Compiler.Syntax.SynLongIdent,System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynExpr]) +FSharp.Compiler.Syntax.RecordBinding: FSharp.Compiler.Syntax.RecordBinding NewSpread(FSharp.Compiler.Syntax.SynExprSpread) +FSharp.Compiler.Syntax.RecordBinding: FSharp.Compiler.Syntax.RecordBinding+Field +FSharp.Compiler.Syntax.RecordBinding: FSharp.Compiler.Syntax.RecordBinding+Spread +FSharp.Compiler.Syntax.RecordBinding: FSharp.Compiler.Syntax.RecordBinding+Tags +FSharp.Compiler.Syntax.RecordBinding: Int32 Tag +FSharp.Compiler.Syntax.RecordBinding: Int32 get_Tag() +FSharp.Compiler.Syntax.RecordBinding: System.String ToString() FSharp.Compiler.Syntax.SeqExprOnly: Boolean Equals(FSharp.Compiler.Syntax.SeqExprOnly) FSharp.Compiler.Syntax.SeqExprOnly: Boolean Equals(FSharp.Compiler.Syntax.SeqExprOnly, System.Collections.IEqualityComparer) FSharp.Compiler.Syntax.SeqExprOnly: Boolean Equals(System.Object) @@ -7098,8 +7150,8 @@ FSharp.Compiler.Syntax.SynExpr+AnonRecd: FSharp.Compiler.SyntaxTrivia.SynExprAno FSharp.Compiler.Syntax.SynExpr+AnonRecd: FSharp.Compiler.SyntaxTrivia.SynExprAnonRecdTrivia trivia FSharp.Compiler.Syntax.SynExpr+AnonRecd: FSharp.Compiler.Text.Range get_range() FSharp.Compiler.Syntax.SynExpr+AnonRecd: FSharp.Compiler.Text.Range range -FSharp.Compiler.Syntax.SynExpr+AnonRecd: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[FSharp.Compiler.Syntax.SynLongIdent,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range],FSharp.Compiler.Syntax.SynExpr]] get_recordFields() -FSharp.Compiler.Syntax.SynExpr+AnonRecd: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[FSharp.Compiler.Syntax.SynLongIdent,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range],FSharp.Compiler.Syntax.SynExpr]] recordFields +FSharp.Compiler.Syntax.SynExpr+AnonRecd: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynExprAnonRecordFieldOrSpread] get_recordFields() +FSharp.Compiler.Syntax.SynExpr+AnonRecd: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynExprAnonRecordFieldOrSpread] recordFields FSharp.Compiler.Syntax.SynExpr+AnonRecd: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[FSharp.Compiler.Syntax.SynExpr,System.Tuple`2[FSharp.Compiler.Text.Range,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Position]]]] copyInfo FSharp.Compiler.Syntax.SynExpr+AnonRecd: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[FSharp.Compiler.Syntax.SynExpr,System.Tuple`2[FSharp.Compiler.Text.Range,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Position]]]] get_copyInfo() FSharp.Compiler.Syntax.SynExpr+App: Boolean get_isInfix() @@ -7482,8 +7534,8 @@ FSharp.Compiler.Syntax.SynExpr+Quote: FSharp.Compiler.Text.Range get_range() FSharp.Compiler.Syntax.SynExpr+Quote: FSharp.Compiler.Text.Range range FSharp.Compiler.Syntax.SynExpr+Record: FSharp.Compiler.Text.Range get_range() FSharp.Compiler.Syntax.SynExpr+Record: FSharp.Compiler.Text.Range range -FSharp.Compiler.Syntax.SynExpr+Record: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynExprRecordField] get_recordFields() -FSharp.Compiler.Syntax.SynExpr+Record: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynExprRecordField] recordFields +FSharp.Compiler.Syntax.SynExpr+Record: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynExprRecordFieldOrSpread] get_recordFields() +FSharp.Compiler.Syntax.SynExpr+Record: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynExprRecordFieldOrSpread] recordFields FSharp.Compiler.Syntax.SynExpr+Record: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[FSharp.Compiler.Syntax.SynExpr,System.Tuple`2[FSharp.Compiler.Text.Range,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Position]]]] copyInfo FSharp.Compiler.Syntax.SynExpr+Record: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[FSharp.Compiler.Syntax.SynExpr,System.Tuple`2[FSharp.Compiler.Text.Range,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Position]]]] get_copyInfo() FSharp.Compiler.Syntax.SynExpr+Record: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`5[FSharp.Compiler.Syntax.SynType,FSharp.Compiler.Syntax.SynExpr,FSharp.Compiler.Text.Range,Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[FSharp.Compiler.Text.Range,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Position]]],FSharp.Compiler.Text.Range]] baseInfo @@ -7834,7 +7886,7 @@ FSharp.Compiler.Syntax.SynExpr: Boolean get_IsWhileBang() FSharp.Compiler.Syntax.SynExpr: Boolean get_IsYieldOrReturn() FSharp.Compiler.Syntax.SynExpr: Boolean get_IsYieldOrReturnFrom() FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewAddressOf(Boolean, FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range, FSharp.Compiler.Text.Range) -FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewAnonRecd(Boolean, Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[FSharp.Compiler.Syntax.SynExpr,System.Tuple`2[FSharp.Compiler.Text.Range,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Position]]]], Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[FSharp.Compiler.Syntax.SynLongIdent,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range],FSharp.Compiler.Syntax.SynExpr]], FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynExprAnonRecdTrivia) +FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewAnonRecd(Boolean, Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[FSharp.Compiler.Syntax.SynExpr,System.Tuple`2[FSharp.Compiler.Text.Range,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Position]]]], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynExprAnonRecordFieldOrSpread], FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynExprAnonRecdTrivia) FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewApp(FSharp.Compiler.Syntax.ExprAtomicFlag, Boolean, FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewArbitraryAfterError(System.String, FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewArrayOrList(Boolean, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynExpr], FSharp.Compiler.Text.Range) @@ -7885,7 +7937,7 @@ FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewNull(FSharp.Co FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewObjExpr(FSharp.Compiler.Syntax.SynType, Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[FSharp.Compiler.Syntax.SynExpr,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident]]], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynBinding], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynMemberDefn], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynInterfaceImpl], FSharp.Compiler.Text.Range, FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewParen(FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range], FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewQuote(FSharp.Compiler.Syntax.SynExpr, Boolean, FSharp.Compiler.Syntax.SynExpr, Boolean, FSharp.Compiler.Text.Range) -FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewRecord(Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`5[FSharp.Compiler.Syntax.SynType,FSharp.Compiler.Syntax.SynExpr,FSharp.Compiler.Text.Range,Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[FSharp.Compiler.Text.Range,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Position]]],FSharp.Compiler.Text.Range]], Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[FSharp.Compiler.Syntax.SynExpr,System.Tuple`2[FSharp.Compiler.Text.Range,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Position]]]], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynExprRecordField], FSharp.Compiler.Text.Range) +FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewRecord(Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`5[FSharp.Compiler.Syntax.SynType,FSharp.Compiler.Syntax.SynExpr,FSharp.Compiler.Text.Range,Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[FSharp.Compiler.Text.Range,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Position]]],FSharp.Compiler.Text.Range]], Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[FSharp.Compiler.Syntax.SynExpr,System.Tuple`2[FSharp.Compiler.Text.Range,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Position]]]], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynExprRecordFieldOrSpread], FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewSequential(FSharp.Compiler.Syntax.DebugPointAtSequential, Boolean, FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynExprSequentialTrivia) FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewSequentialOrImplicitYield(FSharp.Compiler.Syntax.DebugPointAtSequential, FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Syntax.SynExpr NewSet(FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range) @@ -7981,8 +8033,44 @@ FSharp.Compiler.Syntax.SynExpr: FSharp.Compiler.Text.Range get_RangeWithoutAnyEx FSharp.Compiler.Syntax.SynExpr: Int32 Tag FSharp.Compiler.Syntax.SynExpr: Int32 get_Tag() FSharp.Compiler.Syntax.SynExpr: System.String ToString() +FSharp.Compiler.Syntax.SynExprAnonRecordField: FSharp.Compiler.Syntax.SynExpr expr +FSharp.Compiler.Syntax.SynExprAnonRecordField: FSharp.Compiler.Syntax.SynExpr get_expr() +FSharp.Compiler.Syntax.SynExprAnonRecordField: FSharp.Compiler.Syntax.SynExprAnonRecordField NewSynExprAnonRecordField(FSharp.Compiler.Syntax.SynLongIdent, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range], FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range) +FSharp.Compiler.Syntax.SynExprAnonRecordField: FSharp.Compiler.Syntax.SynLongIdent fieldName +FSharp.Compiler.Syntax.SynExprAnonRecordField: FSharp.Compiler.Syntax.SynLongIdent get_fieldName() +FSharp.Compiler.Syntax.SynExprAnonRecordField: FSharp.Compiler.Text.Range get_range() +FSharp.Compiler.Syntax.SynExprAnonRecordField: FSharp.Compiler.Text.Range range +FSharp.Compiler.Syntax.SynExprAnonRecordField: Int32 Tag +FSharp.Compiler.Syntax.SynExprAnonRecordField: Int32 get_Tag() +FSharp.Compiler.Syntax.SynExprAnonRecordField: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] equalsRange +FSharp.Compiler.Syntax.SynExprAnonRecordField: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] get_equalsRange() +FSharp.Compiler.Syntax.SynExprAnonRecordField: System.String ToString() +FSharp.Compiler.Syntax.SynExprAnonRecordFieldOrSpread+Field: FSharp.Compiler.Syntax.SynExprAnonRecordField field +FSharp.Compiler.Syntax.SynExprAnonRecordFieldOrSpread+Field: FSharp.Compiler.Syntax.SynExprAnonRecordField get_field() +FSharp.Compiler.Syntax.SynExprAnonRecordFieldOrSpread+Field: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[FSharp.Compiler.Text.Range,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Position]]] blockSeparator +FSharp.Compiler.Syntax.SynExprAnonRecordFieldOrSpread+Field: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[FSharp.Compiler.Text.Range,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Position]]] get_blockSeparator() +FSharp.Compiler.Syntax.SynExprAnonRecordFieldOrSpread+Spread: FSharp.Compiler.Syntax.SynExprSpread get_spread() +FSharp.Compiler.Syntax.SynExprAnonRecordFieldOrSpread+Spread: FSharp.Compiler.Syntax.SynExprSpread spread +FSharp.Compiler.Syntax.SynExprAnonRecordFieldOrSpread+Spread: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[FSharp.Compiler.Text.Range,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Position]]] blockSeparator +FSharp.Compiler.Syntax.SynExprAnonRecordFieldOrSpread+Spread: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[FSharp.Compiler.Text.Range,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Position]]] get_blockSeparator() +FSharp.Compiler.Syntax.SynExprAnonRecordFieldOrSpread+Tags: Int32 Field +FSharp.Compiler.Syntax.SynExprAnonRecordFieldOrSpread+Tags: Int32 Spread +FSharp.Compiler.Syntax.SynExprAnonRecordFieldOrSpread: Boolean IsField +FSharp.Compiler.Syntax.SynExprAnonRecordFieldOrSpread: Boolean IsSpread +FSharp.Compiler.Syntax.SynExprAnonRecordFieldOrSpread: Boolean get_IsField() +FSharp.Compiler.Syntax.SynExprAnonRecordFieldOrSpread: Boolean get_IsSpread() +FSharp.Compiler.Syntax.SynExprAnonRecordFieldOrSpread: FSharp.Compiler.Syntax.SynExprAnonRecordFieldOrSpread NewField(FSharp.Compiler.Syntax.SynExprAnonRecordField, Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[FSharp.Compiler.Text.Range,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Position]]]) +FSharp.Compiler.Syntax.SynExprAnonRecordFieldOrSpread: FSharp.Compiler.Syntax.SynExprAnonRecordFieldOrSpread NewSpread(FSharp.Compiler.Syntax.SynExprSpread, Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[FSharp.Compiler.Text.Range,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Position]]]) +FSharp.Compiler.Syntax.SynExprAnonRecordFieldOrSpread: FSharp.Compiler.Syntax.SynExprAnonRecordFieldOrSpread+Field +FSharp.Compiler.Syntax.SynExprAnonRecordFieldOrSpread: FSharp.Compiler.Syntax.SynExprAnonRecordFieldOrSpread+Spread +FSharp.Compiler.Syntax.SynExprAnonRecordFieldOrSpread: FSharp.Compiler.Syntax.SynExprAnonRecordFieldOrSpread+Tags +FSharp.Compiler.Syntax.SynExprAnonRecordFieldOrSpread: FSharp.Compiler.Text.Range Range +FSharp.Compiler.Syntax.SynExprAnonRecordFieldOrSpread: FSharp.Compiler.Text.Range get_Range() +FSharp.Compiler.Syntax.SynExprAnonRecordFieldOrSpread: Int32 Tag +FSharp.Compiler.Syntax.SynExprAnonRecordFieldOrSpread: Int32 get_Tag() +FSharp.Compiler.Syntax.SynExprAnonRecordFieldOrSpread: System.String ToString() FSharp.Compiler.Syntax.SynExprModule: Boolean shouldBeParenthesizedInContext(Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,System.String], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], FSharp.Compiler.Syntax.SynExpr) -FSharp.Compiler.Syntax.SynExprRecordField: FSharp.Compiler.Syntax.SynExprRecordField NewSynExprRecordField(System.Tuple`2[FSharp.Compiler.Syntax.SynLongIdent,System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynExpr], FSharp.Compiler.Text.Range, Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[FSharp.Compiler.Text.Range,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Position]]]) +FSharp.Compiler.Syntax.SynExprRecordField: FSharp.Compiler.Syntax.SynExprRecordField NewSynExprRecordField(System.Tuple`2[FSharp.Compiler.Syntax.SynLongIdent,System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynExpr], FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynExprRecordField: FSharp.Compiler.Text.Range get_range() FSharp.Compiler.Syntax.SynExprRecordField: FSharp.Compiler.Text.Range range FSharp.Compiler.Syntax.SynExprRecordField: Int32 Tag @@ -7991,11 +8079,41 @@ FSharp.Compiler.Syntax.SynExprRecordField: Microsoft.FSharp.Core.FSharpOption`1[ FSharp.Compiler.Syntax.SynExprRecordField: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynExpr] get_expr() FSharp.Compiler.Syntax.SynExprRecordField: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] equalsRange FSharp.Compiler.Syntax.SynExprRecordField: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] get_equalsRange() -FSharp.Compiler.Syntax.SynExprRecordField: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[FSharp.Compiler.Text.Range,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Position]]] blockSeparator -FSharp.Compiler.Syntax.SynExprRecordField: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[FSharp.Compiler.Text.Range,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Position]]] get_blockSeparator() FSharp.Compiler.Syntax.SynExprRecordField: System.String ToString() FSharp.Compiler.Syntax.SynExprRecordField: System.Tuple`2[FSharp.Compiler.Syntax.SynLongIdent,System.Boolean] fieldName FSharp.Compiler.Syntax.SynExprRecordField: System.Tuple`2[FSharp.Compiler.Syntax.SynLongIdent,System.Boolean] get_fieldName() +FSharp.Compiler.Syntax.SynExprRecordFieldOrSpread+Field: FSharp.Compiler.Syntax.SynExprRecordField field +FSharp.Compiler.Syntax.SynExprRecordFieldOrSpread+Field: FSharp.Compiler.Syntax.SynExprRecordField get_field() +FSharp.Compiler.Syntax.SynExprRecordFieldOrSpread+Field: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[FSharp.Compiler.Text.Range,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Position]]] blockSeparator +FSharp.Compiler.Syntax.SynExprRecordFieldOrSpread+Field: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[FSharp.Compiler.Text.Range,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Position]]] get_blockSeparator() +FSharp.Compiler.Syntax.SynExprRecordFieldOrSpread+Spread: FSharp.Compiler.Syntax.SynExprSpread get_spread() +FSharp.Compiler.Syntax.SynExprRecordFieldOrSpread+Spread: FSharp.Compiler.Syntax.SynExprSpread spread +FSharp.Compiler.Syntax.SynExprRecordFieldOrSpread+Spread: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[FSharp.Compiler.Text.Range,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Position]]] blockSeparator +FSharp.Compiler.Syntax.SynExprRecordFieldOrSpread+Spread: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[FSharp.Compiler.Text.Range,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Position]]] get_blockSeparator() +FSharp.Compiler.Syntax.SynExprRecordFieldOrSpread+Tags: Int32 Field +FSharp.Compiler.Syntax.SynExprRecordFieldOrSpread+Tags: Int32 Spread +FSharp.Compiler.Syntax.SynExprRecordFieldOrSpread: Boolean IsField +FSharp.Compiler.Syntax.SynExprRecordFieldOrSpread: Boolean IsSpread +FSharp.Compiler.Syntax.SynExprRecordFieldOrSpread: Boolean get_IsField() +FSharp.Compiler.Syntax.SynExprRecordFieldOrSpread: Boolean get_IsSpread() +FSharp.Compiler.Syntax.SynExprRecordFieldOrSpread: FSharp.Compiler.Syntax.SynExprRecordFieldOrSpread NewField(FSharp.Compiler.Syntax.SynExprRecordField, Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[FSharp.Compiler.Text.Range,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Position]]]) +FSharp.Compiler.Syntax.SynExprRecordFieldOrSpread: FSharp.Compiler.Syntax.SynExprRecordFieldOrSpread NewSpread(FSharp.Compiler.Syntax.SynExprSpread, Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[FSharp.Compiler.Text.Range,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Position]]]) +FSharp.Compiler.Syntax.SynExprRecordFieldOrSpread: FSharp.Compiler.Syntax.SynExprRecordFieldOrSpread+Field +FSharp.Compiler.Syntax.SynExprRecordFieldOrSpread: FSharp.Compiler.Syntax.SynExprRecordFieldOrSpread+Spread +FSharp.Compiler.Syntax.SynExprRecordFieldOrSpread: FSharp.Compiler.Syntax.SynExprRecordFieldOrSpread+Tags +FSharp.Compiler.Syntax.SynExprRecordFieldOrSpread: Int32 Tag +FSharp.Compiler.Syntax.SynExprRecordFieldOrSpread: Int32 get_Tag() +FSharp.Compiler.Syntax.SynExprRecordFieldOrSpread: System.String ToString() +FSharp.Compiler.Syntax.SynExprSpread: FSharp.Compiler.Syntax.SynExpr expr +FSharp.Compiler.Syntax.SynExprSpread: FSharp.Compiler.Syntax.SynExpr get_expr() +FSharp.Compiler.Syntax.SynExprSpread: FSharp.Compiler.Syntax.SynExprSpread NewSynExprSpread(FSharp.Compiler.Text.Range, FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range) +FSharp.Compiler.Syntax.SynExprSpread: FSharp.Compiler.Text.Range get_range() +FSharp.Compiler.Syntax.SynExprSpread: FSharp.Compiler.Text.Range get_spreadRange() +FSharp.Compiler.Syntax.SynExprSpread: FSharp.Compiler.Text.Range range +FSharp.Compiler.Syntax.SynExprSpread: FSharp.Compiler.Text.Range spreadRange +FSharp.Compiler.Syntax.SynExprSpread: Int32 Tag +FSharp.Compiler.Syntax.SynExprSpread: Int32 get_Tag() +FSharp.Compiler.Syntax.SynExprSpread: System.String ToString() FSharp.Compiler.Syntax.SynField: Boolean get_isMutable() FSharp.Compiler.Syntax.SynField: Boolean get_isStatic() FSharp.Compiler.Syntax.SynField: Boolean isMutable @@ -8020,6 +8138,24 @@ FSharp.Compiler.Syntax.SynField: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Com FSharp.Compiler.Syntax.SynField: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess] accessibility FSharp.Compiler.Syntax.SynField: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess] get_accessibility() FSharp.Compiler.Syntax.SynField: System.String ToString() +FSharp.Compiler.Syntax.SynFieldOrSpread+Field: FSharp.Compiler.Syntax.SynField field +FSharp.Compiler.Syntax.SynFieldOrSpread+Field: FSharp.Compiler.Syntax.SynField get_field() +FSharp.Compiler.Syntax.SynFieldOrSpread+Spread: FSharp.Compiler.Syntax.SynTypeSpread get_spread() +FSharp.Compiler.Syntax.SynFieldOrSpread+Spread: FSharp.Compiler.Syntax.SynTypeSpread spread +FSharp.Compiler.Syntax.SynFieldOrSpread+Tags: Int32 Field +FSharp.Compiler.Syntax.SynFieldOrSpread+Tags: Int32 Spread +FSharp.Compiler.Syntax.SynFieldOrSpread: Boolean IsField +FSharp.Compiler.Syntax.SynFieldOrSpread: Boolean IsSpread +FSharp.Compiler.Syntax.SynFieldOrSpread: Boolean get_IsField() +FSharp.Compiler.Syntax.SynFieldOrSpread: Boolean get_IsSpread() +FSharp.Compiler.Syntax.SynFieldOrSpread: FSharp.Compiler.Syntax.SynFieldOrSpread NewField(FSharp.Compiler.Syntax.SynField) +FSharp.Compiler.Syntax.SynFieldOrSpread: FSharp.Compiler.Syntax.SynFieldOrSpread NewSpread(FSharp.Compiler.Syntax.SynTypeSpread) +FSharp.Compiler.Syntax.SynFieldOrSpread: FSharp.Compiler.Syntax.SynFieldOrSpread+Field +FSharp.Compiler.Syntax.SynFieldOrSpread: FSharp.Compiler.Syntax.SynFieldOrSpread+Spread +FSharp.Compiler.Syntax.SynFieldOrSpread: FSharp.Compiler.Syntax.SynFieldOrSpread+Tags +FSharp.Compiler.Syntax.SynFieldOrSpread: Int32 Tag +FSharp.Compiler.Syntax.SynFieldOrSpread: Int32 get_Tag() +FSharp.Compiler.Syntax.SynFieldOrSpread: System.String ToString() FSharp.Compiler.Syntax.SynIdent: FSharp.Compiler.Syntax.Ident get_ident() FSharp.Compiler.Syntax.SynIdent: FSharp.Compiler.Syntax.Ident ident FSharp.Compiler.Syntax.SynIdent: FSharp.Compiler.Syntax.SynIdent NewSynIdent(FSharp.Compiler.Syntax.Ident, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.SyntaxTrivia.IdentTrivia]) @@ -9887,8 +10023,8 @@ FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr+None: FSharp.Compiler.Text.Range ge FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr+None: FSharp.Compiler.Text.Range range FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr+Record: FSharp.Compiler.Text.Range get_range() FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr+Record: FSharp.Compiler.Text.Range range -FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr+Record: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynField] get_recordFields() -FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr+Record: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynField] recordFields +FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr+Record: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynFieldOrSpread] get_recordFieldsAndSpreads() +FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr+Record: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynFieldOrSpread] recordFieldsAndSpreads FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr+Record: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess] accessibility FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr+Record: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess] get_accessibility() FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr+Tags: Int32 Enum @@ -9932,7 +10068,7 @@ FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: FSharp.Compiler.Syntax.SynTypeDefn FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr NewGeneral(FSharp.Compiler.Syntax.SynTypeDefnKind, Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[FSharp.Compiler.Syntax.SynType,FSharp.Compiler.Text.Range,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident]]], Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[FSharp.Compiler.Syntax.SynValSig,FSharp.Compiler.Syntax.SynMemberFlags]], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynField], Boolean, Boolean, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynPat], FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr NewLibraryOnlyILAssembly(System.Object, FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr NewNone(FSharp.Compiler.Text.Range) -FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr NewRecord(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynField], FSharp.Compiler.Text.Range) +FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr NewRecord(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynFieldOrSpread], FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr NewTypeAbbrev(FSharp.Compiler.Syntax.ParserDetail, FSharp.Compiler.Syntax.SynType, FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr NewUnion(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynUnionCase], FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr+Enum @@ -9949,6 +10085,16 @@ FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: FSharp.Compiler.Text.Range get_Ran FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: Int32 Tag FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: Int32 get_Tag() FSharp.Compiler.Syntax.SynTypeDefnSimpleRepr: System.String ToString() +FSharp.Compiler.Syntax.SynTypeSpread: FSharp.Compiler.Syntax.SynType get_ty() +FSharp.Compiler.Syntax.SynTypeSpread: FSharp.Compiler.Syntax.SynType ty +FSharp.Compiler.Syntax.SynTypeSpread: FSharp.Compiler.Syntax.SynTypeSpread NewSynTypeSpread(FSharp.Compiler.Text.Range, FSharp.Compiler.Syntax.SynType, FSharp.Compiler.Text.Range) +FSharp.Compiler.Syntax.SynTypeSpread: FSharp.Compiler.Text.Range get_range() +FSharp.Compiler.Syntax.SynTypeSpread: FSharp.Compiler.Text.Range get_spreadRange() +FSharp.Compiler.Syntax.SynTypeSpread: FSharp.Compiler.Text.Range range +FSharp.Compiler.Syntax.SynTypeSpread: FSharp.Compiler.Text.Range spreadRange +FSharp.Compiler.Syntax.SynTypeSpread: Int32 Tag +FSharp.Compiler.Syntax.SynTypeSpread: Int32 get_Tag() +FSharp.Compiler.Syntax.SynTypeSpread: System.String ToString() FSharp.Compiler.Syntax.SynUnionCase: FSharp.Compiler.Syntax.SynIdent get_ident() FSharp.Compiler.Syntax.SynUnionCase: FSharp.Compiler.Syntax.SynIdent ident FSharp.Compiler.Syntax.SynUnionCase: FSharp.Compiler.Syntax.SynUnionCase NewSynUnionCase(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], FSharp.Compiler.Syntax.SynIdent, FSharp.Compiler.Syntax.SynUnionCaseKind, FSharp.Compiler.Xml.PreXmlDoc, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynUnionCaseTrivia) @@ -10201,7 +10347,7 @@ FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOptio FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOption`1[T] VisitModuleOrNamespaceSig(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], FSharp.Compiler.Syntax.SynModuleOrNamespaceSig) FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOption`1[T] VisitModuleSigDecl(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], Microsoft.FSharp.Core.FSharpFunc`2[FSharp.Compiler.Syntax.SynModuleSigDecl,Microsoft.FSharp.Core.FSharpOption`1[T]], FSharp.Compiler.Syntax.SynModuleSigDecl) FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOption`1[T] VisitPat(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], Microsoft.FSharp.Core.FSharpFunc`2[FSharp.Compiler.Syntax.SynPat,Microsoft.FSharp.Core.FSharpOption`1[T]], FSharp.Compiler.Syntax.SynPat) -FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOption`1[T] VisitRecordDefn(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynField], FSharp.Compiler.Text.Range) +FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOption`1[T] VisitRecordDefn(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynFieldOrSpread], FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOption`1[T] VisitRecordField(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynExpr], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynLongIdent]) FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOption`1[T] VisitSimplePats(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], FSharp.Compiler.Syntax.SynPat) FSharp.Compiler.Syntax.SyntaxVisitorBase`1[T]: Microsoft.FSharp.Core.FSharpOption`1[T] VisitType(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SyntaxNode], Microsoft.FSharp.Core.FSharpFunc`2[FSharp.Compiler.Syntax.SynType,Microsoft.FSharp.Core.FSharpOption`1[T]], FSharp.Compiler.Syntax.SynType) @@ -11409,6 +11555,7 @@ FSharp.Compiler.Tokenization.FSharpTokenKind+Tags: Int32 Dollar FSharp.Compiler.Tokenization.FSharpTokenKind+Tags: Int32 Done FSharp.Compiler.Tokenization.FSharpTokenKind+Tags: Int32 Dot FSharp.Compiler.Tokenization.FSharpTokenKind+Tags: Int32 DotDot +FSharp.Compiler.Tokenization.FSharpTokenKind+Tags: Int32 DotDotDot FSharp.Compiler.Tokenization.FSharpTokenKind+Tags: Int32 DotDotHat FSharp.Compiler.Tokenization.FSharpTokenKind+Tags: Int32 DownTo FSharp.Compiler.Tokenization.FSharpTokenKind+Tags: Int32 Downcast @@ -11600,6 +11747,7 @@ FSharp.Compiler.Tokenization.FSharpTokenKind: Boolean IsDollar FSharp.Compiler.Tokenization.FSharpTokenKind: Boolean IsDone FSharp.Compiler.Tokenization.FSharpTokenKind: Boolean IsDot FSharp.Compiler.Tokenization.FSharpTokenKind: Boolean IsDotDot +FSharp.Compiler.Tokenization.FSharpTokenKind: Boolean IsDotDotDot FSharp.Compiler.Tokenization.FSharpTokenKind: Boolean IsDotDotHat FSharp.Compiler.Tokenization.FSharpTokenKind: Boolean IsDownTo FSharp.Compiler.Tokenization.FSharpTokenKind: Boolean IsDowncast @@ -11787,6 +11935,7 @@ FSharp.Compiler.Tokenization.FSharpTokenKind: Boolean get_IsDollar() FSharp.Compiler.Tokenization.FSharpTokenKind: Boolean get_IsDone() FSharp.Compiler.Tokenization.FSharpTokenKind: Boolean get_IsDot() FSharp.Compiler.Tokenization.FSharpTokenKind: Boolean get_IsDotDot() +FSharp.Compiler.Tokenization.FSharpTokenKind: Boolean get_IsDotDotDot() FSharp.Compiler.Tokenization.FSharpTokenKind: Boolean get_IsDotDotHat() FSharp.Compiler.Tokenization.FSharpTokenKind: Boolean get_IsDownTo() FSharp.Compiler.Tokenization.FSharpTokenKind: Boolean get_IsDowncast() @@ -11974,6 +12123,7 @@ FSharp.Compiler.Tokenization.FSharpTokenKind: FSharp.Compiler.Tokenization.FShar FSharp.Compiler.Tokenization.FSharpTokenKind: FSharp.Compiler.Tokenization.FSharpTokenKind Done FSharp.Compiler.Tokenization.FSharpTokenKind: FSharp.Compiler.Tokenization.FSharpTokenKind Dot FSharp.Compiler.Tokenization.FSharpTokenKind: FSharp.Compiler.Tokenization.FSharpTokenKind DotDot +FSharp.Compiler.Tokenization.FSharpTokenKind: FSharp.Compiler.Tokenization.FSharpTokenKind DotDotDot FSharp.Compiler.Tokenization.FSharpTokenKind: FSharp.Compiler.Tokenization.FSharpTokenKind DotDotHat FSharp.Compiler.Tokenization.FSharpTokenKind: FSharp.Compiler.Tokenization.FSharpTokenKind DownTo FSharp.Compiler.Tokenization.FSharpTokenKind: FSharp.Compiler.Tokenization.FSharpTokenKind Downcast @@ -12161,6 +12311,7 @@ FSharp.Compiler.Tokenization.FSharpTokenKind: FSharp.Compiler.Tokenization.FShar FSharp.Compiler.Tokenization.FSharpTokenKind: FSharp.Compiler.Tokenization.FSharpTokenKind get_Done() FSharp.Compiler.Tokenization.FSharpTokenKind: FSharp.Compiler.Tokenization.FSharpTokenKind get_Dot() FSharp.Compiler.Tokenization.FSharpTokenKind: FSharp.Compiler.Tokenization.FSharpTokenKind get_DotDot() +FSharp.Compiler.Tokenization.FSharpTokenKind: FSharp.Compiler.Tokenization.FSharpTokenKind get_DotDotDot() FSharp.Compiler.Tokenization.FSharpTokenKind: FSharp.Compiler.Tokenization.FSharpTokenKind get_DotDotHat() FSharp.Compiler.Tokenization.FSharpTokenKind: FSharp.Compiler.Tokenization.FSharpTokenKind get_DownTo() FSharp.Compiler.Tokenization.FSharpTokenKind: FSharp.Compiler.Tokenization.FSharpTokenKind get_Downcast() @@ -12336,6 +12487,7 @@ FSharp.Compiler.Tokenization.FSharpTokenTag: Int32 COMMENT FSharp.Compiler.Tokenization.FSharpTokenTag: Int32 DO FSharp.Compiler.Tokenization.FSharpTokenTag: Int32 DOT FSharp.Compiler.Tokenization.FSharpTokenTag: Int32 DOT_DOT +FSharp.Compiler.Tokenization.FSharpTokenTag: Int32 DOT_DOT_DOT FSharp.Compiler.Tokenization.FSharpTokenTag: Int32 DOT_DOT_HAT FSharp.Compiler.Tokenization.FSharpTokenTag: Int32 ELSE FSharp.Compiler.Tokenization.FSharpTokenTag: Int32 EQUALS @@ -12400,6 +12552,7 @@ FSharp.Compiler.Tokenization.FSharpTokenTag: Int32 get_COMMENT() FSharp.Compiler.Tokenization.FSharpTokenTag: Int32 get_DO() FSharp.Compiler.Tokenization.FSharpTokenTag: Int32 get_DOT() FSharp.Compiler.Tokenization.FSharpTokenTag: Int32 get_DOT_DOT() +FSharp.Compiler.Tokenization.FSharpTokenTag: Int32 get_DOT_DOT_DOT() FSharp.Compiler.Tokenization.FSharpTokenTag: Int32 get_DOT_DOT_HAT() FSharp.Compiler.Tokenization.FSharpTokenTag: Int32 get_ELSE() FSharp.Compiler.Tokenization.FSharpTokenTag: Int32 get_EQUALS() diff --git a/tests/FSharp.Compiler.Service.Tests/ParsedInputModuleTests.fs b/tests/FSharp.Compiler.Service.Tests/ParsedInputModuleTests.fs index 2ff0eebe32b..c671dbab1f4 100644 --- a/tests/FSharp.Compiler.Service.Tests/ParsedInputModuleTests.fs +++ b/tests/FSharp.Compiler.Service.Tests/ParsedInputModuleTests.fs @@ -2,6 +2,7 @@ module FSharp.Compiler.Service.Tests.ParsedInputModuleTests open FSharp.Compiler.Service.Tests.Common open FSharp.Compiler.Syntax +open FSharp.Compiler.SyntaxTreeOps open FSharp.Compiler.Text.Position open Xunit @@ -27,11 +28,11 @@ let ``tryPick record definition test`` () = (pos0, parseTree) ||> ParsedInput.tryPick (fun _path node -> match node with - | SyntaxNode.SynTypeDefn(SynTypeDefn(typeRepr = SynTypeDefnRepr.Simple(SynTypeDefnSimpleRepr.Record(recordFields = fields), _))) -> Some fields + | SyntaxNode.SynTypeDefn(SynTypeDefn(typeRepr = SynTypeDefnRepr.Simple(SynTypeDefnSimpleRepr.Record(recordFieldsAndSpreads = fieldsAndSpreads), _))) -> Some fieldsAndSpreads | _ -> None) match fields with - | Some [ SynField (idOpt = Some id1); SynField (idOpt = Some id2) ] when id1.idText = "A" && id2.idText = "B" -> () + | Some [ SynFieldOrSpread.Field (SynField (idOpt = Some id1)); SynFieldOrSpread.Field (SynField (idOpt = Some id2)) ] when id1.idText = "A" && id2.idText = "B" -> () | _ -> failwith "Did not visit record definition" [] @@ -145,9 +146,9 @@ type Y = (pos0, parseTree) ||> ParsedInput.tryPick (fun _path node -> match node with - | SyntaxNode.SynTypeDefnSig(SynTypeDefnSig(typeRepr = SynTypeDefnSigRepr.Simple(SynTypeDefnSimpleRepr.Record(recordFields = fields), _))) -> - fields - |> List.choose (function SynField(idOpt = Some ident) -> Some ident.idText | _ -> None) + | SyntaxNode.SynTypeDefnSig(SynTypeDefnSig(typeRepr = SynTypeDefnSigRepr.Simple(SynTypeDefnSimpleRepr.Record(recordFieldsAndSpreads = fieldsAndSpreads), _))) -> + fieldsAndSpreads + |> List.choose (function SynFieldOrSpread.Field (SynField(idOpt = Some ident)) -> Some ident.idText | _ -> None) |> String.concat "," |> Some | _ -> None) diff --git a/tests/FSharp.Compiler.Service.Tests/Symbols.fs b/tests/FSharp.Compiler.Service.Tests/Symbols.fs index e7a1d5f683e..292c6b9a96b 100644 --- a/tests/FSharp.Compiler.Service.Tests/Symbols.fs +++ b/tests/FSharp.Compiler.Service.Tests/Symbols.fs @@ -1772,3 +1772,60 @@ type Outer = { I1: Inner1; I2: Inner2 } let o = { I1 = { A = 1; B = 2 }; I2 = { C = 3 } } let o2 = { o with Outer.I1.A = 10; Outer.I1.B = 20; Outer.I2.C = 30 } """ + +module RecordSpreads = + open FSharp.Compiler.EditorServices + + [] + let ``spread - spread operator is not classified as a record field`` () = + let _, checkResults = + getParseAndCheckResultsPreview """ +type R1 = { A : int; B : int } +type R2 = { ...R1; C : int } +""" + let items = checkResults.GetSemanticClassification(None, RelatedSymbolUseKind.All) + let badItems = + items + |> Array.filter (fun i -> + i.Type = SemanticClassificationType.RecordField + && i.Range.StartLine = 3 + && i.Range.StartColumn < 15 + && i.Range.EndColumn > 12) + if badItems.Length > 0 then + failwith $"Expected the '...' spread operator to NOT be classified as RecordField, but found: %A{badItems |> Array.map (fun i -> getRangeCoords i.Range)}" + + [] + let ``spread - GetSymbolUseAtLocation range excludes leading spread operator`` () = + let _, checkResults = + getParseAndCheckResultsPreview """ +type R1 = { A : int; B : int } +let r1 = { A = 1; B = 2 } +let r2 = { ...r1; C = 3 } +""" + let line4 = "let r2 = { ...r1; C = 3 }" + match checkResults.GetSymbolUseAtLocation(4, 16, line4, [ "r1" ]) with + | None -> failwith "Expected to resolve symbol 'r1' inside the spread '...r1'." + | Some su -> + let spreadUse = + checkResults.GetUsesOfSymbolInFile(su.Symbol) + |> Array.find (fun u -> not u.IsFromDefinition) + if getRangeCoords su.Range <> getRangeCoords spreadUse.Range then + failwith $"GetSymbolUseAtLocation range %A{getRangeCoords su.Range} should match GetUsesOfSymbolInFile range %A{getRangeCoords spreadUse.Range} (no leading '...')." + + [] + let ``spread - GetSymbolUseAtLocation range excludes leading spread operator, anonymous`` () = + let _, checkResults = + getParseAndCheckResultsPreview """ +type R1 = { A : int; B : int } +let r1 = { A = 1; B = 2 } +let r2 = {| ...r1; C = 3 |} +""" + let line4 = "let r2 = {| ...r1; C = 3 |}" + match checkResults.GetSymbolUseAtLocation(4, 17, line4, [ "r1" ]) with + | None -> failwith "Expected to resolve symbol 'r1' inside the spread '...r1'." + | Some su -> + let spreadUse = + checkResults.GetUsesOfSymbolInFile(su.Symbol) + |> Array.find (fun u -> not u.IsFromDefinition) + if getRangeCoords su.Range <> getRangeCoords spreadUse.Range then + failwith $"GetSymbolUseAtLocation range %A{getRangeCoords su.Range} should match GetUsesOfSymbolInFile range %A{getRangeCoords spreadUse.Range} (no leading '...')." diff --git a/tests/FSharp.Compiler.Service.Tests/TreeVisitorTests.fs b/tests/FSharp.Compiler.Service.Tests/TreeVisitorTests.fs index 7d8b10502d3..aa9557b6016 100644 --- a/tests/FSharp.Compiler.Service.Tests/TreeVisitorTests.fs +++ b/tests/FSharp.Compiler.Service.Tests/TreeVisitorTests.fs @@ -31,7 +31,7 @@ let ``Visit record definition test`` () = let parseTree = parseSourceCode("C:\\test.fs", source) match SyntaxTraversal.Traverse(pos0, parseTree, visitor) with - | Some [ SynField (idOpt = Some id1); SynField (idOpt = Some id2) ] when id1.idText = "A" && id2.idText = "B" -> () + | Some [ SynFieldOrSpread.Field (SynField (idOpt = Some id1)); SynFieldOrSpread.Field (SynField (idOpt = Some id2)) ] when id1.idText = "A" && id2.idText = "B" -> () | _ -> failwith "Did not visit record definition" [] @@ -123,7 +123,7 @@ let ``Visit Record in SynTypeDefnSig`` () = { new SyntaxVisitorBase<_>() with member x.VisitRecordDefn(path, fields, range) = fields - |> List.choose (fun (SynField(idOpt = idOpt)) -> idOpt |> Option.map (fun ident -> ident.idText)) + |> List.choose (function SynFieldOrSpread.Field (SynField(idOpt = idOpt)) -> idOpt |> Option.map (fun ident -> ident.idText) | _ -> None) |> String.concat "," |> Some } diff --git a/tests/FSharp.Compiler.Service.Tests/XmlDocTests.fs b/tests/FSharp.Compiler.Service.Tests/XmlDocTests.fs index 8460938b7c1..5bab095f386 100644 --- a/tests/FSharp.Compiler.Service.Tests/XmlDocTests.fs +++ b/tests/FSharp.Compiler.Service.Tests/XmlDocTests.fs @@ -1,9 +1,10 @@ -module FSharp.Compiler.Service.Tests.XmlDocTests +module FSharp.Compiler.Service.Tests.XmlDocTests open FSharp.Compiler.CodeAnalysis open FSharp.Compiler.Service.Tests.Common open FSharp.Compiler.Symbols open FSharp.Compiler.Syntax +open FSharp.Compiler.SyntaxTreeOps open FSharp.Test.Compiler open FSharp.Test.Assert open Xunit @@ -74,9 +75,9 @@ let (|UnionCases|) = function | x -> failwith $"Unexpected ParsedInput %A{x}" let (|Record|) = function - | Types(_, [SynTypeDefn(typeRepr = SynTypeDefnRepr.Simple(simpleRepr = SynTypeDefnSimpleRepr.Record(recordFields = fields)))]) - | TypeSigs(_, [SynTypeDefnSig(typeRepr = SynTypeDefnSigRepr.Simple(repr = SynTypeDefnSimpleRepr.Record(recordFields = fields)))]) -> - Record(fields) + | Types(_, [SynTypeDefn(typeRepr = SynTypeDefnRepr.Simple(simpleRepr = SynTypeDefnSimpleRepr.Record(recordFieldsAndSpreads = fieldsAndSpreads)))]) + | TypeSigs(_, [SynTypeDefnSig(typeRepr = SynTypeDefnSigRepr.Simple(repr = SynTypeDefnSimpleRepr.Record(recordFieldsAndSpreads = fieldsAndSpreads)))]) -> + Record(fieldsAndSpreads |> List.choose (function SynFieldOrSpread.Field f -> Some f | SynFieldOrSpread.Spread _ -> None)) | x -> failwith $"Unexpected ParsedInput %A{x}" diff --git a/tests/service/data/SyntaxTree/Expression/AnonRecd - Quotation 01.fs.bsl b/tests/service/data/SyntaxTree/Expression/AnonRecd - Quotation 01.fs.bsl index 7f3dd8badf2..4b7277f1513 100644 --- a/tests/service/data/SyntaxTree/Expression/AnonRecd - Quotation 01.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/AnonRecd - Quotation 01.fs.bsl @@ -7,60 +7,69 @@ ImplFile [Expr (AnonRecd (false, None, - [(SynLongIdent ([A], [], [None]), Some (3,5--3,6), - Quote - (Ident op_Quotation, false, - App - (NonAtomic, false, - App - (NonAtomic, true, - LongIdent - (false, - SynLongIdent - ([op_Addition], [], - [Some (OriginalNotation "+")]), None, - (3,12--3,13)), Const (Int32 1, (3,10--3,11)), - (3,10--3,13)), Const (Int32 1, (3,14--3,15)), - (3,10--3,15)), false, (3,7--3,18)))], (3,0--3,20), - { OpeningBraceRange = (3,0--3,2) }), (3,0--3,20)); + [Field + (SynExprAnonRecordField + (SynLongIdent ([A], [], [None]), Some (3,5--3,6), + Quote + (Ident op_Quotation, false, + App + (NonAtomic, false, + App + (NonAtomic, true, + LongIdent + (false, + SynLongIdent + ([op_Addition], [], + [Some (OriginalNotation "+")]), None, + (3,12--3,13)), Const (Int32 1, (3,10--3,11)), + (3,10--3,13)), Const (Int32 1, (3,14--3,15)), + (3,10--3,15)), false, (3,7--3,18)), (3,3--3,18)), + None)], (3,0--3,20), { OpeningBraceRange = (3,0--3,2) }), + (3,0--3,20)); Expr (AnonRecd (false, None, - [(SynLongIdent ([A], [], [None]), Some (5,4--5,5), - Quote - (Ident op_Quotation, false, - App - (NonAtomic, false, - App - (NonAtomic, true, - LongIdent - (false, - SynLongIdent - ([op_Addition], [], - [Some (OriginalNotation "+")]), None, - (5,11--5,12)), Const (Int32 1, (5,9--5,10)), - (5,9--5,12)), Const (Int32 1, (5,13--5,14)), - (5,9--5,14)), false, (5,6--5,17)))], (5,0--5,20), - { OpeningBraceRange = (5,0--5,2) }), (5,0--5,20)); + [Field + (SynExprAnonRecordField + (SynLongIdent ([A], [], [None]), Some (5,4--5,5), + Quote + (Ident op_Quotation, false, + App + (NonAtomic, false, + App + (NonAtomic, true, + LongIdent + (false, + SynLongIdent + ([op_Addition], [], + [Some (OriginalNotation "+")]), None, + (5,11--5,12)), Const (Int32 1, (5,9--5,10)), + (5,9--5,12)), Const (Int32 1, (5,13--5,14)), + (5,9--5,14)), false, (5,6--5,17)), (5,2--5,17)), + None)], (5,0--5,20), { OpeningBraceRange = (5,0--5,2) }), + (5,0--5,20)); Expr (AnonRecd (false, None, - [(SynLongIdent ([A], [], [None]), Some (7,5--7,6), - Quote - (Ident op_Quotation, false, - App - (NonAtomic, false, - App - (NonAtomic, true, - LongIdent - (false, - SynLongIdent - ([op_Addition], [], - [Some (OriginalNotation "+")]), None, - (7,12--7,13)), Const (Int32 1, (7,10--7,11)), - (7,10--7,13)), Const (Int32 1, (7,14--7,15)), - (7,10--7,15)), false, (7,7--7,18)))], (7,0--7,21), - { OpeningBraceRange = (7,0--7,2) }), (7,0--7,21))], + [Field + (SynExprAnonRecordField + (SynLongIdent ([A], [], [None]), Some (7,5--7,6), + Quote + (Ident op_Quotation, false, + App + (NonAtomic, false, + App + (NonAtomic, true, + LongIdent + (false, + SynLongIdent + ([op_Addition], [], + [Some (OriginalNotation "+")]), None, + (7,12--7,13)), Const (Int32 1, (7,10--7,11)), + (7,10--7,13)), Const (Int32 1, (7,14--7,15)), + (7,10--7,15)), false, (7,7--7,18)), (7,3--7,18)), + None)], (7,0--7,21), { OpeningBraceRange = (7,0--7,2) }), + (7,0--7,21))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--7,21), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] diff --git a/tests/service/data/SyntaxTree/Expression/AnonRecd - Quotation 02.fs.bsl b/tests/service/data/SyntaxTree/Expression/AnonRecd - Quotation 02.fs.bsl index a17975ba1da..0c4619eda96 100644 --- a/tests/service/data/SyntaxTree/Expression/AnonRecd - Quotation 02.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/AnonRecd - Quotation 02.fs.bsl @@ -7,60 +7,69 @@ ImplFile [Expr (AnonRecd (false, None, - [(SynLongIdent ([A], [], [None]), Some (3,5--3,6), - Quote - (Ident op_QuotationUntyped, true, - App - (NonAtomic, false, - App - (NonAtomic, true, - LongIdent - (false, - SynLongIdent - ([op_Addition], [], - [Some (OriginalNotation "+")]), None, - (3,13--3,14)), Const (Int32 1, (3,11--3,12)), - (3,11--3,14)), Const (Int32 1, (3,15--3,16)), - (3,11--3,16)), false, (3,7--3,20)))], (3,0--3,22), - { OpeningBraceRange = (3,0--3,2) }), (3,0--3,22)); + [Field + (SynExprAnonRecordField + (SynLongIdent ([A], [], [None]), Some (3,5--3,6), + Quote + (Ident op_QuotationUntyped, true, + App + (NonAtomic, false, + App + (NonAtomic, true, + LongIdent + (false, + SynLongIdent + ([op_Addition], [], + [Some (OriginalNotation "+")]), None, + (3,13--3,14)), Const (Int32 1, (3,11--3,12)), + (3,11--3,14)), Const (Int32 1, (3,15--3,16)), + (3,11--3,16)), false, (3,7--3,20)), (3,3--3,20)), + None)], (3,0--3,22), { OpeningBraceRange = (3,0--3,2) }), + (3,0--3,22)); Expr (AnonRecd (false, None, - [(SynLongIdent ([A], [], [None]), Some (5,4--5,5), - Quote - (Ident op_QuotationUntyped, true, - App - (NonAtomic, false, - App - (NonAtomic, true, - LongIdent - (false, - SynLongIdent - ([op_Addition], [], - [Some (OriginalNotation "+")]), None, - (5,12--5,13)), Const (Int32 1, (5,10--5,11)), - (5,10--5,13)), Const (Int32 1, (5,14--5,15)), - (5,10--5,15)), false, (5,6--5,19)))], (5,0--5,22), - { OpeningBraceRange = (5,0--5,2) }), (5,0--5,22)); + [Field + (SynExprAnonRecordField + (SynLongIdent ([A], [], [None]), Some (5,4--5,5), + Quote + (Ident op_QuotationUntyped, true, + App + (NonAtomic, false, + App + (NonAtomic, true, + LongIdent + (false, + SynLongIdent + ([op_Addition], [], + [Some (OriginalNotation "+")]), None, + (5,12--5,13)), Const (Int32 1, (5,10--5,11)), + (5,10--5,13)), Const (Int32 1, (5,14--5,15)), + (5,10--5,15)), false, (5,6--5,19)), (5,2--5,19)), + None)], (5,0--5,22), { OpeningBraceRange = (5,0--5,2) }), + (5,0--5,22)); Expr (AnonRecd (false, None, - [(SynLongIdent ([A], [], [None]), Some (7,5--7,6), - Quote - (Ident op_QuotationUntyped, true, - App - (NonAtomic, false, - App - (NonAtomic, true, - LongIdent - (false, - SynLongIdent - ([op_Addition], [], - [Some (OriginalNotation "+")]), None, - (7,13--7,14)), Const (Int32 1, (7,11--7,12)), - (7,11--7,14)), Const (Int32 1, (7,15--7,16)), - (7,11--7,16)), false, (7,7--7,20)))], (7,0--7,23), - { OpeningBraceRange = (7,0--7,2) }), (7,0--7,23))], + [Field + (SynExprAnonRecordField + (SynLongIdent ([A], [], [None]), Some (7,5--7,6), + Quote + (Ident op_QuotationUntyped, true, + App + (NonAtomic, false, + App + (NonAtomic, true, + LongIdent + (false, + SynLongIdent + ([op_Addition], [], + [Some (OriginalNotation "+")]), None, + (7,13--7,14)), Const (Int32 1, (7,11--7,12)), + (7,11--7,14)), Const (Int32 1, (7,15--7,16)), + (7,11--7,16)), false, (7,7--7,20)), (7,3--7,20)), + None)], (7,0--7,23), { OpeningBraceRange = (7,0--7,2) }), + (7,0--7,23))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--7,23), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] diff --git a/tests/service/data/SyntaxTree/Expression/AnonRecd - Quotation 03.fs.bsl b/tests/service/data/SyntaxTree/Expression/AnonRecd - Quotation 03.fs.bsl index 91f4963b53c..d319e9d8aed 100644 --- a/tests/service/data/SyntaxTree/Expression/AnonRecd - Quotation 03.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/AnonRecd - Quotation 03.fs.bsl @@ -7,78 +7,96 @@ ImplFile [Expr (AnonRecd (false, None, - [(SynLongIdent ([A], [], [None]), Some (3,5--3,6), - Quote - (Ident op_Quotation, false, - App - (NonAtomic, false, - App - (NonAtomic, true, - LongIdent - (false, - SynLongIdent - ([op_Addition], [], - [Some (OriginalNotation "+")]), None, - (3,12--3,13)), Const (Int32 1, (3,10--3,11)), - (3,10--3,13)), Const (Int32 1, (3,14--3,15)), - (3,10--3,15)), false, (3,7--3,18))); - (SynLongIdent ([B], [], [None]), Some (3,22--3,23), - Quote - (Ident op_QuotationUntyped, true, - Const - (String ("test", Regular, (3,28--3,34)), (3,28--3,34)), - false, (3,24--3,38)))], (3,0--3,40), - { OpeningBraceRange = (3,0--3,2) }), (3,0--3,40)); + [Field + (SynExprAnonRecordField + (SynLongIdent ([A], [], [None]), Some (3,5--3,6), + Quote + (Ident op_Quotation, false, + App + (NonAtomic, false, + App + (NonAtomic, true, + LongIdent + (false, + SynLongIdent + ([op_Addition], [], + [Some (OriginalNotation "+")]), None, + (3,12--3,13)), Const (Int32 1, (3,10--3,11)), + (3,10--3,13)), Const (Int32 1, (3,14--3,15)), + (3,10--3,15)), false, (3,7--3,18)), (3,3--3,18)), + Some ((3,18--3,19), Some (3,19))); + Field + (SynExprAnonRecordField + (SynLongIdent ([B], [], [None]), Some (3,22--3,23), + Quote + (Ident op_QuotationUntyped, true, + Const + (String ("test", Regular, (3,28--3,34)), + (3,28--3,34)), false, (3,24--3,38)), (3,20--3,38)), + None)], (3,0--3,40), { OpeningBraceRange = (3,0--3,2) }), + (3,0--3,40)); Expr (AnonRecd (false, None, - [(SynLongIdent ([A], [], [None]), Some (5,4--5,5), - Quote - (Ident op_Quotation, false, - App - (NonAtomic, false, - App - (NonAtomic, true, - LongIdent - (false, - SynLongIdent - ([op_Addition], [], - [Some (OriginalNotation "+")]), None, - (5,11--5,12)), Const (Int32 1, (5,9--5,10)), - (5,9--5,12)), Const (Int32 1, (5,13--5,14)), - (5,9--5,14)), false, (5,6--5,17))); - (SynLongIdent ([B], [], [None]), Some (5,21--5,22), - Quote - (Ident op_QuotationUntyped, true, - Const - (String ("test", Regular, (5,27--5,33)), (5,27--5,33)), - false, (5,23--5,37)))], (5,0--5,40), - { OpeningBraceRange = (5,0--5,2) }), (5,0--5,40)); + [Field + (SynExprAnonRecordField + (SynLongIdent ([A], [], [None]), Some (5,4--5,5), + Quote + (Ident op_Quotation, false, + App + (NonAtomic, false, + App + (NonAtomic, true, + LongIdent + (false, + SynLongIdent + ([op_Addition], [], + [Some (OriginalNotation "+")]), None, + (5,11--5,12)), Const (Int32 1, (5,9--5,10)), + (5,9--5,12)), Const (Int32 1, (5,13--5,14)), + (5,9--5,14)), false, (5,6--5,17)), (5,2--5,17)), + Some ((5,17--5,18), Some (5,18))); + Field + (SynExprAnonRecordField + (SynLongIdent ([B], [], [None]), Some (5,21--5,22), + Quote + (Ident op_QuotationUntyped, true, + Const + (String ("test", Regular, (5,27--5,33)), + (5,27--5,33)), false, (5,23--5,37)), (5,19--5,37)), + None)], (5,0--5,40), { OpeningBraceRange = (5,0--5,2) }), + (5,0--5,40)); Expr (AnonRecd (false, None, - [(SynLongIdent ([A], [], [None]), Some (7,5--7,6), - Quote - (Ident op_Quotation, false, - App - (NonAtomic, false, - App - (NonAtomic, true, - LongIdent - (false, - SynLongIdent - ([op_Addition], [], - [Some (OriginalNotation "+")]), None, - (7,12--7,13)), Const (Int32 1, (7,10--7,11)), - (7,10--7,13)), Const (Int32 1, (7,14--7,15)), - (7,10--7,15)), false, (7,7--7,18))); - (SynLongIdent ([B], [], [None]), Some (7,22--7,23), - Quote - (Ident op_QuotationUntyped, true, - Const - (String ("test", Regular, (7,28--7,34)), (7,28--7,34)), - false, (7,24--7,38)))], (7,0--7,41), - { OpeningBraceRange = (7,0--7,2) }), (7,0--7,41))], + [Field + (SynExprAnonRecordField + (SynLongIdent ([A], [], [None]), Some (7,5--7,6), + Quote + (Ident op_Quotation, false, + App + (NonAtomic, false, + App + (NonAtomic, true, + LongIdent + (false, + SynLongIdent + ([op_Addition], [], + [Some (OriginalNotation "+")]), None, + (7,12--7,13)), Const (Int32 1, (7,10--7,11)), + (7,10--7,13)), Const (Int32 1, (7,14--7,15)), + (7,10--7,15)), false, (7,7--7,18)), (7,3--7,18)), + Some ((7,18--7,19), Some (7,19))); + Field + (SynExprAnonRecordField + (SynLongIdent ([B], [], [None]), Some (7,22--7,23), + Quote + (Ident op_QuotationUntyped, true, + Const + (String ("test", Regular, (7,28--7,34)), + (7,28--7,34)), false, (7,24--7,38)), (7,20--7,38)), + None)], (7,0--7,41), { OpeningBraceRange = (7,0--7,2) }), + (7,0--7,41))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--7,41), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] diff --git a/tests/service/data/SyntaxTree/Expression/AnonRecd - Quotation 04.fs.bsl b/tests/service/data/SyntaxTree/Expression/AnonRecd - Quotation 04.fs.bsl index 5577001a81e..e0f12c90800 100644 --- a/tests/service/data/SyntaxTree/Expression/AnonRecd - Quotation 04.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/AnonRecd - Quotation 04.fs.bsl @@ -7,57 +7,87 @@ ImplFile [Expr (AnonRecd (false, None, - [(SynLongIdent ([Outer], [], [None]), Some (3,9--3,10), - AnonRecd - (false, None, - [(SynLongIdent ([Inner], [], [None]), Some (3,20--3,21), + [Field + (SynExprAnonRecordField + (SynLongIdent ([Outer], [], [None]), Some (3,9--3,10), + AnonRecd + (false, None, + [Field + (SynExprAnonRecordField + (SynLongIdent ([Inner], [], [None]), + Some (3,20--3,21), + Quote + (Ident op_Quotation, false, + Const (Int32 1, (3,25--3,26)), false, + (3,22--3,29)), (3,14--3,29)), None)], + (3,11--3,31), { OpeningBraceRange = (3,11--3,13) }), + (3,3--3,31)), Some ((3,31--3,32), Some (3,32))); + Field + (SynExprAnonRecordField + (SynLongIdent ([Other], [], [None]), Some (3,39--3,40), Quote - (Ident op_Quotation, false, - Const (Int32 1, (3,25--3,26)), false, (3,22--3,29)))], - (3,11--3,31), { OpeningBraceRange = (3,11--3,13) })); - (SynLongIdent ([Other], [], [None]), Some (3,39--3,40), - Quote - (Ident op_QuotationUntyped, true, - Const - (String ("test", Regular, (3,45--3,51)), (3,45--3,51)), - false, (3,41--3,55)))], (3,0--3,57), - { OpeningBraceRange = (3,0--3,2) }), (3,0--3,57)); + (Ident op_QuotationUntyped, true, + Const + (String ("test", Regular, (3,45--3,51)), + (3,45--3,51)), false, (3,41--3,55)), (3,33--3,55)), + None)], (3,0--3,57), { OpeningBraceRange = (3,0--3,2) }), + (3,0--3,57)); Expr (AnonRecd (false, None, - [(SynLongIdent ([Outer], [], [None]), Some (5,8--5,9), - AnonRecd - (false, None, - [(SynLongIdent ([Inner], [], [None]), Some (5,19--5,20), + [Field + (SynExprAnonRecordField + (SynLongIdent ([Outer], [], [None]), Some (5,8--5,9), + AnonRecd + (false, None, + [Field + (SynExprAnonRecordField + (SynLongIdent ([Inner], [], [None]), + Some (5,19--5,20), + Quote + (Ident op_Quotation, false, + Const (Int32 1, (5,24--5,25)), false, + (5,21--5,28)), (5,13--5,28)), None)], + (5,10--5,30), { OpeningBraceRange = (5,10--5,12) }), + (5,2--5,30)), Some ((5,30--5,31), Some (5,31))); + Field + (SynExprAnonRecordField + (SynLongIdent ([Other], [], [None]), Some (5,38--5,39), Quote - (Ident op_Quotation, false, - Const (Int32 1, (5,24--5,25)), false, (5,21--5,28)))], - (5,10--5,30), { OpeningBraceRange = (5,10--5,12) })); - (SynLongIdent ([Other], [], [None]), Some (5,38--5,39), - Quote - (Ident op_QuotationUntyped, true, - Const - (String ("test", Regular, (5,44--5,50)), (5,44--5,50)), - false, (5,40--5,54)))], (5,0--5,57), - { OpeningBraceRange = (5,0--5,2) }), (5,0--5,57)); + (Ident op_QuotationUntyped, true, + Const + (String ("test", Regular, (5,44--5,50)), + (5,44--5,50)), false, (5,40--5,54)), (5,32--5,54)), + None)], (5,0--5,57), { OpeningBraceRange = (5,0--5,2) }), + (5,0--5,57)); Expr (AnonRecd (false, None, - [(SynLongIdent ([Outer], [], [None]), Some (7,9--7,10), - AnonRecd - (false, None, - [(SynLongIdent ([Inner], [], [None]), Some (7,20--7,21), + [Field + (SynExprAnonRecordField + (SynLongIdent ([Outer], [], [None]), Some (7,9--7,10), + AnonRecd + (false, None, + [Field + (SynExprAnonRecordField + (SynLongIdent ([Inner], [], [None]), + Some (7,20--7,21), + Quote + (Ident op_Quotation, false, + Const (Int32 1, (7,25--7,26)), false, + (7,22--7,29)), (7,14--7,29)), None)], + (7,11--7,31), { OpeningBraceRange = (7,11--7,13) }), + (7,3--7,31)), Some ((7,31--7,32), Some (7,32))); + Field + (SynExprAnonRecordField + (SynLongIdent ([Other], [], [None]), Some (7,39--7,40), Quote - (Ident op_Quotation, false, - Const (Int32 1, (7,25--7,26)), false, (7,22--7,29)))], - (7,11--7,31), { OpeningBraceRange = (7,11--7,13) })); - (SynLongIdent ([Other], [], [None]), Some (7,39--7,40), - Quote - (Ident op_QuotationUntyped, true, - Const - (String ("test", Regular, (7,45--7,51)), (7,45--7,51)), - false, (7,41--7,55)))], (7,0--7,58), - { OpeningBraceRange = (7,0--7,2) }), (7,0--7,58))], + (Ident op_QuotationUntyped, true, + Const + (String ("test", Regular, (7,45--7,51)), + (7,45--7,51)), false, (7,41--7,55)), (7,33--7,55)), + None)], (7,0--7,58), { OpeningBraceRange = (7,0--7,2) }), + (7,0--7,58))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--7,58), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] diff --git a/tests/service/data/SyntaxTree/Expression/AnonymousRecords-01.fs.bsl b/tests/service/data/SyntaxTree/Expression/AnonymousRecords-01.fs.bsl index 7dbc5c7695b..1b6ede77ff8 100644 --- a/tests/service/data/SyntaxTree/Expression/AnonymousRecords-01.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/AnonymousRecords-01.fs.bsl @@ -7,15 +7,19 @@ ImplFile [Expr (AnonRecd (false, None, - [(SynLongIdent ([X], [], [None]), Some (1,5--1,6), - Const (Int32 1, (1,7--1,8)))], (1,0--1,11), - { OpeningBraceRange = (1,0--1,2) }), (1,0--1,11)); + [Field + (SynExprAnonRecordField + (SynLongIdent ([X], [], [None]), Some (1,5--1,6), + Const (Int32 1, (1,7--1,8)), (1,3--1,8)), None)], + (1,0--1,11), { OpeningBraceRange = (1,0--1,2) }), (1,0--1,11)); Expr (AnonRecd (true, None, - [(SynLongIdent ([Y], [], [None]), Some (2,12--2,13), - Const (Int32 2, (2,14--2,15)))], (2,0--2,18), - { OpeningBraceRange = (2,7--2,9) }), (2,0--2,18)); + [Field + (SynExprAnonRecordField + (SynLongIdent ([Y], [], [None]), Some (2,12--2,13), + Const (Int32 2, (2,14--2,15)), (2,10--2,15)), None)], + (2,0--2,18), { OpeningBraceRange = (2,7--2,9) }), (2,0--2,18)); Expr (AnonRecd (false, None, [], (3,0--3,5), { OpeningBraceRange = (3,0--3,2) }), diff --git a/tests/service/data/SyntaxTree/Expression/AnonymousRecords-02.fs.bsl b/tests/service/data/SyntaxTree/Expression/AnonymousRecords-02.fs.bsl index fc0a410b79e..c5c448e1dab 100644 --- a/tests/service/data/SyntaxTree/Expression/AnonymousRecords-02.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/AnonymousRecords-02.fs.bsl @@ -7,9 +7,11 @@ ImplFile [Expr (AnonRecd (false, None, - [(SynLongIdent ([X], [], [None]), Some (1,5--1,6), - Const (Int32 0, (1,7--1,8)))], (1,0--2,0), - { OpeningBraceRange = (1,0--1,2) }), (1,0--2,0))], + [Field + (SynExprAnonRecordField + (SynLongIdent ([X], [], [None]), Some (1,5--1,6), + Const (Int32 0, (1,7--1,8)), (1,3--1,8)), None)], + (1,0--2,0), { OpeningBraceRange = (1,0--1,2) }), (1,0--2,0))], PreXmlDocEmpty, [], None, (1,0--2,0), { LeadingKeyword = None })], (true, true), { ConditionalDirectives = [] WarnDirectives = [] diff --git a/tests/service/data/SyntaxTree/Expression/AnonymousRecords-03.fs.bsl b/tests/service/data/SyntaxTree/Expression/AnonymousRecords-03.fs.bsl index 4582e5eca53..d8c1e6ee62b 100644 --- a/tests/service/data/SyntaxTree/Expression/AnonymousRecords-03.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/AnonymousRecords-03.fs.bsl @@ -7,9 +7,11 @@ ImplFile [Expr (AnonRecd (true, None, - [(SynLongIdent ([X], [], [None]), Some (1,12--1,13), - Const (Int32 0, (1,14--1,15)))], (1,0--2,0), - { OpeningBraceRange = (1,7--1,9) }), (1,0--2,0))], + [Field + (SynExprAnonRecordField + (SynLongIdent ([X], [], [None]), Some (1,12--1,13), + Const (Int32 0, (1,14--1,15)), (1,10--1,15)), None)], + (1,0--2,0), { OpeningBraceRange = (1,7--1,9) }), (1,0--2,0))], PreXmlDocEmpty, [], None, (1,0--2,0), { LeadingKeyword = None })], (true, true), { ConditionalDirectives = [] WarnDirectives = [] diff --git a/tests/service/data/SyntaxTree/Expression/AnonymousRecords-06.fs.bsl b/tests/service/data/SyntaxTree/Expression/AnonymousRecords-06.fs.bsl index b58b5e4c944..e9f15787514 100644 --- a/tests/service/data/SyntaxTree/Expression/AnonymousRecords-06.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/AnonymousRecords-06.fs.bsl @@ -20,17 +20,23 @@ ImplFile None, (1,4--1,7)), None, AnonRecd (false, Some (Ident x, ((1,15--1,19), None)), - [(SynLongIdent ([R; D], [(1,21--1,22)], [None; None]), - Some (1,24--1,25), - Const (String ("s", Regular, (1,26--1,29)), (1,26--1,29))); - (SynLongIdent ([A], [], [None]), Some (1,33--1,34), - Const (Int32 3, (1,35--1,36)))], (1,10--1,39), - { OpeningBraceRange = (1,10--1,12) }), (1,4--1,7), - NoneAtLet, { LeadingKeyword = Let (1,0--1,3) - InlineKeyword = None - EqualsRange = Some (1,8--1,9) })], (1,0--1,39), - { InKeyword = None })], PreXmlDocEmpty, [], None, (1,0--2,0), - { LeadingKeyword = None })], (true, true), + [Field + (SynExprAnonRecordField + (SynLongIdent ([R; D], [(1,21--1,22)], [None; None]), + Some (1,24--1,25), + Const + (String ("s", Regular, (1,26--1,29)), (1,26--1,29)), + (1,20--1,29)), Some ((1,29--1,30), Some (1,30))); + Field + (SynExprAnonRecordField + (SynLongIdent ([A], [], [None]), Some (1,33--1,34), + Const (Int32 3, (1,35--1,36)), (1,31--1,36)), None)], + (1,10--1,39), { OpeningBraceRange = (1,10--1,12) }), + (1,4--1,7), NoneAtLet, { LeadingKeyword = Let (1,0--1,3) + InlineKeyword = None + EqualsRange = Some (1,8--1,9) })], + (1,0--1,39), { InKeyword = None })], PreXmlDocEmpty, [], None, + (1,0--2,0), { LeadingKeyword = None })], (true, true), { ConditionalDirectives = [] WarnDirectives = [] CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Expression/AnonymousRecords-07.fs.bsl b/tests/service/data/SyntaxTree/Expression/AnonymousRecords-07.fs.bsl index a8ff99d1b82..9221dc5414f 100644 --- a/tests/service/data/SyntaxTree/Expression/AnonymousRecords-07.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/AnonymousRecords-07.fs.bsl @@ -7,47 +7,59 @@ ImplFile [Expr (AnonRecd (false, None, - [(SynLongIdent ([a], [], [None]), Some (3,3--3,4), - Const - (Measure - (Int32 1, (3,4--3,5), - Seq ([Named ([m], (3,6--3,7))], (3,6--3,7)), - { LessRange = (3,5--3,6) - GreaterRange = (3,7--3,8) }), (3,4--3,8)))], - (3,0--3,11), { OpeningBraceRange = (3,0--3,2) }), (3,0--3,11)); + [Field + (SynExprAnonRecordField + (SynLongIdent ([a], [], [None]), Some (3,3--3,4), + Const + (Measure + (Int32 1, (3,4--3,5), + Seq ([Named ([m], (3,6--3,7))], (3,6--3,7)), + { LessRange = (3,5--3,6) + GreaterRange = (3,7--3,8) }), (3,4--3,8)), + (3,2--3,8)), None)], (3,0--3,11), + { OpeningBraceRange = (3,0--3,2) }), (3,0--3,11)); Expr (AnonRecd (false, None, - [(SynLongIdent ([a], [], [None]), Some (5,3--5,4), - Const - (Measure - (Int32 1, (5,4--5,5), - Seq ([Named ([m], (5,6--5,7))], (5,6--5,7)), - { LessRange = (5,5--5,6) - GreaterRange = (5,7--5,8) }), (5,4--5,8)))], - (5,0--5,10), { OpeningBraceRange = (5,0--5,2) }), (5,0--5,10)); + [Field + (SynExprAnonRecordField + (SynLongIdent ([a], [], [None]), Some (5,3--5,4), + Const + (Measure + (Int32 1, (5,4--5,5), + Seq ([Named ([m], (5,6--5,7))], (5,6--5,7)), + { LessRange = (5,5--5,6) + GreaterRange = (5,7--5,8) }), (5,4--5,8)), + (5,2--5,8)), None)], (5,0--5,10), + { OpeningBraceRange = (5,0--5,2) }), (5,0--5,10)); Expr (AnonRecd (false, None, - [(SynLongIdent ([a], [], [None]), Some (7,4--7,5), - Const - (Measure - (Int32 1, (7,5--7,6), - Seq ([Named ([m], (7,7--7,8))], (7,7--7,8)), - { LessRange = (7,6--7,7) - GreaterRange = (7,8--7,9) }), (7,5--7,9)))], - (7,0--7,11), { OpeningBraceRange = (7,0--7,2) }), (7,0--7,11)); + [Field + (SynExprAnonRecordField + (SynLongIdent ([a], [], [None]), Some (7,4--7,5), + Const + (Measure + (Int32 1, (7,5--7,6), + Seq ([Named ([m], (7,7--7,8))], (7,7--7,8)), + { LessRange = (7,6--7,7) + GreaterRange = (7,8--7,9) }), (7,5--7,9)), + (7,3--7,9)), None)], (7,0--7,11), + { OpeningBraceRange = (7,0--7,2) }), (7,0--7,11)); Expr (AnonRecd (false, None, - [(SynLongIdent ([a], [], [None]), Some (9,4--9,5), - Const - (Measure - (Int32 1, (9,5--9,6), - Seq ([Named ([m], (9,7--9,8))], (9,7--9,8)), - { LessRange = (9,6--9,7) - GreaterRange = (9,8--9,9) }), (9,5--9,9)))], - (9,0--9,12), { OpeningBraceRange = (9,0--9,2) }), (9,0--9,12))], + [Field + (SynExprAnonRecordField + (SynLongIdent ([a], [], [None]), Some (9,4--9,5), + Const + (Measure + (Int32 1, (9,5--9,6), + Seq ([Named ([m], (9,7--9,8))], (9,7--9,8)), + { LessRange = (9,6--9,7) + GreaterRange = (9,8--9,9) }), (9,5--9,9)), + (9,3--9,9)), None)], (9,0--9,12), + { OpeningBraceRange = (9,0--9,2) }), (9,0--9,12))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--9,12), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] diff --git a/tests/service/data/SyntaxTree/Expression/AnonymousRecords-08.fs.bsl b/tests/service/data/SyntaxTree/Expression/AnonymousRecords-08.fs.bsl index ed640191c59..126203ce6bf 100644 --- a/tests/service/data/SyntaxTree/Expression/AnonymousRecords-08.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/AnonymousRecords-08.fs.bsl @@ -7,75 +7,99 @@ ImplFile [Expr (AnonRecd (false, None, - [(SynLongIdent ([a], [], [None]), Some (3,3--3,4), - Const - (Measure - (Int32 1, (3,4--3,5), - Seq ([Named ([m], (3,6--3,7))], (3,6--3,7)), - { LessRange = (3,5--3,6) - GreaterRange = (3,7--3,8) }), (3,4--3,8))); - (SynLongIdent ([b], [], [None]), Some (3,11--3,12), - Const - (Measure - (Int32 2, (3,12--3,13), - Seq ([Named ([m], (3,14--3,15))], (3,14--3,15)), - { LessRange = (3,13--3,14) - GreaterRange = (3,15--3,16) }), (3,12--3,16)))], - (3,0--3,19), { OpeningBraceRange = (3,0--3,2) }), (3,0--3,19)); + [Field + (SynExprAnonRecordField + (SynLongIdent ([a], [], [None]), Some (3,3--3,4), + Const + (Measure + (Int32 1, (3,4--3,5), + Seq ([Named ([m], (3,6--3,7))], (3,6--3,7)), + { LessRange = (3,5--3,6) + GreaterRange = (3,7--3,8) }), (3,4--3,8)), + (3,2--3,8)), Some ((3,8--3,9), Some (3,9))); + Field + (SynExprAnonRecordField + (SynLongIdent ([b], [], [None]), Some (3,11--3,12), + Const + (Measure + (Int32 2, (3,12--3,13), + Seq ([Named ([m], (3,14--3,15))], (3,14--3,15)), + { LessRange = (3,13--3,14) + GreaterRange = (3,15--3,16) }), (3,12--3,16)), + (3,10--3,16)), None)], (3,0--3,19), + { OpeningBraceRange = (3,0--3,2) }), (3,0--3,19)); Expr (AnonRecd (false, None, - [(SynLongIdent ([a], [], [None]), Some (5,3--5,4), - Const - (Measure - (Int32 1, (5,4--5,5), - Seq ([Named ([m], (5,6--5,7))], (5,6--5,7)), - { LessRange = (5,5--5,6) - GreaterRange = (5,7--5,8) }), (5,4--5,8))); - (SynLongIdent ([b], [], [None]), Some (5,11--5,12), - Const - (Measure - (Int32 2, (5,12--5,13), - Seq ([Named ([m], (5,14--5,15))], (5,14--5,15)), - { LessRange = (5,13--5,14) - GreaterRange = (5,15--5,16) }), (5,12--5,16)))], - (5,0--5,18), { OpeningBraceRange = (5,0--5,2) }), (5,0--5,18)); + [Field + (SynExprAnonRecordField + (SynLongIdent ([a], [], [None]), Some (5,3--5,4), + Const + (Measure + (Int32 1, (5,4--5,5), + Seq ([Named ([m], (5,6--5,7))], (5,6--5,7)), + { LessRange = (5,5--5,6) + GreaterRange = (5,7--5,8) }), (5,4--5,8)), + (5,2--5,8)), Some ((5,8--5,9), Some (5,9))); + Field + (SynExprAnonRecordField + (SynLongIdent ([b], [], [None]), Some (5,11--5,12), + Const + (Measure + (Int32 2, (5,12--5,13), + Seq ([Named ([m], (5,14--5,15))], (5,14--5,15)), + { LessRange = (5,13--5,14) + GreaterRange = (5,15--5,16) }), (5,12--5,16)), + (5,10--5,16)), None)], (5,0--5,18), + { OpeningBraceRange = (5,0--5,2) }), (5,0--5,18)); Expr (AnonRecd (false, None, - [(SynLongIdent ([a], [], [None]), Some (7,4--7,5), - Const - (Measure - (Int32 1, (7,5--7,6), - Seq ([Named ([m], (7,7--7,8))], (7,7--7,8)), - { LessRange = (7,6--7,7) - GreaterRange = (7,8--7,9) }), (7,5--7,9))); - (SynLongIdent ([b], [], [None]), Some (7,12--7,13), - Const - (Measure - (Int32 2, (7,13--7,14), - Seq ([Named ([m], (7,15--7,16))], (7,15--7,16)), - { LessRange = (7,14--7,15) - GreaterRange = (7,16--7,17) }), (7,13--7,17)))], - (7,0--7,19), { OpeningBraceRange = (7,0--7,2) }), (7,0--7,19)); + [Field + (SynExprAnonRecordField + (SynLongIdent ([a], [], [None]), Some (7,4--7,5), + Const + (Measure + (Int32 1, (7,5--7,6), + Seq ([Named ([m], (7,7--7,8))], (7,7--7,8)), + { LessRange = (7,6--7,7) + GreaterRange = (7,8--7,9) }), (7,5--7,9)), + (7,3--7,9)), Some ((7,9--7,10), Some (7,10))); + Field + (SynExprAnonRecordField + (SynLongIdent ([b], [], [None]), Some (7,12--7,13), + Const + (Measure + (Int32 2, (7,13--7,14), + Seq ([Named ([m], (7,15--7,16))], (7,15--7,16)), + { LessRange = (7,14--7,15) + GreaterRange = (7,16--7,17) }), (7,13--7,17)), + (7,11--7,17)), None)], (7,0--7,19), + { OpeningBraceRange = (7,0--7,2) }), (7,0--7,19)); Expr (AnonRecd (false, None, - [(SynLongIdent ([a], [], [None]), Some (9,4--9,5), - Const - (Measure - (Int32 1, (9,5--9,6), - Seq ([Named ([m], (9,7--9,8))], (9,7--9,8)), - { LessRange = (9,6--9,7) - GreaterRange = (9,8--9,9) }), (9,5--9,9))); - (SynLongIdent ([b], [], [None]), Some (9,12--9,13), - Const - (Measure - (Int32 2, (9,13--9,14), - Seq ([Named ([m], (9,15--9,16))], (9,15--9,16)), - { LessRange = (9,14--9,15) - GreaterRange = (9,16--9,17) }), (9,13--9,17)))], - (9,0--9,20), { OpeningBraceRange = (9,0--9,2) }), (9,0--9,20))], + [Field + (SynExprAnonRecordField + (SynLongIdent ([a], [], [None]), Some (9,4--9,5), + Const + (Measure + (Int32 1, (9,5--9,6), + Seq ([Named ([m], (9,7--9,8))], (9,7--9,8)), + { LessRange = (9,6--9,7) + GreaterRange = (9,8--9,9) }), (9,5--9,9)), + (9,3--9,9)), Some ((9,9--9,10), Some (9,10))); + Field + (SynExprAnonRecordField + (SynLongIdent ([b], [], [None]), Some (9,12--9,13), + Const + (Measure + (Int32 2, (9,13--9,14), + Seq ([Named ([m], (9,15--9,16))], (9,15--9,16)), + { LessRange = (9,14--9,15) + GreaterRange = (9,16--9,17) }), (9,13--9,17)), + (9,11--9,17)), None)], (9,0--9,20), + { OpeningBraceRange = (9,0--9,2) }), (9,0--9,20))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--9,20), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] diff --git a/tests/service/data/SyntaxTree/Expression/AnonymousRecords-09.fs.bsl b/tests/service/data/SyntaxTree/Expression/AnonymousRecords-09.fs.bsl index ec7c2e4e312..03288dd9864 100644 --- a/tests/service/data/SyntaxTree/Expression/AnonymousRecords-09.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/AnonymousRecords-09.fs.bsl @@ -7,39 +7,51 @@ ImplFile [Expr (AnonRecd (false, None, - [(SynLongIdent ([a], [], [None]), Some (3,3--3,4), - TypeApp - (Ident typeof, (3,10--3,11), - [LongIdent (SynLongIdent ([int], [], [None]))], [], - Some (3,14--3,15), (3,10--3,15), (3,4--3,15)))], - (3,0--3,17), { OpeningBraceRange = (3,0--3,2) }), (3,0--3,17)); + [Field + (SynExprAnonRecordField + (SynLongIdent ([a], [], [None]), Some (3,3--3,4), + TypeApp + (Ident typeof, (3,10--3,11), + [LongIdent (SynLongIdent ([int], [], [None]))], [], + Some (3,14--3,15), (3,10--3,15), (3,4--3,15)), + (3,2--3,15)), None)], (3,0--3,17), + { OpeningBraceRange = (3,0--3,2) }), (3,0--3,17)); Expr (AnonRecd (false, None, - [(SynLongIdent ([a], [], [None]), Some (5,3--5,4), - TypeApp - (Ident typeof, (5,10--5,11), - [LongIdent (SynLongIdent ([int], [], [None]))], [], - Some (5,14--5,15), (5,10--5,15), (5,4--5,15)))], - (5,0--5,18), { OpeningBraceRange = (5,0--5,2) }), (5,0--5,18)); + [Field + (SynExprAnonRecordField + (SynLongIdent ([a], [], [None]), Some (5,3--5,4), + TypeApp + (Ident typeof, (5,10--5,11), + [LongIdent (SynLongIdent ([int], [], [None]))], [], + Some (5,14--5,15), (5,10--5,15), (5,4--5,15)), + (5,2--5,15)), None)], (5,0--5,18), + { OpeningBraceRange = (5,0--5,2) }), (5,0--5,18)); Expr (AnonRecd (false, None, - [(SynLongIdent ([a], [], [None]), Some (7,4--7,5), - TypeApp - (Ident typeof, (7,11--7,12), - [LongIdent (SynLongIdent ([int], [], [None]))], [], - Some (7,15--7,16), (7,11--7,16), (7,5--7,16)))], - (7,0--7,18), { OpeningBraceRange = (7,0--7,2) }), (7,0--7,18)); + [Field + (SynExprAnonRecordField + (SynLongIdent ([a], [], [None]), Some (7,4--7,5), + TypeApp + (Ident typeof, (7,11--7,12), + [LongIdent (SynLongIdent ([int], [], [None]))], [], + Some (7,15--7,16), (7,11--7,16), (7,5--7,16)), + (7,3--7,16)), None)], (7,0--7,18), + { OpeningBraceRange = (7,0--7,2) }), (7,0--7,18)); Expr (AnonRecd (false, None, - [(SynLongIdent ([a], [], [None]), Some (9,4--9,5), - TypeApp - (Ident typeof, (9,11--9,12), - [LongIdent (SynLongIdent ([int], [], [None]))], [], - Some (9,15--9,16), (9,11--9,16), (9,5--9,16)))], - (9,0--9,19), { OpeningBraceRange = (9,0--9,2) }), (9,0--9,19))], + [Field + (SynExprAnonRecordField + (SynLongIdent ([a], [], [None]), Some (9,4--9,5), + TypeApp + (Ident typeof, (9,11--9,12), + [LongIdent (SynLongIdent ([int], [], [None]))], [], + Some (9,15--9,16), (9,11--9,16), (9,5--9,16)), + (9,3--9,16)), None)], (9,0--9,19), + { OpeningBraceRange = (9,0--9,2) }), (9,0--9,19))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--9,19), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] diff --git a/tests/service/data/SyntaxTree/Expression/AnonymousRecords-10.fs.bsl b/tests/service/data/SyntaxTree/Expression/AnonymousRecords-10.fs.bsl index a30127b522f..030773fa567 100644 --- a/tests/service/data/SyntaxTree/Expression/AnonymousRecords-10.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/AnonymousRecords-10.fs.bsl @@ -7,46 +7,58 @@ ImplFile [Expr (AnonRecd (false, None, - [(SynLongIdent ([a], [], [None]), Some (3,3--3,4), - TypeApp - (Ident typedefof, (3,13--3,14), - [App - (LongIdent (SynLongIdent ([option], [], [None])), None, - [Anon (3,14--3,15)], [], None, true, (3,14--3,22))], - [], Some (3,22--3,23), (3,13--3,23), (3,4--3,23)))], + [Field + (SynExprAnonRecordField + (SynLongIdent ([a], [], [None]), Some (3,3--3,4), + TypeApp + (Ident typedefof, (3,13--3,14), + [App + (LongIdent (SynLongIdent ([option], [], [None])), + None, [Anon (3,14--3,15)], [], None, true, + (3,14--3,22))], [], Some (3,22--3,23), + (3,13--3,23), (3,4--3,23)), (3,2--3,23)), None)], (3,0--3,25), { OpeningBraceRange = (3,0--3,2) }), (3,0--3,25)); Expr (AnonRecd (false, None, - [(SynLongIdent ([a], [], [None]), Some (5,3--5,4), - TypeApp - (Ident typedefof, (5,13--5,14), - [App - (LongIdent (SynLongIdent ([option], [], [None])), None, - [Anon (5,14--5,15)], [], None, true, (5,14--5,22))], - [], Some (5,22--5,23), (5,13--5,23), (5,4--5,23)))], + [Field + (SynExprAnonRecordField + (SynLongIdent ([a], [], [None]), Some (5,3--5,4), + TypeApp + (Ident typedefof, (5,13--5,14), + [App + (LongIdent (SynLongIdent ([option], [], [None])), + None, [Anon (5,14--5,15)], [], None, true, + (5,14--5,22))], [], Some (5,22--5,23), + (5,13--5,23), (5,4--5,23)), (5,2--5,23)), None)], (5,0--5,26), { OpeningBraceRange = (5,0--5,2) }), (5,0--5,26)); Expr (AnonRecd (false, None, - [(SynLongIdent ([a], [], [None]), Some (7,4--7,5), - TypeApp - (Ident typedefof, (7,14--7,15), - [App - (LongIdent (SynLongIdent ([option], [], [None])), None, - [Anon (7,15--7,16)], [], None, true, (7,15--7,23))], - [], Some (7,23--7,24), (7,14--7,24), (7,5--7,24)))], + [Field + (SynExprAnonRecordField + (SynLongIdent ([a], [], [None]), Some (7,4--7,5), + TypeApp + (Ident typedefof, (7,14--7,15), + [App + (LongIdent (SynLongIdent ([option], [], [None])), + None, [Anon (7,15--7,16)], [], None, true, + (7,15--7,23))], [], Some (7,23--7,24), + (7,14--7,24), (7,5--7,24)), (7,3--7,24)), None)], (7,0--7,26), { OpeningBraceRange = (7,0--7,2) }), (7,0--7,26)); Expr (AnonRecd (false, None, - [(SynLongIdent ([a], [], [None]), Some (9,4--9,5), - TypeApp - (Ident typedefof, (9,14--9,15), - [App - (LongIdent (SynLongIdent ([option], [], [None])), None, - [Anon (9,15--9,16)], [], None, true, (9,15--9,23))], - [], Some (9,23--9,24), (9,14--9,24), (9,5--9,24)))], + [Field + (SynExprAnonRecordField + (SynLongIdent ([a], [], [None]), Some (9,4--9,5), + TypeApp + (Ident typedefof, (9,14--9,15), + [App + (LongIdent (SynLongIdent ([option], [], [None])), + None, [Anon (9,15--9,16)], [], None, true, + (9,15--9,23))], [], Some (9,23--9,24), + (9,14--9,24), (9,5--9,24)), (9,3--9,24)), None)], (9,0--9,27), { OpeningBraceRange = (9,0--9,2) }), (9,0--9,27))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--9,27), { LeadingKeyword = Module (1,0--1,6) })], (true, true), diff --git a/tests/service/data/SyntaxTree/Expression/AnonymousRecords-11.fs.bsl b/tests/service/data/SyntaxTree/Expression/AnonymousRecords-11.fs.bsl index e33ad8c1418..01168ac1005 100644 --- a/tests/service/data/SyntaxTree/Expression/AnonymousRecords-11.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/AnonymousRecords-11.fs.bsl @@ -23,16 +23,19 @@ ImplFile false)), Pats [], None, (3,4--3,9)), None, AnonRecd (false, None, - [(SynLongIdent ([a], [], [None]), Some (3,15--3,16), - TypeApp - (Ident nameof, (3,22--3,23), - [Var (SynTypar (T, None, false), (3,23--3,25))], [], - Some (3,25--3,26), (3,22--3,26), (3,16--3,26)))], - (3,12--3,28), { OpeningBraceRange = (3,12--3,14) }), - (3,4--3,9), NoneAtLet, { LeadingKeyword = Let (3,0--3,3) - InlineKeyword = None - EqualsRange = Some (3,10--3,11) })], - (3,0--3,28), { InKeyword = None }); + [Field + (SynExprAnonRecordField + (SynLongIdent ([a], [], [None]), Some (3,15--3,16), + TypeApp + (Ident nameof, (3,22--3,23), + [Var (SynTypar (T, None, false), (3,23--3,25))], + [], Some (3,25--3,26), (3,22--3,26), (3,16--3,26)), + (3,14--3,26)), None)], (3,12--3,28), + { OpeningBraceRange = (3,12--3,14) }), (3,4--3,9), + NoneAtLet, { LeadingKeyword = Let (3,0--3,3) + InlineKeyword = None + EqualsRange = Some (3,10--3,11) })], (3,0--3,28), + { InKeyword = None }); Let (false, [SynBinding @@ -52,16 +55,19 @@ ImplFile false)), Pats [], None, (5,4--5,9)), None, AnonRecd (false, None, - [(SynLongIdent ([a], [], [None]), Some (5,15--5,16), - TypeApp - (Ident nameof, (5,22--5,23), - [Var (SynTypar (T, None, false), (5,23--5,25))], [], - Some (5,25--5,26), (5,22--5,26), (5,16--5,26)))], - (5,12--5,29), { OpeningBraceRange = (5,12--5,14) }), - (5,4--5,9), NoneAtLet, { LeadingKeyword = Let (5,0--5,3) - InlineKeyword = None - EqualsRange = Some (5,10--5,11) })], - (5,0--5,29), { InKeyword = None }); + [Field + (SynExprAnonRecordField + (SynLongIdent ([a], [], [None]), Some (5,15--5,16), + TypeApp + (Ident nameof, (5,22--5,23), + [Var (SynTypar (T, None, false), (5,23--5,25))], + [], Some (5,25--5,26), (5,22--5,26), (5,16--5,26)), + (5,14--5,26)), None)], (5,12--5,29), + { OpeningBraceRange = (5,12--5,14) }), (5,4--5,9), + NoneAtLet, { LeadingKeyword = Let (5,0--5,3) + InlineKeyword = None + EqualsRange = Some (5,10--5,11) })], (5,0--5,29), + { InKeyword = None }); Let (false, [SynBinding @@ -81,16 +87,19 @@ ImplFile false)), Pats [], None, (7,4--7,9)), None, AnonRecd (false, None, - [(SynLongIdent ([a], [], [None]), Some (7,16--7,17), - TypeApp - (Ident nameof, (7,23--7,24), - [Var (SynTypar (T, None, false), (7,24--7,26))], [], - Some (7,26--7,27), (7,23--7,27), (7,17--7,27)))], - (7,12--7,29), { OpeningBraceRange = (7,12--7,14) }), - (7,4--7,9), NoneAtLet, { LeadingKeyword = Let (7,0--7,3) - InlineKeyword = None - EqualsRange = Some (7,10--7,11) })], - (7,0--7,29), { InKeyword = None }); + [Field + (SynExprAnonRecordField + (SynLongIdent ([a], [], [None]), Some (7,16--7,17), + TypeApp + (Ident nameof, (7,23--7,24), + [Var (SynTypar (T, None, false), (7,24--7,26))], + [], Some (7,26--7,27), (7,23--7,27), (7,17--7,27)), + (7,15--7,27)), None)], (7,12--7,29), + { OpeningBraceRange = (7,12--7,14) }), (7,4--7,9), + NoneAtLet, { LeadingKeyword = Let (7,0--7,3) + InlineKeyword = None + EqualsRange = Some (7,10--7,11) })], (7,0--7,29), + { InKeyword = None }); Let (false, [SynBinding @@ -110,16 +119,19 @@ ImplFile false)), Pats [], None, (9,4--9,9)), None, AnonRecd (false, None, - [(SynLongIdent ([a], [], [None]), Some (9,16--9,17), - TypeApp - (Ident nameof, (9,23--9,24), - [Var (SynTypar (T, None, false), (9,24--9,26))], [], - Some (9,26--9,27), (9,23--9,27), (9,17--9,27)))], - (9,12--9,30), { OpeningBraceRange = (9,12--9,14) }), - (9,4--9,9), NoneAtLet, { LeadingKeyword = Let (9,0--9,3) - InlineKeyword = None - EqualsRange = Some (9,10--9,11) })], - (9,0--9,30), { InKeyword = None })], + [Field + (SynExprAnonRecordField + (SynLongIdent ([a], [], [None]), Some (9,16--9,17), + TypeApp + (Ident nameof, (9,23--9,24), + [Var (SynTypar (T, None, false), (9,24--9,26))], + [], Some (9,26--9,27), (9,23--9,27), (9,17--9,27)), + (9,15--9,27)), None)], (9,12--9,30), + { OpeningBraceRange = (9,12--9,14) }), (9,4--9,9), + NoneAtLet, { LeadingKeyword = Let (9,0--9,3) + InlineKeyword = None + EqualsRange = Some (9,10--9,11) })], (9,0--9,30), + { InKeyword = None })], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--9,30), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] diff --git a/tests/service/data/SyntaxTree/Expression/AnonymousRecords-12.fs.bsl b/tests/service/data/SyntaxTree/Expression/AnonymousRecords-12.fs.bsl index 1de6c8767d2..af402e59a8a 100644 --- a/tests/service/data/SyntaxTree/Expression/AnonymousRecords-12.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/AnonymousRecords-12.fs.bsl @@ -7,39 +7,51 @@ ImplFile [Expr (AnonRecd (false, None, - [(SynLongIdent ([a], [], [None]), Some (3,3--3,4), - TypeApp - (Ident id, (3,6--3,7), - [LongIdent (SynLongIdent ([int], [], [None]))], [], - Some (3,10--3,11), (3,6--3,11), (3,4--3,11)))], - (3,0--3,13), { OpeningBraceRange = (3,0--3,2) }), (3,0--3,13)); + [Field + (SynExprAnonRecordField + (SynLongIdent ([a], [], [None]), Some (3,3--3,4), + TypeApp + (Ident id, (3,6--3,7), + [LongIdent (SynLongIdent ([int], [], [None]))], [], + Some (3,10--3,11), (3,6--3,11), (3,4--3,11)), + (3,2--3,11)), None)], (3,0--3,13), + { OpeningBraceRange = (3,0--3,2) }), (3,0--3,13)); Expr (AnonRecd (false, None, - [(SynLongIdent ([a], [], [None]), Some (5,3--5,4), - TypeApp - (Ident id, (5,6--5,7), - [LongIdent (SynLongIdent ([int], [], [None]))], [], - Some (5,10--5,11), (5,6--5,11), (5,4--5,11)))], - (5,0--5,14), { OpeningBraceRange = (5,0--5,2) }), (5,0--5,14)); + [Field + (SynExprAnonRecordField + (SynLongIdent ([a], [], [None]), Some (5,3--5,4), + TypeApp + (Ident id, (5,6--5,7), + [LongIdent (SynLongIdent ([int], [], [None]))], [], + Some (5,10--5,11), (5,6--5,11), (5,4--5,11)), + (5,2--5,11)), None)], (5,0--5,14), + { OpeningBraceRange = (5,0--5,2) }), (5,0--5,14)); Expr (AnonRecd (false, None, - [(SynLongIdent ([a], [], [None]), Some (7,4--7,5), - TypeApp - (Ident id, (7,7--7,8), - [LongIdent (SynLongIdent ([int], [], [None]))], [], - Some (7,11--7,12), (7,7--7,12), (7,5--7,12)))], - (7,0--7,14), { OpeningBraceRange = (7,0--7,2) }), (7,0--7,14)); + [Field + (SynExprAnonRecordField + (SynLongIdent ([a], [], [None]), Some (7,4--7,5), + TypeApp + (Ident id, (7,7--7,8), + [LongIdent (SynLongIdent ([int], [], [None]))], [], + Some (7,11--7,12), (7,7--7,12), (7,5--7,12)), + (7,3--7,12)), None)], (7,0--7,14), + { OpeningBraceRange = (7,0--7,2) }), (7,0--7,14)); Expr (AnonRecd (false, None, - [(SynLongIdent ([a], [], [None]), Some (9,4--9,5), - TypeApp - (Ident id, (9,7--9,8), - [LongIdent (SynLongIdent ([int], [], [None]))], [], - Some (9,11--9,12), (9,7--9,12), (9,5--9,12)))], - (9,0--9,15), { OpeningBraceRange = (9,0--9,2) }), (9,0--9,15))], + [Field + (SynExprAnonRecordField + (SynLongIdent ([a], [], [None]), Some (9,4--9,5), + TypeApp + (Ident id, (9,7--9,8), + [LongIdent (SynLongIdent ([int], [], [None]))], [], + Some (9,11--9,12), (9,7--9,12), (9,5--9,12)), + (9,3--9,12)), None)], (9,0--9,15), + { OpeningBraceRange = (9,0--9,2) }), (9,0--9,15))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--9,15), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] diff --git a/tests/service/data/SyntaxTree/Expression/AnonymousRecords-13.fs.bsl b/tests/service/data/SyntaxTree/Expression/AnonymousRecords-13.fs.bsl index ede1aa9a366..2dc59a91f58 100644 --- a/tests/service/data/SyntaxTree/Expression/AnonymousRecords-13.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/AnonymousRecords-13.fs.bsl @@ -7,18 +7,24 @@ ImplFile [Expr (AnonRecd (false, None, - [(SynLongIdent ([a], [], [None]), Some (3,4--3,5), - Quote - (Ident op_Quotation, false, Const (Int32 3, (3,9--3,10)), - false, (3,6--3,13)))], (3,0--3,16), + [Field + (SynExprAnonRecordField + (SynLongIdent ([a], [], [None]), Some (3,4--3,5), + Quote + (Ident op_Quotation, false, + Const (Int32 3, (3,9--3,10)), false, (3,6--3,13)), + (3,2--3,13)), None)], (3,0--3,16), { OpeningBraceRange = (3,0--3,2) }), (3,0--3,16)); Expr (AnonRecd (false, None, - [(SynLongIdent ([a], [], [None]), Some (5,4--5,5), - Quote - (Ident op_Quotation, false, Const (Int32 3, (5,9--5,10)), - false, (5,6--5,13)))], (5,0--5,15), + [Field + (SynExprAnonRecordField + (SynLongIdent ([a], [], [None]), Some (5,4--5,5), + Quote + (Ident op_Quotation, false, + Const (Int32 3, (5,9--5,10)), false, (5,6--5,13)), + (5,2--5,13)), None)], (5,0--5,15), { OpeningBraceRange = (5,0--5,2) }), (5,0--5,15))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--5,15), { LeadingKeyword = Module (1,0--1,6) })], (true, true), diff --git a/tests/service/data/SyntaxTree/Expression/CopySynExprRecordContainsTheRangeOfTheEqualsSignInSynExprRecordField.fs.bsl b/tests/service/data/SyntaxTree/Expression/CopySynExprRecordContainsTheRangeOfTheEqualsSignInSynExprRecordField.fs.bsl index 975d9cc4d21..d0cfb22352e 100644 --- a/tests/service/data/SyntaxTree/Expression/CopySynExprRecordContainsTheRangeOfTheEqualsSignInSynExprRecordField.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/CopySynExprRecordContainsTheRangeOfTheEqualsSignInSynExprRecordField.fs.bsl @@ -10,11 +10,12 @@ ImplFile [Expr (Record (None, Some (Ident foo, ((2,6--2,10), None)), - [SynExprRecordField - ((SynLongIdent ([X], [], [None]), true), Some (4,12--4,13), - Some (Const (Int32 12, (5,16--5,18))), (3,8--5,18), None)], - (2,0--5,20)), (2,0--5,20))], PreXmlDocEmpty, [], None, - (2,0--5,20), { LeadingKeyword = None })], (true, true), - { ConditionalDirectives = [] - WarnDirectives = [] - CodeComments = [] }, set [])) + [Field + (SynExprRecordField + ((SynLongIdent ([X], [], [None]), true), + Some (4,12--4,13), Some (Const (Int32 12, (5,16--5,18))), + (3,8--5,18)), None)], (2,0--5,20)), (2,0--5,20))], + PreXmlDocEmpty, [], None, (2,0--5,20), { LeadingKeyword = None })], + (true, true), { ConditionalDirectives = [] + WarnDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Expression/InheritRecord - Field 1.fs.bsl b/tests/service/data/SyntaxTree/Expression/InheritRecord - Field 1.fs.bsl index 7c41f9d1d94..d5bc96ffc8d 100644 --- a/tests/service/data/SyntaxTree/Expression/InheritRecord - Field 1.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/InheritRecord - Field 1.fs.bsl @@ -41,16 +41,18 @@ ImplFile (6,4--6,13)), (4,4--6,13)), (3,19--3,20), Some (7,2--7,3), (3,19--7,3)), (3,10--7,3), Some ((7,4--8,2), None), (3,2--3,9)), None, - [SynExprRecordField - ((SynLongIdent ([X], [], [None]), true), Some (8,4--8,5), - Some (Const (Int32 42, (8,6--8,8))), (8,2--8,8), + [Field + (SynExprRecordField + ((SynLongIdent ([X], [], [None]), true), Some (8,4--8,5), + Some (Const (Int32 42, (8,6--8,8))), (8,2--8,8)), Some ((8,9--9,2), None)); - SynExprRecordField - ((SynLongIdent ([Y], [], [None]), true), Some (9,4--9,5), - Some - (Const - (String ("test", Regular, (9,6--9,12)), (9,6--9,12))), - (9,2--9,12), None)], (3,0--10,1)), (3,0--10,1))], + Field + (SynExprRecordField + ((SynLongIdent ([Y], [], [None]), true), Some (9,4--9,5), + Some + (Const + (String ("test", Regular, (9,6--9,12)), (9,6--9,12))), + (9,2--9,12)), None)], (3,0--10,1)), (3,0--10,1))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--10,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] diff --git a/tests/service/data/SyntaxTree/Expression/InheritRecord - Field 2.fs.bsl b/tests/service/data/SyntaxTree/Expression/InheritRecord - Field 2.fs.bsl index 0c8fe61edb4..14422349ac6 100644 --- a/tests/service/data/SyntaxTree/Expression/InheritRecord - Field 2.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/InheritRecord - Field 2.fs.bsl @@ -13,21 +13,26 @@ ImplFile (String ("test", Regular, (4,22--4,28)), (4,22--4,28)), (4,21--4,22), Some (4,28--4,29), (4,21--4,29)), (4,12--4,29), Some ((4,30--5,4), None), (4,4--4,11)), None, - [SynExprRecordField - ((SynLongIdent ([Field1], [], [None]), true), - Some (5,11--5,12), Some (Const (Int32 1, (5,13--5,14))), - (5,4--5,14), Some ((5,15--6,4), None)); - SynExprRecordField - ((SynLongIdent ([Field2], [], [None]), true), - Some (6,11--6,12), - Some - (Const - (String ("two", Regular, (6,13--6,18)), (6,13--6,18))), - (6,4--6,18), Some ((6,19--7,4), None)); - SynExprRecordField - ((SynLongIdent ([Field3], [], [None]), true), - Some (7,11--7,12), Some (Const (Double 3.0, (7,13--7,16))), - (7,4--7,16), None)], (3,0--8,1)), (3,0--8,1))], + [Field + (SynExprRecordField + ((SynLongIdent ([Field1], [], [None]), true), + Some (5,11--5,12), Some (Const (Int32 1, (5,13--5,14))), + (5,4--5,14)), Some ((5,15--6,4), None)); + Field + (SynExprRecordField + ((SynLongIdent ([Field2], [], [None]), true), + Some (6,11--6,12), + Some + (Const + (String ("two", Regular, (6,13--6,18)), + (6,13--6,18))), (6,4--6,18)), + Some ((6,19--7,4), None)); + Field + (SynExprRecordField + ((SynLongIdent ([Field3], [], [None]), true), + Some (7,11--7,12), + Some (Const (Double 3.0, (7,13--7,16))), (7,4--7,16)), + None)], (3,0--8,1)), (3,0--8,1))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--8,1), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] diff --git a/tests/service/data/SyntaxTree/Expression/InheritSynExprRecordContainsTheRangeOfTheEqualsSignInSynExprRecordField.fs.bsl b/tests/service/data/SyntaxTree/Expression/InheritSynExprRecordContainsTheRangeOfTheEqualsSignInSynExprRecordField.fs.bsl index 7ad5d76dc22..ae3ae438c62 100644 --- a/tests/service/data/SyntaxTree/Expression/InheritSynExprRecordContainsTheRangeOfTheEqualsSignInSynExprRecordField.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/InheritSynExprRecordContainsTheRangeOfTheEqualsSignInSynExprRecordField.fs.bsl @@ -16,12 +16,13 @@ ImplFile (Ident msg, (2,19--2,20), Some (2,23--2,24), (2,19--2,24)), (2,10--2,24), Some ((2,24--2,25), Some (2,25)), (2,2--2,9)), None, - [SynExprRecordField - ((SynLongIdent ([X], [], [None]), true), Some (2,28--2,29), - Some (Const (Int32 1, (2,30--2,31))), (2,26--2,31), - Some ((2,31--2,32), Some (2,32)))], (2,0--2,34)), - (2,0--2,34))], PreXmlDocEmpty, [], None, (2,0--2,34), - { LeadingKeyword = None })], (true, true), + [Field + (SynExprRecordField + ((SynLongIdent ([X], [], [None]), true), + Some (2,28--2,29), Some (Const (Int32 1, (2,30--2,31))), + (2,26--2,31)), Some ((2,31--2,32), Some (2,32)))], + (2,0--2,34)), (2,0--2,34))], PreXmlDocEmpty, [], None, + (2,0--2,34), { LeadingKeyword = None })], (true, true), { ConditionalDirectives = [] WarnDirectives = [] CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Expression/Record - Anon 01.fs.bsl b/tests/service/data/SyntaxTree/Expression/Record - Anon 01.fs.bsl index 409a6349663..0445032bf15 100644 --- a/tests/service/data/SyntaxTree/Expression/Record - Anon 01.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Record - Anon 01.fs.bsl @@ -7,9 +7,11 @@ ImplFile [Expr (AnonRecd (false, None, - [(SynLongIdent ([F], [], [None]), Some (3,5--3,6), - Const (Int32 1, (3,7--3,8)))], (3,0--3,11), - { OpeningBraceRange = (3,0--3,2) }), (3,0--3,11))], + [Field + (SynExprAnonRecordField + (SynLongIdent ([F], [], [None]), Some (3,5--3,6), + Const (Int32 1, (3,7--3,8)), (3,3--3,8)), None)], + (3,0--3,11), { OpeningBraceRange = (3,0--3,2) }), (3,0--3,11))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--3,11), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] diff --git a/tests/service/data/SyntaxTree/Expression/Record - Anon 02.fs.bsl b/tests/service/data/SyntaxTree/Expression/Record - Anon 02.fs.bsl index abb4f9c61af..58e4aec01dc 100644 --- a/tests/service/data/SyntaxTree/Expression/Record - Anon 02.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Record - Anon 02.fs.bsl @@ -7,8 +7,11 @@ ImplFile [Expr (AnonRecd (false, None, - [(SynLongIdent ([F], [], [None]), Some (3,5--3,6), - ArbitraryAfterError ("anonField", (3,3--3,4)))], (3,0--3,9), + [Field + (SynExprAnonRecordField + (SynLongIdent ([F], [], [None]), Some (3,5--3,6), + ArbitraryAfterError ("anonField", (3,3--3,4)), + (3,3--3,6)), None)], (3,0--3,9), { OpeningBraceRange = (3,0--3,2) }), (3,0--3,9))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--3,9), { LeadingKeyword = Module (1,0--1,6) })], (true, true), diff --git a/tests/service/data/SyntaxTree/Expression/Record - Anon 07.fs.bsl b/tests/service/data/SyntaxTree/Expression/Record - Anon 07.fs.bsl index 0a2441bca98..93ca847d598 100644 --- a/tests/service/data/SyntaxTree/Expression/Record - Anon 07.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Record - Anon 07.fs.bsl @@ -7,10 +7,16 @@ ImplFile [Expr (AnonRecd (false, None, - [(SynLongIdent ([F1], [], [None]), Some (3,6--3,7), - Const (Int32 1, (3,8--3,9))); - (SynLongIdent ([F2], [], [None]), Some (4,6--4,7), - ArbitraryAfterError ("anonField", (4,3--4,5)))], (3,0--4,10), + [Field + (SynExprAnonRecordField + (SynLongIdent ([F1], [], [None]), Some (3,6--3,7), + Const (Int32 1, (3,8--3,9)), (3,3--3,9)), + Some ((3,10--4,3), None)); + Field + (SynExprAnonRecordField + (SynLongIdent ([F2], [], [None]), Some (4,6--4,7), + ArbitraryAfterError ("anonField", (4,3--4,5)), + (4,3--4,7)), None)], (3,0--4,10), { OpeningBraceRange = (3,0--3,2) }), (3,0--4,10))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--4,10), { LeadingKeyword = Module (1,0--1,6) })], (true, true), diff --git a/tests/service/data/SyntaxTree/Expression/Record - Anon 08.fs.bsl b/tests/service/data/SyntaxTree/Expression/Record - Anon 08.fs.bsl index 70fdc8e6a09..7deb988ef57 100644 --- a/tests/service/data/SyntaxTree/Expression/Record - Anon 08.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Record - Anon 08.fs.bsl @@ -7,10 +7,16 @@ ImplFile [Expr (AnonRecd (false, None, - [(SynLongIdent ([F1], [], [None]), Some (3,6--3,7), - Const (Int32 1, (3,8--3,9))); - (SynLongIdent ([F2], [], [None]), None, - ArbitraryAfterError ("anonField", (4,3--4,5)))], (3,0--4,8), + [Field + (SynExprAnonRecordField + (SynLongIdent ([F1], [], [None]), Some (3,6--3,7), + Const (Int32 1, (3,8--3,9)), (3,3--3,9)), + Some ((3,10--4,3), None)); + Field + (SynExprAnonRecordField + (SynLongIdent ([F2], [], [None]), None, + ArbitraryAfterError ("anonField", (4,3--4,5)), + (4,3--4,5)), None)], (3,0--4,8), { OpeningBraceRange = (3,0--3,2) }), (3,0--4,8))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--4,8), { LeadingKeyword = Module (1,0--1,6) })], (true, true), diff --git a/tests/service/data/SyntaxTree/Expression/Record - Anon 09.fs.bsl b/tests/service/data/SyntaxTree/Expression/Record - Anon 09.fs.bsl index c40cd96963e..dcaec38b40f 100644 --- a/tests/service/data/SyntaxTree/Expression/Record - Anon 09.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Record - Anon 09.fs.bsl @@ -7,20 +7,27 @@ ImplFile [Expr (AnonRecd (false, None, - [(SynLongIdent ([F1], [], [None]), Some (3,6--3,7), - Const (Int32 1, (3,8--3,9))); - (SynLongIdent ([F2], [], [None]), Some (4,6--4,7), - App - (NonAtomic, false, - App - (NonAtomic, true, - LongIdent - (false, - SynLongIdent - ([op_Equality], [], [Some (OriginalNotation "=")]), - None, (5,6--5,7)), Ident F3, (5,3--5,7)), - Const (Int32 3, (5,8--5,9)), (5,3--5,9)))], (3,0--5,12), - { OpeningBraceRange = (3,0--3,2) }), (3,0--5,12))], + [Field + (SynExprAnonRecordField + (SynLongIdent ([F1], [], [None]), Some (3,6--3,7), + Const (Int32 1, (3,8--3,9)), (3,3--3,9)), + Some ((3,10--4,3), None)); + Field + (SynExprAnonRecordField + (SynLongIdent ([F2], [], [None]), Some (4,6--4,7), + App + (NonAtomic, false, + App + (NonAtomic, true, + LongIdent + (false, + SynLongIdent + ([op_Equality], [], + [Some (OriginalNotation "=")]), None, + (5,6--5,7)), Ident F3, (5,3--5,7)), + Const (Int32 3, (5,8--5,9)), (5,3--5,9)), (4,3--5,9)), + None)], (3,0--5,12), { OpeningBraceRange = (3,0--3,2) }), + (3,0--5,12))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--5,12), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] diff --git a/tests/service/data/SyntaxTree/Expression/Record - Anon 10.fs.bsl b/tests/service/data/SyntaxTree/Expression/Record - Anon 10.fs.bsl index cc908ff2853..d27d2f0a92e 100644 --- a/tests/service/data/SyntaxTree/Expression/Record - Anon 10.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Record - Anon 10.fs.bsl @@ -7,13 +7,21 @@ ImplFile [Expr (AnonRecd (false, None, - [(SynLongIdent ([F1], [], [None]), Some (3,6--3,7), - Const (Int32 1, (3,8--3,9))); - (SynLongIdent ([F2], [], [None]), None, - ArbitraryAfterError ("anonField", (4,3--4,5))); - (SynLongIdent ([F3], [], [None]), Some (5,6--5,7), - Const (Int32 3, (5,8--5,9)))], (3,0--5,12), - { OpeningBraceRange = (3,0--3,2) }), (3,0--5,12))], + [Field + (SynExprAnonRecordField + (SynLongIdent ([F1], [], [None]), Some (3,6--3,7), + Const (Int32 1, (3,8--3,9)), (3,3--3,9)), + Some ((3,10--4,3), None)); + Field + (SynExprAnonRecordField + (SynLongIdent ([F2], [], [None]), None, + ArbitraryAfterError ("anonField", (4,3--4,5)), + (4,3--4,5)), Some ((4,6--5,3), None)); + Field + (SynExprAnonRecordField + (SynLongIdent ([F3], [], [None]), Some (5,6--5,7), + Const (Int32 3, (5,8--5,9)), (5,3--5,9)), None)], + (3,0--5,12), { OpeningBraceRange = (3,0--3,2) }), (3,0--5,12))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--5,12), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] diff --git a/tests/service/data/SyntaxTree/Expression/Record - Anon 11.fs.bsl b/tests/service/data/SyntaxTree/Expression/Record - Anon 11.fs.bsl index 4fe46cfb3d5..91d64405a00 100644 --- a/tests/service/data/SyntaxTree/Expression/Record - Anon 11.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Record - Anon 11.fs.bsl @@ -7,18 +7,22 @@ ImplFile [Expr (AnonRecd (false, None, - [(SynLongIdent ([F1], [], [None]), Some (3,6--3,7), - App - (NonAtomic, false, - App - (NonAtomic, true, - LongIdent - (false, - SynLongIdent - ([op_Equality], [], [Some (OriginalNotation "=")]), - None, (4,6--4,7)), Ident F2, (4,3--4,7)), - Const (Int32 2, (4,8--4,9)), (4,3--4,9)))], (3,0--4,12), - { OpeningBraceRange = (3,0--3,2) }), (3,0--4,12))], + [Field + (SynExprAnonRecordField + (SynLongIdent ([F1], [], [None]), Some (3,6--3,7), + App + (NonAtomic, false, + App + (NonAtomic, true, + LongIdent + (false, + SynLongIdent + ([op_Equality], [], + [Some (OriginalNotation "=")]), None, + (4,6--4,7)), Ident F2, (4,3--4,7)), + Const (Int32 2, (4,8--4,9)), (4,3--4,9)), (3,3--4,9)), + None)], (3,0--4,12), { OpeningBraceRange = (3,0--3,2) }), + (3,0--4,12))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--4,12), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] diff --git a/tests/service/data/SyntaxTree/Expression/Record - Field 03.fs.bsl b/tests/service/data/SyntaxTree/Expression/Record - Field 03.fs.bsl index 253ba19cef9..84240a87755 100644 --- a/tests/service/data/SyntaxTree/Expression/Record - Field 03.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Record - Field 03.fs.bsl @@ -7,10 +7,11 @@ ImplFile [Expr (Record (None, None, - [SynExprRecordField - ((SynLongIdent ([A], [(3,3--3,4)], [None]), true), - Some (3,5--3,6), Some (Const (Int32 1, (3,7--3,8))), - (3,2--3,8), None)], (3,0--3,10)), (3,0--3,10))], + [Field + (SynExprRecordField + ((SynLongIdent ([A], [(3,3--3,4)], [None]), true), + Some (3,5--3,6), Some (Const (Int32 1, (3,7--3,8))), + (3,2--3,8)), None)], (3,0--3,10)), (3,0--3,10))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--3,10), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] diff --git a/tests/service/data/SyntaxTree/Expression/Record - Field 04.fs.bsl b/tests/service/data/SyntaxTree/Expression/Record - Field 04.fs.bsl index 14d2e09eaf1..1775342609d 100644 --- a/tests/service/data/SyntaxTree/Expression/Record - Field 04.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Record - Field 04.fs.bsl @@ -7,11 +7,13 @@ ImplFile [Expr (Record (None, None, - [SynExprRecordField - ((SynLongIdent - ([A; B], [(3,3--3,4); (3,5--3,6)], [None; None]), true), - Some (3,7--3,8), Some (Const (Int32 1, (3,9--3,10))), - (3,2--3,10), None)], (3,0--3,12)), (3,0--3,12))], + [Field + (SynExprRecordField + ((SynLongIdent + ([A; B], [(3,3--3,4); (3,5--3,6)], [None; None]), + true), Some (3,7--3,8), + Some (Const (Int32 1, (3,9--3,10))), (3,2--3,10)), None)], + (3,0--3,12)), (3,0--3,12))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--3,12), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] diff --git a/tests/service/data/SyntaxTree/Expression/Record - Field 05.fs.bsl b/tests/service/data/SyntaxTree/Expression/Record - Field 05.fs.bsl index f1020c78c2c..c94e13bd9c0 100644 --- a/tests/service/data/SyntaxTree/Expression/Record - Field 05.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Record - Field 05.fs.bsl @@ -7,9 +7,10 @@ ImplFile [Expr (Record (None, None, - [SynExprRecordField - ((SynLongIdent ([A], [], [None]), true), Some (3,4--3,5), - Some (Const (Int32 1, (3,6--3,7))), (3,2--3,7), None)], + [Field + (SynExprRecordField + ((SynLongIdent ([A], [], [None]), true), Some (3,4--3,5), + Some (Const (Int32 1, (3,6--3,7))), (3,2--3,7)), None)], (3,0--3,9)), (3,0--3,9))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--3,9), { LeadingKeyword = Module (1,0--1,6) })], (true, true), diff --git a/tests/service/data/SyntaxTree/Expression/Record - Field 06.fs.bsl b/tests/service/data/SyntaxTree/Expression/Record - Field 06.fs.bsl index 112d7a23329..1fcbf012664 100644 --- a/tests/service/data/SyntaxTree/Expression/Record - Field 06.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Record - Field 06.fs.bsl @@ -7,10 +7,11 @@ ImplFile [Expr (Record (None, None, - [SynExprRecordField - ((SynLongIdent ([A; B], [(3,3--3,4)], [None; None]), true), - Some (3,6--3,7), Some (Const (Int32 1, (3,8--3,9))), - (3,2--3,9), None)], (3,0--3,11)), (3,0--3,11))], + [Field + (SynExprRecordField + ((SynLongIdent ([A; B], [(3,3--3,4)], [None; None]), true), + Some (3,6--3,7), Some (Const (Int32 1, (3,8--3,9))), + (3,2--3,9)), None)], (3,0--3,11)), (3,0--3,11))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--3,11), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] diff --git a/tests/service/data/SyntaxTree/Expression/Record - Field 08.fs.bsl b/tests/service/data/SyntaxTree/Expression/Record - Field 08.fs.bsl index 27b99f20b97..df4373095c8 100644 --- a/tests/service/data/SyntaxTree/Expression/Record - Field 08.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Record - Field 08.fs.bsl @@ -7,13 +7,15 @@ ImplFile [Expr (Record (None, None, - [SynExprRecordField - ((SynLongIdent ([A], [], [None]), true), Some (3,4--3,5), - Some (Const (Int32 1, (3,6--3,7))), (3,2--3,7), + [Field + (SynExprRecordField + ((SynLongIdent ([A], [], [None]), true), Some (3,4--3,5), + Some (Const (Int32 1, (3,6--3,7))), (3,2--3,7)), Some ((3,8--4,2), None)); - SynExprRecordField - ((SynLongIdent ([B], [(4,3--4,4)], [None]), true), None, - None, (4,2--4,4), None)], (3,0--4,6)), (3,0--4,6))], + Field + (SynExprRecordField + ((SynLongIdent ([B], [(4,3--4,4)], [None]), true), None, + None, (4,2--4,4)), None)], (3,0--4,6)), (3,0--4,6))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--4,6), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] diff --git a/tests/service/data/SyntaxTree/Expression/Record - Field 09.fs.bsl b/tests/service/data/SyntaxTree/Expression/Record - Field 09.fs.bsl index 8da1bc6096b..2dca16bf938 100644 --- a/tests/service/data/SyntaxTree/Expression/Record - Field 09.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Record - Field 09.fs.bsl @@ -7,13 +7,15 @@ ImplFile [Expr (Record (None, None, - [SynExprRecordField - ((SynLongIdent ([A], [], [None]), true), Some (3,4--3,5), - Some (Const (Int32 1, (3,6--3,7))), (3,2--3,7), + [Field + (SynExprRecordField + ((SynLongIdent ([A], [], [None]), true), Some (3,4--3,5), + Some (Const (Int32 1, (3,6--3,7))), (3,2--3,7)), Some ((3,8--4,2), None)); - SynExprRecordField - ((SynLongIdent ([B], [], [None]), true), None, None, - (4,2--4,3), None)], (3,0--4,5)), (3,0--4,5))], + Field + (SynExprRecordField + ((SynLongIdent ([B], [], [None]), true), None, None, + (4,2--4,3)), None)], (3,0--4,5)), (3,0--4,5))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--4,5), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] diff --git a/tests/service/data/SyntaxTree/Expression/Record - Field 11.fs.bsl b/tests/service/data/SyntaxTree/Expression/Record - Field 11.fs.bsl index efa568036d4..9c2fb9f08f8 100644 --- a/tests/service/data/SyntaxTree/Expression/Record - Field 11.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Record - Field 11.fs.bsl @@ -7,9 +7,10 @@ ImplFile [Expr (Record (None, None, - [SynExprRecordField - ((SynLongIdent ([A], [], [None]), true), Some (3,4--3,5), - None, (3,2--3,5), None)], (3,0--3,7)), (3,0--3,7))], + [Field + (SynExprRecordField + ((SynLongIdent ([A], [], [None]), true), Some (3,4--3,5), + None, (3,2--3,5)), None)], (3,0--3,7)), (3,0--3,7))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--3,7), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] diff --git a/tests/service/data/SyntaxTree/Expression/Record - Field 12.fs.bsl b/tests/service/data/SyntaxTree/Expression/Record - Field 12.fs.bsl index a2360bb38bd..2d810c85b80 100644 --- a/tests/service/data/SyntaxTree/Expression/Record - Field 12.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Record - Field 12.fs.bsl @@ -7,21 +7,22 @@ ImplFile [Expr (Record (None, None, - [SynExprRecordField - ((SynLongIdent ([F1], [], [None]), true), Some (3,5--3,6), - Some - (App - (NonAtomic, false, - App - (NonAtomic, true, - LongIdent - (false, - SynLongIdent - ([op_Equality], [], - [Some (OriginalNotation "=")]), None, - (4,5--4,6)), Ident F2, (4,2--4,6)), - Const (Int32 2, (4,7--4,8)), (4,2--4,8))), (3,2--4,8), - None)], (3,0--4,10)), (3,0--4,10))], + [Field + (SynExprRecordField + ((SynLongIdent ([F1], [], [None]), true), Some (3,5--3,6), + Some + (App + (NonAtomic, false, + App + (NonAtomic, true, + LongIdent + (false, + SynLongIdent + ([op_Equality], [], + [Some (OriginalNotation "=")]), None, + (4,5--4,6)), Ident F2, (4,2--4,6)), + Const (Int32 2, (4,7--4,8)), (4,2--4,8))), + (3,2--4,8)), None)], (3,0--4,10)), (3,0--4,10))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--4,10), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] diff --git a/tests/service/data/SyntaxTree/Expression/Record - Field 13.fs.bsl b/tests/service/data/SyntaxTree/Expression/Record - Field 13.fs.bsl index 8ce8d350e90..97b3e19bb71 100644 --- a/tests/service/data/SyntaxTree/Expression/Record - Field 13.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Record - Field 13.fs.bsl @@ -7,13 +7,15 @@ ImplFile [Expr (Record (None, None, - [SynExprRecordField - ((SynLongIdent ([F1], [], [None]), true), Some (3,5--3,6), - Some (Const (Int32 1, (3,7--3,8))), (3,2--3,8), + [Field + (SynExprRecordField + ((SynLongIdent ([F1], [], [None]), true), Some (3,5--3,6), + Some (Const (Int32 1, (3,7--3,8))), (3,2--3,8)), Some ((3,9--4,2), None)); - SynExprRecordField - ((SynLongIdent ([F2], [], [None]), true), Some (4,5--4,6), - None, (4,2--4,6), None)], (3,0--4,8)), (3,0--4,8))], + Field + (SynExprRecordField + ((SynLongIdent ([F2], [], [None]), true), Some (4,5--4,6), + None, (4,2--4,6)), None)], (3,0--4,8)), (3,0--4,8))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--4,8), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] diff --git a/tests/service/data/SyntaxTree/Expression/Record - Field 14.fs.bsl b/tests/service/data/SyntaxTree/Expression/Record - Field 14.fs.bsl index 3de711bfbaf..c15b6421bc4 100644 --- a/tests/service/data/SyntaxTree/Expression/Record - Field 14.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Record - Field 14.fs.bsl @@ -7,25 +7,27 @@ ImplFile [Expr (Record (None, None, - [SynExprRecordField - ((SynLongIdent ([F1], [], [None]), true), Some (3,5--3,6), - Some (Const (Int32 1, (3,7--3,8))), (3,2--3,8), + [Field + (SynExprRecordField + ((SynLongIdent ([F1], [], [None]), true), Some (3,5--3,6), + Some (Const (Int32 1, (3,7--3,8))), (3,2--3,8)), Some ((3,9--4,2), None)); - SynExprRecordField - ((SynLongIdent ([F2], [], [None]), true), Some (4,5--4,6), - Some - (App - (NonAtomic, false, - App - (NonAtomic, true, - LongIdent - (false, - SynLongIdent - ([op_Equality], [], - [Some (OriginalNotation "=")]), None, - (5,5--5,6)), Ident F3, (5,2--5,6)), - Const (Int32 3, (5,7--5,8)), (5,2--5,8))), (4,2--5,8), - None)], (3,0--5,10)), (3,0--5,10))], + Field + (SynExprRecordField + ((SynLongIdent ([F2], [], [None]), true), Some (4,5--4,6), + Some + (App + (NonAtomic, false, + App + (NonAtomic, true, + LongIdent + (false, + SynLongIdent + ([op_Equality], [], + [Some (OriginalNotation "=")]), None, + (5,5--5,6)), Ident F3, (5,2--5,6)), + Const (Int32 3, (5,7--5,8)), (5,2--5,8))), + (4,2--5,8)), None)], (3,0--5,10)), (3,0--5,10))], PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None, (1,0--5,10), { LeadingKeyword = Module (1,0--1,6) })], (true, true), { ConditionalDirectives = [] diff --git a/tests/service/data/SyntaxTree/Expression/SynExprAnonRecdWithStructKeyword.fs.bsl b/tests/service/data/SyntaxTree/Expression/SynExprAnonRecdWithStructKeyword.fs.bsl index abb76d98ae6..0efb8dff6a5 100644 --- a/tests/service/data/SyntaxTree/Expression/SynExprAnonRecdWithStructKeyword.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/SynExprAnonRecdWithStructKeyword.fs.bsl @@ -7,8 +7,10 @@ ImplFile [Expr (AnonRecd (true, None, - [(SynLongIdent ([Foo], [], [None]), Some (3,11--3,12), - Ident someValue)], (2,0--5,16), + [Field + (SynExprAnonRecordField + (SynLongIdent ([Foo], [], [None]), Some (3,11--3,12), + Ident someValue, (3,7--5,13)), None)], (2,0--5,16), { OpeningBraceRange = (3,4--3,6) }), (2,0--5,16)); Expr (AnonRecd diff --git a/tests/service/data/SyntaxTree/Expression/SynExprAnonRecordContainsTheRangeOfTheEqualsSignInTheFields.fs.bsl b/tests/service/data/SyntaxTree/Expression/SynExprAnonRecordContainsTheRangeOfTheEqualsSignInTheFields.fs.bsl index e7e6666975a..ffa4b0d290b 100644 --- a/tests/service/data/SyntaxTree/Expression/SynExprAnonRecordContainsTheRangeOfTheEqualsSignInTheFields.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/SynExprAnonRecordContainsTheRangeOfTheEqualsSignInTheFields.fs.bsl @@ -10,13 +10,21 @@ ImplFile [Expr (AnonRecd (false, None, - [(SynLongIdent ([X], [], [None]), Some (2,5--2,6), - Const (Int32 5, (2,7--2,8))); - (SynLongIdent ([Y], [], [None]), Some (3,8--3,9), - Const (Int32 6, (3,10--3,11))); - (SynLongIdent ([Z], [], [None]), Some (4,12--4,13), - Const (Int32 7, (4,14--4,15)))], (2,0--4,18), - { OpeningBraceRange = (2,0--2,2) }), (2,0--4,18))], + [Field + (SynExprAnonRecordField + (SynLongIdent ([X], [], [None]), Some (2,5--2,6), + Const (Int32 5, (2,7--2,8)), (2,3--2,8)), + Some ((2,9--3,3), None)); + Field + (SynExprAnonRecordField + (SynLongIdent ([Y], [], [None]), Some (3,8--3,9), + Const (Int32 6, (3,10--3,11)), (3,3--3,11)), + Some ((3,12--4,3), None)); + Field + (SynExprAnonRecordField + (SynLongIdent ([Z], [], [None]), Some (4,12--4,13), + Const (Int32 7, (4,14--4,15)), (4,3--4,15)), None)], + (2,0--4,18), { OpeningBraceRange = (2,0--2,2) }), (2,0--4,18))], PreXmlDocEmpty, [], None, (2,0--4,18), { LeadingKeyword = None })], (true, true), { ConditionalDirectives = [] WarnDirectives = [] diff --git a/tests/service/data/SyntaxTree/Expression/SynExprRecordContainsTheRangeOfTheEqualsSignInSynExprRecordField.fs.bsl b/tests/service/data/SyntaxTree/Expression/SynExprRecordContainsTheRangeOfTheEqualsSignInSynExprRecordField.fs.bsl index f403c248e54..73264f7a55c 100644 --- a/tests/service/data/SyntaxTree/Expression/SynExprRecordContainsTheRangeOfTheEqualsSignInSynExprRecordField.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/SynExprRecordContainsTheRangeOfTheEqualsSignInSynExprRecordField.fs.bsl @@ -10,22 +10,24 @@ ImplFile [Expr (Record (None, None, - [SynExprRecordField - ((SynLongIdent ([V], [], [None]), true), Some (2,4--2,5), - Some (Ident v), (2,2--2,7), Some ((2,8--3,2), None)); - SynExprRecordField - ((SynLongIdent ([X], [], [None]), true), Some (3,9--3,10), - Some - (App - (NonAtomic, false, - App + [Field + (SynExprRecordField + ((SynLongIdent ([V], [], [None]), true), Some (2,4--2,5), + Some (Ident v), (2,2--2,7)), Some ((2,8--3,2), None)); + Field + (SynExprRecordField + ((SynLongIdent ([X], [], [None]), true), Some (3,9--3,10), + Some + (App (NonAtomic, false, App - (NonAtomic, false, Ident someLongFunctionCall, - Ident a, (4,16--5,21)), Ident b, (4,16--6,21)), - Ident c, (4,16--7,21))), (3,2--7,21), None)], - (2,0--7,23)), (2,0--7,23))], PreXmlDocEmpty, [], None, - (2,0--7,23), { LeadingKeyword = None })], (true, true), - { ConditionalDirectives = [] - WarnDirectives = [] - CodeComments = [LineComment (3,13--3,28)] }, set [])) + (NonAtomic, false, + App + (NonAtomic, false, Ident someLongFunctionCall, + Ident a, (4,16--5,21)), Ident b, + (4,16--6,21)), Ident c, (4,16--7,21))), + (3,2--7,21)), None)], (2,0--7,23)), (2,0--7,23))], + PreXmlDocEmpty, [], None, (2,0--7,23), { LeadingKeyword = None })], + (true, true), { ConditionalDirectives = [] + WarnDirectives = [] + CodeComments = [LineComment (3,13--3,28)] }, set [])) diff --git a/tests/service/data/SyntaxTree/Expression/SynExprRecordFieldsContainCorrectAmountOfTrivia.fs.bsl b/tests/service/data/SyntaxTree/Expression/SynExprRecordFieldsContainCorrectAmountOfTrivia.fs.bsl index 03e2eefdfd4..50834b09847 100644 --- a/tests/service/data/SyntaxTree/Expression/SynExprRecordFieldsContainCorrectAmountOfTrivia.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/SynExprRecordFieldsContainCorrectAmountOfTrivia.fs.bsl @@ -8,59 +8,61 @@ ImplFile [Expr (Record (None, None, - [SynExprRecordField - ((SynLongIdent ([JobType], [], [None]), true), - Some (2,10--2,11), - Some - (App - (NonAtomic, false, - App - (NonAtomic, true, - LongIdent - (false, - SynLongIdent - ([op_Equality], [], - [Some (OriginalNotation "=")]), None, - (5,13--5,14)), + [Field + (SynExprRecordField + ((SynLongIdent ([JobType], [], [None]), true), + Some (2,10--2,11), + Some + (App + (NonAtomic, false, App - (NonAtomic, false, + (NonAtomic, true, + LongIdent + (false, + SynLongIdent + ([op_Equality], [], + [Some (OriginalNotation "=")]), None, + (5,13--5,14)), App - (NonAtomic, true, - LongIdent - (false, - SynLongIdent - ([op_Equality], [], - [Some (OriginalNotation "=")]), None, - (4,12--4,13)), + (NonAtomic, false, App - (NonAtomic, false, + (NonAtomic, true, + LongIdent + (false, + SynLongIdent + ([op_Equality], [], + [Some (OriginalNotation "=")]), + None, (4,12--4,13)), App - (NonAtomic, true, - LongIdent - (false, - SynLongIdent - ([op_Equality], [], - [Some (OriginalNotation "=")]), - None, (3,19--3,20)), + (NonAtomic, false, App - (NonAtomic, false, - Ident EsriBoundaryImport, - Ident FileToImport, (2,12--3,18)), - (2,12--3,20)), - App - (NonAtomic, false, Ident filePath, - Ident State, (3,21--4,11)), - (2,12--4,11)), (2,12--4,13)), - App - (NonAtomic, false, Ident state, Ident DryRun, - (4,14--5,12)), (2,12--5,12)), (2,12--5,14)), - LongIdent - (false, - SynLongIdent - ([args; DryRun], [(5,19--5,20)], [None; None]), - None, (5,15--5,26)), (2,12--5,26))), (2,2--5,26), - None)], (2,0--5,28)), (2,0--5,28))], PreXmlDocEmpty, [], - None, (2,0--5,28), { LeadingKeyword = None })], (true, true), - { ConditionalDirectives = [] - WarnDirectives = [] - CodeComments = [] }, set [])) + (NonAtomic, true, + LongIdent + (false, + SynLongIdent + ([op_Equality], [], + [Some (OriginalNotation "=")]), + None, (3,19--3,20)), + App + (NonAtomic, false, + Ident EsriBoundaryImport, + Ident FileToImport, (2,12--3,18)), + (2,12--3,20)), + App + (NonAtomic, false, Ident filePath, + Ident State, (3,21--4,11)), + (2,12--4,11)), (2,12--4,13)), + App + (NonAtomic, false, Ident state, + Ident DryRun, (4,14--5,12)), (2,12--5,12)), + (2,12--5,14)), + LongIdent + (false, + SynLongIdent + ([args; DryRun], [(5,19--5,20)], [None; None]), + None, (5,15--5,26)), (2,12--5,26))), + (2,2--5,26)), None)], (2,0--5,28)), (2,0--5,28))], + PreXmlDocEmpty, [], None, (2,0--5,28), { LeadingKeyword = None })], + (true, true), { ConditionalDirectives = [] + WarnDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/Pattern/Named field 07.fs.bsl b/tests/service/data/SyntaxTree/Pattern/Named field 07.fs.bsl index 813ba3344bd..7bfd907c406 100644 --- a/tests/service/data/SyntaxTree/Pattern/Named field 07.fs.bsl +++ b/tests/service/data/SyntaxTree/Pattern/Named field 07.fs.bsl @@ -8,10 +8,12 @@ ImplFile (Yes (3,0--3,20), Record (None, None, - [SynExprRecordField - ((SynLongIdent ([A], [], [None]), true), - Some (3,10--3,11), Some (Const (Int32 1, (3,12--3,13))), - (3,8--3,13), None)], (3,6--3,15)), + [Field + (SynExprRecordField + ((SynLongIdent ([A], [], [None]), true), + Some (3,10--3,11), + Some (Const (Int32 1, (3,12--3,13))), (3,8--3,13)), + None)], (3,6--3,15)), [SynMatchClause (Record ([NamePatPairField diff --git a/tests/service/data/SyntaxTree/Pattern/Named field 08.fs.bsl b/tests/service/data/SyntaxTree/Pattern/Named field 08.fs.bsl index cd8a867459d..8a72d830932 100644 --- a/tests/service/data/SyntaxTree/Pattern/Named field 08.fs.bsl +++ b/tests/service/data/SyntaxTree/Pattern/Named field 08.fs.bsl @@ -8,10 +8,12 @@ ImplFile (Yes (3,0--3,20), Record (None, None, - [SynExprRecordField - ((SynLongIdent ([A], [], [None]), true), - Some (3,10--3,11), Some (Const (Int32 1, (3,12--3,13))), - (3,8--3,13), None)], (3,6--3,15)), + [Field + (SynExprRecordField + ((SynLongIdent ([A], [], [None]), true), + Some (3,10--3,11), + Some (Const (Int32 1, (3,12--3,13))), (3,8--3,13)), + None)], (3,6--3,15)), [SynMatchClause (Record ([NamePatPairField diff --git a/tests/service/data/SyntaxTree/SignatureType/RangeOfAttributesShouldBeIncludedInRecursiveTypes.fsi.bsl b/tests/service/data/SyntaxTree/SignatureType/RangeOfAttributesShouldBeIncludedInRecursiveTypes.fsi.bsl index af1c383c20c..5d1b952c47d 100644 --- a/tests/service/data/SyntaxTree/SignatureType/RangeOfAttributesShouldBeIncludedInRecursiveTypes.fsi.bsl +++ b/tests/service/data/SyntaxTree/SignatureType/RangeOfAttributesShouldBeIncludedInRecursiveTypes.fsi.bsl @@ -36,12 +36,14 @@ SigFile Simple (Record (Some (Internal (8,4--8,12)), - [SynField - ([], false, Some LongNameBarBarBarBarBarBarBar, - LongIdent (SynLongIdent ([int], [], [None])), false, - PreXmlDoc ((10,12), FSharp.Compiler.Xml.XmlDocCollector), - None, (10,12--10,46), { LeadingKeyword = None - MutableKeyword = None })], + [Field + (SynField + ([], false, Some LongNameBarBarBarBarBarBarBar, + LongIdent (SynLongIdent ([int], [], [None])), + false, + PreXmlDoc ((10,12), FSharp.Compiler.Xml.XmlDocCollector), + None, (10,12--10,46), { LeadingKeyword = None + MutableKeyword = None }))], (8,4--11,9)), (8,4--11,9)), [Member (SynValSig diff --git a/tests/service/data/SyntaxTree/SignatureType/RangeOfSynTypeDefnSigRecordShouldEndAtLastMember.fsi.bsl b/tests/service/data/SyntaxTree/SignatureType/RangeOfSynTypeDefnSigRecordShouldEndAtLastMember.fsi.bsl index bcbb3398842..dac61202112 100644 --- a/tests/service/data/SyntaxTree/SignatureType/RangeOfSynTypeDefnSigRecordShouldEndAtLastMember.fsi.bsl +++ b/tests/service/data/SyntaxTree/SignatureType/RangeOfSynTypeDefnSigRecordShouldEndAtLastMember.fsi.bsl @@ -13,12 +13,14 @@ SigFile Simple (Record (None, - [SynField - ([], false, Some Level, - LongIdent (SynLongIdent ([int], [], [None])), false, - PreXmlDoc ((4,6), FSharp.Compiler.Xml.XmlDocCollector), - None, (4,6--4,16), { LeadingKeyword = None - MutableKeyword = None })], + [Field + (SynField + ([], false, Some Level, + LongIdent (SynLongIdent ([int], [], [None])), + false, + PreXmlDoc ((4,6), FSharp.Compiler.Xml.XmlDocCollector), + None, (4,6--4,16), { LeadingKeyword = None + MutableKeyword = None }))], (4,4--4,18)), (4,4--4,18)), [Member (SynValSig diff --git a/tests/service/data/SyntaxTree/Type/Module Inside Record 01.fs.bsl b/tests/service/data/SyntaxTree/Type/Module Inside Record 01.fs.bsl index 49bb21bfb20..9bb9daef119 100644 --- a/tests/service/data/SyntaxTree/Type/Module Inside Record 01.fs.bsl +++ b/tests/service/data/SyntaxTree/Type/Module Inside Record 01.fs.bsl @@ -13,12 +13,14 @@ ImplFile Simple (Record (None, - [SynField - ([], false, Some A, - LongIdent (SynLongIdent ([int], [], [None])), false, - PreXmlDoc ((5,6), FSharp.Compiler.Xml.XmlDocCollector), - None, (5,6--5,13), { LeadingKeyword = None - MutableKeyword = None })], + [Field + (SynField + ([], false, Some A, + LongIdent (SynLongIdent ([int], [], [None])), + false, + PreXmlDoc ((5,6), FSharp.Compiler.Xml.XmlDocCollector), + None, (5,6--5,13), { LeadingKeyword = None + MutableKeyword = None }))], (5,4--5,15)), (5,4--5,15)), [], None, (4,5--5,15), { LeadingKeyword = Type (4,0--4,4) EqualsRange = Some (4,7--4,8) diff --git a/tests/service/data/SyntaxTree/Type/Module Same Indentation 01.fs.bsl b/tests/service/data/SyntaxTree/Type/Module Same Indentation 01.fs.bsl index 4b5f37845d7..97eed9f26e1 100644 --- a/tests/service/data/SyntaxTree/Type/Module Same Indentation 01.fs.bsl +++ b/tests/service/data/SyntaxTree/Type/Module Same Indentation 01.fs.bsl @@ -71,12 +71,14 @@ ImplFile Simple (Record (None, - [SynField - ([], false, Some Field, - LongIdent (SynLongIdent ([int], [], [None])), false, - PreXmlDoc ((12,6), FSharp.Compiler.Xml.XmlDocCollector), - None, (12,6--12,16), { LeadingKeyword = None - MutableKeyword = None })], + [Field + (SynField + ([], false, Some Field, + LongIdent (SynLongIdent ([int], [], [None])), + false, + PreXmlDoc ((12,6), FSharp.Compiler.Xml.XmlDocCollector), + None, (12,6--12,16), { LeadingKeyword = None + MutableKeyword = None }))], (12,4--12,18)), (12,4--12,18)), [], None, (11,5--12,18), { LeadingKeyword = Type (11,0--11,4) EqualsRange = Some (11,7--11,8) diff --git a/tests/service/data/SyntaxTree/Type/RangeOfAttributesShouldBeIncludedInRecursiveTypes.fs.bsl b/tests/service/data/SyntaxTree/Type/RangeOfAttributesShouldBeIncludedInRecursiveTypes.fs.bsl index ad592dd5cbb..64f8987ac04 100644 --- a/tests/service/data/SyntaxTree/Type/RangeOfAttributesShouldBeIncludedInRecursiveTypes.fs.bsl +++ b/tests/service/data/SyntaxTree/Type/RangeOfAttributesShouldBeIncludedInRecursiveTypes.fs.bsl @@ -87,24 +87,27 @@ ImplFile Simple (Record (Some (Internal (7,4--7,12)), - [SynField - ([], false, Some Hash, - LongIdent (SynLongIdent ([int], [], [None])), false, - PreXmlDoc ((8,8), FSharp.Compiler.Xml.XmlDocCollector), - None, (8,8--8,18), { LeadingKeyword = None - MutableKeyword = None }); - SynField - ([], false, Some Foo, - App - (LongIdent (SynLongIdent ([Foo], [], [None])), - Some (9,17--9,18), - [Var (SynTypar (a, None, false), (9,18--9,20)); - Var (SynTypar (b, None, false), (9,22--9,24))], - [(9,20--9,21)], Some (9,24--9,25), false, - (9,14--9,25)), false, - PreXmlDoc ((9,8), FSharp.Compiler.Xml.XmlDocCollector), - None, (9,8--9,25), { LeadingKeyword = None - MutableKeyword = None })], + [Field + (SynField + ([], false, Some Hash, + LongIdent (SynLongIdent ([int], [], [None])), + false, + PreXmlDoc ((8,8), FSharp.Compiler.Xml.XmlDocCollector), + None, (8,8--8,18), { LeadingKeyword = None + MutableKeyword = None })); + Field + (SynField + ([], false, Some Foo, + App + (LongIdent (SynLongIdent ([Foo], [], [None])), + Some (9,17--9,18), + [Var (SynTypar (a, None, false), (9,18--9,20)); + Var (SynTypar (b, None, false), (9,22--9,24))], + [(9,20--9,21)], Some (9,24--9,25), false, + (9,14--9,25)), false, + PreXmlDoc ((9,8), FSharp.Compiler.Xml.XmlDocCollector), + None, (9,8--9,25), { LeadingKeyword = None + MutableKeyword = None }))], (7,4--10,5)), (7,4--10,5)), [], None, (6,4--10,5), { LeadingKeyword = And (6,0--6,3) EqualsRange = Some (6,56--6,57) diff --git a/tests/service/data/SyntaxTree/Type/Record - Access 01.fs.bsl b/tests/service/data/SyntaxTree/Type/Record - Access 01.fs.bsl index e2c49be6c8e..c2cc6fa372b 100644 --- a/tests/service/data/SyntaxTree/Type/Record - Access 01.fs.bsl +++ b/tests/service/data/SyntaxTree/Type/Record - Access 01.fs.bsl @@ -12,11 +12,13 @@ ImplFile Simple (Record (None, - [SynField - ([], false, None, FromParseError (5,16--5,16), false, - PreXmlDoc ((5,8), FSharp.Compiler.Xml.XmlDocCollector), - None, (5,8--5,16), { LeadingKeyword = None - MutableKeyword = None })], + [Field + (SynField + ([], false, None, FromParseError (5,16--5,16), + false, + PreXmlDoc ((5,8), FSharp.Compiler.Xml.XmlDocCollector), + None, (5,8--5,16), { LeadingKeyword = None + MutableKeyword = None }))], (4,4--6,5)), (4,4--6,5)), [], None, (3,5--6,5), { LeadingKeyword = Type (3,0--3,4) EqualsRange = Some (3,7--3,8) diff --git a/tests/service/data/SyntaxTree/Type/Record - Access 02.fs.bsl b/tests/service/data/SyntaxTree/Type/Record - Access 02.fs.bsl index 3540dbcc68c..d13bde420d6 100644 --- a/tests/service/data/SyntaxTree/Type/Record - Access 02.fs.bsl +++ b/tests/service/data/SyntaxTree/Type/Record - Access 02.fs.bsl @@ -12,13 +12,15 @@ ImplFile Simple (Record (None, - [SynField - ([], false, None, FromParseError (5,24--5,24), true, - PreXmlDoc ((5,8), FSharp.Compiler.Xml.XmlDocCollector), - None, (5,8--5,24), - { LeadingKeyword = None - MutableKeyword = Some (5,8--5,15) })], (4,4--6,5)), - (4,4--6,5)), [], None, (3,5--6,5), + [Field + (SynField + ([], false, None, FromParseError (5,24--5,24), + true, + PreXmlDoc ((5,8), FSharp.Compiler.Xml.XmlDocCollector), + None, (5,8--5,24), + { LeadingKeyword = None + MutableKeyword = Some (5,8--5,15) }))], + (4,4--6,5)), (4,4--6,5)), [], None, (3,5--6,5), { LeadingKeyword = Type (3,0--3,4) EqualsRange = Some (3,7--3,8) WithKeyword = None })], (3,0--6,5)); diff --git a/tests/service/data/SyntaxTree/Type/Record - Access 03.fs.bsl b/tests/service/data/SyntaxTree/Type/Record - Access 03.fs.bsl index 353570298cd..a72aaf7d8d9 100644 --- a/tests/service/data/SyntaxTree/Type/Record - Access 03.fs.bsl +++ b/tests/service/data/SyntaxTree/Type/Record - Access 03.fs.bsl @@ -12,14 +12,16 @@ ImplFile Simple (Record (None, - [SynField - ([], false, Some F, - LongIdent (SynLongIdent ([int], [], [None])), true, - PreXmlDoc ((5,8), FSharp.Compiler.Xml.XmlDocCollector), - None, (5,8--5,31), - { LeadingKeyword = None - MutableKeyword = Some (5,8--5,15) })], (4,4--6,5)), - (4,4--6,5)), [], None, (3,5--6,5), + [Field + (SynField + ([], false, Some F, + LongIdent (SynLongIdent ([int], [], [None])), + true, + PreXmlDoc ((5,8), FSharp.Compiler.Xml.XmlDocCollector), + None, (5,8--5,31), + { LeadingKeyword = None + MutableKeyword = Some (5,8--5,15) }))], + (4,4--6,5)), (4,4--6,5)), [], None, (3,5--6,5), { LeadingKeyword = Type (3,0--3,4) EqualsRange = Some (3,7--3,8) WithKeyword = None })], (3,0--6,5)); diff --git a/tests/service/data/SyntaxTree/Type/Record - Access 04.fs.bsl b/tests/service/data/SyntaxTree/Type/Record - Access 04.fs.bsl index 37ad416ff25..26111d2dfb2 100644 --- a/tests/service/data/SyntaxTree/Type/Record - Access 04.fs.bsl +++ b/tests/service/data/SyntaxTree/Type/Record - Access 04.fs.bsl @@ -12,12 +12,14 @@ ImplFile Simple (Record (None, - [SynField - ([], false, Some F, - LongIdent (SynLongIdent ([int], [], [None])), false, - PreXmlDoc ((5,8), FSharp.Compiler.Xml.XmlDocCollector), - None, (5,8--5,23), { LeadingKeyword = None - MutableKeyword = None })], + [Field + (SynField + ([], false, Some F, + LongIdent (SynLongIdent ([int], [], [None])), + false, + PreXmlDoc ((5,8), FSharp.Compiler.Xml.XmlDocCollector), + None, (5,8--5,23), { LeadingKeyword = None + MutableKeyword = None }))], (4,4--6,5)), (4,4--6,5)), [], None, (3,5--6,5), { LeadingKeyword = Type (3,0--3,4) EqualsRange = Some (3,7--3,8) diff --git a/tests/service/data/SyntaxTree/Type/Record - Mutable 01.fs.bsl b/tests/service/data/SyntaxTree/Type/Record - Mutable 01.fs.bsl index 37da69f67aa..7b6786f818e 100644 --- a/tests/service/data/SyntaxTree/Type/Record - Mutable 01.fs.bsl +++ b/tests/service/data/SyntaxTree/Type/Record - Mutable 01.fs.bsl @@ -12,13 +12,15 @@ ImplFile Simple (Record (None, - [SynField - ([], false, None, FromParseError (5,15--5,15), true, - PreXmlDoc ((5,8), FSharp.Compiler.Xml.XmlDocCollector), - None, (5,8--5,15), - { LeadingKeyword = None - MutableKeyword = Some (5,8--5,15) })], (4,4--6,5)), - (4,4--6,5)), [], None, (3,5--6,5), + [Field + (SynField + ([], false, None, FromParseError (5,15--5,15), + true, + PreXmlDoc ((5,8), FSharp.Compiler.Xml.XmlDocCollector), + None, (5,8--5,15), + { LeadingKeyword = None + MutableKeyword = Some (5,8--5,15) }))], + (4,4--6,5)), (4,4--6,5)), [], None, (3,5--6,5), { LeadingKeyword = Type (3,0--3,4) EqualsRange = Some (3,7--3,8) WithKeyword = None })], (3,0--6,5)); diff --git a/tests/service/data/SyntaxTree/Type/Record - Mutable 02.fs.bsl b/tests/service/data/SyntaxTree/Type/Record - Mutable 02.fs.bsl index 7b80fa8e08f..dc42d7244dc 100644 --- a/tests/service/data/SyntaxTree/Type/Record - Mutable 02.fs.bsl +++ b/tests/service/data/SyntaxTree/Type/Record - Mutable 02.fs.bsl @@ -12,19 +12,23 @@ ImplFile Simple (Record (None, - [SynField - ([], false, Some F1, - LongIdent (SynLongIdent ([int], [], [None])), false, - PreXmlDoc ((5,8), FSharp.Compiler.Xml.XmlDocCollector), - None, (5,8--5,15), { LeadingKeyword = None - MutableKeyword = None }); - SynField - ([], false, None, FromParseError (6,15--6,15), true, - PreXmlDoc ((6,8), FSharp.Compiler.Xml.XmlDocCollector), - None, (6,8--6,15), - { LeadingKeyword = None - MutableKeyword = Some (6,8--6,15) })], (4,4--7,5)), - (4,4--7,5)), [], None, (3,5--7,5), + [Field + (SynField + ([], false, Some F1, + LongIdent (SynLongIdent ([int], [], [None])), + false, + PreXmlDoc ((5,8), FSharp.Compiler.Xml.XmlDocCollector), + None, (5,8--5,15), { LeadingKeyword = None + MutableKeyword = None })); + Field + (SynField + ([], false, None, FromParseError (6,15--6,15), + true, + PreXmlDoc ((6,8), FSharp.Compiler.Xml.XmlDocCollector), + None, (6,8--6,15), + { LeadingKeyword = None + MutableKeyword = Some (6,8--6,15) }))], + (4,4--7,5)), (4,4--7,5)), [], None, (3,5--7,5), { LeadingKeyword = Type (3,0--3,4) EqualsRange = Some (3,7--3,8) WithKeyword = None })], (3,0--7,5)); diff --git a/tests/service/data/SyntaxTree/Type/Record - Mutable 03.fs.bsl b/tests/service/data/SyntaxTree/Type/Record - Mutable 03.fs.bsl index 64b6dba2775..cd6635ad1eb 100644 --- a/tests/service/data/SyntaxTree/Type/Record - Mutable 03.fs.bsl +++ b/tests/service/data/SyntaxTree/Type/Record - Mutable 03.fs.bsl @@ -12,18 +12,22 @@ ImplFile Simple (Record (None, - [SynField - ([], false, None, FromParseError (5,15--5,15), true, - PreXmlDoc ((5,8), FSharp.Compiler.Xml.XmlDocCollector), - None, (5,8--5,15), - { LeadingKeyword = None - MutableKeyword = Some (5,8--5,15) }); - SynField - ([], false, Some F2, - LongIdent (SynLongIdent ([int], [], [None])), false, - PreXmlDoc ((6,8), FSharp.Compiler.Xml.XmlDocCollector), - None, (6,8--6,15), { LeadingKeyword = None - MutableKeyword = None })], + [Field + (SynField + ([], false, None, FromParseError (5,15--5,15), + true, + PreXmlDoc ((5,8), FSharp.Compiler.Xml.XmlDocCollector), + None, (5,8--5,15), + { LeadingKeyword = None + MutableKeyword = Some (5,8--5,15) })); + Field + (SynField + ([], false, Some F2, + LongIdent (SynLongIdent ([int], [], [None])), + false, + PreXmlDoc ((6,8), FSharp.Compiler.Xml.XmlDocCollector), + None, (6,8--6,15), { LeadingKeyword = None + MutableKeyword = None }))], (4,4--7,5)), (4,4--7,5)), [], None, (3,5--7,5), { LeadingKeyword = Type (3,0--3,4) EqualsRange = Some (3,7--3,8) diff --git a/tests/service/data/SyntaxTree/Type/Record - Mutable 04.fs.bsl b/tests/service/data/SyntaxTree/Type/Record - Mutable 04.fs.bsl index c3b99f04619..143b61b6292 100644 --- a/tests/service/data/SyntaxTree/Type/Record - Mutable 04.fs.bsl +++ b/tests/service/data/SyntaxTree/Type/Record - Mutable 04.fs.bsl @@ -12,24 +12,30 @@ ImplFile Simple (Record (None, - [SynField - ([], false, Some F1, - LongIdent (SynLongIdent ([int], [], [None])), false, - PreXmlDoc ((5,8), FSharp.Compiler.Xml.XmlDocCollector), - None, (5,8--5,15), { LeadingKeyword = None - MutableKeyword = None }); - SynField - ([], false, None, FromParseError (6,15--6,15), true, - PreXmlDoc ((6,8), FSharp.Compiler.Xml.XmlDocCollector), - None, (6,8--6,15), - { LeadingKeyword = None - MutableKeyword = Some (6,8--6,15) }); - SynField - ([], false, Some F3, - LongIdent (SynLongIdent ([int], [], [None])), false, - PreXmlDoc ((7,8), FSharp.Compiler.Xml.XmlDocCollector), - None, (7,8--7,15), { LeadingKeyword = None - MutableKeyword = None })], + [Field + (SynField + ([], false, Some F1, + LongIdent (SynLongIdent ([int], [], [None])), + false, + PreXmlDoc ((5,8), FSharp.Compiler.Xml.XmlDocCollector), + None, (5,8--5,15), { LeadingKeyword = None + MutableKeyword = None })); + Field + (SynField + ([], false, None, FromParseError (6,15--6,15), + true, + PreXmlDoc ((6,8), FSharp.Compiler.Xml.XmlDocCollector), + None, (6,8--6,15), + { LeadingKeyword = None + MutableKeyword = Some (6,8--6,15) })); + Field + (SynField + ([], false, Some F3, + LongIdent (SynLongIdent ([int], [], [None])), + false, + PreXmlDoc ((7,8), FSharp.Compiler.Xml.XmlDocCollector), + None, (7,8--7,15), { LeadingKeyword = None + MutableKeyword = None }))], (4,4--8,5)), (4,4--8,5)), [], None, (3,5--8,5), { LeadingKeyword = Type (3,0--3,4) EqualsRange = Some (3,7--3,8) diff --git a/tests/service/data/SyntaxTree/Type/Record - Mutable 05.fs.bsl b/tests/service/data/SyntaxTree/Type/Record - Mutable 05.fs.bsl index 6443e19b43b..3c2d00eb5cc 100644 --- a/tests/service/data/SyntaxTree/Type/Record - Mutable 05.fs.bsl +++ b/tests/service/data/SyntaxTree/Type/Record - Mutable 05.fs.bsl @@ -12,25 +12,31 @@ ImplFile Simple (Record (None, - [SynField - ([], false, Some F1, - LongIdent (SynLongIdent ([int], [], [None])), false, - PreXmlDoc ((5,8), FSharp.Compiler.Xml.XmlDocCollector), - None, (5,8--5,15), { LeadingKeyword = None - MutableKeyword = None }); - SynField - ([], false, Some F2, - LongIdent (SynLongIdent ([int], [], [None])), true, - PreXmlDoc ((6,8), FSharp.Compiler.Xml.XmlDocCollector), - None, (6,8--6,23), - { LeadingKeyword = None - MutableKeyword = Some (6,8--6,15) }); - SynField - ([], false, Some F3, - LongIdent (SynLongIdent ([int], [], [None])), false, - PreXmlDoc ((7,8), FSharp.Compiler.Xml.XmlDocCollector), - None, (7,8--7,15), { LeadingKeyword = None - MutableKeyword = None })], + [Field + (SynField + ([], false, Some F1, + LongIdent (SynLongIdent ([int], [], [None])), + false, + PreXmlDoc ((5,8), FSharp.Compiler.Xml.XmlDocCollector), + None, (5,8--5,15), { LeadingKeyword = None + MutableKeyword = None })); + Field + (SynField + ([], false, Some F2, + LongIdent (SynLongIdent ([int], [], [None])), + true, + PreXmlDoc ((6,8), FSharp.Compiler.Xml.XmlDocCollector), + None, (6,8--6,23), + { LeadingKeyword = None + MutableKeyword = Some (6,8--6,15) })); + Field + (SynField + ([], false, Some F3, + LongIdent (SynLongIdent ([int], [], [None])), + false, + PreXmlDoc ((7,8), FSharp.Compiler.Xml.XmlDocCollector), + None, (7,8--7,15), { LeadingKeyword = None + MutableKeyword = None }))], (4,4--8,5)), (4,4--8,5)), [], None, (3,5--8,5), { LeadingKeyword = Type (3,0--3,4) EqualsRange = Some (3,7--3,8) diff --git a/tests/service/data/SyntaxTree/Type/Record 01.fs.bsl b/tests/service/data/SyntaxTree/Type/Record 01.fs.bsl index 50126fc6544..96c0fb59387 100644 --- a/tests/service/data/SyntaxTree/Type/Record 01.fs.bsl +++ b/tests/service/data/SyntaxTree/Type/Record 01.fs.bsl @@ -12,17 +12,21 @@ ImplFile Simple (Record (None, - [SynField - ([], false, Some Invest, - LongIdent (SynLongIdent ([int], [], [None])), false, - PreXmlDoc ((5,8), FSharp.Compiler.Xml.XmlDocCollector), - None, (5,8--5,19), { LeadingKeyword = None - MutableKeyword = None }); - SynField - ([], false, Some T, FromParseError (6,9--6,9), false, - PreXmlDoc ((6,8), FSharp.Compiler.Xml.XmlDocCollector), - None, (6,8--6,9), { LeadingKeyword = None - MutableKeyword = None })], + [Field + (SynField + ([], false, Some Invest, + LongIdent (SynLongIdent ([int], [], [None])), + false, + PreXmlDoc ((5,8), FSharp.Compiler.Xml.XmlDocCollector), + None, (5,8--5,19), { LeadingKeyword = None + MutableKeyword = None })); + Field + (SynField + ([], false, Some T, FromParseError (6,9--6,9), + false, + PreXmlDoc ((6,8), FSharp.Compiler.Xml.XmlDocCollector), + None, (6,8--6,9), { LeadingKeyword = None + MutableKeyword = None }))], (4,4--7,5)), (4,4--7,5)), [], None, (3,5--7,5), { LeadingKeyword = Type (3,0--3,4) EqualsRange = Some (3,8--3,9) diff --git a/tests/service/data/SyntaxTree/Type/Record 02.fs.bsl b/tests/service/data/SyntaxTree/Type/Record 02.fs.bsl index 986cadf5de9..8461f3d1a11 100644 --- a/tests/service/data/SyntaxTree/Type/Record 02.fs.bsl +++ b/tests/service/data/SyntaxTree/Type/Record 02.fs.bsl @@ -12,18 +12,21 @@ ImplFile Simple (Record (None, - [SynField - ([], false, Some Invest, - LongIdent (SynLongIdent ([int], [], [None])), false, - PreXmlDoc ((5,8), FSharp.Compiler.Xml.XmlDocCollector), - None, (5,8--5,19), { LeadingKeyword = None - MutableKeyword = None }); - SynField - ([], false, Some T, FromParseError (6,11--6,11), - false, - PreXmlDoc ((6,8), FSharp.Compiler.Xml.XmlDocCollector), - None, (6,8--6,11), { LeadingKeyword = None - MutableKeyword = None })], + [Field + (SynField + ([], false, Some Invest, + LongIdent (SynLongIdent ([int], [], [None])), + false, + PreXmlDoc ((5,8), FSharp.Compiler.Xml.XmlDocCollector), + None, (5,8--5,19), { LeadingKeyword = None + MutableKeyword = None })); + Field + (SynField + ([], false, Some T, FromParseError (6,11--6,11), + false, + PreXmlDoc ((6,8), FSharp.Compiler.Xml.XmlDocCollector), + None, (6,8--6,11), { LeadingKeyword = None + MutableKeyword = None }))], (4,4--7,5)), (4,4--7,5)), [], None, (3,5--7,5), { LeadingKeyword = Type (3,0--3,4) EqualsRange = Some (3,8--3,9) diff --git a/tests/service/data/SyntaxTree/Type/Record 04.fs.bsl b/tests/service/data/SyntaxTree/Type/Record 04.fs.bsl index bc34db45a45..62d89315400 100644 --- a/tests/service/data/SyntaxTree/Type/Record 04.fs.bsl +++ b/tests/service/data/SyntaxTree/Type/Record 04.fs.bsl @@ -12,11 +12,12 @@ ImplFile Simple (Record (None, - [SynField - ([], false, None, FromParseError (5,6--5,6), false, - PreXmlDoc ((5,6), FSharp.Compiler.Xml.XmlDocCollector), - None, (5,6--5,6), { LeadingKeyword = None - MutableKeyword = None })], + [Field + (SynField + ([], false, None, FromParseError (5,6--5,6), false, + PreXmlDoc ((5,6), FSharp.Compiler.Xml.XmlDocCollector), + None, (5,6--5,6), { LeadingKeyword = None + MutableKeyword = None }))], (4,4--6,5)), (4,4--6,5)), [], None, (3,5--6,5), { LeadingKeyword = Type (3,0--3,4) EqualsRange = Some (3,7--3,8) diff --git a/tests/service/data/SyntaxTree/Type/Record 05.fs.bsl b/tests/service/data/SyntaxTree/Type/Record 05.fs.bsl index 65f78f4d5d3..5b7f1e20345 100644 --- a/tests/service/data/SyntaxTree/Type/Record 05.fs.bsl +++ b/tests/service/data/SyntaxTree/Type/Record 05.fs.bsl @@ -12,23 +12,28 @@ ImplFile Simple (Record (None, - [SynField - ([], false, Some F1, - LongIdent (SynLongIdent ([int], [], [None])), false, - PreXmlDoc ((4,6), FSharp.Compiler.Xml.XmlDocCollector), - None, (4,6--4,13), { LeadingKeyword = None - MutableKeyword = None }); - SynField - ([], false, None, FromParseError (5,6--5,6), false, - PreXmlDoc ((5,6), FSharp.Compiler.Xml.XmlDocCollector), - None, (5,6--5,6), { LeadingKeyword = None - MutableKeyword = None }); - SynField - ([], false, Some F3, - LongIdent (SynLongIdent ([int], [], [None])), false, - PreXmlDoc ((6,6), FSharp.Compiler.Xml.XmlDocCollector), - None, (6,6--6,13), { LeadingKeyword = None - MutableKeyword = None })], + [Field + (SynField + ([], false, Some F1, + LongIdent (SynLongIdent ([int], [], [None])), + false, + PreXmlDoc ((4,6), FSharp.Compiler.Xml.XmlDocCollector), + None, (4,6--4,13), { LeadingKeyword = None + MutableKeyword = None })); + Field + (SynField + ([], false, None, FromParseError (5,6--5,6), false, + PreXmlDoc ((5,6), FSharp.Compiler.Xml.XmlDocCollector), + None, (5,6--5,6), { LeadingKeyword = None + MutableKeyword = None })); + Field + (SynField + ([], false, Some F3, + LongIdent (SynLongIdent ([int], [], [None])), + false, + PreXmlDoc ((6,6), FSharp.Compiler.Xml.XmlDocCollector), + None, (6,6--6,13), { LeadingKeyword = None + MutableKeyword = None }))], (4,4--6,15)), (4,4--6,15)), [], None, (3,5--6,15), { LeadingKeyword = Type (3,0--3,4) EqualsRange = Some (3,7--3,8) diff --git a/tests/service/data/SyntaxTree/Type/SynTypeDefnWithRecordContainsTheRangeOfTheWithKeyword.fs.bsl b/tests/service/data/SyntaxTree/Type/SynTypeDefnWithRecordContainsTheRangeOfTheWithKeyword.fs.bsl index 7cb9f5a2af5..993fcc36e63 100644 --- a/tests/service/data/SyntaxTree/Type/SynTypeDefnWithRecordContainsTheRangeOfTheWithKeyword.fs.bsl +++ b/tests/service/data/SyntaxTree/Type/SynTypeDefnWithRecordContainsTheRangeOfTheWithKeyword.fs.bsl @@ -16,12 +16,14 @@ ImplFile Simple (Record (None, - [SynField - ([], false, Some Bar, - LongIdent (SynLongIdent ([int], [], [None])), false, - PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), - None, (3,6--3,15), { LeadingKeyword = None - MutableKeyword = None })], + [Field + (SynField + ([], false, Some Bar, + LongIdent (SynLongIdent ([int], [], [None])), + false, + PreXmlDoc ((3,6), FSharp.Compiler.Xml.XmlDocCollector), + None, (3,6--3,15), { LeadingKeyword = None + MutableKeyword = None }))], (3,4--3,17)), (3,4--3,17)), [Member (SynBinding diff --git a/vsintegration/tests/FSharp.Editor.Tests/SemanticClassificationServiceTests.fs b/vsintegration/tests/FSharp.Editor.Tests/SemanticClassificationServiceTests.fs index 9d0b2346639..6c58f658ee9 100644 --- a/vsintegration/tests/FSharp.Editor.Tests/SemanticClassificationServiceTests.fs +++ b/vsintegration/tests/FSharp.Editor.Tests/SemanticClassificationServiceTests.fs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. namespace FSharp.Editor.Tests From d3403caee0e62ae3a64964f19fc93f20a50d6aae Mon Sep 17 00:00:00 2001 From: Charles Roddie Date: Sat, 1 Aug 2026 07:31:22 +0100 Subject: [PATCH 25/33] Implement interpolated strings via String.Concat (#19971) --- .../.FSharp.Compiler.Service/11.0.100.md | 4 + src/Compiler/Checking/CheckFormatStrings.fs | 6 +- src/Compiler/Checking/CheckFormatStrings.fsi | 9 + .../Checking/Expressions/CheckExpressions.fs | 227 +++++++++--------- src/Compiler/Service/SynExpr.fs | 5 +- src/Compiler/SyntaxTree/ParseHelpers.fs | 46 ++++ src/Compiler/SyntaxTree/ParseHelpers.fsi | 10 + src/Compiler/SyntaxTree/SyntaxTree.fs | 7 +- src/Compiler/SyntaxTree/SyntaxTree.fsi | 11 +- src/Compiler/TypedTree/TcGlobals.fs | 1 - src/Compiler/TypedTree/TcGlobals.fsi | 2 - .../TypedTree/TypedTreeOps.ExprOps.fs | 3 - .../TypedTree/TypedTreeOps.ExprOps.fsi | 3 - src/Compiler/pars.fsy | 4 +- .../NativeAOT/NativeAOT_Test.fsproj | 36 +++ tests/AheadOfTime/NativeAOT/Program.fs | 34 +++ tests/AheadOfTime/NativeAOT/check.cmd | 2 + tests/AheadOfTime/NativeAOT/check.ps1 | 37 +++ tests/AheadOfTime/Trimming/check.ps1 | 4 +- tests/AheadOfTime/check.ps1 | 1 + .../EmittedIL/StringFormatAndInterpolation.fs | 84 +++++++ .../Language/InterpolatedStringsTests.fs | 10 + ...iler.Service.SurfaceArea.netstandard20.bsl | 28 ++- tests/fsharp/core/quotes/test.fsx | 6 +- .../InterpolatedStringOffsideInModule.fs.bsl | 3 +- ...nterpolatedStringOffsideInNestedLet.fs.bsl | 7 +- ...polatedStringAdjacentEqualsWithHole.fs.bsl | 3 +- ...latedStringWithSynStringKindRegular.fs.bsl | 3 +- ...dStringWithSynStringKindTripleQuote.fs.bsl | 3 +- ...atedStringWithSynStringKindVerbatim.fs.bsl | 16 +- ...tringWithTripleQuoteMultipleDollars.fs.bsl | 6 +- ...ringWithTripleQuoteMultipleDollars2.fs.bsl | 2 +- 32 files changed, 468 insertions(+), 155 deletions(-) create mode 100644 tests/AheadOfTime/NativeAOT/NativeAOT_Test.fsproj create mode 100644 tests/AheadOfTime/NativeAOT/Program.fs create mode 100644 tests/AheadOfTime/NativeAOT/check.cmd create mode 100644 tests/AheadOfTime/NativeAOT/check.ps1 diff --git a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md index c0233963b7e..9e5b990b2ce 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md +++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md @@ -158,6 +158,10 @@ * Improvements in error and warning messages: new error FS3885 when `let!`/`use!` is the final expression in a computation expression; new warning FS3886 when a list literal contains a single tuple element (likely missing `;` separator); improved wording for FS0003, FS0025, FS0039, FS0072, FS0247, FS0597, FS0670, FS3082, and SRTP operator-not-in-scope hints. ([PR #19398](https://github.com/dotnet/fsharp/pull/19398)) * Exception field serialization (`GetObjectData` and field-restoring constructor) is now gated behind `langversion:11` (`LanguageFeature.ExceptionFieldSerializationSupport`). With langversion ≤10, exception codegen is unchanged from pre-#19342 behavior. ([PR #19746](https://github.com/dotnet/fsharp/pull/19746)) +* Lower string-typed interpolated strings to `System.String.Concat` rather than the reflection-based `printf` engine, making them trim- and NativeAOT-compatible. This generalizes and ungates the previous all-string `String.Concat` optimization, so it now applies to every string-typed interpolation. ([Language suggestion #1108](https://github.com/fsharp/fslang-suggestions/issues/1108), [PR #19971](https://github.com/dotnet/fsharp/pull/19971)) +* Interpolated string holes (e.g. `$"{x}"`) are now formatted with invariant culture (via the `string` operator) instead of the current thread culture. ([PR #19971](https://github.com/dotnet/fsharp/pull/19971)) ### Breaking Changes + +* `FSharp.Compiler.Syntax.SynInterpolatedStringPart.FillExpr` now carries a `SynInterpolationFormatting` value (separating .NET alignment/format from printf specifiers) instead of an `Ident option`. ([PR #19971](https://github.com/dotnet/fsharp/pull/19971)) * Optimizer: don't inline named functions in debug builds ([PR #19548](https://github.com/dotnet/fsharp/pull/19548) diff --git a/src/Compiler/Checking/CheckFormatStrings.fs b/src/Compiler/Checking/CheckFormatStrings.fs index 70608224578..d768dc9e47d 100644 --- a/src/Compiler/Checking/CheckFormatStrings.fs +++ b/src/Compiler/Checking/CheckFormatStrings.fs @@ -37,6 +37,9 @@ let mkFlexibleDecimalFormatTypar (g: TcGlobals) m = let mkFlexibleFloatFormatTypar (g: TcGlobals) m = mkFlexibleFormatTypar g m [ g.float_ty; g.float32_ty; g.decimal_ty ] g.float_ty +let stringFormatTy (g: TcGlobals) = + if g.checkNullness && g.langFeatureNullness then g.string_ty_ambivalent else g.string_ty + type FormatInfoRegister = { mutable leftJustify : bool mutable numPrefixIfPos : char option @@ -448,8 +451,7 @@ let parseFormatStringInternal checkOtherFlags ch collectSpecifierLocation fragLine fragCol 1 let i = skipPossibleInterpolationHole (i+1) - let stringTy = if g.checkNullness && g.langFeatureNullness then g.string_ty_ambivalent else g.string_ty - parseLoop ((posi, stringTy) :: acc) (i, fragLine, fragCol+1) fragments + parseLoop ((posi, stringFormatTy g) :: acc) (i, fragLine, fragCol+1) fragments | 'O' -> checkOtherFlags ch diff --git a/src/Compiler/Checking/CheckFormatStrings.fsi b/src/Compiler/Checking/CheckFormatStrings.fsi index eb8120f712d..a581f26be8f 100644 --- a/src/Compiler/Checking/CheckFormatStrings.fsi +++ b/src/Compiler/Checking/CheckFormatStrings.fsi @@ -12,6 +12,15 @@ open FSharp.Compiler.TcGlobals open FSharp.Compiler.Text open FSharp.Compiler.TypedTree +/// A flexible type variable constrained to the integer types accepted by the '%d'/'%i'/'%u' specifiers. +val mkFlexibleIntFormatTypar: g: TcGlobals -> m: range -> TType + +/// A flexible type variable constrained to 'decimal', as accepted by the '%M' specifier. +val mkFlexibleDecimalFormatTypar: g: TcGlobals -> m: range -> TType + +/// The type accepted by the '%s' specifier: ambivalent about nullness when nullness is checked. +val stringFormatTy: g: TcGlobals -> TType + val ParseFormatString: m: range -> fragmentRanges: range list -> diff --git a/src/Compiler/Checking/Expressions/CheckExpressions.fs b/src/Compiler/Checking/Expressions/CheckExpressions.fs index cb4543e7498..e4b3e755841 100644 --- a/src/Compiler/Checking/Expressions/CheckExpressions.fs +++ b/src/Compiler/Checking/Expressions/CheckExpressions.fs @@ -6,7 +6,6 @@ module internal FSharp.Compiler.CheckExpressions open System open System.Collections.Generic -open System.Text.RegularExpressions open Internal.Utilities.Collections open Internal.Utilities.Library @@ -146,43 +145,6 @@ exception InvalidInternalsVisibleToAssemblyName of badName: string * fileName: s exception InvalidAttributeTargetForLanguageElement of elementTargets: string array * allowedTargets: string array * range: range -//---------------------------------------------------------------------------------------------- -// Helpers for determining if/what specifiers a string has. -// Used to decide if interpolated string can be lowered to a concat call. -// We don't care about single- vs multi-$ strings here, because lexer took care of that already. -//---------------------------------------------------------------------------------------------- -[] -let (|HasFormatSpecifier|_|) (s: string) = - if - Regex.IsMatch( - s, - // Regex pattern for something like: %[flags][width][.precision][type] - """ - (^|[^%]) # Start with beginning of string or any char other than '%' - (%%)*% # followed by an odd number of '%' chars - [+-0 ]{0,3} # optionally followed by flags - (\d+)? # optionally followed by width - (\.\d+)? # optionally followed by .precision - [bscdiuxXoBeEfFgGMOAat] # and then a char that determines specifier's type - """, - RegexOptions.Compiled ||| RegexOptions.IgnorePatternWhitespace) - then - ValueSome HasFormatSpecifier - else - ValueNone - -// Removes trailing "%s" unless it was escaped by another '%' (checks for odd sequence of '%' before final "%s") -let (|WithTrailingStringSpecifierRemoved|) (s: string) = - if s.EndsWith "%s" then - let i = s.AsSpan(0, s.Length - 2).LastIndexOfAnyExcept '%' - let diff = s.Length - 2 - i - if diff &&& 1 <> 0 then - s[..s.Length - 3] - else - s - else - s - /// Compute the available access rights from a particular location in code let ComputeAccessRights eAccessPath eInternalsVisibleCompPaths eFamilyType = AccessibleFrom (eAccessPath :: eInternalsVisibleCompPaths, eFamilyType) @@ -7724,6 +7686,96 @@ and TcFormatStringExpr cenv (overallTy: OverallTy) env m tpenv (fmtString: strin mkString g m fmtString, tpenv ) +/// Lower a string-typed interpolated string to a reflection-free System.String.Concat of its parts, +/// type-checking each part in place. +and TcInterpolatedStringViaConcat (cenv: cenv, overallTy: OverallTy, env: TcEnv, m: range, tpenv: UnscopedTyparEnv, parts: SynInterpolatedStringPart list) = + let g = cenv.g + let mSynth = m.MakeSynthetic() + let strLit (s: string) = SynExpr.Const(SynConst.String(s, SynStringKind.Regular, mSynth), mSynth) + let paren (e: SynExpr) = SynExpr.Paren(e, range0, None, mSynth) + + // '(sprintf spec e : string)': format a printf-specifier hole (still reflection-based). + let sprintfOp (spec: string, e: SynExpr) = + let f = mkSynApp1 (mkSynLidGet mSynth [ "Microsoft"; "FSharp"; "Core"; "ExtraTopLevelOperators" ] "sprintf") (strLit spec) mSynth + let call = mkSynApp1 f (paren e) mSynth + SynExpr.Typed(call, SynType.LongIdent(SynLongIdent([ mkSynId mSynth "string" ], [], [ None ])), mSynth) + + // 'String.Format(InvariantCulture, "{0,align:format}", e)': format an aligned or '{e:fmt}' hole. + let stringFormatOp (alignment: SynExpr option, format: Ident option, e: SynExpr) = + let alignText = match alignment with Some (SynExpr.Const (SynConst.Int32 n, _)) -> "," + string n | _ -> "" + let formatText = match format with Some n -> ":" + n.idText | None -> "" + let netFormat = "{0" + alignText + formatText + "}" + let invariant = mkSynLidGet mSynth [ "System"; "Globalization"; "CultureInfo" ] "InvariantCulture" + let args = paren (SynExpr.Tuple(false, [ invariant; strLit netFormat; e ], [ range0; range0 ], mSynth)) + mkSynApp1 (mkSynLidGet mSynth [ "System"; "String" ] "Format") args mSynth + + // Type-check one hole and convert it to a (string expression, may-be-null) pair. + let convertHole (synFill: SynExpr, formatting: SynInterpolationFormatting, tpenv: UnscopedTyparEnv) = + // Constrain the hole to 'constraintTy', then render it with 'string' as for a plain '{x}' hole. Used for + // bare specifiers (no flags/width/precision) that act only as a type annotation: the value renders the + // same through 'string' as through the specifier. ('%u' is not one of these: it reinterprets a signed + // value as unsigned, so it does not match 'string' - e.g. '%u' of -1 is "4294967295".) + let convertViaString constraintTy = + let fill, tpenv = TcExpr cenv (MustEqual constraintTy) env tpenv synFill + (mkCallStringOperator g m (tyOfExpr g fill) fill, false), tpenv + match formatting with + | SynInterpolationFormatting.Printf (spec, _) -> + match spec with + // A bare '%s' requires a string; pass it through (it may be null) instead of formatting via 'sprintf'. + // Its type is the one 'sprintf "%s"' uses, so a nullable string is accepted here too. + | "%s" -> + let fill, tpenv = TcExpr cenv (MustEqual (CheckFormatStrings.stringFormatTy g)) env tpenv synFill + (fill, true), tpenv + | "%c" -> convertViaString g.char_ty + | "%d" | "%i" -> convertViaString (CheckFormatStrings.mkFlexibleIntFormatTypar g m) + | "%M" -> convertViaString (CheckFormatStrings.mkFlexibleDecimalFormatTypar g m) + | _ -> + let arg, tpenv = TcExpr cenv (MustEqual g.string_ty) env tpenv (sprintfOp (spec, synFill)) + (arg, false), tpenv + | SynInterpolationFormatting.DotNet (alignment, format) -> + // Type-checking the hole here is also where a function value gets warned about. + let fill, tpenv = TcExprFlex2 cenv (NewInferenceType g) env false tpenv synFill + let fillTy = tyOfExpr g fill + if g.langVersion.SupportsFeature LanguageFeature.WarnWhenFunctionValueUsedAsInterpolatedStringArg && (isFunTy g fillTy || isDelegateTy g fillTy) then + warning (Error(FSComp.SR.tcFunctionValueUsedAsInterpolatedStringArg (), synFill.Range)) + match alignment, format with + | None, None -> (if isStringTy g fillTy then (fill, true) else (mkCallStringOperator g m fillTy fill, false)), tpenv + | _ -> + // Format the already-checked hole via a synthesized 'String.Format', binding its boxed value + // to a temporary so the hole is not type-checked a second time. Re-checking 'synFill' would + // duplicate any error in it; boxing to 'obj' keeps the 'Format' overload unambiguous (so a + // hole that already failed to check doesn't also leak a confusing 'Format' overload error). + let boxedFill = mkCallBox g m fillTy fill + let tmpVal, _ = mkLocal mSynth "interpHole" (tyOfExpr g boxedFill) + let envInner = AddLocalVal g cenv.tcSink mSynth tmpVal env + let tmpRef = SynExpr.Ident(mkSynId mSynth tmpVal.LogicalName) + let arg, tpenv = TcExpr cenv (MustEqual g.string_ty) envInner tpenv (stringFormatOp (alignment, format, tmpRef)) + (mkCompGenLet mSynth tmpVal boxedFill arg, false), tpenv + + // One (string expression, may-be-null) per non-empty part; a builder (not map) since 'tpenv' threads + // through the holes. Literals and conversions are never null; only a raw string passthrough may be. + let argExprs, tpenv = + let ra = ResizeArray() + let mutable tpenvAcc = tpenv + for part in parts do + match part with + | SynInterpolatedStringPart.String (s, _) -> + if s <> "" then + ra.Add((mkString g m (s.Replace("%%", "%")), false)) + | SynInterpolatedStringPart.FillExpr (synFill, formatting) -> + let argExpr, tpenvAfter = convertHole (synFill, formatting, tpenvAcc) + ra.Add argExpr + tpenvAcc <- tpenvAfter + List.ofSeq ra, tpenvAcc + + let resultExpr = + match argExprs with + // A lone arg has no Concat to map its null to ""; a possibly-null one coalesces via 'string'. + | [ (single, true) ] -> mkCallStringOperator g m g.string_ty single + | _ -> mkStringConcat (g, m, List.map fst argExprs) + + TcPropagatingExprLeafThenConvert cenv overallTy g.string_ty env m (fun () -> resultExpr, tpenv) + /// Check an interpolated string expression and [] warnForFunctionValuesInFillExprs (g: TcGlobals) argTys synFillExprs = match argTys, synFillExprs with @@ -7741,11 +7793,7 @@ and TcInterpolatedStringExpr cenv (overallTy: OverallTy) env m tpenv (parts: Syn parts |> List.choose (function | SynInterpolatedStringPart.String _ -> None - | SynInterpolatedStringPart.FillExpr (fillExpr, _) -> - match fillExpr with - // Detect "x" part of "...{x,3}..." - | SynExpr.Tuple (false, [e; SynExpr.Const (SynConst.Int32 _align, _)], _, _) -> Some e - | e -> Some e) + | SynInterpolatedStringPart.FillExpr (fillExpr, _) -> Some fillExpr) let stringFragmentRanges = parts @@ -7813,19 +7861,21 @@ and TcInterpolatedStringExpr cenv (overallTy: OverallTy) env m tpenv (parts: Syn let isFormattableString = (match stringKind with Choice2Of2 _ -> true | _ -> false) - // The format string used for checking in CheckFormatStrings. This replaces interpolation holes with %P + // The format string used for checking in CheckFormatStrings, reconstructed from the parts: each + // hole becomes a '%P(...)' marker, prefixed by its printf specifier or alignment. let printfFormatString = parts |> List.map (function | SynInterpolatedStringPart.String (s, _) -> s - | SynInterpolatedStringPart.FillExpr (fillExpr, format) -> + | SynInterpolatedStringPart.FillExpr (_, SynInterpolationFormatting.Printf (spec, _)) -> + spec + "%P()" + | SynInterpolatedStringPart.FillExpr (fillExpr, SynInterpolationFormatting.DotNet (alignment, format)) -> + match fillExpr with + | SynExpr.Tuple (false, _, _, _) -> errorR(Error(FSComp.SR.tcInvalidAlignmentInInterpolatedString(), m)) + | _ -> () let alignText = - match fillExpr with - // Validate and detect ",3" part of "...{x,3}..." - | SynExpr.Tuple (false, args, _, _) -> - match args with - | [_; SynExpr.Const (SynConst.Int32 align, _)] -> string align - | _ -> errorR(Error(FSComp.SR.tcInvalidAlignmentInInterpolatedString(), m)); "" + match alignment with + | Some (SynExpr.Const (SynConst.Int32 align, _)) -> string align | _ -> "" let formatText = match format with None -> "()" | Some n -> "(" + n.idText + ")" "%" + alignText + "P" + formatText ) @@ -7879,75 +7929,28 @@ and TcInterpolatedStringExpr cenv (overallTy: OverallTy) env m tpenv (parts: Syn else let str = mkString g m printfFormatString mkCallNewFormat g m printerTy printerArgTy printerResidueTy printerResultTy printerTupleTy str, tpenv + elif isString then + // String-typed interpolation: lower to a reflection-free System.String.Concat of the parts, + // type-checking each hole in place (no separate batch, no flat fill-expression list). + TcInterpolatedStringViaConcat (cenv, overallTy, env, m, tpenv, parts) else - // Type check the expressions filling the holes + // $"...{x}..." used as a PrintfFormat value: build a PrintfFormat that captures the args. let fillExprs, tpenv = TcExprsNoFlexes cenv env m tpenv argTys synFillExprs if g.langVersion.SupportsFeature LanguageFeature.WarnWhenFunctionValueUsedAsInterpolatedStringArg then warnForFunctionValuesInFillExprs g argTys synFillExprs - // Take all interpolated string parts and typed fill expressions - // and convert them to typed expressions that can be used as args to System.String.Concat - // return an empty list if there are some format specifiers that make lowering to not applicable - let rec concatenable acc fillExprs parts = - match fillExprs, parts with - | [], [] -> - List.rev acc - | [], SynInterpolatedStringPart.FillExpr _ :: _ - | _, [] -> - // This should never happen, there will always be as many typed fill expressions - // as there are FillExprs in the interpolated string parts - error(InternalError("Mismatch in interpolation expression count", m)) - | _, SynInterpolatedStringPart.String (WithTrailingStringSpecifierRemoved "", _) :: parts -> - // If the string is empty (after trimming %s of the end), we skip it - concatenable acc fillExprs parts - - | _, SynInterpolatedStringPart.String (WithTrailingStringSpecifierRemoved HasFormatSpecifier, _) :: _ - | _, SynInterpolatedStringPart.FillExpr (_, Some _) :: _ - | _, SynInterpolatedStringPart.FillExpr (SynExpr.Tuple (isStruct = false; exprs = [_; SynExpr.Const (SynConst.Int32 _, _)]), _) :: _ -> - // There was a format specifier like %20s{..} or {..,20} or {x:hh}, which means we cannot simply concat - [] - - | _, SynInterpolatedStringPart.String (s & WithTrailingStringSpecifierRemoved trimmed, m) :: parts -> - let finalStr = trimmed.Replace("%%", "%") - concatenable (mkString g (shiftEnd 0 (finalStr.Length - s.Length) m) finalStr :: acc) fillExprs parts - - | fillExpr :: fillExprs, SynInterpolatedStringPart.FillExpr _ :: parts -> - concatenable (fillExpr :: acc) fillExprs parts - - let canLower = - g.langVersion.SupportsFeature LanguageFeature.LowerInterpolatedStringToConcat - && isString - && argTys |> List.forall (isStringTy g) - - let concatenableExprs = if canLower then concatenable [] fillExprs parts else [] - - match concatenableExprs with - | [p1; p2; p3; p4] -> TcPropagatingExprLeafThenConvert cenv overallTy g.string_ty env m (fun () -> mkStaticCall_String_Concat4 g m p1 p2 p3 p4, tpenv) - | [p1; p2; p3] -> TcPropagatingExprLeafThenConvert cenv overallTy g.string_ty env m (fun () -> mkStaticCall_String_Concat3 g m p1 p2 p3, tpenv) - | [p1; p2] -> TcPropagatingExprLeafThenConvert cenv overallTy g.string_ty env m (fun () -> mkStaticCall_String_Concat2 g m p1 p2, tpenv) - | [p1] -> p1, tpenv - | _ -> - - let fillExprsBoxed = (argTys, fillExprs) ||> List.map2 (mkCallBox g m) - - let argsExpr = mkArray (g.obj_ty_withNulls, fillExprsBoxed, m) - let percentATysExpr = - if percentATys.Length = 0 then - mkNull m (mkArrayType g g.system_Type_ty) - else - let tyExprs = percentATys |> Array.map (mkCallTypeOf g m) |> Array.toList - mkArray (g.system_Type_ty, tyExprs, m) - - let fmtExpr = MakeMethInfoCall cenv.amap m newFormatMethod [] [mkString g m printfFormatString; argsExpr; percentATysExpr] None + let fillExprsBoxed = (argTys, fillExprs) ||> List.map2 (mkCallBox g m) - if isString then - TcPropagatingExprLeafThenConvert cenv overallTy g.string_ty env (* true *) m (fun () -> - // Make the call to sprintf - mkCall_sprintf g m printerTy fmtExpr [], tpenv - ) + let argsExpr = mkArray (g.obj_ty_withNulls, fillExprsBoxed, m) + let percentATysExpr = + if percentATys.Length = 0 then + mkNull m (mkArrayType g g.system_Type_ty) else - fmtExpr, tpenv + let tyExprs = percentATys |> Array.map (mkCallTypeOf g m) |> Array.toList + mkArray (g.system_Type_ty, tyExprs, m) + + MakeMethInfoCall cenv.amap m newFormatMethod [] [mkString g m printfFormatString; argsExpr; percentATysExpr] None, tpenv // The case for $"..." used as type FormattableString or IFormattable | Choice2Of2 createFormattableStringMethod -> diff --git a/src/Compiler/Service/SynExpr.fs b/src/Compiler/Service/SynExpr.fs index deff02fe9b0..ef320e68a97 100644 --- a/src/Compiler/Service/SynExpr.fs +++ b/src/Compiler/Service/SynExpr.fs @@ -1087,10 +1087,13 @@ module SynExpr = | SynExpr.InterpolatedString _, SynExpr.Sequential _ | SynExpr.InterpolatedString _, SynExpr.Tuple(isStruct = false) -> true + // Removing the parens would let a trailing alignment or format be parsed as part of the hole, + // e.g. the ',-3' in '$"{(if b then 1 else 0),-3}"' becoming a tuple in the else branch. | SynExpr.InterpolatedString(contents = contents), Dangling.Problematic _ -> contents |> List.exists (function - | SynInterpolatedStringPart.FillExpr(qualifiers = Some _) -> true + | SynInterpolatedStringPart.FillExpr(formatting = SynInterpolationFormatting.DotNet(alignment = Some _)) + | SynInterpolatedStringPart.FillExpr(formatting = SynInterpolationFormatting.DotNet(format = Some _)) -> true | _ -> false) // {| A = (1; 2) |} diff --git a/src/Compiler/SyntaxTree/ParseHelpers.fs b/src/Compiler/SyntaxTree/ParseHelpers.fs index ff54b94af30..c9192060ed3 100644 --- a/src/Compiler/SyntaxTree/ParseHelpers.fs +++ b/src/Compiler/SyntaxTree/ParseHelpers.fs @@ -69,6 +69,52 @@ let rhs2 (parseState: IParseState) i j = /// Get the range corresponding to one of the r.h.s. symbols of a grammar rule while it is being reduced let rhs parseState i = rhs2 parseState i i +/// Split a trailing printf specifier (e.g. "%d") off an interpolated-string literal that precedes a +/// hole. '%%' is a literal escape, not a specifier. +let peelTrailingPrintfSpecifier (litText: string) : string * string option = + let n = litText.Length + let mutable i = 0 + let mutable specStart = -1 + + while i < n && specStart < 0 do + if litText[i] = '%' then + if i + 1 < n && litText[i + 1] = '%' then + i <- i + 2 // '%%' escape, keep scanning + else + specStart <- i // start of a real specifier + else + i <- i + 1 + + // A real printf specifier ends, immediately before the hole, with a type character. Anything else + // (for example the explicit '%P(' placeholder syntax) is left in the literal untouched. + if specStart < 0 || "bscdiuxXoBeEfFgGMOAat".IndexOf litText[n - 1] < 0 then + litText, None + else + litText[.. specStart - 1], Some litText[specStart..] + +/// Build the [String literal; FillExpr hole] pair for one interpolation hole, splitting the '{x,n}' +/// alignment out of its tuple encoding and peeling a trailing printf specifier onto the hole. +let mkInterpolatedStringFillParts (litText: string, litRange: range, fill: SynExpr * Ident option) = + let fillExpr, qualifier = fill + + let holeExpr, alignment = + match fillExpr with + | SynExpr.Tuple(false, [ e; (SynExpr.Const(SynConst.Int32 _, _) as n) ], _, _) -> e, Some n + | _ -> fillExpr, None + + let litValue, formatting = + match qualifier, alignment with + | None, None -> + match peelTrailingPrintfSpecifier litText with + | lit, Some spec -> lit, SynInterpolationFormatting.Printf(spec, litRange) + | _, None -> litText, SynInterpolationFormatting.DotNet(None, None) + | _ -> litText, SynInterpolationFormatting.DotNet(alignment, qualifier) + + [ + SynInterpolatedStringPart.String(litValue, litRange) + SynInterpolatedStringPart.FillExpr(holeExpr, formatting) + ] + //------------------------------------------------------------------------ // Parsing/lexing: status of #if/#endif processing in lexing, used for continuations // for whitespace tokens in parser specification. diff --git a/src/Compiler/SyntaxTree/ParseHelpers.fsi b/src/Compiler/SyntaxTree/ParseHelpers.fsi index b5286edf872..148868c13d2 100644 --- a/src/Compiler/SyntaxTree/ParseHelpers.fsi +++ b/src/Compiler/SyntaxTree/ParseHelpers.fsi @@ -38,6 +38,16 @@ val rhs2: parseState: IParseState -> i: int -> j: int -> range val rhs: parseState: IParseState -> i: int -> range +/// Peel a trailing printf specifier (e.g. "%d") off an interpolated-string literal that precedes a +/// hole, returning the literal without it and the specifier text. '%%' is a literal escape. +val peelTrailingPrintfSpecifier: litText: string -> string * string option + +/// Build the [String literal; FillExpr hole] pair for one interpolation hole, splitting the +/// '{x,n}' alignment out of its tuple encoding and peeling a trailing printf specifier off the +/// literal onto the hole. +val mkInterpolatedStringFillParts: + litText: string * litRange: range * fill: (SynExpr * Ident option) -> SynInterpolatedStringPart list + type LexerIfdefStackEntry = | IfDefIf | IfDefElse diff --git a/src/Compiler/SyntaxTree/SyntaxTree.fs b/src/Compiler/SyntaxTree/SyntaxTree.fs index 27b01c376c6..f5cde6c2b27 100644 --- a/src/Compiler/SyntaxTree/SyntaxTree.fs +++ b/src/Compiler/SyntaxTree/SyntaxTree.fs @@ -898,7 +898,12 @@ type SynExprAnonRecordFieldOrSpread = [] type SynInterpolatedStringPart = | String of value: string * range: range - | FillExpr of fillExpr: SynExpr * qualifiers: Ident option + | FillExpr of fillExpr: SynExpr * formatting: SynInterpolationFormatting + +[] +type SynInterpolationFormatting = + | DotNet of alignment: SynExpr option * format: Ident option + | Printf of specifier: string * range: range [] type SynSimplePat = diff --git a/src/Compiler/SyntaxTree/SyntaxTree.fsi b/src/Compiler/SyntaxTree/SyntaxTree.fsi index 3b254636f68..97ca48b425e 100644 --- a/src/Compiler/SyntaxTree/SyntaxTree.fsi +++ b/src/Compiler/SyntaxTree/SyntaxTree.fsi @@ -1034,7 +1034,16 @@ type SynExprAnonRecordFieldOrSpread = [] type SynInterpolatedStringPart = | String of value: string * range: range - | FillExpr of fillExpr: SynExpr * qualifiers: Ident option + | FillExpr of fillExpr: SynExpr * formatting: SynInterpolationFormatting + +/// Represents how an interpolation hole in an interpolated string is formatted. +[] +type SynInterpolationFormatting = + /// .NET-style formatting: optional alignment '{x,n}' and optional format '{x:fmt}'. + | DotNet of alignment: SynExpr option * format: Ident option + + /// printf-style formatting: a single specifier, the '%d' in '%d{x}'. + | Printf of specifier: string * range: range /// Represents a syntax tree for simple F# patterns [] diff --git a/src/Compiler/TypedTree/TcGlobals.fs b/src/Compiler/TypedTree/TcGlobals.fs index 5b55012f907..3f983633574 100644 --- a/src/Compiler/TypedTree/TcGlobals.fs +++ b/src/Compiler/TypedTree/TcGlobals.fs @@ -1725,7 +1725,6 @@ type TcGlobals( member _.seq_map_info = v_seq_map_info member _.seq_singleton_info = v_seq_singleton_info member _.seq_empty_info = v_seq_empty_info - member _.sprintf_info = v_sprintf_info member _.new_format_info = v_new_format_info member _.unbox_info = v_unbox_info member _.get_generic_comparer_info = v_get_generic_comparer_info diff --git a/src/Compiler/TypedTree/TcGlobals.fsi b/src/Compiler/TypedTree/TcGlobals.fsi index 8ecc7e83f00..709abfc5b18 100644 --- a/src/Compiler/TypedTree/TcGlobals.fsi +++ b/src/Compiler/TypedTree/TcGlobals.fsi @@ -1007,8 +1007,6 @@ type internal TcGlobals = member splice_raw_expr_vref: TypedTree.ValRef - member sprintf_info: IntrinsicValRef - member sprintf_vref: TypedTree.ValRef member string_ty: TypedTree.TType diff --git a/src/Compiler/TypedTree/TypedTreeOps.ExprOps.fs b/src/Compiler/TypedTree/TypedTreeOps.ExprOps.fs index d5dc5ef07f0..0d74adb8be2 100644 --- a/src/Compiler/TypedTree/TypedTreeOps.ExprOps.fs +++ b/src/Compiler/TypedTree/TypedTreeOps.ExprOps.fs @@ -1454,9 +1454,6 @@ module internal Makers = let mkCallSeqEmpty g m ty1 = mkApps g (typedExprForIntrinsic g m g.seq_empty_info, [ [ ty1 ] ], [], m) - let mkCall_sprintf (g: TcGlobals) m funcTy fmtExpr fillExprs = - mkApps g (typedExprForIntrinsic g m g.sprintf_info, [ [ funcTy ] ], fmtExpr :: fillExprs, m) - let mkCallDeserializeQuotationFSharp20Plus g m e1 e2 e3 e4 = let args = [ e1; e2; e3; e4 ] mkApps g (typedExprForIntrinsic g m g.deserialize_quoted_FSharp_20_plus_info, [], [ mkRefTupledNoTypes g m args ], m) diff --git a/src/Compiler/TypedTree/TypedTreeOps.ExprOps.fsi b/src/Compiler/TypedTree/TypedTreeOps.ExprOps.fsi index 70379648e63..cce19a8e556 100644 --- a/src/Compiler/TypedTree/TypedTreeOps.ExprOps.fsi +++ b/src/Compiler/TypedTree/TypedTreeOps.ExprOps.fsi @@ -404,9 +404,6 @@ module internal Makers = val mkCallSeqEmpty: TcGlobals -> range -> TType -> Expr - /// Make a call to the 'isprintf' function for string interpolation - val mkCall_sprintf: g: TcGlobals -> m: range -> funcTy: TType -> fmtExpr: Expr -> fillExprs: Expr list -> Expr - val mkCallDeserializeQuotationFSharp20Plus: TcGlobals -> range -> Expr -> Expr -> Expr -> Expr -> Expr val mkCallDeserializeQuotationFSharp40Plus: TcGlobals -> range -> Expr -> Expr -> Expr -> Expr -> Expr -> Expr diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy index 24a7cd63f70..9e769ad40fe 100644 --- a/src/Compiler/pars.fsy +++ b/src/Compiler/pars.fsy @@ -7235,7 +7235,7 @@ interpolatedStringParts: { [ SynInterpolatedStringPart.String(fst $1, rhs parseState 1) ] } | INTERP_STRING_PART interpolatedStringFill interpolatedStringParts - { SynInterpolatedStringPart.String(fst $1, rhs parseState 1) :: SynInterpolatedStringPart.FillExpr $2 :: $3 } + { mkInterpolatedStringFillParts (fst $1, rhs parseState 1, $2) @ $3 } | INTERP_STRING_PART interpolatedStringParts { let rbrace = parseState.InputEndPosition 1 @@ -7249,7 +7249,7 @@ interpolatedStringParts: interpolatedString: | INTERP_STRING_BEGIN_PART interpolatedStringFill interpolatedStringParts { let s, synStringKind, _ = $1 - SynInterpolatedStringPart.String(s, rhs parseState 1) :: SynInterpolatedStringPart.FillExpr $2 :: $3, synStringKind } + mkInterpolatedStringFillParts (s, rhs parseState 1, $2) @ $3, synStringKind } | INTERP_STRING_BEGIN_END { let s, synStringKind, _ = $1 diff --git a/tests/AheadOfTime/NativeAOT/NativeAOT_Test.fsproj b/tests/AheadOfTime/NativeAOT/NativeAOT_Test.fsproj new file mode 100644 index 00000000000..1fa87907110 --- /dev/null +++ b/tests/AheadOfTime/NativeAOT/NativeAOT_Test.fsproj @@ -0,0 +1,36 @@ + + + + Exe + net9.0 + preview + true + + + + true + true + true + true + win-x64 + + + + $(LocalFSharpBuildBinPath)/FSharp.Build.dll + $(LocalFSharpBuildBinPath)/fsc.dll + $(LocalFSharpBuildBinPath)/fsc.dll + False + True + + + + + + + + + + + + + diff --git a/tests/AheadOfTime/NativeAOT/Program.fs b/tests/AheadOfTime/NativeAOT/Program.fs new file mode 100644 index 00000000000..dce1bbaf53e --- /dev/null +++ b/tests/AheadOfTime/NativeAOT/Program.fs @@ -0,0 +1,34 @@ +module Program + +open System + +// Check a rendering against an expected string literal; a mismatch prints a "FAILED" line. +let check (actual: string, expected: string) = + if actual <> expected then + Console.WriteLine $"FAILED: expected '{expected}' but got '{actual}'" + +let runChecks () = + let x = 42 + let name = "world" + let pi = 3.14159 + let initial = 'F' + check ($"answer = {x}", "answer = 42") + check ($"hello {name}", "hello world") + check ($"pi ~ {pi:F2}", "pi ~ 3.14") + check ($"padded:{x,6}", "padded: 42") + check ($"greeting %s{name}", "greeting world") + // Bare '%d'/'%i'/'%c'/'%M' specifiers lower to the same reflection-free path as a plain hole. + check ($"answer = %d{x}", "answer = 42") + check ($"initial = %c{initial}", "initial = F") + + // The following use printf specifiers that still route through 'sprintf', so they would make the + // NativeAOT publish fail with IL2026/IL2070/IL3050. + // check ($"pi ~ %.2f{pi}", "pi ~ 3.14") + // check ($"value = %A{x}", "value = 42") + +[] +let main _ = + runChecks () + // 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.cmd b/tests/AheadOfTime/NativeAOT/check.cmd new file mode 100644 index 00000000000..4eefff011c5 --- /dev/null +++ b/tests/AheadOfTime/NativeAOT/check.cmd @@ -0,0 +1,2 @@ +@echo off +powershell -ExecutionPolicy ByPass -NoProfile -command "& """%~dp0check.ps1"""" diff --git a/tests/AheadOfTime/NativeAOT/check.ps1 b/tests/AheadOfTime/NativeAOT/check.ps1 new file mode 100644 index 00000000000..dc69fb765df --- /dev/null +++ b/tests/AheadOfTime/NativeAOT/check.ps1 @@ -0,0 +1,37 @@ +# Publish the test project with NativeAOT and check that it runs. +# +# The point of this check is that the publish succeeds: a string-typed interpolated string +# must lower to a reflection-free form (System.String.Concat), not the reflection-based +# printf engine. If it regresses to printf, FSharp.Reflection becomes statically reachable, +# NativeAOT analysis emits IL2026/IL2070/IL3050, TreatWarningsAsErrors turns them into errors, +# and this publish fails. + +$ErrorActionPreference = "Stop" + +$root = "NativeAOT_Test" +$tfm = "net9.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" +if (-not ($LASTEXITCODE -eq 0)) { + Set-Location $cwd + Write-Error "NativeAOT publish failed with exit code $LASTEXITCODE" -ErrorAction Stop +} + +$exe = Join-Path $PSScriptRoot "bin/release/$tfm/win-x64/publish/$root.exe" +$output = (& $exe) -join "`n" +$exitCode = $LASTEXITCODE +Set-Location $cwd + +# The app prints a "FAILED" line per mismatch and "Finished" last, so its output is exactly "Finished" only if all checks passed. +if (-not ($exitCode -eq 0)) { + Write-Error "NativeAOT app crashed with exit code $exitCode.`nOutput:`n$output" -ErrorAction Stop +} + +if ($output.Trim() -ne "Finished") { + Write-Error "NativeAOT interpolation checks failed.`nOutput:`n$output" -ErrorAction Stop +} + +Write-Host "NativeAOT interpolated-string test passed." diff --git a/tests/AheadOfTime/Trimming/check.ps1 b/tests/AheadOfTime/Trimming/check.ps1 index 49cf96e31d3..406eefc616e 100644 --- a/tests/AheadOfTime/Trimming/check.ps1 +++ b/tests/AheadOfTime/Trimming/check.ps1 @@ -68,10 +68,10 @@ $allErrors += CheckTrim -root "SelfContained_Trimming_Test" -tfm "net9.0" -outpu # Check net9.0 trimmed assemblies with static linked FSharpCore. # Statically links FSharp.Compiler.Service; the size is stable now that its codegen is # deterministic (#19928/#19929). Update if compiler/trimming output intentionally changes. -$allErrors += CheckTrim -root "StaticLinkedFSharpCore_Trimming_Test" -tfm "net9.0" -outputfile "StaticLinkedFSharpCore_Trimming_Test.dll" -expected_len 9173504 -callerLineNumber 71 +$allErrors += CheckTrim -root "StaticLinkedFSharpCore_Trimming_Test" -tfm "net9.0" -outputfile "StaticLinkedFSharpCore_Trimming_Test.dll" -expected_len 9174016 -callerLineNumber 71 # Check net9.0 trimmed assemblies with F# metadata resources removed -$allErrors += CheckTrim -root "FSharpMetadataResource_Trimming_Test" -tfm "net9.0" -outputfile "FSharpMetadataResource_Trimming_Test.dll" -expected_len 7612928 -callerLineNumber 74 +$allErrors += CheckTrim -root "FSharpMetadataResource_Trimming_Test" -tfm "net9.0" -outputfile "FSharpMetadataResource_Trimming_Test.dll" -expected_len 7613440 -callerLineNumber 74 # Report all errors and exit with failure if any occurred if ($allErrors.Count -gt 0) { diff --git a/tests/AheadOfTime/check.ps1 b/tests/AheadOfTime/check.ps1 index e8fd72b57e5..5c1de83b903 100644 --- a/tests/AheadOfTime/check.ps1 +++ b/tests/AheadOfTime/check.ps1 @@ -2,3 +2,4 @@ Write-Host "AheadOfTime: check1.ps1" Equality\check.ps1 Trimming\check.ps1 +NativeAOT\check.ps1 diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/StringFormatAndInterpolation.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/StringFormatAndInterpolation.fs index 38729fc70be..57b3c0ae5ec 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/StringFormatAndInterpolation.fs +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/StringFormatAndInterpolation.fs @@ -90,6 +90,90 @@ IL_0014: call string [runtime]System.String::Concat(string, string) IL_0019: ret"""] + [] + let ``Interpolated string with more than 4 parts is lowered to a System.String.Concat array`` () = + FSharp """ +module StringFormatAndInterpolation + +let f (a: string, b: string, c: string, d: string, e: string) = $"{a}{b}{c}{d}{e}" + """ + |> compile + |> shouldSucceed + |> verifyIL [""" +IL_0000: ldc.i4.5 +IL_0001: newarr [runtime]System.String +IL_0006: dup +IL_0007: ldc.i4.0 +IL_0008: ldarg.0 +IL_0009: stelem [runtime]System.String +IL_000e: dup +IL_000f: ldc.i4.1 +IL_0010: ldarg.1 +IL_0011: stelem [runtime]System.String +IL_0016: dup +IL_0017: ldc.i4.2 +IL_0018: ldarg.2 +IL_0019: stelem [runtime]System.String +IL_001e: dup +IL_001f: ldc.i4.3 +IL_0020: ldarg.3 +IL_0021: stelem [runtime]System.String +IL_0026: dup +IL_0027: ldc.i4.4 +IL_0028: ldarg.s e +IL_002a: stelem [runtime]System.String +IL_002f: call string [runtime]System.String::Concat(string[]) +IL_0034: ret"""] + + [] + let ``String-typed interpolation holes are concatenated directly, with no string conversion or null check`` () = + FSharp """ +module StringFormatAndInterpolation + +let f (a: string, b: string) = $"{a}{b.ToLower()}" + """ + |> compile + |> shouldSucceed + |> verifyIL [""" +IL_0000: ldarg.0 +IL_0001: ldarg.1 +IL_0002: callvirt instance string [runtime]System.String::ToLower() +IL_0007: call string [runtime]System.String::Concat(string, + string) +IL_000c: ret"""] + + [] + let ``Interpolated string with a single float hole is rendered via an invariant-culture ToString`` () = + FSharp """ +module StringFormatAndInterpolation + +let f (x: float) = $"{x}" + """ + |> compile + |> shouldSucceed + |> verifyIL [""" +IL_0000: ldarga.s x +IL_0002: ldnull +IL_0003: call class [netstandard]System.Globalization.CultureInfo [netstandard]System.Globalization.CultureInfo::get_InvariantCulture() +IL_0008: call instance string [netstandard]System.Double::ToString(string, + class [netstandard]System.IFormatProvider) +IL_000d: ret"""] + + [] + let ``Interpolated string with a single bool hole is rendered via ToString`` () = + FSharp """ +module StringFormatAndInterpolation + +let f (x: bool) = $"{x}" + """ + |> compile + |> shouldSucceed + |> verifyIL [""" +IL_0000: ldarga.s x +IL_0002: constrained. [runtime]System.Boolean +IL_0008: callvirt instance string [netstandard]System.Object::ToString() +IL_000d: ret"""] + [] let ``Interpolated string with concat converts to span implicitly`` () = let compilation = diff --git a/tests/FSharp.Compiler.ComponentTests/Language/InterpolatedStringsTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/InterpolatedStringsTests.fs index 4db7b63ad4b..6a1e194362d 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/InterpolatedStringsTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/InterpolatedStringsTests.fs @@ -102,6 +102,16 @@ printfn \"%s\" s" |> shouldSucceed |> withStdOutContains "% 42" + [] + let ``Interpolation holes are rendered with invariant culture`` () = + Fsx """ +System.Threading.Thread.CurrentThread.CurrentCulture <- System.Globalization.CultureInfo "de-DE" +printf "%s" $"{1.5}" + """ + |> compileExeAndRun + |> shouldSucceed + |> withStdOutContains "1.5" + [] let ``Percent signs separated by format specifier's flags`` () = Fsx """ diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.bsl b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.bsl index 8ca3e43896e..76080e3d775 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.bsl +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.bsl @@ -8182,8 +8182,8 @@ FSharp.Compiler.Syntax.SynInterfaceImpl: Microsoft.FSharp.Core.FSharpOption`1[FS FSharp.Compiler.Syntax.SynInterfaceImpl: System.String ToString() FSharp.Compiler.Syntax.SynInterpolatedStringPart+FillExpr: FSharp.Compiler.Syntax.SynExpr fillExpr FSharp.Compiler.Syntax.SynInterpolatedStringPart+FillExpr: FSharp.Compiler.Syntax.SynExpr get_fillExpr() -FSharp.Compiler.Syntax.SynInterpolatedStringPart+FillExpr: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident] get_qualifiers() -FSharp.Compiler.Syntax.SynInterpolatedStringPart+FillExpr: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident] qualifiers +FSharp.Compiler.Syntax.SynInterpolatedStringPart+FillExpr: FSharp.Compiler.Syntax.SynInterpolationFormatting formatting +FSharp.Compiler.Syntax.SynInterpolatedStringPart+FillExpr: FSharp.Compiler.Syntax.SynInterpolationFormatting get_formatting() FSharp.Compiler.Syntax.SynInterpolatedStringPart+String: FSharp.Compiler.Text.Range get_range() FSharp.Compiler.Syntax.SynInterpolatedStringPart+String: FSharp.Compiler.Text.Range range FSharp.Compiler.Syntax.SynInterpolatedStringPart+String: System.String get_value() @@ -8194,7 +8194,7 @@ FSharp.Compiler.Syntax.SynInterpolatedStringPart: Boolean IsFillExpr FSharp.Compiler.Syntax.SynInterpolatedStringPart: Boolean IsString FSharp.Compiler.Syntax.SynInterpolatedStringPart: Boolean get_IsFillExpr() FSharp.Compiler.Syntax.SynInterpolatedStringPart: Boolean get_IsString() -FSharp.Compiler.Syntax.SynInterpolatedStringPart: FSharp.Compiler.Syntax.SynInterpolatedStringPart NewFillExpr(FSharp.Compiler.Syntax.SynExpr, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident]) +FSharp.Compiler.Syntax.SynInterpolatedStringPart: FSharp.Compiler.Syntax.SynInterpolatedStringPart NewFillExpr(FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Syntax.SynInterpolationFormatting) FSharp.Compiler.Syntax.SynInterpolatedStringPart: FSharp.Compiler.Syntax.SynInterpolatedStringPart NewString(System.String, FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynInterpolatedStringPart: FSharp.Compiler.Syntax.SynInterpolatedStringPart+FillExpr FSharp.Compiler.Syntax.SynInterpolatedStringPart: FSharp.Compiler.Syntax.SynInterpolatedStringPart+String @@ -8202,6 +8202,28 @@ FSharp.Compiler.Syntax.SynInterpolatedStringPart: FSharp.Compiler.Syntax.SynInte FSharp.Compiler.Syntax.SynInterpolatedStringPart: Int32 Tag FSharp.Compiler.Syntax.SynInterpolatedStringPart: Int32 get_Tag() FSharp.Compiler.Syntax.SynInterpolatedStringPart: System.String ToString() +FSharp.Compiler.Syntax.SynInterpolationFormatting+DotNet: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident] format +FSharp.Compiler.Syntax.SynInterpolationFormatting+DotNet: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident] get_format() +FSharp.Compiler.Syntax.SynInterpolationFormatting+DotNet: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynExpr] alignment +FSharp.Compiler.Syntax.SynInterpolationFormatting+DotNet: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynExpr] get_alignment() +FSharp.Compiler.Syntax.SynInterpolationFormatting+Printf: FSharp.Compiler.Text.Range get_range() +FSharp.Compiler.Syntax.SynInterpolationFormatting+Printf: FSharp.Compiler.Text.Range range +FSharp.Compiler.Syntax.SynInterpolationFormatting+Printf: System.String get_specifier() +FSharp.Compiler.Syntax.SynInterpolationFormatting+Printf: System.String specifier +FSharp.Compiler.Syntax.SynInterpolationFormatting+Tags: Int32 DotNet +FSharp.Compiler.Syntax.SynInterpolationFormatting+Tags: Int32 Printf +FSharp.Compiler.Syntax.SynInterpolationFormatting: Boolean IsDotNet +FSharp.Compiler.Syntax.SynInterpolationFormatting: Boolean IsPrintf +FSharp.Compiler.Syntax.SynInterpolationFormatting: Boolean get_IsDotNet() +FSharp.Compiler.Syntax.SynInterpolationFormatting: Boolean get_IsPrintf() +FSharp.Compiler.Syntax.SynInterpolationFormatting: FSharp.Compiler.Syntax.SynInterpolationFormatting NewDotNet(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynExpr], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident]) +FSharp.Compiler.Syntax.SynInterpolationFormatting: FSharp.Compiler.Syntax.SynInterpolationFormatting NewPrintf(System.String, FSharp.Compiler.Text.Range) +FSharp.Compiler.Syntax.SynInterpolationFormatting: FSharp.Compiler.Syntax.SynInterpolationFormatting+DotNet +FSharp.Compiler.Syntax.SynInterpolationFormatting: FSharp.Compiler.Syntax.SynInterpolationFormatting+Printf +FSharp.Compiler.Syntax.SynInterpolationFormatting: FSharp.Compiler.Syntax.SynInterpolationFormatting+Tags +FSharp.Compiler.Syntax.SynInterpolationFormatting: Int32 Tag +FSharp.Compiler.Syntax.SynInterpolationFormatting: Int32 get_Tag() +FSharp.Compiler.Syntax.SynInterpolationFormatting: System.String ToString() FSharp.Compiler.Syntax.SynLetOrUse: Boolean IsBang FSharp.Compiler.Syntax.SynLetOrUse: Boolean IsFromSource FSharp.Compiler.Syntax.SynLetOrUse: Boolean IsRecursive diff --git a/tests/fsharp/core/quotes/test.fsx b/tests/fsharp/core/quotes/test.fsx index 30ed5ba331a..54364a56125 100644 --- a/tests/fsharp/core/quotes/test.fsx +++ b/tests/fsharp/core/quotes/test.fsx @@ -5884,10 +5884,8 @@ module Interpolation = let interpolatedWithLiteralQuoted = <@ $"abc {1} def" @> let actual2 = interpolatedWithLiteralQuoted.ToString() checkStrings "brewbreebrwhat2" actual2 - """Call (None, PrintFormatToString, - [NewObject (PrintfFormat`5, Value ("abc %P() def"), - NewArray (Object, Call (None, Box, [Value (1)])), - Value ())])""" + """Call (None, Concat, + [Value ("abc "), Call (None, ToString, [Value (1)]), Value (" def")])""" module TestQuotationWithIdenticalStaticInstanceMethods = type C() = diff --git a/tests/service/data/SyntaxTree/String/InterpolatedStringOffsideInModule.fs.bsl b/tests/service/data/SyntaxTree/String/InterpolatedStringOffsideInModule.fs.bsl index d7fb308c07b..1a16a38174d 100644 --- a/tests/service/data/SyntaxTree/String/InterpolatedStringOffsideInModule.fs.bsl +++ b/tests/service/data/SyntaxTree/String/InterpolatedStringOffsideInModule.fs.bsl @@ -21,7 +21,8 @@ ImplFile InterpolatedString ([String (" ", (3,8--4,1)); - FillExpr (Const (Int32 0, (4,1--4,2)), None); + FillExpr + (Const (Int32 0, (4,1--4,2)), DotNet (None, None)); String ("", (4,2--4,4))], Regular, (3,8--4,4)), (2,8--2,9), Yes (2,4--4,4), { LeadingKeyword = Let (2,4--2,7) diff --git a/tests/service/data/SyntaxTree/String/InterpolatedStringOffsideInNestedLet.fs.bsl b/tests/service/data/SyntaxTree/String/InterpolatedStringOffsideInNestedLet.fs.bsl index 1455d3f425e..0c57f36ed8a 100644 --- a/tests/service/data/SyntaxTree/String/InterpolatedStringOffsideInNestedLet.fs.bsl +++ b/tests/service/data/SyntaxTree/String/InterpolatedStringOffsideInNestedLet.fs.bsl @@ -27,9 +27,10 @@ ImplFile InterpolatedString ([String (" ", (3,8--4,1)); - FillExpr (Const (Int32 0, (4,1--4,2)), None); - String ("", (4,2--4,4))], Regular, (3,8--4,4)), - (2,8--2,9), Yes (2,4--4,4), + FillExpr + (Const (Int32 0, (4,1--4,2)), + DotNet (None, None)); String ("", (4,2--4,4))], + Regular, (3,8--4,4)), (2,8--2,9), Yes (2,4--4,4), { LeadingKeyword = Let (2,4--2,7) InlineKeyword = None EqualsRange = Some (2,10--2,11) })] diff --git a/tests/service/data/SyntaxTree/String/SynExprInterpolatedStringAdjacentEqualsWithHole.fs.bsl b/tests/service/data/SyntaxTree/String/SynExprInterpolatedStringAdjacentEqualsWithHole.fs.bsl index bcf55431e8f..9edcf8db177 100644 --- a/tests/service/data/SyntaxTree/String/SynExprInterpolatedStringAdjacentEqualsWithHole.fs.bsl +++ b/tests/service/data/SyntaxTree/String/SynExprInterpolatedStringAdjacentEqualsWithHole.fs.bsl @@ -26,7 +26,8 @@ ImplFile (None, SynValInfo ([], SynArgInfo ([], false, None)), None), Named (SynIdent (x, None), false, None, (2,4--2,5)), None, InterpolatedString - ([String ("", (2,7--2,10)); FillExpr (Ident n, None); + ([String ("", (2,7--2,10)); + FillExpr (Ident n, DotNet (None, None)); String ("", (2,11--2,13))], Regular, (2,7--2,13)), (2,4--2,5), Yes (2,0--2,13), { LeadingKeyword = Let (2,0--2,3) InlineKeyword = None diff --git a/tests/service/data/SyntaxTree/String/SynExprInterpolatedStringWithSynStringKindRegular.fs.bsl b/tests/service/data/SyntaxTree/String/SynExprInterpolatedStringWithSynStringKindRegular.fs.bsl index 7026b9a1034..46da672fdeb 100644 --- a/tests/service/data/SyntaxTree/String/SynExprInterpolatedStringWithSynStringKindRegular.fs.bsl +++ b/tests/service/data/SyntaxTree/String/SynExprInterpolatedStringWithSynStringKindRegular.fs.bsl @@ -14,7 +14,8 @@ ImplFile Named (SynIdent (s, None), false, None, (2,4--2,5)), None, InterpolatedString ([String ("yo ", (2,8--2,14)); - FillExpr (Const (Int32 42, (2,14--2,16)), None); + FillExpr + (Const (Int32 42, (2,14--2,16)), DotNet (None, None)); String ("", (2,16--2,18))], Regular, (2,8--2,18)), (2,4--2,5), Yes (2,0--2,18), { LeadingKeyword = Let (2,0--2,3) InlineKeyword = None diff --git a/tests/service/data/SyntaxTree/String/SynExprInterpolatedStringWithSynStringKindTripleQuote.fs.bsl b/tests/service/data/SyntaxTree/String/SynExprInterpolatedStringWithSynStringKindTripleQuote.fs.bsl index 9e42b6455ce..3945da38dce 100644 --- a/tests/service/data/SyntaxTree/String/SynExprInterpolatedStringWithSynStringKindTripleQuote.fs.bsl +++ b/tests/service/data/SyntaxTree/String/SynExprInterpolatedStringWithSynStringKindTripleQuote.fs.bsl @@ -17,7 +17,8 @@ ImplFile Named (SynIdent (s, None), false, None, (2,4--2,5)), None, InterpolatedString ([String ("yo ", (2,8--2,16)); - FillExpr (Const (Int32 42, (2,16--2,18)), None); + FillExpr + (Const (Int32 42, (2,16--2,18)), DotNet (None, None)); String ("", (2,18--2,22))], TripleQuote, (2,8--2,22)), (2,4--2,5), Yes (2,0--2,22), { LeadingKeyword = Let (2,0--2,3) InlineKeyword = None diff --git a/tests/service/data/SyntaxTree/String/SynExprInterpolatedStringWithSynStringKindVerbatim.fs.bsl b/tests/service/data/SyntaxTree/String/SynExprInterpolatedStringWithSynStringKindVerbatim.fs.bsl index 2fb03900ebf..6c84a3c2f0f 100644 --- a/tests/service/data/SyntaxTree/String/SynExprInterpolatedStringWithSynStringKindVerbatim.fs.bsl +++ b/tests/service/data/SyntaxTree/String/SynExprInterpolatedStringWithSynStringKindVerbatim.fs.bsl @@ -16,15 +16,15 @@ ImplFile Named (SynIdent (s, None), false, None, (2,4--2,5)), None, InterpolatedString ([String ("Migrate notes of file "", (2,8--2,36)); - FillExpr (Ident oldId, None); + FillExpr (Ident oldId, DotNet (None, None)); String ("" to new file "", (2,41--2,60)); - FillExpr (Ident newId, None); String ("".", (2,65--2,70))], - Verbatim, (2,8--2,70)), (2,4--2,5), Yes (2,0--2,70), - { LeadingKeyword = Let (2,0--2,3) - InlineKeyword = None - EqualsRange = Some (2,6--2,7) })], (2,0--2,70), - { InKeyword = None })], PreXmlDocEmpty, [], None, (2,0--3,0), - { LeadingKeyword = None })], (true, true), + FillExpr (Ident newId, DotNet (None, None)); + String ("".", (2,65--2,70))], Verbatim, (2,8--2,70)), + (2,4--2,5), Yes (2,0--2,70), { LeadingKeyword = Let (2,0--2,3) + InlineKeyword = None + EqualsRange = Some (2,6--2,7) })], + (2,0--2,70), { InKeyword = None })], PreXmlDocEmpty, [], None, + (2,0--3,0), { LeadingKeyword = None })], (true, true), { ConditionalDirectives = [] WarnDirectives = [] CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/String/SynExprInterpolatedStringWithTripleQuoteMultipleDollars.fs.bsl b/tests/service/data/SyntaxTree/String/SynExprInterpolatedStringWithTripleQuoteMultipleDollars.fs.bsl index 3bbd9b2ba46..3e12edd2257 100644 --- a/tests/service/data/SyntaxTree/String/SynExprInterpolatedStringWithTripleQuoteMultipleDollars.fs.bsl +++ b/tests/service/data/SyntaxTree/String/SynExprInterpolatedStringWithTripleQuoteMultipleDollars.fs.bsl @@ -17,9 +17,11 @@ ImplFile Named (SynIdent (s, None), false, None, (2,4--2,5)), None, InterpolatedString ([String ("1 + ", (2,8--2,21)); - FillExpr (Const (Int32 41, (2,21--2,23)), None); + FillExpr + (Const (Int32 41, (2,21--2,23)), DotNet (None, None)); String (" = ", (2,23--2,32)); - FillExpr (Const (Int32 6, (2,32--2,33)), None); + FillExpr + (Const (Int32 6, (2,32--2,33)), DotNet (None, None)); String (" * 7", (2,33--2,43))], TripleQuote, (2,8--2,43)), (2,4--2,5), Yes (2,0--2,43), { LeadingKeyword = Let (2,0--2,3) InlineKeyword = None diff --git a/tests/service/data/SyntaxTree/String/SynExprInterpolatedStringWithTripleQuoteMultipleDollars2.fs.bsl b/tests/service/data/SyntaxTree/String/SynExprInterpolatedStringWithTripleQuoteMultipleDollars2.fs.bsl index ca0ac31fffc..c280d8d831b 100644 --- a/tests/service/data/SyntaxTree/String/SynExprInterpolatedStringWithTripleQuoteMultipleDollars2.fs.bsl +++ b/tests/service/data/SyntaxTree/String/SynExprInterpolatedStringWithTripleQuoteMultipleDollars2.fs.bsl @@ -10,7 +10,7 @@ ImplFile [Expr (InterpolatedString ([String ("", (2,0--2,9)); - FillExpr (Const (Int32 5, (2,9--2,10)), None); + FillExpr (Const (Int32 5, (2,9--2,10)), DotNet (None, None)); String ("", (2,10--2,16))], TripleQuote, (2,0--2,16)), (2,0--2,16))], PreXmlDocEmpty, [], None, (2,0--2,16), { LeadingKeyword = None })], (true, true), From f5c88eb5e99201e5537e9ca131051a31fdf6954f Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Mon, 3 Aug 2026 20:40:31 +0200 Subject: [PATCH 26/33] [main] Source code updates from dotnet/dotnet (#20058) * Backflow from https://github.com/dotnet/dotnet / 50dbab4 build 322464 Diff: https://github.com/dotnet/dotnet/compare/920a0d55f8d87a0423dd3a89555f70d9c9004584..50dbab4de210e882172b07934e9666313b7065f1 From: https://github.com/dotnet/dotnet/commit/920a0d55f8d87a0423dd3a89555f70d9c9004584 To: https://github.com/dotnet/dotnet/commit/50dbab4de210e882172b07934e9666313b7065f1 [[ commit created by automation ]] * Update dependencies from build 322464 Updated Dependencies: Microsoft.Build, Microsoft.Build.Framework, Microsoft.Build.Tasks.Core, Microsoft.Build.Utilities.Core (Version 18.10.0-1.26359.10 -> 18.10.0-preview-26357-08) [[ commit created by automation ]] * Update dependencies from build 322734 No dependency updates to commit [[ commit created by automation ]] * Update dependencies from build 322911 No dependency updates to commit [[ commit created by automation ]] * Update dependencies from build 323048 No dependency updates to commit [[ commit created by automation ]] * Fix NU1903 audit failures from updated transitive dependencies The codeflow update to Microsoft.Build.* now transitively pulls System.Security.Cryptography.Xml 10.0.8 (newly flagged by GHSA advisories, patched in 10.0.10) on .NET, and Microsoft.CodeAnalysis.Test.Resources.Proprietary -> NETStandard.Library 1.6.1 pulls vulnerable System.Net.Http 4.3.0 and System.Text.RegularExpressions 4.3.0 on net472. - Bump System.Security.Cryptography.Xml override to 10.0.10 (Version.Details). - Add .NET-only Cryptography.Xml overrides in fsc/fsi/FSharp.Build.UnitTests (net472 excluded: no such transitive there and its deps conflict with System.ValueTuple). These cascade to Microsoft.FSharp.Compiler and FSharpSuite.Tests. - Override the net472 System.Net.Http/System.Text.RegularExpressions facades to patched 4.3.4/4.3.1 in FSharp.Test.Utilities. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Pin MessagePack to patched 2.5.302 to fix NU1902/NU1903 audit StreamJsonRpc 2.25.29 pulls MessagePack transitively; some restore environments resolve the vulnerable 2.5.198 (< 2.5.301 patched line), tripping NuGetAudit warnings-as-errors in FSharp.Compiler.LanguageServer.Tests. Add an explicit direct reference at 2.5.302 (StreamJsonRpc's own minimum, already patched) so the resolved version is deterministic everywhere. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix malformed Version.Details.xml (duplicate closing Dependency tag) A merge conflict resolution left a stray closing tag after Microsoft.Build.Utilities.Core, making the XML invalid and failing the Maestro Version.Details.props Validation and Codeflow verification checks. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: dotnet-maestro[bot] Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Copilot --- NuGet.config | 4 ++++ eng/Version.Details.props | 10 +++++----- eng/Version.Details.xml | 20 +++++++++---------- eng/Versions.props | 3 +++ .../FSharp.Compiler.LanguageServer.fsproj | 2 ++ src/fsc/fscProject/fsc.fsproj | 5 +++++ src/fsi/fsiProject/fsi.fsproj | 5 +++++ .../FSharp.Build.UnitTests.fsproj | 5 +++++ .../FSharp.Test.Utilities.fsproj | 3 +++ 9 files changed, 42 insertions(+), 15 deletions(-) diff --git a/NuGet.config b/NuGet.config index 527f95b5c87..a6df74bb15e 100644 --- a/NuGet.config +++ b/NuGet.config @@ -35,4 +35,8 @@ + + + + diff --git a/eng/Version.Details.props b/eng/Version.Details.props index 775ff7a16c2..6dd4474cadb 100644 --- a/eng/Version.Details.props +++ b/eng/Version.Details.props @@ -8,10 +8,10 @@ This file should be imported by eng/Versions.props 11.0.0-beta.26369.1 - 18.10.0-1.26370.18 - 18.10.0-1.26370.18 - 18.10.0-1.26370.18 - 18.10.0-1.26370.18 + 18.10.0-preview-26357-08 + 18.10.0-preview-26357-08 + 18.10.0-preview-26357-08 + 18.10.0-preview-26357-08 1.0.0-prerelease.26318.1 1.0.0-prerelease.26318.1 @@ -32,7 +32,7 @@ This file should be imported by eng/Versions.props 10.0.8 10.0.8 10.0.8 - 10.0.8 + 10.0.10 diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 9dadf91aba4..0932647c439 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,22 +1,22 @@ - + - + https://github.com/dotnet/msbuild - eae54023463db15e9a9081f35a959c9162797643 + 746aeb090c9e2bcedc398751370da862014ebf7a - + https://github.com/dotnet/msbuild - eae54023463db15e9a9081f35a959c9162797643 + 746aeb090c9e2bcedc398751370da862014ebf7a - + https://github.com/dotnet/msbuild - eae54023463db15e9a9081f35a959c9162797643 + 746aeb090c9e2bcedc398751370da862014ebf7a - + https://github.com/dotnet/msbuild - eae54023463db15e9a9081f35a959c9162797643 + 746aeb090c9e2bcedc398751370da862014ebf7a https://github.com/dotnet/roslyn @@ -75,7 +75,7 @@ - + https://github.com/dotnet/runtime diff --git a/eng/Versions.props b/eng/Versions.props index b22e821a2de..4a024d1ee71 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -89,6 +89,9 @@ 4.6.1 4.6.3 6.1.2 + + 4.3.4 + 4.3.1 diff --git a/src/FSharp.Compiler.LanguageServer/FSharp.Compiler.LanguageServer.fsproj b/src/FSharp.Compiler.LanguageServer/FSharp.Compiler.LanguageServer.fsproj index e1b1f0b35f9..c5cc30680bc 100644 --- a/src/FSharp.Compiler.LanguageServer/FSharp.Compiler.LanguageServer.fsproj +++ b/src/FSharp.Compiler.LanguageServer/FSharp.Compiler.LanguageServer.fsproj @@ -12,6 +12,8 @@ + + diff --git a/src/fsc/fscProject/fsc.fsproj b/src/fsc/fscProject/fsc.fsproj index a8d694360c1..c66429fe0dc 100644 --- a/src/fsc/fscProject/fsc.fsproj +++ b/src/fsc/fscProject/fsc.fsproj @@ -37,6 +37,11 @@ + + + + + diff --git a/src/fsi/fsiProject/fsi.fsproj b/src/fsi/fsiProject/fsi.fsproj index 58a300a0de9..7a0e2d01428 100644 --- a/src/fsi/fsiProject/fsi.fsproj +++ b/src/fsi/fsiProject/fsi.fsproj @@ -25,6 +25,11 @@ $(ArtifactsDir)obj/$(MSBuildProjectName)/$(Configuration)/ + + + + + diff --git a/tests/FSharp.Build.UnitTests/FSharp.Build.UnitTests.fsproj b/tests/FSharp.Build.UnitTests/FSharp.Build.UnitTests.fsproj index 2018b41cb92..08df369bf4a 100644 --- a/tests/FSharp.Build.UnitTests/FSharp.Build.UnitTests.fsproj +++ b/tests/FSharp.Build.UnitTests/FSharp.Build.UnitTests.fsproj @@ -34,4 +34,9 @@ + + + + + diff --git a/tests/FSharp.Test.Utilities/FSharp.Test.Utilities.fsproj b/tests/FSharp.Test.Utilities/FSharp.Test.Utilities.fsproj index a4f64a0f893..e60fa89b94c 100644 --- a/tests/FSharp.Test.Utilities/FSharp.Test.Utilities.fsproj +++ b/tests/FSharp.Test.Utilities/FSharp.Test.Utilities.fsproj @@ -96,6 +96,9 @@ + + + $(NoWarn);NU1510;44 From 647548bcb3d89ccafc26bd96e3259222430a7f89 Mon Sep 17 00:00:00 2001 From: Nat Elkins Date: Mon, 3 Aug 2026 15:03:53 -0400 Subject: [PATCH 27/33] Secure release-note checks for fork pull requests (#20081) * Secure release-note checks for fork pull requests * Address release-note workflow review feedback --- .github/workflows/check_release_notes.yml | 261 ++++++++++++++-------- 1 file changed, 162 insertions(+), 99 deletions(-) diff --git a/.github/workflows/check_release_notes.yml b/.github/workflows/check_release_notes.yml index 1681a57f399..34a19b198c5 100644 --- a/.github/workflows/check_release_notes.yml +++ b/.github/workflows/check_release_notes.yml @@ -6,53 +6,52 @@ on: - 'main' - 'release/*' permissions: + contents: read issues: write - pull-requests: write + pull-requests: read +concurrency: + group: release-notes-${{ github.event.pull_request.number }} + cancel-in-progress: true jobs: check_release_notes: permissions: - issues: write - pull-requests: write + contents: read + issues: write + pull-requests: read env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ github.token }} + PR_AUTHOR: ${{ github.event.pull_request.user.login }} + PR_BASE_SHA: ${{ github.event.pull_request.base.sha }} + PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }} + PR_LABELS: ${{ toJSON(github.event.pull_request.labels) }} + PR_NUMBER: ${{ github.event.pull_request.number }} + OPT_OUT_RELEASE_NOTES: ${{ contains(github.event.pull_request.labels.*.name, 'NO_RELEASE_NOTES') }} + VNEXT: ${{ vars.VNEXT }} runs-on: ubuntu-latest steps: - - name: Get github ref - uses: actions/github-script@v3 - id: get-pr - with: - script: | - const result = await github.pulls.get({ - pull_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - }); - return { "pr_number": context.issue.number, "ref": result.data.head.ref, "repository": result.data.head.repo.full_name}; - - name: Checkout repo - uses: actions/checkout@v2 - with: - repository: ${{ fromJson(steps.get-pr.outputs.result).repository }} - ref: ${{ fromJson(steps.get-pr.outputs.result).ref }} - fetch-depth: 0 - name: Check for release notes changes id: release_notes_changes run: | - set -e + set -euo pipefail EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64) FSHARP_REPO_URL="https://github.com/${GITHUB_REPOSITORY}" - PR_AUTHOR="${{ github.event.pull_request.user.login }}" - PR_NUMBER=${{ github.event.number }} PR_URL="${FSHARP_REPO_URL}/pull/${PR_NUMBER}" - echo "PR Tags: ${{ toJson(github.event.pull_request.labels) }}" - - OPT_OUT_RELEASE_NOTES=${{ contains(github.event.pull_request.labels.*.name, 'NO_RELEASE_NOTES') }} + [[ "$PR_BASE_SHA" =~ ^[0-9a-f]{40}$ ]] || { echo "::error::Unexpected base SHA: $PR_BASE_SHA"; exit 1; } + [[ "$PR_HEAD_SHA" =~ ^[0-9a-f]{40}$ ]] || { echo "::error::Unexpected head SHA: $PR_HEAD_SHA"; exit 1; } + echo "PR Tags: $PR_LABELS" echo "Opt out of release notes: $OPT_OUT_RELEASE_NOTES" + _current_head_sha=$(gh api "repos/${GITHUB_REPOSITORY}/pulls/${PR_NUMBER}" --jq '.head.sha') + + if [[ "$_current_head_sha" != "$PR_HEAD_SHA" ]]; then + echo "::notice::Skipping stale release-note run for ${PR_HEAD_SHA}; current head is ${_current_head_sha}." + exit 0 + fi + # VNEXT is a GitHub repository variable set via admin settings # It controls the expected release notes version for FSharp.Core and FCS - VNEXT="${{ vars.VNEXT }}" if [[ -z "$VNEXT" ]]; then echo "Error: VNEXT repository variable is not set. Please configure it in GitHub repository settings." exit 1 @@ -60,10 +59,17 @@ jobs: # Parse VS major version from eng/Versions.props for the vNext pattern # 18 - _vs_major_version=$(grep -oPm1 "(?<=)[^<]+" eng/Versions.props) + _versions_props=$( + gh api \ + -H 'Accept: application/vnd.github.raw+json' \ + "repos/${GITHUB_REPOSITORY}/contents/eng/Versions.props?ref=${PR_BASE_SHA}" + ) + _vs_major_version=$( + sed -n 's:.*\([^<]*\).*:\1:p' <<< "$_versions_props" \ + | head -n 1 + ) FSHARP_CORE_VERSION="$VNEXT" - FCS_VERSION="$VNEXT" VISUAL_STUDIO_VERSION="$_vs_major_version.vNext" echo "Using VNEXT for release notes: ${VNEXT}" @@ -81,7 +87,7 @@ jobs: readonly paths=( "src/FSharp.Core|${_fsharp_core_release_notes_path}" "src/Compiler|${_fsharp_compiler_release_notes_path}" - "LanguageFeatures.fsi|${_fsharp_language_release_notes_path}" + "src/Compiler/Facilities/LanguageFeatures.fsi|${_fsharp_language_release_notes_path}" "vsintegration/src|${_fsharp_vs_release_notes_path}" ) @@ -89,52 +95,101 @@ jobs: RELEASE_NOTES_MESSAGE="" RELEASE_NOTES_MESSAGE_DETAILS="" RELEASE_NOTES_FOUND="" - RELEASE_NOTES_CHANGES_SUMMARY="" RELEASE_NOTES_NOT_FOUND="" PULL_REQUEST_FOUND=true - gh repo set-default ${GITHUB_REPOSITORY} + _modified_files=$( + gh api \ + --method GET \ + --paginate \ + --slurp \ + "repos/${GITHUB_REPOSITORY}/pulls/${PR_NUMBER}/files" \ + -f per_page=100 + ) + _modified_count=$(jq '[.[][]] | length' <<< "$_modified_files") - _modified_paths=`gh pr view ${PR_NUMBER} --json files --jq '.files.[].path'` + # GitHub caps this endpoint at 3,000 files. At the cap the response may be + # incomplete, so fail closed instead of silently missing a protected path. + if (( _modified_count >= 3000 )); then + echo "::error::Cannot safely validate a PR with 3,000 or more changed files." + exit 1 + fi + + path_changed() { + jq -e --arg path "$1" \ + 'any(.[][]; .filename == $path or (.filename | startswith($path + "/")))' \ + <<< "$_modified_files" >/dev/null + } + + release_note_url() { + jq -r --arg file "$1" \ + 'first(.[][] | select(.filename == $file and .status != "removed") | .contents_url) // empty' \ + <<< "$_modified_files" + } + + record_missing_release_note() { + local path="$1" + local release_notes="$2" + local description="**No release notes found or release notes format is not correct**" + RELEASE_NOTES_NOT_FOUND+="| \\\`$path\\\` | [$release_notes](${FSHARP_REPO_URL}/tree/main/$release_notes) | ${description} |" + RELEASE_NOTES_NOT_FOUND+=$'\n' + } - for fields in ${paths[@]} - do + for fields in "${paths[@]}"; do IFS=$'|' read -r path release_notes <<< "$fields" echo "Checking for changed files in: $path" # Check if path is in modified files: - if [[ "${_modified_paths[@]}" =~ "${path}" ]]; then + if path_changed "$path"; then echo " Found $path in modified files" echo " Checking if release notes modified in: $release_notes" - if [[ "${_modified_paths[@]}" =~ "${release_notes}" ]]; then + if path_changed "$release_notes"; then echo " Found $release_notes in modified files" echo " Checking for pull request URL in $release_notes" - if [[ ! -f $release_notes ]]; then - echo " $release_notes does not exist, please, create it." - #exit 1; - fi + _release_note_url=$(release_note_url "$release_notes") + + if [[ -n "$_release_note_url" ]]; then + if [[ "$_release_note_url" != "https://api.github.com/repos/${GITHUB_REPOSITORY}/contents/"* ]] \ + || [[ "$_release_note_url" != *"?ref=${PR_HEAD_SHA}" ]]; then + echo "::error::Release-note content URL does not target the expected repository and PR head." + exit 1 + fi + + _release_note_file=$(mktemp) + + if ! gh api \ + -H 'Accept: application/vnd.github.raw+json' \ + "$_release_note_url" > "$_release_note_file" + then + rm -f "$_release_note_file" + echo "::error::Unable to read $release_notes at PR head $PR_HEAD_SHA." + exit 1 + fi - _pr_link_occurences=`grep -c "${PR_URL}" $release_notes || true` + _pr_link_occurrences=$(grep -Fc -- "$PR_URL" "$_release_note_file" || true) + rm -f "$_release_note_file" - echo " Found $_pr_link_occurences occurences of $PR_URL in $release_notes" + echo " Found $_pr_link_occurrences occurrences of $PR_URL in $release_notes" - if [[ ${_pr_link_occurences} -eq 1 ]]; then - echo " Found pull request URL in $release_notes once" - RELEASE_NOTES_FOUND+="> | \\\`$path\\\` | [$release_notes](${FSHARP_REPO_URL}/tree/main/$release_notes) | |" - RELEASE_NOTES_FOUND+=$'\n' - elif [[ ${_pr_link_occurences} -eq 0 ]]; then - echo " Did not find pull request URL in $release_notes" - DESCRIPTION="**No current pull request URL (${PR_URL}) found, please consider adding it**" - RELEASE_NOTES_FOUND+="> | \\\`$path\\\` | [$release_notes](${FSHARP_REPO_URL}/tree/main/$release_notes) | ${DESCRIPTION} |" - RELEASE_NOTES_FOUND+=$'\n' - PULL_REQUEST_FOUND=false + if [[ ${_pr_link_occurrences} -eq 1 ]]; then + echo " Found pull request URL in $release_notes once" + RELEASE_NOTES_FOUND+="> | \\\`$path\\\` | [$release_notes](${FSHARP_REPO_URL}/tree/main/$release_notes) | |" + RELEASE_NOTES_FOUND+=$'\n' + elif [[ ${_pr_link_occurrences} -eq 0 ]]; then + echo " Did not find pull request URL in $release_notes" + DESCRIPTION="**No current pull request URL (${PR_URL}) found, please consider adding it**" + RELEASE_NOTES_FOUND+="> | \\\`$path\\\` | [$release_notes](${FSHARP_REPO_URL}/tree/main/$release_notes) | ${DESCRIPTION} |" + RELEASE_NOTES_FOUND+=$'\n' + PULL_REQUEST_FOUND=false + fi + else + echo " $release_notes was removed or cannot be read at the PR head." + record_missing_release_note "$path" "$release_notes" fi else echo " Did not find $release_notes in modified files" - DESCRIPTION="**No release notes found or release notes format is not correct**" - RELEASE_NOTES_NOT_FOUND+="| \\\`$path\\\` | [$release_notes](${FSHARP_REPO_URL}/tree/main/$release_notes) | ${DESCRIPTION} |" - RELEASE_NOTES_NOT_FOUND+=$'\n' + record_missing_release_note "$path" "$release_notes" fi else echo " Nothing found, no release notes required" @@ -220,60 +275,68 @@ jobs: RELEASE_NOTES_MESSAGE+=$RELEASE_NOTES_MESSAGE_DETAILS fi - echo "release-notes-check-message<<$EOF" >>$GITHUB_OUTPUT - - if [[ "$OPT_OUT_RELEASE_NOTES" = true ]]; then - echo "" >>$GITHUB_OUTPUT - echo "" >>$GITHUB_OUTPUT - echo "## :warning: Release notes required, but author opted out" >>$GITHUB_OUTPUT - echo "" >>$GITHUB_OUTPUT - echo "" >>$GITHUB_OUTPUT - echo "> [!WARNING]" >>$GITHUB_OUTPUT - echo "> **Author opted out of release notes, check is disabled for this pull request.**" >>$GITHUB_OUTPUT - echo "> cc @dotnet/fsharp-team-msft" >>$GITHUB_OUTPUT - else - echo "${RELEASE_NOTES_MESSAGE}" >>$GITHUB_OUTPUT + _current_head_sha=$(gh api "repos/${GITHUB_REPOSITORY}/pulls/${PR_NUMBER}" --jq '.head.sha') + + if [[ "$_current_head_sha" != "$PR_HEAD_SHA" ]]; then + echo "::notice::Discarding stale release-note result for ${PR_HEAD_SHA}; current head is ${_current_head_sha}." + exit 0 fi - echo "$EOF" >>$GITHUB_OUTPUT + { + echo "release-notes-check-message<<$EOF" + + if [[ "$OPT_OUT_RELEASE_NOTES" = true ]]; then + echo "" + echo "" + echo "## :warning: Release notes required, but author opted out" + echo "" + echo "" + echo "> [!WARNING]" + echo "> **Author opted out of release notes, check is disabled for this pull request.**" + echo "> cc @dotnet/fsharp-team-msft" + else + echo "${RELEASE_NOTES_MESSAGE}" + fi + + echo "$EOF" + } >> "$GITHUB_OUTPUT" if [[ $RELEASE_NOTES_NOT_FOUND != "" && ${OPT_OUT_RELEASE_NOTES} != true ]]; then exit 1 fi - # Did bot already commented the PR? - - name: Find Comment - if: success() || failure() - uses: peter-evans/find-comment@v2.4.0 - id: fc - with: - issue-number: ${{github.event.pull_request.number}} - comment-author: 'github-actions[bot]' - body-includes: '' - # If not, create a new comment - - name: Create comment - if: steps.fc.outputs.comment-id == '' && (success() || failure()) - uses: actions/github-script@v6 + # Keep one bot comment current without evaluating pull request content as JavaScript. + - name: Create or update comment + if: ${{ (success() || failure()) && steps.release_notes_changes.outputs.release-notes-check-message != '' }} + uses: actions/github-script@v9 + env: + COMMENT_BODY: ${{ steps.release_notes_changes.outputs.release-notes-check-message }} with: github-token: ${{ github.token }} script: | - const comment = await github.rest.issues.createComment({ - issue_number: context.issue.number, + const marker = ''; + const comments = await github.paginate(github.rest.issues.listComments, { owner: context.repo.owner, repo: context.repo.repo, - body: `${{steps.release_notes_changes.outputs.release-notes-check-message}}` + issue_number: context.issue.number, + per_page: 100 }); - return comment.data.id; - # If yes, update the comment - - name: Update comment - if: steps.fc.outputs.comment-id != '' && (success() || failure()) - uses: actions/github-script@v6 - with: - github-token: ${{ github.token }} - script: | - const comment = await github.rest.issues.updateComment({ + const existing = comments.find(comment => + comment.user?.login === 'github-actions[bot]' && comment.body?.includes(marker)); + + if (existing) { + const comment = await github.rest.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: existing.id, + body: process.env.COMMENT_BODY + }); + return comment.data.id; + } + + const comment = await github.rest.issues.createComment({ + issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, - comment_id: ${{steps.fc.outputs.comment-id}}, - body: `${{steps.release_notes_changes.outputs.release-notes-check-message}}` + body: process.env.COMMENT_BODY }); - return comment.data.id; \ No newline at end of file + return comment.data.id; From 536800cd82a0481c055f08d570bbc924712331b2 Mon Sep 17 00:00:00 2001 From: Adam Boniecki <20281641+abonie@users.noreply.github.com> Date: Mon, 3 Aug 2026 21:35:40 +0200 Subject: [PATCH 28/33] Update test project to net11 (#20104) * Update test project to net11 Internal CI was failing since the move to net11 because restoring this test project had to suddenly be done via network call to nuget.org * Update target framework and PDB path in tests --- .../CompilerService/EncMethodDebugInformationTests.fs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/FSharp.Compiler.ComponentTests/CompilerService/EncMethodDebugInformationTests.fs b/tests/FSharp.Compiler.ComponentTests/CompilerService/EncMethodDebugInformationTests.fs index 831d9c6f020..9f933aa7863 100644 --- a/tests/FSharp.Compiler.ComponentTests/CompilerService/EncMethodDebugInformationTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/CompilerService/EncMethodDebugInformationTests.fs @@ -286,10 +286,10 @@ let private buildCSharpScratchPdb () = File.WriteAllText( projPath, - """ + $""" Library - net10.0 + {TestFramework.productTfm} portable false true @@ -323,7 +323,7 @@ let private buildCSharpScratchPdb () = if p.ExitCode <> 0 then failwith $"dotnet build of the C# scratch library failed: {stdout}\n{stderr}" - let pdbPath = Path.Combine(workDir, "bin", "Debug", "net10.0", "scratch.pdb") + let pdbPath = Path.Combine(workDir, "bin", "Debug", TestFramework.productTfm, "scratch.pdb") Assert.True(File.Exists pdbPath, $"expected portable PDB at {pdbPath}") workDir, pdbPath From a6b69ce2401f544d19bc2a322877fe9a15617bb2 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" Date: Tue, 4 Aug 2026 02:05:03 +0000 Subject: [PATCH 29/33] Update dependencies from https://github.com/dotnet/arcade build 20260803.2 On relative base path root Microsoft.DotNet.Arcade.Sdk From Version 10.0.0-beta.26379.2 -> To Version 10.0.0-beta.26403.2 --- eng/Version.Details.props | 2 +- eng/Version.Details.xml | 4 ++-- global.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/eng/Version.Details.props b/eng/Version.Details.props index 90530fac6e9..46235551626 100644 --- a/eng/Version.Details.props +++ b/eng/Version.Details.props @@ -6,7 +6,7 @@ This file should be imported by eng/Versions.props - 10.0.0-beta.26379.2 + 10.0.0-beta.26403.2 18.10.0-preview-26357-08 18.10.0-preview-26357-08 diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 1bcf5a3b3b4..47a21a26b85 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -82,9 +82,9 @@ - + https://github.com/dotnet/arcade - c5d54a9de6e0e20a85e37fa3576a37235276772b + 0e35127eec8820435a0de7f2349ae2b99eeb9c7b https://dev.azure.com/dnceng/internal/_git/dotnet-optimization diff --git a/global.json b/global.json index 53910226296..be22da605c3 100644 --- a/global.json +++ b/global.json @@ -22,7 +22,7 @@ "xcopy-msbuild": "18.0.0" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.26379.2", + "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.26403.2", "Microsoft.DotNet.Helix.Sdk": "8.0.0-beta.23255.2" } } From 3cc77558348067a8a560c0613887fa2a4f07e46e Mon Sep 17 00:00:00 2001 From: Joey Robichaud Date: Tue, 4 Aug 2026 00:55:01 -0700 Subject: [PATCH 30/33] Move to Roslyn's unified ExternalAccess library (#20099) --- docs/release-notes/.VisualStudio/18.vNext.md | 1 + eng/Version.Details.props | 4 ++-- eng/Version.Details.xml | 8 ++++---- eng/Versions.props | 6 +++--- vsintegration/Directory.Build.targets | 2 +- vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj | 2 +- .../tests/FSharp.Editor.Tests/FSharp.Editor.Tests.fsproj | 2 +- .../tests/UnitTests/VisualFSharp.UnitTests.fsproj | 2 +- 8 files changed, 14 insertions(+), 13 deletions(-) diff --git a/docs/release-notes/.VisualStudio/18.vNext.md b/docs/release-notes/.VisualStudio/18.vNext.md index 6205e8caef0..0166a73a6d9 100644 --- a/docs/release-notes/.VisualStudio/18.vNext.md +++ b/docs/release-notes/.VisualStudio/18.vNext.md @@ -15,3 +15,4 @@ * Rename "inline hints" to "inlay hints" in VS options for consistency with industry terminology. ([PR #19318](https://github.com/dotnet/fsharp/pull/19318)) * Unused analyzers: disable in VS when file has errors ([PR #19892](https://github.com/dotnet/fsharp/pull/19892)) +* Move to Roslyn's unified ExternalAccess library ([PR #20099](https://github.com/dotnet/fsharp/pull/20099)) diff --git a/eng/Version.Details.props b/eng/Version.Details.props index 6dd4474cadb..58ea96baca0 100644 --- a/eng/Version.Details.props +++ b/eng/Version.Details.props @@ -24,7 +24,7 @@ This file should be imported by eng/Versions.props 5.10.0-1.26365.3 5.10.0-1.26365.3 5.10.0-1.26365.3 - 5.10.0-1.26365.3 + 5.10.0-1.26365.3 5.10.0-1.26365.3 5.10.0-1.26365.3 @@ -55,7 +55,7 @@ This file should be imported by eng/Versions.props $(MicrosoftCodeAnalysisCSharpPackageVersion) $(MicrosoftCodeAnalysisEditorFeaturesPackageVersion) $(MicrosoftCodeAnalysisEditorFeaturesTextPackageVersion) - $(MicrosoftCodeAnalysisExternalAccessFSharpPackageVersion) + $(MicrosoftVisualStudioLanguageServicesExternalAccessPackageVersion) $(MicrosoftCodeAnalysisFeaturesPackageVersion) $(MicrosoftVisualStudioLanguageServicesPackageVersion) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 0932647c439..b3eb553ea2c 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -34,10 +34,6 @@ https://github.com/dotnet/roslyn 3d32d464e2949f054086fbb5346e4beea0c6df56 - - https://github.com/dotnet/roslyn - 3d32d464e2949f054086fbb5346e4beea0c6df56 - https://github.com/dotnet/roslyn 3d32d464e2949f054086fbb5346e4beea0c6df56 @@ -50,6 +46,10 @@ https://github.com/dotnet/roslyn 3d32d464e2949f054086fbb5346e4beea0c6df56 + + https://github.com/dotnet/roslyn + 3d32d464e2949f054086fbb5346e4beea0c6df56 + https://github.com/dotnet/runtime diff --git a/eng/Versions.props b/eng/Versions.props index 4a024d1ee71..a9b7ec6fd4d 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -113,7 +113,7 @@ $(MicrosoftVisualStudioShellPackagesVersion) $(VisualStudioShellProjectsPackages) - + 18.9.438 18.9.438 18.9.438 @@ -132,7 +132,7 @@ $(VisualStudioEditorPackagesVersion) $(VisualStudioEditorPackagesVersion) @@ -145,7 +145,7 @@ $(MicrosoftVisualStudioThreadingPackagesVersion) - 18.7.1 diff --git a/vsintegration/Directory.Build.targets b/vsintegration/Directory.Build.targets index 16099d6637c..a1d6035a1d3 100644 --- a/vsintegration/Directory.Build.targets +++ b/vsintegration/Directory.Build.targets @@ -14,7 +14,7 @@ - + diff --git a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj index 68206f698bd..e54b6752ea3 100644 --- a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj +++ b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj @@ -179,7 +179,7 @@ - + diff --git a/vsintegration/tests/FSharp.Editor.Tests/FSharp.Editor.Tests.fsproj b/vsintegration/tests/FSharp.Editor.Tests/FSharp.Editor.Tests.fsproj index 0d05a915760..00cf656ed40 100644 --- a/vsintegration/tests/FSharp.Editor.Tests/FSharp.Editor.Tests.fsproj +++ b/vsintegration/tests/FSharp.Editor.Tests/FSharp.Editor.Tests.fsproj @@ -95,7 +95,7 @@ - + diff --git a/vsintegration/tests/UnitTests/VisualFSharp.UnitTests.fsproj b/vsintegration/tests/UnitTests/VisualFSharp.UnitTests.fsproj index cf8cc25e837..8501351f46f 100644 --- a/vsintegration/tests/UnitTests/VisualFSharp.UnitTests.fsproj +++ b/vsintegration/tests/UnitTests/VisualFSharp.UnitTests.fsproj @@ -120,7 +120,7 @@ - + From ea778bb414648883fca4219bf7a69286bf82dd6b Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Tue, 4 Aug 2026 10:00:22 +0200 Subject: [PATCH 31/33] LexFilter: drop non-strict mode (#20106) --- azure-pipelines-PR.yml | 72 ------------------- .../.FSharp.Compiler.Service/11.0.100.md | 1 + src/Compiler/Driver/CompilerConfig.fs | 4 -- src/Compiler/Driver/CompilerConfig.fsi | 4 -- src/Compiler/Driver/CompilerOptions.fs | 8 --- src/Compiler/Driver/ParseAndCheckInputs.fs | 6 +- src/Compiler/Driver/ScriptClosure.fs | 3 +- src/Compiler/FSComp.txt | 4 +- src/Compiler/Facilities/LanguageFeatures.fs | 3 - src/Compiler/Facilities/LanguageFeatures.fsi | 1 - src/Compiler/Facilities/prim-lexing.fs | 26 +++---- src/Compiler/Facilities/prim-lexing.fsi | 14 +--- src/Compiler/Interactive/fsi.fs | 15 ++-- src/Compiler/Service/FSharpCheckerResults.fs | 12 ++-- src/Compiler/Service/FSharpCheckerResults.fsi | 2 - src/Compiler/Service/ServiceLexing.fs | 19 ++--- src/Compiler/Service/ServiceLexing.fsi | 8 +-- src/Compiler/Service/TransparentCompiler.fs | 1 - src/Compiler/Service/service.fs | 2 +- src/Compiler/SyntaxTree/LexFilter.fs | 12 ++-- src/Compiler/SyntaxTree/ParseHelpers.fs | 8 +-- src/Compiler/SyntaxTree/ParseHelpers.fsi | 14 +--- src/Compiler/SyntaxTree/UnicodeLexing.fs | 15 ++-- src/Compiler/SyntaxTree/UnicodeLexing.fsi | 21 ++---- src/Compiler/lex.fsl | 12 ++-- src/Compiler/pars.fsy | 8 +-- src/Compiler/xlf/FSComp.txt.cs.xlf | 14 +--- src/Compiler/xlf/FSComp.txt.de.xlf | 14 +--- src/Compiler/xlf/FSComp.txt.es.xlf | 14 +--- src/Compiler/xlf/FSComp.txt.fr.xlf | 14 +--- src/Compiler/xlf/FSComp.txt.it.xlf | 14 +--- src/Compiler/xlf/FSComp.txt.ja.xlf | 14 +--- src/Compiler/xlf/FSComp.txt.ko.xlf | 14 +--- src/Compiler/xlf/FSComp.txt.pl.xlf | 14 +--- src/Compiler/xlf/FSComp.txt.pt-BR.xlf | 14 +--- src/Compiler/xlf/FSComp.txt.ru.xlf | 14 +--- src/Compiler/xlf/FSComp.txt.tr.xlf | 14 +--- src/Compiler/xlf/FSComp.txt.zh-Hans.xlf | 14 +--- src/Compiler/xlf/FSComp.txt.zh-Hant.xlf | 14 +--- .../CompilerDirectives/Line.fs | 2 +- .../CompilerOptions/Fsc/UncoveredOptions.fs | 2 - .../fsc/misc/compiler_help_output.bsl | 1 - .../PermittedLocations/PermittedLocations.fs | 4 +- .../LetBindings/Basic/Basic.fs | 2 +- .../OffsideExceptions/OffsideExceptions.fs | 2 +- .../OffsideExceptions/RelaxWhitespace2.fs | 2 +- .../Types/UnionTypes/UnionTypes.fs | 2 +- .../Language/CompilerDirectiveTests.fs | 2 +- ...iler.Service.SurfaceArea.netstandard20.bsl | 8 +-- .../HashIfExpression.fs | 2 +- .../PatternMatchCompilationTests.fs | 16 ++--- .../TokenizerTests.fs | 6 +- .../expected-help-output.bsl | 3 - .../CompilerServiceBenchmarks.fs | 1 - .../Compiler/Language/StringInterpolation.fs | 2 +- tests/fsharp/typecheck/sigs/neg114.bsl | 2 - tests/fsharp/typecheck/sigs/neg114.vsbsl | 2 - tests/fsharp/typecheck/sigs/neg69.bsl | 30 -------- tests/fsharp/typecheck/sigs/neg69.vsbsl | 30 -------- tests/fsharp/typecheck/sigs/neg74.bsl | 1 - tests/fsharp/typecheck/sigs/neg74.vsbsl | 1 - tests/fsharp/typecheck/sigs/neg75.bsl | 1 - tests/fsharp/typecheck/sigs/neg75.vsbsl | 1 - tests/fsharp/typecheck/sigs/neg76.bsl | 1 - tests/fsharp/typecheck/sigs/neg76.vsbsl | 1 - tests/fsharp/typecheck/sigs/neg77.bsl | 1 - tests/fsharp/typecheck/sigs/neg77.vsbsl | 1 - tests/fsharp/typecheck/sigs/neg81.bsl | 1 - tests/fsharp/typecheck/sigs/neg81.vsbsl | 1 - tests/fsharp/typecheck/sigs/neg82.bsl | 7 -- tests/fsharp/typecheck/sigs/neg82.vsbsl | 7 -- tests/fsharp/typecheck/sigs/neg83.bsl | 2 - tests/fsharp/typecheck/sigs/neg83.vsbsl | 2 - tests/fsharp/typecheck/sigs/neg_anon_2.bsl | 2 - tests/fsharp/typecheck/sigs/neg_anon_2.vsbsl | 2 - .../Expression/Binary - Plus 02.fs.bsl | 1 - .../Expression/Binary - Plus 05.fs.bsl | 1 - .../data/SyntaxTree/Expression/Do 03.fs.bsl | 1 - .../SyntaxTree/Expression/Downcast 01.fs.bsl | 1 - .../data/SyntaxTree/Expression/For 03.fs.bsl | 1 - .../data/SyntaxTree/Expression/If 05.fs.bsl | 1 - .../data/SyntaxTree/Expression/If 06.fs.bsl | 1 - .../data/SyntaxTree/Expression/If 10.fs.bsl | 1 - .../data/SyntaxTree/Expression/If 11.fs.bsl | 1 - .../data/SyntaxTree/Expression/If 12.fs.bsl | 1 - .../data/SyntaxTree/Expression/If 14.fs.bsl | 1 - .../Lambda - Missing expr 02.fs.bsl | 1 - .../data/SyntaxTree/Expression/Lazy 03.fs.bsl | 1 - .../data/SyntaxTree/Expression/Let 02.fs.bsl | 1 - .../Expression/Object - Class 11.fs.bsl | 1 - .../data/SyntaxTree/Expression/Set 04.fs.bsl | 1 - .../Expression/Try - Finally 04.fs.bsl | 1 - .../Expression/Try - With 04.fs.bsl | 1 - .../Expression/Try - With 06.fs.bsl | 1 - .../data/SyntaxTree/Expression/Try 02.fs.bsl | 1 - .../Try with - Missing expr 02.fs.bsl | 1 - .../Try with - Missing expr 03.fs.bsl | 1 - .../Expression/Tuple - Missing item 08.fs.bsl | 1 - .../Expression/Tuple - Missing item 10.fs.bsl | 1 - .../SyntaxTree/Expression/Upcast 01.fs.bsl | 1 - .../SyntaxTree/Expression/Upcast 04.fs.bsl | 1 - .../SyntaxTree/Expression/Upcast 05.fs.bsl | 1 - .../SyntaxTree/Expression/While 03.fs.bsl | 1 - .../SyntaxTree/Expression/While 04.fs.bsl | 1 - .../SyntaxTree/Expression/WhileBang 03.fs.bsl | 1 - .../SyntaxTree/Expression/WhileBang 04.fs.bsl | 1 - .../IfThenElse/Comment after else 02.fs.bsl | 2 - .../MatchClause/Missing expr 02.fs.bsl | 1 - .../MatchClause/Missing expr 05.fs.bsl | 1 - .../Member/Abstract - Property 03.fs.bsl | 1 - .../Member/Abstract - Property 04.fs.bsl | 1 - .../Member/Abstract - Property 05.fs.bsl | 1 - .../SyntaxTree/Member/Auto property 02.fs.bsl | 1 - .../SyntaxTree/Member/Auto property 03.fs.bsl | 1 - .../SyntaxTree/Member/Auto property 08.fs.bsl | 1 - .../SyntaxTree/Member/Auto property 09.fs.bsl | 1 - .../SyntaxTree/Member/Auto property 10.fs.bsl | 1 - .../SyntaxTree/Member/Auto property 12.fs.bsl | 2 - .../SyntaxTree/Member/Auto property 13.fs.bsl | 2 - .../data/SyntaxTree/Member/Do 03.fs.bsl | 1 - .../data/SyntaxTree/Member/Do 04.fs.bsl | 1 - .../SyntaxTree/Member/Interface 02.fs.bsl | 1 - .../SyntaxTree/Member/Interface 06.fs.bsl | 1 - .../data/SyntaxTree/Member/Let 02.fs.bsl | 1 - .../data/SyntaxTree/Member/Member 05.fs.bsl | 1 - .../data/SyntaxTree/ModuleMember/Do 01.fs.bsl | 1 - .../data/SyntaxTree/ModuleMember/Do 02.fs.bsl | 1 - .../SyntaxTree/ModuleMember/Let 02.fs.bsl | 1 - .../ModuleOrNamespace/Module 04.fs.bsl | 4 -- .../ModuleOrNamespace/Nested module 02.fs.bsl | 1 - .../ModuleOrNamespace/Nested module 09.fs.bsl | 1 - .../ModuleOrNamespace/Nested module 14.fs.bsl | 1 - .../ModuleOrNamespace/Nested module 15.fs.bsl | 1 - .../Pattern/Tuple - Recover 01.fs.bsl | 1 - .../Pattern/Tuple - Recover 02.fs.bsl | 1 - .../data/SyntaxTree/Type/And 06.fs.bsl | 1 - .../data/SyntaxTree/Type/Interface 05.fs.bsl | 1 - .../data/SyntaxTree/Type/Interface 06.fs.bsl | 1 - .../SyntaxTree/Type/Primary ctor 04.fs.bsl | 1 - .../data/SyntaxTree/Type/Type 06.fs.bsl | 1 - .../data/SyntaxTree/Type/Union 03.fs.bsl | 1 - .../data/SyntaxTree/Type/Union 04.fs.bsl | 1 - .../data/SyntaxTree/Type/With 02.fs.bsl | 1 - .../data/SyntaxTree/Type/With 03.fs.bsl | 1 - .../data/SyntaxTree/Type/With 05.fs.bsl | 1 - .../BraceCompletionSessionProvider.fs | 1 - .../Classification/ClassificationService.fs | 3 +- .../CodeFixes/AddMissingFunKeyword.fs | 4 +- .../AddMissingRecToMutuallyRecFunctions.fs | 3 +- .../CodeFixes/AddOpenCodeFixProvider.fs | 3 +- .../CodeFixes/ImplementInterface.fs | 2 - .../Commands/HelpContextService.fs | 3 +- .../Completion/CompletionProvider.fs | 12 ++-- .../Completion/CompletionService.fs | 3 +- .../Completion/CompletionUtils.fs | 27 +------ .../HashDirectiveCompletionProvider.fs | 3 +- .../FSharp.Editor/Completion/SignatureHelp.fs | 8 +-- .../Debugging/LanguageDebugInfoService.fs | 3 +- .../Formatting/EditorFormattingService.fs | 1 - .../Formatting/IndentationService.fs | 1 - .../FSharpProjectOptionsManager.fs | 2 +- .../LanguageService/SymbolHelpers.fs | 3 +- .../LanguageService/Tokenizer.fs | 33 ++------- .../LanguageService/WorkspaceExtensions.fs | 10 +-- .../FSharp.Editor/TaskList/TaskListService.fs | 23 ++---- .../CompletionProviderTests.fs | 13 +--- .../GoToDefinitionServiceTests.fs | 1 - .../HelpContextServiceTests.fs | 1 - .../LanguageDebugInfoServiceTests.fs | 1 - .../SignatureHelpProviderTests.fs | 2 - .../SyntacticColorizationServiceTests.fs | 1 - .../TaskListServiceTests.fs | 2 +- .../Salsa/FSharpLanguageServiceTestable.fs | 2 +- 173 files changed, 153 insertions(+), 724 deletions(-) diff --git a/azure-pipelines-PR.yml b/azure-pipelines-PR.yml index 1f18517bccb..65f45277382 100644 --- a/azure-pipelines-PR.yml +++ b/azure-pipelines-PR.yml @@ -339,78 +339,6 @@ stages: ArtifactType: Container parallel: true - - job: WindowsStrictIndentation - pool: - name: $(DncEngPublicBuildPool) - demands: ImageOverride -equals $(_WindowsMachineQueueName) - timeoutInMinutes: 120 - steps: - - checkout: self - clean: true - - - script: eng\CIBuildNoPublish.cmd -compressallmetadata -configuration Release /p:AdditionalFscCmdFlags=--strict-indentation+ - env: - DOTNET_DbgEnableMiniDump: 1 - DOTNET_DbgMiniDumpType: 2 # 1=mini, 2=heap, 3=triage, 4=full. Heap dumps include managed object data for debugging. - DOTNET_DbgMiniDumpName: $(Build.SourcesDirectory)\artifacts\log\Release\$(Build.BuildId)-%e-%p-%t.dmp - NativeToolsOnMachine: true - displayName: Build - - - task: PublishBuildArtifacts@1 - displayName: Publish Build BinLog - condition: always() - continueOnError: true - inputs: - PathToPublish: '$(Build.SourcesDirectory)\artifacts\log/Release\Build.VisualFSharp.slnx.binlog' - ArtifactName: 'Windows Release build binlogs' - ArtifactType: Container - parallel: true - - task: PublishBuildArtifacts@1 - displayName: Publish Dumps - condition: failed() - continueOnError: true - inputs: - PathToPublish: '$(Build.SourcesDirectory)\artifacts\log\Release' - ArtifactName: 'Windows Release WindowsStrictIndentation process dumps' - ArtifactType: Container - parallel: true - - - job: WindowsNoStrictIndentation - pool: - name: $(DncEngPublicBuildPool) - demands: ImageOverride -equals $(_WindowsMachineQueueName) - timeoutInMinutes: 120 - steps: - - checkout: self - clean: true - - - script: eng\CIBuildNoPublish.cmd -compressallmetadata -configuration Release /p:AdditionalFscCmdFlags=--strict-indentation- - env: - DOTNET_DbgEnableMiniDump: 1 - DOTNET_DbgMiniDumpType: 2 # 1=mini, 2=heap, 3=triage, 4=full. Heap dumps include managed object data for debugging. - DOTNET_DbgMiniDumpName: $(Build.SourcesDirectory)\artifacts\log\Release\$(Build.BuildId)-%e-%p-%t.dmp - NativeToolsOnMachine: true - displayName: Build - - - task: PublishBuildArtifacts@1 - displayName: Publish Build BinLog - condition: always() - continueOnError: true - inputs: - PathToPublish: '$(Build.SourcesDirectory)\artifacts\log/Release\Build.VisualFSharp.slnx.binlog' - ArtifactName: 'Windows Release build binlogs' - ArtifactType: Container - parallel: true - - task: PublishBuildArtifacts@1 - displayName: Publish Dumps - condition: failed() - continueOnError: true - inputs: - PathToPublish: '$(Build.SourcesDirectory)\artifacts\log\Release' - ArtifactName: 'Windows Release WindowsNoStrictIndentation process dumps' - ArtifactType: Container - parallel: true - # Windows With Compressed Metadata - job: WindowsCompressedMetadata variables: diff --git a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md index 9e5b990b2ce..b1d9f90f210 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md +++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md @@ -165,3 +165,4 @@ * `FSharp.Compiler.Syntax.SynInterpolatedStringPart.FillExpr` now carries a `SynInterpolationFormatting` value (separating .NET alignment/format from printf specifiers) instead of an `Ident option`. ([PR #19971](https://github.com/dotnet/fsharp/pull/19971)) * Optimizer: don't inline named functions in debug builds ([PR #19548](https://github.com/dotnet/fsharp/pull/19548) +* LexFilter: drop non-strict mode ([PR #20106](https://github.com/dotnet/fsharp/pull/20106)) diff --git a/src/Compiler/Driver/CompilerConfig.fs b/src/Compiler/Driver/CompilerConfig.fs index a1e7937b0d9..7e04ef173f6 100644 --- a/src/Compiler/Driver/CompilerConfig.fs +++ b/src/Compiler/Driver/CompilerConfig.fs @@ -598,8 +598,6 @@ type TcConfigBuilder = /// If true - every expression in quotations will be augmented with full debug info (fileName, location in file) mutable emitDebugInfoInQuotations: bool - mutable strictIndentation: bool option - mutable alwaysInline: bool option mutable exename: string option @@ -854,7 +852,6 @@ type TcConfigBuilder = } dumpSignatureData = false realsig = false - strictIndentation = None alwaysInline = None compilationMode = TcGlobals.CompilationMode.Unset } @@ -1255,7 +1252,6 @@ type TcConfig private (data: TcConfigBuilder, validate: bool) = member _.bufferWidth = data.bufferWidth member _.fsiMultiAssemblyEmit = data.fsiMultiAssemblyEmit member _.FxResolver = data.FxResolver - member _.strictIndentation = data.strictIndentation member _.alwaysInline = data.alwaysInline diff --git a/src/Compiler/Driver/CompilerConfig.fsi b/src/Compiler/Driver/CompilerConfig.fsi index 9f19b8e59ba..89731f6decc 100644 --- a/src/Compiler/Driver/CompilerConfig.fsi +++ b/src/Compiler/Driver/CompilerConfig.fsi @@ -470,8 +470,6 @@ type TcConfigBuilder = mutable emitDebugInfoInQuotations: bool - mutable strictIndentation: bool option - mutable alwaysInline: bool option mutable exename: string option @@ -814,8 +812,6 @@ type TcConfig = member FxResolver: FxResolver - member strictIndentation: bool option - member alwaysInline: bool member GetTargetFrameworkDirectories: unit -> string list diff --git a/src/Compiler/Driver/CompilerOptions.fs b/src/Compiler/Driver/CompilerOptions.fs index f54f36fa7f9..48574325813 100644 --- a/src/Compiler/Driver/CompilerOptions.fs +++ b/src/Compiler/Driver/CompilerOptions.fs @@ -1200,14 +1200,6 @@ let languageFlags tcConfigB = CompilerOption("define", tagString, OptionString(defineSymbol tcConfigB), None, Some(FSComp.SR.optsDefine ())) - CompilerOption( - "strict-indentation", - tagNone, - OptionSwitch(fun switch -> tcConfigB.strictIndentation <- Some(switch = OptionSwitch.On)), - None, - Some(FSComp.SR.optsStrictIndentation (formatOptionSwitch (Option.defaultValue false tcConfigB.strictIndentation))) - ) - CompilerOption( "always-inline", tagNone, diff --git a/src/Compiler/Driver/ParseAndCheckInputs.fs b/src/Compiler/Driver/ParseAndCheckInputs.fs index 92e72d6b89b..1590b9fe458 100644 --- a/src/Compiler/Driver/ParseAndCheckInputs.fs +++ b/src/Compiler/Driver/ParseAndCheckInputs.fs @@ -648,7 +648,7 @@ let parseInputStreamAux // Set up the LexBuffer for the file let lexbuf = - UnicodeLexing.StreamReaderAsLexbuf(not tcConfig.compilingFSharpCore, tcConfig.langVersion, tcConfig.strictIndentation, reader) + UnicodeLexing.StreamReaderAsLexbuf(not tcConfig.compilingFSharpCore, tcConfig.langVersion, reader) // Parse the file drawing tokens from the lexbuf ParseOneInputLexbuf(tcConfig, lexResourceManager, lexbuf, fileName, isLastCompiland, diagnosticsLogger) @@ -658,7 +658,7 @@ let parseInputSourceTextAux = // Set up the LexBuffer for the file let lexbuf = - UnicodeLexing.SourceTextAsLexbuf(not tcConfig.compilingFSharpCore, tcConfig.langVersion, tcConfig.strictIndentation, sourceText) + UnicodeLexing.SourceTextAsLexbuf(not tcConfig.compilingFSharpCore, tcConfig.langVersion, sourceText) // Parse the file drawing tokens from the lexbuf ParseOneInputLexbuf(tcConfig, lexResourceManager, lexbuf, fileName, isLastCompiland, diagnosticsLogger) @@ -670,7 +670,7 @@ let parseInputFileAux (tcConfig: TcConfig, lexResourceManager, fileName, isLastC // Set up the LexBuffer for the file let lexbuf = - UnicodeLexing.StreamReaderAsLexbuf(not tcConfig.compilingFSharpCore, tcConfig.langVersion, tcConfig.strictIndentation, reader) + UnicodeLexing.StreamReaderAsLexbuf(not tcConfig.compilingFSharpCore, tcConfig.langVersion, reader) // Parse the file drawing tokens from the lexbuf ParseOneInputLexbuf(tcConfig, lexResourceManager, lexbuf, fileName, isLastCompiland, diagnosticsLogger) diff --git a/src/Compiler/Driver/ScriptClosure.fs b/src/Compiler/Driver/ScriptClosure.fs index 7f25c7b826d..a83b49a2a0e 100644 --- a/src/Compiler/Driver/ScriptClosure.fs +++ b/src/Compiler/Driver/ScriptClosure.fs @@ -15,7 +15,6 @@ open FSharp.Compiler.CompilerConfig open FSharp.Compiler.CompilerDiagnostics open FSharp.Compiler.CompilerImports open FSharp.Compiler.DependencyManager -open FSharp.Compiler.Diagnostics open FSharp.Compiler.DiagnosticsLogger open FSharp.Compiler.IO open FSharp.Compiler.CodeAnalysis @@ -135,7 +134,7 @@ module ScriptPreprocessClosure = let tcConfig = TcConfig.Create(tcConfigB, false) let lexbuf = - UnicodeLexing.SourceTextAsLexbuf(true, tcConfig.langVersion, tcConfig.strictIndentation, sourceText) + UnicodeLexing.SourceTextAsLexbuf(true, tcConfig.langVersion, sourceText) // The root compiland is last in the list of compilands. let isLastCompiland = (IsScript fileName, tcConfig.target.IsExe) diff --git a/src/Compiler/FSComp.txt b/src/Compiler/FSComp.txt index 5af5d874d05..fab84a56510 100644 --- a/src/Compiler/FSComp.txt +++ b/src/Compiler/FSComp.txt @@ -999,7 +999,7 @@ lexhlpIdentifierReserved,"The identifier '%s' is reserved for future use by F#" 1118,optFailedToInlineValue,"Failed to inline the value '%s' marked 'inline', perhaps because a recursive value was marked 'inline'" 1119,optRecursiveValValue,"Recursive ValValue %s" lexfltIncorrentIndentationOfIn,"The indentation of this 'in' token is incorrect with respect to the corresponding 'let'" -lexfltTokenIsOffsideOfContextStartedEarlier,"Unexpected syntax or possible incorrect indentation: this token is offside of context started at position %s. Try indenting this further.\nTo continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7." +lexfltTokenIsOffsideOfContextStartedEarlier,"Unexpected syntax or possible incorrect indentation: this token is offside of context started at position %s. Try indenting this further." lexfltSeparatorTokensOfPatternMatchMisaligned,"The '|' tokens separating rules of this pattern match are misaligned by one column. Consider realigning your code or using further indentation." lexfltInvalidNestedTypeDefinition,"Nested type definitions are not allowed. Types must be defined at module or namespace level." lexfltInvalidNestedModule,"Modules cannot be nested inside types. Define modules at module or namespace level." @@ -1560,7 +1560,6 @@ optsGetLangVersions,"Display the allowed values for language version." optsSetLangVersion,"Specify language version such as 'latest' or 'preview'." optsDisableLanguageFeature,"Disable a specific language feature by name." optsSupportedLangVersions,"Supported language versions:" -optsStrictIndentation,"Override indentation rules implied by the language version (%s by default)" optsAlwaysInline,"Always inline 'inline' functions" nativeResourceFormatError,"Stream does not begin with a null resource and is not in '.RES' format." nativeResourceHeaderMalformed,"Resource header beginning at offset %s is malformed." @@ -1606,7 +1605,6 @@ featureNestedCopyAndUpdate,"Nested record field copy-and-update" featureExtendedStringInterpolation,"Extended string interpolation similar to C# raw string literals." featureWarningWhenMultipleRecdTypeChoice,"Raises warnings when multiple record type matches were found during name resolution because of overlapping field names." featureImprovedImpliedArgumentNames,"Improved implied argument names" -featureStrictIndentation,"Raises errors on incorrect indentation, allows better recovery and analysis during editing" featureConstraintIntersectionOnFlexibleTypes,"Constraint intersection on flexible types" featureChkNotTailRecursive,"Raises warnings if a member or function has the 'TailCall' attribute, but is not being used in a tail recursive way." featureWhileBang,"'while!' expression" diff --git a/src/Compiler/Facilities/LanguageFeatures.fs b/src/Compiler/Facilities/LanguageFeatures.fs index e4feee0c451..0941e4b49a8 100644 --- a/src/Compiler/Facilities/LanguageFeatures.fs +++ b/src/Compiler/Facilities/LanguageFeatures.fs @@ -20,7 +20,6 @@ type LanguageFeature = | WildCardInForLoop | RelaxWhitespace | RelaxWhitespace2 - | StrictIndentation | NameOf | ImplicitYield | OpenTypeDeclaration @@ -216,7 +215,6 @@ type LanguageVersion(versionText, ?disabledFeaturesArray: LanguageFeature array) LanguageFeature.DiagnosticForObjInference, languageVersion80 LanguageFeature.WarningWhenTailRecAttributeButNonTailRecUsage, languageVersion80 LanguageFeature.StaticLetInRecordsDusEmptyTypes, languageVersion80 - LanguageFeature.StrictIndentation, languageVersion80 LanguageFeature.ConstraintIntersectionOnFlexibleTypes, languageVersion80 LanguageFeature.WhileBang, languageVersion80 LanguageFeature.ExtendedFixedBindings, languageVersion80 @@ -425,7 +423,6 @@ type LanguageVersion(versionText, ?disabledFeaturesArray: LanguageFeature array) | LanguageFeature.DiagnosticForObjInference -> FSComp.SR.featureInformationalObjInferenceDiagnostic () | LanguageFeature.StaticLetInRecordsDusEmptyTypes -> FSComp.SR.featureStaticLetInRecordsDusEmptyTypes () - | LanguageFeature.StrictIndentation -> FSComp.SR.featureStrictIndentation () | LanguageFeature.ConstraintIntersectionOnFlexibleTypes -> FSComp.SR.featureConstraintIntersectionOnFlexibleTypes () | LanguageFeature.WarningWhenTailRecAttributeButNonTailRecUsage -> FSComp.SR.featureChkNotTailRecursive () | LanguageFeature.UnmanagedConstraintCsharpInterop -> FSComp.SR.featureUnmanagedConstraintCsharpInterop () diff --git a/src/Compiler/Facilities/LanguageFeatures.fsi b/src/Compiler/Facilities/LanguageFeatures.fsi index e77a0a377a7..a0c226f222c 100644 --- a/src/Compiler/Facilities/LanguageFeatures.fsi +++ b/src/Compiler/Facilities/LanguageFeatures.fsi @@ -10,7 +10,6 @@ type LanguageFeature = | WildCardInForLoop | RelaxWhitespace | RelaxWhitespace2 - | StrictIndentation | NameOf | ImplicitYield | OpenTypeDeclaration diff --git a/src/Compiler/Facilities/prim-lexing.fs b/src/Compiler/Facilities/prim-lexing.fs index cfde35d5a77..21b93b12880 100644 --- a/src/Compiler/Facilities/prim-lexing.fs +++ b/src/Compiler/Facilities/prim-lexing.fs @@ -242,8 +242,7 @@ type internal Position = type internal LexBufferFiller<'Char> = LexBuffer<'Char> -> unit -and [] internal LexBuffer<'Char> - (filler: LexBufferFiller<'Char>, reportLibraryOnlyFeatures: bool, langVersion: LanguageVersion, strictIndentation: bool option) = +and [] internal LexBuffer<'Char>(filler: LexBufferFiller<'Char>, reportLibraryOnlyFeatures: bool, langVersion: LanguageVersion) = let context = Dictionary(1) let mutable buffer = [||] /// number of valid characters beyond bufferScanStart. @@ -344,14 +343,10 @@ and [] internal LexBuffer<'Char> member _.SupportsFeature featureId = langVersion.SupportsFeature featureId - member _.StrictIndentation = strictIndentation - member _.CheckLanguageFeatureAndRecover featureId range = FSharp.Compiler.DiagnosticsLogger.checkLanguageFeatureAndRecover langVersion featureId range - static member FromFunction - (reportLibraryOnlyFeatures, langVersion, strictIndentation, f: 'Char[] * int * int -> int) - : LexBuffer<'Char> = + static member FromFunction(reportLibraryOnlyFeatures, langVersion, f: 'Char[] * int * int -> int) : LexBuffer<'Char> = let extension = Array.zeroCreate 4096 let filler (lexBuffer: LexBuffer<'Char>) = @@ -360,35 +355,34 @@ and [] internal LexBuffer<'Char> Array.blit extension 0 lexBuffer.Buffer lexBuffer.BufferScanPos n lexBuffer.BufferMaxScanLength <- lexBuffer.BufferScanLength + n - new LexBuffer<'Char>(filler, reportLibraryOnlyFeatures, langVersion, strictIndentation) + new LexBuffer<'Char>(filler, reportLibraryOnlyFeatures, langVersion) // Important: This method takes ownership of the array - static member FromArrayNoCopy(reportLibraryOnlyFeatures, langVersion, strictIndentation, buffer: 'Char[]) : LexBuffer<'Char> = + static member FromArrayNoCopy(reportLibraryOnlyFeatures, langVersion, buffer: 'Char[]) : LexBuffer<'Char> = let lexBuffer = - new LexBuffer<'Char>((fun _ -> ()), reportLibraryOnlyFeatures, langVersion, strictIndentation) + new LexBuffer<'Char>((fun _ -> ()), reportLibraryOnlyFeatures, langVersion) lexBuffer.Buffer <- buffer lexBuffer.BufferMaxScanLength <- buffer.Length lexBuffer // Important: this method does copy the array - static member FromArray(reportLibraryOnlyFeatures, langVersion, strictIndentation, s: 'Char[]) : LexBuffer<'Char> = + static member FromArray(reportLibraryOnlyFeatures, langVersion, s: 'Char[]) : LexBuffer<'Char> = let buffer = Array.copy s - LexBuffer<'Char>.FromArrayNoCopy(reportLibraryOnlyFeatures, langVersion, strictIndentation, buffer) + LexBuffer<'Char>.FromArrayNoCopy(reportLibraryOnlyFeatures, langVersion, buffer) // Important: This method takes ownership of the array - static member FromChars(reportLibraryOnlyFeatures, langVersion, strictIndentation, arr: char[]) = - LexBuffer.FromArrayNoCopy(reportLibraryOnlyFeatures, langVersion, strictIndentation, arr) + static member FromChars(reportLibraryOnlyFeatures, langVersion, arr: char[]) = + LexBuffer.FromArrayNoCopy(reportLibraryOnlyFeatures, langVersion, arr) - static member FromSourceText(reportLibraryOnlyFeatures, langVersion, strictIndentation, sourceText: ISourceText) = + static member FromSourceText(reportLibraryOnlyFeatures, langVersion, sourceText: ISourceText) = let mutable currentSourceIndex = 0 LexBuffer .FromFunction( reportLibraryOnlyFeatures, langVersion, - strictIndentation, fun (chars, start, length) -> let lengthToCopy = if currentSourceIndex + length <= sourceText.Length then diff --git a/src/Compiler/Facilities/prim-lexing.fsi b/src/Compiler/Facilities/prim-lexing.fsi index bcb60fc4977..f74d4baa2df 100644 --- a/src/Compiler/Facilities/prim-lexing.fsi +++ b/src/Compiler/Facilities/prim-lexing.fsi @@ -146,29 +146,21 @@ type internal LexBuffer<'Char> = /// True if the specified language feature is supported. member SupportsFeature: LanguageFeature -> bool - member StrictIndentation: bool option - /// Logs a recoverable error if a language feature is unsupported, at the specified range. member CheckLanguageFeatureAndRecover: LanguageFeature -> range -> unit /// Create a lex buffer suitable for Unicode lexing that reads characters from the given array. /// Important: does take ownership of the array. - static member FromChars: - reportLibraryOnlyFeatures: bool * langVersion: LanguageVersion * strictIndentation: bool option * char[] -> - LexBuffer + static member FromChars: reportLibraryOnlyFeatures: bool * langVersion: LanguageVersion * char[] -> LexBuffer /// Create a lex buffer that reads character or byte inputs by using the given function. static member FromFunction: - reportLibraryOnlyFeatures: bool * - langVersion: LanguageVersion * - strictIndentation: bool option * - ('Char[] * int * int -> int) -> + reportLibraryOnlyFeatures: bool * langVersion: LanguageVersion * ('Char[] * int * int -> int) -> LexBuffer<'Char> /// Create a lex buffer backed by source text. static member FromSourceText: - reportLibraryOnlyFeatures: bool * langVersion: LanguageVersion * strictIndentation: bool option * ISourceText -> - LexBuffer + reportLibraryOnlyFeatures: bool * langVersion: LanguageVersion * ISourceText -> LexBuffer /// The type of tables for an unicode lexer generated by fslex.exe. [] diff --git a/src/Compiler/Interactive/fsi.fs b/src/Compiler/Interactive/fsi.fs index a41b658cab1..500045c73f7 100644 --- a/src/Compiler/Interactive/fsi.fs +++ b/src/Compiler/Interactive/fsi.fs @@ -3591,7 +3591,6 @@ type FsiStdinLexerProvider UnicodeLexing.FunctionAsLexbuf( true, tcConfigB.langVersion, - tcConfigB.strictIndentation, (fun (buf: char[], start, len) -> //fprintf fsiConsoleOutput.Out "Calling ReadLine\n" let inputOption = @@ -3670,15 +3669,13 @@ type FsiStdinLexerProvider // Create a new lexer to read an "included" script file member _.CreateIncludedScriptLexer(sourceFileName, reader, diagnosticsLogger) = - let lexbuf = - UnicodeLexing.StreamReaderAsLexbuf(true, tcConfigB.langVersion, tcConfigB.strictIndentation, reader) + let lexbuf = UnicodeLexing.StreamReaderAsLexbuf(true, tcConfigB.langVersion, reader) CreateLexerForLexBuffer(sourceFileName, lexbuf, diagnosticsLogger) // Create a new lexer to read a string member _.CreateStringLexer(sourceFileName, source, diagnosticsLogger) = - let lexbuf = - UnicodeLexing.StringAsLexbuf(true, tcConfigB.langVersion, tcConfigB.strictIndentation, source) + let lexbuf = UnicodeLexing.StringAsLexbuf(true, tcConfigB.langVersion, source) CreateLexerForLexBuffer(sourceFileName, lexbuf, diagnosticsLogger) @@ -3799,7 +3796,7 @@ type FsiInteractionProcessor let runhDirective diagnosticsLogger ctok istate source = let lexbuf = - UnicodeLexing.StringAsLexbuf(true, tcConfigB.langVersion, tcConfigB.strictIndentation, $"<@@ {source} @@>") + UnicodeLexing.StringAsLexbuf(true, tcConfigB.langVersion, $"<@@ {source} @@>") let tokenizer = fsiStdinLexerProvider.CreateBufferLexer("hdummy.fsx", lexbuf, diagnosticsLogger) @@ -4362,8 +4359,7 @@ type FsiInteractionProcessor use _ = UseDiagnosticsLogger diagnosticsLogger use _scope = SetCurrentUICultureForThread fsiOptions.FsiLCID - let lexbuf = - UnicodeLexing.StringAsLexbuf(true, tcConfigB.langVersion, tcConfigB.strictIndentation, sourceText) + let lexbuf = UnicodeLexing.StringAsLexbuf(true, tcConfigB.langVersion, sourceText) let tokenizer = fsiStdinLexerProvider.CreateBufferLexer(scriptFileName, lexbuf, diagnosticsLogger) @@ -4384,8 +4380,7 @@ type FsiInteractionProcessor use _unwind2 = UseDiagnosticsLogger diagnosticsLogger use _scope = SetCurrentUICultureForThread fsiOptions.FsiLCID - let lexbuf = - UnicodeLexing.StringAsLexbuf(true, tcConfigB.langVersion, tcConfigB.strictIndentation, sourceText) + let lexbuf = UnicodeLexing.StringAsLexbuf(true, tcConfigB.langVersion, sourceText) let tokenizer = fsiStdinLexerProvider.CreateBufferLexer(scriptFileName, lexbuf, diagnosticsLogger) diff --git a/src/Compiler/Service/FSharpCheckerResults.fs b/src/Compiler/Service/FSharpCheckerResults.fs index f31fa90332a..3d029caa33a 100644 --- a/src/Compiler/Service/FSharpCheckerResults.fs +++ b/src/Compiler/Service/FSharpCheckerResults.fs @@ -2901,7 +2901,6 @@ type FSharpParsingOptions = DiagnosticOptions: FSharpDiagnosticOptions LangVersionText: string IsInteractive: bool - StrictIndentation: bool option CompilingFSharpCore: bool IsExe: bool } @@ -2918,7 +2917,6 @@ type FSharpParsingOptions = DiagnosticOptions = FSharpDiagnosticOptions.Default LangVersionText = LanguageVersion.Default.VersionText IsInteractive = false - StrictIndentation = None CompilingFSharpCore = false IsExe = false } @@ -2931,7 +2929,6 @@ type FSharpParsingOptions = DiagnosticOptions = tcConfig.diagnosticsOptions LangVersionText = tcConfig.langVersion.VersionText IsInteractive = isInteractive - StrictIndentation = tcConfig.strictIndentation CompilingFSharpCore = tcConfig.compilingFSharpCore IsExe = tcConfig.target.IsExe } @@ -2944,7 +2941,6 @@ type FSharpParsingOptions = DiagnosticOptions = tcConfigB.diagnosticsOptions LangVersionText = tcConfigB.langVersion.VersionText IsInteractive = isInteractive - StrictIndentation = tcConfigB.strictIndentation CompilingFSharpCore = tcConfigB.compilingFSharpCore IsExe = tcConfigB.target.IsExe } @@ -3056,8 +3052,8 @@ module internal ParseAndCheckFile = else (fun _ -> tokenizer.GetToken()) - let createLexbuf langVersion strictIndentation sourceText = - UnicodeLexing.SourceTextAsLexbuf(true, LanguageVersion(langVersion), strictIndentation, sourceText) + let createLexbuf langVersion sourceText = + UnicodeLexing.SourceTextAsLexbuf(true, LanguageVersion(langVersion), sourceText) let matchBraces ( @@ -3077,7 +3073,7 @@ module internal ParseAndCheckFile = let matchingBraces = ResizeArray<_>() - usingLexbufForParsing (createLexbuf options.LangVersionText options.StrictIndentation sourceText, fileName) (fun lexbuf -> + usingLexbufForParsing (createLexbuf options.LangVersionText sourceText, fileName) (fun lexbuf -> let errHandler = DiagnosticsHandler(false, fileName, options.DiagnosticOptions, suggestNamesForErrors, false) @@ -3190,7 +3186,7 @@ module internal ParseAndCheckFile = use _ = UseBuildPhase BuildPhase.Parse let parseResult = - usingLexbufForParsing (createLexbuf options.LangVersionText options.StrictIndentation sourceText, fileName) (fun lexbuf -> + usingLexbufForParsing (createLexbuf options.LangVersionText sourceText, fileName) (fun lexbuf -> let lexfun = createLexerFunction options lexbuf errHandler ct diff --git a/src/Compiler/Service/FSharpCheckerResults.fsi b/src/Compiler/Service/FSharpCheckerResults.fsi index 9b5a95c28a9..b1b5f78f675 100644 --- a/src/Compiler/Service/FSharpCheckerResults.fsi +++ b/src/Compiler/Service/FSharpCheckerResults.fsi @@ -224,8 +224,6 @@ type public FSharpParsingOptions = IsInteractive: bool - StrictIndentation: bool option - CompilingFSharpCore: bool IsExe: bool diff --git a/src/Compiler/Service/ServiceLexing.fs b/src/Compiler/Service/ServiceLexing.fs index e8e05595b75..ce501ac7755 100644 --- a/src/Compiler/Service/ServiceLexing.fs +++ b/src/Compiler/Service/ServiceLexing.fs @@ -1132,8 +1132,7 @@ type FSharpLineTokenizer(lexbuf: UnicodeLexing.Lexbuf, maxLength: int option, fi } [] -type FSharpSourceTokenizer - (conditionalDefines: string list, fileName: string option, langVersion: string option, strictIndentation: bool option) = +type FSharpSourceTokenizer(conditionalDefines: string list, fileName: string option, langVersion: string option) = let langVersion = langVersion @@ -1151,13 +1150,13 @@ type FSharpSourceTokenizer member _.CreateLineTokenizer(lineText: string) = let lexbuf = - UnicodeLexing.StringAsLexbuf(reportLibraryOnlyFeatures, langVersion, strictIndentation, lineText) + UnicodeLexing.StringAsLexbuf(reportLibraryOnlyFeatures, langVersion, lineText) FSharpLineTokenizer(lexbuf, Some lineText.Length, fileName, lexargs) member _.CreateBufferTokenizer bufferFiller = let lexbuf = - UnicodeLexing.FunctionAsLexbuf(reportLibraryOnlyFeatures, langVersion, strictIndentation, bufferFiller) + UnicodeLexing.FunctionAsLexbuf(reportLibraryOnlyFeatures, langVersion, bufferFiller) FSharpLineTokenizer(lexbuf, None, fileName, lexargs) @@ -1735,7 +1734,6 @@ module FSharpLexerImpl = (flags: FSharpLexerFlags) reportLibraryOnlyFeatures langVersion - strictIndentation diagnosticsLogger onToken pathMap @@ -1754,7 +1752,7 @@ module FSharpLexerImpl = (flags &&& FSharpLexerFlags.UseLexFilter) = FSharpLexerFlags.UseLexFilter let lexbuf = - UnicodeLexing.SourceTextAsLexbuf(reportLibraryOnlyFeatures, langVersion, strictIndentation, text) + UnicodeLexing.SourceTextAsLexbuf(reportLibraryOnlyFeatures, langVersion, text) let applyLineDirectives = isCompiling @@ -1780,7 +1778,7 @@ module FSharpLexerImpl = ct.ThrowIfCancellationRequested() onToken (getNextToken lexbuf) lexbuf.LexemeRange - let lex text conditionalDefines flags reportLibraryOnlyFeatures langVersion strictIndentation lexCallback pathMap ct = + let lex text conditionalDefines flags reportLibraryOnlyFeatures langVersion lexCallback pathMap ct = let diagnosticsLogger = CompilationDiagnosticLogger("Lexer", FSharpDiagnosticOptions.Default) @@ -1790,7 +1788,6 @@ module FSharpLexerImpl = flags reportLibraryOnlyFeatures langVersion - strictIndentation diagnosticsLogger lexCallback pathMap @@ -1799,9 +1796,7 @@ module FSharpLexerImpl = [] type FSharpLexer = - static member Tokenize - (text: ISourceText, tokenCallback, ?langVersion, ?strictIndentation, ?filePath: string, ?conditionalDefines, ?flags, ?pathMap, ?ct) - = + static member Tokenize(text: ISourceText, tokenCallback, ?langVersion, ?filePath: string, ?conditionalDefines, ?flags, ?pathMap, ?ct) = let langVersion = defaultArg langVersion "latestmajor" |> LanguageVersion let flags = defaultArg flags FSharpLexerFlags.Default ignore filePath // can be removed at later point @@ -1821,4 +1816,4 @@ type FSharpLexer = | _ -> tokenCallback fsTok let reportLibraryOnlyFeatures = true - lex text conditionalDefines flags reportLibraryOnlyFeatures langVersion strictIndentation onToken pathMap ct + lex text conditionalDefines flags reportLibraryOnlyFeatures langVersion onToken pathMap ct diff --git a/src/Compiler/Service/ServiceLexing.fsi b/src/Compiler/Service/ServiceLexing.fsi index 4aad2727e7e..ea7d05b60fe 100755 --- a/src/Compiler/Service/ServiceLexing.fsi +++ b/src/Compiler/Service/ServiceLexing.fsi @@ -327,12 +327,7 @@ type FSharpLineTokenizer = type FSharpSourceTokenizer = /// Create a tokenizer for a source file. - new: - conditionalDefines: string list * - fileName: string option * - langVersion: string option * - strictIndentation: bool option -> - FSharpSourceTokenizer + new: conditionalDefines: string list * fileName: string option * langVersion: string option -> FSharpSourceTokenizer /// Create a tokenizer for a line of this source file member CreateLineTokenizer: lineText: string -> FSharpLineTokenizer @@ -584,7 +579,6 @@ type public FSharpLexer = text: ISourceText * tokenCallback: (FSharpToken -> unit) * ?langVersion: string * - ?strictIndentation: bool * ?filePath: string * ?conditionalDefines: string list * ?flags: FSharpLexerFlags * diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs index fe3caffc6d7..4666aa930ed 100644 --- a/src/Compiler/Service/TransparentCompiler.fs +++ b/src/Compiler/Service/TransparentCompiler.fs @@ -2170,7 +2170,6 @@ type internal TransparentCompiler yield options.ApplyLineDirectives yield options.DiagnosticOptions.GlobalWarnAsError yield options.IsInteractive - yield! (Option.toList options.StrictIndentation) yield options.CompilingFSharpCore yield options.IsExe ] diff --git a/src/Compiler/Service/service.fs b/src/Compiler/Service/service.fs index 3584ca61e49..1006def6da1 100644 --- a/src/Compiler/Service/service.fs +++ b/src/Compiler/Service/service.fs @@ -627,7 +627,7 @@ type FSharpChecker /// Tokenize a single line, returning token information and a tokenization state represented by an integer member _.TokenizeLine(line: string, state: FSharpTokenizerLexState) = - let tokenizer = FSharpSourceTokenizer([], None, None, None) + let tokenizer = FSharpSourceTokenizer([], None, None) let lineTokenizer = tokenizer.CreateLineTokenizer line let mutable state = (None, state) diff --git a/src/Compiler/SyntaxTree/LexFilter.fs b/src/Compiler/SyntaxTree/LexFilter.fs index 96207878289..8f9267909d7 100644 --- a/src/Compiler/SyntaxTree/LexFilter.fs +++ b/src/Compiler/SyntaxTree/LexFilter.fs @@ -771,9 +771,6 @@ type LexFilterImpl ( let relaxWhitespace2 = lexbuf.SupportsFeature LanguageFeature.RelaxWhitespace2 - let strictIndentation = - lexbuf.StrictIndentation |> Option.defaultWith (fun _ -> lexbuf.SupportsFeature LanguageFeature.StrictIndentation) - //let indexerNotationWithoutDot = lexbuf.SupportsFeature LanguageFeature.IndexerNotationWithoutDot let tryPushCtxt strict ignoreIndent tokenTup (newCtxt: Context) = @@ -1010,8 +1007,7 @@ type LexFilterImpl ( let isCorrectIndent = c2 >= p1.Column if not isCorrectIndent then - let warnF = if strictIndentation then error else warn - warnF tokenTup + error tokenTup (if debug then sprintf "possible incorrect indentation: this token is offside of context at (original!) position %s, newCtxt = %A, stack = %A, newCtxtPos = %s, c1 = %d, c2 = %d" (warningStringOfPosition p1.Position) newCtxt offsideStack (stringOfPos newCtxt.StartPos) p1.Column c2 @@ -2358,7 +2354,7 @@ type LexFilterImpl ( let leadingBar = match peekNextToken() with BAR -> true | _ -> false if debug then dprintf "WITH, pushing CtxtMatchClauses, lookaheadTokenStartPos = %a, tokenStartPos = %a\n" outputPos lookaheadTokenStartPos outputPos tokenStartPos - tryPushCtxt strictIndentation false lookaheadTokenTup (CtxtMatchClauses(leadingBar, lookaheadTokenStartPos)) |> ignore + tryPushCtxt true false lookaheadTokenTup (CtxtMatchClauses(leadingBar, lookaheadTokenStartPos)) |> ignore returnToken tokenLexbufState OWITH @@ -2779,10 +2775,10 @@ type LexFilterImpl ( false and pushCtxtSeqBlock fallbackToken addBlockEnd = - pushCtxtSeqBlockAt strictIndentation true fallbackToken (peekNextTokenTup ()) addBlockEnd + pushCtxtSeqBlockAt true true fallbackToken (peekNextTokenTup ()) addBlockEnd and tryPushCtxtSeqBlock fallbackToken addBlockEnd = - pushCtxtSeqBlockAt strictIndentation false fallbackToken (peekNextTokenTup ()) addBlockEnd + pushCtxtSeqBlockAt true false fallbackToken (peekNextTokenTup ()) addBlockEnd and pushCtxtSeqBlockAt strict (useFallback: bool) (fallbackToken: TokenTup) (tokenTup: TokenTup) addBlockEnd = let pushed = tryPushCtxt strict false tokenTup (CtxtSeqBlock(FirstInSeqBlock, startPosOfTokenTup tokenTup, addBlockEnd)) diff --git a/src/Compiler/SyntaxTree/ParseHelpers.fs b/src/Compiler/SyntaxTree/ParseHelpers.fs index c9192060ed3..22eb96151e9 100644 --- a/src/Compiler/SyntaxTree/ParseHelpers.fs +++ b/src/Compiler/SyntaxTree/ParseHelpers.fs @@ -243,7 +243,7 @@ and LexCont = LexerContinuation // Parse IL assembly code //------------------------------------------------------------------------ -let ParseAssemblyCodeInstructions s reportLibraryOnlyFeatures langVersion strictIndentation m : IL.ILInstr[] = +let ParseAssemblyCodeInstructions s reportLibraryOnlyFeatures langVersion m : IL.ILInstr[] = #if NO_INLINE_IL_PARSER ignore s ignore isFeatureSupported @@ -252,13 +252,13 @@ let ParseAssemblyCodeInstructions s reportLibraryOnlyFeatures langVersion strict [||] #else try - AsciiParser.ilInstrs AsciiLexer.token (StringAsLexbuf(reportLibraryOnlyFeatures, langVersion, strictIndentation, s)) + AsciiParser.ilInstrs AsciiLexer.token (StringAsLexbuf(reportLibraryOnlyFeatures, langVersion, s)) with _ -> errorR (Error(FSComp.SR.astParseEmbeddedILError (), m)) [||] #endif -let ParseAssemblyCodeType s reportLibraryOnlyFeatures langVersion strictIndentation m = +let ParseAssemblyCodeType s reportLibraryOnlyFeatures langVersion m = ignore s #if NO_INLINE_IL_PARSER @@ -266,7 +266,7 @@ let ParseAssemblyCodeType s reportLibraryOnlyFeatures langVersion strictIndentat IL.PrimaryAssemblyILGlobals.typ_Object #else try - AsciiParser.ilType AsciiLexer.token (StringAsLexbuf(reportLibraryOnlyFeatures, langVersion, strictIndentation, s)) + AsciiParser.ilType AsciiLexer.token (StringAsLexbuf(reportLibraryOnlyFeatures, langVersion, s)) with RecoverableParseError -> errorR (Error(FSComp.SR.astParseEmbeddedILTypeError (), m)) IL.PrimaryAssemblyILGlobals.typ_Object diff --git a/src/Compiler/SyntaxTree/ParseHelpers.fsi b/src/Compiler/SyntaxTree/ParseHelpers.fsi index 148868c13d2..ca58bdb1534 100644 --- a/src/Compiler/SyntaxTree/ParseHelpers.fsi +++ b/src/Compiler/SyntaxTree/ParseHelpers.fsi @@ -115,24 +115,14 @@ type LexerContinuation = and LexCont = LexerContinuation val ParseAssemblyCodeInstructions: - s: string -> - reportLibraryOnlyFeatures: bool -> - langVersion: LanguageVersion -> - strictIndentation: bool option -> - m: range -> - ILInstr[] + s: string -> reportLibraryOnlyFeatures: bool -> langVersion: LanguageVersion -> m: range -> ILInstr[] val grabXmlDocAtRangeStart: parseState: IParseState * optAttributes: SynAttributeList list * range: range -> PreXmlDoc val grabXmlDoc: parseState: IParseState * optAttributes: SynAttributeList list * elemIdx: int -> PreXmlDoc val ParseAssemblyCodeType: - s: string -> - reportLibraryOnlyFeatures: bool -> - langVersion: LanguageVersion -> - strictIndentation: bool option -> - m: range -> - ILType + s: string -> reportLibraryOnlyFeatures: bool -> langVersion: LanguageVersion -> m: range -> ILType val reportParseErrorAt: range -> (int * string) -> unit diff --git a/src/Compiler/SyntaxTree/UnicodeLexing.fs b/src/Compiler/SyntaxTree/UnicodeLexing.fs index 4ea41cbcf84..ad6ef32154a 100644 --- a/src/Compiler/SyntaxTree/UnicodeLexing.fs +++ b/src/Compiler/SyntaxTree/UnicodeLexing.fs @@ -23,22 +23,21 @@ type LexBuffer<'char> with | true, data -> Some(data :?> 'T) | _ -> None -let StringAsLexbuf (reportLibraryOnlyFeatures, langVersion, strictIndentation, s: string) = - LexBuffer.FromChars(reportLibraryOnlyFeatures, langVersion, strictIndentation, s.ToCharArray()) +let StringAsLexbuf (reportLibraryOnlyFeatures, langVersion, s: string) = + LexBuffer.FromChars(reportLibraryOnlyFeatures, langVersion, s.ToCharArray()) -let FunctionAsLexbuf (reportLibraryOnlyFeatures, langVersion, strictIndentation, bufferFiller) = - LexBuffer.FromFunction(reportLibraryOnlyFeatures, langVersion, strictIndentation, bufferFiller) +let FunctionAsLexbuf (reportLibraryOnlyFeatures, langVersion, bufferFiller) = + LexBuffer.FromFunction(reportLibraryOnlyFeatures, langVersion, bufferFiller) -let SourceTextAsLexbuf (reportLibraryOnlyFeatures, langVersion, strictIndentation, sourceText) = - LexBuffer.FromSourceText(reportLibraryOnlyFeatures, langVersion, strictIndentation, sourceText) +let SourceTextAsLexbuf (reportLibraryOnlyFeatures, langVersion, sourceText) = + LexBuffer.FromSourceText(reportLibraryOnlyFeatures, langVersion, sourceText) -let StreamReaderAsLexbuf (reportLibraryOnlyFeatures, langVersion, strictIndentation, reader: StreamReader) = +let StreamReaderAsLexbuf (reportLibraryOnlyFeatures, langVersion, reader: StreamReader) = let mutable isFinished = false FunctionAsLexbuf( reportLibraryOnlyFeatures, langVersion, - strictIndentation, fun (chars, start, length) -> if isFinished then 0 diff --git a/src/Compiler/SyntaxTree/UnicodeLexing.fsi b/src/Compiler/SyntaxTree/UnicodeLexing.fsi index ee722ee08c3..e8e3d0b3436 100644 --- a/src/Compiler/SyntaxTree/UnicodeLexing.fsi +++ b/src/Compiler/SyntaxTree/UnicodeLexing.fsi @@ -13,27 +13,14 @@ type LexBuffer<'char> with member GetLocalData<'T when 'T: not null> : key: string * initializer: (unit -> 'T) -> 'T member TryGetLocalData<'T when 'T: not null> : key: string -> 'T option -val StringAsLexbuf: - reportLibraryOnlyFeatures: bool * langVersion: LanguageVersion * strictIndentation: bool option * string -> Lexbuf +val StringAsLexbuf: reportLibraryOnlyFeatures: bool * langVersion: LanguageVersion * string -> Lexbuf val FunctionAsLexbuf: - reportLibraryOnlyFeatures: bool * - langVersion: LanguageVersion * - strictIndentation: bool option * - bufferFiller: (char[] * int * int -> int) -> - Lexbuf + reportLibraryOnlyFeatures: bool * langVersion: LanguageVersion * bufferFiller: (char[] * int * int -> int) -> Lexbuf val SourceTextAsLexbuf: - reportLibraryOnlyFeatures: bool * - langVersion: LanguageVersion * - strictIndentation: bool option * - sourceText: ISourceText -> - Lexbuf + reportLibraryOnlyFeatures: bool * langVersion: LanguageVersion * sourceText: ISourceText -> Lexbuf /// Will not dispose of the stream reader. val StreamReaderAsLexbuf: - reportLibraryOnlyFeatures: bool * - langVersion: LanguageVersion * - strictIndentation: bool option * - reader: StreamReader -> - Lexbuf + reportLibraryOnlyFeatures: bool * langVersion: LanguageVersion * reader: StreamReader -> Lexbuf diff --git a/src/Compiler/lex.fsl b/src/Compiler/lex.fsl index ed6227723ea..32d1a39acde 100644 --- a/src/Compiler/lex.fsl +++ b/src/Compiler/lex.fsl @@ -201,8 +201,8 @@ let shouldStartFile args lexbuf (m:range) err tok = if (m.StartColumn <> 0 || m.StartLine <> 1) then fail args lexbuf err tok else tok -let evalIfDefExpression startPos reportLibraryOnlyFeatures langVersion strictIndentation args (lookup: string -> bool) (lexed: string) = - let lexbuf = LexBuffer.FromChars (reportLibraryOnlyFeatures, langVersion, strictIndentation, lexed.ToCharArray ()) +let evalIfDefExpression startPos reportLibraryOnlyFeatures langVersion args (lookup: string -> bool) (lexed: string) = + let lexbuf = LexBuffer.FromChars (reportLibraryOnlyFeatures, langVersion, lexed.ToCharArray ()) lexbuf.StartPos <- startPos lexbuf.EndPos <- startPos let tokenStream = FSharp.Compiler.PPLexer.tokenstream args @@ -1026,7 +1026,7 @@ rule token (args: LexArgs) (skip: bool) = parse shouldStartLine args lexbuf m (FSComp.SR.lexHashIfMustBeFirst()) let lookup id = List.contains id args.conditionalDefines let lexed = lexeme lexbuf - let isTrue, expr = evalIfDefExpression lexbuf.StartPos lexbuf.ReportLibraryOnlyFeatures lexbuf.LanguageVersion lexbuf.StrictIndentation args lookup lexed + let isTrue, expr = evalIfDefExpression lexbuf.StartPos lexbuf.ReportLibraryOnlyFeatures lexbuf.LanguageVersion args lookup lexed args.ifdefStack <- (IfDefIf,m) :: args.ifdefStack IfdefStore.SaveIfHash(lexbuf, lexed, expr, m) let contCase = if isTrue then LexerEndlineContinuation.Token else LexerEndlineContinuation.IfdefSkip(0, m) @@ -1058,7 +1058,7 @@ rule token (args: LexArgs) (skip: bool) = parse let lookup id = List.contains id args.conditionalDefines // Result is discarded: in active code, a prior #if/#elif branch is executing, // so this #elif always transitions to skipping. Eval is needed for trivia storage. - let _, expr = evalIfDefExpression lexbuf.StartPos lexbuf.ReportLibraryOnlyFeatures lexbuf.LanguageVersion lexbuf.StrictIndentation args lookup lexed + let _, expr = evalIfDefExpression lexbuf.StartPos lexbuf.ReportLibraryOnlyFeatures lexbuf.LanguageVersion args lookup lexed args.ifdefStack <- (IfDefElif,m) :: rest IfdefStore.SaveElifHash(lexbuf, lexed, expr, m) let tok = HASH_ELIF(m, lexed, LexCont.EndLine(args.ifdefStack, args.stringNest, LexerEndlineContinuation.IfdefSkip(0, m))) @@ -1123,7 +1123,7 @@ and ifdefSkip (n: int) (m: range) (args: LexArgs) (skip: bool) = parse else let lexed = lexeme lexbuf let lookup id = List.contains id args.conditionalDefines - let _, expr = evalIfDefExpression lexbuf.StartPos lexbuf.ReportLibraryOnlyFeatures lexbuf.LanguageVersion lexbuf.StrictIndentation args lookup lexed + let _, expr = evalIfDefExpression lexbuf.StartPos lexbuf.ReportLibraryOnlyFeatures lexbuf.LanguageVersion args lookup lexed IfdefStore.SaveIfHash(lexbuf, lexed, expr, m) let tok = INACTIVECODE(LexCont.EndLine(args.ifdefStack, args.stringNest, LexerEndlineContinuation.IfdefSkip(n+1, m))) if skip then endline (LexerEndlineContinuation.IfdefSkip(n+1, m)) args skip lexbuf else tok } @@ -1162,7 +1162,7 @@ and ifdefSkip (n: int) (m: range) (args: LexArgs) (skip: bool) = parse let evalAndSaveElif () = let lookup id = List.contains id args.conditionalDefines - let result, expr = evalIfDefExpression lexbuf.StartPos lexbuf.ReportLibraryOnlyFeatures lexbuf.LanguageVersion lexbuf.StrictIndentation args lookup lexed + let result, expr = evalIfDefExpression lexbuf.StartPos lexbuf.ReportLibraryOnlyFeatures lexbuf.LanguageVersion args lookup lexed IfdefStore.SaveElifHash(lexbuf, lexed, expr, m) result diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy index 9e769ad40fe..b83bcaefefd 100644 --- a/src/Compiler/pars.fsy +++ b/src/Compiler/pars.fsy @@ -1857,9 +1857,7 @@ classDefnMembersAtLeastOne: | classDefnMember opt_seps classDefnMembers { match $1, $3 with | [ SynMemberDefn.Interface(members=Some []; range=m) ], nextMember :: _ -> - let strictIndentation = parseState.LexBuffer.SupportsFeature LanguageFeature.StrictIndentation - let warnF = if strictIndentation then errorR else warning - warnF(IndentationProblem(FSComp.SR.lexfltTokenIsOffsideOfContextStartedEarlier(warningStringOfPos m.Start), nextMember.Range)) + errorR(IndentationProblem(FSComp.SR.lexfltTokenIsOffsideOfContextStartedEarlier(warningStringOfPos m.Start), nextMember.Range)) | _ -> () $1 @ $3 } @@ -2486,7 +2484,7 @@ tyconDefnOrSpfnSimpleRepr: if parseState.LexBuffer.ReportLibraryOnlyFeatures then libraryOnlyError mLhs if Option.isSome $2 then errorR(Error(FSComp.SR.parsInlineAssemblyCannotHaveVisibilityDeclarations(), rhs parseState 2)) let s, _ = $5 - let ilType = ParseAssemblyCodeType s parseState.LexBuffer.ReportLibraryOnlyFeatures parseState.LexBuffer.LanguageVersion parseState.LexBuffer.StrictIndentation (rhs parseState 5) + let ilType = ParseAssemblyCodeType s parseState.LexBuffer.ReportLibraryOnlyFeatures parseState.LexBuffer.LanguageVersion (rhs parseState 5) SynTypeDefnSimpleRepr.LibraryOnlyILAssembly(box ilType, mLhs) } @@ -5764,7 +5762,7 @@ inlineAssemblyExpr: { if parseState.LexBuffer.ReportLibraryOnlyFeatures then libraryOnlyWarning (lhs parseState) let (s, _), sm = $2, rhs parseState 2 (fun m -> - let ilInstrs = ParseAssemblyCodeInstructions s parseState.LexBuffer.ReportLibraryOnlyFeatures parseState.LexBuffer.LanguageVersion parseState.LexBuffer.StrictIndentation sm + let ilInstrs = ParseAssemblyCodeInstructions s parseState.LexBuffer.ReportLibraryOnlyFeatures parseState.LexBuffer.LanguageVersion sm SynExpr.LibraryOnlyILAssembly(box ilInstrs, $3, List.rev $4, $5, m)) } optCurriedArgExprs: diff --git a/src/Compiler/xlf/FSComp.txt.cs.xlf b/src/Compiler/xlf/FSComp.txt.cs.xlf index 27327ec82f3..d1dcfe2543c 100644 --- a/src/Compiler/xlf/FSComp.txt.cs.xlf +++ b/src/Compiler/xlf/FSComp.txt.cs.xlf @@ -677,11 +677,6 @@ Statické členy v rozhraních - - Raises errors on incorrect indentation, allows better recovery and analysis during editing - Vyvolává chyby při nesprávném odsazení, umožňuje lepší obnovení a analýzu během úprav - - string interpolation interpolace řetězce @@ -1127,11 +1122,6 @@ Zahrnout informace o rozhraní F#, výchozí je soubor. Klíčové pro distribuci knihoven. - - Override indentation rules implied by the language version ({0} by default) - Override indentation rules implied by the language version ({0} by default) - - Supported language versions: Podporované jazykové verze: @@ -6713,8 +6703,8 @@ - Unexpected syntax or possible incorrect indentation: this token is offside of context started at position {0}. Try indenting this further.\nTo continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. - Neočekávaná syntaxe nebo možné nesprávné odsazení: Tento token je mimo kontext spuštěný na pozici {0}. Zkuste toto odsazení ještě více odsadit.\nPokud chcete dál používat neodpovídající odsazení, předejte kompilátoru příznak '--strict-indentation-' nebo nastavte jazykovou verzi na F# 7. + Unexpected syntax or possible incorrect indentation: this token is offside of context started at position {0}. Try indenting this further. + Neočekávaná syntaxe nebo možné nesprávné odsazení: Tento token je mimo kontext spuštěný na pozici {0}. Zkuste toto odsazení ještě více odsadit.\nPokud chcete dál používat neodpovídající odsazení, předejte kompilátoru příznak '--strict-indentation-' nebo nastavte jazykovou verzi na F# 7. diff --git a/src/Compiler/xlf/FSComp.txt.de.xlf b/src/Compiler/xlf/FSComp.txt.de.xlf index cffe0a18264..916e62a5cc7 100644 --- a/src/Compiler/xlf/FSComp.txt.de.xlf +++ b/src/Compiler/xlf/FSComp.txt.de.xlf @@ -677,11 +677,6 @@ Statische Member in Schnittstellen - - Raises errors on incorrect indentation, allows better recovery and analysis during editing - Löst Fehler bei fehlerhaftem Einzug aus und ermöglicht eine bessere Wiederherstellung und Analyse während der Bearbeitung. - - string interpolation Zeichenfolgeninterpolation @@ -1127,11 +1122,6 @@ Schließen Sie F#-Schnittstelleninformationen ein, der Standardwert ist „file“. Wesentlich für die Verteilung von Bibliotheken. - - Override indentation rules implied by the language version ({0} by default) - Override indentation rules implied by the language version ({0} by default) - - Supported language versions: Unterstützte Sprachversionen: @@ -6713,8 +6703,8 @@ - Unexpected syntax or possible incorrect indentation: this token is offside of context started at position {0}. Try indenting this further.\nTo continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. - Unerwartete Syntax oder möglicherweise falscher Einzug: Dieses Token befindet sich außerhalb des Kontexts, der an Position {0}gestartet wurde. Versuchen Sie, dies weiter einzurücken.\nUm weiterhin eine nicht konforme Einrückung zu verwenden, übergeben Sie dem Compiler das Flag „--strict-indentation-“ oder setzen Sie die Sprachversion auf F# 7. + Unexpected syntax or possible incorrect indentation: this token is offside of context started at position {0}. Try indenting this further. + Unerwartete Syntax oder möglicherweise falscher Einzug: Dieses Token befindet sich außerhalb des Kontexts, der an Position {0}gestartet wurde. Versuchen Sie, dies weiter einzurücken.\nUm weiterhin eine nicht konforme Einrückung zu verwenden, übergeben Sie dem Compiler das Flag „--strict-indentation-“ oder setzen Sie die Sprachversion auf F# 7. diff --git a/src/Compiler/xlf/FSComp.txt.es.xlf b/src/Compiler/xlf/FSComp.txt.es.xlf index ec9a74bd72c..b3e2ccabb2c 100644 --- a/src/Compiler/xlf/FSComp.txt.es.xlf +++ b/src/Compiler/xlf/FSComp.txt.es.xlf @@ -677,11 +677,6 @@ Miembros estáticos en interfaces - - Raises errors on incorrect indentation, allows better recovery and analysis during editing - Genera errores en una sangría incorrecta, permite una mejor recuperación y análisis durante la edición. - - string interpolation interpolación de cadena @@ -1127,11 +1122,6 @@ Incluir información de interfaz de F#, el valor predeterminado es file. Esencial para distribuir bibliotecas. - - Override indentation rules implied by the language version ({0} by default) - Override indentation rules implied by the language version ({0} by default) - - Supported language versions: Versiones de lenguaje admitidas: @@ -6713,8 +6703,8 @@ - Unexpected syntax or possible incorrect indentation: this token is offside of context started at position {0}. Try indenting this further.\nTo continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. - Sintaxis inesperada o posible sangría incorrecta: este token está fuera del contexto iniciado en la posición {0}. Intente aplicar más sangría.\nPara seguir usando la sangría no conforme, pase la marca "--strict-indentation-" al compilador o establezca la versión del lenguaje en F# 7. + Unexpected syntax or possible incorrect indentation: this token is offside of context started at position {0}. Try indenting this further. + Sintaxis inesperada o posible sangría incorrecta: este token está fuera del contexto iniciado en la posición {0}. Intente aplicar más sangría.\nPara seguir usando la sangría no conforme, pase la marca "--strict-indentation-" al compilador o establezca la versión del lenguaje en F# 7. diff --git a/src/Compiler/xlf/FSComp.txt.fr.xlf b/src/Compiler/xlf/FSComp.txt.fr.xlf index 5157305f7c8..0388bbb9a94 100644 --- a/src/Compiler/xlf/FSComp.txt.fr.xlf +++ b/src/Compiler/xlf/FSComp.txt.fr.xlf @@ -677,11 +677,6 @@ Membres statiques dans les interfaces - - Raises errors on incorrect indentation, allows better recovery and analysis during editing - Génère des erreurs en cas d'indentation incorrecte, permet une meilleure récupération et analyse lors de l'édition - - string interpolation interpolation de chaîne @@ -1127,11 +1122,6 @@ Incluez les informations de l’interface F#, la valeur par défaut est un fichier. Essentiel pour la distribution des bibliothèques. - - Override indentation rules implied by the language version ({0} by default) - Override indentation rules implied by the language version ({0} by default) - - Supported language versions: Versions linguistiques prises en charge : @@ -6713,8 +6703,8 @@ - Unexpected syntax or possible incorrect indentation: this token is offside of context started at position {0}. Try indenting this further.\nTo continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. - Syntaxe inattendue ou mise en retrait incorrecte possible : ce jeton est hors du contexte démarré à la position {0}. Essayez de mettre cela en retrait.\nPour continuer à utiliser une mise en retrait non conforme, passez l’indicateur '--strict-indentation-' au compilateur ou définissez la version de langage sur F# 7. + Unexpected syntax or possible incorrect indentation: this token is offside of context started at position {0}. Try indenting this further. + Syntaxe inattendue ou mise en retrait incorrecte possible : ce jeton est hors du contexte démarré à la position {0}. Essayez de mettre cela en retrait.\nPour continuer à utiliser une mise en retrait non conforme, passez l’indicateur '--strict-indentation-' au compilateur ou définissez la version de langage sur F# 7. diff --git a/src/Compiler/xlf/FSComp.txt.it.xlf b/src/Compiler/xlf/FSComp.txt.it.xlf index 53b61ab8458..a9ec9727009 100644 --- a/src/Compiler/xlf/FSComp.txt.it.xlf +++ b/src/Compiler/xlf/FSComp.txt.it.xlf @@ -677,11 +677,6 @@ Membri statici nelle interfacce - - Raises errors on incorrect indentation, allows better recovery and analysis during editing - Genera errori di rientro non corretto. Consente un ripristino e un'analisi migliori durante la modifica - - string interpolation interpolazione di stringhe @@ -1127,11 +1122,6 @@ Includere le informazioni sull'interfaccia F#. Il valore predefinito è file. Essential per la distribuzione di librerie. - - Override indentation rules implied by the language version ({0} by default) - Override indentation rules implied by the language version ({0} by default) - - Supported language versions: Versioni del linguaggio supportate: @@ -6713,8 +6703,8 @@ - Unexpected syntax or possible incorrect indentation: this token is offside of context started at position {0}. Try indenting this further.\nTo continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. - Sintassi imprevista o possibile rientro non corretto: questo token è fuori dal contesto avviato nella posizione {0}. Provare a impostare ulteriormente il rientro.\nPer continuare a usare un rientro non conforme, passare il flag '--strict-indentation-' al compilatore, o impostare la versione del linguaggio su F# 7. + Unexpected syntax or possible incorrect indentation: this token is offside of context started at position {0}. Try indenting this further. + Sintassi imprevista o possibile rientro non corretto: questo token è fuori dal contesto avviato nella posizione {0}. Provare a impostare ulteriormente il rientro.\nPer continuare a usare un rientro non conforme, passare il flag '--strict-indentation-' al compilatore, o impostare la versione del linguaggio su F# 7. diff --git a/src/Compiler/xlf/FSComp.txt.ja.xlf b/src/Compiler/xlf/FSComp.txt.ja.xlf index 7f716fd56a7..84ff697946f 100644 --- a/src/Compiler/xlf/FSComp.txt.ja.xlf +++ b/src/Compiler/xlf/FSComp.txt.ja.xlf @@ -677,11 +677,6 @@ インターフェイス内の静的メンバー - - Raises errors on incorrect indentation, allows better recovery and analysis during editing - 不適切なインデントでエラーが発生し、編集中の回復と分析が向上します - - string interpolation 文字列の補間 @@ -1127,11 +1122,6 @@ F# インターフェイス情報を含めます。既定値は file です。ライブラリの配布に不可欠です。 - - Override indentation rules implied by the language version ({0} by default) - Override indentation rules implied by the language version ({0} by default) - - Supported language versions: サポートされる言語バージョン: @@ -6713,8 +6703,8 @@ - Unexpected syntax or possible incorrect indentation: this token is offside of context started at position {0}. Try indenting this further.\nTo continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. - 予期しない構文またはインデントが正しくない可能性: このトークンは位置 {0} から開始されるコンテキストのオフサイドになります。このトークンのインデントを増やしてみてください。\n非準拠のインデントを引き続き使用するには、'--strict-indent-' フラグをコンパイラに渡すか、言語バージョンを F# 7 に設定してください。 + Unexpected syntax or possible incorrect indentation: this token is offside of context started at position {0}. Try indenting this further. + 予期しない構文またはインデントが正しくない可能性: このトークンは位置 {0} から開始されるコンテキストのオフサイドになります。このトークンのインデントを増やしてみてください。\n非準拠のインデントを引き続き使用するには、'--strict-indent-' フラグをコンパイラに渡すか、言語バージョンを F# 7 に設定してください。 diff --git a/src/Compiler/xlf/FSComp.txt.ko.xlf b/src/Compiler/xlf/FSComp.txt.ko.xlf index 1e323fe7bc7..8b169c14354 100644 --- a/src/Compiler/xlf/FSComp.txt.ko.xlf +++ b/src/Compiler/xlf/FSComp.txt.ko.xlf @@ -677,11 +677,6 @@ 인터페이스의 정적 멤버 - - Raises errors on incorrect indentation, allows better recovery and analysis during editing - 잘못된 들여쓰기에 대한 오류를 제기하고 편집 중에 더 나은 복구 및 분석이 가능합니다. - - string interpolation 문자열 보간 @@ -1127,11 +1122,6 @@ F# 인터페이스 정보를 포함합니다. 기본값은 파일입니다. 라이브러리를 배포하는 데 필수적입니다. - - Override indentation rules implied by the language version ({0} by default) - Override indentation rules implied by the language version ({0} by default) - - Supported language versions: 지원되는 언어 버전: @@ -6713,8 +6703,8 @@ - Unexpected syntax or possible incorrect indentation: this token is offside of context started at position {0}. Try indenting this further.\nTo continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. - 예기치 않은 구문 또는 잘못된 들여쓰기: 이 토큰은 {0} 위치에서 시작된 컨텍스트의 오프 사이드입니다. 이를 더 들여쓰기해 보세요.\n규정을 준수하지 않는 들여쓰기를 계속 사용하려면 '--strict-indentation-' 플래그를 컴파일러에 전달하거나 언어 버전을 F# 7로 설정합니다. + Unexpected syntax or possible incorrect indentation: this token is offside of context started at position {0}. Try indenting this further. + 예기치 않은 구문 또는 잘못된 들여쓰기: 이 토큰은 {0} 위치에서 시작된 컨텍스트의 오프 사이드입니다. 이를 더 들여쓰기해 보세요.\n규정을 준수하지 않는 들여쓰기를 계속 사용하려면 '--strict-indentation-' 플래그를 컴파일러에 전달하거나 언어 버전을 F# 7로 설정합니다. diff --git a/src/Compiler/xlf/FSComp.txt.pl.xlf b/src/Compiler/xlf/FSComp.txt.pl.xlf index 2f00a532f3c..ee94b000c13 100644 --- a/src/Compiler/xlf/FSComp.txt.pl.xlf +++ b/src/Compiler/xlf/FSComp.txt.pl.xlf @@ -677,11 +677,6 @@ Statyczne składowe w interfejsach - - Raises errors on incorrect indentation, allows better recovery and analysis during editing - Zgłasza błędy w przypadku nieprawidłowego wcięcia, umożliwia lepsze odzyskiwanie i analizę podczas edytowania - - string interpolation interpolacja ciągu @@ -1127,11 +1122,6 @@ Uwzględnij informacje o interfejsie języka F#. Wartość domyślna to plik. Niezbędne do rozpowszechniania bibliotek. - - Override indentation rules implied by the language version ({0} by default) - Override indentation rules implied by the language version ({0} by default) - - Supported language versions: Obsługiwane wersje językowe: @@ -6713,8 +6703,8 @@ - Unexpected syntax or possible incorrect indentation: this token is offside of context started at position {0}. Try indenting this further.\nTo continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. - Nieoczekiwana składnia lub możliwe niepoprawne wcięcie: ten token jest poza kontekstem uruchomionym na pozycji {0}. Spróbuj jeszcze bardziej wciąć to ustawienie.\nAby kontynuować używanie niezgodnych wcięć, przekaż flagę „--strict-indentation-” do kompilatora lub ustaw wersję języka na F# 7. + Unexpected syntax or possible incorrect indentation: this token is offside of context started at position {0}. Try indenting this further. + Nieoczekiwana składnia lub możliwe niepoprawne wcięcie: ten token jest poza kontekstem uruchomionym na pozycji {0}. Spróbuj jeszcze bardziej wciąć to ustawienie.\nAby kontynuować używanie niezgodnych wcięć, przekaż flagę „--strict-indentation-” do kompilatora lub ustaw wersję języka na F# 7. diff --git a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf index 4febb800c76..1dfe6078674 100644 --- a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf +++ b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf @@ -677,11 +677,6 @@ Membros estáticos em interfaces - - Raises errors on incorrect indentation, allows better recovery and analysis during editing - Gera erros de recuo incorreto, permite uma melhor recuperação e análise durante a edição - - string interpolation interpolação da cadeia de caracteres @@ -1127,11 +1122,6 @@ Inclua informações da interface F#, o padrão é file. Essencial para distribuir bibliotecas. - - Override indentation rules implied by the language version ({0} by default) - Override indentation rules implied by the language version ({0} by default) - - Supported language versions: Versões de linguagens com suporte: @@ -6713,8 +6703,8 @@ - Unexpected syntax or possible incorrect indentation: this token is offside of context started at position {0}. Try indenting this further.\nTo continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. - Sintaxe inesperada ou possível recuo incorreto: esse token está fora do contexto iniciado na posição {0}. Tente recuar isso ainda mais.\nPara continuar usando o recuo não compatível, passe o sinalizador '--strict-indentation-' para o compilador ou defina a versão da linguagem como F# 7. + Unexpected syntax or possible incorrect indentation: this token is offside of context started at position {0}. Try indenting this further. + Sintaxe inesperada ou possível recuo incorreto: esse token está fora do contexto iniciado na posição {0}. Tente recuar isso ainda mais.\nPara continuar usando o recuo não compatível, passe o sinalizador '--strict-indentation-' para o compilador ou defina a versão da linguagem como F# 7. diff --git a/src/Compiler/xlf/FSComp.txt.ru.xlf b/src/Compiler/xlf/FSComp.txt.ru.xlf index e59e2044060..37c37f61657 100644 --- a/src/Compiler/xlf/FSComp.txt.ru.xlf +++ b/src/Compiler/xlf/FSComp.txt.ru.xlf @@ -677,11 +677,6 @@ Статические элементы в интерфейсах - - Raises errors on incorrect indentation, allows better recovery and analysis during editing - Выдает ошибки при неправильном отступе, обеспечивает более эффективное восстановление и анализ во время редактирования - - string interpolation интерполяция строк @@ -1127,11 +1122,6 @@ Включить сведения об интерфейсе F#, по умолчанию используется файл. Необходимо для распространения библиотек. - - Override indentation rules implied by the language version ({0} by default) - Override indentation rules implied by the language version ({0} by default) - - Supported language versions: Поддерживаемые языковые версии: @@ -6713,8 +6703,8 @@ - Unexpected syntax or possible incorrect indentation: this token is offside of context started at position {0}. Try indenting this further.\nTo continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. - Неожиданный синтаксис или, возможно, неправильный отступ: этот токен находится вне контекста, начатого в позиции {0}. Попробуйте увеличить отступ.\nЧтобы продолжить использование несоответствующего отступа, передайте компилятору флаг '--strict-indentation-' или установите версию языка F# 7. + Unexpected syntax or possible incorrect indentation: this token is offside of context started at position {0}. Try indenting this further. + Неожиданный синтаксис или, возможно, неправильный отступ: этот токен находится вне контекста, начатого в позиции {0}. Попробуйте увеличить отступ.\nЧтобы продолжить использование несоответствующего отступа, передайте компилятору флаг '--strict-indentation-' или установите версию языка F# 7. diff --git a/src/Compiler/xlf/FSComp.txt.tr.xlf b/src/Compiler/xlf/FSComp.txt.tr.xlf index e8c0d9a790d..89dbcc9eee2 100644 --- a/src/Compiler/xlf/FSComp.txt.tr.xlf +++ b/src/Compiler/xlf/FSComp.txt.tr.xlf @@ -677,11 +677,6 @@ Arabirimlerdeki statik üyeler - - Raises errors on incorrect indentation, allows better recovery and analysis during editing - Yanlış girinti üzerine hata verir ve düzenleme sırasında daha iyi kurtarma ve analize olanak sağlar - - string interpolation dizede düz metin arasına kod ekleme @@ -1127,11 +1122,6 @@ F# arabirim bilgilerini dahil edin; varsayılan değer dosyadır. Kitaplıkları dağıtmak için gereklidir. - - Override indentation rules implied by the language version ({0} by default) - Override indentation rules implied by the language version ({0} by default) - - Supported language versions: Desteklenen dil sürümleri: @@ -6713,8 +6703,8 @@ - Unexpected syntax or possible incorrect indentation: this token is offside of context started at position {0}. Try indenting this further.\nTo continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. - Beklenmeyen sözdizimi veya olası yanlış girinti: Bu belirteç, {0} konumunda başlayan bağlamın ofsaytıdır. Bunu daha fazla girintilemeyi deneyin.\nUygun olmayan girintiyi kullanmaya devam etmek için '--strict-indentation-' işaretini derleyiciye iletin veya dil sürümünü F# 7 olarak ayarlayın. + Unexpected syntax or possible incorrect indentation: this token is offside of context started at position {0}. Try indenting this further. + Beklenmeyen sözdizimi veya olası yanlış girinti: Bu belirteç, {0} konumunda başlayan bağlamın ofsaytıdır. Bunu daha fazla girintilemeyi deneyin.\nUygun olmayan girintiyi kullanmaya devam etmek için '--strict-indentation-' işaretini derleyiciye iletin veya dil sürümünü F# 7 olarak ayarlayın. diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf index 1037d060431..0f206016433 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf @@ -677,11 +677,6 @@ 接口中的静态成员 - - Raises errors on incorrect indentation, allows better recovery and analysis during editing - 在缩进不准确时引发错误,以便在编辑期间更好地恢复和分析 - - string interpolation 字符串内插 @@ -1127,11 +1122,6 @@ 包括 F# 接口信息,默认值为文件。对于分发库必不可少。 - - Override indentation rules implied by the language version ({0} by default) - Override indentation rules implied by the language version ({0} by default) - - Supported language versions: 支持的语言版本: @@ -6713,8 +6703,8 @@ - Unexpected syntax or possible incorrect indentation: this token is offside of context started at position {0}. Try indenting this further.\nTo continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. - 意外语法或可能错误的缩进: 此令牌对于 {0} 处开始的上下文来说越位。尝试进一步缩进此内容。\n若要继续使用不符合条件的索引,请将 "--strict-indentation-" 传递给编译器,或者将语言版本设置为 F# 7。 + Unexpected syntax or possible incorrect indentation: this token is offside of context started at position {0}. Try indenting this further. + 意外语法或可能错误的缩进: 此令牌对于 {0} 处开始的上下文来说越位。尝试进一步缩进此内容。\n若要继续使用不符合条件的索引,请将 "--strict-indentation-" 传递给编译器,或者将语言版本设置为 F# 7。 diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf index ceb937ec683..1c0f4305257 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf @@ -677,11 +677,6 @@ 介面中的靜態成員 - - Raises errors on incorrect indentation, allows better recovery and analysis during editing - 縮排不正確時引發錯誤,以便在編輯期間進行更好的復原和分析 - - string interpolation 字串內插補點 @@ -1127,11 +1122,6 @@ 包含 F# 介面資訊,預設值為檔案。發佈程式庫的基本功能。 - - Override indentation rules implied by the language version ({0} by default) - Override indentation rules implied by the language version ({0} by default) - - Supported language versions: 支援的語言版本: @@ -6713,8 +6703,8 @@ - Unexpected syntax or possible incorrect indentation: this token is offside of context started at position {0}. Try indenting this further.\nTo continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. - 未預期的語法或可能不正確的縮排: 此權杖與在位置 {0} 啟動的內容不同步。請嘗試進一步縮排。\n若要繼續使用不符合的縮排,請傳遞 '--strict-indentation-' 旗標給編譯器,或將語言版本設定為 F# 7。 + Unexpected syntax or possible incorrect indentation: this token is offside of context started at position {0}. Try indenting this further. + 未預期的語法或可能不正確的縮排: 此權杖與在位置 {0} 啟動的內容不同步。請嘗試進一步縮排。\n若要繼續使用不符合的縮排,請傳遞 '--strict-indentation-' 旗標給編譯器,或將語言版本設定為 F# 7。 diff --git a/tests/FSharp.Compiler.ComponentTests/CompilerDirectives/Line.fs b/tests/FSharp.Compiler.ComponentTests/CompilerDirectives/Line.fs index 51a171b3ac4..6eef92698cd 100644 --- a/tests/FSharp.Compiler.ComponentTests/CompilerDirectives/Line.fs +++ b/tests/FSharp.Compiler.ComponentTests/CompilerDirectives/Line.fs @@ -135,7 +135,7 @@ printfn "" PathMap.empty, true ) - let lexbuf = StringAsLexbuf(true, langVersion, None, sourceText) + let lexbuf = StringAsLexbuf(true, langVersion, sourceText) resetLexbufPos "testt.fs" lexbuf let tokenizer _ = let t = Lexer.token lexargs true lexbuf diff --git a/tests/FSharp.Compiler.ComponentTests/CompilerOptions/Fsc/UncoveredOptions.fs b/tests/FSharp.Compiler.ComponentTests/CompilerOptions/Fsc/UncoveredOptions.fs index dc0c6e0762f..ef40f3b8159 100644 --- a/tests/FSharp.Compiler.ComponentTests/CompilerOptions/Fsc/UncoveredOptions.fs +++ b/tests/FSharp.Compiler.ComponentTests/CompilerOptions/Fsc/UncoveredOptions.fs @@ -19,8 +19,6 @@ module UncoveredOptions = [] [] [] - [] - [] [] [] [] diff --git a/tests/FSharp.Compiler.ComponentTests/CompilerOptions/fsc/misc/compiler_help_output.bsl b/tests/FSharp.Compiler.ComponentTests/CompilerOptions/fsc/misc/compiler_help_output.bsl index 56df6419a54..fb9b669e05c 100644 --- a/tests/FSharp.Compiler.ComponentTests/CompilerOptions/fsc/misc/compiler_help_output.bsl +++ b/tests/FSharp.Compiler.ComponentTests/CompilerOptions/fsc/misc/compiler_help_output.bsl @@ -83,7 +83,6 @@ Copyright (c) Microsoft Corporation. All Rights Reserved. --disableLanguageFeature: Disable a specific language feature by name. --checked[+|-] Generate overflow checks (off by default) --define: Define conditional compilation symbols (Short form: -d) ---strict-indentation[+|-] Override indentation rules implied by the language version (off by default) --always-inline[+|-] Always inline 'inline' functions diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/AccessibilityAnnotations/PermittedLocations/PermittedLocations.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/AccessibilityAnnotations/PermittedLocations/PermittedLocations.fs index 7f4c02ab56f..b8ded929963 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/AccessibilityAnnotations/PermittedLocations/PermittedLocations.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/AccessibilityAnnotations/PermittedLocations/PermittedLocations.fs @@ -131,9 +131,9 @@ module AccessibilityAnnotations_PermittedLocations = |> shouldFail |> withDiagnostics [ (Error 531, Line 11, Col 13, Line 11, Col 20, "Accessibility modifiers should come immediately prior to the identifier naming a construct") - (Error 58, Line 12, Col 23, Line 12, Col 26, "Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (11:23). Try indenting this further.\nTo continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7.") + (Error 58, Line 12, Col 23, Line 12, Col 26, "Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (11:23). Try indenting this further.") (Error 531, Line 12, Col 13, Line 12, Col 19, "Accessibility modifiers should come immediately prior to the identifier naming a construct") - (Error 58, Line 13, Col 23, Line 13, Col 26, "Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (12:23). Try indenting this further.\nTo continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7.") + (Error 58, Line 13, Col 23, Line 13, Col 26, "Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (12:23). Try indenting this further.") (Error 531, Line 13, Col 13, Line 13, Col 21, "Accessibility modifiers should come immediately prior to the identifier naming a construct") ] diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/LetBindings/Basic/Basic.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/LetBindings/Basic/Basic.fs index b59d28cbdd2..0e2ef117ea6 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/LetBindings/Basic/Basic.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/LetBindings/Basic/Basic.fs @@ -76,7 +76,7 @@ module LetBindings_Basic = |> verifyCompile |> shouldFail |> withDiagnostics [ - (Error 58, Line 10, Col 1, Line 10, Col 5, "Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (8:1). Try indenting this further.\nTo continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7.") + (Error 58, Line 10, Col 1, Line 10, Col 5, "Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (8:1). Try indenting this further.") (Error 10, Line 10, Col 6, Line 10, Col 7, "Unexpected start of structured construct in expression") (Error 583, Line 9, Col 5, Line 9, Col 6, "Unmatched '('") (Error 10, Line 10, Col 16, Line 10, Col 17, "Unexpected symbol ')' in implementation file") diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/LexicalFiltering/OffsideExceptions/OffsideExceptions.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/LexicalFiltering/OffsideExceptions/OffsideExceptions.fs index 9dc910ba249..39db4d639a8 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/LexicalFiltering/OffsideExceptions/OffsideExceptions.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/LexicalFiltering/OffsideExceptions/OffsideExceptions.fs @@ -229,7 +229,7 @@ module A EndLine = 4 EndColumn = 6 } Message = - "Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (3:5). Try indenting this further.\nTo continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7." + "Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (3:5). Try indenting this further." } |> ignore [] diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/LexicalFiltering/OffsideExceptions/RelaxWhitespace2.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/LexicalFiltering/OffsideExceptions/RelaxWhitespace2.fs index ef83e1ba871..4b90ca2988a 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/LexicalFiltering/OffsideExceptions/RelaxWhitespace2.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/LexicalFiltering/OffsideExceptions/RelaxWhitespace2.fs @@ -3434,7 +3434,7 @@ let c = f' { let d = f' {| X = 2 (* FS0058 Possible incorrect indentation: this token is offside of context started at position (12:11). -Try indenting this further.\nTo continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7 *) +Try indenting this further. *) |} let e = f' {| X = 2 // Indenting further is needed diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/Types/UnionTypes/UnionTypes.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/Types/UnionTypes/UnionTypes.fs index 7d5db82abde..49c5b41d7cc 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/Types/UnionTypes/UnionTypes.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/Types/UnionTypes/UnionTypes.fs @@ -608,7 +608,7 @@ module UnionTypes = |> verifyCompile |> shouldFail |> withDiagnostics [ - (Error 58, Line 9, Col 1, Line 9, Col 2, "Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (8:19). Try indenting this further.\nTo continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7.") + (Error 58, Line 9, Col 1, Line 9, Col 2, "Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (8:19). Try indenting this further.") (Error 547, Line 8, Col 24, Line 8, Col 33, "A type definition requires one or more members or other declarations. If you intend to define an empty class, struct or interface, then use 'type ... = class end', 'interface end' or 'struct end'.") (Error 10, Line 9, Col 1, Line 9, Col 2, "Unexpected symbol '|' in implementation file") ] diff --git a/tests/FSharp.Compiler.ComponentTests/Language/CompilerDirectiveTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/CompilerDirectiveTests.fs index 829b56eca14..9db654de7af 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/CompilerDirectiveTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/CompilerDirectiveTests.fs @@ -44,7 +44,7 @@ let y = x |> compile |> shouldFail |> withSingleDiagnostic - (Error 58, Line 11, Col 1, Line 11, Col 4, "Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (9:5). Try indenting this further.\nTo continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7.") + (Error 58, Line 11, Col 1, Line 11, Col 4, "Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (9:5). Try indenting this further.") module ``Test compiler directives in FSI`` = [] diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.bsl b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.bsl index 76080e3d775..f4b39a1066f 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.bsl +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.bsl @@ -2265,14 +2265,12 @@ FSharp.Compiler.CodeAnalysis.FSharpParsingOptions: Int32 GetHashCode() FSharp.Compiler.CodeAnalysis.FSharpParsingOptions: Int32 GetHashCode(System.Collections.IEqualityComparer) FSharp.Compiler.CodeAnalysis.FSharpParsingOptions: Microsoft.FSharp.Collections.FSharpList`1[System.String] ConditionalDefines FSharp.Compiler.CodeAnalysis.FSharpParsingOptions: Microsoft.FSharp.Collections.FSharpList`1[System.String] get_ConditionalDefines() -FSharp.Compiler.CodeAnalysis.FSharpParsingOptions: Microsoft.FSharp.Core.FSharpOption`1[System.Boolean] StrictIndentation -FSharp.Compiler.CodeAnalysis.FSharpParsingOptions: Microsoft.FSharp.Core.FSharpOption`1[System.Boolean] get_StrictIndentation() FSharp.Compiler.CodeAnalysis.FSharpParsingOptions: System.String LangVersionText FSharp.Compiler.CodeAnalysis.FSharpParsingOptions: System.String ToString() FSharp.Compiler.CodeAnalysis.FSharpParsingOptions: System.String get_LangVersionText() FSharp.Compiler.CodeAnalysis.FSharpParsingOptions: System.String[] SourceFiles FSharp.Compiler.CodeAnalysis.FSharpParsingOptions: System.String[] get_SourceFiles() -FSharp.Compiler.CodeAnalysis.FSharpParsingOptions: Void .ctor(System.String[], Boolean, Microsoft.FSharp.Collections.FSharpList`1[System.String], FSharp.Compiler.Diagnostics.FSharpDiagnosticOptions, System.String, Boolean, Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Boolean, Boolean) +FSharp.Compiler.CodeAnalysis.FSharpParsingOptions: Void .ctor(System.String[], Boolean, Microsoft.FSharp.Collections.FSharpList`1[System.String], FSharp.Compiler.Diagnostics.FSharpDiagnosticOptions, System.String, Boolean, Boolean, Boolean) FSharp.Compiler.CodeAnalysis.FSharpProjectContext: FSharp.Compiler.CodeAnalysis.FSharpProjectOptions ProjectOptions FSharp.Compiler.CodeAnalysis.FSharpProjectContext: FSharp.Compiler.CodeAnalysis.FSharpProjectOptions get_ProjectOptions() FSharp.Compiler.CodeAnalysis.FSharpProjectContext: FSharp.Compiler.Symbols.FSharpAccessibilityRights AccessibilityRights @@ -11460,7 +11458,7 @@ FSharp.Compiler.Tokenization.FSharpKeywords: Microsoft.FSharp.Collections.FSharp FSharp.Compiler.Tokenization.FSharpKeywords: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[System.String,System.String]] KeywordsWithDescription FSharp.Compiler.Tokenization.FSharpKeywords: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[System.String,System.String]] get_KeywordsWithDescription() FSharp.Compiler.Tokenization.FSharpKeywords: System.String NormalizeIdentifierBackticks(System.String) -FSharp.Compiler.Tokenization.FSharpLexer: Void Tokenize(FSharp.Compiler.Text.ISourceText, Microsoft.FSharp.Core.FSharpFunc`2[FSharp.Compiler.Tokenization.FSharpToken,Microsoft.FSharp.Core.Unit], Microsoft.FSharp.Core.FSharpOption`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean], Microsoft.FSharp.Core.FSharpOption`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[System.String]], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Tokenization.FSharpLexerFlags], Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpMap`2[System.String,System.String]], Microsoft.FSharp.Core.FSharpOption`1[System.Threading.CancellationToken]) +FSharp.Compiler.Tokenization.FSharpLexer: Void Tokenize(FSharp.Compiler.Text.ISourceText, Microsoft.FSharp.Core.FSharpFunc`2[FSharp.Compiler.Tokenization.FSharpToken,Microsoft.FSharp.Core.Unit], Microsoft.FSharp.Core.FSharpOption`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[System.String]], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Tokenization.FSharpLexerFlags], Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpMap`2[System.String,System.String]], Microsoft.FSharp.Core.FSharpOption`1[System.Threading.CancellationToken]) FSharp.Compiler.Tokenization.FSharpLexerFlags: FSharp.Compiler.Tokenization.FSharpLexerFlags Compiling FSharp.Compiler.Tokenization.FSharpLexerFlags: FSharp.Compiler.Tokenization.FSharpLexerFlags CompilingFSharpCore FSharp.Compiler.Tokenization.FSharpLexerFlags: FSharp.Compiler.Tokenization.FSharpLexerFlags Default @@ -11472,7 +11470,7 @@ FSharp.Compiler.Tokenization.FSharpLineTokenizer: FSharp.Compiler.Tokenization.F FSharp.Compiler.Tokenization.FSharpLineTokenizer: System.Tuple`2[Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Tokenization.FSharpTokenInfo],FSharp.Compiler.Tokenization.FSharpTokenizerLexState] ScanToken(FSharp.Compiler.Tokenization.FSharpTokenizerLexState) FSharp.Compiler.Tokenization.FSharpSourceTokenizer: FSharp.Compiler.Tokenization.FSharpLineTokenizer CreateBufferTokenizer(Microsoft.FSharp.Core.FSharpFunc`2[System.Tuple`3[System.Char[],System.Int32,System.Int32],System.Int32]) FSharp.Compiler.Tokenization.FSharpSourceTokenizer: FSharp.Compiler.Tokenization.FSharpLineTokenizer CreateLineTokenizer(System.String) -FSharp.Compiler.Tokenization.FSharpSourceTokenizer: Void .ctor(Microsoft.FSharp.Collections.FSharpList`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[System.Boolean]) +FSharp.Compiler.Tokenization.FSharpSourceTokenizer: Void .ctor(Microsoft.FSharp.Collections.FSharpList`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.Tokenization.FSharpToken: Boolean IsCommentTrivia FSharp.Compiler.Tokenization.FSharpToken: Boolean IsIdentifier FSharp.Compiler.Tokenization.FSharpToken: Boolean IsKeyword diff --git a/tests/FSharp.Compiler.Service.Tests/HashIfExpression.fs b/tests/FSharp.Compiler.Service.Tests/HashIfExpression.fs index 68015d13271..4bbf2c5fb41 100644 --- a/tests/FSharp.Compiler.Service.Tests/HashIfExpression.fs +++ b/tests/FSharp.Compiler.Service.Tests/HashIfExpression.fs @@ -66,7 +66,7 @@ type public HashIfExpression() = DiagnosticsThreadStatics.DiagnosticsLogger <- diagnosticsLogger let parser (s : string) = - let lexbuf = LexBuffer.FromChars (true, LanguageVersion.Default, None, s.ToCharArray ()) + let lexbuf = LexBuffer.FromChars (true, LanguageVersion.Default, s.ToCharArray ()) lexbuf.StartPos <- startPos lexbuf.EndPos <- startPos let tokenStream = PPLexer.tokenstream args diff --git a/tests/FSharp.Compiler.Service.Tests/PatternMatchCompilationTests.fs b/tests/FSharp.Compiler.Service.Tests/PatternMatchCompilationTests.fs index f3c31f000da..8aa15e83899 100644 --- a/tests/FSharp.Compiler.Service.Tests/PatternMatchCompilationTests.fs +++ b/tests/FSharp.Compiler.Service.Tests/PatternMatchCompilationTests.fs @@ -551,7 +551,7 @@ let z as "(14,6--14,8): Expecting pattern"; "(15,13--15,14): Unexpected symbol '=' in pattern. Expected ')' or other token."; "(15,9--15,10): Unmatched '('"; - "(16,0--16,3): Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (15:1). Try indenting this further. To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7."; + "(16,0--16,3): Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (15:1). Try indenting this further."; "(17,16--17,17): Unexpected identifier in pattern. Expected '(' or other token."; "(19,6--19,8): Expecting pattern"; "(20,0--20,0): Incomplete structured construct at or before this point in binding. Expected '=' or other token."; @@ -688,11 +688,11 @@ let z as = "(14,8--14,10): Unexpected keyword 'as' in binding"; "(15,8--15,10): Unexpected keyword 'as' in pattern. Expected ')' or other token."; "(15,6--15,7): Unmatched '('"; - "(16,0--16,3): Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (15:1). Try indenting this further. To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7."; + "(16,0--16,3): Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (15:1). Try indenting this further."; "(16,0--16,3): Unexpected keyword 'let' or 'use' in binding. Expected incomplete structured construct at or before this point or other token."; "(15,0--15,3): Incomplete value or function definition. If this is in an expression, the body of the expression must be indented to the same column as the 'let' keyword."; "(17,0--17,3): Incomplete structured construct at or before this point in implementation file"; - "(20,0--20,0): Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (19:1). Try indenting this further. To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7."; + "(20,0--20,0): Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (19:1). Try indenting this further."; "(3,13--3,17): This expression was expected to have type 'int' but here has type 'bool'"; "(3,4--3,10): Incomplete pattern matches on this expression. For example, the value '0' may indicate a case not covered by the pattern(s)."; "(4,16--4,17): This expression was expected to have type 'bool' but here has type 'int'"; @@ -875,7 +875,7 @@ let :? z as "(14,9--14,11): Expecting pattern"; "(15,16--15,17): Unexpected symbol '=' in pattern. Expected ')' or other token."; "(15,12--15,13): Unmatched '('"; - "(16,0--16,3): Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (15:1). Try indenting this further. To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7."; + "(16,0--16,3): Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (15:1). Try indenting this further."; "(17,19--17,20): Unexpected identifier in pattern. Expected '(' or other token."; "(19,9--19,11): Expecting pattern"; "(20,0--20,0): Incomplete structured construct at or before this point in binding. Expected '=' or other token."; @@ -1092,13 +1092,13 @@ let as :? z = "(15,13--15,15): Unexpected keyword 'as' in pattern. Expected '(' or other token."; "(16,8--16,10): Unexpected keyword 'as' in pattern. Expected ')' or other token."; "(16,6--16,7): Unmatched '('"; - "(17,0--17,3): Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (16:1). Try indenting this further. To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7."; + "(17,0--17,3): Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (16:1). Try indenting this further."; "(17,0--17,3): Unexpected keyword 'let' or 'use' in binding. Expected incomplete structured construct at or before this point or other token."; "(16,0--16,3): Incomplete value or function definition. If this is in an expression, the body of the expression must be indented to the same column as the 'let' keyword."; "(17,8--17,10): Unexpected keyword 'as' in pattern. Expected ']' or other token."; - "(18,0--18,3): Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (17:1). Try indenting this further. To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7."; - "(19,0--19,3): Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (18:1). Try indenting this further. To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7."; - "(20,0--20,0): Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (19:1). Try indenting this further. To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7."; + "(18,0--18,3): Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (17:1). Try indenting this further."; + "(19,0--19,3): Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (18:1). Try indenting this further."; + "(20,0--20,0): Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (19:1). Try indenting this further."; "(3,12--3,13): The type 'a' is not defined."; "(3,9--3,13): The type 'int' does not have any proper subtypes and cannot be used as the source of a type test or runtime coercion."; "(4,15--4,16): The type 'b' is not defined."; diff --git a/tests/FSharp.Compiler.Service.Tests/TokenizerTests.fs b/tests/FSharp.Compiler.Service.Tests/TokenizerTests.fs index 48dd529b2af..566dc150ce7 100644 --- a/tests/FSharp.Compiler.Service.Tests/TokenizerTests.fs +++ b/tests/FSharp.Compiler.Service.Tests/TokenizerTests.fs @@ -16,7 +16,7 @@ let rec parseLine(line: string, state: FSharpTokenizerLexState ref, tokenizer: F state.Value <- nstate } let tokenizeLines (lines:string[]) = - let sourceTok = FSharpSourceTokenizer([], Some "C:\\test.fsx", None, None) + let sourceTok = FSharpSourceTokenizer([], Some "C:\\test.fsx", None) [ let state = ref FSharpTokenizerLexState.Initial for n, line in lines |> Seq.zip [ 0 .. lines.Length-1 ] do @@ -26,7 +26,7 @@ let tokenizeLines (lines:string[]) = /// Scans every token of a (possibly multi-line) source using a single line tokenizer, /// threading the lex state across embedded newlines (column index resets at each newline). let scanTokens (defines: string list) (source: string) = - let sourceTok = FSharpSourceTokenizer(defines, Some "C:\\test.fsx", None, None) + let sourceTok = FSharpSourceTokenizer(defines, Some "C:\\test.fsx", None) let tokenizer = sourceTok.CreateLineTokenizer(source) let rec loop (state: FSharpTokenizerLexState) acc = match tokenizer.ScanToken(state) with @@ -220,7 +220,7 @@ let ``Tokenizer test - single-line nested string interpolation``() = [] let ``Tokenizer test - elif directive produces HASH_ELIF token``() = let defines = ["DEBUG"] - let sourceTok = FSharpSourceTokenizer(defines, Some "C:\\test.fsx", None, None) + let sourceTok = FSharpSourceTokenizer(defines, Some "C:\\test.fsx", None) let lines = [| "#if DEBUG" "let x = 1" diff --git a/tests/FSharp.Compiler.Service.Tests/expected-help-output.bsl b/tests/FSharp.Compiler.Service.Tests/expected-help-output.bsl index bbcf59bb8f5..134e6313ab8 100644 --- a/tests/FSharp.Compiler.Service.Tests/expected-help-output.bsl +++ b/tests/FSharp.Compiler.Service.Tests/expected-help-output.bsl @@ -128,9 +128,6 @@ default) --define: Define conditional compilation symbols (Short form: -d) ---strict-indentation[+|-] Override indentation rules implied - by the language version (off by - default) --always-inline[+|-] Always inline 'inline' functions diff --git a/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/CompilerServiceBenchmarks.fs b/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/CompilerServiceBenchmarks.fs index aa7f623cad0..912ed142b5a 100644 --- a/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/CompilerServiceBenchmarks.fs +++ b/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/CompilerServiceBenchmarks.fs @@ -84,7 +84,6 @@ type CompilerServiceBenchmarks() = LangVersionText = "default" IsInteractive = false ApplyLineDirectives = false - StrictIndentation = None CompilingFSharpCore = false IsExe = false } diff --git a/tests/fsharp/Compiler/Language/StringInterpolation.fs b/tests/fsharp/Compiler/Language/StringInterpolation.fs index eade5119a44..05f0956081a 100644 --- a/tests/fsharp/Compiler/Language/StringInterpolation.fs +++ b/tests/fsharp/Compiler/Language/StringInterpolation.fs @@ -813,7 +813,7 @@ let TripleInterpolatedInVerbatimInterpolated = $\"123{456}789{$\"\"\"012\"\"\"}3 CompilerAssert.TypeCheckWithErrorsAndOptions [| "--langversion:8.0" |] code [|(FSharpDiagnosticSeverity.Error, 58, (1, 1, 1, 17), - "Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (1:1). Try indenting this further.\nTo continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7."); + "Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (1:1). Try indenting this further."); (FSharpDiagnosticSeverity.Error, 10, (1, 1, 1, 17), "Incomplete structured construct at or before this point in binding"); (FSharpDiagnosticSeverity.Error, 3381, (1, 10, 1, 14), diff --git a/tests/fsharp/typecheck/sigs/neg114.bsl b/tests/fsharp/typecheck/sigs/neg114.bsl index d75d2a8c5ff..8b114a975d0 100644 --- a/tests/fsharp/typecheck/sigs/neg114.bsl +++ b/tests/fsharp/typecheck/sigs/neg114.bsl @@ -4,10 +4,8 @@ neg114.fs(6,38,6,39): parse error FS0010: Unexpected symbol '}' in binding. Expe neg114.fs(6,29,6,31): parse error FS0605: Unmatched '{|' neg114.fs(8,5,8,8): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (6:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg114.fs(10,5,10,9): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (8:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg114.fs(10,5,10,9): parse error FS0010: Unexpected keyword 'type' in binding. Expected incomplete structured construct at or before this point or other token. diff --git a/tests/fsharp/typecheck/sigs/neg114.vsbsl b/tests/fsharp/typecheck/sigs/neg114.vsbsl index ba9c3df9c9b..ae7af779861 100644 --- a/tests/fsharp/typecheck/sigs/neg114.vsbsl +++ b/tests/fsharp/typecheck/sigs/neg114.vsbsl @@ -4,10 +4,8 @@ neg114.fs(6,38,6,39): parse error FS0010: Unexpected symbol '}' in binding. Expe neg114.fs(6,29,6,31): parse error FS0605: Unmatched '{|' neg114.fs(8,5,8,8): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (6:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg114.fs(10,5,10,9): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (8:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg114.fs(10,5,10,9): parse error FS0010: Unexpected keyword 'type' in binding. Expected incomplete structured construct at or before this point or other token. diff --git a/tests/fsharp/typecheck/sigs/neg69.bsl b/tests/fsharp/typecheck/sigs/neg69.bsl index bce5b5cb823..c578bb87bca 100644 --- a/tests/fsharp/typecheck/sigs/neg69.bsl +++ b/tests/fsharp/typecheck/sigs/neg69.bsl @@ -4,93 +4,63 @@ neg69.fsx(88,43,88,44): parse error FS1241: Expected type argument or static arg neg69.fsx(88,44,88,45): parse error FS0010: Unexpected symbol '>' in type definition. Expected '=' or other token. neg69.fsx(94,5,94,8): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (93:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(94,5,94,8): parse error FS0010: Unexpected keyword 'let' or 'use' in implementation file neg69.fsx(95,5,95,8): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (94:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(96,5,96,8): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (95:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(98,5,98,11): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (96:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(98,19,98,20): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (96:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(99,5,99,11): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (96:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(100,5,100,11): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (96:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(101,5,101,11): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (96:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(102,5,102,11): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (96:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(104,5,104,14): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (96:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(113,1,113,5): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (96:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(168,1,168,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (96:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(170,1,170,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (168:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(171,1,171,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (170:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(172,1,172,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (171:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(173,1,173,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (172:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(174,1,174,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (173:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(176,1,176,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (174:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(177,1,177,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (176:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(178,1,178,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (177:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(180,1,180,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (178:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(181,1,181,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (180:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(182,1,182,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (181:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(183,1,183,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (182:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(185,1,185,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (183:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(194,1,194,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (185:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(203,1,203,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (194:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(212,1,212,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (203:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(221,1,221,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (212:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(242,1,242,3): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (221:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. diff --git a/tests/fsharp/typecheck/sigs/neg69.vsbsl b/tests/fsharp/typecheck/sigs/neg69.vsbsl index 75e44001573..e0eea56c1d4 100644 --- a/tests/fsharp/typecheck/sigs/neg69.vsbsl +++ b/tests/fsharp/typecheck/sigs/neg69.vsbsl @@ -4,96 +4,66 @@ neg69.fsx(88,43,88,44): parse error FS1241: Expected type argument or static arg neg69.fsx(88,44,88,45): parse error FS0010: Unexpected symbol '>' in type definition. Expected '=' or other token. neg69.fsx(94,5,94,8): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (93:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(94,5,94,8): parse error FS0010: Unexpected keyword 'let' or 'use' in implementation file neg69.fsx(95,5,95,8): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (94:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(96,5,96,8): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (95:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(98,5,98,11): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (96:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(98,19,98,20): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (96:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(99,5,99,11): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (96:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(100,5,100,11): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (96:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(101,5,101,11): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (96:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(102,5,102,11): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (96:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(104,5,104,14): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (96:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(113,1,113,5): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (96:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(168,1,168,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (96:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(170,1,170,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (168:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(171,1,171,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (170:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(172,1,172,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (171:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(173,1,173,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (172:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(174,1,174,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (173:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(176,1,176,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (174:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(177,1,177,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (176:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(178,1,178,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (177:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(180,1,180,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (178:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(181,1,181,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (180:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(182,1,182,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (181:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(183,1,183,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (182:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(185,1,185,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (183:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(194,1,194,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (185:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(203,1,203,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (194:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(212,1,212,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (203:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(221,1,221,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (212:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(242,1,242,3): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (221:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg69.fsx(87,6,87,12): typecheck error FS0929: This type requires a definition diff --git a/tests/fsharp/typecheck/sigs/neg74.bsl b/tests/fsharp/typecheck/sigs/neg74.bsl index b4917792cfb..f67bcbd38bb 100644 --- a/tests/fsharp/typecheck/sigs/neg74.bsl +++ b/tests/fsharp/typecheck/sigs/neg74.bsl @@ -1,5 +1,4 @@ neg74.fsx(185,1,185,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (183:29). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg74.fsx(183,53,183,54): parse error FS3156: Unexpected token '+' or incomplete expression diff --git a/tests/fsharp/typecheck/sigs/neg74.vsbsl b/tests/fsharp/typecheck/sigs/neg74.vsbsl index b4917792cfb..f67bcbd38bb 100644 --- a/tests/fsharp/typecheck/sigs/neg74.vsbsl +++ b/tests/fsharp/typecheck/sigs/neg74.vsbsl @@ -1,5 +1,4 @@ neg74.fsx(185,1,185,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (183:29). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg74.fsx(183,53,183,54): parse error FS3156: Unexpected token '+' or incomplete expression diff --git a/tests/fsharp/typecheck/sigs/neg75.bsl b/tests/fsharp/typecheck/sigs/neg75.bsl index 11f78e08d29..3d0d6b6409c 100644 --- a/tests/fsharp/typecheck/sigs/neg75.bsl +++ b/tests/fsharp/typecheck/sigs/neg75.bsl @@ -1,5 +1,4 @@ neg75.fsx(154,24,154,27): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (153:38). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg75.fsx(153,79,153,80): parse error FS3156: Unexpected token '+' or incomplete expression diff --git a/tests/fsharp/typecheck/sigs/neg75.vsbsl b/tests/fsharp/typecheck/sigs/neg75.vsbsl index 11f78e08d29..3d0d6b6409c 100644 --- a/tests/fsharp/typecheck/sigs/neg75.vsbsl +++ b/tests/fsharp/typecheck/sigs/neg75.vsbsl @@ -1,5 +1,4 @@ neg75.fsx(154,24,154,27): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (153:38). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg75.fsx(153,79,153,80): parse error FS3156: Unexpected token '+' or incomplete expression diff --git a/tests/fsharp/typecheck/sigs/neg76.bsl b/tests/fsharp/typecheck/sigs/neg76.bsl index 4e96d3f044a..291d5f1d972 100644 --- a/tests/fsharp/typecheck/sigs/neg76.bsl +++ b/tests/fsharp/typecheck/sigs/neg76.bsl @@ -1,5 +1,4 @@ neg76.fsx(154,24,154,27): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (153:38). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg76.fsx(153,79,153,80): parse error FS3156: Unexpected token '*' or incomplete expression diff --git a/tests/fsharp/typecheck/sigs/neg76.vsbsl b/tests/fsharp/typecheck/sigs/neg76.vsbsl index 4e96d3f044a..291d5f1d972 100644 --- a/tests/fsharp/typecheck/sigs/neg76.vsbsl +++ b/tests/fsharp/typecheck/sigs/neg76.vsbsl @@ -1,5 +1,4 @@ neg76.fsx(154,24,154,27): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (153:38). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg76.fsx(153,79,153,80): parse error FS3156: Unexpected token '*' or incomplete expression diff --git a/tests/fsharp/typecheck/sigs/neg77.bsl b/tests/fsharp/typecheck/sigs/neg77.bsl index 8d21e0d775b..0faf3c89199 100644 --- a/tests/fsharp/typecheck/sigs/neg77.bsl +++ b/tests/fsharp/typecheck/sigs/neg77.bsl @@ -1,5 +1,4 @@ neg77.fsx(134,15,134,16): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (133:19). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg77.fsx(134,15,134,16): parse error FS0010: Incomplete structured construct at or before this point in expression diff --git a/tests/fsharp/typecheck/sigs/neg77.vsbsl b/tests/fsharp/typecheck/sigs/neg77.vsbsl index 536ab2db3de..a01edbb5d1e 100644 --- a/tests/fsharp/typecheck/sigs/neg77.vsbsl +++ b/tests/fsharp/typecheck/sigs/neg77.vsbsl @@ -1,6 +1,5 @@ neg77.fsx(134,15,134,16): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (133:19). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg77.fsx(134,15,134,16): parse error FS0010: Incomplete structured construct at or before this point in expression diff --git a/tests/fsharp/typecheck/sigs/neg81.bsl b/tests/fsharp/typecheck/sigs/neg81.bsl index 4e454a3c858..360ad962ff6 100644 --- a/tests/fsharp/typecheck/sigs/neg81.bsl +++ b/tests/fsharp/typecheck/sigs/neg81.bsl @@ -1,5 +1,4 @@ neg81.fsx(8,1,8,5): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (6:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg81.fsx(6,6,6,7): parse error FS3156: Unexpected token '+' or incomplete expression diff --git a/tests/fsharp/typecheck/sigs/neg81.vsbsl b/tests/fsharp/typecheck/sigs/neg81.vsbsl index 4e454a3c858..360ad962ff6 100644 --- a/tests/fsharp/typecheck/sigs/neg81.vsbsl +++ b/tests/fsharp/typecheck/sigs/neg81.vsbsl @@ -1,5 +1,4 @@ neg81.fsx(8,1,8,5): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (6:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg81.fsx(6,6,6,7): parse error FS3156: Unexpected token '+' or incomplete expression diff --git a/tests/fsharp/typecheck/sigs/neg82.bsl b/tests/fsharp/typecheck/sigs/neg82.bsl index 77e03fe479a..c63c76c0845 100644 --- a/tests/fsharp/typecheck/sigs/neg82.bsl +++ b/tests/fsharp/typecheck/sigs/neg82.bsl @@ -2,26 +2,19 @@ neg82.fsx(84,5,84,6): parse error FS0010: Unexpected symbol '|' in expression neg82.fsx(88,1,88,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (81:9). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg82.fsx(90,5,90,8): parse error FS0010: Incomplete structured construct at or before this point in expression. Expected incomplete structured construct at or before this point or other token. neg82.fsx(95,1,95,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (88:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg82.fsx(95,1,95,4): parse error FS0010: Unexpected keyword 'let' or 'use' in implementation file neg82.fsx(96,1,96,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (95:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg82.fsx(97,1,97,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (96:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg82.fsx(100,1,100,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (97:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg82.fsx(102,1,102,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (100:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg82.fsx(138,1,138,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (102:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. diff --git a/tests/fsharp/typecheck/sigs/neg82.vsbsl b/tests/fsharp/typecheck/sigs/neg82.vsbsl index af56fd45ac2..c0d5efe68ea 100644 --- a/tests/fsharp/typecheck/sigs/neg82.vsbsl +++ b/tests/fsharp/typecheck/sigs/neg82.vsbsl @@ -2,29 +2,22 @@ neg82.fsx(84,5,84,6): parse error FS0010: Unexpected symbol '|' in expression neg82.fsx(88,1,88,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (81:9). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg82.fsx(90,5,90,8): parse error FS0010: Incomplete structured construct at or before this point in expression. Expected incomplete structured construct at or before this point or other token. neg82.fsx(95,1,95,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (88:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg82.fsx(95,1,95,4): parse error FS0010: Unexpected keyword 'let' or 'use' in implementation file neg82.fsx(96,1,96,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (95:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg82.fsx(97,1,97,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (96:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg82.fsx(100,1,100,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (97:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg82.fsx(102,1,102,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (100:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg82.fsx(138,1,138,4): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (102:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg82.fsx(76,11,76,13): typecheck error FS0025: Incomplete pattern matches on this expression. For example, the value 'Horizontal (_, _)' may indicate a case not covered by the pattern(s). diff --git a/tests/fsharp/typecheck/sigs/neg83.bsl b/tests/fsharp/typecheck/sigs/neg83.bsl index b8858cfbe11..ebeb901c96b 100644 --- a/tests/fsharp/typecheck/sigs/neg83.bsl +++ b/tests/fsharp/typecheck/sigs/neg83.bsl @@ -2,9 +2,7 @@ neg83.fsx(10,5,10,6): parse error FS0010: Unexpected symbol '|' in expression neg83.fsx(13,1,13,2): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:4). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg83.fsx(13,2,13,5): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:4). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg83.fsx(16,1,16,1): parse error FS0010: Incomplete structured construct at or before this point in expression diff --git a/tests/fsharp/typecheck/sigs/neg83.vsbsl b/tests/fsharp/typecheck/sigs/neg83.vsbsl index 84ee39a23f5..fc217b74fe9 100644 --- a/tests/fsharp/typecheck/sigs/neg83.vsbsl +++ b/tests/fsharp/typecheck/sigs/neg83.vsbsl @@ -2,10 +2,8 @@ neg83.fsx(10,5,10,6): parse error FS0010: Unexpected symbol '|' in expression neg83.fsx(13,1,13,2): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:4). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg83.fsx(13,2,13,5): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:4). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg83.fsx(16,1,16,1): parse error FS0010: Incomplete structured construct at or before this point in expression diff --git a/tests/fsharp/typecheck/sigs/neg_anon_2.bsl b/tests/fsharp/typecheck/sigs/neg_anon_2.bsl index b8c33cdb475..b74cd93bed4 100644 --- a/tests/fsharp/typecheck/sigs/neg_anon_2.bsl +++ b/tests/fsharp/typecheck/sigs/neg_anon_2.bsl @@ -4,10 +4,8 @@ neg_anon_2.fs(6,38,6,39): parse error FS0010: Unexpected symbol '}' in binding. neg_anon_2.fs(6,29,6,31): parse error FS0605: Unmatched '{|' neg_anon_2.fs(8,5,8,8): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (6:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg_anon_2.fs(10,5,10,9): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (8:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg_anon_2.fs(10,5,10,9): parse error FS0010: Unexpected keyword 'type' in binding. Expected incomplete structured construct at or before this point or other token. diff --git a/tests/fsharp/typecheck/sigs/neg_anon_2.vsbsl b/tests/fsharp/typecheck/sigs/neg_anon_2.vsbsl index ca4db6fcfb7..eb34b56bd1f 100644 --- a/tests/fsharp/typecheck/sigs/neg_anon_2.vsbsl +++ b/tests/fsharp/typecheck/sigs/neg_anon_2.vsbsl @@ -4,10 +4,8 @@ neg_anon_2.fs(6,38,6,39): parse error FS0010: Unexpected symbol '}' in binding. neg_anon_2.fs(6,29,6,31): parse error FS0605: Unmatched '{|' neg_anon_2.fs(8,5,8,8): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (6:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg_anon_2.fs(10,5,10,9): parse error FS0058: Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (8:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. neg_anon_2.fs(10,5,10,9): parse error FS0010: Unexpected keyword 'type' in binding. Expected incomplete structured construct at or before this point or other token. diff --git a/tests/service/data/SyntaxTree/Expression/Binary - Plus 02.fs.bsl b/tests/service/data/SyntaxTree/Expression/Binary - Plus 02.fs.bsl index 145364c43c1..c94a546574d 100644 --- a/tests/service/data/SyntaxTree/Expression/Binary - Plus 02.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Binary - Plus 02.fs.bsl @@ -23,5 +23,4 @@ ImplFile CodeComments = [] }, set [])) (4,0)-(4,0) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (3:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (3,2)-(3,3) parse error Unexpected token '+' or incomplete expression diff --git a/tests/service/data/SyntaxTree/Expression/Binary - Plus 05.fs.bsl b/tests/service/data/SyntaxTree/Expression/Binary - Plus 05.fs.bsl index 6deea904868..e36078f80cc 100644 --- a/tests/service/data/SyntaxTree/Expression/Binary - Plus 05.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Binary - Plus 05.fs.bsl @@ -34,5 +34,4 @@ ImplFile CodeComments = [] }, set [])) (6,0)-(6,1) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (4,6)-(4,7) parse error Unexpected token '+' or incomplete expression diff --git a/tests/service/data/SyntaxTree/Expression/Do 03.fs.bsl b/tests/service/data/SyntaxTree/Expression/Do 03.fs.bsl index 4dacefd20d5..7b0614023db 100644 --- a/tests/service/data/SyntaxTree/Expression/Do 03.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Do 03.fs.bsl @@ -26,5 +26,4 @@ ImplFile CodeComments = [] }, set [])) (6,0)-(6,1) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (3:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (4,6)-(4,6) parse error Expecting expression diff --git a/tests/service/data/SyntaxTree/Expression/Downcast 01.fs.bsl b/tests/service/data/SyntaxTree/Expression/Downcast 01.fs.bsl index e090f188cc3..f20132e9a61 100644 --- a/tests/service/data/SyntaxTree/Expression/Downcast 01.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Downcast 01.fs.bsl @@ -13,5 +13,4 @@ ImplFile CodeComments = [] }, set [])) (4,0)-(4,0) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (3:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (4,0)-(4,0) parse error Incomplete structured construct at or before this point in expression diff --git a/tests/service/data/SyntaxTree/Expression/For 03.fs.bsl b/tests/service/data/SyntaxTree/Expression/For 03.fs.bsl index 1dcae506443..bf587abbeb5 100644 --- a/tests/service/data/SyntaxTree/Expression/For 03.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/For 03.fs.bsl @@ -28,5 +28,4 @@ ImplFile CodeComments = [] }, set [])) (6,0)-(6,1) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (6,0)-(6,1) parse error Incomplete structured construct at or before this point in expression diff --git a/tests/service/data/SyntaxTree/Expression/If 05.fs.bsl b/tests/service/data/SyntaxTree/Expression/If 05.fs.bsl index b890559871b..eb42079eec0 100644 --- a/tests/service/data/SyntaxTree/Expression/If 05.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/If 05.fs.bsl @@ -21,5 +21,4 @@ ImplFile CodeComments = [] }, set [])) (5,0)-(5,1) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (3:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (5,0)-(5,1) parse error Expecting expression diff --git a/tests/service/data/SyntaxTree/Expression/If 06.fs.bsl b/tests/service/data/SyntaxTree/Expression/If 06.fs.bsl index e1d1405077e..7c5b1a9491c 100644 --- a/tests/service/data/SyntaxTree/Expression/If 06.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/If 06.fs.bsl @@ -27,5 +27,4 @@ ImplFile CodeComments = [] }, set [])) (6,0)-(6,4) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (6,0)-(6,4) parse error Expecting expression diff --git a/tests/service/data/SyntaxTree/Expression/If 10.fs.bsl b/tests/service/data/SyntaxTree/Expression/If 10.fs.bsl index edf40c04710..ebf20412664 100644 --- a/tests/service/data/SyntaxTree/Expression/If 10.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/If 10.fs.bsl @@ -33,5 +33,4 @@ ImplFile CodeComments = [] }, set [])) (6,0)-(6,1) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (6,0)-(6,1) parse error Expecting expression diff --git a/tests/service/data/SyntaxTree/Expression/If 11.fs.bsl b/tests/service/data/SyntaxTree/Expression/If 11.fs.bsl index 905054b3f44..1fb569378ca 100644 --- a/tests/service/data/SyntaxTree/Expression/If 11.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/If 11.fs.bsl @@ -37,6 +37,5 @@ ImplFile CodeComments = [] }, set [])) (6,4)-(6,5) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (4,12)-(4,14) parse error Unexpected token '&&' or incomplete expression (4,4)-(4,6) parse error Incomplete conditional. Expected 'if then ' or 'if then else '. diff --git a/tests/service/data/SyntaxTree/Expression/If 12.fs.bsl b/tests/service/data/SyntaxTree/Expression/If 12.fs.bsl index 42d610056cb..0138af46bc4 100644 --- a/tests/service/data/SyntaxTree/Expression/If 12.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/If 12.fs.bsl @@ -33,6 +33,5 @@ ImplFile CodeComments = [] }, set [])) (6,0)-(6,1) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (4,12)-(4,14) parse error Unexpected token '&&' or incomplete expression (4,4)-(4,6) parse error Incomplete conditional. Expected 'if then ' or 'if then else '. diff --git a/tests/service/data/SyntaxTree/Expression/If 14.fs.bsl b/tests/service/data/SyntaxTree/Expression/If 14.fs.bsl index 6a79bb6b7ae..42f6bf18770 100644 --- a/tests/service/data/SyntaxTree/Expression/If 14.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/If 14.fs.bsl @@ -37,6 +37,5 @@ ImplFile CodeComments = [] }, set [])) (6,4)-(6,5) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (4,12)-(4,14) parse error Unexpected token '==' or incomplete expression (4,4)-(4,6) parse error Incomplete conditional. Expected 'if then ' or 'if then else '. diff --git a/tests/service/data/SyntaxTree/Expression/Lambda - Missing expr 02.fs.bsl b/tests/service/data/SyntaxTree/Expression/Lambda - Missing expr 02.fs.bsl index db52b133a52..d8985f3c700 100644 --- a/tests/service/data/SyntaxTree/Expression/Lambda - Missing expr 02.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Lambda - Missing expr 02.fs.bsl @@ -22,5 +22,4 @@ ImplFile CodeComments = [] }, set [])) (4,0)-(4,0) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (1:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (3,0)-(3,8) parse error Missing function body diff --git a/tests/service/data/SyntaxTree/Expression/Lazy 03.fs.bsl b/tests/service/data/SyntaxTree/Expression/Lazy 03.fs.bsl index 50283d947be..712cdb177e8 100644 --- a/tests/service/data/SyntaxTree/Expression/Lazy 03.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Lazy 03.fs.bsl @@ -26,5 +26,4 @@ ImplFile CodeComments = [] }, set [])) (6,0)-(6,1) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (6,0)-(6,1) parse error Expecting expression diff --git a/tests/service/data/SyntaxTree/Expression/Let 02.fs.bsl b/tests/service/data/SyntaxTree/Expression/Let 02.fs.bsl index 79a7938b21c..16cd84421d7 100644 --- a/tests/service/data/SyntaxTree/Expression/Let 02.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Let 02.fs.bsl @@ -24,5 +24,4 @@ ImplFile CodeComments = [] }, set [])) (5,0)-(5,1) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (3:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (5,0)-(5,1) parse error Incomplete structured construct at or before this point in binding diff --git a/tests/service/data/SyntaxTree/Expression/Object - Class 11.fs.bsl b/tests/service/data/SyntaxTree/Expression/Object - Class 11.fs.bsl index eeb2063d6ac..af95daa6366 100644 --- a/tests/service/data/SyntaxTree/Expression/Object - Class 11.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Object - Class 11.fs.bsl @@ -63,5 +63,4 @@ ImplFile CodeComments = [] }, set [])) (5,5)-(5,11) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:6). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (5,5)-(5,11) parse error Expecting expression diff --git a/tests/service/data/SyntaxTree/Expression/Set 04.fs.bsl b/tests/service/data/SyntaxTree/Expression/Set 04.fs.bsl index 2224bb7089a..6354b107bfb 100644 --- a/tests/service/data/SyntaxTree/Expression/Set 04.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Set 04.fs.bsl @@ -27,5 +27,4 @@ ImplFile CodeComments = [] }, set [])) (6,0)-(6,1) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (6,0)-(6,1) parse error Expecting expression diff --git a/tests/service/data/SyntaxTree/Expression/Try - Finally 04.fs.bsl b/tests/service/data/SyntaxTree/Expression/Try - Finally 04.fs.bsl index 9a3f520f603..5329d9bc147 100644 --- a/tests/service/data/SyntaxTree/Expression/Try - Finally 04.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Try - Finally 04.fs.bsl @@ -31,5 +31,4 @@ ImplFile CodeComments = [] }, set [])) (7,0)-(7,1) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (7,0)-(7,1) parse error Expecting expression diff --git a/tests/service/data/SyntaxTree/Expression/Try - With 04.fs.bsl b/tests/service/data/SyntaxTree/Expression/Try - With 04.fs.bsl index eb43b43e8ef..963a8538740 100644 --- a/tests/service/data/SyntaxTree/Expression/Try - With 04.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Try - With 04.fs.bsl @@ -36,5 +36,4 @@ ImplFile CodeComments = [] }, set [])) (7,0)-(7,1) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (7,0)-(7,1) parse error Incomplete structured construct at or before this point in pattern matching diff --git a/tests/service/data/SyntaxTree/Expression/Try - With 06.fs.bsl b/tests/service/data/SyntaxTree/Expression/Try - With 06.fs.bsl index e07b5e0d1d7..5d7a2825d27 100644 --- a/tests/service/data/SyntaxTree/Expression/Try - With 06.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Try - With 06.fs.bsl @@ -29,5 +29,4 @@ ImplFile CodeComments = [] }, set [])) (7,0)-(7,1) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (7,0)-(7,1) parse error Incomplete structured construct at or before this point in expression diff --git a/tests/service/data/SyntaxTree/Expression/Try 02.fs.bsl b/tests/service/data/SyntaxTree/Expression/Try 02.fs.bsl index 9c2a801dc89..381de96e340 100644 --- a/tests/service/data/SyntaxTree/Expression/Try 02.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Try 02.fs.bsl @@ -30,5 +30,4 @@ ImplFile CodeComments = [] }, set [])) (6,0)-(6,1) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (6,0)-(6,1) parse error Expecting expression diff --git a/tests/service/data/SyntaxTree/Expression/Try with - Missing expr 02.fs.bsl b/tests/service/data/SyntaxTree/Expression/Try with - Missing expr 02.fs.bsl index 0ee1ddcecc9..d206b782c0a 100644 --- a/tests/service/data/SyntaxTree/Expression/Try with - Missing expr 02.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Try with - Missing expr 02.fs.bsl @@ -24,6 +24,5 @@ ImplFile CodeComments = [] }, set [])) (5,0)-(5,0) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (3:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (5,0)-(5,0) parse error Incomplete structured construct at or before this point in pattern matching (4,0)-(4,4) parse error Expecting expression diff --git a/tests/service/data/SyntaxTree/Expression/Try with - Missing expr 03.fs.bsl b/tests/service/data/SyntaxTree/Expression/Try with - Missing expr 03.fs.bsl index 7fe035f2d55..d2caf41ea24 100644 --- a/tests/service/data/SyntaxTree/Expression/Try with - Missing expr 03.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Try with - Missing expr 03.fs.bsl @@ -19,5 +19,4 @@ ImplFile CodeComments = [] }, set [])) (4,0)-(4,0) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (3:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (4,0)-(4,0) parse error Expecting expression diff --git a/tests/service/data/SyntaxTree/Expression/Tuple - Missing item 08.fs.bsl b/tests/service/data/SyntaxTree/Expression/Tuple - Missing item 08.fs.bsl index 4626a7a68a3..eee88a85afd 100644 --- a/tests/service/data/SyntaxTree/Expression/Tuple - Missing item 08.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Tuple - Missing item 08.fs.bsl @@ -20,6 +20,5 @@ ImplFile CodeComments = [] }, set [])) (4,0)-(4,0) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (1:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (3,2)-(3,3) parse error Expected an expression after this point (3,0)-(3,1) parse error Unmatched '(' diff --git a/tests/service/data/SyntaxTree/Expression/Tuple - Missing item 10.fs.bsl b/tests/service/data/SyntaxTree/Expression/Tuple - Missing item 10.fs.bsl index 2595dd0fc1a..c763b94b616 100644 --- a/tests/service/data/SyntaxTree/Expression/Tuple - Missing item 10.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Tuple - Missing item 10.fs.bsl @@ -28,5 +28,4 @@ ImplFile CodeComments = [] }, set [])) (4,0)-(4,0) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (3:9). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (3,9)-(3,10) parse error Expected an expression after this point diff --git a/tests/service/data/SyntaxTree/Expression/Upcast 01.fs.bsl b/tests/service/data/SyntaxTree/Expression/Upcast 01.fs.bsl index 3a61bc5ca0e..1e1e97f753e 100644 --- a/tests/service/data/SyntaxTree/Expression/Upcast 01.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Upcast 01.fs.bsl @@ -13,5 +13,4 @@ ImplFile CodeComments = [] }, set [])) (4,0)-(4,0) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (3:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (4,0)-(4,0) parse error Incomplete structured construct at or before this point in expression diff --git a/tests/service/data/SyntaxTree/Expression/Upcast 04.fs.bsl b/tests/service/data/SyntaxTree/Expression/Upcast 04.fs.bsl index ea64ddbe559..1398f23dee9 100644 --- a/tests/service/data/SyntaxTree/Expression/Upcast 04.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Upcast 04.fs.bsl @@ -15,5 +15,4 @@ ImplFile CodeComments = [] }, set [])) (5,0)-(5,1) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (5,0)-(5,1) parse error Incomplete structured construct at or before this point in expression diff --git a/tests/service/data/SyntaxTree/Expression/Upcast 05.fs.bsl b/tests/service/data/SyntaxTree/Expression/Upcast 05.fs.bsl index 78cddea4a93..c881b8e0362 100644 --- a/tests/service/data/SyntaxTree/Expression/Upcast 05.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/Upcast 05.fs.bsl @@ -14,5 +14,4 @@ ImplFile CodeComments = [] }, set [])) (5,0)-(5,1) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (5,0)-(5,1) parse error Incomplete structured construct at or before this point in expression diff --git a/tests/service/data/SyntaxTree/Expression/While 03.fs.bsl b/tests/service/data/SyntaxTree/Expression/While 03.fs.bsl index 388e60dbb47..5385322d7ea 100644 --- a/tests/service/data/SyntaxTree/Expression/While 03.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/While 03.fs.bsl @@ -26,5 +26,4 @@ ImplFile CodeComments = [] }, set [])) (6,0)-(6,1) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (6,0)-(6,1) parse error Incomplete structured construct at or before this point in expression diff --git a/tests/service/data/SyntaxTree/Expression/While 04.fs.bsl b/tests/service/data/SyntaxTree/Expression/While 04.fs.bsl index cb31897188d..ecdba40ba92 100644 --- a/tests/service/data/SyntaxTree/Expression/While 04.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/While 04.fs.bsl @@ -25,5 +25,4 @@ ImplFile CodeComments = [] }, set [])) (5,0)-(5,0) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (5,0)-(5,0) parse error Incomplete structured construct at or before this point in expression diff --git a/tests/service/data/SyntaxTree/Expression/WhileBang 03.fs.bsl b/tests/service/data/SyntaxTree/Expression/WhileBang 03.fs.bsl index c9ce876b390..eceeb3dc1c8 100644 --- a/tests/service/data/SyntaxTree/Expression/WhileBang 03.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/WhileBang 03.fs.bsl @@ -35,5 +35,4 @@ ImplFile CodeComments = [] }, set [])) (6,0)-(6,1) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (6,0)-(6,1) parse error Incomplete structured construct at or before this point in expression diff --git a/tests/service/data/SyntaxTree/Expression/WhileBang 04.fs.bsl b/tests/service/data/SyntaxTree/Expression/WhileBang 04.fs.bsl index 90038fb639e..e83fa41d384 100644 --- a/tests/service/data/SyntaxTree/Expression/WhileBang 04.fs.bsl +++ b/tests/service/data/SyntaxTree/Expression/WhileBang 04.fs.bsl @@ -34,5 +34,4 @@ ImplFile CodeComments = [] }, set [])) (5,0)-(5,0) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (5,0)-(5,0) parse error Incomplete structured construct at or before this point in expression diff --git a/tests/service/data/SyntaxTree/IfThenElse/Comment after else 02.fs.bsl b/tests/service/data/SyntaxTree/IfThenElse/Comment after else 02.fs.bsl index d3974f75b62..00c9bdae95d 100644 --- a/tests/service/data/SyntaxTree/IfThenElse/Comment after else 02.fs.bsl +++ b/tests/service/data/SyntaxTree/IfThenElse/Comment after else 02.fs.bsl @@ -21,9 +21,7 @@ ImplFile CodeComments = [BlockComment (3,5--3,33)] }, set [])) (2,0)-(2,1) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (1:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (2,0)-(2,1) parse error Expecting expression (3,0)-(3,36) parse error Unexpected keyword 'elif' in implementation file (4,0)-(4,1) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (3:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (1,0)-(2,0) parse warning The declarations in this file will be placed in an implicit module 'Comment after else 02' based on the file name 'Comment after else 02.fs'. However this is not a valid F# identifier, so the contents will not be accessible from other files. Consider renaming the file or adding a 'module' or 'namespace' declaration at the top of the file. diff --git a/tests/service/data/SyntaxTree/MatchClause/Missing expr 02.fs.bsl b/tests/service/data/SyntaxTree/MatchClause/Missing expr 02.fs.bsl index ad4bd5152d4..abc42c4ee26 100644 --- a/tests/service/data/SyntaxTree/MatchClause/Missing expr 02.fs.bsl +++ b/tests/service/data/SyntaxTree/MatchClause/Missing expr 02.fs.bsl @@ -22,5 +22,4 @@ ImplFile CodeComments = [] }, set [])) (5,0)-(5,0) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (3:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (5,0)-(5,0) parse error Incomplete structured construct at or before this point in pattern matching diff --git a/tests/service/data/SyntaxTree/MatchClause/Missing expr 05.fs.bsl b/tests/service/data/SyntaxTree/MatchClause/Missing expr 05.fs.bsl index f84c19d5a60..877848c740b 100644 --- a/tests/service/data/SyntaxTree/MatchClause/Missing expr 05.fs.bsl +++ b/tests/service/data/SyntaxTree/MatchClause/Missing expr 05.fs.bsl @@ -33,5 +33,4 @@ ImplFile CodeComments = [] }, set [])) (7,0)-(7,1) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (7,0)-(7,1) parse error Incomplete structured construct at or before this point in pattern matching diff --git a/tests/service/data/SyntaxTree/Member/Abstract - Property 03.fs.bsl b/tests/service/data/SyntaxTree/Member/Abstract - Property 03.fs.bsl index 2ac250de233..07d51906c13 100644 --- a/tests/service/data/SyntaxTree/Member/Abstract - Property 03.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Abstract - Property 03.fs.bsl @@ -44,5 +44,4 @@ ImplFile CodeComments = [] }, set [])) (6,0)-(6,1) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (6,0)-(6,1) parse error Incomplete structured construct at or before this point in property definition. Expected identifier, '(', '(*)' or other token. diff --git a/tests/service/data/SyntaxTree/Member/Abstract - Property 04.fs.bsl b/tests/service/data/SyntaxTree/Member/Abstract - Property 04.fs.bsl index a208af54581..e9388ad2eca 100644 --- a/tests/service/data/SyntaxTree/Member/Abstract - Property 04.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Abstract - Property 04.fs.bsl @@ -43,5 +43,4 @@ ImplFile CodeComments = [] }, set [])) (6,0)-(6,1) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (4,20)-(4,24) parse error Identifier expected diff --git a/tests/service/data/SyntaxTree/Member/Abstract - Property 05.fs.bsl b/tests/service/data/SyntaxTree/Member/Abstract - Property 05.fs.bsl index 6ad8da57115..453337e9c1d 100644 --- a/tests/service/data/SyntaxTree/Member/Abstract - Property 05.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Abstract - Property 05.fs.bsl @@ -63,5 +63,4 @@ ImplFile CodeComments = [] }, set [])) (5,4)-(5,12) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (4,21)-(4,25) parse error Identifier expected diff --git a/tests/service/data/SyntaxTree/Member/Auto property 02.fs.bsl b/tests/service/data/SyntaxTree/Member/Auto property 02.fs.bsl index cd6d84a1903..cea938842b8 100644 --- a/tests/service/data/SyntaxTree/Member/Auto property 02.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Auto property 02.fs.bsl @@ -46,5 +46,4 @@ ImplFile CodeComments = [] }, set [])) (6,0)-(6,1) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (6,0)-(6,1) parse error Expecting expression diff --git a/tests/service/data/SyntaxTree/Member/Auto property 03.fs.bsl b/tests/service/data/SyntaxTree/Member/Auto property 03.fs.bsl index 499e1c4c6ec..80d0d805119 100644 --- a/tests/service/data/SyntaxTree/Member/Auto property 03.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Auto property 03.fs.bsl @@ -68,5 +68,4 @@ ImplFile CodeComments = [] }, set [])) (5,4)-(5,10) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (5,4)-(5,10) parse error Expecting expression diff --git a/tests/service/data/SyntaxTree/Member/Auto property 08.fs.bsl b/tests/service/data/SyntaxTree/Member/Auto property 08.fs.bsl index eff63393708..5f1a9c86844 100644 --- a/tests/service/data/SyntaxTree/Member/Auto property 08.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Auto property 08.fs.bsl @@ -45,5 +45,4 @@ ImplFile CodeComments = [] }, set [])) (6,0)-(6,1) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:22). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (6,0)-(6,1) parse error Incomplete structured construct at or before this point in property definition. Expected identifier, '(', '(*)' or other token. diff --git a/tests/service/data/SyntaxTree/Member/Auto property 09.fs.bsl b/tests/service/data/SyntaxTree/Member/Auto property 09.fs.bsl index cbb94cfd556..1051d50be3f 100644 --- a/tests/service/data/SyntaxTree/Member/Auto property 09.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Auto property 09.fs.bsl @@ -68,5 +68,4 @@ ImplFile CodeComments = [] }, set [])) (5,4)-(5,10) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:23). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (5,4)-(5,10) parse error Incomplete structured construct at or before this point in property definition. Expected identifier, '(', '(*)' or other token. diff --git a/tests/service/data/SyntaxTree/Member/Auto property 10.fs.bsl b/tests/service/data/SyntaxTree/Member/Auto property 10.fs.bsl index faddd5d4fdd..3f9146bf5be 100644 --- a/tests/service/data/SyntaxTree/Member/Auto property 10.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Auto property 10.fs.bsl @@ -44,5 +44,4 @@ ImplFile CodeComments = [] }, set [])) (5,0)-(5,0) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:22). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (5,0)-(5,0) parse error Incomplete structured construct at or before this point in property definition. Expected identifier, '(', '(*)' or other token. diff --git a/tests/service/data/SyntaxTree/Member/Auto property 12.fs.bsl b/tests/service/data/SyntaxTree/Member/Auto property 12.fs.bsl index 80e694f5424..4156e496244 100644 --- a/tests/service/data/SyntaxTree/Member/Auto property 12.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Auto property 12.fs.bsl @@ -44,7 +44,5 @@ ImplFile CodeComments = [] }, set [])) (4,21)-(4,25) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (6,0)-(6,1) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (4,21)-(4,25) parse error Identifier expected diff --git a/tests/service/data/SyntaxTree/Member/Auto property 13.fs.bsl b/tests/service/data/SyntaxTree/Member/Auto property 13.fs.bsl index d6522b75532..9a86d1dabaf 100644 --- a/tests/service/data/SyntaxTree/Member/Auto property 13.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Auto property 13.fs.bsl @@ -67,7 +67,5 @@ ImplFile CodeComments = [] }, set [])) (4,21)-(4,25) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (5,4)-(5,10) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (4,21)-(4,25) parse error Identifier expected diff --git a/tests/service/data/SyntaxTree/Member/Do 03.fs.bsl b/tests/service/data/SyntaxTree/Member/Do 03.fs.bsl index eb75b56a51d..6defeb3fc49 100644 --- a/tests/service/data/SyntaxTree/Member/Do 03.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Do 03.fs.bsl @@ -48,5 +48,4 @@ ImplFile CodeComments = [] }, set [])) (7,4)-(7,6) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (5:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (5,13)-(5,13) parse error Expecting expression diff --git a/tests/service/data/SyntaxTree/Member/Do 04.fs.bsl b/tests/service/data/SyntaxTree/Member/Do 04.fs.bsl index 2c6ac32e12e..0a32c187243 100644 --- a/tests/service/data/SyntaxTree/Member/Do 04.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Do 04.fs.bsl @@ -46,5 +46,4 @@ ImplFile CodeComments = [] }, set [])) (7,4)-(7,6) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (5:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (5,6)-(5,6) parse error Expecting expression diff --git a/tests/service/data/SyntaxTree/Member/Interface 02.fs.bsl b/tests/service/data/SyntaxTree/Member/Interface 02.fs.bsl index 7d67643e0fa..a6e8c38de3c 100644 --- a/tests/service/data/SyntaxTree/Member/Interface 02.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Interface 02.fs.bsl @@ -48,4 +48,3 @@ ImplFile CodeComments = [] }, set [])) (6,4)-(6,21) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. diff --git a/tests/service/data/SyntaxTree/Member/Interface 06.fs.bsl b/tests/service/data/SyntaxTree/Member/Interface 06.fs.bsl index 2552febe621..15fc3f40c4a 100644 --- a/tests/service/data/SyntaxTree/Member/Interface 06.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Interface 06.fs.bsl @@ -38,4 +38,3 @@ ImplFile CodeComments = [] }, set [])) (6,4)-(6,14) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. diff --git a/tests/service/data/SyntaxTree/Member/Let 02.fs.bsl b/tests/service/data/SyntaxTree/Member/Let 02.fs.bsl index 00844e3bd36..d2e863de852 100644 --- a/tests/service/data/SyntaxTree/Member/Let 02.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Let 02.fs.bsl @@ -47,5 +47,4 @@ ImplFile CodeComments = [] }, set [])) (7,4)-(7,6) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (5:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (7,4)-(7,6) parse error Incomplete structured construct at or before this point in binding diff --git a/tests/service/data/SyntaxTree/Member/Member 05.fs.bsl b/tests/service/data/SyntaxTree/Member/Member 05.fs.bsl index 9f480a45c60..256a0147888 100644 --- a/tests/service/data/SyntaxTree/Member/Member 05.fs.bsl +++ b/tests/service/data/SyntaxTree/Member/Member 05.fs.bsl @@ -113,5 +113,4 @@ ImplFile CodeComments = [] }, set [])) (6,4)-(6,6) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (5:11). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (6,4)-(6,6) parse error Expecting expression diff --git a/tests/service/data/SyntaxTree/ModuleMember/Do 01.fs.bsl b/tests/service/data/SyntaxTree/ModuleMember/Do 01.fs.bsl index b7e8db2446d..d69a7bbc38d 100644 --- a/tests/service/data/SyntaxTree/ModuleMember/Do 01.fs.bsl +++ b/tests/service/data/SyntaxTree/ModuleMember/Do 01.fs.bsl @@ -15,5 +15,4 @@ ImplFile CodeComments = [] }, set [])) (5,0)-(5,1) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (3:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (3,2)-(3,2) parse error Expecting expression diff --git a/tests/service/data/SyntaxTree/ModuleMember/Do 02.fs.bsl b/tests/service/data/SyntaxTree/ModuleMember/Do 02.fs.bsl index 6838d51523f..04b98eb8b7d 100644 --- a/tests/service/data/SyntaxTree/ModuleMember/Do 02.fs.bsl +++ b/tests/service/data/SyntaxTree/ModuleMember/Do 02.fs.bsl @@ -15,5 +15,4 @@ ImplFile CodeComments = [] }, set [])) (4,0)-(4,4) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (3:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (4,0)-(4,4) parse error Expecting expression diff --git a/tests/service/data/SyntaxTree/ModuleMember/Let 02.fs.bsl b/tests/service/data/SyntaxTree/ModuleMember/Let 02.fs.bsl index a463512f96a..438b52a84ce 100644 --- a/tests/service/data/SyntaxTree/ModuleMember/Let 02.fs.bsl +++ b/tests/service/data/SyntaxTree/ModuleMember/Let 02.fs.bsl @@ -24,5 +24,4 @@ ImplFile CodeComments = [] }, set [])) (5,0)-(5,1) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (3:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (5,0)-(5,1) parse error Incomplete structured construct at or before this point in binding diff --git a/tests/service/data/SyntaxTree/ModuleOrNamespace/Module 04.fs.bsl b/tests/service/data/SyntaxTree/ModuleOrNamespace/Module 04.fs.bsl index ec78caa48c3..5a2569e2426 100644 --- a/tests/service/data/SyntaxTree/ModuleOrNamespace/Module 04.fs.bsl +++ b/tests/service/data/SyntaxTree/ModuleOrNamespace/Module 04.fs.bsl @@ -12,10 +12,6 @@ ImplFile CodeComments = [] }, set [])) (3,0)-(3,1) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (1:3). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (3,0)-(3,1) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (1:3). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (3,1)-(3,2) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (1:3). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (3,0)-(3,1) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (1:3). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. diff --git a/tests/service/data/SyntaxTree/ModuleOrNamespace/Nested module 02.fs.bsl b/tests/service/data/SyntaxTree/ModuleOrNamespace/Nested module 02.fs.bsl index 9724fa99d55..c14ada26001 100644 --- a/tests/service/data/SyntaxTree/ModuleOrNamespace/Nested module 02.fs.bsl +++ b/tests/service/data/SyntaxTree/ModuleOrNamespace/Nested module 02.fs.bsl @@ -19,5 +19,4 @@ ImplFile CodeComments = [] }, set [])) (5,0)-(5,1) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (3:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (5,0)-(5,1) parse error Incomplete structured construct at or before this point in definition diff --git a/tests/service/data/SyntaxTree/ModuleOrNamespace/Nested module 09.fs.bsl b/tests/service/data/SyntaxTree/ModuleOrNamespace/Nested module 09.fs.bsl index c4e7b8b3451..e1090ee682a 100644 --- a/tests/service/data/SyntaxTree/ModuleOrNamespace/Nested module 09.fs.bsl +++ b/tests/service/data/SyntaxTree/ModuleOrNamespace/Nested module 09.fs.bsl @@ -26,5 +26,4 @@ ImplFile CodeComments = [] }, set [])) (6,4)-(6,5) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (6,4)-(6,5) parse error Incomplete structured construct at or before this point in definition diff --git a/tests/service/data/SyntaxTree/ModuleOrNamespace/Nested module 14.fs.bsl b/tests/service/data/SyntaxTree/ModuleOrNamespace/Nested module 14.fs.bsl index d79064e294f..54c0b7139ae 100644 --- a/tests/service/data/SyntaxTree/ModuleOrNamespace/Nested module 14.fs.bsl +++ b/tests/service/data/SyntaxTree/ModuleOrNamespace/Nested module 14.fs.bsl @@ -18,5 +18,4 @@ ImplFile CodeComments = [] }, set [])) (4,0)-(4,0) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (3:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (4,0)-(4,0) parse error Incomplete structured construct at or before this point in definition diff --git a/tests/service/data/SyntaxTree/ModuleOrNamespace/Nested module 15.fs.bsl b/tests/service/data/SyntaxTree/ModuleOrNamespace/Nested module 15.fs.bsl index f837a3cf675..ecfd9b6f223 100644 --- a/tests/service/data/SyntaxTree/ModuleOrNamespace/Nested module 15.fs.bsl +++ b/tests/service/data/SyntaxTree/ModuleOrNamespace/Nested module 15.fs.bsl @@ -17,5 +17,4 @@ ImplFile CodeComments = [] }, set [])) (4,0)-(4,0) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (3:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (4,0)-(4,0) parse error Incomplete structured construct at or before this point in definition diff --git a/tests/service/data/SyntaxTree/Pattern/Tuple - Recover 01.fs.bsl b/tests/service/data/SyntaxTree/Pattern/Tuple - Recover 01.fs.bsl index 27fbcf69530..14aaac27c2e 100644 --- a/tests/service/data/SyntaxTree/Pattern/Tuple - Recover 01.fs.bsl +++ b/tests/service/data/SyntaxTree/Pattern/Tuple - Recover 01.fs.bsl @@ -27,7 +27,6 @@ ImplFile CodeComments = [] }, set [])) (5,0)-(5,0) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (3:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (5,0)-(5,0) parse error Incomplete structured construct at or before this point in binding (4,8)-(4,9) parse error Expecting pattern (5,0)-(5,0) parse error Unexpected end of input in value, function or member definition diff --git a/tests/service/data/SyntaxTree/Pattern/Tuple - Recover 02.fs.bsl b/tests/service/data/SyntaxTree/Pattern/Tuple - Recover 02.fs.bsl index 12a43f5fd10..491197add18 100644 --- a/tests/service/data/SyntaxTree/Pattern/Tuple - Recover 02.fs.bsl +++ b/tests/service/data/SyntaxTree/Pattern/Tuple - Recover 02.fs.bsl @@ -28,7 +28,6 @@ ImplFile CodeComments = [] }, set [])) (4,0)-(4,0) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (3:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (4,0)-(4,0) parse error Incomplete structured construct at or before this point in binding (4,0)-(4,0) parse error Unexpected end of input in value, function or member definition (3,0)-(3,3) parse error Incomplete value or function definition. If this is in an expression, the body of the expression must be indented to the same column as the 'let' keyword. diff --git a/tests/service/data/SyntaxTree/Type/And 06.fs.bsl b/tests/service/data/SyntaxTree/Type/And 06.fs.bsl index 88650dda065..d890eff6034 100644 --- a/tests/service/data/SyntaxTree/Type/And 06.fs.bsl +++ b/tests/service/data/SyntaxTree/Type/And 06.fs.bsl @@ -32,5 +32,4 @@ ImplFile CodeComments = [] }, set [])) (6,0)-(6,0) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (3:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (5,4)-(5,7) parse error A type definition requires one or more members or other declarations. If you intend to define an empty class, struct or interface, then use 'type ... = class end', 'interface end' or 'struct end'. diff --git a/tests/service/data/SyntaxTree/Type/Interface 05.fs.bsl b/tests/service/data/SyntaxTree/Type/Interface 05.fs.bsl index e6801e0c2fc..39d0743692d 100644 --- a/tests/service/data/SyntaxTree/Type/Interface 05.fs.bsl +++ b/tests/service/data/SyntaxTree/Type/Interface 05.fs.bsl @@ -9,6 +9,5 @@ ImplFile CodeComments = [] }, set [])) (7,0)-(7,1) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (3:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (7,0)-(7,1) parse error Unexpected symbol '(' in type definition (4,4)-(4,13) parse error Unmatched 'class', 'interface' or 'struct' diff --git a/tests/service/data/SyntaxTree/Type/Interface 06.fs.bsl b/tests/service/data/SyntaxTree/Type/Interface 06.fs.bsl index fcb667c6f0a..4e8e6f9f31d 100644 --- a/tests/service/data/SyntaxTree/Type/Interface 06.fs.bsl +++ b/tests/service/data/SyntaxTree/Type/Interface 06.fs.bsl @@ -9,6 +9,5 @@ ImplFile CodeComments = [] }, set [])) (6,0)-(6,1) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (3:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (6,0)-(6,1) parse error Unexpected symbol '(' in type definition (3,9)-(3,18) parse error Unmatched 'class', 'interface' or 'struct' diff --git a/tests/service/data/SyntaxTree/Type/Primary ctor 04.fs.bsl b/tests/service/data/SyntaxTree/Type/Primary ctor 04.fs.bsl index 057d2f4c5b5..7da848e85d2 100644 --- a/tests/service/data/SyntaxTree/Type/Primary ctor 04.fs.bsl +++ b/tests/service/data/SyntaxTree/Type/Primary ctor 04.fs.bsl @@ -30,5 +30,4 @@ ImplFile CodeComments = [] }, set [])) (4,0)-(4,0) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (3:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (3,5)-(3,7) parse error A type definition requires one or more members or other declarations. If you intend to define an empty class, struct or interface, then use 'type ... = class end', 'interface end' or 'struct end'. diff --git a/tests/service/data/SyntaxTree/Type/Type 06.fs.bsl b/tests/service/data/SyntaxTree/Type/Type 06.fs.bsl index 9fbbe27cb68..8850ddee773 100644 --- a/tests/service/data/SyntaxTree/Type/Type 06.fs.bsl +++ b/tests/service/data/SyntaxTree/Type/Type 06.fs.bsl @@ -20,6 +20,5 @@ ImplFile CodeComments = [] }, set [])) (4,0)-(4,0) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (3:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (3,5)-(3,6) parse error Unexpected symbol '=' in type name (3,5)-(3,6) parse error A type definition requires one or more members or other declarations. If you intend to define an empty class, struct or interface, then use 'type ... = class end', 'interface end' or 'struct end'. diff --git a/tests/service/data/SyntaxTree/Type/Union 03.fs.bsl b/tests/service/data/SyntaxTree/Type/Union 03.fs.bsl index 9623dd96ac7..143718f6cae 100644 --- a/tests/service/data/SyntaxTree/Type/Union 03.fs.bsl +++ b/tests/service/data/SyntaxTree/Type/Union 03.fs.bsl @@ -40,5 +40,4 @@ ImplFile CodeComments = [] }, set [])) (5,0)-(5,0) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (5,0)-(5,0) parse error Incomplete structured construct at or before this point in union case diff --git a/tests/service/data/SyntaxTree/Type/Union 04.fs.bsl b/tests/service/data/SyntaxTree/Type/Union 04.fs.bsl index a83e76cb5a0..b2400b2ded9 100644 --- a/tests/service/data/SyntaxTree/Type/Union 04.fs.bsl +++ b/tests/service/data/SyntaxTree/Type/Union 04.fs.bsl @@ -47,5 +47,4 @@ ImplFile CodeComments = [] }, set [])) (5,0)-(5,0) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (4:5). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (5,0)-(5,0) parse error Incomplete structured construct at or before this point in union case diff --git a/tests/service/data/SyntaxTree/Type/With 02.fs.bsl b/tests/service/data/SyntaxTree/Type/With 02.fs.bsl index f319074e37e..c877d126a1d 100644 --- a/tests/service/data/SyntaxTree/Type/With 02.fs.bsl +++ b/tests/service/data/SyntaxTree/Type/With 02.fs.bsl @@ -20,5 +20,4 @@ ImplFile CodeComments = [] }, set [])) (4,0)-(4,6) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (3:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (4,0)-(4,6) parse error Unexpected keyword 'member' in definition. Expected incomplete structured construct at or before this point or other token. diff --git a/tests/service/data/SyntaxTree/Type/With 03.fs.bsl b/tests/service/data/SyntaxTree/Type/With 03.fs.bsl index 197d6d3efc9..ae8767fd547 100644 --- a/tests/service/data/SyntaxTree/Type/With 03.fs.bsl +++ b/tests/service/data/SyntaxTree/Type/With 03.fs.bsl @@ -21,4 +21,3 @@ ImplFile CodeComments = [] }, set [])) (5,0)-(5,1) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (3:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. diff --git a/tests/service/data/SyntaxTree/Type/With 05.fs.bsl b/tests/service/data/SyntaxTree/Type/With 05.fs.bsl index 8dedec200dd..80d7ab2967f 100644 --- a/tests/service/data/SyntaxTree/Type/With 05.fs.bsl +++ b/tests/service/data/SyntaxTree/Type/With 05.fs.bsl @@ -27,5 +27,4 @@ ImplFile CodeComments = [] }, set [])) (6,0)-(6,6) parse error Unexpected syntax or possible incorrect indentation: this token is offside of context started at position (3:1). Try indenting this further. -To continue using non-conforming indentation, pass the '--strict-indentation-' flag to the compiler, or set the language version to F# 7. (6,0)-(6,6) parse error Unexpected keyword 'member' in definition. Expected incomplete structured construct at or before this point or other token. diff --git a/vsintegration/src/FSharp.Editor/AutomaticCompletion/BraceCompletionSessionProvider.fs b/vsintegration/src/FSharp.Editor/AutomaticCompletion/BraceCompletionSessionProvider.fs index c73e85c3a58..a2ed5ad4c35 100644 --- a/vsintegration/src/FSharp.Editor/AutomaticCompletion/BraceCompletionSessionProvider.fs +++ b/vsintegration/src/FSharp.Editor/AutomaticCompletion/BraceCompletionSessionProvider.fs @@ -505,7 +505,6 @@ type EditorBraceCompletionSessionFactory() = Some(document.FilePath), [], None, - None, colorizationData, cancellationToken ) diff --git a/vsintegration/src/FSharp.Editor/Classification/ClassificationService.fs b/vsintegration/src/FSharp.Editor/Classification/ClassificationService.fs index 93cc2cb4a21..738003d5e3a 100644 --- a/vsintegration/src/FSharp.Editor/Classification/ClassificationService.fs +++ b/vsintegration/src/FSharp.Editor/Classification/ClassificationService.fs @@ -166,7 +166,7 @@ type internal FSharpClassificationService [] () = let! cancellationToken = CancellableTask.getCancellationToken () - let defines, langVersion, strictIndentation = document.GetFsharpParsingOptions() + let defines, langVersion = document.GetFsharpParsingOptions() let! sourceText = document.GetTextAsync(cancellationToken) @@ -199,7 +199,6 @@ type internal FSharpClassificationService [] () = Some(document.FilePath), defines, Some langVersion, - strictIndentation, result, cancellationToken ) diff --git a/vsintegration/src/FSharp.Editor/CodeFixes/AddMissingFunKeyword.fs b/vsintegration/src/FSharp.Editor/CodeFixes/AddMissingFunKeyword.fs index adc0cc8db01..7b209b757da 100644 --- a/vsintegration/src/FSharp.Editor/CodeFixes/AddMissingFunKeyword.fs +++ b/vsintegration/src/FSharp.Editor/CodeFixes/AddMissingFunKeyword.fs @@ -52,8 +52,7 @@ type internal AddMissingFunKeywordCodeFixProvider [] () = let! cancellationToken = CancellableTask.getCancellationToken () let document = context.Document - let! defines, langVersion, strictIndentation = - document.GetFsharpParsingOptionsAsync(nameof AddMissingFunKeywordCodeFixProvider) + let! defines, langVersion = document.GetFsharpParsingOptionsAsync(nameof AddMissingFunKeywordCodeFixProvider) let! sourceText = context.GetSourceTextAsync() let adjustedPosition = adjustPosition sourceText context.Span @@ -69,7 +68,6 @@ type internal AddMissingFunKeywordCodeFixProvider [] () = false, false, Some langVersion, - strictIndentation, cancellationToken ) |> ValueOption.ofOption diff --git a/vsintegration/src/FSharp.Editor/CodeFixes/AddMissingRecToMutuallyRecFunctions.fs b/vsintegration/src/FSharp.Editor/CodeFixes/AddMissingRecToMutuallyRecFunctions.fs index 0a601af0e55..91f796121b5 100644 --- a/vsintegration/src/FSharp.Editor/CodeFixes/AddMissingRecToMutuallyRecFunctions.fs +++ b/vsintegration/src/FSharp.Editor/CodeFixes/AddMissingRecToMutuallyRecFunctions.fs @@ -26,7 +26,7 @@ type internal AddMissingRecToMutuallyRecFunctionsCodeFixProvider [ ValueOption.ofOption diff --git a/vsintegration/src/FSharp.Editor/CodeFixes/AddOpenCodeFixProvider.fs b/vsintegration/src/FSharp.Editor/CodeFixes/AddOpenCodeFixProvider.fs index 77727c18684..57bca908da6 100644 --- a/vsintegration/src/FSharp.Editor/CodeFixes/AddOpenCodeFixProvider.fs +++ b/vsintegration/src/FSharp.Editor/CodeFixes/AddOpenCodeFixProvider.fs @@ -118,7 +118,7 @@ type internal AddOpenCodeFixProvider [] (assemblyContentPr let line = sourceText.Lines.GetLineFromPosition(context.Span.End) let linePos = sourceText.Lines.GetLinePosition(context.Span.End) - let! defines, langVersion, strictIndentation = document.GetFsharpParsingOptionsAsync(nameof AddOpenCodeFixProvider) + let! defines, langVersion = document.GetFsharpParsingOptionsAsync(nameof AddOpenCodeFixProvider) return Tokenizer.getSymbolAtPosition ( @@ -131,7 +131,6 @@ type internal AddOpenCodeFixProvider [] (assemblyContentPr false, false, Some langVersion, - strictIndentation, context.CancellationToken ) |> Option.filter (fun lexerSymbol -> diff --git a/vsintegration/src/FSharp.Editor/CodeFixes/ImplementInterface.fs b/vsintegration/src/FSharp.Editor/CodeFixes/ImplementInterface.fs index 92f0c0077d7..55e58e6d27e 100644 --- a/vsintegration/src/FSharp.Editor/CodeFixes/ImplementInterface.fs +++ b/vsintegration/src/FSharp.Editor/CodeFixes/ImplementInterface.fs @@ -197,7 +197,6 @@ type internal ImplementInterfaceCodeFixProvider [] () = context.Document.FilePath, defines, langVersionOpt, - parsingOptions.StrictIndentation, cancellationToken ) @@ -245,7 +244,6 @@ type internal ImplementInterfaceCodeFixProvider [] () = false, false, langVersionOpt, - parsingOptions.StrictIndentation, cancellationToken ) diff --git a/vsintegration/src/FSharp.Editor/Commands/HelpContextService.fs b/vsintegration/src/FSharp.Editor/Commands/HelpContextService.fs index eefb7eab8df..b68676989de 100644 --- a/vsintegration/src/FSharp.Editor/Commands/HelpContextService.fs +++ b/vsintegration/src/FSharp.Editor/Commands/HelpContextService.fs @@ -112,7 +112,7 @@ type internal FSharpHelpContextService [] () = let! cancellationToken = CancellableTask.getCancellationToken () let! sourceText = document.GetTextAsync(cancellationToken) - let defines, langVersion, strictIndentation = document.GetFsharpParsingOptions() + let defines, langVersion = document.GetFsharpParsingOptions() let textLine = sourceText.Lines.GetLineFromPosition(textSpan.Start) @@ -125,7 +125,6 @@ type internal FSharpHelpContextService [] () = Some document.Name, defines, Some langVersion, - strictIndentation, classifiedSpans, cancellationToken ) diff --git a/vsintegration/src/FSharp.Editor/Completion/CompletionProvider.fs b/vsintegration/src/FSharp.Editor/Completion/CompletionProvider.fs index fa7db6ec835..45d13b0fef8 100644 --- a/vsintegration/src/FSharp.Editor/Completion/CompletionProvider.fs +++ b/vsintegration/src/FSharp.Editor/Completion/CompletionProvider.fs @@ -104,7 +104,7 @@ type internal FSharpCompletionProvider sourceText: SourceText, caretPosition: int, trigger: CompletionTriggerKind, - getInfo: (unit -> DocumentId * string * string list * string option * bool option), + getInfo: (unit -> DocumentId * string * string list * string option), intelliSenseOptions: IntelliSenseOptions, cancellationToken: CancellationToken ) = @@ -129,14 +129,13 @@ type internal FSharpCompletionProvider then false else - let documentId, filePath, defines, langVersion, strictIndentation = getInfo () + let documentId, filePath, defines, langVersion = getInfo () CompletionUtils.shouldProvideCompletion ( documentId, filePath, defines, langVersion, - strictIndentation, sourceText, triggerPosition, cancellationToken @@ -303,9 +302,9 @@ type internal FSharpCompletionProvider let documentId = workspace.GetDocumentIdInCurrentContext(sourceText.Container) let document = workspace.CurrentSolution.GetDocument(documentId) - let defines, langVersion, strictIndentation = document.GetFsharpParsingOptions() + let defines, langVersion = document.GetFsharpParsingOptions() - (documentId, document.FilePath, defines, Some langVersion, strictIndentation) + (documentId, document.FilePath, defines, Some langVersion) FSharpCompletionProvider.ShouldTriggerCompletionAux( sourceText, @@ -336,7 +335,7 @@ type internal FSharpCompletionProvider let! sourceText = context.Document.GetTextAsync(ct) - let defines, langVersion, strictIndentation = document.GetFsharpParsingOptions() + let defines, langVersion = document.GetFsharpParsingOptions() let shouldProvideCompletion = CompletionUtils.shouldProvideCompletion ( @@ -344,7 +343,6 @@ type internal FSharpCompletionProvider document.FilePath, defines, Some langVersion, - strictIndentation, sourceText, context.Position, ct diff --git a/vsintegration/src/FSharp.Editor/Completion/CompletionService.fs b/vsintegration/src/FSharp.Editor/Completion/CompletionService.fs index 450d8ed67ac..38e410b4b90 100644 --- a/vsintegration/src/FSharp.Editor/Completion/CompletionService.fs +++ b/vsintegration/src/FSharp.Editor/Completion/CompletionService.fs @@ -43,7 +43,7 @@ type internal FSharpCompletionService let documentId = workspace.GetDocumentIdInCurrentContext(sourceText.Container) let document = workspace.CurrentSolution.GetDocument(documentId) - let defines, langVersion, strictIndentation = + let defines, langVersion = projectInfoManager.GetCompilationDefinesAndLangVersionForEditingDocument(document) CompletionUtils.getDefaultCompletionListSpan ( @@ -53,7 +53,6 @@ type internal FSharpCompletionService document.FilePath, defines, Some langVersion, - strictIndentation, CancellationToken.None ) diff --git a/vsintegration/src/FSharp.Editor/Completion/CompletionUtils.fs b/vsintegration/src/FSharp.Editor/Completion/CompletionUtils.fs index 1bb5958418c..aa200d70ce9 100644 --- a/vsintegration/src/FSharp.Editor/Completion/CompletionUtils.fs +++ b/vsintegration/src/FSharp.Editor/Completion/CompletionUtils.fs @@ -96,7 +96,6 @@ module internal CompletionUtils = filePath: string, defines: string list, langVersion: string option, - strictIndentation: bool option, sourceText: SourceText, triggerPosition: int, ct: CancellationToken @@ -106,17 +105,7 @@ module internal CompletionUtils = let classifiedSpans = ResizeArray<_>() - Tokenizer.classifySpans ( - documentId, - sourceText, - triggerLine.Span, - Some filePath, - defines, - langVersion, - strictIndentation, - classifiedSpans, - ct - ) + Tokenizer.classifySpans (documentId, sourceText, triggerLine.Span, Some filePath, defines, langVersion, classifiedSpans, ct) classifiedSpans.Count = 0 || // we should provide completion at the start of empty line, where there are no tokens at all @@ -148,7 +137,7 @@ module internal CompletionUtils = /// Indicates the text span to be replaced by a committed completion list item. let getDefaultCompletionListSpan - (sourceText: SourceText, caretIndex, documentId, filePath, defines, langVersion, strictIndentation, ct: CancellationToken) + (sourceText: SourceText, caretIndex, documentId, filePath, defines, langVersion, ct: CancellationToken) = // Gets connected identifier-part characters backward and forward from caret. @@ -186,17 +175,7 @@ module internal CompletionUtils = let classifiedSpans = ResizeArray<_>() - Tokenizer.classifySpans ( - documentId, - sourceText, - line.Span, - Some filePath, - defines, - langVersion, - strictIndentation, - classifiedSpans, - ct - ) + Tokenizer.classifySpans (documentId, sourceText, line.Span, Some filePath, defines, langVersion, classifiedSpans, ct) let inline isBacktickIdentifier (classifiedSpan: ClassifiedSpan) = classifiedSpan.ClassificationType = ClassificationTypeNames.Identifier diff --git a/vsintegration/src/FSharp.Editor/Completion/HashDirectiveCompletionProvider.fs b/vsintegration/src/FSharp.Editor/Completion/HashDirectiveCompletionProvider.fs index 4e2b31f3ab4..43d05744b42 100644 --- a/vsintegration/src/FSharp.Editor/Completion/HashDirectiveCompletionProvider.fs +++ b/vsintegration/src/FSharp.Editor/Completion/HashDirectiveCompletionProvider.fs @@ -64,7 +64,7 @@ type internal HashDirectiveCompletionProvider let documentId = workspace.GetDocumentIdInCurrentContext(text.Container) let document = workspace.CurrentSolution.GetDocument(documentId) - let defines, langVersion, strictIndentation = + let defines, langVersion = projectInfoManager.GetCompilationDefinesAndLangVersionForEditingDocument(document) let textLines = text.Lines @@ -79,7 +79,6 @@ type internal HashDirectiveCompletionProvider Some document.FilePath, defines, Some langVersion, - strictIndentation, classifiedSpans, CancellationToken.None ) diff --git a/vsintegration/src/FSharp.Editor/Completion/SignatureHelp.fs b/vsintegration/src/FSharp.Editor/Completion/SignatureHelp.fs index f00deaa9250..9842f3f578c 100644 --- a/vsintegration/src/FSharp.Editor/Completion/SignatureHelp.fs +++ b/vsintegration/src/FSharp.Editor/Completion/SignatureHelp.fs @@ -290,7 +290,6 @@ type internal FSharpSignatureHelpProvider [] (serviceProvi documentId: DocumentId, defines: string list, langVersion: string option, - strictIndentation: bool option, documentationBuilder: IDocumentationBuilder, sourceText: SourceText, caretPosition: int, @@ -329,7 +328,6 @@ type internal FSharpSignatureHelpProvider [] (serviceProvi false, false, langVersion, - strictIndentation, ct ) @@ -607,7 +605,6 @@ type internal FSharpSignatureHelpProvider [] (serviceProvi document: Document, defines: string list, langVersion: string option, - strictIndentation: bool option, documentationBuilder: IDocumentationBuilder, caretPosition: int, triggerTypedChar: char option, @@ -660,7 +657,6 @@ type internal FSharpSignatureHelpProvider [] (serviceProvi document.Id, defines, langVersion, - strictIndentation, documentationBuilder, sourceText, caretPosition, @@ -680,7 +676,6 @@ type internal FSharpSignatureHelpProvider [] (serviceProvi document.Id, defines, langVersion, - strictIndentation, documentationBuilder, sourceText, caretPosition, @@ -713,7 +708,7 @@ type internal FSharpSignatureHelpProvider [] (serviceProvi member _.GetItemsAsync(document, position, triggerInfo, cancellationToken) = asyncMaybe { - let defines, langVersion, strictIndentation = document.GetFsharpParsingOptions() + let defines, langVersion = document.GetFsharpParsingOptions() let triggerTypedChar = if @@ -731,7 +726,6 @@ type internal FSharpSignatureHelpProvider [] (serviceProvi document, defines, Some langVersion, - strictIndentation, documentationBuilder, position, triggerTypedChar, diff --git a/vsintegration/src/FSharp.Editor/Debugging/LanguageDebugInfoService.fs b/vsintegration/src/FSharp.Editor/Debugging/LanguageDebugInfoService.fs index 3d815f92343..c3917db51fa 100644 --- a/vsintegration/src/FSharp.Editor/Debugging/LanguageDebugInfoService.fs +++ b/vsintegration/src/FSharp.Editor/Debugging/LanguageDebugInfoService.fs @@ -53,7 +53,7 @@ type internal FSharpLanguageDebugInfoService [] () = (document: Document, position: int, cancellationToken: CancellationToken) : Task = cancellableTask { - let defines, langVersion, strictIndentation = document.GetFsharpParsingOptions() + let defines, langVersion = document.GetFsharpParsingOptions() let! cancellationToken = CancellableTask.getCancellationToken () let! sourceText = document.GetTextAsync(cancellationToken) @@ -68,7 +68,6 @@ type internal FSharpLanguageDebugInfoService [] () = Some(document.Name), defines, Some langVersion, - strictIndentation, classifiedSpans, cancellationToken ) diff --git a/vsintegration/src/FSharp.Editor/Formatting/EditorFormattingService.fs b/vsintegration/src/FSharp.Editor/Formatting/EditorFormattingService.fs index 88aa10e23ab..cb7e2c5a0a6 100644 --- a/vsintegration/src/FSharp.Editor/Formatting/EditorFormattingService.fs +++ b/vsintegration/src/FSharp.Editor/Formatting/EditorFormattingService.fs @@ -57,7 +57,6 @@ type internal FSharpEditorFormattingService [] (settings: filePath, defines, Some parsingOptions.LangVersionText, - parsingOptions.StrictIndentation, cancellationToken ) diff --git a/vsintegration/src/FSharp.Editor/Formatting/IndentationService.fs b/vsintegration/src/FSharp.Editor/Formatting/IndentationService.fs index d874656c176..5c38459d212 100644 --- a/vsintegration/src/FSharp.Editor/Formatting/IndentationService.fs +++ b/vsintegration/src/FSharp.Editor/Formatting/IndentationService.fs @@ -36,7 +36,6 @@ type internal FSharpIndentationService [] () = filePath, defines, Some parsingOptions.LangVersionText, - parsingOptions.StrictIndentation, CancellationToken.None ) diff --git a/vsintegration/src/FSharp.Editor/LanguageService/FSharpProjectOptionsManager.fs b/vsintegration/src/FSharp.Editor/LanguageService/FSharpProjectOptionsManager.fs index d61ba717b4d..08bfbbddaa8 100644 --- a/vsintegration/src/FSharp.Editor/LanguageService/FSharpProjectOptionsManager.fs +++ b/vsintegration/src/FSharp.Editor/LanguageService/FSharpProjectOptionsManager.fs @@ -608,7 +608,7 @@ type internal FSharpProjectOptionsManager(checker: FSharpChecker, workspace: Wor IsInteractive = CompilerEnvironment.IsScriptFile document.Name } - CompilerEnvironment.GetConditionalDefinesForEditing parsingOptions, parsingOptions.LangVersionText, parsingOptions.StrictIndentation + CompilerEnvironment.GetConditionalDefinesForEditing parsingOptions, parsingOptions.LangVersionText member _.TryGetOptionsByProject(project) = reactor.TryGetOptionsByProjectAsync(project) diff --git a/vsintegration/src/FSharp.Editor/LanguageService/SymbolHelpers.fs b/vsintegration/src/FSharp.Editor/LanguageService/SymbolHelpers.fs index aa355c9922e..36319820f80 100644 --- a/vsintegration/src/FSharp.Editor/LanguageService/SymbolHelpers.fs +++ b/vsintegration/src/FSharp.Editor/LanguageService/SymbolHelpers.fs @@ -32,7 +32,7 @@ module internal SymbolHelpers = |> Async.AwaitTask |> liftAsync - let! defines, langVersion, strictIndentation = document.GetFsharpParsingOptionsAsync(userOpName) |> liftAsync + let! defines, langVersion = document.GetFsharpParsingOptionsAsync(userOpName) |> liftAsync let! cancellationToken = Async.CancellationToken |> liftAsync let! sourceText = document.GetTextAsync(cancellationToken) @@ -51,7 +51,6 @@ module internal SymbolHelpers = false, false, Some langVersion, - strictIndentation, cancellationToken ) diff --git a/vsintegration/src/FSharp.Editor/LanguageService/Tokenizer.fs b/vsintegration/src/FSharp.Editor/LanguageService/Tokenizer.fs index 49ac6a4ad8b..6901ceb97b1 100644 --- a/vsintegration/src/FSharp.Editor/LanguageService/Tokenizer.fs +++ b/vsintegration/src/FSharp.Editor/LanguageService/Tokenizer.fs @@ -688,14 +688,12 @@ module internal Tokenizer = fileName: string option, defines: string list, langVersion, - strictIndentation, result: ResizeArray, cancellationToken: CancellationToken ) : unit = try - let sourceTokenizer = - FSharpSourceTokenizer(defines, fileName, langVersion, strictIndentation) + let sourceTokenizer = FSharpSourceTokenizer(defines, fileName, langVersion) let lines = sourceText.Lines let sourceTextData = getSourceTextData (documentKey, defines, lines.Count) @@ -902,13 +900,11 @@ module internal Tokenizer = fileName: string, defines: string list, langVersion, - strictIndentation, cancellationToken ) = let textLinePos = sourceText.Lines.GetLinePosition(position) - let sourceTokenizer = - FSharpSourceTokenizer(defines, Some fileName, langVersion, strictIndentation) + let sourceTokenizer = FSharpSourceTokenizer(defines, Some fileName, langVersion) // We keep incremental data per-document. When text changes we correlate text line-by-line (by hash codes of lines) let sourceTextData = getSourceTextData (documentKey, defines, sourceText.Lines.Count) @@ -921,19 +917,10 @@ module internal Tokenizer = lineData, textLinePos, contents - let tokenizeLine (documentKey, sourceText, position, fileName, defines, langVersion, strictIndentation, cancellationToken) = + let tokenizeLine (documentKey, sourceText, position, fileName, defines, langVersion, cancellationToken) = try let lineData, _, _ = - getCachedSourceLineData ( - documentKey, - sourceText, - position, - fileName, - defines, - langVersion, - strictIndentation, - cancellationToken - ) + getCachedSourceLineData (documentKey, sourceText, position, fileName, defines, langVersion, cancellationToken) lineData.SavedTokens with ex -> @@ -951,22 +938,12 @@ module internal Tokenizer = wholeActivePatterns: bool, allowStringToken: bool, langVersion, - strictIndentation, cancellationToken ) : LexerSymbol option = try let lineData, textLinePos, lineContents = - getCachedSourceLineData ( - documentKey, - sourceText, - position, - fileName, - defines, - langVersion, - strictIndentation, - cancellationToken - ) + getCachedSourceLineData (documentKey, sourceText, position, fileName, defines, langVersion, cancellationToken) getSymbolFromSavedTokens ( fileName, diff --git a/vsintegration/src/FSharp.Editor/LanguageService/WorkspaceExtensions.fs b/vsintegration/src/FSharp.Editor/LanguageService/WorkspaceExtensions.fs index c7eb1e50e41..ef0929a1211 100644 --- a/vsintegration/src/FSharp.Editor/LanguageService/WorkspaceExtensions.fs +++ b/vsintegration/src/FSharp.Editor/LanguageService/WorkspaceExtensions.fs @@ -539,10 +539,7 @@ type Document with async { let! _, _, parsingOptions, _ = this.GetFSharpCompilationOptionsAsync(userOpName) - return - CompilerEnvironment.GetConditionalDefinesForEditing parsingOptions, - parsingOptions.LangVersionText, - parsingOptions.StrictIndentation + return CompilerEnvironment.GetConditionalDefinesForEditing parsingOptions, parsingOptions.LangVersionText } /// Get the instance of the FSharpChecker from the workspace by the given F# document. @@ -571,7 +568,7 @@ type Document with /// This tries to get the defines by looking at an internal cache; if it doesn't exist in the cache it will create an inaccurate but usable form of the defines. member this.GetFSharpQuickDefines() = match this.GetFsharpParsingOptions() with - | defines, _, _ -> defines + | defines, _ -> defines /// Parses the given F# document. member this.GetFSharpParseResultsAsync(userOpName) = @@ -641,7 +638,7 @@ type Document with /// Try to find a F# lexer/token symbol of the given F# document and position. member this.TryFindFSharpLexerSymbolAsync(position, lookupKind, wholeActivePattern, allowStringToken, userOpName) = cancellableTask { - let! defines, langVersion, strictIndentation = this.GetFsharpParsingOptionsAsync(userOpName) + let! defines, langVersion = this.GetFsharpParsingOptionsAsync(userOpName) let! ct = CancellableTask.getCancellationToken () let! sourceText = this.GetTextAsync(ct) @@ -656,7 +653,6 @@ type Document with wholeActivePattern, allowStringToken, Some langVersion, - strictIndentation, ct ) } diff --git a/vsintegration/src/FSharp.Editor/TaskList/TaskListService.fs b/vsintegration/src/FSharp.Editor/TaskList/TaskListService.fs index a82e414e754..da01bff2dce 100644 --- a/vsintegration/src/FSharp.Editor/TaskList/TaskListService.fs +++ b/vsintegration/src/FSharp.Editor/TaskList/TaskListService.fs @@ -28,12 +28,9 @@ type internal FSharpTaskListService [] () as this = |> Async.AwaitTask |> liftAsync - return - CompilerEnvironment.GetConditionalDefinesForEditing parsingOptions, - Some parsingOptions.LangVersionText, - parsingOptions.StrictIndentation + return CompilerEnvironment.GetConditionalDefinesForEditing parsingOptions, Some parsingOptions.LangVersionText } - |> Async.map (Option.defaultValue ([], None, None)) + |> Async.map (Option.defaultValue ([], None)) let extractContractedComments (tokens: Tokenizer.SavedTokenInfo[]) = let granularTokens = @@ -61,7 +58,6 @@ type internal FSharpTaskListService [] () as this = sourceText: SourceText, defines: string list, langVersion: string option, - strictIndentation: bool option, descriptors: (string * FSharpTaskListDescriptor)[], cancellationToken ) = @@ -71,16 +67,7 @@ type internal FSharpTaskListService [] () as this = for line in sourceText.Lines do let contractedTokens = - Tokenizer.tokenizeLine ( - doc.Id, - sourceText, - line.Span.Start, - doc.FilePath, - defines, - langVersion, - strictIndentation, - cancellationToken - ) + Tokenizer.tokenizeLine (doc.Id, sourceText, line.Span.Start, doc.FilePath, defines, langVersion, cancellationToken) |> extractContractedComments if contractedTokens |> List.isEmpty then @@ -120,6 +107,6 @@ type internal FSharpTaskListService [] () as this = backgroundTask { let descriptors = desc |> Seq.map (fun d -> d.Text, d) |> Array.ofSeq let! sourceText = doc.GetTextAsync(cancellationToken) - let! defines, langVersion, strictIndentation = doc |> getDefinesAndLangVersion - return this.GetTaskListItems(doc, sourceText, defines, langVersion, strictIndentation, descriptors, cancellationToken) + let! defines, langVersion = doc |> getDefinesAndLangVersion + return this.GetTaskListItems(doc, sourceText, defines, langVersion, descriptors, cancellationToken) } diff --git a/vsintegration/tests/FSharp.Editor.Tests/CompletionProviderTests.fs b/vsintegration/tests/FSharp.Editor.Tests/CompletionProviderTests.fs index 942701b37b9..f85608e0cf9 100644 --- a/vsintegration/tests/FSharp.Editor.Tests/CompletionProviderTests.fs +++ b/vsintegration/tests/FSharp.Editor.Tests/CompletionProviderTests.fs @@ -20,7 +20,7 @@ module CompletionProviderTests = let filePath = "C:\\test.fs" let mkGetInfo documentId = - fun () -> documentId, filePath, [], (Some "preview"), None + fun () -> documentId, filePath, [], (Some "preview") let formatCompletions (completions: string seq) = "\n\t" + String.Join("\n\t", completions) @@ -145,16 +145,7 @@ module CompletionProviderTests = let sourceText = SourceText.From(fileContents) let resultSpan = - CompletionUtils.getDefaultCompletionListSpan ( - sourceText, - caretPosition, - documentId, - filePath, - [], - None, - None, - CancellationToken.None - ) + CompletionUtils.getDefaultCompletionListSpan (sourceText, caretPosition, documentId, filePath, [], None, CancellationToken.None) Assert.Equal(expected, sourceText.ToString(resultSpan)) diff --git a/vsintegration/tests/FSharp.Editor.Tests/GoToDefinitionServiceTests.fs b/vsintegration/tests/FSharp.Editor.Tests/GoToDefinitionServiceTests.fs index d0e4b5efad1..fe10a42a125 100644 --- a/vsintegration/tests/FSharp.Editor.Tests/GoToDefinitionServiceTests.fs +++ b/vsintegration/tests/FSharp.Editor.Tests/GoToDefinitionServiceTests.fs @@ -35,7 +35,6 @@ module GoToDefinitionServiceTests = false, false, langVersion, - None, System.Threading.CancellationToken.None ) diff --git a/vsintegration/tests/FSharp.Editor.Tests/HelpContextServiceTests.fs b/vsintegration/tests/FSharp.Editor.Tests/HelpContextServiceTests.fs index e8a1588f13b..ad690e1d92f 100644 --- a/vsintegration/tests/FSharp.Editor.Tests/HelpContextServiceTests.fs +++ b/vsintegration/tests/FSharp.Editor.Tests/HelpContextServiceTests.fs @@ -51,7 +51,6 @@ type HelpContextServiceTests() = Some "test.fs", [], None, - None, classifiedSpans, CancellationToken.None ) diff --git a/vsintegration/tests/FSharp.Editor.Tests/LanguageDebugInfoServiceTests.fs b/vsintegration/tests/FSharp.Editor.Tests/LanguageDebugInfoServiceTests.fs index 8b3146ee754..b6ab2381b0a 100644 --- a/vsintegration/tests/FSharp.Editor.Tests/LanguageDebugInfoServiceTests.fs +++ b/vsintegration/tests/FSharp.Editor.Tests/LanguageDebugInfoServiceTests.fs @@ -61,7 +61,6 @@ let main argv = Some(fileName), defines, None, - None, classifiedSpans, CancellationToken.None ) diff --git a/vsintegration/tests/FSharp.Editor.Tests/SignatureHelpProviderTests.fs b/vsintegration/tests/FSharp.Editor.Tests/SignatureHelpProviderTests.fs index 398ece88fa3..8c3af8f90d7 100644 --- a/vsintegration/tests/FSharp.Editor.Tests/SignatureHelpProviderTests.fs +++ b/vsintegration/tests/FSharp.Editor.Tests/SignatureHelpProviderTests.fs @@ -177,7 +177,6 @@ module SignatureHelpProvider = document.Id, [], None, - None, DefaultDocumentationProvider, sourceText, caretPosition, @@ -521,7 +520,6 @@ M.f document.Id, [], None, - None, DefaultDocumentationProvider, sourceText, caretPosition, diff --git a/vsintegration/tests/FSharp.Editor.Tests/SyntacticColorizationServiceTests.fs b/vsintegration/tests/FSharp.Editor.Tests/SyntacticColorizationServiceTests.fs index af0fc3ec4c8..230a96bde80 100644 --- a/vsintegration/tests/FSharp.Editor.Tests/SyntacticColorizationServiceTests.fs +++ b/vsintegration/tests/FSharp.Editor.Tests/SyntacticColorizationServiceTests.fs @@ -34,7 +34,6 @@ type SyntacticClassificationServiceTests() = Some(fileName), defines, langVersion, - None, tokens, CancellationToken.None ) diff --git a/vsintegration/tests/FSharp.Editor.Tests/TaskListServiceTests.fs b/vsintegration/tests/FSharp.Editor.Tests/TaskListServiceTests.fs index d84a049ada6..f342b0e92aa 100644 --- a/vsintegration/tests/FSharp.Editor.Tests/TaskListServiceTests.fs +++ b/vsintegration/tests/FSharp.Editor.Tests/TaskListServiceTests.fs @@ -26,7 +26,7 @@ let assertTasks expectedTasks fileContents = let sourceText = doc.GetTextAsync().Result let t = - service.GetTaskListItems(doc, sourceText, [], (Some "preview"), None, descriptors, ct) + service.GetTaskListItems(doc, sourceText, [], (Some "preview"), descriptors, ct) let tasks = t |> Seq.map (fun t -> t.Message) |> List.ofSeq Assert.Equal(expectedTasks |> List.sort, tasks |> List.sort) diff --git a/vsintegration/tests/Salsa/FSharpLanguageServiceTestable.fs b/vsintegration/tests/Salsa/FSharpLanguageServiceTestable.fs index 37654820814..db86271c8d0 100644 --- a/vsintegration/tests/Salsa/FSharpLanguageServiceTestable.fs +++ b/vsintegration/tests/Salsa/FSharpLanguageServiceTestable.fs @@ -212,7 +212,7 @@ type internal FSharpLanguageServiceTestable() as this = let fileName = VsTextLines.GetFilename buffer let rdt = this.ServiceProvider.RunningDocumentTable let defines = this.ProjectSitesAndFiles.GetDefinesForFile_DEPRECATED(rdt, fileName, this.FSharpChecker) - let sourceTokenizer = FSharpSourceTokenizer(defines,Some(fileName), None, None) + let sourceTokenizer = FSharpSourceTokenizer(defines,Some(fileName), None) sourceTokenizer.CreateLineTokenizer(source)) let colorizer = new FSharpColorizer_DEPRECATED(this.CloseColorizer, buffer, scanner) From 36ce34832713bb979e03625eaadb323b9acf47c6 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Tue, 4 Aug 2026 11:26:44 +0200 Subject: [PATCH 32/33] Enable Central Package Management with transitive pinning (#20084) --- .../server/Directory.Build.props | 2 + Directory.Build.targets | 29 +++-- Directory.Packages.props | 10 ++ buildtools/AssemblyCheck/AssemblyCheck.fsproj | 2 +- .../checkpackages/Directory.Build.props | 2 + buildtools/fslex/fslex.fsproj | 2 +- buildtools/fsyacc/fsyacc.fsproj | 2 +- docs/fcs-samples/Directory.Build.props | 7 ++ eng/Packages.props | 115 ++++++++++++++++++ eng/Versions.props | 113 +++++------------ setup/Swix/Directory.Build.props | 2 + src/Compiler/FSharp.Compiler.Service.fsproj | 16 +-- src/FSharp.Build/FSharp.Build.fsproj | 11 +- ...Sharp.Compiler.Interactive.Settings.fsproj | 2 +- .../FSharp.Compiler.LanguageServer.fsproj | 14 +-- .../FSharp.DependencyManager.Nuget.fsproj | 8 +- .../FSharp.VisualStudio.Extension.csproj | 11 +- ...guageServerProtocol.Framework.Proxy.csproj | 5 +- .../Microsoft.FSharp.Compiler.fsproj | 2 +- src/fsc/fsc.targets | 13 +- src/fsc/fscProject/fsc.fsproj | 5 - src/fsi/fsi.targets | 8 +- src/fsi/fsiProject/fsi.fsproj | 5 - tests/AheadOfTime/Directory.Build.props | 2 + tests/Directory.Build.props | 31 +++-- .../EndToEndBuildTests/Directory.Build.props | 3 +- .../FSharp.Build.UnitTests.fsproj | 13 +- .../FSharp.Compiler.ComponentTests.fsproj | 2 +- ...Sharp.Compiler.LanguageServer.Tests.fsproj | 4 +- .../FSharp.Compiler.Service.Tests.fsproj | 3 - .../FSharp.Core.UnitTests.fsproj | 2 +- .../FSharp.Test.Utilities.fsproj | 40 +++--- tests/benchmarks/Directory.Build.props | 2 + tests/fsharp/SDKTests/Directory.Build.props | 2 + .../CompilerCompat/Directory.Build.props | 7 ++ tests/service/data/TestTP/TestTP.fsproj | 2 +- vsintegration/Directory.Build.targets | 30 ++--- .../VisualFSharp.Core.targets | 4 +- .../src/FSharp.Editor/FSharp.Editor.fsproj | 12 +- .../FSharp.LanguageService.Base.csproj | 6 +- .../FSharp.LanguageService.fsproj | 16 +-- .../FSharp.ProjectSystem.Base.csproj | 11 +- .../FSharp.ProjectSystem.FSharp.fsproj | 12 +- .../FSharp.ProjectSystem.PropertyPages.vbproj | 6 +- .../src/FSharp.VS.FSI/FSharp.VS.FSI.fsproj | 5 +- vsintegration/tests/Directory.Build.targets | 2 +- .../FSharp.Editor.IntegrationTests.csproj | 12 +- .../FSharp.Editor.Tests.fsproj | 20 +-- .../tests/Salsa/VisualFSharp.Salsa.fsproj | 16 +-- .../UnitTests/VisualFSharp.UnitTests.fsproj | 24 ++-- 50 files changed, 386 insertions(+), 289 deletions(-) create mode 100644 Directory.Packages.props create mode 100644 docs/fcs-samples/Directory.Build.props create mode 100644 eng/Packages.props create mode 100644 tests/projects/CompilerCompat/Directory.Build.props diff --git a/.github/skills/fsharp-diagnostics/server/Directory.Build.props b/.github/skills/fsharp-diagnostics/server/Directory.Build.props index 5a08e96c89f..48e48f88427 100644 --- a/.github/skills/fsharp-diagnostics/server/Directory.Build.props +++ b/.github/skills/fsharp-diagnostics/server/Directory.Build.props @@ -3,6 +3,8 @@ Also blocks Directory.Build.targets import. --> false + + false $(MSBuildThisFileDirectory)../../../../.tools/fsharp-diag/bin/ $(MSBuildThisFileDirectory)../../../../.tools/fsharp-diag/obj/ diff --git a/Directory.Build.targets b/Directory.Build.targets index 4e5dab341de..a0ac2867bd2 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -3,6 +3,13 @@ + + + $(NoWarn);NU1507 + + - - - - - - - - + + + + + + + + + diff --git a/Directory.Packages.props b/Directory.Packages.props new file mode 100644 index 00000000000..80c569422a8 --- /dev/null +++ b/Directory.Packages.props @@ -0,0 +1,10 @@ + + + + true + true + + + + + diff --git a/buildtools/AssemblyCheck/AssemblyCheck.fsproj b/buildtools/AssemblyCheck/AssemblyCheck.fsproj index 78d24349889..8023580df5a 100644 --- a/buildtools/AssemblyCheck/AssemblyCheck.fsproj +++ b/buildtools/AssemblyCheck/AssemblyCheck.fsproj @@ -23,7 +23,7 @@ - + diff --git a/buildtools/checkpackages/Directory.Build.props b/buildtools/checkpackages/Directory.Build.props index a9a651c4a65..1aa11050403 100644 --- a/buildtools/checkpackages/Directory.Build.props +++ b/buildtools/checkpackages/Directory.Build.props @@ -3,6 +3,8 @@ + + false true $(MSBuildProjectDirectory)\..\..\artifacts\tmp\$([System.Guid]::NewGuid()) $(CachePath)\obj\ diff --git a/buildtools/fslex/fslex.fsproj b/buildtools/fslex/fslex.fsproj index 3b8aafb532b..08f77151636 100644 --- a/buildtools/fslex/fslex.fsproj +++ b/buildtools/fslex/fslex.fsproj @@ -38,7 +38,7 @@ - + diff --git a/buildtools/fsyacc/fsyacc.fsproj b/buildtools/fsyacc/fsyacc.fsproj index ba57de811c9..42ea6e1bf36 100644 --- a/buildtools/fsyacc/fsyacc.fsproj +++ b/buildtools/fsyacc/fsyacc.fsproj @@ -38,7 +38,7 @@ - + diff --git a/docs/fcs-samples/Directory.Build.props b/docs/fcs-samples/Directory.Build.props new file mode 100644 index 00000000000..21aa3b5274e --- /dev/null +++ b/docs/fcs-samples/Directory.Build.props @@ -0,0 +1,7 @@ + + + + + false + + diff --git a/eng/Packages.props b/eng/Packages.props new file mode 100644 index 00000000000..b609655af51 --- /dev/null +++ b/eng/Packages.props @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/eng/Versions.props b/eng/Versions.props index a9b7ec6fd4d..773e10bfb8c 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -28,7 +28,6 @@ 1 - $(FSMajorVersion).$(FSMinorVersion) $(FSMajorVersion).$(FSMinorVersion).$(FSBuildVersion) $(FSMajorVersion).$(FSMinorVersion).$(FSBuildVersion) $(FSMajorVersion).$(FSMinorVersion).0.0 @@ -89,10 +88,26 @@ 4.6.1 4.6.3 6.1.2 - - 4.3.4 - 4.3.1 - + + + $(SystemSecurityCryptographyXmlVersion) + $(SystemCollectionsImmutableVersion) + $(SystemReflectionMetadataVersion) + + + + + 10.0.9 + $(SystemRuntimeCentralFloorVersion) + $(SystemRuntimeCentralFloorVersion) + $(SystemRuntimeCentralFloorVersion) @@ -100,92 +115,30 @@ 4.7.0 - 1.6.0 - - 18.0.404-preview - 18.0.2188-preview.1 - 18.0.1237-pre - 18.0.2077-preview.1 - 18.7.19 - - - 2.0.28 - - $(MicrosoftVisualStudioShellPackagesVersion) - $(VisualStudioShellProjectsPackages) - - 18.9.438 - 18.9.438 - 18.9.438 - $(MicrosoftVisualStudioShellPackagesVersion) - $(MicrosoftVisualStudioShellPackagesVersion) - $(MicrosoftVisualStudioShellPackagesVersion) - $(VisualStudioShellProjectsPackages) - $(MicrosoftVisualStudioShellPackagesVersion) - 10.0.30319 - 11.0.50727 - 15.0.25123-Dev15Preview - - - $(VisualStudioEditorPackagesVersion) - $(VisualStudioEditorPackagesVersion) - $(VisualStudioEditorPackagesVersion) - - 18.9.123 - $(VisualStudioEditorPackagesVersion) - 17.14.0 + + + 18.9.123 0.1.800-beta - $(MicrosoftVisualStudioExtensibilityTestingVersion) - - - $(MicrosoftVisualStudioThreadingPackagesVersion) - - 18.7.1 - 18.9.453 - 4.10.128 - 2.26.5 - - - 1.0.52 + + 17.14.2120 - - $(VisualStudioProjectSystemPackagesVersion) - 2.3.6152103 + + 4.3.0-1.22220.8 + 5.0.0-preview.7.20364.11 + 5.0.0-preview.7.20364.11 - - 17.14.2120 - 17.0.0 - - - 0.2.0 - 1.0.0 - 1.1.87 - 0.13.10 - 2.16.6 - 4.3.0-1.22220.8 - - 5.0.0-preview.7.20364.11 - 5.0.0-preview.7.20364.11 18.0.1 2.0.2 - 13.0.4 3.2.2 - 3.2.2 8.0.0 - diff --git a/setup/Swix/Directory.Build.props b/setup/Swix/Directory.Build.props index 0a9e6f4ecc5..3e43aa310f4 100644 --- a/setup/Swix/Directory.Build.props +++ b/setup/Swix/Directory.Build.props @@ -1,6 +1,8 @@ + + false true Microsoft.FSharp neutral diff --git a/src/Compiler/FSharp.Compiler.Service.fsproj b/src/Compiler/FSharp.Compiler.Service.fsproj index bd9be2c907f..6e623f0654e 100644 --- a/src/Compiler/FSharp.Compiler.Service.fsproj +++ b/src/Compiler/FSharp.Compiler.Service.fsproj @@ -627,17 +627,17 @@ - + - - - - - - - + + + + + + + diff --git a/src/FSharp.Build/FSharp.Build.fsproj b/src/FSharp.Build/FSharp.Build.fsproj index d7f814ce261..90912e95fe2 100644 --- a/src/FSharp.Build/FSharp.Build.fsproj +++ b/src/FSharp.Build/FSharp.Build.fsproj @@ -82,16 +82,13 @@ - + - - - - - - + + + diff --git a/src/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj b/src/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj index a8ecf73e065..0302ae845f5 100644 --- a/src/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj +++ b/src/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj @@ -45,7 +45,7 @@ - + diff --git a/src/FSharp.Compiler.LanguageServer/FSharp.Compiler.LanguageServer.fsproj b/src/FSharp.Compiler.LanguageServer/FSharp.Compiler.LanguageServer.fsproj index c5cc30680bc..ffa91fc3cac 100644 --- a/src/FSharp.Compiler.LanguageServer/FSharp.Compiler.LanguageServer.fsproj +++ b/src/FSharp.Compiler.LanguageServer/FSharp.Compiler.LanguageServer.fsproj @@ -8,12 +8,12 @@ - - - - - - + + + + + + @@ -30,7 +30,7 @@ - + diff --git a/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.Nuget.fsproj b/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.Nuget.fsproj index 500f3b32208..a24d5b0e5d9 100644 --- a/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.Nuget.fsproj +++ b/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.Nuget.fsproj @@ -51,13 +51,7 @@ - - - - - - - + diff --git a/src/FSharp.VisualStudio.Extension/FSharp.VisualStudio.Extension.csproj b/src/FSharp.VisualStudio.Extension/FSharp.VisualStudio.Extension.csproj index 862decf5606..f2f8ab61ede 100644 --- a/src/FSharp.VisualStudio.Extension/FSharp.VisualStudio.Extension.csproj +++ b/src/FSharp.VisualStudio.Extension/FSharp.VisualStudio.Extension.csproj @@ -12,11 +12,12 @@ - - - - - + + + + + + + diff --git a/src/Microsoft.FSharp.Compiler/Microsoft.FSharp.Compiler.fsproj b/src/Microsoft.FSharp.Compiler/Microsoft.FSharp.Compiler.fsproj index 066a59b1538..ec0704c0cf1 100644 --- a/src/Microsoft.FSharp.Compiler/Microsoft.FSharp.Compiler.fsproj +++ b/src/Microsoft.FSharp.Compiler/Microsoft.FSharp.Compiler.fsproj @@ -12,7 +12,7 @@ - + diff --git a/src/fsc/fsc.targets b/src/fsc/fsc.targets index c85dc1e66ab..f54cb4b32a9 100644 --- a/src/fsc/fsc.targets +++ b/src/fsc/fsc.targets @@ -43,7 +43,7 @@ - + @@ -53,14 +53,9 @@ - - - - - - - - + + + diff --git a/src/fsc/fscProject/fsc.fsproj b/src/fsc/fscProject/fsc.fsproj index c66429fe0dc..a8d694360c1 100644 --- a/src/fsc/fscProject/fsc.fsproj +++ b/src/fsc/fscProject/fsc.fsproj @@ -37,11 +37,6 @@ - - - - - diff --git a/src/fsi/fsi.targets b/src/fsi/fsi.targets index cba9355e99f..b38960f7f0e 100644 --- a/src/fsi/fsi.targets +++ b/src/fsi/fsi.targets @@ -48,7 +48,7 @@ - + @@ -65,9 +65,9 @@ - - - + + + \ No newline at end of file diff --git a/src/fsi/fsiProject/fsi.fsproj b/src/fsi/fsiProject/fsi.fsproj index 7a0e2d01428..58a300a0de9 100644 --- a/src/fsi/fsiProject/fsi.fsproj +++ b/src/fsi/fsiProject/fsi.fsproj @@ -25,11 +25,6 @@ $(ArtifactsDir)obj/$(MSBuildProjectName)/$(Configuration)/ - - - - - diff --git a/tests/AheadOfTime/Directory.Build.props b/tests/AheadOfTime/Directory.Build.props index 6b0a85482a8..7c6ff208af6 100644 --- a/tests/AheadOfTime/Directory.Build.props +++ b/tests/AheadOfTime/Directory.Build.props @@ -4,6 +4,8 @@ + + false $(MSBuildThisFileDirectory)/../../artifacts/bin/fsc/Release/$(FSharpNetCoreProductTargetFramework) diff --git a/tests/Directory.Build.props b/tests/Directory.Build.props index 0c1a2882fda..38571805a89 100644 --- a/tests/Directory.Build.props +++ b/tests/Directory.Build.props @@ -5,22 +5,34 @@ true portable + + <_IsTestRunnerProject Condition="$(MSBuildProjectName.EndsWith('.Tests')) OR $(MSBuildProjectName.EndsWith('.ComponentTests')) OR $(MSBuildProjectName.EndsWith('.UnitTests'))">true - - - + + + - + - + - + + + + + + + + + + - + true - + OutputType isn't available at props evaluation time, so this applies to all net472 test-runner projects. --> + x64 diff --git a/tests/EndToEndBuildTests/Directory.Build.props b/tests/EndToEndBuildTests/Directory.Build.props index 66d1e05ada9..a40f84977bd 100644 --- a/tests/EndToEndBuildTests/Directory.Build.props +++ b/tests/EndToEndBuildTests/Directory.Build.props @@ -1,11 +1,12 @@ + + false net40 LatestMajor 3.2.2 - 3.2.2 2.0.2 8.0.0 18.0.1 diff --git a/tests/FSharp.Build.UnitTests/FSharp.Build.UnitTests.fsproj b/tests/FSharp.Build.UnitTests/FSharp.Build.UnitTests.fsproj index 08df369bf4a..0b489b6cc7c 100644 --- a/tests/FSharp.Build.UnitTests/FSharp.Build.UnitTests.fsproj +++ b/tests/FSharp.Build.UnitTests/FSharp.Build.UnitTests.fsproj @@ -25,18 +25,13 @@ - + - - - - - - - - + + + diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj index e50201ba8f9..b92e9ef8638 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj +++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj @@ -558,7 +558,7 @@ - + diff --git a/tests/FSharp.Compiler.LanguageServer.Tests/FSharp.Compiler.LanguageServer.Tests.fsproj b/tests/FSharp.Compiler.LanguageServer.Tests/FSharp.Compiler.LanguageServer.Tests.fsproj index 181cc03f4d3..90993cf5b32 100644 --- a/tests/FSharp.Compiler.LanguageServer.Tests/FSharp.Compiler.LanguageServer.Tests.fsproj +++ b/tests/FSharp.Compiler.LanguageServer.Tests/FSharp.Compiler.LanguageServer.Tests.fsproj @@ -25,7 +25,7 @@ - + @@ -39,7 +39,7 @@ - + diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj index 5b589936a98..30eb9be672c 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj @@ -197,9 +197,6 @@ - - - TargetFramework=netstandard2.0 diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core.UnitTests.fsproj b/tests/FSharp.Core.UnitTests/FSharp.Core.UnitTests.fsproj index d4ff59d3cbd..1694e8eb4ca 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core.UnitTests.fsproj +++ b/tests/FSharp.Core.UnitTests/FSharp.Core.UnitTests.fsproj @@ -98,6 +98,6 @@ - + diff --git a/tests/FSharp.Test.Utilities/FSharp.Test.Utilities.fsproj b/tests/FSharp.Test.Utilities/FSharp.Test.Utilities.fsproj index e60fa89b94c..3d63d7bfac0 100644 --- a/tests/FSharp.Test.Utilities/FSharp.Test.Utilities.fsproj +++ b/tests/FSharp.Test.Utilities/FSharp.Test.Utilities.fsproj @@ -54,7 +54,7 @@ - + @@ -65,19 +65,19 @@ - + runtime; native all - + runtime; native all - + runtime; native all - + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -94,27 +94,29 @@ - - - - - + + + + + $(NoWarn);NU1510;44 - - - - - - + + + + + + - - - + + + diff --git a/tests/benchmarks/Directory.Build.props b/tests/benchmarks/Directory.Build.props index ba9f0b7a4fa..e6b735ad57b 100644 --- a/tests/benchmarks/Directory.Build.props +++ b/tests/benchmarks/Directory.Build.props @@ -2,6 +2,8 @@ + + false true $(FSharpNetCoreProductTargetFramework) diff --git a/tests/fsharp/SDKTests/Directory.Build.props b/tests/fsharp/SDKTests/Directory.Build.props index b8ed27bf510..e0f9795a355 100644 --- a/tests/fsharp/SDKTests/Directory.Build.props +++ b/tests/fsharp/SDKTests/Directory.Build.props @@ -1,6 +1,8 @@ + + false false diff --git a/tests/projects/CompilerCompat/Directory.Build.props b/tests/projects/CompilerCompat/Directory.Build.props new file mode 100644 index 00000000000..d02e351a949 --- /dev/null +++ b/tests/projects/CompilerCompat/Directory.Build.props @@ -0,0 +1,7 @@ + + + + + false + + diff --git a/tests/service/data/TestTP/TestTP.fsproj b/tests/service/data/TestTP/TestTP.fsproj index 4bf7e293c3a..3c421bdbe21 100644 --- a/tests/service/data/TestTP/TestTP.fsproj +++ b/tests/service/data/TestTP/TestTP.fsproj @@ -18,7 +18,7 @@ - + diff --git a/vsintegration/Directory.Build.targets b/vsintegration/Directory.Build.targets index a1d6035a1d3..9d253c24d27 100644 --- a/vsintegration/Directory.Build.targets +++ b/vsintegration/Directory.Build.targets @@ -3,22 +3,22 @@ - - - - - - - - - - - + + + + + + + + + + + - - - - + + + + diff --git a/vsintegration/Vsix/VisualFSharpFull/VisualFSharp.Core.targets b/vsintegration/Vsix/VisualFSharpFull/VisualFSharp.Core.targets index 674c3487ac7..db4b3097d66 100644 --- a/vsintegration/Vsix/VisualFSharpFull/VisualFSharp.Core.targets +++ b/vsintegration/Vsix/VisualFSharpFull/VisualFSharp.Core.targets @@ -260,8 +260,8 @@ - - + + diff --git a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj index e54b6752ea3..319bdd5a264 100644 --- a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj +++ b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj @@ -177,12 +177,12 @@ - - - - - - + + + + + + diff --git a/vsintegration/src/FSharp.LanguageService.Base/FSharp.LanguageService.Base.csproj b/vsintegration/src/FSharp.LanguageService.Base/FSharp.LanguageService.Base.csproj index fbf420a0741..3a71ba25a3c 100644 --- a/vsintegration/src/FSharp.LanguageService.Base/FSharp.LanguageService.Base.csproj +++ b/vsintegration/src/FSharp.LanguageService.Base/FSharp.LanguageService.Base.csproj @@ -46,9 +46,9 @@ - - - + + + diff --git a/vsintegration/src/FSharp.LanguageService/FSharp.LanguageService.fsproj b/vsintegration/src/FSharp.LanguageService/FSharp.LanguageService.fsproj index 848ba3fcf67..ead290f6ec0 100644 --- a/vsintegration/src/FSharp.LanguageService/FSharp.LanguageService.fsproj +++ b/vsintegration/src/FSharp.LanguageService/FSharp.LanguageService.fsproj @@ -56,14 +56,14 @@ - - - - - - - - + + + + + + + + diff --git a/vsintegration/src/FSharp.ProjectSystem.Base/FSharp.ProjectSystem.Base.csproj b/vsintegration/src/FSharp.ProjectSystem.Base/FSharp.ProjectSystem.Base.csproj index be6eb82d080..379bfd8b328 100644 --- a/vsintegration/src/FSharp.ProjectSystem.Base/FSharp.ProjectSystem.Base.csproj +++ b/vsintegration/src/FSharp.ProjectSystem.Base/FSharp.ProjectSystem.Base.csproj @@ -39,12 +39,11 @@ - - - - - - + + + + + diff --git a/vsintegration/src/FSharp.ProjectSystem.FSharp/FSharp.ProjectSystem.FSharp.fsproj b/vsintegration/src/FSharp.ProjectSystem.FSharp/FSharp.ProjectSystem.FSharp.fsproj index da59e918292..97811017810 100644 --- a/vsintegration/src/FSharp.ProjectSystem.FSharp/FSharp.ProjectSystem.FSharp.fsproj +++ b/vsintegration/src/FSharp.ProjectSystem.FSharp/FSharp.ProjectSystem.FSharp.fsproj @@ -104,12 +104,12 @@ - - - - - - + + + + + + diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/FSharp.ProjectSystem.PropertyPages.vbproj b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/FSharp.ProjectSystem.PropertyPages.vbproj index e964555f55f..4b2657c9977 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/FSharp.ProjectSystem.PropertyPages.vbproj +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/FSharp.ProjectSystem.PropertyPages.vbproj @@ -46,9 +46,9 @@ - - - + + + diff --git a/vsintegration/src/FSharp.VS.FSI/FSharp.VS.FSI.fsproj b/vsintegration/src/FSharp.VS.FSI/FSharp.VS.FSI.fsproj index 95878c043b9..5827d12b71a 100644 --- a/vsintegration/src/FSharp.VS.FSI/FSharp.VS.FSI.fsproj +++ b/vsintegration/src/FSharp.VS.FSI/FSharp.VS.FSI.fsproj @@ -57,9 +57,8 @@ - - - + + diff --git a/vsintegration/tests/Directory.Build.targets b/vsintegration/tests/Directory.Build.targets index 2bbbb8d4d4c..1b4f33eed3a 100644 --- a/vsintegration/tests/Directory.Build.targets +++ b/vsintegration/tests/Directory.Build.targets @@ -5,6 +5,6 @@ - + diff --git a/vsintegration/tests/FSharp.Editor.IntegrationTests/FSharp.Editor.IntegrationTests.csproj b/vsintegration/tests/FSharp.Editor.IntegrationTests/FSharp.Editor.IntegrationTests.csproj index 374c8164a5b..b68a4d941dc 100644 --- a/vsintegration/tests/FSharp.Editor.IntegrationTests/FSharp.Editor.IntegrationTests.csproj +++ b/vsintegration/tests/FSharp.Editor.IntegrationTests/FSharp.Editor.IntegrationTests.csproj @@ -27,12 +27,12 @@ - - - - - - + + + + + + diff --git a/vsintegration/tests/FSharp.Editor.Tests/FSharp.Editor.Tests.fsproj b/vsintegration/tests/FSharp.Editor.Tests/FSharp.Editor.Tests.fsproj index 00cf656ed40..ecce1205b8c 100644 --- a/vsintegration/tests/FSharp.Editor.Tests/FSharp.Editor.Tests.fsproj +++ b/vsintegration/tests/FSharp.Editor.Tests/FSharp.Editor.Tests.fsproj @@ -92,12 +92,12 @@ - - + + - - - + + + @@ -106,11 +106,11 @@ - - - - - + + + + + diff --git a/vsintegration/tests/Salsa/VisualFSharp.Salsa.fsproj b/vsintegration/tests/Salsa/VisualFSharp.Salsa.fsproj index 83d89379565..1dd626fc421 100644 --- a/vsintegration/tests/Salsa/VisualFSharp.Salsa.fsproj +++ b/vsintegration/tests/Salsa/VisualFSharp.Salsa.fsproj @@ -53,14 +53,14 @@ - - - - - - - - + + + + + + + + diff --git a/vsintegration/tests/UnitTests/VisualFSharp.UnitTests.fsproj b/vsintegration/tests/UnitTests/VisualFSharp.UnitTests.fsproj index 8501351f46f..7e5640241fd 100644 --- a/vsintegration/tests/UnitTests/VisualFSharp.UnitTests.fsproj +++ b/vsintegration/tests/UnitTests/VisualFSharp.UnitTests.fsproj @@ -117,19 +117,19 @@ - - + + - - - - - - - - - - + + + + + + + + + + From d89529c5625350ac93562c665061ea3dcfd6b689 Mon Sep 17 00:00:00 2001 From: kerams Date: Tue, 4 Aug 2026 12:45:06 +0200 Subject: [PATCH 33/33] Implement direct delegates (#19993) --- .../.FSharp.Compiler.Service/11.0.100.md | 1 + docs/release-notes/.Language/preview.md | 5 + src/Compiler/CodeGen/IlxGen.fs | 374 ++++-- src/Compiler/FSComp.txt | 1 + src/Compiler/FSharp.Compiler.Service.fsproj | 1 + src/Compiler/Facilities/LanguageFeatures.fs | 3 + src/Compiler/Facilities/LanguageFeatures.fsi | 1 + src/Compiler/Optimize/DelegateForwarding.fs | 295 +++++ src/Compiler/Optimize/Optimizer.fs | 53 +- src/Compiler/xlf/FSComp.txt.cs.xlf | 5 + src/Compiler/xlf/FSComp.txt.de.xlf | 5 + src/Compiler/xlf/FSComp.txt.es.xlf | 5 + src/Compiler/xlf/FSComp.txt.fr.xlf | 5 + src/Compiler/xlf/FSComp.txt.it.xlf | 5 + src/Compiler/xlf/FSComp.txt.ja.xlf | 5 + src/Compiler/xlf/FSComp.txt.ko.xlf | 5 + src/Compiler/xlf/FSComp.txt.pl.xlf | 5 + src/Compiler/xlf/FSComp.txt.pt-BR.xlf | 5 + src/Compiler/xlf/FSComp.txt.ru.xlf | 5 + src/Compiler/xlf/FSComp.txt.tr.xlf | 5 + src/Compiler/xlf/FSComp.txt.zh-Hans.xlf | 5 + src/Compiler/xlf/FSComp.txt.zh-Hant.xlf | 5 + .../DirectDelegates/DelegateCustomType.fs | 42 + ...teCustomType.fs.OptimizeOff.Preview.il.bsl | 348 ++++++ .../DelegateCustomType.fs.OptimizeOff.il.bsl | 414 +++++++ ...ateCustomType.fs.OptimizeOn.Preview.il.bsl | 282 +++++ .../DelegateCustomType.fs.OptimizeOn.il.bsl | 378 ++++++ .../DelegateExtensionMethod.fs | 22 + ...ensionMethod.fs.OptimizeOff.Preview.il.bsl | 138 +++ ...egateExtensionMethod.fs.OptimizeOff.il.bsl | 138 +++ ...tensionMethod.fs.OptimizeOn.Preview.il.bsl | 105 ++ ...legateExtensionMethod.fs.OptimizeOn.il.bsl | 121 ++ .../DelegateGenericInstanceMethod.fs | 13 + ...stanceMethod.fs.OptimizeOff.Preview.il.bsl | 179 +++ ...enericInstanceMethod.fs.OptimizeOff.il.bsl | 179 +++ ...nstanceMethod.fs.OptimizeOn.Preview.il.bsl | 111 ++ ...GenericInstanceMethod.fs.OptimizeOn.il.bsl | 139 +++ .../DelegateGenericStaticMethod.fs | 16 + ...StaticMethod.fs.OptimizeOff.Preview.il.bsl | 152 +++ ...eGenericStaticMethod.fs.OptimizeOff.il.bsl | 171 +++ ...cStaticMethod.fs.OptimizeOn.Preview.il.bsl | 114 ++ ...teGenericStaticMethod.fs.OptimizeOn.il.bsl | 156 +++ .../DirectDelegates/DelegateILMethod.fs | 15 + ...gateILMethod.fs.OptimizeOff.Preview.il.bsl | 127 ++ .../DelegateILMethod.fs.OptimizeOff.il.bsl | 127 ++ ...egateILMethod.fs.OptimizeOn.Preview.il.bsl | 78 ++ .../DelegateILMethod.fs.OptimizeOn.il.bsl | 127 ++ .../DirectDelegates/DelegateInstanceMethod.fs | 21 + ...stanceMethod.fs.OptimizeOff.Preview.il.bsl | 228 ++++ ...legateInstanceMethod.fs.OptimizeOff.il.bsl | 295 +++++ ...nstanceMethod.fs.OptimizeOn.Preview.il.bsl | 148 +++ ...elegateInstanceMethod.fs.OptimizeOn.il.bsl | 223 ++++ .../DirectDelegates/DelegateKnownFunction.fs | 20 + ...nownFunction.fs.OptimizeOff.Preview.il.bsl | 190 +++ ...elegateKnownFunction.fs.OptimizeOff.il.bsl | 209 ++++ ...KnownFunction.fs.OptimizeOn.Preview.il.bsl | 145 +++ ...DelegateKnownFunction.fs.OptimizeOn.il.bsl | 187 +++ .../DirectDelegates/DelegateNegativeCases.fs | 42 + ...egativeCases.fs.OptimizeOff.Preview.il.bsl | 361 ++++++ ...elegateNegativeCases.fs.OptimizeOff.il.bsl | 361 ++++++ ...NegativeCases.fs.OptimizeOn.Preview.il.bsl | 323 +++++ ...DelegateNegativeCases.fs.OptimizeOn.il.bsl | 323 +++++ .../DelegatePartialApplication.fs | 32 + ...lApplication.fs.OptimizeOff.Preview.il.bsl | 270 ++++ ...tePartialApplication.fs.OptimizeOff.il.bsl | 270 ++++ ...alApplication.fs.OptimizeOn.Preview.il.bsl | 195 +++ ...atePartialApplication.fs.OptimizeOn.il.bsl | 195 +++ .../DirectDelegates/DelegateStaticMethod.fs | 21 + ...StaticMethod.fs.OptimizeOff.Preview.il.bsl | 196 +++ ...DelegateStaticMethod.fs.OptimizeOff.il.bsl | 215 ++++ ...eStaticMethod.fs.OptimizeOn.Preview.il.bsl | 151 +++ .../DelegateStaticMethod.fs.OptimizeOn.il.bsl | 193 +++ .../DirectDelegates/DelegateStructTarget.fs | 16 + ...StructTarget.fs.OptimizeOff.Preview.il.bsl | 281 +++++ ...DelegateStructTarget.fs.OptimizeOff.il.bsl | 316 +++++ ...eStructTarget.fs.OptimizeOn.Preview.il.bsl | 219 ++++ .../DelegateStructTarget.fs.OptimizeOn.il.bsl | 251 ++++ .../DirectDelegates/DelegateUnitArg.fs | 20 + ...egateUnitArg.fs.OptimizeOff.Preview.il.bsl | 176 +++ .../DelegateUnitArg.fs.OptimizeOff.il.bsl | 225 ++++ ...legateUnitArg.fs.OptimizeOn.Preview.il.bsl | 130 ++ .../DelegateUnitArg.fs.OptimizeOn.il.bsl | 182 +++ .../DirectDelegates/DelegateUnitReturn.fs | 25 + ...teUnitReturn.fs.OptimizeOff.Preview.il.bsl | 158 +++ .../DelegateUnitReturn.fs.OptimizeOff.il.bsl | 192 +++ ...ateUnitReturn.fs.OptimizeOn.Preview.il.bsl | 124 ++ .../DelegateUnitReturn.fs.OptimizeOn.il.bsl | 180 +++ .../DirectDelegates/DirectDelegates.fs | 1094 +++++++++++++++++ .../FSharp.Compiler.ComponentTests.fsproj | 1 + .../Language/CodeQuotationTests.fs | 36 + .../ProjectGeneration.fs | 27 +- 91 files changed, 12841 insertions(+), 117 deletions(-) create mode 100644 src/Compiler/Optimize/DelegateForwarding.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateCustomType.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateCustomType.fs.OptimizeOff.Preview.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateCustomType.fs.OptimizeOff.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateCustomType.fs.OptimizeOn.Preview.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateCustomType.fs.OptimizeOn.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateExtensionMethod.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateExtensionMethod.fs.OptimizeOff.Preview.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateExtensionMethod.fs.OptimizeOff.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateExtensionMethod.fs.OptimizeOn.Preview.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateExtensionMethod.fs.OptimizeOn.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericInstanceMethod.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericInstanceMethod.fs.OptimizeOff.Preview.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericInstanceMethod.fs.OptimizeOff.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericInstanceMethod.fs.OptimizeOn.Preview.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericInstanceMethod.fs.OptimizeOn.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericStaticMethod.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericStaticMethod.fs.OptimizeOff.Preview.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericStaticMethod.fs.OptimizeOff.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericStaticMethod.fs.OptimizeOn.Preview.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericStaticMethod.fs.OptimizeOn.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateILMethod.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateILMethod.fs.OptimizeOff.Preview.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateILMethod.fs.OptimizeOff.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateILMethod.fs.OptimizeOn.Preview.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateILMethod.fs.OptimizeOn.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateInstanceMethod.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateInstanceMethod.fs.OptimizeOff.Preview.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateInstanceMethod.fs.OptimizeOff.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateInstanceMethod.fs.OptimizeOn.Preview.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateInstanceMethod.fs.OptimizeOn.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateKnownFunction.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateKnownFunction.fs.OptimizeOff.Preview.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateKnownFunction.fs.OptimizeOff.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateKnownFunction.fs.OptimizeOn.Preview.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateKnownFunction.fs.OptimizeOn.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateNegativeCases.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateNegativeCases.fs.OptimizeOff.Preview.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateNegativeCases.fs.OptimizeOff.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateNegativeCases.fs.OptimizeOn.Preview.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateNegativeCases.fs.OptimizeOn.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegatePartialApplication.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegatePartialApplication.fs.OptimizeOff.Preview.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegatePartialApplication.fs.OptimizeOff.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegatePartialApplication.fs.OptimizeOn.Preview.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegatePartialApplication.fs.OptimizeOn.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateStaticMethod.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateStaticMethod.fs.OptimizeOff.Preview.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateStaticMethod.fs.OptimizeOff.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateStaticMethod.fs.OptimizeOn.Preview.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateStaticMethod.fs.OptimizeOn.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateStructTarget.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateStructTarget.fs.OptimizeOff.Preview.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateStructTarget.fs.OptimizeOff.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateStructTarget.fs.OptimizeOn.Preview.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateStructTarget.fs.OptimizeOn.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateUnitArg.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateUnitArg.fs.OptimizeOff.Preview.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateUnitArg.fs.OptimizeOff.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateUnitArg.fs.OptimizeOn.Preview.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateUnitArg.fs.OptimizeOn.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateUnitReturn.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateUnitReturn.fs.OptimizeOff.Preview.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateUnitReturn.fs.OptimizeOff.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateUnitReturn.fs.OptimizeOn.Preview.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateUnitReturn.fs.OptimizeOn.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DirectDelegates.fs diff --git a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md index b1d9f90f210..52698cc182b 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md +++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md @@ -153,6 +153,7 @@ ### Improved * Nullness warning FS3261 on dotted method or property access (e.g. `x.Member`) now underlines the receiver expression and includes the member name and (when known) the binding name in the message. ([Issue #19658](https://github.com/dotnet/fsharp/issues/19658), [PR #19814](https://github.com/dotnet/fsharp/pull/19814)) +* Direct delegate construction ([PR ##19993](https://github.com/dotnet/fsharp/pull/19993)) ### Changed diff --git a/docs/release-notes/.Language/preview.md b/docs/release-notes/.Language/preview.md index d48e49c4e21..30df5427619 100644 --- a/docs/release-notes/.Language/preview.md +++ b/docs/release-notes/.Language/preview.md @@ -11,3 +11,8 @@ ### Fixed ### Changed + +* Direct delegate construction ([PR #19993](https://github.com/dotnet/fsharp/pull/19993)) + * A delegate built from a method or function now points straight at that method instead of an intermediate closure, so `delegate.Method` is the real target and no closure class is generated. + * Two delegates built from the same method and target now compare equal, where the previous closure form produced distinct instances; this also makes `Delegate.Remove` (and `-=` on events) match and remove such a delegate that it previously left in place. + * A `null` instance receiver now faults at delegate construction rather than at the first invoke: an `ArgumentException` for a non-virtual target (the delegate constructor rejects a null `this`) or a `NullReferenceException` for a virtual one (from `ldvirtftn`), matching how C# builds the same delegate. diff --git a/src/Compiler/CodeGen/IlxGen.fs b/src/Compiler/CodeGen/IlxGen.fs index a6aa05c4035..c4fbea22a66 100644 --- a/src/Compiler/CodeGen/IlxGen.fs +++ b/src/Compiler/CodeGen/IlxGen.fs @@ -25,6 +25,7 @@ open FSharp.Compiler.AbstractIL.ILX open FSharp.Compiler.AbstractIL.ILX.Types open FSharp.Compiler.AttributeChecking open FSharp.Compiler.CompilerGlobalState +open FSharp.Compiler.DelegateForwarding open FSharp.Compiler.DiagnosticsLogger open FSharp.Compiler.Features open FSharp.Compiler.Infos @@ -7524,136 +7525,303 @@ and GenDelegateExpr cenv cgbuf eenvouter expr (TObjExprMethod(slotsig, _attribs, with _ -> false - // Work out the free type variables for the morphing thunk - let takenNames = List.map nameOfVal tmvs + let invokeParamInfos = + List.replicate (List.concat slotsig.FormalParams).Length ValReprInfo.unnamedTopArg1 - let cloFreeTyvars, cloWitnessInfos, cloFreeVars, ilDelegeeTypeRef, ilCloAllFreeVars, eenvinner = - GetIlxClosureFreeVars cenv m [] ILBoxity.AsObject eenvouter takenNames expr + let numDelegeeParams = invokeParamInfos.Length - let ilDelegeeGenericParams = GenGenericParams cenv eenvinner cloFreeTyvars - let ilDelegeeGenericActualsInner = mkILFormalGenericArgs 0 ilDelegeeGenericParams + let etaUnitDelegate = + match tmvs, invokeParamInfos with + | [ _ ], [] -> true + | _ -> false - // When creating a delegate that does not capture any variables, we can instead create a static closure and directly reference the method. - let useStaticClosure = cloFreeVars.IsEmpty + let tmvs, body = BindUnitVars g (tmvs, invokeParamInfos, body) - // Create a new closure class with a single "delegee" method that implements the delegate. - let delegeeMethName = "Invoke" - let ilDelegeeTyInner = mkILBoxedTy ilDelegeeTypeRef ilDelegeeGenericActualsInner + // Point the delegate directly at a recognized transparent-forwarding target instead of generating an + // intermediate closure; anything unmatched falls back to the closure path below. + let directDelegateTarget = + if not (g.langVersion.SupportsFeature LanguageFeature.DirectDelegateConstruction) then + None + elif + not cenv.options.localOptimizationsEnabled + && (etaUnitDelegate || tmvs |> List.exists (fun v -> not v.IsCompilerGenerated)) + then + // Keep eta-expanded delegates as closures in unoptimized builds so the user's lambda parameter + // names survive for debugging; non-eta parameters are synthesized, so nothing is lost there. + None + else + match classifyForwardingTarget (Optimizer.ExprHasEffect Optimizer.EffectContext.Emit) g tmvs body with + | DirectDelegateForwardingTargetCandidate.FSharpVal(vref, valUseFlags, tyargs, leadingArgs) -> + match StorageForValRef m vref eenvouter with + | Method(valReprInfo, vrefM, mspec, _, _, ctps, _, _, _, _, _, _) -> + let _, witnessInfos, _, _, _ = + GetValReprTypeInCompiledForm g valReprInfo ctps.Length vrefM.Type m - let envForDelegeeUnderTypars = AddTyparsToEnv methTyparsOfOverridingMethod eenvinner + let hasWitnesses = ComputeGenerateWitnesses g eenvouter && not witnessInfos.IsEmpty - let numthis = if useStaticClosure then 0 else 1 + match + fsharpValDirectlyBindable + (Optimizer.ExprHasEffect Optimizer.EffectContext.Emit) + g + tmvs + leadingArgs + vrefM + valUseFlags + hasWitnesses + with + | ValueSome(virtualCall, takesInstanceArg) -> + let ilTyArgs = GenTypeArgs cenv m eenvouter.tyenv tyargs - let tmvs, body = - BindUnitVars g (tmvs, List.replicate (List.concat slotsig.FormalParams).Length ValReprInfo.unnamedTopArg1, body) + let numEnclILTypeArgs = + if vrefM.MemberInfo.IsSome && not vrefM.IsExtensionMember then + List.length (vrefM.MemberApparentEntity.Typars |> DropErasedTypars) + else + 0 - // The slot sig contains a formal instantiation. When creating delegates we're only - // interested in the actual instantiation since we don't have to emit a method impl. - let ilDelegeeParams, ilDelegeeRet = - GenActualSlotsig m cenv envForDelegeeUnderTypars slotsig methTyparsOfOverridingMethod tmvs + if ilTyArgs.Length < numEnclILTypeArgs then + None + else + let ilEnclArgTys, ilMethArgTys = List.splitAt numEnclILTypeArgs ilTyArgs - let envForDelegeeMeth = - AddStorageForLocalVals g (List.mapi (fun i v -> (v, Arg(i + numthis))) tmvs) envForDelegeeUnderTypars + let targetMspec = + mkILMethSpec (mspec.MethodRef, mspec.DeclaringType.Boxity, ilEnclArgTys, ilMethArgTys) - let ilMethodBody = - CodeGenMethodForExpr - cenv - cgbuf.mgbuf - ([], - delegeeMethName, - envForDelegeeMeth, - 1, - None, - body, - (if slotSigHasVoidReturnTy slotsig then - discardAndReturnVoid - else - Return)) + let numBoundLeadingFormals = if takesInstanceArg then 0 else leadingArgs.Length - let delegeeInvokeMeth = - (if useStaticClosure then - mkILNonGenericStaticMethod - else - mkILNonGenericInstanceMethod) ( - delegeeMethName, - ILMemberAccess.Assembly, - ilDelegeeParams, - ilDelegeeRet, - MethodBody.IL(InterruptibleLazy.FromValue ilMethodBody) - ) + if takesInstanceArg <> targetMspec.MethodRef.CallingConv.IsInstance then + None + else + let ilDelegeeRetTy = + let envUnderTypars = AddTyparsToEnv methTyparsOfOverridingMethod eenvouter - let delegeeCtorMeth = - mkILSimpleStorageCtor (Some g.ilg.typ_Object.TypeSpec, ilDelegeeTyInner, [], [], ILMemberAccess.Assembly, None, eenvouter.imports) + let _, ilDelegeeRet = + GenActualSlotsig m cenv envUnderTypars slotsig methTyparsOfOverridingMethod tmvs - let ilCtorBody = delegeeCtorMeth.MethodBody + ilDelegeeRet.Type - let ilCloLambdas = Lambdas_return ilCtxtDelTy + if + signatureMatches + numBoundLeadingFormals + numDelegeeParams + ilDelegeeRetTy + ilEnclArgTys + ilMethArgTys + targetMspec + then + Some(targetMspec, receiverInfo leadingArgs virtualCall takesInstanceArg) + else + None + | ValueNone -> None + | _ -> None - let cloTypeDefs = - (if useStaticClosure then - GenStaticDelegateClosureTypeDefs - else - GenClosureTypeDefs) - cenv - (ilDelegeeTypeRef, - ilDelegeeGenericParams, - [], - ilCloAllFreeVars, - ilCloLambdas, - ilCtorBody, - [ delegeeInvokeMeth ], - [], - g.ilg.typ_Object, - [], - None) + | DirectDelegateForwardingTargetCandidate.ILMethod(isVirtual, + isStruct, + isCtor, + valUseFlag, + ilMethRef, + enclTypeInst, + methInst, + leadingArgs) -> + if + ilMethodDirectlyBindable + (Optimizer.ExprHasEffect Optimizer.EffectContext.Emit) + g + tmvs + leadingArgs + ilMethRef + valUseFlag + isCtor + then + let ilEnclArgTys = GenTypeArgs cenv m eenvouter.tyenv enclTypeInst + let ilMethArgTys = GenTypeArgs cenv m eenvouter.tyenv methInst + let boxity = if isStruct then AsValue else AsObject + let targetMspec = mkILMethSpec (ilMethRef, boxity, ilEnclArgTys, ilMethArgTys) + + let numBoundLeadingFormals = + if ilMethRef.CallingConv.IsInstance then + 0 + else + leadingArgs.Length - for cloTypeDef in cloTypeDefs do - cgbuf.mgbuf.AddTypeDef(ilDelegeeTypeRef, cloTypeDef, false, false, None, m) + // Imported metadata carries different assembly scope refs than the compiler-generated + // delegee types, so structural IL type comparison reports false negatives even for + // primitives; the arity check is the sound residual guard (the call is already typed). + if targetMspec.FormalArgTypes.Length - numBoundLeadingFormals = numDelegeeParams then + Some(targetMspec, receiverInfo leadingArgs isVirtual ilMethRef.CallingConv.IsInstance) + else + None + else + None - CountClosure() + | DirectDelegateForwardingTargetCandidate.Other -> None - // Push the constructor for the delegee - let ctxtGenericArgsForDelegee = GenGenericArgs m eenvouter.tyenv cloFreeTyvars + match directDelegateTarget with + | Some(targetMspec, receiverInfo) -> + match receiverInfo with + | None -> + // Static target: null Target. + GenUnit cenv eenvouter m cgbuf + CG.EmitInstr cgbuf (pop 0) (Push [ g.ilg.typ_IntPtr ]) (I_ldftn targetMspec) + | Some(receiverExpr, isVirtual, isInstanceReceiver) -> + // The leading argument becomes the Target: an instance receiver, or a static method's closed-over first argument. + GenExpr cenv cgbuf eenvouter receiverExpr Continue + + if isInstanceReceiver && targetMspec.DeclaringType.Boxity.IsAsValue then + // Box a copy of a value-type instance receiver as the 'object' Target; invocation reaches 'this' + // through the runtime's unboxing stub, matching the closure's by-value capture. Only an instance + // receiver is boxed - a static closed-over first argument is already a reference. + CG.EmitInstr cgbuf (pop 1) (Push [ g.ilg.typ_Object ]) (I_box targetMspec.DeclaringType) + + if isVirtual then + // dup the receiver so ldvirtftn can bind its runtime type's override. + CG.EmitInstr cgbuf (pop 0) (Push [ targetMspec.DeclaringType ]) AI_dup + CG.EmitInstr cgbuf (pop 1) (Push [ g.ilg.typ_IntPtr ]) (I_ldvirtftn targetMspec) + else + CG.EmitInstr cgbuf (pop 0) (Push [ g.ilg.typ_IntPtr ]) (I_ldftn targetMspec) - if useStaticClosure then - GenUnit cenv eenvouter m cgbuf - else - let ilxCloSpec = - IlxClosureSpec.Create(IlxClosureRef(ilDelegeeTypeRef, ilCloLambdas, ilCloAllFreeVars), ctxtGenericArgsForDelegee, false) + // newobj Delegate::.ctor(object, native int) + let ilDelegeeCtorMethOuter = + mkCtorMethSpecForDelegate g.ilg (ilCtxtDelTy, useUIntPtrForDelegateCtor) - GenWitnessArgsFromWitnessInfos cenv cgbuf eenvouter m cloWitnessInfos + CG.EmitInstr cgbuf (pop 2) (Push [ ilCtxtDelTy ]) (I_newobj(ilDelegeeCtorMethOuter, None)) + GenSequel cenv eenvouter.cloc cgbuf sequel - for fv in cloFreeVars do - GenGetFreeVarForClosure cenv cgbuf eenvouter m fv + | None -> + let takenNames = List.map nameOfVal tmvs - CG.EmitInstr - cgbuf - (pop ilCloAllFreeVars.Length) - (Push [ EraseClosures.mkTyOfLambdas cenv.ilxPubCloEnv ilCloLambdas ]) - (I_newobj(ilxCloSpec.Constructor, None)) + // Work out the free type variables for the morphing thunk + let cloFreeTyvars, cloWitnessInfos, cloFreeVars, ilDelegeeTypeRef, ilCloAllFreeVars, eenvinner = + GetIlxClosureFreeVars cenv m [] ILBoxity.AsObject eenvouter takenNames expr - // Push the function pointer to the Invoke method of the delegee - let ilDelegeeTyOuter = mkILBoxedTy ilDelegeeTypeRef ctxtGenericArgsForDelegee + let ilDelegeeGenericParams = GenGenericParams cenv eenvinner cloFreeTyvars + let ilDelegeeGenericActualsInner = mkILFormalGenericArgs 0 ilDelegeeGenericParams - let ilDelegeeInvokeMethOuter = - (if useStaticClosure then - mkILNonGenericStaticMethSpecInTy - else - mkILNonGenericInstanceMethSpecInTy) ( - ilDelegeeTyOuter, - "Invoke", - typesOfILParams ilDelegeeParams, - ilDelegeeRet.Type - ) + // When creating a delegate that does not capture any variables, we can instead create a static closure and directly reference the method. + let useStaticClosure = cloFreeVars.IsEmpty - CG.EmitInstr cgbuf (pop 0) (Push [ g.ilg.typ_IntPtr ]) (I_ldftn ilDelegeeInvokeMethOuter) + // Create a new closure class with a single "delegee" method that implements the delegate. + let delegeeMethName = "Invoke" + let ilDelegeeTyInner = mkILBoxedTy ilDelegeeTypeRef ilDelegeeGenericActualsInner - // Instantiate the delegate - let ilDelegeeCtorMethOuter = - mkCtorMethSpecForDelegate g.ilg (ilCtxtDelTy, useUIntPtrForDelegateCtor) + let envForDelegeeUnderTypars = AddTyparsToEnv methTyparsOfOverridingMethod eenvinner - CG.EmitInstr cgbuf (pop 2) (Push [ ilCtxtDelTy ]) (I_newobj(ilDelegeeCtorMethOuter, None)) - GenSequel cenv eenvouter.cloc cgbuf sequel + let numthis = if useStaticClosure then 0 else 1 + + // The slot sig contains a formal instantiation. When creating delegates we're only + // interested in the actual instantiation since we don't have to emit a method impl. + let ilDelegeeParams, ilDelegeeRet = + GenActualSlotsig m cenv envForDelegeeUnderTypars slotsig methTyparsOfOverridingMethod tmvs + + let envForDelegeeMeth = + AddStorageForLocalVals g (List.mapi (fun i v -> (v, Arg(i + numthis))) tmvs) envForDelegeeUnderTypars + + let ilMethodBody = + CodeGenMethodForExpr + cenv + cgbuf.mgbuf + ([], + delegeeMethName, + envForDelegeeMeth, + 1, + None, + body, + (if slotSigHasVoidReturnTy slotsig then + discardAndReturnVoid + else + Return)) + + let delegeeInvokeMeth = + (if useStaticClosure then + mkILNonGenericStaticMethod + else + mkILNonGenericInstanceMethod) ( + delegeeMethName, + ILMemberAccess.Assembly, + ilDelegeeParams, + ilDelegeeRet, + MethodBody.IL(InterruptibleLazy.FromValue ilMethodBody) + ) + + let delegeeCtorMeth = + mkILSimpleStorageCtor ( + Some g.ilg.typ_Object.TypeSpec, + ilDelegeeTyInner, + [], + [], + ILMemberAccess.Assembly, + None, + eenvouter.imports + ) + + let ilCtorBody = delegeeCtorMeth.MethodBody + + let ilCloLambdas = Lambdas_return ilCtxtDelTy + + let cloTypeDefs = + (if useStaticClosure then + GenStaticDelegateClosureTypeDefs + else + GenClosureTypeDefs) + cenv + (ilDelegeeTypeRef, + ilDelegeeGenericParams, + [], + ilCloAllFreeVars, + ilCloLambdas, + ilCtorBody, + [ delegeeInvokeMeth ], + [], + g.ilg.typ_Object, + [], + None) + + for cloTypeDef in cloTypeDefs do + cgbuf.mgbuf.AddTypeDef(ilDelegeeTypeRef, cloTypeDef, false, false, None, m) + + CountClosure() + + // Push the constructor for the delegee + let ctxtGenericArgsForDelegee = GenGenericArgs m eenvouter.tyenv cloFreeTyvars + + if useStaticClosure then + GenUnit cenv eenvouter m cgbuf + else + let ilxCloSpec = + IlxClosureSpec.Create(IlxClosureRef(ilDelegeeTypeRef, ilCloLambdas, ilCloAllFreeVars), ctxtGenericArgsForDelegee, false) + + GenWitnessArgsFromWitnessInfos cenv cgbuf eenvouter m cloWitnessInfos + + for fv in cloFreeVars do + GenGetFreeVarForClosure cenv cgbuf eenvouter m fv + + CG.EmitInstr + cgbuf + (pop ilCloAllFreeVars.Length) + (Push [ EraseClosures.mkTyOfLambdas cenv.ilxPubCloEnv ilCloLambdas ]) + (I_newobj(ilxCloSpec.Constructor, None)) + + // Push the function pointer to the Invoke method of the delegee + let ilDelegeeTyOuter = mkILBoxedTy ilDelegeeTypeRef ctxtGenericArgsForDelegee + + let ilDelegeeInvokeMethOuter = + (if useStaticClosure then + mkILNonGenericStaticMethSpecInTy + else + mkILNonGenericInstanceMethSpecInTy) ( + ilDelegeeTyOuter, + "Invoke", + typesOfILParams ilDelegeeParams, + ilDelegeeRet.Type + ) + + CG.EmitInstr cgbuf (pop 0) (Push [ g.ilg.typ_IntPtr ]) (I_ldftn ilDelegeeInvokeMethOuter) + + // Instantiate the delegate + let ilDelegeeCtorMethOuter = + mkCtorMethSpecForDelegate g.ilg (ilCtxtDelTy, useUIntPtrForDelegateCtor) + + CG.EmitInstr cgbuf (pop 2) (Push [ ilCtxtDelTy ]) (I_newobj(ilDelegeeCtorMethOuter, None)) + GenSequel cenv eenvouter.cloc cgbuf sequel /// Used to search FSharp.Core implementations of "^T : ^T" and decide whether the conditional activates and ExprIsTraitCall expr = diff --git a/src/Compiler/FSComp.txt b/src/Compiler/FSComp.txt index fab84a56510..68a2764b197 100644 --- a/src/Compiler/FSComp.txt +++ b/src/Compiler/FSComp.txt @@ -1824,6 +1824,7 @@ featurePreprocessorElif,"#elif preprocessor directive" featureExceptionFieldSerializationSupport,"emit GetObjectData and field-restoring deserialization constructor for exception types" featureErrorOnMissingSignatureAttribute,"error (rather than warning) when an enforced compiler-semantic attribute is present in the .fs but missing from the .fsi" featureNotNullIfNotNull,"honor the 'NotNullIfNotNull' attribute on a method's return value" +featureDirectDelegateConstruction,"construct delegates that point directly at the target method, avoiding an intermediate closure" featureAccessProtectedBaseFieldFromClosure,"Access a protected base-class field from a closure inside a member" featureImprovedImpliedArgumentNamesPartTwo,"Improved implied argument names with partial application" 3891,tcRecordTypeDefinitionSpreadSourceMustBeRecord,"The source type of a spread into a record type definition must itself be a nominal or anonymous record type." diff --git a/src/Compiler/FSharp.Compiler.Service.fsproj b/src/Compiler/FSharp.Compiler.Service.fsproj index 6e623f0654e..bdaf5999a16 100644 --- a/src/Compiler/FSharp.Compiler.Service.fsproj +++ b/src/Compiler/FSharp.Compiler.Service.fsproj @@ -424,6 +424,7 @@ + diff --git a/src/Compiler/Facilities/LanguageFeatures.fs b/src/Compiler/Facilities/LanguageFeatures.fs index 0941e4b49a8..c4f81878f8d 100644 --- a/src/Compiler/Facilities/LanguageFeatures.fs +++ b/src/Compiler/Facilities/LanguageFeatures.fs @@ -110,6 +110,7 @@ type LanguageFeature = | ExceptionFieldSerializationSupport | ErrorOnMissingSignatureAttribute | NotNullIfNotNull + | DirectDelegateConstruction | AccessProtectedBaseFieldFromClosure | ImprovedImpliedArgumentNamesPartTwo | RecordSpreads @@ -267,6 +268,7 @@ type LanguageVersion(versionText, ?disabledFeaturesArray: LanguageFeature array) LanguageFeature.MethodOverloadsCache, previewVersion // Performance optimization for overload resolution LanguageFeature.ImplicitDIMCoverage, languageVersion110 LanguageFeature.ErrorOnMissingSignatureAttribute, previewVersion // Opt-in: turn FS3888 from warning into error + LanguageFeature.DirectDelegateConstruction, previewVersion LanguageFeature.AccessProtectedBaseFieldFromClosure, previewVersion // #5302: read a protected base field from a closure LanguageFeature.RecordSpreads, previewVersion ] @@ -465,6 +467,7 @@ type LanguageVersion(versionText, ?disabledFeaturesArray: LanguageFeature array) | LanguageFeature.ExceptionFieldSerializationSupport -> FSComp.SR.featureExceptionFieldSerializationSupport () | LanguageFeature.ErrorOnMissingSignatureAttribute -> FSComp.SR.featureErrorOnMissingSignatureAttribute () | LanguageFeature.NotNullIfNotNull -> FSComp.SR.featureNotNullIfNotNull () + | LanguageFeature.DirectDelegateConstruction -> FSComp.SR.featureDirectDelegateConstruction () | LanguageFeature.AccessProtectedBaseFieldFromClosure -> FSComp.SR.featureAccessProtectedBaseFieldFromClosure () | LanguageFeature.ImprovedImpliedArgumentNamesPartTwo -> FSComp.SR.featureImprovedImpliedArgumentNamesPartTwo () | LanguageFeature.RecordSpreads -> FSComp.SR.featureRecordSpreads () diff --git a/src/Compiler/Facilities/LanguageFeatures.fsi b/src/Compiler/Facilities/LanguageFeatures.fsi index a0c226f222c..d0b97987137 100644 --- a/src/Compiler/Facilities/LanguageFeatures.fsi +++ b/src/Compiler/Facilities/LanguageFeatures.fsi @@ -101,6 +101,7 @@ type LanguageFeature = | ExceptionFieldSerializationSupport | ErrorOnMissingSignatureAttribute | NotNullIfNotNull + | DirectDelegateConstruction | AccessProtectedBaseFieldFromClosure | ImprovedImpliedArgumentNamesPartTwo | RecordSpreads diff --git a/src/Compiler/Optimize/DelegateForwarding.fs b/src/Compiler/Optimize/DelegateForwarding.fs new file mode 100644 index 00000000000..efa0fdfe9b3 --- /dev/null +++ b/src/Compiler/Optimize/DelegateForwarding.fs @@ -0,0 +1,295 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +/// Recognition of delegate constructions whose Invoke body is a transparent forwarding call to a known +/// method, shared by the optimizer (which preserves the call from inlining) and the ILX generator (which +/// points the delegate directly at the target). The 'exprHasEffect' parameter is Optimizer.ExprHasEffect; +/// it is passed in because this file compiles before the optimizer. +module internal FSharp.Compiler.DelegateForwarding + +open Internal.Utilities.Collections + +open FSharp.Compiler.AbstractIL.IL +open FSharp.Compiler.Text +open FSharp.Compiler.TcGlobals +open FSharp.Compiler.TypedTree +open FSharp.Compiler.TypedTreeBasics +open FSharp.Compiler.TypedTreeOps + +/// A delegate target that can potentially be forwarded to directly, without an intermediate closure +[] +type DirectDelegateForwardingTargetCandidate = + /// A known F# value: a module-level function or a member + | FSharpVal of vref: ValRef * valUseFlags: ValUseFlag * tyargs: TypeInst * leadingArgs: Expr list + /// A direct IL method call (e.g. a BCL method) + | ILMethod of + isVirtual: bool * + isStruct: bool * + isCtor: bool * + valUseFlags: ValUseFlag * + ilMethRef: ILMethodRef * + enclTypeInst: TypeInst * + methInst: TypeInst * + leadingArgs: Expr list + | Other + +let private isUnitValue e = + match stripDebugPoints e with + | Expr.Const(Const.Unit, _, _) -> true + | _ -> false + +// Mirror the code generator's arity-based de-tupling (a tupled argument group is one tuple node in the +// call but separate IL parameters in the compiled target) so the match sees the flattened argument list. +// The group count must equal the target's arity exactly: fewer is a partial application, more an +// over-application whose trailing arguments are consumed by the target's *result*, and a target without +// arity information has no compiled method to point at. +let private tryFlattenTupledArgs (vref: ValRef) (args: Expr list) = + let arities = (arityOfVal vref.Deref).AritiesOfArgs + + if arities.Length <> args.Length then + None + else + (arities, args) + ||> List.map2 (fun arity arg -> + match stripDebugPoints arg with + | Expr.Op(TOp.Tuple _, _, elems, _) when arity >= 2 && elems.Length = arity -> elems + | _ -> [ arg ]) + |> List.concat + |> Some + +let rec private resolveAliases (aliases: ValMap) e = + let e = stripDebugPoints e + + match e with + | Expr.Val(vref, _, _) -> + match aliases.TryFind vref.Deref with + | Some e2 -> resolveAliases aliases e2 + | None -> e + | _ -> e + +// Trailing arguments must be the delegate's Invoke parameters, verbatim and in order; the leading rest +// (e.g. an instance receiver) is resolved and returned for the caller to check and emit. +let private matchForwarding g (aliases: ValMap) (invokeParams: Val list) (args: Expr list) = + let args = args |> List.map (resolveAliases aliases) + + // Drop the elided unit argument when the Invoke takes no parameters. + let args = + match List.tryLast args with + | Some last when List.isEmpty invokeParams && isUnitValue last -> List.truncate (args.Length - 1) args + | _ -> args + + let numLeading = args.Length - invokeParams.Length + + if numLeading >= 0 then + let leadingArgs, forwardedArgs = List.splitAt numLeading args + + if + List.forall2 + (fun (a: Expr) (tv: Val) -> + match a with + | Expr.Val(avref, _, _) -> valRefEq g avref (mkLocalValRef tv) + | _ -> false) + forwardedArgs + invokeParams + then + // A struct receiver arrives by address; recover the value so the emit can box it as the + // Target (invocation reaches 'this' through the runtime's unboxing stub). + let leadingArgs = + leadingArgs + |> List.map (fun a -> + match a with + | Expr.Op(TOp.LValueOp(LAddrOf _, vref), _, _, m) -> resolveAliases aliases (exprForValRef m vref) + | _ -> a) + + Some leadingArgs + else + None + else + None + +// Peel the wrappers the elaborator and BuildNewDelegateExpr leave around the forwarding call: effect-free +// let-bindings, applications of let-wrapped or immediate lambdas (method-group coercions, the shells of +// curried member calls), and curried application nesting. The optimizer reduces these only while already +// making inlining decisions - too late for a recognizer that must precede them - so peel by aliasing: +// each bound value maps to the expression flowing into it, resolved when the arguments are matched. +// Anything else is left in place and fails the match, conservatively keeping the closure. +let rec private stripToForwardingCall exprHasEffect g (aliases: ValMap) expr = + match stripDebugPoints expr with + | Expr.Let(TBind(v, rhs, _), inner, _, _) when not (exprHasEffect g rhs) -> + stripToForwardingCall exprHasEffect g (aliases.Add v rhs) inner + | Expr.App(f, fty, tyargs, args, m) as app -> + match stripDebugPoints f with + | Expr.Let(TBind(v, rhs, _), f2, _, _) when not (exprHasEffect g rhs) -> + stripToForwardingCall exprHasEffect g (aliases.Add v rhs) (Expr.App(f2, fty, tyargs, args, m)) + | Expr.Lambda(_, None, None, [ v ], body, _, _) when List.isEmpty tyargs -> + match args with + | a :: rest when not (exprHasEffect g a) -> + let aliases = aliases.Add v a + + match rest with + | [] -> stripToForwardingCall exprHasEffect g aliases body + | _ -> stripToForwardingCall exprHasEffect g aliases (Expr.App(body, tyOfExpr g body, [], rest, m)) + | _ -> app, aliases + | Expr.App(f2, f2ty, tyargs2, args2, _) when List.isEmpty tyargs -> + stripToForwardingCall exprHasEffect g aliases (Expr.App(f2, f2ty, tyargs2, args2 @ args, m)) + | _ -> app, aliases + | e -> e, aliases + +let classifyForwardingTarget exprHasEffect g (invokeParams: Val list) expr = + let call, aliases = stripToForwardingCall exprHasEffect g ValMap.Empty expr + + match call with + | Expr.App(f, _, tyargs, args, _) -> + match stripDebugPoints f with + | Expr.Val(vref, valUseFlags, _) -> + match + tryFlattenTupledArgs vref args + |> Option.bind (matchForwarding g aliases invokeParams) + with + | Some leadingArgs -> DirectDelegateForwardingTargetCandidate.FSharpVal(vref, valUseFlags, tyargs, leadingArgs) + | None -> DirectDelegateForwardingTargetCandidate.Other + | _ -> DirectDelegateForwardingTargetCandidate.Other + | Expr.Op(TOp.ILCall(isVirtual, _, isStruct, isCtor, valUseFlag, _, _, ilMethRef, enclTypeInst, methInst, _), _, args, _) -> + match matchForwarding g aliases invokeParams args with + | Some leadingArgs -> + DirectDelegateForwardingTargetCandidate.ILMethod( + isVirtual, + isStruct, + isCtor, + valUseFlag, + ilMethRef, + enclTypeInst, + methInst, + leadingArgs + ) + | None -> DirectDelegateForwardingTargetCandidate.Other + | _ -> DirectDelegateForwardingTargetCandidate.Other + +/// At most one leading argument can become the delegate's Target: the receiver of an instance target, or +/// the first parameter of a static one via the CLR's "closed over the first argument" delegate form +/// (extension-member receivers, one-argument partial applications). More has no closed form. +let private receiverShapeOk (leadingArgs: Expr list) takesInstanceArg = + if takesInstanceArg then + match leadingArgs with + | [ _ ] -> true + | _ -> false + else + match leadingArgs with + | [] + | [ _ ] -> true + | _ -> false + +let private staticLeadingArgIsRefType g takesInstanceArg (leadingArgs: Expr list) = + match leadingArgs with + | [ recv ] when not takesInstanceArg -> isRefTy g (tyOfExpr g recv) + | _ -> true + +let private receiverNotByref g (leadingArgs: Expr list) = + match leadingArgs with + | [ recv ] -> not (isByrefTy g (tyOfExpr g recv)) + | _ -> true + +let private receiverNotTypar g (leadingArgs: Expr list) = + match leadingArgs with + | [ recv ] -> not (isTyparTy g (tyOfExpr g recv)) + | _ -> true + +let private receiverNotMutableStruct g takesInstanceArg (leadingArgs: Expr list) = + match leadingArgs with + | [ recv ] when takesInstanceArg -> + let ty = tyOfExpr g recv + not (isStructTy g ty) || isRecdOrStructTyReadOnly g Range.range0 ty + | _ -> true + +/// The receiver is evaluated once at the construction site rather than on every Invoke, which is only +/// unobservable when it is effect-free; and it must not reference the Invoke parameters, which exist +/// only inside the delegee. +let private receiverBindable exprHasEffect g (invokeParams: Val list) (leadingArgs: Expr list) = + match leadingArgs with + | [ recv ] -> + let recvFreeLocals = (freeInExpr CollectLocals recv).FreeLocals + + not (exprHasEffect g recv) + && (not (invokeParams |> List.exists (fun tv -> Zset.contains tv recvFreeLocals))) + | _ -> true + +/// Returns the virtual-call and instance-receiver facts derived from the member call info when the +/// target is directly bindable. Witnesses are passed in: computing them needs the IlxGen environment. +let fsharpValDirectlyBindable + exprHasEffect + g + (invokeParams: Val list) + (leadingArgs: Expr list) + (vrefM: ValRef) + (valUseFlags: ValUseFlag) + hasWitnesses + = + let _, virtualCall, newobj, isSuperInit, isSelfInit, takesInstanceArg, _, _ = + GetMemberCallInfo g (vrefM, valUseFlags) + + if + not hasWitnesses + && not newobj + && not isSuperInit + && not isSelfInit + && not valUseFlags.IsVSlotDirectCall + && receiverShapeOk leadingArgs takesInstanceArg + && receiverBindable exprHasEffect g invokeParams leadingArgs + && staticLeadingArgIsRefType g takesInstanceArg leadingArgs + && receiverNotByref g leadingArgs + && receiverNotTypar g leadingArgs + && receiverNotMutableStruct g takesInstanceArg leadingArgs + then + ValueSome(virtualCall, takesInstanceArg) + else + ValueNone + +let ilMethodDirectlyBindable + exprHasEffect + g + (invokeParams: Val list) + (leadingArgs: Expr list) + (ilMethRef: ILMethodRef) + (valUseFlag: ValUseFlag) + isCtor + = + let takesInstanceArg = ilMethRef.CallingConv.IsInstance + + not isCtor + && not valUseFlag.IsVSlotDirectCall + && not valUseFlag.IsPossibleConstrainedCall + && receiverShapeOk leadingArgs takesInstanceArg + && receiverBindable exprHasEffect g invokeParams leadingArgs + && staticLeadingArgIsRefType g takesInstanceArg leadingArgs + && receiverNotByref g leadingArgs + && receiverNotTypar g leadingArgs + && receiverNotMutableStruct g takesInstanceArg leadingArgs + +/// Residual IL compatibility check; the type checker verified the call and the forwarding match pinned +/// the shape. Parameter types are deliberately not compared - value types are exact by construction and +/// reference types may use the CLR's contravariant delegate relaxation - only their count, minus any +/// leading formals consumed by a bound Target. The return type must match exactly for a non-generic +/// target (the CLR does not relax e.g. 'void' against 'Unit'); a generic target's return is written in +/// type variables, where no exact comparison is meaningful. +let signatureMatches + numBoundLeadingFormals + (numDelegeeParams: int) + (ilDelegeeRetTy: ILType) + (ilEnclArgTys: ILType list) + (ilMethArgTys: ILType list) + (targetMspec: ILMethodSpec) + = + let arityMatches = + targetMspec.FormalArgTypes.Length - numBoundLeadingFormals = numDelegeeParams + + let returnMatches = + if List.isEmpty ilEnclArgTys && List.isEmpty ilMethArgTys then + ilDelegeeRetTy = targetMspec.FormalReturnType + else + true + + arityMatches && returnMatches + +let receiverInfo (leadingArgs: Expr list) virtualCall isInstanceReceiver = + match leadingArgs with + | [ recv ] -> Some(recv, virtualCall, isInstanceReceiver) + | _ -> None diff --git a/src/Compiler/Optimize/Optimizer.fs b/src/Compiler/Optimize/Optimizer.fs index 3d88004e673..a6b21b577eb 100644 --- a/src/Compiler/Optimize/Optimizer.fs +++ b/src/Compiler/Optimize/Optimizer.fs @@ -12,6 +12,7 @@ open FSharp.Compiler open FSharp.Compiler.AbstractIL.IL open FSharp.Compiler.AttributeChecking open FSharp.Compiler.CompilerGlobalState +open FSharp.Compiler.DelegateForwarding open FSharp.Compiler.DiagnosticsLogger open FSharp.Compiler.Text.Range open FSharp.Compiler.Syntax.PrettyNaming @@ -1707,7 +1708,7 @@ and OpHasEffect context g m op tyargs = | TOp.ExnFieldSet _ | TOp.Coerce | TOp.Reraise - | TOp.IntegerForLoop _ + | TOp.IntegerForLoop _ | TOp.While _ | TOp.TryWith _ (* conservative *) | TOp.TryFinally _ (* conservative *) @@ -1722,6 +1723,43 @@ and OpHasEffect context g m op tyargs = let effectContextOf (cenv: cenv) = if cenv.optimizing then EffectContext.Emit else EffectContext.InlineBody +/// Prevent the optimizer from inlining a recognized direct-delegate forwarding target into the delegate +/// body: inlining would dissolve the call before IlxGen can point the delegate at it, making the emitted +/// form depend on the target's size (locally, and through a referenced assembly's optimization data). +/// Mandatory inlining of 'inline' values takes precedence via OptimizeVal. +let AddDirectDelegateTargetToDontInlineSet cenv env (slotsig: SlotSig) tmvs body m = + let g = cenv.g + + if + g.langVersion.SupportsFeature Features.LanguageFeature.DirectDelegateConstruction + && cenv.optimizing + && cenv.settings.InlineLambdas + then + let exprHasEffect = ExprHasEffect (effectContextOf cenv) + + // Normalize the elided unit parameter of a zero-parameter Invoke (e.g. System.Action) exactly as + // IlxGen will before it runs the recognizer + let tmvs, body = + if slotsig.FormalParams |> List.forall List.isEmpty then + BindUnitVars g (tmvs, [], body) + else + tmvs, body + + match classifyForwardingTarget exprHasEffect g tmvs body with + | DirectDelegateForwardingTargetCandidate.FSharpVal(vref, valUseFlags, _, leadingArgs) when + // ValReprInfo.IsSome mirrors IlxGen's Method-storage requirement. Witnesses are not knowable + // here; over-suppressing a witness-requiring target only costs an inline in a closure body. + vref.ValReprInfo.IsSome + && (fsharpValDirectlyBindable exprHasEffect g tmvs leadingArgs vref valUseFlags false) + .IsSome + -> + match (GetInfoForVal cenv env m vref).ValExprInfo with + | StripLambdaValue(lambdaId, _, _, _, _) -> + { env with dontInline = Map.add lambdaId [] env.dontInline } + | _ -> env + | _ -> env + else + env let TryEliminateBinding cenv _env bind e2 _m = let g = cenv.g @@ -2441,11 +2479,16 @@ let rec OptimizeExpr cenv (env: IncrementalOptimizationEnv) expr = MightMakeCriticalTailcall=false Info=UnknownValue } - | Expr.Obj (_, ty, basev, createExpr, overrides, iimpls, m) -> - match expr with - | NewDelegateExpr g (lambdaId, vsl, body, _, remake) -> + | Expr.Obj (_, ty, basev, createExpr, overrides, iimpls, m) -> + match expr with + | NewDelegateExpr g (lambdaId, vsl, body, _, remake) -> + let env = + match overrides with + | [ TObjExprMethod(slotsig, _, _, _, _, mMeth) ] -> + AddDirectDelegateTargetToDontInlineSet cenv env slotsig vsl body mMeth + | _ -> env OptimizeNewDelegateExpr cenv env (lambdaId, vsl, body, remake) - | _ -> + | _ -> OptimizeObjectExpr cenv env (ty, basev, createExpr, overrides, iimpls, m) | Expr.Op (op, tyargs, args, m) -> diff --git a/src/Compiler/xlf/FSComp.txt.cs.xlf b/src/Compiler/xlf/FSComp.txt.cs.xlf index d1dcfe2543c..acda98d97e1 100644 --- a/src/Compiler/xlf/FSComp.txt.cs.xlf +++ b/src/Compiler/xlf/FSComp.txt.cs.xlf @@ -367,6 +367,11 @@ Deprecate places where 'seq' can be omitted + + construct delegates that point directly at the target method, avoiding an intermediate closure + construct delegates that point directly at the target method, avoiding an intermediate closure + + discard pattern in use binding vzor discard ve vazbě použití diff --git a/src/Compiler/xlf/FSComp.txt.de.xlf b/src/Compiler/xlf/FSComp.txt.de.xlf index 916e62a5cc7..eaa6f820a95 100644 --- a/src/Compiler/xlf/FSComp.txt.de.xlf +++ b/src/Compiler/xlf/FSComp.txt.de.xlf @@ -367,6 +367,11 @@ Deprecate places where 'seq' can be omitted + + construct delegates that point directly at the target method, avoiding an intermediate closure + construct delegates that point directly at the target method, avoiding an intermediate closure + + discard pattern in use binding Das Verwerfen des verwendeten Musters ist verbindlich. diff --git a/src/Compiler/xlf/FSComp.txt.es.xlf b/src/Compiler/xlf/FSComp.txt.es.xlf index b3e2ccabb2c..b6f9e45d7dd 100644 --- a/src/Compiler/xlf/FSComp.txt.es.xlf +++ b/src/Compiler/xlf/FSComp.txt.es.xlf @@ -367,6 +367,11 @@ Deprecate places where 'seq' can be omitted + + construct delegates that point directly at the target method, avoiding an intermediate closure + construct delegates that point directly at the target method, avoiding an intermediate closure + + discard pattern in use binding descartar enlace de patrón en uso diff --git a/src/Compiler/xlf/FSComp.txt.fr.xlf b/src/Compiler/xlf/FSComp.txt.fr.xlf index 0388bbb9a94..590ea0015b4 100644 --- a/src/Compiler/xlf/FSComp.txt.fr.xlf +++ b/src/Compiler/xlf/FSComp.txt.fr.xlf @@ -367,6 +367,11 @@ Deprecate places where 'seq' can be omitted + + construct delegates that point directly at the target method, avoiding an intermediate closure + construct delegates that point directly at the target method, avoiding an intermediate closure + + discard pattern in use binding annuler le modèle dans la liaison d’utilisation diff --git a/src/Compiler/xlf/FSComp.txt.it.xlf b/src/Compiler/xlf/FSComp.txt.it.xlf index a9ec9727009..6ef40f0aae4 100644 --- a/src/Compiler/xlf/FSComp.txt.it.xlf +++ b/src/Compiler/xlf/FSComp.txt.it.xlf @@ -367,6 +367,11 @@ Deprecate places where 'seq' can be omitted + + construct delegates that point directly at the target method, avoiding an intermediate closure + construct delegates that point directly at the target method, avoiding an intermediate closure + + discard pattern in use binding rimuovi criterio nell'utilizzo dell'associazione diff --git a/src/Compiler/xlf/FSComp.txt.ja.xlf b/src/Compiler/xlf/FSComp.txt.ja.xlf index 84ff697946f..883e3285d63 100644 --- a/src/Compiler/xlf/FSComp.txt.ja.xlf +++ b/src/Compiler/xlf/FSComp.txt.ja.xlf @@ -367,6 +367,11 @@ Deprecate places where 'seq' can be omitted + + construct delegates that point directly at the target method, avoiding an intermediate closure + construct delegates that point directly at the target method, avoiding an intermediate closure + + discard pattern in use binding 使用バインドでパターンを破棄する diff --git a/src/Compiler/xlf/FSComp.txt.ko.xlf b/src/Compiler/xlf/FSComp.txt.ko.xlf index 8b169c14354..8040a2c7c16 100644 --- a/src/Compiler/xlf/FSComp.txt.ko.xlf +++ b/src/Compiler/xlf/FSComp.txt.ko.xlf @@ -367,6 +367,11 @@ Deprecate places where 'seq' can be omitted + + construct delegates that point directly at the target method, avoiding an intermediate closure + construct delegates that point directly at the target method, avoiding an intermediate closure + + discard pattern in use binding 사용 중인 패턴 바인딩 무시 diff --git a/src/Compiler/xlf/FSComp.txt.pl.xlf b/src/Compiler/xlf/FSComp.txt.pl.xlf index ee94b000c13..82fb9e683d5 100644 --- a/src/Compiler/xlf/FSComp.txt.pl.xlf +++ b/src/Compiler/xlf/FSComp.txt.pl.xlf @@ -367,6 +367,11 @@ Deprecate places where 'seq' can be omitted + + construct delegates that point directly at the target method, avoiding an intermediate closure + construct delegates that point directly at the target method, avoiding an intermediate closure + + discard pattern in use binding odrzuć wzorzec w powiązaniu użycia diff --git a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf index 1dfe6078674..b369e181e5a 100644 --- a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf +++ b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf @@ -367,6 +367,11 @@ Deprecate places where 'seq' can be omitted + + construct delegates that point directly at the target method, avoiding an intermediate closure + construct delegates that point directly at the target method, avoiding an intermediate closure + + discard pattern in use binding descartar o padrão em uso de associação diff --git a/src/Compiler/xlf/FSComp.txt.ru.xlf b/src/Compiler/xlf/FSComp.txt.ru.xlf index 37c37f61657..a8a6f7923e1 100644 --- a/src/Compiler/xlf/FSComp.txt.ru.xlf +++ b/src/Compiler/xlf/FSComp.txt.ru.xlf @@ -367,6 +367,11 @@ Deprecate places where 'seq' can be omitted + + construct delegates that point directly at the target method, avoiding an intermediate closure + construct delegates that point directly at the target method, avoiding an intermediate closure + + discard pattern in use binding шаблон отмены в привязке использования diff --git a/src/Compiler/xlf/FSComp.txt.tr.xlf b/src/Compiler/xlf/FSComp.txt.tr.xlf index 89dbcc9eee2..74f800138e0 100644 --- a/src/Compiler/xlf/FSComp.txt.tr.xlf +++ b/src/Compiler/xlf/FSComp.txt.tr.xlf @@ -367,6 +367,11 @@ Deprecate places where 'seq' can be omitted + + construct delegates that point directly at the target method, avoiding an intermediate closure + construct delegates that point directly at the target method, avoiding an intermediate closure + + discard pattern in use binding kullanım bağlamasında deseni at diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf index 0f206016433..8477219f669 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf @@ -367,6 +367,11 @@ Deprecate places where 'seq' can be omitted + + construct delegates that point directly at the target method, avoiding an intermediate closure + construct delegates that point directly at the target method, avoiding an intermediate closure + + discard pattern in use binding 放弃使用绑定模式 diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf index 1c0f4305257..e791722cb90 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf @@ -367,6 +367,11 @@ Deprecate places where 'seq' can be omitted + + construct delegates that point directly at the target method, avoiding an intermediate closure + construct delegates that point directly at the target method, avoiding an intermediate closure + + discard pattern in use binding 捨棄使用繫結中的模式 diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateCustomType.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateCustomType.fs new file mode 100644 index 00000000000..b0d991a9b7f --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateCustomType.fs @@ -0,0 +1,42 @@ +module DelegateCustomType + +open System + +// Custom, F#-declared delegate types exercise construction with delegates defined in the *compiled* assembly +// (local scope, unlike imported BCL Func/Action) and with Invoke signatures the Func/Action tests do not +// cover: a multi-argument (tupled) signature, a generic delegate, and a byref parameter. (F# forbids curried +// delegate signatures — FS0950 — so every F# delegate has a single tupled Invoke parameter group.) + +type DTupled = delegate of int * int -> int +type DGen<'T> = delegate of 'T -> 'T +type DByref = delegate of byref -> unit + +let acc (x: int) (y: int) : int = x + y + +let ident (x: 'T) : 'T = x + +type C() = + member _.M (x: int) (y: int) : int = x * y + +// Tupled-signature custom delegate: Invoke(int, int). +// 28. non-eta module function, custom delegate +let tupledNonEta () = DTupled(acc) +// 14. eta module function, custom delegate +let tupledEta () = DTupled(fun a b -> acc a b) + +// Instance member through a custom delegate: the receiver becomes the delegate's Target. +// 29. non-eta instance member, custom delegate +let instanceNonEta (c: C) = DTupled(c.M) +// 15. eta instance member, custom delegate +let instanceEta (c: C) = DTupled(fun a b -> c.M a b) + +// Generic custom delegate instantiated at int: Invoke(int):int over the generic target. +// 30. non-eta generic method, generic custom delegate +let genNonEta () = DGen(ident) +// 16. eta generic method, generic custom delegate +let genEta () = DGen(fun x -> ident x) + +// byref-parameter custom delegate: the body mutates through the byref, so it is not a transparent forwarding +// call and stays a closure. Documents that a byref Invoke parameter does not break the recognizer. +// 53. byref-parameter delegate (mutating body) +let byrefMutate () = DByref(fun x -> x <- x + 1) diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateCustomType.fs.OptimizeOff.Preview.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateCustomType.fs.OptimizeOff.Preview.il.bsl new file mode 100644 index 00000000000..c9d56b7d0a0 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateCustomType.fs.OptimizeOff.Preview.il.bsl @@ -0,0 +1,348 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable sealed nested public DTupled + extends [runtime]System.MulticastDelegate + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public hidebysig specialname rtspecialname instance void .ctor(object 'object', native int 'method') runtime managed + { + } + + .method public hidebysig strict virtual instance int32 Invoke(int32 A_1, int32 A_2) runtime managed + { + } + + .method public hidebysig strict virtual + instance class [runtime]System.IAsyncResult + BeginInvoke(int32 A_1, + int32 A_2, + class [runtime]System.AsyncCallback callback, + object objects) runtime managed + { + } + + .method public hidebysig strict virtual instance int32 EndInvoke(class [runtime]System.IAsyncResult result) runtime managed + { + } + + } + + .class auto ansi serializable sealed nested public DGen`1 + extends [runtime]System.MulticastDelegate + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public hidebysig specialname rtspecialname instance void .ctor(object 'object', native int 'method') runtime managed + { + } + + .method public hidebysig strict virtual instance !T Invoke(!T A_1) runtime managed + { + } + + .method public hidebysig strict virtual + instance class [runtime]System.IAsyncResult + BeginInvoke(!T A_1, + class [runtime]System.AsyncCallback callback, + object objects) runtime managed + { + } + + .method public hidebysig strict virtual instance !T EndInvoke(class [runtime]System.IAsyncResult result) runtime managed + { + } + + } + + .class auto ansi serializable sealed nested public DByref + extends [runtime]System.MulticastDelegate + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public hidebysig specialname rtspecialname instance void .ctor(object 'object', native int 'method') runtime managed + { + } + + .method public hidebysig strict virtual instance void Invoke(int32& A_1) runtime managed + { + } + + .method public hidebysig strict virtual + instance class [runtime]System.IAsyncResult + BeginInvoke(int32& A_1, + class [runtime]System.AsyncCallback callback, + object objects) runtime managed + { + } + + .method public hidebysig strict virtual instance void EndInvoke(class [runtime]System.IAsyncResult result) runtime managed + { + } + + } + + .class auto ansi serializable nested public C + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor() cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: callvirt instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ret + } + + .method public hidebysig instance int32 M(int32 x, int32 y) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: ldarg.2 + IL_0002: mul + IL_0003: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname tupledEta@25 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static int32 Invoke(int32 a, + int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: call int32 assembly::acc(int32, + int32) + IL_0007: ret + } + + } + + .class auto autochar serializable sealed nested assembly beforefieldinit specialname instanceEta@31 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public class assembly/C c + .method public specialname rtspecialname instance void .ctor(class assembly/C c) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld class assembly/C assembly/instanceEta@31::c + IL_0007: ldarg.0 + IL_0008: call instance void [runtime]System.Object::.ctor() + IL_000d: ret + } + + .method assembly hidebysig instance int32 Invoke(int32 a, int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld class assembly/C assembly/instanceEta@31::c + IL_0006: ldarg.1 + IL_0007: ldarg.2 + IL_0008: callvirt instance int32 assembly/C::M(int32, + int32) + IL_000d: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname genEta@37 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static int32 Invoke(int32 x) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call !!0 assembly::ident(!!0) + IL_0006: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname byrefMutate@42 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32& x) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.0 + IL_0002: ldobj [runtime]System.Int32 + IL_0007: ldc.i4.1 + IL_0008: add + IL_0009: stobj [runtime]System.Int32 + IL_000e: ret + } + + } + + .method public static int32 acc(int32 x, + int32 y) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: add + IL_0003: ret + } + + .method public static !!T ident(!!T x) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ret + } + + .method public static class assembly/DTupled tupledNonEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn int32 assembly::acc(int32, + int32) + IL_0007: newobj instance void assembly/DTupled::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class assembly/DTupled tupledEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn int32 assembly/tupledEta@25::Invoke(int32, + int32) + IL_0007: newobj instance void assembly/DTupled::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class assembly/DTupled instanceNonEta(class assembly/C c) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldftn instance int32 assembly/C::M(int32, + int32) + IL_0007: newobj instance void assembly/DTupled::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class assembly/DTupled instanceEta(class assembly/C c) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: newobj instance void assembly/instanceEta@31::.ctor(class assembly/C) + IL_0006: ldftn instance int32 assembly/instanceEta@31::Invoke(int32, + int32) + IL_000c: newobj instance void assembly/DTupled::.ctor(object, + native int) + IL_0011: ret + } + + .method public static class assembly/DGen`1 genNonEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn !!0 assembly::ident(!!0) + IL_0007: newobj instance void class assembly/DGen`1::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class assembly/DGen`1 genEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn int32 assembly/genEta@37::Invoke(int32) + IL_0007: newobj instance void class assembly/DGen`1::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class assembly/DByref byrefMutate() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/byrefMutate@42::Invoke(int32&) + IL_0007: newobj instance void assembly/DByref::.ctor(object, + native int) + IL_000c: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateCustomType.fs.OptimizeOff.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateCustomType.fs.OptimizeOff.il.bsl new file mode 100644 index 00000000000..66053083940 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateCustomType.fs.OptimizeOff.il.bsl @@ -0,0 +1,414 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable sealed nested public DTupled + extends [runtime]System.MulticastDelegate + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public hidebysig specialname rtspecialname instance void .ctor(object 'object', native int 'method') runtime managed + { + } + + .method public hidebysig strict virtual instance int32 Invoke(int32 A_1, int32 A_2) runtime managed + { + } + + .method public hidebysig strict virtual + instance class [runtime]System.IAsyncResult + BeginInvoke(int32 A_1, + int32 A_2, + class [runtime]System.AsyncCallback callback, + object objects) runtime managed + { + } + + .method public hidebysig strict virtual instance int32 EndInvoke(class [runtime]System.IAsyncResult result) runtime managed + { + } + + } + + .class auto ansi serializable sealed nested public DGen`1 + extends [runtime]System.MulticastDelegate + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public hidebysig specialname rtspecialname instance void .ctor(object 'object', native int 'method') runtime managed + { + } + + .method public hidebysig strict virtual instance !T Invoke(!T A_1) runtime managed + { + } + + .method public hidebysig strict virtual + instance class [runtime]System.IAsyncResult + BeginInvoke(!T A_1, + class [runtime]System.AsyncCallback callback, + object objects) runtime managed + { + } + + .method public hidebysig strict virtual instance !T EndInvoke(class [runtime]System.IAsyncResult result) runtime managed + { + } + + } + + .class auto ansi serializable sealed nested public DByref + extends [runtime]System.MulticastDelegate + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public hidebysig specialname rtspecialname instance void .ctor(object 'object', native int 'method') runtime managed + { + } + + .method public hidebysig strict virtual instance void Invoke(int32& A_1) runtime managed + { + } + + .method public hidebysig strict virtual + instance class [runtime]System.IAsyncResult + BeginInvoke(int32& A_1, + class [runtime]System.AsyncCallback callback, + object objects) runtime managed + { + } + + .method public hidebysig strict virtual instance void EndInvoke(class [runtime]System.IAsyncResult result) runtime managed + { + } + + } + + .class auto ansi serializable nested public C + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor() cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: callvirt instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ret + } + + .method public hidebysig instance int32 M(int32 x, int32 y) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: ldarg.2 + IL_0002: mul + IL_0003: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname tupledNonEta@23 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static int32 Invoke(int32 x, + int32 y) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: call int32 assembly::acc(int32, + int32) + IL_0007: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname tupledEta@25 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static int32 Invoke(int32 a, + int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: call int32 assembly::acc(int32, + int32) + IL_0007: ret + } + + } + + .class auto autochar serializable sealed nested assembly beforefieldinit specialname instanceNonEta@29 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public class assembly/C c + .method public specialname rtspecialname instance void .ctor(class assembly/C c) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld class assembly/C assembly/instanceNonEta@29::c + IL_0007: ldarg.0 + IL_0008: call instance void [runtime]System.Object::.ctor() + IL_000d: ret + } + + .method assembly hidebysig instance int32 Invoke(int32 delegateArg0, int32 delegateArg1) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld class assembly/C assembly/instanceNonEta@29::c + IL_0006: ldarg.1 + IL_0007: ldarg.2 + IL_0008: callvirt instance int32 assembly/C::M(int32, + int32) + IL_000d: ret + } + + } + + .class auto autochar serializable sealed nested assembly beforefieldinit specialname instanceEta@31 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public class assembly/C c + .method public specialname rtspecialname instance void .ctor(class assembly/C c) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld class assembly/C assembly/instanceEta@31::c + IL_0007: ldarg.0 + IL_0008: call instance void [runtime]System.Object::.ctor() + IL_000d: ret + } + + .method assembly hidebysig instance int32 Invoke(int32 a, int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld class assembly/C assembly/instanceEta@31::c + IL_0006: ldarg.1 + IL_0007: ldarg.2 + IL_0008: callvirt instance int32 assembly/C::M(int32, + int32) + IL_000d: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname genNonEta@35 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static int32 Invoke(int32 delegateArg0) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call !!0 assembly::ident(!!0) + IL_0006: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname genEta@37 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static int32 Invoke(int32 x) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call !!0 assembly::ident(!!0) + IL_0006: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname byrefMutate@42 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32& x) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.0 + IL_0002: ldobj [runtime]System.Int32 + IL_0007: ldc.i4.1 + IL_0008: add + IL_0009: stobj [runtime]System.Int32 + IL_000e: ret + } + + } + + .method public static int32 acc(int32 x, + int32 y) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: add + IL_0003: ret + } + + .method public static !!T ident(!!T x) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ret + } + + .method public static class assembly/DTupled tupledNonEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn int32 assembly/tupledNonEta@23::Invoke(int32, + int32) + IL_0007: newobj instance void assembly/DTupled::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class assembly/DTupled tupledEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn int32 assembly/tupledEta@25::Invoke(int32, + int32) + IL_0007: newobj instance void assembly/DTupled::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class assembly/DTupled instanceNonEta(class assembly/C c) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: newobj instance void assembly/instanceNonEta@29::.ctor(class assembly/C) + IL_0006: ldftn instance int32 assembly/instanceNonEta@29::Invoke(int32, + int32) + IL_000c: newobj instance void assembly/DTupled::.ctor(object, + native int) + IL_0011: ret + } + + .method public static class assembly/DTupled instanceEta(class assembly/C c) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: newobj instance void assembly/instanceEta@31::.ctor(class assembly/C) + IL_0006: ldftn instance int32 assembly/instanceEta@31::Invoke(int32, + int32) + IL_000c: newobj instance void assembly/DTupled::.ctor(object, + native int) + IL_0011: ret + } + + .method public static class assembly/DGen`1 genNonEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn int32 assembly/genNonEta@35::Invoke(int32) + IL_0007: newobj instance void class assembly/DGen`1::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class assembly/DGen`1 genEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn int32 assembly/genEta@37::Invoke(int32) + IL_0007: newobj instance void class assembly/DGen`1::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class assembly/DByref byrefMutate() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/byrefMutate@42::Invoke(int32&) + IL_0007: newobj instance void assembly/DByref::.ctor(object, + native int) + IL_000c: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateCustomType.fs.OptimizeOn.Preview.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateCustomType.fs.OptimizeOn.Preview.il.bsl new file mode 100644 index 00000000000..15a1a5f9f34 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateCustomType.fs.OptimizeOn.Preview.il.bsl @@ -0,0 +1,282 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable sealed nested public DTupled + extends [runtime]System.MulticastDelegate + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public hidebysig specialname rtspecialname instance void .ctor(object 'object', native int 'method') runtime managed + { + } + + .method public hidebysig strict virtual instance int32 Invoke(int32 A_1, int32 A_2) runtime managed + { + } + + .method public hidebysig strict virtual + instance class [runtime]System.IAsyncResult + BeginInvoke(int32 A_1, + int32 A_2, + class [runtime]System.AsyncCallback callback, + object objects) runtime managed + { + } + + .method public hidebysig strict virtual instance int32 EndInvoke(class [runtime]System.IAsyncResult result) runtime managed + { + } + + } + + .class auto ansi serializable sealed nested public DGen`1 + extends [runtime]System.MulticastDelegate + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public hidebysig specialname rtspecialname instance void .ctor(object 'object', native int 'method') runtime managed + { + } + + .method public hidebysig strict virtual instance !T Invoke(!T A_1) runtime managed + { + } + + .method public hidebysig strict virtual + instance class [runtime]System.IAsyncResult + BeginInvoke(!T A_1, + class [runtime]System.AsyncCallback callback, + object objects) runtime managed + { + } + + .method public hidebysig strict virtual instance !T EndInvoke(class [runtime]System.IAsyncResult result) runtime managed + { + } + + } + + .class auto ansi serializable sealed nested public DByref + extends [runtime]System.MulticastDelegate + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public hidebysig specialname rtspecialname instance void .ctor(object 'object', native int 'method') runtime managed + { + } + + .method public hidebysig strict virtual instance void Invoke(int32& A_1) runtime managed + { + } + + .method public hidebysig strict virtual + instance class [runtime]System.IAsyncResult + BeginInvoke(int32& A_1, + class [runtime]System.AsyncCallback callback, + object objects) runtime managed + { + } + + .method public hidebysig strict virtual instance void EndInvoke(class [runtime]System.IAsyncResult result) runtime managed + { + } + + } + + .class auto ansi serializable nested public C + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor() cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: callvirt instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ret + } + + .method public hidebysig instance int32 M(int32 x, int32 y) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: ldarg.2 + IL_0002: mul + IL_0003: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname byrefMutate@42 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32& x) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.0 + IL_0002: ldobj [runtime]System.Int32 + IL_0007: ldc.i4.1 + IL_0008: add + IL_0009: stobj [runtime]System.Int32 + IL_000e: ret + } + + } + + .method public static int32 acc(int32 x, + int32 y) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: add + IL_0003: ret + } + + .method public static !!T ident(!!T x) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ret + } + + .method public static class assembly/DTupled tupledNonEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn int32 assembly::acc(int32, + int32) + IL_0007: newobj instance void assembly/DTupled::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class assembly/DTupled tupledEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn int32 assembly::acc(int32, + int32) + IL_0007: newobj instance void assembly/DTupled::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class assembly/DTupled instanceNonEta(class assembly/C c) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldftn instance int32 assembly/C::M(int32, + int32) + IL_0007: newobj instance void assembly/DTupled::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class assembly/DTupled instanceEta(class assembly/C c) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldftn instance int32 assembly/C::M(int32, + int32) + IL_0007: newobj instance void assembly/DTupled::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class assembly/DGen`1 genNonEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn !!0 assembly::ident(!!0) + IL_0007: newobj instance void class assembly/DGen`1::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class assembly/DGen`1 genEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn !!0 assembly::ident(!!0) + IL_0007: newobj instance void class assembly/DGen`1::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class assembly/DByref byrefMutate() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/byrefMutate@42::Invoke(int32&) + IL_0007: newobj instance void assembly/DByref::.ctor(object, + native int) + IL_000c: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateCustomType.fs.OptimizeOn.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateCustomType.fs.OptimizeOn.il.bsl new file mode 100644 index 00000000000..91f76166944 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateCustomType.fs.OptimizeOn.il.bsl @@ -0,0 +1,378 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable sealed nested public DTupled + extends [runtime]System.MulticastDelegate + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public hidebysig specialname rtspecialname instance void .ctor(object 'object', native int 'method') runtime managed + { + } + + .method public hidebysig strict virtual instance int32 Invoke(int32 A_1, int32 A_2) runtime managed + { + } + + .method public hidebysig strict virtual + instance class [runtime]System.IAsyncResult + BeginInvoke(int32 A_1, + int32 A_2, + class [runtime]System.AsyncCallback callback, + object objects) runtime managed + { + } + + .method public hidebysig strict virtual instance int32 EndInvoke(class [runtime]System.IAsyncResult result) runtime managed + { + } + + } + + .class auto ansi serializable sealed nested public DGen`1 + extends [runtime]System.MulticastDelegate + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public hidebysig specialname rtspecialname instance void .ctor(object 'object', native int 'method') runtime managed + { + } + + .method public hidebysig strict virtual instance !T Invoke(!T A_1) runtime managed + { + } + + .method public hidebysig strict virtual + instance class [runtime]System.IAsyncResult + BeginInvoke(!T A_1, + class [runtime]System.AsyncCallback callback, + object objects) runtime managed + { + } + + .method public hidebysig strict virtual instance !T EndInvoke(class [runtime]System.IAsyncResult result) runtime managed + { + } + + } + + .class auto ansi serializable sealed nested public DByref + extends [runtime]System.MulticastDelegate + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public hidebysig specialname rtspecialname instance void .ctor(object 'object', native int 'method') runtime managed + { + } + + .method public hidebysig strict virtual instance void Invoke(int32& A_1) runtime managed + { + } + + .method public hidebysig strict virtual + instance class [runtime]System.IAsyncResult + BeginInvoke(int32& A_1, + class [runtime]System.AsyncCallback callback, + object objects) runtime managed + { + } + + .method public hidebysig strict virtual instance void EndInvoke(class [runtime]System.IAsyncResult result) runtime managed + { + } + + } + + .class auto ansi serializable nested public C + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor() cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: callvirt instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ret + } + + .method public hidebysig instance int32 M(int32 x, int32 y) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: ldarg.2 + IL_0002: mul + IL_0003: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname tupledNonEta@23 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static int32 Invoke(int32 x, + int32 y) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: add + IL_0003: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname tupledEta@25 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static int32 Invoke(int32 a, + int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: add + IL_0003: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname instanceNonEta@29 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static int32 Invoke(int32 delegateArg0, + int32 delegateArg1) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: mul + IL_0003: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname instanceEta@31 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static int32 Invoke(int32 a, + int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: mul + IL_0003: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname genNonEta@35 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static int32 Invoke(int32 delegateArg0) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname genEta@37 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static int32 Invoke(int32 x) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname byrefMutate@42 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32& x) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.0 + IL_0002: ldobj [runtime]System.Int32 + IL_0007: ldc.i4.1 + IL_0008: add + IL_0009: stobj [runtime]System.Int32 + IL_000e: ret + } + + } + + .method public static int32 acc(int32 x, + int32 y) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: add + IL_0003: ret + } + + .method public static !!T ident(!!T x) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ret + } + + .method public static class assembly/DTupled tupledNonEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn int32 assembly/tupledNonEta@23::Invoke(int32, + int32) + IL_0007: newobj instance void assembly/DTupled::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class assembly/DTupled tupledEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn int32 assembly/tupledEta@25::Invoke(int32, + int32) + IL_0007: newobj instance void assembly/DTupled::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class assembly/DTupled instanceNonEta(class assembly/C c) cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn int32 assembly/instanceNonEta@29::Invoke(int32, + int32) + IL_0007: newobj instance void assembly/DTupled::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class assembly/DTupled instanceEta(class assembly/C c) cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn int32 assembly/instanceEta@31::Invoke(int32, + int32) + IL_0007: newobj instance void assembly/DTupled::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class assembly/DGen`1 genNonEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn int32 assembly/genNonEta@35::Invoke(int32) + IL_0007: newobj instance void class assembly/DGen`1::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class assembly/DGen`1 genEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn int32 assembly/genEta@37::Invoke(int32) + IL_0007: newobj instance void class assembly/DGen`1::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class assembly/DByref byrefMutate() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/byrefMutate@42::Invoke(int32&) + IL_0007: newobj instance void assembly/DByref::.ctor(object, + native int) + IL_000c: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateExtensionMethod.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateExtensionMethod.fs new file mode 100644 index 00000000000..6d7ecdd9960 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateExtensionMethod.fs @@ -0,0 +1,22 @@ +module DelegateExtensionMethod + +open System +open System.Runtime.CompilerServices + +type Holder() = + class + end + +[] +type HolderExtensions = + [] + static member Combine (h: Holder, x: int, y: int) : int = x + y + +// An extension member compiles to a static method whose first parameter is the receiver. Using it as a +// delegate target binds that receiver as a leading argument, which the CLR's "closed over the first argument" +// delegate stores as the Target while the function pointer points at the static method - a direct delegate. +// (The member here is tupled, 'Combine(h, x, y)'; the recognizer de-tuples the forwarding call by the target's +// arity, exactly as the code generator does when emitting the call.) As an eta-expanded delegate it is direct +// only in optimized builds, where the user's lambda need not survive for debugging. +// 52. extension member (receiver is a leading static arg, bound as Target) +let extensionEta (h: Holder) = Func(fun a b -> h.Combine(a, b)) diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateExtensionMethod.fs.OptimizeOff.Preview.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateExtensionMethod.fs.OptimizeOff.Preview.il.bsl new file mode 100644 index 00000000000..0e4b863938b --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateExtensionMethod.fs.OptimizeOff.Preview.il.bsl @@ -0,0 +1,138 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable nested public Holder + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor() cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: callvirt instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ret + } + + } + + .class auto ansi serializable nested public HolderExtensions + extends [runtime]System.Object + { + .custom instance void [runtime]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public static int32 Combine(class assembly/Holder h, + int32 x, + int32 y) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: ldarg.2 + IL_0002: add + IL_0003: ret + } + + } + + .class auto autochar serializable sealed nested assembly beforefieldinit specialname extensionEta@22 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public class assembly/Holder h + .method public specialname rtspecialname instance void .ctor(class assembly/Holder h) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld class assembly/Holder assembly/extensionEta@22::h + IL_0007: ldarg.0 + IL_0008: call instance void [runtime]System.Object::.ctor() + IL_000d: ret + } + + .method assembly hidebysig instance int32 Invoke(int32 a, int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld class assembly/Holder assembly/extensionEta@22::h + IL_0006: ldarg.1 + IL_0007: ldarg.2 + IL_0008: call int32 assembly/HolderExtensions::Combine(class assembly/Holder, + int32, + int32) + IL_000d: ret + } + + } + + .method public static class [runtime]System.Func`3 extensionEta(class assembly/Holder h) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: newobj instance void assembly/extensionEta@22::.ctor(class assembly/Holder) + IL_0006: ldftn instance int32 assembly/extensionEta@22::Invoke(int32, + int32) + IL_000c: newobj instance void class [runtime]System.Func`3::.ctor(object, + native int) + IL_0011: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateExtensionMethod.fs.OptimizeOff.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateExtensionMethod.fs.OptimizeOff.il.bsl new file mode 100644 index 00000000000..940811fcfab --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateExtensionMethod.fs.OptimizeOff.il.bsl @@ -0,0 +1,138 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable nested public Holder + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor() cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: callvirt instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ret + } + + } + + .class auto ansi serializable nested public HolderExtensions + extends [runtime]System.Object + { + .custom instance void [runtime]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public static int32 Combine(class assembly/Holder h, + int32 x, + int32 y) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: ldarg.2 + IL_0002: add + IL_0003: ret + } + + } + + .class auto autochar serializable sealed nested assembly beforefieldinit specialname extensionEta@22 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public class assembly/Holder h + .method public specialname rtspecialname instance void .ctor(class assembly/Holder h) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld class assembly/Holder assembly/extensionEta@22::h + IL_0007: ldarg.0 + IL_0008: call instance void [runtime]System.Object::.ctor() + IL_000d: ret + } + + .method assembly hidebysig instance int32 Invoke(int32 a, int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld class assembly/Holder assembly/extensionEta@22::h + IL_0006: ldarg.1 + IL_0007: ldarg.2 + IL_0008: call int32 assembly/HolderExtensions::Combine(class assembly/Holder, + int32, + int32) + IL_000d: ret + } + + } + + .method public static class [runtime]System.Func`3 extensionEta(class assembly/Holder h) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: newobj instance void assembly/extensionEta@22::.ctor(class assembly/Holder) + IL_0006: ldftn instance int32 assembly/extensionEta@22::Invoke(int32, + int32) + IL_000c: newobj instance void class [runtime]System.Func`3::.ctor(object, + native int) + IL_0011: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateExtensionMethod.fs.OptimizeOn.Preview.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateExtensionMethod.fs.OptimizeOn.Preview.il.bsl new file mode 100644 index 00000000000..6e78d1cdc46 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateExtensionMethod.fs.OptimizeOn.Preview.il.bsl @@ -0,0 +1,105 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable nested public Holder + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor() cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: callvirt instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ret + } + + } + + .class auto ansi serializable nested public HolderExtensions + extends [runtime]System.Object + { + .custom instance void [runtime]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public static int32 Combine(class assembly/Holder h, + int32 x, + int32 y) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: ldarg.2 + IL_0002: add + IL_0003: ret + } + + } + + .method public static class [runtime]System.Func`3 extensionEta(class assembly/Holder h) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldftn int32 assembly/HolderExtensions::Combine(class assembly/Holder, + int32, + int32) + IL_0007: newobj instance void class [runtime]System.Func`3::.ctor(object, + native int) + IL_000c: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateExtensionMethod.fs.OptimizeOn.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateExtensionMethod.fs.OptimizeOn.il.bsl new file mode 100644 index 00000000000..8168284b0b3 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateExtensionMethod.fs.OptimizeOn.il.bsl @@ -0,0 +1,121 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable nested public Holder + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor() cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: callvirt instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ret + } + + } + + .class auto ansi serializable nested public HolderExtensions + extends [runtime]System.Object + { + .custom instance void [runtime]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public static int32 Combine(class assembly/Holder h, + int32 x, + int32 y) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: ldarg.2 + IL_0002: add + IL_0003: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname extensionEta@22 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static int32 Invoke(int32 a, + int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: add + IL_0003: ret + } + + } + + .method public static class [runtime]System.Func`3 extensionEta(class assembly/Holder h) cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn int32 assembly/extensionEta@22::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Func`3::.ctor(object, + native int) + IL_000c: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericInstanceMethod.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericInstanceMethod.fs new file mode 100644 index 00000000000..535bee3d582 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericInstanceMethod.fs @@ -0,0 +1,13 @@ +module DelegateGenericInstanceMethod + +open System + +type C() = + member _.IMc<'T> (x: 'T) (y: 'T) : unit = () + member _.IMt<'T> (x: 'T, y: 'T) : unit = () + +// 5. eta generic instance method (curried application) +let case5_etaCurried (o: C) = Action(fun a b -> o.IMc a b) + +// 35. eta generic instance method, tupled application +let case35_etaTupled (o: C) = Action(fun a b -> o.IMt(a, b)) diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericInstanceMethod.fs.OptimizeOff.Preview.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericInstanceMethod.fs.OptimizeOff.Preview.il.bsl new file mode 100644 index 00000000000..12696733399 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericInstanceMethod.fs.OptimizeOff.Preview.il.bsl @@ -0,0 +1,179 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable nested public C + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor() cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: callvirt instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ret + } + + .method public hidebysig instance void IMc(!!T x, !!T y) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 8 + IL_0000: ret + } + + .method public hidebysig instance void IMt(!!T x, !!T y) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + } + + .class auto autochar serializable sealed nested assembly beforefieldinit specialname case5_etaCurried@10 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public class assembly/C o + .method public specialname rtspecialname instance void .ctor(class assembly/C o) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld class assembly/C assembly/case5_etaCurried@10::o + IL_0007: ldarg.0 + IL_0008: call instance void [runtime]System.Object::.ctor() + IL_000d: ret + } + + .method assembly hidebysig instance void Invoke(int32 a, int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld class assembly/C assembly/case5_etaCurried@10::o + IL_0006: ldarg.1 + IL_0007: ldarg.2 + IL_0008: callvirt instance void assembly/C::IMc(!!0, + !!0) + IL_000d: nop + IL_000e: ret + } + + } + + .class auto autochar serializable sealed nested assembly beforefieldinit specialname case35_etaTupled@13 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public class assembly/C o + .method public specialname rtspecialname instance void .ctor(class assembly/C o) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld class assembly/C assembly/case35_etaTupled@13::o + IL_0007: ldarg.0 + IL_0008: call instance void [runtime]System.Object::.ctor() + IL_000d: ret + } + + .method assembly hidebysig instance void Invoke(int32 a, int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld class assembly/C assembly/case35_etaTupled@13::o + IL_0006: ldarg.1 + IL_0007: ldarg.2 + IL_0008: callvirt instance void assembly/C::IMt(!!0, + !!0) + IL_000d: nop + IL_000e: ret + } + + } + + .method public static class [runtime]System.Action`2 case5_etaCurried(class assembly/C o) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: newobj instance void assembly/case5_etaCurried@10::.ctor(class assembly/C) + IL_0006: ldftn instance void assembly/case5_etaCurried@10::Invoke(int32, + int32) + IL_000c: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_0011: ret + } + + .method public static class [runtime]System.Action`2 case35_etaTupled(class assembly/C o) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: newobj instance void assembly/case35_etaTupled@13::.ctor(class assembly/C) + IL_0006: ldftn instance void assembly/case35_etaTupled@13::Invoke(int32, + int32) + IL_000c: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_0011: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericInstanceMethod.fs.OptimizeOff.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericInstanceMethod.fs.OptimizeOff.il.bsl new file mode 100644 index 00000000000..12696733399 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericInstanceMethod.fs.OptimizeOff.il.bsl @@ -0,0 +1,179 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable nested public C + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor() cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: callvirt instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ret + } + + .method public hidebysig instance void IMc(!!T x, !!T y) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 8 + IL_0000: ret + } + + .method public hidebysig instance void IMt(!!T x, !!T y) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + } + + .class auto autochar serializable sealed nested assembly beforefieldinit specialname case5_etaCurried@10 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public class assembly/C o + .method public specialname rtspecialname instance void .ctor(class assembly/C o) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld class assembly/C assembly/case5_etaCurried@10::o + IL_0007: ldarg.0 + IL_0008: call instance void [runtime]System.Object::.ctor() + IL_000d: ret + } + + .method assembly hidebysig instance void Invoke(int32 a, int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld class assembly/C assembly/case5_etaCurried@10::o + IL_0006: ldarg.1 + IL_0007: ldarg.2 + IL_0008: callvirt instance void assembly/C::IMc(!!0, + !!0) + IL_000d: nop + IL_000e: ret + } + + } + + .class auto autochar serializable sealed nested assembly beforefieldinit specialname case35_etaTupled@13 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public class assembly/C o + .method public specialname rtspecialname instance void .ctor(class assembly/C o) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld class assembly/C assembly/case35_etaTupled@13::o + IL_0007: ldarg.0 + IL_0008: call instance void [runtime]System.Object::.ctor() + IL_000d: ret + } + + .method assembly hidebysig instance void Invoke(int32 a, int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld class assembly/C assembly/case35_etaTupled@13::o + IL_0006: ldarg.1 + IL_0007: ldarg.2 + IL_0008: callvirt instance void assembly/C::IMt(!!0, + !!0) + IL_000d: nop + IL_000e: ret + } + + } + + .method public static class [runtime]System.Action`2 case5_etaCurried(class assembly/C o) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: newobj instance void assembly/case5_etaCurried@10::.ctor(class assembly/C) + IL_0006: ldftn instance void assembly/case5_etaCurried@10::Invoke(int32, + int32) + IL_000c: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_0011: ret + } + + .method public static class [runtime]System.Action`2 case35_etaTupled(class assembly/C o) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: newobj instance void assembly/case35_etaTupled@13::.ctor(class assembly/C) + IL_0006: ldftn instance void assembly/case35_etaTupled@13::Invoke(int32, + int32) + IL_000c: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_0011: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericInstanceMethod.fs.OptimizeOn.Preview.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericInstanceMethod.fs.OptimizeOn.Preview.il.bsl new file mode 100644 index 00000000000..26e0b7e9705 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericInstanceMethod.fs.OptimizeOn.Preview.il.bsl @@ -0,0 +1,111 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable nested public C + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor() cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: callvirt instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ret + } + + .method public hidebysig instance void IMc(!!T x, !!T y) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 8 + IL_0000: ret + } + + .method public hidebysig instance void IMt(!!T x, !!T y) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + } + + .method public static class [runtime]System.Action`2 case5_etaCurried(class assembly/C o) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldftn instance void assembly/C::IMc(!!0, + !!0) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 case35_etaTupled(class assembly/C o) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldftn instance void assembly/C::IMt(!!0, + !!0) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericInstanceMethod.fs.OptimizeOn.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericInstanceMethod.fs.OptimizeOn.il.bsl new file mode 100644 index 00000000000..74be77228f1 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericInstanceMethod.fs.OptimizeOn.il.bsl @@ -0,0 +1,139 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable nested public C + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor() cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: callvirt instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ret + } + + .method public hidebysig instance void IMc(!!T x, !!T y) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 8 + IL_0000: ret + } + + .method public hidebysig instance void IMt(!!T x, !!T y) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case5_etaCurried@10 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 a, + int32 b) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case35_etaTupled@13 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 a, + int32 b) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + } + + .method public static class [runtime]System.Action`2 case5_etaCurried(class assembly/C o) cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/case5_etaCurried@10::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 case35_etaTupled(class assembly/C o) cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/case35_etaTupled@13::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericStaticMethod.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericStaticMethod.fs new file mode 100644 index 00000000000..a4e30bdaf08 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericStaticMethod.fs @@ -0,0 +1,16 @@ +module DelegateGenericStaticMethod + +open System + +type G<'U> = + static member SMc<'T> (x: 'T) (y: 'T) : unit = () + static member SMt<'T> (x: 'T, y: 'T) : unit = () + +// 19. non-eta generic static method (generic type + generic method) +let case19_nonEta () = Action(G.SMc) + +// 3. eta generic static method (curried application) +let case3_etaCurried () = Action(fun a b -> G.SMc a b) + +// 33. eta generic static method, tupled application +let case33_etaTupled () = Action(fun a b -> G.SMt(a, b)) diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericStaticMethod.fs.OptimizeOff.Preview.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericStaticMethod.fs.OptimizeOff.Preview.il.bsl new file mode 100644 index 00000000000..39cb26442a6 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericStaticMethod.fs.OptimizeOff.Preview.il.bsl @@ -0,0 +1,152 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable nested public G`1 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public static void SMc(!!T x, + !!T y) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 8 + IL_0000: ret + } + + .method public static void SMt(!!T x, + !!T y) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case3_etaCurried@13 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 a, + int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: call void class assembly/G`1::SMc(!!0, + !!0) + IL_0007: nop + IL_0008: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case33_etaTupled@16 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 a, + int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: call void class assembly/G`1::SMt(!!0, + !!0) + IL_0007: nop + IL_0008: ret + } + + } + + .method public static class [runtime]System.Action`2 case19_nonEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void class assembly/G`1::SMc(!!0, + !!0) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 case3_etaCurried() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/case3_etaCurried@13::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 case33_etaTupled() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/case33_etaTupled@16::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericStaticMethod.fs.OptimizeOff.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericStaticMethod.fs.OptimizeOff.il.bsl new file mode 100644 index 00000000000..52f0ce42863 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericStaticMethod.fs.OptimizeOff.il.bsl @@ -0,0 +1,171 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable nested public G`1 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public static void SMc(!!T x, + !!T y) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 8 + IL_0000: ret + } + + .method public static void SMt(!!T x, + !!T y) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case19_nonEta@10 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 x, + int32 y) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: call void class assembly/G`1::SMc(!!0, + !!0) + IL_0007: nop + IL_0008: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case3_etaCurried@13 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 a, + int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: call void class assembly/G`1::SMc(!!0, + !!0) + IL_0007: nop + IL_0008: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case33_etaTupled@16 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 a, + int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: call void class assembly/G`1::SMt(!!0, + !!0) + IL_0007: nop + IL_0008: ret + } + + } + + .method public static class [runtime]System.Action`2 case19_nonEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/case19_nonEta@10::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 case3_etaCurried() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/case3_etaCurried@13::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 case33_etaTupled() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/case33_etaTupled@16::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericStaticMethod.fs.OptimizeOn.Preview.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericStaticMethod.fs.OptimizeOn.Preview.il.bsl new file mode 100644 index 00000000000..cb158381c58 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericStaticMethod.fs.OptimizeOn.Preview.il.bsl @@ -0,0 +1,114 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable nested public G`1 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public static void SMc(!!T x, + !!T y) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 8 + IL_0000: ret + } + + .method public static void SMt(!!T x, + !!T y) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + } + + .method public static class [runtime]System.Action`2 case19_nonEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void class assembly/G`1::SMc(!!0, + !!0) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 case3_etaCurried() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void class assembly/G`1::SMc(!!0, + !!0) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 case33_etaTupled() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void class assembly/G`1::SMt(!!0, + !!0) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericStaticMethod.fs.OptimizeOn.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericStaticMethod.fs.OptimizeOn.il.bsl new file mode 100644 index 00000000000..97f8c55b9dc --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericStaticMethod.fs.OptimizeOn.il.bsl @@ -0,0 +1,156 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable nested public G`1 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public static void SMc(!!T x, + !!T y) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 8 + IL_0000: ret + } + + .method public static void SMt(!!T x, + !!T y) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case19_nonEta@10 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 x, + int32 y) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case3_etaCurried@13 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 a, + int32 b) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case33_etaTupled@16 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 a, + int32 b) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + } + + .method public static class [runtime]System.Action`2 case19_nonEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/case19_nonEta@10::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 case3_etaCurried() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/case3_etaCurried@13::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 case33_etaTupled() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/case33_etaTupled@16::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateILMethod.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateILMethod.fs new file mode 100644 index 00000000000..d5a9ebf9fbe --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateILMethod.fs @@ -0,0 +1,15 @@ +module DelegateILMethod + +open System +open System.Text + +// IL (BCL) method targets are compiled as TOp.ILCall rather than an F# value application. They are made +// direct only in optimized builds; in unoptimized builds the eta form keeps a closure (matching the F# +// eta policy). See DelegateKnownFunction for the F#-value equivalent. + +// 12. eta IL/BCL static method (System.Math.Max). +let ilStaticEta () = Func(fun a b -> Math.Max(a, b)) + +// 13. eta IL/BCL instance method (StringBuilder.Append(string)) on a reference type. The receiver is a +// parameter, evaluated at the construction site and carried as the delegate's Target. +let ilInstanceEta (sb: StringBuilder) = Func(fun s -> sb.Append(s)) diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateILMethod.fs.OptimizeOff.Preview.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateILMethod.fs.OptimizeOff.Preview.il.bsl new file mode 100644 index 00000000000..5ca457d058f --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateILMethod.fs.OptimizeOff.Preview.il.bsl @@ -0,0 +1,127 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname ilStaticEta@11 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static int32 Invoke(int32 a, + int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: call int32 [runtime]System.Math::Max(int32, + int32) + IL_0007: ret + } + + } + + .class auto autochar serializable sealed nested assembly beforefieldinit specialname ilInstanceEta@15 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public class [runtime]System.Text.StringBuilder sb + .method public specialname rtspecialname instance void .ctor(class [runtime]System.Text.StringBuilder sb) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld class [runtime]System.Text.StringBuilder assembly/ilInstanceEta@15::sb + IL_0007: ldarg.0 + IL_0008: call instance void [runtime]System.Object::.ctor() + IL_000d: ret + } + + .method assembly hidebysig instance class [runtime]System.Text.StringBuilder Invoke(string s) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld class [runtime]System.Text.StringBuilder assembly/ilInstanceEta@15::sb + IL_0006: ldarg.1 + IL_0007: callvirt instance class [runtime]System.Text.StringBuilder [runtime]System.Text.StringBuilder::Append(string) + IL_000c: ret + } + + } + + .method public static class [runtime]System.Func`3 ilStaticEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn int32 assembly/ilStaticEta@11::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Func`3::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Func`2 ilInstanceEta(class [runtime]System.Text.StringBuilder sb) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: newobj instance void assembly/ilInstanceEta@15::.ctor(class [runtime]System.Text.StringBuilder) + IL_0006: ldftn instance class [runtime]System.Text.StringBuilder assembly/ilInstanceEta@15::Invoke(string) + IL_000c: newobj instance void class [runtime]System.Func`2::.ctor(object, + native int) + IL_0011: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateILMethod.fs.OptimizeOff.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateILMethod.fs.OptimizeOff.il.bsl new file mode 100644 index 00000000000..98e340a1d79 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateILMethod.fs.OptimizeOff.il.bsl @@ -0,0 +1,127 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname ilStaticEta@11 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static int32 Invoke(int32 a, + int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: call int32 [runtime]System.Math::Max(int32, + int32) + IL_0007: ret + } + + } + + .class auto autochar serializable sealed nested assembly beforefieldinit specialname ilInstanceEta@15 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public class [runtime]System.Text.StringBuilder sb + .method public specialname rtspecialname instance void .ctor(class [runtime]System.Text.StringBuilder sb) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld class [runtime]System.Text.StringBuilder assembly/ilInstanceEta@15::sb + IL_0007: ldarg.0 + IL_0008: call instance void [runtime]System.Object::.ctor() + IL_000d: ret + } + + .method assembly hidebysig instance class [runtime]System.Text.StringBuilder Invoke(string s) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld class [runtime]System.Text.StringBuilder assembly/ilInstanceEta@15::sb + IL_0006: ldarg.1 + IL_0007: callvirt instance class [runtime]System.Text.StringBuilder [runtime]System.Text.StringBuilder::Append(string) + IL_000c: ret + } + + } + + .method public static class [runtime]System.Func`3 ilStaticEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn int32 assembly/ilStaticEta@11::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Func`3::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Func`2 ilInstanceEta(class [runtime]System.Text.StringBuilder sb) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: newobj instance void assembly/ilInstanceEta@15::.ctor(class [runtime]System.Text.StringBuilder) + IL_0006: ldftn instance class [runtime]System.Text.StringBuilder assembly/ilInstanceEta@15::Invoke(string) + IL_000c: newobj instance void class [runtime]System.Func`2::.ctor(object, + native int) + IL_0011: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateILMethod.fs.OptimizeOn.Preview.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateILMethod.fs.OptimizeOn.Preview.il.bsl new file mode 100644 index 00000000000..ef4e95130a2 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateILMethod.fs.OptimizeOn.Preview.il.bsl @@ -0,0 +1,78 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .method public static class [runtime]System.Func`3 ilStaticEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn int32 [runtime]System.Math::Max(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Func`3::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Func`2 ilInstanceEta(class [runtime]System.Text.StringBuilder sb) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldftn instance class [runtime]System.Text.StringBuilder [runtime]System.Text.StringBuilder::Append(string) + IL_0007: newobj instance void class [runtime]System.Func`2::.ctor(object, + native int) + IL_000c: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateILMethod.fs.OptimizeOn.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateILMethod.fs.OptimizeOn.il.bsl new file mode 100644 index 00000000000..98e340a1d79 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateILMethod.fs.OptimizeOn.il.bsl @@ -0,0 +1,127 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname ilStaticEta@11 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static int32 Invoke(int32 a, + int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: call int32 [runtime]System.Math::Max(int32, + int32) + IL_0007: ret + } + + } + + .class auto autochar serializable sealed nested assembly beforefieldinit specialname ilInstanceEta@15 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public class [runtime]System.Text.StringBuilder sb + .method public specialname rtspecialname instance void .ctor(class [runtime]System.Text.StringBuilder sb) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld class [runtime]System.Text.StringBuilder assembly/ilInstanceEta@15::sb + IL_0007: ldarg.0 + IL_0008: call instance void [runtime]System.Object::.ctor() + IL_000d: ret + } + + .method assembly hidebysig instance class [runtime]System.Text.StringBuilder Invoke(string s) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld class [runtime]System.Text.StringBuilder assembly/ilInstanceEta@15::sb + IL_0006: ldarg.1 + IL_0007: callvirt instance class [runtime]System.Text.StringBuilder [runtime]System.Text.StringBuilder::Append(string) + IL_000c: ret + } + + } + + .method public static class [runtime]System.Func`3 ilStaticEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn int32 assembly/ilStaticEta@11::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Func`3::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Func`2 ilInstanceEta(class [runtime]System.Text.StringBuilder sb) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: newobj instance void assembly/ilInstanceEta@15::.ctor(class [runtime]System.Text.StringBuilder) + IL_0006: ldftn instance class [runtime]System.Text.StringBuilder assembly/ilInstanceEta@15::Invoke(string) + IL_000c: newobj instance void class [runtime]System.Func`2::.ctor(object, + native int) + IL_0011: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateInstanceMethod.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateInstanceMethod.fs new file mode 100644 index 00000000000..76c6c53e334 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateInstanceMethod.fs @@ -0,0 +1,21 @@ +module DelegateInstanceMethod + +open System + +type C(k: int) = + member _.AddC (x: int) (y: int) : unit = ignore k + member _.AddT (x: int, y: int) : unit = ignore k + abstract V : int -> int -> unit + default _.V (x: int) (y: int) : unit = ignore k + +// 20. non-eta instance method +let case20_nonEta (o: C) = Action(o.AddC) + +// 4. eta instance method (curried application) +let case4_etaCurried (o: C) = Action(fun a b -> o.AddC a b) + +// 34. eta instance method, tupled application +let case34_etaTupled (o: C) = Action(fun a b -> o.AddT(a, b)) + +// 21. non-eta virtual instance method: a direct delegate must use ldvirtftn (with dup) to preserve dispatch +let case21_virtual (o: C) = Action(o.V) diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateInstanceMethod.fs.OptimizeOff.Preview.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateInstanceMethod.fs.OptimizeOff.Preview.il.bsl new file mode 100644 index 00000000000..876f6a1aaee --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateInstanceMethod.fs.OptimizeOff.Preview.il.bsl @@ -0,0 +1,228 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable nested public C + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .field assembly int32 k + .method public specialname rtspecialname instance void .ctor(int32 k) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: callvirt instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ldarg.0 + IL_0009: ldarg.1 + IL_000a: stfld int32 assembly/C::k + IL_000f: ret + } + + .method public hidebysig instance void AddC(int32 x, int32 y) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 3 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: ldfld int32 assembly/C::k + IL_0006: stloc.0 + IL_0007: ret + } + + .method public hidebysig instance void AddT(int32 x, int32 y) cil managed + { + + .maxstack 3 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: ldfld int32 assembly/C::k + IL_0006: stloc.0 + IL_0007: ret + } + + .method public hidebysig virtual instance void V(int32 x, int32 y) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 3 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: ldfld int32 assembly/C::k + IL_0006: stloc.0 + IL_0007: ret + } + + } + + .class auto autochar serializable sealed nested assembly beforefieldinit specialname case4_etaCurried@15 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public class assembly/C o + .method public specialname rtspecialname instance void .ctor(class assembly/C o) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld class assembly/C assembly/case4_etaCurried@15::o + IL_0007: ldarg.0 + IL_0008: call instance void [runtime]System.Object::.ctor() + IL_000d: ret + } + + .method assembly hidebysig instance void Invoke(int32 a, int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld class assembly/C assembly/case4_etaCurried@15::o + IL_0006: ldarg.1 + IL_0007: ldarg.2 + IL_0008: callvirt instance void assembly/C::AddC(int32, + int32) + IL_000d: nop + IL_000e: ret + } + + } + + .class auto autochar serializable sealed nested assembly beforefieldinit specialname case34_etaTupled@18 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public class assembly/C o + .method public specialname rtspecialname instance void .ctor(class assembly/C o) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld class assembly/C assembly/case34_etaTupled@18::o + IL_0007: ldarg.0 + IL_0008: call instance void [runtime]System.Object::.ctor() + IL_000d: ret + } + + .method assembly hidebysig instance void Invoke(int32 a, int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld class assembly/C assembly/case34_etaTupled@18::o + IL_0006: ldarg.1 + IL_0007: ldarg.2 + IL_0008: callvirt instance void assembly/C::AddT(int32, + int32) + IL_000d: nop + IL_000e: ret + } + + } + + .method public static class [runtime]System.Action`2 case20_nonEta(class assembly/C o) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldftn instance void assembly/C::AddC(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 case4_etaCurried(class assembly/C o) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: newobj instance void assembly/case4_etaCurried@15::.ctor(class assembly/C) + IL_0006: ldftn instance void assembly/case4_etaCurried@15::Invoke(int32, + int32) + IL_000c: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_0011: ret + } + + .method public static class [runtime]System.Action`2 case34_etaTupled(class assembly/C o) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: newobj instance void assembly/case34_etaTupled@18::.ctor(class assembly/C) + IL_0006: ldftn instance void assembly/case34_etaTupled@18::Invoke(int32, + int32) + IL_000c: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_0011: ret + } + + .method public static class [runtime]System.Action`2 case21_virtual(class assembly/C o) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: dup + IL_0002: ldvirtftn instance void assembly/C::V(int32, + int32) + IL_0008: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000d: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateInstanceMethod.fs.OptimizeOff.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateInstanceMethod.fs.OptimizeOff.il.bsl new file mode 100644 index 00000000000..a9c6bfae607 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateInstanceMethod.fs.OptimizeOff.il.bsl @@ -0,0 +1,295 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable nested public C + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .field assembly int32 k + .method public specialname rtspecialname instance void .ctor(int32 k) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: callvirt instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ldarg.0 + IL_0009: ldarg.1 + IL_000a: stfld int32 assembly/C::k + IL_000f: ret + } + + .method public hidebysig instance void AddC(int32 x, int32 y) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 3 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: ldfld int32 assembly/C::k + IL_0006: stloc.0 + IL_0007: ret + } + + .method public hidebysig instance void AddT(int32 x, int32 y) cil managed + { + + .maxstack 3 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: ldfld int32 assembly/C::k + IL_0006: stloc.0 + IL_0007: ret + } + + .method public hidebysig virtual instance void V(int32 x, int32 y) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 3 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: ldfld int32 assembly/C::k + IL_0006: stloc.0 + IL_0007: ret + } + + } + + .class auto autochar serializable sealed nested assembly beforefieldinit specialname case20_nonEta@12 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public class assembly/C o + .method public specialname rtspecialname instance void .ctor(class assembly/C o) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld class assembly/C assembly/case20_nonEta@12::o + IL_0007: ldarg.0 + IL_0008: call instance void [runtime]System.Object::.ctor() + IL_000d: ret + } + + .method assembly hidebysig instance void Invoke(int32 delegateArg0, int32 delegateArg1) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld class assembly/C assembly/case20_nonEta@12::o + IL_0006: ldarg.1 + IL_0007: ldarg.2 + IL_0008: callvirt instance void assembly/C::AddC(int32, + int32) + IL_000d: nop + IL_000e: ret + } + + } + + .class auto autochar serializable sealed nested assembly beforefieldinit specialname case4_etaCurried@15 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public class assembly/C o + .method public specialname rtspecialname instance void .ctor(class assembly/C o) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld class assembly/C assembly/case4_etaCurried@15::o + IL_0007: ldarg.0 + IL_0008: call instance void [runtime]System.Object::.ctor() + IL_000d: ret + } + + .method assembly hidebysig instance void Invoke(int32 a, int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld class assembly/C assembly/case4_etaCurried@15::o + IL_0006: ldarg.1 + IL_0007: ldarg.2 + IL_0008: callvirt instance void assembly/C::AddC(int32, + int32) + IL_000d: nop + IL_000e: ret + } + + } + + .class auto autochar serializable sealed nested assembly beforefieldinit specialname case34_etaTupled@18 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public class assembly/C o + .method public specialname rtspecialname instance void .ctor(class assembly/C o) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld class assembly/C assembly/case34_etaTupled@18::o + IL_0007: ldarg.0 + IL_0008: call instance void [runtime]System.Object::.ctor() + IL_000d: ret + } + + .method assembly hidebysig instance void Invoke(int32 a, int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld class assembly/C assembly/case34_etaTupled@18::o + IL_0006: ldarg.1 + IL_0007: ldarg.2 + IL_0008: callvirt instance void assembly/C::AddT(int32, + int32) + IL_000d: nop + IL_000e: ret + } + + } + + .class auto autochar serializable sealed nested assembly beforefieldinit specialname case21_virtual@21 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public class assembly/C o + .method public specialname rtspecialname instance void .ctor(class assembly/C o) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld class assembly/C assembly/case21_virtual@21::o + IL_0007: ldarg.0 + IL_0008: call instance void [runtime]System.Object::.ctor() + IL_000d: ret + } + + .method assembly hidebysig instance void Invoke(int32 delegateArg0, int32 delegateArg1) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld class assembly/C assembly/case21_virtual@21::o + IL_0006: ldarg.1 + IL_0007: ldarg.2 + IL_0008: tail. + IL_000a: callvirt instance void assembly/C::V(int32, + int32) + IL_000f: ret + } + + } + + .method public static class [runtime]System.Action`2 case20_nonEta(class assembly/C o) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: newobj instance void assembly/case20_nonEta@12::.ctor(class assembly/C) + IL_0006: ldftn instance void assembly/case20_nonEta@12::Invoke(int32, + int32) + IL_000c: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_0011: ret + } + + .method public static class [runtime]System.Action`2 case4_etaCurried(class assembly/C o) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: newobj instance void assembly/case4_etaCurried@15::.ctor(class assembly/C) + IL_0006: ldftn instance void assembly/case4_etaCurried@15::Invoke(int32, + int32) + IL_000c: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_0011: ret + } + + .method public static class [runtime]System.Action`2 case34_etaTupled(class assembly/C o) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: newobj instance void assembly/case34_etaTupled@18::.ctor(class assembly/C) + IL_0006: ldftn instance void assembly/case34_etaTupled@18::Invoke(int32, + int32) + IL_000c: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_0011: ret + } + + .method public static class [runtime]System.Action`2 case21_virtual(class assembly/C o) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: newobj instance void assembly/case21_virtual@21::.ctor(class assembly/C) + IL_0006: ldftn instance void assembly/case21_virtual@21::Invoke(int32, + int32) + IL_000c: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_0011: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateInstanceMethod.fs.OptimizeOn.Preview.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateInstanceMethod.fs.OptimizeOn.Preview.il.bsl new file mode 100644 index 00000000000..13e7184f77c --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateInstanceMethod.fs.OptimizeOn.Preview.il.bsl @@ -0,0 +1,148 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable nested public C + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .field assembly int32 k + .method public specialname rtspecialname instance void .ctor(int32 k) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: callvirt instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ldarg.0 + IL_0009: ldarg.1 + IL_000a: stfld int32 assembly/C::k + IL_000f: ret + } + + .method public hidebysig instance void AddC(int32 x, int32 y) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 8 + IL_0000: ret + } + + .method public hidebysig instance void AddT(int32 x, int32 y) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + .method public hidebysig virtual instance void V(int32 x, int32 y) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 8 + IL_0000: ret + } + + } + + .method public static class [runtime]System.Action`2 case20_nonEta(class assembly/C o) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldftn instance void assembly/C::AddC(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 case4_etaCurried(class assembly/C o) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldftn instance void assembly/C::AddC(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 case34_etaTupled(class assembly/C o) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldftn instance void assembly/C::AddT(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 case21_virtual(class assembly/C o) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: dup + IL_0002: ldvirtftn instance void assembly/C::V(int32, + int32) + IL_0008: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000d: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateInstanceMethod.fs.OptimizeOn.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateInstanceMethod.fs.OptimizeOn.il.bsl new file mode 100644 index 00000000000..b3569cf1a24 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateInstanceMethod.fs.OptimizeOn.il.bsl @@ -0,0 +1,223 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable nested public C + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .field assembly int32 k + .method public specialname rtspecialname instance void .ctor(int32 k) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: callvirt instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ldarg.0 + IL_0009: ldarg.1 + IL_000a: stfld int32 assembly/C::k + IL_000f: ret + } + + .method public hidebysig instance void AddC(int32 x, int32 y) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 8 + IL_0000: ret + } + + .method public hidebysig instance void AddT(int32 x, int32 y) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + .method public hidebysig virtual instance void V(int32 x, int32 y) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 8 + IL_0000: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case20_nonEta@12 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 delegateArg0, + int32 delegateArg1) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case4_etaCurried@15 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 a, + int32 b) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case34_etaTupled@18 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 a, + int32 b) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + } + + .class auto autochar serializable sealed nested assembly beforefieldinit specialname case21_virtual@21 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public class assembly/C o + .method public specialname rtspecialname instance void .ctor(class assembly/C o) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld class assembly/C assembly/case21_virtual@21::o + IL_0007: ldarg.0 + IL_0008: call instance void [runtime]System.Object::.ctor() + IL_000d: ret + } + + .method assembly hidebysig instance void Invoke(int32 delegateArg0, int32 delegateArg1) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld class assembly/C assembly/case21_virtual@21::o + IL_0006: ldarg.1 + IL_0007: ldarg.2 + IL_0008: tail. + IL_000a: callvirt instance void assembly/C::V(int32, + int32) + IL_000f: ret + } + + } + + .method public static class [runtime]System.Action`2 case20_nonEta(class assembly/C o) cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/case20_nonEta@12::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 case4_etaCurried(class assembly/C o) cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/case4_etaCurried@15::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 case34_etaTupled(class assembly/C o) cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/case34_etaTupled@18::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 case21_virtual(class assembly/C o) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: newobj instance void assembly/case21_virtual@21::.ctor(class assembly/C) + IL_0006: ldftn instance void assembly/case21_virtual@21::Invoke(int32, + int32) + IL_000c: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_0011: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateKnownFunction.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateKnownFunction.fs new file mode 100644 index 00000000000..8e550999ddf --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateKnownFunction.fs @@ -0,0 +1,20 @@ +module DelegateKnownFunction + +open System + +// known F# functions compiled as methods +let handlerCurried (x: int) (y: int) : unit = () +let handlerTupled (x: int, y: int) : unit = () +let handler3 (x: int) (y: int) (z: int) : unit = () + +// 17. non-eta module function +let case17_nonEta () = Action(handlerCurried) + +// 1. eta module function (curried application) +let case1_etaCurried () = Action(fun a b -> handlerCurried a b) + +// 31. eta module function, tupled application (same compiled representation) +let case31_etaTupled () = Action(fun a b -> handlerTupled (a, b)) + +// 37. partial application of module function (constant arg) +let case37_partial () = Action(handler3 1) diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateKnownFunction.fs.OptimizeOff.Preview.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateKnownFunction.fs.OptimizeOff.Preview.il.bsl new file mode 100644 index 00000000000..dd1c081a62f --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateKnownFunction.fs.OptimizeOff.Preview.il.bsl @@ -0,0 +1,190 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case1_etaCurried@14 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 a, + int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: call void assembly::handlerCurried(int32, + int32) + IL_0007: nop + IL_0008: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case31_etaTupled@17 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 a, + int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: call void assembly::handlerTupled(int32, + int32) + IL_0007: nop + IL_0008: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case37_partial@20 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 arg1, + int32 arg2) cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.1 + IL_0001: ldarg.0 + IL_0002: ldarg.1 + IL_0003: call void assembly::handler3(int32, + int32, + int32) + IL_0008: nop + IL_0009: ret + } + + } + + .method public static void handlerCurried(int32 x, + int32 y) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 8 + IL_0000: ret + } + + .method public static void handlerTupled(int32 x, + int32 y) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + .method public static void handler3(int32 x, + int32 y, + int32 z) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 03 00 00 00 01 00 00 00 01 00 00 00 01 00 + 00 00 00 00 ) + + .maxstack 8 + IL_0000: ret + } + + .method public static class [runtime]System.Action`2 case17_nonEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly::handlerCurried(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 case1_etaCurried() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/case1_etaCurried@14::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 case31_etaTupled() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/case31_etaTupled@17::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 case37_partial() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/case37_partial@20::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateKnownFunction.fs.OptimizeOff.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateKnownFunction.fs.OptimizeOff.il.bsl new file mode 100644 index 00000000000..4d080c7c4a9 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateKnownFunction.fs.OptimizeOff.il.bsl @@ -0,0 +1,209 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case17_nonEta@11 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 x, + int32 y) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: call void assembly::handlerCurried(int32, + int32) + IL_0007: nop + IL_0008: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case1_etaCurried@14 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 a, + int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: call void assembly::handlerCurried(int32, + int32) + IL_0007: nop + IL_0008: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case31_etaTupled@17 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 a, + int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: call void assembly::handlerTupled(int32, + int32) + IL_0007: nop + IL_0008: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case37_partial@20 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 delegateArg0, + int32 delegateArg1) cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.1 + IL_0001: ldarg.0 + IL_0002: ldarg.1 + IL_0003: call void assembly::handler3(int32, + int32, + int32) + IL_0008: nop + IL_0009: ret + } + + } + + .method public static void handlerCurried(int32 x, + int32 y) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 8 + IL_0000: ret + } + + .method public static void handlerTupled(int32 x, + int32 y) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + .method public static void handler3(int32 x, + int32 y, + int32 z) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 03 00 00 00 01 00 00 00 01 00 00 00 01 00 + 00 00 00 00 ) + + .maxstack 8 + IL_0000: ret + } + + .method public static class [runtime]System.Action`2 case17_nonEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/case17_nonEta@11::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 case1_etaCurried() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/case1_etaCurried@14::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 case31_etaTupled() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/case31_etaTupled@17::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 case37_partial() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/case37_partial@20::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateKnownFunction.fs.OptimizeOn.Preview.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateKnownFunction.fs.OptimizeOn.Preview.il.bsl new file mode 100644 index 00000000000..d881a035d3d --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateKnownFunction.fs.OptimizeOn.Preview.il.bsl @@ -0,0 +1,145 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case37_partial@20 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 arg1, + int32 arg2) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + } + + .method public static void handlerCurried(int32 x, + int32 y) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 8 + IL_0000: ret + } + + .method public static void handlerTupled(int32 x, + int32 y) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + .method public static void handler3(int32 x, + int32 y, + int32 z) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 03 00 00 00 01 00 00 00 01 00 00 00 01 00 + 00 00 00 00 ) + + .maxstack 8 + IL_0000: ret + } + + .method public static class [runtime]System.Action`2 case17_nonEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly::handlerCurried(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 case1_etaCurried() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly::handlerCurried(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 case31_etaTupled() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly::handlerTupled(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 case37_partial() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/case37_partial@20::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateKnownFunction.fs.OptimizeOn.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateKnownFunction.fs.OptimizeOn.il.bsl new file mode 100644 index 00000000000..2ac94696387 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateKnownFunction.fs.OptimizeOn.il.bsl @@ -0,0 +1,187 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case17_nonEta@11 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 x, + int32 y) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case1_etaCurried@14 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 a, + int32 b) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case31_etaTupled@17 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 a, + int32 b) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case37_partial@20 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 delegateArg0, + int32 delegateArg1) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + } + + .method public static void handlerCurried(int32 x, + int32 y) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 8 + IL_0000: ret + } + + .method public static void handlerTupled(int32 x, + int32 y) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + .method public static void handler3(int32 x, + int32 y, + int32 z) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 03 00 00 00 01 00 00 00 01 00 00 00 01 00 + 00 00 00 00 ) + + .maxstack 8 + IL_0000: ret + } + + .method public static class [runtime]System.Action`2 case17_nonEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/case17_nonEta@11::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 case1_etaCurried() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/case1_etaCurried@14::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 case31_etaTupled() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/case31_etaTupled@17::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 case37_partial() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/case37_partial@20::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateNegativeCases.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateNegativeCases.fs new file mode 100644 index 00000000000..3d00a59a5cb --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateNegativeCases.fs @@ -0,0 +1,42 @@ +module DelegateNegativeCases + +open System +open System.Runtime.CompilerServices + +// 42. first-class function value: there is no target method to point at, so a closure must remain +let firstClass (handler: int -> int -> unit) = Action(handler) + +// 43. lambda body is not a single direct forwarding call to a known target (the argument is computed, +// not the delegate parameters forwarded as-is): a closure must remain +let private sink (x: int) : unit = () +let notDirect (k: int) = Action(fun a b -> sink (a + b + k)) + +// 44. arguments reordered: not a transparent forwarding, so a closure must remain +let reordered (handler: int -> int -> unit) = Action(fun a b -> handler b a) + +type Holder() = + member _.TakesObj (x: obj) : int = 1 + +// 45. Reference-parameter contravariance: the delegate's Invoke is (string):int and the target is (object):int. +// The CLR would accept this binding directly (a delegate may bind a method whose parameter is a supertype), +// but it stays a closure: F# elaborates the 'string -> obj' argument upcast as a coercion, so the forwarded +// argument is no longer a verbatim Invoke parameter and the direct-delegate recognizer does not match. (The +// signature check is not involved - it never even runs here.) +let contra (h: Holder) = System.Func(fun s -> h.TakesObj s) + +[] +type Extensions = + [] + static member Echo<'T> (x: 'T, y: int, z: int) : 'T = x + +// 54. extension member on a VALUE-TYPE receiver: an extension member compiles to a static method whose first +// parameter is the receiver, which the closed-delegate mechanism would store as the 'object' Target and pass +// straight into that first by-value parameter with no unboxing. A value-type receiver therefore has no closed +// form (unlike a value-type *instance* receiver, which is reached through the method's unboxing stub), so a +// closure must remain. +let valueTypeExtension () = Func(fun a b -> (3).Echo(a, b)) + +// 55. over-application: 'failwith' takes only the message, and it is the *returned function* that consumes +// the delegate's (elided unit) argument. There is no saturated call to the target to point at - and binding +// 'failwith' directly would evaluate it once instead of per invocation - so a closure must remain. +let overApplied () = Action(failwith "nope") diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateNegativeCases.fs.OptimizeOff.Preview.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateNegativeCases.fs.OptimizeOff.Preview.il.bsl new file mode 100644 index 00000000000..77ad669f0e0 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateNegativeCases.fs.OptimizeOff.Preview.il.bsl @@ -0,0 +1,361 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto autochar serializable sealed nested assembly beforefieldinit specialname firstClass@7 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> 'handler' + .method public specialname rtspecialname instance void .ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> 'handler') cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> assembly/firstClass@7::'handler' + IL_0007: ldarg.0 + IL_0008: call instance void [runtime]System.Object::.ctor() + IL_000d: ret + } + + .method assembly hidebysig instance void Invoke(int32 arg1, int32 arg2) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> assembly/firstClass@7::'handler' + IL_0006: ldarg.1 + IL_0007: ldarg.2 + IL_0008: call !!0 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::InvokeFast(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>, + !0, + !1) + IL_000d: pop + IL_000e: ret + } + + } + + .class auto autochar serializable sealed nested assembly beforefieldinit specialname notDirect@12 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public int32 k + .method public specialname rtspecialname instance void .ctor(int32 k) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld int32 assembly/notDirect@12::k + IL_0007: ldarg.0 + IL_0008: call instance void [runtime]System.Object::.ctor() + IL_000d: ret + } + + .method assembly hidebysig instance void Invoke(int32 a, int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: ldarg.2 + IL_0002: add + IL_0003: ldarg.0 + IL_0004: ldfld int32 assembly/notDirect@12::k + IL_0009: add + IL_000a: call void assembly::sink(int32) + IL_000f: nop + IL_0010: ret + } + + } + + .class auto autochar serializable sealed nested assembly beforefieldinit specialname reordered@15 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> 'handler' + .method public specialname rtspecialname instance void .ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> 'handler') cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> assembly/reordered@15::'handler' + IL_0007: ldarg.0 + IL_0008: call instance void [runtime]System.Object::.ctor() + IL_000d: ret + } + + .method assembly hidebysig instance void Invoke(int32 a, int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> assembly/reordered@15::'handler' + IL_0006: ldarg.2 + IL_0007: ldarg.1 + IL_0008: call !!0 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::InvokeFast(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>, + !0, + !1) + IL_000d: pop + IL_000e: ret + } + + } + + .class auto ansi serializable nested public Holder + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor() cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: callvirt instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ret + } + + .method public hidebysig instance int32 TakesObj(object x) cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.1 + IL_0001: ret + } + + } + + .class auto autochar serializable sealed nested assembly beforefieldinit specialname contra@25 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public class assembly/Holder h + .method public specialname rtspecialname instance void .ctor(class assembly/Holder h) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld class assembly/Holder assembly/contra@25::h + IL_0007: ldarg.0 + IL_0008: call instance void [runtime]System.Object::.ctor() + IL_000d: ret + } + + .method assembly hidebysig instance int32 Invoke(string s) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld class assembly/Holder assembly/contra@25::h + IL_0006: ldarg.1 + IL_0007: callvirt instance int32 assembly/Holder::TakesObj(object) + IL_000c: ret + } + + } + + .class auto ansi serializable nested public Extensions + extends [runtime]System.Object + { + .custom instance void [runtime]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public static !!T Echo(!!T x, + int32 y, + int32 z) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname valueTypeExtension@37 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static int32 Invoke(int32 a, + int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.3 + IL_0001: ldarg.0 + IL_0002: ldarg.1 + IL_0003: call !!0 assembly/Extensions::Echo(!!0, + int32, + int32) + IL_0008: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname overApplied@42 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke() cil managed + { + + .maxstack 6 + .locals init (string V_0) + IL_0000: ldstr "nope" + IL_0005: stloc.0 + IL_0006: ldc.i4.0 + IL_0007: brfalse.s IL_0011 + + IL_0009: ldnull + IL_000a: unbox.any class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 + IL_000f: br.s IL_0018 + + IL_0011: ldloc.0 + IL_0012: call class [runtime]System.Exception [FSharp.Core]Microsoft.FSharp.Core.Operators::Failure(string) + IL_0017: throw + + IL_0018: ldnull + IL_0019: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_001e: pop + IL_001f: ret + } + + } + + .method public static class [runtime]System.Action`2 firstClass(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> 'handler') cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: newobj instance void assembly/firstClass@7::.ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) + IL_0006: ldftn instance void assembly/firstClass@7::Invoke(int32, + int32) + IL_000c: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_0011: ret + } + + .method private static void sink(int32 x) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + .method public static class [runtime]System.Action`2 notDirect(int32 k) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: newobj instance void assembly/notDirect@12::.ctor(int32) + IL_0006: ldftn instance void assembly/notDirect@12::Invoke(int32, + int32) + IL_000c: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_0011: ret + } + + .method public static class [runtime]System.Action`2 reordered(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> 'handler') cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: newobj instance void assembly/reordered@15::.ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) + IL_0006: ldftn instance void assembly/reordered@15::Invoke(int32, + int32) + IL_000c: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_0011: ret + } + + .method public static class [runtime]System.Func`2 contra(class assembly/Holder h) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: newobj instance void assembly/contra@25::.ctor(class assembly/Holder) + IL_0006: ldftn instance int32 assembly/contra@25::Invoke(string) + IL_000c: newobj instance void class [runtime]System.Func`2::.ctor(object, + native int) + IL_0011: ret + } + + .method public static class [runtime]System.Func`3 valueTypeExtension() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn int32 assembly/valueTypeExtension@37::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Func`3::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action overApplied() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/overApplied@42::Invoke() + IL_0007: newobj instance void [runtime]System.Action::.ctor(object, + native int) + IL_000c: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateNegativeCases.fs.OptimizeOff.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateNegativeCases.fs.OptimizeOff.il.bsl new file mode 100644 index 00000000000..ea6c1edee84 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateNegativeCases.fs.OptimizeOff.il.bsl @@ -0,0 +1,361 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto autochar serializable sealed nested assembly beforefieldinit specialname firstClass@7 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> 'handler' + .method public specialname rtspecialname instance void .ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> 'handler') cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> assembly/firstClass@7::'handler' + IL_0007: ldarg.0 + IL_0008: call instance void [runtime]System.Object::.ctor() + IL_000d: ret + } + + .method assembly hidebysig instance void Invoke(int32 delegateArg0, int32 delegateArg1) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> assembly/firstClass@7::'handler' + IL_0006: ldarg.1 + IL_0007: ldarg.2 + IL_0008: call !!0 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::InvokeFast(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>, + !0, + !1) + IL_000d: pop + IL_000e: ret + } + + } + + .class auto autochar serializable sealed nested assembly beforefieldinit specialname notDirect@12 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public int32 k + .method public specialname rtspecialname instance void .ctor(int32 k) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld int32 assembly/notDirect@12::k + IL_0007: ldarg.0 + IL_0008: call instance void [runtime]System.Object::.ctor() + IL_000d: ret + } + + .method assembly hidebysig instance void Invoke(int32 a, int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: ldarg.2 + IL_0002: add + IL_0003: ldarg.0 + IL_0004: ldfld int32 assembly/notDirect@12::k + IL_0009: add + IL_000a: call void assembly::sink(int32) + IL_000f: nop + IL_0010: ret + } + + } + + .class auto autochar serializable sealed nested assembly beforefieldinit specialname reordered@15 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> 'handler' + .method public specialname rtspecialname instance void .ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> 'handler') cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> assembly/reordered@15::'handler' + IL_0007: ldarg.0 + IL_0008: call instance void [runtime]System.Object::.ctor() + IL_000d: ret + } + + .method assembly hidebysig instance void Invoke(int32 a, int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> assembly/reordered@15::'handler' + IL_0006: ldarg.2 + IL_0007: ldarg.1 + IL_0008: call !!0 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::InvokeFast(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>, + !0, + !1) + IL_000d: pop + IL_000e: ret + } + + } + + .class auto ansi serializable nested public Holder + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor() cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: callvirt instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ret + } + + .method public hidebysig instance int32 TakesObj(object x) cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.1 + IL_0001: ret + } + + } + + .class auto autochar serializable sealed nested assembly beforefieldinit specialname contra@25 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public class assembly/Holder h + .method public specialname rtspecialname instance void .ctor(class assembly/Holder h) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld class assembly/Holder assembly/contra@25::h + IL_0007: ldarg.0 + IL_0008: call instance void [runtime]System.Object::.ctor() + IL_000d: ret + } + + .method assembly hidebysig instance int32 Invoke(string s) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld class assembly/Holder assembly/contra@25::h + IL_0006: ldarg.1 + IL_0007: callvirt instance int32 assembly/Holder::TakesObj(object) + IL_000c: ret + } + + } + + .class auto ansi serializable nested public Extensions + extends [runtime]System.Object + { + .custom instance void [runtime]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public static !!T Echo(!!T x, + int32 y, + int32 z) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname valueTypeExtension@37 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static int32 Invoke(int32 a, + int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.3 + IL_0001: ldarg.0 + IL_0002: ldarg.1 + IL_0003: call !!0 assembly/Extensions::Echo(!!0, + int32, + int32) + IL_0008: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname overApplied@42 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke() cil managed + { + + .maxstack 6 + .locals init (string V_0) + IL_0000: ldstr "nope" + IL_0005: stloc.0 + IL_0006: ldc.i4.0 + IL_0007: brfalse.s IL_0011 + + IL_0009: ldnull + IL_000a: unbox.any class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 + IL_000f: br.s IL_0018 + + IL_0011: ldloc.0 + IL_0012: call class [runtime]System.Exception [FSharp.Core]Microsoft.FSharp.Core.Operators::Failure(string) + IL_0017: throw + + IL_0018: ldnull + IL_0019: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_001e: pop + IL_001f: ret + } + + } + + .method public static class [runtime]System.Action`2 firstClass(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> 'handler') cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: newobj instance void assembly/firstClass@7::.ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) + IL_0006: ldftn instance void assembly/firstClass@7::Invoke(int32, + int32) + IL_000c: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_0011: ret + } + + .method private static void sink(int32 x) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + .method public static class [runtime]System.Action`2 notDirect(int32 k) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: newobj instance void assembly/notDirect@12::.ctor(int32) + IL_0006: ldftn instance void assembly/notDirect@12::Invoke(int32, + int32) + IL_000c: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_0011: ret + } + + .method public static class [runtime]System.Action`2 reordered(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> 'handler') cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: newobj instance void assembly/reordered@15::.ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) + IL_0006: ldftn instance void assembly/reordered@15::Invoke(int32, + int32) + IL_000c: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_0011: ret + } + + .method public static class [runtime]System.Func`2 contra(class assembly/Holder h) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: newobj instance void assembly/contra@25::.ctor(class assembly/Holder) + IL_0006: ldftn instance int32 assembly/contra@25::Invoke(string) + IL_000c: newobj instance void class [runtime]System.Func`2::.ctor(object, + native int) + IL_0011: ret + } + + .method public static class [runtime]System.Func`3 valueTypeExtension() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn int32 assembly/valueTypeExtension@37::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Func`3::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action overApplied() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/overApplied@42::Invoke() + IL_0007: newobj instance void [runtime]System.Action::.ctor(object, + native int) + IL_000c: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateNegativeCases.fs.OptimizeOn.Preview.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateNegativeCases.fs.OptimizeOn.Preview.il.bsl new file mode 100644 index 00000000000..cadd0be4581 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateNegativeCases.fs.OptimizeOn.Preview.il.bsl @@ -0,0 +1,323 @@ + + + + + +.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, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto autochar serializable sealed nested assembly beforefieldinit specialname firstClass@7 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> 'handler' + .method public specialname rtspecialname instance void .ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> 'handler') cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> assembly/firstClass@7::'handler' + IL_0007: ldarg.0 + IL_0008: call instance void [runtime]System.Object::.ctor() + IL_000d: ret + } + + .method assembly hidebysig instance void Invoke(int32 arg1, int32 arg2) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> assembly/firstClass@7::'handler' + IL_0006: ldarg.1 + IL_0007: ldarg.2 + IL_0008: call !!0 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::InvokeFast(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>, + !0, + !1) + IL_000d: pop + IL_000e: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname notDirect@12 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 a, + int32 b) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + } + + .class auto autochar serializable sealed nested assembly beforefieldinit specialname reordered@15 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> 'handler' + .method public specialname rtspecialname instance void .ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> 'handler') cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> assembly/reordered@15::'handler' + IL_0007: ldarg.0 + IL_0008: call instance void [runtime]System.Object::.ctor() + IL_000d: ret + } + + .method assembly hidebysig instance void Invoke(int32 a, int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> assembly/reordered@15::'handler' + IL_0006: ldarg.2 + IL_0007: ldarg.1 + IL_0008: call !!0 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::InvokeFast(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>, + !0, + !1) + IL_000d: pop + IL_000e: ret + } + + } + + .class auto ansi serializable nested public Holder + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor() cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: callvirt instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ret + } + + .method public hidebysig instance int32 TakesObj(object x) cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.1 + IL_0001: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname contra@25 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static int32 Invoke(string s) cil managed + { + + .maxstack 5 + .locals init (object V_0) + IL_0000: ldarg.0 + IL_0001: stloc.0 + IL_0002: ldc.i4.1 + IL_0003: ret + } + + } + + .class auto ansi serializable nested public Extensions + extends [runtime]System.Object + { + .custom instance void [runtime]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public static !!T Echo(!!T x, + int32 y, + int32 z) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname valueTypeExtension@37 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static int32 Invoke(int32 a, + int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.3 + IL_0001: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname overApplied@42 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke() cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.0 + IL_0001: brfalse.s IL_000b + + IL_0003: ldnull + IL_0004: unbox.any class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 + IL_0009: br.s IL_0016 + + IL_000b: ldstr "nope" + IL_0010: newobj instance void [netstandard]System.Exception::.ctor(string) + IL_0015: throw + + IL_0016: ldnull + IL_0017: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_001c: pop + IL_001d: ret + } + + } + + .method public static class [runtime]System.Action`2 firstClass(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> 'handler') cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: newobj instance void assembly/firstClass@7::.ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) + IL_0006: ldftn instance void assembly/firstClass@7::Invoke(int32, + int32) + IL_000c: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_0011: ret + } + + .method private static void sink(int32 x) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + .method public static class [runtime]System.Action`2 notDirect(int32 k) cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/notDirect@12::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 reordered(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> 'handler') cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: newobj instance void assembly/reordered@15::.ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) + IL_0006: ldftn instance void assembly/reordered@15::Invoke(int32, + int32) + IL_000c: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_0011: ret + } + + .method public static class [runtime]System.Func`2 contra(class assembly/Holder h) cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn int32 assembly/contra@25::Invoke(string) + IL_0007: newobj instance void class [runtime]System.Func`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Func`3 valueTypeExtension() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn int32 assembly/valueTypeExtension@37::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Func`3::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action overApplied() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/overApplied@42::Invoke() + IL_0007: newobj instance void [runtime]System.Action::.ctor(object, + native int) + IL_000c: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateNegativeCases.fs.OptimizeOn.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateNegativeCases.fs.OptimizeOn.il.bsl new file mode 100644 index 00000000000..6f3ed2ddc14 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateNegativeCases.fs.OptimizeOn.il.bsl @@ -0,0 +1,323 @@ + + + + + +.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, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto autochar serializable sealed nested assembly beforefieldinit specialname firstClass@7 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> 'handler' + .method public specialname rtspecialname instance void .ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> 'handler') cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> assembly/firstClass@7::'handler' + IL_0007: ldarg.0 + IL_0008: call instance void [runtime]System.Object::.ctor() + IL_000d: ret + } + + .method assembly hidebysig instance void Invoke(int32 delegateArg0, int32 delegateArg1) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> assembly/firstClass@7::'handler' + IL_0006: ldarg.1 + IL_0007: ldarg.2 + IL_0008: call !!0 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::InvokeFast(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>, + !0, + !1) + IL_000d: pop + IL_000e: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname notDirect@12 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 a, + int32 b) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + } + + .class auto autochar serializable sealed nested assembly beforefieldinit specialname reordered@15 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> 'handler' + .method public specialname rtspecialname instance void .ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> 'handler') cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> assembly/reordered@15::'handler' + IL_0007: ldarg.0 + IL_0008: call instance void [runtime]System.Object::.ctor() + IL_000d: ret + } + + .method assembly hidebysig instance void Invoke(int32 a, int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> assembly/reordered@15::'handler' + IL_0006: ldarg.2 + IL_0007: ldarg.1 + IL_0008: call !!0 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::InvokeFast(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>, + !0, + !1) + IL_000d: pop + IL_000e: ret + } + + } + + .class auto ansi serializable nested public Holder + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor() cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: callvirt instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ret + } + + .method public hidebysig instance int32 TakesObj(object x) cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.1 + IL_0001: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname contra@25 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static int32 Invoke(string s) cil managed + { + + .maxstack 5 + .locals init (object V_0) + IL_0000: ldarg.0 + IL_0001: stloc.0 + IL_0002: ldc.i4.1 + IL_0003: ret + } + + } + + .class auto ansi serializable nested public Extensions + extends [runtime]System.Object + { + .custom instance void [runtime]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public static !!T Echo(!!T x, + int32 y, + int32 z) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname valueTypeExtension@37 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static int32 Invoke(int32 a, + int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.3 + IL_0001: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname overApplied@42 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke() cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.0 + IL_0001: brfalse.s IL_000b + + IL_0003: ldnull + IL_0004: unbox.any class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 + IL_0009: br.s IL_0016 + + IL_000b: ldstr "nope" + IL_0010: newobj instance void [netstandard]System.Exception::.ctor(string) + IL_0015: throw + + IL_0016: ldnull + IL_0017: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_001c: pop + IL_001d: ret + } + + } + + .method public static class [runtime]System.Action`2 firstClass(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> 'handler') cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: newobj instance void assembly/firstClass@7::.ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) + IL_0006: ldftn instance void assembly/firstClass@7::Invoke(int32, + int32) + IL_000c: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_0011: ret + } + + .method private static void sink(int32 x) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + .method public static class [runtime]System.Action`2 notDirect(int32 k) cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/notDirect@12::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 reordered(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> 'handler') cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: newobj instance void assembly/reordered@15::.ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) + IL_0006: ldftn instance void assembly/reordered@15::Invoke(int32, + int32) + IL_000c: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_0011: ret + } + + .method public static class [runtime]System.Func`2 contra(class assembly/Holder h) cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn int32 assembly/contra@25::Invoke(string) + IL_0007: newobj instance void class [runtime]System.Func`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Func`3 valueTypeExtension() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn int32 assembly/valueTypeExtension@37::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Func`3::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action overApplied() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/overApplied@42::Invoke() + IL_0007: newobj instance void [runtime]System.Action::.ctor(object, + native int) + IL_000c: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegatePartialApplication.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegatePartialApplication.fs new file mode 100644 index 00000000000..a77f70c8adb --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegatePartialApplication.fs @@ -0,0 +1,32 @@ +module DelegatePartialApplication + +open System + +// Cases 37/38 (in DelegateKnownFunction.fs / DelegateStaticMethod.fs) capture a +// constant first argument, so their closure can stay static (the constant is re-materialised in Invoke +// with no instance field). Capturing a runtime VALUE instead forces the closure to carry an instance +// field, which exercises a distinct emit path. None of the cases below can become a direct delegate: +// - The CLR's closed delegate binds exactly ONE leading value as the Target. papInstanceVar fixes two +// leading values (the receiver 'o' and the argument 'n'), so there is no closed form. +// - papKnownVar / papStaticVar fix a single leading value, but it is an 'int'. The closed-delegate thunk +// passes the Target (an 'object') straight into the method's first parameter with NO unboxing, so a +// value-type first parameter has no closed form at all (the same reason a value-type receiver is +// excluded). A reference-type fixed argument, by contrast, IS emitted directly (see the execution test +// `Reference-type single-argument partial application is direct`). + +let handler3 (x: int) (y: int) (z: int) : unit = () + +type C = + static member Add3 (x: int) (y: int) (z: int) : unit = () + +type I(k: int) = + member _.Add3 (x: int) (y: int) (z: int) : unit = ignore k + +// 39. partial application of module function (captured var: instance-field capture of n) +let papKnownVar (n: int) = Action(handler3 n) + +// 40. partial application of static method (captured var) +let papStaticVar (n: int) = Action(C.Add3 n) + +// 41. partial application of instance method (captures both the receiver and n) +let papInstanceVar (o: I) (n: int) = Action(o.Add3 n) diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegatePartialApplication.fs.OptimizeOff.Preview.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegatePartialApplication.fs.OptimizeOff.Preview.il.bsl new file mode 100644 index 00000000000..64b30067a6b --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegatePartialApplication.fs.OptimizeOff.Preview.il.bsl @@ -0,0 +1,270 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable nested public C + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public static void Add3(int32 x, + int32 y, + int32 z) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 03 00 00 00 01 00 00 00 01 00 00 00 01 00 + 00 00 00 00 ) + + .maxstack 8 + IL_0000: ret + } + + } + + .class auto ansi serializable nested public I + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .field assembly int32 k + .method public specialname rtspecialname instance void .ctor(int32 k) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: callvirt instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ldarg.0 + IL_0009: ldarg.1 + IL_000a: stfld int32 assembly/I::k + IL_000f: ret + } + + .method public hidebysig instance void + Add3(int32 x, + int32 y, + int32 z) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 03 00 00 00 01 00 00 00 01 00 00 00 01 00 + 00 00 00 00 ) + + .maxstack 3 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: ldfld int32 assembly/I::k + IL_0006: stloc.0 + IL_0007: ret + } + + } + + .class auto autochar serializable sealed nested assembly beforefieldinit specialname papKnownVar@26 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public int32 n + .method public specialname rtspecialname instance void .ctor(int32 n) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld int32 assembly/papKnownVar@26::n + IL_0007: ldarg.0 + IL_0008: call instance void [runtime]System.Object::.ctor() + IL_000d: ret + } + + .method assembly hidebysig instance void Invoke(int32 arg1, int32 arg2) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld int32 assembly/papKnownVar@26::n + IL_0006: ldarg.1 + IL_0007: ldarg.2 + IL_0008: call void assembly::handler3(int32, + int32, + int32) + IL_000d: nop + IL_000e: ret + } + + } + + .class auto autochar serializable sealed nested assembly beforefieldinit specialname papStaticVar@29 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public int32 n + .method public specialname rtspecialname instance void .ctor(int32 n) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld int32 assembly/papStaticVar@29::n + IL_0007: ldarg.0 + IL_0008: call instance void [runtime]System.Object::.ctor() + IL_000d: ret + } + + .method assembly hidebysig instance void Invoke(int32 arg1, int32 arg2) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld int32 assembly/papStaticVar@29::n + IL_0006: ldarg.1 + IL_0007: ldarg.2 + IL_0008: call void assembly/C::Add3(int32, + int32, + int32) + IL_000d: nop + IL_000e: ret + } + + } + + .class auto autochar serializable sealed nested assembly beforefieldinit specialname papInstanceVar@32 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public class assembly/I o + .field public int32 n + .method public specialname rtspecialname instance void .ctor(class assembly/I o, int32 n) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld class assembly/I assembly/papInstanceVar@32::o + IL_0007: ldarg.0 + IL_0008: ldarg.2 + IL_0009: stfld int32 assembly/papInstanceVar@32::n + IL_000e: ldarg.0 + IL_000f: call instance void [runtime]System.Object::.ctor() + IL_0014: ret + } + + .method assembly hidebysig instance void Invoke(int32 arg1, int32 arg2) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld class assembly/I assembly/papInstanceVar@32::o + IL_0006: ldarg.0 + IL_0007: ldfld int32 assembly/papInstanceVar@32::n + IL_000c: ldarg.1 + IL_000d: ldarg.2 + IL_000e: callvirt instance void assembly/I::Add3(int32, + int32, + int32) + IL_0013: nop + IL_0014: ret + } + + } + + .method public static void handler3(int32 x, + int32 y, + int32 z) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 03 00 00 00 01 00 00 00 01 00 00 00 01 00 + 00 00 00 00 ) + + .maxstack 8 + IL_0000: ret + } + + .method public static class [runtime]System.Action`2 papKnownVar(int32 n) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: newobj instance void assembly/papKnownVar@26::.ctor(int32) + IL_0006: ldftn instance void assembly/papKnownVar@26::Invoke(int32, + int32) + IL_000c: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_0011: ret + } + + .method public static class [runtime]System.Action`2 papStaticVar(int32 n) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: newobj instance void assembly/papStaticVar@29::.ctor(int32) + IL_0006: ldftn instance void assembly/papStaticVar@29::Invoke(int32, + int32) + IL_000c: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_0011: ret + } + + .method public static class [runtime]System.Action`2 papInstanceVar(class assembly/I o, int32 n) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: newobj instance void assembly/papInstanceVar@32::.ctor(class assembly/I, + int32) + IL_0007: ldftn instance void assembly/papInstanceVar@32::Invoke(int32, + int32) + IL_000d: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_0012: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegatePartialApplication.fs.OptimizeOff.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegatePartialApplication.fs.OptimizeOff.il.bsl new file mode 100644 index 00000000000..d8ecbf83e0c --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegatePartialApplication.fs.OptimizeOff.il.bsl @@ -0,0 +1,270 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable nested public C + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public static void Add3(int32 x, + int32 y, + int32 z) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 03 00 00 00 01 00 00 00 01 00 00 00 01 00 + 00 00 00 00 ) + + .maxstack 8 + IL_0000: ret + } + + } + + .class auto ansi serializable nested public I + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .field assembly int32 k + .method public specialname rtspecialname instance void .ctor(int32 k) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: callvirt instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ldarg.0 + IL_0009: ldarg.1 + IL_000a: stfld int32 assembly/I::k + IL_000f: ret + } + + .method public hidebysig instance void + Add3(int32 x, + int32 y, + int32 z) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 03 00 00 00 01 00 00 00 01 00 00 00 01 00 + 00 00 00 00 ) + + .maxstack 3 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: ldfld int32 assembly/I::k + IL_0006: stloc.0 + IL_0007: ret + } + + } + + .class auto autochar serializable sealed nested assembly beforefieldinit specialname papKnownVar@26 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public int32 n + .method public specialname rtspecialname instance void .ctor(int32 n) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld int32 assembly/papKnownVar@26::n + IL_0007: ldarg.0 + IL_0008: call instance void [runtime]System.Object::.ctor() + IL_000d: ret + } + + .method assembly hidebysig instance void Invoke(int32 delegateArg0, int32 delegateArg1) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld int32 assembly/papKnownVar@26::n + IL_0006: ldarg.1 + IL_0007: ldarg.2 + IL_0008: call void assembly::handler3(int32, + int32, + int32) + IL_000d: nop + IL_000e: ret + } + + } + + .class auto autochar serializable sealed nested assembly beforefieldinit specialname papStaticVar@29 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public int32 n + .method public specialname rtspecialname instance void .ctor(int32 n) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld int32 assembly/papStaticVar@29::n + IL_0007: ldarg.0 + IL_0008: call instance void [runtime]System.Object::.ctor() + IL_000d: ret + } + + .method assembly hidebysig instance void Invoke(int32 delegateArg0, int32 delegateArg1) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld int32 assembly/papStaticVar@29::n + IL_0006: ldarg.1 + IL_0007: ldarg.2 + IL_0008: call void assembly/C::Add3(int32, + int32, + int32) + IL_000d: nop + IL_000e: ret + } + + } + + .class auto autochar serializable sealed nested assembly beforefieldinit specialname papInstanceVar@32 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public class assembly/I o + .field public int32 n + .method public specialname rtspecialname instance void .ctor(class assembly/I o, int32 n) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld class assembly/I assembly/papInstanceVar@32::o + IL_0007: ldarg.0 + IL_0008: ldarg.2 + IL_0009: stfld int32 assembly/papInstanceVar@32::n + IL_000e: ldarg.0 + IL_000f: call instance void [runtime]System.Object::.ctor() + IL_0014: ret + } + + .method assembly hidebysig instance void Invoke(int32 delegateArg0, int32 delegateArg1) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld class assembly/I assembly/papInstanceVar@32::o + IL_0006: ldarg.0 + IL_0007: ldfld int32 assembly/papInstanceVar@32::n + IL_000c: ldarg.1 + IL_000d: ldarg.2 + IL_000e: callvirt instance void assembly/I::Add3(int32, + int32, + int32) + IL_0013: nop + IL_0014: ret + } + + } + + .method public static void handler3(int32 x, + int32 y, + int32 z) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 03 00 00 00 01 00 00 00 01 00 00 00 01 00 + 00 00 00 00 ) + + .maxstack 8 + IL_0000: ret + } + + .method public static class [runtime]System.Action`2 papKnownVar(int32 n) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: newobj instance void assembly/papKnownVar@26::.ctor(int32) + IL_0006: ldftn instance void assembly/papKnownVar@26::Invoke(int32, + int32) + IL_000c: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_0011: ret + } + + .method public static class [runtime]System.Action`2 papStaticVar(int32 n) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: newobj instance void assembly/papStaticVar@29::.ctor(int32) + IL_0006: ldftn instance void assembly/papStaticVar@29::Invoke(int32, + int32) + IL_000c: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_0011: ret + } + + .method public static class [runtime]System.Action`2 papInstanceVar(class assembly/I o, int32 n) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: newobj instance void assembly/papInstanceVar@32::.ctor(class assembly/I, + int32) + IL_0007: ldftn instance void assembly/papInstanceVar@32::Invoke(int32, + int32) + IL_000d: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_0012: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegatePartialApplication.fs.OptimizeOn.Preview.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegatePartialApplication.fs.OptimizeOn.Preview.il.bsl new file mode 100644 index 00000000000..bfbde14b661 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegatePartialApplication.fs.OptimizeOn.Preview.il.bsl @@ -0,0 +1,195 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable nested public C + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public static void Add3(int32 x, + int32 y, + int32 z) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 03 00 00 00 01 00 00 00 01 00 00 00 01 00 + 00 00 00 00 ) + + .maxstack 8 + IL_0000: ret + } + + } + + .class auto ansi serializable nested public I + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .field assembly int32 k + .method public specialname rtspecialname instance void .ctor(int32 k) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: callvirt instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ldarg.0 + IL_0009: ldarg.1 + IL_000a: stfld int32 assembly/I::k + IL_000f: ret + } + + .method public hidebysig instance void + Add3(int32 x, + int32 y, + int32 z) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 03 00 00 00 01 00 00 00 01 00 00 00 01 00 + 00 00 00 00 ) + + .maxstack 8 + IL_0000: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname papKnownVar@26 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 arg1, + int32 arg2) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname papStaticVar@29 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 arg1, + int32 arg2) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname papInstanceVar@32 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 arg1, + int32 arg2) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + } + + .method public static void handler3(int32 x, + int32 y, + int32 z) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 03 00 00 00 01 00 00 00 01 00 00 00 01 00 + 00 00 00 00 ) + + .maxstack 8 + IL_0000: ret + } + + .method public static class [runtime]System.Action`2 papKnownVar(int32 n) cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/papKnownVar@26::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 papStaticVar(int32 n) cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/papStaticVar@29::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 papInstanceVar(class assembly/I o, int32 n) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/papInstanceVar@32::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegatePartialApplication.fs.OptimizeOn.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegatePartialApplication.fs.OptimizeOn.il.bsl new file mode 100644 index 00000000000..4c748f45b02 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegatePartialApplication.fs.OptimizeOn.il.bsl @@ -0,0 +1,195 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable nested public C + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public static void Add3(int32 x, + int32 y, + int32 z) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 03 00 00 00 01 00 00 00 01 00 00 00 01 00 + 00 00 00 00 ) + + .maxstack 8 + IL_0000: ret + } + + } + + .class auto ansi serializable nested public I + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .field assembly int32 k + .method public specialname rtspecialname instance void .ctor(int32 k) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: callvirt instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ldarg.0 + IL_0009: ldarg.1 + IL_000a: stfld int32 assembly/I::k + IL_000f: ret + } + + .method public hidebysig instance void + Add3(int32 x, + int32 y, + int32 z) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 03 00 00 00 01 00 00 00 01 00 00 00 01 00 + 00 00 00 00 ) + + .maxstack 8 + IL_0000: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname papKnownVar@26 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 delegateArg0, + int32 delegateArg1) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname papStaticVar@29 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 delegateArg0, + int32 delegateArg1) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname papInstanceVar@32 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 delegateArg0, + int32 delegateArg1) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + } + + .method public static void handler3(int32 x, + int32 y, + int32 z) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 03 00 00 00 01 00 00 00 01 00 00 00 01 00 + 00 00 00 00 ) + + .maxstack 8 + IL_0000: ret + } + + .method public static class [runtime]System.Action`2 papKnownVar(int32 n) cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/papKnownVar@26::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 papStaticVar(int32 n) cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/papStaticVar@29::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 papInstanceVar(class assembly/I o, int32 n) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/papInstanceVar@32::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateStaticMethod.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateStaticMethod.fs new file mode 100644 index 00000000000..a78c9c97dac --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateStaticMethod.fs @@ -0,0 +1,21 @@ +module DelegateStaticMethod + +open System + +type C = + static member AddC (x: int) (y: int) : unit = () + static member AddT (x: int, y: int) : unit = () + static member Add3 (x: int) (y: int) (z: int) : unit = () + +// 18. non-eta static method +// (a tupled member is seen as a single tuple-arg value and will not coerce non-eta; use the curried member) +let case18_nonEta () = Action(C.AddC) + +// 2. eta static method (curried application) +let case2_etaCurried () = Action(fun a b -> C.AddC a b) + +// 32. eta static method, tupled application +let case32_etaTupled () = Action(fun a b -> C.AddT(a, b)) + +// 38. partial application of static method (constant arg) +let case38_partial () = Action(C.Add3 1) diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateStaticMethod.fs.OptimizeOff.Preview.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateStaticMethod.fs.OptimizeOff.Preview.il.bsl new file mode 100644 index 00000000000..35c6be20bc0 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateStaticMethod.fs.OptimizeOff.Preview.il.bsl @@ -0,0 +1,196 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable nested public C + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public static void AddC(int32 x, + int32 y) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 8 + IL_0000: ret + } + + .method public static void AddT(int32 x, + int32 y) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + .method public static void Add3(int32 x, + int32 y, + int32 z) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 03 00 00 00 01 00 00 00 01 00 00 00 01 00 + 00 00 00 00 ) + + .maxstack 8 + IL_0000: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case2_etaCurried@15 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 a, + int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: call void assembly/C::AddC(int32, + int32) + IL_0007: nop + IL_0008: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case32_etaTupled@18 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 a, + int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: call void assembly/C::AddT(int32, + int32) + IL_0007: nop + IL_0008: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case38_partial@21 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 arg1, + int32 arg2) cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.1 + IL_0001: ldarg.0 + IL_0002: ldarg.1 + IL_0003: call void assembly/C::Add3(int32, + int32, + int32) + IL_0008: nop + IL_0009: ret + } + + } + + .method public static class [runtime]System.Action`2 case18_nonEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/C::AddC(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 case2_etaCurried() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/case2_etaCurried@15::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 case32_etaTupled() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/case32_etaTupled@18::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 case38_partial() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/case38_partial@21::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateStaticMethod.fs.OptimizeOff.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateStaticMethod.fs.OptimizeOff.il.bsl new file mode 100644 index 00000000000..ce68901f780 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateStaticMethod.fs.OptimizeOff.il.bsl @@ -0,0 +1,215 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable nested public C + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public static void AddC(int32 x, + int32 y) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 8 + IL_0000: ret + } + + .method public static void AddT(int32 x, + int32 y) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + .method public static void Add3(int32 x, + int32 y, + int32 z) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 03 00 00 00 01 00 00 00 01 00 00 00 01 00 + 00 00 00 00 ) + + .maxstack 8 + IL_0000: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case18_nonEta@12 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 x, + int32 y) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: call void assembly/C::AddC(int32, + int32) + IL_0007: nop + IL_0008: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case2_etaCurried@15 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 a, + int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: call void assembly/C::AddC(int32, + int32) + IL_0007: nop + IL_0008: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case32_etaTupled@18 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 a, + int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: call void assembly/C::AddT(int32, + int32) + IL_0007: nop + IL_0008: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case38_partial@21 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 delegateArg0, + int32 delegateArg1) cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.1 + IL_0001: ldarg.0 + IL_0002: ldarg.1 + IL_0003: call void assembly/C::Add3(int32, + int32, + int32) + IL_0008: nop + IL_0009: ret + } + + } + + .method public static class [runtime]System.Action`2 case18_nonEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/case18_nonEta@12::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 case2_etaCurried() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/case2_etaCurried@15::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 case32_etaTupled() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/case32_etaTupled@18::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 case38_partial() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/case38_partial@21::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateStaticMethod.fs.OptimizeOn.Preview.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateStaticMethod.fs.OptimizeOn.Preview.il.bsl new file mode 100644 index 00000000000..8fa5fc34989 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateStaticMethod.fs.OptimizeOn.Preview.il.bsl @@ -0,0 +1,151 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable nested public C + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public static void AddC(int32 x, + int32 y) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 8 + IL_0000: ret + } + + .method public static void AddT(int32 x, + int32 y) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + .method public static void Add3(int32 x, + int32 y, + int32 z) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 03 00 00 00 01 00 00 00 01 00 00 00 01 00 + 00 00 00 00 ) + + .maxstack 8 + IL_0000: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case38_partial@21 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 arg1, + int32 arg2) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + } + + .method public static class [runtime]System.Action`2 case18_nonEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/C::AddC(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 case2_etaCurried() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/C::AddC(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 case32_etaTupled() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/C::AddT(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 case38_partial() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/case38_partial@21::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateStaticMethod.fs.OptimizeOn.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateStaticMethod.fs.OptimizeOn.il.bsl new file mode 100644 index 00000000000..1de6bfcc577 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateStaticMethod.fs.OptimizeOn.il.bsl @@ -0,0 +1,193 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable nested public C + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public static void AddC(int32 x, + int32 y) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 8 + IL_0000: ret + } + + .method public static void AddT(int32 x, + int32 y) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + .method public static void Add3(int32 x, + int32 y, + int32 z) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 03 00 00 00 01 00 00 00 01 00 00 00 01 00 + 00 00 00 00 ) + + .maxstack 8 + IL_0000: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case18_nonEta@12 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 x, + int32 y) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case2_etaCurried@15 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 a, + int32 b) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case32_etaTupled@18 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 a, + int32 b) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case38_partial@21 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 delegateArg0, + int32 delegateArg1) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + } + + .method public static class [runtime]System.Action`2 case18_nonEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/case18_nonEta@12::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 case2_etaCurried() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/case2_etaCurried@15::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 case32_etaTupled() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/case32_etaTupled@18::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 case38_partial() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/case38_partial@21::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateStructTarget.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateStructTarget.fs new file mode 100644 index 00000000000..7bed97158ec --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateStructTarget.fs @@ -0,0 +1,16 @@ +module DelegateStructTarget + +open System + +[] +type S = + member _.Add (x: int) (y: int) : int = x + y + +// The target is an instance method on a value type. A delegate's Target is an 'object', so the receiver is +// boxed (a copy) at the construction site and the runtime binds the unboxing stub; this matches the closure +// form, which also captures the struct by value. (See DelegateInstanceMethod for the reference-type case.) +// 50. non-eta struct (value-type) receiver +let structInstanceNonEta (s: S) = Func(s.Add) + +// 51. eta struct (value-type) receiver +let structInstanceEta (s: S) = Func(fun a b -> s.Add a b) diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateStructTarget.fs.OptimizeOff.Preview.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateStructTarget.fs.OptimizeOff.Preview.il.bsl new file mode 100644 index 00000000000..5b9ce3e8a8d --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateStructTarget.fs.OptimizeOff.Preview.il.bsl @@ -0,0 +1,281 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class sequential ansi serializable sealed nested public S + extends [runtime]System.ValueType + implements class [runtime]System.IEquatable`1, + [runtime]System.Collections.IStructuralEquatable, + class [runtime]System.IComparable`1, + [runtime]System.IComparable, + [runtime]System.Collections.IStructuralComparable + { + .pack 0 + .size 1 + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.StructAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public hidebysig virtual final instance int32 CompareTo(valuetype assembly/S obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 3 + .locals init (valuetype assembly/S& V_0) + IL_0000: ldarga.s obj + IL_0002: stloc.0 + IL_0003: ldc.i4.0 + IL_0004: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: unbox.any assembly/S + IL_0007: call instance int32 assembly/S::CompareTo(valuetype assembly/S) + IL_000c: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj, class [runtime]System.Collections.IComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 3 + .locals init (valuetype assembly/S V_0, + valuetype assembly/S& V_1) + IL_0000: ldarg.1 + IL_0001: unbox.any assembly/S + IL_0006: stloc.0 + IL_0007: ldloca.s V_0 + IL_0009: stloc.1 + IL_000a: ldc.i4.0 + IL_000b: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode(class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldc.i4.0 + IL_0001: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() + IL_0006: call instance int32 assembly/S::GetHashCode(class [runtime]System.Collections.IEqualityComparer) + IL_000b: ret + } + + .method public hidebysig instance bool Equals(valuetype assembly/S obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 3 + .locals init (valuetype assembly/S& V_0) + IL_0000: ldarga.s obj + IL_0002: stloc.0 + IL_0003: ldc.i4.1 + IL_0004: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (object V_0, + valuetype assembly/S V_1) + IL_0000: ldarg.1 + IL_0001: stloc.0 + IL_0002: ldloc.0 + IL_0003: isinst assembly/S + IL_0008: ldnull + IL_0009: cgt.un + IL_000b: brfalse.s IL_001d + + IL_000d: ldarg.1 + IL_000e: unbox.any assembly/S + IL_0013: stloc.1 + IL_0014: ldarg.0 + IL_0015: ldloc.1 + IL_0016: ldarg.2 + IL_0017: call instance bool assembly/S::Equals(valuetype assembly/S, + class [runtime]System.Collections.IEqualityComparer) + IL_001c: ret + + IL_001d: ldc.i4.0 + IL_001e: ret + } + + .method public hidebysig instance int32 Add(int32 x, int32 y) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: ldarg.2 + IL_0002: add + IL_0003: ret + } + + .method public hidebysig virtual final instance bool Equals(valuetype assembly/S obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 3 + .locals init (valuetype assembly/S& V_0) + IL_0000: ldarga.s obj + IL_0002: stloc.0 + IL_0003: ldc.i4.1 + IL_0004: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (object V_0, + valuetype assembly/S V_1) + IL_0000: ldarg.1 + IL_0001: stloc.0 + IL_0002: ldloc.0 + IL_0003: isinst assembly/S + IL_0008: ldnull + IL_0009: cgt.un + IL_000b: brfalse.s IL_001c + + IL_000d: ldarg.1 + IL_000e: unbox.any assembly/S + IL_0013: stloc.1 + IL_0014: ldarg.0 + IL_0015: ldloc.1 + IL_0016: call instance bool assembly/S::Equals(valuetype assembly/S) + IL_001b: ret + + IL_001c: ldc.i4.0 + IL_001d: ret + } + + } + + .class auto autochar serializable sealed nested assembly beforefieldinit specialname structInstanceEta@16 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public valuetype assembly/S s + .method public specialname rtspecialname instance void .ctor(valuetype assembly/S s) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld valuetype assembly/S assembly/structInstanceEta@16::s + IL_0007: ldarg.0 + IL_0008: call instance void [runtime]System.Object::.ctor() + IL_000d: ret + } + + .method assembly hidebysig instance int32 Invoke(int32 a, int32 b) cil managed + { + + .maxstack 7 + .locals init (valuetype assembly/S V_0) + IL_0000: ldarg.0 + IL_0001: ldfld valuetype assembly/S assembly/structInstanceEta@16::s + IL_0006: stloc.0 + IL_0007: ldloca.s V_0 + IL_0009: ldarg.1 + IL_000a: ldarg.2 + IL_000b: call instance int32 assembly/S::Add(int32, + int32) + IL_0010: ret + } + + } + + .method public static class [runtime]System.Func`3 structInstanceNonEta(valuetype assembly/S s) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: box assembly/S + IL_0006: ldftn instance int32 assembly/S::Add(int32, + int32) + IL_000c: newobj instance void class [runtime]System.Func`3::.ctor(object, + native int) + IL_0011: ret + } + + .method public static class [runtime]System.Func`3 structInstanceEta(valuetype assembly/S s) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: newobj instance void assembly/structInstanceEta@16::.ctor(valuetype assembly/S) + IL_0006: ldftn instance int32 assembly/structInstanceEta@16::Invoke(int32, + int32) + IL_000c: newobj instance void class [runtime]System.Func`3::.ctor(object, + native int) + IL_0011: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateStructTarget.fs.OptimizeOff.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateStructTarget.fs.OptimizeOff.il.bsl new file mode 100644 index 00000000000..474c9e2b6ad --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateStructTarget.fs.OptimizeOff.il.bsl @@ -0,0 +1,316 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class sequential ansi serializable sealed nested public S + extends [runtime]System.ValueType + implements class [runtime]System.IEquatable`1, + [runtime]System.Collections.IStructuralEquatable, + class [runtime]System.IComparable`1, + [runtime]System.IComparable, + [runtime]System.Collections.IStructuralComparable + { + .pack 0 + .size 1 + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.StructAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public hidebysig virtual final instance int32 CompareTo(valuetype assembly/S obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 3 + .locals init (valuetype assembly/S& V_0) + IL_0000: ldarga.s obj + IL_0002: stloc.0 + IL_0003: ldc.i4.0 + IL_0004: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: unbox.any assembly/S + IL_0007: call instance int32 assembly/S::CompareTo(valuetype assembly/S) + IL_000c: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj, class [runtime]System.Collections.IComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 3 + .locals init (valuetype assembly/S V_0, + valuetype assembly/S& V_1) + IL_0000: ldarg.1 + IL_0001: unbox.any assembly/S + IL_0006: stloc.0 + IL_0007: ldloca.s V_0 + IL_0009: stloc.1 + IL_000a: ldc.i4.0 + IL_000b: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode(class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldc.i4.0 + IL_0001: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() + IL_0006: call instance int32 assembly/S::GetHashCode(class [runtime]System.Collections.IEqualityComparer) + IL_000b: ret + } + + .method public hidebysig instance bool Equals(valuetype assembly/S obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 3 + .locals init (valuetype assembly/S& V_0) + IL_0000: ldarga.s obj + IL_0002: stloc.0 + IL_0003: ldc.i4.1 + IL_0004: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (object V_0, + valuetype assembly/S V_1) + IL_0000: ldarg.1 + IL_0001: stloc.0 + IL_0002: ldloc.0 + IL_0003: isinst assembly/S + IL_0008: ldnull + IL_0009: cgt.un + IL_000b: brfalse.s IL_001d + + IL_000d: ldarg.1 + IL_000e: unbox.any assembly/S + IL_0013: stloc.1 + IL_0014: ldarg.0 + IL_0015: ldloc.1 + IL_0016: ldarg.2 + IL_0017: call instance bool assembly/S::Equals(valuetype assembly/S, + class [runtime]System.Collections.IEqualityComparer) + IL_001c: ret + + IL_001d: ldc.i4.0 + IL_001e: ret + } + + .method public hidebysig instance int32 Add(int32 x, int32 y) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: ldarg.2 + IL_0002: add + IL_0003: ret + } + + .method public hidebysig virtual final instance bool Equals(valuetype assembly/S obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 3 + .locals init (valuetype assembly/S& V_0) + IL_0000: ldarga.s obj + IL_0002: stloc.0 + IL_0003: ldc.i4.1 + IL_0004: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (object V_0, + valuetype assembly/S V_1) + IL_0000: ldarg.1 + IL_0001: stloc.0 + IL_0002: ldloc.0 + IL_0003: isinst assembly/S + IL_0008: ldnull + IL_0009: cgt.un + IL_000b: brfalse.s IL_001c + + IL_000d: ldarg.1 + IL_000e: unbox.any assembly/S + IL_0013: stloc.1 + IL_0014: ldarg.0 + IL_0015: ldloc.1 + IL_0016: call instance bool assembly/S::Equals(valuetype assembly/S) + IL_001b: ret + + IL_001c: ldc.i4.0 + IL_001d: ret + } + + } + + .class auto autochar serializable sealed nested assembly beforefieldinit specialname structInstanceNonEta@13 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public valuetype assembly/S s + .method public specialname rtspecialname instance void .ctor(valuetype assembly/S s) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld valuetype assembly/S assembly/structInstanceNonEta@13::s + IL_0007: ldarg.0 + IL_0008: call instance void [runtime]System.Object::.ctor() + IL_000d: ret + } + + .method assembly hidebysig instance int32 Invoke(int32 delegateArg0, int32 delegateArg1) cil managed + { + + .maxstack 7 + .locals init (valuetype assembly/S V_0) + IL_0000: ldarg.0 + IL_0001: ldfld valuetype assembly/S assembly/structInstanceNonEta@13::s + IL_0006: stloc.0 + IL_0007: ldloca.s V_0 + IL_0009: ldarg.1 + IL_000a: ldarg.2 + IL_000b: call instance int32 assembly/S::Add(int32, + int32) + IL_0010: ret + } + + } + + .class auto autochar serializable sealed nested assembly beforefieldinit specialname structInstanceEta@16 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public valuetype assembly/S s + .method public specialname rtspecialname instance void .ctor(valuetype assembly/S s) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld valuetype assembly/S assembly/structInstanceEta@16::s + IL_0007: ldarg.0 + IL_0008: call instance void [runtime]System.Object::.ctor() + IL_000d: ret + } + + .method assembly hidebysig instance int32 Invoke(int32 a, int32 b) cil managed + { + + .maxstack 7 + .locals init (valuetype assembly/S V_0) + IL_0000: ldarg.0 + IL_0001: ldfld valuetype assembly/S assembly/structInstanceEta@16::s + IL_0006: stloc.0 + IL_0007: ldloca.s V_0 + IL_0009: ldarg.1 + IL_000a: ldarg.2 + IL_000b: call instance int32 assembly/S::Add(int32, + int32) + IL_0010: ret + } + + } + + .method public static class [runtime]System.Func`3 structInstanceNonEta(valuetype assembly/S s) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: newobj instance void assembly/structInstanceNonEta@13::.ctor(valuetype assembly/S) + IL_0006: ldftn instance int32 assembly/structInstanceNonEta@13::Invoke(int32, + int32) + IL_000c: newobj instance void class [runtime]System.Func`3::.ctor(object, + native int) + IL_0011: ret + } + + .method public static class [runtime]System.Func`3 structInstanceEta(valuetype assembly/S s) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: newobj instance void assembly/structInstanceEta@16::.ctor(valuetype assembly/S) + IL_0006: ldftn instance int32 assembly/structInstanceEta@16::Invoke(int32, + int32) + IL_000c: newobj instance void class [runtime]System.Func`3::.ctor(object, + native int) + IL_0011: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateStructTarget.fs.OptimizeOn.Preview.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateStructTarget.fs.OptimizeOn.Preview.il.bsl new file mode 100644 index 00000000000..72cbb30bc84 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateStructTarget.fs.OptimizeOn.Preview.il.bsl @@ -0,0 +1,219 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class sequential ansi serializable sealed nested public S + extends [runtime]System.ValueType + implements class [runtime]System.IEquatable`1, + [runtime]System.Collections.IStructuralEquatable, + class [runtime]System.IComparable`1, + [runtime]System.IComparable, + [runtime]System.Collections.IStructuralComparable + { + .pack 0 + .size 1 + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.StructAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public hidebysig virtual final instance int32 CompareTo(valuetype assembly/S obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldc.i4.0 + IL_0001: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 3 + .locals init (valuetype assembly/S V_0) + IL_0000: ldarg.1 + IL_0001: unbox.any assembly/S + IL_0006: stloc.0 + IL_0007: ldc.i4.0 + IL_0008: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj, class [runtime]System.Collections.IComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 3 + .locals init (valuetype assembly/S V_0) + IL_0000: ldarg.1 + IL_0001: unbox.any assembly/S + IL_0006: stloc.0 + IL_0007: ldc.i4.0 + IL_0008: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode(class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldc.i4.0 + IL_0001: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() + IL_0006: call instance int32 assembly/S::GetHashCode(class [runtime]System.Collections.IEqualityComparer) + IL_000b: ret + } + + .method public hidebysig instance bool Equals(valuetype assembly/S obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldc.i4.1 + IL_0001: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 3 + .locals init (valuetype assembly/S V_0) + IL_0000: ldarg.1 + IL_0001: isinst assembly/S + IL_0006: brfalse.s IL_0011 + + IL_0008: ldarg.1 + IL_0009: unbox.any assembly/S + IL_000e: stloc.0 + IL_000f: ldc.i4.1 + IL_0010: ret + + IL_0011: ldc.i4.0 + IL_0012: ret + } + + .method public hidebysig instance int32 Add(int32 x, int32 y) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: ldarg.2 + IL_0002: add + IL_0003: ret + } + + .method public hidebysig virtual final instance bool Equals(valuetype assembly/S obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldc.i4.1 + IL_0001: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 3 + .locals init (valuetype assembly/S V_0) + IL_0000: ldarg.1 + IL_0001: isinst assembly/S + IL_0006: brfalse.s IL_0011 + + IL_0008: ldarg.1 + IL_0009: unbox.any assembly/S + IL_000e: stloc.0 + IL_000f: ldc.i4.1 + IL_0010: ret + + IL_0011: ldc.i4.0 + IL_0012: ret + } + + } + + .method public static class [runtime]System.Func`3 structInstanceNonEta(valuetype assembly/S s) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: box assembly/S + IL_0006: ldftn instance int32 assembly/S::Add(int32, + int32) + IL_000c: newobj instance void class [runtime]System.Func`3::.ctor(object, + native int) + IL_0011: ret + } + + .method public static class [runtime]System.Func`3 structInstanceEta(valuetype assembly/S s) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: box assembly/S + IL_0006: ldftn instance int32 assembly/S::Add(int32, + int32) + IL_000c: newobj instance void class [runtime]System.Func`3::.ctor(object, + native int) + IL_0011: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateStructTarget.fs.OptimizeOn.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateStructTarget.fs.OptimizeOn.il.bsl new file mode 100644 index 00000000000..c00b5018301 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateStructTarget.fs.OptimizeOn.il.bsl @@ -0,0 +1,251 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class sequential ansi serializable sealed nested public S + extends [runtime]System.ValueType + implements class [runtime]System.IEquatable`1, + [runtime]System.Collections.IStructuralEquatable, + class [runtime]System.IComparable`1, + [runtime]System.IComparable, + [runtime]System.Collections.IStructuralComparable + { + .pack 0 + .size 1 + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.StructAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public hidebysig virtual final instance int32 CompareTo(valuetype assembly/S obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldc.i4.0 + IL_0001: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 3 + .locals init (valuetype assembly/S V_0) + IL_0000: ldarg.1 + IL_0001: unbox.any assembly/S + IL_0006: stloc.0 + IL_0007: ldc.i4.0 + IL_0008: ret + } + + .method public hidebysig virtual final instance int32 CompareTo(object obj, class [runtime]System.Collections.IComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 3 + .locals init (valuetype assembly/S V_0) + IL_0000: ldarg.1 + IL_0001: unbox.any assembly/S + IL_0006: stloc.0 + IL_0007: ldc.i4.0 + IL_0008: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode(class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldc.i4.0 + IL_0001: ret + } + + .method public hidebysig virtual final instance int32 GetHashCode() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call class [runtime]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() + IL_0006: call instance int32 assembly/S::GetHashCode(class [runtime]System.Collections.IEqualityComparer) + IL_000b: ret + } + + .method public hidebysig instance bool Equals(valuetype assembly/S obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldc.i4.1 + IL_0001: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj, class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 3 + .locals init (valuetype assembly/S V_0) + IL_0000: ldarg.1 + IL_0001: isinst assembly/S + IL_0006: brfalse.s IL_0011 + + IL_0008: ldarg.1 + IL_0009: unbox.any assembly/S + IL_000e: stloc.0 + IL_000f: ldc.i4.1 + IL_0010: ret + + IL_0011: ldc.i4.0 + IL_0012: ret + } + + .method public hidebysig instance int32 Add(int32 x, int32 y) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: ldarg.2 + IL_0002: add + IL_0003: ret + } + + .method public hidebysig virtual final instance bool Equals(valuetype assembly/S obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldc.i4.1 + IL_0001: ret + } + + .method public hidebysig virtual final instance bool Equals(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 3 + .locals init (valuetype assembly/S V_0) + IL_0000: ldarg.1 + IL_0001: isinst assembly/S + IL_0006: brfalse.s IL_0011 + + IL_0008: ldarg.1 + IL_0009: unbox.any assembly/S + IL_000e: stloc.0 + IL_000f: ldc.i4.1 + IL_0010: ret + + IL_0011: ldc.i4.0 + IL_0012: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname structInstanceNonEta@13 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static int32 Invoke(int32 delegateArg0, + int32 delegateArg1) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: add + IL_0003: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname structInstanceEta@16 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static int32 Invoke(int32 a, + int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: add + IL_0003: ret + } + + } + + .method public static class [runtime]System.Func`3 structInstanceNonEta(valuetype assembly/S s) cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn int32 assembly/structInstanceNonEta@13::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Func`3::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Func`3 structInstanceEta(valuetype assembly/S s) cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn int32 assembly/structInstanceEta@16::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Func`3::.ctor(object, + native int) + IL_000c: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateUnitArg.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateUnitArg.fs new file mode 100644 index 00000000000..27c5b27b332 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateUnitArg.fs @@ -0,0 +1,20 @@ +module DelegateUnitArg + +open System + +let handler () : unit = () + +type C() = + member _.M () : unit = () + +// 46. non-eta unit-argument delegate +let caseUnitNonEta () = Action(handler) + +// 47. eta unit-argument delegate +let caseUnitEta () = Action(fun () -> handler ()) + +// 48. non-eta unit-argument delegate, instance method (receiver kept, unit stripped) +let caseUnitInstanceNonEta (c: C) = Action(c.M) + +// 49. eta unit-argument delegate, instance method +let caseUnitInstanceEta (c: C) = Action(fun () -> c.M ()) diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateUnitArg.fs.OptimizeOff.Preview.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateUnitArg.fs.OptimizeOff.Preview.il.bsl new file mode 100644 index 00000000000..a6ffdf256a7 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateUnitArg.fs.OptimizeOff.Preview.il.bsl @@ -0,0 +1,176 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable nested public C + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor() cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: callvirt instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ret + } + + .method public hidebysig instance void M() cil managed + { + + .maxstack 8 + IL_0000: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname caseUnitEta@14 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke() cil managed + { + + .maxstack 8 + IL_0000: call void assembly::'handler'() + IL_0005: nop + IL_0006: ret + } + + } + + .class auto autochar serializable sealed nested assembly beforefieldinit specialname caseUnitInstanceEta@20 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public class assembly/C c + .method public specialname rtspecialname instance void .ctor(class assembly/C c) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld class assembly/C assembly/caseUnitInstanceEta@20::c + IL_0007: ldarg.0 + IL_0008: call instance void [runtime]System.Object::.ctor() + IL_000d: ret + } + + .method assembly hidebysig instance void Invoke() cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld class assembly/C assembly/caseUnitInstanceEta@20::c + IL_0006: callvirt instance void assembly/C::M() + IL_000b: nop + IL_000c: ret + } + + } + + .method public static void 'handler'() cil managed + { + + .maxstack 8 + IL_0000: ret + } + + .method public static class [runtime]System.Action caseUnitNonEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly::'handler'() + IL_0007: newobj instance void [runtime]System.Action::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action caseUnitEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/caseUnitEta@14::Invoke() + IL_0007: newobj instance void [runtime]System.Action::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action caseUnitInstanceNonEta(class assembly/C c) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldftn instance void assembly/C::M() + IL_0007: newobj instance void [runtime]System.Action::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action caseUnitInstanceEta(class assembly/C c) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: newobj instance void assembly/caseUnitInstanceEta@20::.ctor(class assembly/C) + IL_0006: ldftn instance void assembly/caseUnitInstanceEta@20::Invoke() + IL_000c: newobj instance void [runtime]System.Action::.ctor(object, + native int) + IL_0011: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateUnitArg.fs.OptimizeOff.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateUnitArg.fs.OptimizeOff.il.bsl new file mode 100644 index 00000000000..da567add265 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateUnitArg.fs.OptimizeOff.il.bsl @@ -0,0 +1,225 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable nested public C + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor() cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: callvirt instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ret + } + + .method public hidebysig instance void M() cil managed + { + + .maxstack 8 + IL_0000: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname caseUnitNonEta@11 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke() cil managed + { + + .maxstack 8 + IL_0000: call void assembly::'handler'() + IL_0005: nop + IL_0006: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname caseUnitEta@14 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke() cil managed + { + + .maxstack 8 + IL_0000: call void assembly::'handler'() + IL_0005: nop + IL_0006: ret + } + + } + + .class auto autochar serializable sealed nested assembly beforefieldinit specialname caseUnitInstanceNonEta@17 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public class assembly/C c + .method public specialname rtspecialname instance void .ctor(class assembly/C c) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld class assembly/C assembly/caseUnitInstanceNonEta@17::c + IL_0007: ldarg.0 + IL_0008: call instance void [runtime]System.Object::.ctor() + IL_000d: ret + } + + .method assembly hidebysig instance void Invoke() cil managed + { + + .maxstack 5 + .locals init (class assembly/C V_0) + IL_0000: ldarg.0 + IL_0001: ldfld class assembly/C assembly/caseUnitInstanceNonEta@17::c + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: callvirt instance void assembly/C::M() + IL_000d: nop + IL_000e: ret + } + + } + + .class auto autochar serializable sealed nested assembly beforefieldinit specialname caseUnitInstanceEta@20 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public class assembly/C c + .method public specialname rtspecialname instance void .ctor(class assembly/C c) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld class assembly/C assembly/caseUnitInstanceEta@20::c + IL_0007: ldarg.0 + IL_0008: call instance void [runtime]System.Object::.ctor() + IL_000d: ret + } + + .method assembly hidebysig instance void Invoke() cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld class assembly/C assembly/caseUnitInstanceEta@20::c + IL_0006: callvirt instance void assembly/C::M() + IL_000b: nop + IL_000c: ret + } + + } + + .method public static void 'handler'() cil managed + { + + .maxstack 8 + IL_0000: ret + } + + .method public static class [runtime]System.Action caseUnitNonEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/caseUnitNonEta@11::Invoke() + IL_0007: newobj instance void [runtime]System.Action::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action caseUnitEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/caseUnitEta@14::Invoke() + IL_0007: newobj instance void [runtime]System.Action::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action caseUnitInstanceNonEta(class assembly/C c) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: newobj instance void assembly/caseUnitInstanceNonEta@17::.ctor(class assembly/C) + IL_0006: ldftn instance void assembly/caseUnitInstanceNonEta@17::Invoke() + IL_000c: newobj instance void [runtime]System.Action::.ctor(object, + native int) + IL_0011: ret + } + + .method public static class [runtime]System.Action caseUnitInstanceEta(class assembly/C c) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: newobj instance void assembly/caseUnitInstanceEta@20::.ctor(class assembly/C) + IL_0006: ldftn instance void assembly/caseUnitInstanceEta@20::Invoke() + IL_000c: newobj instance void [runtime]System.Action::.ctor(object, + native int) + IL_0011: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateUnitArg.fs.OptimizeOn.Preview.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateUnitArg.fs.OptimizeOn.Preview.il.bsl new file mode 100644 index 00000000000..2c12314501a --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateUnitArg.fs.OptimizeOn.Preview.il.bsl @@ -0,0 +1,130 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable nested public C + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor() cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: callvirt instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ret + } + + .method public hidebysig instance void M() cil managed + { + + .maxstack 8 + IL_0000: ret + } + + } + + .method public static void 'handler'() cil managed + { + + .maxstack 8 + IL_0000: ret + } + + .method public static class [runtime]System.Action caseUnitNonEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly::'handler'() + IL_0007: newobj instance void [runtime]System.Action::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action caseUnitEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly::'handler'() + IL_0007: newobj instance void [runtime]System.Action::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action caseUnitInstanceNonEta(class assembly/C c) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldftn instance void assembly/C::M() + IL_0007: newobj instance void [runtime]System.Action::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action caseUnitInstanceEta(class assembly/C c) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldftn instance void assembly/C::M() + IL_0007: newobj instance void [runtime]System.Action::.ctor(object, + native int) + IL_000c: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateUnitArg.fs.OptimizeOn.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateUnitArg.fs.OptimizeOn.il.bsl new file mode 100644 index 00000000000..9746aa37757 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateUnitArg.fs.OptimizeOn.il.bsl @@ -0,0 +1,182 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable nested public C + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public specialname rtspecialname instance void .ctor() cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: callvirt instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ret + } + + .method public hidebysig instance void M() cil managed + { + + .maxstack 8 + IL_0000: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname caseUnitNonEta@11 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke() cil managed + { + + .maxstack 8 + IL_0000: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname caseUnitEta@14 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke() cil managed + { + + .maxstack 8 + IL_0000: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname caseUnitInstanceNonEta@17 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke() cil managed + { + + .maxstack 8 + IL_0000: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname caseUnitInstanceEta@20 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke() cil managed + { + + .maxstack 8 + IL_0000: ret + } + + } + + .method public static void 'handler'() cil managed + { + + .maxstack 8 + IL_0000: ret + } + + .method public static class [runtime]System.Action caseUnitNonEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/caseUnitNonEta@11::Invoke() + IL_0007: newobj instance void [runtime]System.Action::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action caseUnitEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/caseUnitEta@14::Invoke() + IL_0007: newobj instance void [runtime]System.Action::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action caseUnitInstanceNonEta(class assembly/C c) cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/caseUnitInstanceNonEta@17::Invoke() + IL_0007: newobj instance void [runtime]System.Action::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action caseUnitInstanceEta(class assembly/C c) cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/caseUnitInstanceEta@20::Invoke() + IL_0007: newobj instance void [runtime]System.Action::.ctor(object, + native int) + IL_000c: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateUnitReturn.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateUnitReturn.fs new file mode 100644 index 00000000000..ba6da87996a --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateUnitReturn.fs @@ -0,0 +1,25 @@ +module DelegateUnitReturn + +open System + +// Target returns unit, compiled to void; delegate (Action) returns void. +let returnsUnit (x: int) (y: int) : unit = () + +// 26. non-eta unit-returning member (compiled to void) +let voidNonEta () = Action(returnsUnit) + +// 10. eta unit-returning member +let voidEta () = Action(fun a b -> returnsUnit a b) + +type C = + // Generic method returning its own type variable; instantiated to unit below. The compiled method + // returns the type variable (System.Unit once instantiated), not void - a distinct case from the + // void-returning member above. + static member Echo<'T>(x: 'T) : 'T = x + +// Generic return type variable instantiated to unit; the delegate likewise returns unit. +// 27. non-eta generic return tyvar instantiated to unit (compiled return is Unit, not void) +let unitGenericReturnNonEta () = Func(C.Echo) + +// 11. eta generic unit-returning method +let unitGenericReturnEta () = Func(fun (x: unit) -> C.Echo x) diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateUnitReturn.fs.OptimizeOff.Preview.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateUnitReturn.fs.OptimizeOff.Preview.il.bsl new file mode 100644 index 00000000000..2f1068b4215 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateUnitReturn.fs.OptimizeOff.Preview.il.bsl @@ -0,0 +1,158 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname voidEta@12 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 a, + int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: call void assembly::returnsUnit(int32, + int32) + IL_0007: nop + IL_0008: ret + } + + } + + .class auto ansi serializable nested public C + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public static !!T Echo(!!T x) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname unitGenericReturnEta@25 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static class [FSharp.Core]Microsoft.FSharp.Core.Unit Invoke(class [FSharp.Core]Microsoft.FSharp.Core.Unit x) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call !!0 assembly/C::Echo(!!0) + IL_0006: ret + } + + } + + .method public static void returnsUnit(int32 x, + int32 y) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 8 + IL_0000: ret + } + + .method public static class [runtime]System.Action`2 voidNonEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly::returnsUnit(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 voidEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/voidEta@12::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Func`2 unitGenericReturnNonEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn !!0 assembly/C::Echo(!!0) + IL_0007: newobj instance void class [runtime]System.Func`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Func`2 unitGenericReturnEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn class [FSharp.Core]Microsoft.FSharp.Core.Unit assembly/unitGenericReturnEta@25::Invoke(class [FSharp.Core]Microsoft.FSharp.Core.Unit) + IL_0007: newobj instance void class [runtime]System.Func`2::.ctor(object, + native int) + IL_000c: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateUnitReturn.fs.OptimizeOff.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateUnitReturn.fs.OptimizeOff.il.bsl new file mode 100644 index 00000000000..69a6b147055 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateUnitReturn.fs.OptimizeOff.il.bsl @@ -0,0 +1,192 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname voidNonEta@9 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 x, + int32 y) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: call void assembly::returnsUnit(int32, + int32) + IL_0007: nop + IL_0008: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname voidEta@12 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 a, + int32 b) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: call void assembly::returnsUnit(int32, + int32) + IL_0007: nop + IL_0008: ret + } + + } + + .class auto ansi serializable nested public C + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public static !!T Echo(!!T x) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname unitGenericReturnNonEta@22 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static class [FSharp.Core]Microsoft.FSharp.Core.Unit Invoke(class [FSharp.Core]Microsoft.FSharp.Core.Unit x) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call !!0 assembly/C::Echo(!!0) + IL_0006: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname unitGenericReturnEta@25 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static class [FSharp.Core]Microsoft.FSharp.Core.Unit Invoke(class [FSharp.Core]Microsoft.FSharp.Core.Unit x) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call !!0 assembly/C::Echo(!!0) + IL_0006: ret + } + + } + + .method public static void returnsUnit(int32 x, + int32 y) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 8 + IL_0000: ret + } + + .method public static class [runtime]System.Action`2 voidNonEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/voidNonEta@9::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 voidEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/voidEta@12::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Func`2 unitGenericReturnNonEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn class [FSharp.Core]Microsoft.FSharp.Core.Unit assembly/unitGenericReturnNonEta@22::Invoke(class [FSharp.Core]Microsoft.FSharp.Core.Unit) + IL_0007: newobj instance void class [runtime]System.Func`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Func`2 unitGenericReturnEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn class [FSharp.Core]Microsoft.FSharp.Core.Unit assembly/unitGenericReturnEta@25::Invoke(class [FSharp.Core]Microsoft.FSharp.Core.Unit) + IL_0007: newobj instance void class [runtime]System.Func`2::.ctor(object, + native int) + IL_000c: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateUnitReturn.fs.OptimizeOn.Preview.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateUnitReturn.fs.OptimizeOn.Preview.il.bsl new file mode 100644 index 00000000000..a9708f88712 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateUnitReturn.fs.OptimizeOn.Preview.il.bsl @@ -0,0 +1,124 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable nested public C + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public static !!T Echo(!!T x) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ret + } + + } + + .method public static void returnsUnit(int32 x, + int32 y) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 8 + IL_0000: ret + } + + .method public static class [runtime]System.Action`2 voidNonEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly::returnsUnit(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 voidEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly::returnsUnit(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Func`2 unitGenericReturnNonEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn !!0 assembly/C::Echo(!!0) + IL_0007: newobj instance void class [runtime]System.Func`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Func`2 unitGenericReturnEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn !!0 assembly/C::Echo(!!0) + IL_0007: newobj instance void class [runtime]System.Func`2::.ctor(object, + native int) + IL_000c: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateUnitReturn.fs.OptimizeOn.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateUnitReturn.fs.OptimizeOn.il.bsl new file mode 100644 index 00000000000..f57b5694074 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateUnitReturn.fs.OptimizeOn.il.bsl @@ -0,0 +1,180 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname voidNonEta@9 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 x, + int32 y) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname voidEta@12 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static void Invoke(int32 a, + int32 b) cil managed + { + + .maxstack 8 + IL_0000: ret + } + + } + + .class auto ansi serializable nested public C + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public static !!T Echo(!!T x) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname unitGenericReturnNonEta@22 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static class [FSharp.Core]Microsoft.FSharp.Core.Unit Invoke(class [FSharp.Core]Microsoft.FSharp.Core.Unit x) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ret + } + + } + + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname unitGenericReturnEta@25 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static class [FSharp.Core]Microsoft.FSharp.Core.Unit Invoke(class [FSharp.Core]Microsoft.FSharp.Core.Unit x) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ret + } + + } + + .method public static void returnsUnit(int32 x, + int32 y) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 8 + IL_0000: ret + } + + .method public static class [runtime]System.Action`2 voidNonEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/voidNonEta@9::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Action`2 voidEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn void assembly/voidEta@12::Invoke(int32, + int32) + IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Func`2 unitGenericReturnNonEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn class [FSharp.Core]Microsoft.FSharp.Core.Unit assembly/unitGenericReturnNonEta@22::Invoke(class [FSharp.Core]Microsoft.FSharp.Core.Unit) + IL_0007: newobj instance void class [runtime]System.Func`2::.ctor(object, + native int) + IL_000c: ret + } + + .method public static class [runtime]System.Func`2 unitGenericReturnEta() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ldftn class [FSharp.Core]Microsoft.FSharp.Core.Unit assembly/unitGenericReturnEta@25::Invoke(class [FSharp.Core]Microsoft.FSharp.Core.Unit) + IL_0007: newobj instance void class [runtime]System.Func`2::.ctor(object, + native int) + IL_000c: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + + .maxstack 8 + IL_0000: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DirectDelegates.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DirectDelegates.fs new file mode 100644 index 00000000000..f247d1c2210 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DirectDelegates.fs @@ -0,0 +1,1094 @@ +module EmittedIL.RealInternalSignature.DirectDelegates + +open System.IO +open Xunit +open FSharp.Test +open FSharp.Test.Compiler +open FSharp.Test.ProjectGeneration + +let private coreOptions compilation = + compilation + |> withOptions [ "--test:EmitFeeFeeAs100001" ] + |> asExe + |> withEmbeddedPdb + |> withEmbedAllSource + |> ignoreWarnings + +let verifyCompilation compilation = + compilation + |> coreOptions + |> compile + |> shouldSucceed + |> verifyPEFileWithSystemDlls + |> verifyILBaseline + +// Redirect the IL baseline to a distinct *.Preview.il.bsl path so the preview variant can reuse the +// very same input .fs file (no input duplication / drift) without clobbering the default baseline. +let private withPreviewBaseline (cUnit: CompilationUnit) : CompilationUnit = + match cUnit with + | FS src -> + let baseline = + src.Baseline + |> Option.map (fun bsl -> + let path = bsl.ILBaseline.BslSource.Replace(".il.bsl", ".Preview.il.bsl") + let content = if File.Exists path then Some(File.ReadAllText path) else None + { bsl with ILBaseline = { bsl.ILBaseline with BslSource = path; Content = content } }) + FS { src with Baseline = baseline } + | other -> other + +let verifyPreviewCompilation compilation = + compilation + |> coreOptions + |> withLangVersionPreview + |> withPreviewBaseline + |> compile + |> shouldSucceed + |> verifyPEFileWithSystemDlls + |> verifyILBaseline + +[] +let ``DelegateKnownFunction_fs`` compilation = + compilation |> getCompilation |> verifyCompilation + +[] +let ``DelegateKnownFunction_fs preview`` compilation = + compilation |> getCompilation |> verifyPreviewCompilation + +[] +let ``DelegateStaticMethod_fs`` compilation = + compilation |> getCompilation |> verifyCompilation + +[] +let ``DelegateStaticMethod_fs preview`` compilation = + compilation |> getCompilation |> verifyPreviewCompilation + +[] +let ``DelegateGenericStaticMethod_fs`` compilation = + compilation |> getCompilation |> verifyCompilation + +[] +let ``DelegateGenericStaticMethod_fs preview`` compilation = + compilation |> getCompilation |> verifyPreviewCompilation + +[] +let ``DelegateInstanceMethod_fs`` compilation = + compilation |> getCompilation |> verifyCompilation + +[] +let ``DelegateInstanceMethod_fs preview`` compilation = + compilation |> getCompilation |> verifyPreviewCompilation + +[] +let ``DelegateGenericInstanceMethod_fs`` compilation = + compilation |> getCompilation |> verifyCompilation + +[] +let ``DelegateGenericInstanceMethod_fs preview`` compilation = + compilation |> getCompilation |> verifyPreviewCompilation + +[] +let ``DelegateUnitArg_fs`` compilation = + compilation |> getCompilation |> verifyCompilation + +[] +let ``DelegateUnitArg_fs preview`` compilation = + compilation |> getCompilation |> verifyPreviewCompilation + +[] +let ``DelegateNegativeCases_fs`` compilation = + compilation |> getCompilation |> verifyCompilation + +[] +let ``DelegateNegativeCases_fs preview`` compilation = + compilation |> getCompilation |> verifyPreviewCompilation + +[] +let ``DelegatePartialApplication_fs`` compilation = + compilation |> getCompilation |> verifyCompilation + +[] +let ``DelegatePartialApplication_fs preview`` compilation = + compilation |> getCompilation |> verifyPreviewCompilation + +[] +let ``DelegateUnitReturn_fs`` compilation = + compilation |> getCompilation |> verifyCompilation + +[] +let ``DelegateUnitReturn_fs preview`` compilation = + compilation |> getCompilation |> verifyPreviewCompilation + +[] +let ``DelegateStructTarget_fs`` compilation = + compilation |> getCompilation |> verifyCompilation + +[] +let ``DelegateStructTarget_fs preview`` compilation = + compilation |> getCompilation |> verifyPreviewCompilation + +[] +let ``DelegateExtensionMethod_fs`` compilation = + compilation |> getCompilation |> verifyCompilation + +[] +let ``DelegateExtensionMethod_fs preview`` compilation = + compilation |> getCompilation |> verifyPreviewCompilation + +[] +let ``DelegateILMethod_fs`` compilation = + compilation |> getCompilation |> verifyCompilation + +[] +let ``DelegateILMethod_fs preview`` compilation = + compilation |> getCompilation |> verifyPreviewCompilation + +[] +let ``DelegateCustomType_fs`` compilation = + compilation |> getCompilation |> verifyCompilation + +[] +let ``DelegateCustomType_fs preview`` compilation = + compilation |> getCompilation |> verifyPreviewCompilation + +[] +let ``Direct delegates target the real method and dispatch correctly (preview)`` () = + FSharp """ +module DirectDelegateExecution + +open System + +let add (x: int) (y: int) : int = x + y + +type G<'U> = + static member Pick<'T>(x: 'T) (y: 'T) : 'T = x + +[] +type Base() = + abstract M: int -> int + +type Derived() = + inherit Base() + override _.M x = x + 100 + +[] +let main _ = + // Non-eta known function: the delegate points directly at 'add'. + let d = Func(add) + if d.Invoke(2, 3) <> 5 then failwith "add: wrong result" + if d.Method.Name <> "add" then failwithf "add: expected Method.Name 'add' but got '%s'" d.Method.Name + + // Non-eta generic method on a generic type: the delegate points directly at the fully instantiated method. + let gd = Func(G.Pick) + if gd.Invoke(7, 9) <> 7 then failwithf "generic: expected 7 but got %d" (gd.Invoke(7, 9)) + if gd.Method.Name <> "Pick" then failwithf "generic: expected Method.Name 'Pick' but got '%s'" gd.Method.Name + + // Non-eta virtual instance method: dup; ldvirtftn must preserve override dispatch. + let b: Base = Derived() + let vd = Func(b.M) + if vd.Invoke 1 <> 101 then failwithf "virtual: expected 101 but got %d" (vd.Invoke 1) + if vd.Method.Name <> "M" then failwithf "virtual: expected Method.Name 'M' but got '%s'" vd.Method.Name + if not (obj.ReferenceEquals(vd.Target, b)) then failwith "virtual: Target is not the receiver" + + 0 + """ + |> withLangVersionPreview + |> compileExeAndRun + |> shouldSucceed + +[] +let ``Without the feature the delegate goes through a closure (default langversion)`` () = + FSharp """ +module ClosureDelegateExecution + +open System + +let add (x: int) (y: int) : int = x + y + +[] +let main _ = + let d = Func(add) + if d.Invoke(2, 3) <> 5 then failwith "add: wrong result" + // Without the feature the delegate is built over a generated closure method named 'Invoke'. + if d.Method.Name <> "Invoke" then failwithf "expected closure Method.Name 'Invoke' but got '%s'" d.Method.Name + 0 + """ + |> compileExeAndRun + |> shouldSucceed + +// IL (BCL) method target: compiled as TOp.ILCall. With ILCall recognition the optimized eta-expanded +// delegate points directly at the BCL method, so Method.Name is the real method ('Max'), not a closure +// 'Invoke'. Compiled with --optimize+ so the eta forwarding call survives to codegen. +[] +let ``IL method targets are emitted directly when optimized (preview)`` () = + FSharp """ +module IlMethodDelegate + +open System + +[] +let main _ = + let d = Func(fun a b -> Math.Max(a, b)) + if d.Invoke(3, 7) <> 7 then failwith "il: wrong result" + if d.Method.Name <> "Max" then failwithf "il: expected direct 'Max' but got '%s'" d.Method.Name + 0 + """ + |> withLangVersionPreview + |> withOptions [ "--optimize+" ] + |> compileExeAndRun + |> shouldSucceed + +// A closure built from an explicit eta-lambda re-evaluates the receiver on every Invoke; a direct +// delegate would evaluate it once at construction. When the receiver has an effect (here a counter- +// bumping call) that difference is observable, so the closure must be kept even under optimization. +[] +let ``Side-effecting receiver keeps the closure so it is re-evaluated per invoke (preview)`` () = + FSharp """ +module ReceiverEffectDelegate + +open System + +let mutable calls = 0 + +type Box(tag: int) = + member _.Read (_: int) : int = tag + +let getBox () = + calls <- calls + 1 + Box(calls) + +[] +let main _ = + // The receiver 'getBox()' has an effect, so it must run on each invocation, not once at construction. + let d = Func(fun a -> (getBox()).Read a) + let r1 = d.Invoke 0 + let r2 = d.Invoke 0 + if calls <> 2 then failwithf "receiver should be re-evaluated per invoke; calls=%d" calls + if r1 = r2 then failwithf "expected distinct boxes per invoke but got %d and %d" r1 r2 + if d.Method.Name <> "Invoke" then failwithf "expected closure 'Invoke' but got '%s'" d.Method.Name + 0 + """ + |> withLangVersionPreview + |> withOptions [ "--optimize+" ] + |> compileExeAndRun + |> shouldSucceed + +// Instance IL method target: a BCL instance method bound directly. The delegate's Target must be the +// receiver and Method.Name the real method. +[] +let ``Instance IL method targets are emitted directly when optimized (preview)`` () = + FSharp """ +module IlInstanceMethodDelegate + +open System +open System.Text + +[] +let main _ = + let sb = StringBuilder() + // StringBuilder.Append(string) is an instance method on a reference type. + let d = Func(fun s -> sb.Append(s)) + d.Invoke "hello" |> ignore + if sb.ToString() <> "hello" then failwith "il-instance: wrong result" + if d.Method.Name <> "Append" then failwithf "il-instance: expected direct 'Append' but got '%s'" d.Method.Name + if not (obj.ReferenceEquals(d.Target, sb)) then failwith "il-instance: Target is not the receiver" + 0 + """ + |> withLangVersionPreview + |> withOptions [ "--optimize+" ] + |> compileExeAndRun + |> shouldSucceed + +// Custom, F#-declared delegate types (not just BCL Func/Action) point directly at the target method. +// Non-eta targets, so direct in both debug and release. Covers a static target (null Target) and an +// instance target (Target = receiver) through a user-defined delegate. +[] +let ``Custom F# delegate targets the real method and dispatch correctly (preview)`` () = + FSharp """ +module CustomDelegateExecution + +open System + +type DTupled = delegate of int * int -> int + +let acc (x: int) (y: int) : int = x + y + +type C() = + member _.M (x: int) (y: int) : int = x * y + +[] +let main _ = + let ds = DTupled(acc) + if ds.Invoke(2, 3) <> 5 then failwith "static: wrong result" + if ds.Method.Name <> "acc" then failwithf "static: expected 'acc' but got '%s'" ds.Method.Name + if not (isNull ds.Target) then failwith "static: Target should be null" + + let c = C() + let di = DTupled(c.M) + if di.Invoke(4, 5) <> 20 then failwith "instance: wrong result" + if di.Method.Name <> "M" then failwithf "instance: expected 'M' but got '%s'" di.Method.Name + if not (obj.ReferenceEquals(di.Target, c)) then failwith "instance: Target is not the receiver" + 0 + """ + |> withLangVersionPreview + |> compileExeAndRun + |> shouldSucceed + +// Cases 31-35: a tupled application carries each tupled group as a single tuple node, exactly the shape the +// code generator de-tuples by the target's arity when it emits the call. The recognizer de-tuples the same +// way, so a tupled target is as direct-able as its curried counterpart and points at the real method. +[] +let ``Tupled application targets the real method (preview)`` () = + FSharp """ +module TupledDirect + +open System + +let accT (x: int, y: int) : int = x + y + +[] +let main _ = + let d = Func(fun a b -> accT (a, b)) + if d.Invoke(2, 3) <> 5 then failwith "wrong result" + if d.Method.Name <> "accT" then failwithf "expected direct 'accT' but got '%s'" d.Method.Name + if not (isNull d.Target) then failwith "Target should be null for a static target" + 0 + """ + |> withLangVersionPreview + |> withOptions [ "--optimize+" ] + |> compileExeAndRun + |> shouldSucceed + +// Cases 37-41: the CLR's closed delegate binds exactly one leading argument as the Target, so a partial +// application that fixes two or more arguments (or also fixes a receiver) has no closed direct form and stays +// a closure. A one-argument partial application could be closed, but only if that argument is a reference type +// (a value-type Target would need boxing - the same gap as a value-type receiver), so fixing a value-type +// argument keeps a closure too. +[] +let ``Partial application stays a closure (preview)`` () = + FSharp """ +module PartialClosure + +open System + +let add3 (x: int) (y: int) (z: int) : int = x + y + z + +[] +let main _ = + // One fixed argument, but it is a value type: a value-type Target would need boxing, so a closure is kept. + let d = Func(add3 1) + if d.Invoke(2, 3) <> 6 then failwith "wrong result" + if d.Method.Name <> "Invoke" then failwithf "expected closure 'Invoke' but got '%s'" d.Method.Name + 0 + """ + |> withLangVersionPreview + |> compileExeAndRun + |> shouldSucceed + +// A one-argument partial application whose fixed argument is a reference type is expressible as a closed +// delegate: the argument is bound as the Target and the delegate points directly at the static method. +[] +let ``Reference-type single-argument partial application is direct (preview)`` () = + FSharp """ +module PartialDirect + +open System + +let prepend (prefix: string) (x: int) (y: int) : string = sprintf "%s%d%d" prefix x y + +[] +let main _ = + let p = "p" + let d = Func(prepend p) + if d.Invoke(2, 3) <> "p23" then failwith "wrong result" + if d.Method.Name <> "prepend" then failwithf "expected direct 'prepend' but got '%s'" d.Method.Name + if not (obj.ReferenceEquals(d.Target, p)) then failwith "Target is not the fixed argument" + 0 + """ + |> withLangVersionPreview + |> withOptions [ "--optimize+" ] + |> compileExeAndRun + |> shouldSucceed + +// Cases 46-49: the forwarded unit argument is stripped, so a unit-argument delegate points directly at the +// target - a static target carries a null Target, an instance target carries the receiver. +[] +let ``Unit-argument delegate targets the real method (preview)`` () = + FSharp """ +module UnitArgDirect + +open System + +let mutable ran = 0 + +let handler () : unit = ran <- ran + 1 + +type C() = + member _.M () : unit = ran <- ran + 10 + +[] +let main _ = + // Static unit-argument target: direct, null Target, real Method.Name. + let ds = Action(handler) + ds.Invoke() + if ds.Method.Name <> "handler" then failwithf "static: expected 'handler' but got '%s'" ds.Method.Name + if not (isNull ds.Target) then failwith "static: Target should be null" + + // Instance unit-argument target: direct, Target is the receiver. + let c = C() + let di = Action(c.M) + di.Invoke() + if di.Method.Name <> "M" then failwithf "instance: expected 'M' but got '%s'" di.Method.Name + if not (obj.ReferenceEquals(di.Target, c)) then failwith "instance: Target is not the receiver" + + if ran <> 11 then failwithf "expected both targets to run (ran=%d)" ran + 0 + """ + |> withLangVersionPreview + |> compileExeAndRun + |> shouldSucceed + +// Cases 50-51: a value-type receiver is boxed (a copy) and stored as the delegate's Target; the runtime binds +// the unboxing stub, so the delegate points at the real struct method and dispatches correctly, with the boxed +// copy carrying the receiver's value. The receiver must be effect-free, so it comes from a (non-mutable) +// parameter here. (By-value capture cannot be observed via external mutation on a *direct* struct delegate: a +// mutable receiver - or the defensive copy it forces - reads a mutable value, which counts as an effect, so it +// is kept as a closure instead. The boxing itself guarantees the by-value copy.) +[] +let ``Struct value-type receiver targets the real method (preview)`` () = + FSharp """ +module StructDirect + +open System + +[] +type S = + val V : int + new (v: int) = { V = v } + member this.AddV (x: int) (y: int) : int = this.V + x + y + +let makeAdder (s: S) = Func(s.AddV) + +[] +let main _ = + let d = makeAdder (S(100)) + if d.Invoke(2, 3) <> 105 then failwithf "wrong result: %d" (d.Invoke(2, 3)) + if d.Method.Name <> "AddV" then failwithf "expected direct 'AddV' but got '%s'" d.Method.Name + if isNull d.Target then failwith "Target should be the boxed receiver, not null" + if not (d.Target :? S) then failwith "Target should be a boxed S" + 0 + """ + |> withLangVersionPreview + |> compileExeAndRun + |> shouldSucceed + +// A *mutable* value-type receiver is kept as a closure. Boxing it once as the delegate Target would let a +// mutating method accumulate changes across invocations, whereas the closure works on a fresh by-value copy +// each call. Here Bump adds 100 to the receiver's field; both invocations must return 105 (not 105 then 205), +// preserving the pre-feature by-value semantics. The immutable-struct case above still goes direct. +[] +let ``Mutable struct receiver stays a closure so mutation does not persist (preview)`` () = + FSharp """ +module MutableStructReceiverClosure + +open System + +[] +type C = + val mutable N : int + new (n) = { N = n } + member this.Bump () : int = this.N <- this.N + 100; this.N + +[] +let main _ = + let c = C(5) + let d = Func(c.Bump) + let r1 = d.Invoke() + let r2 = d.Invoke() + if r1 <> 105 then failwithf "first invoke: expected 105 but got %d" r1 + if r2 <> 105 then failwithf "second invoke: expected 105 (no persisted mutation) but got %d" r2 + if d.Method.Name <> "Invoke" then failwithf "expected closure 'Invoke' but got '%s'" d.Method.Name + 0 + """ + |> withLangVersionPreview + |> withOptions [ "--optimize+" ] + |> withNoWarn 52 + |> compileExeAndRun + |> shouldSucceed + +// Case 52: an extension member compiles to a static method whose first parameter is the receiver. The CLR's +// "closed over the first argument" delegate binds that receiver as the Target, so the delegate points directly +// at the static extension method (in release, where the eta-lambda does not need to survive for debugging). +[] +let ``Extension member targets the real method (preview)`` () = + FSharp """ +module ExtensionDirect + +open System +open System.Runtime.CompilerServices + +type Holder() = class end + +[] +type Extensions = + [] + static member Combine (h: Holder, x: int, y: int) : int = x + y + +[] +let main _ = + let h = Holder() + let d = Func(fun a b -> h.Combine(a, b)) + if d.Invoke(2, 3) <> 5 then failwith "wrong result" + if d.Method.Name <> "Combine" then failwithf "expected direct 'Combine' but got '%s'" d.Method.Name + if not (obj.ReferenceEquals(d.Target, h)) then failwith "Target is not the extension receiver" + 0 + """ + |> withLangVersionPreview + |> withOptions [ "--optimize+" ] + |> compileExeAndRun + |> shouldSucceed + +// A generic extension member whose receiver type uses the method's type parameter ('T list) still binds the +// receiver as the Target: the type argument is threaded through as a method instantiation (an extension member +// has no enclosing type arguments), and the receiver - a reference type - is the closed-over first argument. +[] +let ``Generic extension member receiver targets the real method (preview)`` () = + FSharp """ +module GenericExtensionDirect + +open System +open System.Runtime.CompilerServices + +[] +type ListExtensions = + [] + static member CountWith<'T> (xs: 'T list, x: int, y: int) : int = List.length xs + x + y + +[] +let main _ = + let xs = [ "a"; "b"; "c" ] + let d = Func(fun a b -> xs.CountWith(a, b)) + if d.Invoke(2, 3) <> 8 then failwithf "wrong result: %d" (d.Invoke(2, 3)) + if d.Method.Name <> "CountWith" then failwithf "expected direct 'CountWith' but got '%s'" d.Method.Name + if not (obj.ReferenceEquals(d.Target, xs)) then failwith "Target is not the extension receiver" + 0 + """ + |> withLangVersionPreview + |> withOptions [ "--optimize+" ] + |> compileExeAndRun + |> shouldSucceed + +// A static method on a value type whose first argument is a reference type: that argument becomes the CLR's +// closed-over Target (a reference), not a value-type instance receiver, so it must be passed as-is and must +// NOT be boxed as the declaring struct. +[] +let ``Static method on a value type with a reference first argument is not boxed (preview)`` () = + FSharp """ +module StaticValueTypeFirstArg + +open System + +[] +type V = + static member Pick (s: string, n: int) : int = s.Length + n + +[] +let main _ = + // F# static member on a struct: the leading arg "abc" is a reference, closed over as the Target. + let d = Func(fun n -> V.Pick("abc", n)) + if d.Invoke 10 <> 13 then failwithf "fsharp: expected 13 but got %d" (d.Invoke 10) + if d.Method.Name <> "Pick" then failwithf "fsharp: expected direct 'Pick' but got '%s'" d.Method.Name + if not (d.Target :? string) then failwith "fsharp: Target should be the reference first argument, not a boxed struct" + + // BCL static method on a struct (System.Int32): the leading arg "41" is a reference, closed over as the Target. + let b = Func(fun () -> Int32.Parse "41") + if b.Invoke() <> 41 then failwithf "il: expected 41 but got %d" (b.Invoke()) + if b.Method.Name <> "Parse" then failwithf "il: expected direct 'Parse' but got '%s'" b.Method.Name + if not (b.Target :? string) then failwith "il: Target should be the reference first argument, not a boxed struct" + 0 + """ + |> withLangVersionPreview + |> withOptions [ "--optimize+" ] + |> compileExeAndRun + |> shouldSucceed + +// Case 53: a byref Invoke parameter with a mutating body is not a transparent forwarding call, so it stays +// a closure and mutates through the byref correctly. +[] +let ``Byref-parameter delegate stays a closure and mutates (preview)`` () = + FSharp """ +module ByrefClosure + +open System + +type D = delegate of byref -> unit + +[] +let main _ = + let d = D(fun x -> x <- x + 1) + let mutable v = 10 + d.Invoke(&v) + if v <> 11 then failwithf "expected 11 but got %d" v + if d.Method.Name <> "Invoke" then failwithf "expected closure 'Invoke' but got '%s'" d.Method.Name + 0 + """ + |> withLangVersionPreview + |> compileExeAndRun + |> shouldSucceed + +// Case 55: an over-application - the target's *result* consumes the delegate argument(s) - is not a saturated +// call to the target, so it must stay a closure with per-invocation evaluation of the function position. A +// direct delegate here would be doubly wrong: it would point at the wrong method (with an incompatible IL +// return) and would stop re-evaluating the function position on each invocation. +[] +let ``Over-application stays a closure and evaluates per invocation (preview)`` () = + FSharp """ +module OverApplicationClosure + +open System + +let mutable calls = 0 + +let makeHandler (tag: string) : unit -> unit = + calls <- calls + 1 + fun () -> () + +[] +let main _ = + // 'makeHandler "h"' returns the function that consumes the Invoke argument list, so the closure must + // re-evaluate it on every invocation, not bind 'makeHandler' at construction. + let d = Action(makeHandler "h") + if calls <> 0 then failwith "over-application was evaluated at construction" + if d.Method.Name <> "Invoke" then failwithf "expected closure 'Invoke' but got '%s'" d.Method.Name + d.Invoke() + d.Invoke() + if calls <> 2 then failwithf "expected per-invocation evaluation, calls=%d" calls + + // A throwing function position likewise stays a closure and faults at invocation, not construction. + let f = Action(failwith "boom") + if f.Method.Name <> "Invoke" then failwithf "expected closure 'Invoke' but got '%s'" f.Method.Name + + try + f.Invoke() + failwith "expected the lazy 'failwith' to throw on Invoke" + with Failure "boom" -> + () + + 0 + """ + |> withLangVersionPreview + |> withOptions [ "--optimize+" ] + |> compileExeAndRun + |> shouldSucceed + +let private crossAssemblyLibrary = + FSharp """ +module DelegateLib + +let add (x: int) (y: int) : int = x + y + +type Calc(k: int) = + member _.Scale (x: int) (y: int) : int = (x + y) * k + +// A small inline function: its body is serialized into the referenced assembly and is always inlined at the +// use site (independent of --optimize), so a delegate over it can never see a forwarding call. +let inline addInline (x: int) (y: int) : int = x + y + """ + |> asLibrary + +[] +let ``Cross-assembly F# target is emitted directly (preview)`` () = + FSharp """ +module CrossAsmDirect + +open System +open DelegateLib + +[] +let main _ = + // Static module function imported from another assembly: direct, null Target, real Method.Name. + let ds = Func(add) + if ds.Invoke(2, 3) <> 5 then failwith "static: wrong result" + if ds.Method.Name <> "add" then failwithf "static: expected 'add' but got '%s'" ds.Method.Name + if not (isNull ds.Target) then failwith "static: Target should be null" + + // Instance member imported from another assembly: direct, Target is the receiver. + let c = Calc(10) + let di = Func(c.Scale) + if di.Invoke(2, 3) <> 50 then failwithf "instance: expected 50 but got %d" (di.Invoke(2, 3)) + if di.Method.Name <> "Scale" then failwithf "instance: expected 'Scale' but got '%s'" di.Method.Name + if not (obj.ReferenceEquals(di.Target, c)) then failwith "instance: Target is not the receiver" + 0 + """ + |> withReferences [ crossAssemblyLibrary ] + |> withLangVersionPreview + |> withOptions [ "--optimize+" ] + |> compileExeAndRun + |> shouldSucceed + +// An 'inline' target from a referenced assembly is always inlined (mandatory inlining takes precedence over +// the forwarding-call preservation), so the forwarding call vanishes and a closure is kept even in release. +[] +let ``Cross-assembly inline target stays a closure (preview)`` () = + FSharp """ +module CrossAsmInline + +open System +open DelegateLib + +[] +let main _ = + let d = Func(fun a b -> addInline a b) + if d.Invoke(2, 3) <> 5 then failwith "wrong result" + if d.Method.Name <> "Invoke" then failwithf "expected closure 'Invoke' but got '%s'" d.Method.Name + 0 + """ + |> withReferences [ crossAssemblyLibrary ] + |> withLangVersionPreview + |> withOptions [ "--optimize+" ] + |> compileExeAndRun + |> shouldSucceed + +// An [] function parameter yields a direct delegate only when full inlining leaves a +// forwarding call to a named method as the delegate body: when the inlined lambda body is arbitrary code +// there is no method to point at, and when either inlining does not happen, the parameter is a first-class +// function value (case 42) - both keep a closure. +[] +let ``InlineIfLambda function parameter keeps a closure unless inlining exposes a forwarding call (preview)`` () = + FSharp """ +module InlineIfLambdaClosure + +open System + +let mutable acc = 0 + +let inline makeAction ([] f: int -> int -> unit) = Action(fun a b -> f a b) + +// Read through a mutable so no inlining step can turn the argument back into a lambda. +let mutable handler : int -> int -> unit = fun a b -> acc <- acc + a * 100 + b + +let bump (a: int) (b: int) : unit = acc <- acc + a * 1000 + b + +[] +let main _ = + // Lambda argument: 'makeAction' and the lambda both inline, leaving inlined code as the delegate body. + let k = 7 + let d = makeAction (fun a b -> acc <- acc + a * 10 + b + k) + d.Invoke(1, 2) + if acc <> 19 then failwithf "lambda: wrong result %d" acc + if d.Method.Name <> "Invoke" then failwithf "lambda: expected closure 'Invoke' but got '%s'" d.Method.Name + + // First-class argument: there is no lambda to inline, so 'f' is a function value. + acc <- 0 + let d2 = makeAction handler + d2.Invoke(1, 2) + if acc <> 102 then failwithf "value: wrong result %d" acc + if d2.Method.Name <> "Invoke" then failwithf "value: expected closure 'Invoke' but got '%s'" d2.Method.Name + + // Forwarding lambda argument: after both inline, the delegate body is a forwarding call to 'bump', + // which the recognizer binds directly. + acc <- 0 + let d3 = makeAction (fun a b -> bump a b) + d3.Invoke(1, 2) + if acc <> 1002 then failwithf "forwarding: wrong result %d" acc + if d3.Method.Name <> "bump" then failwithf "forwarding: expected direct 'bump' but got '%s'" d3.Method.Name + if not (isNull d3.Target) then failwith "forwarding: Target should be null for a static target" + 0 + """ + |> withLangVersionPreview + |> withOptions [ "--optimize+" ] + |> compileExeAndRun + |> shouldSucceed + +// A static method's closed-over first argument must be a *known* reference type: the CLR stores it as the +// delegate's 'object' Target and passes it unboxed into the method's first by-value parameter, so a value type +// has no closed form. A type parameter is not known to be a reference type (it could be instantiated with a +// value type), so closing over a type-parameter-typed first argument stays a closure - a direct delegate would +// push an unboxed !!T where an object Target is expected (invalid IL, InvalidProgramException at runtime). +[] +let ``Static method with a type-parameter first argument stays a closure (preview)`` () = + FSharp """ +module GenericStaticFirstArgClosure + +open System + +let pick<'T> (tag: 'T) (n: int) : int = n + 1 + +let make<'T> (v: 'T) = Func(fun n -> pick v n) + +[] +let main _ = + // 'T = int (value type): must be a closure, not a direct delegate closing over an unboxed int. + let di = make 100 + if di.Invoke 5 <> 6 then failwithf "int: wrong result %d" (di.Invoke 5) + if di.Method.Name <> "Invoke" then failwithf "int: expected closure 'Invoke' but got '%s'" di.Method.Name + + // 'T = string (reference type): also a closure, since the recognizer cannot know 'T is a reference type. + let ds = make "abc" + if ds.Invoke 5 <> 6 then failwithf "string: wrong result %d" (ds.Invoke 5) + if ds.Method.Name <> "Invoke" then failwithf "string: expected closure 'Invoke' but got '%s'" ds.Method.Name + 0 + """ + |> withLangVersionPreview + |> withOptions [ "--optimize+" ] + |> compileExeAndRun + |> shouldSucceed + +// An instance receiver typed as a bare type parameter has no direct form either: generic code shares one body +// across reference instantiations but specializes value ones, so pushing an unboxed !!T as the 'object' Target +// is invalid IL for a value-type instantiation (and unverifiable even for a reference one). Both a struct and a +// class instantiation must therefore stay a closure. +[] +let ``Type-parameter instance receiver stays a closure (preview)`` () = + FSharp """ +module TyparInstanceReceiverClosure + +open System + +type IFoo = + abstract M : int -> int + +[] +type SFoo = + interface IFoo with + member _.M x = x + 1 + +type CFoo() = + interface IFoo with + member _.M x = x + 1 + +let make<'T when 'T :> IFoo> (x: 'T) = Func(x.M) + +[] +let main _ = + // 'T = struct implementing IFoo: a direct delegate would emit invalid IL, so a closure is kept. + let ds = make (SFoo()) + if ds.Invoke 5 <> 6 then failwithf "struct: wrong result %d" (ds.Invoke 5) + if ds.Method.Name <> "Invoke" then failwithf "struct: expected closure 'Invoke' but got '%s'" ds.Method.Name + + // 'T = class implementing IFoo: also a closure, since the receiver type is a bare type parameter. + let dc = make (CFoo()) + if dc.Invoke 5 <> 6 then failwithf "class: wrong result %d" (dc.Invoke 5) + if dc.Method.Name <> "Invoke" then failwithf "class: expected closure 'Invoke' but got '%s'" dc.Method.Name + 0 + """ + |> withLangVersionPreview + |> withOptions [ "--optimize+" ] + |> compileExeAndRun + |> shouldSucceed + +// A BCL instance method on a value type is reached via the ILCall path and boxes the receiver as the Target +// (the same box logic as an F# struct instance receiver, exercised through imported metadata). +[] +let ``BCL value-type instance method targets the real method (preview)`` () = + FSharp """ +module BclStructInstanceDirect + +open System + +[] +let main _ = + // Int32.CompareTo(int) is an instance method on a value type. + let d = Func(fun x -> (42).CompareTo(x)) + if d.Invoke 42 <> 0 then failwithf "compare-eq: %d" (d.Invoke 42) + if d.Invoke 100 >= 0 then failwithf "compare-lt: %d" (d.Invoke 100) + if d.Invoke 1 <= 0 then failwithf "compare-gt: %d" (d.Invoke 1) + if d.Method.Name <> "CompareTo" then failwithf "expected direct 'CompareTo' but got '%s'" d.Method.Name + if isNull d.Target then failwith "Target should be the boxed receiver" + 0 + """ + |> withLangVersionPreview + |> withOptions [ "--optimize+" ] + |> withNoWarn 52 // calling an instance method on the '42' literal defensively copies the value type + |> compileExeAndRun + |> shouldSucceed + +// Property accessors compile to get_/set_ methods and are direct instance targets like any other member; the +// setter additionally exercises a void-returning instance target. +[] +let ``Property getter and setter are emitted directly (preview)`` () = + FSharp """ +module PropertyAccessorDirect + +open System + +type C() = + let mutable v = 7 + member _.Value with get () = v and set x = v <- x + +[] +let main _ = + let c = C() + let g = Func(fun () -> c.Value) + if g.Invoke() <> 7 then failwithf "getter: %d" (g.Invoke()) + if g.Method.Name <> "get_Value" then failwithf "getter: expected 'get_Value' but got '%s'" g.Method.Name + + let s = Action(fun x -> c.Value <- x) + s.Invoke 99 + if c.Value <> 99 then failwithf "setter did not run: %d" c.Value + if s.Method.Name <> "set_Value" then failwithf "setter: expected 'set_Value' but got '%s'" s.Method.Name + 0 + """ + |> withLangVersionPreview + |> withOptions [ "--optimize+" ] + |> compileExeAndRun + |> shouldSucceed + +// A value-type receiver reached as a byref that the recognizer cannot recover to a local value (here a struct +// array element, addressed as &arr.[0]) has no boxable value to store as the Target, so a closure is kept. +[] +let ``Byref struct receiver stays a closure (preview)`` () = + FSharp """ +module ByrefReceiverClosure + +open System + +[] +type S = + val V : int + new (v) = { V = v } + member this.Add (x: int) : int = this.V + x + +[] +let main _ = + let arr = [| S 100 |] + // The receiver is &arr.[0] - an array-element address, not the address of a local, so it stays a byref. + let d = Func(fun x -> arr.[0].Add x) + if d.Invoke 5 <> 105 then failwithf "wrong result %d" (d.Invoke 5) + if d.Method.Name <> "Invoke" then failwithf "expected closure 'Invoke' but got '%s'" d.Method.Name + 0 + """ + |> withLangVersionPreview + |> withOptions [ "--optimize+" ] + |> compileExeAndRun + |> shouldSucceed + +// An inline function with a statically-resolved-type-parameter (SRTP) constraint is expanded at the use site +// (mandatory inlining), leaving arithmetic rather than a forwarding call, so a closure is kept. The witness- +// argument guard is a defensive backstop for the same family: a witness-passing target is never bound directly. +[] +let ``SRTP inline target stays a closure (preview)`` () = + FSharp """ +module SrtpInlineClosure + +open System + +let inline addTwice (x: ^T) : ^T = x + x + +[] +let main _ = + let d = Func(fun x -> addTwice x) + if d.Invoke 5 <> 10 then failwithf "wrong result %d" (d.Invoke 5) + if d.Method.Name <> "Invoke" then failwithf "expected closure 'Invoke' but got '%s'" d.Method.Name + 0 + """ + |> withLangVersionPreview + |> withOptions [ "--optimize+" ] + |> compileExeAndRun + |> shouldSucceed + +// A virtual method invoked on a value type is a 'constrained.' callvirt; the direct IL-method path excludes +// constrained calls (the closed delegate cannot reproduce the constrained receiver), so a closure is kept. +[] +let ``Constrained virtual call on a value type stays a closure (preview)`` () = + FSharp """ +module ConstrainedCallClosure + +open System + +[] +let main _ = + // e.ToString() on an enum is a constrained callvirt to Object::ToString. + let make (e: DayOfWeek) = Func(fun () -> e.ToString()) + let d = make DayOfWeek.Monday + if d.Invoke() <> "Monday" then failwithf "wrong result %s" (d.Invoke()) + if d.Method.Name <> "Invoke" then failwithf "expected closure 'Invoke' but got '%s'" d.Method.Name + 0 + """ + |> withLangVersionPreview + |> withOptions [ "--optimize+" ] + |> compileExeAndRun + |> shouldSucceed + +// A constructor (newobj) as the delegate body is a structural bail - grouped with base and self-init calls, +// which the type checker anyway forbids inside a closure (FS0408) - so a closure is kept. +[] +let ``Constructor target stays a closure (preview)`` () = + FSharp """ +module ConstructorClosure + +open System + +type Boxed(v: int) = + member _.V = v + +[] +let main _ = + let d = Func(fun n -> Boxed(n)) + let r = d.Invoke 5 + if r.V <> 5 then failwithf "wrong result %d" r.V + if d.Method.Name <> "Invoke" then failwithf "expected closure 'Invoke' but got '%s'" d.Method.Name + 0 + """ + |> withLangVersionPreview + |> withOptions [ "--optimize+" ] + |> compileExeAndRun + |> shouldSucceed + +[] +let ``Minimal API binds a direct delegate handler by parameter name (preview)`` () = + let aspNetFrameworkReferences = + ReferenceHelpers.getFrameworkReference { Name = "Microsoft.AspNetCore.App"; Version = None } + + let script = aspNetFrameworkReferences + """ +module X = + open System + open System.Net + open System.Net.Http + open System.Net.Sockets + open Microsoft.AspNetCore.Builder + open Microsoft.AspNetCore.Http + open Microsoft.Extensions.Logging + + let divide (first: int) (second: int) : int = first / second + + let run () = + let port = + let listener = new TcpListener(IPAddress.Loopback, 0) + listener.Start() + let p = (listener.LocalEndpoint :?> IPEndPoint).Port + listener.Stop() + p + + let url = sprintf "http://127.0.0.1:%d" port + let builder = WebApplication.CreateBuilder() + builder.Logging.ClearProviders() |> ignore + let app = builder.Build() + + // Route parameters {second}/{first} bind to the handler's parameters by name, which requires delegate.Method to be the + // real 'divide' (a direct delegate), not a synthesized closure 'Invoke'. + app.MapGet("/divide/{second}/{first}", Func(fun z w -> divide z w)) |> ignore + app.Urls.Add url + app.StartAsync().GetAwaiter().GetResult() + + try + let client = new HttpClient() + let body = client.GetStringAsync(url + "/divide/2/6").GetAwaiter().GetResult() + if body.Trim() <> "3" then failwithf "minimal API returned '%s', expected '3'" body + finally + app.StopAsync().GetAwaiter().GetResult() + +X.run () """ + + let scriptPath = + Path.Combine(Path.GetTempPath(), $"direct_delegate_minimal_api_{System.Guid.NewGuid():N}.fsx") + + File.WriteAllText(scriptPath, script) + + try + let result = runFsiProcess [ "--langversion:preview"; scriptPath ] + + Assert.True( + result.ExitCode = 0, + $"fsi exited with %d{result.ExitCode}.\nstdout:\n%s{result.StdOut}\nstderr:\n%s{result.StdErr}") + finally + try File.Delete scriptPath with _ -> () diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj index b92e9ef8638..9552df0463c 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj +++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj @@ -266,6 +266,7 @@ + diff --git a/tests/FSharp.Compiler.ComponentTests/Language/CodeQuotationTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/CodeQuotationTests.fs index 29556381221..7085bd7a3a7 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/CodeQuotationTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/CodeQuotationTests.fs @@ -40,6 +40,42 @@ let z : unit = |> compileAndRun |> shouldSucceed + [] + let ``Delegate construction quotations are unaffected by the direct delegate optimization`` () = + Fsx """ +open System +open FSharp.Quotations.Patterns + +let handlerCurried (x: int) (y: int) : unit = () + +type C(k: int) = + member _.AddC (x: int) (y: int) : unit = ignore k + +let check (label: string) (target: string) (expr: Quotations.Expr) = + match expr with + | NewDelegate(dty, _, _) when dty = typeof> -> () + | e -> failwithf "%s: expected NewDelegate of Action, got %A" label e + if not ((string expr).Contains target) then + failwithf "%s: expected the quotation to reference target '%s', got %A" label target expr + +let o = C(1) + +// non-eta-expanded known function +check "nonEta" "handlerCurried" <@ Action(handlerCurried) @> +// eta-expanded known function +check "etaCurried" "handlerCurried" <@ Action(fun a b -> handlerCurried a b) @> +// non-eta-expanded instance method +check "instanceNonEta" "AddC" <@ Action(o.AddC) @> +// eta-expanded instance method +check "instanceEta" "AddC" <@ Action(fun a b -> o.AddC a b) @> + +printfn "ok" + """ + |> asExe + |> withLangVersionPreview + |> compileAndRun + |> shouldSucceed + [] let ``Quotation on decimal literal compiles and runs`` () = FSharp """ diff --git a/tests/FSharp.Test.Utilities/ProjectGeneration.fs b/tests/FSharp.Test.Utilities/ProjectGeneration.fs index dd1e2eacb65..9a7d8930c24 100644 --- a/tests/FSharp.Test.Utilities/ProjectGeneration.fs +++ b/tests/FSharp.Test.Utilities/ProjectGeneration.fs @@ -155,25 +155,34 @@ module ReferenceHelpers = |> Seq.map (fun (name, runtimes) -> name, runtimes |> Seq.map snd |> Seq.toList) |> Map + let preferReleased candidates = + let released, previews = + candidates |> List.partition (fun ((r: Runtime), _) -> not (r.Version.Contains "preview")) + + let newestFirst = List.sortByDescending (fun ((r: Runtime), _) -> r.Version) + newestFirst released @ newestFirst previews + runTimeLoadScripts |> Map.tryFind reference.Name |> Option.map ( List.filter (fun (r, _) -> match reference.Version with | Some v -> r.Version = v - | None -> not (r.Version.Contains "preview")) - >> List.sortByDescending (fun (r, _) -> r.Version) + | None -> true) + >> preferReleased ) |> Option.bind List.tryHead |> Option.map snd |> Option.defaultWith (fun () -> - failwith $"Couldn't find framework reference {reference.Name} {reference.Version}. Available Runtimes: \n" - + (runTimeLoadScripts - |> Map.toSeq - |> Seq.map snd - |> Seq.collect (List.map fst) - |> Seq.map (fun r -> $"{r.Name} {r.Version}") - |> String.concat "\n")) + let available = + runTimeLoadScripts + |> Map.toSeq + |> Seq.map snd + |> Seq.collect (List.map fst) + |> Seq.map (fun r -> $"{r.Name} {r.Version}") + |> String.concat "\n" + + failwith $"Couldn't find framework reference {reference.Name} {reference.Version}. Available Runtimes: \n{available}") open ReferenceHelpers