From 581be73e2da322a7a10f776bdc2418fe03bd5eb6 Mon Sep 17 00:00:00 2001 From: Brian Rourke Boll Date: Tue, 6 Aug 2024 14:20:45 -0400 Subject: [PATCH 1/4] Handle all branches of match-lambdas --- .../Checking/Expressions/CheckExpressions.fs | 45 ++++++++++++------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/src/Compiler/Checking/Expressions/CheckExpressions.fs b/src/Compiler/Checking/Expressions/CheckExpressions.fs index 528c855cbb8..abdcb1e0deb 100644 --- a/src/Compiler/Checking/Expressions/CheckExpressions.fs +++ b/src/Compiler/Checking/Expressions/CheckExpressions.fs @@ -9674,23 +9674,34 @@ and TcMethodApplicationThen PropagateThenTcDelayed cenv overallTy env tpenv mWholeExpr (MakeApplicableExprNoFlex cenv expr) exprTy atomicFlag delayed /// Infer initial type information at the callsite from the syntax of an argument, prior to overload resolution. -and GetNewInferenceTypeForMethodArg (cenv: cenv) env tpenv x = +and GetNewInferenceTypeForMethodArg (cenv: cenv) x = let g = cenv.g - match x with - | SynExprParen(a, _, _, _) -> - GetNewInferenceTypeForMethodArg cenv env tpenv a - | SynExpr.AddressOf (true, a, _, m) -> - mkByrefTyWithInference g (GetNewInferenceTypeForMethodArg cenv env tpenv a) (NewByRefKindInferenceType g m) - | SynExpr.Lambda (body = a) - | SynExpr.DotLambda (expr = a) - | SynExpr.MatchLambda (matchClauses = SynMatchClause (resultExpr = a) :: _) -> - mkFunTy g (NewInferenceType g) (GetNewInferenceTypeForMethodArg cenv env tpenv a) - | SynExpr.Quote (_, raw, a, _, _) -> - if raw then mkRawQuotedExprTy g - else mkQuotedExprTy g (GetNewInferenceTypeForMethodArg cenv env tpenv a) - | _ -> NewInferenceType g + let rec loopExpr expr cont = + match expr with + | SynExprParen (a, _, _, _) -> + loopExpr a cont + | SynExpr.AddressOf (true, a, _, m) -> + loopExpr a (cont << fun (depth, ty) -> depth + 1, mkByrefTyWithInference g ty (NewByRefKindInferenceType g m)) + | SynExpr.Lambda (body = a) + | SynExpr.DotLambda (expr = a) -> + loopExpr a (cont << fun (depth, ty) -> depth + 1, mkFunTy g (NewInferenceType g) ty) + | SynExpr.MatchLambda (matchClauses = SynMatchClause (resultExpr = a) :: clauses) -> + let loopClause a = loopExpr a (cont << fun (depth, ty) -> depth + 1, mkFunTy g (NewInferenceType g) ty) + + (loopClause a, clauses) + ||> List.fold (fun ((maxClauseDepth, _) as acc) (SynMatchClause (resultExpr = a)) -> + match loopClause a with + | clauseDepth, ty when clauseDepth > maxClauseDepth -> clauseDepth, ty + | _ -> acc) + | SynExpr.Quote (_, raw, a, _, _) -> + if raw then cont (0, mkRawQuotedExprTy g) + else loopExpr a (cont << fun (depth, ty) -> depth + 1, mkQuotedExprTy g ty) + | _ -> cont (0, NewInferenceType g) + + let _depth, ty = loopExpr x id + ty and CalledMethHasSingleArgumentGroupOfThisLength n (calledMeth: MethInfo) = match calledMeth.NumArgs with @@ -9725,7 +9736,7 @@ and UnifyMatchingSimpleArgumentTypes (cenv: cenv) (env: TcEnv) exprTy (calledMet and TcMethodApplication_SplitSynArguments (cenv: cenv) (env: TcEnv) - tpenv + _tpenv isProp (candidates: MethInfo list) (exprTy: OverallTy) @@ -9753,7 +9764,7 @@ and TcMethodApplication_SplitSynArguments else unnamedCurriedCallerArgs, namedCurriedCallerArgs - let MakeUnnamedCallerArgInfo x = (x, GetNewInferenceTypeForMethodArg cenv env tpenv x, x.Range) + let MakeUnnamedCallerArgInfo x = (x, GetNewInferenceTypeForMethodArg cenv x, x.Range) let singleMethodCurriedArgs = match candidates with @@ -9792,7 +9803,7 @@ and TcMethodApplication_SplitSynArguments | _ -> let unnamedCurriedCallerArgs = unnamedCurriedCallerArgs |> List.mapSquared MakeUnnamedCallerArgInfo let namedCurriedCallerArgs = namedCurriedCallerArgs |> List.mapSquared (fun (isOpt, nm, x) -> - let ty = GetNewInferenceTypeForMethodArg cenv env tpenv x + let ty = GetNewInferenceTypeForMethodArg cenv x // #435263: compiler crash with .net optional parameters and F# optional syntax // named optional arguments should always have option type // STRUCT OPTIONS: if we allow struct options as optional arguments then we should relax this and rely From 589a8294424552c1acb3c4e521661004008bdbad Mon Sep 17 00:00:00 2001 From: Brian Rourke Boll Date: Tue, 6 Aug 2024 14:21:23 -0400 Subject: [PATCH 2/4] Add a couple more match-lambda tests --- .../OverloadResolutionUsingFunction.fs | 29 ++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MemberDefinitions/OverloadingMembers/OverloadResolutionUsingFunction.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MemberDefinitions/OverloadingMembers/OverloadResolutionUsingFunction.fs index 55853bb86af..c343be7adc6 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MemberDefinitions/OverloadingMembers/OverloadResolutionUsingFunction.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MemberDefinitions/OverloadingMembers/OverloadResolutionUsingFunction.fs @@ -4,17 +4,38 @@ let ae = new AggregateException() ae.Handle(fun e -> match e with | :? OperationCanceledException -> true - | _ -> false + | _ -> false ) ae.Handle(function | :? OperationCanceledException -> true - | _ -> false + | _ -> false ) ae.Handle( Func( function | :? OperationCanceledException -> true - | _ -> false - )) \ No newline at end of file + | _ -> false + )) + +module M1 = + type T = + static member M (_ : Func) = () + + T.M (function _ -> function :? ArgumentException -> 3 | _ -> 4) + +module M2 = + type T = + static member M (_ : Func) = () + + T.M (function 0 -> (function _ -> 1) | _ -> (function 0 -> 3 | _ -> 4)) + T.M (function 0 -> id | _ -> (function 0 -> 3 | _ -> 4)) + T.M (function 0 -> (function 0 -> 3 | _ -> 4) | _ -> id) + +module M3 = + type T = + static member M (_ : Func) = () + + T.M (function 0 -> (function 0 -> (function 0 -> 1 | _ -> 0) | _ -> (function 0 -> 2 | _ -> 3)) | _ -> (function 0 -> (function _ -> 3) | _ -> (function 3 -> 4 | _ -> 5))) + T.M (function 0 -> (function 0 -> id | _ -> (function 0 -> 2 | _ -> 3)) | _ -> (function 0 -> (function _ -> 3) | _ -> (function 3 -> 4 | _ -> 5))) From 5ed6fce908845ca147e0a4bc9822f73927665ed4 Mon Sep 17 00:00:00 2001 From: Brian Rourke Boll Date: Tue, 6 Aug 2024 14:31:20 -0400 Subject: [PATCH 3/4] One more --- .../OverloadingMembers/OverloadResolutionUsingFunction.fs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MemberDefinitions/OverloadingMembers/OverloadResolutionUsingFunction.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MemberDefinitions/OverloadingMembers/OverloadResolutionUsingFunction.fs index c343be7adc6..33560ae9389 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MemberDefinitions/OverloadingMembers/OverloadResolutionUsingFunction.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MemberDefinitions/OverloadingMembers/OverloadResolutionUsingFunction.fs @@ -24,6 +24,7 @@ module M1 = static member M (_ : Func) = () T.M (function _ -> function :? ArgumentException -> 3 | _ -> 4) + T.M (function 0 -> (function _ -> 3) | _ -> function :? ArgumentException -> 3 | _ -> 4) module M2 = type T = From f393219328d475fa57520da9bc2eac2792fcad46 Mon Sep 17 00:00:00 2001 From: Brian Rourke Boll Date: Tue, 6 Aug 2024 14:35:04 -0400 Subject: [PATCH 4/4] Add comment --- src/Compiler/Checking/Expressions/CheckExpressions.fs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Compiler/Checking/Expressions/CheckExpressions.fs b/src/Compiler/Checking/Expressions/CheckExpressions.fs index abdcb1e0deb..c7ff5b22c47 100644 --- a/src/Compiler/Checking/Expressions/CheckExpressions.fs +++ b/src/Compiler/Checking/Expressions/CheckExpressions.fs @@ -9690,6 +9690,8 @@ and GetNewInferenceTypeForMethodArg (cenv: cenv) x = | SynExpr.MatchLambda (matchClauses = SynMatchClause (resultExpr = a) :: clauses) -> let loopClause a = loopExpr a (cont << fun (depth, ty) -> depth + 1, mkFunTy g (NewInferenceType g) ty) + // Look at all branches, keeping the one + // that gives us the most syntactic information. (loopClause a, clauses) ||> List.fold (fun ((maxClauseDepth, _) as acc) (SynMatchClause (resultExpr = a)) -> match loopClause a with