Skip to content

Commit 8ba53ff

Browse files
edgarfgp0101T-Grodsyme
authored
Wrong type is reported in type mismatch error (#13347)
Co-authored-by: Petr Pokorny <[email protected]> Co-authored-by: Tomas Grosup <[email protected]> Co-authored-by: Don Syme <[email protected]>
1 parent 0040029 commit 8ba53ff

File tree

25 files changed

+236
-57
lines changed

25 files changed

+236
-57
lines changed

src/Compiler/Checking/CheckExpressions.fs

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -590,8 +590,8 @@ let UnifyTupleTypeAndInferCharacteristics contextInfo (cenv: cenv) denv m knownT
590590
if isAnyTupleTy g knownTy then
591591
let tupInfo, ptys = destAnyTupleTy g knownTy
592592
let tupInfo = (if isExplicitStruct then tupInfoStruct else tupInfo)
593-
let ptys =
594-
if List.length ps = List.length ptys then ptys
593+
let ptys =
594+
if List.length ps = List.length ptys then ptys
595595
else NewInferenceTypes g ps
596596
tupInfo, ptys
597597
else
@@ -5288,11 +5288,16 @@ and TcExprThenDynamic (cenv: cenv) overallTy env tpenv isArg e1 mQmark e2 delaye
52885288

52895289
TcExprThen cenv overallTy env tpenv isArg appExpr delayed
52905290

5291-
and TcExprsWithFlexes (cenv: cenv) env m tpenv flexes argTys args =
5292-
if List.length args <> List.length argTys then error(Error(FSComp.SR.tcExpressionCountMisMatch((List.length argTys), (List.length args)), m))
5291+
and TcExprsWithFlexes (cenv: cenv) env m tpenv flexes (argTys: TType list) (args: SynExpr list) =
5292+
if args.Length <> argTys.Length then error(Error(FSComp.SR.tcExpressionCountMisMatch((argTys.Length), (args.Length)), m))
52935293
(tpenv, List.zip3 flexes argTys args) ||> List.mapFold (fun tpenv (flex, ty, e) ->
52945294
TcExprFlex cenv flex false ty env tpenv e)
52955295

5296+
and TcExprsNoFlexes (cenv: cenv) env m tpenv (argTys: TType list) (args: SynExpr list) =
5297+
if args.Length <> argTys.Length then error(Error(FSComp.SR.tcExpressionCountMisMatch((argTys.Length), (args.Length)), m))
5298+
(tpenv, List.zip argTys args) ||> List.mapFold (fun tpenv (ty, e) ->
5299+
TcExprFlex2 cenv ty env false tpenv e)
5300+
52965301
and CheckSuperInit (cenv: cenv) objTy m =
52975302
let g = cenv.g
52985303

@@ -5348,7 +5353,7 @@ and TcPropagatingExprLeafThenConvert (cenv: cenv) overallTy actualTy (env: TcEnv
53485353
UnifyTypes cenv env m overallTy.Commit actualTy
53495354
f ()
53505355

5351-
/// Process a leaf construct, for cases where we propogate the overall type eagerly in
5356+
/// Process a leaf construct, for cases where we propagate the overall type eagerly in
53525357
/// some cases. Then apply additional type-directed conversions.
53535358
///
53545359
/// However in some cases favour propagating characteristics of the overall type.
@@ -5360,7 +5365,7 @@ and TcPropagatingExprLeafThenConvert (cenv: cenv) overallTy actualTy (env: TcEnv
53605365
/// - tuple (except if overallTy is a tuple type or a variable type that can become one)
53615366
/// - anon record (except if overallTy is an anon record type or a variable type that can become one)
53625367
/// - record (except if overallTy is requiresCtor || haveCtor or a record type or a variable type that can become one))
5363-
and TcPossiblyPropogatingExprLeafThenConvert isPropagating (cenv: cenv) (overallTy: OverallTy) (env: TcEnv) m processExpr =
5368+
and TcPossiblyPropagatingExprLeafThenConvert isPropagating (cenv: cenv) (overallTy: OverallTy) (env: TcEnv) m processExpr =
53645369

53655370
let g = cenv.g
53665371

@@ -5538,7 +5543,7 @@ and TcExprUndelayed (cenv: cenv) (overallTy: OverallTy) env tpenv (synExpr: SynE
55385543

55395544
| SynExpr.AnonRecd (isStruct, withExprOpt, unsortedFieldExprs, mWholeExpr) ->
55405545
TcNonControlFlowExpr env <| fun env ->
5541-
TcPossiblyPropogatingExprLeafThenConvert (fun ty -> isAnonRecdTy g ty || isTyparTy g ty) cenv overallTy env mWholeExpr (fun overallTy ->
5546+
TcPossiblyPropagatingExprLeafThenConvert (fun ty -> isAnonRecdTy g ty || isTyparTy g ty) cenv overallTy env mWholeExpr (fun overallTy ->
55425547
TcAnonRecdExpr cenv overallTy env tpenv (isStruct, withExprOpt, unsortedFieldExprs, mWholeExpr)
55435548
)
55445549

@@ -5799,13 +5804,27 @@ and TcExprLazy (cenv: cenv) overallTy env tpenv (synInnerExpr, m) =
57995804
let expr = mkLazyDelayed g m innerTy (mkUnitDelayLambda g m innerExpr)
58005805
expr, tpenv
58015806

5807+
and CheckTupleIsCorrectLength g (env: TcEnv) m tupleTy (args: 'a list) tcArgs =
5808+
if isAnyTupleTy g tupleTy then
5809+
let tupInfo, ptys = destAnyTupleTy g tupleTy
5810+
5811+
if args.Length <> ptys.Length then
5812+
let argTys = NewInferenceTypes g args
5813+
suppressErrorReporting (fun () -> tcArgs argTys)
5814+
let expectedTy = TType_tuple (tupInfo, argTys)
5815+
5816+
// We let error recovery handle this exception
5817+
error (ErrorFromAddingTypeEquation(g, env.DisplayEnv, tupleTy, expectedTy,
5818+
(ConstraintSolverTupleDiffLengths(env.DisplayEnv, ptys, argTys, m, m)), m))
5819+
58025820
and TcExprTuple (cenv: cenv) overallTy env tpenv (isExplicitStruct, args, m) =
58035821
let g = cenv.g
5804-
TcPossiblyPropogatingExprLeafThenConvert (fun ty -> isAnyTupleTy g ty || isTyparTy g ty) cenv overallTy env m (fun overallTy ->
5805-
let tupInfo, argTys = UnifyTupleTypeAndInferCharacteristics env.eContextInfo cenv env.DisplayEnv m overallTy isExplicitStruct args
5822+
TcPossiblyPropagatingExprLeafThenConvert (fun ty -> isAnyTupleTy g ty || isTyparTy g ty) cenv overallTy env m (fun overallTy ->
58065823

5807-
let flexes = argTys |> List.map (fun _ -> false)
5808-
let argsR, tpenv = TcExprsWithFlexes cenv env m tpenv flexes argTys args
5824+
CheckTupleIsCorrectLength g env m overallTy args (fun argTys -> TcExprsNoFlexes cenv env m tpenv argTys args |> ignore)
5825+
5826+
let tupInfo, argTys = UnifyTupleTypeAndInferCharacteristics env.eContextInfo cenv env.DisplayEnv m overallTy isExplicitStruct args
5827+
let argsR, tpenv = TcExprsNoFlexes cenv env m tpenv argTys args
58095828
let expr = mkAnyTupled g m tupInfo argsR argTys
58105829
expr, tpenv
58115830
)
@@ -5882,7 +5901,7 @@ and TcExprRecord (cenv: cenv) overallTy env tpenv (inherits, withExprOpt, synRec
58825901
CallExprHasTypeSink cenv.tcSink (mWholeExpr, env.NameEnv, overallTy.Commit, env.AccessRights)
58835902
let requiresCtor = (GetCtorShapeCounter env = 1) // Get special expression forms for constructors
58845903
let haveCtor = Option.isSome inherits
5885-
TcPossiblyPropogatingExprLeafThenConvert (fun ty -> requiresCtor || haveCtor || isRecdTy g ty || isTyparTy g ty) cenv overallTy env mWholeExpr (fun overallTy ->
5904+
TcPossiblyPropagatingExprLeafThenConvert (fun ty -> requiresCtor || haveCtor || isRecdTy g ty || isTyparTy g ty) cenv overallTy env mWholeExpr (fun overallTy ->
58865905
TcRecdExpr cenv overallTy env tpenv (inherits, withExprOpt, synRecdFields, mWholeExpr)
58875906
)
58885907

@@ -6085,8 +6104,7 @@ and TcExprILAssembly (cenv: cenv) overallTy env tpenv (ilInstrs, synTyArgs, synA
60856104
let argTys = NewInferenceTypes g synArgs
60866105
let tyargs, tpenv = TcTypes cenv NewTyparsOK CheckCxs ItemOccurence.UseInType WarnOnIWSAM.Yes env tpenv synTyArgs
60876106
// No subsumption at uses of IL assembly code
6088-
let flexes = argTys |> List.map (fun _ -> false)
6089-
let args, tpenv = TcExprsWithFlexes cenv env m tpenv flexes argTys synArgs
6107+
let args, tpenv = TcExprsNoFlexes cenv env m tpenv argTys synArgs
60906108
let retTys, tpenv = TcTypes cenv NewTyparsOK CheckCxs ItemOccurence.UseInType WarnOnIWSAM.Yes env tpenv synRetTys
60916109
let returnTy =
60926110
match retTys with
@@ -7151,8 +7169,7 @@ and TcInterpolatedStringExpr cenv (overallTy: OverallTy) env m tpenv (parts: Syn
71517169
mkCallNewFormat g m printerTy printerArgTy printerResidueTy printerResultTy printerTupleTy str, tpenv
71527170
else
71537171
// Type check the expressions filling the holes
7154-
let flexes = argTys |> List.map (fun _ -> false)
7155-
let fillExprs, tpenv = TcExprsWithFlexes cenv env m tpenv flexes argTys synFillExprs
7172+
let fillExprs, tpenv = TcExprsNoFlexes cenv env m tpenv argTys synFillExprs
71567173

71577174
let fillExprsBoxed = (argTys, fillExprs) ||> List.map2 (mkCallBox g m)
71587175

@@ -7178,8 +7195,7 @@ and TcInterpolatedStringExpr cenv (overallTy: OverallTy) env m tpenv (parts: Syn
71787195
| Choice2Of2 createFormattableStringMethod ->
71797196

71807197
// Type check the expressions filling the holes
7181-
let flexes = argTys |> List.map (fun _ -> false)
7182-
let fillExprs, tpenv = TcExprsWithFlexes cenv env m tpenv flexes argTys synFillExprs
7198+
let fillExprs, tpenv = TcExprsNoFlexes cenv env m tpenv argTys synFillExprs
71837199

71847200
let fillExprsBoxed = (argTys, fillExprs) ||> List.map2 (mkCallBox g m)
71857201

src/Compiler/Checking/CheckExpressions.fsi

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,12 @@ val TcExpr:
623623
synExpr: SynExpr ->
624624
Expr * UnscopedTyparEnv
625625

626+
/// Check that 'args' have the correct number of elements for a tuple expression.
627+
/// If not, use 'tcArgs' to type check the given elements to show
628+
/// their correct types (if known) in the error message and raise the error
629+
val CheckTupleIsCorrectLength:
630+
g: TcGlobals -> env: TcEnv -> m: range -> tupleTy: TType -> args: 'a list -> tcArgs: (TType list -> unit) -> unit
631+
626632
/// Converts 'a..b' to a call to the '(..)' operator in FSharp.Core
627633
/// Converts 'a..b..c' to a call to the '(.. ..)' operator in FSharp.Core
628634
val RewriteRangeExpr: synExpr: SynExpr -> SynExpr option

src/Compiler/Checking/CheckPatterns.fs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,8 @@ and TcPatAnds warnOnUpper cenv env vFlags patEnv ty pats m =
423423
and TcPatTuple warnOnUpper cenv env vFlags patEnv ty isExplicitStruct args m =
424424
let g = cenv.g
425425
try
426+
CheckTupleIsCorrectLength g env m ty args (fun argTys -> TcPatterns warnOnUpper cenv env vFlags patEnv argTys args |> ignore)
427+
426428
let tupInfo, argTys = UnifyTupleTypeAndInferCharacteristics env.eContextInfo cenv env.DisplayEnv m ty isExplicitStruct args
427429
let argsR, acc = TcPatterns warnOnUpper cenv env vFlags patEnv argTys args
428430
let phase2 values = TPat_tuple(tupInfo, List.map (fun f -> f values) argsR, argTys, m)

src/Compiler/Checking/ConstraintSolver.fs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1225,9 +1225,9 @@ and SolveTypeEqualsTypeEqns csenv ndeep m2 trace cxsln origl1 origl2 =
12251225
let rec loop l1 l2 =
12261226
match l1, l2 with
12271227
| [], [] -> CompleteD
1228-
| h1 :: t1, h2 :: t2 ->
1228+
| h1 :: t1, h2 :: t2 when t1.Length = t2.Length ->
12291229
SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m2 trace cxsln h1 h2 ++ (fun () -> loop t1 t2)
1230-
| _ ->
1230+
| _ ->
12311231
ErrorD(ConstraintSolverTupleDiffLengths(csenv.DisplayEnv, origl1, origl2, csenv.m, m2))
12321232
loop origl1 origl2
12331233

src/Compiler/Driver/CompilerDiagnostics.fs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,7 @@ module OldStyleMessages =
440440
let ConstraintSolverTypesNotInSubsumptionRelationE () = Message("ConstraintSolverTypesNotInSubsumptionRelation", "%s%s%s")
441441
let ErrorFromAddingTypeEquation1E () = Message("ErrorFromAddingTypeEquation1", "%s%s%s")
442442
let ErrorFromAddingTypeEquation2E () = Message("ErrorFromAddingTypeEquation2", "%s%s%s")
443+
let ErrorFromAddingTypeEquationTuplesE () = Message("ErrorFromAddingTypeEquationTuples", "%d%s%d%s%s")
443444
let ErrorFromApplyingDefault1E () = Message("ErrorFromApplyingDefault1", "%s")
444445
let ErrorFromApplyingDefault2E () = Message("ErrorFromApplyingDefault2", "")
445446
let ErrorsFromAddingSubsumptionConstraintE () = Message("ErrorsFromAddingSubsumptionConstraint", "%s%s%s")
@@ -737,6 +738,12 @@ type Exception with
737738

738739
| ErrorFromAddingTypeEquation(error = ConstraintSolverError _ as e) -> e.Output(os, suggestNames)
739740

741+
| ErrorFromAddingTypeEquation (_g, denv, ty1, ty2, ConstraintSolverTupleDiffLengths (_, tl1, tl2, _, _), _) ->
742+
let ty1, ty2, tpcs = NicePrint.minimalStringsOfTwoTypes denv ty1 ty2
743+
744+
if ty1 <> ty2 + tpcs then
745+
os.AppendString(ErrorFromAddingTypeEquationTuplesE().Format tl1.Length ty1 tl2.Length ty2 tpcs)
746+
740747
| ErrorFromAddingTypeEquation (g, denv, ty1, ty2, e, _) ->
741748
if not (typeEquiv g ty1 ty2) then
742749
let ty1, ty2, tpcs = NicePrint.minimalStringsOfTwoTypes denv ty1 ty2

src/Compiler/FSStrings.resx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,7 @@
573573
<data name="Parser.TOKEN.AND" xml:space="preserve">
574574
<value>keyword 'and'</value>
575575
</data>
576-
!<data name="Parser.TOKEN.AND.BANG" xml:space="preserve">
576+
<data name="Parser.TOKEN.AND.BANG" xml:space="preserve">
577577
<value>keyword 'and!'</value>
578578
</data>
579579
<data name="Parser.TOKEN.AS" xml:space="preserve">
@@ -907,7 +907,7 @@
907907
<value>This expression is a function value, i.e. is missing arguments. Its type is {0}.</value>
908908
</data>
909909
<data name="UnitTypeExpected" xml:space="preserve">
910-
<value>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'.</value>
910+
<value>The result of this expression has type '{0}' and is implicitly ignored. Consider using 'ignore' to discard this value explicitly, e.g. 'expr |&gt; ignore', or 'let' to bind the result to a name, e.g. 'let result = expr'.</value>
911911
</data>
912912
<data name="UnitTypeExpectedWithEquality" xml:space="preserve">
913913
<value>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'.</value>
@@ -1110,4 +1110,7 @@
11101110
<data name="NotUpperCaseConstructorWithoutRQA" xml:space="preserve">
11111111
<value>Lowercase discriminated union cases are only allowed when using RequireQualifiedAccess attribute</value>
11121112
</data>
1113+
<data name="ErrorFromAddingTypeEquationTuples" xml:space="preserve">
1114+
<value>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</value>
1115+
</data>
11131116
</root>

src/Compiler/Facilities/DiagnosticsLogger.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -614,7 +614,7 @@ let conditionallySuppressErrorReporting cond f =
614614
//------------------------------------------------------------------------
615615
// Errors as data: Sometimes we have to reify errors as data, e.g. if backtracking
616616

617-
/// The result type of a computational modality to colelct warnings and possibly fail
617+
/// The result type of a computational modality to collect warnings and possibly fail
618618
[<NoEquality; NoComparison>]
619619
type OperationResult<'T> =
620620
| OkResult of warnings: exn list * result: 'T

src/Compiler/xlf/FSStrings.cs.xlf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
33
<file datatype="xml" source-language="en" target-language="cs" original="../FSStrings.resx">
44
<body>
5+
<trans-unit id="ErrorFromAddingTypeEquationTuples">
6+
<source>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</source>
7+
<target state="new">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</target>
8+
<note />
9+
</trans-unit>
510
<trans-unit id="HashLoadedSourceHasIssues0">
611
<source>One or more informational messages in loaded file.\n</source>
712
<target state="translated">Nejméně jedna informační zpráva v načteném souboru\n</target>

src/Compiler/xlf/FSStrings.de.xlf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
33
<file datatype="xml" source-language="en" target-language="de" original="../FSStrings.resx">
44
<body>
5+
<trans-unit id="ErrorFromAddingTypeEquationTuples">
6+
<source>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</source>
7+
<target state="new">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</target>
8+
<note />
9+
</trans-unit>
510
<trans-unit id="HashLoadedSourceHasIssues0">
611
<source>One or more informational messages in loaded file.\n</source>
712
<target state="translated">Mindestens eine Informationsmeldung in der geladenen Datei.\n</target>

src/Compiler/xlf/FSStrings.es.xlf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
33
<file datatype="xml" source-language="en" target-language="es" original="../FSStrings.resx">
44
<body>
5+
<trans-unit id="ErrorFromAddingTypeEquationTuples">
6+
<source>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</source>
7+
<target state="new">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</target>
8+
<note />
9+
</trans-unit>
510
<trans-unit id="HashLoadedSourceHasIssues0">
611
<source>One or more informational messages in loaded file.\n</source>
712
<target state="translated">Uno o más mensajes informativos en el archivo cargado.\n</target>

0 commit comments

Comments
 (0)