Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make errors nicer when TDNR fails #4641

Merged
merged 19 commits into from
Jan 26, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/unison-pretty-printer/src/Unison/Util/Pretty.hs
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ wrapImplPreserveSpaces = \case
(Lit s) -> fromMaybe False (fmap (isSpaceNotNewline . fst) $ LL.uncons s)
_ -> False
f p | startsWithSpace p = p `orElse` newline
f p = p
f p = p `orElse` (newline <> p)

isSpaceNotNewline :: Char -> Bool
isSpaceNotNewline c = isSpace c && not (c == '\n')
Expand Down
171 changes: 97 additions & 74 deletions parser-typechecker/src/Unison/PrintError.hs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import Unison.Prelude
import Unison.PrettyPrintEnv qualified as PPE
import Unison.PrettyPrintEnv.Names qualified as PPE
import Unison.Reference qualified as R
import Unison.Referent (Referent, pattern Ref)
import Unison.Referent (Referent, toReference, pattern Ref)
import Unison.Result (Note (..))
import Unison.Result qualified as Result
import Unison.Settings qualified as Settings
Expand Down Expand Up @@ -173,7 +173,7 @@ renderTypeError ::
String ->
Path.Absolute ->
Pretty ColorText
renderTypeError e env src curPath = case e of
renderTypeError e env src _curPath = case e of
runarorama marked this conversation as resolved.
Show resolved Hide resolved
BooleanMismatch {..} ->
mconcat
[ Pr.wrap $
Expand Down Expand Up @@ -629,51 +629,68 @@ renderTypeError e env src curPath = case e of
_ -> Pr.wrap $ "It should be of type " <> Pr.group (style Type1 (renderType' env expectedType) <> ".")
UnknownTerm {..} ->
let (correct, wrongTypes, wrongNames) =
foldr sep id suggestions ([], [], [])
sep (C.Suggestion name typ _ match) r =
foldr sep id (sortOn (Text.length . C.suggestionName) suggestions) ([], [], [])
runarorama marked this conversation as resolved.
Show resolved Hide resolved
sep s@(C.Suggestion _ _ _ match) r =
case match of
C.Exact -> (_1 %~ ((name, typ) :)) . r
C.WrongType -> (_2 %~ ((name, typ) :)) . r
C.WrongName -> (_3 %~ ((name, typ) :)) . r
libPath = Path.absoluteToPath' curPath Path.:> "lib"
C.Exact -> (_1 %~ (s :)) . r
C.WrongType -> (_2 %~ (s :)) . r
C.WrongName -> (_3 %~ (s :)) . r
-- libPath = Path.absoluteToPath' curPath Path.:> "lib"
runarorama marked this conversation as resolved.
Show resolved Hide resolved
undefinedSymbolHelp =
Pr.wrap $
mconcat
[ mconcat ["Its type should conform to ", style Type1 (renderType' env expectedType), "."],
Pr.hang
"Some common causes of this error include:"
( Pr.bulleted
[ Pr.wrap "Your current namespace is too deep to contain the definition in its subtree",
Pr.wrap "The definition is part of a library which hasn't been added to this project",
Pr.wrap "You have a typo in the name"
]
)
]
in mconcat
[ "I couldn't find any definitions matching the name ",
[ "I couldn't figure out what ",
style ErrorSite (Var.nameStr unknownTermV),
" inside the namespace ",
prettyPath' (Path.absoluteToPath' curPath),
"\n\n",
" refers to here:\n\n",
annotatedAsErrorSite src termSite,
"\n",
Pr.hang
"Some common causes of this error include:"
( Pr.bulleted
[ Pr.wrap "Your current namespace is too deep to contain the definition in its subtree",
Pr.wrap "The definition is part of a library which hasn't been added to this project"
]
)
<> "\n\n"
<> "To add a library to this project use the command: "
<> Pr.backticked ("fork <.path.to.lib> " <> Pr.shown (libPath Path.:> "<libname>")),
"\n\n",
case expectedType of
Type.Var' (TypeVar.Existential {}) -> "There are no constraints on its type."
_ ->
"Whatever it is, its type should conform to "
<> style Type1 (renderType' env expectedType)
<> ".",
"\n\n",
-- ++ showTypeWithProvenance env src Type1 expectedType
case correct of
[] -> case wrongTypes of
[] -> case wrongNames of
[] -> mempty
[] -> undefinedSymbolHelp
wrongs -> formatWrongs wrongNameText wrongs
wrongs -> formatWrongs wrongTypeText wrongs
wrongs ->
Pr.wrap
( "The name "
<> style Identifier (Var.nameStr unknownTermV)
<> " is ambiguous. I tried to resolve it by type but"
)
<> " "
<> case expectedType of
Type.Var' (TypeVar.Existential {}) -> Pr.wrap "its type could be anything." <> "\n"
_ ->
Pr.wrap
"no term with that name would pass typechecking. I think its type should be:"
<> "\n\n"
<> Pr.indentN 4 (style Type1 (renderType' env expectedType))
<> "\n\n"
<> Pr.wrap "If that's not what you expected, you may have a type error somewhere else in your code."
<> " "
<> Pr.wrap (Pr.bold "Help me out by using a more specific name here or adding a type annotation.")
runarorama marked this conversation as resolved.
Show resolved Hide resolved
<> "\n\n"
<> formatWrongs wrongTypeText wrongs
suggs ->
mconcat
[ "I found some terms in scope that have matching names and types. ",
"Maybe you meant one of these:\n\n",
intercalateMap "\n" formatSuggestion suggs
[ "The name "
<> style Identifier (Var.nameStr unknownTermV)
<> " is ambiguous. ",
"Its type should conform to:\n\n",
Pr.indentN 4 (style Type1 (renderType' env expectedType)),
"\n\n",
Pr.wrap "I found some terms in scope that have matching names and types. Maybe you meant one of these:",
"\n\n",
intercalateMap "\n" (renderSuggestion env) suggs
]
]
DuplicateDefinitions {..} ->
Expand Down Expand Up @@ -735,47 +752,48 @@ renderTypeError e env src curPath = case e of
]
where
wrongTypeText pl =
mconcat
[ "I found ",
pl "a term" "some terms",
" in scope with ",
pl "a " "",
"matching name",
pl "" "s",
" but ",
pl "a " "",
"different type",
pl "" "s",
". ",
"If ",
pl "this" "one of these",
" is what you meant, try using the fully qualified name and I might ",
"be able to give you a more illuminating error message: \n\n"
]
Pr.paragraphyText
( mconcat
[ "I found ",
pl "a term" "some terms",
" in scope with ",
pl "a " "",
"matching name",
pl "" "s",
" but ",
pl "a " "",
"different type",
pl "" "s",
". ",
"If ",
pl "this" "one of these",
" is what you meant, try using its full name:"
]
)
<> "\n\n"
wrongNameText pl =
mconcat
[ "I found ",
pl "a term" "some terms",
" in scope with ",
pl "a " "",
"matching type",
pl "" "s",
" but ",
pl "a " "",
"different name",
pl "" "s",
". ",
"Maybe you meant ",
pl "this" "one of these",
":\n\n"
]
formatSuggestion :: (Text, C.Type v loc) -> Pretty ColorText
formatSuggestion (name, typ) =
" - " <> fromString (Text.unpack name) <> " : " <> renderType' env typ
Pr.paragraphyText
( mconcat
[ "I found ",
pl "a term" "some terms",
" in scope with ",
pl "a " "",
"matching type",
pl "" "s",
" but ",
pl "a " "",
"different name",
pl "" "s",
". ",
"Maybe you meant ",
pl "this" "one of these",
":\n\n"
]
)
formatWrongs txt wrongs =
let sz = length wrongs
pl a b = if sz == 1 then a else b
in mconcat [txt pl, intercalateMap "\n" formatSuggestion wrongs]
in mconcat [txt pl, intercalateMap "\n" (renderSuggestion env) wrongs]
ordinal :: (IsString s) => Int -> s
ordinal n =
fromString $
Expand Down Expand Up @@ -1134,7 +1152,12 @@ renderType env f t = renderType0 env f (0 :: Int) (cleanup t)
renderSuggestion ::
(IsString s, Semigroup s, Var v) => Env -> C.Suggestion v loc -> s
renderSuggestion env sug =
fromString (Text.unpack $ C.suggestionName sug)
renderTerm
env
( case C.suggestionReplacement sug of
Right ref -> Term.ref () (toReference ref)
Left v -> Term.var () v
)
<> " : "
<> renderType'
env
Expand Down
20 changes: 6 additions & 14 deletions unison-src/transcripts-manual/rewrites.output.md
Original file line number Diff line number Diff line change
Expand Up @@ -306,21 +306,17 @@ Instead, it should be an unbound free variable, which doesn't typecheck:

Loading changes detected in scratch.u.

I couldn't find any definitions matching the name bar21 inside the namespace .
I couldn't figure out what bar21 refers to here:

19 | bar21

Its type should conform to _ .
runarorama marked this conversation as resolved.
Show resolved Hide resolved
Some common causes of this error include:
* Your current namespace is too deep to contain the
definition in its subtree
* The definition is part of a library which hasn't been
added to this project

To add a library to this project use the command: `fork <.path.to.lib> .lib.<libname>`

There are no constraints on its type.


* You have a typo in the name

```
In this example, the `a` is locally bound by the rule, so it shouldn't capture the `a = 39494` binding which is in scope at the point of the replacement:
Expand Down Expand Up @@ -366,21 +362,17 @@ The `a` introduced will be freshened to not capture the `a` in scope, so it rema

Loading changes detected in scratch.u.

I couldn't find any definitions matching the name a1 inside the namespace .
I couldn't figure out what a1 refers to here:

6 | a1

Its type should conform to _ .
Some common causes of this error include:
* Your current namespace is too deep to contain the
definition in its subtree
* The definition is part of a library which hasn't been
added to this project

To add a library to this project use the command: `fork <.path.to.lib> .lib.<libname>`

There are no constraints on its type.


* You have a typo in the name

```
## Structural find
Expand Down
10 changes: 3 additions & 7 deletions unison-src/transcripts/destructuring-binds.output.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,21 +86,17 @@ ex4 =

Loading changes detected in scratch.u.

I couldn't find any definitions matching the name a inside the namespace .
I couldn't figure out what a refers to here:

2 | (a,b) = (a Nat.+ b, 19)

Its type should conform to Nat .
runarorama marked this conversation as resolved.
Show resolved Hide resolved
Some common causes of this error include:
* Your current namespace is too deep to contain the
definition in its subtree
* The definition is part of a library which hasn't been
added to this project

To add a library to this project use the command: `fork <.path.to.lib> .lib.<libname>`

Whatever it is, its type should conform to Nat.


* You have a typo in the name

```
Even though the parser accepts any pattern on the LHS of a bind, it looks pretty weird to see things like `12 = x`, so we avoid showing a destructuring bind when the LHS is a "literal" pattern (like `42` or "hi"). Again these examples wouldn't compile with coverage checking.
Expand Down
Loading
Loading