error-messages icon indicating copy to clipboard operation
error-messages copied to clipboard

Suggest -XMagicHash where appropriate

Open chessai opened this issue 3 years ago • 8 comments

Consider using a primitive such as spark#. Without -XMagicHash, on GHC 9.2.1, I get the following error:

src/Rtq/Internal.hs:172:31: error:
    Variable not in scope:
      (#) :: t0 -> t1 -> (# GHC.Prim.State# GHC.Prim.RealWorld, a #)
    |
172 | par x = Par $ IO $ \s -> spark# x s
    |  

In almost every case when a haskell developer is writing the hash character (#), they mean to invoke the use of a primitive, or some identifier which is donning a hash to signal its involvement with unboxed things or primitives (e.g. I have implemented compareByteArray# :: ByteArray# -> ByteArray# -> Int#). There are some instances for which this is not the case, such as (#) in profunctors, but I can't see why it would hurt to say "Perhaps you intended to enable MagicHash?". I also think this is another case where allowing operators without spaces is suboptimal from a UX perspective (e.g. IMO using (.) without spaces is poor form), but disallowing that is not what I hope to accomplish from posting here, improving the error message is.

Thanks

chessai avatar Feb 18 '22 20:02 chessai

To be honest, I expect every developer involved with GHC magic to immediately know that they forgot to enable MagicHash from that error message. The number of developers who intend to use the magic hash but don't understand the error message might be smaller than the number of beginners trying to use a # operator and who would accidentally enable the MagicHash extension because the error message suggested it. So, if such a suggestion is added, I would definitely want a "For advanced users..." prefix on it (discussed previously here).

noughtmare avatar Feb 18 '22 21:02 noughtmare

Seconding @noughtmare. I'm pretty sure I've typed the # character in Haskell, but I'm pretty sure I've never used MagicHash. Optics are one good source of #.

tomjaguarpaw avatar Feb 18 '22 21:02 tomjaguarpaw

Seconding @noughtmare. I'm pretty sure I've typed the # character in Haskell, but I'm pretty sure I've never used MagicHash. Optics are one good source of #.

This ties in to the allowance of 0 space characters between operators and other identifiers.

I'm not sure we should label this as something that is only "For advanced users"; the number of users of MagicHash may be small, but the concept is not that advanced. Compare to many extensions which influence the type checker. Is MagicHash harder to understand than GADTs? Hmmmm... perhaps it is advanced in that it is easier to footgun yourself with primitives. So I'm on the fence about the advanced part, probably leaning toward a weak +1 at this point. I would just like to see the error message improved, if possible.

chessai avatar Feb 18 '22 22:02 chessai

Maybe rather than saying "perhaps you wanted..." (which is suggestive), it would better to be more definitive with an error like:

# is not permitted in symbol names. To relax this restriction, enable the MagicHash extension.

I object to saying something is for "advanced users" because such a statement is nebulous/vague and needlessly divisive

ocharles avatar Feb 18 '22 22:02 ocharles

I just want to try to prevent people who don't know what the MagicHash extension does from enabling it, because in that case it is probably not the right solution.

I don't think your suggestion is enough to prevent users accidentally enabling MagicHash hoping it would magically fix their errors. It makes it seem like it is just lifting a syntactic restriction. Technically that is true, but in practice it is meant for giving access to unboxed types and primitives.

Some other suggestions:

  1. If you know what it does, perhaps you want to enable the 'MagicHash' extension.
    Instead of grouping users into advanced and non-advanced, only distinguish between the relevant criterion: knowing about the MagicHash extension.

  2. Advanced: perhaps you want to enable the 'MagicHash' extension.
    Instead of calling some users advanced, just call the feature/suggestion advanced.

  3. To access unboxed types and primitives, enable the 'MagicHash' extension.
    This clearly states what the MagicHash extension is intended for, but I can imagine this can be confusing to people who don't know about the MagicHash extension.

noughtmare avatar Feb 19 '22 15:02 noughtmare

How about

The character # is reserved for working with unboxed types and primitives. If you need to use #, enable the MagicHash language extension.

This is similar to your option 3, but I think it's important to anchor the error around the use of #. Having the error just say "if you want to access unboxed primitives..", and not that # is about primitives, is quite a leap for someone who doesn't know anything about this.

ocharles avatar Feb 19 '22 15:02 ocharles

Sounds good but shouldn't it be qualified with "in a non-operator identifier"? # isn't reserved in operators!

(I forget if there's particular terminology for non-operator identifiers)

tomjaguarpaw avatar Feb 19 '22 15:02 tomjaguarpaw

I like where we're going here, but I would say that # isn't reserved at all: We can use a # suffix on any function. It so happens that we have conventions around using # around unboxed types, but that's just a convention.

We can also be selective in when we print the message, doing so only when a sequence of 1 or more #s is used in a suffix occurrence. (That is, the sequence is not preceded by a space but is followed by one.)

As to the wording, I'll throw out my offer:

To parse identifiers ending in #s, enable the MagicHash extension

This is similar to @ocharles's first suggestion. There's nothing about "advanced" or "unboxed" here, because I agree how those terms could make things worse, not better. Instead, this note tells the user exactly what MagicHash does. My hope would be that the user would read enough of the error message to consider whether they want to e.g. import a module that exports # or to parse identifiers ending in #s.

One confounding variable: right now, HLS looks at error messages for names of extensions and enables users just to enable the extension. So HLS would suggest enabling MagicHash here. Instead, the new errors infrastructure allows GHC to make a conditional recommendation of an extension; the hope would be that HLS would present this information to users when they're choosing a code repair.

goldfirere avatar Feb 21 '22 16:02 goldfirere