Opened 3 years ago

Closed 3 years ago

Last modified 23 months ago

#10351 closed bug (fixed)

Inferred type is rejected

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

Description

Consider

class C a where
 op :: a -> ()

f x = op [x]

we get

Foo.hs:14:1: error:
    Non type-variable argument in the constraint: C [t]
    (Use FlexibleContexts to permit this)
    When checking that ‘f’ has the inferred type
      f :: forall t. C [t] => t -> ()

Arguably, if FlexibleContexts is not on, we should not infer a type that will immediately be rejected.

Change History (6)

comment:1 Changed 3 years ago by Simon Peyton Jones <simonpj@…>

In b83160d07e626bee685f329a9a73e90a4a6074ae/ghc:

Tidy up treatment of FlexibleContexts

Previously (Trac #10351) we could get

    Non type-variable argument in the constraint: C [t]
    (Use FlexibleContexts to permit this)
    When checking that `f' has the inferred type
      f :: forall t. C [t] => t -> ()

which is a bit stupid: we have *inferred* a type that we
immediately *reject*.  This patch arranges that that the
generalisation mechanism (TcSimplify.decideQuantification)
doesn't pick a predicate that will be rejected by the
subsequent validity check.

This forced some minor refactoring, as usual.

comment:2 Changed 3 years ago by simonpj

Resolution: fixed
Status: newclosed
Test Case: typecheck/should_fail/T10351

comment:3 Changed 3 years ago by darchon

I don't know if this ticket should be re-opened or not, but I do want to note the following.

I was compiling the tasty package (http://hackage.haskell.org/package/tasty) with ghc-7.11.20150505 and got the following error:

[11 of 17] Compiling Test.Tasty.Ingredients.ConsoleReporter ( Test/Tasty/Ingredients/ConsoleReporter.hs, dist/dist-sandbox-4347b07a/build/Test/Tasty/Ingredients/ConsoleReporter.o )

Test/Tasty/Ingredients/ConsoleReporter.hs:124:11: error:
    Could not deduce (MonadState IntMap.Key f)
      arising from a use of ‘get’
    from the context: (?colors::Bool, Monoid b)
      bound by the type signature for:
               foldTestOutput :: (?colors::Bool, Monoid b) =>
                                 (IO () -> IO Result -> (Result -> IO ()) -> b)
                                 -> (IO () -> b -> b) -> TestOutput -> StatusMap -> b
      at Test/Tasty/Ingredients/ConsoleReporter.hs:(117,6)-(120,33)
    or from: Monad f
      bound by the inferred type of go :: Monad f => TestOutput -> Ap f b
      at Test/Tasty/Ingredients/ConsoleReporter.hs:(123,3)-(135,18)
    In a stmt of a 'do' block: ix <- get
    In the second argument of ‘($)’, namely
      ‘do { ix <- get;
            put $! ix + 1;
            let statusVar
                  = fromMaybe (error "internal error: index out of bounds")
                    $ IntMap.lookup ix smap
                readStatusVar = getResultFromTVar statusVar;
            return $ foldTest printName readStatusVar printResult }’
    In the expression:
      Ap
      $ do { ix <- get;
             put $! ix + 1;
             let statusVar
                   = fromMaybe (error "internal error: index out of bounds")
                     $ IntMap.lookup ix smap
                 readStatusVar = getResultFromTVar statusVar;
             return $ foldTest printName readStatusVar printResult }

Where this reported

go :: Mond f => TestOutput -> Ap f b

function is defined within a where clause. With the behaviour as implemented in the above patch, I first had to annotate go in the code as:

go :: MonadState IntMap.Key f => TestOutput -> Ap f b

And only then GHC would inform me that I needed to enable FlexibleContexts. However, if the behaviour was still as it was as reported in the ticket, pre-patch, GHC would have informed me immediately that I should have enabled FlexibleContexts. Or do I misunderstand the intention of the patch?

I don't know if it is a bad (and/or common) programming practice to add as many LANGUAGE pragma's as GHC tells you to until your code starts compiling. But I know the above patch certainly hinders that practice.

Perhaps a separate issue: I don't understand why the tasty package compiled on GHC 7.10.1 in the first place, but started failing in HEAD.

comment:4 Changed 3 years ago by simonpj

The difficulty before is that GHC would infer a type and then complain that its own inferred type was illegal. That seems confusing.

Moreover sometimes, if it had simply refrained from generalising over that constraint, the program would have been accepted. So the change means that strictly more programs are accepted.

But as you discovered, failing to generalise over a constraint may mean that it is reported as unsolved; and only when you fix that does it ask for FlexibleContexts.

I'm open to suggestions, but the new behaviour seems cleaner to me.

Simon

comment:5 Changed 2 years ago by Simon Peyton Jones <simonpj@…>

In b5aabfbdb96ba8abf2748d089f40c267c2131215/ghc:

Infer types with flexible contexts

Responding to Trac #10608 and Trac #10351, I've reverted
to making type inference infer structured constraint like
    f :: C [t] => t -> t
even if -XFlexibleContexts is not set.  That elicits an
error message suggesting the flag.  The result is more
helpful than the error message you get otherwise.

comment:6 Changed 23 months ago by thomie

Milestone: 8.0.1
Note: See TracTickets for help on using tickets.