I just encountered this. I would say that the current implementation logic is pretty counterintuitive:

```
{-# LANGUAGE ApplicativeDo #-}
module Main where
bug :: Applicative f => f ()
bug = do
let _ = ()
_ <- pure ()
let _ = ()
_ <- pure ()
-- let _ = ()
pure ()
main :: IO ()
main = pure ()
```

The above is accepted or rejected depending on whether the commented line is uncommented or not.

The following is accepted (with a warning telling the solution to `_`

) on GHC 8.10.7, but fails to type check on newer GHCs:

```
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE PartialTypeSignatures #-}
{-# LANGUAGE RankNTypes #-}
module Main where
import GHC.TypeLits
import Data.Functor.Identity
import Data.Functor.Const
import Data.Functor
-- import fluff
type ASetter s t a b = (a -> Identity b) -> s -> Identity t
type Getting r s a = (a -> Const r a) -> s -> Const r s
type Lens s t a b = forall f . Functor f => (a -> f b) -> (s -> f t)
type Traversal s t a b = forall f . Applicative f => (a -> f b) -> (s -> f t)
set :: ASetter s t a b -> b -> s -> t
set = undefined
view :: MonadReader s m => Getting a s a -> m a
view = undefined
class Monad m => MonadReader r (m :: * -> *) | m -> r where
instance MonadReader r ((->) r) where
-- test case
data Item (a :: *) (f :: Symbol -> * -> *)
l :: Lens (Item a f) (Item a' g) (f "1" ()) (g "1" ())
l = undefined
type ExoticTraversal' a y f = Traversal
(Item a f)
(Item a f)
(f y ())
(f y ())
test :: ExoticTraversal' a _ f
test f x = f (view l x) <&> \w -> set l w x
main :: IO ()
main = pure ()
```

The following compiles on GHC 8.10.7, but fails on GHC 9.0.2 and GHC 9.2.2:

```
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE UndecidableInstances #-}
module Main where
import Data.Function
import Data.Kind
import GHC.Generics
import GHC.TypeLits
-- inlined generic-data imports:
from' :: Generic a => a -> Rep a ()
from' = from
geq :: (Generic a, Eq (Rep a ())) => a -> a -> Bool
geq = (==) `on` from'
gcompare :: (Generic a, Ord (Rep a ())) => a -> a -> Ordering
gcompare = compare `on` from'
-- test case:
data A (v :: Symbol -> Type -> Type) a b deriving (Generic,Generic1)
instance (Eq a , (forall w z . Eq z => Eq (v w z)) , Eq b) => Eq (A v a b) where
{-# INLINE (==) #-}
(==) = geq
instance (Ord a , (forall w z . Eq z => Eq (v w z)) , (forall w z . Ord z => Ord (v w z)) , Ord b) => Ord (A v a b) where
{-# INLINE compare #-}
compare = gcompare
main :: IO ()
main = pure ()
```

I have pattern synonyms of the following style:

```
newtype LGate = LGate CChar
deriving newtype (Eq,Ord,B.Bits,Show)
{-# INLINE And #-}
pattern And :: LGate
pattern And <- LGate 0b00000000
where
And = LGate 0b00000000
```

I added that `INLINE`

pragma for GHC 9.2.2, but when I compile I get a bunch of `makeCorePair: arity missing $mAnd`

messages appearing in my terminal. Everything seems to run correctly, but it smells suspicious so I thought I'd report it here just in case.

Looking at `fromIntegral`

in GHC.Real, it looks like there are no rewrite rules for sized numerics like `Word8`

etc., which is critical since users are likely to reach for these types when they're most interested in bit-twiddling high-performance code.

Also, I'm not sure how the `NOINLINE`

annotation works here with the rewrite rules, but just to be clear, for these cases where the rules fire, we do want the subsequent body inlined, as without that, you incur function call overhead for a trivial operation.

Consider the following:

```
{-# LANGUAGE ConstrainedClassMethods #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE TypeFamilies #-}
{-# OPTIONS_GHC -Wredundant-constraints #-}
module Main where
-- declare class
class Mode t where
type Scalar t
myf :: Fractional (Scalar t) => t -> Scalar t -> t
-- declare data type + instance
data ReverseDouble a
instance Mode (ReverseDouble s) where
type Scalar (ReverseDouble s) = Double
myf = undefined
-- declare a newtype and derive the instance from the above data type
newtype GDouble s a = GDouble (ReverseDouble s)
deriving newtype Mode
main :: IO ()
main = pure ()
```

Compiling this with GHC 8.10.4 yields a warning about a redundant `Fractional`

constraint on that `deriving newtype Mode`

line, but this is quite confusing as a user - GHC seems to be warning about its own generated code here (and I'm not even sure it's correct in its self-indictment).

The problem is that the only half-way comfortable API I know of is in primitive

Not sure if it's useful or not, but I just pushed a simple Vector interface for SmallArray# that I had sitting around on my pc. It's basically just a bunch of boilerplate, but it should give access to common instances and of course the whole generic vector API. You can just copy this module as a starting point, though I'm sure there's plenty of stuff to trim/add to tweak it into a shape acceptable for a GHC internal module.

Consider the following:

```
type Joules = Double
type Grams = Double
data Unit a where
Energy :: Unit Joules
Mass :: Unit Grams
test :: Unit a -> a
test Energy = _
```

GHC reports the hole as `_ :: Double`

, but I expected the synonym to remain intact, i.e., that the hole would be `_ :: Joules`

.