haskell / haskell-language-server

Official haskell ide support via language server (LSP). Successor of ghcide & haskell-ide-engine.
Apache License 2.0
2.72k stars 367 forks source link

Type-on-hover for type constructors shows linear arrows even if `-XLinearTypes` is not enabled #2904

Open akrmn opened 2 years ago

akrmn commented 2 years ago

This is probably confusing for newcomers and those who don't know about LinearTypes, even if technically correct according to the user's guide

By default, all fields in algebraic data types are linear -- https://downloads.haskell.org/ghc/9.0.2/docs/html/users_guide/exts/linear_types.html#data-types

GHCi gets around this because, also according to the user's guide,

[...] Given data T1 a = MkT1 a [...] [w]hen used as a value, MkT1 is given a multiplicity-polymorphic type: MkT1 :: forall {m} a. a %m -> T1 a. [...] When displaying types, unless -XLinearTypes is enabled, multiplicity polymorphic functions are printed as regular functions [...]; therefore constructors appear to have regular function types. -- https://downloads.haskell.org/ghc/9.0.2/docs/html/users_guide/exts/linear_types.html#data-types

The solution, then, would be to use MkT1-the-value for the type-on-hover tooltip, instead of MkT1-the-constructor.

Your environment

Which OS do you use: macOS Which LSP client (editor/plugin) do you use: VSCode Describe your project (alternative: link to the project): plain cabal project, ghc-9.0.2

Steps to reproduce

Define a newtype or data type and hover on one of its constructors.

newtype WrappedInt = MkWrapped Int

Expected behaviour

The tooltip shows the type MkWrapped :: Int -> WrappedInt

Actual behaviour

The tooltip shows the type MkWrapped :: Int %1 -> WrappedInt, which includes a linear arrow.

michaelpj commented 2 years ago

cc @July541, who looked a pretty-printing of stuff recently?

July541 commented 2 years ago

A quick peek: we rely on printOutputable to print type info. I'll dive into it later.

https://github.com/haskell/haskell-language-server/blob/b1bf5499155e259341e4868863b0fd743b6bd65f/ghcide/src/Development/IDE/Spans/AtPoint.hs#L250-L252

akrmn commented 2 years ago

Just wanted to add that I thought I'd check what happens when the constructor is used as a value, and to my surprise that also shows the linear arrows,

mkWrapped = MkWrapped
--          ^^^^^^^^^~ MkWrapped :: Int %1 -> WrappedInt

hovering on mkWrapped does show the expected non-linear arrow, though.

July541 commented 2 years ago

It's from https://github.com/haskell/haskell-language-server/blob/b1bf5499155e259341e4868863b0fd743b6bd65f/ghcide/src/Development/IDE/Spans/AtPoint.hs#L232-L238

maybeKind if we have newtype WrappedInt = MkWrapped Int and hover on MkWrapped. And it is something about (AConLike (RealDataCon dataCon)) https://github.com/haskell/haskell-language-server/blob/b1bf5499155e259341e4868863b0fd743b6bd65f/ghcide/src/Development/IDE/Spans/Common.hs#L40-L49

We will get linear arrow If we print RealDataCon directly, and it can be disabled by dataConNonlinearType.

I Don't know how to control the printing in showSDoc, A potential solution is reading the dynflag about lineartype to control the behavior by dataConNonlinearType, not sure there exists a better way.

michaelpj commented 10 months ago

Is this still a problem?

jhrcek commented 10 months ago

Yes, I’m pretty sure I saw it today with hls built from master, using ghc 9.4.8

On Tue 16. 1. 2024 at 18:55, Michael Peyton Jones @.***> wrote:

Is this still a problem?

— Reply to this email directly, view it on GitHub https://github.com/haskell/haskell-language-server/issues/2904#issuecomment-1894233740, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAUXDJKU3MEHIGLHF47LXHTYO25KFAVCNFSM5VYFURF2U5DIOJSWCZC7NNSXTN2JONZXKZKDN5WW2ZLOOQ5TCOBZGQZDGMZXGQYA . You are receiving this because you are subscribed to this thread.Message ID: @.***>

emlautarom1 commented 7 months ago

I can reproduce the issue on GHC 9.4.8 + HLS 2.7.0.0

ShrykeWindgrace commented 4 weeks ago

Still present; GHC-9.6.6, HLS-2.9.0.1.