Skip to content

Commit 0afcd23

Browse files
committed
Special error for underapplied functions
1 parent 806a49f commit 0afcd23

File tree

3 files changed

+87
-1
lines changed

3 files changed

+87
-1
lines changed

parser-typechecker/src/Unison/PrintError.hs

+57
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ import Unison.Util.AnnotatedText qualified as AT
7373
import Unison.Util.ColorText (Color)
7474
import Unison.Util.ColorText qualified as Color
7575
import Unison.Util.Monoid (intercalateMap)
76+
import Unison.Util.Monoid qualified as Monoid
7677
import Unison.Util.Pretty (ColorText, Pretty)
7778
import Unison.Util.Pretty qualified as Pr
7879
import Unison.Util.Range (Range (..), startingLine)
@@ -274,6 +275,62 @@ renderTypeError e env src = case e of
274275
" expression ",
275276
"need to have the same type."
276277
]
278+
FunctionUnderApplied {..} ->
279+
mconcat
280+
[ Pr.lines
281+
[ "I found a value of type: " <> style Type1 (renderType' env foundLeaf),
282+
"where I expected to find: " <> style Type2 (renderType' env expectedLeaf),
283+
"it looks like it might be a function application that's just missing these arguments:\n\n",
284+
Monoid.intercalateMap ", " (style Type1 . renderType' env) needArgs
285+
],
286+
"\n\n",
287+
showSourceMaybes
288+
src
289+
[ -- these are overwriting the colored ranges for some reason?
290+
-- (,Color.ForceShow) <$> rangeForAnnotated mismatchSite
291+
-- , (,Color.ForceShow) <$> rangeForType foundType
292+
-- , (,Color.ForceShow) <$> rangeForType expectedType
293+
-- ,
294+
(,Type1) . startingLine <$> (rangeForAnnotated mismatchSite),
295+
(,Type2) <$> rangeForAnnotated expectedLeaf
296+
],
297+
fromOverHere'
298+
src
299+
[styleAnnotated Type1 foundLeaf]
300+
[styleAnnotated Type2 expectedLeaf],
301+
unitHint,
302+
intLiteralSyntaxTip mismatchSite expectedType,
303+
debugNoteLoc
304+
. mconcat
305+
$ [ "\nloc debug:",
306+
"\n mismatchSite: ",
307+
annotatedToEnglish mismatchSite,
308+
"\n foundType: ",
309+
annotatedToEnglish foundType,
310+
"\n foundLeaf: ",
311+
annotatedToEnglish foundLeaf,
312+
"\n expectedType: ",
313+
annotatedToEnglish expectedType,
314+
"\n expectedLeaf: ",
315+
annotatedToEnglish expectedLeaf,
316+
"\n"
317+
],
318+
debugSummary note
319+
]
320+
where
321+
unitHintMsg =
322+
"\nHint: Actions within a block must have type "
323+
<> style Type2 (renderType' env expectedLeaf)
324+
<> ".\n"
325+
<> " Use "
326+
<> style Type1 "_ = <expr>"
327+
<> " to ignore a result."
328+
unitHint = if giveUnitHint then unitHintMsg else ""
329+
giveUnitHint = case expectedType of
330+
Type.Ref' u | u == unitRef -> case mismatchSite of
331+
Term.Let1Named' v _ _ -> Var.isAction v
332+
_ -> False
333+
_ -> False
277334
NotFunctionApplication {..} ->
278335
case Type.arity ft of
279336
0 ->

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

+29-1
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

+1
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)