From ae6a943e50685055dc654e9fd1a8252d07ecbf38 Mon Sep 17 00:00:00 2001 From: Copilot Date: Tue, 9 Jun 2026 08:13:47 +0200 Subject: [PATCH 1/5] Tests (RED): add failing Go-to-Metadata tests for IL literal fields (#11526) Adds a new MetadataAsTextILField module in tests/FSharp.Compiler.Service.Tests/Symbols.fs covering the rendering of IL literal (const) static fields via FSharpEntity.TryGetMetadataText(). Tests added: - Theory with 5 rows (Int32/Int64/Byte/SByte MaxValue/MinValue) asserting the rendered metadata contains [] and "= ". - Fact for System.Char.MaxValue asserting [] and "=" appear on the MaxValue line. - Negative Fact for System.Math.PI (initonly, non-literal) asserting it is NOT tagged [] and has no "=". Current state (RED): total: 7, failed: 6, succeeded: 1 - 5 Theory rows + Char.MaxValue Fact fail with Assert.Contains() Failure: Sub-string not found because NicePrint.layoutILFieldInfo currently drops [] and the literal value. - Math.PI passes (guards against regression of normal static val rendering). Sprint 02 will implement the fix in src/Compiler/Checking/NicePrint.fs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../FSharp.Compiler.Service.Tests/Symbols.fs | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/tests/FSharp.Compiler.Service.Tests/Symbols.fs b/tests/FSharp.Compiler.Service.Tests/Symbols.fs index 25cc0cd4b6e..5f2d6399599 100644 --- a/tests/FSharp.Compiler.Service.Tests/Symbols.fs +++ b/tests/FSharp.Compiler.Service.Tests/Symbols.fs @@ -1445,6 +1445,65 @@ let test = System.DateTimeKind.Utc failwith "Expected metadata text, got None" | _ -> failwith "Expected FSharpEntity symbol" +module MetadataAsTextILField = + + let private getMetadataTextForEntity (entityName: string) (source: string) : string = + let _, checkResults = getParseAndCheckResults source + let symbolUse = checkResults |> findSymbolUseByName entityName + match symbolUse.Symbol with + | :? FSharpEntity as entity -> + match entity.TryGetMetadataText() with + | Some text -> text.ToString() + | None -> failwithf "Expected metadata text for %s, got None" entityName + | other -> failwithf "Expected FSharpEntity for %s, got %A" entityName other + + [] + [] + [] + [] + [] + [] + let ``IL literal static field renders with [] attribute and value`` + (typeName: string, fieldName: string, expectedValueText: string) = + let source = $"let _ = typeof<{typeName}>" + let shortName = typeName.Substring(typeName.LastIndexOf('.') + 1) + let metadataText = getMetadataTextForEntity shortName source + + Assert.Contains(fieldName, metadataText) + + let line = + metadataText.Split('\n') + |> Array.tryFind (fun l -> l.Contains(fieldName)) + |> Option.defaultWith (fun () -> failwithf "field %s not found in metadata text:\n%s" fieldName metadataText) + + Assert.Contains("[]", metadataText) + Assert.Contains("= " + expectedValueText, line) + + [] + let ``System.Char.MaxValue renders as a literal field`` () = + let metadataText = getMetadataTextForEntity "Char" "let _ = typeof" + + Assert.Contains("[]", metadataText) + let line = + metadataText.Split('\n') + |> Array.tryFind (fun l -> l.Contains("MaxValue")) + |> Option.defaultWith (fun () -> failwithf "MaxValue not found:\n%s" metadataText) + Assert.Contains("=", line) + Assert.False(line.TrimEnd().EndsWith(": char"), + sprintf "MaxValue line is missing its literal value: %s" line) + + [] + let ``System.Math.PI (initonly, non-literal) renders without [] and without value`` () = + let metadataText = getMetadataTextForEntity "Math" "let _ = typeof" + + let line = + metadataText.Split('\n') + |> Array.tryFind (fun l -> l.Contains(" PI") || l.Contains("\tPI")) + |> Option.defaultWith (fun () -> failwithf "PI not found:\n%s" metadataText) + + Assert.Contains("static val", line) + Assert.DoesNotContain("=", line) + module IsByRef = // https://github.com/dotnet/fsharp/issues/3532 [] From 2ccf48fca82adea39a7a228f1017630a3afacc6a Mon Sep 17 00:00:00 2001 From: Copilot Date: Tue, 9 Jun 2026 09:12:15 +0200 Subject: [PATCH 2/5] Fix #11526: render IL literal fields with [] and value in Go-to-Metadata Note: Sprint 01 test assumptions were partially incorrect: - Math.PI is actually a literal const in IL (not initonly); replaced with System.String.Empty for the non-literal case. - The 'first line containing fieldName' finder matched doc-comment lines; narrowed to lines containing 'val :'. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/Compiler/Checking/NicePrint.fs | 5 +++++ tests/FSharp.Compiler.Service.Tests/Symbols.fs | 16 ++++++++-------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/Compiler/Checking/NicePrint.fs b/src/Compiler/Checking/NicePrint.fs index de8daffa7c5..fdd2899bfae 100644 --- a/src/Compiler/Checking/NicePrint.fs +++ b/src/Compiler/Checking/NicePrint.fs @@ -1954,6 +1954,11 @@ module TastDefinitionPrinting = let nameL = ConvertLogicalNameToDisplayLayout (tagField >> wordL) finfo.FieldName let typL = layoutType denv (finfo.FieldType(infoReader.amap, m)) let fieldL = staticL ^^ WordL.keywordVal ^^ (nameL |> addColonL) ^^ typL + let isLiteral = finfo.LiteralValue.IsSome + let fieldL = + if isLiteral then fieldL ^^ PrintIL.layoutILFieldInit finfo.LiteralValue + else fieldL + let fieldL = fieldL |> PrintTypes.layoutAttribs denv None isLiteral TyparKind.Type [] layoutXmlDocOfILFieldInfo denv infoReader finfo fieldL let layoutEventInfo denv (infoReader: InfoReader) m (einfo: EventInfo) = diff --git a/tests/FSharp.Compiler.Service.Tests/Symbols.fs b/tests/FSharp.Compiler.Service.Tests/Symbols.fs index 5f2d6399599..ffce69cd9af 100644 --- a/tests/FSharp.Compiler.Service.Tests/Symbols.fs +++ b/tests/FSharp.Compiler.Service.Tests/Symbols.fs @@ -1473,8 +1473,8 @@ module MetadataAsTextILField = let line = metadataText.Split('\n') - |> Array.tryFind (fun l -> l.Contains(fieldName)) - |> Option.defaultWith (fun () -> failwithf "field %s not found in metadata text:\n%s" fieldName metadataText) + |> Array.tryFind (fun l -> l.Contains("val " + fieldName + ":")) + |> Option.defaultWith (fun () -> failwithf "field declaration for %s not found in metadata text:\n%s" fieldName metadataText) Assert.Contains("[]", metadataText) Assert.Contains("= " + expectedValueText, line) @@ -1486,20 +1486,20 @@ module MetadataAsTextILField = Assert.Contains("[]", metadataText) let line = metadataText.Split('\n') - |> Array.tryFind (fun l -> l.Contains("MaxValue")) - |> Option.defaultWith (fun () -> failwithf "MaxValue not found:\n%s" metadataText) + |> Array.tryFind (fun l -> l.Contains("val MaxValue:")) + |> Option.defaultWith (fun () -> failwithf "MaxValue declaration not found:\n%s" metadataText) Assert.Contains("=", line) Assert.False(line.TrimEnd().EndsWith(": char"), sprintf "MaxValue line is missing its literal value: %s" line) [] - let ``System.Math.PI (initonly, non-literal) renders without [] and without value`` () = - let metadataText = getMetadataTextForEntity "Math" "let _ = typeof" + let ``System.String.Empty (initonly, non-literal) renders without [] and without value`` () = + let metadataText = getMetadataTextForEntity "String" "let _ = typeof" let line = metadataText.Split('\n') - |> Array.tryFind (fun l -> l.Contains(" PI") || l.Contains("\tPI")) - |> Option.defaultWith (fun () -> failwithf "PI not found:\n%s" metadataText) + |> Array.tryFind (fun l -> l.Contains("val Empty:")) + |> Option.defaultWith (fun () -> failwithf "Empty not found:\n%s" metadataText) Assert.Contains("static val", line) Assert.DoesNotContain("=", line) From f62712ab829c4d7dd224a8c1e3bff3c15144d437 Mon Sep 17 00:00:00 2001 From: Copilot Date: Tue, 9 Jun 2026 14:03:18 +0200 Subject: [PATCH 3/5] Format, release notes, baseline updates for #11526 fix fantomas no-op (both touched files are in .fantomasignore); no .bsl baseline drift observed in targeted MetadataAsTextILField run (7/7 passed in 13s). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- docs/release-notes/.FSharp.Compiler.Service/9.0.300.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/release-notes/.FSharp.Compiler.Service/9.0.300.md b/docs/release-notes/.FSharp.Compiler.Service/9.0.300.md index 7f5ab7289d2..eb25fa1ee29 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/9.0.300.md +++ b/docs/release-notes/.FSharp.Compiler.Service/9.0.300.md @@ -33,6 +33,7 @@ * Fix parsing errors using anonymous records and units of measures ([PR #18543](https://github.com/dotnet/fsharp/pull/18543)) * Fixed: [#18441](https://github.com/dotnet/fsharp/issues/18441) FSI multi-emit unstable. ([PR #18465](https://github.com/dotnet/fsharp/pull/18465)) * Fixed: Allow `return`, `return!`, `yield`, `yield!` type annotations without parentheses ([PR #18533](https://github.com/dotnet/fsharp/pull/18533)) +* 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)) ### Added * Added missing type constraints in FCS. ([PR #18241](https://github.com/dotnet/fsharp/pull/18241)) From f4526ad1be0e06a85b0c545ff536a9d86a237def Mon Sep 17 00:00:00 2001 From: Copilot Date: Tue, 9 Jun 2026 16:36:27 +0200 Subject: [PATCH 4/5] Update release notes with PR link (#19922) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- docs/release-notes/.FSharp.Compiler.Service/9.0.300.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/release-notes/.FSharp.Compiler.Service/9.0.300.md b/docs/release-notes/.FSharp.Compiler.Service/9.0.300.md index eb25fa1ee29..56134ffc162 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/9.0.300.md +++ b/docs/release-notes/.FSharp.Compiler.Service/9.0.300.md @@ -33,7 +33,7 @@ * Fix parsing errors using anonymous records and units of measures ([PR #18543](https://github.com/dotnet/fsharp/pull/18543)) * Fixed: [#18441](https://github.com/dotnet/fsharp/issues/18441) FSI multi-emit unstable. ([PR #18465](https://github.com/dotnet/fsharp/pull/18465)) * Fixed: Allow `return`, `return!`, `yield`, `yield!` type annotations without parentheses ([PR #18533](https://github.com/dotnet/fsharp/pull/18533)) -* 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)) +* 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)) ### Added * Added missing type constraints in FCS. ([PR #18241](https://github.com/dotnet/fsharp/pull/18241)) From 6fc5dd8e0226e73a3b549dbeea14f369ef222a7e Mon Sep 17 00:00:00 2001 From: Copilot Date: Tue, 9 Jun 2026 18:01:15 +0200 Subject: [PATCH 5/5] Move #11526 release-notes entry to VNEXT (11.0.100) CI `check_release_notes` requires the entry to live in the VNEXT release-notes path (currently 11.0.100.md), not in the shipped 9.0.300.md release. Move the bullet, no behavior change. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- docs/release-notes/.FSharp.Compiler.Service/11.0.100.md | 1 + docs/release-notes/.FSharp.Compiler.Service/9.0.300.md | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) 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 965957dbc0c..4c84e8f68b5 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md +++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md @@ -75,6 +75,7 @@ ([PR #19724](https://github.com/dotnet/fsharp/pull/19724)) * 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)) +* 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)) ### Added diff --git a/docs/release-notes/.FSharp.Compiler.Service/9.0.300.md b/docs/release-notes/.FSharp.Compiler.Service/9.0.300.md index 56134ffc162..7f5ab7289d2 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/9.0.300.md +++ b/docs/release-notes/.FSharp.Compiler.Service/9.0.300.md @@ -33,7 +33,6 @@ * Fix parsing errors using anonymous records and units of measures ([PR #18543](https://github.com/dotnet/fsharp/pull/18543)) * Fixed: [#18441](https://github.com/dotnet/fsharp/issues/18441) FSI multi-emit unstable. ([PR #18465](https://github.com/dotnet/fsharp/pull/18465)) * Fixed: Allow `return`, `return!`, `yield`, `yield!` type annotations without parentheses ([PR #18533](https://github.com/dotnet/fsharp/pull/18533)) -* 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)) ### Added * Added missing type constraints in FCS. ([PR #18241](https://github.com/dotnet/fsharp/pull/18241))