on master help sign in
Make some progress on type error messages!

The thing I am most excited about is specialized hints that form learning paths. For example, the hints can now lead you on this path: ‘hello’ + 3 “hello” + 3 “hello” ++ 3 “hello” ++ String.fromInt 3 Or on this one: 3 + userInput 3 + String.toInt userInput 3 + Maybe.withDefault 0 (String.toInt userInput) I have been wondering “how far can the compiler take a total beginner?” for a while now, so it is cool to make some progress along those lines!

commit0bdfd738259705c115d994ec47df4bfbfc576090 authorEvan Czaplicki <evancz@users.noreply.github.com> dateFri 16 Feb 2018, 18:30 (9 years ago) parentd924db7
4 files changed+552−232
src/Reporting/Error/Type.hs+430−184 src/Reporting/Helpers.hs+7−1 src/Type/Error.hs+102−43 src/Type/Type.hs+13−4
src/Reporting/Error/Type.hs+430−184
@@ -307,7 +307,7 @@ toPatternReport source localizer patternRegion category tipe expected =
307307
308308
309309patternTypeComparison :: T.Localizer -> T.Type -> T.Type -> ( String, String, [H.Doc] ) -> H.Doc
310−patternTypeComparison localizer actual expected ( iAmSeeing, insteadOf, soHereAreSomeThoughts ) =
310+patternTypeComparison localizer actual expected ( iAmSeeing, insteadOf, contextHints ) =
311311 let
312312 (actualDoc, expectedDoc, problems) =
313313 T.toDiffDocs localizer actual expected
@@ -318,8 +318,8 @@ patternTypeComparison localizer actual expected ( iAmSeeing, insteadOf, soHereAr
318318 , H.reflow insteadOf
319319 , H.indent 4 expectedDoc
320320 ]
321− ++ soHereAreSomeThoughts
322− ++ map problemToHints problems
321+ ++ problemsToHint problems
322+ ++ contextHints
323323
324324
325325toPatternDescription :: PCategory -> String -> String
@@ -341,7 +341,7 @@ toPatternDescription category iAmTryingToMatch =
341341
342342
343343typeComparison :: T.Localizer -> T.Type -> T.Type -> ( String, String, [H.Doc] ) -> H.Doc
344−typeComparison localizer actual expected ( iAmSeeing, insteadOf, soHereAreSomeThoughts ) =
344+typeComparison localizer actual expected ( iAmSeeing, insteadOf, contextHints ) =
345345 let
346346 (actualDoc, expectedDoc, problems) =
347347 T.toDiffDocs localizer actual expected
@@ -352,13 +352,22 @@ typeComparison localizer actual expected ( iAmSeeing, insteadOf, soHereAreSomeTh
352352 , H.reflow insteadOf
353353 , H.indent 4 expectedDoc
354354 ]
355− ++ soHereAreSomeThoughts
356− ++ map problemToHints problems
355+ ++ problemsToHint problems
356+ ++ contextHints
357357
358358
359−indentType :: T.Localizer -> T.Type -> H.Doc
360−indentType localizer tipe =
361− H.indent 4 (H.dullyellow (T.toDoc localizer RT.None tipe))
359+loneType :: T.Localizer -> T.Type -> T.Type -> ( H.Doc, [H.Doc] ) -> H.Doc
360+loneType localizer actual expected ( iAmSeeing, furtherDetails ) =
361+ let
362+ (actualDoc, _, problems) =
363+ T.toDiffDocs localizer actual expected
364+ in
365+ H.stack $
366+ [ iAmSeeing
367+ , H.indent 4 actualDoc
368+ ]
369+ ++ furtherDetails
370+ ++ problemsToHint problems
362371
363372
364373toDescription :: Category -> String -> String
@@ -389,19 +398,189 @@ toDescription category thatThingIs =
389398 OpName _ -> thatThingIs <> ":"
390399
391400
392−-- TODO be sure to avoid duplicate Problems (e.g. two instances of BadRigidVar)
393−--
394−problemToHints :: T.Problem -> H.Doc
395−problemToHints problem =
401+problemsToHint :: [T.Problem] -> [H.Doc]
402+problemsToHint problems =
403+ case problems of
404+ [] ->
405+ []
406+
407+ problem : _ ->
408+ problemToHint problem
409+
410+
411+problemToHint :: T.Problem -> [H.Doc]
412+problemToHint problem =
396413 case problem of
397− T.FieldMismatch leftOnly rightOnly -> error "TODO FieldMismatch" leftOnly rightOnly
398− T.IntFloat -> error "TODO IntFloat"
399− T.MissingArgs numMissing -> error "TODO MissingArgs" numMissing
400− T.ReturnMismatch -> error "TODO ReturnMismatch"
401− T.TupleMismatch -> error "TODO TupleMismatch"
402− T.BadFlexSuper x tipe -> error "TODO BadFlexSuper" x tipe
403− T.BadRigidVar x tipe -> error "TODO BadRigidVar" x tipe
404− T.BadRigidSuper x tipe -> error "TODO BadRigidSuper" x tipe
414+ T.FieldMismatch _ _ -> [] -- TODO do a better job?
415+
416+ T.IntFloat ->
417+ [ H.fancyLink "Note" ["Read"] "implicit-casts"
418+ ["to","learn","why","Elm","does","not","implicitly","convert"
419+ ,"Ints","to","Floats.","Use",H.green "toFloat","and"
420+ ,H.green "round","to","do","explicit","conversions."
421+ ]
422+ ]
423+
424+ T.StringFromInt ->
425+ [ H.toFancyHint
426+ ["Want","to","convert","an","Int","into","a","String?"
427+ ,"Use","the",H.green "String.fromInt","function!"
428+ ]
429+ ]
430+
431+ T.StringFromFloat ->
432+ [ H.toFancyHint
433+ ["Want","to","convert","a","Float","into","a","String?"
434+ ,"Use","the",H.green "String.fromFloat","function!"
435+ ]
436+ ]
437+
438+ T.StringToInt ->
439+ [ H.toFancyHint
440+ ["Want","to","convert","a","String","into","an","Int?"
441+ ,"Use","the",H.green "String.toInt","function!"
442+ ]
443+ ]
444+
445+ T.StringToFloat ->
446+ [ H.toFancyHint
447+ ["Want","to","convert","a","String","into","a","Float?"
448+ ,"Use","the",H.green "String.toFloat","function!"
449+ ]
450+ ]
451+
452+ T.AnythingToBool ->
453+ [ H.toSimpleHint $
454+ "Elm does not have “truthiness” such that ints and strings and lists\
455+ \ are automatically converted to booleans. Do that conversion explicitly!"
456+ ]
457+
458+ T.AnythingFromMaybe ->
459+ [ H.toFancyHint
460+ ["Use",H.green "Maybe.withDefault","to","handle","possible","errors."
461+ ,"Longer","term,","it","is","usually","better","to","write","out","the"
462+ ,"full","`case`","though!"
463+ ]
464+ ]
465+
466+ T.AnythingToList ->
467+ [ H.toSimpleHint "Did you forget to add [] around it?"
468+ ]
469+
470+ T.MissingArgs _ -> []
471+ T.ReturnMismatch -> []
472+
473+ T.BadFlexSuper super _ tipe ->
474+ case tipe of
475+ T.Lambda _ _ _ -> badFlexSuper super
476+ T.Infinite -> []
477+ T.Error -> []
478+ T.FlexVar _ -> []
479+ T.FlexSuper s _ -> badDoubleFlexSuper super s
480+ T.RigidVar _y -> error "TODO"
481+ T.RigidSuper _s _y -> error "TODO"
482+ T.Type _ _ _ -> badFlexSuper super
483+ T.Record _ _ -> badFlexSuper super
484+ T.Unit -> badFlexSuper super
485+ T.Tuple _ _ _ -> badFlexSuper super
486+ T.Alias _ _ _ _ -> badFlexSuper super
487+
488+ T.BadRigidVar x tipe ->
489+ case tipe of
490+ T.Lambda _ _ _ -> badRigidVar x "a function"
491+ T.Infinite -> []
492+ T.Error -> []
493+ T.FlexVar _ -> []
494+ T.FlexSuper _s _y -> error "TODO"
495+ T.RigidVar y -> badDoubleRigid x y
496+ T.RigidSuper _ y -> badDoubleRigid x y
497+ T.Type _ name _ -> badRigidVar x ("a `" ++ N.toString name ++ "` value")
498+ T.Record _ _ -> badRigidVar x "a record"
499+ T.Unit -> badRigidVar x "a unit value"
500+ T.Tuple _ _ _ -> badRigidVar x "a tuple"
501+ T.Alias _ name _ _ -> badRigidVar x ("a `" ++ N.toString name ++ "` value")
502+
503+ T.BadRigidSuper super x tipe ->
504+ case tipe of
505+ T.Lambda _ _ _ -> badRigidSuper super "a function"
506+ T.Infinite -> []
507+ T.Error -> []
508+ T.FlexVar _ -> []
509+ T.FlexSuper _s _y -> error "TODO"
510+ T.RigidVar y -> badDoubleRigid x y
511+ T.RigidSuper _ y -> badDoubleRigid x y
512+ T.Type _ name _ -> badRigidSuper super ("a `" ++ N.toString name ++ "` value")
513+ T.Record _ _ -> badRigidSuper super "a record"
514+ T.Unit -> badRigidSuper super "a unit value"
515+ T.Tuple _ _ _ -> badRigidSuper super "a tuple"
516+ T.Alias _ name _ _ -> badRigidSuper super ("a `" ++ N.toString name ++ "` value")
517+
518+
519+badFlexSuper :: T.Super -> [H.Doc]
520+badFlexSuper super =
521+ case super of
522+ T.Comparable -> [ H.toSimpleHint "Only ints, floats, chars, strings, lists, and tuples are comparable." ]
523+ T.Appendable -> [ H.toSimpleHint "Only strings and lists are appendable." ]
524+ T.CompAppend -> [ H.toSimpleHint "Only strings and lists are both comparable and appendable." ]
525+ T.Number ->
526+ [ H.toFancyHint ["Only",H.green "Int","and",H.green "Float","values","work","as","numbers."]
527+ ]
528+
529+
530+badRigidVar :: N.Name -> String -> [H.Doc]
531+badRigidVar name aThing =
532+ [ H.toSimpleHint $
533+ "Your type annotation uses type variable `" ++ N.toString name ++
534+ "` which means ANY type of value can flow through, but your code is saying it specifically wants "
535+ ++ aThing ++ ". Maybe change your type annotation to\
536+ \ be more specific? Maybe change the code to be more general?"
537+ , H.reflowLink "Read" "type-annotations" "for more advice!"
538+ ]
539+
540+
541+badDoubleFlexSuper :: T.Super -> T.Super -> [H.Doc]
542+badDoubleFlexSuper s1 s2 =
543+ let
544+ whatever =
545+ [ H.toSimpleHint $
546+ "There are no "
547+ ]
548+ in
549+ case s1 of
550+ T.Number -> error "TODO" whatever s1 s2
551+ T.Comparable -> error "TODO" whatever s1 s2
552+ T.Appendable -> error "TODO" whatever s1 s2
553+ T.CompAppend -> error "TODO" whatever s1 s2
554+
555+
556+badRigidSuper :: T.Super -> String -> [H.Doc]
557+badRigidSuper super aThing =
558+ let
559+ (superType, manyThings) =
560+ case super of
561+ T.Number -> ("number", "ints AND floats")
562+ T.Comparable -> ("comparable", "ints, floats, chars, strings, lists, and tuples")
563+ T.Appendable -> ("appendable", "strings AND lists")
564+ T.CompAppend -> ("compappend", "strings AND lists")
565+ in
566+ [ H.toSimpleHint $
567+ "The `" ++ superType ++ "` in your type annotation is saying that " ++
568+ manyThings ++ " can flow through, but your code is saying it specifically wants "
569+ ++ aThing ++ ". Maybe change your type annotation to\
570+ \ be more specific? Maybe change the code to be more general?"
571+ , H.reflowLink "Read" "type-annotations" "for more advice!"
572+ ]
573+
574+
575+badDoubleRigid :: N.Name -> N.Name -> [H.Doc]
576+badDoubleRigid x y =
577+ [ H.toSimpleHint $
578+ "Your type annotation uses `" ++ N.toString x ++ "` and `" ++ N.toString y ++
579+ "` as separate type variables. Your code seems to be saying they are the\
580+ \ same though! Maybe they should be the same in your type annotation?\
581+ \ Maybe your code uses them in a weird way?"
582+ , H.reflowLink "Read" "type-annotations" "for more advice!"
583+ ]
405584
406585
407586
@@ -423,9 +602,7 @@ toExprReport source localizer exprRegion category tipe expected =
423602 ,
424603 "But you are trying to use it as:"
425604 ,
426− [
427− -- problem
428− ]
605+ []
429606 )
430607 )
431608
@@ -491,15 +668,16 @@ toExprReport source localizer exprRegion category tipe expected =
491668 (
492669 "I do not know how to negate this type of value:"
493670 ,
494− H.stack
495− [ H.reflow $ toDescription category "It is"
496− , indentType localizer tipe
497− , H.fillSep
498− ["But","I","only","now","how","to","negate"
499− ,H.dullyellow "Int","and",H.dullyellow "Float","values."
500− ]
501− --, problem
502− ]
671+ loneType localizer tipe expectedType
672+ (
673+ H.reflow $ toDescription category "It is"
674+ ,
675+ [ H.fillSep
676+ ["But","I","only","now","how","to","negate"
677+ ,H.dullyellow "Int","and",H.dullyellow "Float","values."
678+ ]
679+ ]
680+ )
503681 )
504682
505683 OpLeft op ->
@@ -519,14 +697,13 @@ toExprReport source localizer exprRegion category tipe expected =
519697 (
520698 "This `if` condition does not evaluate to a boolean value, True or False."
521699 ,
522− H.stack
523− [ H.reflow $ toDescription category "It is"
524− , indentType localizer tipe
525− , H.fillSep ["But","I","need","this","`if`","condition","to","be","a",H.dullyellow "Bool","value."]
526− , H.toSimpleHint $
527− "Elm does not have “truthiness” such that ints and strings and lists\
528− \ are automatically converted to booleans. Do that conversion explicitly!"
529− ]
700+ loneType localizer tipe expectedType
701+ (
702+ H.reflow $ toDescription category "It is"
703+ ,
704+ [ H.fillSep ["But","I","need","this","`if`","condition","to","be","a",H.dullyellow "Bool","value."]
705+ ]
706+ )
530707 )
531708
532709 IfBranch index ->
@@ -698,13 +875,16 @@ toExprReport source localizer exprRegion category tipe expected =
698875 H.reflow $
699876 "This record does not have a `" <> N.toString field <> "` field:"
700877 ,
701− H.stack $
702− [ H.reflow $
703− "It is a record with this type:"
704− , indentType localizer tipe
705− , H.reflow $
706− "So maybe the ." <> N.toString field <> " field access is misspelled?"
707− ]
878+ loneType localizer tipe expectedType
879+ (
880+ H.reflow $ "It is a record with this type:"
881+ ,
882+ [ H.fillSep
883+ ["Is","the",H.dullyellow ("." <> H.nameToDoc field)
884+ ,"field","access","is","misspelled?"
885+ ]
886+ ]
887+ )
708888 )
709889
710890 _ ->
@@ -712,12 +892,14 @@ toExprReport source localizer exprRegion category tipe expected =
712892 H.reflow $
713893 "This is not a record, so it has no fields to access!"
714894 ,
715− H.stack
716− [ H.reflow $ toDescription category "It is"
717− , indentType localizer tipe
718− , H.fillSep
719− ["But","I","need","a","record","with","a",H.dullyellow (H.nameToDoc field),"field!"]
720− ]
895+ loneType localizer tipe expectedType
896+ ( H.reflow $ toDescription category "It is"
897+ , [ H.fillSep
898+ ["But","I","need","a","record","with","a"
899+ ,H.dullyellow (H.nameToDoc field),"field!"
900+ ]
901+ ]
902+ )
721903 )
722904
723905 RecordUpdate ->
@@ -744,11 +926,11 @@ toExprReport source localizer exprRegion category tipe expected =
744926 (
745927 "The record update syntax does not work with this value:"
746928 ,
747− H.stack
748− [ H.reflow $ toDescription category "It is"
749− , indentType localizer tipe
750− , H.reflow $ "But I need some kind of record here!"
751− ]
929+ loneType localizer tipe expectedType
930+ ( H.reflow $ toDescription category "It is"
931+ , [ H.reflow $ "But I need some kind of record here!"
932+ ]
933+ )
752934 )
753935
754936 Destructure ->
@@ -787,36 +969,38 @@ countArgs tipe =
787969
788970
789971opLeftToDocs :: T.Localizer -> Category -> N.Name -> T.Type -> T.Type -> (H.Doc, H.Doc)
790−opLeftToDocs localizer category op tipe expectedType =
972+opLeftToDocs localizer category op tipe expected =
791973 case op of
792974 "+"
793975 | isString tipe -> badStringAdd
794− | isList tipe -> badListAdd localizer category "left" tipe
795− | otherwise -> badMath localizer category "Addition" "left" "+" tipe []
976+ | isList tipe -> badListAdd localizer category "left" tipe expected
977+ | otherwise -> badMath localizer category "Addition" "left" "+" tipe expected []
796978
797979 "*"
798− | isList tipe -> badListMul localizer category "left" tipe
799− | otherwise -> badMath localizer category "Multiplication" "left" "*" tipe []
800−
801− "-" -> badMath localizer category "Subtraction" "left" "-" tipe []
802− "^" -> badMath localizer category "Exponentiation" "left" "^" tipe []
803− "/" -> badFDiv localizer "left" tipe
804− "//" -> badIDiv localizer "left" tipe
805− "&&" -> badBool localizer "&&" "left" tipe
806− "||" -> badBool localizer "||" "left" tipe
807− "<" -> badCompLeft localizer category "<" "left" tipe
808− ">" -> badCompLeft localizer category ">" "left" tipe
809− "<=" -> badCompLeft localizer category "<=" "left" tipe
810− ">=" -> badCompLeft localizer category ">=" "left" tipe
980+ | isList tipe -> badListMul localizer category "left" tipe expected
981+ | otherwise -> badMath localizer category "Multiplication" "left" "*" tipe expected []
982+
983+ "-" -> badMath localizer category "Subtraction" "left" "-" tipe expected []
984+ "^" -> badMath localizer category "Exponentiation" "left" "^" tipe expected []
985+ "/" -> badFDiv localizer "left" tipe expected
986+ "//" -> badIDiv localizer "left" tipe expected
987+ "&&" -> badBool localizer "&&" "left" tipe expected
988+ "||" -> badBool localizer "||" "left" tipe expected
989+ "<" -> badCompLeft localizer category "<" "left" tipe expected
990+ ">" -> badCompLeft localizer category ">" "left" tipe expected
991+ "<=" -> badCompLeft localizer category "<=" "left" tipe expected
992+ ">=" -> badCompLeft localizer category ">=" "left" tipe expected
993+
994+ "++" -> badAppend localizer category "left" tipe expected
811995
812996 "<|" ->
813997 ( "The left side of (<|) needs to be a function so I can pipe arguments to it!"
814998 ,
815− H.stack
816− [ H.reflow $ toDescription category "I am seeing"
817− , indentType localizer tipe
818− , H.reflow $ "This needs to be some kind of function though!"
819− ]
999+ loneType localizer tipe expected
1000+ ( H.reflow $ toDescription category "I am seeing"
1001+ , [ H.reflow $ "This needs to be some kind of function though!"
1002+ ]
1003+ )
8201004 )
8211005
8221006 _ ->
@@ -824,7 +1008,7 @@ opLeftToDocs localizer category op tipe expectedType =
8241008 H.reflow $
8251009 "The left argument of (" <> N.toString op <> ") is causing problems:"
8261010 ,
827− typeComparison localizer tipe expectedType
1011+ typeComparison localizer tipe expected
8281012 (
8291013 toDescription category "The left argument is"
8301014 ,
@@ -845,41 +1029,46 @@ data RightDocs
8451029
8461030
8471031opRightToDocs :: T.Localizer -> Category -> N.Name -> T.Type -> T.Type -> RightDocs
848−opRightToDocs localizer category op tipe expectedType =
1032+opRightToDocs localizer category op tipe expected =
8491033 case op of
8501034 "+"
851− | isInt tipe -> badCast op FloatInt
852− | isFloat tipe -> badCast op IntFloat
1035+ | isFloat expected && isInt tipe -> badCast op FloatInt
1036+ | isInt expected && isFloat tipe -> badCast op IntFloat
8531037 | isString tipe -> EmphRight $ badStringAdd
854− | isList tipe -> EmphRight $ badListAdd localizer category "right" tipe
855− | otherwise -> EmphRight $ badMath localizer category "Addition" "right" "+" tipe []
1038+ | isList tipe -> EmphRight $ badListAdd localizer category "right" tipe expected
1039+ | otherwise -> EmphRight $ badMath localizer category "Addition" "right" "+" tipe expected []
8561040
8571041 "*"
858− | isInt tipe -> badCast op FloatInt
859− | isFloat tipe -> badCast op IntFloat
860− | isList tipe -> EmphRight $ badListMul localizer category "right" tipe
861− | otherwise -> EmphRight $ badMath localizer category "Multiplication" "right" "*" tipe []
1042+ | isFloat expected && isInt tipe -> badCast op FloatInt
1043+ | isInt expected && isFloat tipe -> badCast op IntFloat
1044+ | isList tipe -> EmphRight $ badListMul localizer category "right" tipe expected
1045+ | otherwise -> EmphRight $ badMath localizer category "Multiplication" "right" "*" tipe expected []
8621046
8631047 "-"
864− | isInt tipe -> badCast op FloatInt
865− | isFloat tipe -> badCast op IntFloat
866− | otherwise -> EmphRight $ badMath localizer category "Subtraction" "right" "-" tipe []
1048+ | isFloat expected && isInt tipe -> badCast op FloatInt
1049+ | isInt expected && isFloat tipe -> badCast op IntFloat
1050+ | otherwise ->
1051+ EmphRight $ badMath localizer category "Subtraction" "right" "-" tipe expected []
8671052
8681053 "^"
869− | isInt tipe -> badCast op FloatInt
870− | isFloat tipe -> badCast op IntFloat
871− | otherwise -> EmphRight $ badMath localizer category "Exponentiation" "right" "^" tipe []
872−
873− "/" -> EmphRight $ badFDiv localizer "right" tipe
874− "//" -> EmphRight $ badIDiv localizer "right" tipe
875− "&&" -> EmphRight $ badBool localizer "&&" "right" tipe
876− "||" -> EmphRight $ badBool localizer "||" "right" tipe
877− "<" -> badCompRight localizer "<" tipe expectedType
878− ">" -> badCompRight localizer ">" tipe expectedType
879− "<=" -> badCompRight localizer "<=" tipe expectedType
880− ">=" -> badCompRight localizer ">=" tipe expectedType
881− "==" -> badEquality localizer "==" tipe expectedType
882− "/=" -> badEquality localizer "/=" tipe expectedType
1054+ | isFloat expected && isInt tipe -> badCast op FloatInt
1055+ | isInt expected && isFloat tipe -> badCast op IntFloat
1056+ | otherwise ->
1057+ EmphRight $ badMath localizer category "Exponentiation" "right" "^" tipe expected []
1058+
1059+ "/" -> EmphRight $ badFDiv localizer "right" tipe expected
1060+ "//" -> EmphRight $ badIDiv localizer "right" tipe expected
1061+ "&&" -> EmphRight $ badBool localizer "&&" "right" tipe expected
1062+ "||" -> EmphRight $ badBool localizer "||" "right" tipe expected
1063+ "<" -> badCompRight localizer "<" tipe expected
1064+ ">" -> badCompRight localizer ">" tipe expected
1065+ "<=" -> badCompRight localizer "<=" tipe expected
1066+ ">=" -> badCompRight localizer ">=" tipe expected
1067+ "==" -> badEquality localizer "==" tipe expected
1068+ "/=" -> badEquality localizer "/=" tipe expected
1069+
1070+ "::" -> error "TODO"
1071+ "++" -> EmphRight $ badAppend localizer category "right" tipe expected
8831072
8841073 "<|" ->
8851074 EmphRight
@@ -887,7 +1076,7 @@ opRightToDocs localizer category op tipe expectedType =
8871076 H.reflow $
8881077 "I cannot send this through the (<|) pipe:"
8891078 ,
890− typeComparison localizer tipe expectedType
1079+ typeComparison localizer tipe expected
8911080 (
8921081 toDescription category "You are providing"
8931082 ,
@@ -898,7 +1087,7 @@ opRightToDocs localizer category op tipe expectedType =
8981087 )
8991088
9001089 "|>" ->
901− case (tipe, expectedType) of
1090+ case (tipe, expected) of
9021091 (T.Lambda expectedArgType _ _, T.Lambda argType _ _) ->
9031092 EmphRight
9041093 (
@@ -919,11 +1108,11 @@ opRightToDocs localizer category op tipe expectedType =
9191108 (
9201109 "The right side of (|>) needs to be a function so I can pipe arguments to it!"
9211110 ,
922− H.stack
923− [ H.reflow $ toDescription category $
924− "Instead of a function, I am seeing "
925− , indentType localizer tipe
926− ]
1111+ loneType localizer tipe expected
1112+ ( H.reflow $ toDescription category $
1113+ "But instead of a function, I am seeing "
1114+ , []
1115+ )
9271116 )
9281117
9291118 _ ->
@@ -932,7 +1121,7 @@ opRightToDocs localizer category op tipe expectedType =
9321121 H.reflow $
9331122 "The right argument of (" <> N.toString op <> ") is causing problems."
9341123 ,
935− typeComparison localizer tipe expectedType
1124+ typeComparison localizer tipe expected
9361125 (
9371126 toDescription category "The right argument is"
9381127 ,
@@ -989,6 +1178,57 @@ isList tipe =
9891178
9901179
9911180
1181+-- BAD APPEND
1182+
1183+
1184+badAppend :: T.Localizer -> Category -> String -> T.Type -> T.Type -> (H.Doc, H.Doc)
1185+badAppend localizer category direction tipe expected =
1186+ let
1187+ maybeDetails =
1188+ case tipe of
1189+ T.Type home name []
1190+ | ModuleName.basics == home && name == N.int -> Just ("ints", "String.fromInt")
1191+ | ModuleName.basics == home && name == N.float -> Just ("floats", "String.fromFloat")
1192+
1193+ T.FlexSuper T.Number _ ->
1194+ Just ("numbers", "String.fromInt")
1195+
1196+ _ ->
1197+ Nothing
1198+ in
1199+ case maybeDetails of
1200+ Just (things, stringFromThing) ->
1201+ (
1202+ H.fillSep
1203+ ["The","(++)","operator","is","for","appending",H.dullyellow "List","and"
1204+ ,H.dullyellow "String","values,","not",H.dullyellow things,"like","this:"
1205+ ]
1206+ ,
1207+ H.fillSep
1208+ ["Try","using",H.green stringFromThing,"to","turn","it","into","a"
1209+ ,H.dullyellow "String" <> "?"
1210+ ]
1211+ )
1212+
1213+ Nothing ->
1214+ (
1215+ H.reflow $
1216+ "The (++) operator cannot append this type of value:"
1217+ ,
1218+ loneType localizer tipe expected
1219+ ( H.reflow $ toDescription category $
1220+ "The " <> direction <> " side of (++) is"
1221+ ,
1222+ [ H.fillSep
1223+ ["But","the","(++)","operator","is","only","for","appending"
1224+ ,H.dullyellow "List","and",H.dullyellow "String","values."
1225+ ]
1226+ ]
1227+ )
1228+ )
1229+
1230+
1231+
9921232-- BAD MATH
9931233
9941234
@@ -1050,28 +1290,30 @@ badStringAdd =
10501290 )
10511291
10521292
1053−badListAdd :: T.Localizer -> Category -> String -> T.Type -> (H.Doc, H.Doc)
1054−badListAdd localizer category direction tipe =
1293+badListAdd :: T.Localizer -> Category -> String -> T.Type -> T.Type -> (H.Doc, H.Doc)
1294+badListAdd localizer category direction tipe expected =
10551295 (
10561296 "I cannot do addition with lists:"
10571297 ,
1058− H.stack
1059− [ H.reflow $ toDescription category $
1298+ loneType localizer tipe expected
1299+ (
1300+ H.reflow $ toDescription category $
10601301 "The " <> direction <> " side of (+) is"
1061− , indentType localizer tipe
1062− , H.fillSep
1063− ["But","(+)","only","works","with",H.dullyellow "Int","and",H.dullyellow "Float","values."
1064− ]
1065− , H.toFancyHint
1066− ["Switch","to","the",H.green "(++)","operator","to","append","lists!"
1067− ]
1068− ]
1302+ ,
1303+ [ H.fillSep
1304+ ["But","(+)","only","works","with",H.dullyellow "Int","and",H.dullyellow "Float","values."
1305+ ]
1306+ , H.toFancyHint
1307+ ["Switch","to","the",H.green "(++)","operator","to","append","lists!"
1308+ ]
1309+ ]
1310+ )
10691311 )
10701312
10711313
1072−badListMul :: T.Localizer -> Category -> String -> T.Type -> (H.Doc, H.Doc)
1073−badListMul localizer category direction tipe =
1074− badMath localizer category "Multiplication" direction "*" tipe
1314+badListMul :: T.Localizer -> Category -> String -> T.Type -> T.Type -> (H.Doc, H.Doc)
1315+badListMul localizer category direction tipe expected =
1316+ badMath localizer category "Multiplication" direction "*" tipe expected
10751317 [
10761318 H.toFancyHint
10771319 [ "Maybe", "you", "want"
@@ -1081,27 +1323,28 @@ badListMul localizer category direction tipe =
10811323 ]
10821324
10831325
1084−badMath :: T.Localizer -> Category -> String -> String -> String -> T.Type -> [H.Doc] -> (H.Doc, H.Doc)
1085−badMath localizer category operation direction op tipe otherHints =
1326+badMath :: T.Localizer -> Category -> String -> String -> String -> T.Type -> T.Type -> [H.Doc] -> (H.Doc, H.Doc)
1327+badMath localizer category operation direction op tipe expected otherHints =
10861328 (
10871329 H.reflow $
10881330 operation ++ " does not work with this value:"
10891331 ,
1090− H.stack $
1091− [ H.reflow $ toDescription category $
1332+ loneType localizer tipe expected
1333+ ( H.reflow $ toDescription category $
10921334 "The " <> direction <> " side of (" <> op <> ") is"
1093− , indentType localizer tipe
1094− , H.fillSep
1095− ["But","(" <> H.text op <> ")","only","works","with"
1096− ,H.dullyellow "Int","and",H.dullyellow "Float","values."
1097− ]
1098− ]
1099− ++ otherHints
1335+ ,
1336+ [ H.fillSep
1337+ ["But","(" <> H.text op <> ")","only","works","with"
1338+ ,H.dullyellow "Int","and",H.dullyellow "Float","values."
1339+ ]
1340+ ]
1341+ ++ otherHints
1342+ )
11001343 )
11011344
11021345
1103−badFDiv :: T.Localizer -> H.Doc -> T.Type -> (H.Doc, H.Doc)
1104−badFDiv localizer direction tipe =
1346+badFDiv :: T.Localizer -> H.Doc -> T.Type -> T.Type -> (H.Doc, H.Doc)
1347+badFDiv localizer direction tipe expected =
11051348 (
11061349 H.reflow $
11071350 "The (/) operator is specifically for floating-point division:"
@@ -1122,19 +1365,20 @@ badFDiv localizer direction tipe =
11221365 ]
11231366
11241367 else
1125− H.stack
1126− [ H.fillSep
1368+ loneType localizer tipe expected
1369+ (
1370+ H.fillSep
11271371 ["The",direction,"side","of","(/)","must","be","a"
11281372 ,H.dullyellow "Float" <> ","
11291373 ,"but","instead","I","am","seeing:"
11301374 ]
1131− , indentType localizer tipe
1132− ]
1375+ , []
1376+ )
11331377 )
11341378
11351379
1136−badIDiv :: T.Localizer -> H.Doc -> T.Type -> (H.Doc, H.Doc)
1137−badIDiv localizer direction tipe =
1380+badIDiv :: T.Localizer -> H.Doc -> T.Type -> T.Type -> (H.Doc, H.Doc)
1381+badIDiv localizer direction tipe expected =
11381382 (
11391383 H.reflow $
11401384 "The (//) operator is specifically for integer division:"
@@ -1157,14 +1401,15 @@ badIDiv localizer direction tipe =
11571401 , H.link "Note" "Read" "implicit-casts" "to learn why Elm does not implicitly convert Ints to Floats."
11581402 ]
11591403 else
1160− H.stack
1161− [ H.fillSep
1404+ loneType localizer tipe expected
1405+ (
1406+ H.fillSep
11621407 ["The",direction,"side","of","(//)","must","be","an"
11631408 ,H.dullyellow "Int" <> ","
11641409 ,"but","instead","I","am","seeing:"
11651410 ]
1166− , indentType localizer tipe
1167− ]
1411+ , []
1412+ )
11681413 )
11691414
11701415
@@ -1172,22 +1417,21 @@ badIDiv localizer direction tipe =
11721417-- BAD BOOLS
11731418
11741419
1175−badBool :: T.Localizer -> H.Doc -> H.Doc -> T.Type -> (H.Doc, H.Doc)
1176−badBool localizer op direction tipe =
1420+badBool :: T.Localizer -> H.Doc -> H.Doc -> T.Type -> T.Type -> (H.Doc, H.Doc)
1421+badBool localizer op direction tipe expected =
11771422 (
11781423 H.reflow $
11791424 "I am struggling with this boolean operation:"
11801425 ,
1181− H.stack
1182− [ H.fillSep
1426+ loneType localizer tipe expected
1427+ (
1428+ H.fillSep
11831429 ["Both","sides","of","(" <> op <> ")","must","be"
11841430 ,H.dullyellow "Bool","values,","but","the",direction,"side","is:"
11851431 ]
1186− , indentType localizer tipe
1187− , H.toSimpleHint
1188− "Elm does not have “truthiness” such that ints and strings and lists are\
1189− \ automatically converted to booleans. Do that conversion explicitly!"
1190− ]
1432+ ,
1433+ []
1434+ )
11911435 )
11921436
11931437
@@ -1195,38 +1439,40 @@ badBool localizer op direction tipe =
11951439-- BAD COMPARISON
11961440
11971441
1198−badCompLeft :: T.Localizer -> Category -> String -> String -> T.Type -> (H.Doc, H.Doc)
1199−badCompLeft localizer category op direction tipe =
1442+badCompLeft :: T.Localizer -> Category -> String -> String -> T.Type -> T.Type -> (H.Doc, H.Doc)
1443+badCompLeft localizer category op direction tipe expected =
12001444 (
12011445 H.reflow $
12021446 "I cannot do a comparison with this value:"
12031447 ,
1204− H.stack
1205− [ H.reflow $ toDescription category $
1448+ loneType localizer tipe expected
1449+ (
1450+ H.reflow $ toDescription category $
12061451 "The " <> direction <> " side of (" <> op <> ") is"
1207− , indentType localizer tipe
1208− , H.fillSep
1209− ["But","(" <> H.text op <> ")","only","works","on"
1210− ,H.dullyellow "Int" <> ","
1211− ,H.dullyellow "Float" <> ","
1212− ,H.dullyellow "Char" <> ","
1213− ,"and"
1214− ,H.dullyellow "String"
1215− ,"values.","If","you","want","to","get","crazy,","it","will","work","on"
1216− ,"lists","and","tuples","of","comparable","values","as","well."
1217− ]
1218− ]
1452+ ,
1453+ [ H.fillSep
1454+ ["But","(" <> H.text op <> ")","only","works","on"
1455+ ,H.dullyellow "Int" <> ","
1456+ ,H.dullyellow "Float" <> ","
1457+ ,H.dullyellow "Char" <> ","
1458+ ,"and"
1459+ ,H.dullyellow "String"
1460+ ,"values.","If","you","want","to","get","crazy,","it","will","work","on"
1461+ ,"lists","and","tuples","of","comparable","values","as","well."
1462+ ]
1463+ ]
1464+ )
12191465 )
12201466
12211467
12221468badCompRight :: T.Localizer -> String -> T.Type -> T.Type -> RightDocs
1223−badCompRight localizer op tipe expectedType =
1469+badCompRight localizer op tipe expected =
12241470 EmphBoth
12251471 (
12261472 H.reflow $
12271473 "I need both sides of (" <> op <> ") to be the same type:"
12281474 ,
1229− typeComparison localizer expectedType tipe
1475+ typeComparison localizer expected tipe
12301476 (
12311477 "The left side of is:"
12321478 ,
@@ -1244,19 +1490,19 @@ badCompRight localizer op tipe expectedType =
12441490
12451491
12461492badEquality :: T.Localizer -> String -> T.Type -> T.Type -> RightDocs
1247−badEquality localizer op tipe expectedType =
1493+badEquality localizer op tipe expected =
12481494 EmphBoth
12491495 (
12501496 H.reflow $
12511497 "I need both sides of (" <> op <> ") to be the same type:"
12521498 ,
1253− typeComparison localizer expectedType tipe
1499+ typeComparison localizer expected tipe
12541500 (
12551501 "The left side of is:"
12561502 ,
12571503 "But the right side is:"
12581504 ,
1259− if isFloat tipe || isFloat expectedType then
1505+ if isFloat tipe || isFloat expected then
12601506 [ H.toSimpleNote $
12611507 "Equality on floats is not 100% reliable due to the design of IEEE 754. I\
12621508 \ recommend a check like (abs (x - y) < 0.0001) instead."
@@ -1285,7 +1531,7 @@ toInfiniteReport source localizer region name overallType =
12851531 [ H.reflow $
12861532 "Here is my best effort at writing down the type. You will see ∞ for\
12871533 \ parts of the type that repeat something already printed out infinitely."
1288− , indentType localizer overallType
1534+ , H.indent 4 (H.dullyellow (T.toDoc localizer RT.None overallType))
12891535 , H.reflowLink
12901536 "Staring at the type is usually not so helpful, so I recommend reading the hints at"
12911537 "infinite-type"
src/Reporting/Helpers.hs+7−1
@@ -5,7 +5,7 @@ module Reporting.Helpers
55 , nameToDoc
66 , args, moreArgs
77 , toSimpleNote, toSimpleHint, toFancyHint
8− , link, reflowLink, makeLink
8+ , link, fancyLink, reflowLink, makeLink
99 , stack, reflow
1010 , commaSep, capitalize, ordinalize, drawCycle
1111 , findPotentialTypos, findTypoPairs, vetTypos
@@ -87,6 +87,12 @@ link word before fileName after =
8787 : map text (words after)
8888
8989
90+fancyLink :: Doc -> [Doc] -> String -> [Doc] -> Doc
91+fancyLink word before fileName after =
92+ fillSep $
93+ (underline word <> ":") : before ++ P.text (makeLink fileName) : after
94+
95+
9096makeLink :: String -> String
9197makeLink fileName =
9298 "<https://elm-lang.org/hints/" <> Pkg.versionToString Compiler.version <> "/" <> fileName <> ">"
src/Type/Error.hs+102−43
@@ -2,6 +2,7 @@
22{-# LANGUAGE OverloadedStrings #-}
33module Type.Error
44 ( Type(..)
5+ , Super(..)
56 , Extension(..)
67 , iteratedDealias
78 , Localizer
@@ -32,9 +33,9 @@ data Type
3233 | Infinite
3334 | Error
3435 | FlexVar N.Name
35− | FlexSuper N.Name
36+ | FlexSuper Super N.Name
3637 | RigidVar N.Name
37− | RigidSuper N.Name
38+ | RigidSuper Super N.Name
3839 | Type ModuleName.Canonical N.Name [Type]
3940 | Record (Map.Map N.Name Type) Extension
4041 | Unit
@@ -42,6 +43,13 @@ data Type
4243 | Alias ModuleName.Canonical N.Name [(N.Name, Type)] Type
4344
4445
46+data Super
47+ = Number
48+ | Comparable
49+ | Appendable
50+ | CompAppend
51+
52+
4553data Extension
4654 = Closed
4755 | FlexOpen N.Name
@@ -93,13 +101,13 @@ toDoc dict ctx tipe =
93101 FlexVar name ->
94102 H.nameToDoc name
95103
96− FlexSuper name ->
104+ FlexSuper _ name ->
97105 H.nameToDoc name
98106
99107 RigidVar name ->
100108 H.nameToDoc name
101109
102− RigidSuper name ->
110+ RigidSuper _ name ->
103111 H.nameToDoc name
104112
105113 Type home name args ->
@@ -121,7 +129,6 @@ toDoc dict ctx tipe =
121129 FlexOpen x -> Just (H.nameToDoc x)
122130 RigidOpen x -> Just (H.nameToDoc x)
123131
124−
125132 Unit ->
126133 "()"
127134
@@ -187,12 +194,18 @@ instance Applicative Diff where
187194data Problem
188195 = FieldMismatch [N.Name] [N.Name]
189196 | IntFloat
197+ | StringFromInt
198+ | StringFromFloat
199+ | StringToInt
200+ | StringToFloat
201+ | AnythingToBool
202+ | AnythingFromMaybe
203+ | AnythingToList
190204 | MissingArgs Int
191205 | ReturnMismatch
192− | TupleMismatch
193− | BadFlexSuper N.Name Type
206+ | BadFlexSuper Super N.Name Type
194207 | BadRigidVar N.Name Type
195− | BadRigidSuper N.Name Type
208+ | BadRigidSuper Super N.Name Type
196209
197210
198211
@@ -202,10 +215,10 @@ data Problem
202215diff :: Localizer -> RT.Context -> Type -> Type -> Diff H.Doc
203216diff dict ctx tipe1 tipe2 =
204217 case (tipe1, tipe2) of
205− (FlexVar x, FlexVar y) | x == y -> pure (H.nameToDoc x)
206− (FlexSuper x, FlexSuper y) | x == y -> pure (H.nameToDoc x)
207− (RigidVar x, RigidVar y) | x == y -> pure (H.nameToDoc x)
208− (RigidSuper x, RigidSuper y) | x == y -> pure (H.nameToDoc x)
218+ (FlexVar x, FlexVar y) | x == y -> pure (H.nameToDoc x)
219+ (FlexSuper _ x, FlexSuper _ y) | x == y -> pure (H.nameToDoc x)
220+ (RigidVar x, RigidVar y) | x == y -> pure (H.nameToDoc x)
221+ (RigidSuper _ x, RigidSuper _ y) | x == y -> pure (H.nameToDoc x)
209222
210223 (Infinite, Infinite) -> pure "∞"
211224 (Error, Error) -> pure "?"
@@ -218,8 +231,8 @@ diff dict ctx tipe1 tipe2 =
218231 <*>
219232 case (maybeC, maybeZ) of
220233 (Nothing, Nothing) -> pure []
221− (Just c , Nothing) -> Different [H.dullyellow (toDoc dict RT.None c)] [] (Bag.one TupleMismatch)
222− (Nothing, Just z ) -> Different [] [H.dullyellow (toDoc dict RT.None z)] (Bag.one TupleMismatch)
234+ (Just c , Nothing) -> Different [H.dullyellow (toDoc dict RT.None c)] [] Bag.empty
235+ (Nothing, Just z ) -> Different [] [H.dullyellow (toDoc dict RT.None z)] Bag.empty
223236 (Just c , Just z ) -> (:[]) <$> diff dict RT.None c z
224237
225238 (Record fields1 ext1, Record fields2 ext2) -> diffRecord dict fields1 ext1 fields2 ext2
@@ -243,35 +256,81 @@ diff dict ctx tipe1 tipe2 =
243256 (other, FlexVar x) -> Similar (toDoc dict ctx other) (H.nameToDoc x)
244257
245258 pair ->
246− let
247− doc1 = H.dullyellow (toDoc dict ctx tipe1)
248− doc2 = H.dullyellow (toDoc dict ctx tipe2)
249− in
250− Different doc1 doc2 $
251− case pair of
252− (RigidVar x, other) -> Bag.one $ BadRigidVar x other
253− (FlexSuper x, other) -> Bag.one $ BadFlexSuper x other
254− (RigidSuper x, other) -> Bag.one $ BadRigidSuper x other
255− (other, RigidVar x) -> Bag.one $ BadRigidVar x other
256− (other, FlexSuper x) -> Bag.one $ BadFlexSuper x other
257− (other, RigidSuper x) -> Bag.one $ BadRigidSuper x other
258−
259− (Type home1 name1 [], Type home2 name2 []) | isIntFloat home1 name1 home2 name2 -> Bag.one IntFloat
260−
261− (_, _) -> Bag.empty
262−
263−
264−isIntFloat :: ModuleName.Canonical -> N.Name -> ModuleName.Canonical -> N.Name -> Bool
265−isIntFloat home1 name1 home2 name2 =
266− home1 == ModuleName.basics
267− &&
268− home2 == ModuleName.basics
269− &&
270− (
271− (name1 == N.int && name2 == N.float)
272− ||
273− (name1 == N.float && name2 == N.int)
274− )
259+ case pair of
260+ (Type home name [t1], t2) | isMaybe home name && isSimilar t1 t2 ->
261+ Different (yellowApply dict ctx home name t1) (toDoc dict ctx t2) (Bag.one AnythingFromMaybe)
262+
263+ (t1, Type home name [t2]) | isList home name && isSimilar t1 t2 ->
264+ Different (toDoc dict ctx t1) (yellowApply dict ctx home name t2) (Bag.one AnythingToList)
265+
266+ _ ->
267+ let
268+ doc1 = H.dullyellow (toDoc dict ctx tipe1)
269+ doc2 = H.dullyellow (toDoc dict ctx tipe2)
270+ in
271+ Different doc1 doc2 $
272+ case pair of
273+ (RigidVar x, other) -> Bag.one $ BadRigidVar x other
274+ (FlexSuper s x, other) -> Bag.one $ BadFlexSuper s x other
275+ (RigidSuper s x, other) -> Bag.one $ BadRigidSuper s x other
276+ (other, RigidVar x) -> Bag.one $ BadRigidVar x other
277+ (other, FlexSuper s x) -> Bag.one $ BadFlexSuper s x other
278+ (other, RigidSuper s x) -> Bag.one $ BadRigidSuper s x other
279+
280+ (Type home1 name1 [], Type home2 name2 [])
281+ | isInt home1 name1 && isFloat home2 name2 -> Bag.one IntFloat
282+ | isFloat home1 name1 && isInt home2 name2 -> Bag.one IntFloat
283+ | isInt home1 name1 && isString home2 name2 -> Bag.one StringFromInt
284+ | isFloat home1 name1 && isString home2 name2 -> Bag.one StringFromFloat
285+ | isString home1 name1 && isInt home2 name2 -> Bag.one StringToInt
286+ | isString home1 name1 && isFloat home2 name2 -> Bag.one StringToFloat
287+ | isBool home2 name2 -> Bag.one AnythingToBool
288+
289+ (_, _) -> Bag.empty
290+
291+
292+isBool :: ModuleName.Canonical -> N.Name -> Bool
293+isBool home name =
294+ home == ModuleName.basics && name == N.bool
295+
296+
297+isInt :: ModuleName.Canonical -> N.Name -> Bool
298+isInt home name =
299+ home == ModuleName.basics && name == N.int
300+
301+
302+isFloat :: ModuleName.Canonical -> N.Name -> Bool
303+isFloat home name =
304+ home == ModuleName.basics && name == N.float
305+
306+
307+isString :: ModuleName.Canonical -> N.Name -> Bool
308+isString home name =
309+ home == ModuleName.string && name == N.string
310+
311+
312+isMaybe :: ModuleName.Canonical -> N.Name -> Bool
313+isMaybe home name =
314+ home == ModuleName.maybe && name == N.maybe
315+
316+
317+isList :: ModuleName.Canonical -> N.Name -> Bool
318+isList home name =
319+ home == ModuleName.list && name == N.list
320+
321+
322+isSimilar :: Type -> Type -> Bool
323+isSimilar tipe1 tipe2 =
324+ case diff Map.empty RT.None tipe1 tipe2 of
325+ Similar _ _ -> True
326+ Different _ _ _ -> False
327+
328+
329+yellowApply :: Localizer -> RT.Context -> ModuleName.Canonical -> N.Name -> Type -> H.Doc
330+yellowApply dict ctx home name tipe =
331+ RT.apply ctx
332+ (H.dullyellow (nameToDoc dict home name))
333+ [toDoc dict RT.App tipe]
275334
276335
277336
src/Type/Type.hs+13−4
@@ -473,18 +473,18 @@ contentToErrorType variable content =
473473 FlexSuper super maybeName ->
474474 case maybeName of
475475 Just name ->
476− return (ET.FlexSuper name)
476+ return (ET.FlexSuper (superToSuper super) name)
477477
478478 Nothing ->
479479 do name <- getFreshSuperName super
480480 liftIO $ UF.modify variable (\desc -> desc { _content = FlexSuper super (Just name) })
481− return (ET.FlexSuper name)
481+ return (ET.FlexSuper (superToSuper super) name)
482482
483483 RigidVar name ->
484484 return (ET.RigidVar name)
485485
486− RigidSuper _ name ->
487− return (ET.RigidSuper name)
486+ RigidSuper super name ->
487+ return (ET.RigidSuper (superToSuper super) name)
488488
489489 Alias home name args realVariable ->
490490 do errArgs <- traverse (traverse variableToErrorType) args
@@ -495,6 +495,15 @@ contentToErrorType variable content =
495495 return ET.Error
496496
497497
498+superToSuper :: SuperType -> ET.Super
499+superToSuper super =
500+ case super of
501+ Number -> ET.Number
502+ Comparable -> ET.Comparable
503+ Appendable -> ET.Appendable
504+ CompAppend -> ET.CompAppend
505+
506+
498507termToErrorType :: FlatType -> StateT NameState IO ET.Type
499508termToErrorType term =
500509 case term of