Opened 3 months ago

Closed 2 months ago

#12797 closed bug (fixed)

Default Rules stop working when providing some constraints

Reported by: danilo2 Owned by:
Priority: normal Milestone: 8.0.2
Component: Compiler Version: 8.0.1
Keywords: Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: GHC rejects valid program Test Case: typecheck/should_compile/T12797
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:

Description (last modified by danilo2)

I've just found a very strange behavior. Let's consider following program:

{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE TypeFamilies              #-}
{-# LANGUAGE ExtendedDefaultRules      #-}

module Main where

import Prelude
import Control.Monad.IO.Class


type family FuncArg m where
    FuncArg ((->) t) = 'Just t
    FuncArg m        = 'Nothing

test1 :: (MonadIO m) => m ()
test1 = do
    liftIO $ print 6

test2 :: (MonadIO m, FuncArg m ~ 'Nothing) => m ()
test2 = do
    liftIO $ print 6

main :: IO ()
main = return ()

The function tst1 compiles fine, while tst2 fails:

exe/Main.hs:21:14: error:
    • Could not deduce (Show a0) arising from a use of ‘print’
      from the context: (MonadIO m, FuncArg m ~ 'Nothing)
        bound by the type signature for:
                   tst2 :: (MonadIO m, FuncArg m ~ 'Nothing) => m ()
        at exe/Main.hs:19:1-49
      The type variable ‘a0’ is ambiguous
      These potential instances exist:
        instance Show Ordering -- Defined in ‘GHC.Show’
        instance Show Integer -- Defined in ‘GHC.Show’
        instance Show a => Show (Maybe a) -- Defined in ‘GHC.Show’
        ...plus 22 others
        ...plus six instances involving out-of-scope types
        (use -fprint-potential-instances to see them all)
    • In the second argument of ‘($)’, namely ‘print 6’
      In a stmt of a 'do' block: liftIO $ print 6
      In the expression: do { liftIO $ print 6 }

exe/Main.hs:21:20: error:
    • Could not deduce (Num a0) arising from the literal ‘6’
      from the context: (MonadIO m, FuncArg m ~ 'Nothing)
        bound by the type signature for:
                   tst2 :: (MonadIO m, FuncArg m ~ 'Nothing) => m ()
        at exe/Main.hs:19:1-49
      The type variable ‘a0’ is ambiguous
      These potential instances exist:
        instance Num Integer -- Defined in ‘GHC.Num’
        instance Num Double -- Defined in ‘GHC.Float’
        instance Num Float -- Defined in ‘GHC.Float’
        ...plus two others
        (use -fprint-potential-instances to see them all)
    • In the first argument of ‘print’, namely ‘6’
      In the second argument of ‘($)’, namely ‘print 6’
      In a stmt of a 'do' block: liftIO $ print 6

Giving explicit types to literals fixes the problem.

Change History (8)

comment:1 Changed 3 months ago by danilo2

  • Description modified (diff)

comment:2 Changed 3 months ago by danilo2

Some notes from #ghc IRC: The error can be reproduced in GHC 7.10.3 (after adding -XDataKinds). It never even gets to the rewrites, apparently (compiling with -O0 so no RULES).

comment:3 Changed 3 months ago by simonpj

I took a quick look. It's because TcSimplify.findDefaultableGroups uses TcSimplify.approximateWC; and the latter is also used when inferring the most general type of a function that lacks a type signature. And approximateWC has the following note:

Note [ApproximateWC]
~~~~~~~~~~~~~~~~~~~~
1.  We do *not* float anything out if the implication binds equality
    constraints, because that defeats the OutsideIn story.  Consider
       data T a where
         TInt :: T Int
         MkT :: T a

       f TInt = 3::Int

    We get the implication (a ~ Int => res ~ Int), where so far we've decided
      f :: T a -> res
    We don't want to float (res~Int) out because then we'll infer
      f :: T a -> Int
    which is only on of the possible types. (GHC 7.6 accidentally *did*
    float out of such implications, which meant it would happily infer
    non-principal types.)

But in the case of defaulting we do want to infer a less-than-most-general type; and that's just what is happening here.

The fix is easy: give a boolean flag to approximateWC. I'll do that soon.

comment:4 Changed 3 months ago by Simon Peyton Jones <simonpj@…>

In 13508bad/ghc:

Fix Trac #12797: approximateWC

This patch makes approximateWC a bit more gung-ho when called
from the defaulting code.  See Note [ApproximateWC], item (1).

comment:5 Changed 3 months ago by simonpj

  • Status changed from new to merge
  • Test Case set to typecheck/should_compile/T12797

Thanks for the example. Fixed!

Merge if easy.

comment:6 Changed 3 months ago by danilo2

@Simon that was fast! Thank you! :)

comment:7 Changed 2 months ago by simonpj

  • Milestone set to 8.0.2

comment:8 Changed 2 months ago by bgamari

  • Resolution set to fixed
  • Status changed from merge to closed
Note: See TracTickets for help on using tickets.