Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 14 additions & 19 deletions src/Fable.Transforms/Python/Fable2Python.Transforms.fs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand Down
18 changes: 18 additions & 0 deletions tests/Python/TestPatternMatch.fs
Original file line number Diff line number Diff line change
Expand Up @@ -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

[<Fact>]
let ``test union match with field extraction`` () =
unionMatch (Circle 5.0) |> equal "Circle 5"
Expand All @@ -159,6 +171,12 @@ let ``test simple union match with 3 cases`` () =
colorMatch3 Blue |> equal "blue"
colorMatch3 Green |> equal "other"

[<Fact>]
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)
// ----------------------------------------------------------------------------
Expand Down
Loading