Opened 12 days ago

Closed 4 days ago

#14643 closed bug (fixed)

Partial type signatures in class constraints behave unexpectedly

Reported by: mnislaih Owned by:
Priority: normal Milestone: 8.4.1
Component: Compiler Version: 8.2.2
Keywords: Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case: partial-sigs/should_compile/T14643, T14643a
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:

Description

Minimal example:

{-# LANGUAGE PartialTypeSignatures #-}
{-# LANGUAGE TemplateHaskell #-}
module Minimal where

id [d|
    f :: (Monad m, _) => [m a] -> m [a]
    f' :: (Monad m, _) => [m a] -> m [a]
    f = f'
    f' [] = return []
    f' (x:xx) = f xx
  |]
[1 of 1] Compiling Minimal          ( /Users/pepe/Dropbox/code/debug-hoed/test/minimal.hs, interpreted )

/Users/pepe/Dropbox/code/debug-hoed/test/minimal.hs:5:1: warning: [-Wpartial-type-signatures]
    • Found type wildcard ‘_’ standing for ‘()’
    • In the type signature:
        f :: (Monad m_a7NN, _) => [m_a7NN a_a7NO] -> m_a7NN [a_a7NO]
  |
5 | id [d|
  | ^^^^^^...

/Users/pepe/Dropbox/code/debug-hoed/test/minimal.hs:5:1: warning: [-Wpartial-type-signatures]
    • Found type wildcard ‘_’ standing for ‘()’
    • In the type signature:
        f' :: (Monad m_a7NL, _) => [m_a7NL a_a7NM] -> m_a7NL [a_a7NM]
  |
5 | id [d|
  | ^^^^^^...
Ok, one module loaded.
 :browse
f :: (Monad m, Monad m) => [m a] -> m [a]
f' :: (Monad m, Monad m) => [m a] -> m [a]

Notice the duplicate Monad m constraint.

Things get even more weird if the type signatures are declared together:

id [d|
    f, f' :: (Monad m, _) => [m a] -> m [a]
    f = f'
    f' [] = return []
    f' (x:xx) = f xx
     |]
[1 of 1] Compiling Minimal          ( /Users/pepe/Dropbox/code/debug-hoed/test/minimal.hs, interpreted )

/Users/pepe/Dropbox/code/debug-hoed/test/minimal.hs:5:1: warning: [-Wpartial-type-signatures]
    • Found type wildcard ‘_’ standing for ‘()’
    • In the type signature:
        f :: (Monad m_a88E, _) => [m_a88E a_a88F] -> m_a88E [a_a88F]
  |
5 | id [d|
  | ^^^^^^...

/Users/pepe/Dropbox/code/debug-hoed/test/minimal.hs:5:1: warning: [-Wpartial-type-signatures]
    • Found type wildcard ‘_’ standing for ‘()’
    • In the type signature:
        f' :: (Monad m_a88E, _) => [m_a88E a_a88F] -> m_a88E [a_a88F]
  |
5 | id [d|
  | ^^^^^^...
Ok, one module loaded.
 :browse
f ::
  (Monad ghc-prim-0.5.1.1:GHC.Types.Any, Monad m) =>
  [ghc-prim-0.5.1.1:GHC.Types.Any ghc-prim-0.5.1.1:GHC.Types.Any]
  -> ghc-prim-0.5.1.1:GHC.Types.Any [ghc-prim-0.5.1.1:GHC.Types.Any]
f' ::
  (Monad ghc-prim-0.5.1.1:GHC.Types.Any, Monad m) => [m a] -> m [a]

Change History (8)

comment:1 Changed 12 days ago by mnislaih

It looks the same under ghc 8.4 alpha:

GHCi, version 8.4.0.20171214: http://www.haskell.org/ghc/  :? for help
[1 of 1] Compiling Minimal          ( code/debug-hoed/test/minimal.hs, interpreted )

code/debug-hoed/test/minimal.hs:5:1: warning: [-Wpartial-type-signatures]
    • Found type wildcard ‘_’ standing for ‘()’
    • In the type signature:
        f :: (Monad m_a46U, _) => [m_a46U a_a46V] -> m_a46U [a_a46V]
  |
5 | id [d|
  | ^^^^^^...

code/debug-hoed/test/minimal.hs:5:1: warning: [-Wpartial-type-signatures]
    • Found type wildcard ‘_’ standing for ‘()’
    • In the type signature:
        f' :: (Monad m_a46U, _) => [m_a46U a_a46V] -> m_a46U [a_a46V]
  |
5 | id [d|
  | ^^^^^^...
Ok, one module loaded.
*Minimal> :browse
f ::
  (Monad GHC.Types.Any, Monad m) =>
  [GHC.Types.Any GHC.Types.Any] -> GHC.Types.Any [GHC.Types.Any]
f' :: (Monad GHC.Types.Any, Monad m) => [m a] -> m [a]

comment:2 Changed 11 days ago by RyanGlScott

Summary: Partial type signatures in spliced TH declarations behave unexpectedlyPartial type signatures interact unexpectedly with :browse

Note that this has nothing to do with Template Haskell. You can also trigger the issue with this (slightly more) minimal file:

{-# LANGUAGE PartialTypeSignatures #-}
{-# LANGUAGE TemplateHaskell #-}
module Bug where

f :: (Monad m, _) => [m a] -> m [a]
f' :: (Monad m, _) => [m a] -> m [a]
f = f'
f' [] = return []
f' (x:xx) = f xx

g, g' :: (Monad m, _) => [m a] -> m [a]
g = g'
g' [] = return []
g' (x:xx) = g xx
$ ghci Bug.hs -Wno-partial-type-signatures
GHCi, version 8.2.2: http://www.haskell.org/ghc/  :? for help
Loaded GHCi configuration from /home/rgscott/.ghci
[1 of 1] Compiling Bug              ( Bug.hs, interpreted )
Ok, one module loaded.
λ> :browse
f :: (Monad m, Monad m) => [m a] -> m [a]
f' :: (Monad m, Monad m) => [m a] -> m [a]
g ::
  (Monad GHC.Types.Any, Monad m) =>
  [GHC.Types.Any GHC.Types.Any] -> GHC.Types.Any [GHC.Types.Any]
g' :: (Monad GHC.Types.Any, Monad m) => [m a] -> m [a]

The same behavior also happens with :type v (but not :type, since that performs deep instantiation of the types):

λ> :type +v f
f :: (Monad m, Monad m) => [m a] -> m [a]
λ> :type +v f'
f' :: (Monad m, Monad m) => [m a] -> m [a]
λ> :type +v g
g :: (Monad GHC.Types.Any, Monad m) =>
     [GHC.Types.Any GHC.Types.Any] -> GHC.Types.Any [GHC.Types.Any]
λ> :type +v g'
g' :: (Monad GHC.Types.Any, Monad m) => [m a] -> m [a]

comment:3 Changed 11 days ago by mnislaih

Summary: Partial type signatures interact unexpectedly with :browsePartial type signatures in class constraints behave unexpectedly

Hi Ryan, thanks for the even smaller example! For some reason I didn't think of removing the TH splice. But just to clarify, this issue is not restricted to :browse. The type signatures with Any in them cannot be instantiated, or at least I haven't figured out how. Found an even smaller example:

af, ag :: (Num a,_) => a -> a
af = ag
ag x = af(x-1)

The Num constraint is duplicated. Suggests the bug is related to tyvar identity

Last edited 11 days ago by mnislaih (previous) (diff)

comment:4 Changed 9 days ago by Simon Peyton Jones <simonpj@…>

In 1577908/ghc:

Fix two more bugs in partial signatures

These were shown up by Trac #14643

Bug 1: if we had a single partial signature for
two functions
   f, g :: forall a. _ -> a
then we made two different SigTvs but with the sane Name.
This was jolly confusing and ultimately led to deeply bogus
results with Any's appearing in the resulting program. Yikes.
Fix: clone the quantified variables in TcSigs.tcInstSig (as
indeed its name suggests).

Bug 2: we were not eliminating duplicate/superclass constraints
in the partial signatures of a mutually recursive group.

Easy to fix: we are already doing dup/superclass elim in
TcSimplify.decideQuantification.  So we move the partial-sig
constraints there too.

comment:5 Changed 9 days ago by simonpj

Status: newmerge
Test Case: partial-sigs/should_compile/T14643, T14643a

Thanks for the report. It was trickier than I thought, and showed up not one but two separate bugs.

We could merge this... it's an outright bug.

comment:6 Changed 9 days ago by Simon Peyton Jones <simonpj@…>

In f3f90a07/ghc:

Fix previous patch

This recent patch
    commit 1577908f2a9db0fcf6f749d40dd75481015f5497
    Author: Simon Peyton Jones <simonpj@microsoft.com>
    Date:   Tue Jan 9 16:20:46 2018 +0000

        Fix two more bugs in partial signatures

        These were shown up by Trac #14643

failed validation for typecheck/should_run/T10846
(Reported in Trac #14658.)

The fix is simple.

comment:7 Changed 9 days ago by simonpj

If you merge, merge both!

comment:8 Changed 4 days ago by bgamari

Milestone: 8.4.1
Resolution: fixed
Status: mergeclosed
Note: See TracTickets for help on using tickets.