Skip to content

Warn when function type passed to interpolated string#19289

Open
T-Gro wants to merge 8 commits intomainfrom
bugfix-warning-wrong-interpolation
Open

Warn when function type passed to interpolated string#19289
T-Gro wants to merge 8 commits intomainfrom
bugfix-warning-wrong-interpolation

Conversation

@T-Gro
Copy link
Member

@T-Gro T-Gro commented Feb 13, 2026

Warn when function value is used as interpolated string argument

Adds a new warning FS3882 when a function or delegate value is used as an interpolated string fill expression — a common mistake where the user likely forgot to apply the function to its arguments.

let f x = x + 1
let s = $"{f}"       // FS3882: This expression is a function value...
let s = $"{f 42}"    // OK

What's in this PR

  • New warning gated behind LanguageFeature.WarnWhenFunctionValueUsedAsInterpolatedStringArg (F# 11.0)
  • Detects both F# function types (isFunTy) and delegate types (isDelegateTy) — System.Action, System.Func<>, etc.
  • Fires for both string-typed and FormattableString-typed interpolated strings
  • Suppressible via #nowarn "3882"

Bootstrap fixes

The new warning correctly caught real issues in the compiler's own codebase:

  • DependencyGraph.fs — was interpolating function parameters ({unpacker}) instead of meaningful strings
  • FSharpProjectSnapshot.fs — was interpolating a callback {f} where {fileName} was intended

Tests

14 new tests covering: lambdas, partial application, _.Member shorthand, named functions, delegates (Action/Func), multiple holes, FormattableString, format specifiers, #nowarn suppression, and language version gating.

- Extract duplicated warning block into warnForFunctionValuesInFillExprs local function
- Restore accidentally deleted withStdOutContains assertion in FormattableString test
@github-actions
Copy link
Contributor

github-actions bot commented Feb 13, 2026

❗ Release notes required


✅ Found changes and release notes in following paths:

Change path Release notes path Description
src/Compiler docs/release-notes/.FSharp.Compiler.Service/10.0.300.md
LanguageFeatures.fsi docs/release-notes/.Language/preview.md

@T-Gro
Copy link
Member Author

T-Gro commented Feb 15, 2026

I just realized that the warning would work best if we could already hint for suggesting [<CallerArgumentExpression>] as the alternative.
I came across it when bootstrap build after this feature reported this new diagnostic for the compiler codebase itself:

failwith $"Expected exactly one dependency matching {unpacker} but got: %A{dependencies |> Seq.toArray}")
[<Extension>]
static member UnpackMany(dependencies: 'NodeValue seq, unpacker) =
let results = dependencies |> Seq.choose unpacker
if dependencies |> Seq.length <> (results |> Seq.length) then
failwith $"Expected all dependencies to match {unpacker} but got: %A{dependencies |> Seq.toArray}"

@Happypig375
Copy link
Member

Consider also applying the warning to delegate types too, which are effectively also functions.

@Happypig375
Copy link
Member

Happypig375 commented Feb 16, 2026

Should this warning also apply to .ToString() and calling the string function? How about printf formats with %A or %O?

@T-Gro T-Gro marked this pull request as ready for review February 16, 2026 15:25
@T-Gro T-Gro requested a review from a team as a code owner February 16, 2026 15:25
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@T-Gro
Copy link
Member Author

T-Gro commented Feb 16, 2026

Should this warning also apply to .ToString() and calling the string function? How about printf formats with %A or %O?

Conceptually, those would make sense as well - but they need more design when it comes to the compile vs runtime split and figure out what to do with delayed (currying) or delegated (e.g. fields on a record) invocation.

= Not in this PR, but feel free to expand in the related suggestion for example 👍 .

T-Gro and others added 4 commits February 16, 2026 16:32
…interpolation

# Conflicts:
#	docs/release-notes/.Language/preview.md
#	src/Compiler/FSComp.txt
#	src/Compiler/Facilities/LanguageFeatures.fs
#	src/Compiler/Facilities/LanguageFeatures.fsi
#	src/Compiler/xlf/FSComp.txt.cs.xlf
#	src/Compiler/xlf/FSComp.txt.de.xlf
#	src/Compiler/xlf/FSComp.txt.es.xlf
#	src/Compiler/xlf/FSComp.txt.fr.xlf
#	src/Compiler/xlf/FSComp.txt.it.xlf
#	src/Compiler/xlf/FSComp.txt.ja.xlf
#	src/Compiler/xlf/FSComp.txt.ko.xlf
#	src/Compiler/xlf/FSComp.txt.pl.xlf
#	src/Compiler/xlf/FSComp.txt.pt-BR.xlf
#	src/Compiler/xlf/FSComp.txt.ru.xlf
#	src/Compiler/xlf/FSComp.txt.tr.xlf
#	src/Compiler/xlf/FSComp.txt.zh-Hans.xlf
#	src/Compiler/xlf/FSComp.txt.zh-Hant.xlf
#	tests/FSharp.Compiler.ComponentTests/Language/InterpolatedStringsTests.fs
… directive

The PR's warning code 3882 collided with main's lexHashElifMustBeFirst
(3882) added by the #elif preprocessor directive feature. Renumbered to
3884 (next available). Updated all tests, release notes, and xlf files.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use withDiagnosticMessageMatches instead of withSingleDiagnostic for
the System.Action delegate test, since net472 may produce additional
diagnostics alongside warning 3884.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@T-Gro T-Gro requested a review from abonie March 4, 2026 13:12
@github-project-automation github-project-automation bot moved this from New to In Progress in F# Compiler and Tooling Mar 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

5 participants