on master help sign in
show error properly on arity mismatched function types

Fix https://github.com/elm/compiler/issues/1898 There was a bug in toGreedyMatchHelp that dropped longerDocs when things lined up in a pretty common way. I ended up deciding to just make the whole type show as different, and then add a HINT that it has too many (or too few) arguments.

commita5febad184588ae79b404d22a020020408580041 authorEvan Czaplicki <evancz@users.noreply.github.com> dateTue 2 Jul 2019, 16:45 (7 years ago) parent72c83e2
2 files changed+13−123
compiler/src/Reporting/Error/Type.hs+7−2 compiler/src/Type/Error.hs+6−121
compiler/src/Reporting/Error/Type.hs+7−2
@@ -435,8 +435,13 @@ problemToHint problem =
435435 [ D.toSimpleHint "Did you forget to add [] around it?"
436436 ]
437437
438− T.MissingArgs _ -> []
439− T.ReturnMismatch -> []
438+ T.ArityMismatch x y ->
439+ [ D.toSimpleHint $
440+ if x < y then
441+ "It looks like it takes too few arguments. I was expecting " ++ show (y - x) ++ " more."
442+ else
443+ "It looks like it takes too many arguments. I see " ++ show (x - y) ++ " extra."
444+ ]
440445
441446 T.BadFlexSuper direction super _ tipe ->
442447 case tipe of
compiler/src/Type/Error.hs+6−121
@@ -176,8 +176,7 @@ data Problem
176176 | AnythingToBool
177177 | AnythingFromMaybe
178178 | AnythingToList
179− | MissingArgs Int
180− | ReturnMismatch
179+ | ArityMismatch Int Int
181180 | BadFlexSuper Direction Super Name.Name Type
182181 | BadRigidVar Name.Name Type
183182 | BadRigidSuper Super Name.Name Type
@@ -255,7 +254,11 @@ toDiff localizer ctx tipe1 tipe2 =
255254 <*> toDiff localizer RT.Func b y
256255 <*> sequenceA (zipWith (toDiff localizer RT.Func) cs zs)
257256 else
258− diffLambda localizer ctx a b cs x y zs
257+ let f = toDoc localizer RT.Func in
258+ different
259+ (D.dullyellow (RT.lambda ctx (f a) (f b) (map f cs)))
260+ (D.dullyellow (RT.lambda ctx (f x) (f y) (map f zs)))
261+ (Bag.one (ArityMismatch (2 + length cs) (2 + length zs)))
259262
260263 (Tuple a b Nothing, Tuple x y Nothing) ->
261264 RT.tuple
@@ -477,124 +480,6 @@ diffAliasedRecord localizer t1 t2 =
477480
478481
479482
480−-- DIFF LAMBDAS
481−
482−
483−--
484−-- INVARIANTS:
485−-- length cs1 /= length cs2
486−--
487−diffLambda :: L.Localizer -> RT.Context -> Type -> Type -> [Type] -> Type -> Type -> [Type] -> Diff D.Doc
488−diffLambda localizer ctx a1 b1 cs1 a2 b2 cs2 =
489− let
490− (result1:revArgs1) = reverse (a1:b1:cs1)
491− (result2:revArgs2) = reverse (a2:b2:cs2)
492−
493− numArgs1 = length revArgs1
494− numArgs2 = length revArgs2
495− in
496− case toDiff localizer RT.Func result1 result2 of
497− Diff resultDoc1 resultDoc2 Similar ->
498− if numArgs1 < numArgs2 then
499− diffArgMismatch localizer ctx revArgs1 resultDoc1 revArgs2 resultDoc2
500−
501− else
502− diffArgMismatch localizer ctx revArgs2 resultDoc2 revArgs1 resultDoc1
503−
504− Diff resultDoc1 resultDoc2 (Different problems) ->
505− let
506− (a:b:cs) = reverse (resultDoc1 : map (toDoc localizer RT.Func) revArgs1)
507− (x:y:zs) = reverse (resultDoc2 : map (toDoc localizer RT.Func) revArgs2)
508− in
509− different
510− (D.dullyellow (RT.lambda ctx a b cs))
511− (D.dullyellow (RT.lambda ctx x y zs))
512− (Bag.append problems (Bag.one ReturnMismatch))
513−
514−
515−--
516−-- INVARIANTS:
517−-- length shortRevArgs >= 2
518−-- length longRevArgs >= 2
519−-- length shortRevArgs < length longRevArgs
520−--
521−diffArgMismatch :: L.Localizer -> RT.Context -> [Type] -> D.Doc -> [Type] -> D.Doc -> Diff D.Doc
522−diffArgMismatch localizer ctx shortRevArgs shortResult longRevArgs longResult =
523− let
524− (a:b:cs, x:y:zs) =
525− case toGreedyMatch localizer shortRevArgs longRevArgs of
526− Just (GreedyMatch shortRevArgDocs longRevArgDocs) ->
527− ( reverse (shortResult:shortRevArgDocs)
528− , reverse (longResult:longRevArgDocs)
529− )
530−
531− Nothing ->
532− case toGreedyMatch localizer (reverse shortRevArgs) (reverse longRevArgs) of
533− Just (GreedyMatch shortArgDocs longArgDocs) ->
534− ( shortArgDocs ++ [shortResult]
535− , longArgDocs ++ [longResult]
536− )
537−
538− Nothing ->
539− let
540− toYellowDoc tipe =
541− D.dullyellow (toDoc localizer RT.Func tipe)
542− in
543− ( reverse (shortResult : map toYellowDoc shortRevArgs)
544− , reverse (longResult : map toYellowDoc longRevArgs )
545− )
546− in
547− different
548− (RT.lambda ctx a b cs)
549− (RT.lambda ctx x y zs)
550− (Bag.one (MissingArgs (length longRevArgs - length shortRevArgs)))
551−
552−
553−
554−-- GREEDY ARG MATCHER
555−
556−
557−data GreedyMatch =
558− GreedyMatch [D.Doc] [D.Doc]
559−
560−
561−--
562−-- INVARIANTS:
563−-- length shorterArgs < length longerArgs
564−--
565−toGreedyMatch :: L.Localizer -> [Type] -> [Type] -> Maybe GreedyMatch
566−toGreedyMatch localizer shorterArgs longerArgs =
567− toGreedyMatchHelp localizer shorterArgs longerArgs (GreedyMatch [] [])
568−
569−
570−toGreedyMatchHelp :: L.Localizer -> [Type] -> [Type] -> GreedyMatch -> Maybe GreedyMatch
571−toGreedyMatchHelp localizer shorterArgs longerArgs match@(GreedyMatch shorterDocs longerDocs) =
572− let
573− toYellowDoc tipe =
574− D.dullyellow (toDoc localizer RT.Func tipe)
575− in
576− case (shorterArgs, longerArgs) of
577− (x:xs, y:ys) ->
578− case toDiff localizer RT.Func x y of
579− Diff a b Similar ->
580− toGreedyMatchHelp localizer xs ys $
581− GreedyMatch (a:shorterDocs) (b:longerDocs)
582−
583− Diff _ _ (Different _) ->
584− toGreedyMatchHelp localizer shorterArgs ys $
585− GreedyMatch shorterDocs (toYellowDoc y : longerDocs)
586−
587− ([], []) ->
588− Just match
589−
590− ([], _:_) ->
591− Just (GreedyMatch shorterDocs (map toYellowDoc longerArgs))
592−
593− (_:_, []) ->
594− Nothing
595−
596−
597−
598483-- RECORD DIFFS
599484
600485