## ApplicativeDo selects "GHC.Base.Monad.return" when actions are used without patterns.

GHC 8.0.2 and 8.2.1-rc1 (rc2 not checked) have a bug where -XApplicativeDo causes "GHC.Base.Monad.return" to be used instead of the locally available "return", and a spurious "return ()" shows up. This desugaring is not adhering to the -XRebindableSyntax spec (see: #12490 (closed)).

Example:

```
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE RebindableSyntax #-}
-- Bug vanishes if this next line is removed:
{-# LANGUAGE ApplicativeDo #-}
module Main where
import Prelude (String, print)
class MyFunctor f where
fmap :: (a -> b) -> f a -> f b
class MyApplicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
class MyMonad m where
return :: a -> m a
(>>) :: m a -> m b -> m b
(>>=) :: m a -> (a -> m b) -> m b
fail :: String -> m a
join :: m (m a) -> m a
testCase1 m1 m2 = do
m1
m2
return ()
testCase2 m1 m2 = do
_ <- m1
_ <- m2
return ()
main = print "42"
```

```
:t testCase1
testCase1
:: (MyFunctor f, MyApplicative f, MyMonad f, Monad f) =>
f a2 -> f a1 -> f ()
:t testCase2
:: testCase2 :: (MyFunctor f, MyApplicative f) => f t -> f a -> f ()
```

The desugaring for testCase1 shows the issue:

```
testCase1' m1 m2 =
(<*>)
(fmap
(\ r1 r2 ->
case r1 of { () -> case r2 of { () -> () } })
(m1 >> (GHC.Base.Monad.return ())))
(m2 >> (GHC.Base.Monad.return ()))
-- or:
testCase1'' m1 m2 = (fmap (\() () -> () ) (m1 >> (GHC.Base.Monad.return ()))) <*> (m2 >> (GHC.Base.Monad.return ()))
```

I would be able to work on this if someone pointed me in the right direction. It looks like it would be in `compiler/rename/RnEnv`

and `compiler/rename/RnExpr`

, as with #12490 (closed)?

As a proposed fix, I would want to implement a limited-scope fix before the 8.2.1 release which would not address the thornier issue of #10892. The patch would:

- Replace
`GHC.Base.Monad.return`

with local`pure`

, removing the`Monad`

constraint. - Replace
`>>`

with`*>`

, removing the`MyMonad`

constraint.

This isn't a *complete* fix, as this would still leave the unnecessary pattern matches in the use of `fmap`

. The resulting desugaring would be:

`testCase1''' m1 m2 = (fmap (\() () -> () ) (m1 *> (pure ()))) <*> (m2 *> (pure ()))`