[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 {}`?
* 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
* 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
Precisely that program :-) See `Data.Void`: {{{ absurd :: Void -> a absurd a = case a of {} }}} diverge. 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

#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

#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

#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

#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

#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