I think the confusion stems from what the deprecation of the
module means, i.e.
module A {-# DEPRECATED "This module will be hidden in future
versions". #-} ( ... ) where
I think it does two things:
1. deprecates the module A, so if it's imported anywhere, the
deprecation warning will be reported
2. deprecates all symbols defined in the module, so the use-sites
are reported as well. (This is like deprecating an individual
binding, {-# DEPRECATED symbolInA "..." #-}.
The second point is why re-exporting names defined in A still
causes the warning. The thing is deprecated, it doesn't matter how
you import it.
However, if A re-exports some other symbols (e.g. from
A.Internal), these things are not deprecated, and thus no
warnings.
This explains why a workaround you mention works. Or we could even
argue that the (first) workaround is not even a workaround, but
the right way to do what you want.
Defining new binding is not the same as re-exporting. There is a
bit discussion about it in [1], e.g. users can define different
RULES for the thing "renamed" in B.
There is an interesting challenge in [1] too:
> the proposal would be stronger if it explicitly explained
that much of what is proposed [renaming on import] could be done
with existing mechanisms [like writing new definitions, type,
etc.]
For your use case (in second workaround) you'll rely that
redefinition (as "heavy" renaming) will strip the deprecation bit.
But we can argue that it's still a renaming, so it should not! :)
[1]:
https://github.com/ghc-proposals/ghc-proposals/pull/408#issuecomment-806064864
- Oleg
Hello Café,
TL;DR: should the deprecation GHC option be transitively reported for re-exported definitions?
I have a library that is exposing too much. As a minimal example, say the library contains:- Module A, which defines several functions and types.
- Module B, which exports specific definitions from module A and has none of its own.
It so happens that, to keep things as clean and abstract as possible, only module B should be exposed.
As per library policy, we give users time to adapt. A way to do that would be to deprecate module A, but configure B to ignore deprecations (-Wno-deprecations) so GHC does not complain during the compilation of the library itself.
My expectation was that library users who imported A directly would get a warning, but importing definitions in A via B would not give out any warnings.
That, however, is not what is happening:
In the use of ‘functionInA’
(imported from B, but defined in A):
Deprecated: "This module will be hidden in future versions."
There are "workarounds": I could move all definitions in A to new module C, deprecate A, and re-export C in B, or I could re-define the exported definitions in B as identities of those in A (easy for functions, probably more cumbersome for data constructors or classes.)
However, more generally, if you use a function from A in a NEW function definition in B and then export that second definition instead, the compiler won't tell the library user that B is internally relying on a deprecated function. Reexporting a function without changes could conceptually be seen as an "extreme" case of that, where where the name and the implementation in B coincide with those in A.
So I ask: should deprecation work the way it is working in the first place?
All the best,
Ivan
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.