on master help sign in
Make record access error messages much more precise!

Say we have the expression model.height. - If `model` is not a record, it will underline model - If it is a record but it has no `height` field, it will underline height So it should feel much more specific.

commitbd99774eb2995760405db64e94192bd42a36fbaf authorEvan Czaplicki <evancz@users.noreply.github.com> dateWed 25 Apr 2018, 02:29 (9 years ago) parent2b0bc09
2 files changed+34−42
compiler/src/Reporting/Error/Type.hs+17−21 compiler/src/Type/Constrain/Expression.hs+17−21
compiler/src/Reporting/Error/Type.hs+17−21
@@ -66,7 +66,7 @@ data Context
6666 | CaseBranch Index.ZeroBased
6767 | CallArity MaybeName Int
6868 | CallArg MaybeName Index.ZeroBased
69− | RecordAccess N.Name
69+ | RecordAccess R.Region (Maybe N.Name) R.Region N.Name
7070 | RecordUpdateKeys N.Name (Map.Map N.Name Can.FieldUpdate)
7171 | RecordUpdateValue N.Name
7272 | Destructure
@@ -805,30 +805,35 @@ toExprReport source localizer exprRegion category tipe expected =
805805 ]
806806 )
807807
808− RecordAccess field ->
808+ RecordAccess recordRegion maybeName fieldRegion field ->
809809 case T.iteratedDealias tipe of
810810 T.Record fields ext ->
811− custom (Just exprRegion)
811+ custom (Just fieldRegion)
812812 ( D.reflow $
813− "This record does not have a `" <> N.toString field <> "` field:"
813+ "This "
814+ <> maybe "" (\n -> "`" <> N.toString n <> "`") maybeName
815+ <> " record does not have a `" <> N.toString field <> "` field:"
814816 , case Suggest.sort (N.toString field) (N.toString . fst) (Map.toList fields) of
815817 [] ->
816818 D.reflow "In fact, it is a record with NO fields!"
817819
818820 f:fs ->
819821 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:"
821826 , toNearbyRecord localizer f fs ext
822827 , D.fillSep
823− ["So","instead","of",D.dullyellow (D.fromName field) <> ","
824− ,"maybe","you","want",D.green (D.fromName (fst f)) <> "?"
828+ ["So","maybe",D.dullyellow (D.fromName field)
829+ ,"should","be",D.green (D.fromName (fst f)) <> "?"
825830 ]
826831 ]
827832 )
828833
829834 _ ->
830835 badType
831− ( Just exprRegion
836+ ( Just recordRegion
832837 , "This is not a record, so it has no fields to access!"
833838 , "It is"
834839 , [ D.fillSep
@@ -869,11 +874,12 @@ toExprReport source localizer exprRegion category tipe expected =
869874
870875 f:fs ->
871876 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:"
873879 , toNearbyRecord localizer f fs ext
874880 , D.fillSep
875− ["So","instead","of",D.dullyellow (D.fromName field) <> ","
876− ,"maybe","you","want",D.green (D.fromName (fst f)) <> "?"
881+ ["So","maybe",D.dullyellow (D.fromName field)
882+ ,"should","be",D.green (D.fromName (fst f)) <> "?"
877883 ]
878884 ]
879885 )
@@ -923,16 +929,6 @@ countArgs tipe =
923929 0
924930
925931
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−
936932
937933-- FIELD NAME HELPERS
938934
compiler/src/Type/Constrain/Expression.hs+17−21
@@ -121,15 +121,15 @@ constrain rtv (A.At region expression) expected =
121121 return $ exists [ fieldVar, extVar ] $
122122 CEqual region (Accessor field) (FunN recordType fieldType) expected
123123
124− Can.Access expr field ->
124+ Can.Access expr (A.At accessRegion field) ->
125125 do extVar <- mkFlexVar
126126 fieldVar <- mkFlexVar
127127 let extType = VarN extVar
128128 let fieldType = VarN fieldVar
129129 let recordType = RecordN (Map.singleton field fieldType) extType
130130
131− recordCon <-
132− constrain rtv expr (FromContext region (RecordAccess field) recordType)
131+ let context = RecordAccess (A.toRegion expr) (getAccessName expr) accessRegion field
132+ recordCon <- constrain rtv expr (FromContext region context recordType)
133133
134134 return $ exists [ fieldVar, extVar ] $
135135 CAnd
@@ -219,26 +219,22 @@ constrainArg rtv region maybeName index arg =
219219getName :: Can.Expr -> MaybeName
220220getName (A.At _ expr) =
221221 case expr of
222− Can.VarLocal name ->
223− FuncName name
224−
225− Can.VarTopLevel _ name ->
226− FuncName name
227−
228− Can.VarForeign _ name _ ->
229− FuncName name
222+ Can.VarLocal name -> FuncName name
223+ Can.VarTopLevel _ name -> FuncName name
224+ Can.VarForeign _ name _ -> FuncName name
225+ Can.VarCtor _ _ name _ _ -> CtorName name
226+ Can.VarOperator op _ _ _ -> OpName op
227+ Can.VarKernel _ name -> FuncName name
228+ _ -> NoName
230229
231− Can.VarCtor _ _ name _ _ ->
232− CtorName name
233230
234− Can.VarOperator op _ _ _ ->
235− OpName op
236−
237− Can.VarKernel _ name ->
238− FuncName name
239−
240− _ ->
241− NoName
231+getAccessName :: Can.Expr -> Maybe N.Name
232+getAccessName (A.At _ expr) =
233+ case expr of
234+ Can.VarLocal name -> Just name
235+ Can.VarTopLevel _ name -> Just name
236+ Can.VarForeign _ name _ -> Just name
237+ _ -> Nothing
242238
243239
244240