[GHC] #13977: ExnStr doesn't propagate "outwards"
#13977: ExnStr doesn't propagate "outwards" -------------------------------------+------------------------------------- Reporter: bgamari | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.0.1 Keywords: | Operating System: Unknown/Multiple Architecture: | Type of failure: None/Unknown Unknown/Multiple | Test Case: | Blocked By: Blocking: | Related Tickets: Differential Rev(s): | Wiki Page: -------------------------------------+------------------------------------- While looking into #8091 (see ticket:8091#comment:9) and #13916, I noticed something that I found rather surprising. Consider this program, {{{#!hs hello :: STR Char -> STM Char hello a = a `orElse` pure 'a' }}} Recall that `catchRetry#` (which `orElse` is defined in terms of) has the following demand signature, {{{ <xC(S),1*C1(U)><L,1*C1(U)><L,U> }}} Note the `x` here: this means it is `ExnStr`, since it doesn't bottom even if the first argument does (despite the fact that it's strict). So, the question is this: What demand should `hello` place on its first argument? I would have thought that it should be precisely the same as the demand that `catchRetry#` places on **its** first argument. However, the demand analyser seems to conclude this: {{{ <C(S),1*C1(U)> }}} Not the lack of an `x`. I believe this may be what causes #13916. -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13977> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#13977: ExnStr doesn't propagate "outwards" -------------------------------------+------------------------------------- Reporter: bgamari | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.0.1 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by bgamari): I think I might see why the demand analyser drops the `x`. Consider `postProcessDmdEnv`, {{{#!hs postProcessDmdEnv :: DmdShell -> DmdEnv -> DmdEnv postProcessDmdEnv ds@(JD { sd = ss, ud = us }) env | Abs <- us = emptyDmdEnv | Str _ _ <- ss , Use One _ <- us = env -- Shell is a no-op | otherwise = mapVarEnv (postProcessDmd ds) env }}} When we get here while demand-analysing the `catchRetry# @Char a` application in `hello` we will have the "shell" equal to `JD {sd = Str ExnStr (), ud = Use One ()}` (as computed as `defer_and_use` by `dmdAnalStar`). The environment we are post-processing is `{aQq-><C(S),1*C1(U)>}`. Note that the shell has an `ExnStr` which gets eaten by the `Str _ _ <- ss` case of `postProcessDmdEnv`, meaning we don't transform the environment. I haven't yet done enough reading to know whether this is correct but is seems suspicious. -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13977#comment:1> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#13977: ExnStr doesn't propagate "outwards" -------------------------------------+------------------------------------- Reporter: bgamari | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.0.1 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Description changed by bgamari: Old description:
While looking into #8091 (see ticket:8091#comment:9) and #13916, I noticed something that I found rather surprising. Consider this program,
{{{#!hs hello :: STR Char -> STM Char hello a = a `orElse` pure 'a' }}}
Recall that `catchRetry#` (which `orElse` is defined in terms of) has the following demand signature, {{{ <xC(S),1*C1(U)><L,1*C1(U)><L,U> }}} Note the `x` here: this means it is `ExnStr`, since it doesn't bottom even if the first argument does (despite the fact that it's strict).
So, the question is this: What demand should `hello` place on its first argument? I would have thought that it should be precisely the same as the demand that `catchRetry#` places on **its** first argument. However, the demand analyser seems to conclude this: {{{ <C(S),1*C1(U)> }}}
Not the lack of an `x`. I believe this may be what causes #13916.
New description: While looking into #8091 (see ticket:8091#comment:9) and #13916, I noticed something that I found rather surprising. Consider this program, {{{#!hs hello :: STR Char -> STM Char hello a = a `orElse` pure 'a' }}} Recall that `catchRetry#` (which `orElse` is defined in terms of) has the following demand signature, {{{ <xC(S),1*C1(U)><L,1*C1(U)><L,U> }}} Note the `x` here: this means it is `ExnStr`, since it doesn't bottom even if the first argument does (despite the fact that it's strict). So, the question is this: What demand should `hello` place on its first argument? I would have thought that it should be precisely the same as the demand that `catchRetry#` places on **its** first argument. However, the demand analyser seems to conclude this: {{{ <C(S),1*C1(U)> }}} Note the lack of an `x`. I believe this may be what causes #13916. -- -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13977#comment:2> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#13977: ExnStr doesn't propagate "outwards" -------------------------------------+------------------------------------- Reporter: bgamari | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.0.1 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Description changed by bgamari: Old description:
While looking into #8091 (see ticket:8091#comment:9) and #13916, I noticed something that I found rather surprising. Consider this program,
{{{#!hs hello :: STR Char -> STM Char hello a = a `orElse` pure 'a' }}}
Recall that `catchRetry#` (which `orElse` is defined in terms of) has the following demand signature, {{{ <xC(S),1*C1(U)><L,1*C1(U)><L,U> }}} Note the `x` here: this means it is `ExnStr`, since it doesn't bottom even if the first argument does (despite the fact that it's strict).
So, the question is this: What demand should `hello` place on its first argument? I would have thought that it should be precisely the same as the demand that `catchRetry#` places on **its** first argument. However, the demand analyser seems to conclude this: {{{ <C(S),1*C1(U)> }}}
Note the lack of an `x`. I believe this may be what causes #13916.
New description: While looking into #8091 (see ticket:8091#comment:9) and #13916, I noticed something that I found rather surprising. Consider this program, {{{#!hs hello :: STM Char -> STM Char hello a = a `orElse` pure 'a' }}} Recall that `catchRetry#` (which `orElse` is defined in terms of) has the following demand signature, {{{ <xC(S),1*C1(U)><L,1*C1(U)><L,U> }}} Note the `x` here: this means it is `ExnStr`, since it doesn't bottom even if the first argument does (despite the fact that it's strict). So, the question is this: What demand should `hello` place on its first argument? I would have thought that it should be precisely the same as the demand that `catchRetry#` places on **its** first argument. However, the demand analyser seems to conclude this: {{{ <C(S),1*C1(U)> }}} Note the lack of an `x`. I believe this may be what causes #13916. -- -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13977#comment:3> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#13977: ExnStr doesn't propagate "outwards" -------------------------------------+------------------------------------- Reporter: bgamari | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.0.1 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by jmct): * cc: jmct (added) -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13977#comment:4> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#13977: ExnStr doesn't propagate "outwards" -------------------------------------+------------------------------------- Reporter: bgamari | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.0.1 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by bgamari): {{{#!patch diff --git a/compiler/basicTypes/Demand.hs b/compiler/basicTypes/Demand.hs index 95c7b79b4f..d777da63f0 100644 --- a/compiler/basicTypes/Demand.hs +++ b/compiler/basicTypes/Demand.hs @@ -1442,7 +1442,8 @@ postProcessDmdResult _ res = res postProcessDmdEnv :: DmdShell -> DmdEnv -> DmdEnv postProcessDmdEnv ds@(JD { sd = ss, ud = us }) env | Abs <- us = emptyDmdEnv - | Str _ _ <- ss + | Str VanStr _ <- ss -- Make sure we don't throw about ExnStrs. + -- See #13977. , Use One _ <- us = env -- Shell is a no-op | otherwise = mapVarEnv (postProcessDmd ds) env -- For the Absent case just discard all usage information }}} -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13977#comment:5> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#13977: ExnStr doesn't propagate "outwards" -------------------------------------+------------------------------------- Reporter: bgamari | Owner: (none) Type: bug | Status: patch Priority: normal | Milestone: Component: Compiler | Version: 8.0.1 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D3756 Wiki Page: | -------------------------------------+------------------------------------- Changes (by bgamari): * status: new => patch * differential: => Phab:D3756 -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13977#comment:6> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#13977: ExnStr doesn't propagate "outwards" -------------------------------------+------------------------------------- Reporter: bgamari | Owner: (none) Type: bug | Status: patch Priority: normal | Milestone: Component: Compiler | Version: 8.0.1 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D3756 Wiki Page: | -------------------------------------+------------------------------------- Comment (by Ben Gamari <ben@…>): In [changeset:"c940e3b92f4527ca59fcae93f36c869de3e7ccb9/ghc" c940e3b/ghc]: {{{ #!CommitTicketReference repository="ghc" revision="c940e3b92f4527ca59fcae93f36c869de3e7ccb9" dmdAnal: Ensure that ExnStr flag isn't dropped inappropriately This fixes #13977 and consequently #13615. Here an optimization in the demand analyser was too liberal, causing us to drop the ExnStr flag and consequently resulting in incorrect demand signatures. This manifested as a segmentation fault in #13615 as we incorrectly concluded that an application of catchRetry# would bottom. Specifically, we had orElse' :: STM a -> STM a -> STM a orElse' x = catchRetry# x y where y = {- some action -} Where the catchRetry# primop places a demand of <xC(S),1*C1(U)> on its first argument. However, due to #13977 the demand analyser would assign a demand of <C(S),1*C1(U)> on the first argument of orElse'. Note the missing `x`. case orElse' bottomingAction anotherAction of { x -> Just x } being transformed to, case orElse' bottomingAction anotherAction of {} by the simplifier. This would naturally blow up when orElse' returned at runtime, causing the segmentation fault described in #13615. Test Plan: Validate, perhaps add a testcase Reviewers: austin, simonpj Reviewed By: simonpj Subscribers: rwbarton, thomie GHC Trac Issues: #13977, #13615 Differential Revision: https://phabricator.haskell.org/D3756 }}} -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13977#comment:7> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#13977: ExnStr doesn't propagate "outwards" -------------------------------------+------------------------------------- Reporter: bgamari | Owner: (none) Type: bug | Status: closed Priority: normal | Milestone: 8.2.1 Component: Compiler | Version: 8.0.1 Resolution: fixed | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D3756 Wiki Page: | -------------------------------------+------------------------------------- Changes (by bgamari): * status: patch => closed * resolution: => fixed * milestone: => 8.2.1 Comment: Merged to `ghc-8.2` with 26f839f457ce1bf1a940a12e45c8137621ce1378. -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13977#comment:8> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#13977: ExnStr doesn't propagate "outwards" -------------------------------------+------------------------------------- Reporter: bgamari | Owner: (none) Type: bug | Status: closed Priority: normal | Milestone: 8.2.1 Component: Compiler | Version: 8.0.1 Resolution: fixed | Keywords: Exceptions Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D3756 Wiki Page: | -------------------------------------+------------------------------------- Changes (by bgamari): * keywords: => Exceptions Comment: I believe this fix may bear on a number of tickets which have come up in the past year or so, * #13380: `raiseIO#` result looks wrong * #13330: `forkIO` has inconsistent behavior under optimization * #11555: `catch` _|_ breaks at `-O1` * #11222: Teach strictness analysis about `catch`-like operations * #13357: Check demand signatures for `catchRetry#` and `catchSTM#` -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13977#comment:9> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
participants (1)
-
GHC