on 00a3069 help sign in
elk/src/Reporting/Error/Canonicalize.hs
766 lines 26 kB history raw
1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
3module Reporting.Error.Canonicalize
4 ( Error(..)
5 , BadArityContext(..)
6 , InvalidPayload(..)
7 , DuplicatePatternContext(..)
8 , variable
9 , VarKind(..)
10 , VarProblem(..)
11 , toReport
12 )
13 where
16import qualified Data.Char as Char
17import Data.Text (Text)
19import qualified AST.Canonical as Can
20import qualified AST.Source as Src
21import qualified Data.Index as Index
22import qualified Elm.Name as N
23import qualified Reporting.Annotation as A
24import qualified Reporting.Region as R
25import qualified Reporting.Render.Code as Code
26import qualified Reporting.Render.Type as RenderType
27import qualified Reporting.Report as Report
28import qualified Reporting.Helpers as H
29import Reporting.Helpers ( Doc, (<>) )
33-- CANONICALIZATION ERRORS
36data Error
37 = Var VarError
38 | AnnotationTooShort R.Region N.Name Index.ZeroBased Int
39 | BadArity R.Region BadArityContext N.Name Int Int
40 | Binop R.Region N.Name N.Name
41 | DuplicateDecl N.Name R.Region R.Region
42 | DuplicateType N.Name R.Region R.Region
43 | DuplicateCtor N.Name R.Region R.Region
44 | DuplicateBinop N.Name R.Region R.Region
45 | DuplicateField N.Name R.Region R.Region
46 | DuplicateAliasArg N.Name N.Name R.Region R.Region
47 | DuplicateUnionArg N.Name N.Name R.Region R.Region
48 | DuplicatePattern DuplicatePatternContext N.Name R.Region R.Region
49 | EffectNotFound R.Region N.Name
50 | EffectFunctionNotFound R.Region N.Name
51 | ExportDuplicate N.Name R.Region R.Region
52 | ExportNotFound R.Region VarKind N.Name [N.Name]
53 | ExportOpenAlias R.Region N.Name
54 | ImportCtorByName R.Region N.Name N.Name
55 | ImportNotFound R.Region N.Name [N.Name]
56 | ImportOpenAlias R.Region N.Name
57 | ImportExposingNotFound R.Region N.Name N.Name [N.Name]
58 | PatternHasRecordCtor R.Region N.Name
59 | PortPayloadInvalid R.Region N.Name Can.Type InvalidPayload
60 | PortTypeInvalid R.Region N.Name Can.Type
61 | RecursiveAlias R.Region N.Name [N.Name] Src.Type [N.Name]
62 | RecursiveDecl [Can.Def]
63 | RecursiveLet (A.Located N.Name) [N.Name]
64 | Shadowing N.Name R.Region R.Region
65 | TupleLargerThanThree R.Region
66 | TypeVarsUnboundInUnion R.Region N.Name [N.Name] [A.Located N.Name]
67 | TypeVarsMessedUpInAlias R.Region N.Name [N.Name] [A.Located N.Name] [A.Located N.Name]
70data BadArityContext
71 = TypeArity
72 | PatternArity
75data DuplicatePatternContext
76 = DPLambdaArgs
77 | DPFuncArgs N.Name
78 | DPCaseBranch
79 | DPLetBinding
80 | DPDestruct
83data InvalidPayload
84 = ExtendedRecord
85 | Function
86 | TypeVariable N.Name
87 | UnsupportedType N.Name
91-- VARIABLES
94data VarError =
95 VarError
96 { _kind :: VarKind
97 , _name :: Text
98 , _problem :: VarProblem
99 , _suggestions :: [Text]
100 }
103data VarProblem
104 = Ambiguous
105 | UnknownQualifier Text Text
106 | QualifiedUnknown Text Text
107 | ExposedUnknown
110variable :: VarKind -> Text -> VarProblem -> [Text] -> Error
111variable kind name problem suggestions =
112 Var (VarError kind name problem suggestions)
116-- KIND
119data VarKind
120 = BadOp
121 | BadVar
122 | BadPattern
123 | BadType
126toKindInfo :: VarKind -> N.Name -> ( Doc, Doc, Doc )
127toKindInfo kind name =
128 case kind of
129 BadOp ->
130 ( "an", "operator", "(" <> H.nameToDoc name <> ")" )
132 BadVar ->
133 ( "a", "value", "`" <> H.nameToDoc name <> "`" )
135 BadPattern ->
136 ( "a", "pattern", "`" <> H.nameToDoc name <> "`" )
138 BadType ->
139 ( "a", "type", "`" <> H.nameToDoc name <> "`" )
143-- TO REPORT
146toReport :: Code.Source -> RenderType.Localizer -> Error -> Report.Report
147toReport source localizer err =
148 case err of
149 Var varError ->
150 error "TODO" varError
152 AnnotationTooShort region name index leftovers ->
153 let
154 numTypeArgs = Index.toHuman index
155 numDefArgs = numTypeArgs + leftovers
156 in
157 Report.Report "BAD TYPE ANNOTATION" region [] $
158 Report.toCodeSnippet source region Nothing
159 (
160 H.reflow $
161 "The type annotation for `" <> N.toString name <> "` says it can accept "
162 <> H.args numTypeArgs <> ", but the definition says it has "
163 <> H.args numDefArgs <> ":"
164 ,
165 H.reflow $
166 "Is the type annotation missing something? Should some argument"
167 <> (if leftovers == 1 then "" else "s")
168 <> " be deleted? Maybe some parentheses are missing?"
169 )
171 BadArity region badArityContext name expected actual ->
172 let
173 thing =
174 case badArityContext of
175 TypeArity -> "type"
176 PatternArity -> "constructor"
177 in
178 if actual < expected then
179 Report.Report "TOO FEW ARGS" region [] $
180 Report.toCodeSnippet source region Nothing
181 (
182 H.reflow $
183 "The `" <> N.toString name <> "` " <> thing <> " needs "
184 <> H.args expected <> ", but I only see " <> show actual <> ":"
185 ,
186 "What is missing? Is there some typo?"
187 )
189 else
190 Report.Report "TOO MANY ARGS" region [] $
191 Report.toCodeSnippet source region Nothing
192 (
193 H.reflow $
194 "The `" <> N.toString name <> "` " <> thing <> " needs "
195 <> H.args expected <> ", but I see " <> show actual <> " instead:"
196 ,
197 if actual - expected == 1 then
198 "Which is the extra one? Maybe some parentheses are missing?"
199 else
200 "Which are the extra ones? Maybe some parentheses are missing?"
201 )
203 Binop region op1 op2 ->
204 Report.Report "INFIX PROBLEM" region [] $
205 Report.toCodeSnippet source region Nothing
206 (
207 H.reflow $
208 "You cannot mix (" <> N.toString op1 <> ") and (" <> N.toString op2 <> ") without parentheses."
209 ,
210 H.reflow
211 "I do not know how to group these expressions. Add parentheses for me!"
212 )
214 DuplicateDecl name r1 r2 ->
215 nameClash source r1 r2 $
216 "This file has multiple `" <> N.toString name <> "` declarations."
218 DuplicateType name r1 r2 ->
219 nameClash source r1 r2 $
220 "This file defines multiple `" <> N.toString name <> "` types."
222 DuplicateCtor name r1 r2 ->
223 nameClash source r1 r2 $
224 "This file defines multiple `" <> N.toString name <> "` type constructors."
226 DuplicateBinop name r1 r2 ->
227 nameClash source r1 r2 $
228 "This file defines multiple (" <> N.toString name <> ") operators."
230 DuplicateField name r1 r2 ->
231 nameClash source r1 r2 $
232 "This record has multiple `" <> N.toString name <> "` fields."
234 DuplicateAliasArg typeName name r1 r2 ->
235 nameClash source r1 r2 $
236 "The `" <> N.toString typeName <> "` type alias has multilpe `" <> N.toString name <> "` type variables."
238 DuplicateUnionArg typeName name r1 r2 ->
239 nameClash source r1 r2 $
240 "The `" <> N.toString typeName <> "` type has multilpe `" <> N.toString name <> "` type variables."
242 DuplicatePattern context name r1 r2 ->
243 nameClash source r1 r2 $
244 case context of
245 DPLambdaArgs ->
246 "This anonymous function has multiple `" <> N.toString name <> "` arguments."
248 DPFuncArgs funcName ->
249 "The `" <> N.toString funcName <> "` function has multiple `" <> N.toString name <> "` arguments."
251 DPCaseBranch ->
252 "This `case` pattern has multiple `" <> N.toString name <> "` variables."
254 DPLetBinding ->
255 "This `let` expression defines `" <> N.toString name <> "` more than once!"
257 DPDestruct ->
258 "This pattern contains multiple `" <> N.toString name <> "` variables."
260 EffectNotFound _ _ ->
261 error "TODO EffectNotFound"
263 EffectFunctionNotFound _ _ ->
264 error "TODO EffectFunctionNotFound"
266 ExportDuplicate name r1 r2 ->
267 let
268 messageThatEndsWithPunctuation =
269 "You are trying to expose `" <> N.toString name <> "` multiple times!"
270 in
271 Report.Report "REDUNDANT EXPORT" r2 [] $
272 Report.toCodePair source r1 r2
273 (
274 H.reflow messageThatEndsWithPunctuation
275 ,
276 "Remove one of them and you should be all set!"
277 )
278 (
279 H.reflow (messageThatEndsWithPunctuation <> " Once here:")
280 ,
281 "And again right here:"
282 ,
283 "Remove one of them and you should be all set!"
284 )
286 ExportNotFound region kind rawName suggestions ->
287 Report.Report "UNKNOWN EXPORT" region suggestions $
288 let (a, thing, name) = toKindInfo kind rawName in
289 H.stack
290 [ H.fillSep
291 ["You","are","trying","to","expose",a,thing,"named"
292 ,name,"but","I","cannot","find","its","definition."
293 ]
294 , H.maybeYouWant Nothing suggestions
295 ]
297 ExportOpenAlias region name ->
298 error "TODO" region name
300 ImportCtorByName region ctor tipe ->
301 Report.Report "BAD IMPORT" region [] $
302 Report.toCodeSnippet source region Nothing
303 (
304 H.reflow $
305 "You are trying to import the `" <> N.toString ctor
306 <> "` type constructor by name:"
307 ,
308 H.fillSep
309 ["Try","importing",H.green (H.nameToDoc tipe <> "(..)"),"instead."
310 ,"The","dots","mean","“expose","the",H.nameToDoc tipe,"type","and"
311 ,"all","its","constructors”","so","it","gives","you","access","to"
312 , H.nameToDoc ctor <> "."
313 ]
314 )
316 ImportNotFound region name suggestions ->
317 Report.Report "UNKNOWN IMPORT" region suggestions $
318 Report.toCodeSnippet source region Nothing
319 (
320 H.reflow $
321 "I could not find a `" <> N.toString name <> "` module to import!"
322 ,
323 H.maybeYouWant Nothing suggestions
324 )
326 ImportOpenAlias region name ->
327 Report.Report "BAD IMPORT" region [] $
328 Report.toCodeSnippet source region Nothing
329 (
330 H.reflow $
331 "The `" <> N.toString name <> "` type alias cannot be followed by (..) like this:"
332 ,
333 H.stack
334 [ "Remove the (..) and it should work."
335 , H.link "Hint"
336 "The distinction between `type` and `type alias` is important here. Read"
337 "types-vs-type-aliases"
338 "to learn more."
339 ]
340 )
342 ImportExposingNotFound region name value suggestions ->
343 Report.Report "BAD IMPORT" region suggestions $
344 Report.toCodeSnippet source region Nothing
345 (
346 H.reflow $
347 "The `" <> N.toString name
348 <> "` module does not expose `"
349 <> N.toString value <> "`:"
350 ,
351 H.maybeYouWant Nothing suggestions
352 )
354 PatternHasRecordCtor region name ->
355 Report.Report "BAD PATTERN" region [] $
356 Report.toCodeSnippet source region Nothing
357 (
358 H.reflow $
359 "You can construct records by using `" <> N.toString name
360 <> "` as a function, but it is not available in pattern matching like this:"
361 ,
362 H.reflow $
363 "I recommend matching matching the record as a variable and unpacking it later."
364 )
366 PortPayloadInvalid region portName badType invalidPayload ->
367 let
368 (aBadKindOfThing, elaboration) =
369 case invalidPayload of
370 ExtendedRecord ->
371 (
372 "an extended record"
373 ,
374 H.reflow $
375 "The exact shape of the record must be known at compile time. No type variables!"
376 )
378 Function ->
379 (
380 "a function"
381 ,
382 H.reflow $
383 "Functions cannot be sent in and out ports. If we allowed functions in from JS\
384 \ they may perform some side-effects. If we let functions out, they could produce\
385 \ incorrect results because Elm optimizations assume there are no side-effects."
386 )
389 TypeVariable name ->
390 (
391 "an unspecified type"
392 ,
393 H.reflow $
394 "Type variables like `" <> N.toString name <> "` cannot flow through ports because\
395 \ the marshalling code needs to know the exact data that it is going to process."
396 )
398 UnsupportedType name ->
399 (
400 "a `" <> N.toString name <> "` value"
401 ,
402 H.stack
403 [ H.reflow $ "The types that can flow in and out of Elm include:"
404 , H.indent 4 $
405 H.reflow $
406 "Ints, Floats, Bools, Strings, Maybes, Lists, Arrays,\
407 \ tuples, records, and JSON values."
408 , H.reflow $
409 "Since JSON values can flow through, you can use JSON encoders and decoders\
410 \ to allow other types through as well. More advanced users often just do\
411 \ everything with encoders and decoders for more control and better errors."
412 ]
413 )
414 in
415 Report.Report "PORT ERROR" region [] $
416 Report.toCodeSnippet source region Nothing
417 (
418 H.reflow $
419 "The `" <> N.toString portName <> "` port is trying to transmit " <> aBadKindOfThing <> ":"
420 ,
421 H.stack
422 [ error "TODO" badType
423 , elaboration
424 , H.link "Hint"
425 "Ports are not a traditional FFI for calling JS functions directly. They need a different mindset! Read"
426 "ports"
427 "to learn how to use ports effectively."
428 ]
429 )
431 PortTypeInvalid region name badType ->
432 Report.Report "BAD PORT" region [] $
433 Report.toCodeSnippet source region Nothing
434 (
435 H.reflow $
436 "Port `" <> N.toString name <> "` has an invalid type."
437 ,
438 error "TODO PortTypeInvalid" badType
439 )
441 RecursiveAlias region name args tipe others ->
442 aliasRecursionReport source localizer region name args tipe others
444 RecursiveDecl cyclicValueDefs ->
445 error "TODO" cyclicValueDefs
447 RecursiveLet (A.At region name) names ->
448 Report.Report "CYCLIC VALUE" region [] $
449 Report.toCodeSnippet source region Nothing $
450 case names of
451 [] ->
452 (
453 H.reflow $
454 "The `" <> N.toString name <> "` value has a direct use of `" <> N.toString name <> "` in its definition."
455 ,
456 H.stack
457 [ H.reflow $
458 "To know what `" <> N.toString name
459 <> "` is, I need to know what `" <> N.toString name
460 <> "` is. Let me recursively figure that out. Hmm, I need to know what `"
461 <> N.toString name <> "` is..."
462 , H.link "Hint"
463 "The root problem is often a typo in some variable name, but I recommend reading"
464 "bad-recursion"
465 "for more detailed advice, especially if you actually do need a recursive value."
466 ]
467 )
469 _ ->
470 (
471 H.reflow $
472 "I do not allow cyclic values in `let` expressions."
473 ,
474 H.stack
475 [ H.reflow $
476 "The `" <> N.toString name
477 <> "` value depends on itself through the following chain of definitions:"
478 , H.indent 4 $ H.drawCycle (name:names)
479 , H.link "Hint"
480 "The root problem is often a typo in some variable name, but I recommend reading"
481 "bad-recursion"
482 "for more detailed advice, especially if you actually do want mutually recursive values."
483 ]
484 )
486 Shadowing name r1 r2 ->
487 Report.Report "SHADOWING" r2 [] $
488 Report.toCodePair source r1 r2
489 ( "These variables cannot have the same name:"
490 , advice
491 )
492 ( H.reflow $ "The name `" <> N.toString name <> "` is first defined here:"
493 , "But then it is defined AGAIN over here:"
494 , advice
495 )
496 where
497 advice =
498 H.stack
499 [ H.reflow $
500 "Think of a more helpful name for one of them and you should be all set!"
501 , H.link "Note"
502 "Linters advise against shadowing, so Elm makes “best practices” the default. Read"
503 "shadowing"
504 "for more details on this choice."
505 ]
507 TupleLargerThanThree region ->
508 Report.Report "BAD TUPLE" region [] $
509 Report.toCodeSnippet source region Nothing
510 (
511 "I only accept tuples with two or three items. This has too many:"
512 ,
513 H.stack
514 [ H.reflow $
515 "I recommend switching to records. Each item will be named, and you can use\
516 \ the `point.x` syntax to access them."
518 , H.link "Note" "Read" "tuples"
519 "for more comprehensive advice on working with large chunks of data in Elm."
520 ]
521 )
523 TypeVarsUnboundInUnion _ _ _ _ ->
524 error "TODO TypeVarsUnboundInUnion"
526 TypeVarsMessedUpInAlias _ _ _ _ _ ->
527 error "TODO TypeVarsMessedUpInAlias"
532-- UnboundTypeVarsInUnion typeName givenVars unbound ->
533-- unboundTypeVars "type" typeName givenVars unbound
535-- UnboundTypeVarsInAlias typeName givenVars unbound ->
536-- unboundTypeVars "type alias" typeName givenVars unbound
538-- UnusedTypeVarsInAlias typeName givenVars unused ->
539-- Report.report
540-- "UNUSED TYPE VARIABLES"
541-- Nothing
542-- ( "Type alias `" <> typeName <> "` cannot have unused type variables: "
543-- <> H.commaSep unused
544-- )
545-- ( H.stack
546-- [ text "You probably need to change the declaration like this:"
547-- , H.dullyellow $ hsep $
548-- map text ("type" : "alias" : typeName : filter (`notElem` unused) givenVars ++ ["=", "..."])
549-- ]
550-- )
552-- MessyTypeVarsInAlias typeName givenVars unused unbound ->
553-- Report.report
554-- "TYPE VARIABLE PROBLEMS"
555-- Nothing
556-- ( "Type alias `" <> typeName <> "` has some problems with type variables."
557-- )
558-- ( H.stack
559-- [ H.reflow $
560-- "The declaration says it uses certain type variables ("
561-- <> H.commaSep unused <> ") but they do not appear in the aliased type. "
562-- <> "Furthermore, the aliased type says it uses type variables ("
563-- <> H.commaSep unbound
564-- <> ") that do not appear in the declaration."
565-- , text "You probably need to change the declaration like this:"
566-- , H.dullyellow $ hsep $
567-- map text ("type" : "alias" : typeName : filter (`notElem` unused) givenVars ++ unbound ++ ["=", "..."])
568-- ]
569-- )
572--unboundTypeVars :: Text -> Text -> [Text] -> [Text] -> Report.Report
573--unboundTypeVars declKind typeName givenVars unboundVars =
574-- Report.report
575-- "UNBOUND TYPE VARIABLES"
576-- Nothing
577-- ( H.capitalize declKind <> " `" <> typeName <> "` must declare its use of type variable"
578-- <> H.commaSep unboundVars
579-- )
580-- ( H.stack
581-- [ text "You probably need to change the declaration like this:"
582-- , hsep $
583-- map text (declKind : typeName : givenVars)
584-- ++ map (H.dullyellow . text) unboundVars
585-- ++ map text ["=", "..."]
586-- , reflow $
587-- "Here's why. Imagine one `" <> typeName <> "` where `" <> head unboundVars <>
588-- "` is an Int and another where it is a Bool. When we explicitly list the type\
589-- \ variables, the type checker can see that they are actually different types."
590-- ]
591-- )
595-- NAME CLASH
598nameClash :: Code.Source -> R.Region -> R.Region -> String -> Report.Report
599nameClash source r1 r2 messageThatEndsWithPunctuation =
600 Report.Report "NAME CLASH" r2 [] $
601 Report.toCodePair source r1 r2
602 (
603 H.reflow messageThatEndsWithPunctuation
604 ,
605 "How can I know which one you want? Rename one of them!"
606 )
607 (
608 H.reflow (messageThatEndsWithPunctuation <> " One here:")
609 ,
610 "And another one here:"
611 ,
612 "How can I know which one you want? Rename one of them!"
613 )
617{-- VAR ERROR
620varErrorToReport :: VarError -> Report.Report
621varErrorToReport (VarError kind name problem suggestions) =
622 let
623 learnMore orMaybe =
624 H.reflow $
625 orMaybe <> " `import` works different than you expect? Learn all about it here: "
626 <> H.hintLink "imports"
628 namingError overview maybeStarter specializedSuggestions =
629 Report.reportDoc "NAMING ERROR" Nothing overview $
630 case H.maybeYouWant' maybeStarter specializedSuggestions of
631 Nothing ->
632 learnMore "Maybe"
633 Just doc ->
634 H.stack [ doc, learnMore "Or maybe" ]
636 specialNamingError specialHint =
637 Report.reportDoc "NAMING ERROR" Nothing (cannotFind kind name) (H.hsep specialHint)
638 in
639 case problem of
640 Ambiguous ->
641 namingError (ambiguous kind name) Nothing suggestions
643 UnknownQualifier qualifier localName ->
644 namingError
645 (cannotFind kind name)
646 (Just $ text $ "No module called `" <> qualifier <> "` has been imported.")
647 (map (\modul -> modul <> "." <> localName) suggestions)
649 QualifiedUnknown qualifier localName ->
650 namingError
651 (cannotFind kind name)
652 (Just $ text $ "`" <> qualifier <> "` does not expose `" <> localName <> "`.")
653 (map (\v -> qualifier <> "." <> v) suggestions)
655 ExposedUnknown ->
656 case name of
657 "!=" -> specialNamingError (notEqualsHint name)
658 "!==" -> specialNamingError (notEqualsHint name)
659 "===" -> specialNamingError equalsHint
660 "%" -> specialNamingError modHint
661 _ -> namingError (cannotFind kind name) Nothing suggestions
664cannotFind :: VarKind -> Text -> [Doc]
665cannotFind kind rawName =
666 let ( a, thing, name ) = toKindInfo kind rawName in
667 [ "Cannot", "find", a, thing, "named", H.dullyellow name <> ":" ]
670ambiguous :: VarKind -> Text -> [Doc]
671ambiguous kind rawName =
672 let ( _a, thing, name ) = toKindInfo kind rawName in
673 [ "This", "usage", "of", "the", H.dullyellow name, thing, "is", "ambiguous." ]
676notEqualsHint :: Text -> [Doc]
677notEqualsHint op =
678 [ "Looking", "for", "the", "“not", "equal”", "operator?", "The", "traditional"
679 , H.dullyellow $ text $ "(" <> op <> ")"
680 , "is", "replaced", "by", H.green "(/=)", "in", "Elm.", "It", "is", "meant"
681 , "to", "look", "like", "the", "“not", "equal”", "sign", "from", "math!", "(≠)"
682 ]
685equalsHint :: [Doc]
686equalsHint =
687 [ "A", "special", H.dullyellow "(===)", "operator", "is", "not", "needed"
688 , "in", "Elm.", "We", "use", H.green "(==)", "for", "everything!"
689 ]
692modHint :: [Doc]
693modHint =
694 [ "Rather", "than", "a", H.dullyellow "(%)", "operator,"
695 , "Elm", "has", "a", H.green "modBy", "function."
696 , "Learn", "more", "here:"
697 , "<https://package.elm-lang.org/packages/elm-lang/core/latest/Basics#modBy>"
698 ]
701-}
704-- ARG MISMATCH
707_argMismatchReport :: Code.Source -> R.Region -> String -> N.Name -> Int -> Int -> Report.Report
708_argMismatchReport source region kind name expected actual =
709 let
710 numArgs =
711 "too "
712 <> (if actual < expected then "few" else "many")
713 <> " arguments"
714 in
715 Report.Report (map Char.toUpper numArgs) region [] $
716 Report.toCodeSnippet source region Nothing
717 (
718 H.reflow $
719 kind <> " " <> N.toString name <> " has " <> numArgs <> "."
720 ,
721 H.reflow $
722 "Expecting " <> show expected <> ", but got " <> show actual <> "."
723 )
727-- BAD ALIAS RECURSION
730aliasRecursionReport :: Code.Source -> RenderType.Localizer -> R.Region -> N.Name -> [N.Name] -> Src.Type -> [N.Name] -> Report.Report
731aliasRecursionReport source localizer region name args tipe others =
732 case others of
733 [] ->
734 Report.Report "ALIAS PROBLEM" region [] $
735 Report.toCodeSnippet source region Nothing
736 (
737 "This type alias is recursive, forming an infinite type!"
738 ,
739 H.stack
740 [ H.reflow $
741 "When I expand a recursive type alias, it just keeps getting bigger and bigger.\
742 \ So dealiasing results in an infinitely large type! Try this instead:"
743 , H.indent 4 $
744 RenderType.decl localizer name args [(name, [error "TODO" tipe])]
745 , H.link "Hint"
746 "This is kind of a subtle distinction. I suggested the naive fix, but I recommend reading"
747 "recursive-alias"
748 "for ideas on how to do better."
749 ]
750 )
752 _ ->
753 Report.Report "ALIAS PROBLEM" region [] $
754 Report.toCodeSnippet source region Nothing
755 (
756 "This type alias is part of a mutually recursive set of type aliases."
757 ,
758 H.stack
759 [ "It is part of this cycle of type aliases:"
760 , H.indent 4 (H.drawCycle (name:others))
761 , H.reflow $
762 "You need to convert at least one of these type aliases into a `type`."
763 , H.link "Note" "Read" "recursive-alias"
764 "to learn why this `type` vs `type alias` distinction matters. It is subtle but important!"
765 ]
766 )