[GHC] #10180: Lint check: Empty alternatives imply bottoming scrutinee
#10180: Lint check: Empty alternatives imply bottoming scrutinee -------------------------------------+------------------------------------- Reporter: nomeata | Owner: nomeata Type: task | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.11 Keywords: | Operating System: Unknown/Multiple Architecture: | Type of failure: None/Unknown Unknown/Multiple | Blocked By: Test Case: | Related Tickets: Blocking: | Differential Revisions: | -------------------------------------+------------------------------------- As suggested by SPJ in https://phabricator.haskell.org/D747?id=2498#inline-6057 -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10180> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#10180: Lint check: Empty alternatives imply bottoming scrutinee -------------------------------------+------------------------------------- Reporter: nomeata | Owner: nomeata Type: task | Status: infoneeded Priority: normal | Milestone: Component: Compiler | Version: 7.11 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: None/Unknown | Unknown/Multiple Blocked By: | Test Case: Related Tickets: | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Changes (by nomeata): * status: new => infoneeded Comment: Sure enough, it trips over this {{{ *** Core Lint errors : in result of Simplifier *** libraries/base/Data/Void.hs:66:8: Warning: [in body of lambda with binder a_a2y6 :: Void] No alternatives for a case scrutinee not known to diverge for sure: a_a2y6 }}} Simon, what would you prefer: Should `exprIsBottom e` hold for all `e` where the type is a data type with no constructors, or should the lint check take that into account? -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10180#comment:1> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#10180: Lint check: Empty alternatives imply bottoming scrutinee -------------------------------------+------------------------------------- Reporter: nomeata | Owner: nomeata Type: task | Status: infoneeded Priority: normal | Milestone: Component: Compiler | Version: 7.11 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: None/Unknown | Unknown/Multiple Blocked By: | Test Case: Related Tickets: | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Comment (by nomeata): Ok, added it to the linter for now; whether `exprIsBottom` should be extended is a different question. Next linter error when compiling GHC: It complains about this code: {{{ *** Core Lint errors : in result of Simplifier *** <no location info>: Warning: In a case alternative: (False) No alternatives for a case scrutinee not known to diverge for sure: \ (@ a_agBy) -> lvl_smAM @ a_agBy ds3_alsA [...] case \ (@ a_agBy) -> lvl_smAM @ a_agBy ds3_alsA of _ [Occ=Dead] { }}} So there is a lambda under the case, but it is a type lambda. Bogus or not? -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10180#comment:2> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#10180: Lint check: Empty alternatives imply bottoming scrutinee -------------------------------------+------------------------------------- Reporter: nomeata | Owner: nomeata Type: task | Status: infoneeded Priority: normal | Milestone: Component: Compiler | Version: 7.11 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: None/Unknown | Unknown/Multiple Blocked By: | Test Case: Related Tickets: | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Comment (by simonpj):
Simon, what would you prefer: Should `exprIsBottom e` hold for all `e` where the type is a data type with no constructors, or should the lint check take that into account?
Very interesting. * What program gives rise to `case (x::Void) of {}`? * Yes, I think there is a case for making `exprIsBottom` hold for data types with no constructors; after all, such an expression is bound to diverge. * A slightly less pervasive change would to to say that an empty `case` is ok on a data type that has an empty set of constructors. Less pervasive in the sense that it affects this Lint check only, whereas the `exprIsBottom` fix would have broader implications: good ones, I think, but also rare. -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10180#comment:3> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#10180: Lint check: Empty alternatives imply bottoming scrutinee -------------------------------------+------------------------------------- Reporter: nomeata | Owner: nomeata Type: task | Status: infoneeded Priority: normal | Milestone: Component: Compiler | Version: 7.11 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: None/Unknown | Unknown/Multiple Blocked By: | Test Case: Related Tickets: | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Comment (by simonpj): Replying to [comment:2 nomeata]:
So there is a lambda under the case, but it is a type lambda. Bogus or not?
Ha! There's a missing case in `exprIsBottom`: {{{ exprIsBottom (Lam v e) | isTyVar v = exprIsBottom e }}} Well spotted. Simon -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10180#comment:4> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#10180: Lint check: Empty alternatives imply bottoming scrutinee -------------------------------------+------------------------------------- Reporter: nomeata | Owner: nomeata Type: task | Status: infoneeded Priority: normal | Milestone: Component: Compiler | Version: 7.11 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: None/Unknown | Unknown/Multiple Blocked By: | Test Case: Related Tickets: | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Comment (by nomeata): Hi, Replying to [comment:3 simonpj]:
Very interesting. * What program gives rise to `case (x::Void) of {}`?
Precisely that program :-) See `Data.Void`: {{{ absurd :: Void -> a absurd a = case a of {} }}}
* Yes, I think there is a case for making `exprIsBottom` hold for data types with no constructors; after all, such an expression is bound to diverge. * A slightly less pervasive change would to to say that an empty `case` is ok on a data type that has an empty set of constructors. Less pervasive in the sense that it affects this Lint check only, whereas the `exprIsBottom` fix would have broader implications: good ones, I think, but also rare.
I’ll do that first, and afterwards look into moving the no-constructor- test into `exprIsBottom`. Replying to [comment:4 simonpj]:
Replying to [comment:2 nomeata]:
So there is a lambda under the case, but it is a type lambda. Bogus or not?
Ha! There's a missing case in `exprIsBottom`: {{{ exprIsBottom (Lam v e) | isTyVar v = exprIsBottom e }}} Well spotted.
I’ll add that and see if the linter is happy then. -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10180#comment:5> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#10180: Lint check: Empty alternatives imply bottoming scrutinee -------------------------------------+------------------------------------- Reporter: nomeata | Owner: nomeata Type: task | Status: infoneeded Priority: normal | Milestone: Component: Compiler | Version: 7.11 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: None/Unknown | Unknown/Multiple Blocked By: | Test Case: Related Tickets: | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Comment (by simonpj): BTW, there should be no need to check ''both'' `exprIsHNF` ''and'' `exprIsBottom`! -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10180#comment:6> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#10180: Lint check: Empty alternatives imply bottoming scrutinee -------------------------------------+------------------------------------- Reporter: nomeata | Owner: nomeata Type: task | Status: infoneeded Priority: normal | Milestone: Component: Compiler | Version: 7.11 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: None/Unknown | Unknown/Multiple Blocked By: | Test Case: Related Tickets: | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Comment (by simonpj): branch `wip/T10180` -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10180#comment:7> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#10180: Lint check: Empty alternatives imply bottoming scrutinee -------------------------------------+------------------------------------- Reporter: nomeata | Owner: nomeata Type: task | Status: infoneeded Priority: normal | Milestone: Component: Compiler | Version: 7.11 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: None/Unknown | Unknown/Multiple Blocked By: | Test Case: Related Tickets: | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Comment (by nomeata): There is no end of reasons why something diverges: {{{ =====> T2431(normal) 339 of 4438 [0, 0, 0] cd ./deSugar/should_compile && "/home/jojo/build/haskell/ghc- validate/inplace/bin/ghc-stage2" -c T2431.hs -fforce-recomp -dcore-lint -dcmm-lint -dno-debug-output -no-user-package-db -rtsopts -fno-warn-tabs -fno-ghci-history -ddump-simpl -dsuppress-uniques > T2431.comp.stderr 2>&1 Compile failed (status 256) errors were: *** Core Lint errors : in result of Simplifier *** T2431.hs:8:8: Warning: [in body of lambda with binder x :: Int :~: Bool] No alternatives for a case scrutinee not known to diverge for sure: x *** Offending Program *** absurd :: forall a. Int :~: Bool -> a [LclIdX, Arity=1, Str=DmdType, Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=ALWAYS_IF(arity=1,unsat_ok=True,boring_ok=True)}] absurd = \ (@ a) (x :: Int :~: Bool) -> case x of _ [Occ=Dead] { } *** End of Offense *** }}} I’m beginning to wonder if the lint rule is a good idea. After all, by trying to add such a rule we are saying “definite divergence must be obvious”, and hence we would be precluding the compiler to derive and use definite divergence that is non-obvious, or that was obvious at one point in the pipeline, but isn’t any more later when the linter runs. Here is an example of non-trivially always empty types: `Void` wrapped deeply in some strict data type. Or even `Void` as the result of a type function wrapped deeply in some strict data type. -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10180#comment:8> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#10180: Lint check: Empty alternatives imply bottoming scrutinee -------------------------------------+------------------------------------- Reporter: nomeata | Owner: nomeata Type: task | Status: infoneeded Priority: normal | Milestone: Component: Compiler | Version: 7.11 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: None/Unknown | Unknown/Multiple Blocked By: | Test Case: Related Tickets: | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Comment (by simonpj): Well that's why I said (somewhere) that I wasn't certain this would work, but it would be interesting to know. The point is: to make the empty case, GHC '''knew''' at some point that the expression must diverge. So how has it lost that knowledge? I think that in this case it's a use of `dataConCantMatch`. So maybe we can beef up `isEmptyTy` to use that information? (And ultimately perhaps beef up `exprIsBottom`.) My point is, this is a useful quest. Simon -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10180#comment:9> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#10180: Lint check: Empty alternatives imply bottoming scrutinee -------------------------------------+------------------------------------- Reporter: nomeata | Owner: nomeata Type: task | Status: infoneeded Priority: normal | Milestone: Component: Compiler | Version: 7.11 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: None/Unknown | Unknown/Multiple Blocked By: | Test Case: Related Tickets: | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Comment (by nomeata): I’ll be happy to pursue this course and see how far it will take us, but my gut feeling is that this will never be complete and even if GHC+the test suite go through, someone will be able to figure out how to make the linter fail erroneously. Making the check use `dataConCannotMatch` now, but it uses `Unify.typesCantMatch` which does not even look through newtypes (yet), so this will only get us so far... -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10180#comment:10> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#10180: Lint check: Empty alternatives imply bottoming scrutinee -------------------------------------+------------------------------------- Reporter: nomeata | Owner: nomeata Type: task | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.11 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: None/Unknown | Unknown/Multiple Blocked By: | Test Case: Related Tickets: | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Changes (by nomeata): * status: infoneeded => new Comment: Ok, with the better `isEmptyTy`, it goes through, see Phab:D753. I’m not sure where best to put `isEmptyTy`. My first guess was `Types.hs`, but that would require extending `DataCon.hs-boot`. -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10180#comment:11> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#10180: Lint check: Empty alternatives imply bottoming scrutinee -------------------------------------+------------------------------------- Reporter: nomeata | Owner: nomeata Type: task | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.11 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: None/Unknown | Unknown/Multiple Blocked By: | Test Case: Related Tickets: | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Comment (by simonpj): Perhaps in `CoreUtils` which contains the other place that `dataConCannotMatch` is called, so it's a related chunk of code. -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10180#comment:12> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#10180: Lint check: Empty alternatives imply bottoming scrutinee -------------------------------------+------------------------------------- Reporter: nomeata | Owner: nomeata Type: task | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.11 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: None/Unknown | Unknown/Multiple Blocked By: | Test Case: Related Tickets: | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Comment (by nomeata): Sounds good, thanks! Will push this as soon as the build validates on phabricator. -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10180#comment:13> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#10180: Lint check: Empty alternatives imply bottoming scrutinee -------------------------------------+------------------------------------- Reporter: nomeata | Owner: nomeata Type: task | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.11 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: None/Unknown | Unknown/Multiple Blocked By: | Test Case: Related Tickets: | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Comment (by Joachim Breitner <mail@…>): In [changeset:"5673bfc49ec1e54a1540197078041a9da9754fa3/ghc"]: {{{ #!CommitTicketReference repository="ghc" revision="5673bfc49ec1e54a1540197078041a9da9754fa3" exprIsBottom should look through type lambdas as evaluting (\ (@ a) -> e) diverges if and only if evaluating e diverges. This was found in the context of #10180. }}} -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10180#comment:14> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#10180: Lint check: Empty alternatives imply bottoming scrutinee -------------------------------------+------------------------------------- Reporter: nomeata | Owner: nomeata Type: task | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.11 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: None/Unknown | Unknown/Multiple Blocked By: | Test Case: Related Tickets: | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Comment (by Joachim Breitner <mail@…>): In [changeset:"a0678f1f0e62496c108491e1c80d5eef3936474a/ghc"]: {{{ #!CommitTicketReference repository="ghc" revision="a0678f1f0e62496c108491e1c80d5eef3936474a" New Lint check: no alternatives implies bottoming expression detected either by exprIsBottom or by an empty type. This was suggested by SPJ and fixes #10180. }}} -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10180#comment:15> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#10180: Lint check: Empty alternatives imply bottoming scrutinee -------------------------------------+------------------------------------- Reporter: nomeata | Owner: nomeata Type: task | Status: closed Priority: normal | Milestone: Component: Compiler | Version: 7.11 Resolution: fixed | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: None/Unknown | Unknown/Multiple Blocked By: | Test Case: Related Tickets: | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Changes (by nomeata): * status: new => closed * resolution: => fixed -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10180#comment:16> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#10180: Lint check: Empty alternatives imply bottoming scrutinee -------------------------------------+------------------------------------- Reporter: nomeata | Owner: nomeata Type: task | Status: closed Priority: normal | Milestone: Component: Compiler | Version: 7.11 Resolution: fixed | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: None/Unknown | Unknown/Multiple Blocked By: | Test Case: Related Tickets: | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Comment (by simonpj): Wuuld it be possible to add a `Note` to `isEmptyTy` and the call in CoreLint, explaiing what is going on, and referring to this ticket. As its stands there is zero commentary. Thanks Simon -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10180#comment:17> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#10180: Lint check: Empty alternatives imply bottoming scrutinee -------------------------------------+------------------------------------- Reporter: nomeata | Owner: nomeata Type: task | Status: closed Priority: normal | Milestone: Component: Compiler | Version: 7.11 Resolution: fixed | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: None/Unknown | Unknown/Multiple Blocked By: | Test Case: Related Tickets: | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Comment (by Joachim Breitner <mail@…>): In [changeset:"8f08069668f12ce019be3277bc4baacb477a77ed/ghc"]: {{{ #!CommitTicketReference repository="ghc" revision="8f08069668f12ce019be3277bc4baacb477a77ed" Add Note [No alternatives lint check] in a follow up to #10180. }}} -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10180#comment:18> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#10180: Lint check: Empty alternatives imply bottoming scrutinee -------------------------------------+------------------------------------- Reporter: nomeata | Owner: nomeata Type: task | Status: closed Priority: normal | Milestone: Component: Compiler | Version: 7.11 Resolution: fixed | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: None/Unknown | Unknown/Multiple Blocked By: | Test Case: Related Tickets: | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Comment (by nomeata): Of course, sorry for the negligence. -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10180#comment:19> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#10180: Lint check: Empty alternatives imply bottoming scrutinee -------------------------------------+------------------------------------- Reporter: nomeata | Owner: nomeata Type: task | Status: closed Priority: normal | Milestone: Component: Compiler | Version: 7.11 Resolution: fixed | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: None/Unknown | Unknown/Multiple Blocked By: | Test Case: Related Tickets: | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Comment (by Joachim Breitner <mail@…>): In [changeset:"6cf0c7962c582eefb84cdf2735504d034fb16314/ghc"]: {{{ #!CommitTicketReference repository="ghc" revision="6cf0c7962c582eefb84cdf2735504d034fb16314" Some stress tests for the empty case linter This is a variation of T2431 where the emptyness of the type is hidden behind a newtype, a type family and a closed type family. In all cases, it would be sound for the compiler to determine that the equality type is empty and the case alternatives may be dropped. At the moment, GHC does _not_ determine that. But if it ever does, this test ensures that we do not forget to make the lint from #10180 smarter as well. }}} -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10180#comment:20> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#10180: Lint check: Empty alternatives imply bottoming scrutinee -------------------------------------+------------------------------------- Reporter: nomeata | Owner: nomeata Type: task | Status: closed Priority: normal | Milestone: Component: Compiler | Version: 7.11 Resolution: fixed | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: None/Unknown | Unknown/Multiple Blocked By: | Test Case: Related Tickets: | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Comment (by Simon Peyton Jones <simonpj@…>): In [changeset:"33cfa5ff9db4e7886b3e7c2eed5ac1c75436bc4c/ghc"]: {{{ #!CommitTicketReference repository="ghc" revision="33cfa5ff9db4e7886b3e7c2eed5ac1c75436bc4c" More comments (related to Trac #10180) }}} -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10180#comment:21> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#10180: Lint check: Empty alternatives imply bottoming scrutinee -------------------------------------+------------------------------------- Reporter: nomeata | Owner: nomeata Type: task | Status: closed Priority: normal | Milestone: Component: Compiler | Version: 7.11 Resolution: fixed | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: None/Unknown | Unknown/Multiple Blocked By: | Test Case: Related Tickets: | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Comment (by nomeata): A small change in the simplifier settings showed a False Positive of the new lint check: https://phabricator.haskell.org/D851#23033 Given that the check is known to be not complete, I suggest to turn it into a lint warning. -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10180#comment:22> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#10180: Lint check: Empty alternatives imply bottoming scrutinee -------------------------------------+------------------------------------- Reporter: nomeata | Owner: nomeata Type: task | Status: closed Priority: normal | Milestone: Component: Compiler | Version: 7.11 Resolution: fixed | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: None/Unknown | Unknown/Multiple Blocked By: | Test Case: Related Tickets: | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Comment (by simonpj): Let's not move too fast See my comments on Phab:D851. -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10180#comment:23> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
participants (1)
-
GHC