
#9418: Warnings about "INLINE binder is (non-rule) loop breaker" -------------------------------------+------------------------------------- Reporter: simonpj | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.8.2 Resolution: | Keywords: Operating System: | Architecture: Unknown/Multiple Unknown/Multiple | Difficulty: Unknown Type of failure: | Blocked By: None/Unknown | Related Tickets: Test Case: | Blocking: | Differential Revisions: | -------------------------------------+------------------------------------- Comment (by simonpj): What is happening is this. Consider {{{ class C a where op1 :: a -> a -> (a,a) op2 :: a -> a -> (a,a) {-# INLINE op2 #-} op2 x y = op1 y x instance C Int where op1 x y = (x,y) }}} The intent of the INLINE pragma is obviously to ensure that in every instance declaration we get an INLINEd definition for op2. These declarations desugar to something like this: {{{ op1 :: forall a. C a => a -> a -> (a,a,) op1 c = case c of MkC op1 op2 -> op1 Rec { $dCInt :: C Int = MkC $cop1 $cop2 $cop1 :: Int->Int->(Int,Int) = \xy. (x,y) $cop2 :: Int->Int->(Int,Int) {-# INLINE #-} = \xy -> op1 $dCInt y x } }}} Here * `op1` is the method selector, which picks the `op1` field out of a `C` dictionary. * `$dCInt` is the dictionary for `C Int`. * `$cop1` and `$cop2` are the implementations of `op1` and `op2` at type `Int`. Notice that `$dCInt` and `$cop2` are apparently mutually recursive; each uses the other. We break the mutual recursion by inlining the `op1` selector and `$dCInt` (in the rhs of `$cop2`) so that now we can do the record selection. But do to this, we must inline `$dCInt`, so it can't be a loop breaker. So `$cop2` must be picked as the loop breaker, ''even though it has an INLINE pragma''. That's fine, and it's what GHC does. But Lint is just warning that, as a result, the INLINE pragma isn't going to do anything. This might be useful to the programmer. If you wrote {{{ f x = ....(f y).... {-# INLINE f #-} }}} then `f` won't be inlnined (despite the pragma) because it's recursive. So you might want to re-think your definitions. The Lint warning is just that: a warning. The unravelling of the mutual recursion happens early, otherwise the warning would be repeated after in every subsequent run of the simplifier. So one possible fix would be to have a flag for Core Lint to control whether the warning was enabled, and only switch it on later in the pipeline. But that doesn't seem very satisfactory. Well then. That's why it is the way it is. I'd like it to be better! Simon -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/9418#comment:1 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler