diff --git a/src/Fable.Transforms/Python/Fable2Python.Transforms.fs b/src/Fable.Transforms/Python/Fable2Python.Transforms.fs index 668d6800d..88da9750f 100644 --- a/src/Fable.Transforms/Python/Fable2Python.Transforms.fs +++ b/src/Fable.Transforms/Python/Fable2Python.Transforms.fs @@ -1994,19 +1994,23 @@ let private transformSwitchPatternAsMatch else let ctx = { ctx with DecisionTargets = targets } - // Group cases by target index to create or-patterns + // Group cases by target index to create or-patterns. Drop cases routing to the + // default's target since the always-emitted wildcard already covers them (#4649). let groupedCases = convertedCases |> List.groupBy snd - |> List.map (fun (targetIndex, patterns) -> - let patterns = patterns |> List.map fst + |> List.choose (fun (targetIndex, patterns) -> + if targetIndex = defaultIndex then + None + else + let patterns = patterns |> List.map fst - let pattern = - match patterns with - | [ single ] -> single - | multiple -> MatchOr multiple + let pattern = + match patterns with + | [ single ] -> single + | multiple -> MatchOr multiple - (pattern, targetIndex) + Some(pattern, targetIndex) ) // Build match cases @@ -2018,18 +2022,9 @@ let private transformSwitchPatternAsMatch MatchCase.matchCase (pattern, body) ) - // Build default case (wildcard) + // Build default case (wildcard) and always append it last let defaultCase = buildDefaultMatchCase com ctx returnStrategy targets defaultIndex - - // Check if the default case is already covered by the grouped cases - let defaultAlreadyCovered = - groupedCases |> List.exists (fun (_, idx) -> idx = defaultIndex) - - let allCases = - if defaultAlreadyCovered then - matchCases - else - matchCases @ [ defaultCase ] + let allCases = matchCases @ [ defaultCase ] // Transform the evaluation expression let subject, stmts = com.TransformAsExpr(ctx, evalExpr) diff --git a/tests/Python/TestPatternMatch.fs b/tests/Python/TestPatternMatch.fs index dd852c25c..932d0eb98 100644 --- a/tests/Python/TestPatternMatch.fs +++ b/tests/Python/TestPatternMatch.fs @@ -135,6 +135,18 @@ let colorMatch3 c = | Blue -> "blue" | _ -> "other" +type Case = + | BestCase + | MidCase + | WorstCase + +// Or-pattern over union cases where the grouped cases share the same target +// as the default branch. See https://github.com/fable-compiler/Fable/issues/4649 +let atLeastMid c = + match c with + | BestCase | MidCase -> true + | WorstCase -> false + [] let ``test union match with field extraction`` () = unionMatch (Circle 5.0) |> equal "Circle 5" @@ -159,6 +171,12 @@ let ``test simple union match with 3 cases`` () = colorMatch3 Blue |> equal "blue" colorMatch3 Green |> equal "other" +[] +let ``test or-pattern over union cases sharing default target`` () = + atLeastMid BestCase |> equal true + atLeastMid MidCase |> equal true + atLeastMid WorstCase |> equal false + // ---------------------------------------------------------------------------- // 5. Guard Expressions (when clauses) // ----------------------------------------------------------------------------