From f0274f6acd91577a4027a67e4e3990efdb22a937 Mon Sep 17 00:00:00 2001 From: Edgar Gonzalez Date: Wed, 22 Jun 2022 09:48:44 -1100 Subject: [PATCH 01/19] Wrong type is reported in type mismatch error --- src/Compiler/Checking/ConstraintSolver.fs | 27 ++++++++++--------- .../ErrorMessages/TypeMismatchTests.fs | 15 +++++++++++ 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/src/Compiler/Checking/ConstraintSolver.fs b/src/Compiler/Checking/ConstraintSolver.fs index cb70cd5835e..2791edc7e9f 100644 --- a/src/Compiler/Checking/ConstraintSolver.fs +++ b/src/Compiler/Checking/ConstraintSolver.fs @@ -1200,19 +1200,20 @@ and private SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m2 trace cxsln t | LocallyAbortOperationThatLosesAbbrevs -> ErrorD(ConstraintSolverTypesNotInEqualityRelation(csenv.DisplayEnv, ty1, ty2, csenv.m, m2, csenv.eContextInfo)) | err -> ErrorD err) -and SolveTypeEqualsTypeEqns csenv ndeep m2 trace cxsln origl1 origl2 = - match origl1, origl2 with - | [], [] -> CompleteD - | _ -> - // We unwind Iterate2D by hand here for performance reasons. - let rec loop l1 l2 = - match l1, l2 with - | [], [] -> CompleteD - | h1 :: t1, h2 :: t2 -> - SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m2 trace cxsln h1 h2 ++ (fun () -> loop t1 t2) - | _ -> - ErrorD(ConstraintSolverTupleDiffLengths(csenv.DisplayEnv, origl1, origl2, csenv.m, m2)) - loop origl1 origl2 +and SolveTypeEqualsTypeEqns csenv ndeep m2 trace cxsln origl1 origl2 = + match origl1, origl2 with + | [], [] -> CompleteD + | _ -> + // We unwind Iterate2D by hand here for performance reasons. + let rec loop l1 l2 = + match l1, l2 with + | [], [] -> CompleteD + | h1 :: t1, h2 :: t2 when t1.Length = t2.Length -> + SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m2 trace cxsln h1 h2 ++ (fun () -> loop t1 t2) + | _ -> + // It would be better to have an instance of FSharpType contained in the error somehow but until it's not implemented it'd be good to report the correct type. + ErrorD(ConstraintSolverTupleDiffLengths(csenv.DisplayEnv, origl1, origl2, csenv.m, m2)) + loop origl1 origl2 and SolveFunTypeEqn csenv ndeep m2 trace cxsln domainTy1 domainTy2 rangeTy1 rangeTy2 = trackErrors { do! SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m2 trace cxsln domainTy1 domainTy2 diff --git a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeMismatchTests.fs b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeMismatchTests.fs index 24adc58d391..e3b2d991d3c 100644 --- a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeMismatchTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeMismatchTests.fs @@ -7,6 +7,21 @@ open FSharp.Test.Compiler module ``Type Mismatch`` = + [] + let ``type mistmach is reported when tupes have differing lenghts``() = + FSharp """ + let x: int * int * int = 1, "" + let x: int * string * int = "", 1 + let x: int * int = "", "", 1 + """ + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Error 1, Line 2, Col 27, Line 2, Col 32, "Type mismatch. Expecting a\n 'int * int * int' \nbut given a\n ''a * 'b' \nThe tuples have differing lengths of 3 and 2"); + (Error 1, Line 3, Col 30, Line 3, Col 35, "Type mismatch. Expecting a\n 'int * string * int' \nbut given a\n ''a * 'b' \nThe tuples have differing lengths of 3 and 2"); + (Error 1, Line 4, Col 21, Line 4, Col 30, "Type mismatch. Expecting a\n 'int * int' \nbut given a\n ''a * 'b * 'c' \nThe tuples have differing lengths of 2 and 3") + ] + [] let ``return Instead Of return!``() = FSharp """ From 4078e92d64cb4dab8ba949481c7a0c3dd100427f Mon Sep 17 00:00:00 2001 From: Petr Pokorny Date: Thu, 8 Sep 2022 11:43:24 +0200 Subject: [PATCH 02/19] WIP --- src/Compiler/Checking/CheckExpressions.fs | 92 +++++++++++++------ src/Compiler/Checking/CheckPatterns.fs | 1 - src/Compiler/Checking/ConstraintSolver.fs | 6 +- src/Compiler/Checking/ConstraintSolver.fsi | 2 + src/Compiler/Facilities/DiagnosticsLogger.fs | 2 +- .../ErrorMessages/TypeMismatchTests.fs | 8 +- 6 files changed, 76 insertions(+), 35 deletions(-) diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs index 537887747d6..40791449cfb 100644 --- a/src/Compiler/Checking/CheckExpressions.fs +++ b/src/Compiler/Checking/CheckExpressions.fs @@ -582,30 +582,6 @@ let ShrinkContext env oldRange newRange = if not (equals m oldRange) then env else { env with eContextInfo = ContextInfo.ElseBranchResult newRange } -/// Allow the inference of structness from the known type, e.g. -/// let (x: struct (int * int)) = (3,4) -let UnifyTupleTypeAndInferCharacteristics contextInfo (cenv: cenv) denv m knownTy isExplicitStruct ps = - let g = cenv.g - let tupInfo, ptys = - if isAnyTupleTy g knownTy then - let tupInfo, ptys = destAnyTupleTy g knownTy - let tupInfo = (if isExplicitStruct then tupInfoStruct else tupInfo) - let ptys = - if List.length ps = List.length ptys then ptys - else NewInferenceTypes g ps - tupInfo, ptys - else - mkTupInfo isExplicitStruct, NewInferenceTypes g ps - - let contextInfo = - match contextInfo with - | ContextInfo.RecordFields -> ContextInfo.TupleInRecordFields - | _ -> contextInfo - - let ty2 = TType_tuple (tupInfo, ptys) - AddCxTypeEqualsType contextInfo denv cenv.css m knownTy ty2 - tupInfo, ptys - // Allow inference of assembly-affinity and structness from the known type - even from another assembly. This is a rule of // the language design and allows effective cross-assembly use of anonymous types in some limited circumstances. let UnifyAnonRecdTypeAndInferCharacteristics contextInfo (cenv: cenv) denv m ty isExplicitStruct unsortedNames = @@ -5334,7 +5310,7 @@ and TcPropagatingExprLeafThenConvert (cenv: cenv) overallTy actualTy (env: TcEnv UnifyTypes cenv env m overallTy.Commit actualTy f () -/// Process a leaf construct, for cases where we propogate the overall type eagerly in +/// Process a leaf construct, for cases where we propagate the overall type eagerly in /// some cases. Then apply additional type-directed conversions. /// /// However in some cases favour propagating characteristics of the overall type. @@ -5785,14 +5761,78 @@ and TcExprLazy (cenv: cenv) overallTy env tpenv (synInnerExpr, m) = let expr = mkLazyDelayed g m innerTy (mkUnitDelayLambda g m innerExpr) expr, tpenv + +/// Allow the inference of structness from the known type, e.g. +/// let (x: struct (int * int)) = (3,4) +and UnifyTupleTypeAndInferCharacteristics contextInfo (cenv: cenv) denv m knownTy isExplicitStruct ps = + let g = cenv.g + let tupInfo, ptys = + if isAnyTupleTy g knownTy then + let tupInfo, ptys = destAnyTupleTy g knownTy + let tupInfo = (if isExplicitStruct then tupInfoStruct else tupInfo) + let ptys = + if List.length ps = List.length ptys then ptys + else NewInferenceTypes g ps + tupInfo, ptys + else + mkTupInfo isExplicitStruct, NewInferenceTypes g ps + + let contextInfo = + match contextInfo with + | ContextInfo.RecordFields -> ContextInfo.TupleInRecordFields + | _ -> contextInfo + + let ty2 = TType_tuple (tupInfo, ptys) + AddCxTypeEqualsType' contextInfo denv cenv.css m knownTy ty2 |> RaiseOperationResult + tupInfo, ptys + +/// Allow the inference of structness from the known type, e.g. +/// let (x: struct (int * int)) = (3,4) +and UnifyTupleTypeAndInferCharacteristics' env tpenv contextInfo (cenv: cenv) denv m knownTy isExplicitStruct ps = + let g = cenv.g + let tupInfo, ptys = + if isAnyTupleTy g knownTy then + let tupInfo, ptys = destAnyTupleTy g knownTy + let tupInfo = (if isExplicitStruct then tupInfoStruct else tupInfo) + let ptys = + if List.length ps = List.length ptys then ptys + else NewInferenceTypes g ps + tupInfo, ptys + else + mkTupInfo isExplicitStruct, NewInferenceTypes g ps + + let contextInfo = + match contextInfo with + | ContextInfo.RecordFields -> ContextInfo.TupleInRecordFields + | _ -> contextInfo + + // TcExprsWithFlexes + + let ty2 = TType_tuple (tupInfo, ptys) + match AddCxTypeEqualsType' contextInfo denv cenv.css m knownTy ty2 with + | ErrorResult(warnings, ErrorFromAddingTypeEquation(g, displayEnv, actualTy, expectedTy, ex, m)) -> + + let flexes = ptys |> List.map (fun _ -> false) + let argsR, _tpenv = TcExprsWithFlexes cenv env m tpenv flexes ptys ps + let fixedExpectedTy = + match mkAnyTupled g m tupInfo argsR ptys with + | TypedTree.Expr.Op (TOp.Tuple _, typeArgs, _, _) -> TType_tuple (mkTupInfo false, typeArgs) + | _ -> expectedTy + + ErrorResult(warnings, ErrorFromAddingTypeEquation(g, displayEnv, actualTy, fixedExpectedTy, ex, m)) + | x -> x + |> RaiseOperationResult + tupInfo, ptys + and TcExprTuple (cenv: cenv) overallTy env tpenv (isExplicitStruct, args, m) = let g = cenv.g TcPossiblyPropogatingExprLeafThenConvert (fun ty -> isAnyTupleTy g ty || isTyparTy g ty) cenv overallTy env m (fun overallTy -> - let tupInfo, argTys = UnifyTupleTypeAndInferCharacteristics env.eContextInfo cenv env.DisplayEnv m overallTy isExplicitStruct args + let tupInfo, argTys = UnifyTupleTypeAndInferCharacteristics' env tpenv env.eContextInfo cenv env.DisplayEnv m overallTy isExplicitStruct args let flexes = argTys |> List.map (fun _ -> false) let argsR, tpenv = TcExprsWithFlexes cenv env m tpenv flexes argTys args let expr = mkAnyTupled g m tupInfo argsR argTys + expr, tpenv ) diff --git a/src/Compiler/Checking/CheckPatterns.fs b/src/Compiler/Checking/CheckPatterns.fs index dccff65781b..ee6227aa99a 100644 --- a/src/Compiler/Checking/CheckPatterns.fs +++ b/src/Compiler/Checking/CheckPatterns.fs @@ -759,4 +759,3 @@ and TcPatLongIdentLiteral warnOnUpper (cenv: cenv) env vFlags patEnv ty (mLongId and TcPatterns warnOnUpper cenv env vFlags s argTys args = assert (List.length args = List.length argTys) List.mapFold (fun s (ty, pat) -> TcPat warnOnUpper cenv env None vFlags s ty pat) s (List.zip argTys args) - diff --git a/src/Compiler/Checking/ConstraintSolver.fs b/src/Compiler/Checking/ConstraintSolver.fs index 7c5f62298e3..359bb5e3c4d 100644 --- a/src/Compiler/Checking/ConstraintSolver.fs +++ b/src/Compiler/Checking/ConstraintSolver.fs @@ -1228,7 +1228,6 @@ and SolveTypeEqualsTypeEqns csenv ndeep m2 trace cxsln origl1 origl2 = | h1 :: t1, h2 :: t2 when t1.Length = t2.Length -> SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m2 trace cxsln h1 h2 ++ (fun () -> loop t1 t2) | _ -> - // It would be better to have an instance of FSharpType contained in the error somehow but until it's not implemented it'd be good to report the correct type. ErrorD(ConstraintSolverTupleDiffLengths(csenv.DisplayEnv, origl1, origl2, csenv.m, m2)) loop origl1 origl2 @@ -3454,12 +3453,13 @@ let EliminateConstraintsForGeneralizedTypars (denv: DisplayEnv) css m (trace: Op // No error recovery here: we do that on a per-expression basis. //------------------------------------------------------------------------- -let AddCxTypeEqualsType contextInfo denv css m actual expected = +let AddCxTypeEqualsType' contextInfo denv css m actual expected = let csenv = MakeConstraintSolverEnv contextInfo css m denv PostponeOnFailedMemberConstraintResolution csenv NoTrace (fun csenv -> SolveTypeEqualsTypeWithReport csenv 0 m NoTrace None actual expected) ErrorD - |> RaiseOperationResult + +let AddCxTypeEqualsType contextInfo denv css m actual expected = AddCxTypeEqualsType' contextInfo denv css m actual expected |> RaiseOperationResult let UndoIfFailed f = let trace = Trace.New() diff --git a/src/Compiler/Checking/ConstraintSolver.fsi b/src/Compiler/Checking/ConstraintSolver.fsi index c45db538fc2..af001015f2f 100644 --- a/src/Compiler/Checking/ConstraintSolver.fsi +++ b/src/Compiler/Checking/ConstraintSolver.fsi @@ -266,6 +266,8 @@ val EliminateConstraintsForGeneralizedTypars: val CheckDeclaredTypars: DisplayEnv -> ConstraintSolverState -> range -> Typars -> Typars -> unit +val AddCxTypeEqualsType': ContextInfo -> DisplayEnv -> ConstraintSolverState -> range -> TType -> TType -> OperationResult + val AddCxTypeEqualsType: ContextInfo -> DisplayEnv -> ConstraintSolverState -> range -> TType -> TType -> unit val AddCxTypeEqualsTypeUndoIfFailed: DisplayEnv -> ConstraintSolverState -> range -> TType -> TType -> bool diff --git a/src/Compiler/Facilities/DiagnosticsLogger.fs b/src/Compiler/Facilities/DiagnosticsLogger.fs index aebfd1cfd6e..23f17956e28 100644 --- a/src/Compiler/Facilities/DiagnosticsLogger.fs +++ b/src/Compiler/Facilities/DiagnosticsLogger.fs @@ -595,7 +595,7 @@ let conditionallySuppressErrorReporting cond f = //------------------------------------------------------------------------ // Errors as data: Sometimes we have to reify errors as data, e.g. if backtracking -/// The result type of a computational modality to colelct warnings and possibly fail +/// The result type of a computational modality to collect warnings and possibly fail [] type OperationResult<'T> = | OkResult of warnings: exn list * result: 'T diff --git a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeMismatchTests.fs b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeMismatchTests.fs index e3b2d991d3c..e2d12a32c27 100644 --- a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeMismatchTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeMismatchTests.fs @@ -8,7 +8,7 @@ open FSharp.Test.Compiler module ``Type Mismatch`` = [] - let ``type mistmach is reported when tupes have differing lenghts``() = + let ``type mismatch is reported when tuples have differing lengths``() = FSharp """ let x: int * int * int = 1, "" let x: int * string * int = "", 1 @@ -17,9 +17,9 @@ module ``Type Mismatch`` = |> typecheck |> shouldFail |> withDiagnostics [ - (Error 1, Line 2, Col 27, Line 2, Col 32, "Type mismatch. Expecting a\n 'int * int * int' \nbut given a\n ''a * 'b' \nThe tuples have differing lengths of 3 and 2"); - (Error 1, Line 3, Col 30, Line 3, Col 35, "Type mismatch. Expecting a\n 'int * string * int' \nbut given a\n ''a * 'b' \nThe tuples have differing lengths of 3 and 2"); - (Error 1, Line 4, Col 21, Line 4, Col 30, "Type mismatch. Expecting a\n 'int * int' \nbut given a\n ''a * 'b * 'c' \nThe tuples have differing lengths of 2 and 3") + (Error 1, Line 2, Col 27, Line 2, Col 32, "Type mismatch. Expecting a\n 'int * int * int' \nbut given a\n 'int * string' \nThe tuples have differing lengths of 3 and 2"); + (Error 1, Line 3, Col 30, Line 3, Col 35, "Type mismatch. Expecting a\n 'int * string * int' \nbut given a\n 'string * int' \nThe tuples have differing lengths of 3 and 2"); + (Error 1, Line 4, Col 21, Line 4, Col 30, "Type mismatch. Expecting a\n 'int * int' \nbut given a\n 'string * string * int' \nThe tuples have differing lengths of 2 and 3") ] [] From 0882f49837312b1abf6e7a0975fefc3918e38d0f Mon Sep 17 00:00:00 2001 From: 0101 <0101@innit.cz> Date: Thu, 8 Sep 2022 14:46:28 +0200 Subject: [PATCH 03/19] still WIP --- src/Compiler/Checking/CheckExpressions.fs | 58 ++++++------------- src/Compiler/Checking/CheckExpressions.fsi | 1 + src/Compiler/Checking/CheckPatterns.fs | 2 +- .../LetBindings/Basic/Basic.fs | 2 +- 4 files changed, 21 insertions(+), 42 deletions(-) diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs index 40791449cfb..2ffdd6ef21d 100644 --- a/src/Compiler/Checking/CheckExpressions.fs +++ b/src/Compiler/Checking/CheckExpressions.fs @@ -5761,10 +5761,9 @@ and TcExprLazy (cenv: cenv) overallTy env tpenv (synInnerExpr, m) = let expr = mkLazyDelayed g m innerTy (mkUnitDelayLambda g m innerExpr) expr, tpenv - /// Allow the inference of structness from the known type, e.g. /// let (x: struct (int * int)) = (3,4) -and UnifyTupleTypeAndInferCharacteristics contextInfo (cenv: cenv) denv m knownTy isExplicitStruct ps = +and UnifyTupleTypeAndInferCharacteristics contextInfo (cenv: cenv) denv m knownTy isExplicitStruct tcForErrorMessage ps = let g = cenv.g let tupInfo, ptys = if isAnyTupleTy g knownTy then @@ -5783,57 +5782,36 @@ and UnifyTupleTypeAndInferCharacteristics contextInfo (cenv: cenv) denv m knownT | _ -> contextInfo let ty2 = TType_tuple (tupInfo, ptys) - AddCxTypeEqualsType' contextInfo denv cenv.css m knownTy ty2 |> RaiseOperationResult - tupInfo, ptys - -/// Allow the inference of structness from the known type, e.g. -/// let (x: struct (int * int)) = (3,4) -and UnifyTupleTypeAndInferCharacteristics' env tpenv contextInfo (cenv: cenv) denv m knownTy isExplicitStruct ps = - let g = cenv.g - let tupInfo, ptys = - if isAnyTupleTy g knownTy then - let tupInfo, ptys = destAnyTupleTy g knownTy - let tupInfo = (if isExplicitStruct then tupInfoStruct else tupInfo) - let ptys = - if List.length ps = List.length ptys then ptys - else NewInferenceTypes g ps - tupInfo, ptys - else - mkTupInfo isExplicitStruct, NewInferenceTypes g ps - - let contextInfo = - match contextInfo with - | ContextInfo.RecordFields -> ContextInfo.TupleInRecordFields - | _ -> contextInfo - - // TcExprsWithFlexes - let ty2 = TType_tuple (tupInfo, ptys) - match AddCxTypeEqualsType' contextInfo denv cenv.css m knownTy ty2 with - | ErrorResult(warnings, ErrorFromAddingTypeEquation(g, displayEnv, actualTy, expectedTy, ex, m)) -> - - let flexes = ptys |> List.map (fun _ -> false) - let argsR, _tpenv = TcExprsWithFlexes cenv env m tpenv flexes ptys ps + let cxOperationResult = AddCxTypeEqualsType' contextInfo denv cenv.css m knownTy ty2 + match cxOperationResult, tcForErrorMessage with + // Try to type check the tuple values when there's an incorrect number of them + | ErrorResult(warnings, ErrorFromAddingTypeEquation(g, displayEnv, actualTy, expectedTy, (ConstraintSolverTupleDiffLengths _ as ex), m)), Some tcForErrorMessage -> + let fixedExpectedTy = - match mkAnyTupled g m tupInfo argsR ptys with - | TypedTree.Expr.Op (TOp.Tuple _, typeArgs, _, _) -> TType_tuple (mkTupInfo false, typeArgs) + match tcForErrorMessage (tupInfo, ptys) with + | Expr.Op (TOp.Tuple _, typeArgs, _, _) -> TType_tuple (mkTupInfo false, typeArgs) | _ -> expectedTy - + ErrorResult(warnings, ErrorFromAddingTypeEquation(g, displayEnv, actualTy, fixedExpectedTy, ex, m)) - | x -> x + | operationResult, _ -> operationResult |> RaiseOperationResult + tupInfo, ptys and TcExprTuple (cenv: cenv) overallTy env tpenv (isExplicitStruct, args, m) = let g = cenv.g - TcPossiblyPropogatingExprLeafThenConvert (fun ty -> isAnyTupleTy g ty || isTyparTy g ty) cenv overallTy env m (fun overallTy -> - let tupInfo, argTys = UnifyTupleTypeAndInferCharacteristics' env tpenv env.eContextInfo cenv env.DisplayEnv m overallTy isExplicitStruct args - + + let tcTuple (tupInfo, argTys) = let flexes = argTys |> List.map (fun _ -> false) let argsR, tpenv = TcExprsWithFlexes cenv env m tpenv flexes argTys args let expr = mkAnyTupled g m tupInfo argsR argTys - + expr, tpenv + + TcPossiblyPropogatingExprLeafThenConvert (fun ty -> isAnyTupleTy g ty || isTyparTy g ty) cenv overallTy env m (fun overallTy -> + UnifyTupleTypeAndInferCharacteristics env.eContextInfo cenv env.DisplayEnv m overallTy isExplicitStruct (Some (tcTuple >> fst)) args + |> tcTuple ) and TcExprArrayOrList (cenv: cenv) overallTy env tpenv (isArray, args, m) = diff --git a/src/Compiler/Checking/CheckExpressions.fsi b/src/Compiler/Checking/CheckExpressions.fsi index 0bbaca89177..08545d04696 100644 --- a/src/Compiler/Checking/CheckExpressions.fsi +++ b/src/Compiler/Checking/CheckExpressions.fsi @@ -871,6 +871,7 @@ val UnifyTupleTypeAndInferCharacteristics: m: range -> knownTy: TType -> isExplicitStruct: bool -> + tcForErrorMessage: (TupInfo * TTypes -> Expr) option -> 'T list -> TupInfo * TTypes diff --git a/src/Compiler/Checking/CheckPatterns.fs b/src/Compiler/Checking/CheckPatterns.fs index ee6227aa99a..6fb2a05bfbf 100644 --- a/src/Compiler/Checking/CheckPatterns.fs +++ b/src/Compiler/Checking/CheckPatterns.fs @@ -418,7 +418,7 @@ and TcPatAnds warnOnUpper cenv env vFlags patEnv ty pats m = and TcPatTuple warnOnUpper cenv env vFlags patEnv ty isExplicitStruct args m = let g = cenv.g try - let tupInfo, argTys = UnifyTupleTypeAndInferCharacteristics env.eContextInfo cenv env.DisplayEnv m ty isExplicitStruct args + let tupInfo, argTys = UnifyTupleTypeAndInferCharacteristics env.eContextInfo cenv env.DisplayEnv m ty isExplicitStruct None args let argsR, acc = TcPatterns warnOnUpper cenv env vFlags patEnv argTys args let phase2 values = TPat_tuple(tupInfo, List.map (fun f -> f values) argsR, argTys, m) phase2, acc diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/DeclarationElements/LetBindings/Basic/Basic.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/DeclarationElements/LetBindings/Basic/Basic.fs index fc9e36d748e..d16093d1c41 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/DeclarationElements/LetBindings/Basic/Basic.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/DeclarationElements/LetBindings/Basic/Basic.fs @@ -42,7 +42,7 @@ module Basic = |> verifyCompile |> shouldFail |> withDiagnostics [ - (Error 1, Line 5, Col 16, Line 5, Col 23, "Type mismatch. Expecting a\n ''a * 'b' \nbut given a\n ''a * 'b * 'c' \nThe tuples have differing lengths of 2 and 3") + (Error 1, Line 5, Col 16, Line 5, Col 23, "Type mismatch. Expecting a\n ''a * 'b' \nbut given a\n 'int * int * int' \nThe tuples have differing lengths of 2 and 3") ] // SOURCE=E_AttributesOnLet01.fs SCFLAGS="--test:ErrorRanges" # E_AttributesOnLet01.fs From 0d1ca761b75234f3ff76afa80fce9403d69d7bf7 Mon Sep 17 00:00:00 2001 From: Petr Pokorny Date: Fri, 9 Sep 2022 17:58:00 +0200 Subject: [PATCH 04/19] Simpler solution --- src/Compiler/Checking/CheckExpressions.fs | 78 +++++++------------ src/Compiler/Checking/CheckExpressions.fsi | 1 - src/Compiler/Checking/CheckPatterns.fs | 3 +- src/Compiler/Checking/ConstraintSolver.fs | 32 ++++---- src/Compiler/Checking/ConstraintSolver.fsi | 2 - src/Compiler/Driver/CompilerDiagnostics.fs | 16 ++++ .../ErrorMessages/TypeMismatchTests.fs | 59 ++++++++++---- 7 files changed, 109 insertions(+), 82 deletions(-) diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs index 2ffdd6ef21d..4410cc0e3f7 100644 --- a/src/Compiler/Checking/CheckExpressions.fs +++ b/src/Compiler/Checking/CheckExpressions.fs @@ -582,6 +582,30 @@ let ShrinkContext env oldRange newRange = if not (equals m oldRange) then env else { env with eContextInfo = ContextInfo.ElseBranchResult newRange } +/// Allow the inference of structness from the known type, e.g. +/// let (x: struct (int * int)) = (3,4) +let UnifyTupleTypeAndInferCharacteristics contextInfo (cenv: cenv) denv m knownTy isExplicitStruct ps = + let g = cenv.g + let tupInfo, ptys = + if isAnyTupleTy g knownTy then + let tupInfo, ptys = destAnyTupleTy g knownTy + let tupInfo = (if isExplicitStruct then tupInfoStruct else tupInfo) + let ptys = + if List.length ps = List.length ptys then ptys + else NewInferenceTypes g ps + tupInfo, ptys + else + mkTupInfo isExplicitStruct, NewInferenceTypes g ps + + let contextInfo = + match contextInfo with + | ContextInfo.RecordFields -> ContextInfo.TupleInRecordFields + | _ -> contextInfo + + let ty2 = TType_tuple (tupInfo, ptys) + AddCxTypeEqualsType contextInfo denv cenv.css m knownTy ty2 + tupInfo, ptys + // Allow inference of assembly-affinity and structness from the known type - even from another assembly. This is a rule of // the language design and allows effective cross-assembly use of anonymous types in some limited circumstances. let UnifyAnonRecdTypeAndInferCharacteristics contextInfo (cenv: cenv) denv m ty isExplicitStruct unsortedNames = @@ -5322,7 +5346,7 @@ and TcPropagatingExprLeafThenConvert (cenv: cenv) overallTy actualTy (env: TcEnv /// - tuple (except if overallTy is a tuple type or a variable type that can become one) /// - anon record (except if overallTy is an anon record type or a variable type that can become one) /// - record (except if overallTy is requiresCtor || haveCtor or a record type or a variable type that can become one)) -and TcPossiblyPropogatingExprLeafThenConvert isPropagating (cenv: cenv) (overallTy: OverallTy) (env: TcEnv) m processExpr = +and TcPossiblyPropagatingExprLeafThenConvert isPropagating (cenv: cenv) (overallTy: OverallTy) (env: TcEnv) m processExpr = let g = cenv.g @@ -5500,7 +5524,7 @@ and TcExprUndelayed (cenv: cenv) (overallTy: OverallTy) env tpenv (synExpr: SynE | SynExpr.AnonRecd (isStruct, withExprOpt, unsortedFieldExprs, mWholeExpr) -> TcNonControlFlowExpr env <| fun env -> - TcPossiblyPropogatingExprLeafThenConvert (fun ty -> isAnonRecdTy g ty || isTyparTy g ty) cenv overallTy env mWholeExpr (fun overallTy -> + TcPossiblyPropagatingExprLeafThenConvert (fun ty -> isAnonRecdTy g ty || isTyparTy g ty) cenv overallTy env mWholeExpr (fun overallTy -> TcAnonRecdExpr cenv overallTy env tpenv (isStruct, withExprOpt, unsortedFieldExprs, mWholeExpr) ) @@ -5761,57 +5785,15 @@ and TcExprLazy (cenv: cenv) overallTy env tpenv (synInnerExpr, m) = let expr = mkLazyDelayed g m innerTy (mkUnitDelayLambda g m innerExpr) expr, tpenv -/// Allow the inference of structness from the known type, e.g. -/// let (x: struct (int * int)) = (3,4) -and UnifyTupleTypeAndInferCharacteristics contextInfo (cenv: cenv) denv m knownTy isExplicitStruct tcForErrorMessage ps = - let g = cenv.g - let tupInfo, ptys = - if isAnyTupleTy g knownTy then - let tupInfo, ptys = destAnyTupleTy g knownTy - let tupInfo = (if isExplicitStruct then tupInfoStruct else tupInfo) - let ptys = - if List.length ps = List.length ptys then ptys - else NewInferenceTypes g ps - tupInfo, ptys - else - mkTupInfo isExplicitStruct, NewInferenceTypes g ps - - let contextInfo = - match contextInfo with - | ContextInfo.RecordFields -> ContextInfo.TupleInRecordFields - | _ -> contextInfo - - let ty2 = TType_tuple (tupInfo, ptys) - - let cxOperationResult = AddCxTypeEqualsType' contextInfo denv cenv.css m knownTy ty2 - match cxOperationResult, tcForErrorMessage with - // Try to type check the tuple values when there's an incorrect number of them - | ErrorResult(warnings, ErrorFromAddingTypeEquation(g, displayEnv, actualTy, expectedTy, (ConstraintSolverTupleDiffLengths _ as ex), m)), Some tcForErrorMessage -> - - let fixedExpectedTy = - match tcForErrorMessage (tupInfo, ptys) with - | Expr.Op (TOp.Tuple _, typeArgs, _, _) -> TType_tuple (mkTupInfo false, typeArgs) - | _ -> expectedTy - - ErrorResult(warnings, ErrorFromAddingTypeEquation(g, displayEnv, actualTy, fixedExpectedTy, ex, m)) - | operationResult, _ -> operationResult - |> RaiseOperationResult - - tupInfo, ptys - and TcExprTuple (cenv: cenv) overallTy env tpenv (isExplicitStruct, args, m) = let g = cenv.g - - let tcTuple (tupInfo, argTys) = + TcPossiblyPropagatingExprLeafThenConvert (fun ty -> isAnyTupleTy g ty || isTyparTy g ty) cenv overallTy env m (fun overallTy -> + let tupInfo, argTys = UnifyTupleTypeAndInferCharacteristics env.eContextInfo cenv env.DisplayEnv m overallTy isExplicitStruct args + let flexes = argTys |> List.map (fun _ -> false) let argsR, tpenv = TcExprsWithFlexes cenv env m tpenv flexes argTys args let expr = mkAnyTupled g m tupInfo argsR argTys - expr, tpenv - - TcPossiblyPropogatingExprLeafThenConvert (fun ty -> isAnyTupleTy g ty || isTyparTy g ty) cenv overallTy env m (fun overallTy -> - UnifyTupleTypeAndInferCharacteristics env.eContextInfo cenv env.DisplayEnv m overallTy isExplicitStruct (Some (tcTuple >> fst)) args - |> tcTuple ) and TcExprArrayOrList (cenv: cenv) overallTy env tpenv (isArray, args, m) = @@ -5886,7 +5868,7 @@ and TcExprRecord (cenv: cenv) overallTy env tpenv (inherits, withExprOpt, synRec CallExprHasTypeSink cenv.tcSink (mWholeExpr, env.NameEnv, overallTy.Commit, env.AccessRights) let requiresCtor = (GetCtorShapeCounter env = 1) // Get special expression forms for constructors let haveCtor = Option.isSome inherits - TcPossiblyPropogatingExprLeafThenConvert (fun ty -> requiresCtor || haveCtor || isRecdTy g ty || isTyparTy g ty) cenv overallTy env mWholeExpr (fun overallTy -> + TcPossiblyPropagatingExprLeafThenConvert (fun ty -> requiresCtor || haveCtor || isRecdTy g ty || isTyparTy g ty) cenv overallTy env mWholeExpr (fun overallTy -> TcRecdExpr cenv overallTy env tpenv (inherits, withExprOpt, synRecdFields, mWholeExpr) ) diff --git a/src/Compiler/Checking/CheckExpressions.fsi b/src/Compiler/Checking/CheckExpressions.fsi index 08545d04696..0bbaca89177 100644 --- a/src/Compiler/Checking/CheckExpressions.fsi +++ b/src/Compiler/Checking/CheckExpressions.fsi @@ -871,7 +871,6 @@ val UnifyTupleTypeAndInferCharacteristics: m: range -> knownTy: TType -> isExplicitStruct: bool -> - tcForErrorMessage: (TupInfo * TTypes -> Expr) option -> 'T list -> TupInfo * TTypes diff --git a/src/Compiler/Checking/CheckPatterns.fs b/src/Compiler/Checking/CheckPatterns.fs index 6fb2a05bfbf..dccff65781b 100644 --- a/src/Compiler/Checking/CheckPatterns.fs +++ b/src/Compiler/Checking/CheckPatterns.fs @@ -418,7 +418,7 @@ and TcPatAnds warnOnUpper cenv env vFlags patEnv ty pats m = and TcPatTuple warnOnUpper cenv env vFlags patEnv ty isExplicitStruct args m = let g = cenv.g try - let tupInfo, argTys = UnifyTupleTypeAndInferCharacteristics env.eContextInfo cenv env.DisplayEnv m ty isExplicitStruct None args + let tupInfo, argTys = UnifyTupleTypeAndInferCharacteristics env.eContextInfo cenv env.DisplayEnv m ty isExplicitStruct args let argsR, acc = TcPatterns warnOnUpper cenv env vFlags patEnv argTys args let phase2 values = TPat_tuple(tupInfo, List.map (fun f -> f values) argsR, argTys, m) phase2, acc @@ -759,3 +759,4 @@ and TcPatLongIdentLiteral warnOnUpper (cenv: cenv) env vFlags patEnv ty (mLongId and TcPatterns warnOnUpper cenv env vFlags s argTys args = assert (List.length args = List.length argTys) List.mapFold (fun s (ty, pat) -> TcPat warnOnUpper cenv env None vFlags s ty pat) s (List.zip argTys args) + diff --git a/src/Compiler/Checking/ConstraintSolver.fs b/src/Compiler/Checking/ConstraintSolver.fs index 359bb5e3c4d..fc00af6da5a 100644 --- a/src/Compiler/Checking/ConstraintSolver.fs +++ b/src/Compiler/Checking/ConstraintSolver.fs @@ -1217,19 +1217,20 @@ and private SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m2 trace cxsln t | LocallyAbortOperationThatLosesAbbrevs -> ErrorD(ConstraintSolverTypesNotInEqualityRelation(csenv.DisplayEnv, ty1, ty2, csenv.m, m2, csenv.eContextInfo)) | err -> ErrorD err) -and SolveTypeEqualsTypeEqns csenv ndeep m2 trace cxsln origl1 origl2 = - match origl1, origl2 with - | [], [] -> CompleteD - | _ -> - // We unwind Iterate2D by hand here for performance reasons. - let rec loop l1 l2 = - match l1, l2 with - | [], [] -> CompleteD - | h1 :: t1, h2 :: t2 when t1.Length = t2.Length -> - SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m2 trace cxsln h1 h2 ++ (fun () -> loop t1 t2) - | _ -> - ErrorD(ConstraintSolverTupleDiffLengths(csenv.DisplayEnv, origl1, origl2, csenv.m, m2)) - loop origl1 origl2 +and SolveTypeEqualsTypeEqns csenv ndeep m2 trace cxsln origl1 origl2 = + match origl1, origl2 with + | [], [] -> CompleteD + | _ -> + // We unwind Iterate2D by hand here for performance reasons. + let rec loop l1 l2 = + match l1, l2 with + | [], [] -> CompleteD + | h1 :: t1, h2 :: t2 when t1.Length = t2.Length -> + SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m2 trace cxsln h1 h2 ++ (fun () -> loop t1 t2) + | _ -> + // TODO: we should probably keep the ContextInfo here + ErrorD(ConstraintSolverTupleDiffLengths(csenv.DisplayEnv, origl1, origl2, csenv.m, m2)) + loop origl1 origl2 and SolveFunTypeEqn csenv ndeep m2 trace cxsln domainTy1 domainTy2 rangeTy1 rangeTy2 = trackErrors { do! SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m2 trace cxsln domainTy1 domainTy2 @@ -3453,13 +3454,12 @@ let EliminateConstraintsForGeneralizedTypars (denv: DisplayEnv) css m (trace: Op // No error recovery here: we do that on a per-expression basis. //------------------------------------------------------------------------- -let AddCxTypeEqualsType' contextInfo denv css m actual expected = +let AddCxTypeEqualsType contextInfo denv css m actual expected = let csenv = MakeConstraintSolverEnv contextInfo css m denv PostponeOnFailedMemberConstraintResolution csenv NoTrace (fun csenv -> SolveTypeEqualsTypeWithReport csenv 0 m NoTrace None actual expected) ErrorD - -let AddCxTypeEqualsType contextInfo denv css m actual expected = AddCxTypeEqualsType' contextInfo denv css m actual expected |> RaiseOperationResult + |> RaiseOperationResult let UndoIfFailed f = let trace = Trace.New() diff --git a/src/Compiler/Checking/ConstraintSolver.fsi b/src/Compiler/Checking/ConstraintSolver.fsi index af001015f2f..c45db538fc2 100644 --- a/src/Compiler/Checking/ConstraintSolver.fsi +++ b/src/Compiler/Checking/ConstraintSolver.fsi @@ -266,8 +266,6 @@ val EliminateConstraintsForGeneralizedTypars: val CheckDeclaredTypars: DisplayEnv -> ConstraintSolverState -> range -> Typars -> Typars -> unit -val AddCxTypeEqualsType': ContextInfo -> DisplayEnv -> ConstraintSolverState -> range -> TType -> TType -> OperationResult - val AddCxTypeEqualsType: ContextInfo -> DisplayEnv -> ConstraintSolverState -> range -> TType -> TType -> unit val AddCxTypeEqualsTypeUndoIfFailed: DisplayEnv -> ConstraintSolverState -> range -> TType -> TType -> bool diff --git a/src/Compiler/Driver/CompilerDiagnostics.fs b/src/Compiler/Driver/CompilerDiagnostics.fs index a6e0450af3a..d162d2624e4 100644 --- a/src/Compiler/Driver/CompilerDiagnostics.fs +++ b/src/Compiler/Driver/CompilerDiagnostics.fs @@ -735,6 +735,22 @@ let OutputPhasedErrorR (os: StringBuilder) (diagnostic: PhasedDiagnostic) (canSu | ConstraintSolverError _ as e), _) -> OutputExceptionR os e + | ErrorFromAddingTypeEquation (_g, denv, ty1, ty2, ConstraintSolverTupleDiffLengths (_, tl1, tl2, _, _ ), _) -> + + let ty1, ty2, tpcs = NicePrint.minimalStringsOfTwoTypes denv ty1 ty2 + + let rec isKnownType = function TType_var ({typar_solution = None}, _) -> false + | TType_var ({typar_solution = Some s}, _) -> isKnownType s + | _ -> true + + let formatTuple tl ty = + if tl |> List.exists isKnownType then + $"tuple of length {tl.Length} ({ty})" + else $"tuple of length {tl.Length}" + + if ty1 <> ty2 + tpcs then + os.AppendString(ErrorFromAddingTypeEquation2E().Format (formatTuple tl1 ty1) (formatTuple tl2 ty2) tpcs) + | ErrorFromAddingTypeEquation (g, denv, ty1, ty2, e, _) -> if not (typeEquiv g ty1 ty2) then let ty1, ty2, tpcs = NicePrint.minimalStringsOfTwoTypes denv ty1 ty2 diff --git a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeMismatchTests.fs b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeMismatchTests.fs index e2d12a32c27..566b7945324 100644 --- a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeMismatchTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeMismatchTests.fs @@ -7,20 +7,51 @@ open FSharp.Test.Compiler module ``Type Mismatch`` = - [] - let ``type mismatch is reported when tuples have differing lengths``() = - FSharp """ - let x: int * int * int = 1, "" - let x: int * string * int = "", 1 - let x: int * int = "", "", 1 - """ - |> typecheck - |> shouldFail - |> withDiagnostics [ - (Error 1, Line 2, Col 27, Line 2, Col 32, "Type mismatch. Expecting a\n 'int * int * int' \nbut given a\n 'int * string' \nThe tuples have differing lengths of 3 and 2"); - (Error 1, Line 3, Col 30, Line 3, Col 35, "Type mismatch. Expecting a\n 'int * string * int' \nbut given a\n 'string * int' \nThe tuples have differing lengths of 3 and 2"); - (Error 1, Line 4, Col 21, Line 4, Col 30, "Type mismatch. Expecting a\n 'int * int' \nbut given a\n 'string * string * int' \nThe tuples have differing lengths of 2 and 3") - ] + module ``Different tuple lengths`` = + + [] + let ``Known type on the left``() = + FSharp """ +let x: int * int * int = 1, "" +let x: int * string * int = "", 1 +let x: int * int = "", "", 1 + """ + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Error 1, Line 2, Col 26, Line 2, Col 31, + "Type mismatch. Expecting a\n 'tuple of length 3 (int * int * int)' \nbut given a\n 'tuple of length 2' \n") + (Error 1, Line 3, Col 29, Line 3, Col 34, + "Type mismatch. Expecting a\n 'tuple of length 3 (int * string * int)' \nbut given a\n 'tuple of length 2' \n") + (Error 1, Line 4, Col 20, Line 4, Col 29, + "Type mismatch. Expecting a\n 'tuple of length 2 (int * int)' \nbut given a\n 'tuple of length 3' \n") + ] + + [] + let ``Known type on the right``() = + FSharp """ +let x : int * string = 1, "" +let a, b, c = x + """ + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Error 1, Line 3, Col 15, Line 3, Col 16, + "Type mismatch. Expecting a\n 'tuple of length 3' \nbut given a\n 'tuple of length 2 (int * string)' \n") + ] + + // TODO + let ``Else branch context``() = + FSharp """ +let f1(a, b, c) = + if true then (1, 2) else (a, b, c) + """ + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Error 1, Line 3, Col 30, Line 3, Col 39, + "All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is 'tuple of length 2 (int * int)'. This branch returns a value of type 'tuple of length 3'.") + ] [] let ``return Instead Of return!``() = From fc388458203f79bf0b0626fd9b366bab050894aa Mon Sep 17 00:00:00 2001 From: Petr Pokorny Date: Fri, 9 Sep 2022 18:09:23 +0200 Subject: [PATCH 05/19] test update --- .../Conformance/DeclarationElements/LetBindings/Basic/Basic.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/DeclarationElements/LetBindings/Basic/Basic.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/DeclarationElements/LetBindings/Basic/Basic.fs index d16093d1c41..84e5dfa2253 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/DeclarationElements/LetBindings/Basic/Basic.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/DeclarationElements/LetBindings/Basic/Basic.fs @@ -42,7 +42,7 @@ module Basic = |> verifyCompile |> shouldFail |> withDiagnostics [ - (Error 1, Line 5, Col 16, Line 5, Col 23, "Type mismatch. Expecting a\n ''a * 'b' \nbut given a\n 'int * int * int' \nThe tuples have differing lengths of 2 and 3") + (Error 1, Line 5, Col 16, Line 5, Col 23, "Type mismatch. Expecting a\n 'tuple of length 2' \nbut given a\n 'tuple of length 3' \n") ] // SOURCE=E_AttributesOnLet01.fs SCFLAGS="--test:ErrorRanges" # E_AttributesOnLet01.fs From cf11713d1f92a862139ed8be6d8a9de759350c51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pokorn=C3=BD?= Date: Thu, 22 Sep 2022 16:42:42 +0200 Subject: [PATCH 06/19] Detecting tuple length mismatch early and type checking the RHS --- src/Compiler/Checking/CheckExpressions.fs | 18 +++++++++ src/Compiler/Driver/CompilerDiagnostics.fs | 14 ++----- src/Compiler/FSStrings.resx | 7 +++- src/Compiler/xlf/FSStrings.cs.xlf | 5 +++ src/Compiler/xlf/FSStrings.de.xlf | 5 +++ src/Compiler/xlf/FSStrings.es.xlf | 5 +++ src/Compiler/xlf/FSStrings.fr.xlf | 5 +++ src/Compiler/xlf/FSStrings.it.xlf | 5 +++ src/Compiler/xlf/FSStrings.ja.xlf | 5 +++ src/Compiler/xlf/FSStrings.ko.xlf | 5 +++ src/Compiler/xlf/FSStrings.pl.xlf | 5 +++ src/Compiler/xlf/FSStrings.pt-BR.xlf | 5 +++ src/Compiler/xlf/FSStrings.ru.xlf | 5 +++ src/Compiler/xlf/FSStrings.tr.xlf | 5 +++ src/Compiler/xlf/FSStrings.zh-Hans.xlf | 5 +++ src/Compiler/xlf/FSStrings.zh-Hant.xlf | 5 +++ .../ErrorMessages/TypeMismatchTests.fs | 37 +++++++++---------- 17 files changed, 109 insertions(+), 32 deletions(-) diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs index a15bd96a712..19661f0ca33 100644 --- a/src/Compiler/Checking/CheckExpressions.fs +++ b/src/Compiler/Checking/CheckExpressions.fs @@ -603,6 +603,7 @@ let UnifyTupleTypeAndInferCharacteristics contextInfo (cenv: cenv) denv m knownT | _ -> contextInfo let ty2 = TType_tuple (tupInfo, ptys) + AddCxTypeEqualsType contextInfo denv cenv.css m knownTy ty2 tupInfo, ptys @@ -5792,6 +5793,23 @@ and TcExprLazy (cenv: cenv) overallTy env tpenv (synInnerExpr, m) = and TcExprTuple (cenv: cenv) overallTy env tpenv (isExplicitStruct, args, m) = let g = cenv.g TcPossiblyPropagatingExprLeafThenConvert (fun ty -> isAnyTupleTy g ty || isTyparTy g ty) cenv overallTy env m (fun overallTy -> + + // We preemptively check if the tuple has the correct length before submitting it to the + // constraint solver. If not we type check it against empty inference variables so that + // we can show the types in the error message if they are known. + if isAnyTupleTy g overallTy then + let tupInfo, ptys = destAnyTupleTy g overallTy + + if List.length args <> List.length ptys then + let rhsTys = NewInferenceTypes g args + let flexes = rhsTys |> List.map (fun _ -> false) + suppressErrorReporting (fun () -> TcExprsWithFlexes cenv env m tpenv flexes rhsTys args) |> ignore + let expectedTy = TType_tuple (tupInfo, rhsTys) + + // We let error recovery handle this exception + error (ErrorFromAddingTypeEquation(g, env.DisplayEnv, overallTy, expectedTy, + (ConstraintSolverTupleDiffLengths(env.DisplayEnv, ptys, rhsTys, m, m)), m)) + let tupInfo, argTys = UnifyTupleTypeAndInferCharacteristics env.eContextInfo cenv env.DisplayEnv m overallTy isExplicitStruct args let flexes = argTys |> List.map (fun _ -> false) diff --git a/src/Compiler/Driver/CompilerDiagnostics.fs b/src/Compiler/Driver/CompilerDiagnostics.fs index e0e346e4523..64ab01c6e3b 100644 --- a/src/Compiler/Driver/CompilerDiagnostics.fs +++ b/src/Compiler/Driver/CompilerDiagnostics.fs @@ -439,6 +439,7 @@ module OldStyleMessages = let ConstraintSolverTypesNotInSubsumptionRelationE () = Message("ConstraintSolverTypesNotInSubsumptionRelation", "%s%s%s") let ErrorFromAddingTypeEquation1E () = Message("ErrorFromAddingTypeEquation1", "%s%s%s") let ErrorFromAddingTypeEquation2E () = Message("ErrorFromAddingTypeEquation2", "%s%s%s") + let ErrorFromAddingTypeEquationTuplesE () = Message("ErrorFromAddingTypeEquationTuples", "%d%s%d%s%s") let ErrorFromApplyingDefault1E () = Message("ErrorFromApplyingDefault1", "%s") let ErrorFromApplyingDefault2E () = Message("ErrorFromApplyingDefault2", "") let ErrorsFromAddingSubsumptionConstraintE () = Message("ErrorsFromAddingSubsumptionConstraint", "%s%s%s") @@ -739,18 +740,9 @@ type Exception with | ErrorFromAddingTypeEquation (_g, denv, ty1, ty2, ConstraintSolverTupleDiffLengths (_, tl1, tl2, _, _ ), _) -> let ty1, ty2, tpcs = NicePrint.minimalStringsOfTwoTypes denv ty1 ty2 - - let rec isKnownType = function TType_var ({typar_solution = None}, _) -> false - | TType_var ({typar_solution = Some s}, _) -> isKnownType s - | _ -> true - - let formatTuple tl ty = - if tl |> List.exists isKnownType then - $"tuple of length {tl.Length} ({ty})" - else $"tuple of length {tl.Length}" - + if ty1 <> ty2 + tpcs then - os.AppendString(ErrorFromAddingTypeEquation2E().Format (formatTuple tl1 ty1) (formatTuple tl2 ty2) tpcs) + os.AppendString(ErrorFromAddingTypeEquationTuplesE().Format tl1.Length ty1 tl2.Length ty2 tpcs) | ErrorFromAddingTypeEquation (g, denv, ty1, ty2, e, _) -> if not (typeEquiv g ty1 ty2) then diff --git a/src/Compiler/FSStrings.resx b/src/Compiler/FSStrings.resx index 51f172fbbea..7616276cc99 100644 --- a/src/Compiler/FSStrings.resx +++ b/src/Compiler/FSStrings.resx @@ -573,7 +573,7 @@ keyword 'and' - ! + keyword 'and!' @@ -907,7 +907,7 @@ This expression is a function value, i.e. is missing arguments. Its type is {0}. - The result of this expression has type '{0}' 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'. + The result of this expression has type '{0}' 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'. The result of this equality expression has type '{0}' and is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'. @@ -1110,4 +1110,7 @@ Lowercase discriminated union cases are only allowed when using RequireQualifiedAccess attribute + + Type mismatch. Expecting a tuple of length {0} of type\n {1} \nbut given a tuple of length {2} of type\n {3} {4}\n + \ No newline at end of file diff --git a/src/Compiler/xlf/FSStrings.cs.xlf b/src/Compiler/xlf/FSStrings.cs.xlf index f80da09f758..9ae4a01d0df 100644 --- a/src/Compiler/xlf/FSStrings.cs.xlf +++ b/src/Compiler/xlf/FSStrings.cs.xlf @@ -2,6 +2,11 @@ + + Type mismatch. Expecting a tuple of length {0} of type\n {1} \nbut given a tuple of length {2} of type\n {3} {4}\n + Type mismatch. Expecting a tuple of length {0} of type\n {1} \nbut given a tuple of length {2} of type\n {3} {4}\n + + One or more informational messages in loaded file.\n Nejméně jedna informační zpráva v načteném souboru\n diff --git a/src/Compiler/xlf/FSStrings.de.xlf b/src/Compiler/xlf/FSStrings.de.xlf index 8978b176751..3701029f76a 100644 --- a/src/Compiler/xlf/FSStrings.de.xlf +++ b/src/Compiler/xlf/FSStrings.de.xlf @@ -2,6 +2,11 @@ + + Type mismatch. Expecting a tuple of length {0} of type\n {1} \nbut given a tuple of length {2} of type\n {3} {4}\n + Type mismatch. Expecting a tuple of length {0} of type\n {1} \nbut given a tuple of length {2} of type\n {3} {4}\n + + One or more informational messages in loaded file.\n Mindestens eine Informationsmeldung in der geladenen Datei.\n diff --git a/src/Compiler/xlf/FSStrings.es.xlf b/src/Compiler/xlf/FSStrings.es.xlf index bc0ce4ad5a8..d836ca97b1e 100644 --- a/src/Compiler/xlf/FSStrings.es.xlf +++ b/src/Compiler/xlf/FSStrings.es.xlf @@ -2,6 +2,11 @@ + + Type mismatch. Expecting a tuple of length {0} of type\n {1} \nbut given a tuple of length {2} of type\n {3} {4}\n + Type mismatch. Expecting a tuple of length {0} of type\n {1} \nbut given a tuple of length {2} of type\n {3} {4}\n + + One or more informational messages in loaded file.\n Uno o más mensajes informativos en el archivo cargado.\n diff --git a/src/Compiler/xlf/FSStrings.fr.xlf b/src/Compiler/xlf/FSStrings.fr.xlf index f88d8e7182b..aba1f520dc8 100644 --- a/src/Compiler/xlf/FSStrings.fr.xlf +++ b/src/Compiler/xlf/FSStrings.fr.xlf @@ -2,6 +2,11 @@ + + Type mismatch. Expecting a tuple of length {0} of type\n {1} \nbut given a tuple of length {2} of type\n {3} {4}\n + Type mismatch. Expecting a tuple of length {0} of type\n {1} \nbut given a tuple of length {2} of type\n {3} {4}\n + + One or more informational messages in loaded file.\n Un ou plusieurs messages d’information dans le fichier chargé.\n diff --git a/src/Compiler/xlf/FSStrings.it.xlf b/src/Compiler/xlf/FSStrings.it.xlf index 90d7b1611ff..b0a0bb8a1a6 100644 --- a/src/Compiler/xlf/FSStrings.it.xlf +++ b/src/Compiler/xlf/FSStrings.it.xlf @@ -2,6 +2,11 @@ + + Type mismatch. Expecting a tuple of length {0} of type\n {1} \nbut given a tuple of length {2} of type\n {3} {4}\n + Type mismatch. Expecting a tuple of length {0} of type\n {1} \nbut given a tuple of length {2} of type\n {3} {4}\n + + One or more informational messages in loaded file.\n Uno o più messaggi informativi nel file caricato.\n diff --git a/src/Compiler/xlf/FSStrings.ja.xlf b/src/Compiler/xlf/FSStrings.ja.xlf index b0a149427b1..7259d209c4e 100644 --- a/src/Compiler/xlf/FSStrings.ja.xlf +++ b/src/Compiler/xlf/FSStrings.ja.xlf @@ -2,6 +2,11 @@ + + Type mismatch. Expecting a tuple of length {0} of type\n {1} \nbut given a tuple of length {2} of type\n {3} {4}\n + Type mismatch. Expecting a tuple of length {0} of type\n {1} \nbut given a tuple of length {2} of type\n {3} {4}\n + + One or more informational messages in loaded file.\n 読み込まれたファイル内の 1 つ以上の情報メッセージ。\n diff --git a/src/Compiler/xlf/FSStrings.ko.xlf b/src/Compiler/xlf/FSStrings.ko.xlf index 95015040f09..df894d6e464 100644 --- a/src/Compiler/xlf/FSStrings.ko.xlf +++ b/src/Compiler/xlf/FSStrings.ko.xlf @@ -2,6 +2,11 @@ + + Type mismatch. Expecting a tuple of length {0} of type\n {1} \nbut given a tuple of length {2} of type\n {3} {4}\n + Type mismatch. Expecting a tuple of length {0} of type\n {1} \nbut given a tuple of length {2} of type\n {3} {4}\n + + One or more informational messages in loaded file.\n 로드된 파일에 하나 이상의 정보 메시지가 있습니다.\n diff --git a/src/Compiler/xlf/FSStrings.pl.xlf b/src/Compiler/xlf/FSStrings.pl.xlf index 48a2f8adedc..c013efe5e25 100644 --- a/src/Compiler/xlf/FSStrings.pl.xlf +++ b/src/Compiler/xlf/FSStrings.pl.xlf @@ -2,6 +2,11 @@ + + Type mismatch. Expecting a tuple of length {0} of type\n {1} \nbut given a tuple of length {2} of type\n {3} {4}\n + Type mismatch. Expecting a tuple of length {0} of type\n {1} \nbut given a tuple of length {2} of type\n {3} {4}\n + + One or more informational messages in loaded file.\n Jeden lub więcej komunikatów informacyjnych w załadowanym pliku.\n diff --git a/src/Compiler/xlf/FSStrings.pt-BR.xlf b/src/Compiler/xlf/FSStrings.pt-BR.xlf index 1929c486cda..cbfdb3d9571 100644 --- a/src/Compiler/xlf/FSStrings.pt-BR.xlf +++ b/src/Compiler/xlf/FSStrings.pt-BR.xlf @@ -2,6 +2,11 @@ + + Type mismatch. Expecting a tuple of length {0} of type\n {1} \nbut given a tuple of length {2} of type\n {3} {4}\n + Type mismatch. Expecting a tuple of length {0} of type\n {1} \nbut given a tuple of length {2} of type\n {3} {4}\n + + One or more informational messages in loaded file.\n Uma ou mais mensagens informativas no arquivo carregado.\n diff --git a/src/Compiler/xlf/FSStrings.ru.xlf b/src/Compiler/xlf/FSStrings.ru.xlf index 1e91c13cd4c..2e5990bf60a 100644 --- a/src/Compiler/xlf/FSStrings.ru.xlf +++ b/src/Compiler/xlf/FSStrings.ru.xlf @@ -2,6 +2,11 @@ + + Type mismatch. Expecting a tuple of length {0} of type\n {1} \nbut given a tuple of length {2} of type\n {3} {4}\n + Type mismatch. Expecting a tuple of length {0} of type\n {1} \nbut given a tuple of length {2} of type\n {3} {4}\n + + One or more informational messages in loaded file.\n Одно или несколько информационных сообщений в загруженном файле.\n diff --git a/src/Compiler/xlf/FSStrings.tr.xlf b/src/Compiler/xlf/FSStrings.tr.xlf index 31b4cad81af..f39a7c98226 100644 --- a/src/Compiler/xlf/FSStrings.tr.xlf +++ b/src/Compiler/xlf/FSStrings.tr.xlf @@ -2,6 +2,11 @@ + + Type mismatch. Expecting a tuple of length {0} of type\n {1} \nbut given a tuple of length {2} of type\n {3} {4}\n + Type mismatch. Expecting a tuple of length {0} of type\n {1} \nbut given a tuple of length {2} of type\n {3} {4}\n + + One or more informational messages in loaded file.\n Yüklenen dosyada bir veya daha fazla bilgi mesajı.\n diff --git a/src/Compiler/xlf/FSStrings.zh-Hans.xlf b/src/Compiler/xlf/FSStrings.zh-Hans.xlf index be3604df4bf..4e165af368e 100644 --- a/src/Compiler/xlf/FSStrings.zh-Hans.xlf +++ b/src/Compiler/xlf/FSStrings.zh-Hans.xlf @@ -2,6 +2,11 @@ + + Type mismatch. Expecting a tuple of length {0} of type\n {1} \nbut given a tuple of length {2} of type\n {3} {4}\n + Type mismatch. Expecting a tuple of length {0} of type\n {1} \nbut given a tuple of length {2} of type\n {3} {4}\n + + One or more informational messages in loaded file.\n 加载文件 .\n 中有一条或多条信息性消息 diff --git a/src/Compiler/xlf/FSStrings.zh-Hant.xlf b/src/Compiler/xlf/FSStrings.zh-Hant.xlf index 67e6c25370e..0539395909b 100644 --- a/src/Compiler/xlf/FSStrings.zh-Hant.xlf +++ b/src/Compiler/xlf/FSStrings.zh-Hant.xlf @@ -2,6 +2,11 @@ + + Type mismatch. Expecting a tuple of length {0} of type\n {1} \nbut given a tuple of length {2} of type\n {3} {4}\n + Type mismatch. Expecting a tuple of length {0} of type\n {1} \nbut given a tuple of length {2} of type\n {3} {4}\n + + One or more informational messages in loaded file.\n 已載入檔案中的一或多個資訊訊息。\n diff --git a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeMismatchTests.fs b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeMismatchTests.fs index 566b7945324..8025a7f7746 100644 --- a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeMismatchTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeMismatchTests.fs @@ -8,25 +8,19 @@ open FSharp.Test.Compiler module ``Type Mismatch`` = module ``Different tuple lengths`` = - + [] let ``Known type on the left``() = FSharp """ -let x: int * int * int = 1, "" -let x: int * string * int = "", 1 -let x: int * int = "", "", 1 +let x a b c : int * int = a, b, c """ |> typecheck |> shouldFail |> withDiagnostics [ - (Error 1, Line 2, Col 26, Line 2, Col 31, - "Type mismatch. Expecting a\n 'tuple of length 3 (int * int * int)' \nbut given a\n 'tuple of length 2' \n") - (Error 1, Line 3, Col 29, Line 3, Col 34, - "Type mismatch. Expecting a\n 'tuple of length 3 (int * string * int)' \nbut given a\n 'tuple of length 2' \n") - (Error 1, Line 4, Col 20, Line 4, Col 29, - "Type mismatch. Expecting a\n 'tuple of length 2 (int * int)' \nbut given a\n 'tuple of length 3' \n") + (Error 1, Line 2, Col 27, Line 2, Col 34, + "Type mismatch. Expecting a tuple of length 2 of type\n int * int \nbut given a tuple of length 3 of type\n 'a * 'b * 'c \n") ] - + [] let ``Known type on the right``() = FSharp """ @@ -37,20 +31,25 @@ let a, b, c = x |> shouldFail |> withDiagnostics [ (Error 1, Line 3, Col 15, Line 3, Col 16, - "Type mismatch. Expecting a\n 'tuple of length 3' \nbut given a\n 'tuple of length 2 (int * string)' \n") + "Type mismatch. Expecting a tuple of length 3 of type\n 'a * 'b * 'c \nbut given a tuple of length 2 of type\n int * string \n") ] - - // TODO - let ``Else branch context``() = + + [] + let ``Known types on both sides``() = FSharp """ -let f1(a, b, c) = - if true then (1, 2) else (a, b, c) +let x: int * int * int = 1, "" +let x: int * string * int = "", 1 +let x: int * int = "", "", 1 """ |> typecheck |> shouldFail |> withDiagnostics [ - (Error 1, Line 3, Col 30, Line 3, Col 39, - "All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is 'tuple of length 2 (int * int)'. This branch returns a value of type 'tuple of length 3'.") + (Error 1, Line 2, Col 26, Line 2, Col 31, + "Type mismatch. Expecting a tuple of length 3 of type\n int * int * int \nbut given a tuple of length 2 of type\n int * string \n") + (Error 1, Line 3, Col 29, Line 3, Col 34, + "Type mismatch. Expecting a tuple of length 3 of type\n int * string * int \nbut given a tuple of length 2 of type\n string * int \n") + (Error 1, Line 4, Col 20, Line 4, Col 29, + "Type mismatch. Expecting a tuple of length 2 of type\n int * int \nbut given a tuple of length 3 of type\n string * string * int \n") ] [] From 5d832201f82c57e15204264a5f601ed3e4d4e949 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pokorn=C3=BD?= Date: Thu, 22 Sep 2022 16:47:51 +0200 Subject: [PATCH 07/19] fantomas --- src/Compiler/Driver/CompilerDiagnostics.fs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Compiler/Driver/CompilerDiagnostics.fs b/src/Compiler/Driver/CompilerDiagnostics.fs index 64ab01c6e3b..7da2a668d99 100644 --- a/src/Compiler/Driver/CompilerDiagnostics.fs +++ b/src/Compiler/Driver/CompilerDiagnostics.fs @@ -737,13 +737,13 @@ type Exception with | ErrorFromAddingTypeEquation(error = ConstraintSolverError _ as e) -> e.Output(os, suggestNames) - | ErrorFromAddingTypeEquation (_g, denv, ty1, ty2, ConstraintSolverTupleDiffLengths (_, tl1, tl2, _, _ ), _) -> - + | ErrorFromAddingTypeEquation (_g, denv, ty1, ty2, ConstraintSolverTupleDiffLengths (_, tl1, tl2, _, _), _) -> + let ty1, ty2, tpcs = NicePrint.minimalStringsOfTwoTypes denv ty1 ty2 if ty1 <> ty2 + tpcs then os.AppendString(ErrorFromAddingTypeEquationTuplesE().Format tl1.Length ty1 tl2.Length ty2 tpcs) - + | ErrorFromAddingTypeEquation (g, denv, ty1, ty2, e, _) -> if not (typeEquiv g ty1 ty2) then let ty1, ty2, tpcs = NicePrint.minimalStringsOfTwoTypes denv ty1 ty2 From 756357e118baf45513c278a408ecfd92b2e4f039 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pokorn=C3=BD?= Date: Thu, 22 Sep 2022 17:02:53 +0200 Subject: [PATCH 08/19] Test update --- .../Conformance/DeclarationElements/LetBindings/Basic/Basic.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/DeclarationElements/LetBindings/Basic/Basic.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/DeclarationElements/LetBindings/Basic/Basic.fs index 84e5dfa2253..aace49ba0d7 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/DeclarationElements/LetBindings/Basic/Basic.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/DeclarationElements/LetBindings/Basic/Basic.fs @@ -42,7 +42,7 @@ module Basic = |> verifyCompile |> shouldFail |> withDiagnostics [ - (Error 1, Line 5, Col 16, Line 5, Col 23, "Type mismatch. Expecting a\n 'tuple of length 2' \nbut given a\n 'tuple of length 3' \n") + (Error 1, Line 5, Col 16, Line 5, Col 23, "Type mismatch. Expecting a tuple of length 2 of type\n 'a * 'b \nbut given a tuple of length 3 of type\n int * int * int \n") ] // SOURCE=E_AttributesOnLet01.fs SCFLAGS="--test:ErrorRanges" # E_AttributesOnLet01.fs From 656c24891133a04c413ab8b2fd015857ae46074d Mon Sep 17 00:00:00 2001 From: Petr Pokorny Date: Thu, 22 Sep 2022 17:10:15 +0200 Subject: [PATCH 09/19] Remove comment --- src/Compiler/Checking/ConstraintSolver.fs | 1 - src/Compiler/Driver/CompilerDiagnostics.fs | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/Compiler/Checking/ConstraintSolver.fs b/src/Compiler/Checking/ConstraintSolver.fs index 384d7a4e92d..9f35a8a52aa 100644 --- a/src/Compiler/Checking/ConstraintSolver.fs +++ b/src/Compiler/Checking/ConstraintSolver.fs @@ -1228,7 +1228,6 @@ and SolveTypeEqualsTypeEqns csenv ndeep m2 trace cxsln origl1 origl2 = | h1 :: t1, h2 :: t2 when t1.Length = t2.Length -> SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m2 trace cxsln h1 h2 ++ (fun () -> loop t1 t2) | _ -> - // TODO: we should probably keep the ContextInfo here ErrorD(ConstraintSolverTupleDiffLengths(csenv.DisplayEnv, origl1, origl2, csenv.m, m2)) loop origl1 origl2 diff --git a/src/Compiler/Driver/CompilerDiagnostics.fs b/src/Compiler/Driver/CompilerDiagnostics.fs index 7da2a668d99..02934061602 100644 --- a/src/Compiler/Driver/CompilerDiagnostics.fs +++ b/src/Compiler/Driver/CompilerDiagnostics.fs @@ -738,9 +738,7 @@ type Exception with | ErrorFromAddingTypeEquation(error = ConstraintSolverError _ as e) -> e.Output(os, suggestNames) | ErrorFromAddingTypeEquation (_g, denv, ty1, ty2, ConstraintSolverTupleDiffLengths (_, tl1, tl2, _, _), _) -> - let ty1, ty2, tpcs = NicePrint.minimalStringsOfTwoTypes denv ty1 ty2 - if ty1 <> ty2 + tpcs then os.AppendString(ErrorFromAddingTypeEquationTuplesE().Format tl1.Length ty1 tl2.Length ty2 tpcs) From 0e2b146af4b4f56bd242fa0117bd45bd6aa97290 Mon Sep 17 00:00:00 2001 From: Petr Pokorny Date: Thu, 22 Sep 2022 17:12:36 +0200 Subject: [PATCH 10/19] Undo whitespace change --- src/Compiler/Checking/CheckExpressions.fs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs index 19661f0ca33..0cdf33cb218 100644 --- a/src/Compiler/Checking/CheckExpressions.fs +++ b/src/Compiler/Checking/CheckExpressions.fs @@ -603,7 +603,6 @@ let UnifyTupleTypeAndInferCharacteristics contextInfo (cenv: cenv) denv m knownT | _ -> contextInfo let ty2 = TType_tuple (tupInfo, ptys) - AddCxTypeEqualsType contextInfo denv cenv.css m knownTy ty2 tupInfo, ptys From dd248b010a51c453e4bb34870cdd5858d459fc0c Mon Sep 17 00:00:00 2001 From: Petr Pokorny Date: Tue, 27 Sep 2022 13:53:08 +0200 Subject: [PATCH 11/19] Tuple length mismatch in patterns --- src/Compiler/Checking/CheckExpressions.fs | 51 +++++++++---------- src/Compiler/Checking/CheckExpressions.fsi | 12 +++++ src/Compiler/Checking/CheckPatterns.fs | 2 + .../ErrorMessages/TypeMismatchTests.fs | 37 ++++++++++++++ .../Tuple/E_TupleMismatch01.fs | 15 ------ .../Conformance/PatternMatching/Tuple/env.lst | 4 +- 6 files changed, 77 insertions(+), 44 deletions(-) delete mode 100644 tests/fsharpqa/Source/Conformance/PatternMatching/Tuple/E_TupleMismatch01.fs diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs index 0cdf33cb218..22c86ee6ef5 100644 --- a/src/Compiler/Checking/CheckExpressions.fs +++ b/src/Compiler/Checking/CheckExpressions.fs @@ -590,8 +590,8 @@ let UnifyTupleTypeAndInferCharacteristics contextInfo (cenv: cenv) denv m knownT if isAnyTupleTy g knownTy then let tupInfo, ptys = destAnyTupleTy g knownTy let tupInfo = (if isExplicitStruct then tupInfoStruct else tupInfo) - let ptys = - if List.length ps = List.length ptys then ptys + let ptys = + if List.length ps = List.length ptys then ptys else NewInferenceTypes g ps tupInfo, ptys else @@ -5283,6 +5283,11 @@ and TcExprsWithFlexes (cenv: cenv) env m tpenv flexes argTys args = (tpenv, List.zip3 flexes argTys args) ||> List.mapFold (fun tpenv (flex, ty, e) -> TcExprFlex cenv flex false ty env tpenv e) +and TcExprsNoFlexes (cenv: cenv) env m tpenv argTys args = + if List.length args <> List.length argTys then error(Error(FSComp.SR.tcExpressionCountMisMatch((List.length argTys), (List.length args)), m)) + (tpenv, List.zip argTys args) ||> List.mapFold (fun tpenv (ty, e) -> + TcExprFlex2 cenv ty env false tpenv e) + and CheckSuperInit (cenv: cenv) objTy m = let g = cenv.g @@ -5789,30 +5794,27 @@ and TcExprLazy (cenv: cenv) overallTy env tpenv (synInnerExpr, m) = let expr = mkLazyDelayed g m innerTy (mkUnitDelayLambda g m innerExpr) expr, tpenv +and CheckTupleIsCorrectLength g (env: TcEnv) m tupleTy args typeCheckArgs = + if isAnyTupleTy g tupleTy then + let tupInfo, ptys = destAnyTupleTy g tupleTy + + if List.length args <> List.length ptys then + let argTys = NewInferenceTypes g args + suppressErrorReporting (fun () -> typeCheckArgs argTys) + let expectedTy = TType_tuple (tupInfo, argTys) + + // We let error recovery handle this exception + error (ErrorFromAddingTypeEquation(g, env.DisplayEnv, tupleTy, expectedTy, + (ConstraintSolverTupleDiffLengths(env.DisplayEnv, ptys, argTys, m, m)), m)) + and TcExprTuple (cenv: cenv) overallTy env tpenv (isExplicitStruct, args, m) = let g = cenv.g TcPossiblyPropagatingExprLeafThenConvert (fun ty -> isAnyTupleTy g ty || isTyparTy g ty) cenv overallTy env m (fun overallTy -> - // We preemptively check if the tuple has the correct length before submitting it to the - // constraint solver. If not we type check it against empty inference variables so that - // we can show the types in the error message if they are known. - if isAnyTupleTy g overallTy then - let tupInfo, ptys = destAnyTupleTy g overallTy - - if List.length args <> List.length ptys then - let rhsTys = NewInferenceTypes g args - let flexes = rhsTys |> List.map (fun _ -> false) - suppressErrorReporting (fun () -> TcExprsWithFlexes cenv env m tpenv flexes rhsTys args) |> ignore - let expectedTy = TType_tuple (tupInfo, rhsTys) - - // We let error recovery handle this exception - error (ErrorFromAddingTypeEquation(g, env.DisplayEnv, overallTy, expectedTy, - (ConstraintSolverTupleDiffLengths(env.DisplayEnv, ptys, rhsTys, m, m)), m)) + CheckTupleIsCorrectLength g env m overallTy args (fun argTys -> TcExprsNoFlexes cenv env m tpenv argTys args |> ignore) let tupInfo, argTys = UnifyTupleTypeAndInferCharacteristics env.eContextInfo cenv env.DisplayEnv m overallTy isExplicitStruct args - - let flexes = argTys |> List.map (fun _ -> false) - let argsR, tpenv = TcExprsWithFlexes cenv env m tpenv flexes argTys args + let argsR, tpenv = TcExprsNoFlexes cenv env m tpenv argTys args let expr = mkAnyTupled g m tupInfo argsR argTys expr, tpenv ) @@ -6092,8 +6094,7 @@ and TcExprILAssembly (cenv: cenv) overallTy env tpenv (ilInstrs, synTyArgs, synA let argTys = NewInferenceTypes g synArgs let tyargs, tpenv = TcTypes cenv NewTyparsOK CheckCxs ItemOccurence.UseInType WarnOnIWSAM.Yes env tpenv synTyArgs // No subsumption at uses of IL assembly code - let flexes = argTys |> List.map (fun _ -> false) - let args, tpenv = TcExprsWithFlexes cenv env m tpenv flexes argTys synArgs + let args, tpenv = TcExprsNoFlexes cenv env m tpenv argTys synArgs let retTys, tpenv = TcTypes cenv NewTyparsOK CheckCxs ItemOccurence.UseInType WarnOnIWSAM.Yes env tpenv synRetTys let returnTy = match retTys with @@ -7157,8 +7158,7 @@ and TcInterpolatedStringExpr cenv (overallTy: OverallTy) env m tpenv (parts: Syn mkCallNewFormat g m printerTy printerArgTy printerResidueTy printerResultTy printerTupleTy str, tpenv else // Type check the expressions filling the holes - let flexes = argTys |> List.map (fun _ -> false) - let fillExprs, tpenv = TcExprsWithFlexes cenv env m tpenv flexes argTys synFillExprs + let fillExprs, tpenv = TcExprsNoFlexes cenv env m tpenv argTys synFillExprs let fillExprsBoxed = (argTys, fillExprs) ||> List.map2 (mkCallBox g m) @@ -7184,8 +7184,7 @@ and TcInterpolatedStringExpr cenv (overallTy: OverallTy) env m tpenv (parts: Syn | Choice2Of2 createFormattableStringMethod -> // Type check the expressions filling the holes - let flexes = argTys |> List.map (fun _ -> false) - let fillExprs, tpenv = TcExprsWithFlexes cenv env m tpenv flexes argTys synFillExprs + let fillExprs, tpenv = TcExprsNoFlexes cenv env m tpenv argTys synFillExprs let fillExprsBoxed = (argTys, fillExprs) ||> List.map2 (mkCallBox g m) diff --git a/src/Compiler/Checking/CheckExpressions.fsi b/src/Compiler/Checking/CheckExpressions.fsi index 0bbaca89177..6c86f8b4525 100644 --- a/src/Compiler/Checking/CheckExpressions.fsi +++ b/src/Compiler/Checking/CheckExpressions.fsi @@ -623,6 +623,18 @@ val TcExpr: synExpr: SynExpr -> Expr * UnscopedTyparEnv +/// Check that 'args' have the correct number of elements for a tuple expression. +/// If not, use 'typeCheckArgs' to type check the given elements to show +/// their correct types (if known) in the error message and raise the error +val CheckTupleIsCorrectLength: + g: TcGlobals -> + env: TcEnv -> + m: range -> + tupleTy: TType -> + args: 'a list -> + typeCheckArgs: (TType list -> unit) -> + unit + /// Converts 'a..b' to a call to the '(..)' operator in FSharp.Core /// Converts 'a..b..c' to a call to the '(.. ..)' operator in FSharp.Core val RewriteRangeExpr: synExpr: SynExpr -> SynExpr option diff --git a/src/Compiler/Checking/CheckPatterns.fs b/src/Compiler/Checking/CheckPatterns.fs index dccff65781b..7ddf4b4a0a0 100644 --- a/src/Compiler/Checking/CheckPatterns.fs +++ b/src/Compiler/Checking/CheckPatterns.fs @@ -418,6 +418,8 @@ and TcPatAnds warnOnUpper cenv env vFlags patEnv ty pats m = and TcPatTuple warnOnUpper cenv env vFlags patEnv ty isExplicitStruct args m = let g = cenv.g try + CheckTupleIsCorrectLength g env m ty args (fun argTys -> TcPatterns warnOnUpper cenv env vFlags patEnv argTys args |> ignore) + let tupInfo, argTys = UnifyTupleTypeAndInferCharacteristics env.eContextInfo cenv env.DisplayEnv m ty isExplicitStruct args let argsR, acc = TcPatterns warnOnUpper cenv env vFlags patEnv argTys args let phase2 values = TPat_tuple(tupInfo, List.map (fun f -> f values) argsR, argTys, m) diff --git a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeMismatchTests.fs b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeMismatchTests.fs index 8025a7f7746..cf7b994b20f 100644 --- a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeMismatchTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeMismatchTests.fs @@ -52,6 +52,43 @@ let x: int * int = "", "", 1 "Type mismatch. Expecting a tuple of length 2 of type\n int * int \nbut given a tuple of length 3 of type\n string * string * int \n") ] + [] + let ``Patterns minimal`` () = + FSharp """ +let test (x : int * string * char) = + match x with + | 10, "20" -> true + | _ -> false + """ + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Error 1, Line 4, Col 7, Line 4, Col 15, + "Type mismatch. Expecting a tuple of length 3 of type\n int * string * char \nbut given a tuple of length 2 of type\n int * string \n") + ] + + [] + let ``Patterns with inference`` () = + FSharp """ +let test x = + match x with + | 0, "1", '2' -> true + | 10, "20" -> true + | "-1", '0' -> true + | 99, '9' -> true + | _ -> false + """ + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Error 1, Line 5, Col 7, Line 5, Col 15, + "Type mismatch. Expecting a tuple of length 3 of type\n int * string * char \nbut given a tuple of length 2 of type\n int * string \n") + (Error 1, Line 6, Col 11, Line 6, Col 20, + "Type mismatch. Expecting a tuple of length 3 of type\n int * string * char \nbut given a tuple of length 2 of type\n string * char \n") + (Error 1, Line 7, Col 7, Line 7, Col 20, + "Type mismatch. Expecting a tuple of length 3 of type\n int * string * char \nbut given a tuple of length 2 of type\n int * char \n") + ] + [] let ``return Instead Of return!``() = FSharp """ diff --git a/tests/fsharpqa/Source/Conformance/PatternMatching/Tuple/E_TupleMismatch01.fs b/tests/fsharpqa/Source/Conformance/PatternMatching/Tuple/E_TupleMismatch01.fs deleted file mode 100644 index b8df6f86f79..00000000000 --- a/tests/fsharpqa/Source/Conformance/PatternMatching/Tuple/E_TupleMismatch01.fs +++ /dev/null @@ -1,15 +0,0 @@ -// #Regression #Conformance #PatternMatching #Tuples -// Verify error if tuple sizes mismatch - -//Type mismatch\. Expecting a. 'int \* string \* char' .but given a. 'int \* string' .The tuples have differing lengths of 3 and 2 - -let test (x : int * string * char) = - match x with - | 0, "1", '2' -> true - | 10, "20" -> true - | "-1", '0' -> true - | 99, '9' -> true - | _ -> false - -exit 1 - diff --git a/tests/fsharpqa/Source/Conformance/PatternMatching/Tuple/env.lst b/tests/fsharpqa/Source/Conformance/PatternMatching/Tuple/env.lst index 1aa69ff867a..93d1e5338a4 100644 --- a/tests/fsharpqa/Source/Conformance/PatternMatching/Tuple/env.lst +++ b/tests/fsharpqa/Source/Conformance/PatternMatching/Tuple/env.lst @@ -2,6 +2,4 @@ SOURCE=SimpleTuples01.fs # SimpleTuples01.fs SOURCE=W_IncompleteMatches01.fs # W_IncompleteMatches01.fs SOURCE=W_RedundantPattern01.fs # W_RedundantPattern01.fs - SOURCE=W_RedundantPattern02.fs # W_RedundantPattern02.fs - - SOURCE=E_TupleMismatch01.fs SCFLAGS="--test:ErrorRanges --flaterrors" # E_TupleMismatch01.fs + SOURCE=W_RedundantPattern02.fs # W_RedundantPattern02.fss From 2a2eb0ad223288a0521333ea59652c455f3b02ed Mon Sep 17 00:00:00 2001 From: Petr Pokorny Date: Tue, 27 Sep 2022 14:00:27 +0200 Subject: [PATCH 12/19] typo --- tests/fsharpqa/Source/Conformance/PatternMatching/Tuple/env.lst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fsharpqa/Source/Conformance/PatternMatching/Tuple/env.lst b/tests/fsharpqa/Source/Conformance/PatternMatching/Tuple/env.lst index 93d1e5338a4..25f330533ba 100644 --- a/tests/fsharpqa/Source/Conformance/PatternMatching/Tuple/env.lst +++ b/tests/fsharpqa/Source/Conformance/PatternMatching/Tuple/env.lst @@ -2,4 +2,4 @@ SOURCE=SimpleTuples01.fs # SimpleTuples01.fs SOURCE=W_IncompleteMatches01.fs # W_IncompleteMatches01.fs SOURCE=W_RedundantPattern01.fs # W_RedundantPattern01.fs - SOURCE=W_RedundantPattern02.fs # W_RedundantPattern02.fss + SOURCE=W_RedundantPattern02.fs # W_RedundantPattern02.fs From c92271731074d6268dc64b428c867640f6d32312 Mon Sep 17 00:00:00 2001 From: Petr Pokorny Date: Tue, 27 Sep 2022 14:52:02 +0200 Subject: [PATCH 13/19] Update test baseline --- tests/fsharp/typecheck/sigs/neg04.bsl | 32 +++++++++++++-------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/tests/fsharp/typecheck/sigs/neg04.bsl b/tests/fsharp/typecheck/sigs/neg04.bsl index f71119b8722..25a4a425582 100644 --- a/tests/fsharp/typecheck/sigs/neg04.bsl +++ b/tests/fsharp/typecheck/sigs/neg04.bsl @@ -14,31 +14,31 @@ neg04.fs(26,8,26,17): typecheck error FS0912: This declaration element is not pe neg04.fs(32,8,32,11): typecheck error FS0039: The type 'Double' does not define the field, constructor or member 'Nan'. Maybe you want one of the following: IsNaN -neg04.fs(46,69,46,94): typecheck error FS0001: Type mismatch. Expecting a - ''a * 'b * 'c * 'e' -but given a - ''a * 'b * 'c' -The tuples have differing lengths of 4 and 3 +neg04.fs(46,69,46,94): typecheck error FS0001: Type mismatch. Expecting a tuple of length 4 of type + 'a * 'g * 'f * 'i +but given a tuple of length 3 of type + 'c * 'l * 'm + + +neg04.fs(46,99,46,107): typecheck error FS0001: Type mismatch. Expecting a tuple of length 4 of type + 'a * 'g * 'f * 'i +but given a tuple of length 3 of type + 'n * 'o * 'p -neg04.fs(46,99,46,107): typecheck error FS0001: Type mismatch. Expecting a - ''a * 'b * 'c * 'e' -but given a - ''a * 'b * 'c' -The tuples have differing lengths of 4 and 3 neg04.fs(47,30,47,51): typecheck error FS0001: Type mismatch. Expecting a - 'seq<'a> -> 'f' + 'seq<'a> -> 'n' but given a - ''g list -> 'h' -The type 'seq<'a>' does not match the type ''f list' + ''o list -> 'p' +The type 'seq<'a>' does not match the type ''n list' neg04.fs(47,49,47,51): typecheck error FS0784: This numeric literal requires that a module 'NumericLiteralN' defining functions FromZero, FromOne, FromInt32, FromInt64 and FromString be in scope neg04.fs(47,30,47,51): typecheck error FS0001: Type mismatch. Expecting a - 'seq<'a> -> 'f' + 'seq<'a> -> 'n' but given a - ''g list -> 'h' -The type 'seq<'a>' does not match the type ''f list' + ''o list -> 'p' +The type 'seq<'a>' does not match the type ''n list' neg04.fs(61,25,61,40): typecheck error FS0001: This expression was expected to have type 'ClassType1' From 790280a62fdc2092ac7cad636f1ba73bb54dd4cc Mon Sep 17 00:00:00 2001 From: Petr Pokorny Date: Tue, 27 Sep 2022 15:09:19 +0200 Subject: [PATCH 14/19] Type annotation test --- .../ErrorMessages/TypeMismatchTests.fs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeMismatchTests.fs b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeMismatchTests.fs index cf7b994b20f..9447c8821f8 100644 --- a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeMismatchTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeMismatchTests.fs @@ -21,6 +21,21 @@ let x a b c : int * int = a, b, c "Type mismatch. Expecting a tuple of length 2 of type\n int * int \nbut given a tuple of length 3 of type\n 'a * 'b * 'c \n") ] + [] + let ``Type annotation propagates to the error message``() = + FSharp """ +let x a b (c: string) : int * int = a, b, c +let y a (b: string) c : int * int = a, b, c + """ + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Error 1, Line 2, Col 37, Line 2, Col 44, + "Type mismatch. Expecting a tuple of length 2 of type\n int * int \nbut given a tuple of length 3 of type\n 'a * 'b * string \n") + (Error 1, Line 3, Col 37, Line 3, Col 44, + "Type mismatch. Expecting a tuple of length 2 of type\n int * int \nbut given a tuple of length 3 of type\n 'a * string * 'b \n") + ] + [] let ``Known type on the right``() = FSharp """ From 15c7dc3ce29977af71e79f8b274d5a2c7724787c Mon Sep 17 00:00:00 2001 From: Petr Pokorny Date: Fri, 30 Sep 2022 16:41:55 +0200 Subject: [PATCH 15/19] Keep error context for tuple length mismatch --- src/Compiler/Checking/CheckExpressions.fs | 2 +- src/Compiler/Checking/ConstraintSolver.fs | 4 +- src/Compiler/Checking/ConstraintSolver.fsi | 8 +- src/Compiler/Driver/CompilerDiagnostics.fs | 90 +++++++++---------- src/Compiler/FSComp.txt | 5 ++ src/Compiler/xlf/FSComp.txt.cs.xlf | 25 ++++++ src/Compiler/xlf/FSComp.txt.de.xlf | 25 ++++++ src/Compiler/xlf/FSComp.txt.es.xlf | 25 ++++++ src/Compiler/xlf/FSComp.txt.fr.xlf | 25 ++++++ src/Compiler/xlf/FSComp.txt.it.xlf | 25 ++++++ src/Compiler/xlf/FSComp.txt.ja.xlf | 25 ++++++ src/Compiler/xlf/FSComp.txt.ko.xlf | 25 ++++++ src/Compiler/xlf/FSComp.txt.pl.xlf | 25 ++++++ src/Compiler/xlf/FSComp.txt.pt-BR.xlf | 25 ++++++ src/Compiler/xlf/FSComp.txt.ru.xlf | 25 ++++++ src/Compiler/xlf/FSComp.txt.tr.xlf | 25 ++++++ src/Compiler/xlf/FSComp.txt.zh-Hans.xlf | 25 ++++++ src/Compiler/xlf/FSComp.txt.zh-Hant.xlf | 25 ++++++ .../ErrorMessages/TypeMismatchTests.fs | 68 ++++++++++++++ 19 files changed, 453 insertions(+), 49 deletions(-) diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs index 55ac9f53334..d96bb32b8ab 100644 --- a/src/Compiler/Checking/CheckExpressions.fs +++ b/src/Compiler/Checking/CheckExpressions.fs @@ -5810,7 +5810,7 @@ and CheckTupleIsCorrectLength g (env: TcEnv) m tupleTy args typeCheckArgs = // We let error recovery handle this exception error (ErrorFromAddingTypeEquation(g, env.DisplayEnv, tupleTy, expectedTy, - (ConstraintSolverTupleDiffLengths(env.DisplayEnv, ptys, argTys, m, m)), m)) + (ConstraintSolverTupleDiffLengths(env.DisplayEnv, env.eContextInfo, ptys, argTys, m, m)), m)) and TcExprTuple (cenv: cenv) overallTy env tpenv (isExplicitStruct, args, m) = let g = cenv.g diff --git a/src/Compiler/Checking/ConstraintSolver.fs b/src/Compiler/Checking/ConstraintSolver.fs index 9f35a8a52aa..751e71bff5c 100644 --- a/src/Compiler/Checking/ConstraintSolver.fs +++ b/src/Compiler/Checking/ConstraintSolver.fs @@ -232,7 +232,7 @@ type OverallTy = | MustEqual ty -> ty | MustConvertTo (_, ty) -> ty -exception ConstraintSolverTupleDiffLengths of displayEnv: DisplayEnv * TType list * TType list * range * range +exception ConstraintSolverTupleDiffLengths of displayEnv: DisplayEnv * contextInfo: ContextInfo * TType list * TType list * range * range exception ConstraintSolverInfiniteTypes of displayEnv: DisplayEnv * contextInfo: ContextInfo * TType * TType * range * range @@ -1228,7 +1228,7 @@ and SolveTypeEqualsTypeEqns csenv ndeep m2 trace cxsln origl1 origl2 = | h1 :: t1, h2 :: t2 when t1.Length = t2.Length -> SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m2 trace cxsln h1 h2 ++ (fun () -> loop t1 t2) | _ -> - ErrorD(ConstraintSolverTupleDiffLengths(csenv.DisplayEnv, origl1, origl2, csenv.m, m2)) + ErrorD(ConstraintSolverTupleDiffLengths(csenv.DisplayEnv, csenv.eContextInfo, origl1, origl2, csenv.m, m2)) loop origl1 origl2 and SolveFunTypeEqn csenv ndeep m2 trace cxsln domainTy1 domainTy2 rangeTy1 rangeTy2 = trackErrors { diff --git a/src/Compiler/Checking/ConstraintSolver.fsi b/src/Compiler/Checking/ConstraintSolver.fsi index ca6a0bc4c47..d6cc309c6b5 100644 --- a/src/Compiler/Checking/ConstraintSolver.fsi +++ b/src/Compiler/Checking/ConstraintSolver.fsi @@ -141,7 +141,13 @@ type OverallTy = /// Represents a point where no subsumption/widening is possible member Commit: TType -exception ConstraintSolverTupleDiffLengths of displayEnv: DisplayEnv * TType list * TType list * range * range +exception ConstraintSolverTupleDiffLengths of + displayEnv: DisplayEnv * + contextInfo: ContextInfo * + TType list * + TType list * + range * + range exception ConstraintSolverInfiniteTypes of displayEnv: DisplayEnv * diff --git a/src/Compiler/Driver/CompilerDiagnostics.fs b/src/Compiler/Driver/CompilerDiagnostics.fs index 02934061602..4f6aacbf0db 100644 --- a/src/Compiler/Driver/CompilerDiagnostics.fs +++ b/src/Compiler/Driver/CompilerDiagnostics.fs @@ -170,7 +170,7 @@ type Exception with | VirtualAugmentationOnNullValuedType m | NonVirtualAugmentationOnNullValuedType m | NonRigidTypar (_, _, _, _, _, m) - | ConstraintSolverTupleDiffLengths (_, _, _, m, _) + | ConstraintSolverTupleDiffLengths (_, _, _, _, m, _) | ConstraintSolverInfiniteTypes (_, _, _, _, m, _) | ConstraintSolverMissingConstraint (_, _, _, m, _) | ConstraintSolverTypesNotInEqualityRelation (_, _, _, m, _, _) @@ -616,12 +616,28 @@ let OutputNameSuggestions (os: StringBuilder) suggestNames suggestionsF idText = os.AppendString " " os.AppendString(ConvertValLogicalNameToDisplayNameCore value) +let OutputTypesNotInEqualityRelationContextInfo contextInfo ty1 ty2 m (os: StringBuilder) fallback = + match contextInfo with + | ContextInfo.IfExpression range when equals range m -> os.AppendString(FSComp.SR.ifExpression (ty1, ty2)) + | ContextInfo.CollectionElement (isArray, range) when equals range m -> + if isArray then + os.AppendString(FSComp.SR.arrayElementHasWrongType (ty1, ty2)) + else + os.AppendString(FSComp.SR.listElementHasWrongType (ty1, ty2)) + | ContextInfo.OmittedElseBranch range when equals range m -> os.AppendString(FSComp.SR.missingElseBranch (ty2)) + | ContextInfo.ElseBranchResult range when equals range m -> os.AppendString(FSComp.SR.elseBranchHasWrongType (ty1, ty2)) + | ContextInfo.FollowingPatternMatchClause range when equals range m -> + os.AppendString(FSComp.SR.followingPatternMatchClauseHasWrongType (ty1, ty2)) + | ContextInfo.PatternMatchGuard range when equals range m -> os.AppendString(FSComp.SR.patternMatchGuardIsNotBool (ty2)) + | contextInfo -> fallback contextInfo + type Exception with member exn.Output(os: StringBuilder, suggestNames) = match exn with - | ConstraintSolverTupleDiffLengths (_, tl1, tl2, m, m2) -> + // TODO: this is now unused...? + | ConstraintSolverTupleDiffLengths (_, _, tl1, tl2, m, m2) -> os.AppendString(ConstraintSolverTupleDiffLengthsE().Format tl1.Length tl2.Length) if m.StartLine <> m2.StartLine then @@ -662,19 +678,8 @@ type Exception with // REVIEW: consider if we need to show _cxs (the type parameter constraints) let ty1, ty2, _cxs = NicePrint.minimalStringsOfTwoTypes denv ty1 ty2 - match contextInfo with - | ContextInfo.IfExpression range when equals range m -> os.AppendString(FSComp.SR.ifExpression (ty1, ty2)) - | ContextInfo.CollectionElement (isArray, range) when equals range m -> - if isArray then - os.AppendString(FSComp.SR.arrayElementHasWrongType (ty1, ty2)) - else - os.AppendString(FSComp.SR.listElementHasWrongType (ty1, ty2)) - | ContextInfo.OmittedElseBranch range when equals range m -> os.AppendString(FSComp.SR.missingElseBranch (ty2)) - | ContextInfo.ElseBranchResult range when equals range m -> os.AppendString(FSComp.SR.elseBranchHasWrongType (ty1, ty2)) - | ContextInfo.FollowingPatternMatchClause range when equals range m -> - os.AppendString(FSComp.SR.followingPatternMatchClauseHasWrongType (ty1, ty2)) - | ContextInfo.PatternMatchGuard range when equals range m -> os.AppendString(FSComp.SR.patternMatchGuardIsNotBool (ty2)) - | _ -> os.AppendString(ConstraintSolverTypesNotInEqualityRelation2E().Format ty1 ty2) + OutputTypesNotInEqualityRelationContextInfo contextInfo ty1 ty2 m os (fun _ -> + os.AppendString(ConstraintSolverTypesNotInEqualityRelation2E().Format ty1 ty2)) if m.StartLine <> m2.StartLine then os.AppendString(SeeAlsoE().Format(stringOfRange m)) @@ -698,33 +703,15 @@ type Exception with -> let ty1, ty2, tpcs = NicePrint.minimalStringsOfTwoTypes denv ty1 ty2 - match contextInfo with - | ContextInfo.IfExpression range when equals range m -> os.AppendString(FSComp.SR.ifExpression (ty1, ty2)) - - | ContextInfo.CollectionElement (isArray, range) when equals range m -> - if isArray then - os.AppendString(FSComp.SR.arrayElementHasWrongType (ty1, ty2)) - else - os.AppendString(FSComp.SR.listElementHasWrongType (ty1, ty2)) - - | ContextInfo.OmittedElseBranch range when equals range m -> os.AppendString(FSComp.SR.missingElseBranch (ty2)) - - | ContextInfo.ElseBranchResult range when equals range m -> os.AppendString(FSComp.SR.elseBranchHasWrongType (ty1, ty2)) - - | ContextInfo.FollowingPatternMatchClause range when equals range m -> - os.AppendString(FSComp.SR.followingPatternMatchClauseHasWrongType (ty1, ty2)) - - | ContextInfo.PatternMatchGuard range when equals range m -> os.AppendString(FSComp.SR.patternMatchGuardIsNotBool (ty2)) - - | ContextInfo.TupleInRecordFields -> - os.AppendString(ErrorFromAddingTypeEquation1E().Format ty2 ty1 tpcs) - os.AppendString(Environment.NewLine + FSComp.SR.commaInsteadOfSemicolonInRecord ()) - - | _ when ty2 = "bool" && ty1.EndsWithOrdinal(" ref") -> - os.AppendString(ErrorFromAddingTypeEquation1E().Format ty2 ty1 tpcs) - os.AppendString(Environment.NewLine + FSComp.SR.derefInsteadOfNot ()) - - | _ -> os.AppendString(ErrorFromAddingTypeEquation1E().Format ty2 ty1 tpcs) + OutputTypesNotInEqualityRelationContextInfo contextInfo ty1 ty2 m os (fun contextInfo -> + match contextInfo with + | ContextInfo.TupleInRecordFields -> + os.AppendString(ErrorFromAddingTypeEquation1E().Format ty2 ty1 tpcs) + os.AppendString(Environment.NewLine + FSComp.SR.commaInsteadOfSemicolonInRecord ()) + | _ when ty2 = "bool" && ty1.EndsWithOrdinal(" ref") -> + os.AppendString(ErrorFromAddingTypeEquation1E().Format ty2 ty1 tpcs) + os.AppendString(Environment.NewLine + FSComp.SR.derefInsteadOfNot ()) + | _ -> os.AppendString(ErrorFromAddingTypeEquation1E().Format ty2 ty1 tpcs)) | ErrorFromAddingTypeEquation (_, _, _, _, (ConstraintSolverTypesNotInEqualityRelation (_, _, _, _, _, contextInfo) as e), _) when (match contextInfo with @@ -737,10 +724,23 @@ type Exception with | ErrorFromAddingTypeEquation(error = ConstraintSolverError _ as e) -> e.Output(os, suggestNames) - | ErrorFromAddingTypeEquation (_g, denv, ty1, ty2, ConstraintSolverTupleDiffLengths (_, tl1, tl2, _, _), _) -> + | ErrorFromAddingTypeEquation (_g, denv, ty1, ty2, ConstraintSolverTupleDiffLengths (_, contextInfo, tl1, tl2, _, _), m) -> let ty1, ty2, tpcs = NicePrint.minimalStringsOfTwoTypes denv ty1 ty2 + let messageArgs = tl1.Length, ty1, tl2.Length, ty2 + if ty1 <> ty2 + tpcs then - os.AppendString(ErrorFromAddingTypeEquationTuplesE().Format tl1.Length ty1 tl2.Length ty2 tpcs) + match contextInfo with + | ContextInfo.IfExpression range when equals range m -> os.AppendString(FSComp.SR.ifExpressionTuple messageArgs) + | ContextInfo.ElseBranchResult range when equals range m -> + os.AppendString(FSComp.SR.elseBranchHasWrongTypeTuple messageArgs) + | ContextInfo.FollowingPatternMatchClause range when equals range m -> + os.AppendString(FSComp.SR.followingPatternMatchClauseHasWrongTypeTuple messageArgs) + | ContextInfo.CollectionElement (isArray, range) when equals range m -> + if isArray then + os.AppendString(FSComp.SR.arrayElementHasWrongTypeTuple messageArgs) + else + os.AppendString(FSComp.SR.listElementHasWrongTypeTuple messageArgs) + | _ -> os.AppendString(ErrorFromAddingTypeEquationTuplesE().Format tl1.Length ty1 tl2.Length ty2 tpcs) | ErrorFromAddingTypeEquation (g, denv, ty1, ty2, e, _) -> if not (typeEquiv g ty1 ty2) then @@ -2105,7 +2105,7 @@ type PhasedDiagnostic with Printf.bprintf buf "\n" match e with - | FormattedDiagnostic.Short (_, txt) -> buf.AppendString txt |> ignore + | FormattedDiagnostic.Short (_, txt) -> buf.AppendString txt | FormattedDiagnostic.Long (_, details) -> match details.Location with | Some l when not l.IsEmpty -> buf.AppendString l.TextRepresentation diff --git a/src/Compiler/FSComp.txt b/src/Compiler/FSComp.txt index 61054bba210..d6caebaf999 100644 --- a/src/Compiler/FSComp.txt +++ b/src/Compiler/FSComp.txt @@ -19,11 +19,16 @@ undefinedNamePatternDiscriminator,"The pattern discriminator '%s' is not defined replaceWithSuggestion,"Replace with '%s'" addIndexerDot,"Add . for indexer access." listElementHasWrongType,"All elements of a list must be implicitly convertible to the type of the first element, which here is '%s'. This element has type '%s'." +listElementHasWrongTypeTuple,"All elements of a list must be implicitly convertible to the type of the first element, which here is a tuple of length %d of type\n %s \nThis element is a tuple of length %d of type\n %s \n" arrayElementHasWrongType,"All elements of an array must be implicitly convertible to the type of the first element, which here is '%s'. This element has type '%s'." +arrayElementHasWrongTypeTuple,"All elements of an array must be implicitly convertible to the type of the first element, which here is a tuple of length %d of type\n %s \nThis element is a tuple of length %d of type\n %s \n" missingElseBranch,"This 'if' expression is missing an 'else' branch. Because 'if' is an expression, and not a statement, add an 'else' branch which also returns a value of type '%s'." ifExpression,"The 'if' expression needs to have type '%s' to satisfy context type requirements. It currently has type '%s'." +ifExpressionTuple,"The 'if' expression needs to return a tuple of length %d of type\n %s \nto satisfy context type requirements. It currently returns a tuple of length %d of type\n %s \n" elseBranchHasWrongType,"All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is '%s'. This branch returns a value of type '%s'." +elseBranchHasWrongTypeTuple,"All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length %d of type\n %s \nThis branch returns a tuple of length %d of type\n %s \n" followingPatternMatchClauseHasWrongType,"All branches of a pattern match expression must return values implicitly convertible to the type of the first branch, which here is '%s'. This branch returns a value of type '%s'." +followingPatternMatchClauseHasWrongTypeTuple,"All branches of a pattern match expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length %d of type\n %s \nThis branch returns a tuple of length %d of type\n %s \n" patternMatchGuardIsNotBool,"A pattern match guard must be of type 'bool', but this 'when' expression is of type '%s'." commaInsteadOfSemicolonInRecord,"A ';' is used to separate field values in records. Consider replacing ',' with ';'." derefInsteadOfNot,"The '!' operator is used to dereference a ref cell. Consider using 'not expr' here." diff --git a/src/Compiler/xlf/FSComp.txt.cs.xlf b/src/Compiler/xlf/FSComp.txt.cs.xlf index e0e999dc993..37b9dcdf71c 100644 --- a/src/Compiler/xlf/FSComp.txt.cs.xlf +++ b/src/Compiler/xlf/FSComp.txt.cs.xlf @@ -2,6 +2,11 @@ + + All elements of an array must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + All elements of an array must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + + The file extension of '{0}' is not recognized. Source files must have extension .fs, .fsi, .fsx or .fsscript. To enable the deprecated use of .ml or .mli extensions, use '--langversion:5.0' and '--mlcompatibility'. Soubor {0} má nerozpoznanou příponu. Zdrojové soubory musí mít příponu .fs, .fsi, .fsx nebo .fsscript. Pokud chcete povolit použití zastaralých přípon .ml nebo .mli, použijte parametry --langversion:5.0 a --mlcompatibility. @@ -102,6 +107,11 @@ Argument {0} neodpovídá + + All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + + The type provider designer assembly '{0}' could not be loaded from folder '{1}' because a dependency was missing or could not loaded. All dependencies of the type provider designer assembly must be located in the same folder as that assembly. The exception reported was: {2} - {3} Navržené sestavení poskytovatele typu {0} nešlo načíst ze složky {1}, protože chyběla závislost nebo ji nešlo načíst. Všechny závislosti tohoto sestavení se musí nacházet ve stejné složce jako toto sestavení. Ohlášená výjimka: {2} – {3} @@ -307,6 +317,11 @@ Předávání kopie clusteru pro omezení vlastností v uvozovkách v jazyce F# + + All branches of a pattern match expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + All branches of a pattern match expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + + Interpolated strings may not use '%' format specifiers unless each is given an expression, e.g. '%d{{1+1}}'. Interpolované řetězce nemůžou používat specifikátory formátu %, pokud se každému z nich nezadá nějaký výraz, např. %d{{1+1}}. @@ -347,6 +362,11 @@ Neplatná direktiva #{0} {1} + + The 'if' expression needs to return a tuple of length {0} of type\n {1} \nto satisfy context type requirements. It currently returns a tuple of length {2} of type\n {3} \n + The 'if' expression needs to return a tuple of length {0} of type\n {1} \nto satisfy context type requirements. It currently returns a tuple of length {2} of type\n {3} \n + + Unknown debug point '{0}'. The available debug points are '{1}'. Neznámý bod ladění {0}. Dostupné body ladění jsou {1}. @@ -402,6 +422,11 @@ Neplatný interpolovaný řetězec. V interpolovaných výrazech se nedají použít řetězcové literály s trojitými uvozovkami. Zvažte možnost použít pro interpolovaný výraz explicitní vazbu let. + + All elements of a list must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + All elements of a list must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + + This construct is deprecated. {0}. You can enable this feature by using '--langversion:5.0' and '--mlcompatibility'. Tento konstruktor je zastaralý. {0}. Tuto funkci můžete povolit pomocí parametrů --langversion:5.0 a --mlcompatibility. diff --git a/src/Compiler/xlf/FSComp.txt.de.xlf b/src/Compiler/xlf/FSComp.txt.de.xlf index 9b090dcdb5c..e321e217f53 100644 --- a/src/Compiler/xlf/FSComp.txt.de.xlf +++ b/src/Compiler/xlf/FSComp.txt.de.xlf @@ -2,6 +2,11 @@ + + All elements of an array must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + All elements of an array must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + + The file extension of '{0}' is not recognized. Source files must have extension .fs, .fsi, .fsx or .fsscript. To enable the deprecated use of .ml or .mli extensions, use '--langversion:5.0' and '--mlcompatibility'. Die Dateierweiterung von „{0}“ wurde nicht erkannt. Quelldateien müssen die Erweiterung .fs, .fsi, .fsx oder .fsscript haben. Um die veraltete Verwendung der Erweiterungen .ml oder .mli zu aktivieren, verwenden Sie „--langversion:5.0“ und „--mlcompatibility“. @@ -102,6 +107,11 @@ Das Argument "{0}" stimmt nicht überein. + + All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + + The type provider designer assembly '{0}' could not be loaded from folder '{1}' because a dependency was missing or could not loaded. All dependencies of the type provider designer assembly must be located in the same folder as that assembly. The exception reported was: {2} - {3} Die Typanbieter-Designerassembly "{0}" konnte aus dem Ordner "{1}" nicht geladen werden, weil eine Abhängigkeit fehlte oder nicht geladen werden konnte. Alle Abhängigkeiten der Typanbieter-Designerassembly müssen sich in demselben Ordner wie die Assembly befinden. Gemeldete Ausnahme: {2} – {3} @@ -307,6 +317,11 @@ Zeugenübergabe für Merkmalseinschränkungen in F#-Zitaten + + All branches of a pattern match expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + All branches of a pattern match expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + + Interpolated strings may not use '%' format specifiers unless each is given an expression, e.g. '%d{{1+1}}'. Interpolierte Zeichenfolgen dürfen keine Formatbezeichner vom Typ "%" verwenden, es sei denn, jeder erhält einen Ausdruck, z. B. "%d{{1+1}}". @@ -347,6 +362,11 @@ Ungültige Direktive "#{0} {1}" + + The 'if' expression needs to return a tuple of length {0} of type\n {1} \nto satisfy context type requirements. It currently returns a tuple of length {2} of type\n {3} \n + The 'if' expression needs to return a tuple of length {0} of type\n {1} \nto satisfy context type requirements. It currently returns a tuple of length {2} of type\n {3} \n + + Unknown debug point '{0}'. The available debug points are '{1}'. Unbekannter Debugpunkt „{0}“. Die verfügbaren Debugpunkte sind „{1}“. @@ -402,6 +422,11 @@ Ungültige interpolierte Zeichenfolge. Zeichenfolgenliterale mit dreifachen Anführungszeichen dürfen in interpolierten Ausdrücken nicht verwendet werden. Erwägen Sie die Verwendung einer expliziten let-Bindung für den Interpolationsausdruck. + + All elements of a list must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + All elements of a list must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + + This construct is deprecated. {0}. You can enable this feature by using '--langversion:5.0' and '--mlcompatibility'. Dieses Konstrukt ist veraltet. {0}. Sie können dieses Feature mithilfe von „--langversion:5.0“ und „--mlcompatibility“ aktivieren. diff --git a/src/Compiler/xlf/FSComp.txt.es.xlf b/src/Compiler/xlf/FSComp.txt.es.xlf index a410c3381fd..1b39719b981 100644 --- a/src/Compiler/xlf/FSComp.txt.es.xlf +++ b/src/Compiler/xlf/FSComp.txt.es.xlf @@ -2,6 +2,11 @@ + + All elements of an array must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + All elements of an array must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + + The file extension of '{0}' is not recognized. Source files must have extension .fs, .fsi, .fsx or .fsscript. To enable the deprecated use of .ml or .mli extensions, use '--langversion:5.0' and '--mlcompatibility'. No se reconoce la extensión de archivo de '{0}'. Los archivos de código fuente deben tener las extensiones .fs, .fsi, .fsx o .fsscript. Para habilitar el uso en desuso de las extensiones .ml o .mli, use '--langversion:5.0' y '--mlcompatibility'. @@ -102,6 +107,11 @@ El argumento "{0}" no coincide. + + All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + + The type provider designer assembly '{0}' could not be loaded from folder '{1}' because a dependency was missing or could not loaded. All dependencies of the type provider designer assembly must be located in the same folder as that assembly. The exception reported was: {2} - {3} No se pudo cargar el ensamblado del diseñador de proveedores de tipos "{0}" desde la carpeta "{1}" porque falta una dependencia o no se pudo cargar. Todas las dependencias del ensamblado del diseñador de proveedores de tipos deben encontrarse en la misma carpeta que el ensamblado. Se notificó la excepción: {2} - {3}. @@ -307,6 +317,11 @@ Paso de testigo para las restricciones de rasgos en las expresiones de código delimitadas de F# + + All branches of a pattern match expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + All branches of a pattern match expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + + Interpolated strings may not use '%' format specifiers unless each is given an expression, e.g. '%d{{1+1}}'. Las cadenas interpoladas no pueden usar los especificadores de formato "%", a menos que se les proporcione una expresión individualmente; por ejemplo, "%d{{1+1}}". @@ -347,6 +362,11 @@ Directiva '#{0} {1}' no válida. + + The 'if' expression needs to return a tuple of length {0} of type\n {1} \nto satisfy context type requirements. It currently returns a tuple of length {2} of type\n {3} \n + The 'if' expression needs to return a tuple of length {0} of type\n {1} \nto satisfy context type requirements. It currently returns a tuple of length {2} of type\n {3} \n + + Unknown debug point '{0}'. The available debug points are '{1}'. Punto de depuración desconocido \"{0}\". Los puntos de depuración disponibles son \"{1}\". @@ -402,6 +422,11 @@ Cadena interpolada no válida. No se pueden usar literales de cadena de comillas triples en las expresiones interpoladas. Puede usar un enlace "let" explícito para la expresión de interpolación. + + All elements of a list must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + All elements of a list must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + + This construct is deprecated. {0}. You can enable this feature by using '--langversion:5.0' and '--mlcompatibility'. Esta construcción está en desuso. {0}. Puede habilitar esta característica usando '--langversion:5.0' y '--mlcompatibility'. diff --git a/src/Compiler/xlf/FSComp.txt.fr.xlf b/src/Compiler/xlf/FSComp.txt.fr.xlf index 542a1f4fc33..6fb8d3519a6 100644 --- a/src/Compiler/xlf/FSComp.txt.fr.xlf +++ b/src/Compiler/xlf/FSComp.txt.fr.xlf @@ -2,6 +2,11 @@ + + All elements of an array must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + All elements of an array must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + + The file extension of '{0}' is not recognized. Source files must have extension .fs, .fsi, .fsx or .fsscript. To enable the deprecated use of .ml or .mli extensions, use '--langversion:5.0' and '--mlcompatibility'. L’extension de fichier « {0} » n’est pas reconnue. Les fichiers sources doivent avoir l’extension. FS,. FSI,. FSX ou. fsscript. Pour activer l’utilisation déconseillée des extensions. ml ou. MLI, utilisez'--langversion : 5.0 'et'--mlcompatibility'. @@ -102,6 +107,11 @@ L'argument '{0}' ne correspond pas + + All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + + The type provider designer assembly '{0}' could not be loaded from folder '{1}' because a dependency was missing or could not loaded. All dependencies of the type provider designer assembly must be located in the same folder as that assembly. The exception reported was: {2} - {3} Impossible de charger l'assembly de concepteur de fournisseur de type '{0}' à partir du dossier '{1}', car une dépendance est manquante ou n'a pas pu être chargée. Toutes les dépendances de l'assembly de concepteur de fournisseur de type doivent se trouver dans le même dossier que cet assembly. Exception signalée : {2} - {3} @@ -307,6 +317,11 @@ Passage de témoin pour les contraintes de trait dans les quotations F# + + All branches of a pattern match expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + All branches of a pattern match expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + + Interpolated strings may not use '%' format specifiers unless each is given an expression, e.g. '%d{{1+1}}'. Les chaînes interpolées ne peuvent pas utiliser les spécificateurs de format '%' à moins de recevoir une expression, par exemple '%d{{1+1}}'. @@ -347,6 +362,11 @@ Directive non valide '#{0} {1}' + + The 'if' expression needs to return a tuple of length {0} of type\n {1} \nto satisfy context type requirements. It currently returns a tuple of length {2} of type\n {3} \n + The 'if' expression needs to return a tuple of length {0} of type\n {1} \nto satisfy context type requirements. It currently returns a tuple of length {2} of type\n {3} \n + + Unknown debug point '{0}'. The available debug points are '{1}'. Point de débogage inconnu « {0} ». Les points de débogage disponibles sont «{1}». @@ -402,6 +422,11 @@ Chaîne interpolée non valide. Les littéraux de chaîne à guillemets triples ne peuvent pas être utilisés dans des expressions interpolées. Utilisez une liaison 'let' explicite pour l'expression d'interpolation. + + All elements of a list must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + All elements of a list must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + + This construct is deprecated. {0}. You can enable this feature by using '--langversion:5.0' and '--mlcompatibility'. Cette construction est déconseillée. {0}. Vous pouvez activer cette fonctionnalité à l’aide de'--langversion : 5.0 'et'--mlcompatibility'. diff --git a/src/Compiler/xlf/FSComp.txt.it.xlf b/src/Compiler/xlf/FSComp.txt.it.xlf index 885462d4313..286d05eef51 100644 --- a/src/Compiler/xlf/FSComp.txt.it.xlf +++ b/src/Compiler/xlf/FSComp.txt.it.xlf @@ -2,6 +2,11 @@ + + All elements of an array must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + All elements of an array must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + + The file extension of '{0}' is not recognized. Source files must have extension .fs, .fsi, .fsx or .fsscript. To enable the deprecated use of .ml or .mli extensions, use '--langversion:5.0' and '--mlcompatibility'. L'estensione di file di '{0}' non è riconosciuta. I file di origine devono avere estensione fs, fsi, fsx o fsscript. Per abilitare l'uso deprecato delle estensioni ml o mli, usare '--langversion:5.0' e '--mlcompatibility'. @@ -102,6 +107,11 @@ L'argomento '{0}' non corrisponde + + All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + + The type provider designer assembly '{0}' could not be loaded from folder '{1}' because a dependency was missing or could not loaded. All dependencies of the type provider designer assembly must be located in the same folder as that assembly. The exception reported was: {2} - {3} Non è stato possibile caricare l'assembly '{0}' della finestra di progettazione del provider di tipi dalla cartella '{1}' perché una dipendenza non è presente o non è stato possibile caricarla. Tutte le dipendenze dell'assembly della finestra di progettazione del provider di tipi devono trovarsi nella stessa cartella dell'assembly. L'eccezione restituita è {2} - {3} @@ -307,6 +317,11 @@ Passaggio del testimone per vincoli di tratto in quotation F# + + All branches of a pattern match expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + All branches of a pattern match expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + + Interpolated strings may not use '%' format specifiers unless each is given an expression, e.g. '%d{{1+1}}'. Nelle stringhe interpolate non è possibile usare gli identificatori di formato '%' a meno che non si indichi un'espressione per ognuno di essi, ad esempio '%d{{1+1}}'. @@ -347,6 +362,11 @@ Direttiva '#{0} {1}' non valida + + The 'if' expression needs to return a tuple of length {0} of type\n {1} \nto satisfy context type requirements. It currently returns a tuple of length {2} of type\n {3} \n + The 'if' expression needs to return a tuple of length {0} of type\n {1} \nto satisfy context type requirements. It currently returns a tuple of length {2} of type\n {3} \n + + Unknown debug point '{0}'. The available debug points are '{1}'. Punto di debug '{0}' sconosciuto. I punti di debug disponibili sono '{1}'. @@ -402,6 +422,11 @@ La stringa interpolata non è valida. Non è possibile usare valori letterali stringa tra virgolette triple in espressioni interpolate. Provare a usare un binding 'let' esplicito per l'espressione di interpolazione. + + All elements of a list must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + All elements of a list must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + + This construct is deprecated. {0}. You can enable this feature by using '--langversion:5.0' and '--mlcompatibility'. Questo costrutto è deprecato. {0}. È possibile abilitare questa funzionalità usando '--langversion:5.0' and '--mlcompatibility'. diff --git a/src/Compiler/xlf/FSComp.txt.ja.xlf b/src/Compiler/xlf/FSComp.txt.ja.xlf index e75546a4060..731029671fa 100644 --- a/src/Compiler/xlf/FSComp.txt.ja.xlf +++ b/src/Compiler/xlf/FSComp.txt.ja.xlf @@ -2,6 +2,11 @@ + + All elements of an array must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + All elements of an array must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + + The file extension of '{0}' is not recognized. Source files must have extension .fs, .fsi, .fsx or .fsscript. To enable the deprecated use of .ml or .mli extensions, use '--langversion:5.0' and '--mlcompatibility'. '{0}' のファイル拡張子を認識できません。ソース ファイル拡張子は .fs、.fsi、.fsx、または .fsscript にする必要があります。非推奨の拡張子 .ml または .mli の使用を有効にするには、'--langversion:5.0' および '--mlcompatibility' を使用してください。 @@ -102,6 +107,11 @@ 引数 '{0}' が一致しません + + All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + + The type provider designer assembly '{0}' could not be loaded from folder '{1}' because a dependency was missing or could not loaded. All dependencies of the type provider designer assembly must be located in the same folder as that assembly. The exception reported was: {2} - {3} 依存関係がないか、または読み込めなかったため、型プロバイダーのデザイナー アセンブリ '{0}' をフォルダー '{1}' から読み込めませんでした。型プロバイダーのデザイナー アセンブリのすべての依存関係は、そのアセンブリと同じフォルダーに配置されている必要があります。次の例外が報告されました: {2} - {3} @@ -307,6 +317,11 @@ F# 引用での特性制約に対する監視の引き渡し + + All branches of a pattern match expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + All branches of a pattern match expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + + Interpolated strings may not use '%' format specifiers unless each is given an expression, e.g. '%d{{1+1}}'. '%d{{1+1}}' などの式が指定されている場合を除き、補間された文字列では '%' 書式指定子を使用できません。 @@ -347,6 +362,11 @@ 無効なディレクティブ '#{0} {1}' + + The 'if' expression needs to return a tuple of length {0} of type\n {1} \nto satisfy context type requirements. It currently returns a tuple of length {2} of type\n {3} \n + The 'if' expression needs to return a tuple of length {0} of type\n {1} \nto satisfy context type requirements. It currently returns a tuple of length {2} of type\n {3} \n + + Unknown debug point '{0}'. The available debug points are '{1}'. 不明なデバッグ ポイントの `{0}`。使用可能なデバッグ ポイントは `{1}` です。 @@ -402,6 +422,11 @@ 補間された文字列が無効です。三重引用符文字列リテラルは、補間された式では使用できません。補間式に対して明示的な 'let' バインドを使用することをご検討ください。 + + All elements of a list must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + All elements of a list must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + + This construct is deprecated. {0}. You can enable this feature by using '--langversion:5.0' and '--mlcompatibility'. このコンストラクトは使用されなくなりました。{0}。'--langversion:5.0' と '--mlcompatibility' を使用することで、この機能を有効にすることができます。 diff --git a/src/Compiler/xlf/FSComp.txt.ko.xlf b/src/Compiler/xlf/FSComp.txt.ko.xlf index 0d61eacd4aa..479aa260678 100644 --- a/src/Compiler/xlf/FSComp.txt.ko.xlf +++ b/src/Compiler/xlf/FSComp.txt.ko.xlf @@ -2,6 +2,11 @@ + + All elements of an array must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + All elements of an array must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + + The file extension of '{0}' is not recognized. Source files must have extension .fs, .fsi, .fsx or .fsscript. To enable the deprecated use of .ml or .mli extensions, use '--langversion:5.0' and '--mlcompatibility'. '{0}'의 파일 확장자가 인식되지 않습니다. 원본 파일의 확장자는 .fs, .fsi, .fsx 또는 .fsscript여야 합니다. 더 이상 사용되지 않는 .ml 또는 .mli 확장자를 사용하려면 '--langversion:5.0' 및 '--mlcompatibility'를 사용하세요. @@ -102,6 +107,11 @@ '{0}' 인수가 일치하지 않습니다. + + All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + + The type provider designer assembly '{0}' could not be loaded from folder '{1}' because a dependency was missing or could not loaded. All dependencies of the type provider designer assembly must be located in the same folder as that assembly. The exception reported was: {2} - {3} 종속성이 없거나 로드되지 않았으므로 '{0}' 형식 공급자 디자이너 어셈블리를 '{1}' 폴더에서 로드할 수 없습니다. 형식 공급자 디자이너 어셈블리의 모든 종속성은 해당 어셈블리와 동일한 폴더에 있어야 합니다. 보고된 예외: {2} - {3} @@ -307,6 +317,11 @@ F# 인용의 특성 제약 조건에 대한 감시 전달 + + All branches of a pattern match expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + All branches of a pattern match expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + + Interpolated strings may not use '%' format specifiers unless each is given an expression, e.g. '%d{{1+1}}'. 각 보간 문자열에 식(예: '%d{{1+1}}')이 지정되지 않는 한 '%' 형식 지정자를 사용할 수 없습니다. @@ -347,6 +362,11 @@ 잘못된 지시문 '#{0} {1}' + + The 'if' expression needs to return a tuple of length {0} of type\n {1} \nto satisfy context type requirements. It currently returns a tuple of length {2} of type\n {3} \n + The 'if' expression needs to return a tuple of length {0} of type\n {1} \nto satisfy context type requirements. It currently returns a tuple of length {2} of type\n {3} \n + + Unknown debug point '{0}'. The available debug points are '{1}'. 알 수 없는 디버그 지점 '{0}'. 사용 가능한 디버그 지점은 '{1}'입니다. @@ -402,6 +422,11 @@ 잘못된 보간 문자열. 삼중 따옴표 문자열 리터럴은 보간 식에 사용할 수 없습니다. 보간 식에 명시적 'let' 바인딩을 사용해 보세요. + + All elements of a list must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + All elements of a list must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + + This construct is deprecated. {0}. You can enable this feature by using '--langversion:5.0' and '--mlcompatibility'. 이 구성은 더 이상 사용되지 않습니다. {0}. '--langversion:5.0' 및 '--mlcompatibility'를 사용하여 이 기능을 활성화할 수 있습니다. diff --git a/src/Compiler/xlf/FSComp.txt.pl.xlf b/src/Compiler/xlf/FSComp.txt.pl.xlf index 32a58e4b23a..86453f1948d 100644 --- a/src/Compiler/xlf/FSComp.txt.pl.xlf +++ b/src/Compiler/xlf/FSComp.txt.pl.xlf @@ -2,6 +2,11 @@ + + All elements of an array must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + All elements of an array must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + + The file extension of '{0}' is not recognized. Source files must have extension .fs, .fsi, .fsx or .fsscript. To enable the deprecated use of .ml or .mli extensions, use '--langversion:5.0' and '--mlcompatibility'. Rozszerzenie pliku "{0}" nie zostało rozpoznane. Pliki źródłowe muszą mieć rozszerzenie .fs, .fsi, .fsx lub .fsscript. Aby włączyć przestarzałe używanie rozszerzeń. ml lub .mli, użyj polecenia "--langversion: 5.0" i "--mlcompatibility". @@ -102,6 +107,11 @@ Argument „{0}” nie jest zgodny + + All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + + The type provider designer assembly '{0}' could not be loaded from folder '{1}' because a dependency was missing or could not loaded. All dependencies of the type provider designer assembly must be located in the same folder as that assembly. The exception reported was: {2} - {3} Nie można załadować zestawu projektanta dostawców typów „{0}” z folderu „{1}”, ponieważ brakuje zależności lub nie można jej załadować. Wszystkie zależności zestawu projektanta dostawców typów muszą znajdować się w tym samym folderze co ten zestaw. Zgłoszony wyjątek: {2} — {3} @@ -307,6 +317,11 @@ monitor, który przekazuje ograniczenia cech języka F# + + All branches of a pattern match expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + All branches of a pattern match expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + + Interpolated strings may not use '%' format specifiers unless each is given an expression, e.g. '%d{{1+1}}'. W interpolowanych ciągach nie można używać specyfikatorów formatu „%”, chyba że każdemu z nich odpowiada wyrażenie, na przykład „%d{{1+1}}”. @@ -347,6 +362,11 @@ Nieprawidłowa dyrektywa „#{0} {1}” + + The 'if' expression needs to return a tuple of length {0} of type\n {1} \nto satisfy context type requirements. It currently returns a tuple of length {2} of type\n {3} \n + The 'if' expression needs to return a tuple of length {0} of type\n {1} \nto satisfy context type requirements. It currently returns a tuple of length {2} of type\n {3} \n + + Unknown debug point '{0}'. The available debug points are '{1}'. Nieznany punkt debugowania „{0}”. Dostępnymi punktami debugowania są „{1}”. @@ -402,6 +422,11 @@ Nieprawidłowy ciąg interpolowany. Literały ciągów z potrójnymi cudzysłowami nie mogą być używane w wyrażeniach interpolowanych. Rozważ użycie jawnego powiązania „let” dla wyrażenia interpolacji. + + All elements of a list must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + All elements of a list must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + + This construct is deprecated. {0}. You can enable this feature by using '--langversion:5.0' and '--mlcompatibility'. Ta konstrukcja jest przestarzała. {0}. Tę funkcję można włączyć przy użyciu poleceń"--langversion:5.0" i "--mlcompatibility". diff --git a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf index 41465827411..ad6c10e2b8f 100644 --- a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf +++ b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf @@ -2,6 +2,11 @@ + + All elements of an array must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + All elements of an array must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + + The file extension of '{0}' is not recognized. Source files must have extension .fs, .fsi, .fsx or .fsscript. To enable the deprecated use of .ml or .mli extensions, use '--langversion:5.0' and '--mlcompatibility'. A extensão do arquivo '{0}' não foi reconhecida. Os arquivos de origem devem ter a extensão .fs, .fsi, .fsx ou .fsscript. Para ativar o uso preterido das extensões .ml ou .mli, use '--langversion:5.0' e '--mlcompatibility'. @@ -102,6 +107,11 @@ O argumento '{0}' não corresponde + + All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + + The type provider designer assembly '{0}' could not be loaded from folder '{1}' because a dependency was missing or could not loaded. All dependencies of the type provider designer assembly must be located in the same folder as that assembly. The exception reported was: {2} - {3} Não foi possível carregar o assembly do designer do provedor de tipos '{0}' da pasta '{1}' porque uma dependência estava ausente ou não pôde ser carregada. Todas as dependências do assembly do designer do provedor de tipos precisam estar localizadas na mesma pasta que esse assembly. A exceção relatada foi: {2} – {3} @@ -307,6 +317,11 @@ Passagem de testemunha para restrições de característica nas citações do F# + + All branches of a pattern match expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + All branches of a pattern match expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + + Interpolated strings may not use '%' format specifiers unless each is given an expression, e.g. '%d{{1+1}}'. As cadeias de caracteres interpoladas não podem usar especificadores de formato '%', a menos que cada um receba uma expressão, por exemplo, '%d{{1+1}}'. @@ -347,6 +362,11 @@ Diretriz inválida '#{0} {1}' + + The 'if' expression needs to return a tuple of length {0} of type\n {1} \nto satisfy context type requirements. It currently returns a tuple of length {2} of type\n {3} \n + The 'if' expression needs to return a tuple of length {0} of type\n {1} \nto satisfy context type requirements. It currently returns a tuple of length {2} of type\n {3} \n + + Unknown debug point '{0}'. The available debug points are '{1}'. Ponto de depuração desconhecido '{0}'. Os pontos de depuração disponíveis são '{1}'. @@ -402,6 +422,11 @@ Cadeia de caracteres interpolada inválida. Literais de cadeia de caracteres de aspas triplas não podem ser usados em expressões interpoladas. Considere usar uma associação 'let' explícita para a expressão de interpolação. + + All elements of a list must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + All elements of a list must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + + This construct is deprecated. {0}. You can enable this feature by using '--langversion:5.0' and '--mlcompatibility'. Esta construção foi preterida. {0} Você pode habilitar este recurso usando '--langversion:5.0' e '--mlcompatibility'. diff --git a/src/Compiler/xlf/FSComp.txt.ru.xlf b/src/Compiler/xlf/FSComp.txt.ru.xlf index 303abbe53e7..d66df6dddcb 100644 --- a/src/Compiler/xlf/FSComp.txt.ru.xlf +++ b/src/Compiler/xlf/FSComp.txt.ru.xlf @@ -2,6 +2,11 @@ + + All elements of an array must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + All elements of an array must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + + The file extension of '{0}' is not recognized. Source files must have extension .fs, .fsi, .fsx or .fsscript. To enable the deprecated use of .ml or .mli extensions, use '--langversion:5.0' and '--mlcompatibility'. Расширение файла "{0}" не распознано. Исходные файлы должны иметь расширения FS, FSI, FSX или FSSCRIPT. Чтобы включить использование нерекомендуемых расширений ML или MLI, примените команду "--langversion:5.0" и "--mlcompatibility". @@ -102,6 +107,11 @@ Аргумент "{0}" не соответствует + + All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + + The type provider designer assembly '{0}' could not be loaded from folder '{1}' because a dependency was missing or could not loaded. All dependencies of the type provider designer assembly must be located in the same folder as that assembly. The exception reported was: {2} - {3} Не удалось загрузить сборку конструктора поставщика типа "{0}" из папки "{1}", так как зависимость отсутствует или не может быть загружена. Все зависимости для сборки конструктора поставщика типа должны находиться в папке сборки. Получено исключение: {2} — {3} @@ -307,6 +317,11 @@ Передача свидетеля для ограничений признаков в цитированиях F# + + All branches of a pattern match expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + All branches of a pattern match expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + + Interpolated strings may not use '%' format specifiers unless each is given an expression, e.g. '%d{{1+1}}'. В интерполированных строках запрещено использовать описатели формата "%", если только каждому из них не назначено выражение, например "'%d{{1+1}}". @@ -347,6 +362,11 @@ Недопустимая директива "#{0} {1}" + + The 'if' expression needs to return a tuple of length {0} of type\n {1} \nto satisfy context type requirements. It currently returns a tuple of length {2} of type\n {3} \n + The 'if' expression needs to return a tuple of length {0} of type\n {1} \nto satisfy context type requirements. It currently returns a tuple of length {2} of type\n {3} \n + + Unknown debug point '{0}'. The available debug points are '{1}'. Неизвестная точка отладки \"{0}\". Доступные точки отладки: \"{1}\". @@ -402,6 +422,11 @@ Недопустимая интерполированная строка. Строковые литералы с тройными кавычками запрещено использовать в интерполированных выражениях. Рекомендуется использовать явную привязку "let" для выражения интерполяции. + + All elements of a list must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + All elements of a list must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + + This construct is deprecated. {0}. You can enable this feature by using '--langversion:5.0' and '--mlcompatibility'. Эта конструкция не рекомендуется к использованию. {0}. Вы можете включить эту функцию с помощью команд "--langversion:5.0" и "--mlcompatibility". diff --git a/src/Compiler/xlf/FSComp.txt.tr.xlf b/src/Compiler/xlf/FSComp.txt.tr.xlf index d3e695d0686..f724c4e9901 100644 --- a/src/Compiler/xlf/FSComp.txt.tr.xlf +++ b/src/Compiler/xlf/FSComp.txt.tr.xlf @@ -2,6 +2,11 @@ + + All elements of an array must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + All elements of an array must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + + The file extension of '{0}' is not recognized. Source files must have extension .fs, .fsi, .fsx or .fsscript. To enable the deprecated use of .ml or .mli extensions, use '--langversion:5.0' and '--mlcompatibility'. '{0}' kaynak dosyasının dosya uzantısı tanınmadı. Kaynak dosyaların uzantısı .fs, .fsi, .fsx veya .fsscript olmalıdır. Kullanım dışı .ml veya .mli uzantılarını etkinleştirmek için '--langversion:5.0' ve '--mlcompatibility' kullanın. @@ -102,6 +107,11 @@ '{0}' bağımsız değişkeni eşleşmiyor + + All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + + The type provider designer assembly '{0}' could not be loaded from folder '{1}' because a dependency was missing or could not loaded. All dependencies of the type provider designer assembly must be located in the same folder as that assembly. The exception reported was: {2} - {3} '{0}' tür sağlayıcısı tasarımcı bütünleştirilmiş kodu, bir bağımlılık eksik olduğundan veya yüklenemediğinden '{1}' klasöründen yüklenemedi. Tür sağlayıcısı tasarımcısı bütünleştirilmiş kodunun tüm bağımlılıkları, ilgili bütünleştirilmiş kodun bulunduğu klasörde bulunmalıdır. Bildirilen özel durum: {2} - {3} @@ -307,6 +317,11 @@ F# alıntılarındaki nitelik kısıtlamaları için tanık geçirme + + All branches of a pattern match expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + All branches of a pattern match expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + + Interpolated strings may not use '%' format specifiers unless each is given an expression, e.g. '%d{{1+1}}'. Düz metin arasına kod eklenmiş dizeler, her birine '%d{{1+1}}' gibi bir ifade verilmedikçe '%' biçim belirticilerini kullanamaz. @@ -347,6 +362,11 @@ Geçersiz yönerge '#{0} {1}' + + The 'if' expression needs to return a tuple of length {0} of type\n {1} \nto satisfy context type requirements. It currently returns a tuple of length {2} of type\n {3} \n + The 'if' expression needs to return a tuple of length {0} of type\n {1} \nto satisfy context type requirements. It currently returns a tuple of length {2} of type\n {3} \n + + Unknown debug point '{0}'. The available debug points are '{1}'. Bilinmeyen hata ayıklama noktası '{0}'. Kullanılabilir hata ayıklama noktaları '{1}'. @@ -402,6 +422,11 @@ Geçersiz düz metin arasına kod eklenmiş dize. Üç tırnaklı dize sabitleri, düz metin arasına kod eklenmiş ifadelerde kullanılamaz. Düz metin arasına kod ekleme ifadesi için açık bir 'let' bağlaması kullanmayı düşünün. + + All elements of a list must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + All elements of a list must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + + This construct is deprecated. {0}. You can enable this feature by using '--langversion:5.0' and '--mlcompatibility'. Bu yapı kullanım dışı. {0}. Bu özelliği '--langversion:5.0' ve '--mlcompatibility' kullanarak etkinleştirebilirsiniz. diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf index 29db57871b0..7397a602419 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf @@ -2,6 +2,11 @@ + + All elements of an array must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + All elements of an array must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + + The file extension of '{0}' is not recognized. Source files must have extension .fs, .fsi, .fsx or .fsscript. To enable the deprecated use of .ml or .mli extensions, use '--langversion:5.0' and '--mlcompatibility'. 无法识别“{0}”的文件扩展名。源文件必须具有扩展名 .fs、.fsi、.fsx 或 .fsscript。要启用已弃用的 .ml 或 .mli 扩展名,请使用 “--langversion:5.0” 和 “--mlcompatibility”。 @@ -102,6 +107,11 @@ 参数 "{0}" 不匹配 + + All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + + The type provider designer assembly '{0}' could not be loaded from folder '{1}' because a dependency was missing or could not loaded. All dependencies of the type provider designer assembly must be located in the same folder as that assembly. The exception reported was: {2} - {3} 无法从文件夹“{1}”加载类型提供程序设计器程序集“{0}”,因为依赖项缺失或无法加载。类型提供程序设计器程序集的所有依赖项必须与该程序集位于同一文件夹中。报告的异常是: {2} - {3} @@ -307,6 +317,11 @@ F# 引号中特征约束的见证传递 + + All branches of a pattern match expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + All branches of a pattern match expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + + Interpolated strings may not use '%' format specifiers unless each is given an expression, e.g. '%d{{1+1}}'. 内插字符串不会使用 "%" 格式说明符,除非为每个字符串提供诸如 "%d{{1+1}}" 之类的表达式。 @@ -347,6 +362,11 @@ 无效的指令“#{0} {1}” + + The 'if' expression needs to return a tuple of length {0} of type\n {1} \nto satisfy context type requirements. It currently returns a tuple of length {2} of type\n {3} \n + The 'if' expression needs to return a tuple of length {0} of type\n {1} \nto satisfy context type requirements. It currently returns a tuple of length {2} of type\n {3} \n + + Unknown debug point '{0}'. The available debug points are '{1}'. 调试点“{0}”未知。可用的调试点为“{1}”。 @@ -402,6 +422,11 @@ 内插字符串无效。在内插表达式中不能使用三重引号字符串文字。请考虑对内插表达式使用显式的 "let" 绑定。 + + All elements of a list must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + All elements of a list must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + + This construct is deprecated. {0}. You can enable this feature by using '--langversion:5.0' and '--mlcompatibility'. 此构造已弃用。{0}。可以通过使用 “--langversion:5.0” 和 “--mlcompatibility” 启用此功能。 diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf index 45bf1a52370..97f067dd474 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf @@ -2,6 +2,11 @@ + + All elements of an array must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + All elements of an array must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + + The file extension of '{0}' is not recognized. Source files must have extension .fs, .fsi, .fsx or .fsscript. To enable the deprecated use of .ml or .mli extensions, use '--langversion:5.0' and '--mlcompatibility'. 無法辨識 '{0}' 的副檔名。來源檔案的副檔名必須是 fsi、.fsx 或 .fsscript。若要啟用已被取代的 .ml 或 .mli 副檔名,請使用 '--langversion:5.0' and '--mlcompatibility'。 @@ -102,6 +107,11 @@ 引數 '{0}' 不相符 + + All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + + The type provider designer assembly '{0}' could not be loaded from folder '{1}' because a dependency was missing or could not loaded. All dependencies of the type provider designer assembly must be located in the same folder as that assembly. The exception reported was: {2} - {3} 因為缺少相依性或相依性無法載入,導致無法從資料夾 '{1}' 載入類型提供者設計工具組件 '{0}'。類型提供者設計工具組件的所有相依性都必須位於該組件所在的資料夾內。回報的例外狀況: {2} - {3} @@ -307,6 +317,11 @@ 見證 F# 引號中特徵條件約束的傳遞 + + All branches of a pattern match expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + All branches of a pattern match expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length {0} of type\n {1} \nThis branch returns a tuple of length {2} of type\n {3} \n + + Interpolated strings may not use '%' format specifiers unless each is given an expression, e.g. '%d{{1+1}}'. 除非每個插補字串都有一個運算式,否則不可使用 '%' 格式指定名稱,例如 '%d{{1+1}}'。 @@ -347,6 +362,11 @@ 無效的指示詞 '#{0} {1}' + + The 'if' expression needs to return a tuple of length {0} of type\n {1} \nto satisfy context type requirements. It currently returns a tuple of length {2} of type\n {3} \n + The 'if' expression needs to return a tuple of length {0} of type\n {1} \nto satisfy context type requirements. It currently returns a tuple of length {2} of type\n {3} \n + + Unknown debug point '{0}'. The available debug points are '{1}'. 未知的偵錯點 '{0}'。可用的偵錯點為 '{1}'。 @@ -402,6 +422,11 @@ 插補字串無效。三引號字串常值不可用於插補運算式。請考慮為內插補點運算式使用明確的 'let' 繫結。 + + All elements of a list must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + All elements of a list must be implicitly convertible to the type of the first element, which here is a tuple of length {0} of type\n {1} \nThis element is a tuple of length {2} of type\n {3} \n + + This construct is deprecated. {0}. You can enable this feature by using '--langversion:5.0' and '--mlcompatibility'. 此建構已被取代。{0}。您可以使用 '--langversion:5.0' and '--mlcompatibility' 來啟用此功能。 diff --git a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeMismatchTests.fs b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeMismatchTests.fs index 9447c8821f8..7a64b56dabf 100644 --- a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeMismatchTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeMismatchTests.fs @@ -104,6 +104,74 @@ let test x = "Type mismatch. Expecting a tuple of length 3 of type\n int * string * char \nbut given a tuple of length 2 of type\n int * char \n") ] + [] + let ``Else branch context``() = + FSharp """ +let f1(a, b: string, c) = + if true then (1, 2) else (a, b, c) + """ + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Error 1, Line 3, Col 31, Line 3, Col 38, + "All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length 2 of type\n int * int \nThis branch returns a tuple of length 3 of type\n 'a * string * 'b \n") + ] + + [] + let ``Match branch context``() = + FSharp """ +let f x = + match x with + | 0 -> 0, 0, 0 + | _ -> "a", "a" + """ + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Error 1, Line 5, Col 12, Line 5, Col 20, + "All branches of a pattern match expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length 3 of type\n int * int * int \nThis branch returns a tuple of length 2 of type\n string * string \n") + ] + + [] + let ``If context`` () = + FSharp """ +let y : bool * int * int = + if true then "A", "B" + else "B", "C" + """ + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Error 1, Line 3, Col 18, Line 3, Col 26, + "The 'if' expression needs to return a tuple of length 3 of type\n bool * int * int \nto satisfy context type requirements. It currently returns a tuple of length 2 of type\n string * string \n") + (Error 1, Line 4, Col 10, Line 4, Col 18, + "All branches of an 'if' expression must return values implicitly convertible to the type of the first branch, which here is a tuple of length 3 of type\n bool * int * int \nThis branch returns a tuple of length 2 of type\n string * string \n") + ] + + [] + let ``Array context`` () = + FSharp """ +let f x y = [| 1, 2; x, "a", y |] + """ + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Error 1, Line 2, Col 22, Line 2, Col 31, + "All elements of an array must be implicitly convertible to the type of the first element, which here is a tuple of length 2 of type\n int * int \nThis element is a tuple of length 3 of type\n 'a * string * 'b \n") + ] + + [] + let ``List context`` () = + FSharp """ +let f x y = [ 1, 2; x, "a", y ] + """ + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Error 1, Line 2, Col 21, Line 2, Col 30, + "All elements of a list must be implicitly convertible to the type of the first element, which here is a tuple of length 2 of type\n int * int \nThis element is a tuple of length 3 of type\n 'a * string * 'b \n") + ] + [] let ``return Instead Of return!``() = FSharp """ From d9d840ed26831173b3e6eb21713db5af49d65a71 Mon Sep 17 00:00:00 2001 From: Petr Pokorny Date: Tue, 11 Oct 2022 10:35:24 +0200 Subject: [PATCH 16/19] fantomas after merge --- src/Compiler/Driver/CompilerDiagnostics.fs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Compiler/Driver/CompilerDiagnostics.fs b/src/Compiler/Driver/CompilerDiagnostics.fs index d90f3f0d969..b518ea9338d 100644 --- a/src/Compiler/Driver/CompilerDiagnostics.fs +++ b/src/Compiler/Driver/CompilerDiagnostics.fs @@ -740,6 +740,7 @@ type Exception with | ErrorFromAddingTypeEquation (_g, denv, ty1, ty2, ConstraintSolverTupleDiffLengths (_, tl1, tl2, _, _), _) -> let ty1, ty2, tpcs = NicePrint.minimalStringsOfTwoTypes denv ty1 ty2 + if ty1 <> ty2 + tpcs then os.AppendString(ErrorFromAddingTypeEquationTuplesE().Format tl1.Length ty1 tl2.Length ty2 tpcs) From cc56c30a1c5c0564cba8a92ed5dedba2bb479a42 Mon Sep 17 00:00:00 2001 From: Petr Pokorny Date: Mon, 17 Oct 2022 13:30:42 +0200 Subject: [PATCH 17/19] Applied review suggestions --- src/Compiler/Checking/CheckExpressions.fs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs index 0c5c478be42..f3b1e9ca645 100644 --- a/src/Compiler/Checking/CheckExpressions.fs +++ b/src/Compiler/Checking/CheckExpressions.fs @@ -5288,13 +5288,13 @@ and TcExprThenDynamic (cenv: cenv) overallTy env tpenv isArg e1 mQmark e2 delaye TcExprThen cenv overallTy env tpenv isArg appExpr delayed -and TcExprsWithFlexes (cenv: cenv) env m tpenv flexes argTys args = - if List.length args <> List.length argTys then error(Error(FSComp.SR.tcExpressionCountMisMatch((List.length argTys), (List.length args)), m)) +and TcExprsWithFlexes (cenv: cenv) env m tpenv flexes (argTys: TType list) (args: SynExpr list) = + if args.Length <> argTys.Length then error(Error(FSComp.SR.tcExpressionCountMisMatch((argTys.Length), (args.Length)), m)) (tpenv, List.zip3 flexes argTys args) ||> List.mapFold (fun tpenv (flex, ty, e) -> TcExprFlex cenv flex false ty env tpenv e) -and TcExprsNoFlexes (cenv: cenv) env m tpenv argTys args = - if List.length args <> List.length argTys then error(Error(FSComp.SR.tcExpressionCountMisMatch((List.length argTys), (List.length args)), m)) +and TcExprsNoFlexes (cenv: cenv) env m tpenv (argTys: TType list) (args: SynExpr list) = + if args.Length <> argTys.Length then error(Error(FSComp.SR.tcExpressionCountMisMatch((argTys.Length), (args.Length)), m)) (tpenv, List.zip argTys args) ||> List.mapFold (fun tpenv (ty, e) -> TcExprFlex2 cenv ty env false tpenv e) @@ -5804,13 +5804,13 @@ and TcExprLazy (cenv: cenv) overallTy env tpenv (synInnerExpr, m) = let expr = mkLazyDelayed g m innerTy (mkUnitDelayLambda g m innerExpr) expr, tpenv -and CheckTupleIsCorrectLength g (env: TcEnv) m tupleTy args typeCheckArgs = +and CheckTupleIsCorrectLength g (env: TcEnv) m tupleTy (args: 'a list) tcArgs = if isAnyTupleTy g tupleTy then let tupInfo, ptys = destAnyTupleTy g tupleTy - if List.length args <> List.length ptys then + if args.Length <> ptys.Length then let argTys = NewInferenceTypes g args - suppressErrorReporting (fun () -> typeCheckArgs argTys) + suppressErrorReporting (fun () -> tcArgs argTys) let expectedTy = TType_tuple (tupInfo, argTys) // We let error recovery handle this exception From 2c7656beefd59d8b73326ed9c119cfb845bc831a Mon Sep 17 00:00:00 2001 From: Petr Pokorny Date: Mon, 17 Oct 2022 13:48:44 +0200 Subject: [PATCH 18/19] Fix signature file --- src/Compiler/Checking/CheckExpressions.fsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Compiler/Checking/CheckExpressions.fsi b/src/Compiler/Checking/CheckExpressions.fsi index 6c86f8b4525..11f0ff1ccb0 100644 --- a/src/Compiler/Checking/CheckExpressions.fsi +++ b/src/Compiler/Checking/CheckExpressions.fsi @@ -624,7 +624,7 @@ val TcExpr: Expr * UnscopedTyparEnv /// Check that 'args' have the correct number of elements for a tuple expression. -/// If not, use 'typeCheckArgs' to type check the given elements to show +/// If not, use 'tcArgs' to type check the given elements to show /// their correct types (if known) in the error message and raise the error val CheckTupleIsCorrectLength: g: TcGlobals -> @@ -632,7 +632,7 @@ val CheckTupleIsCorrectLength: m: range -> tupleTy: TType -> args: 'a list -> - typeCheckArgs: (TType list -> unit) -> + tcArgs: (TType list -> unit) -> unit /// Converts 'a..b' to a call to the '(..)' operator in FSharp.Core From 41893dbc47481d019efea4e829d7e918f2a831f9 Mon Sep 17 00:00:00 2001 From: Petr Pokorny Date: Mon, 17 Oct 2022 13:52:47 +0200 Subject: [PATCH 19/19] fantomas --- src/Compiler/Checking/CheckExpressions.fsi | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/Compiler/Checking/CheckExpressions.fsi b/src/Compiler/Checking/CheckExpressions.fsi index 11f0ff1ccb0..5c2b0b6451f 100644 --- a/src/Compiler/Checking/CheckExpressions.fsi +++ b/src/Compiler/Checking/CheckExpressions.fsi @@ -627,13 +627,7 @@ val TcExpr: /// If not, use 'tcArgs' to type check the given elements to show /// their correct types (if known) in the error message and raise the error val CheckTupleIsCorrectLength: - g: TcGlobals -> - env: TcEnv -> - m: range -> - tupleTy: TType -> - args: 'a list -> - tcArgs: (TType list -> unit) -> - unit + g: TcGlobals -> env: TcEnv -> m: range -> tupleTy: TType -> args: 'a list -> tcArgs: (TType list -> unit) -> unit /// Converts 'a..b' to a call to the '(..)' operator in FSharp.Core /// Converts 'a..b..c' to a call to the '(.. ..)' operator in FSharp.Core