diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs index ea02aca3f03..f3b1e9ca645 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 @@ -5288,11 +5288,16 @@ 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: 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) + and CheckSuperInit (cenv: cenv) objTy m = let g = cenv.g @@ -5348,7 +5353,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. @@ -5360,7 +5365,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 @@ -5538,7 +5543,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) ) @@ -5799,13 +5804,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: 'a list) tcArgs = + if isAnyTupleTy g tupleTy then + let tupInfo, ptys = destAnyTupleTy g tupleTy + + if args.Length <> ptys.Length then + let argTys = NewInferenceTypes g args + suppressErrorReporting (fun () -> tcArgs 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 - 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 + TcPossiblyPropagatingExprLeafThenConvert (fun ty -> isAnyTupleTy g ty || isTyparTy g ty) cenv overallTy env m (fun overallTy -> - let flexes = argTys |> List.map (fun _ -> false) - let argsR, tpenv = TcExprsWithFlexes cenv env m tpenv flexes argTys args + 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 argsR, tpenv = TcExprsNoFlexes cenv env m tpenv argTys args let expr = mkAnyTupled g m tupInfo argsR argTys expr, tpenv ) @@ -5882,7 +5901,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) ) @@ -6085,8 +6104,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 @@ -7151,8 +7169,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) @@ -7178,8 +7195,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..5c2b0b6451f 100644 --- a/src/Compiler/Checking/CheckExpressions.fsi +++ b/src/Compiler/Checking/CheckExpressions.fsi @@ -623,6 +623,12 @@ val TcExpr: synExpr: SynExpr -> Expr * UnscopedTyparEnv +/// Check that 'args' have the correct number of elements for a tuple expression. +/// 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 + /// 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 87b0678b69c..2767cca37de 100644 --- a/src/Compiler/Checking/CheckPatterns.fs +++ b/src/Compiler/Checking/CheckPatterns.fs @@ -423,6 +423,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/src/Compiler/Checking/ConstraintSolver.fs b/src/Compiler/Checking/ConstraintSolver.fs index c69db854c24..9f35a8a52aa 100644 --- a/src/Compiler/Checking/ConstraintSolver.fs +++ b/src/Compiler/Checking/ConstraintSolver.fs @@ -1225,9 +1225,9 @@ and SolveTypeEqualsTypeEqns csenv ndeep m2 trace cxsln origl1 origl2 = let rec loop l1 l2 = match l1, l2 with | [], [] -> CompleteD - | h1 :: t1, h2 :: t2 -> + | 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 diff --git a/src/Compiler/Driver/CompilerDiagnostics.fs b/src/Compiler/Driver/CompilerDiagnostics.fs index 6314212327a..b518ea9338d 100644 --- a/src/Compiler/Driver/CompilerDiagnostics.fs +++ b/src/Compiler/Driver/CompilerDiagnostics.fs @@ -440,6 +440,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") @@ -737,6 +738,12 @@ 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) + | 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/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/Facilities/DiagnosticsLogger.fs b/src/Compiler/Facilities/DiagnosticsLogger.fs index 8bf00bef80f..af937a28151 100644 --- a/src/Compiler/Facilities/DiagnosticsLogger.fs +++ b/src/Compiler/Facilities/DiagnosticsLogger.fs @@ -614,7 +614,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/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/Conformance/DeclarationElements/LetBindings/Basic/Basic.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/DeclarationElements/LetBindings/Basic/Basic.fs index c472ec9b0ea..a357441a2f1 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 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 diff --git a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeMismatchTests.fs b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeMismatchTests.fs index 24adc58d391..9447c8821f8 100644 --- a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeMismatchTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeMismatchTests.fs @@ -7,6 +7,103 @@ open FSharp.Test.Compiler module ``Type Mismatch`` = + module ``Different tuple lengths`` = + + [] + let ``Known type on the left``() = + FSharp """ +let x a b c : int * int = a, b, c + """ + |> typecheck + |> shouldFail + |> withDiagnostics [ + (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 ``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 """ +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 tuple of length 3 of type\n 'a * 'b * 'c \nbut given a tuple of length 2 of type\n int * string \n") + ] + + [] + let ``Known types on both sides``() = + 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 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") + ] + + [] + 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/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' 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..25f330533ba 100644 --- a/tests/fsharpqa/Source/Conformance/PatternMatching/Tuple/env.lst +++ b/tests/fsharpqa/Source/Conformance/PatternMatching/Tuple/env.lst @@ -3,5 +3,3 @@ 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