GHC issueshttps://gitlab.haskell.org/ghc/ghc/-/issues2024-03-26T15:25:02Zhttps://gitlab.haskell.org/ghc/ghc/-/issues/24590Out-of-range literal warnings interact poorly with rebindable syntax2024-03-26T15:25:02ZDavid FeuerOut-of-range literal warnings interact poorly with rebindable syntax## Summary
The fancy logic in `-Woverflowed-literals` can be triggered improperly under `RebindableSyntax`.
## Steps to reproduce
```haskell
{-# LANGUAGE RebindableSyntax #-}
module Silly where
import Prelude hiding (negate)
negate :...## Summary
The fancy logic in `-Woverflowed-literals` can be triggered improperly under `RebindableSyntax`.
## Steps to reproduce
```haskell
{-# LANGUAGE RebindableSyntax #-}
module Silly where
import Prelude hiding (negate)
negate :: Word -> Word
negate x = x + 1
foo :: Word
foo = -40
```
```plaintext
dfeuer@squirrel:~/src> ghc -fforce-recomp -Wall Silly
[1 of 1] Compiling Silly ( Silly.hs, Silly.o )Silly.hs:9:8: warning: [GHC-97441] [-Woverflowed-literals]
Literal -40 is out of the Word range 0..18446744073709551615
|
9 | foo = -40
| ^^
```
## Expected behavior
I expect the module to compile with no warnings.
## Discussion
As I understand it, there are three functions potentially involved in literal out of range warnings: `fromInteger`, `fromRational`, and `negate`. I believe that in a module using `RebindableSyntax` we want to modify the warning mechanism under the following circumstances.
1. If the literal is non-negative, or if `NegativeLiterals` is enabled, then we should not get a warning for an integer literal if `fromInteger` is rebound, and we should not get a warning for a rational literal if `fromRational` is rebound.
2. If the literal is negative, `NegativeLiterals` is disabled, and `negate` is rebound, then we should act exactly as though the user had written `negate lit`. That is, the range check should be performed on `lit` (unless the relevant `fromInteger` or `fromRational` is rebound), rather than on `-lit`. That can potentially produce warnings we do not currently produce. For example, if `negate` is rebound but `fromInteger` is not, `-128 :: Int8` should produce a warning, because `128` is out of range for `Int8`.
## Environment
* GHC version used: 9.8.2
Optional:
* Operating System:
* System Architecture:https://gitlab.haskell.org/ghc/ghc/-/issues/24419GHCi statements to use HsExpansions route2024-02-15T15:43:46ZApoorv IngleGHCi statements to use HsExpansions route## Summary
Currently GHCi statements are typechecked using `tcStmtsAndThen` in `GHC.Tc.Gen.TcGhciStmts`.
`tcStmtsAndThen` internally uses `tcSyntaxOp` to typecheck statements.
We should instead be using `GHC.Tc.Gen.Do.expandDoStmts` ...## Summary
Currently GHCi statements are typechecked using `tcStmtsAndThen` in `GHC.Tc.Gen.TcGhciStmts`.
`tcStmtsAndThen` internally uses `tcSyntaxOp` to typecheck statements.
We should instead be using `GHC.Tc.Gen.Do.expandDoStmts` so that we can start removing the dependency from `tcSyntaxOp`
## Steps to reproduce
ghci script
```haskell
:set -XImpredicativeTypes
type Id = forall a. a -> a
t :: IO Id; t = return id
p :: Id -> (Bool, Int); p f = (f True, f 3)
x <- t
```
fails with the following error message:
```
Couldn't match type ‘a0’ with ‘Id’
Expected: IO a0
Actual: IO Id
Cannot instantiate unification variable ‘a0’
with a type involving polytypes: Id
In a stmt of an interactive GHCi command:
x <- GHC.GHCi.ghciStepIO :: IO a -> IO a t
```
Expected output is that it should assign polymorphic typed value `id` to `x`
## GHC
version: 9.9 (Head)Apoorv IngleApoorv Inglehttps://gitlab.haskell.org/ghc/ghc/-/issues/24406Applicative Do should go via HsExpansion Route2024-03-28T05:02:38ZApoorv IngleApplicative Do should go via HsExpansion Route## Summary
Impredicativity does not play well with `do`-blocks expanding under `ApplicativeDo` Language pragma due to ill-designed `tcSyntaxOp` (c.f. issues documented in [wiki page](https://gitlab.haskell.org/ghc/ghc/-/wikis/Rebindable...## Summary
Impredicativity does not play well with `do`-blocks expanding under `ApplicativeDo` Language pragma due to ill-designed `tcSyntaxOp` (c.f. issues documented in [wiki page](https://gitlab.haskell.org/ghc/ghc/-/wikis/Rebindable-syntax))
## Steps to reproduce
```haskell
-- test.hs
{-# LANGUAGE ImpredicativeTypes, ApplicativeDo #-}
module T where
t :: IO (forall a. a -> a)
t = return id
p :: (forall a. a -> a) -> (Bool, Int)
p f = (f True, f 3)
-- This typechecks (with QL)
foo1 = t >>= \x -> return (p x)
-- But this does *not* type check:
foo2 = do { x <- t ; return (p x) }
```
```
$ ghc test.hs
```
Error:
```
test.hs:14:18: error: [GHC-91028]
• Couldn't match type ‘a0’ with ‘forall a. a -> a’
Expected: IO a0
Actual: IO (forall a. a -> a)
Cannot instantiate unification variable ‘a0’
with a type involving polytypes: forall a. a -> a
• In a stmt of a 'do' block: x <- t
In the expression:
do x <- t
return (p x)
In an equation for ‘foo2’:
foo2
= do x <- t
return (p x)
|
14 | foo2 = do { x <- t ; return (p x) }
| ^
test.hs:14:32: error: [GHC-46956]
• Couldn't match expected type ‘a -> a’ with actual type ‘a0’
because type variable ‘a’ would escape its scope
This (rigid, skolem) type variable is bound by
a type expected by the context:
forall a. a -> a
at test.hs:14:32
• In the first argument of ‘p’, namely ‘x’
In a stmt of a 'do' block: return (p x)
In the expression:
do x <- t
return (p x)
• Relevant bindings include x :: a0 (bound at test.hs:14:13)
|
14 | foo2 = do { x <- t ; return (p x) }
```
## Expected behavior
It should type check and execute as expected
## Environment
* GHC version used: 9.6, 9.9Apoorv IngleApoorv Inglehttps://gitlab.haskell.org/ghc/ghc/-/issues/24218QualifiedDo causes Core lint error (with my typechecker plugin)2024-03-09T02:05:30ZJaro ReindersQualifiedDo causes Core lint error (with my typechecker plugin)## Summary
I'm trying to develop a plugin that automatically solves transitivity of a type class that I've defined myself:
```haskell
type (<=) :: (Type -> Type) -> (Type -> Type) -> Constraint
class f <= g where
inj :: f x -> g x
-...## Summary
I'm trying to develop a plugin that automatically solves transitivity of a type class that I've defined myself:
```haskell
type (<=) :: (Type -> Type) -> (Type -> Type) -> Constraint
class f <= g where
inj :: f x -> g x
-- These are overlapping, but our plugin will resolve the overlap.
instance f <= f where
inj = id
instance forall f g h. (f <= g, g <= h) => f <= h where
inj = inj @g @h . inj @f @g
```
However, I'm running into an error that I cannot explain.
The error occurs in the `hsapply` function which is defined like this:
```haskell
hsapply :: Free MySig u (a -> b) -> Free MySig u a -> Free MySig u b
hsapply x y = Main.do
x' <- x
y' <- injfree y
Free (HsApply (inj x') y' (coerce Pure))
```
But the error disappears if I manually use my own `>>=`:
```haskell
hsapply :: Free MySig u (a -> b) -> Free MySig u a -> Free MySig u b
hsapply x y =
x Main.>>= \x' ->
injfree y Main.>>= \y' ->
Free (HsApply (inj x') y' (coerce Pure))
```
The type of my bind is:
```haskell
(>>=) :: UFunctor f => Free f u a -> (forall u'. (u <= u') => u' a -> Free f u' b) -> Free f u b
```
## Steps to reproduce
1. Clone https://github.com/noughtmare/transitive-constraint-plugin
2. Check out this problematic commit: `git checkout bb7f4cfec371f6053bb3f4d33130bc7a67166596`
3. Try to build the 'Free' example: `cabal build exe:free-example`
This produces a core lint error:
```
Out of scope: $d<=_a1fj :: u_a1eN <= u'_a1eW
[LclId]
```
The relevant snippet of Core is:
```haskell
>>=
@MySig
@u'_a1eW
@a_a1eO
@b_a1eP
$dUFunctor_a1f9
(injfree @u_a1eN @u'_a1eW @a_a1eO $d<=_a1fj y_aXB)
(\ (@(u'_a1fa :: * -> *)) ($d<=_a1fb :: u'_a1eW <= u'_a1fa) ->
let {
$d<=_a1fj :: u_a1eN <= u'_a1eW
[LclId]
$d<=_a1fj = $d<=_a1eX } in
```
Note how the `$d<=_a1fj` is referenced outside the let it is bound in.
But my plugin does not produce that reference as far as I can tell. My tracing ([source](https://github.com/noughtmare/transitive-constraint-plugin/blob/bb7f4cfec371f6053bb3f4d33130bc7a67166596/src/TransitiveConstraintPlugin.hs#L74)) shows that it only touches that name once and in that case it produces a contradiction:
```
contradiction: [W] $d<=_a1fj {0}:: u_a1eN[sk:1] <= u'_a1eW[sk:2] (CDictCan)
```
## Expected behavior
The `Free.hs` example should compile without issues.
## Environment
* GHC version used: 9.6.3Apoorv IngleApoorv Inglehttps://gitlab.haskell.org/ghc/ghc/-/issues/24201Tidy up Do Expansion implimentation/Kill `GHC.Types.Basic.Origin`2024-02-15T15:32:43ZApoorv IngleTidy up Do Expansion implimentation/Kill `GHC.Types.Basic.Origin`This ticket tracks various tidying up tasks for HsExpansion
Here are some ideas:
1. Get rid `Origin` to beautify and stream line the `Generated` code vs `FromSource` Code meta-data.
See discussion here: https://gitlab.haskell.org/ghc/gh...This ticket tracks various tidying up tasks for HsExpansion
Here are some ideas:
1. Get rid `Origin` to beautify and stream line the `Generated` code vs `FromSource` Code meta-data.
See discussion here: https://gitlab.haskell.org/ghc/ghc/-/merge_requests/10140#note_535779
The current design depends on `GHC.Types.Basic.Origin` and also `GHC.Types.SrcLoc.GenLocated` to figure out whether a source code's origin is user written or not.
The objective is that we should only be using one thing to identify the source codes origin. The current `tcExpr` already uses `GHC.Types.SrcLoc.GenLocated` to identify the src origin using `isGeneratedCode :: TcRn Bool` and we would be able to reuse that functionality rather than depending on `GHC.Types.Basic.Origin`.
2. Kill `GenReason` in `GHC.Types.Basic.Origin` and clean up smelly code like this one in [GHC.HstoCore.Match.matchWrapper](https://gitlab.haskell.org/ghc/ghc/-/blob/master/compiler/GHC/HsToCore/Match.hs#L773)
```haskell
= do { dflags <- getDynFlags
; locn <- getSrcSpanDs
; let matches
= if any (is_pat_syn_match origin) matches'
then filter (non_gen_wc origin) matches'
-- filter out the wild pattern fail alternatives
-- which have a do expansion origin
-- They generate spurious overlapping warnings
-- Due to pattern synonyms treated as refutable patterns
-- See Part 1's Wrinkle 1 in Note [Expanding HsDo with XXExprGhcRn] in GHC.Tc.Gen.Do
```Apoorv IngleApoorv Inglehttps://gitlab.haskell.org/ghc/ghc/-/issues/23061ArrowChoice and RebindableSyntax causes core lint error2023-06-05T12:02:10ZEdsko de VriesArrowChoice and RebindableSyntax causes core lint errorThe below module causes a panic about "no skolem info" in ghc 8.6, 8.8 and 8.10, and a core lint error in ghc 9.0, 9.2, 9.4, and 9.7.20230301
```haskell
{-# LANGUAGE Arrows #-}
{-# LANGUAGE RebindableSyntax #-}
{-# OPTIONS_GH...The below module causes a panic about "no skolem info" in ghc 8.6, 8.8 and 8.10, and a core lint error in ghc 9.0, 9.2, 9.4, and 9.7.20230301
```haskell
{-# LANGUAGE Arrows #-}
{-# LANGUAGE RebindableSyntax #-}
{-# OPTIONS_GHC -dcore-lint #-}
module T where
import Prelude
import Control.Arrow
ifThenElse :: Bool -> a -> a -> a
ifThenElse b x y = if b then x else y
f :: ArrowChoice arr => (Int -> Int -> Bool) -> arr Int t -> arr (Int, Int) t
f p f = proc (x,y) ->
if p x y
then f -< x+1
else f -< y+2
```https://gitlab.haskell.org/ghc/ghc/-/issues/20731Static pointers should work with RebindableSyntax2021-11-24T11:37:26ZKrzysztof GogolewskiStatic pointers should work with RebindableSyntaxWhen `RebindableSyntax` is enabled, GHC uses functions such as `fromInteger`, `fromString` from scope, rather than relying on the typeclasses. This principle is not upheld for `fromStaticPtr`:
```haskell
{-# LANGUAGE RebindableSyntax, S...When `RebindableSyntax` is enabled, GHC uses functions such as `fromInteger`, `fromString` from scope, rather than relying on the typeclasses. This principle is not upheld for `fromStaticPtr`:
```haskell
{-# LANGUAGE RebindableSyntax, StaticPointers, NoMonomorphismRestriction #-}
module M where
data T = MkT
fromInteger :: a -> T
fromInteger _ = MkT
fromStaticPtr :: a -> T
fromStaticPtr _ = MkT
x = 0
y = static 'a'
```
gives
```
x :: T
y :: GHC.StaticPtr.IsStatic t => t GHC.Types.Char
```
The type of `y` should be `T`, just like `x`.https://gitlab.haskell.org/ghc/ghc/-/issues/20014Allow OverloadedLists to overload (:) in patterns and expressions2021-06-18T11:26:16Zsheafsam.derbyshire@gmail.comAllow OverloadedLists to overload (:) in patterns and expressions@simonpj suggested ([here](https://gitlab.haskell.org/ghc/ghc/-/merge_requests/5985?commit_id=bc20a16ec9c877e0a07c25468c9566ae6339d2c7#note_359845)) that the `OverloadedLists` extension should also overload the `(:)` constructor, both in...@simonpj suggested ([here](https://gitlab.haskell.org/ghc/ghc/-/merge_requests/5985?commit_id=bc20a16ec9c877e0a07c25468c9566ae6339d2c7#note_359845)) that the `OverloadedLists` extension should also overload the `(:)` constructor, both in expressions and patterns. This requires adding new methods to the `IsList` typeclass; Simon suggests:
```haskell
class IsList l where
type Item l
fromList :: [Item l] -> l
toList :: l -> [Item l]
fromListN :: Int -> [Item l] -> l
fromListN _ = fromList
cons :: Item l -> l -> l
unCons :: l -> Maybe (Item l, l)
```
This will allow users to write code that looks like it should work with overloaded lists, such as:
```haskell
f [] = 1
f [_] = 2
f (x:xs) = x
```
Simon notes that this will probably require a GHC proposal.https://gitlab.haskell.org/ghc/ghc/-/issues/19979Better error for out-of-scope RebindableSyntax2021-08-19T17:53:00ZKrzysztof GogolewskiBetter error for out-of-scope RebindableSyntaxIf a RebindableSyntax identifier is missing, GHC reports "out of scope". I think the error could mention the provenance "required by RebindableSyntax", to distinguish it from user-written out-of-scope identifiers.
```
{-# LANGUAGE Rebin...If a RebindableSyntax identifier is missing, GHC reports "out of scope". I think the error could mention the provenance "required by RebindableSyntax", to distinguish it from user-written out-of-scope identifiers.
```
{-# LANGUAGE RebindableSyntax #-}
x = 1
```
```
T.hs:2:5: error: Not in scope: ‘fromInteger’
|
2 | x = 1
| ^
```
Same for the error "Ambiguous occurrence".https://gitlab.haskell.org/ghc/ghc/-/issues/19477Rebindable Syntax and LinearTypes (allow a version of RebindableSyntax withou...2021-04-08T09:55:27ZEdward KmettRebindable Syntax and LinearTypes (allow a version of RebindableSyntax without ifThenElse)When working with both `LinearTypes` and unlifted data types, I find I often want to use `RebindableSyntax` to overload things.
However, right now `RebindableSyntax` is one monolithic switch which turns on things that are desirable to o...When working with both `LinearTypes` and unlifted data types, I find I often want to use `RebindableSyntax` to overload things.
However, right now `RebindableSyntax` is one monolithic switch which turns on things that are desirable to overload e.g. numeric literals, but also turns on things that I can't properly typecheck myself, such as `ifThenElse`.
Being able to split apart the scope of `RebindableSyntax` to allow the exclusion of `ifThenElse` would suffice.
## Alternatives
Morally, one can view the issue that viewed as a function `ifThenElse` doesn't really look like `ifThenElse :: Bool -> a -> a -> a`. The one supplied by GHC has superpowers that such a function lacks.
First, it works for all runtime representations, and it only forces one of its arguments. You see this if you to to define
```haskell
ifThenElse :: forall (a :: TYPE 'IntRep). Bool -> a -> a -> a
ifThenElse True t _ = t
ifThenElse False _ f = f
```
Evaluating `ifThenElse False undefined 1#` now throws an exception.
We can fix this part by defining
```haskell
type Lev (a :: TYPE r) = ()~() => a
ifThenElse :: forall (a :: TYPE r). Bool -> Lev a -> Lev a -> a
ifThenElse True t _ = t
ifThenElse False _ f = f
```
Now, `ifThenElse False undefined 1#` returns `1#` as expected. Lev also trickily let us side-step any levity polymorphism concerns with taking values of unknown `RuntimeRep` in negative position.
However, even if we can fix the levity issue we can't currently fix the linearity issue with the current type.
```haskell
ifThenElse :: forall (a :: TYPE r). Bool -> a -> a -> a
```
isn't general enough to handle `if _ then _ else _` at linear types.
We can't put
```haskell
ifThenElse :: forall (a :: TYPE r). Bool -> a %1 -> a %1 -> a
```
as we don't use each branch linearly. Morally we don't take two functions, we take the "with" or `&` of two functions in the linear logic sense. `With a b` isn't two separate arguments it a single-shot user choice to get one of the two things. It is the third linear logic connective that usually shows up in intuitionistic linear logic. In the vending machine metaphor. `(a,b)` is the ability/requirement to consume `a` and `b` both. `Either a b` is the ability/requirement to consume `a` or `b`, but you don't get to pick which, it is the suppliers choice. `With a b` is the ability/requirement to consume `a` or `b`, but the consumer gets to pick. That is exactly what `ifThenElse` is doing above when linear types are turned on.
We can model `With` in haskell as a function.
```haskell
data Choice a b x where
L :: Choice a b a
R :: Choice a b b
newtype With a b = With { runWith :: (forall x. Choice a b x %1 -> x) }
pickL :: With a b -> a
pickR :: With a b -> b
```
Then a user version of `ifThenElse` morally wants to consume the `With` of two code branches it is supplied.
However, here the rabbit hole ends, it's not really all that convenient to define such a beast, and even if we made up a `With` data type and used it to wrap both branches of the ifThenElse, this style of overloading `ifThenElse` isn't compatible with the version that arises in EDSLs and needs `GADTs`, `RankNTypes`...
As a result, I currently have to just advocate for users using `MultiWayIf` or pattern guards if they use my library, but would like to be able to leave them access to `if then else` notation.
*tl;dr* I'd like some way to split off `ifThenElse` from `RebindableSyntax` it is currently quite the blunt instrument and `ifThenElse` currently _can't_ be overloaded correctly in light of new language features.https://gitlab.haskell.org/ghc/ghc/-/issues/19354Operator sections and rebindable syntax2021-03-01T11:20:58ZSimon Peyton JonesOperator sections and rebindable syntaxAs part of fixing #19154 and #19167 I developed !4981, fleshing out out
plan to implement RebindableSyntax in the renamer rather than the typechecker.
As part of that it felt natural to give the same treatment to operator
sections. Thi...As part of fixing #19154 and #19167 I developed !4981, fleshing out out
plan to implement RebindableSyntax in the renamer rather than the typechecker.
As part of that it felt natural to give the same treatment to operator
sections. This ticket is to discuss the details.
I ended up with this translation
```
(`op` e) ==> rightSection op e
(e `op`) ==> leftSection (op e)
```
where those two new function are defined like this
```
leftSection :: (a->b) -> a -> b
rightSection :: (a->b->c) -> b -> a -> c
```
Benefits:
1. This expansion is pretty easy, and can be done in the renamer. Special code paths in the typechecker and desugarer can disappear.
2. When RebindableSyntax is on, we can just use whatever `leftSection` and `rightSection` are in scope, extending the range of `RebindableSyntax`.
Benefit (1) is purely internal. Benefit (2) is user-visible.
Some observations and questions.
* Do we want infix application to be rebindable too?
* `leftSection` looks like an identity function. Why don't we do this
```
(e `op`) ==> op e
```
Answer: we want to enforce that `op e` has a function type; that's all `leftSection` does.
* What about higher rank types? Suppose
```
op :: (forall a. a->a) -> (forall b. [b] -> [b]) -> blah
```
We might hope that
```
(id `op`)
(`op` reverse)
```
would both work. And the will, under the above translation, through the magic of Quick Look
* What about nested quantification? Suppose
```
op :: forall a. Eq a => a -> forall b. Ord b => b -> blah
```
That will work for left sections (under the scheme above) but not for right sections (because we don't do deep instantiation any more).
If we changed the expansion thus:
```
(`op` e) ==> rightSection (\x y -> op x y) e
```
then we'd get nested quantification, but would lose higher rank functions, because the lambda-bound `x` and `y` would get monotypes.
* `leftSection` and `rightSection` as not treated uniformly. Why not make it
```
leftSection :: (a->b) -> a -> b
rightSection :: (a->b->c) -> b -> a -> c
```
We could do that, but then nested quantification would not work for left sections either. On the other hand it would give more wiggle room for what you can do with RebindableSyntax, because the operator and argument are passed separately.
No one is begging for rebindable syntax for operator sections or infix operators so, since there are some tricky corners, perhaps we should park rebindable syntax for now.
That leaves benefit (1). And there we still have the questions about
* Whether higher-rank operators should work. I think they should
* Whether operators with nested quantification should work. I'm happy if they don't, because it's hard to give a typing rule.
The unifying idea is that we explain the typing rule for sections (and indeed infix) by saying "It typechecks iff this translation typechecks", which is much easier for users and implementors than some fancy new rule that has to account for higher rank, nested quantification, and impredicative instantiation.https://gitlab.haskell.org/ghc/ghc/-/issues/18816ApplicativeDo requires (>>=) and (<*>)2020-10-07T14:01:55ZKrzysztof GogolewskiApplicativeDo requires (>>=) and (<*>)The following ApplicativeDo+RebindableSyntax program requires `(>>=)` and `(<*>)` to be present in scope, even though neither is used. There's a similar problem with `return`, covered by #18313.
```
{-# LANGUAGE ApplicativeDo #-}
{-# LA...The following ApplicativeDo+RebindableSyntax program requires `(>>=)` and `(<*>)` to be present in scope, even though neither is used. There's a similar problem with `return`, covered by #18313.
```
{-# LANGUAGE ApplicativeDo #-}
{-# LANGUAGE RebindableSyntax #-}
module Bug where
import Prelude (Applicative(pure), Functor(..))
return x = [x]
(>>=) = (>>=) -- shouldn't be needed
(<*>) = (<*>) -- shouldn't be needed
xs :: [a]
xs = do
x <- []
pure x
```
Similar issue arises from combining ApplicativeDo+QualifiedDo:
```
module Ado where
(>>=) = undefined -- shouldn't be needed
(<*>) = undefined -- shouldn't be needed
pure :: Applicative f => a -> f a
pure = undefined
return :: Applicative f => a -> f a
return = Prelude.pure
fmap :: Functor f => (a -> b) -> f a -> f b
fmap = Prelude.fmap
----
{-# LANGUAGE QualifiedDo #-}
{-# LANGUAGE ApplicativeDo #-}
module Adotry where
import qualified Ado as A
xs :: [Int]
xs = A.do
x <- []
A.pure $ x
```
Bug found by Georgi Lyubenov https://twitter.com/aspiwack/status/1313595873058750464https://gitlab.haskell.org/ghc/ghc/-/issues/18636RebindableSyntax cannot defer-out-of-scope-variables2021-02-16T21:02:59ZRichard Eisenbergrae@richarde.devRebindableSyntax cannot defer-out-of-scope-variablesWhen I say
```hs
{-# LANGUAGE RebindableSyntax #-}
{-# OPTIONS_GHC -fdefer-out-of-scope-variables #-}
module Bug where
foo = 5
```
I get
```
Bug.hs:6:7: error: Not in scope: ‘fromInteger’
```
But I told GHC to defer such errors!
N...When I say
```hs
{-# LANGUAGE RebindableSyntax #-}
{-# OPTIONS_GHC -fdefer-out-of-scope-variables #-}
module Bug where
foo = 5
```
I get
```
Bug.hs:6:7: error: Not in scope: ‘fromInteger’
```
But I told GHC to defer such errors!
Nobody is really asking for this (I was just trying to abuse GHC for fun), but I think it should be very very easy to implement.https://gitlab.haskell.org/ghc/ghc/-/issues/18313ApplicativeDo and RebindableSyntax requires *both* return and pure2024-03-11T17:38:47ZRichard Eisenbergrae@richarde.devApplicativeDo and RebindableSyntax requires *both* return and pure`-XApplicativeDo` applies special treatment to `do`-blocks whose last statement is a call to `return` or `pure`. With `-XRebindableSyntax`, the `return`/`pure` is the one in scope, not the one from the `Prelude`. But this means that this...`-XApplicativeDo` applies special treatment to `do`-blocks whose last statement is a call to `return` or `pure`. With `-XRebindableSyntax`, the `return`/`pure` is the one in scope, not the one from the `Prelude`. But this means that this combination of extensions requires a user to define *both* `return` *and* `pure`. This is silly; if one isn't in scope, we should simply not look for it.
Here is a test case:
```hs
{-# LANGUAGE RebindableSyntax, ApplicativeDo #-}
module Bug where
_ >> _ = ()
return _ = ()
_ <*> _ = ()
fmap _ _ = ()
x = do x
return x
```
This currently fails with
```
Bug.hs:10:5: error: Not in scope: ‘pure’
|
10 | x = do x
| ^^^^...
```
but I think it should succeed.
Sidenote: changing to `x = do x` is accepted, but I have no idea *why* it doesn't look for `pure` in a one-line `do`. Maybe that's special-cased. But it's not documented.https://gitlab.haskell.org/ghc/ghc/-/issues/18102TemplateHaskellQuotes and RebindableSyntax don't play nicely2021-02-05T10:11:11ZRichard Eisenbergrae@richarde.devTemplateHaskellQuotes and RebindableSyntax don't play nicelyEDIT: The original problem described here was about untyped TH, and it was fixed in !2960. But we identify a new problem with typed Template Haskell, which has yet to be solved. https://gitlab.haskell.org/ghc/ghc/-/issues/18102#note_2922...EDIT: The original problem described here was about untyped TH, and it was fixed in !2960. But we identify a new problem with typed Template Haskell, which has yet to be solved. https://gitlab.haskell.org/ghc/ghc/-/issues/18102#note_292247 shows two illustrative examples.
-------------------------------------------------------
If I say
```hs
{-# LANGUAGE TemplateHaskell, RebindableSyntax #-}
module Bug where
import Prelude ( Monad(..), Bool(..), print, ($) )
import Language.Haskell.TH.Syntax
$( do stuff <- [| if True then 10 else 15 |]
runIO $ print stuff
return [] )
```
then I get errors about `ifThenElse` and `fromInteger` not being in scope. When I bring them into scope, the code is accepted, but the quoted syntax does not mention them, instead accurately reflecting the original source Haskell I wrote.
There are several problems in this story:
1. Template Haskell quotes are meant to work even in the presence of unbound identifiers.
2. Template Haskell is all about quoting (and splicing) surface syntax. Quoting should not care about `-XRebindableSyntax`.
3. If we were to decide that quoting should respect `-XRebindableSyntax` (I disagree with this design, to be clear), then the output of the quote is incorrect.
I propose: disable `-XRebindableSyntax` within quotes. That should fix all these problems.
Other reasonable possibility: disable `-XRebindableSyntax` within quotes, but use the TH combinators that are in scope (like `conE` and `appE`, etc.). I think this would be nightmarish to implement, and no one is asking for it, but it would be a consistent way forward.https://gitlab.haskell.org/ghc/ghc/-/issues/16618RebindableSyntax demands `fail` even when bindings are exhaustive2023-06-02T12:41:23ZFumiaki KinoshitaRebindableSyntax demands `fail` even when bindings are exhaustiveReproducing example:
```haskell
{-# LANGUAGE RebindableSyntax #-}
import Prelude hiding (fail)
main = do
() <- pure ()
pure ()
```
```
fail-scope.hs:4:3: error:
Not in scope: ‘fail’
Perhaps you meant ‘tail’ (imported from P...Reproducing example:
```haskell
{-# LANGUAGE RebindableSyntax #-}
import Prelude hiding (fail)
main = do
() <- pure ()
pure ()
```
```
fail-scope.hs:4:3: error:
Not in scope: ‘fail’
Perhaps you meant ‘tail’ (imported from Prelude)
Perhaps you want to remove ‘fail’ from the explicit hiding list
in the import of ‘Prelude’ (fail-scope.hs:2:1-28).
|
4 | () <- pure ()
|
```
This causes [basement](http://hackage.haskell.org/package/basement) to break on 8.8.1.sheafsam.derbyshire@gmail.comsheafsam.derbyshire@gmail.com