diff --git a/docs/release-notes/.FSharp.Compiler.Service/11.0.0.md b/docs/release-notes/.FSharp.Compiler.Service/11.0.0.md index 233d62d27c3..4e08d88ed2e 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/11.0.0.md +++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.0.md @@ -14,6 +14,7 @@ ### Added +* Type checker: recover function type unification in method checking ([#19036](https://github.com/dotnet/fsharp/pull/19036#pullrequestreview-3392846258)) * Add FSharpCodeCompletionOptions ([PR #19030](https://github.com/dotnet/fsharp/pull/19030)) * Type checker: recover on checking binding parameter constraints ([#19046](https://github.com/dotnet/fsharp/pull/19046)) * Debugger: provide breakpoint ranges for short lambdas ([#19067](https://github.com/dotnet/fsharp/pull/19067)) diff --git a/src/Compiler/Checking/Expressions/CheckExpressions.fs b/src/Compiler/Checking/Expressions/CheckExpressions.fs index 527a09cf1d0..28f816077b3 100644 --- a/src/Compiler/Checking/Expressions/CheckExpressions.fs +++ b/src/Compiler/Checking/Expressions/CheckExpressions.fs @@ -689,6 +689,20 @@ let UnifyFunctionType extraInfo (cenv: cenv) denv mFunExpr ty = | Some argm -> error (NotAFunction(denv, ty, mFunExpr, argm)) | None -> error (FunctionExpected(denv, ty, mFunExpr)) +let UnifyFunctionTypeAndRecover extraInfo (cenv: cenv) denv mFunExpr ty = + match UnifyFunctionTypeUndoIfFailed cenv denv mFunExpr ty with + | ValueSome res -> res + | ValueNone -> + match extraInfo with + | Some argm -> errorR (NotAFunction(denv, ty, mFunExpr, argm)) + | None -> errorR (FunctionExpected(denv, ty, mFunExpr)) + + let g = cenv.g + let domainTy = NewInferenceType g + let resultTy = NewInferenceType g + domainTy, resultTy + + let ReportImplicitlyIgnoredBoolExpression denv m ty expr = let checkExpr m expr = match stripDebugPoints expr with @@ -9988,7 +10002,7 @@ and TcMethodApplication_UniqueOverloadInference // type we assume the number of arguments is just "1". | None, _ -> - let domainTy, returnTy = UnifyFunctionType None cenv denv mMethExpr exprTy.Commit + let domainTy, returnTy = UnifyFunctionTypeAndRecover None cenv denv mMethExpr exprTy.Commit let argTys = if isUnitTy g domainTy then [] else tryDestRefTupleTy g domainTy // Only apply this rule if a candidate method exists with this number of arguments let argTys = @@ -10068,7 +10082,7 @@ and TcMethodApplication_CheckArguments let curriedArgTys, returnTy = UnifyMatchingSimpleArgumentTypes cenv env exprTy.Commit calledMeth mMethExpr mItem curriedArgTys, paramNamesIfFeatureEnabled g calledMeth, MustEqual returnTy | _ -> - let domainTy, returnTy = UnifyFunctionType None cenv denv mMethExpr exprTy.Commit + let domainTy, returnTy = UnifyFunctionTypeAndRecover None cenv denv mMethExpr exprTy.Commit let argTys = if isUnitTy g domainTy then [] else tryDestRefTupleTy g domainTy // Only apply this rule if a candidate method exists with this number of arguments let argTys, argNames = diff --git a/tests/FSharp.Compiler.Service.Tests/TypeChecker/TypeCheckerRecoveryTests.fs b/tests/FSharp.Compiler.Service.Tests/TypeChecker/TypeCheckerRecoveryTests.fs index 1f9dd815c80..1b4e4c4c89b 100644 --- a/tests/FSharp.Compiler.Service.Tests/TypeChecker/TypeCheckerRecoveryTests.fs +++ b/tests/FSharp.Compiler.Service.Tests/TypeChecker/TypeCheckerRecoveryTests.fs @@ -62,6 +62,45 @@ Math.Max(a,b,) assertHasSymbolUsages ["Max"] checkResults +module Expressions = + [] + let ``Method type 01`` () = + assertHasSymbolUsageAtCaret "ToString" """ +if true then + "".ToString{caret} +""" + + + [] + let ``Method type 02`` () = + assertHasSymbolUsageAtCaret "M" """ +type T = + static member M() = "" + +if true then + T.M{caret} +""" + + [] + let ``Method type 03`` () = + assertHasSymbolUsageAtCaret "M" """ +type T = + static member M(i: int) = "" + static member M(s: string) = "" + +if true then + T.M{caret} +""" + + [] + let ``Method type 04`` () = + assertHasSymbolUsageAtCaret "GetHashCode" """ +let o: obj = null +if true then + o.GetHashCode{caret} +""" + + module Constraints = [] let ``Type 01`` () =