Skip to content

Warn when function type passed to interpolated string#19289

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

Warn when function type passed to interpolated string#19289
T-Gro wants to merge 5 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 👍 .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: New

Development

Successfully merging this pull request may close these issues.

4 participants