From 1a1de10fecc4578a4b1de14988973f04724a3481 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Thu, 14 Aug 2025 18:26:19 +0200 Subject: [PATCH 1/4] Type checker: use inner expr range in upcast constraints errors --- .../Checking/Expressions/CheckExpressions.fs | 13 ++++++------- .../Type-relatedExpressions.fs | 12 ++++++++++++ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/Compiler/Checking/Expressions/CheckExpressions.fs b/src/Compiler/Checking/Expressions/CheckExpressions.fs index a2c1a2d4e9..c5228adecc 100644 --- a/src/Compiler/Checking/Expressions/CheckExpressions.fs +++ b/src/Compiler/Checking/Expressions/CheckExpressions.fs @@ -3004,20 +3004,19 @@ let TcRuntimeTypeTest isCast isOperator (cenv: cenv) denv m tgtTy srcTy = warning(Error(FSComp.SR.tcTypeTestLossy(NicePrint.minimalStringOfTypeWithNullness denv ety, NicePrint.minimalStringOfType denv (stripTyEqnsWrtErasure EraseAll g ety)), m)) /// Checks, warnings and constraint assertions for upcasts -let TcStaticUpcast (cenv: cenv) denv m tgtTy srcTy = +let TcStaticUpcast (cenv: cenv) denv mSourceExpr mUpcastExpr tgtTy srcTy = let g = cenv.g if isTyparTy g tgtTy then if not (destTyparTy g tgtTy).IsCompatFlex then - error(IndeterminateStaticCoercion(denv, srcTy, tgtTy, m)) - //else warning(UpcastUnnecessary m) + error(IndeterminateStaticCoercion(denv, srcTy, tgtTy, mUpcastExpr)) if isSealedTy g tgtTy && not (isTyparTy g tgtTy) then - warning(CoercionTargetSealed(denv, tgtTy, m)) + warning(CoercionTargetSealed(denv, tgtTy, mUpcastExpr)) if typeEquiv g srcTy tgtTy then - warning(UpcastUnnecessary m) + warning(UpcastUnnecessary mUpcastExpr) - AddCxTypeMustSubsumeType ContextInfo.NoContext denv cenv.css m NoTrace tgtTy srcTy + AddCxTypeMustSubsumeType ContextInfo.NoContext denv cenv.css mSourceExpr NoTrace tgtTy srcTy let BuildPossiblyConditionalMethodCall (cenv: cenv) env isMutable m isProp minfo valUseFlags minst objArgs args staticTyOpt = @@ -6139,7 +6138,7 @@ and TcExprUpcast (cenv: cenv) overallTy env tpenv (synExpr, synInnerExpr, m) = | SynExpr.InferredUpcast _ -> overallTy.Commit, tpenv | _ -> failwith "upcast" - TcStaticUpcast cenv env.DisplayEnv m tgtTy srcTy + TcStaticUpcast cenv env.DisplayEnv synInnerExpr.Range m tgtTy srcTy let expr = mkCoerceExpr(innerExpr, tgtTy, m, srcTy) expr, tpenv diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/ControlFlowExpressions/Type-relatedExpressions/Type-relatedExpressions.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/ControlFlowExpressions/Type-relatedExpressions/Type-relatedExpressions.fs index b0e0d389b2..b833530ced 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/ControlFlowExpressions/Type-relatedExpressions/Type-relatedExpressions.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/ControlFlowExpressions/Type-relatedExpressions/Type-relatedExpressions.fs @@ -74,4 +74,16 @@ module TyperelatedExpressions = (Warning 20, Line 9, Col 1, Line 9, Col 22, "The result of this expression has type 'obj' and is implicitly ignored. Consider using 'ignore' to discard this value explicitly, e.g. 'expr |> ignore', or 'let' to bind the result to a name, e.g. 'let result = expr'.") ] + [] + let ``Upcast 01`` () = + FSharp """ +module Module +type A() = + class end + +not true :> A |> ignore +""" + |> compile + |> shouldFail + |> withDiagnostics [(Error 193, Line 7, Col 1, Line 7, Col 9, "Type constraint mismatch. The type \n 'bool' \nis not compatible with type\n 'A' \n")] From b9c54c07a2a846c6ba9829cdfb43363a0d6913da Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Thu, 14 Aug 2025 18:37:04 +0200 Subject: [PATCH 2/4] Release notes --- docs/release-notes/.FSharp.Compiler.Service/10.0.100.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/release-notes/.FSharp.Compiler.Service/10.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/10.0.100.md index b69621fc79..4f5975f3e8 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/10.0.100.md +++ b/docs/release-notes/.FSharp.Compiler.Service/10.0.100.md @@ -24,6 +24,7 @@ ### Changed * Use `errorR` instead of `error` in `CheckDeclarations.fs` when possible. ([PR #18645](https://github.com/dotnet/fsharp/pull/18645)) +* Type checker: use inner expr range in upcast constraints errors ([PR #18850](https://github.com/dotnet/fsharp/pull/18850)) ### Breaking Changes From ea5eb49744dc9824b987521551a0042213029fcb Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Fri, 15 Aug 2025 13:03:13 +0200 Subject: [PATCH 3/4] Update baselines --- .../ErrorMessages/UpcastDowncastTests.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/UpcastDowncastTests.fs b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/UpcastDowncastTests.fs index a25753fdc7..ea053cc8bf 100644 --- a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/UpcastDowncastTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/UpcastDowncastTests.fs @@ -17,7 +17,7 @@ let c = orig :> Dictionary """ |> typecheck |> shouldFail - |> withSingleDiagnostic (Error 193, Line 5, Col 9, Line 5, Col 36, + |> withSingleDiagnostic (Error 193, Line 5, Col 9, Line 5, Col 13, "Type constraint mismatch. The type \n 'IDictionary' \nis not compatible with type\n 'Dictionary' \n") [] From 0bab041a8827d11ae983a49f51badd7da2ce5f76 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Fri, 15 Aug 2025 15:33:00 +0200 Subject: [PATCH 4/4] Update baselines --- .../E_StaticCoercion_class_not_impl_iface.fsx | 6 +++--- .../E_StaticCoercion_class_not_subclass.fsx | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/fsharpqa/Source/Conformance/Expressions/Type-relatedExpressions/E_StaticCoercion_class_not_impl_iface.fsx b/tests/fsharpqa/Source/Conformance/Expressions/Type-relatedExpressions/E_StaticCoercion_class_not_impl_iface.fsx index 228904421a..d3c8b164b4 100644 --- a/tests/fsharpqa/Source/Conformance/Expressions/Type-relatedExpressions/E_StaticCoercion_class_not_impl_iface.fsx +++ b/tests/fsharpqa/Source/Conformance/Expressions/Type-relatedExpressions/E_StaticCoercion_class_not_impl_iface.fsx @@ -2,11 +2,11 @@ // Negative tests on :> // Cast to an interface not implemented -//Type constraint mismatch\. The type +//Type constraint mismatch\. The type -//Type constraint mismatch\. The type +//Type constraint mismatch\. The type -//Type constraint mismatch\. The type +//Type constraint mismatch\. The type diff --git a/tests/fsharpqa/Source/Conformance/Expressions/Type-relatedExpressions/E_StaticCoercion_class_not_subclass.fsx b/tests/fsharpqa/Source/Conformance/Expressions/Type-relatedExpressions/E_StaticCoercion_class_not_subclass.fsx index 99ed789f34..360093c1b5 100644 --- a/tests/fsharpqa/Source/Conformance/Expressions/Type-relatedExpressions/E_StaticCoercion_class_not_subclass.fsx +++ b/tests/fsharpqa/Source/Conformance/Expressions/Type-relatedExpressions/E_StaticCoercion_class_not_subclass.fsx @@ -2,11 +2,11 @@ // Negative tests on :> // Cast to a class that is not parent -//Type constraint mismatch\. The type +//Type constraint mismatch\. The type -//Type constraint mismatch\. The type +//Type constraint mismatch\. The type -//Type constraint mismatch\. The type +//Type constraint mismatch\. The type