coercion errors don't always mention that data constructors are not in scope
Suppose a library defines a newtype with a nominal type parameter:
{-# LANGUAGE RoleAnnotations #-}
module Lib where
type role LibIdentity nominal
newtype LibIdentity a = LibIdentity a
(in my code, that newtype is ExceptT, whose last argument is inferred to be nominal)
In a different module, I also define a newtype, and then I try to use coerce to remove some of the newtype wrappers. Unfortunately I forgot to import LibIdentity's data constructor, and so the coercions fail. Sometimes, the error message helpfully explains that I need that import... but sometimes it doesn't!
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Local where
import Data.Coerce (coerce)
import Lib (LibIdentity)
newtype LocalIdentity a = LocalIdentity a
-- error:
-- • Couldn't match representation of type ‘()’
-- with that of ‘LibIdentity ()’
-- arising from a use of ‘coerce’
-- The data constructor ‘Lib.LibIdentity’
-- of newtype ‘LibIdentity’ is not in scope
helpfulError :: LocalIdentity (LibIdentity ()) -> LocalIdentity ()
helpfulError = coerce
-- error:
-- • Couldn't match type ‘LocalIdentity ()’ with ‘()’
-- arising from a use of ‘coerce’
difficultError :: LibIdentity (LocalIdentity ()) -> LibIdentity ()
difficultError = coerce
Expected: both uses of coerce remind me to import the data constructor of LibIdentity.
Observed: only helpfulError reminds me, while difficultError doesn't.
(in my code, the coerce is generated by GeneralizedNewtypeDeriving and the error message does not include the type whose data constructor needs to be imported, making it quite difficult to guess how to fix the error)
Trac metadata
| Trac field | Value |
|---|---|
| Version | 8.6.1 |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture |