From 725e8cbcdfb684df8193796208a9807cddc57f5b Mon Sep 17 00:00:00 2001 From: Edgar Gonzalez Date: Sun, 4 Aug 2024 18:28:18 +0100 Subject: [PATCH 01/10] `function` implicit conversion the same way as `fun x` --- .../Checking/Expressions/CheckExpressions.fs | 2 ++ .../OverloadResolutionUsingFunction.fs | 20 +++++++++++++++++++ .../OverloadingMembers/OverloadingMembers.fs | 6 ++++++ 3 files changed, 28 insertions(+) create mode 100644 tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MemberDefinitions/OverloadingMembers/OverloadResolutionUsingFunction.fs diff --git a/src/Compiler/Checking/Expressions/CheckExpressions.fs b/src/Compiler/Checking/Expressions/CheckExpressions.fs index 2b3d9e7f6c6..38d2b69cb70 100644 --- a/src/Compiler/Checking/Expressions/CheckExpressions.fs +++ b/src/Compiler/Checking/Expressions/CheckExpressions.fs @@ -9685,6 +9685,8 @@ and GetNewInferenceTypeForMethodArg (cenv: cenv) env tpenv x = | SynExpr.Lambda (body = a) | SynExpr.DotLambda (expr = a) -> mkFunTy g (NewInferenceType g) (GetNewInferenceTypeForMethodArg cenv env tpenv a) + | SynExpr.MatchLambda _ -> + mkFunTy g (NewInferenceType g) (NewInferenceType g) | SynExpr.Quote (_, raw, a, _, _) -> if raw then mkRawQuotedExprTy g else mkQuotedExprTy g (GetNewInferenceTypeForMethodArg cenv env tpenv a) diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MemberDefinitions/OverloadingMembers/OverloadResolutionUsingFunction.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MemberDefinitions/OverloadingMembers/OverloadResolutionUsingFunction.fs new file mode 100644 index 00000000000..55853bb86af --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MemberDefinitions/OverloadingMembers/OverloadResolutionUsingFunction.fs @@ -0,0 +1,20 @@ +open System +let ae = new AggregateException() + +ae.Handle(fun e -> + match e with + | :? OperationCanceledException -> true + | _ -> false + ) + +ae.Handle(function + | :? OperationCanceledException -> true + | _ -> false + ) + +ae.Handle( + Func( + function + | :? OperationCanceledException -> true + | _ -> false + )) \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MemberDefinitions/OverloadingMembers/OverloadingMembers.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MemberDefinitions/OverloadingMembers/OverloadingMembers.fs index 1bc2d332247..e0b4c824187 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MemberDefinitions/OverloadingMembers/OverloadingMembers.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MemberDefinitions/OverloadingMembers/OverloadingMembers.fs @@ -229,3 +229,9 @@ module MemberDefinitions_OverloadingMembers = |> withDefines ["TOO_GENERIC"] |> verifyCompileAndRun |> shouldSucceed + + [] + let ``OverloadResolutionUsingFunction_fs`` compilation = + compilation + |> verifyCompileAndRun + |> shouldSucceed From bfcd2d87925d6e95f4911c220c494ed2ed926b2d Mon Sep 17 00:00:00 2001 From: Edgar Gonzalez Date: Sun, 4 Aug 2024 20:51:28 +0100 Subject: [PATCH 02/10] release notes --- docs/release-notes/.FSharp.Compiler.Service/9.0.100.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/release-notes/.FSharp.Compiler.Service/9.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/9.0.100.md index 9b71a9c31b1..405e4a49a36 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/9.0.100.md +++ b/docs/release-notes/.FSharp.Compiler.Service/9.0.100.md @@ -4,6 +4,7 @@ * Fix reporting IsFromComputationExpression only for CE builder type constructors and let bindings. ([PR #17375](https://github.com/dotnet/fsharp/pull/17375)) * Optimize simple mappings in comprehensions when the body of the mapping has `let`-bindings and/or sequential expressions before a single yield. ([PR #17419](https://github.com/dotnet/fsharp/pull/17419)) * C# protected property can be assigned in F# inherit constructor call. ([Issue #13299](https://github.com/dotnet/fsharp/issues/13299), [PR #17391](https://github.com/dotnet/fsharp/pull/17391)) +* Fix `function` implicit conversion. ([Issue #7401](https://github.com/dotnet/fsharp/issues/7401), [PR #17487](https://github.com/dotnet/fsharp/pull/17487)) ### Added From 24b789bdb17b56aa528a8d3b2edfab584b5fc147 Mon Sep 17 00:00:00 2001 From: Edgar Gonzalez Date: Mon, 5 Aug 2024 09:02:58 +0100 Subject: [PATCH 03/10] Update src/Compiler/Checking/Expressions/CheckExpressions.fs Co-authored-by: Brian Rourke Boll --- src/Compiler/Checking/Expressions/CheckExpressions.fs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Compiler/Checking/Expressions/CheckExpressions.fs b/src/Compiler/Checking/Expressions/CheckExpressions.fs index 92c658dd837..528c855cbb8 100644 --- a/src/Compiler/Checking/Expressions/CheckExpressions.fs +++ b/src/Compiler/Checking/Expressions/CheckExpressions.fs @@ -9684,10 +9684,9 @@ and GetNewInferenceTypeForMethodArg (cenv: cenv) env tpenv x = | SynExpr.AddressOf (true, a, _, m) -> mkByrefTyWithInference g (GetNewInferenceTypeForMethodArg cenv env tpenv a) (NewByRefKindInferenceType g m) | SynExpr.Lambda (body = a) - | SynExpr.DotLambda (expr = a) -> + | SynExpr.DotLambda (expr = a) + | SynExpr.MatchLambda (matchClauses = SynMatchClause (resultExpr = a) :: _) -> mkFunTy g (NewInferenceType g) (GetNewInferenceTypeForMethodArg cenv env tpenv a) - | SynExpr.MatchLambda _ -> - mkFunTy g (NewInferenceType g) (NewInferenceType g) | SynExpr.Quote (_, raw, a, _, _) -> if raw then mkRawQuotedExprTy g else mkQuotedExprTy g (GetNewInferenceTypeForMethodArg cenv env tpenv a) From 358d2961c9ab7a0bd2ab54e712a54c8bced61dbc Mon Sep 17 00:00:00 2001 From: Edgar Gonzalez Date: Mon, 5 Aug 2024 16:03:20 +0100 Subject: [PATCH 04/10] More test cases --- .../OverloadResolutionUsingFunction.fs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) 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..05f30ca48ba 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MemberDefinitions/OverloadingMembers/OverloadResolutionUsingFunction.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MemberDefinitions/OverloadingMembers/OverloadResolutionUsingFunction.fs @@ -17,4 +17,12 @@ ae.Handle( function | :? OperationCanceledException -> true | _ -> false - )) \ No newline at end of file + )) + +let m () = + fun x ->(function x -> function y -> function z -> <@ x + y + z @>) + +let f () = + (function + | None -> fun x -> x + 2 + | Some f -> f) \ No newline at end of file From da5d09e8bdfca69376dac88ed196303dba03c699 Mon Sep 17 00:00:00 2001 From: Edgar Gonzalez Date: Mon, 5 Aug 2024 20:37:59 +0100 Subject: [PATCH 05/10] Revert "More test cases" This reverts commit 358d2961c9ab7a0bd2ab54e712a54c8bced61dbc. --- .../OverloadResolutionUsingFunction.fs | 10 +--------- 1 file changed, 1 insertion(+), 9 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 05f30ca48ba..55853bb86af 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MemberDefinitions/OverloadingMembers/OverloadResolutionUsingFunction.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MemberDefinitions/OverloadingMembers/OverloadResolutionUsingFunction.fs @@ -17,12 +17,4 @@ ae.Handle( function | :? OperationCanceledException -> true | _ -> false - )) - -let m () = - fun x ->(function x -> function y -> function z -> <@ x + y + z @>) - -let f () = - (function - | None -> fun x -> x + 2 - | Some f -> f) \ No newline at end of file + )) \ No newline at end of file From 581be73e2da322a7a10f776bdc2418fe03bd5eb6 Mon Sep 17 00:00:00 2001 From: Brian Rourke Boll Date: Tue, 6 Aug 2024 14:20:45 -0400 Subject: [PATCH 06/10] 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 07/10] 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 08/10] 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 09/10] 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 From 81b75fd216cbcc32268b1d8329a5c88840288ada Mon Sep 17 00:00:00 2001 From: Brian Rourke Boll Date: Wed, 7 Aug 2024 09:40:07 -0400 Subject: [PATCH 10/10] Struct tuples --- .../Checking/Expressions/CheckExpressions.fs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Compiler/Checking/Expressions/CheckExpressions.fs b/src/Compiler/Checking/Expressions/CheckExpressions.fs index c7ff5b22c47..23b72e3c608 100644 --- a/src/Compiler/Checking/Expressions/CheckExpressions.fs +++ b/src/Compiler/Checking/Expressions/CheckExpressions.fs @@ -9678,17 +9678,17 @@ and GetNewInferenceTypeForMethodArg (cenv: cenv) x = let g = cenv.g - let rec loopExpr expr cont = + let rec loopExpr expr cont : struct (_ * _) = 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)) + loopExpr a (cont << fun struct (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) + loopExpr a (cont << fun struct (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) + let loopClause a = loopExpr a (cont << fun struct (depth, ty) -> depth + 1, mkFunTy g (NewInferenceType g) ty) // Look at all branches, keeping the one // that gives us the most syntactic information. @@ -9699,10 +9699,10 @@ and GetNewInferenceTypeForMethodArg (cenv: cenv) x = | _ -> acc) | SynExpr.Quote (_, raw, a, _, _) -> if raw then cont (0, mkRawQuotedExprTy g) - else loopExpr a (cont << fun (depth, ty) -> depth + 1, mkQuotedExprTy g ty) + else loopExpr a (cont << fun struct (depth, ty) -> depth + 1, mkQuotedExprTy g ty) | _ -> cont (0, NewInferenceType g) - let _depth, ty = loopExpr x id + let struct (_depth, ty) = loopExpr x id ty and CalledMethHasSingleArgumentGroupOfThisLength n (calledMeth: MethInfo) =