Skip to content

Commit 1e9d40c

Browse files
authored
Merge pull request dotnet#8667 from dotnet/merges/master-to-release/fsharp5
Merge master to release/fsharp5
2 parents a883c67 + d1a3d07 commit 1e9d40c

25 files changed

+632
-166
lines changed

fcs/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22
<Import Project="..\netfx.props" />
33
<Import Project="..\..\eng\Versions.props"/> <!-- keep our test deps in line with the overall compiler -->
44
<PropertyGroup>
@@ -61,6 +61,9 @@
6161
<Compile Include="$(FSharpSourcesRoot)\..\tests\service\TreeVisitorTests.fs">
6262
<Link>TreeVisitorTests.fs</Link>
6363
</Compile>
64+
<Compile Include="$(FSharpSourcesRoot)\..\tests\service\PatternMatchCompilationTests.fs">
65+
<Link>PatternMatchCompilationTests.fs</Link>
66+
</Compile>
6467
<Compile Include="$(FSharpSourcesRoot)\..\tests\service\ScriptOptionsTests.fs">
6568
<Link>ScriptOptionsTests.fs</Link>
6669
</Compile>

src/fsharp/FindUnsolved.fs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ and accDiscrim cenv env d =
188188
| DecisionTreeTest.ActivePatternCase (exp, tys, _, _, _) ->
189189
accExpr cenv env exp
190190
accTypeInst cenv env tys
191+
| DecisionTreeTest.Error _ -> ()
191192

192193
and accAttrib cenv env (Attrib(_, _k, args, props, _, _, _m)) =
193194
args |> List.iter (fun (AttribExpr(expr1, expr2)) ->

src/fsharp/IlxGen.fs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5083,6 +5083,7 @@ and GenDecisionTreeSwitch cenv cgbuf inplabOpt stackAtTargets eenv e cases defau
50835083
error(InternalError("non-dense integer matches not implemented in codegen - these should have been removed by the pattern match compiler", switchm))
50845084
GenDecisionTreeCases cenv cgbuf stackAtTargets eenv defaultTargetOpt targets repeatSP targetInfos sequel caseLabels cases contf
50855085
| _ -> error(InternalError("these matches should never be needed", switchm))
5086+
| DecisionTreeTest.Error m -> error(InternalError("Trying to compile error recovery branch", m))
50865087

50875088
and GenDecisionTreeCases cenv cgbuf stackAtTargets eenv defaultTargetOpt targets repeatSP targetInfos sequel caseLabels cases (contf: Zmap<_,_> -> FakeUnit) =
50885089

src/fsharp/PatternMatchCompilation.fs

Lines changed: 46 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -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

6568
and 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

425432
let 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
495507
let 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

702714
let 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

721734
and 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

src/fsharp/PatternMatchCompilation.fsi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ type Pattern =
3434
| TPat_range of char * char * range
3535
| TPat_null of range
3636
| TPat_isinst of TType * TType * PatternValBinding option * range
37+
| TPat_error of range
3738

3839
member Range: range
3940

src/fsharp/PostInferenceChecks.fs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1584,6 +1584,7 @@ and CheckDecisionTreeTest cenv env m discrim =
15841584
| DecisionTreeTest.IsNull -> ()
15851585
| DecisionTreeTest.IsInst (srcTy, tgtTy) -> CheckTypeNoInnerByrefs cenv env m srcTy; CheckTypeNoInnerByrefs cenv env m tgtTy
15861586
| DecisionTreeTest.ActivePatternCase (exp, _, _, _, _) -> CheckExprNoByrefs cenv env exp
1587+
| DecisionTreeTest.Error _ -> ()
15871588

15881589
and CheckAttrib cenv env (Attrib(_, _, args, props, _, _, _)) =
15891590
props |> List.iter (fun (AttribNamedArg(_, _, _, expr)) -> CheckAttribExpr cenv env expr)

src/fsharp/QuotationTranslator.fs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -933,6 +933,8 @@ and ConvDecisionTree cenv env tgs typR x =
933933
| DecisionTreeTest.ActivePatternCase _ -> wfail(InternalError( "DecisionTreeTest.ActivePatternCase test in quoted expression", m))
934934

935935
| DecisionTreeTest.ArrayLength _ -> wfail(Error(FSComp.SR.crefQuotationsCantContainArrayPatternMatching(), m))
936+
937+
| DecisionTreeTest.Error m -> wfail(InternalError( "DecisionTreeTest.Error in quoted expression", m))
936938
)
937939
EmitDebugInfoIfNecessary cenv env m converted
938940

src/fsharp/TastOps.fs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3944,6 +3944,7 @@ module DebugPrint =
39443944
| (DecisionTreeTest.IsNull ) -> wordL(tagText "isnull")
39453945
| (DecisionTreeTest.IsInst (_, ty)) -> wordL(tagText "isinst") ^^ typeL ty
39463946
| (DecisionTreeTest.ActivePatternCase (exp, _, _, _, _)) -> wordL(tagText "query") ^^ exprL g exp
3947+
| (DecisionTreeTest.Error _) -> wordL (tagText "error recovery")
39473948

39483949
and targetL g i (TTarget (argvs, body, _)) = leftL(tagText "T") ^^ intL i ^^ tupleL (flatValsL argvs) ^^ rightL(tagText ":") --- exprL g body
39493950

@@ -4421,6 +4422,7 @@ and accFreeInTest (opts: FreeVarOptions) discrim acc =
44214422
accFreeInExpr opts exp
44224423
(accFreeVarsInTys opts tys
44234424
(Option.foldBack (fun (vref, tinst) acc -> accFreeValRef opts vref (accFreeVarsInTys opts tinst acc)) activePatIdentity acc))
4425+
| DecisionTreeTest.Error _ -> acc
44244426

44254427
and accFreeInDecisionTree opts x (acc: FreeVars) =
44264428
match x with
@@ -5227,6 +5229,7 @@ and remapDecisionTree g compgen tmenv x =
52275229
| DecisionTreeTest.IsInst (srcty, tgty) -> DecisionTreeTest.IsInst (remapType tmenv srcty, remapType tmenv tgty)
52285230
| DecisionTreeTest.IsNull -> DecisionTreeTest.IsNull
52295231
| DecisionTreeTest.ActivePatternCase _ -> failwith "DecisionTreeTest.ActivePatternCase should only be used during pattern match compilation"
5232+
| DecisionTreeTest.Error _ -> failwith "DecisionTreeTest.Error should only be used during pattern match compilation"
52305233
TCase(test', remapDecisionTree g compgen tmenv y)) csl,
52315234
Option.map (remapDecisionTree g compgen tmenv) dflt,
52325235
m)

src/fsharp/TastPickle.fs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2397,7 +2397,8 @@ and p_dtree_discrim x st =
23972397
| DecisionTreeTest.IsNull -> p_byte 2 st
23982398
| DecisionTreeTest.IsInst (srcty, tgty) -> p_byte 3 st; p_ty srcty st; p_ty tgty st
23992399
| DecisionTreeTest.ArrayLength (n, ty) -> p_byte 4 st; p_tup2 p_int p_ty (n, ty) st
2400-
| DecisionTreeTest.ActivePatternCase _ -> pfailwith st "DecisionTreeTest.ActivePatternCase: only used during pattern match compilation"
2400+
| DecisionTreeTest.ActivePatternCase _ -> pfailwith st "DecisionTreeTest.ActivePatternCase: only used during pattern match compilation"
2401+
| DecisionTreeTest.Error _ -> pfailwith st "DecisionTreeTest.Error: only used during pattern match compilation"
24012402

24022403
and p_target (TTarget(a, b, _)) st = p_tup2 p_Vals p_expr (a, b) st
24032404
and p_bind (TBind(a, b, _)) st = p_tup2 p_Val p_expr (a, b) st

0 commit comments

Comments
 (0)