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.\nNejmé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.\nMindestens 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.\nUno 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.\nUn 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.\nUno 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.\nJeden 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.\nUma 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.\nYü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