Opened 4 years ago

Closed 4 years ago

#7279 closed feature request (fixed)

warning for unused type variables in instance contexts; -fwarn-unreachable-type-variables?

Reported by: nfrisby Owned by:
Priority: normal Milestone:
Component: Compiler (Type checker) Version: 7.6.1
Keywords: Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case: typecheck/should_fail/T7279
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:


I just spend 90 minutes tracking down what ended up being a typo introduced via find-and-replace.

I accidentally introduced a spurious constraint on an instance context:

instance (Monoid m, Context t) => Class t where …

I would like to be warned about constraints on variables that certainly have no connection to variables in the instance head. -fwarn-unreachable-type-variables?

This might also help catch those signatures where all occurrences of type variable are as index arguments to a type family, rendering the functional unusable because of "ambiguous type variable" errors at every call site.

Change History (1)

comment:1 Changed 4 years ago by simonpj

difficulty: Unknown
Resolution: fixed
Status: newclosed
Test Case: typecheck/should_fail/T7279

This fix to ambiguity checking solves the problem

commit 97db0edc4e637dd61ec635d1f9b6b6dd25ad890c
Author: Simon Peyton Jones <>
Date:   Tue Jan 8 08:26:40 2013 +0000

    Re-engineer the ambiguity test for user type signatures
    Two main changes. First, re-engineer the ambiguity test.  Previously
    TcMType.checkAmbiguity used a rather syntactic test to detect some
    types that are certainly ambiguous.  But a much easier test is available,
    and it is used for inferred types in TcBinds. Namely
        <type> is ambiguous
       <type> `TcUnify.isSubType` <type>
    fails to hold, where "isSubType" means "is provably more polymorphic than".
          C a => Int
    is ambiguous, because isSubType instantiates the (C a => Int)
    to (C alpha => Int) and then tries to deduce (C alpha) from (C a). This is
    Martin Sulzmann's definition of ambiguity.  (Defn 10 of "Understanding
    functional dependencies via constraint handling rules", JFP.)
    This change is neat, reduces code, and correctly rejects more programs.
    However is *is* just possible to have a useful program that would be
    rejected. For example
              class C a b
              f :: C Int b => Int -> Int
    Here 'f' would be rejected as having an ambiguous type. But it is
    just possible that, at a *call* site there might be an instance
    declaration  instance C Int b, which does not constrain 'b' at all.
    This is pretty strange -- why is 'b' overloaded at all? -- but it's
    possible, so I also added a flag -XAllowAmbiguousTypes that simply
    removes the ambiguity check.  Let's see if anyone cares.  Meanwhile
    the earlier error report will be useful for everyone else.
    A handful of regression tests had to be adjusted as a result, because
    they used ambiguous types, somewhat accidentally.
    Second, split TcMType (already too large) into two
      * TcMType: a low-level module dealing with monadic operations like
        zonking, creating new evidence variables, etc
      * TcValidity: a brand-new higher-level module dealing with
        validity checking for types: checkValidType, checkValidInstance,
        checkFamInstPats etc
    Apart from the fact that TcMType was too big, this allows TcValidity
    to import TcUnify(tcSubType) without causing a loop.

 compiler/               |    1 +
 compiler/main/DynFlags.hs           |    2 +
 compiler/typecheck/TcBinds.lhs      |   28 +-
 compiler/typecheck/TcDeriv.lhs      |  132 +++++
 compiler/typecheck/TcErrors.lhs     |  143 ++---
 compiler/typecheck/TcEvidence.lhs   |    4 +-
 compiler/typecheck/TcHsType.lhs     |    1 +
 compiler/typecheck/TcInstDcls.lhs   |    1 +
 compiler/typecheck/TcMType.lhs      | 1063 +----------------------------------
 compiler/typecheck/TcPat.lhs        |    1 +
 compiler/typecheck/TcRnTypes.lhs    |    8 +-
 compiler/typecheck/TcSMonad.lhs     |    9 +-
 compiler/typecheck/TcSimplify.lhs   |  152 +-----
 compiler/typecheck/TcTyClsDecls.lhs |    1 +
 14 files changed, 248 insertions(+), 1298 deletions(-)

Now the instance declaration will (rightly) be rejected as ambiguous. So either you get

    Variable `b' occurs more often than in the instance head
      in the constraint: Show b
    (Use -XUndecidableInstances to permit this)
    In the instance declaration for `Eq (T a)'

or, if you add -XUndecidableInstances you get the ambiguity error instead:

    Could not deduce (Show b0)
      arising from the ambiguity check for an instance declaration
    from the context (Eq a, Show b)
      bound by an instance declaration: (Eq a, Show b) => Eq (T a)
      at T7279.hs:6:10-35
    The type variable `b0' is ambiguous
    In the ambiguity check for: forall a b. (Eq a, Show b) => Eq (T a)
    In the instance declaration for `Eq (T a)'
Note: See TracTickets for help on using tickets.