I noticed this some time ago, but I thought this is expected, because
there's a comment in CoreLint that mentions this:
lintCoreBindings dflags pass local_in_scope binds = initL dflags flags in_scope_set $ addLoc TopLevelBindings $ lintLetBndrs TopLevel binders $ -- Put all the top-level binders in scope at the start -- This is because transformation rules can bring something -- into use 'unexpectedly' ...
However talking to SPJ today he mentioned that in Core we should actually
preserve dependency ordering, hence this ticket.
I'll update with a reproducer.
Trac metadata
Trac field
Value
Version
8.6.3
Type
Bug
TypeOfFailure
OtherFailure
Priority
normal
Resolution
Unresolved
Component
Compiler
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Child items
0
Show closed items
No child items are currently assigned. Use child items to break down this issue into smaller parts.
Linked items
0
Link issues together to show that they're related or that one is blocking others.
Learn more.
Related merge requests
2
When these merge requests are accepted, this issue will be closed automatically.
module Lib wherefoo :: Int -> Intfoo n = go (Just n) (Just (6::Int)) where go Nothing (Just x) = go (Just 10) (Just x) go (Just n) (Just x) | n <= 0 = 0 | otherwise = go (Just (n-1)) (Just x)
Another example is the recently added test T16066:
{-# LANGUAGE FlexibleContexts #-}{-# LANGUAGE FlexibleInstances #-}{-# LANGUAGE TypeFamilies #-}module Main (main) whereimport Control.Monad (join)import Control.Monad.Reader (ReaderT(..))import Control.Concurrent.STM (STM, atomically)import Data.Kind (Type)class Monad (Transaction m) => MonadPersist m where type Transaction m :: Type -> Type atomicTransaction :: Transaction m y -> m yinstance MonadPersist (ReaderT () IO) where type Transaction (ReaderT () IO) = ReaderT () STM atomicTransaction act = ReaderT (atomically . runReaderT act)main :: IO ()main = join (runReaderT doPure2 ()) >>= \x -> seq x (return ())doPure2 :: MonadPersist m => m (IO ())doPure2 = atomicTransaction $ do () <- pure () () <- pure () error "exit never happens"
Build with -dcore-lint -O. Lint error caught in result of Simplifier.
However talking to SPJ today he mentioned that in Core we should actually preserve dependency ordering, hence this ticket.
Not so. In fact this is defintely (albeit annoyingly) false, becuause of RULES: see Note [Glomming] in OccurAnal. This won't come up in the testsuite (I guess) because (as the Note says) "NOTICE that this cannot happen for rules whose head is a locally-defined function", and I bet all regression tests have rules only for locally defined functions.
What I intended to say is that the output of the occurrence analyser is in dependency order. If you need dependency order, run the occurrence analyser.
Nevertheless, it very much the exception, so flagging up cases where it is false is very interesting. Your determ006 one is a bug in SpecConstr`, andI have opened #16884 to track it.
I do not know what is happening in T16066 -- can you show the error (ie what is out of scope) and exactly which pass it follows?