[GHC] #16305: When should -Wmissed-specializations fire?

#16305: When should -Wmissed-specializations fire? -------------------------------------+------------------------------------- Reporter: crockeea | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.7 Keywords: | Operating System: Unknown/Multiple Architecture: | Type of failure: Poor/confusing Unknown/Multiple | error message Test Case: | Blocked By: Blocking: | Related Tickets: Differential Rev(s): | Wiki Page: -------------------------------------+------------------------------------- While working on a fix for #16282, I noticed: 1. that `-Wmissed-specializations` doesn't fire when the docs say it should 2. that the "probable fix" suggested when a warning does fire is highly suspect {{{ import Data.Map main :: IO () main = do let m = [] :: [Map String Bool] mapM_ print m }}} With GHC 8.4.3, 8.6.3, and HEAD: `ghc -O2 -Wmissed-specializations Main.hs` does *not* issue any warnings. However, `ghc -O2 -Wall-missed-specializations Main.hs` *does* create a warning: {{{ Main.hs: warning: [-Wall-missed-specialisations] Could not specialise imported function ‘Data.Map.Internal.$w$cshowsPrec’ when specialising ‘Data.Map.Internal.$fShowMap_$cshowsPrec’ Probable fix: add INLINABLE pragma on ‘Data.Map.Internal.$w$cshowsPrec’ }}} The docs for `-Wmissed-specializations` say, "warn when specialisation of an imported, overloaded function fails." Since `showsPrec` is an imported function, it seems that a warning should have been issued with `-Wmissed- specs`. My reading of the docs is that `-Wall-missed-specs` should output everything `-Wmissed-specs` does, along with any *local* overloaded and unspecialized functions. Moreover, the "Probable fix" is suspect. A warning recommending an `INLINABLE` pragma is issued depending on the output of `warnMissedSpec` in specialise/Specialise.hs. For `-Wall-missed-specs`, `warnMissedSpec` doesn't check if an INLINABLE pragma is already present, so the fix could be redundant. For `-Wmissed-specs`, `warnMissedSpecs` *only* issues a warning if there *is* any inline pragma (of one sort of another) on all the callers, making the `probable fix` definitely redundant. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/16305 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#16305: When should -Wmissed-specializations fire? -------------------------------------+------------------------------------- Reporter: crockeea | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.7 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Poor/confusing | Unknown/Multiple error message | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by crockeea): I should point out that the fact that `-Wmissed-specs` doesn't create a warning in the example above seems to (according to the code) be due to `showsPrec` not having any type of inline pragma. The following evaluates to `False` on `f=showsPrec`: `has_inline_prag f = isAnyInlinePragma (idInlinePragma f)` -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/16305#comment:1 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#16305: When should -Wmissed-specializations fire? -------------------------------------+------------------------------------- Reporter: crockeea | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.7 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Poor/confusing | Unknown/Multiple error message | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Description changed by crockeea: Old description:
While working on a fix for #16282, I noticed:
1. that `-Wmissed-specializations` doesn't fire when the docs say it should 2. that the "probable fix" suggested when a warning does fire is highly suspect
{{{ import Data.Map main :: IO () main = do let m = [] :: [Map String Bool] mapM_ print m }}}
With GHC 8.4.3, 8.6.3, and HEAD: `ghc -O2 -Wmissed-specializations Main.hs` does *not* issue any warnings.
However, `ghc -O2 -Wall-missed-specializations Main.hs` *does* create a warning: {{{ Main.hs: warning: [-Wall-missed-specialisations] Could not specialise imported function ‘Data.Map.Internal.$w$cshowsPrec’ when specialising ‘Data.Map.Internal.$fShowMap_$cshowsPrec’ Probable fix: add INLINABLE pragma on ‘Data.Map.Internal.$w$cshowsPrec’ }}}
The docs for `-Wmissed-specializations` say, "warn when specialisation of an imported, overloaded function fails." Since `showsPrec` is an imported function, it seems that a warning should have been issued with `-Wmissed- specs`. My reading of the docs is that `-Wall-missed-specs` should output everything `-Wmissed-specs` does, along with any *local* overloaded and unspecialized functions.
Moreover, the "Probable fix" is suspect. A warning recommending an `INLINABLE` pragma is issued depending on the output of `warnMissedSpec` in specialise/Specialise.hs. For `-Wall-missed-specs`, `warnMissedSpec` doesn't check if an INLINABLE pragma is already present, so the fix could be redundant. For `-Wmissed-specs`, `warnMissedSpecs` *only* issues a warning if there *is* any inline pragma (of one sort of another) on all the callers, making the `probable fix` definitely redundant.
New description: While working on a fix for #16282, I noticed: 1. that `-Wmissed-specializations` doesn't fire when the docs say it should 2. that the "probable fix" suggested when a warning does fire is highly suspect {{{ import Data.Map main :: IO () main = do let m = [] :: [Map String Bool] mapM_ print m }}} With GHC 8.4.3, 8.6.3, and HEAD: `ghc -O2 -Wmissed-specializations Main.hs` does *not* issue any warnings. However, in 8.6.3 and HEAD, `ghc -O2 -Wall-missed-specializations Main.hs` *does* create a warning: {{{ Main.hs: warning: [-Wall-missed-specialisations] Could not specialise imported function ‘Data.Map.Internal.$w$cshowsPrec’ when specialising ‘Data.Map.Internal.$fShowMap_$cshowsPrec’ Probable fix: add INLINABLE pragma on ‘Data.Map.Internal.$w$cshowsPrec’ }}} The docs for `-Wmissed-specializations` say, "warn when specialisation of an imported, overloaded function fails." Since `showsPrec` is an imported function, it seems that a warning should have been issued with `-Wmissed- specs`. My reading of the docs is that `-Wall-missed-specs` should output everything `-Wmissed-specs` does, along with any *local* overloaded and unspecialized functions. Moreover, the "Probable fix" is suspect. A warning recommending an `INLINABLE` pragma is issued depending on the output of `warnMissedSpec` in specialise/Specialise.hs. For `-Wall-missed-specs`, `warnMissedSpec` doesn't check if an INLINABLE pragma is already present, so the fix could be redundant. For `-Wmissed-specs`, `warnMissedSpecs` *only* issues a warning if there *is* any inline pragma (of one sort of another) on all the callers, making the `probable fix` definitely redundant. -- -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/16305#comment:2 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#16305: When should -Wmissed-specializations fire? -------------------------------------+------------------------------------- Reporter: crockeea | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.7 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Poor/confusing | Unknown/Multiple error message | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by mpickering): It seems to me that `-Wmissed-specs` should warn when a function which has an `INLINABLE` pragma on fails to specialise for some reason and `-Wall- missed-specs` should warn whenever an overloaded function fails to specialise. Is that what the implementation does? -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/16305#comment:3 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#16305: When should -Wmissed-specializations fire? -------------------------------------+------------------------------------- Reporter: crockeea | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.7 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Poor/confusing | Unknown/Multiple error message | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by crockeea): Nearly. `-Wmissed-specs` warns when an *imported* function which has *any* "inline" pragma (haven't dug into which are allowed) doesn't get specialized. `-Wall-missed-specs` warns whenever any overloaded function fails to specialize, exactly as you say. Questions are: 1. Should `-Wmissed-specs` warn in the example above? 2. What should the "Probable fix" be for either flag? -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/16305#comment:4 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#16305: When should -Wmissed-specializations fire? -------------------------------------+------------------------------------- Reporter: crockeea | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.7 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Poor/confusing | Unknown/Multiple error message | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by simonpj): For what it's worth, here's the Note in `Specialise.hs` {{{ {- Note [Warning about missed specialisations] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Suppose * In module Lib, you carefully mark a function 'foo' INLINABLE * Import Lib(foo) into another module M * Call 'foo' at some specialised type in M Then you jolly well expect it to be specialised in M. But what if 'foo' calls another function 'Lib.bar'. Then you'd like 'bar' to be specialised too. But if 'bar' is not marked INLINABLE it may well not be specialised. The warning Opt_WarnMissedSpecs warns about this. It's more noisy to warning about a missed specialisation opportunity for /every/ overloaded imported function, but sometimes useful. That is what Opt_WarnAllMissedSpecs does. ToDo: warn about missed opportunities for local functions. }}} -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/16305#comment:5 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#16305: When should -Wmissed-specializations fire? -------------------------------------+------------------------------------- Reporter: crockeea | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.7 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Poor/confusing | Unknown/Multiple error message | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by simonpj): As I read the code it is trying to do this: * `-Wall-missed-specs`: warn about ''any'' overloaded imported functions that cannot be specialised. Usually this means we don't have its RHS. * `-Wmissed-specs`: warn about any overloaded imported functions that can't be specialised, and is transitively called by a chain of imported functions each with an INLINEABLE pragma. For the latter consider {{{ module A where import B foo = f (3::Int) + g (4::Int) module B where f :: Num a => a -> a {-# INLINABLE f #-} f x = h x g x = Num a => a -> a g x = blah h x :: Num a => a -> a h x = blah }}} Then when compiling A, `-Wmissed-specs` is supposed to * Not warn about not-specialising `g`, because `g` didn't have an INLINABLE pragma. * Warn about non-specialising `h` because `f` (which is directly called from A) has a careful `INLINABLE` pragma, but `h` (perhaps due to an oversight) does not. In contrast `-Wall-missed-specs` should warn about both. Does that make sense? Is it what we want? -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/16305#comment:6 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#16305: When should -Wmissed-specializations fire? -------------------------------------+------------------------------------- Reporter: crockeea | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.7 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Poor/confusing | Unknown/Multiple error message | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by crockeea): Looks like your assessment is accurate, Simon. Perhaps the only problem here is a documentation issue, because I don't think the docs for `-Wmissed-specs` make it clear when a warning is issued. I'm also interested in understanding the warning from my example. The function names appear to be core, and it's not clear to me that `Data.Map.Internal.$fShowMap_$cshowsPrec` even corresponds to a function in source code. If that's the case, then the warning isn't very useful, either. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/16305#comment:7 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler
participants (1)
-
GHC