Documentation should not resolve type aliases
Opened this issue · 8 comments
Type signatures in generated HTML docs have resolved (i.e. original) names instead of type aliases.
For example, for a function f :: Int -> Foo
where type Foo = String
, the generated document says f :: Int -> String
.
The below is an exhaustive list I'm aware of so far:
--- Generated document should say @type Foo = 'String'@
--- instead of @type Foo = 'StringJ' 'Char'@
type Foo = String
--- should say @fun :: 'Foo' -> 'String'@
--- instead of @fun :: 'String' -> 'String'@
func :: Foo -> String
func = undefined
--- should say @Dat 'Foo'@
--- instead of @Dat ('String')@
data Dat = Dat Foo
--- should say @Newt { n :: 'Foo' }@
--- instead of @Newt { n :: 'String' }@
newtype Newt = Newt { n :: Foo }
--- should say @Known Instances 'Foo'@
--- instead of @Known Instances 'StringJ'@
class Cls a where
--- should say @toFoo :: 'Cls' a => a -> 'Foo'@
--- instead of @toFoo :: 'Cls' a => a -> 'String'@
toFoo :: a -> Foo
--- should say @'Cls' 'Foo'@
--- instead of @'Cls' 'String'@
instance Cls Foo where
--- should say @toFoo :: 'Foo' -> 'Foo'@
--- instead of @toFoo :: 'String' -> 'String'@
toFoo = undefined
Note that type aliases in documentation code (that begins with ---
) won't be resolved.
Basically, this problem is unsolvable. As your own example shows, both Foo and String are aliases of what appears early in the compilation process as StringJ Char. So, on what basis does the Doc tool decide whether to use 'Foo' or 'String'? (Remember that the Doc tool works on class files, not source code.)
However, one can do something with a bit of heuristic. Which is already done both in the compiler (for error mesages) and in the Doc tool. For details see frege.compiler.common.UnAlias
As it stands, UnAliasing (it should better be named ReAliasing) works in all stages of compilation, and even after compilation, as in the Doc tool. (So, sneaking at the source definitions is not an option.)
If you feel like so, you can realize your ideas here. But the following basic premise is not to be changed: when type checking starts, no type expression seen by type checker and following passes must mention any type alias anymore.
If I understand correctly, aliases can be rendered to HTML if SymA
s (type aliases) instead of resolved SymV
s are contained in the java annotations (frege metapackages).
But I also guess it is extremely difficult (unsolvable in the current inplementation ?) because I think all SymA
s are resolved at the typechecking pass at latest, so when generating java annotations, they are already lost.
If the type checker insists on taking no SymA
s, it should not take SymbolT
. Instead, it should take a new Symbol
-like type that consists of resolved symbols only. (And somehow retain SymbolT
s as well to put them into java annotations)
But first, since I haven't studied UnAlias yet, I think I'll try to look at it. It seems to sometimes give incorrect results however (you already called it "heuristic").
I think I found a way to improve the situation. It looks that unAlias
isn't working because g.thisTab
isn't populated properly:
frege/frege/compiler/common/UnAlias.fr
Line 89 in d384bdf
The local function aliases
consists of type aliases which are declared in the documented module (plus some more, because in frege.Prelude
it can unalias ST RealWorld
to IO
).
It should also contain the imported ones. This is why IO and String work in most cases.
They didn't work for me. In my environment, frege.prelude.PreludeIO
for example couldn't resolve ST RealWorld
. It is maintenance24
compiled for JDK7. Does this matter?
No it shouldn't matter. This code is quite stable, and the target JVM version must not change the semantics.
Can you be more specific? I look at www. frege-lang.org/doc/frege/prelude/PreludeIO.fr and it looks ok for me. Does yours differ?
I myself couldn't reproduce the issue:
java -cp ~/lib/java/frege-3.24.421-jdk8.jar frege.tools.Doc frege.prelude.PreludeIO
does indeed generate throwIO ∷ Throwable → IO a
, etc. Passing a directory path seems to work, too. My actual use case is convoluted, so it seems something is wrong in my side. Anyway, sorry for the noise.