on master help sign in
Make record access error messages much more precise!
bd99774Evan Czaplicki
compiler/src/Reporting/Error/Type.hs+17−21
@@ -66,7 +66,7 @@ data Context
66 | CaseBranch Index.ZeroBased
66 | CaseBranch Index.ZeroBased
67 | CallArity MaybeName Int
67 | CallArity MaybeName Int
68 | CallArg MaybeName Index.ZeroBased
68 | CallArg MaybeName Index.ZeroBased
69− | RecordAccess N.Name
69+ | RecordAccess R.Region (Maybe N.Name) R.Region N.Name
70 | RecordUpdateKeys N.Name (Map.Map N.Name Can.FieldUpdate)
70 | RecordUpdateKeys N.Name (Map.Map N.Name Can.FieldUpdate)
71 | RecordUpdateValue N.Name
71 | RecordUpdateValue N.Name
72 | Destructure
72 | Destructure
@@ -805,30 +805,35 @@ toExprReport source localizer exprRegion category tipe expected =
805 ]
805 ]
806 )
806 )
807
807
808− RecordAccess field ->
808+ RecordAccess recordRegion maybeName fieldRegion field ->
809 case T.iteratedDealias tipe of
809 case T.iteratedDealias tipe of
810 T.Record fields ext ->
810 T.Record fields ext ->
811− custom (Just exprRegion)
811+ custom (Just fieldRegion)
812 ( D.reflow $
812 ( D.reflow $
813+ "This "
814+ <> maybe "" (\n -> "`" <> N.toString n <> "`") maybeName
813− "This record does not have a `" <> N.toString field <> "` field:"
815+ <> " record does not have a `" <> N.toString field <> "` field:"
814 , case Suggest.sort (N.toString field) (N.toString . fst) (Map.toList fields) of
816 , case Suggest.sort (N.toString field) (N.toString . fst) (Map.toList fields) of
815 [] ->
817 [] ->
816 D.reflow "In fact, it is a record with NO fields!"
818 D.reflow "In fact, it is a record with NO fields!"
817
819
818 f:fs ->
820 f:fs ->
819 D.stack
821 D.stack
820− [ addAlias "record" tipe (\noun -> "It is a " <> noun <> " with fields:")
822+ [ D.reflow $
823+ "This is usually a typo. Here are the "
824+ <> maybe "" (\n -> "`" <> N.toString n <> "`") maybeName
825+ <> " fields that are most similar:"
821 , toNearbyRecord localizer f fs ext
826 , toNearbyRecord localizer f fs ext
822 , D.fillSep
827 , D.fillSep
823− ["So","instead","of",D.dullyellow (D.fromName field) <> ","
828+ ["So","maybe",D.dullyellow (D.fromName field)
824− ,"maybe","you","want",D.green (D.fromName (fst f)) <> "?"
829+ ,"should","be",D.green (D.fromName (fst f)) <> "?"
825 ]
830 ]
826 ]
831 ]
827 )
832 )
828
833
829 _ ->
834 _ ->
830 badType
835 badType
831− ( Just exprRegion
836+ ( Just recordRegion
832 , "This is not a record, so it has no fields to access!"
837 , "This is not a record, so it has no fields to access!"
833 , "It is"
838 , "It is"
834 , [ D.fillSep
839 , [ D.fillSep
@@ -869,11 +874,12 @@ toExprReport source localizer exprRegion category tipe expected =
869
874
870 f:fs ->
875 f:fs ->
871 D.stack
876 D.stack
872− [ addAlias "record" tipe (\noun -> rStr <> " is a " <> noun <> " with fields:")
877+ [ D.reflow $
878+ "This is usually a typo. Here are the " <> rStr <> " fields that are most similar:"
873 , toNearbyRecord localizer f fs ext
879 , toNearbyRecord localizer f fs ext
874 , D.fillSep
880 , D.fillSep
875− ["So","instead","of",D.dullyellow (D.fromName field) <> ","
881+ ["So","maybe",D.dullyellow (D.fromName field)
876− ,"maybe","you","want",D.green (D.fromName (fst f)) <> "?"
882+ ,"should","be",D.green (D.fromName (fst f)) <> "?"
877 ]
883 ]
878 ]
884 ]
879 )
885 )
@@ -923,16 +929,6 @@ countArgs tipe =
923 0
929 0
924
930
925
931
926−addAlias :: String -> T.Type -> (String -> String) -> D.Doc
927−addAlias noun tipe toMessage =
928− case tipe of
929− T.Alias _ name _ _ ->
930− D.reflow (toMessage ("`" <> N.toString name <> "`"))
931−
932− _ ->
933− D.reflow (toMessage noun)
934−
935−
936
932
937-- FIELD NAME HELPERS
933-- FIELD NAME HELPERS
938
934
compiler/src/Type/Constrain/Expression.hs+17−21
@@ -121,15 +121,15 @@ constrain rtv (A.At region expression) expected =
121 return $ exists [ fieldVar, extVar ] $
121 return $ exists [ fieldVar, extVar ] $
122 CEqual region (Accessor field) (FunN recordType fieldType) expected
122 CEqual region (Accessor field) (FunN recordType fieldType) expected
123
123
124− Can.Access expr field ->
124+ Can.Access expr (A.At accessRegion field) ->
125 do extVar <- mkFlexVar
125 do extVar <- mkFlexVar
126 fieldVar <- mkFlexVar
126 fieldVar <- mkFlexVar
127 let extType = VarN extVar
127 let extType = VarN extVar
128 let fieldType = VarN fieldVar
128 let fieldType = VarN fieldVar
129 let recordType = RecordN (Map.singleton field fieldType) extType
129 let recordType = RecordN (Map.singleton field fieldType) extType
130
130
131− recordCon <-
131+ let context = RecordAccess (A.toRegion expr) (getAccessName expr) accessRegion field
132− constrain rtv expr (FromContext region (RecordAccess field) recordType)
132+ recordCon <- constrain rtv expr (FromContext region context recordType)
133
133
134 return $ exists [ fieldVar, extVar ] $
134 return $ exists [ fieldVar, extVar ] $
135 CAnd
135 CAnd
@@ -219,26 +219,22 @@ constrainArg rtv region maybeName index arg =
219getName :: Can.Expr -> MaybeName
219getName :: Can.Expr -> MaybeName
220getName (A.At _ expr) =
220getName (A.At _ expr) =
221 case expr of
221 case expr of
222− Can.VarLocal name ->
222+ Can.VarLocal name -> FuncName name
223− FuncName name
224−
225− Can.VarTopLevel _ name ->
223+ Can.VarTopLevel _ name -> FuncName name
226− FuncName name
227−
228− Can.VarForeign _ name _ ->
224+ Can.VarForeign _ name _ -> FuncName name
225+ Can.VarCtor _ _ name _ _ -> CtorName name
226+ Can.VarOperator op _ _ _ -> OpName op
229− FuncName name
227+ Can.VarKernel _ name -> FuncName name
228+ _ -> NoName
230
229
231− Can.VarCtor _ _ name _ _ ->
232− CtorName name
233
230
234− Can.VarOperator op _ _ _ ->
231+getAccessName :: Can.Expr -> Maybe N.Name
235− OpName op
232+getAccessName (A.At _ expr) =
236−
233+ case expr of
237− Can.VarKernel _ name ->
234+ Can.VarLocal name -> Just name
238− FuncName name
235+ Can.VarTopLevel _ name -> Just name
239−
236+ Can.VarForeign _ name _ -> Just name
240− _ ->
237+ _ -> Nothing
241− NoName
242
238
243
239
244
240