From 40eb2c0ddbb142b901907ff1558004cf226cd8bf Mon Sep 17 00:00:00 2001 From: Brian Rourke Boll Date: Sun, 1 Mar 2026 11:04:40 -0500 Subject: [PATCH 1/3] Add failing tests showing https://github.com/dotnet/fsharp/issues/19367 --- .../Language/InterpolatedStringsTests.fs | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/tests/FSharp.Compiler.ComponentTests/Language/InterpolatedStringsTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/InterpolatedStringsTests.fs index e7c18f0d679..02157e7cf67 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/InterpolatedStringsTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/InterpolatedStringsTests.fs @@ -181,4 +181,26 @@ printfn "%%s" (System.Globalization.CultureInfo "en-US" |> x.ToString) """ |> compileExeAndRun |> shouldSucceed - |> withStdOutContains "abcde" \ No newline at end of file + |> withStdOutContains "abcde" + + // See https://github.com/dotnet/fsharp/issues/19367. + [] + let ``Hole without specifier parsed correctly when culture set to Thai`` () = + Fsx + """ + let s = $"{3}" + if s <> "3" then + failwith $"Expected \"3\" but got \"%s{s}\"." + """ + |> compileExeAndRun + |> shouldSucceed + + // See https://github.com/dotnet/fsharp/issues/19367. + [] + let ``Explicit %P does not cause exception when culture set to Thai`` () = + Fsx + """ + let s = $"%P({3})" + """ + |> compileExeAndRun + |> shouldSucceed From d124b178f34e3b68adafad3bf05e8b6fdeafcd47 Mon Sep 17 00:00:00 2001 From: Brian Rourke Boll Date: Sun, 1 Mar 2026 11:08:05 -0500 Subject: [PATCH 2/3] Use `char` overload of `IndexOf` --- src/FSharp.Core/printf.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FSharp.Core/printf.fs b/src/FSharp.Core/printf.fs index 3c01be097e2..8dfaf52b680 100644 --- a/src/FSharp.Core/printf.fs +++ b/src/FSharp.Core/printf.fs @@ -209,7 +209,7 @@ module internal PrintfImpl = let parseInterpolatedHoleDotNetFormat typeChar (s: string) (i: byref) = if typeChar = 'P' then if i < s.Length && s.[i] = '(' then - let i2 = s.IndexOf(")", i) + let i2 = s.IndexOf(')', i) if i2 = -1 then ValueNone else From ddffc521f9a668ab8a1f23c3b71604e91058fe96 Mon Sep 17 00:00:00 2001 From: Brian Rourke Boll Date: Sun, 1 Mar 2026 11:14:48 -0500 Subject: [PATCH 3/3] Update release notes --- docs/release-notes/.FSharp.Core/10.0.300.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/release-notes/.FSharp.Core/10.0.300.md b/docs/release-notes/.FSharp.Core/10.0.300.md index f823f462ee8..9218bf299a0 100644 --- a/docs/release-notes/.FSharp.Core/10.0.300.md +++ b/docs/release-notes/.FSharp.Core/10.0.300.md @@ -6,6 +6,7 @@ * Fix tuple/multi-value projections in queries to use Queryable.Select instead of Enumerable.Select when the source is IQueryable, preserving query composition and enabling async operations like ToListAsync() in Entity Framework Core. ([Issue #3782](https://github.com/dotnet/fsharp/issues/3782), [Issue #15133](https://github.com/dotnet/fsharp/issues/15133)) * Fix EvaluateQuotation to handle Sequential expressions, void method calls (unit return), and other patterns that were previously throwing NotSupportedException. Also properly handles unit-returning expressions by using Action delegates instead of Func delegates. ([Issue #19099](https://github.com/dotnet/fsharp/issues/19099)) * Fix query conditionals without else branch (if-then only) that were causing type mismatch errors. Now properly extracts element type from IQueryable for creating empty sequences. ([Issue #3445](https://github.com/dotnet/fsharp/issues/3445)) +* Ensure culture-independent parsing of .NET-style interpolated string holes. ([Issue #19367](https://github.com/dotnet/fsharp/issues/19367), [PR #19370](https://github.com/dotnet/fsharp/pull/19370)) ### Added