on master help sign in
Better error messages for bad record accesses

Add Hint specifically about record access. Instead of showing a type diff, only show the type of the record being accessed. Seemed more confusing than helpful to keep showing the { a | field : b } type.

commitb17a4f051af5780950b790eb50ecb4093c699ab0 authorEvan Czaplicki <evancz@users.noreply.github.com> dateTue 20 Sep 2016, 16:58 (10 years ago) parenta2a2fc0
3 files changed+59−8
src/AST/Expression/General.hs+20 src/Reporting/Error/Type.hs+31−5 src/Type/Constrain/Expression.hs+8−3
src/AST/Expression/General.hs+20
@@ -8,6 +8,8 @@ enrich the AST with more information.
88-}
99module AST.Expression.General where
1010
11+import qualified Data.List as List
12+
1113import qualified AST.Effects as Effects
1214import qualified AST.Literal as Literal
1315import qualified AST.Module.Name as ModuleName
@@ -88,6 +90,24 @@ tuple expressions =
8890 Data ("_Tuple" ++ show (length expressions)) expressions
8991
9092
93+collectFields :: (Var.ToString var) => Expr ann def var typ -> Maybe String
94+collectFields expr =
95+ collectFieldsHelp expr []
96+
97+
98+collectFieldsHelp :: (Var.ToString var) => Expr ann def var typ -> [String] -> Maybe String
99+collectFieldsHelp (A.A _ expr) fields =
100+ case expr of
101+ Var var ->
102+ Just (List.intercalate "." (Var.toString var : fields))
103+
104+ Access record field ->
105+ collectFieldsHelp record (field : fields)
106+
107+ _ ->
108+ Nothing
109+
110+
91111collectApps :: Expr ann def var typ -> [Expr ann def var typ]
92112collectApps annExpr@(A.A _ expr) =
93113 case expr of
src/Reporting/Error/Type.hs+31−5
@@ -75,6 +75,7 @@ data Hint
7575 | Pattern Pattern
7676 | Shader
7777 | Lambda
78+ | Access (Maybe String) String
7879 | Record
7980 -- effect manager problems
8081 | Manager String
@@ -145,11 +146,12 @@ mismatchToReport localizer (MismatchInfo hint leftType rightType maybeReason) =
145146 report =
146147 Report.report "TYPE MISMATCH"
147148
149+ typicalHints =
150+ Maybe.maybeToList (reasonToString =<< maybeReason)
151+
148152 cmpHint leftWords rightWords extraHints =
149153 comparisonHint localizer leftType rightType leftWords rightWords
150− ( Maybe.maybeToList (reasonToString =<< maybeReason)
151− ++ map toHint extraHints
152− )
154+ (typicalHints ++ map toHint extraHints)
153155 in
154156 case hint of
155157 CaseBranch branchNumber region ->
@@ -446,6 +448,30 @@ mismatchToReport localizer (MismatchInfo hint leftType rightType maybeReason) =
446448 []
447449 )
448450
451+ Access (Just body) field ->
452+ let
453+ header =
454+ "`" ++ body ++ "` does not have a field named `" ++ field ++ "`."
455+ in
456+ report Nothing header $ Help.stack $
457+ [ Help.reflowParagraph $ "The type of `" ++ body ++ "` is:"
458+ , indent 4 $ dullyellow $ RenderType.toDoc localizer leftType
459+ , Help.reflowParagraph $ "Which does not contain a field named `" ++ field ++ "`."
460+ ]
461+ ++ typicalHints
462+
463+ Access Nothing field ->
464+ let
465+ header =
466+ "Cannot access a field named `" ++ field ++ "`."
467+ in
468+ report Nothing header $ Help.stack $
469+ [ Help.reflowParagraph $ "You are trying to get `" ++ field ++ "` from a value with this type:"
470+ , indent 4 $ dullyellow $ RenderType.toDoc localizer leftType
471+ , Help.reflowParagraph $ "It is not in there!"
472+ ]
473+ ++ typicalHints
474+
449475 Record ->
450476 report
451477 Nothing
@@ -653,7 +679,7 @@ reasonToString reason =
653679 (fields, maybeDeepReason) =
654680 collectFields reason
655681
656− mabyeDocs =
682+ maybeDocs =
657683 reasonToStringHelp =<< maybeDeepReason
658684
659685 starter =
@@ -667,7 +693,7 @@ reasonToString reason =
667693 _ ->
668694 Just $ "Problem at `" ++ List.intercalate "." fields ++ "`. "
669695 in
670− case (starter, mabyeDocs) of
696+ case (starter, maybeDocs) of
671697 (Nothing, Nothing) ->
672698 Nothing
673699
src/Type/Constrain/Expression.hs+8−3
@@ -110,9 +110,14 @@ constrain env annotatedExpr@(A.A region expression) tipe =
110110 do c' <- constrain env e x
111111 return (x ==> t, c /\ c')
112112
113− E.Access expr label ->
114− exists $ \t ->
115− constrain env expr (record (Map.singleton label tipe) t)
113+ E.Access expr field ->
114+ exists $ \recordType ->
115+ exists $ \ext ->
116+ do recordCon <- constrain env expr recordType
117+ let maybeBody = E.collectFields expr
118+ let desiredType = record (Map.singleton field tipe) ext
119+ let fieldCon = CEqual (Error.Access maybeBody field) region recordType desiredType
120+ return $ recordCon /\ fieldCon
116121
117122 E.Update expr fields ->
118123 exists $ \t ->