@@ -45,6 +45,8 @@ type Pattern =
4545 | TPat_ range of char * char * range
4646 | TPat_ null of range
4747 | TPat_ isinst of TType * TType * PatternValBinding option * range
48+ | TPat_ error of range
49+
4850 member this.Range =
4951 match this with
5052 | TPat_ const(_, m) -> m
@@ -61,6 +63,7 @@ type Pattern =
6163 | TPat_ range(_, _, m) -> m
6264 | TPat_ null m -> m
6365 | TPat_ isinst(_, _, _, m) -> m
66+ | TPat_ error m -> m
6467
6568and PatternValBinding = PBind of Val * TypeScheme
6669
@@ -419,7 +422,11 @@ let getDiscrimOfPattern (g: TcGlobals) tpinst t =
419422 | TPat_ array ( args, ty, _ m) ->
420423 Some( DecisionTreeTest.ArrayLength ( args.Length, ty))
421424 | TPat_ query (( activePatExpr, resTys, apatVrefOpt, idx, apinfo), _, _ m) ->
422- Some( DecisionTreeTest.ActivePatternCase ( activePatExpr, instTypes tpinst resTys, apatVrefOpt, idx, apinfo))
425+ Some ( DecisionTreeTest.ActivePatternCase ( activePatExpr, instTypes tpinst resTys, apatVrefOpt, idx, apinfo))
426+
427+ | TPat_ error range ->
428+ Some ( DecisionTreeTest.Error range)
429+
423430 | _ -> None
424431
425432let constOfDiscrim discrim =
@@ -459,10 +466,10 @@ let rec chooseSimultaneousEdgeSet prevOpt f l =
459466 | [] -> [], []
460467 | h :: t ->
461468 match f prevOpt h with
462- | Some x, _ ->
469+ | Some x ->
463470 let l , r = chooseSimultaneousEdgeSet ( Some x) f t
464471 x :: l, r
465- | None, _ cont ->
472+ | None ->
466473 let l , r = chooseSimultaneousEdgeSet prevOpt f t
467474 l, h :: r
468475
@@ -490,6 +497,11 @@ let discrimsHaveSameSimultaneousClass g d1 d2 =
490497
491498 | _ -> false
492499
500+ let canInvestigate ( pat : Pattern ) =
501+ match pat with
502+ | TPat_ null _ | TPat_ isinst _ | TPat_ exnconstr _ | TPat_ unioncase _
503+ | TPat_ array _ | TPat_ const _ | TPat_ query _ | TPat_ range _ | TPat_ error _ -> true
504+ | _ -> false
493505
494506/// Decide the next pattern to investigate
495507let ChooseInvestigationPointLeftToRight frontiers =
@@ -498,8 +510,7 @@ let ChooseInvestigationPointLeftToRight frontiers =
498510 let rec choose l =
499511 match l with
500512 | [] -> failwith " ChooseInvestigationPointLeftToRight: no non-immediate patterns in first rule"
501- | ( Active(_, _, ( TPat_ null _ | TPat_ isinst _ | TPat_ exnconstr _ | TPat_ unioncase _ | TPat_ array _ | TPat_ const _ | TPat_ query _ | TPat_ range _)) as active)
502- :: _ -> active
513+ | Active (_, _, pat) as active :: _ when canInvestigate pat -> active
503514 | _ :: t -> choose t
504515 choose actives
505516 | [] -> failwith " ChooseInvestigationPointLeftToRight: no frontiers!"
@@ -698,6 +709,7 @@ let rec isPatternPartial p =
698709 | TPat_ range _ -> false
699710 | TPat_ null _ -> false
700711 | TPat_ isinst _ -> false
712+ | TPat_ error _ -> false
701713
702714let rec erasePartialPatterns inpp =
703715 match inpp with
@@ -716,7 +728,8 @@ let rec erasePartialPatterns inpp =
716728 | TPat_ wild _
717729 | TPat_ range _
718730 | TPat_ null _
719- | TPat_ isinst _ -> inpp
731+ | TPat_ isinst _
732+ | TPat_ error _ -> inpp
720733
721734and erasePartials inps =
722735 List.map erasePartialPatterns inps
@@ -736,14 +749,14 @@ let CompilePatternBasic
736749 warnOnIncomplete
737750 actionOnFailure
738751 ( origInputVal , origInputValTypars , _origInputExprOpt : Expr option )
739- ( clausesL : TypedMatchClause list )
752+ ( typedClauses : TypedMatchClause list )
740753 inputTy
741754 resultTy =
742755 // Add the targets to a match builder.
743756 // Note the input expression has already been evaluated and saved into a variable,
744757 // hence no need for a new sequence point.
745758 let matchBuilder = MatchBuilder ( NoSequencePointAtInvisibleBinding, exprm)
746- clausesL |> List.iter ( fun c -> matchBuilder.AddTarget c.Target |> ignore)
759+ typedClauses |> List.iter ( fun c -> matchBuilder.AddTarget c.Target |> ignore)
747760
748761 // Add the incomplete or rethrow match clause on demand,
749762 // printing a warning if necessary (only if it is ever exercised).
@@ -807,8 +820,8 @@ let CompilePatternBasic
807820 | Some c -> c
808821
809822 // Helpers to get the variables bound at a target.
810- // We conceptually add a dummy clause that will always succeed with a "throw"
811- let clausesA = Array.ofList clausesL
823+ // We conceptually add a dummy clause that will always succeed with a "throw".
824+ let clausesA = Array.ofList typedClauses
812825 let nClauses = clausesA.Length
813826 let GetClause i refuted =
814827 if i < nClauses then
@@ -842,14 +855,10 @@ let CompilePatternBasic
842855 | _ ->
843856 // Otherwise choose a point (i.e. a path) to investigate.
844857 let ( Active ( path , subexpr , pat )) = ChooseInvestigationPointLeftToRight frontiers
845- match pat with
846- // All these constructs should have been eliminated in BindProjectionPattern
847- | TPat_ as _ | TPat_ tuple _ | TPat_ wild _ | TPat_ disjs _ | TPat_ conjs _ | TPat_ recd _ ->
858+ if not ( canInvestigate pat) then
859+ // All these constructs should have been eliminated in BindProjectionPattern
848860 failwith " Unexpected pattern"
849-
850- // Leaving the ones where we have real work to do.
851- | _ ->
852-
861+ else
853862 let simulSetOfEdgeDiscrims , fallthroughPathFrontiers = ChooseSimultaneousEdges frontiers path
854863
855864 let inpExprOpt , bindOpt = ChoosePreBinder simulSetOfEdgeDiscrims subexpr
@@ -861,8 +870,7 @@ let CompilePatternBasic
861870
862871 // Work out what the default/fall-through tree looks like, is any
863872 // Check if match is complete, if so optimize the default case away.
864-
865- let defaultTreeOpt : DecisionTree option = CompileFallThroughTree fallthroughPathFrontiers path refuted simulSetOfCases
873+ let defaultTreeOpt = CompileFallThroughTree fallthroughPathFrontiers path refuted simulSetOfCases
866874
867875 // OK, build the whole tree and whack on the binding if any
868876 let finalDecisionTree =
@@ -879,7 +887,7 @@ let CompilePatternBasic
879887 let es2 =
880888 vs2 |> List.map ( fun v ->
881889 match valMap.TryFind v with
882- | None -> error ( Error ( FSComp.SR.patcMissingVariable ( v.DisplayName ), v.Range))
890+ | None -> mkUnit g v.Range
883891 | Some res -> res)
884892 let rhs ' = TDSuccess( es2, i)
885893 match GetWhenGuardOfClause i refuted with
@@ -913,14 +921,14 @@ let CompilePatternBasic
913921 match getDiscrimOfPattern p with
914922 | Some discrim ->
915923 if ( match prevOpt with None -> true | Some ( EdgeDiscrim(_, discrimPrev, _)) -> discrimsHaveSameSimultaneousClass g discrim discrimPrev) then
916- Some ( EdgeDiscrim( i', discrim, p.Range)), true
924+ Some ( EdgeDiscrim( i', discrim, p.Range))
917925 else
918- None, false
926+ None
919927
920928 | None ->
921- None, true
929+ None
922930 else
923- None, true )
931+ None)
924932
925933 and IsCopyableInputExpr origInputExpr =
926934 match origInputExpr with
@@ -1235,8 +1243,17 @@ let CompilePatternBasic
12351243 | _ ->
12361244 [ frontier]
12371245
1246+ | TPat_ error range ->
1247+ match discrim with
1248+ | DecisionTreeTest.Error testRange when range = testRange ->
1249+ [ Frontier ( i, active', valMap)]
1250+ | _ ->
1251+ [ frontier]
1252+
12381253 | _ -> failwith " pattern compilation: GenerateNewFrontiersAfterSuccessfulInvestigation"
1239- else [ frontier]
1254+
1255+ else
1256+ [ frontier]
12401257
12411258 and BindProjectionPattern ( Active ( path , subExpr , p ) as inp ) (( accActive , accValMap ) as s ) =
12421259 let ( SubExpr ( accessf , ve )) = subExpr
@@ -1286,11 +1303,11 @@ let CompilePatternBasic
12861303 and BindProjectionPatterns ps s =
12871304 List.foldBack ( fun p sofar -> List.collect ( BindProjectionPattern p) sofar) ps [ s]
12881305
1289- (* The setup routine of the match compiler *)
1306+ // The setup routine of the match compiler.
12901307 let frontiers =
1291- (( clausesL
1308+ (( typedClauses
12921309 |> List.mapi ( fun i c ->
1293- let initialSubExpr = SubExpr(( fun _tpinst x -> x), ( exprForVal origInputVal.Range origInputVal, origInputVal))
1310+ let initialSubExpr = SubExpr(( fun _ x -> x), ( exprForVal origInputVal.Range origInputVal, origInputVal))
12941311 let investigations = BindProjectionPattern ( Active( PathEmpty inputTy, initialSubExpr, c.Pattern)) ([], ValMap<_>. Empty)
12951312 mkFrontiers investigations i)
12961313 |> List.concat)
@@ -1308,7 +1325,7 @@ let CompilePatternBasic
13081325 if warnOnUnused then
13091326 let used = HashSet<_>( accTargetsOfDecisionTree dtree [], HashIdentity.Structural)
13101327
1311- clausesL |> List.iteri ( fun i c ->
1328+ typedClauses |> List.iteri ( fun i c ->
13121329 if not ( used.Contains i) then warning ( RuleNeverMatched c.Range))
13131330
13141331 dtree, targets
0 commit comments