[GHC] #10071: Implement warnings for class-method overriding

#10071: Implement warnings for class-method overriding -------------------------------------+------------------------------------- Reporter: hvr | Owner: Type: feature | Status: new request | Milestone: 7.12.1 Priority: normal | Version: 7.8.4 Component: Compiler | Operating System: Unknown/Multiple Keywords: AMP | Type of failure: None/Unknown Architecture: | Blocked By: Unknown/Multiple | Related Tickets: #8004, #4384 Test Case: | Blocking: | Differential Revisions: | -------------------------------------+------------------------------------- This would aid long-term transitions like phasing out `Monad(return)` (in the spirit of #4834): With the AMP, `Monad(return)` being a class method becomes an historic artifact. The ideal long-term situation would rather be to have `return` become a top-level definition (i.e. outside the `Monad`-class), generalised to `Applicative` just aliasing `Applicative(pure)`, i.e. {{{#!hs return :: Applicative f => a -> f a return = pure }}} This may be beneficial for things like ApplicativeDo which otherwise would require a `return` to be handled is if it was `pure` in order to weaken the type-constraint in an `do`-expression like e.g. {{{#!hs do { x <- f; return (fst x) } }}} Right now, we can attach a `DEPRECATE`-pragma to the `return`-class- method. That however would trigger warnings on ''all'' uses of `return`, rather than only when using `return` in a context that requires it to be a class-method (like overriding `return` in instance definitions, or importing/exporting it via the explicit `Monad(return)`-syntax) Instead we need a way to warn about such uses of `return` which assume it to be a class-method, in order to phase out such uses. NB: This will probably require additional discussions, but we shouldn't wait too long, if we want to integrate the AMP into a future Haskell Report (for which we should try to clean up historic warts such as `Monad(return)` if feasable). -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10071 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#10071: Implement warnings for class-method overriding -------------------------------------+------------------------------------- Reporter: hvr | Owner: Type: feature request | Status: new Priority: normal | Milestone: 7.12.1 Component: Compiler | Version: 7.8.4 Resolution: | Keywords: AMP Operating System: Unknown/Multiple | Architecture: Type of failure: None/Unknown | Unknown/Multiple Blocked By: | Test Case: Related Tickets: #8004, #4384 | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Comment (by simonpj): What on earth is this ticket about? The first word is "This", presumably referring to something, but with no clue about ''what'' it is referring to. I am utterly lost. A feature request (which I assume this is) needs a specification! Simon -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10071#comment:1 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#10071: Implement deprecation-warnings for class-methods to non-method transitions -------------------------------------+------------------------------------- Reporter: hvr | Owner: Type: feature request | Status: new Priority: normal | Milestone: 7.12.1 Component: Compiler | Version: 7.8.4 Resolution: | Keywords: AMP Operating System: Unknown/Multiple | Architecture: Type of failure: None/Unknown | Unknown/Multiple Blocked By: | Test Case: Related Tickets: #8004, #4384 | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Old description:
This would aid long-term transitions like phasing out `Monad(return)` (in the spirit of #4834):
With the AMP, `Monad(return)` being a class method becomes an historic artifact. The ideal long-term situation would rather be to have `return` become a top-level definition (i.e. outside the `Monad`-class), generalised to `Applicative` just aliasing `Applicative(pure)`, i.e.
{{{#!hs return :: Applicative f => a -> f a return = pure }}}
This may be beneficial for things like ApplicativeDo which otherwise would require a `return` to be handled is if it was `pure` in order to weaken the type-constraint in an `do`-expression like e.g.
{{{#!hs do { x <- f; return (fst x) } }}}
Right now, we can attach a `DEPRECATE`-pragma to the `return`-class- method. That however would trigger warnings on ''all'' uses of `return`, rather than only when using `return` in a context that requires it to be a class-method (like overriding `return` in instance definitions, or importing/exporting it via the explicit `Monad(return)`-syntax)
Instead we need a way to warn about such uses of `return` which assume it to be a class-method, in order to phase out such uses.
NB: This will probably require additional discussions, but we shouldn't wait too long, if we want to integrate the AMP into a future Haskell Report (for which we should try to clean up historic warts such as `Monad(return)` if feasable).
New description: == What? Implement a `DEPRECATED`-variant to be attached to method declarations (in `class`-definitions) with default implementations that triggers warnings when 1. When an `instance` overrides the default implementation of that method, and/or 2. when such a deprecated method is explicitly im/(re)exported via `Class(method)`-syntax. But not when 1. imported as e.g. `import Mod1 (Class, method)` (which doesn't require `method` to be a method of `Class`), nor when 2. merely referring to `method` in an expression (as that doesn't require `method` to be a method either). Syntax suggestion: {{{ class C a where foo :: a bar :: a -> a bar x = x doo :: a -- this is the new syntax {-# DEPRECATED C(bar) "'bar' is going to become a non-method soon, please avoid referring to it as a method" #-} -- this works already now {-# DEPRECATED foo "'foo' is obsolete and going away soon, please use 'doo' instead" #-} }}} == Why? This would aid long-term transitions like phasing out class-methods, such as e.g. `Monad(return)` in the spirit of #4834: With the AMP, `Monad(return)` being a class method becomes an historic artifact. The ideal long-term situation would rather be to have `return` become a top-level definition (i.e. outside the `Monad`-class), generalised to `Applicative` just aliasing `Applicative(pure)`, i.e. {{{#!hs return :: Applicative f => a -> f a return = pure }}} This may be beneficial for things like ApplicativeDo which otherwise would require a `return` to be handled is if it was `pure` in order to weaken the type-constraint in an `do`-expression like e.g. {{{#!hs do { x <- f; return (fst x) } }}} Right now, we can attach a `DEPRECATED`-pragma to the `return`-class- method. That however would trigger warnings on ''all'' uses of `return`, rather than only when using `return` in a context that requires it to be a class-method (like overriding `return` in instance definitions, or importing/exporting it via the explicit `Monad(return)`-syntax) Instead we need a way to warn about such uses of `return` which assume it to be a class-method, in order to phase out such uses. NB: This will probably require additional discussions, but we shouldn't wait too long, if we want to integrate the AMP into a future Haskell Report (for which we should try to clean up historic warts such as `Monad(return)` if feasable). -- Comment (by hvr): I hope this makes it more clear what I'm proposing. When I started writing the ticket I wasn't sure if I wanted a general facility, or something more adhoc for the specific AMP use-case, and so ended up with the incomplete description... -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10071#comment:2 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#10071: Implement deprecation-warnings for class-methods to non-method transitions -------------------------------------+------------------------------------- Reporter: hvr | Owner: Type: feature request | Status: new Priority: normal | Milestone: 7.12.1 Component: Compiler | Version: 7.8.4 Resolution: | Keywords: AMP Operating System: Unknown/Multiple | Architecture: Type of failure: None/Unknown | Unknown/Multiple Blocked By: | Test Case: Related Tickets: #8004, #4384 | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Comment (by simonpj): Better. Syntax: why not just do this for a nested DEPRECATED pragma, thus {{{ class C a where foo :: a bar :: a -> a bar x = x {-# DEPRECATED bar "burble wurble" #-} doo :: a }}} -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10071#comment:3 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

Better. Syntax: why not just do this for a nested DEPRECATED pragma,
#10071: Implement deprecation-warnings for class-methods to non-method transitions -------------------------------------+------------------------------------- Reporter: hvr | Owner: Type: feature request | Status: new Priority: normal | Milestone: 7.12.1 Component: Compiler | Version: 7.8.4 Resolution: | Keywords: AMP Operating System: Unknown/Multiple | Architecture: Type of failure: None/Unknown | Unknown/Multiple Blocked By: | Test Case: Related Tickets: #8004, #4384 | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Comment (by hvr): Replying to [comment:3 simonpj]: thus Works too (I'm only slightly worried that it might be confusing for users that the indentation-level of the `{-# DEPRECATED #-}` changes its semantics, but I have no strong preference here) -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10071#comment:4 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#10071: Implement deprecation-warnings for class-methods to non-method transitions -------------------------------------+------------------------------------- Reporter: hvr | Owner: Type: feature request | Status: new Priority: normal | Milestone: 7.12.1 Component: Compiler | Version: 7.8.4 Resolution: | Keywords: AMP Operating System: Unknown/Multiple | Architecture: Type of failure: None/Unknown | Unknown/Multiple Blocked By: | Test Case: Related Tickets: #8004, #4384 | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Comment (by ekmett): The main purpose of such a feature is to give us the ability to smoothly remove redundant class members over a deprecation cycle. (Admittedly, perhaps, quite a long deprecation cycle in the case of something like `return`!) e.g. `(>>)` could be reduced to a top level binding to `(*>)` after a period with a warning making it clear that this was coming. Other examples of candidates are Traversable's `sequence` and `sequenceA`, although there is currently a technical barrier to removing `mapM` entirely. This would enable us to eventually reclaim `sequence` for use on `Applicative` data types. Having the ability to do these things means we can put together future proposals for how to move AMP (or FTP) along with reduced breakage. I confess to not being terribly concerned about the choice of syntax, though. =) -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10071#comment:5 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#10071: Implement deprecation-warnings for class-methods to non-method transitions -------------------------------------+------------------------------------- Reporter: hvr | Owner: Type: feature request | Status: new Priority: normal | Milestone: 7.12.1 Component: Compiler | Version: 7.8.4 Resolution: | Keywords: AMP Operating System: Unknown/Multiple | Architecture: Type of failure: None/Unknown | Unknown/Multiple Blocked By: | Test Case: Related Tickets: #8004, #4384 | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Changes (by oerjan): * cc: oerjan (added) Comment: Just found this via a libraries archive discussion. I think there are subtle cases here, if a `..` wildcard is used (possibly a fishy thing in itself). With the `return` example, this is fine: {{{ import Control.Monad (Monad(..), return) }}} This is fine ''provided'' `return` is not used or re-exported, including implicitly: {{{ import Control.Monad (Monad(..)) }}} This is fine if the corresponding import is fine: {{{ module Test (Monad(..), return) where }}} This is definitely wrong: {{{ module Test (Monad(..)) where }}} -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10071#comment:6 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#10071: Implement deprecation-warnings for class-methods to non-method transitions -------------------------------------+------------------------------------- Reporter: hvr | Owner: Type: feature request | Status: new Priority: normal | Milestone: 7.12.1 Component: Compiler | Version: 7.8.4 Resolution: | Keywords: AMP Operating System: Unknown/Multiple | Architecture: Type of failure: None/Unknown | Unknown/Multiple Blocked By: | Test Case: Related Tickets: #8004, #4384 | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Changes (by alanz): * cc: alanz (added) -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10071#comment:7 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#10071: Implement deprecation-warnings for class-methods to non-method transitions -------------------------------------+------------------------------------- Reporter: hvr | Owner: Type: feature request | Status: new Priority: normal | Milestone: 7.12.1 Component: Compiler | Version: 7.8.4 Resolution: | Keywords: AMP Operating System: Unknown/Multiple | Architecture: Type of failure: None/Unknown | Unknown/Multiple Blocked By: | Test Case: Related Tickets: #8004, #4384 | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Comment (by simonpj): Notes from conversation with Herbert and Simon PJ. Proposed data types: {{{ data Warnings = ... | WarnSome [WarnItem] data WarnItem = WI OccName WarnInfo (Located SourceText) [Located (SourceText,FastString)] data WarnInfo = Warning | DeprecTop | DeprecMeth }}} The new bit is the `DeprecMeth`. Need updated ticket description, or wiki page, to give examples of the different behaviour. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10071#comment:8 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#10071: Implement deprecation-warnings for class-methods to non-method transitions -------------------------------------+------------------------------------- Reporter: hvr | Owner: Type: feature request | Status: new Priority: normal | Milestone: 7.12.1 Component: Compiler | Version: 7.8.4 Resolution: | Keywords: AMP Operating System: Unknown/Multiple | MonadFail Type of failure: None/Unknown | Architecture: Blocked By: | Unknown/Multiple Related Tickets: #8004, #4384 | Test Case: | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Changes (by hvr): * keywords: AMP => AMP MonadFail Old description:
== What?
Implement a `DEPRECATED`-variant to be attached to method declarations (in `class`-definitions) with default implementations that triggers warnings when
1. When an `instance` overrides the default implementation of that method, and/or 2. when such a deprecated method is explicitly im/(re)exported via `Class(method)`-syntax.
But not when
1. imported as e.g. `import Mod1 (Class, method)` (which doesn't require `method` to be a method of `Class`), nor when 2. merely referring to `method` in an expression (as that doesn't require `method` to be a method either).
Syntax suggestion:
{{{ class C a where foo :: a
bar :: a -> a bar x = x
doo :: a
-- this is the new syntax {-# DEPRECATED C(bar) "'bar' is going to become a non-method soon, please avoid referring to it as a method" #-}
-- this works already now {-# DEPRECATED foo "'foo' is obsolete and going away soon, please use 'doo' instead" #-} }}}
== Why?
This would aid long-term transitions like phasing out class-methods, such as e.g. `Monad(return)` in the spirit of #4834:
With the AMP, `Monad(return)` being a class method becomes an historic artifact. The ideal long-term situation would rather be to have `return` become a top-level definition (i.e. outside the `Monad`-class), generalised to `Applicative` just aliasing `Applicative(pure)`, i.e.
{{{#!hs return :: Applicative f => a -> f a return = pure }}}
This may be beneficial for things like ApplicativeDo which otherwise would require a `return` to be handled is if it was `pure` in order to weaken the type-constraint in an `do`-expression like e.g.
{{{#!hs do { x <- f; return (fst x) } }}}
Right now, we can attach a `DEPRECATED`-pragma to the `return`-class- method. That however would trigger warnings on ''all'' uses of `return`, rather than only when using `return` in a context that requires it to be a class-method (like overriding `return` in instance definitions, or importing/exporting it via the explicit `Monad(return)`-syntax)
Instead we need a way to warn about such uses of `return` which assume it to be a class-method, in order to phase out such uses.
NB: This will probably require additional discussions, but we shouldn't wait too long, if we want to integrate the AMP into a future Haskell Report (for which we should try to clean up historic warts such as `Monad(return)` if feasable).
New description: See Design/MethodDeprecations for details -- -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10071#comment:9 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#10071: Implement deprecation-warnings for class-methods to non-method transitions -------------------------------------+------------------------------------- Reporter: hvr | Owner: Type: feature request | Status: new Priority: normal | Milestone: 7.12.1 Component: Compiler | Version: 7.8.4 Resolution: | Keywords: AMP Operating System: Unknown/Multiple | MonadFail Type of failure: None/Unknown | Architecture: Blocked By: | Unknown/Multiple Related Tickets: #8004, #4384 | Test Case: | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Comment (by simonpj): I have attempted a precise specification, in [wiki:Design/MethodDeprecations]. See if you agree with it. What about this? (Using the main example in [wiki:Design/MethodDeprecations] {{{ module M where import X import M1 ( C(..) ) x = bar () }}} Do we get a warning here? You might say that since `X` doesn't export `bar` (which is not obvious) that the only way it can be in scope is via `C(..)`. I say yes, and I have articulated that in the wiki page. There is a design alternative described there too; I'm not sure what you want. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10071#comment:10 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#10071: Implement deprecation-warnings for class-methods to non-method transitions -------------------------------------+------------------------------------- Reporter: hvr | Owner: Type: feature request | Status: new Priority: normal | Milestone: 7.12.1 Component: Compiler | Version: 7.8.4 Resolution: | Keywords: AMP Operating System: Unknown/Multiple | MonadFail Type of failure: None/Unknown | Architecture: Blocked By: | Unknown/Multiple Related Tickets: #8004, #4384, | Test Case: #4879 | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Changes (by hvr): * related: #8004, #4384 => #8004, #4384, #4879 Comment: Replying to [comment:10 simonpj]:
I have attempted a precise specification, in [wiki:Design/MethodDeprecations]. See if you agree with it.
I think so. However, you added this code example: {{{#!hs module Use where import Def( C( bar ) ) import Def( bar ) x = bar () }}} which should definitely be complained about (if `bar` is deprecated-as- method-of-C), as this code would break as soon as `bar` moved out of `C` for real.
What about this? (Using the main example in
[wiki:Design/MethodDeprecations]
{{{ module M where import X import M1 ( C(..) ) x = bar () }}} Do we get a warning here? You might say that since `X` doesn't export `bar` (which is not obvious) that the only way it can be in scope is via `C(..)`.
I say yes, and I have articulated that in the wiki page. There is a design alternative described there too; I'm not sure what you want.
That's indeed a not so clear case, but I'd consider this a case where we need to warn, as the assumed use case for this new deprecation is that such methods will eventually be *moved* outside the class, but with the intent to remain exported (but not belonging to `C` anymore) from that very module that currently exports `bar` as method of `C`. PS: ...and I forgot to mention that this feature should be implemented (and data types refactored) while keeping the related #4879 feature- request in mind -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10071#comment:11 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#10071: Implement deprecation-warnings for class-methods to non-method transitions -------------------------------------+------------------------------------- Reporter: hvr | Owner: Type: feature request | Status: new Priority: normal | Milestone: 7.12.1 Component: Compiler | Version: 7.8.4 Resolution: | Keywords: AMP Operating System: Unknown/Multiple | MonadFail Type of failure: None/Unknown | Architecture: Blocked By: | Unknown/Multiple Related Tickets: #8004, #4384, | Test Case: #4879 | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Comment (by simonpj): Ok, well, please go to the specification and modify it to your satisfaction. Remember that the existing behaviour is that import and export lists never generate deprecations. I think you want them to do so. That's ok but the specification should say so, esp as it's different to the current behaviour. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10071#comment:12 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#10071: Implement deprecation-warnings for class-methods to non-method transitions -------------------------------------+------------------------------------- Reporter: hvr | Owner: Type: feature request | Status: new Priority: normal | Milestone: 7.12.1 Component: Compiler | Version: 7.8.4 Resolution: | Keywords: AMP Operating System: Unknown/Multiple | MonadFail deprecate warning Type of failure: None/Unknown | Architecture: Blocked By: | Unknown/Multiple Related Tickets: #8004, #4384, | Test Case: #4879, #2119 | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Changes (by hvr): * keywords: AMP MonadFail => AMP MonadFail deprecate warning * related: #8004, #4384, #4879 => #8004, #4384, #4879, #2119 Comment: (turns out there's yet another deprecation/warning related ticket...) -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10071#comment:13 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#10071: Implement deprecation-warnings for class-methods to non-method transitions -------------------------------------+------------------------------------- Reporter: hvr | Owner: Type: feature request | Status: new Priority: normal | Milestone: 7.12.1 Component: Compiler | Version: 7.8.4 Resolution: | Keywords: AMP Operating System: Unknown/Multiple | MonadFail deprecate warning Type of failure: None/Unknown | Architecture: Blocked By: | Unknown/Multiple Related Tickets: #8004, #4834, | Test Case: #4879, #2119 | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Changes (by oerjan): * related: #8004, #4384, #4879, #2119 => #8004, #4834, #4879, #2119 Comment: (fix typo in related ticket number) -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10071#comment:14 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#10071: Implement deprecation-warnings for class-methods to non-method transitions -------------------------------------+------------------------------------- Reporter: hvr | Owner: Type: feature request | Status: new Priority: normal | Milestone: 8.0.1 Component: Compiler | Version: 7.8.4 Resolution: | Keywords: AMP MonadFail | deprecate warning Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #8004, #4834, | Differential Rev(s): #4879, #2119 | -------------------------------------+------------------------------------- Comment (by bgamari): See [[Design/DeprecationMechanisms]] for a summary of this and related deprecation proposals. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10071#comment:16 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler
participants (1)
-
GHC