Skip to content

Fix YieldFromFinal/ReturnFromFinal being called in non-tail positions#19403

Merged
T-Gro merged 4 commits intodotnet:mainfrom
majocha:fromfinal-fixes
Mar 8, 2026
Merged

Fix YieldFromFinal/ReturnFromFinal being called in non-tail positions#19403
T-Gro merged 4 commits intodotnet:mainfrom
majocha:fromfinal-fixes

Conversation

@majocha
Copy link
Contributor

@majocha majocha commented Mar 8, 2026

Fix YieldFromFinal/ReturnFromFinal being called in non-tail positions

Problem

The *Final variants (YieldFromFinal, ReturnFromFinal) were incorrectly dispatched in several non-tail-position contexts within computation expressions:

  1. for loop bodiesyield!/return! inside for was calling YieldFromFinal instead of YieldFrom (regression from YieldFromFinal being called from a non-tailcall position #19402)
  2. use bindings — the body of use was treated as tail position, but it's wrapped in Using/TryFinally so it's not actually a tail call
  3. use! bindings — same issue as use

Fix

Pass noTailCall ceenv instead of ceenv when translating:

  • ForEach body (line 1325)
  • use body (line 1915)
  • use! body (line 1979)

Tests

Added a ListBuilder — a realistic seq-like builder that uses list<'T> throughout and tracks YieldFrom vs YieldFromFinal call counts. Each test verifies both the produced result and which method variant was called.

Covers 11 scenarios:

Position Expected variant
for loop body YieldFrom
Genuine tail position YieldFromFinal
try/with body YieldFrom
try/finally body YieldFrom
try/with handler YieldFromFinal
use body YieldFrom
while body YieldFrom
match branch (tail) YieldFromFinal
if/else (tail) YieldFromFinal
let! continuation (tail) YieldFromFinal
Sequential: non-tail + tail YieldFrom + YieldFromFinal

Added a try/with handler case in coroutines.fsx.

Fixes #19402

@majocha
Copy link
Contributor Author

majocha commented Mar 8, 2026

I asked Copilot to do a comprehensive audit. It revealed a few more bugs.

I'm not sure about try/with handler. It's not clear to me why it shouldn't be final.

@github-actions
Copy link
Contributor

github-actions bot commented Mar 8, 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/11.0.100.md

@majocha majocha changed the title Fix #19402 Fix YieldFromFinal/ReturnFromFinal being called in non-tail positions Mar 8, 2026
@majocha
Copy link
Contributor Author

majocha commented Mar 8, 2026

In hindsight not covering a sample seq builder in tests was a huge oversight.

@majocha majocha marked this pull request as ready for review March 8, 2026 12:28
@majocha majocha requested a review from a team as a code owner March 8, 2026 12:28
@github-project-automation github-project-automation bot moved this from New to In Progress in F# Compiler and Tooling Mar 8, 2026
@T-Gro T-Gro merged commit 6609928 into dotnet:main Mar 8, 2026
45 checks passed
@majocha majocha deleted the fromfinal-fixes branch March 9, 2026 10:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

YieldFromFinal being called from a non-tailcall position

2 participants