Skip to content

Commit d35c9c5

Browse files
committed
Special error for underapplied functions
1 parent 67bd215 commit d35c9c5

File tree

3 files changed

+87
-1
lines changed

3 files changed

+87
-1
lines changed

parser-typechecker/src/Unison/PrintError.hs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ import Unison.Util.AnnotatedText qualified as AT
7474
import Unison.Util.ColorText (Color)
7575
import Unison.Util.ColorText qualified as Color
7676
import Unison.Util.Monoid (intercalateMap)
77+
import Unison.Util.Monoid qualified as Monoid
7778
import Unison.Util.Pretty (ColorText, Pretty)
7879
import Unison.Util.Pretty qualified as Pr
7980
import Unison.Util.Range (Range (..), startingLine)
@@ -328,6 +329,62 @@ renderTypeError e env src = case e of
328329
" expression ",
329330
"need to have the same type."
330331
]
332+
FunctionUnderApplied {..} ->
333+
mconcat
334+
[ Pr.lines
335+
[ "I found a value of type: " <> style Type1 (renderType' env foundLeaf),
336+
"where I expected to find: " <> style Type2 (renderType' env expectedLeaf),
337+
"it looks like it might be a function application that's just missing these arguments:\n\n",
338+
Monoid.intercalateMap ", " (style Type1 . renderType' env) needArgs
339+
],
340+
"\n\n",
341+
showSourceMaybes
342+
src
343+
[ -- these are overwriting the colored ranges for some reason?
344+
-- (,Color.ForceShow) <$> rangeForAnnotated mismatchSite
345+
-- , (,Color.ForceShow) <$> rangeForType foundType
346+
-- , (,Color.ForceShow) <$> rangeForType expectedType
347+
-- ,
348+
(,Type1) . startingLine <$> (rangeForAnnotated mismatchSite),
349+
(,Type2) <$> rangeForAnnotated expectedLeaf
350+
],
351+
fromOverHere'
352+
src
353+
[styleAnnotated Type1 foundLeaf]
354+
[styleAnnotated Type2 expectedLeaf],
355+
unitHint,
356+
intLiteralSyntaxTip mismatchSite expectedType,
357+
debugNoteLoc
358+
. mconcat
359+
$ [ "\nloc debug:",
360+
"\n mismatchSite: ",
361+
annotatedToEnglish mismatchSite,
362+
"\n foundType: ",
363+
annotatedToEnglish foundType,
364+
"\n foundLeaf: ",
365+
annotatedToEnglish foundLeaf,
366+
"\n expectedType: ",
367+
annotatedToEnglish expectedType,
368+
"\n expectedLeaf: ",
369+
annotatedToEnglish expectedLeaf,
370+
"\n"
371+
],
372+
debugSummary note
373+
]
374+
where
375+
unitHintMsg =
376+
"\nHint: Actions within a block must have type "
377+
<> style Type2 (renderType' env expectedLeaf)
378+
<> ".\n"
379+
<> " Use "
380+
<> style Type1 "_ = <expr>"
381+
<> " to ignore a result."
382+
unitHint = if giveUnitHint then unitHintMsg else ""
383+
giveUnitHint = case expectedType of
384+
Type.Ref' u | u == unitRef -> case mismatchSite of
385+
Term.Let1Named' v _ _ -> Var.isAction v
386+
_ -> False
387+
_ -> False
331388
NotFunctionApplication {..} ->
332389
case Type.arity ft of
333390
0 ->

parser-typechecker/src/Unison/Typechecker/TypeError.hs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import Unison.Type (Type)
1111
import Unison.Type qualified as Type
1212
import Unison.Typechecker.Context qualified as C
1313
import Unison.Typechecker.Extractor qualified as Ex
14+
import Unison.Typechecker.TypeVar (lowerType)
1415
import Unison.Util.Monoid (whenM)
1516
import Unison.Var (Var)
1617
import Prelude hiding (all, and, or)
@@ -61,6 +62,15 @@ data TypeError v loc
6162
note :: C.ErrorNote v loc,
6263
args :: [C.Term v loc]
6364
}
65+
| FunctionUnderApplied
66+
{ foundType :: C.Type v loc, -- overallType1
67+
expectedType :: C.Type v loc, -- overallType2
68+
foundLeaf :: C.Type v loc, -- leaf1
69+
expectedLeaf :: C.Type v loc, -- leaf2
70+
mismatchSite :: C.Term v loc,
71+
note :: C.ErrorNote v loc,
72+
needArgs :: [Type v loc]
73+
}
6474
| AbilityCheckFailure
6575
{ ambient :: [C.Type v loc],
6676
requested :: [C.Type v loc],
@@ -242,9 +252,27 @@ generalMismatch = do
242252
n <- Ex.errorNote
243253
mismatchSite <- Ex.innermostTerm
244254
((foundLeaf, expectedLeaf), (foundType, expectedType)) <- firstLastSubtype
255+
let mayNeedArgs = findUnderApplication foundLeaf expectedLeaf
256+
-- If the found type is a function, and the result of that function matches the expected type,
257+
-- it's likely we're missing some arguments from a function.
258+
245259
case Type.cleanups [sub foundType, sub expectedType, sub foundLeaf, sub expectedLeaf] of
246-
[ft, et, fl, el] -> pure $ Mismatch ft et fl el mismatchSite n
260+
[ft, et, fl, el] ->
261+
case mayNeedArgs of
262+
Just needArgs ->
263+
pure $ FunctionUnderApplied ft et fl el mismatchSite n (lowerType <$> needArgs)
264+
Nothing ->
265+
pure $ Mismatch ft et fl el mismatchSite n
247266
_ -> error "generalMismatch: Mismatched type binding"
267+
where
268+
findUnderApplication found expected
269+
| Right True <- C.isSubtype found expected = pure []
270+
| otherwise =
271+
case found of
272+
Type.Arrow' i o -> (i :) <$> findUnderApplication o expected
273+
Type.ForallNamed' _ body -> findUnderApplication body expected
274+
Type.Effect' _ inner -> findUnderApplication inner expected
275+
_ -> Nothing
248276

249277
and,
250278
or,

unison-cli/src/Unison/LSP/FileAnalysis.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@ analyseNotes fileUri ppe src notes = do
278278
TypeError.Mismatch {mismatchSite} -> singleRange $ ABT.annotation mismatchSite
279279
TypeError.BooleanMismatch {mismatchSite} -> singleRange $ ABT.annotation mismatchSite
280280
TypeError.ExistentialMismatch {mismatchSite} -> singleRange $ ABT.annotation mismatchSite
281+
TypeError.FunctionUnderApplied {mismatchSite} -> singleRange $ ABT.annotation mismatchSite
281282
TypeError.FunctionApplication {f} -> singleRange $ ABT.annotation f
282283
TypeError.NotFunctionApplication {f} -> singleRange $ ABT.annotation f
283284
TypeError.AbilityCheckFailure {abilityCheckFailureSite} -> singleRange abilityCheckFailureSite

0 commit comments

Comments
 (0)