Filtered try/with in seq { } emits int 0 where seq<'T> is expected for the unmatched case
Les mainteneurs répondent en général sous 2 jours
Personne n'a encore pris cette issue.
Évaluation
- Difficulté
- 2/5
- Temps estimé
- 1-3 heures
- Accessibilité débutants
- 78/100
- Type d'issue
- Bug
- Clarté
- Clairement spécifiée
- Activité
- Calme
- Stack technique
- fsharp
- Domaine
- compilers
Piste de recherche
Commencez dans CheckSequenceExpressions.fs, au niveau de la compilation du handler autour des lignes 356-360, puis comparez-la avec TcExprTryWith dans CheckExpressions.fs autour des lignes 6511-6512 et avec les actions d’échec dans PatternMatchCompilation.fs. Reproduisez la séquence try/with filtrée et inspectez son arbre typé. C’est terminé lorsque la branche du handler sans correspondance est un rethrow plutôt que int 0, tandis que le filtre utilise toujours FailFilter.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Description
This affects F# Compiler Services (FCS). We hit it in the Fable compiler, which builds on FCS and consumes the typed tree to transpile F# to other languages. The mistyped node breaks Fable's statically-typed targets.
A try/with inside a sequence expression (seq { }) that uses a filtered handler — a type test (with :? SomeExn ->) or a when guard — is lowered to RuntimeHelpers.EnumerateTryWith. In CheckSequenceExpressions.fs the handler clauses are compiled with FailFilter as the match-failure action, so the unmatched fallback branch is emitted as a literal 0 of type int in a position where the handler must return seq<'T>. A normal (non-sequence) try/with compiles its handler with Rethrow, which is correctly typed. The wrong type produces invalid output on downstream consumers that rely on the typed tree.
Repro steps
- Compile a sequence expression containing a
try/withwith a filtered handler:seq { try raise (System.InvalidOperationException "boom") with :? System.ArgumentException -> yield 0 } |> Seq.toList |> ignore - Inspect the typed tree for the
RuntimeHelpers.EnumerateTryWithhandler lambda and look at the branch taken when the exception does not match the filter.
Expected behavior
The unmatched/fallback case of the handler should be compiled the same way as a normal try/with — as a rethrow (reraise) of the caught exception. That expression is bottom-typed and therefore compatible with the seq<'T> result type, and it is semantically correct (a non-matching exception should re-propagate).
In CheckExpressions.fs, TcExprTryWith already does this — the handler is compiled with Rethrow:
// CheckExpressions.fs:6511-6512
let v1, filterExpr = CompilePatternForMatchClauses cenv env mWithToLast mWithToLast true FailFilter None g.exn_ty g.int_ty checkedFilterClauses
let v2, handlerExpr = CompilePatternForMatchClauses cenv env mWithToLast mWithToLast true Rethrow None g.exn_ty overallTy.Commit checkedHandlerClauses
CheckSequenceExpressions.fs should use Rethrow for the handler in the same way.
Actual behavior
CheckSequenceExpressions.fs compiles the handler with FailFilter instead of Rethrow:
// CheckSequenceExpressions.fs:356-360
let v1, filterExpr =
CompilePatternForMatchClauses cenv env withRange withRange true FailFilter None g.exn_ty g.int_ty filterClauses
// correct: int
let v2, handlerExpr =
CompilePatternForMatchClauses cenv env withRange withRange true FailFilter None g.exn_ty genOuterTy handlers
// BUG: should be Rethrow
FailFilter lowers the fallback leaf to a literal int 0:
// PatternMatchCompilation.fs:1029-1035
| FailFilter -> mkInt g mMatch 0 // returns 0 (int) — wrong when result type is seq<'T>
| Rethrow -> mkReraise mMatch resultTy // bottom-typed — what's needed here
So the handler's unmatched fallback is int 0 where genOuterTy (seq<'T>) is expected. The branch is unreachable at runtime (the handler only runs after the filter matches), so it is harmless on .NET, but the mistyped node is invalid for consumers of the typed tree that require correct types on every branch. In Fable this breaks compilation of the statically-typed targets.
Suggested fix: in CheckSequenceExpressions.fs (line 360), change the handler's ActionOnFailure from FailFilter to Rethrow, mirroring CheckExpressions.fs:6512.
Known workarounds
In the Fable compiler we post-process the EnumerateTryWith handler lambda and rewrite the mistyped int 0 fallback leaf into a rethrow of the caught exception (walking through if/then/else, decision trees, and let bindings to reach the leaf).
Related information
- Affected component: F# Compiler Services (FCS) —
CheckSequenceExpressions.fs; surfaced via the Fable compiler - Operating system: macOS (Darwin), cross-platform
- .NET Runtime kind: .NET (Core), SDK 10+
- Editing Tools: N/A — reproduces via the compiler directly (F# Compiler Services)
- Langage dominant
- F#
- Étoiles
- 4.3k
- Forks
- 883
- Merge moyen
- 3 j 39 min
- PR mergées (30 j)
- 83
Préparer son environnement
Lance le conteneur de développement du projet dans votre navigateur, avec votre propre compte GitHub.
- Aucun Dockerfile ni fichier Docker Compose
- Propose un modèle de pull request
- Lire le guide de contribution
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Autres issues de dotnet/fsharp
-
Needs-Triage
Difficulté 1/5 Moins d'une heure Accessibilité débutants 95/100
Les mainteneurs répondent en général sous 2 jours
-
Semantic classification cache for opened documents is never populated (written to the unopened-documents cache)Peut-être pris @xperiandri l’a pris il y a 65 jours. OuverteNeeds-Triage
Difficulté 1/5 Moins d'une heure Accessibilité débutants 90/100
Les mainteneurs répondent en général sous 2 jours
-
Needs-Triage
Difficulté 2/5 1-3 heures Accessibilité débutants 78/100
dotnet/fsharp#20265 · 1 commentaire ·
Les mainteneurs répondent en général sous 2 jours
-
Needs-Triage
Difficulté 4/5 3-5 jours Accessibilité débutants 42/100
Les mainteneurs répondent en général sous 2 jours
-
Bug Needs-Triage
Difficulté 4/5 3-5 jours Accessibilité débutants 45/100
Les mainteneurs répondent en général sous 2 jours
Toutes les issues de dotnet/fsharp
Issues similaires
-
Difficulté 2/5 1-3 heures Accessibilité débutants 76/100
voidzero-dev/oxc-angular-compiler#686 ·
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 2/5 1-3 heures Accessibilité débutants 72/100
godotengine/godot#125272 ·
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 2/5 1-3 heures Accessibilité débutants 73/100
Les mainteneurs répondent en général sous 1 jour
-
bug compiler copilot good first issue help wanted
Difficulté 2/5 1-3 heures Accessibilité débutants 82/100
-
bug front-end
Difficulté 2/5 1-3 heures Accessibilité débutants 78/100
Les mainteneurs répondent en général sous 1 jour